this repo has no description
1/*
2 * fmax.s
3 *
4 * by Ian Ollmann
5 *
6 * Copyright � 2007 Apple Inc. All Rights Reserved.
7 */
8
9
10#include <machine/asm.h>
11#include "abi.h"
12
13#if defined( BUILDING_FOR_CARBONCORE_LEGACY )
14
15 #if defined( __i386__ )
16
17 ENTRY( fmax )
18 fldl 8+FRAME_SIZE(STACKP) //{ y }
19 fldl FRAME_SIZE(STACKP) //{ x, y }
20 fucomi %st(0), %st(0) //Check for x is NaN
21 fcmovb %st(1), %st(0) //{ x or y, y}
22 fxch //{ y, x or y }
23 fucomi %st(1), %st(0) //Check y < x or y is NaN
24 fcmovb %st(1), %st(0) //{ max, x or y }
25 fstp %st(1) //{ max }
26 ret
27
28 ENTRY( fmin )
29 fldl 8+FRAME_SIZE(STACKP) //{ y }
30 fldl FRAME_SIZE(STACKP) //{ x, y }
31 fucomi %st(0), %st(0) //Check for x is NaN
32 fcmovb %st(1), %st(0) //{ x or y, y }
33 fucomi %st(1), %st(0) //Check x < y or y is NaN
34 fxch //{ y, x or y }
35 fcmovb %st(1), %st(0) //{ max, x or y }
36 fstp %st(1) //{ max }
37 ret
38
39 ENTRY( fdim )
40 movsd FRAME_SIZE( STACKP), %xmm0 // x
41 movsd 8+FRAME_SIZE( STACKP), %xmm1 // y
42 movapd %xmm1, %xmm2 // x
43 ucomisd %xmm0, %xmm1 // if( x != x || y != y )
44 jp 1f // goto 1
45 cmpltpd %xmm0, %xmm2 // y < x
46 andpd %xmm2, %xmm0
47 andpd %xmm2, %xmm1
48 1: subsd %xmm1, %xmm0
49 movsd %xmm0, FRAME_SIZE(STACKP)
50 fldl FRAME_SIZE(STACKP)
51 ret
52
53 #else
54
55 ENTRY( fmax )
56 SUBP $16, STACKP
57
58 //create an array on the stack s[2] = { x, y }
59 movsd %xmm0, (STACKP)
60 movsd %xmm1, 8(STACKP)
61
62 //test a = x < y
63 xorq %rax, %rax
64 xorq %rdx, %rdx
65 ucomisd %xmm1, %xmm0
66 setb %al // a = x < y || isnan(y) || isnan(x)
67 ucomisd %xmm1, %xmm1
68 setp %dl // isnan(y)
69 xorq %rdx, %rax // if (isnan(y)) a = 0
70
71 // return s[a]
72 movsd (STACKP,%rax,8), %xmm0
73 ADDP $16, STACKP
74 ret
75
76 ENTRY( fmin )
77 SUBP $16, STACKP
78
79 //create an array on the stack s[2] = { x, y }
80 movsd %xmm0, (STACKP)
81 movsd %xmm1, 8(STACKP)
82
83 //test a = y < x
84 xorq %rax, %rax
85 xorq %rdx, %rdx
86 ucomisd %xmm0, %xmm1
87 setb %al // a = y < x || isnan(y) || isnan(x)
88 ucomisd %xmm1, %xmm1
89 setp %dl // isnan(y)
90 xorq %rdx, %rax // if (isnan(y)) a = 0
91
92 // return s[a]
93 movsd (STACKP,%rax,8), %xmm0
94 ADDP $16, STACKP
95 ret
96
97 ENTRY( fdim )
98 //a == ( y < x || isnan( y) || isnan(x) )
99 xor %eax, %eax
100 ucomisd %xmm0, %xmm1
101 setb %al
102
103 // map a = {0,1} to a = { 0, -1ULL }
104 movd %eax, %xmm2
105 pxor %xmm3, %xmm3
106 psubq %xmm2, %xmm3
107
108 //mask x and y to zero if ( y > x && ! isnan( y) && ! isnan(x) )
109 andpd %xmm3, %xmm1
110 andpd %xmm3, %xmm0
111
112 //Do the subtract
113 subsd %xmm1, %xmm0
114 ret
115
116 #endif
117
118#else
119
120 //Not CARBONCORE LEGACY
121
122 #if defined( __i386__ )
123 ENTRY( fmaxf )
124 flds 4+FRAME_SIZE(STACKP) //{ y }
125 flds FRAME_SIZE(STACKP) //{ x, y }
126 fucomi %st(0), %st(0) //Check for x is NaN
127 fcmovb %st(1), %st(0) //{ x or y, y}
128 fxch //{ y, x or y }
129 fucomi %st(1), %st(0) //Check y < x or y is NaN
130 fcmovb %st(1), %st(0) //{ max, x or y }
131 fstp %st(1) //{ max }
132 ret
133
134 ENTRY( fminf )
135 flds 4+FRAME_SIZE(STACKP) //{ y }
136 flds FRAME_SIZE(STACKP) //{ x, y }
137 fucomi %st(0), %st(0) //Check for x is NaN
138 fcmovb %st(1), %st(0) //{ x or y, y }
139 fucomi %st(1), %st(0) //Check x < y or y is NaN
140 fxch //{ y, x or y }
141 fcmovb %st(1), %st(0) //{ max, x or y }
142 fstp %st(1) //{ max }
143 ret
144
145 //We have to use xmm here so that the subtraction doesnt take a double rounding
146 ENTRY( fdimf )
147 movss FRAME_SIZE(STACKP), %xmm0
148 movss 4+FRAME_SIZE(STACKP), %xmm1
149
150 SUBP $4, STACKP
151
152 //a == ( y < x || isnan( y) || isnan(x) )
153 xor %eax, %eax
154 ucomiss %xmm0, %xmm1
155 setb %al
156
157 // map a = {0,1} to a = { 0, -1ULL }
158 negl %eax
159 movd %eax, %xmm2
160
161 //mask x and y to zero if ( y > x && ! isnan( y) && ! isnan(x) )
162 andps %xmm2, %xmm1
163 andps %xmm2, %xmm0
164
165 //Do the subtract
166 subss %xmm1, %xmm0
167 movss %xmm0, (STACKP)
168 flds (STACKP)
169
170 ADDP $4, STACKP
171 ret
172
173
174 #else
175
176 ENTRY( fmaxf )
177 SUBP $8, STACKP
178
179 //create an array on the stack s[2] = { x, y }
180 movss %xmm0, (STACKP)
181 movss %xmm1, 4(STACKP)
182
183 //test a = x < y
184 xorq %rax, %rax
185 xorq %rdx, %rdx
186 ucomiss %xmm1, %xmm0
187 setb %al // a = x < y || isnan(y) || isnan(x)
188 ucomiss %xmm1, %xmm1
189 setp %dl // isnan(y)
190 xorq %rdx, %rax // if (isnan(y)) a = 0
191
192 // return s[a]
193 movss (STACKP,%rax,4), %xmm0
194 ADDP $8, STACKP
195 ret
196
197 ENTRY( fminf )
198 SUBP $8, STACKP
199
200 //create an array on the stack s[2] = { x, y }
201 movss %xmm0, (STACKP)
202 movss %xmm1, 4(STACKP)
203
204 //test a = y < x
205 xorq %rax, %rax
206 xorq %rdx, %rdx
207 ucomiss %xmm0, %xmm1
208 setb %al // a = y < x || isnan(y) || isnan(x)
209 ucomiss %xmm1, %xmm1
210 setp %dl // isnan(y)
211 xorq %rdx, %rax // if (isnan(y)) a = 0
212
213 // return s[a]
214 movss (STACKP,%rax,4), %xmm0
215 ADDP $8, STACKP
216 ret
217
218 ENTRY( fdimf )
219 //a == ( y < x || isnan( y) || isnan(x) )
220 xor %eax, %eax
221 ucomiss %xmm0, %xmm1
222 setb %al
223
224 // map a = {0,1} to a = { 0, -1ULL }
225 negl %eax
226 movd %eax, %xmm2
227
228 //mask x and y to zero if ( y > x && ! isnan( y) && ! isnan(x) )
229 andps %xmm2, %xmm1
230 andps %xmm2, %xmm0
231
232 //Do the subtract
233 subss %xmm1, %xmm0
234 ret
235
236 #endif
237
238
239 // long double fminl( long double a, long double b )
240 ENTRY( fminl )
241 fldt FIRST_ARG_OFFSET(STACKP) // {a}
242 fldt SECOND_ARG_OFFSET(STACKP) // {b,a}
243 fucomi %ST(0), %ST // test b is NaN
244 fcmovu %ST(1), %ST(0) // if( b is NaN) b = a
245 fucomi %ST(1), %ST // b > a
246 fcmovnb %ST(1), %ST(0)
247 fstp %ST(1)
248 ret
249
250 // long double fmaxl( long double a, long double b )
251 ENTRY( fmaxl )
252 fldt FIRST_ARG_OFFSET(STACKP) // {a}
253 fldt SECOND_ARG_OFFSET(STACKP) // {b,a}
254 fucomi %ST(0), %ST // test b is NaN
255 fcmovu %ST(1), %ST(0) // if( b is NaN) b = a
256 fld %ST(1) // {a, b, a}
257 fucomip %ST(1), %ST // a >= b
258 fcmovnb %ST(1), %ST(0)
259 fstp %ST(1)
260 ret
261
262 // long double fdiml( long double a, long double b )
263 ENTRY( fdiml )
264 fldz // {0}
265 fldt FIRST_ARG_OFFSET(STACKP) // {a, 0}
266 fldt SECOND_ARG_OFFSET(STACKP) // {b, a, 0}
267 fucomi %ST(1), %ST // {b, a, 0} b >= a and not NaN
268 fcmovnb %ST(2), %ST(0) // {b or 0, a, 0 }
269 fxch // {a, b or 0, 0 }
270 fcmovnb %ST(2), %ST(0) // {a or 0, b or 0, 0 }
271 fsubp // {result, 0 }
272 fstp %ST(1) // {result}
273 ret
274
275
276#endif /*BUILDING_FOR_CARBONCORE_LEGACY*/