root/include/math-emu/op-common.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


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

/* [<][>][^][v][top][bottom][index][help] */