1 /* Software floating-point emulation. Common operations.
 
   2    Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
 
   3    This file is part of the GNU C Library.
 
   4    Contributed by Richard Henderson (rth@cygnus.com),
 
   5                   Jakub Jelinek (jj@ultra.linux.cz),
 
   6                   David S. Miller (davem@redhat.com) and
 
   7                   Peter Maydell (pmaydell@chiark.greenend.org.uk).
 
   9    The GNU C Library is free software; you can redistribute it and/or
 
  10    modify it under the terms of the GNU Library General Public License as
 
  11    published by the Free Software Foundation; either version 2 of the
 
  12    License, or (at your option) any later version.
 
  14    The GNU C Library is distributed in the hope that it will be useful,
 
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
  17    Library General Public License for more details.
 
  19    You should have received a copy of the GNU Library General Public
 
  20    License along with the GNU C Library; see the file COPYING.LIB.  If
 
  21    not, write to the Free Software Foundation, Inc.,
 
  22    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
  24 #ifndef __MATH_EMU_OP_COMMON_H__
 
  25 #define __MATH_EMU_OP_COMMON_H__
 
  27 #define _FP_DECL(wc, X)                 \
 
  28   _FP_I_TYPE X##_c=0, X##_s=0, X##_e=0; \
 
  32  * Finish truely unpacking a native fp value by classifying the kind
 
  33  * of fp value and normalizing both the exponent and the fraction.
 
  36 #define _FP_UNPACK_CANONICAL(fs, wc, X)                                 \
 
  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;                                              \
 
  48     if (_FP_FRAC_ZEROP_##wc(X))                                         \
 
  49       X##_c = FP_CLS_ZERO;                                              \
 
  52         /* a denormalized number */                                     \
 
  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);                                 \
 
  62             FP_SET_EXCEPTION(FP_EX_INEXACT);                            \
 
  63             X##_c = FP_CLS_ZERO;                                        \
 
  68   case _FP_EXPMAX_##fs:                                                 \
 
  69     if (_FP_FRAC_ZEROP_##wc(X))                                         \
 
  74         /* Check for signaling NaN */                                   \
 
  75         if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))            \
 
  76           FP_SET_EXCEPTION(FP_EX_INVALID);                              \
 
  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.
 
  89 #define _FP_PACK_CANONICAL(fs, wc, X)                           \
 
  94     X##_e += _FP_EXPBIAS_##fs;                                  \
 
  98         if (_FP_FRAC_OVERP_##wc(fs, X))                         \
 
 100             _FP_FRAC_CLEAR_OVERP_##wc(fs, X);                   \
 
 103         _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                     \
 
 104         if (X##_e >= _FP_EXPMAX_##fs)                           \
 
 107             switch (FP_ROUNDMODE)                               \
 
 109               case FP_RND_NEAREST:                              \
 
 110                 X##_c = FP_CLS_INF;                             \
 
 113                 if (!X##_s) X##_c = FP_CLS_INF;                 \
 
 116                 if (X##_s) X##_c = FP_CLS_INF;                  \
 
 119             if (X##_c == FP_CLS_INF)                            \
 
 121                 /* Overflow to infinity */                      \
 
 122                 X##_e = _FP_EXPMAX_##fs;                        \
 
 123                 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
 
 127                 /* Overflow to maximum normal */                \
 
 128                 X##_e = _FP_EXPMAX_##fs - 1;                    \
 
 129                 _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);         \
 
 131             FP_SET_EXCEPTION(FP_EX_OVERFLOW);                   \
 
 132             FP_SET_EXCEPTION(FP_EX_INEXACT);                    \
 
 137         /* we've got a denormalized number */                   \
 
 138         X##_e = -X##_e + 1;                                     \
 
 139         if (X##_e <= _FP_WFRACBITS_##fs)                        \
 
 141             _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);    \
 
 143             if (_FP_FRAC_HIGH_##fs(X)                           \
 
 144                 & (_FP_OVERFLOW_##fs >> 1))                     \
 
 147                 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
 
 148                 FP_SET_EXCEPTION(FP_EX_INEXACT);                \
 
 153                 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);             \
 
 155             if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) ||          \
 
 156                 (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))     \
 
 157                 FP_SET_EXCEPTION(FP_EX_UNDERFLOW);              \
 
 161             /* underflow to zero */                             \
 
 163             if (!_FP_FRAC_ZEROP_##wc(X))                        \
 
 165                 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);         \
 
 167                 _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);        \
 
 169             FP_SET_EXCEPTION(FP_EX_UNDERFLOW);                  \
 
 176     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                    \
 
 180     X##_e = _FP_EXPMAX_##fs;                                    \
 
 181     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                    \
 
 185     X##_e = _FP_EXPMAX_##fs;                                    \
 
 186     if (!_FP_KEEPNANFRACP)                                      \
 
 188         _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);                 \
 
 189         X##_s = _FP_NANSIGN_##fs;                               \
 
 192       _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;            \
 
 197 /* This one accepts raw argument and not cooked,  returns
 
 198  * 1 if X is a signaling NaN.
 
 200 #define _FP_ISSIGNAN(fs, wc, X)                                 \
 
 203   if (X##_e == _FP_EXPMAX_##fs)                                 \
 
 205       if (!_FP_FRAC_ZEROP_##wc(X)                               \
 
 206           && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))   \
 
 217  * Main addition routine.  The input values should be cooked.
 
 220 #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)                                \
 
 222   switch (_FP_CLS_COMBINE(X##_c, Y##_c))                                     \
 
 224   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):                         \
 
 226       /* shift the smaller number so that its exponent matches the larger */ \
 
 227       _FP_I_TYPE diff = X##_e - Y##_e;                                       \
 
 232           if (diff <= _FP_WFRACBITS_##fs)                                    \
 
 233             _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);                  \
 
 234           else if (!_FP_FRAC_ZEROP_##wc(X))                                  \
 
 235             _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                          \
 
 242               if (diff <= _FP_WFRACBITS_##fs)                                \
 
 243                 _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);              \
 
 244               else if (!_FP_FRAC_ZEROP_##wc(Y))                              \
 
 245                 _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);                      \
 
 250       R##_c = FP_CLS_NORMAL;                                                 \
 
 252       if (X##_s == Y##_s)                                                    \
 
 255           _FP_FRAC_ADD_##wc(R, X, Y);                                        \
 
 256           if (_FP_FRAC_OVERP_##wc(fs, R))                                    \
 
 258               _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);                   \
 
 265           _FP_FRAC_SUB_##wc(R, X, Y);                                        \
 
 266           if (_FP_FRAC_ZEROP_##wc(R))                                        \
 
 268               /* return an exact zero */                                     \
 
 269               if (FP_ROUNDMODE == FP_RND_MINF)                               \
 
 273               R##_c = FP_CLS_ZERO;                                           \
 
 277               if (_FP_FRAC_NEGP_##wc(R))                                     \
 
 279                   _FP_FRAC_SUB_##wc(R, Y, X);                                \
 
 283               /* renormalize after subtraction */                            \
 
 284               _FP_FRAC_CLZ_##wc(diff, R);                                    \
 
 285               diff -= _FP_WFRACXBITS_##fs;                                   \
 
 289                   _FP_FRAC_SLL_##wc(R, diff);                                \
 
 296   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):                               \
 
 297     _FP_CHOOSENAN(fs, wc, R, X, Y, OP);                                      \
 
 300   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):                           \
 
 302   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):                            \
 
 303   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):                               \
 
 304   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):                              \
 
 305     _FP_FRAC_COPY_##wc(R, X);                                                \
 
 310   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):                           \
 
 312   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):                            \
 
 313   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):                               \
 
 314   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):                              \
 
 315     _FP_FRAC_COPY_##wc(R, Y);                                                \
 
 320   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):                               \
 
 321     if (X##_s != Y##_s)                                                      \
 
 323         /* +INF + -INF => NAN */                                             \
 
 324         _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                              \
 
 325         R##_s = _FP_NANSIGN_##fs;                                            \
 
 326         R##_c = FP_CLS_NAN;                                                  \
 
 327         FP_SET_EXCEPTION(FP_EX_INVALID);                                     \
 
 332   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):                            \
 
 333   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):                              \
 
 335     R##_c = FP_CLS_INF;                                                      \
 
 338   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):                            \
 
 339   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):                              \
 
 341     R##_c = FP_CLS_INF;                                                      \
 
 344   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):                             \
 
 345     /* make sure the sign is correct */                                      \
 
 346     if (FP_ROUNDMODE == FP_RND_MINF)                                         \
 
 347       R##_s = X##_s | Y##_s;                                                 \
 
 349       R##_s = X##_s & Y##_s;                                                 \
 
 350     R##_c = FP_CLS_ZERO;                                                     \
 
 358 #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
 
 359 #define _FP_SUB(fs, wc, R, X, Y)                                             \
 
 361     if (Y##_c != FP_CLS_NAN) Y##_s ^= 1;                                     \
 
 362     _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-');                                  \
 
 367  * Main negation routine.  FIXME -- when we care about setting exception
 
 368  * bits reliably, this will not do.  We should examine all of the fp classes.
 
 371 #define _FP_NEG(fs, wc, R, X)           \
 
 373     _FP_FRAC_COPY_##wc(R, X);           \
 
 381  * Main multiplication routine.  The input values should be cooked.
 
 384 #define _FP_MUL(fs, wc, R, X, Y)                        \
 
 386   R##_s = X##_s ^ Y##_s;                                \
 
 387   switch (_FP_CLS_COMBINE(X##_c, Y##_c))                \
 
 389   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
 
 390     R##_c = FP_CLS_NORMAL;                              \
 
 391     R##_e = X##_e + Y##_e + 1;                          \
 
 393     _FP_MUL_MEAT_##fs(R,X,Y);                           \
 
 395     if (_FP_FRAC_OVERP_##wc(fs, R))                     \
 
 396       _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);      \
 
 401   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):          \
 
 402     _FP_CHOOSENAN(fs, wc, R, X, Y, '*');                \
 
 405   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):       \
 
 406   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):          \
 
 407   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):         \
 
 410   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):          \
 
 411   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):       \
 
 412   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):      \
 
 413   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):        \
 
 414     _FP_FRAC_COPY_##wc(R, X);                           \
 
 418   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):       \
 
 419   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):          \
 
 420   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):         \
 
 423   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):       \
 
 424   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):      \
 
 425     _FP_FRAC_COPY_##wc(R, Y);                           \
 
 429   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):         \
 
 430   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):         \
 
 431     R##_s = _FP_NANSIGN_##fs;                           \
 
 432     R##_c = FP_CLS_NAN;                                 \
 
 433     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);             \
 
 434     FP_SET_EXCEPTION(FP_EX_INVALID);                    \
 
 444  * Main division routine.  The input values should be cooked.
 
 447 #define _FP_DIV(fs, wc, R, X, Y)                        \
 
 449   R##_s = X##_s ^ Y##_s;                                \
 
 450   switch (_FP_CLS_COMBINE(X##_c, Y##_c))                \
 
 452   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
 
 453     R##_c = FP_CLS_NORMAL;                              \
 
 454     R##_e = X##_e - Y##_e;                              \
 
 456     _FP_DIV_MEAT_##fs(R,X,Y);                           \
 
 459   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):          \
 
 460     _FP_CHOOSENAN(fs, wc, R, X, Y, '/');                \
 
 463   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):       \
 
 464   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):          \
 
 465   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):         \
 
 467     _FP_FRAC_COPY_##wc(R, X);                           \
 
 471   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):       \
 
 472   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):          \
 
 473   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):         \
 
 475     _FP_FRAC_COPY_##wc(R, Y);                           \
 
 479   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):       \
 
 480   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):         \
 
 481   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):      \
 
 482     R##_c = FP_CLS_ZERO;                                \
 
 485   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):      \
 
 486     FP_SET_EXCEPTION(FP_EX_DIVZERO);                    \
 
 487   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):         \
 
 488   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):       \
 
 489     R##_c = FP_CLS_INF;                                 \
 
 492   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):          \
 
 493   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):        \
 
 494     R##_s = _FP_NANSIGN_##fs;                           \
 
 495     R##_c = FP_CLS_NAN;                                 \
 
 496     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);             \
 
 497     FP_SET_EXCEPTION(FP_EX_INVALID);                    \
 
 507  * Main differential comparison routine.  The inputs should be raw not
 
 508  * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
 
 511 #define _FP_CMP(fs, wc, ret, X, Y, un)                                  \
 
 513     /* NANs are unordered */                                            \
 
 514     if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))           \
 
 515         || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))       \
 
 524         __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;       \
 
 525         __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;       \
 
 527         if (__is_zero_x && __is_zero_y)                                 \
 
 529         else if (__is_zero_x)                                           \
 
 530                 ret = Y##_s ? 1 : -1;                                   \
 
 531         else if (__is_zero_y)                                           \
 
 532                 ret = X##_s ? -1 : 1;                                   \
 
 533         else if (X##_s != Y##_s)                                        \
 
 534           ret = X##_s ? -1 : 1;                                         \
 
 535         else if (X##_e > Y##_e)                                         \
 
 536           ret = X##_s ? -1 : 1;                                         \
 
 537         else if (X##_e < Y##_e)                                         \
 
 538           ret = X##_s ? 1 : -1;                                         \
 
 539         else if (_FP_FRAC_GT_##wc(X, Y))                                \
 
 540           ret = X##_s ? -1 : 1;                                         \
 
 541         else if (_FP_FRAC_GT_##wc(Y, X))                                \
 
 542           ret = X##_s ? 1 : -1;                                         \
 
 549 /* Simplification for strict equality.  */
 
 551 #define _FP_CMP_EQ(fs, wc, ret, X, Y)                                     \
 
 553     /* NANs are unordered */                                              \
 
 554     if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))             \
 
 555         || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))         \
 
 561         ret = !(X##_e == Y##_e                                            \
 
 562                 && _FP_FRAC_EQ_##wc(X, Y)                                 \
 
 563                 && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
 
 568  * Main square root routine.  The input value should be cooked.
 
 571 #define _FP_SQRT(fs, wc, R, X)                                          \
 
 573     _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);                       \
 
 578         _FP_FRAC_COPY_##wc(R, X);                                       \
 
 580         R##_c = FP_CLS_NAN;                                             \
 
 585             R##_s = _FP_NANSIGN_##fs;                                   \
 
 586             R##_c = FP_CLS_NAN; /* NAN */                               \
 
 587             _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                     \
 
 588             FP_SET_EXCEPTION(FP_EX_INVALID);                            \
 
 593             R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */                 \
 
 598         R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */                      \
 
 600     case FP_CLS_NORMAL:                                                 \
 
 604             R##_c = FP_CLS_NAN; /* sNAN */                              \
 
 605             R##_s = _FP_NANSIGN_##fs;                                   \
 
 606             _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                     \
 
 607             FP_SET_EXCEPTION(FP_EX_INVALID);                            \
 
 610         R##_c = FP_CLS_NORMAL;                                          \
 
 612           _FP_FRAC_SLL_##wc(X, 1);                                      \
 
 613         R##_e = X##_e >> 1;                                             \
 
 614         _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);                        \
 
 615         _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);                        \
 
 616         q = _FP_OVERFLOW_##fs >> 1;                                     \
 
 617         _FP_SQRT_MEAT_##wc(R, S, T, X, q);                              \
 
 622  * Convert from FP to integer
 
 625 /* RSIGNED can have following values:
 
 626  * 0:  the number is required to be 0..(2^rsize)-1, if not, NV is set plus
 
 627  *     the result is either 0 or (2^rsize)-1 depending on the sign in such case.
 
 628  * 1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-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  * 2:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
 
 632  *     set plus the result is truncated to fit into destination.
 
 633  * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
 
 634  *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
 
 635  *     on the sign in such case.
 
 637 #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)                                \
 
 641       case FP_CLS_NORMAL:                                                       \
 
 644             FP_SET_EXCEPTION(FP_EX_INEXACT);                                    \
 
 648         else if (X##_e >= rsize - (rsigned > 0 || X##_s)                        \
 
 649                  || (!rsigned && X##_s))                                        \
 
 655                 if (X##_c != FP_CLS_NORMAL                                      \
 
 656                     || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs)                 \
 
 660                     _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));     \
 
 661                     _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                        \
 
 676             FP_SET_EXCEPTION(FP_EX_INVALID);                                    \
 
 680             if (_FP_W_TYPE_SIZE*wc < rsize)                                     \
 
 682                 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                            \
 
 683                 r <<= X##_e - _FP_WFRACBITS_##fs;                               \
 
 687                 if (X##_e >= _FP_WFRACBITS_##fs)                                \
 
 688                   _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));       \
 
 689                 else if (X##_e < _FP_WFRACBITS_##fs - 1)                        \
 
 691                     _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2),      \
 
 692                                       _FP_WFRACBITS_##fs);                      \
 
 693                     if (_FP_FRAC_LOW_##wc(X) & 1)                               \
 
 694                       FP_SET_EXCEPTION(FP_EX_INEXACT);                          \
 
 695                     _FP_FRAC_SRL_##wc(X, 1);                                    \
 
 697                 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                            \
 
 699             if (rsigned && X##_s)                                               \
 
 706 #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned)                          \
 
 711       case FP_CLS_NORMAL:                                                       \
 
 712         if (X##_e >= _FP_FRACBITS_##fs - 1)                                     \
 
 714             if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs)                         \
 
 716                 if (X##_e >= _FP_WFRACBITS_##fs - 1)                            \
 
 718                     _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                        \
 
 719                     r <<= X##_e - _FP_WFRACBITS_##fs + 1;                       \
 
 723                     _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e                   \
 
 724                                       + _FP_FRACBITS_##fs - 1);                 \
 
 725                     _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                        \
 
 731             if (X##_e <= -_FP_WORKBITS - 1)                                     \
 
 732               _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                           \
 
 734               _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e,               \
 
 735                                 _FP_WFRACBITS_##fs);                            \
 
 737             _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                                 \
 
 738             _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                                \
 
 740         if (rsigned && X##_s)                                                   \
 
 742         if (X##_e >= rsize - (rsigned > 0 || X##_s)                             \
 
 743             || (!rsigned && X##_s))                                             \
 
 753             else if (rsigned != 2)                                              \
 
 759             FP_SET_EXCEPTION(FP_EX_INVALID);                                    \
 
 767 #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)                        \
 
 771         unsigned rtype ur_;                                             \
 
 772         X##_c = FP_CLS_NORMAL;                                          \
 
 774         if ((X##_s = (r < 0)))                                          \
 
 775           ur_ = (unsigned rtype) -r;                                    \
 
 777           ur_ = (unsigned rtype) r;                                     \
 
 778         if (rsize <= _FP_W_TYPE_SIZE)                                   \
 
 779           __FP_CLZ(X##_e, ur_);                                         \
 
 781           __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE),       \
 
 783         if (rsize < _FP_W_TYPE_SIZE)                                    \
 
 784                 X##_e -= (_FP_W_TYPE_SIZE - rsize);                     \
 
 785         X##_e = rsize - X##_e - 1;                                      \
 
 787         if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e)    \
 
 788           __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
 
 789         _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);                       \
 
 790         if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0)                       \
 
 791           _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));       \
 
 795         X##_c = FP_CLS_ZERO, X##_s = 0;                                 \
 
 800 #define FP_CONV(dfs,sfs,dwc,swc,D,S)                    \
 
 802     _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);        \
 
 812 /* Count leading zeros in a word.  */
 
 815 #if _FP_W_TYPE_SIZE < 64
 
 816 /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
 
 817 #define __FP_CLZ(r, x)                          \
 
 819     _FP_W_TYPE _t = (x);                        \
 
 820     r = _FP_W_TYPE_SIZE - 1;                    \
 
 821     if (_t > 0xffff) r -= 16;                   \
 
 822     if (_t > 0xffff) _t >>= 16;                 \
 
 823     if (_t > 0xff) r -= 8;                      \
 
 824     if (_t > 0xff) _t >>= 8;                    \
 
 825     if (_t & 0xf0) r -= 4;                      \
 
 826     if (_t & 0xf0) _t >>= 4;                    \
 
 827     if (_t & 0xc) r -= 2;                       \
 
 828     if (_t & 0xc) _t >>= 2;                     \
 
 829     if (_t & 0x2) r -= 1;                       \
 
 831 #else /* not _FP_W_TYPE_SIZE < 64 */
 
 832 #define __FP_CLZ(r, x)                          \
 
 834     _FP_W_TYPE _t = (x);                        \
 
 835     r = _FP_W_TYPE_SIZE - 1;                    \
 
 836     if (_t > 0xffffffff) r -= 32;               \
 
 837     if (_t > 0xffffffff) _t >>= 32;             \
 
 838     if (_t > 0xffff) r -= 16;                   \
 
 839     if (_t > 0xffff) _t >>= 16;                 \
 
 840     if (_t > 0xff) r -= 8;                      \
 
 841     if (_t > 0xff) _t >>= 8;                    \
 
 842     if (_t & 0xf0) r -= 4;                      \
 
 843     if (_t & 0xf0) _t >>= 4;                    \
 
 844     if (_t & 0xc) r -= 2;                       \
 
 845     if (_t & 0xc) _t >>= 2;                     \
 
 846     if (_t & 0x2) r -= 1;                       \
 
 848 #endif /* not _FP_W_TYPE_SIZE < 64 */
 
 849 #endif /* ndef __FP_CLZ */
 
 851 #define _FP_DIV_HELP_imm(q, r, n, d)            \
 
 853     q = n / d, r = n % d;                       \
 
 856 #endif /* __MATH_EMU_OP_COMMON_H__ */