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