~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/math-emu/op-common.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 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.
 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    Library General Public License for more details.
 18 
 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.  */
 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         if (FP_DENORM_ZERO)                                             \
 58           {                                                             \
 59             FP_SET_EXCEPTION(FP_EX_INEXACT);                            \
 60             X##_c = FP_CLS_ZERO;                                        \
 61           }                                                             \
 62       }                                                                 \
 63     break;                                                              \
 64                                                                         \
 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)
 78 
 79 /*
 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.
 84  */
 85 
 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)                           \
103           {                                                     \
104             /* overflow */                                      \
105             switch (FP_ROUNDMODE)                               \
106               {                                                 \
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;                                          \
116               }                                                 \
117             if (X##_c == FP_CLS_INF)                            \
118               {                                                 \
119                 /* Overflow to infinity */                      \
120                 X##_e = _FP_EXPMAX_##fs;                        \
121                 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
122               }                                                 \
123             else                                                \
124               {                                                 \
125                 /* Overflow to maximum normal */                \
126                 X##_e = _FP_EXPMAX_##fs - 1;                    \
127                 _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);         \
128               }                                                 \
129             FP_SET_EXCEPTION(FP_EX_OVERFLOW);                   \
130             FP_SET_EXCEPTION(FP_EX_INEXACT);                    \
131           }                                                     \
132       }                                                         \
133     else                                                        \
134       {                                                         \
135         /* we've got a denormalized number */                   \
136         X##_e = -X##_e + 1;                                     \
137         if (X##_e <= _FP_WFRACBITS_##fs)                        \
138           {                                                     \
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))                     \
143               {                                                 \
144                 X##_e = 1;                                      \
145                 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
146               }                                                 \
147             else                                                \
148               {                                                 \
149                 X##_e = 0;                                      \
150                 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);             \
151                 FP_SET_EXCEPTION(FP_EX_UNDERFLOW);              \
152               }                                                 \
153           }                                                     \
154         else                                                    \
155           {                                                     \
156             /* underflow to zero */                             \
157             X##_e = 0;                                          \
158             if (!_FP_FRAC_ZEROP_##wc(X))                        \
159               {                                                 \
160                 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);         \
161                 _FP_ROUND(wc, X);                               \
162                 _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);        \
163               }                                                 \
164             FP_SET_EXCEPTION(FP_EX_UNDERFLOW);                  \
165           }                                                     \
166       }                                                         \
167     break;                                                      \
168                                                                 \
169   case FP_CLS_ZERO:                                             \
170     X##_e = 0;                                                  \
171     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                    \
172     break;                                                      \
173                                                                 \
174   case FP_CLS_INF:                                              \
175     X##_e = _FP_EXPMAX_##fs;                                    \
176     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                    \
177     break;                                                      \
178                                                                 \
179   case FP_CLS_NAN:                                              \
180     X##_e = _FP_EXPMAX_##fs;                                    \
181     if (!_FP_KEEPNANFRACP)                                      \
182       {                                                         \
183         _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);                 \
184         X##_s = _FP_NANSIGN_##fs;                               \
185       }                                                         \
186     else                                                        \
187       _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;            \
188     break;                                                      \
189   }                                                             \
190 } while (0)
191 
192 /* This one accepts raw argument and not cooked,  returns
193  * 1 if X is a signaling NaN.
194  */
195 #define _FP_ISSIGNAN(fs, wc, X)                                 \
196 ({                                                              \
197   int __ret = 0;                                                \
198   if (X##_e == _FP_EXPMAX_##fs)                                 \
199     {                                                           \
200       if (!_FP_FRAC_ZEROP_##wc(X)                               \
201           && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))   \
202         __ret = 1;                                              \
203     }                                                           \
204   __ret;                                                        \
205 })
206 
207 
208 
209 
210 
211 /*
212  * Main addition routine.  The input values should be cooked.
213  */
214 
215 #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)                                \
216 do {                                                                         \
217   switch (_FP_CLS_COMBINE(X##_c, Y##_c))                                     \
218   {                                                                          \
219   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):                         \
220     {                                                                        \
221       /* shift the smaller number so that its exponent matches the larger */ \
222       _FP_I_TYPE diff = X##_e - Y##_e;                                       \
223                                                                              \
224       if (diff < 0)                                                          \
225         {                                                                    \
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;                                                     \
232         }                                                                    \
233       else                                                                   \
234         {                                                                    \
235           if (diff > 0)                                                      \
236             {                                                                \
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);                      \
241             }                                                                \
242           R##_e = X##_e;                                                     \
243         }                                                                    \
244                                                                              \
245       R##_c = FP_CLS_NORMAL;                                                 \
246                                                                              \
247       if (X##_s == Y##_s)                                                    \
248         {                                                                    \
249           R##_s = X##_s;                                                     \
250           _FP_FRAC_ADD_##wc(R, X, Y);                                        \
251           if (_FP_FRAC_OVERP_##wc(fs, R))                                    \
252             {                                                                \
253               _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);                   \
254               R##_e++;                                                       \
255             }                                                                \
256         }                                                                    \
257       else                                                                   \
258         {                                                                    \
259           R##_s = X##_s;                                                     \
260           _FP_FRAC_SUB_##wc(R, X, Y);                                        \
261           if (_FP_FRAC_ZEROP_##wc(R))                                        \
262             {                                                                \
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;                                           \
269             }                                                                \
270           else                                                               \
271             {                                                                \
272               if (_FP_FRAC_NEGP_##wc(R))                                     \
273                 {                                                            \
274                   _FP_FRAC_SUB_##wc(R, Y, X);                                \
275                   R##_s = Y##_s;                                             \
276                 }                                                            \
277                                                                              \
278               /* renormalize after subtraction */                            \
279               _FP_FRAC_CLZ_##wc(diff, R);                                    \
280               diff -= _FP_WFRACXBITS_##fs;                                   \
281               if (diff)                                                      \
282                 {                                                            \
283                   R##_e -= diff;                                             \
284                   _FP_FRAC_SLL_##wc(R, diff);                                \
285                 }                                                            \
286             }                                                                \
287         }                                                                    \
288       break;                                                                 \
289     }                                                                        \
290                                                                              \
291   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):                               \
292     _FP_CHOOSENAN(fs, wc, R, X, Y, OP);                                      \
293     break;                                                                   \
294                                                                              \
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;                                                                   \
304                                                                              \
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;                                                                   \
314                                                                              \
315   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):                               \
316     if (X##_s != Y##_s)                                                      \
317       {                                                                      \
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;                                                               \
324       }                                                                      \
325     /* FALLTHRU */                                                           \
326                                                                              \
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;                                                                   \
332                                                                              \
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;                                                                   \
338                                                                              \
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;                                                                   \
347                                                                              \
348   default:                                                                   \
349     abort();                                                                 \
350   }                                                                          \
351 } while (0)
352 
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)
359 
360 
361 /*
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.
364  */
365 
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)
373 
374 
375 /*
376  * Main multiplication routine.  The input values should be cooked.
377  */
378 
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))                \
383   {                                                     \
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;                          \
387                                                         \
388     _FP_MUL_MEAT_##fs(R,X,Y);                           \
389                                                         \
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;                                              \
395                                                         \
396   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):          \
397     _FP_CHOOSENAN(fs, wc, R, X, Y, '*');                \
398     break;                                              \
399                                                         \
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;                                      \
404                                                         \
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;                                              \
412                                                         \
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;                                      \
417                                                         \
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;                                              \
423                                                         \
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;                                              \
431                                                         \
432   default:                                              \
433     abort();                                            \
434   }                                                     \
435 } while (0)
436 
437 
438 /*
439  * Main division routine.  The input values should be cooked.
440  */
441 
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))                \
446   {                                                     \
447   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
448     R##_c = FP_CLS_NORMAL;                              \
449     R##_e = X##_e - Y##_e;                              \
450                                                         \
451     _FP_DIV_MEAT_##fs(R,X,Y);                           \
452     break;                                              \
453                                                         \
454   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):          \
455     _FP_CHOOSENAN(fs, wc, R, X, Y, '/');                \
456     break;                                              \
457                                                         \
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;                                              \
465                                                         \
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;                                              \
473                                                         \
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;                                              \
479                                                         \
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;                                              \
486                                                         \
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;                                              \
494                                                         \
495   default:                                              \
496     abort();                                            \
497   }                                                     \
498 } while (0)
499 
500 
501 /*
502  * Main differential comparison routine.  The inputs should be raw not
503  * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
504  */
505 
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)))       \
511       {                                                                 \
512         ret = un;                                                       \
513       }                                                                 \
514     else                                                                \
515       {                                                                 \
516         int __is_zero_x;                                                \
517         int __is_zero_y;                                                \
518                                                                         \
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;       \
521                                                                         \
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;                                                      \
540       }                                                                 \
541   } while (0)
542 
543 
544 /* Simplification for strict equality.  */
545 
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)))         \
551       {                                                                   \
552         ret = 1;                                                          \
553       }                                                                   \
554     else                                                                  \
555       {                                                                   \
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))); \
559       }                                                                   \
560   } while (0)
561 
562 /*
563  * Main square root routine.  The input value should be cooked.
564  */
565 
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)                                                      \
571     {                                                                   \
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)                                                      \
579           {                                                             \
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);                            \
584           }                                                             \
585         else                                                            \
586           {                                                             \
587             R##_s = 0;                                                  \
588             R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */                 \
589           }                                                             \
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)                                                      \
598           {                                                             \
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;                                                      \
604           }                                                             \
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);                              \
613     }                                                                   \
614   } while (0)
615 
616 /*
617  * Convert from FP to integer
618  */
619 
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.
631  */
632 #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)                                \
633   do {                                                                          \
634     switch (X##_c)                                                              \
635       {                                                                         \
636       case FP_CLS_NORMAL:                                                       \
637         if (X##_e < 0)                                                          \
638           {                                                                     \
639             FP_SET_EXCEPTION(FP_EX_INEXACT);                                    \
640           case FP_CLS_ZERO:                                                     \
641             r = 0;                                                              \
642           }                                                                     \
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)                                                   \
649               {                                                                 \
650                 if (X##_c != FP_CLS_NORMAL                                      \
651                     || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs)                 \
652                   r = 0;                                                        \
653                 else                                                            \
654                   {                                                             \
655                     _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));     \
656                     _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                        \
657                   }                                                             \
658               }                                                                 \
659             else if (rsigned)                                                   \
660               {                                                                 \
661                 r = 1;                                                          \
662                 r <<= rsize - 1;                                                \
663                 r -= 1 - X##_s;                                                 \
664               }                                                                 \
665             else                                                                \
666               {                                                                 \
667                 r = 0;                                                          \
668                 if (X##_s)                                                      \
669                   r = ~r;                                                       \
670               }                                                                 \
671             FP_SET_EXCEPTION(FP_EX_INVALID);                                    \
672           }                                                                     \
673         else                                                                    \
674           {                                                                     \
675             if (_FP_W_TYPE_SIZE*wc < rsize)                                     \
676               {                                                                 \
677                 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                            \
678                 r <<= X##_e - _FP_WFRACBITS_##fs;                               \
679               }                                                                 \
680             else                                                                \
681               {                                                                 \
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)                        \
685                   {                                                             \
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);                                    \
691                   }                                                             \
692                 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                            \
693               }                                                                 \
694             if (rsigned && X##_s)                                               \
695               r = -r;                                                           \
696           }                                                                     \
697         break;                                                                  \
698       }                                                                         \
699   } while (0)
700 
701 #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned)                          \
702   do {                                                                          \
703     r = 0;                                                                      \
704     switch (X##_c)                                                              \
705       {                                                                         \
706       case FP_CLS_NORMAL:                                                       \
707         if (X##_e >= _FP_FRACBITS_##fs - 1)                                     \
708           {                                                                     \
709             if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs)                         \
710               {                                                                 \
711                 if (X##_e >= _FP_WFRACBITS_##fs - 1)                            \
712                   {                                                             \
713                     _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                        \
714                     r <<= X##_e - _FP_WFRACBITS_##fs + 1;                       \
715                   }                                                             \
716                 else                                                            \
717                   {                                                             \
718                     _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e                   \
719                                       + _FP_FRACBITS_##fs - 1);                 \
720                     _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                        \
721                   }                                                             \
722               }                                                                 \
723           }                                                                     \
724         else                                                                    \
725           {                                                                     \
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);                                \
734           }                                                                     \
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)                                                       \
743               {                                                                 \
744                 r = 0;                                                          \
745                 if (X##_s)                                                      \
746                   r = ~r;                                                       \
747               }                                                                 \
748             else if (rsigned != 2)                                              \
749               {                                                                 \
750                 r = 1;                                                          \
751                 r <<= rsize - 1;                                                \
752                 r -= 1 - X##_s;                                                 \
753               }                                                                 \
754             FP_SET_EXCEPTION(FP_EX_INVALID);                                    \
755           }                                                                     \
756         break;                                                                  \
757       case FP_CLS_ZERO:                                                         \
758         break;                                                                  \
759       }                                                                         \
760   } while (0)
761 
762 #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)                        \
763   do {                                                                  \
764     if (r)                                                              \
765       {                                                                 \
766         X##_c = FP_CLS_NORMAL;                                          \
767                                                                         \
768         if ((X##_s = (r < 0)))                                          \
769           r = -r;                                                       \
770                                                                         \
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;                                      \
779                                                                         \
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));         \
785       }                                                                 \
786     else                                                                \
787       {                                                                 \
788         X##_c = FP_CLS_ZERO, X##_s = 0;                                 \
789       }                                                                 \
790   } while (0)
791 
792 
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)
800 
801 /*
802  * Helper primitives.
803  */
804 
805 /* Count leading zeros in a word.  */
806 
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 */
843 
844 #define _FP_DIV_HELP_imm(q, r, n, d)            \
845   do {                                          \
846     q = n / d, r = n % d;                       \
847   } while (0)
848 
849 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.