aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/math-emu/ieee754sp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/math-emu/ieee754sp.c')
-rw-r--r--arch/mips/math-emu/ieee754sp.c126
1 files changed, 43 insertions, 83 deletions
diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c
index 15d1e36cfe64..d348efe91445 100644
--- a/arch/mips/math-emu/ieee754sp.c
+++ b/arch/mips/math-emu/ieee754sp.c
@@ -5,8 +5,6 @@
5 * MIPS floating point support 5 * MIPS floating point support
6 * Copyright (C) 1994-2000 Algorithmics Ltd. 6 * Copyright (C) 1994-2000 Algorithmics Ltd.
7 * 7 *
8 * ########################################################################
9 *
10 * This program is free software; you can distribute it and/or modify it 8 * This program is free software; you can distribute it and/or modify it
11 * under the terms of the GNU General Public License (Version 2) as 9 * under the terms of the GNU General Public License (Version 2) as
12 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
@@ -18,105 +16,68 @@
18 * 16 *
19 * You should have received a copy of the GNU General Public License along 17 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc., 18 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 19 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * ########################################################################
24 */ 20 */
25 21
22#include <linux/compiler.h>
26 23
27#include "ieee754sp.h" 24#include "ieee754sp.h"
28 25
29int ieee754sp_class(ieee754sp x) 26int ieee754sp_class(union ieee754sp x)
30{ 27{
31 COMPXSP; 28 COMPXSP;
32 EXPLODEXSP; 29 EXPLODEXSP;
33 return xc; 30 return xc;
34} 31}
35 32
36int ieee754sp_isnan(ieee754sp x) 33int ieee754sp_isnan(union ieee754sp x)
37{ 34{
38 return ieee754sp_class(x) >= IEEE754_CLASS_SNAN; 35 return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
39} 36}
40 37
41int ieee754sp_issnan(ieee754sp x) 38static inline int ieee754sp_issnan(union ieee754sp x)
42{ 39{
43 assert(ieee754sp_isnan(x)); 40 assert(ieee754sp_isnan(x));
44 return (SPMANT(x) & SP_MBIT(SP_MBITS-1)); 41 return (SPMANT(x) & SP_MBIT(SP_FBITS-1));
45} 42}
46 43
47 44
48ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) 45union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)
49{
50 struct ieee754xctx ax;
51
52 if (!TSTX())
53 return r;
54
55 ax.op = op;
56 ax.rt = IEEE754_RT_SP;
57 ax.rv.sp = r;
58 va_start(ax.ap, op);
59 ieee754_xcpt(&ax);
60 va_end(ax.ap);
61 return ax.rv.sp;
62}
63
64ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
65{ 46{
66 struct ieee754xctx ax;
67
68 assert(ieee754sp_isnan(r)); 47 assert(ieee754sp_isnan(r));
69 48
70 if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ 49 if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */
71 return r; 50 return r;
72 51
73 if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { 52 if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) {
74 /* not enabled convert to a quiet NaN */ 53 /* not enabled convert to a quiet NaN */
75 SPMANT(r) &= (~SP_MBIT(SP_MBITS-1)); 54 SPMANT(r) &= (~SP_MBIT(SP_FBITS-1));
76 if (ieee754sp_isnan(r)) 55 if (ieee754sp_isnan(r))
77 return r; 56 return r;
78 else 57 else
79 return ieee754sp_indef(); 58 return ieee754sp_indef();
80 } 59 }
81 60
82 ax.op = op; 61 return r;
83 ax.rt = 0;
84 ax.rv.sp = r;
85 va_start(ax.ap, op);
86 ieee754_xcpt(&ax);
87 va_end(ax.ap);
88 return ax.rv.sp;
89}
90
91ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
92{
93 assert(ieee754sp_isnan(x));
94 assert(ieee754sp_isnan(y));
95
96 if (SPMANT(x) > SPMANT(y))
97 return x;
98 else
99 return y;
100} 62}
101 63
102 64static unsigned ieee754sp_get_rounding(int sn, unsigned xm)
103static unsigned get_rounding(int sn, unsigned xm)
104{ 65{
105 /* inexact must round of 3 bits 66 /* inexact must round of 3 bits
106 */ 67 */
107 if (xm & (SP_MBIT(3) - 1)) { 68 if (xm & (SP_MBIT(3) - 1)) {
108 switch (ieee754_csr.rm) { 69 switch (ieee754_csr.rm) {
109 case IEEE754_RZ: 70 case FPU_CSR_RZ:
110 break; 71 break;
111 case IEEE754_RN: 72 case FPU_CSR_RN:
112 xm += 0x3 + ((xm >> 3) & 1); 73 xm += 0x3 + ((xm >> 3) & 1);
113 /* xm += (xm&0x8)?0x4:0x3 */ 74 /* xm += (xm&0x8)?0x4:0x3 */
114 break; 75 break;
115 case IEEE754_RU: /* toward +Infinity */ 76 case FPU_CSR_RU: /* toward +Infinity */
116 if (!sn) /* ?? */ 77 if (!sn) /* ?? */
117 xm += 0x8; 78 xm += 0x8;
118 break; 79 break;
119 case IEEE754_RD: /* toward -Infinity */ 80 case FPU_CSR_RD: /* toward -Infinity */
120 if (sn) /* ?? */ 81 if (sn) /* ?? */
121 xm += 0x8; 82 xm += 0x8;
122 break; 83 break;
@@ -131,11 +92,11 @@ static unsigned get_rounding(int sn, unsigned xm)
131 * xe is an unbiased exponent 92 * xe is an unbiased exponent
132 * xm is 3bit extended precision value. 93 * xm is 3bit extended precision value.
133 */ 94 */
134ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) 95union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
135{ 96{
136 assert(xm); /* we don't gen exact zeros (probably should) */ 97 assert(xm); /* we don't gen exact zeros (probably should) */
137 98
138 assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */ 99 assert((xm >> (SP_FBITS + 1 + 3)) == 0); /* no execess */
139 assert(xm & (SP_HIDDEN_BIT << 3)); 100 assert(xm & (SP_HIDDEN_BIT << 3));
140 101
141 if (xe < SP_EMIN) { 102 if (xe < SP_EMIN) {
@@ -143,38 +104,37 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
143 int es = SP_EMIN - xe; 104 int es = SP_EMIN - xe;
144 105
145 if (ieee754_csr.nod) { 106 if (ieee754_csr.nod) {
146 SETCX(IEEE754_UNDERFLOW); 107 ieee754_setcx(IEEE754_UNDERFLOW);
147 SETCX(IEEE754_INEXACT); 108 ieee754_setcx(IEEE754_INEXACT);
148 109
149 switch(ieee754_csr.rm) { 110 switch(ieee754_csr.rm) {
150 case IEEE754_RN: 111 case FPU_CSR_RN:
151 case IEEE754_RZ: 112 case FPU_CSR_RZ:
152 return ieee754sp_zero(sn); 113 return ieee754sp_zero(sn);
153 case IEEE754_RU: /* toward +Infinity */ 114 case FPU_CSR_RU: /* toward +Infinity */
154 if(sn == 0) 115 if (sn == 0)
155 return ieee754sp_min(0); 116 return ieee754sp_min(0);
156 else 117 else
157 return ieee754sp_zero(1); 118 return ieee754sp_zero(1);
158 case IEEE754_RD: /* toward -Infinity */ 119 case FPU_CSR_RD: /* toward -Infinity */
159 if(sn == 0) 120 if (sn == 0)
160 return ieee754sp_zero(0); 121 return ieee754sp_zero(0);
161 else 122 else
162 return ieee754sp_min(1); 123 return ieee754sp_min(1);
163 } 124 }
164 } 125 }
165 126
166 if (xe == SP_EMIN - 1 127 if (xe == SP_EMIN - 1 &&
167 && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3)) 128 ieee754sp_get_rounding(sn, xm) >> (SP_FBITS + 1 + 3))
168 { 129 {
169 /* Not tiny after rounding */ 130 /* Not tiny after rounding */
170 SETCX(IEEE754_INEXACT); 131 ieee754_setcx(IEEE754_INEXACT);
171 xm = get_rounding(sn, xm); 132 xm = ieee754sp_get_rounding(sn, xm);
172 xm >>= 1; 133 xm >>= 1;
173 /* Clear grs bits */ 134 /* Clear grs bits */
174 xm &= ~(SP_MBIT(3) - 1); 135 xm &= ~(SP_MBIT(3) - 1);
175 xe++; 136 xe++;
176 } 137 } else {
177 else {
178 /* sticky right shift es bits 138 /* sticky right shift es bits
179 */ 139 */
180 SPXSRSXn(es); 140 SPXSRSXn(es);
@@ -183,17 +143,17 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
183 } 143 }
184 } 144 }
185 if (xm & (SP_MBIT(3) - 1)) { 145 if (xm & (SP_MBIT(3) - 1)) {
186 SETCX(IEEE754_INEXACT); 146 ieee754_setcx(IEEE754_INEXACT);
187 if ((xm & (SP_HIDDEN_BIT << 3)) == 0) { 147 if ((xm & (SP_HIDDEN_BIT << 3)) == 0) {
188 SETCX(IEEE754_UNDERFLOW); 148 ieee754_setcx(IEEE754_UNDERFLOW);
189 } 149 }
190 150
191 /* inexact must round of 3 bits 151 /* inexact must round of 3 bits
192 */ 152 */
193 xm = get_rounding(sn, xm); 153 xm = ieee754sp_get_rounding(sn, xm);
194 /* adjust exponent for rounding add overflowing 154 /* adjust exponent for rounding add overflowing
195 */ 155 */
196 if (xm >> (SP_MBITS + 1 + 3)) { 156 if (xm >> (SP_FBITS + 1 + 3)) {
197 /* add causes mantissa overflow */ 157 /* add causes mantissa overflow */
198 xm >>= 1; 158 xm >>= 1;
199 xe++; 159 xe++;
@@ -202,24 +162,24 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
202 /* strip grs bits */ 162 /* strip grs bits */
203 xm >>= 3; 163 xm >>= 3;
204 164
205 assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ 165 assert((xm >> (SP_FBITS + 1)) == 0); /* no execess */
206 assert(xe >= SP_EMIN); 166 assert(xe >= SP_EMIN);
207 167
208 if (xe > SP_EMAX) { 168 if (xe > SP_EMAX) {
209 SETCX(IEEE754_OVERFLOW); 169 ieee754_setcx(IEEE754_OVERFLOW);
210 SETCX(IEEE754_INEXACT); 170 ieee754_setcx(IEEE754_INEXACT);
211 /* -O can be table indexed by (rm,sn) */ 171 /* -O can be table indexed by (rm,sn) */
212 switch (ieee754_csr.rm) { 172 switch (ieee754_csr.rm) {
213 case IEEE754_RN: 173 case FPU_CSR_RN:
214 return ieee754sp_inf(sn); 174 return ieee754sp_inf(sn);
215 case IEEE754_RZ: 175 case FPU_CSR_RZ:
216 return ieee754sp_max(sn); 176 return ieee754sp_max(sn);
217 case IEEE754_RU: /* toward +Infinity */ 177 case FPU_CSR_RU: /* toward +Infinity */
218 if (sn == 0) 178 if (sn == 0)
219 return ieee754sp_inf(0); 179 return ieee754sp_inf(0);
220 else 180 else
221 return ieee754sp_max(1); 181 return ieee754sp_max(1);
222 case IEEE754_RD: /* toward -Infinity */ 182 case FPU_CSR_RD: /* toward -Infinity */
223 if (sn == 0) 183 if (sn == 0)
224 return ieee754sp_max(0); 184 return ieee754sp_max(0);
225 else 185 else
@@ -232,10 +192,10 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
232 /* we underflow (tiny/zero) */ 192 /* we underflow (tiny/zero) */
233 assert(xe == SP_EMIN); 193 assert(xe == SP_EMIN);
234 if (ieee754_csr.mx & IEEE754_UNDERFLOW) 194 if (ieee754_csr.mx & IEEE754_UNDERFLOW)
235 SETCX(IEEE754_UNDERFLOW); 195 ieee754_setcx(IEEE754_UNDERFLOW);
236 return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm); 196 return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
237 } else { 197 } else {
238 assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ 198 assert((xm >> (SP_FBITS + 1)) == 0); /* no execess */
239 assert(xm & SP_HIDDEN_BIT); 199 assert(xm & SP_HIDDEN_BIT);
240 200
241 return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); 201 return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);