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