math: fix x86 asin, atan, exp, log1p to raise underflow
[musl] / src / math / i386 / exp.s
1 .global expm1f
2 .type expm1f,@function
3 expm1f:
4         flds 4(%esp)
5         mov 4(%esp),%eax
6         add %eax,%eax
7         cmp $0x01000000,%eax
8         jae 1f
9                 # subnormal x, return x with underflow
10         fnstsw %ax
11         and $16,%ax
12         jnz 2f
13         fld %st(0)
14         fmul %st(1)
15         fstps 4(%esp)
16 2:      ret
17
18 .global expm1l
19 .type expm1l,@function
20 expm1l:
21         fldt 4(%esp)
22         jmp 1f
23
24 .global expm1
25 .type expm1,@function
26 expm1:
27         fldl 4(%esp)
28         mov 8(%esp),%eax
29         add %eax,%eax
30         cmp $0x00200000,%eax
31         jae 1f
32                 # subnormal x, return x with underflow
33         fnstsw %ax
34         and $16,%ax
35         jnz 2f
36         fsts 4(%esp)
37 2:      ret
38 1:      fldl2e
39         fmulp
40         mov $0xc2820000,%eax
41         push %eax
42         flds (%esp)
43         pop %eax
44         fucomp %st(1)
45         fnstsw %ax
46         sahf
47         fld1
48         jb 1f
49                 # x*log2e < -65, return -1 without underflow
50         fstp %st(1)
51         fchs
52         ret
53 1:      fld %st(1)
54         fabs
55         fucom %st(1)
56         fnstsw %ax
57         fstp %st(0)
58         fstp %st(0)
59         sahf
60         ja 1f
61         f2xm1
62         ret
63 1:      call 1f
64         fld1
65         fsubrp
66         ret
67
68 .global exp2f
69 .type exp2f,@function
70 exp2f:
71         flds 4(%esp)
72         jmp 1f
73
74 .global exp2l
75 .type exp2l,@function
76 exp2l:
77         fldt 4(%esp)
78         jmp 1f
79
80 .global expf
81 .type expf,@function
82 expf:
83         flds 4(%esp)
84         jmp 2f
85
86 .global exp
87 .type exp,@function
88 exp:
89         fldl 4(%esp)
90 2:      fldl2e
91         fmulp
92         jmp 1f
93
94 .global exp2
95 .type exp2,@function
96 exp2:
97         fldl 4(%esp)
98 1:      pushl $0x467ff000
99         flds (%esp)       # 16380
100         xorl %eax,%eax
101         pushl $0x80000000
102         push %eax
103         fld %st(1)
104         fabs
105         fucomp %st(1)
106         fnstsw
107         fstp %st(0)
108         sahf
109         ja 3f             # |x| > 16380
110         jp 2f             # x is nan (avoid invalid except in fistp)
111         fld %st(0)
112         fistpl 8(%esp)
113         fildl 8(%esp)
114         fxch %st(1)
115         fsub %st(1)
116         mov $0x3fff,%eax
117         add %eax,8(%esp)
118         f2xm1
119         fld1
120         faddp             # 2^(x-rint(x))
121         fldt (%esp)       # 2^rint(x)
122         fmulp
123         fstp %st(1)
124 2:      add $12,%esp
125         ret
126
127 3:      fld %st(0)
128         fstpt (%esp)
129         fld1
130         mov 8(%esp),%ax
131         and $0x7fff,%ax
132         cmp $0x7fff,%ax
133         je 1f             # x = +-inf
134         fld %st(1)
135         frndint
136         fxch %st(2)
137         fsub %st(2)       # st(0)=x-rint(x), st(1)=1, st(2)=rint(x)
138         f2xm1
139         faddp             # 2^(x-rint(x))
140 1:      fscale
141         fstp %st(1)
142         add $12,%esp
143         ret