0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "ieee754sp.h"
0013
0014
0015 static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
0016 union ieee754sp y, enum maddf_flags flags)
0017 {
0018 int re;
0019 int rs;
0020 unsigned int rm;
0021 u64 rm64;
0022 u64 zm64;
0023 int s;
0024
0025 COMPXSP;
0026 COMPYSP;
0027 COMPZSP;
0028
0029 EXPLODEXSP;
0030 EXPLODEYSP;
0031 EXPLODEZSP;
0032
0033 FLUSHXSP;
0034 FLUSHYSP;
0035 FLUSHZSP;
0036
0037 ieee754_clearcx();
0038
0039 rs = xs ^ ys;
0040 if (flags & MADDF_NEGATE_PRODUCT)
0041 rs ^= 1;
0042 if (flags & MADDF_NEGATE_ADDITION)
0043 zs ^= 1;
0044
0045
0046
0047
0048
0049 if (zc == IEEE754_CLASS_SNAN)
0050 return ieee754sp_nanxcpt(z);
0051 if (xc == IEEE754_CLASS_SNAN)
0052 return ieee754sp_nanxcpt(x);
0053 if (yc == IEEE754_CLASS_SNAN)
0054 return ieee754sp_nanxcpt(y);
0055 if (zc == IEEE754_CLASS_QNAN)
0056 return z;
0057 if (xc == IEEE754_CLASS_QNAN)
0058 return x;
0059 if (yc == IEEE754_CLASS_QNAN)
0060 return y;
0061
0062 if (zc == IEEE754_CLASS_DNORM)
0063 SPDNORMZ;
0064
0065
0066 switch (CLPAIR(xc, yc)) {
0067
0068
0069
0070
0071
0072 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
0073 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
0074 ieee754_setcx(IEEE754_INVALID_OPERATION);
0075 return ieee754sp_indef();
0076
0077 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
0078 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
0079 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
0080 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
0081 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
0082 if ((zc == IEEE754_CLASS_INF) && (zs != rs)) {
0083
0084
0085
0086
0087 ieee754_setcx(IEEE754_INVALID_OPERATION);
0088 return ieee754sp_indef();
0089 }
0090
0091
0092
0093
0094
0095 return ieee754sp_inf(rs);
0096
0097 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
0098 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
0099 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
0100 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
0101 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
0102 if (zc == IEEE754_CLASS_INF)
0103 return ieee754sp_inf(zs);
0104 if (zc == IEEE754_CLASS_ZERO) {
0105
0106 if (zs == rs)
0107
0108
0109
0110
0111
0112
0113 return z;
0114
0115 return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
0116 }
0117
0118 return z;
0119
0120 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
0121 SPDNORMX;
0122 fallthrough;
0123 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
0124 if (zc == IEEE754_CLASS_INF)
0125 return ieee754sp_inf(zs);
0126 SPDNORMY;
0127 break;
0128
0129 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
0130 if (zc == IEEE754_CLASS_INF)
0131 return ieee754sp_inf(zs);
0132 SPDNORMX;
0133 break;
0134
0135 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
0136 if (zc == IEEE754_CLASS_INF)
0137 return ieee754sp_inf(zs);
0138
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152 assert(xm & SP_HIDDEN_BIT);
0153 assert(ym & SP_HIDDEN_BIT);
0154
0155 re = xe + ye;
0156
0157
0158 rm64 = (uint64_t)xm * ym;
0159
0160
0161 rm64 = rm64 << 16;
0162
0163
0164 if ((int64_t) rm64 < 0) {
0165 rm64 = rm64 >> 1;
0166 re++;
0167 }
0168
0169 assert(rm64 & (1 << 62));
0170
0171 if (zc == IEEE754_CLASS_ZERO) {
0172
0173
0174
0175
0176
0177 rm = XSPSRS64(rm64, (62 - 26));
0178 return ieee754sp_format(rs, re, rm);
0179 }
0180
0181
0182 zm64 = (uint64_t)zm << (62 - 23);
0183 assert(zm64 & (1 << 62));
0184
0185
0186 if (ze > re) {
0187
0188
0189
0190 s = ze - re;
0191 rm64 = XSPSRS64(rm64, s);
0192 re += s;
0193 } else if (re > ze) {
0194
0195
0196
0197 s = re - ze;
0198 zm64 = XSPSRS64(zm64, s);
0199 ze += s;
0200 }
0201 assert(ze == re);
0202 assert(ze <= SP_EMAX);
0203
0204
0205 if (zs == rs) {
0206
0207
0208
0209
0210 zm64 = zm64 + rm64;
0211 if ((int64_t)zm64 < 0) {
0212 zm64 = XSPSRS1(zm64);
0213 ze++;
0214 }
0215 } else {
0216 if (zm64 >= rm64) {
0217 zm64 = zm64 - rm64;
0218 } else {
0219 zm64 = rm64 - zm64;
0220 zs = rs;
0221 }
0222 if (zm64 == 0)
0223 return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
0224
0225
0226
0227
0228 while ((zm64 >> 62) == 0) {
0229 zm64 <<= 1;
0230 ze--;
0231 }
0232 }
0233
0234
0235
0236
0237
0238
0239 zm = XSPSRS64(zm64, (62 - 26));
0240
0241 return ieee754sp_format(zs, ze, zm);
0242 }
0243
0244 union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
0245 union ieee754sp y)
0246 {
0247 return _sp_maddf(z, x, y, 0);
0248 }
0249
0250 union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
0251 union ieee754sp y)
0252 {
0253 return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
0254 }
0255
0256 union ieee754sp ieee754sp_madd(union ieee754sp z, union ieee754sp x,
0257 union ieee754sp y)
0258 {
0259 return _sp_maddf(z, x, y, 0);
0260 }
0261
0262 union ieee754sp ieee754sp_msub(union ieee754sp z, union ieee754sp x,
0263 union ieee754sp y)
0264 {
0265 return _sp_maddf(z, x, y, MADDF_NEGATE_ADDITION);
0266 }
0267
0268 union ieee754sp ieee754sp_nmadd(union ieee754sp z, union ieee754sp x,
0269 union ieee754sp y)
0270 {
0271 return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT|MADDF_NEGATE_ADDITION);
0272 }
0273
0274 union ieee754sp ieee754sp_nmsub(union ieee754sp z, union ieee754sp x,
0275 union ieee754sp y)
0276 {
0277 return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
0278 }