1 // SPDX-License-Identifier: GPL-2.0-only 1 2 /* IEEE754 floating point arithmetic 3 * double precision: common utilities 4 */ 5 /* 6 * MIPS floating point support 7 * Copyright (C) 1994-2000 Algorithmics Ltd. 8 */ 9 10 #include <linux/compiler.h> 11 12 #include "ieee754dp.h" 13 14 int ieee754dp_class(union ieee754dp x) 15 { 16 COMPXDP; 17 EXPLODEXDP; 18 return xc; 19 } 20 21 static inline int ieee754dp_isnan(union ieee75 22 { 23 return ieee754_class_nan(ieee754dp_cla 24 } 25 26 static inline int ieee754dp_issnan(union ieee7 27 { 28 int qbit; 29 30 assert(ieee754dp_isnan(x)); 31 qbit = (DPMANT(x) & DP_MBIT(DP_FBITS - 32 return ieee754_csr.nan2008 ^ qbit; 33 } 34 35 36 /* 37 * Raise the Invalid Operation IEEE 754 except 38 * and convert the signaling NaN supplied to a 39 */ 40 union ieee754dp __cold ieee754dp_nanxcpt(union 41 { 42 assert(ieee754dp_issnan(r)); 43 44 ieee754_setcx(IEEE754_INVALID_OPERATIO 45 if (ieee754_csr.nan2008) { 46 DPMANT(r) |= DP_MBIT(DP_FBITS 47 } else { 48 DPMANT(r) &= ~DP_MBIT(DP_FBITS 49 if (!ieee754dp_isnan(r)) 50 DPMANT(r) |= DP_MBIT(D 51 } 52 53 return r; 54 } 55 56 static u64 ieee754dp_get_rounding(int sn, u64 57 { 58 /* inexact must round of 3 bits 59 */ 60 if (xm & (DP_MBIT(3) - 1)) { 61 switch (ieee754_csr.rm) { 62 case FPU_CSR_RZ: 63 break; 64 case FPU_CSR_RN: 65 xm += 0x3 + ((xm >> 3) 66 /* xm += (xm&0x8)?0x4: 67 break; 68 case FPU_CSR_RU: /* tow 69 if (!sn) /* ?? 70 xm += 0x8; 71 break; 72 case FPU_CSR_RD: /* tow 73 if (sn) /* ?? */ 74 xm += 0x8; 75 break; 76 } 77 } 78 return xm; 79 } 80 81 82 /* generate a normal/denormal number with over 83 * sn is sign 84 * xe is an unbiased exponent 85 * xm is 3bit extended precision value. 86 */ 87 union ieee754dp ieee754dp_format(int sn, int x 88 { 89 assert(xm); /* we don't ge 90 91 assert((xm >> (DP_FBITS + 1 + 3)) == 0 92 assert(xm & (DP_HIDDEN_BIT << 3)); 93 94 if (xe < DP_EMIN) { 95 /* strip lower bits */ 96 int es = DP_EMIN - xe; 97 98 if (ieee754_csr.nod) { 99 ieee754_setcx(IEEE754_ 100 ieee754_setcx(IEEE754_ 101 102 switch(ieee754_csr.rm) 103 case FPU_CSR_RN: 104 case FPU_CSR_RZ: 105 return ieee754 106 case FPU_CSR_RU: /* 107 if (sn == 0) 108 return 109 else 110 return 111 case FPU_CSR_RD: /* 112 if (sn == 0) 113 return 114 else 115 return 116 } 117 } 118 119 if (xe == DP_EMIN - 1 && 120 ieee754dp_get_rounding(sn, 121 { 122 /* Not tiny after roun 123 ieee754_setcx(IEEE754_ 124 xm = ieee754dp_get_rou 125 xm >>= 1; 126 /* Clear grs bits */ 127 xm &= ~(DP_MBIT(3) - 1 128 xe++; 129 } 130 else { 131 /* sticky right shift 132 */ 133 xm = XDPSRS(xm, es); 134 xe += es; 135 assert((xm & (DP_HIDDE 136 assert(xe == DP_EMIN); 137 } 138 } 139 if (xm & (DP_MBIT(3) - 1)) { 140 ieee754_setcx(IEEE754_INEXACT) 141 if ((xm & (DP_HIDDEN_BIT << 3) 142 ieee754_setcx(IEEE754_ 143 } 144 145 /* inexact must round of 3 bit 146 */ 147 xm = ieee754dp_get_rounding(sn 148 /* adjust exponent for roundin 149 */ 150 if (xm >> (DP_FBITS + 3 + 1)) 151 /* add causes mantissa 152 xm >>= 1; 153 xe++; 154 } 155 } 156 /* strip grs bits */ 157 xm >>= 3; 158 159 assert((xm >> (DP_FBITS + 1)) == 0); 160 assert(xe >= DP_EMIN); 161 162 if (xe > DP_EMAX) { 163 ieee754_setcx(IEEE754_OVERFLOW 164 ieee754_setcx(IEEE754_INEXACT) 165 /* -O can be table indexed by 166 switch (ieee754_csr.rm) { 167 case FPU_CSR_RN: 168 return ieee754dp_inf(s 169 case FPU_CSR_RZ: 170 return ieee754dp_max(s 171 case FPU_CSR_RU: /* tow 172 if (sn == 0) 173 return ieee754 174 else 175 return ieee754 176 case FPU_CSR_RD: /* tow 177 if (sn == 0) 178 return ieee754 179 else 180 return ieee754 181 } 182 } 183 /* gen norm/denorm/zero */ 184 185 if ((xm & DP_HIDDEN_BIT) == 0) { 186 /* we underflow (tiny/zero) */ 187 assert(xe == DP_EMIN); 188 if (ieee754_csr.mx & IEEE754_U 189 ieee754_setcx(IEEE754_ 190 return builddp(sn, DP_EMIN - 1 191 } else { 192 assert((xm >> (DP_FBITS + 1)) 193 assert(xm & DP_HIDDEN_BIT); 194 195 return builddp(sn, xe + DP_EBI 196 } 197 } 198
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.