8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libc / i386 / fp / _base_il.s
blob157e9779228836cd900eac771ea1c8a9c64e1c21
1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
16 .file "_base_il.s"
19 * These files are in assembly because some compilers will mistakenly reorder
20 * multiplications or divisions wrapped in _putsw() and _getsw(). They are
21 * proper subroutines for now, but should be considered candidates for
22 * inlining eventually.
24 * The original C sources are included for readability in the pre-function
25 * comment blocks.
28 #include <SYS.h>
31 * Multiplies two normal or subnormal doubles, returns result and exceptions.
34 double
35 __mul_set(double x, double y, int *pe) {
36 extern void _putsw(), _getsw();
37 int sw;
38 double z;
40 _putsw(0);
41 z = x * y;
42 _getsw(&sw);
43 if ((sw & 0x3f) == 0) {
44 *pe = 0;
45 } else {
46 *pe = 1;
48 return (z);
52 ENTRY(__mul_set)
53 subl $0x8, %esp /* Give us an extra 8 bytes to play with. */
54 /* Clear the floating point exception register. */
55 fnclex /* Equivalent of _putsw(0); */
57 fldl 0xc(%esp) /* Load up x */
58 fmull 0x14(%esp) /* And multiply! */
60 /* Check to see if the multiply caused any exceptions. */
61 fstsw (%esp) /* Equivalent of... */
62 xorl %edx, %edx
63 andl $0x3f, (%esp) /* If the status word (low bits) are zero... */
64 setne %dl /* ... set *pe (aka. (%eax)) accordingly. */
65 movl 0x1c(%esp), %eax/* Get pe. */
66 movl %edx, (%eax) /* And set it. (True == FP exception). */
67 addl $0x8, %esp /* Release the 8 play bytes. */
68 ret
69 SET_SIZE(__mul_set)
72 * Divides two normal or subnormal doubles x/y, returns result and exceptions.
75 double
76 __div_set(double x, double y, int *pe) {
77 extern void _putsw(), _getsw();
78 int sw;
79 double z;
81 _putsw(0);
82 z = x / y;
83 _getsw(&sw);
84 if ((sw & 0x3f) == 0) {
85 *pe = 0;
86 } else {
87 *pe = 1;
89 return (z);
94 ENTRY(__div_set)
95 subl $0x8, %esp /* Give us an extra 8 bytes to play with. */
96 /* Clear the floating point exception register. */
97 fnclex /* Equivalent of _putsw(0); */
99 fldl 0xc(%esp) /* Load up x */
100 fdivl 0x14(%esp) /* And divide! */
102 /* Check to see if the divide caused any exceptions. */
103 fstsw (%esp) /* Equivalent of... */
104 xorl %edx, %edx
105 andl $0x3f, (%esp) /* If the status word (low bits) are zero... */
106 setne %dl /* ... set *pe (aka. (%eax)) accordingly. */
107 movl 0x1c(%esp), %eax/* Get pe. */
108 movl %edx, (%eax) /* And set it. (True == FP exception). */
109 addl $0x8, %esp /* Release the 8 play bytes. */
111 SET_SIZE(__div_set)
113 /* double __dabs(double *d) - Get the abs. value of *d. Straightforward. */
115 ENTRY(__dabs)
116 movl 0x4(%esp), %eax
117 fldl (%eax)
118 fabs /* Just let the FPU do its thing. */
120 SET_SIZE(__dabs)