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