0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/compiler.h>
0011
0012 #include "ieee754dp.h"
0013
0014 int ieee754dp_class(union ieee754dp x)
0015 {
0016 COMPXDP;
0017 EXPLODEXDP;
0018 return xc;
0019 }
0020
0021 static inline int ieee754dp_isnan(union ieee754dp x)
0022 {
0023 return ieee754_class_nan(ieee754dp_class(x));
0024 }
0025
0026 static inline int ieee754dp_issnan(union ieee754dp x)
0027 {
0028 int qbit;
0029
0030 assert(ieee754dp_isnan(x));
0031 qbit = (DPMANT(x) & DP_MBIT(DP_FBITS - 1)) == DP_MBIT(DP_FBITS - 1);
0032 return ieee754_csr.nan2008 ^ qbit;
0033 }
0034
0035
0036
0037
0038
0039
0040 union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r)
0041 {
0042 assert(ieee754dp_issnan(r));
0043
0044 ieee754_setcx(IEEE754_INVALID_OPERATION);
0045 if (ieee754_csr.nan2008) {
0046 DPMANT(r) |= DP_MBIT(DP_FBITS - 1);
0047 } else {
0048 DPMANT(r) &= ~DP_MBIT(DP_FBITS - 1);
0049 if (!ieee754dp_isnan(r))
0050 DPMANT(r) |= DP_MBIT(DP_FBITS - 2);
0051 }
0052
0053 return r;
0054 }
0055
0056 static u64 ieee754dp_get_rounding(int sn, u64 xm)
0057 {
0058
0059
0060 if (xm & (DP_MBIT(3) - 1)) {
0061 switch (ieee754_csr.rm) {
0062 case FPU_CSR_RZ:
0063 break;
0064 case FPU_CSR_RN:
0065 xm += 0x3 + ((xm >> 3) & 1);
0066
0067 break;
0068 case FPU_CSR_RU:
0069 if (!sn)
0070 xm += 0x8;
0071 break;
0072 case FPU_CSR_RD:
0073 if (sn)
0074 xm += 0x8;
0075 break;
0076 }
0077 }
0078 return xm;
0079 }
0080
0081
0082
0083
0084
0085
0086
0087 union ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
0088 {
0089 assert(xm);
0090
0091 assert((xm >> (DP_FBITS + 1 + 3)) == 0);
0092 assert(xm & (DP_HIDDEN_BIT << 3));
0093
0094 if (xe < DP_EMIN) {
0095
0096 int es = DP_EMIN - xe;
0097
0098 if (ieee754_csr.nod) {
0099 ieee754_setcx(IEEE754_UNDERFLOW);
0100 ieee754_setcx(IEEE754_INEXACT);
0101
0102 switch(ieee754_csr.rm) {
0103 case FPU_CSR_RN:
0104 case FPU_CSR_RZ:
0105 return ieee754dp_zero(sn);
0106 case FPU_CSR_RU:
0107 if (sn == 0)
0108 return ieee754dp_min(0);
0109 else
0110 return ieee754dp_zero(1);
0111 case FPU_CSR_RD:
0112 if (sn == 0)
0113 return ieee754dp_zero(0);
0114 else
0115 return ieee754dp_min(1);
0116 }
0117 }
0118
0119 if (xe == DP_EMIN - 1 &&
0120 ieee754dp_get_rounding(sn, xm) >> (DP_FBITS + 1 + 3))
0121 {
0122
0123 ieee754_setcx(IEEE754_INEXACT);
0124 xm = ieee754dp_get_rounding(sn, xm);
0125 xm >>= 1;
0126
0127 xm &= ~(DP_MBIT(3) - 1);
0128 xe++;
0129 }
0130 else {
0131
0132
0133 xm = XDPSRS(xm, es);
0134 xe += es;
0135 assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
0136 assert(xe == DP_EMIN);
0137 }
0138 }
0139 if (xm & (DP_MBIT(3) - 1)) {
0140 ieee754_setcx(IEEE754_INEXACT);
0141 if ((xm & (DP_HIDDEN_BIT << 3)) == 0) {
0142 ieee754_setcx(IEEE754_UNDERFLOW);
0143 }
0144
0145
0146
0147 xm = ieee754dp_get_rounding(sn, xm);
0148
0149
0150 if (xm >> (DP_FBITS + 3 + 1)) {
0151
0152 xm >>= 1;
0153 xe++;
0154 }
0155 }
0156
0157 xm >>= 3;
0158
0159 assert((xm >> (DP_FBITS + 1)) == 0);
0160 assert(xe >= DP_EMIN);
0161
0162 if (xe > DP_EMAX) {
0163 ieee754_setcx(IEEE754_OVERFLOW);
0164 ieee754_setcx(IEEE754_INEXACT);
0165
0166 switch (ieee754_csr.rm) {
0167 case FPU_CSR_RN:
0168 return ieee754dp_inf(sn);
0169 case FPU_CSR_RZ:
0170 return ieee754dp_max(sn);
0171 case FPU_CSR_RU:
0172 if (sn == 0)
0173 return ieee754dp_inf(0);
0174 else
0175 return ieee754dp_max(1);
0176 case FPU_CSR_RD:
0177 if (sn == 0)
0178 return ieee754dp_max(0);
0179 else
0180 return ieee754dp_inf(1);
0181 }
0182 }
0183
0184
0185 if ((xm & DP_HIDDEN_BIT) == 0) {
0186
0187 assert(xe == DP_EMIN);
0188 if (ieee754_csr.mx & IEEE754_UNDERFLOW)
0189 ieee754_setcx(IEEE754_UNDERFLOW);
0190 return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
0191 } else {
0192 assert((xm >> (DP_FBITS + 1)) == 0);
0193 assert(xm & DP_HIDDEN_BIT);
0194
0195 return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
0196 }
0197 }