- Linus: drop support for old-style Makefiles entirely. Big.
[davej-history.git] / include / math-emu / op-common.h
blobe03e40e656bc3943994031587477384cd628e3b3
1 /* Software floating-point emulation. Common operations.
2 Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Richard Henderson (rth@cygnus.com),
5 Jakub Jelinek (jj@ultra.linux.cz),
6 David S. Miller (davem@redhat.com) and
7 Peter Maydell (pmaydell@chiark.greenend.org.uk).
9 The GNU C Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
14 The GNU C Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with the GNU C Library; see the file COPYING.LIB. If
21 not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 #define _FP_DECL(wc, X) \
25 _FP_I_TYPE X##_c, X##_s, X##_e; \
26 _FP_FRAC_DECL_##wc(X)
29 * Finish truely unpacking a native fp value by classifying the kind
30 * of fp value and normalizing both the exponent and the fraction.
33 #define _FP_UNPACK_CANONICAL(fs, wc, X) \
34 do { \
35 switch (X##_e) \
36 { \
37 default: \
38 _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \
39 _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
40 X##_e -= _FP_EXPBIAS_##fs; \
41 X##_c = FP_CLS_NORMAL; \
42 break; \
44 case 0: \
45 if (_FP_FRAC_ZEROP_##wc(X)) \
46 X##_c = FP_CLS_ZERO; \
47 else \
48 { \
49 /* a denormalized number */ \
50 _FP_I_TYPE _shift; \
51 _FP_FRAC_CLZ_##wc(_shift, X); \
52 _shift -= _FP_FRACXBITS_##fs; \
53 _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \
54 X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
55 X##_c = FP_CLS_NORMAL; \
56 FP_SET_EXCEPTION(FP_EX_DENORM); \
57 if (FP_DENORM_ZERO) \
58 { \
59 FP_SET_EXCEPTION(FP_EX_INEXACT); \
60 X##_c = FP_CLS_ZERO; \
61 } \
62 } \
63 break; \
65 case _FP_EXPMAX_##fs: \
66 if (_FP_FRAC_ZEROP_##wc(X)) \
67 X##_c = FP_CLS_INF; \
68 else \
69 { \
70 X##_c = FP_CLS_NAN; \
71 /* Check for signaling NaN */ \
72 if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
73 FP_SET_EXCEPTION(FP_EX_INVALID); \
74 } \
75 break; \
76 } \
77 } while (0)
80 * Before packing the bits back into the native fp result, take care
81 * of such mundane things as rounding and overflow. Also, for some
82 * kinds of fp values, the original parts may not have been fully
83 * extracted -- but that is ok, we can regenerate them now.
86 #define _FP_PACK_CANONICAL(fs, wc, X) \
87 do { \
88 switch (X##_c) \
89 { \
90 case FP_CLS_NORMAL: \
91 X##_e += _FP_EXPBIAS_##fs; \
92 if (X##_e > 0) \
93 { \
94 _FP_ROUND(wc, X); \
95 if (_FP_FRAC_OVERP_##wc(fs, X)) \
96 { \
97 _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \
98 X##_e++; \
99 } \
100 else \
101 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
102 if (X##_e >= _FP_EXPMAX_##fs) \
104 /* overflow */ \
105 switch (FP_ROUNDMODE) \
107 case FP_RND_NEAREST: \
108 X##_c = FP_CLS_INF; \
109 break; \
110 case FP_RND_PINF: \
111 if (!X##_s) X##_c = FP_CLS_INF; \
112 break; \
113 case FP_RND_MINF: \
114 if (X##_s) X##_c = FP_CLS_INF; \
115 break; \
117 if (X##_c == FP_CLS_INF) \
119 /* Overflow to infinity */ \
120 X##_e = _FP_EXPMAX_##fs; \
121 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
123 else \
125 /* Overflow to maximum normal */ \
126 X##_e = _FP_EXPMAX_##fs - 1; \
127 _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \
129 FP_SET_EXCEPTION(FP_EX_OVERFLOW); \
130 FP_SET_EXCEPTION(FP_EX_INEXACT); \
133 else \
135 /* we've got a denormalized number */ \
136 X##_e = -X##_e + 1; \
137 if (X##_e <= _FP_WFRACBITS_##fs) \
139 _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
140 _FP_ROUND(wc, X); \
141 if (_FP_FRAC_HIGH_##fs(X) \
142 & (_FP_OVERFLOW_##fs >> 1)) \
144 X##_e = 1; \
145 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
147 else \
149 X##_e = 0; \
150 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
151 FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
154 else \
156 /* underflow to zero */ \
157 X##_e = 0; \
158 if (!_FP_FRAC_ZEROP_##wc(X)) \
160 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
161 _FP_ROUND(wc, X); \
162 _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \
164 FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
167 break; \
169 case FP_CLS_ZERO: \
170 X##_e = 0; \
171 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
172 break; \
174 case FP_CLS_INF: \
175 X##_e = _FP_EXPMAX_##fs; \
176 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
177 break; \
179 case FP_CLS_NAN: \
180 X##_e = _FP_EXPMAX_##fs; \
181 if (!_FP_KEEPNANFRACP) \
183 _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
184 X##_s = _FP_NANSIGN_##fs; \
186 else \
187 _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
188 break; \
190 } while (0)
192 /* This one accepts raw argument and not cooked, returns
193 * 1 if X is a signaling NaN.
195 #define _FP_ISSIGNAN(fs, wc, X) \
196 ({ \
197 int __ret = 0; \
198 if (X##_e == _FP_EXPMAX_##fs) \
200 if (!_FP_FRAC_ZEROP_##wc(X) \
201 && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
202 __ret = 1; \
204 __ret; \
212 * Main addition routine. The input values should be cooked.
215 #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \
216 do { \
217 switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
219 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
221 /* shift the smaller number so that its exponent matches the larger */ \
222 _FP_I_TYPE diff = X##_e - Y##_e; \
224 if (diff < 0) \
226 diff = -diff; \
227 if (diff <= _FP_WFRACBITS_##fs) \
228 _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \
229 else if (!_FP_FRAC_ZEROP_##wc(X)) \
230 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
231 R##_e = Y##_e; \
233 else \
235 if (diff > 0) \
237 if (diff <= _FP_WFRACBITS_##fs) \
238 _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \
239 else if (!_FP_FRAC_ZEROP_##wc(Y)) \
240 _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
242 R##_e = X##_e; \
245 R##_c = FP_CLS_NORMAL; \
247 if (X##_s == Y##_s) \
249 R##_s = X##_s; \
250 _FP_FRAC_ADD_##wc(R, X, Y); \
251 if (_FP_FRAC_OVERP_##wc(fs, R)) \
253 _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
254 R##_e++; \
257 else \
259 R##_s = X##_s; \
260 _FP_FRAC_SUB_##wc(R, X, Y); \
261 if (_FP_FRAC_ZEROP_##wc(R)) \
263 /* return an exact zero */ \
264 if (FP_ROUNDMODE == FP_RND_MINF) \
265 R##_s |= Y##_s; \
266 else \
267 R##_s &= Y##_s; \
268 R##_c = FP_CLS_ZERO; \
270 else \
272 if (_FP_FRAC_NEGP_##wc(R)) \
274 _FP_FRAC_SUB_##wc(R, Y, X); \
275 R##_s = Y##_s; \
278 /* renormalize after subtraction */ \
279 _FP_FRAC_CLZ_##wc(diff, R); \
280 diff -= _FP_WFRACXBITS_##fs; \
281 if (diff) \
283 R##_e -= diff; \
284 _FP_FRAC_SLL_##wc(R, diff); \
288 break; \
291 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
292 _FP_CHOOSENAN(fs, wc, R, X, Y, OP); \
293 break; \
295 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
296 R##_e = X##_e; \
297 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
298 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
299 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
300 _FP_FRAC_COPY_##wc(R, X); \
301 R##_s = X##_s; \
302 R##_c = X##_c; \
303 break; \
305 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
306 R##_e = Y##_e; \
307 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
308 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
309 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
310 _FP_FRAC_COPY_##wc(R, Y); \
311 R##_s = Y##_s; \
312 R##_c = Y##_c; \
313 break; \
315 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
316 if (X##_s != Y##_s) \
318 /* +INF + -INF => NAN */ \
319 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
320 R##_s = _FP_NANSIGN_##fs; \
321 R##_c = FP_CLS_NAN; \
322 FP_SET_EXCEPTION(FP_EX_INVALID); \
323 break; \
325 /* FALLTHRU */ \
327 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
328 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
329 R##_s = X##_s; \
330 R##_c = FP_CLS_INF; \
331 break; \
333 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
334 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
335 R##_s = Y##_s; \
336 R##_c = FP_CLS_INF; \
337 break; \
339 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
340 /* make sure the sign is correct */ \
341 if (FP_ROUNDMODE == FP_RND_MINF) \
342 R##_s = X##_s | Y##_s; \
343 else \
344 R##_s = X##_s & Y##_s; \
345 R##_c = FP_CLS_ZERO; \
346 break; \
348 default: \
349 abort(); \
351 } while (0)
353 #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
354 #define _FP_SUB(fs, wc, R, X, Y) \
355 do { \
356 if (Y##_c != FP_CLS_NAN) Y##_s ^= 1; \
357 _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \
358 } while (0)
362 * Main negation routine. FIXME -- when we care about setting exception
363 * bits reliably, this will not do. We should examine all of the fp classes.
366 #define _FP_NEG(fs, wc, R, X) \
367 do { \
368 _FP_FRAC_COPY_##wc(R, X); \
369 R##_c = X##_c; \
370 R##_e = X##_e; \
371 R##_s = 1 ^ X##_s; \
372 } while (0)
376 * Main multiplication routine. The input values should be cooked.
379 #define _FP_MUL(fs, wc, R, X, Y) \
380 do { \
381 R##_s = X##_s ^ Y##_s; \
382 switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
384 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
385 R##_c = FP_CLS_NORMAL; \
386 R##_e = X##_e + Y##_e + 1; \
388 _FP_MUL_MEAT_##fs(R,X,Y); \
390 if (_FP_FRAC_OVERP_##wc(fs, R)) \
391 _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
392 else \
393 R##_e--; \
394 break; \
396 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
397 _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \
398 break; \
400 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
401 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
402 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
403 R##_s = X##_s; \
405 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
406 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
407 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
408 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
409 _FP_FRAC_COPY_##wc(R, X); \
410 R##_c = X##_c; \
411 break; \
413 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
414 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
415 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
416 R##_s = Y##_s; \
418 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
419 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
420 _FP_FRAC_COPY_##wc(R, Y); \
421 R##_c = Y##_c; \
422 break; \
424 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
425 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
426 R##_s = _FP_NANSIGN_##fs; \
427 R##_c = FP_CLS_NAN; \
428 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
429 FP_SET_EXCEPTION(FP_EX_INVALID); \
430 break; \
432 default: \
433 abort(); \
435 } while (0)
439 * Main division routine. The input values should be cooked.
442 #define _FP_DIV(fs, wc, R, X, Y) \
443 do { \
444 R##_s = X##_s ^ Y##_s; \
445 switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
447 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
448 R##_c = FP_CLS_NORMAL; \
449 R##_e = X##_e - Y##_e; \
451 _FP_DIV_MEAT_##fs(R,X,Y); \
452 break; \
454 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
455 _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \
456 break; \
458 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
459 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
460 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
461 R##_s = X##_s; \
462 _FP_FRAC_COPY_##wc(R, X); \
463 R##_c = X##_c; \
464 break; \
466 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
467 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
468 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
469 R##_s = Y##_s; \
470 _FP_FRAC_COPY_##wc(R, Y); \
471 R##_c = Y##_c; \
472 break; \
474 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
475 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
476 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
477 R##_c = FP_CLS_ZERO; \
478 break; \
480 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
481 FP_SET_EXCEPTION(FP_EX_DIVZERO); \
482 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
483 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
484 R##_c = FP_CLS_INF; \
485 break; \
487 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
488 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
489 R##_s = _FP_NANSIGN_##fs; \
490 R##_c = FP_CLS_NAN; \
491 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
492 FP_SET_EXCEPTION(FP_EX_INVALID); \
493 break; \
495 default: \
496 abort(); \
498 } while (0)
502 * Main differential comparison routine. The inputs should be raw not
503 * cooked. The return is -1,0,1 for normal values, 2 otherwise.
506 #define _FP_CMP(fs, wc, ret, X, Y, un) \
507 do { \
508 /* NANs are unordered */ \
509 if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
510 || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
512 ret = un; \
514 else \
516 int __is_zero_x; \
517 int __is_zero_y; \
519 __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
520 __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
522 if (__is_zero_x && __is_zero_y) \
523 ret = 0; \
524 else if (__is_zero_x) \
525 ret = Y##_s ? 1 : -1; \
526 else if (__is_zero_y) \
527 ret = X##_s ? -1 : 1; \
528 else if (X##_s != Y##_s) \
529 ret = X##_s ? -1 : 1; \
530 else if (X##_e > Y##_e) \
531 ret = X##_s ? -1 : 1; \
532 else if (X##_e < Y##_e) \
533 ret = X##_s ? 1 : -1; \
534 else if (_FP_FRAC_GT_##wc(X, Y)) \
535 ret = X##_s ? -1 : 1; \
536 else if (_FP_FRAC_GT_##wc(Y, X)) \
537 ret = X##_s ? 1 : -1; \
538 else \
539 ret = 0; \
541 } while (0)
544 /* Simplification for strict equality. */
546 #define _FP_CMP_EQ(fs, wc, ret, X, Y) \
547 do { \
548 /* NANs are unordered */ \
549 if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
550 || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
552 ret = 1; \
554 else \
556 ret = !(X##_e == Y##_e \
557 && _FP_FRAC_EQ_##wc(X, Y) \
558 && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
560 } while (0)
563 * Main square root routine. The input value should be cooked.
566 #define _FP_SQRT(fs, wc, R, X) \
567 do { \
568 _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
569 _FP_W_TYPE q; \
570 switch (X##_c) \
572 case FP_CLS_NAN: \
573 _FP_FRAC_COPY_##wc(R, X); \
574 R##_s = X##_s; \
575 R##_c = FP_CLS_NAN; \
576 break; \
577 case FP_CLS_INF: \
578 if (X##_s) \
580 R##_s = _FP_NANSIGN_##fs; \
581 R##_c = FP_CLS_NAN; /* NAN */ \
582 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
583 FP_SET_EXCEPTION(FP_EX_INVALID); \
585 else \
587 R##_s = 0; \
588 R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
590 break; \
591 case FP_CLS_ZERO: \
592 R##_s = X##_s; \
593 R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
594 break; \
595 case FP_CLS_NORMAL: \
596 R##_s = 0; \
597 if (X##_s) \
599 R##_c = FP_CLS_NAN; /* sNAN */ \
600 R##_s = _FP_NANSIGN_##fs; \
601 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
602 FP_SET_EXCEPTION(FP_EX_INVALID); \
603 break; \
605 R##_c = FP_CLS_NORMAL; \
606 if (X##_e & 1) \
607 _FP_FRAC_SLL_##wc(X, 1); \
608 R##_e = X##_e >> 1; \
609 _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
610 _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
611 q = _FP_OVERFLOW_##fs >> 1; \
612 _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
614 } while (0)
617 * Convert from FP to integer
620 /* RSIGNED can have following values:
621 * 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
622 * the result is either 0 or (2^rsize)-1 depending on the sign in such case.
623 * 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
624 * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
625 * on the sign in such case.
626 * 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
627 * set plus the result is truncated to fit into destination.
628 * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
629 * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
630 * on the sign in such case.
632 #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
633 do { \
634 switch (X##_c) \
636 case FP_CLS_NORMAL: \
637 if (X##_e < 0) \
639 FP_SET_EXCEPTION(FP_EX_INEXACT); \
640 case FP_CLS_ZERO: \
641 r = 0; \
643 else if (X##_e >= rsize - (rsigned > 0 || X##_s) \
644 || (!rsigned && X##_s)) \
645 { /* overflow */ \
646 case FP_CLS_NAN: \
647 case FP_CLS_INF: \
648 if (rsigned == 2) \
650 if (X##_c != FP_CLS_NORMAL \
651 || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs) \
652 r = 0; \
653 else \
655 _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
656 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
659 else if (rsigned) \
661 r = 1; \
662 r <<= rsize - 1; \
663 r -= 1 - X##_s; \
665 else \
667 r = 0; \
668 if (X##_s) \
669 r = ~r; \
671 FP_SET_EXCEPTION(FP_EX_INVALID); \
673 else \
675 if (_FP_W_TYPE_SIZE*wc < rsize) \
677 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
678 r <<= X##_e - _FP_WFRACBITS_##fs; \
680 else \
682 if (X##_e >= _FP_WFRACBITS_##fs) \
683 _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
684 else if (X##_e < _FP_WFRACBITS_##fs - 1) \
686 _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2), \
687 _FP_WFRACBITS_##fs); \
688 if (_FP_FRAC_LOW_##wc(X) & 1) \
689 FP_SET_EXCEPTION(FP_EX_INEXACT); \
690 _FP_FRAC_SRL_##wc(X, 1); \
692 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
694 if (rsigned && X##_s) \
695 r = -r; \
697 break; \
699 } while (0)
701 #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \
702 do { \
703 r = 0; \
704 switch (X##_c) \
706 case FP_CLS_NORMAL: \
707 if (X##_e >= _FP_FRACBITS_##fs - 1) \
709 if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs) \
711 if (X##_e >= _FP_WFRACBITS_##fs - 1) \
713 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
714 r <<= X##_e - _FP_WFRACBITS_##fs + 1; \
716 else \
718 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e \
719 + _FP_FRACBITS_##fs - 1); \
720 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
724 else \
726 if (X##_e <= -_FP_WORKBITS - 1) \
727 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
728 else \
729 _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e, \
730 _FP_WFRACBITS_##fs); \
731 _FP_ROUND(wc, X); \
732 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
733 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
735 if (rsigned && X##_s) \
736 r = -r; \
737 if (X##_e >= rsize - (rsigned > 0 || X##_s) \
738 || (!rsigned && X##_s)) \
739 { /* overflow */ \
740 case FP_CLS_NAN: \
741 case FP_CLS_INF: \
742 if (!rsigned) \
744 r = 0; \
745 if (X##_s) \
746 r = ~r; \
748 else if (rsigned != 2) \
750 r = 1; \
751 r <<= rsize - 1; \
752 r -= 1 - X##_s; \
754 FP_SET_EXCEPTION(FP_EX_INVALID); \
756 break; \
757 case FP_CLS_ZERO: \
758 break; \
760 } while (0)
762 #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
763 do { \
764 if (r) \
766 X##_c = FP_CLS_NORMAL; \
768 if ((X##_s = (r < 0))) \
769 r = -r; \
771 if (rsize <= _FP_W_TYPE_SIZE) \
772 __FP_CLZ(X##_e, r); \
773 else \
774 __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), \
775 (_FP_W_TYPE)r); \
776 if (rsize < _FP_W_TYPE_SIZE) \
777 X##_e -= (_FP_W_TYPE_SIZE - rsize); \
778 X##_e = rsize - X##_e - 1; \
780 if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \
781 __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize); \
782 r &= ~((rtype)1 << X##_e); \
783 _FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize); \
784 _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
786 else \
788 X##_c = FP_CLS_ZERO, X##_s = 0; \
790 } while (0)
793 #define FP_CONV(dfs,sfs,dwc,swc,D,S) \
794 do { \
795 _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
796 D##_e = S##_e; \
797 D##_c = S##_c; \
798 D##_s = S##_s; \
799 } while (0)
802 * Helper primitives.
805 /* Count leading zeros in a word. */
807 #ifndef __FP_CLZ
808 #if _FP_W_TYPE_SIZE < 64
809 /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
810 #define __FP_CLZ(r, x) \
811 do { \
812 _FP_W_TYPE _t = (x); \
813 r = _FP_W_TYPE_SIZE - 1; \
814 if (_t > 0xffff) r -= 16; \
815 if (_t > 0xffff) _t >>= 16; \
816 if (_t > 0xff) r -= 8; \
817 if (_t > 0xff) _t >>= 8; \
818 if (_t & 0xf0) r -= 4; \
819 if (_t & 0xf0) _t >>= 4; \
820 if (_t & 0xc) r -= 2; \
821 if (_t & 0xc) _t >>= 2; \
822 if (_t & 0x2) r -= 1; \
823 } while (0)
824 #else /* not _FP_W_TYPE_SIZE < 64 */
825 #define __FP_CLZ(r, x) \
826 do { \
827 _FP_W_TYPE _t = (x); \
828 r = _FP_W_TYPE_SIZE - 1; \
829 if (_t > 0xffffffff) r -= 32; \
830 if (_t > 0xffffffff) _t >>= 32; \
831 if (_t > 0xffff) r -= 16; \
832 if (_t > 0xffff) _t >>= 16; \
833 if (_t > 0xff) r -= 8; \
834 if (_t > 0xff) _t >>= 8; \
835 if (_t & 0xf0) r -= 4; \
836 if (_t & 0xf0) _t >>= 4; \
837 if (_t & 0xc) r -= 2; \
838 if (_t & 0xc) _t >>= 2; \
839 if (_t & 0x2) r -= 1; \
840 } while (0)
841 #endif /* not _FP_W_TYPE_SIZE < 64 */
842 #endif /* ndef __FP_CLZ */
844 #define _FP_DIV_HELP_imm(q, r, n, d) \
845 do { \
846 q = n / d, r = n % d; \
847 } while (0)