Back to home page

OSCL-LXR

 
 

    


0001 /* Software floating-point emulation. Common operations.
0002    Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
0003    This file is part of the GNU C Library.
0004    Contributed by Richard Henderson (rth@cygnus.com),
0005           Jakub Jelinek (jj@ultra.linux.cz),
0006           David S. Miller (davem@redhat.com) and
0007           Peter Maydell (pmaydell@chiark.greenend.org.uk).
0008 
0009    The GNU C Library is free software; you can redistribute it and/or
0010    modify it under the terms of the GNU Library General Public License as
0011    published by the Free Software Foundation; either version 2 of the
0012    License, or (at your option) any later version.
0013 
0014    The GNU C Library is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017    Library General Public License for more details.
0018 
0019    You should have received a copy of the GNU Library General Public
0020    License along with the GNU C Library; see the file COPYING.LIB.  If
0021    not, write to the Free Software Foundation, Inc.,
0022    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
0023 
0024 #ifndef __MATH_EMU_OP_COMMON_H__
0025 #define __MATH_EMU_OP_COMMON_H__
0026 
0027 #define _FP_DECL(wc, X)         \
0028   _FP_I_TYPE X##_c=0, X##_s=0, X##_e=0; \
0029   _FP_FRAC_DECL_##wc(X)
0030 
0031 /*
0032  * Finish truly unpacking a native fp value by classifying the kind
0033  * of fp value and normalizing both the exponent and the fraction.
0034  */
0035 
0036 #define _FP_UNPACK_CANONICAL(fs, wc, X)                 \
0037 do {                                    \
0038   switch (X##_e)                            \
0039   {                                 \
0040   default:                              \
0041     _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs;          \
0042     _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);                 \
0043     X##_e -= _FP_EXPBIAS_##fs;                      \
0044     X##_c = FP_CLS_NORMAL;                      \
0045     break;                              \
0046                                     \
0047   case 0:                               \
0048     if (_FP_FRAC_ZEROP_##wc(X))                     \
0049       X##_c = FP_CLS_ZERO;                      \
0050     else                                \
0051       {                                 \
0052     /* a denormalized number */                 \
0053     _FP_I_TYPE _shift;                      \
0054     _FP_FRAC_CLZ_##wc(_shift, X);                   \
0055     _shift -= _FP_FRACXBITS_##fs;                   \
0056     _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));            \
0057     X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;             \
0058     X##_c = FP_CLS_NORMAL;                      \
0059     FP_SET_EXCEPTION(FP_EX_DENORM);                 \
0060     if (FP_DENORM_ZERO)                     \
0061       {                             \
0062         FP_SET_EXCEPTION(FP_EX_INEXACT);                \
0063         X##_c = FP_CLS_ZERO;                    \
0064       }                             \
0065       }                                 \
0066     break;                              \
0067                                     \
0068   case _FP_EXPMAX_##fs:                         \
0069     if (_FP_FRAC_ZEROP_##wc(X))                     \
0070       X##_c = FP_CLS_INF;                       \
0071     else                                \
0072       {                                 \
0073     X##_c = FP_CLS_NAN;                     \
0074     /* Check for signaling NaN */                   \
0075     if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))        \
0076       FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_SNAN);     \
0077       }                                 \
0078     break;                              \
0079   }                                 \
0080 } while (0)
0081 
0082 /*
0083  * Before packing the bits back into the native fp result, take care
0084  * of such mundane things as rounding and overflow.  Also, for some
0085  * kinds of fp values, the original parts may not have been fully
0086  * extracted -- but that is ok, we can regenerate them now.
0087  */
0088 
0089 #define _FP_PACK_CANONICAL(fs, wc, X)               \
0090 do {                                \
0091   switch (X##_c)                        \
0092   {                             \
0093   case FP_CLS_NORMAL:                       \
0094     X##_e += _FP_EXPBIAS_##fs;                  \
0095     if (X##_e > 0)                      \
0096       {                             \
0097     _FP_ROUND(wc, X);                   \
0098     if (_FP_FRAC_OVERP_##wc(fs, X))             \
0099       {                         \
0100         _FP_FRAC_CLEAR_OVERP_##wc(fs, X);           \
0101         X##_e++;                        \
0102       }                         \
0103     _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);         \
0104     if (X##_e >= _FP_EXPMAX_##fs)               \
0105       {                         \
0106         /* overflow */                  \
0107         switch (FP_ROUNDMODE)               \
0108           {                         \
0109           case FP_RND_NEAREST:              \
0110         X##_c = FP_CLS_INF;             \
0111         break;                      \
0112           case FP_RND_PINF:                 \
0113         if (!X##_s) X##_c = FP_CLS_INF;         \
0114         break;                      \
0115           case FP_RND_MINF:                 \
0116         if (X##_s) X##_c = FP_CLS_INF;          \
0117         break;                      \
0118           }                         \
0119         if (X##_c == FP_CLS_INF)                \
0120           {                         \
0121         /* Overflow to infinity */          \
0122         X##_e = _FP_EXPMAX_##fs;            \
0123         _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);    \
0124           }                         \
0125         else                        \
0126           {                         \
0127         /* Overflow to maximum normal */        \
0128         X##_e = _FP_EXPMAX_##fs - 1;            \
0129         _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);     \
0130           }                         \
0131         FP_SET_EXCEPTION(FP_EX_OVERFLOW);           \
0132             FP_SET_EXCEPTION(FP_EX_INEXACT);            \
0133       }                         \
0134       }                             \
0135     else                            \
0136       {                             \
0137     /* we've got a denormalized number */           \
0138     X##_e = -X##_e + 1;                 \
0139     if (X##_e <= _FP_WFRACBITS_##fs)            \
0140       {                         \
0141         _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);    \
0142         if (_FP_FRAC_HIGH_##fs(X)               \
0143         & (_FP_OVERFLOW_##fs >> 1))         \
0144           {                         \
0145             X##_e = 1;                  \
0146             _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);    \
0147           }                         \
0148         else                        \
0149           {                         \
0150         _FP_ROUND(wc, X);               \
0151         if (_FP_FRAC_HIGH_##fs(X)           \
0152            & (_FP_OVERFLOW_##fs >> 1))          \
0153           {                     \
0154             X##_e = 1;                  \
0155             _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);    \
0156             FP_SET_EXCEPTION(FP_EX_INEXACT);        \
0157           }                     \
0158         else                        \
0159           {                     \
0160             X##_e = 0;                  \
0161             _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);     \
0162           }                     \
0163           }                         \
0164         if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) ||      \
0165         (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \
0166         FP_SET_EXCEPTION(FP_EX_UNDERFLOW);      \
0167       }                         \
0168     else                            \
0169       {                         \
0170         /* underflow to zero */             \
0171         X##_e = 0;                      \
0172         if (!_FP_FRAC_ZEROP_##wc(X))            \
0173           {                         \
0174             _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);     \
0175             _FP_ROUND(wc, X);               \
0176             _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);    \
0177           }                         \
0178         FP_SET_EXCEPTION(FP_EX_UNDERFLOW);          \
0179       }                         \
0180       }                             \
0181     break;                          \
0182                                 \
0183   case FP_CLS_ZERO:                     \
0184     X##_e = 0;                          \
0185     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);            \
0186     break;                          \
0187                                 \
0188   case FP_CLS_INF:                      \
0189     X##_e = _FP_EXPMAX_##fs;                    \
0190     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);            \
0191     break;                          \
0192                                 \
0193   case FP_CLS_NAN:                      \
0194     X##_e = _FP_EXPMAX_##fs;                    \
0195     if (!_FP_KEEPNANFRACP)                  \
0196       {                             \
0197     _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);         \
0198     X##_s = _FP_NANSIGN_##fs;               \
0199       }                             \
0200     else                            \
0201       _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;        \
0202     break;                          \
0203   }                             \
0204 } while (0)
0205 
0206 /* This one accepts raw argument and not cooked,  returns
0207  * 1 if X is a signaling NaN.
0208  */
0209 #define _FP_ISSIGNAN(fs, wc, X)                 \
0210 ({                              \
0211   int __ret = 0;                        \
0212   if (X##_e == _FP_EXPMAX_##fs)                 \
0213     {                               \
0214       if (!_FP_FRAC_ZEROP_##wc(X)               \
0215       && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))   \
0216     __ret = 1;                      \
0217     }                               \
0218   __ret;                            \
0219 })
0220 
0221 
0222 
0223 
0224 
0225 /*
0226  * Main addition routine.  The input values should be cooked.
0227  */
0228 
0229 #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)                    \
0230 do {                                         \
0231   switch (_FP_CLS_COMBINE(X##_c, Y##_c))                     \
0232   {                                      \
0233   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):                 \
0234     {                                        \
0235       /* shift the smaller number so that its exponent matches the larger */ \
0236       _FP_I_TYPE diff = X##_e - Y##_e;                       \
0237                                          \
0238       if (diff < 0)                              \
0239     {                                    \
0240       diff = -diff;                              \
0241       if (diff <= _FP_WFRACBITS_##fs)                    \
0242         _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);          \
0243       else if (!_FP_FRAC_ZEROP_##wc(X))                  \
0244         _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);              \
0245       R##_e = Y##_e;                             \
0246     }                                    \
0247       else                                   \
0248     {                                    \
0249       if (diff > 0)                              \
0250         {                                    \
0251           if (diff <= _FP_WFRACBITS_##fs)                    \
0252             _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);          \
0253           else if (!_FP_FRAC_ZEROP_##wc(Y))                  \
0254             _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);              \
0255         }                                    \
0256       R##_e = X##_e;                             \
0257     }                                    \
0258                                          \
0259       R##_c = FP_CLS_NORMAL;                             \
0260                                          \
0261       if (X##_s == Y##_s)                            \
0262     {                                    \
0263       R##_s = X##_s;                             \
0264       _FP_FRAC_ADD_##wc(R, X, Y);                        \
0265       if (_FP_FRAC_OVERP_##wc(fs, R))                    \
0266         {                                    \
0267           _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);           \
0268           R##_e++;                               \
0269         }                                    \
0270     }                                    \
0271       else                                   \
0272     {                                    \
0273       R##_s = X##_s;                             \
0274       _FP_FRAC_SUB_##wc(R, X, Y);                        \
0275       if (_FP_FRAC_ZEROP_##wc(R))                        \
0276         {                                    \
0277           /* return an exact zero */                     \
0278           if (FP_ROUNDMODE == FP_RND_MINF)                   \
0279         R##_s |= Y##_s;                          \
0280           else                               \
0281         R##_s &= Y##_s;                          \
0282           R##_c = FP_CLS_ZERO;                       \
0283         }                                    \
0284       else                                   \
0285         {                                    \
0286           if (_FP_FRAC_NEGP_##wc(R))                     \
0287         {                                \
0288           _FP_FRAC_SUB_##wc(R, Y, X);                    \
0289           R##_s = Y##_s;                         \
0290         }                                \
0291                                          \
0292           /* renormalize after subtraction */                \
0293           _FP_FRAC_CLZ_##wc(diff, R);                    \
0294           diff -= _FP_WFRACXBITS_##fs;                   \
0295           if (diff)                              \
0296         {                                \
0297           R##_e -= diff;                         \
0298           _FP_FRAC_SLL_##wc(R, diff);                    \
0299         }                                \
0300         }                                    \
0301     }                                    \
0302       break;                                     \
0303     }                                        \
0304                                          \
0305   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):                   \
0306     _FP_CHOOSENAN(fs, wc, R, X, Y, OP);                      \
0307     break;                                   \
0308                                          \
0309   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):               \
0310     R##_e = X##_e;                               \
0311     fallthrough;                                 \
0312   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):                \
0313   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):                   \
0314   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):                  \
0315     _FP_FRAC_COPY_##wc(R, X);                            \
0316     R##_s = X##_s;                               \
0317     R##_c = X##_c;                               \
0318     break;                                   \
0319                                          \
0320   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):               \
0321     R##_e = Y##_e;                               \
0322     fallthrough;                                 \
0323   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):                \
0324   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):                   \
0325   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):                  \
0326     _FP_FRAC_COPY_##wc(R, Y);                            \
0327     R##_s = Y##_s;                               \
0328     R##_c = Y##_c;                               \
0329     break;                                   \
0330                                          \
0331   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):                   \
0332     if (X##_s != Y##_s)                              \
0333       {                                      \
0334     /* +INF + -INF => NAN */                         \
0335     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                  \
0336     R##_s = _FP_NANSIGN_##fs;                        \
0337     R##_c = FP_CLS_NAN;                          \
0338     FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ISI);             \
0339     break;                                   \
0340       }                                      \
0341     fallthrough;                                 \
0342                                          \
0343   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):                \
0344   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):                  \
0345     R##_s = X##_s;                               \
0346     R##_c = FP_CLS_INF;                              \
0347     break;                                   \
0348                                          \
0349   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):                \
0350   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):                  \
0351     R##_s = Y##_s;                               \
0352     R##_c = FP_CLS_INF;                              \
0353     break;                                   \
0354                                          \
0355   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):                 \
0356     /* make sure the sign is correct */                      \
0357     if (FP_ROUNDMODE == FP_RND_MINF)                         \
0358       R##_s = X##_s | Y##_s;                             \
0359     else                                     \
0360       R##_s = X##_s & Y##_s;                             \
0361     R##_c = FP_CLS_ZERO;                             \
0362     break;                                   \
0363                                          \
0364   default:                                   \
0365     abort();                                     \
0366   }                                      \
0367 } while (0)
0368 
0369 #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
0370 #define _FP_SUB(fs, wc, R, X, Y)                         \
0371   do {                                       \
0372     if (Y##_c != FP_CLS_NAN) Y##_s ^= 1;                     \
0373     _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-');                  \
0374   } while (0)
0375 
0376 
0377 /*
0378  * Main negation routine.  FIXME -- when we care about setting exception
0379  * bits reliably, this will not do.  We should examine all of the fp classes.
0380  */
0381 
0382 #define _FP_NEG(fs, wc, R, X)       \
0383   do {                  \
0384     _FP_FRAC_COPY_##wc(R, X);       \
0385     R##_c = X##_c;          \
0386     R##_e = X##_e;          \
0387     R##_s = 1 ^ X##_s;          \
0388   } while (0)
0389 
0390 
0391 /*
0392  * Main multiplication routine.  The input values should be cooked.
0393  */
0394 
0395 #define _FP_MUL(fs, wc, R, X, Y)            \
0396 do {                            \
0397   R##_s = X##_s ^ Y##_s;                \
0398   switch (_FP_CLS_COMBINE(X##_c, Y##_c))        \
0399   {                         \
0400   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
0401     R##_c = FP_CLS_NORMAL;              \
0402     R##_e = X##_e + Y##_e + 1;              \
0403                             \
0404     _FP_MUL_MEAT_##fs(R,X,Y);               \
0405                             \
0406     if (_FP_FRAC_OVERP_##wc(fs, R))         \
0407       _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);  \
0408     else                        \
0409       R##_e--;                      \
0410     break;                      \
0411                             \
0412   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):      \
0413     _FP_CHOOSENAN(fs, wc, R, X, Y, '*');        \
0414     break;                      \
0415                             \
0416   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):   \
0417   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):      \
0418   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):     \
0419     R##_s = X##_s;                  \
0420       fallthrough;                  \
0421                             \
0422   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):      \
0423   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):   \
0424   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):  \
0425   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):    \
0426     _FP_FRAC_COPY_##wc(R, X);               \
0427     R##_c = X##_c;                  \
0428     break;                      \
0429                             \
0430   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):   \
0431   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):      \
0432   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):     \
0433     R##_s = Y##_s;                  \
0434       fallthrough;                  \
0435                             \
0436   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):   \
0437   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):  \
0438     _FP_FRAC_COPY_##wc(R, Y);               \
0439     R##_c = Y##_c;                  \
0440     break;                      \
0441                             \
0442   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):     \
0443   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):     \
0444     R##_s = _FP_NANSIGN_##fs;               \
0445     R##_c = FP_CLS_NAN;                 \
0446     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);     \
0447     FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IMZ);\
0448     break;                      \
0449                             \
0450   default:                      \
0451     abort();                        \
0452   }                         \
0453 } while (0)
0454 
0455 
0456 /*
0457  * Main division routine.  The input values should be cooked.
0458  */
0459 
0460 #define _FP_DIV(fs, wc, R, X, Y)            \
0461 do {                            \
0462   R##_s = X##_s ^ Y##_s;                \
0463   switch (_FP_CLS_COMBINE(X##_c, Y##_c))        \
0464   {                         \
0465   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
0466     R##_c = FP_CLS_NORMAL;              \
0467     R##_e = X##_e - Y##_e;              \
0468                             \
0469     _FP_DIV_MEAT_##fs(R,X,Y);               \
0470     break;                      \
0471                             \
0472   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):      \
0473     _FP_CHOOSENAN(fs, wc, R, X, Y, '/');        \
0474     break;                      \
0475                             \
0476   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):   \
0477   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):      \
0478   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):     \
0479     R##_s = X##_s;                  \
0480     _FP_FRAC_COPY_##wc(R, X);               \
0481     R##_c = X##_c;                  \
0482     break;                      \
0483                             \
0484   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):   \
0485   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):      \
0486   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):     \
0487     R##_s = Y##_s;                  \
0488     _FP_FRAC_COPY_##wc(R, Y);               \
0489     R##_c = Y##_c;                  \
0490     break;                      \
0491                             \
0492   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):   \
0493   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):     \
0494   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):  \
0495     R##_c = FP_CLS_ZERO;                \
0496     break;                      \
0497                             \
0498   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):  \
0499     FP_SET_EXCEPTION(FP_EX_DIVZERO);            \
0500     fallthrough;                    \
0501   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):     \
0502   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):   \
0503     R##_c = FP_CLS_INF;                 \
0504     break;                      \
0505                             \
0506   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):      \
0507     R##_s = _FP_NANSIGN_##fs;               \
0508     R##_c = FP_CLS_NAN;                 \
0509     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);     \
0510     FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\
0511     break;                      \
0512                             \
0513   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):    \
0514     R##_s = _FP_NANSIGN_##fs;               \
0515     R##_c = FP_CLS_NAN;                 \
0516     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);     \
0517     FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ZDZ);\
0518     break;                      \
0519                             \
0520   default:                      \
0521     abort();                        \
0522   }                         \
0523 } while (0)
0524 
0525 
0526 /*
0527  * Main differential comparison routine.  The inputs should be raw not
0528  * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
0529  */
0530 
0531 #define _FP_CMP(fs, wc, ret, X, Y, un)                  \
0532   do {                                  \
0533     /* NANs are unordered */                        \
0534     if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))       \
0535     || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))   \
0536       {                                 \
0537     ret = un;                           \
0538       }                                 \
0539     else                                \
0540       {                                 \
0541     int __is_zero_x;                        \
0542     int __is_zero_y;                        \
0543                                     \
0544     __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;   \
0545     __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;   \
0546                                     \
0547     if (__is_zero_x && __is_zero_y)                 \
0548         ret = 0;                        \
0549     else if (__is_zero_x)                       \
0550         ret = Y##_s ? 1 : -1;                   \
0551     else if (__is_zero_y)                       \
0552         ret = X##_s ? -1 : 1;                   \
0553     else if (X##_s != Y##_s)                    \
0554       ret = X##_s ? -1 : 1;                     \
0555     else if (X##_e > Y##_e)                     \
0556       ret = X##_s ? -1 : 1;                     \
0557     else if (X##_e < Y##_e)                     \
0558       ret = X##_s ? 1 : -1;                     \
0559     else if (_FP_FRAC_GT_##wc(X, Y))                \
0560       ret = X##_s ? -1 : 1;                     \
0561     else if (_FP_FRAC_GT_##wc(Y, X))                \
0562       ret = X##_s ? 1 : -1;                     \
0563     else                                \
0564       ret = 0;                          \
0565       }                                 \
0566   } while (0)
0567 
0568 
0569 /* Simplification for strict equality.  */
0570 
0571 #define _FP_CMP_EQ(fs, wc, ret, X, Y)                     \
0572   do {                                    \
0573     /* NANs are unordered */                          \
0574     if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))         \
0575     || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))     \
0576       {                                   \
0577     ret = 1;                              \
0578       }                                   \
0579     else                                  \
0580       {                                   \
0581     ret = !(X##_e == Y##_e                        \
0582         && _FP_FRAC_EQ_##wc(X, Y)                 \
0583         && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
0584       }                                   \
0585   } while (0)
0586 
0587 /*
0588  * Main square root routine.  The input value should be cooked.
0589  */
0590 
0591 #define _FP_SQRT(fs, wc, R, X)                      \
0592 do {                                    \
0593     _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);           \
0594     _FP_W_TYPE q;                           \
0595     switch (X##_c)                          \
0596     {                                   \
0597     case FP_CLS_NAN:                            \
0598     _FP_FRAC_COPY_##wc(R, X);                   \
0599     R##_s = X##_s;                          \
0600         R##_c = FP_CLS_NAN;                     \
0601         break;                              \
0602     case FP_CLS_INF:                            \
0603         if (X##_s)                          \
0604           {                             \
0605             R##_s = _FP_NANSIGN_##fs;                   \
0606         R##_c = FP_CLS_NAN; /* NAN */               \
0607         _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);         \
0608         FP_SET_EXCEPTION(FP_EX_INVALID);                \
0609           }                             \
0610         else                                \
0611           {                             \
0612             R##_s = 0;                          \
0613             R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */         \
0614           }                             \
0615         break;                              \
0616     case FP_CLS_ZERO:                           \
0617     R##_s = X##_s;                          \
0618     R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */          \
0619     break;                              \
0620     case FP_CLS_NORMAL:                         \
0621         R##_s = 0;                          \
0622         if (X##_s)                          \
0623           {                             \
0624         R##_c = FP_CLS_NAN; /* sNAN */              \
0625         R##_s = _FP_NANSIGN_##fs;                   \
0626         _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);         \
0627         FP_SET_EXCEPTION(FP_EX_INVALID);                \
0628         break;                          \
0629           }                             \
0630         R##_c = FP_CLS_NORMAL;                      \
0631         if (X##_e & 1)                          \
0632           _FP_FRAC_SLL_##wc(X, 1);                  \
0633         R##_e = X##_e >> 1;                     \
0634         _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);            \
0635         _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);            \
0636         q = _FP_OVERFLOW_##fs >> 1;                 \
0637         _FP_SQRT_MEAT_##wc(R, S, T, X, q);              \
0638     }                                   \
0639   } while (0)
0640 
0641 /*
0642  * Convert from FP to integer
0643  */
0644 
0645 /* RSIGNED can have following values:
0646  * 0:  the number is required to be 0..(2^rsize)-1, if not, NV is set plus
0647  *     the result is either 0 or (2^rsize)-1 depending on the sign in such case.
0648  * 1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
0649  *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
0650  *     on the sign in such case.
0651  * 2:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
0652  *     set plus the result is truncated to fit into destination.
0653  * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
0654  *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
0655  *     on the sign in such case.
0656  */
0657 #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)                \
0658   do {                                      \
0659     switch (X##_c)                              \
0660       {                                     \
0661       case FP_CLS_NORMAL:                           \
0662     if (X##_e < 0)                              \
0663       {                                 \
0664         FP_SET_EXCEPTION(FP_EX_INEXACT);                    \
0665       case FP_CLS_ZERO:                         \
0666         r = 0;                              \
0667       }                                 \
0668     else if (X##_e >= rsize - (rsigned > 0 || X##_s)            \
0669          || (!rsigned && X##_s))                    \
0670       { /* overflow */                          \
0671       case FP_CLS_NAN:                                                      \
0672       case FP_CLS_INF:                          \
0673         if (rsigned == 2)                           \
0674           {                                 \
0675         if (X##_c != FP_CLS_NORMAL                  \
0676             || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs)         \
0677           r = 0;                            \
0678         else                                \
0679           {                             \
0680             _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
0681             _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);            \
0682           }                             \
0683           }                                 \
0684         else if (rsigned)                           \
0685           {                                 \
0686         r = 1;                              \
0687         r <<= rsize - 1;                        \
0688         r -= 1 - X##_s;                         \
0689           }                                 \
0690         else                                \
0691           {                                 \
0692         r = 0;                              \
0693         if (!X##_s)                         \
0694           r = ~r;                           \
0695           }                                 \
0696         FP_SET_EXCEPTION(FP_EX_INVALID);                    \
0697       }                                 \
0698     else                                    \
0699       {                                 \
0700         if (_FP_W_TYPE_SIZE*wc < rsize)                 \
0701           {                                 \
0702         _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                \
0703         r <<= X##_e - _FP_WFRACBITS_##fs;               \
0704           }                                 \
0705         else                                \
0706           {                                 \
0707         if (X##_e >= _FP_WFRACBITS_##fs)                \
0708           _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));   \
0709         else if (X##_e < _FP_WFRACBITS_##fs - 1)            \
0710           {                             \
0711             _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2),  \
0712                       _FP_WFRACBITS_##fs);          \
0713             if (_FP_FRAC_LOW_##wc(X) & 1)               \
0714               FP_SET_EXCEPTION(FP_EX_INEXACT);              \
0715             _FP_FRAC_SRL_##wc(X, 1);                    \
0716           }                             \
0717         _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                \
0718           }                                 \
0719         if (rsigned && X##_s)                       \
0720           r = -r;                               \
0721       }                                 \
0722     break;                                  \
0723       }                                     \
0724   } while (0)
0725 
0726 #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned)              \
0727   do {                                      \
0728     r = 0;                                  \
0729     switch (X##_c)                              \
0730       {                                     \
0731       case FP_CLS_NORMAL:                           \
0732     if (X##_e >= _FP_FRACBITS_##fs - 1)                 \
0733       {                                 \
0734         if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs)             \
0735           {                                 \
0736         if (X##_e >= _FP_WFRACBITS_##fs - 1)                \
0737           {                             \
0738             _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);            \
0739             r <<= X##_e - _FP_WFRACBITS_##fs + 1;           \
0740           }                             \
0741         else                                \
0742           {                             \
0743             _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e           \
0744                       + _FP_FRACBITS_##fs - 1);         \
0745             _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);            \
0746           }                             \
0747           }                                 \
0748       }                                 \
0749     else                                    \
0750       {                                 \
0751         int _lz0, _lz1;                         \
0752         if (X##_e <= -_FP_WORKBITS - 1)                 \
0753           _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);               \
0754         else                                \
0755           _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e,       \
0756                 _FP_WFRACBITS_##fs);                \
0757         _FP_FRAC_CLZ_##wc(_lz0, X);                     \
0758         _FP_ROUND(wc, X);                           \
0759         _FP_FRAC_CLZ_##wc(_lz1, X);                     \
0760         if (_lz1 < _lz0)                            \
0761           X##_e++; /* For overflow detection.  */               \
0762         _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                 \
0763         _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                \
0764       }                                 \
0765     if (rsigned && X##_s)                           \
0766       r = -r;                               \
0767     if (X##_e >= rsize - (rsigned > 0 || X##_s)             \
0768         || (!rsigned && X##_s))                     \
0769       { /* overflow */                          \
0770       case FP_CLS_NAN:                                                      \
0771       case FP_CLS_INF:                          \
0772         if (!rsigned)                           \
0773           {                                 \
0774         r = 0;                              \
0775         if (!X##_s)                         \
0776           r = ~r;                           \
0777           }                                 \
0778         else if (rsigned != 2)                      \
0779           {                                 \
0780         r = 1;                              \
0781         r <<= rsize - 1;                        \
0782         r -= 1 - X##_s;                         \
0783           }                                 \
0784         FP_SET_EXCEPTION(FP_EX_INVALID);                    \
0785       }                                 \
0786     break;                                  \
0787       case FP_CLS_ZERO:                             \
0788         break;                                  \
0789       }                                     \
0790   } while (0)
0791 
0792 #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)            \
0793   do {                                  \
0794     if (r)                              \
0795       {                                 \
0796         unsigned rtype ur_;                     \
0797     X##_c = FP_CLS_NORMAL;                      \
0798                                     \
0799     if ((X##_s = (r < 0)))                      \
0800       ur_ = (unsigned rtype) -r;                    \
0801     else                                \
0802       ur_ = (unsigned rtype) r;                 \
0803     (void) (((rsize) <= _FP_W_TYPE_SIZE)                \
0804         ? ({ __FP_CLZ(X##_e, ur_); })               \
0805         : ({                            \
0806              __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE),  \
0807                                 (_FP_W_TYPE)ur_); \
0808           }));                          \
0809     if (rsize < _FP_W_TYPE_SIZE)                    \
0810         X##_e -= (_FP_W_TYPE_SIZE - rsize);         \
0811     X##_e = rsize - X##_e - 1;                  \
0812                                     \
0813     if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs <= X##_e)   \
0814       __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
0815     _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);           \
0816     if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0)           \
0817       _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));   \
0818       }                                 \
0819     else                                \
0820       {                                 \
0821     X##_c = FP_CLS_ZERO, X##_s = 0;                 \
0822       }                                 \
0823   } while (0)
0824 
0825 
0826 #define FP_CONV(dfs,sfs,dwc,swc,D,S)            \
0827   do {                          \
0828     _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);    \
0829     D##_e = S##_e;                  \
0830     D##_c = S##_c;                  \
0831     D##_s = S##_s;                  \
0832   } while (0)
0833 
0834 /*
0835  * Helper primitives.
0836  */
0837 
0838 /* Count leading zeros in a word.  */
0839 
0840 #ifndef __FP_CLZ
0841 #if _FP_W_TYPE_SIZE < 64
0842 /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
0843 #define __FP_CLZ(r, x)              \
0844   do {                      \
0845     _FP_W_TYPE _t = (x);            \
0846     r = _FP_W_TYPE_SIZE - 1;            \
0847     if (_t > 0xffff) r -= 16;           \
0848     if (_t > 0xffff) _t >>= 16;         \
0849     if (_t > 0xff) r -= 8;          \
0850     if (_t > 0xff) _t >>= 8;            \
0851     if (_t & 0xf0) r -= 4;          \
0852     if (_t & 0xf0) _t >>= 4;            \
0853     if (_t & 0xc) r -= 2;           \
0854     if (_t & 0xc) _t >>= 2;         \
0855     if (_t & 0x2) r -= 1;           \
0856   } while (0)
0857 #else /* not _FP_W_TYPE_SIZE < 64 */
0858 #define __FP_CLZ(r, x)              \
0859   do {                      \
0860     _FP_W_TYPE _t = (x);            \
0861     r = _FP_W_TYPE_SIZE - 1;            \
0862     if (_t > 0xffffffff) r -= 32;       \
0863     if (_t > 0xffffffff) _t >>= 32;     \
0864     if (_t > 0xffff) r -= 16;           \
0865     if (_t > 0xffff) _t >>= 16;         \
0866     if (_t > 0xff) r -= 8;          \
0867     if (_t > 0xff) _t >>= 8;            \
0868     if (_t & 0xf0) r -= 4;          \
0869     if (_t & 0xf0) _t >>= 4;            \
0870     if (_t & 0xc) r -= 2;           \
0871     if (_t & 0xc) _t >>= 2;         \
0872     if (_t & 0x2) r -= 1;           \
0873   } while (0)
0874 #endif /* not _FP_W_TYPE_SIZE < 64 */
0875 #endif /* ndef __FP_CLZ */
0876 
0877 #define _FP_DIV_HELP_imm(q, r, n, d)        \
0878   do {                      \
0879     q = n / d, r = n % d;           \
0880   } while (0)
0881 
0882 #endif /* __MATH_EMU_OP_COMMON_H__ */