diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/math-emu/op-common.h |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/ppc/math-emu/op-common.h')
-rw-r--r-- | arch/ppc/math-emu/op-common.h | 688 |
1 files changed, 688 insertions, 0 deletions
diff --git a/arch/ppc/math-emu/op-common.h b/arch/ppc/math-emu/op-common.h new file mode 100644 index 000000000000..afb82b6498ce --- /dev/null +++ b/arch/ppc/math-emu/op-common.h | |||
@@ -0,0 +1,688 @@ | |||
1 | #define _FP_DECL(wc, X) \ | ||
2 | _FP_I_TYPE X##_c, X##_s, X##_e; \ | ||
3 | _FP_FRAC_DECL_##wc(X) | ||
4 | |||
5 | /* | ||
6 | * Finish truely unpacking a native fp value by classifying the kind | ||
7 | * of fp value and normalizing both the exponent and the fraction. | ||
8 | */ | ||
9 | |||
10 | #define _FP_UNPACK_CANONICAL(fs, wc, X) \ | ||
11 | do { \ | ||
12 | switch (X##_e) \ | ||
13 | { \ | ||
14 | default: \ | ||
15 | _FP_FRAC_HIGH_##wc(X) |= _FP_IMPLBIT_##fs; \ | ||
16 | _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \ | ||
17 | X##_e -= _FP_EXPBIAS_##fs; \ | ||
18 | X##_c = FP_CLS_NORMAL; \ | ||
19 | break; \ | ||
20 | \ | ||
21 | case 0: \ | ||
22 | if (_FP_FRAC_ZEROP_##wc(X)) \ | ||
23 | X##_c = FP_CLS_ZERO; \ | ||
24 | else \ | ||
25 | { \ | ||
26 | /* a denormalized number */ \ | ||
27 | _FP_I_TYPE _shift; \ | ||
28 | _FP_FRAC_CLZ_##wc(_shift, X); \ | ||
29 | _shift -= _FP_FRACXBITS_##fs; \ | ||
30 | _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \ | ||
31 | X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \ | ||
32 | X##_c = FP_CLS_NORMAL; \ | ||
33 | } \ | ||
34 | break; \ | ||
35 | \ | ||
36 | case _FP_EXPMAX_##fs: \ | ||
37 | if (_FP_FRAC_ZEROP_##wc(X)) \ | ||
38 | X##_c = FP_CLS_INF; \ | ||
39 | else \ | ||
40 | /* we don't differentiate between signaling and quiet nans */ \ | ||
41 | X##_c = FP_CLS_NAN; \ | ||
42 | break; \ | ||
43 | } \ | ||
44 | } while (0) | ||
45 | |||
46 | |||
47 | /* | ||
48 | * Before packing the bits back into the native fp result, take care | ||
49 | * of such mundane things as rounding and overflow. Also, for some | ||
50 | * kinds of fp values, the original parts may not have been fully | ||
51 | * extracted -- but that is ok, we can regenerate them now. | ||
52 | */ | ||
53 | |||
54 | #define _FP_PACK_CANONICAL(fs, wc, X) \ | ||
55 | ({int __ret = 0; \ | ||
56 | switch (X##_c) \ | ||
57 | { \ | ||
58 | case FP_CLS_NORMAL: \ | ||
59 | X##_e += _FP_EXPBIAS_##fs; \ | ||
60 | if (X##_e > 0) \ | ||
61 | { \ | ||
62 | __ret |= _FP_ROUND(wc, X); \ | ||
63 | if (_FP_FRAC_OVERP_##wc(fs, X)) \ | ||
64 | { \ | ||
65 | _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \ | ||
66 | X##_e++; \ | ||
67 | } \ | ||
68 | else \ | ||
69 | _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ | ||
70 | if (X##_e >= _FP_EXPMAX_##fs) \ | ||
71 | { \ | ||
72 | /* overflow to infinity */ \ | ||
73 | X##_e = _FP_EXPMAX_##fs; \ | ||
74 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
75 | __ret |= EFLAG_OVERFLOW; \ | ||
76 | } \ | ||
77 | } \ | ||
78 | else \ | ||
79 | { \ | ||
80 | /* we've got a denormalized number */ \ | ||
81 | X##_e = -X##_e + 1; \ | ||
82 | if (X##_e <= _FP_WFRACBITS_##fs) \ | ||
83 | { \ | ||
84 | _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ | ||
85 | _FP_FRAC_SLL_##wc(X, 1); \ | ||
86 | if (_FP_FRAC_OVERP_##wc(fs, X)) \ | ||
87 | { \ | ||
88 | X##_e = 1; \ | ||
89 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
90 | } \ | ||
91 | else \ | ||
92 | { \ | ||
93 | X##_e = 0; \ | ||
94 | _FP_FRAC_SRL_##wc(X, _FP_WORKBITS+1); \ | ||
95 | __ret |= EFLAG_UNDERFLOW; \ | ||
96 | } \ | ||
97 | } \ | ||
98 | else \ | ||
99 | { \ | ||
100 | /* underflow to zero */ \ | ||
101 | X##_e = 0; \ | ||
102 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
103 | __ret |= EFLAG_UNDERFLOW; \ | ||
104 | } \ | ||
105 | } \ | ||
106 | break; \ | ||
107 | \ | ||
108 | case FP_CLS_ZERO: \ | ||
109 | X##_e = 0; \ | ||
110 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
111 | break; \ | ||
112 | \ | ||
113 | case FP_CLS_INF: \ | ||
114 | X##_e = _FP_EXPMAX_##fs; \ | ||
115 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
116 | break; \ | ||
117 | \ | ||
118 | case FP_CLS_NAN: \ | ||
119 | X##_e = _FP_EXPMAX_##fs; \ | ||
120 | if (!_FP_KEEPNANFRACP) \ | ||
121 | { \ | ||
122 | _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \ | ||
123 | X##_s = 0; \ | ||
124 | } \ | ||
125 | else \ | ||
126 | _FP_FRAC_HIGH_##wc(X) |= _FP_QNANBIT_##fs; \ | ||
127 | break; \ | ||
128 | } \ | ||
129 | __ret; \ | ||
130 | }) | ||
131 | |||
132 | |||
133 | /* | ||
134 | * Main addition routine. The input values should be cooked. | ||
135 | */ | ||
136 | |||
137 | #define _FP_ADD(fs, wc, R, X, Y) \ | ||
138 | do { \ | ||
139 | switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ | ||
140 | { \ | ||
141 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ | ||
142 | { \ | ||
143 | /* shift the smaller number so that its exponent matches the larger */ \ | ||
144 | _FP_I_TYPE diff = X##_e - Y##_e; \ | ||
145 | \ | ||
146 | if (diff < 0) \ | ||
147 | { \ | ||
148 | diff = -diff; \ | ||
149 | if (diff <= _FP_WFRACBITS_##fs) \ | ||
150 | _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \ | ||
151 | else if (!_FP_FRAC_ZEROP_##wc(X)) \ | ||
152 | _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ | ||
153 | else \ | ||
154 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
155 | R##_e = Y##_e; \ | ||
156 | } \ | ||
157 | else \ | ||
158 | { \ | ||
159 | if (diff > 0) \ | ||
160 | { \ | ||
161 | if (diff <= _FP_WFRACBITS_##fs) \ | ||
162 | _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \ | ||
163 | else if (!_FP_FRAC_ZEROP_##wc(Y)) \ | ||
164 | _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \ | ||
165 | else \ | ||
166 | _FP_FRAC_SET_##wc(Y, _FP_ZEROFRAC_##wc); \ | ||
167 | } \ | ||
168 | R##_e = X##_e; \ | ||
169 | } \ | ||
170 | \ | ||
171 | R##_c = FP_CLS_NORMAL; \ | ||
172 | \ | ||
173 | if (X##_s == Y##_s) \ | ||
174 | { \ | ||
175 | R##_s = X##_s; \ | ||
176 | _FP_FRAC_ADD_##wc(R, X, Y); \ | ||
177 | if (_FP_FRAC_OVERP_##wc(fs, R)) \ | ||
178 | { \ | ||
179 | _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ | ||
180 | R##_e++; \ | ||
181 | } \ | ||
182 | } \ | ||
183 | else \ | ||
184 | { \ | ||
185 | R##_s = X##_s; \ | ||
186 | _FP_FRAC_SUB_##wc(R, X, Y); \ | ||
187 | if (_FP_FRAC_ZEROP_##wc(R)) \ | ||
188 | { \ | ||
189 | /* return an exact zero */ \ | ||
190 | if (FP_ROUNDMODE == FP_RND_MINF) \ | ||
191 | R##_s |= Y##_s; \ | ||
192 | else \ | ||
193 | R##_s &= Y##_s; \ | ||
194 | R##_c = FP_CLS_ZERO; \ | ||
195 | } \ | ||
196 | else \ | ||
197 | { \ | ||
198 | if (_FP_FRAC_NEGP_##wc(R)) \ | ||
199 | { \ | ||
200 | _FP_FRAC_SUB_##wc(R, Y, X); \ | ||
201 | R##_s = Y##_s; \ | ||
202 | } \ | ||
203 | \ | ||
204 | /* renormalize after subtraction */ \ | ||
205 | _FP_FRAC_CLZ_##wc(diff, R); \ | ||
206 | diff -= _FP_WFRACXBITS_##fs; \ | ||
207 | if (diff) \ | ||
208 | { \ | ||
209 | R##_e -= diff; \ | ||
210 | _FP_FRAC_SLL_##wc(R, diff); \ | ||
211 | } \ | ||
212 | } \ | ||
213 | } \ | ||
214 | break; \ | ||
215 | } \ | ||
216 | \ | ||
217 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ | ||
218 | _FP_CHOOSENAN(fs, wc, R, X, Y); \ | ||
219 | break; \ | ||
220 | \ | ||
221 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ | ||
222 | R##_e = X##_e; \ | ||
223 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ | ||
224 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ | ||
225 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ | ||
226 | _FP_FRAC_COPY_##wc(R, X); \ | ||
227 | R##_s = X##_s; \ | ||
228 | R##_c = X##_c; \ | ||
229 | break; \ | ||
230 | \ | ||
231 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ | ||
232 | R##_e = Y##_e; \ | ||
233 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ | ||
234 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ | ||
235 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ | ||
236 | _FP_FRAC_COPY_##wc(R, Y); \ | ||
237 | R##_s = Y##_s; \ | ||
238 | R##_c = Y##_c; \ | ||
239 | break; \ | ||
240 | \ | ||
241 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ | ||
242 | if (X##_s != Y##_s) \ | ||
243 | { \ | ||
244 | /* +INF + -INF => NAN */ \ | ||
245 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
246 | R##_s = X##_s ^ Y##_s; \ | ||
247 | R##_c = FP_CLS_NAN; \ | ||
248 | break; \ | ||
249 | } \ | ||
250 | /* FALLTHRU */ \ | ||
251 | \ | ||
252 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ | ||
253 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ | ||
254 | R##_s = X##_s; \ | ||
255 | R##_c = FP_CLS_INF; \ | ||
256 | break; \ | ||
257 | \ | ||
258 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ | ||
259 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ | ||
260 | R##_s = Y##_s; \ | ||
261 | R##_c = FP_CLS_INF; \ | ||
262 | break; \ | ||
263 | \ | ||
264 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ | ||
265 | /* make sure the sign is correct */ \ | ||
266 | if (FP_ROUNDMODE == FP_RND_MINF) \ | ||
267 | R##_s = X##_s | Y##_s; \ | ||
268 | else \ | ||
269 | R##_s = X##_s & Y##_s; \ | ||
270 | R##_c = FP_CLS_ZERO; \ | ||
271 | break; \ | ||
272 | \ | ||
273 | default: \ | ||
274 | abort(); \ | ||
275 | } \ | ||
276 | } while (0) | ||
277 | |||
278 | |||
279 | /* | ||
280 | * Main negation routine. FIXME -- when we care about setting exception | ||
281 | * bits reliably, this will not do. We should examine all of the fp classes. | ||
282 | */ | ||
283 | |||
284 | #define _FP_NEG(fs, wc, R, X) \ | ||
285 | do { \ | ||
286 | _FP_FRAC_COPY_##wc(R, X); \ | ||
287 | R##_c = X##_c; \ | ||
288 | R##_e = X##_e; \ | ||
289 | R##_s = 1 ^ X##_s; \ | ||
290 | } while (0) | ||
291 | |||
292 | |||
293 | /* | ||
294 | * Main multiplication routine. The input values should be cooked. | ||
295 | */ | ||
296 | |||
297 | #define _FP_MUL(fs, wc, R, X, Y) \ | ||
298 | do { \ | ||
299 | R##_s = X##_s ^ Y##_s; \ | ||
300 | switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ | ||
301 | { \ | ||
302 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ | ||
303 | R##_c = FP_CLS_NORMAL; \ | ||
304 | R##_e = X##_e + Y##_e + 1; \ | ||
305 | \ | ||
306 | _FP_MUL_MEAT_##fs(R,X,Y); \ | ||
307 | \ | ||
308 | if (_FP_FRAC_OVERP_##wc(fs, R)) \ | ||
309 | _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ | ||
310 | else \ | ||
311 | R##_e--; \ | ||
312 | break; \ | ||
313 | \ | ||
314 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ | ||
315 | _FP_CHOOSENAN(fs, wc, R, X, Y); \ | ||
316 | break; \ | ||
317 | \ | ||
318 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ | ||
319 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ | ||
320 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ | ||
321 | R##_s = X##_s; \ | ||
322 | \ | ||
323 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ | ||
324 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ | ||
325 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ | ||
326 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ | ||
327 | _FP_FRAC_COPY_##wc(R, X); \ | ||
328 | R##_c = X##_c; \ | ||
329 | break; \ | ||
330 | \ | ||
331 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ | ||
332 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ | ||
333 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ | ||
334 | R##_s = Y##_s; \ | ||
335 | \ | ||
336 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ | ||
337 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ | ||
338 | _FP_FRAC_COPY_##wc(R, Y); \ | ||
339 | R##_c = Y##_c; \ | ||
340 | break; \ | ||
341 | \ | ||
342 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ | ||
343 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ | ||
344 | R##_c = FP_CLS_NAN; \ | ||
345 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
346 | break; \ | ||
347 | \ | ||
348 | default: \ | ||
349 | abort(); \ | ||
350 | } \ | ||
351 | } while (0) | ||
352 | |||
353 | |||
354 | /* | ||
355 | * Main division routine. The input values should be cooked. | ||
356 | */ | ||
357 | |||
358 | #define _FP_DIV(fs, wc, R, X, Y) \ | ||
359 | do { \ | ||
360 | R##_s = X##_s ^ Y##_s; \ | ||
361 | switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ | ||
362 | { \ | ||
363 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ | ||
364 | R##_c = FP_CLS_NORMAL; \ | ||
365 | R##_e = X##_e - Y##_e; \ | ||
366 | \ | ||
367 | _FP_DIV_MEAT_##fs(R,X,Y); \ | ||
368 | break; \ | ||
369 | \ | ||
370 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ | ||
371 | _FP_CHOOSENAN(fs, wc, R, X, Y); \ | ||
372 | break; \ | ||
373 | \ | ||
374 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ | ||
375 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ | ||
376 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ | ||
377 | R##_s = X##_s; \ | ||
378 | _FP_FRAC_COPY_##wc(R, X); \ | ||
379 | R##_c = X##_c; \ | ||
380 | break; \ | ||
381 | \ | ||
382 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ | ||
383 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ | ||
384 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ | ||
385 | R##_s = Y##_s; \ | ||
386 | _FP_FRAC_COPY_##wc(R, Y); \ | ||
387 | R##_c = Y##_c; \ | ||
388 | break; \ | ||
389 | \ | ||
390 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ | ||
391 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ | ||
392 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ | ||
393 | R##_c = FP_CLS_ZERO; \ | ||
394 | break; \ | ||
395 | \ | ||
396 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ | ||
397 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ | ||
398 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ | ||
399 | R##_c = FP_CLS_INF; \ | ||
400 | break; \ | ||
401 | \ | ||
402 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ | ||
403 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ | ||
404 | R##_c = FP_CLS_NAN; \ | ||
405 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
406 | break; \ | ||
407 | \ | ||
408 | default: \ | ||
409 | abort(); \ | ||
410 | } \ | ||
411 | } while (0) | ||
412 | |||
413 | |||
414 | /* | ||
415 | * Main differential comparison routine. The inputs should be raw not | ||
416 | * cooked. The return is -1,0,1 for normal values, 2 otherwise. | ||
417 | */ | ||
418 | |||
419 | #define _FP_CMP(fs, wc, ret, X, Y, un) \ | ||
420 | do { \ | ||
421 | /* NANs are unordered */ \ | ||
422 | if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ | ||
423 | || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ | ||
424 | { \ | ||
425 | ret = un; \ | ||
426 | } \ | ||
427 | else \ | ||
428 | { \ | ||
429 | int __x_zero = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \ | ||
430 | int __y_zero = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \ | ||
431 | \ | ||
432 | if (__x_zero && __y_zero) \ | ||
433 | ret = 0; \ | ||
434 | else if (__x_zero) \ | ||
435 | ret = Y##_s ? 1 : -1; \ | ||
436 | else if (__y_zero) \ | ||
437 | ret = X##_s ? -1 : 1; \ | ||
438 | else if (X##_s != Y##_s) \ | ||
439 | ret = X##_s ? -1 : 1; \ | ||
440 | else if (X##_e > Y##_e) \ | ||
441 | ret = X##_s ? -1 : 1; \ | ||
442 | else if (X##_e < Y##_e) \ | ||
443 | ret = X##_s ? 1 : -1; \ | ||
444 | else if (_FP_FRAC_GT_##wc(X, Y)) \ | ||
445 | ret = X##_s ? -1 : 1; \ | ||
446 | else if (_FP_FRAC_GT_##wc(Y, X)) \ | ||
447 | ret = X##_s ? 1 : -1; \ | ||
448 | else \ | ||
449 | ret = 0; \ | ||
450 | } \ | ||
451 | } while (0) | ||
452 | |||
453 | |||
454 | /* Simplification for strict equality. */ | ||
455 | |||
456 | #define _FP_CMP_EQ(fs, wc, ret, X, Y) \ | ||
457 | do { \ | ||
458 | /* NANs are unordered */ \ | ||
459 | if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ | ||
460 | || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ | ||
461 | { \ | ||
462 | ret = 1; \ | ||
463 | } \ | ||
464 | else \ | ||
465 | { \ | ||
466 | ret = !(X##_e == Y##_e \ | ||
467 | && _FP_FRAC_EQ_##wc(X, Y) \ | ||
468 | && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \ | ||
469 | } \ | ||
470 | } while (0) | ||
471 | |||
472 | /* | ||
473 | * Main square root routine. The input value should be cooked. | ||
474 | */ | ||
475 | |||
476 | #define _FP_SQRT(fs, wc, R, X) \ | ||
477 | do { \ | ||
478 | _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \ | ||
479 | _FP_W_TYPE q; \ | ||
480 | switch (X##_c) \ | ||
481 | { \ | ||
482 | case FP_CLS_NAN: \ | ||
483 | R##_s = 0; \ | ||
484 | R##_c = FP_CLS_NAN; \ | ||
485 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
486 | break; \ | ||
487 | case FP_CLS_INF: \ | ||
488 | if (X##_s) \ | ||
489 | { \ | ||
490 | R##_s = 0; \ | ||
491 | R##_c = FP_CLS_NAN; /* sNAN */ \ | ||
492 | } \ | ||
493 | else \ | ||
494 | { \ | ||
495 | R##_s = 0; \ | ||
496 | R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ | ||
497 | } \ | ||
498 | break; \ | ||
499 | case FP_CLS_ZERO: \ | ||
500 | R##_s = X##_s; \ | ||
501 | R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ | ||
502 | break; \ | ||
503 | case FP_CLS_NORMAL: \ | ||
504 | R##_s = 0; \ | ||
505 | if (X##_s) \ | ||
506 | { \ | ||
507 | R##_c = FP_CLS_NAN; /* sNAN */ \ | ||
508 | break; \ | ||
509 | } \ | ||
510 | R##_c = FP_CLS_NORMAL; \ | ||
511 | if (X##_e & 1) \ | ||
512 | _FP_FRAC_SLL_##wc(X, 1); \ | ||
513 | R##_e = X##_e >> 1; \ | ||
514 | _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \ | ||
515 | _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \ | ||
516 | q = _FP_OVERFLOW_##fs; \ | ||
517 | _FP_FRAC_SLL_##wc(X, 1); \ | ||
518 | _FP_SQRT_MEAT_##wc(R, S, T, X, q); \ | ||
519 | _FP_FRAC_SRL_##wc(R, 1); \ | ||
520 | } \ | ||
521 | } while (0) | ||
522 | |||
523 | /* | ||
524 | * Convert from FP to integer | ||
525 | */ | ||
526 | |||
527 | /* "When a NaN, infinity, large positive argument >= 2147483648.0, or | ||
528 | * large negative argument <= -2147483649.0 is converted to an integer, | ||
529 | * the invalid_current bit...should be set and fp_exception_IEEE_754 should | ||
530 | * be raised. If the floating point invalid trap is disabled, no trap occurs | ||
531 | * and a numerical result is generated: if the sign bit of the operand | ||
532 | * is 0, the result is 2147483647; if the sign bit of the operand is 1, | ||
533 | * the result is -2147483648." | ||
534 | * Similarly for conversion to extended ints, except that the boundaries | ||
535 | * are >= 2^63, <= -(2^63 + 1), and the results are 2^63 + 1 for s=0 and | ||
536 | * -2^63 for s=1. | ||
537 | * -- SPARC Architecture Manual V9, Appendix B, which specifies how | ||
538 | * SPARCs resolve implementation dependencies in the IEEE-754 spec. | ||
539 | * I don't believe that the code below follows this. I'm not even sure | ||
540 | * it's right! | ||
541 | * It doesn't cope with needing to convert to an n bit integer when there | ||
542 | * is no n bit integer type. Fortunately gcc provides long long so this | ||
543 | * isn't a problem for sparc32. | ||
544 | * I have, however, fixed its NaN handling to conform as above. | ||
545 | * -- PMM 02/1998 | ||
546 | * NB: rsigned is not 'is r declared signed?' but 'should the value stored | ||
547 | * in r be signed or unsigned?'. r is always(?) declared unsigned. | ||
548 | * Comments below are mine, BTW -- PMM | ||
549 | */ | ||
550 | #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \ | ||
551 | do { \ | ||
552 | switch (X##_c) \ | ||
553 | { \ | ||
554 | case FP_CLS_NORMAL: \ | ||
555 | if (X##_e < 0) \ | ||
556 | { \ | ||
557 | /* case FP_CLS_NAN: see above! */ \ | ||
558 | case FP_CLS_ZERO: \ | ||
559 | r = 0; \ | ||
560 | } \ | ||
561 | else if (X##_e >= rsize - (rsigned != 0)) \ | ||
562 | { /* overflow */ \ | ||
563 | case FP_CLS_NAN: \ | ||
564 | case FP_CLS_INF: \ | ||
565 | if (rsigned) \ | ||
566 | { \ | ||
567 | r = 1; \ | ||
568 | r <<= rsize - 1; \ | ||
569 | r -= 1 - X##_s; \ | ||
570 | } \ | ||
571 | else \ | ||
572 | { \ | ||
573 | r = 0; \ | ||
574 | if (!X##_s) \ | ||
575 | r = ~r; \ | ||
576 | } \ | ||
577 | } \ | ||
578 | else \ | ||
579 | { \ | ||
580 | if (_FP_W_TYPE_SIZE*wc < rsize) \ | ||
581 | { \ | ||
582 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
583 | r <<= X##_e - _FP_WFRACBITS_##fs; \ | ||
584 | } \ | ||
585 | else \ | ||
586 | { \ | ||
587 | if (X##_e >= _FP_WFRACBITS_##fs) \ | ||
588 | _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));\ | ||
589 | else \ | ||
590 | _FP_FRAC_SRL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));\ | ||
591 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
592 | } \ | ||
593 | if (rsigned && X##_s) \ | ||
594 | r = -r; \ | ||
595 | } \ | ||
596 | break; \ | ||
597 | } \ | ||
598 | } while (0) | ||
599 | |||
600 | #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \ | ||
601 | do { \ | ||
602 | if (r) \ | ||
603 | { \ | ||
604 | X##_c = FP_CLS_NORMAL; \ | ||
605 | \ | ||
606 | if ((X##_s = (r < 0))) \ | ||
607 | r = -r; \ | ||
608 | /* Note that `r' is now considered unsigned, so we don't have \ | ||
609 | to worry about the single signed overflow case. */ \ | ||
610 | \ | ||
611 | if (rsize <= _FP_W_TYPE_SIZE) \ | ||
612 | __FP_CLZ(X##_e, r); \ | ||
613 | else \ | ||
614 | __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), \ | ||
615 | (_FP_W_TYPE)r); \ | ||
616 | if (rsize < _FP_W_TYPE_SIZE) \ | ||
617 | X##_e -= (_FP_W_TYPE_SIZE - rsize); \ | ||
618 | X##_e = rsize - X##_e - 1; \ | ||
619 | \ | ||
620 | if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \ | ||
621 | __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize); \ | ||
622 | r &= ~((_FP_W_TYPE)1 << X##_e); \ | ||
623 | _FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize); \ | ||
624 | _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \ | ||
625 | } \ | ||
626 | else \ | ||
627 | { \ | ||
628 | X##_c = FP_CLS_ZERO, X##_s = 0; \ | ||
629 | } \ | ||
630 | } while (0) | ||
631 | |||
632 | |||
633 | #define FP_CONV(dfs,sfs,dwc,swc,D,S) \ | ||
634 | do { \ | ||
635 | _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \ | ||
636 | D##_e = S##_e; \ | ||
637 | D##_c = S##_c; \ | ||
638 | D##_s = S##_s; \ | ||
639 | } while (0) | ||
640 | |||
641 | /* | ||
642 | * Helper primitives. | ||
643 | */ | ||
644 | |||
645 | /* Count leading zeros in a word. */ | ||
646 | |||
647 | #ifndef __FP_CLZ | ||
648 | #if _FP_W_TYPE_SIZE < 64 | ||
649 | /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */ | ||
650 | #define __FP_CLZ(r, x) \ | ||
651 | do { \ | ||
652 | _FP_W_TYPE _t = (x); \ | ||
653 | r = _FP_W_TYPE_SIZE - 1; \ | ||
654 | if (_t > 0xffff) r -= 16; \ | ||
655 | if (_t > 0xffff) _t >>= 16; \ | ||
656 | if (_t > 0xff) r -= 8; \ | ||
657 | if (_t > 0xff) _t >>= 8; \ | ||
658 | if (_t & 0xf0) r -= 4; \ | ||
659 | if (_t & 0xf0) _t >>= 4; \ | ||
660 | if (_t & 0xc) r -= 2; \ | ||
661 | if (_t & 0xc) _t >>= 2; \ | ||
662 | if (_t & 0x2) r -= 1; \ | ||
663 | } while (0) | ||
664 | #else /* not _FP_W_TYPE_SIZE < 64 */ | ||
665 | #define __FP_CLZ(r, x) \ | ||
666 | do { \ | ||
667 | _FP_W_TYPE _t = (x); \ | ||
668 | r = _FP_W_TYPE_SIZE - 1; \ | ||
669 | if (_t > 0xffffffff) r -= 32; \ | ||
670 | if (_t > 0xffffffff) _t >>= 32; \ | ||
671 | if (_t > 0xffff) r -= 16; \ | ||
672 | if (_t > 0xffff) _t >>= 16; \ | ||
673 | if (_t > 0xff) r -= 8; \ | ||
674 | if (_t > 0xff) _t >>= 8; \ | ||
675 | if (_t & 0xf0) r -= 4; \ | ||
676 | if (_t & 0xf0) _t >>= 4; \ | ||
677 | if (_t & 0xc) r -= 2; \ | ||
678 | if (_t & 0xc) _t >>= 2; \ | ||
679 | if (_t & 0x2) r -= 1; \ | ||
680 | } while (0) | ||
681 | #endif /* not _FP_W_TYPE_SIZE < 64 */ | ||
682 | #endif /* ndef __FP_CLZ */ | ||
683 | |||
684 | #define _FP_DIV_HELP_imm(q, r, n, d) \ | ||
685 | do { \ | ||
686 | q = n / d, r = n % d; \ | ||
687 | } while (0) | ||
688 | |||