add sse fenv support on i386 through hwcap
[musl] / src / fenv / i386 / fenv.s
1 .hidden __hwcap
2
3 .global feclearexcept
4 .type feclearexcept,@function
5 feclearexcept:  
6         mov 4(%esp),%ecx
7         not %ecx
8                 # consider sse fenv as well if the cpu has XMM capability
9         call 1f
10 1:      addl $__hwcap-1b,(%esp)
11         pop %edx
12         testl $0x02000000,(%edx)
13         jz 1f
14         stmxcsr 4(%esp)
15         and %ecx,4(%esp)
16         ldmxcsr 4(%esp)
17 1:      test $0x3f,%ecx
18         jnz 2f
19 1:      fnclex
20         xor %eax,%eax
21         ret
22 2:      fnstsw %ax
23                 # TODO: only load/store fenv if exceptions arent clear yet
24         and %ecx,%eax
25         jz 1b
26         sub $32,%esp
27         fnstenv (%esp)
28         mov %al,4(%esp)
29         fldenv (%esp)
30         add $32,%esp
31         xor %eax,%eax
32         ret
33
34 .global feraiseexcept
35 .type feraiseexcept,@function
36 feraiseexcept:  
37         mov 4(%esp),%eax
38         sub $32,%esp
39         fnstenv (%esp)
40         or %al,4(%esp)
41         fldenv (%esp)
42         add $32,%esp
43         xor %eax,%eax
44         ret
45
46 .global fesetround
47 .type fesetround,@function
48 fesetround:
49         mov 4(%esp),%ecx
50         push %eax
51         xor %eax,%eax
52         fnstcw (%esp)
53         andb $0xf3,1(%esp)
54         or %ch,1(%esp)
55         fldcw (%esp)
56                 # consider sse fenv as well if the cpu has XMM capability
57         call 1f
58 1:      addl $__hwcap-1b,(%esp)
59         pop %edx
60         testl $0x02000000,(%edx)
61         jmp 1f
62         stmxcsr (%esp)
63         shl $3,%ch
64         andb $0x9f,1(%esp)
65         or %ch,1(%esp)
66         ldmxcsr (%esp)
67 1:      pop %ecx
68         ret
69
70 .global fegetround
71 .type fegetround,@function
72 fegetround:
73         push %eax
74         fnstcw (%esp)
75         pop %eax
76         and $0xc00,%eax
77         ret
78
79 .global fegetenv
80 .type fegetenv,@function
81 fegetenv:
82         mov 4(%esp),%ecx
83         xor %eax,%eax
84         fnstenv (%ecx)
85                 # consider sse fenv as well if the cpu has XMM capability
86         call 1f
87 1:      addl $__hwcap-1b,(%esp)
88         pop %edx
89         testl $0x02000000,(%edx)
90         jz 1f
91         push %eax
92         stmxcsr (%esp)
93         pop %edx
94         and $0x3f,%edx
95         or %edx,4(%ecx)
96 1:      ret
97
98 .global fesetenv
99 .type fesetenv,@function
100 fesetenv:
101         mov 4(%esp),%ecx
102         xor %eax,%eax
103         inc %ecx
104         jz 1f
105         fldenv -1(%ecx)
106         movl -1(%ecx),%ecx
107         jmp 2f
108 1:      push %eax
109         push %eax
110         push %eax
111         push %eax
112         push %eax
113         push %eax
114         pushl $0x37f
115         fldenv (%esp)
116         add $28,%esp
117                 # consider sse fenv as well if the cpu has XMM capability
118 2:      call 1f
119 1:      addl $__hwcap-1b,(%esp)
120         pop %edx
121         testl $0x02000000,(%edx)
122         jz 1f
123                 # mxcsr := same rounding mode, cleared exceptions, default mask
124         and $0xc00,%ecx
125         shl $3,%ecx
126         or $0x1f80,%ecx
127         mov %ecx,4(%esp)
128         ldmxcsr 4(%esp)
129 1:      ret
130
131 .global fetestexcept
132 .type fetestexcept,@function
133 fetestexcept:
134         mov 4(%esp),%ecx
135         fnstsw %ax
136                 # consider sse fenv as well if the cpu has XMM capability
137         call 1f
138 1:      addl $__hwcap-1b,(%esp)
139         pop %edx
140         testl $0x02000000,(%edx)
141         jz 1f
142         stmxcsr 4(%esp)
143         or 4(%esp),%eax
144 1:      and %ecx,%eax
145         ret