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