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_mul(union ieee754sp x, union ieee754sp y) 13 { 14 int re; 15 int rs; 16 unsigned int rm; 17 unsigned short lxm; 18 unsigned short hxm; 19 unsigned short lym; 20 unsigned short hym; 21 unsigned int lrm; 22 unsigned int hrm; 23 unsigned int t; 24 unsigned int at; 25 26 COMPXSP; 27 COMPYSP; 28 29 EXPLODEXSP; 30 EXPLODEYSP; 31 32 ieee754_clearcx(); 33 34 FLUSHXSP; 35 FLUSHYSP; 36 37 switch (CLPAIR(xc, yc)) { 38 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): 39 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): 40 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): 41 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): 42 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): 43 return ieee754sp_nanxcpt(y); 44 45 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): 46 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): 47 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): 48 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): 49 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): 50 case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): 51 return ieee754sp_nanxcpt(x); 52 53 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): 54 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): 55 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): 56 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): 57 return y; 58 59 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): 60 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): 61 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): 62 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): 63 case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): 64 return x; 65 66 67 /* 68 * Infinity handling 69 */ 70 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): 71 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): 72 ieee754_setcx(IEEE754_INVALID_OPERATION); 73 return ieee754sp_indef(); 74 75 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): 76 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): 77 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): 78 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): 79 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): 80 return ieee754sp_inf(xs ^ ys); 81 82 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): 83 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): 84 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): 85 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): 86 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): 87 return ieee754sp_zero(xs ^ ys); 88 89 90 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): 91 SPDNORMX; 92 /* fall through */ 93 94 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): 95 SPDNORMY; 96 break; 97 98 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): 99 SPDNORMX; 100 break; 101 102 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): 103 break; 104 } 105 /* rm = xm * ym, re = xe+ye basically */ 106 assert(xm & SP_HIDDEN_BIT); 107 assert(ym & SP_HIDDEN_BIT); 108 109 re = xe + ye; 110 rs = xs ^ ys; 111 112 /* shunt to top of word */ 113 xm <<= 32 - (SP_FBITS + 1); 114 ym <<= 32 - (SP_FBITS + 1); 115 116 /* 117 * Multiply 32 bits xm, ym to give high 32 bits rm with stickness. 118 */ 119 lxm = xm & 0xffff; 120 hxm = xm >> 16; 121 lym = ym & 0xffff; 122 hym = ym >> 16; 123 124 lrm = lxm * lym; /* 16 * 16 => 32 */ 125 hrm = hxm * hym; /* 16 * 16 => 32 */ 126 127 t = lxm * hym; /* 16 * 16 => 32 */ 128 at = lrm + (t << 16); 129 hrm += at < lrm; 130 lrm = at; 131 hrm = hrm + (t >> 16); 132 133 t = hxm * lym; /* 16 * 16 => 32 */ 134 at = lrm + (t << 16); 135 hrm += at < lrm; 136 lrm = at; 137 hrm = hrm + (t >> 16); 138 139 rm = hrm | (lrm != 0); 140 141 /* 142 * Sticky shift down to normal rounding precision. 143 */ 144 if ((int) rm < 0) { 145 rm = (rm >> (32 - (SP_FBITS + 1 + 3))) | 146 ((rm << (SP_FBITS + 1 + 3)) != 0); 147 re++; 148 } else { 149 rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) | 150 ((rm << (SP_FBITS + 1 + 3 + 1)) != 0); 151 } 152 assert(rm & (SP_HIDDEN_BIT << 3)); 153 154 return ieee754sp_format(rs, re, rm); 155 } 156