^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* IEEE754 floating point arithmetic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * double precision: common utilities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * MIPS floating point support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 1994-2000 Algorithmics Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "ieee754dp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) int ieee754dp_tint(union ieee754dp x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) u64 residue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) int round;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) int sticky;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) int odd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) COMPXDP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) ieee754_clearcx();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) EXPLODEXDP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) FLUSHXDP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) switch (xc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) case IEEE754_CLASS_SNAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) case IEEE754_CLASS_QNAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ieee754_setcx(IEEE754_INVALID_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return ieee754si_indef();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) case IEEE754_CLASS_INF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ieee754_setcx(IEEE754_INVALID_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return ieee754si_overflow(xs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) case IEEE754_CLASS_ZERO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) case IEEE754_CLASS_DNORM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) case IEEE754_CLASS_NORM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (xe > 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Set invalid. We will only use overflow for floating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) point overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ieee754_setcx(IEEE754_INVALID_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return ieee754si_overflow(xs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* oh gawd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (xe > DP_FBITS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) xm <<= xe - DP_FBITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) } else if (xe < DP_FBITS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (xe < -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) residue = xm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) round = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) sticky = residue != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) xm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) residue = xm << (64 - DP_FBITS + xe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) round = (residue >> 63) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) sticky = (residue << 1) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) xm >>= DP_FBITS - xe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* Note: At this point upper 32 bits of xm are guaranteed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) to be zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) odd = (xm & 0x1) != 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) switch (ieee754_csr.rm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) case FPU_CSR_RN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (round && (sticky || odd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) xm++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) case FPU_CSR_RZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) case FPU_CSR_RU: /* toward +Infinity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if ((round || sticky) && !xs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) xm++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) case FPU_CSR_RD: /* toward -Infinity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if ((round || sticky) && xs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) xm++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* look for valid corner case 0x80000000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* This can happen after rounding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ieee754_setcx(IEEE754_INVALID_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return ieee754si_overflow(xs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (round || sticky)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ieee754_setcx(IEEE754_INEXACT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (xs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return -xm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return xm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }