1 // SPDX-License-Identifier: GPL-2.0-only 2 /* IEEE754 floating point arithmetic 3 * single precision 4 */ 5 /* 6 * MIPS floating point support 7 * Copyright (C) 1994-2000 Algorithmics Ltd. 8 */ 9 10 #include "ieee754sp.h" 11 12 union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) 13 { 14 int s; 15 16 COMPXSP; 17 COMPYSP; 18 19 EXPLODEXSP; 20 EXPLODEYSP; 21 22 ieee754_clearcx(); 23 24 FLUSHXSP; 25 FLUSHYSP; 26 27 switch (CLPAIR(xc, yc)) { 28 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): 29 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): 30 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): 31 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): 32 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): 33 return ieee754sp_nanxcpt(y); 34 35 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): 36 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): 37 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): 38 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): 39 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): 40 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): 41 return ieee754sp_nanxcpt(x); 42 43 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): 44 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): 45 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): 46 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): 47 return y; 48 49 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): 50 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): 51 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): 52 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): 53 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): 54 return x; 55 56 57 /* 58 * Infinity handling 59 */ 60 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): 61 if (xs == ys) 62 return x; 63 ieee754_setcx(IEEE754_INVALID_OPERATION); 64 return ieee754sp_indef(); 65 66 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): 67 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): 68 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): 69 return y; 70 71 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): 72 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): 73 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): 74 return x; 75 76 /* 77 * Zero handling 78 */ 79 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): 80 if (xs == ys) 81 return x; 82 else 83 return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD); 84 85 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): 86 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): 87 return x; 88 89 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): 90 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): 91 return y; 92 93 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): 94 SPDNORMX; 95 /* fall through */ 96 97 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): 98 SPDNORMY; 99 break; 100 101 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): 102 SPDNORMX; 103 break; 104 105 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): 106 break; 107 } 108 assert(xm & SP_HIDDEN_BIT); 109 assert(ym & SP_HIDDEN_BIT); 110 111 /* 112 * Provide guard, round and stick bit space. 113 */ 114 xm <<= 3; 115 ym <<= 3; 116 117 if (xe > ye) { 118 /* 119 * Have to shift y fraction right to align. 120 */ 121 s = xe - ye; 122 ym = XSPSRS(ym, s); 123 ye += s; 124 } else if (ye > xe) { 125 /* 126 * Have to shift x fraction right to align. 127 */ 128 s = ye - xe; 129 xm = XSPSRS(xm, s); 130 xe += s; 131 } 132 assert(xe == ye); 133 assert(xe <= SP_EMAX); 134 135 if (xs == ys) { 136 /* 137 * Generate 28 bit result of adding two 27 bit numbers 138 * leaving result in xm, xs and xe. 139 */ 140 xm = xm + ym; 141 142 if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */ 143 SPXSRSX1(); 144 } 145 } else { 146 if (xm >= ym) { 147 xm = xm - ym; 148 } else { 149 xm = ym - xm; 150 xs = ys; 151 } 152 if (xm == 0) 153 return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD); 154 155 /* 156 * Normalize in extended single precision 157 */ 158 while ((xm >> (SP_FBITS + 3)) == 0) { 159 xm <<= 1; 160 xe--; 161 } 162 } 163 164 return ieee754sp_format(xs, xe, xm); 165 } 166