* soft-fp/soft-fp.h (FP_EX_UNDERFLOW): Define to 0.
[platform/upstream/glibc.git] / soft-fp / op-common.h
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).
8
9    The GNU C Library is free software; you can redistribute it and/or
10    modify it under the terms of the GNU Lesser General Public
11    License as published by the Free Software Foundation; either
12    version 2.1 of the License, or (at your option) any later version.
13
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    Lesser General Public License for more details.
18
19    You should have received a copy of the GNU Lesser General Public
20    License along with the GNU C Library; if not, write to the Free
21    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22    02111-1307 USA.  */
23
24 #define _FP_DECL(wc, X)                 \
25   _FP_I_TYPE X##_c, X##_s, X##_e;       \
26   _FP_FRAC_DECL_##wc(X)
27
28 /*
29  * Finish truely unpacking a native fp value by classifying the kind
30  * of fp value and normalizing both the exponent and the fraction.
31  */
32
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;                                                              \
43                                                                         \
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       }                                                                 \
58     break;                                                              \
59                                                                         \
60   case _FP_EXPMAX_##fs:                                                 \
61     if (_FP_FRAC_ZEROP_##wc(X))                                         \
62       X##_c = FP_CLS_INF;                                               \
63     else                                                                \
64       {                                                                 \
65         X##_c = FP_CLS_NAN;                                             \
66         /* Check for signaling NaN */                                   \
67         if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))            \
68           FP_SET_EXCEPTION(FP_EX_INVALID);                              \
69       }                                                                 \
70     break;                                                              \
71   }                                                                     \
72 } while (0)
73
74 /*
75  * Before packing the bits back into the native fp result, take care
76  * of such mundane things as rounding and overflow.  Also, for some
77  * kinds of fp values, the original parts may not have been fully
78  * extracted -- but that is ok, we can regenerate them now.
79  */
80
81 #define _FP_PACK_CANONICAL(fs, wc, X)                           \
82 do {                                                            \
83   switch (X##_c)                                                \
84   {                                                             \
85   case FP_CLS_NORMAL:                                           \
86     X##_e += _FP_EXPBIAS_##fs;                                  \
87     if (X##_e > 0)                                              \
88       {                                                         \
89         _FP_ROUND(wc, X);                                       \
90         if (_FP_FRAC_OVERP_##wc(fs, X))                         \
91           {                                                     \
92             _FP_FRAC_CLEAR_OVERP_##wc(fs, X);                   \
93             X##_e++;                                            \
94           }                                                     \
95         _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                     \
96         if (X##_e >= _FP_EXPMAX_##fs)                           \
97           {                                                     \
98             /* overflow */                                      \
99             switch (FP_ROUNDMODE)                               \
100               {                                                 \
101               case FP_RND_NEAREST:                              \
102                 X##_c = FP_CLS_INF;                             \
103                 break;                                          \
104               case FP_RND_PINF:                                 \
105                 if (!X##_s) X##_c = FP_CLS_INF;                 \
106                 break;                                          \
107               case FP_RND_MINF:                                 \
108                 if (X##_s) X##_c = FP_CLS_INF;                  \
109                 break;                                          \
110               }                                                 \
111             if (X##_c == FP_CLS_INF)                            \
112               {                                                 \
113                 /* Overflow to infinity */                      \
114                 X##_e = _FP_EXPMAX_##fs;                        \
115                 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
116               }                                                 \
117             else                                                \
118               {                                                 \
119                 /* Overflow to maximum normal */                \
120                 X##_e = _FP_EXPMAX_##fs - 1;                    \
121                 _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);         \
122               }                                                 \
123             FP_SET_EXCEPTION(FP_EX_OVERFLOW);                   \
124             FP_SET_EXCEPTION(FP_EX_INEXACT);                    \
125           }                                                     \
126       }                                                         \
127     else                                                        \
128       {                                                         \
129         /* we've got a denormalized number */                   \
130         X##_e = -X##_e + 1;                                     \
131         if (X##_e <= _FP_WFRACBITS_##fs)                        \
132           {                                                     \
133             _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);    \
134             _FP_ROUND(wc, X);                                   \
135             if (_FP_FRAC_HIGH_##fs(X)                           \
136                 & (_FP_OVERFLOW_##fs >> 1))                     \
137               {                                                 \
138                 X##_e = 1;                                      \
139                 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
140               }                                                 \
141             else                                                \
142               {                                                 \
143                 X##_e = 0;                                      \
144                 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);             \
145                 FP_SET_EXCEPTION(FP_EX_UNDERFLOW);              \
146               }                                                 \
147           }                                                     \
148         else                                                    \
149           {                                                     \
150             /* underflow to zero */                             \
151             X##_e = 0;                                          \
152             if (!_FP_FRAC_ZEROP_##wc(X))                        \
153               {                                                 \
154                 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);         \
155                 _FP_ROUND(wc, X);                               \
156                 _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);        \
157               }                                                 \
158             FP_SET_EXCEPTION(FP_EX_UNDERFLOW);                  \
159           }                                                     \
160       }                                                         \
161     break;                                                      \
162                                                                 \
163   case FP_CLS_ZERO:                                             \
164     X##_e = 0;                                                  \
165     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                    \
166     break;                                                      \
167                                                                 \
168   case FP_CLS_INF:                                              \
169     X##_e = _FP_EXPMAX_##fs;                                    \
170     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                    \
171     break;                                                      \
172                                                                 \
173   case FP_CLS_NAN:                                              \
174     X##_e = _FP_EXPMAX_##fs;                                    \
175     if (!_FP_KEEPNANFRACP)                                      \
176       {                                                         \
177         _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);                 \
178         X##_s = _FP_NANSIGN_##fs;                               \
179       }                                                         \
180     else                                                        \
181       _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;            \
182     break;                                                      \
183   }                                                             \
184 } while (0)
185
186 /* This one accepts raw argument and not cooked,  returns
187  * 1 if X is a signaling NaN.
188  */
189 #define _FP_ISSIGNAN(fs, wc, X)                                 \
190 ({                                                              \
191   int __ret = 0;                                                \
192   if (X##_e == _FP_EXPMAX_##fs)                                 \
193     {                                                           \
194       if (!_FP_FRAC_ZEROP_##wc(X)                               \
195           && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))   \
196         __ret = 1;                                              \
197     }                                                           \
198   __ret;                                                        \
199 })
200
201
202
203
204
205 /*
206  * Main addition routine.  The input values should be cooked.
207  */
208
209 #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)                                \
210 do {                                                                         \
211   switch (_FP_CLS_COMBINE(X##_c, Y##_c))                                     \
212   {                                                                          \
213   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):                         \
214     {                                                                        \
215       /* shift the smaller number so that its exponent matches the larger */ \
216       _FP_I_TYPE diff = X##_e - Y##_e;                                       \
217                                                                              \
218       if (diff < 0)                                                          \
219         {                                                                    \
220           diff = -diff;                                                      \
221           if (diff <= _FP_WFRACBITS_##fs)                                    \
222             _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);                  \
223           else if (!_FP_FRAC_ZEROP_##wc(X))                                  \
224             _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                          \
225           R##_e = Y##_e;                                                     \
226         }                                                                    \
227       else                                                                   \
228         {                                                                    \
229           if (diff > 0)                                                      \
230             {                                                                \
231               if (diff <= _FP_WFRACBITS_##fs)                                \
232                 _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);              \
233               else if (!_FP_FRAC_ZEROP_##wc(Y))                              \
234                 _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);                      \
235             }                                                                \
236           R##_e = X##_e;                                                     \
237         }                                                                    \
238                                                                              \
239       R##_c = FP_CLS_NORMAL;                                                 \
240                                                                              \
241       if (X##_s == Y##_s)                                                    \
242         {                                                                    \
243           R##_s = X##_s;                                                     \
244           _FP_FRAC_ADD_##wc(R, X, Y);                                        \
245           if (_FP_FRAC_OVERP_##wc(fs, R))                                    \
246             {                                                                \
247               _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);                   \
248               R##_e++;                                                       \
249             }                                                                \
250         }                                                                    \
251       else                                                                   \
252         {                                                                    \
253           R##_s = X##_s;                                                     \
254           _FP_FRAC_SUB_##wc(R, X, Y);                                        \
255           if (_FP_FRAC_ZEROP_##wc(R))                                        \
256             {                                                                \
257               /* return an exact zero */                                     \
258               if (FP_ROUNDMODE == FP_RND_MINF)                               \
259                 R##_s |= Y##_s;                                              \
260               else                                                           \
261                 R##_s &= Y##_s;                                              \
262               R##_c = FP_CLS_ZERO;                                           \
263             }                                                                \
264           else                                                               \
265             {                                                                \
266               if (_FP_FRAC_NEGP_##wc(R))                                     \
267                 {                                                            \
268                   _FP_FRAC_SUB_##wc(R, Y, X);                                \
269                   R##_s = Y##_s;                                             \
270                 }                                                            \
271                                                                              \
272               /* renormalize after subtraction */                            \
273               _FP_FRAC_CLZ_##wc(diff, R);                                    \
274               diff -= _FP_WFRACXBITS_##fs;                                   \
275               if (diff)                                                      \
276                 {                                                            \
277                   R##_e -= diff;                                             \
278                   _FP_FRAC_SLL_##wc(R, diff);                                \
279                 }                                                            \
280             }                                                                \
281         }                                                                    \
282       break;                                                                 \
283     }                                                                        \
284                                                                              \
285   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):                               \
286     _FP_CHOOSENAN(fs, wc, R, X, Y, OP);                                      \
287     break;                                                                   \
288                                                                              \
289   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):                           \
290     R##_e = X##_e;                                                           \
291   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):                            \
292   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):                               \
293   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):                              \
294     _FP_FRAC_COPY_##wc(R, X);                                                \
295     R##_s = X##_s;                                                           \
296     R##_c = X##_c;                                                           \
297     break;                                                                   \
298                                                                              \
299   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):                           \
300     R##_e = Y##_e;                                                           \
301   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):                            \
302   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):                               \
303   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):                              \
304     _FP_FRAC_COPY_##wc(R, Y);                                                \
305     R##_s = Y##_s;                                                           \
306     R##_c = Y##_c;                                                           \
307     break;                                                                   \
308                                                                              \
309   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):                               \
310     if (X##_s != Y##_s)                                                      \
311       {                                                                      \
312         /* +INF + -INF => NAN */                                             \
313         _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                              \
314         R##_s = _FP_NANSIGN_##fs;                                            \
315         R##_c = FP_CLS_NAN;                                                  \
316         FP_SET_EXCEPTION(FP_EX_INVALID);                                     \
317         break;                                                               \
318       }                                                                      \
319     /* FALLTHRU */                                                           \
320                                                                              \
321   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):                            \
322   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):                              \
323     R##_s = X##_s;                                                           \
324     R##_c = FP_CLS_INF;                                                      \
325     break;                                                                   \
326                                                                              \
327   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):                            \
328   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):                              \
329     R##_s = Y##_s;                                                           \
330     R##_c = FP_CLS_INF;                                                      \
331     break;                                                                   \
332                                                                              \
333   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):                             \
334     /* make sure the sign is correct */                                      \
335     if (FP_ROUNDMODE == FP_RND_MINF)                                         \
336       R##_s = X##_s | Y##_s;                                                 \
337     else                                                                     \
338       R##_s = X##_s & Y##_s;                                                 \
339     R##_c = FP_CLS_ZERO;                                                     \
340     break;                                                                   \
341                                                                              \
342   default:                                                                   \
343     abort();                                                                 \
344   }                                                                          \
345 } while (0)
346
347 #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
348 #define _FP_SUB(fs, wc, R, X, Y)                                             \
349   do {                                                                       \
350     if (Y##_c != FP_CLS_NAN) Y##_s ^= 1;                                     \
351     _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-');                                  \
352   } while (0)
353
354
355 /*
356  * Main negation routine.  FIXME -- when we care about setting exception
357  * bits reliably, this will not do.  We should examine all of the fp classes.
358  */
359
360 #define _FP_NEG(fs, wc, R, X)           \
361   do {                                  \
362     _FP_FRAC_COPY_##wc(R, X);           \
363     R##_c = X##_c;                      \
364     R##_e = X##_e;                      \
365     R##_s = 1 ^ X##_s;                  \
366   } while (0)
367
368
369 /*
370  * Main multiplication routine.  The input values should be cooked.
371  */
372
373 #define _FP_MUL(fs, wc, R, X, Y)                        \
374 do {                                                    \
375   R##_s = X##_s ^ Y##_s;                                \
376   switch (_FP_CLS_COMBINE(X##_c, Y##_c))                \
377   {                                                     \
378   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
379     R##_c = FP_CLS_NORMAL;                              \
380     R##_e = X##_e + Y##_e + 1;                          \
381                                                         \
382     _FP_MUL_MEAT_##fs(R,X,Y);                           \
383                                                         \
384     if (_FP_FRAC_OVERP_##wc(fs, R))                     \
385       _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);      \
386     else                                                \
387       R##_e--;                                          \
388     break;                                              \
389                                                         \
390   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):          \
391     _FP_CHOOSENAN(fs, wc, R, X, Y, '*');                \
392     break;                                              \
393                                                         \
394   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):       \
395   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):          \
396   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):         \
397     R##_s = X##_s;                                      \
398                                                         \
399   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):          \
400   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):       \
401   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):      \
402   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):        \
403     _FP_FRAC_COPY_##wc(R, X);                           \
404     R##_c = X##_c;                                      \
405     break;                                              \
406                                                         \
407   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):       \
408   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):          \
409   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):         \
410     R##_s = Y##_s;                                      \
411                                                         \
412   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):       \
413   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):      \
414     _FP_FRAC_COPY_##wc(R, Y);                           \
415     R##_c = Y##_c;                                      \
416     break;                                              \
417                                                         \
418   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):         \
419   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):         \
420     R##_s = _FP_NANSIGN_##fs;                           \
421     R##_c = FP_CLS_NAN;                                 \
422     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);             \
423     FP_SET_EXCEPTION(FP_EX_INVALID);                    \
424     break;                                              \
425                                                         \
426   default:                                              \
427     abort();                                            \
428   }                                                     \
429 } while (0)
430
431
432 /*
433  * Main division routine.  The input values should be cooked.
434  */
435
436 #define _FP_DIV(fs, wc, R, X, Y)                        \
437 do {                                                    \
438   R##_s = X##_s ^ Y##_s;                                \
439   switch (_FP_CLS_COMBINE(X##_c, Y##_c))                \
440   {                                                     \
441   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
442     R##_c = FP_CLS_NORMAL;                              \
443     R##_e = X##_e - Y##_e;                              \
444                                                         \
445     _FP_DIV_MEAT_##fs(R,X,Y);                           \
446     break;                                              \
447                                                         \
448   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):          \
449     _FP_CHOOSENAN(fs, wc, R, X, Y, '/');                \
450     break;                                              \
451                                                         \
452   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):       \
453   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):          \
454   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):         \
455     R##_s = X##_s;                                      \
456     _FP_FRAC_COPY_##wc(R, X);                           \
457     R##_c = X##_c;                                      \
458     break;                                              \
459                                                         \
460   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):       \
461   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):          \
462   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):         \
463     R##_s = Y##_s;                                      \
464     _FP_FRAC_COPY_##wc(R, Y);                           \
465     R##_c = Y##_c;                                      \
466     break;                                              \
467                                                         \
468   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):       \
469   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):         \
470   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):      \
471     R##_c = FP_CLS_ZERO;                                \
472     break;                                              \
473                                                         \
474   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):      \
475     FP_SET_EXCEPTION(FP_EX_DIVZERO);                    \
476   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):         \
477   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):       \
478     R##_c = FP_CLS_INF;                                 \
479     break;                                              \
480                                                         \
481   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):          \
482   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):        \
483     R##_s = _FP_NANSIGN_##fs;                           \
484     R##_c = FP_CLS_NAN;                                 \
485     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);             \
486     FP_SET_EXCEPTION(FP_EX_INVALID);                    \
487     break;                                              \
488                                                         \
489   default:                                              \
490     abort();                                            \
491   }                                                     \
492 } while (0)
493
494
495 /*
496  * Main differential comparison routine.  The inputs should be raw not
497  * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
498  */
499
500 #define _FP_CMP(fs, wc, ret, X, Y, un)                                  \
501   do {                                                                  \
502     /* NANs are unordered */                                            \
503     if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))           \
504         || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))       \
505       {                                                                 \
506         ret = un;                                                       \
507       }                                                                 \
508     else                                                                \
509       {                                                                 \
510         int __is_zero_x;                                                \
511         int __is_zero_y;                                                \
512                                                                         \
513         __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;       \
514         __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;       \
515                                                                         \
516         if (__is_zero_x && __is_zero_y)                                 \
517                 ret = 0;                                                \
518         else if (__is_zero_x)                                           \
519                 ret = Y##_s ? 1 : -1;                                   \
520         else if (__is_zero_y)                                           \
521                 ret = X##_s ? -1 : 1;                                   \
522         else if (X##_s != Y##_s)                                        \
523           ret = X##_s ? -1 : 1;                                         \
524         else if (X##_e > Y##_e)                                         \
525           ret = X##_s ? -1 : 1;                                         \
526         else if (X##_e < Y##_e)                                         \
527           ret = X##_s ? 1 : -1;                                         \
528         else if (_FP_FRAC_GT_##wc(X, Y))                                \
529           ret = X##_s ? -1 : 1;                                         \
530         else if (_FP_FRAC_GT_##wc(Y, X))                                \
531           ret = X##_s ? 1 : -1;                                         \
532         else                                                            \
533           ret = 0;                                                      \
534       }                                                                 \
535   } while (0)
536
537
538 /* Simplification for strict equality.  */
539
540 #define _FP_CMP_EQ(fs, wc, ret, X, Y)                                     \
541   do {                                                                    \
542     /* NANs are unordered */                                              \
543     if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))             \
544         || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))         \
545       {                                                                   \
546         ret = 1;                                                          \
547       }                                                                   \
548     else                                                                  \
549       {                                                                   \
550         ret = !(X##_e == Y##_e                                            \
551                 && _FP_FRAC_EQ_##wc(X, Y)                                 \
552                 && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
553       }                                                                   \
554   } while (0)
555
556 /*
557  * Main square root routine.  The input value should be cooked.
558  */
559
560 #define _FP_SQRT(fs, wc, R, X)                                          \
561 do {                                                                    \
562     _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);                       \
563     _FP_W_TYPE q;                                                       \
564     switch (X##_c)                                                      \
565     {                                                                   \
566     case FP_CLS_NAN:                                                    \
567         _FP_FRAC_COPY_##wc(R, X);                                       \
568         R##_s = X##_s;                                                  \
569         R##_c = FP_CLS_NAN;                                             \
570         break;                                                          \
571     case FP_CLS_INF:                                                    \
572         if (X##_s)                                                      \
573           {                                                             \
574             R##_s = _FP_NANSIGN_##fs;                                   \
575             R##_c = FP_CLS_NAN; /* NAN */                               \
576             _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                     \
577             FP_SET_EXCEPTION(FP_EX_INVALID);                            \
578           }                                                             \
579         else                                                            \
580           {                                                             \
581             R##_s = 0;                                                  \
582             R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */                 \
583           }                                                             \
584         break;                                                          \
585     case FP_CLS_ZERO:                                                   \
586         R##_s = X##_s;                                                  \
587         R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */                      \
588         break;                                                          \
589     case FP_CLS_NORMAL:                                                 \
590         R##_s = 0;                                                      \
591         if (X##_s)                                                      \
592           {                                                             \
593             R##_c = FP_CLS_NAN; /* sNAN */                              \
594             R##_s = _FP_NANSIGN_##fs;                                   \
595             _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                     \
596             FP_SET_EXCEPTION(FP_EX_INVALID);                            \
597             break;                                                      \
598           }                                                             \
599         R##_c = FP_CLS_NORMAL;                                          \
600         if (X##_e & 1)                                                  \
601           _FP_FRAC_SLL_##wc(X, 1);                                      \
602         R##_e = X##_e >> 1;                                             \
603         _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);                        \
604         _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);                        \
605         q = _FP_OVERFLOW_##fs >> 1;                                     \
606         _FP_SQRT_MEAT_##wc(R, S, T, X, q);                              \
607     }                                                                   \
608   } while (0)
609
610 /*
611  * Convert from FP to integer
612  */
613
614 /* RSIGNED can have following values:
615  * 0:  the number is required to be 0..(2^rsize)-1, if not, NV is set plus
616  *     the result is either 0 or (2^rsize)-1 depending on the sign in such case.
617  * 1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
618  *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
619  *     on the sign in such case.
620  * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
621  *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
622  *     on the sign in such case.
623  */
624 #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)                                \
625   do {                                                                          \
626     switch (X##_c)                                                              \
627       {                                                                         \
628       case FP_CLS_NORMAL:                                                       \
629         if (X##_e < 0)                                                          \
630           {                                                                     \
631             FP_SET_EXCEPTION(FP_EX_INEXACT);                                    \
632           case FP_CLS_ZERO:                                                     \
633             r = 0;                                                              \
634           }                                                                     \
635         else if (X##_e >= rsize - (rsigned > 0 || X##_s)                        \
636                  || (!rsigned && X##_s))                                        \
637           {     /* overflow */                                                  \
638           case FP_CLS_NAN:                                                      \
639           case FP_CLS_INF:                                                      \
640             if (rsigned)                                                        \
641               {                                                                 \
642                 r = 1;                                                          \
643                 r <<= rsize - 1;                                                \
644                 r -= 1 - X##_s;                                                 \
645               } else {                                                          \
646                 r = 0;                                                          \
647                 if (X##_s)                                                      \
648                   r = ~r;                                                       \
649               }                                                                 \
650             FP_SET_EXCEPTION(FP_EX_INVALID);                                    \
651           }                                                                     \
652         else                                                                    \
653           {                                                                     \
654             if (_FP_W_TYPE_SIZE*wc < rsize)                                     \
655               {                                                                 \
656                 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                            \
657                 r <<= X##_e - _FP_WFRACBITS_##fs;                               \
658               }                                                                 \
659             else                                                                \
660               {                                                                 \
661                 if (X##_e >= _FP_WFRACBITS_##fs)                                \
662                   _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));       \
663                 else if (X##_e < _FP_WFRACBITS_##fs - 1)                        \
664                   {                                                             \
665                     _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2),      \
666                                       _FP_WFRACBITS_##fs);                      \
667                     if (_FP_FRAC_LOW_##wc(X) & 1)                               \
668                       FP_SET_EXCEPTION(FP_EX_INEXACT);                          \
669                     _FP_FRAC_SRL_##wc(X, 1);                                    \
670                   }                                                             \
671                 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                            \
672               }                                                                 \
673             if (rsigned && X##_s)                                               \
674               r = -r;                                                           \
675           }                                                                     \
676         break;                                                                  \
677       }                                                                         \
678   } while (0)
679
680 #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)                        \
681   do {                                                                  \
682     if (r)                                                              \
683       {                                                                 \
684         unsigned rtype ur_;                                             \
685         X##_c = FP_CLS_NORMAL;                                          \
686                                                                         \
687         if ((X##_s = (r < 0)))                                          \
688           r = -r;                                                       \
689                                                                         \
690         ur_ = (unsigned rtype) r;                                       \
691         if (rsize <= _FP_W_TYPE_SIZE)                                   \
692           __FP_CLZ(X##_e, ur_);                                         \
693         else                                                            \
694           __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE),       \
695                      (_FP_W_TYPE)ur_);                                  \
696         if (rsize < _FP_W_TYPE_SIZE)                                    \
697                 X##_e -= (_FP_W_TYPE_SIZE - rsize);                     \
698         X##_e = rsize - X##_e - 1;                                      \
699                                                                         \
700         if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e)    \
701           __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
702         _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);                       \
703         if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0)                       \
704           _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));       \
705       }                                                                 \
706     else                                                                \
707       {                                                                 \
708         X##_c = FP_CLS_ZERO, X##_s = 0;                                 \
709       }                                                                 \
710   } while (0)
711
712
713 #define FP_CONV(dfs,sfs,dwc,swc,D,S)                    \
714   do {                                                  \
715     _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);        \
716     D##_e = S##_e;                                      \
717     D##_c = S##_c;                                      \
718     D##_s = S##_s;                                      \
719   } while (0)
720
721 /*
722  * Helper primitives.
723  */
724
725 /* Count leading zeros in a word.  */
726
727 #ifndef __FP_CLZ
728 #if _FP_W_TYPE_SIZE < 64
729 /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
730 #define __FP_CLZ(r, x)                          \
731   do {                                          \
732     _FP_W_TYPE _t = (x);                        \
733     r = _FP_W_TYPE_SIZE - 1;                    \
734     if (_t > 0xffff) r -= 16;                   \
735     if (_t > 0xffff) _t >>= 16;                 \
736     if (_t > 0xff) r -= 8;                      \
737     if (_t > 0xff) _t >>= 8;                    \
738     if (_t & 0xf0) r -= 4;                      \
739     if (_t & 0xf0) _t >>= 4;                    \
740     if (_t & 0xc) r -= 2;                       \
741     if (_t & 0xc) _t >>= 2;                     \
742     if (_t & 0x2) r -= 1;                       \
743   } while (0)
744 #else /* not _FP_W_TYPE_SIZE < 64 */
745 #define __FP_CLZ(r, x)                          \
746   do {                                          \
747     _FP_W_TYPE _t = (x);                        \
748     r = _FP_W_TYPE_SIZE - 1;                    \
749     if (_t > 0xffffffff) r -= 32;               \
750     if (_t > 0xffffffff) _t >>= 32;             \
751     if (_t > 0xffff) r -= 16;                   \
752     if (_t > 0xffff) _t >>= 16;                 \
753     if (_t > 0xff) r -= 8;                      \
754     if (_t > 0xff) _t >>= 8;                    \
755     if (_t & 0xf0) r -= 4;                      \
756     if (_t & 0xf0) _t >>= 4;                    \
757     if (_t & 0xc) r -= 2;                       \
758     if (_t & 0xc) _t >>= 2;                     \
759     if (_t & 0x2) r -= 1;                       \
760   } while (0)
761 #endif /* not _FP_W_TYPE_SIZE < 64 */
762 #endif /* ndef __FP_CLZ */
763
764 #define _FP_DIV_HELP_imm(q, r, n, d)            \
765   do {                                          \
766     q = n / d, r = n % d;                       \
767   } while (0)
768
769
770 /* A restoring bit-by-bit division primitive.  */
771
772 #define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y)                            \
773   do {                                                                  \
774     int count = _FP_WFRACBITS_##fs;                                     \
775     _FP_FRAC_DECL_##wc (u);                                             \
776     _FP_FRAC_DECL_##wc (v);                                             \
777     _FP_FRAC_COPY_##wc (u, X);                                          \
778     _FP_FRAC_COPY_##wc (v, Y);                                          \
779     _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc);                           \
780     /* Normalize U and V.  */                                           \
781     _FP_FRAC_SLL_##wc (u, _FP_WFRACXBITS_##fs);                         \
782     _FP_FRAC_SLL_##wc (v, _FP_WFRACXBITS_##fs);                         \
783     /* First round.  Since the operands are normalized, either the      \
784        first or second bit will be set in the fraction.  Produce a      \
785        normalized result by checking which and adjusting the loop       \
786        count and exponent accordingly.  */                              \
787     if (_FP_FRAC_GE_1 (u, v))                                           \
788       {                                                                 \
789         _FP_FRAC_SUB_##wc (u, u, v);                                    \
790         _FP_FRAC_LOW_##wc (R) |= 1;                                     \
791         count--;                                                        \
792       }                                                                 \
793     else                                                                \
794       R##_e--;                                                          \
795     /* Subsequent rounds.  */                                           \
796     do {                                                                \
797       int msb = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (u) < 0;               \
798       _FP_FRAC_SLL_##wc (u, 1);                                         \
799       _FP_FRAC_SLL_##wc (R, 1);                                         \
800       if (msb || _FP_FRAC_GE_1 (u, v))                                  \
801         {                                                               \
802           _FP_FRAC_SUB_##wc (u, u, v);                                  \
803           _FP_FRAC_LOW_##wc (R) |= 1;                                   \
804         }                                                               \
805     } while (--count > 0);                                              \
806     /* If there's anything left in U, the result is inexact.  */        \
807     _FP_FRAC_LOW_##wc (R) |= !_FP_FRAC_ZEROP_##wc (u);                  \
808   } while (0)
809
810 #define _FP_DIV_MEAT_1_loop(fs, R, X, Y)  _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y)
811 #define _FP_DIV_MEAT_2_loop(fs, R, X, Y)  _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y)
812 #define _FP_DIV_MEAT_4_loop(fs, R, X, Y)  _FP_DIV_MEAT_N_loop (fs, 4, R, X, Y)