diff options
Diffstat (limited to 'arch/parisc/math-emu')
37 files changed, 15182 insertions, 0 deletions
diff --git a/arch/parisc/math-emu/Makefile b/arch/parisc/math-emu/Makefile new file mode 100644 index 000000000000..affd4c80e3b7 --- /dev/null +++ b/arch/parisc/math-emu/Makefile | |||
@@ -0,0 +1,19 @@ | |||
1 | # | ||
2 | # Makefile for the linux/parisc floating point code | ||
3 | # | ||
4 | |||
5 | # See arch/parisc/math-emu/README | ||
6 | CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \ | ||
7 | -Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \ | ||
8 | -Wno-implicit-int | ||
9 | |||
10 | obj-y := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \ | ||
11 | dfmpy.o sfmpy.o sfsqrt.o dfsqrt.o dfadd.o fmpyfadd.o \ | ||
12 | sfadd.o dfsub.o sfsub.o fcnvfxt.o fcnvff.o fcnvxf.o \ | ||
13 | fcnvfx.o fcnvuf.o fcnvfu.o fcnvfut.o dfdiv.o sfdiv.o \ | ||
14 | dfrem.o sfrem.o dfcmp.o sfcmp.o | ||
15 | |||
16 | # Math emulation code beyond the FRND is required for 712/80i and | ||
17 | # other very old or stripped-down PA-RISC CPUs -- not currently supported | ||
18 | |||
19 | obj-$(CONFIG_MATH_EMULATION) += unimplemented-math-emulation.o | ||
diff --git a/arch/parisc/math-emu/README b/arch/parisc/math-emu/README new file mode 100644 index 000000000000..1a0124ef02f2 --- /dev/null +++ b/arch/parisc/math-emu/README | |||
@@ -0,0 +1,11 @@ | |||
1 | All files except driver.c are snapshots from the HP-UX kernel. They've | ||
2 | been modified as little as possible. Even though they don't fit the | ||
3 | Linux coding style, please leave them in their funny format just in case | ||
4 | someone in the future, with access to HP-UX source code, is generous | ||
5 | enough to update our copies with later changes from HP-UX -- it'll | ||
6 | make their 'diff' job easier if our code is relatively unmodified. | ||
7 | |||
8 | Required Disclaimer: Hewlett-Packard makes no implied or expressed | ||
9 | warranties about this code nor any promises to maintain or test it | ||
10 | in any way. This copy of this snapshot is no longer the property | ||
11 | of Hewlett-Packard. | ||
diff --git a/arch/parisc/math-emu/cnv_float.h b/arch/parisc/math-emu/cnv_float.h new file mode 100644 index 000000000000..9071e093164a --- /dev/null +++ b/arch/parisc/math-emu/cnv_float.h | |||
@@ -0,0 +1,377 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifdef __NO_PA_HDRS | ||
23 | PA header file -- do not include this header file for non-PA builds. | ||
24 | #endif | ||
25 | |||
26 | /* | ||
27 | * Some more constants | ||
28 | */ | ||
29 | #define SGL_FX_MAX_EXP 30 | ||
30 | #define DBL_FX_MAX_EXP 62 | ||
31 | #define QUAD_FX_MAX_EXP 126 | ||
32 | |||
33 | #define Dintp1(object) (object) | ||
34 | #define Dintp2(object) (object) | ||
35 | |||
36 | #define Duintp1(object) (object) | ||
37 | #define Duintp2(object) (object) | ||
38 | |||
39 | #define Qintp0(object) (object) | ||
40 | #define Qintp1(object) (object) | ||
41 | #define Qintp2(object) (object) | ||
42 | #define Qintp3(object) (object) | ||
43 | |||
44 | |||
45 | /* | ||
46 | * These macros will be used specifically by the convert instructions. | ||
47 | * | ||
48 | * | ||
49 | * Single format macros | ||
50 | */ | ||
51 | |||
52 | #define Sgl_to_dbl_exponent(src_exponent,dest) \ | ||
53 | Deposit_dexponent(dest,src_exponent+(DBL_BIAS-SGL_BIAS)) | ||
54 | |||
55 | #define Sgl_to_dbl_mantissa(src_mantissa,destA,destB) \ | ||
56 | Deposit_dmantissap1(destA,src_mantissa>>3); \ | ||
57 | Dmantissap2(destB) = src_mantissa << 29 | ||
58 | |||
59 | #define Sgl_isinexact_to_fix(sgl_value,exponent) \ | ||
60 | ((exponent < (SGL_P - 1)) ? \ | ||
61 | (Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : FALSE) | ||
62 | |||
63 | #define Int_isinexact_to_sgl(int_value) (int_value << 33 - SGL_EXP_LENGTH) | ||
64 | |||
65 | #define Sgl_roundnearest_from_int(int_value,sgl_value) \ | ||
66 | if (int_value & 1<<(SGL_EXP_LENGTH - 2)) /* round bit */ \ | ||
67 | if ((int_value << 34 - SGL_EXP_LENGTH) || Slow(sgl_value)) \ | ||
68 | Sall(sgl_value)++ | ||
69 | |||
70 | #define Dint_isinexact_to_sgl(dint_valueA,dint_valueB) \ | ||
71 | ((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) || Dintp2(dint_valueB)) | ||
72 | |||
73 | #define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value) \ | ||
74 | if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2)) \ | ||
75 | if ((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) || \ | ||
76 | Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++ | ||
77 | |||
78 | #define Dint_isinexact_to_dbl(dint_value) \ | ||
79 | (Dintp2(dint_value) << 33 - DBL_EXP_LENGTH) | ||
80 | |||
81 | #define Dbl_roundnearest_from_dint(dint_opndB,dbl_opndA,dbl_opndB) \ | ||
82 | if (Dintp2(dint_opndB) & 1<<(DBL_EXP_LENGTH - 2)) \ | ||
83 | if ((Dintp2(dint_opndB) << 34 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \ | ||
84 | if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++ | ||
85 | |||
86 | #define Sgl_isone_roundbit(sgl_value,exponent) \ | ||
87 | ((Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) >> 31) | ||
88 | |||
89 | #define Sgl_isone_stickybit(sgl_value,exponent) \ | ||
90 | (exponent < (SGL_P - 2) ? \ | ||
91 | Sall(sgl_value) << (SGL_EXP_LENGTH + 2 + exponent) : FALSE) | ||
92 | |||
93 | |||
94 | /* | ||
95 | * Double format macros | ||
96 | */ | ||
97 | |||
98 | #define Dbl_to_sgl_exponent(src_exponent,dest) \ | ||
99 | dest = src_exponent + (SGL_BIAS - DBL_BIAS) | ||
100 | |||
101 | #define Dbl_to_sgl_mantissa(srcA,srcB,dest,inexact,guard,sticky,odd) \ | ||
102 | Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \ | ||
103 | guard = Dbit3p2(srcB); \ | ||
104 | sticky = Dallp2(srcB)<<4; \ | ||
105 | inexact = guard | sticky; \ | ||
106 | odd = Dbit2p2(srcB) | ||
107 | |||
108 | #define Dbl_to_sgl_denormalized(srcA,srcB,exp,dest,inexact,guard,sticky,odd,tiny) \ | ||
109 | Deposit_dexponent(srcA,1); \ | ||
110 | tiny = TRUE; \ | ||
111 | if (exp >= -2) { \ | ||
112 | if (exp == 0) { \ | ||
113 | inexact = Dallp2(srcB) << 3; \ | ||
114 | guard = inexact >> 31; \ | ||
115 | sticky = inexact << 1; \ | ||
116 | Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \ | ||
117 | odd = dest << 31; \ | ||
118 | if (inexact) { \ | ||
119 | switch(Rounding_mode()) { \ | ||
120 | case ROUNDPLUS: \ | ||
121 | if (Dbl_iszero_sign(srcA)) { \ | ||
122 | dest++; \ | ||
123 | if (Sgl_isone_hidden(dest)) \ | ||
124 | tiny = FALSE; \ | ||
125 | dest--; \ | ||
126 | } \ | ||
127 | break; \ | ||
128 | case ROUNDMINUS: \ | ||
129 | if (Dbl_isone_sign(srcA)) { \ | ||
130 | dest++; \ | ||
131 | if (Sgl_isone_hidden(dest)) \ | ||
132 | tiny = FALSE; \ | ||
133 | dest--; \ | ||
134 | } \ | ||
135 | break; \ | ||
136 | case ROUNDNEAREST: \ | ||
137 | if (guard && (sticky || odd)) { \ | ||
138 | dest++; \ | ||
139 | if (Sgl_isone_hidden(dest)) \ | ||
140 | tiny = FALSE; \ | ||
141 | dest--; \ | ||
142 | } \ | ||
143 | break; \ | ||
144 | } \ | ||
145 | } \ | ||
146 | /* shift right by one to get correct result */ \ | ||
147 | guard = odd; \ | ||
148 | sticky = inexact; \ | ||
149 | inexact |= guard; \ | ||
150 | dest >>= 1; \ | ||
151 | Deposit_dsign(srcA,0); \ | ||
152 | Shiftdouble(Dallp1(srcA),Dallp2(srcB),30,dest); \ | ||
153 | odd = dest << 31; \ | ||
154 | } \ | ||
155 | else { \ | ||
156 | inexact = Dallp2(srcB) << (2 + exp); \ | ||
157 | guard = inexact >> 31; \ | ||
158 | sticky = inexact << 1; \ | ||
159 | Deposit_dsign(srcA,0); \ | ||
160 | if (exp == -2) dest = Dallp1(srcA); \ | ||
161 | else Variable_shift_double(Dallp1(srcA),Dallp2(srcB),30-exp,dest); \ | ||
162 | odd = dest << 31; \ | ||
163 | } \ | ||
164 | } \ | ||
165 | else { \ | ||
166 | Deposit_dsign(srcA,0); \ | ||
167 | if (exp > (1 - SGL_P)) { \ | ||
168 | dest = Dallp1(srcA) >> (- 2 - exp); \ | ||
169 | inexact = Dallp1(srcA) << (34 + exp); \ | ||
170 | guard = inexact >> 31; \ | ||
171 | sticky = (inexact << 1) | Dallp2(srcB); \ | ||
172 | inexact |= Dallp2(srcB); \ | ||
173 | odd = dest << 31; \ | ||
174 | } \ | ||
175 | else { \ | ||
176 | dest = 0; \ | ||
177 | inexact = Dallp1(srcA) | Dallp2(srcB); \ | ||
178 | if (exp == (1 - SGL_P)) { \ | ||
179 | guard = Dhidden(srcA); \ | ||
180 | sticky = Dmantissap1(srcA) | Dallp2(srcB); \ | ||
181 | } \ | ||
182 | else { \ | ||
183 | guard = 0; \ | ||
184 | sticky = inexact; \ | ||
185 | } \ | ||
186 | odd = 0; \ | ||
187 | } \ | ||
188 | } \ | ||
189 | exp = 0 | ||
190 | |||
191 | #define Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent) \ | ||
192 | (exponent < (DBL_P-33) ? \ | ||
193 | Dallp2(dbl_valueB) || Dallp1(dbl_valueA) << (DBL_EXP_LENGTH+1+exponent) : \ | ||
194 | (exponent < (DBL_P-1) ? Dallp2(dbl_valueB) << (exponent + (33-DBL_P)) : \ | ||
195 | FALSE)) | ||
196 | |||
197 | #define Dbl_isoverflow_to_int(exponent,dbl_valueA,dbl_valueB) \ | ||
198 | ((exponent > SGL_FX_MAX_EXP + 1) || Dsign(dbl_valueA)==0 || \ | ||
199 | Dmantissap1(dbl_valueA)!=0 || (Dallp2(dbl_valueB)>>21)!=0 ) | ||
200 | |||
201 | #define Dbl_isone_roundbit(dbl_valueA,dbl_valueB,exponent) \ | ||
202 | ((exponent < (DBL_P - 33) ? \ | ||
203 | Dallp1(dbl_valueA) >> ((30 - DBL_EXP_LENGTH) - exponent) : \ | ||
204 | Dallp2(dbl_valueB) >> ((DBL_P - 2) - exponent)) & 1) | ||
205 | |||
206 | #define Dbl_isone_stickybit(dbl_valueA,dbl_valueB,exponent) \ | ||
207 | (exponent < (DBL_P-34) ? \ | ||
208 | (Dallp2(dbl_valueB) || Dallp1(dbl_valueA)<<(DBL_EXP_LENGTH+2+exponent)) : \ | ||
209 | (exponent<(DBL_P-2) ? (Dallp2(dbl_valueB) << (exponent + (34-DBL_P))) : \ | ||
210 | FALSE)) | ||
211 | |||
212 | |||
213 | /* Int macros */ | ||
214 | |||
215 | #define Int_from_sgl_mantissa(sgl_value,exponent) \ | ||
216 | Sall(sgl_value) = \ | ||
217 | (unsigned)(Sall(sgl_value) << SGL_EXP_LENGTH)>>(31 - exponent) | ||
218 | |||
219 | #define Int_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent) \ | ||
220 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),22,Dallp1(dbl_valueA)); \ | ||
221 | if (exponent < 31) Dallp1(dbl_valueA) >>= 30 - exponent; \ | ||
222 | else Dallp1(dbl_valueA) <<= 1 | ||
223 | |||
224 | #define Int_negate(int_value) int_value = -int_value | ||
225 | |||
226 | |||
227 | /* Dint macros */ | ||
228 | |||
229 | #define Dint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ | ||
230 | {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \ | ||
231 | if (exponent <= 31) { \ | ||
232 | Dintp1(dresultA) = 0; \ | ||
233 | Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \ | ||
234 | } \ | ||
235 | else { \ | ||
236 | Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \ | ||
237 | Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \ | ||
238 | }} | ||
239 | |||
240 | |||
241 | #define Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \ | ||
242 | {if (exponent < 32) { \ | ||
243 | Dintp1(destA) = 0; \ | ||
244 | if (exponent <= 20) \ | ||
245 | Dintp2(destB) = Dallp1(dbl_valueA) >> 20-exponent; \ | ||
246 | else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \ | ||
247 | 52-exponent,Dintp2(destB)); \ | ||
248 | } \ | ||
249 | else { \ | ||
250 | if (exponent <= 52) { \ | ||
251 | Dintp1(destA) = Dallp1(dbl_valueA) >> 52-exponent; \ | ||
252 | if (exponent == 52) Dintp2(destB) = Dallp2(dbl_valueB); \ | ||
253 | else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \ | ||
254 | 52-exponent,Dintp2(destB)); \ | ||
255 | } \ | ||
256 | else { \ | ||
257 | Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \ | ||
258 | 84-exponent,Dintp1(destA)); \ | ||
259 | Dintp2(destB) = Dallp2(dbl_valueB) << exponent-52; \ | ||
260 | } \ | ||
261 | }} | ||
262 | |||
263 | #define Dint_setzero(dresultA,dresultB) \ | ||
264 | Dintp1(dresultA) = 0; \ | ||
265 | Dintp2(dresultB) = 0 | ||
266 | |||
267 | #define Dint_setone_sign(dresultA,dresultB) \ | ||
268 | Dintp1(dresultA) = ~Dintp1(dresultA); \ | ||
269 | if ((Dintp2(dresultB) = -Dintp2(dresultB)) == 0) Dintp1(dresultA)++ | ||
270 | |||
271 | #define Dint_set_minint(dresultA,dresultB) \ | ||
272 | Dintp1(dresultA) = (unsigned int)1<<31; \ | ||
273 | Dintp2(dresultB) = 0 | ||
274 | |||
275 | #define Dint_isone_lowp2(dresultB) (Dintp2(dresultB) & 01) | ||
276 | |||
277 | #define Dint_increment(dresultA,dresultB) \ | ||
278 | if ((++Dintp2(dresultB))==0) Dintp1(dresultA)++ | ||
279 | |||
280 | #define Dint_decrement(dresultA,dresultB) \ | ||
281 | if ((Dintp2(dresultB)--)==0) Dintp1(dresultA)-- | ||
282 | |||
283 | #define Dint_negate(dresultA,dresultB) \ | ||
284 | Dintp1(dresultA) = ~Dintp1(dresultA); \ | ||
285 | if ((Dintp2(dresultB) = -Dintp2(dresultB))==0) Dintp1(dresultA)++ | ||
286 | |||
287 | #define Dint_copyfromptr(src,destA,destB) \ | ||
288 | Dintp1(destA) = src->wd0; \ | ||
289 | Dintp2(destB) = src->wd1 | ||
290 | #define Dint_copytoptr(srcA,srcB,dest) \ | ||
291 | dest->wd0 = Dintp1(srcA); \ | ||
292 | dest->wd1 = Dintp2(srcB) | ||
293 | |||
294 | |||
295 | /* other macros */ | ||
296 | |||
297 | #define Find_ms_one_bit(value, position) \ | ||
298 | { \ | ||
299 | int var; \ | ||
300 | for (var=8; var >=1; var >>= 1) { \ | ||
301 | if (value >> 32 - position) \ | ||
302 | position -= var; \ | ||
303 | else position += var; \ | ||
304 | } \ | ||
305 | if ((value >> 32 - position) == 0) \ | ||
306 | position--; \ | ||
307 | else position -= 2; \ | ||
308 | } | ||
309 | |||
310 | |||
311 | /* | ||
312 | * Unsigned int macros | ||
313 | */ | ||
314 | #define Duint_copyfromptr(src,destA,destB) \ | ||
315 | Dint_copyfromptr(src,destA,destB) | ||
316 | #define Duint_copytoptr(srcA,srcB,dest) \ | ||
317 | Dint_copytoptr(srcA,srcB,dest) | ||
318 | |||
319 | #define Suint_isinexact_to_sgl(int_value) \ | ||
320 | (int_value << 32 - SGL_EXP_LENGTH) | ||
321 | |||
322 | #define Sgl_roundnearest_from_suint(suint_value,sgl_value) \ | ||
323 | if (suint_value & 1<<(SGL_EXP_LENGTH - 1)) /* round bit */ \ | ||
324 | if ((suint_value << 33 - SGL_EXP_LENGTH) || Slow(sgl_value)) \ | ||
325 | Sall(sgl_value)++ | ||
326 | |||
327 | #define Duint_isinexact_to_sgl(duint_valueA,duint_valueB) \ | ||
328 | ((Duintp1(duint_valueA) << 32 - SGL_EXP_LENGTH) || Duintp2(duint_valueB)) | ||
329 | |||
330 | #define Sgl_roundnearest_from_duint(duint_valueA,duint_valueB,sgl_value) \ | ||
331 | if (Duintp1(duint_valueA) & 1<<(SGL_EXP_LENGTH - 1)) \ | ||
332 | if ((Duintp1(duint_valueA) << 33 - SGL_EXP_LENGTH) || \ | ||
333 | Duintp2(duint_valueB) || Slow(sgl_value)) Sall(sgl_value)++ | ||
334 | |||
335 | #define Duint_isinexact_to_dbl(duint_value) \ | ||
336 | (Duintp2(duint_value) << 32 - DBL_EXP_LENGTH) | ||
337 | |||
338 | #define Dbl_roundnearest_from_duint(duint_opndB,dbl_opndA,dbl_opndB) \ | ||
339 | if (Duintp2(duint_opndB) & 1<<(DBL_EXP_LENGTH - 1)) \ | ||
340 | if ((Duintp2(duint_opndB) << 33 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \ | ||
341 | if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++ | ||
342 | |||
343 | #define Suint_from_sgl_mantissa(src,exponent,result) \ | ||
344 | Sall(result) = (unsigned)(Sall(src) << SGL_EXP_LENGTH)>>(31 - exponent) | ||
345 | |||
346 | #define Sgl_isinexact_to_unsigned(sgl_value,exponent) \ | ||
347 | Sgl_isinexact_to_fix(sgl_value,exponent) | ||
348 | |||
349 | #define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ | ||
350 | {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \ | ||
351 | if (exponent <= 31) { \ | ||
352 | Dintp1(dresultA) = 0; \ | ||
353 | Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \ | ||
354 | } \ | ||
355 | else { \ | ||
356 | Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \ | ||
357 | Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \ | ||
358 | } \ | ||
359 | Sall(sgl_value) >>= SGL_EXP_LENGTH; /* return to original */ \ | ||
360 | } | ||
361 | |||
362 | #define Duint_setzero(dresultA,dresultB) \ | ||
363 | Dint_setzero(dresultA,dresultB) | ||
364 | |||
365 | #define Duint_increment(dresultA,dresultB) Dint_increment(dresultA,dresultB) | ||
366 | |||
367 | #define Duint_isone_lowp2(dresultB) Dint_isone_lowp2(dresultB) | ||
368 | |||
369 | #define Suint_from_dbl_mantissa(srcA,srcB,exponent,dest) \ | ||
370 | Shiftdouble(Dallp1(srcA),Dallp2(srcB),21,dest); \ | ||
371 | dest = (unsigned)dest >> 31 - exponent | ||
372 | |||
373 | #define Dbl_isinexact_to_unsigned(dbl_valueA,dbl_valueB,exponent) \ | ||
374 | Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent) | ||
375 | |||
376 | #define Duint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \ | ||
377 | Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) | ||
diff --git a/arch/parisc/math-emu/dbl_float.h b/arch/parisc/math-emu/dbl_float.h new file mode 100644 index 000000000000..1570e2e0a327 --- /dev/null +++ b/arch/parisc/math-emu/dbl_float.h | |||
@@ -0,0 +1,847 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | #ifdef __NO_PA_HDRS | ||
22 | PA header file -- do not include this header file for non-PA builds. | ||
23 | #endif | ||
24 | |||
25 | /* 32-bit word grabing functions */ | ||
26 | #define Dbl_firstword(value) Dallp1(value) | ||
27 | #define Dbl_secondword(value) Dallp2(value) | ||
28 | #define Dbl_thirdword(value) dummy_location | ||
29 | #define Dbl_fourthword(value) dummy_location | ||
30 | |||
31 | #define Dbl_sign(object) Dsign(object) | ||
32 | #define Dbl_exponent(object) Dexponent(object) | ||
33 | #define Dbl_signexponent(object) Dsignexponent(object) | ||
34 | #define Dbl_mantissap1(object) Dmantissap1(object) | ||
35 | #define Dbl_mantissap2(object) Dmantissap2(object) | ||
36 | #define Dbl_exponentmantissap1(object) Dexponentmantissap1(object) | ||
37 | #define Dbl_allp1(object) Dallp1(object) | ||
38 | #define Dbl_allp2(object) Dallp2(object) | ||
39 | |||
40 | /* dbl_and_signs ands the sign bits of each argument and puts the result | ||
41 | * into the first argument. dbl_or_signs ors those same sign bits */ | ||
42 | #define Dbl_and_signs( src1dst, src2) \ | ||
43 | Dallp1(src1dst) = (Dallp1(src2)|~((unsigned int)1<<31)) & Dallp1(src1dst) | ||
44 | #define Dbl_or_signs( src1dst, src2) \ | ||
45 | Dallp1(src1dst) = (Dallp1(src2)&((unsigned int)1<<31)) | Dallp1(src1dst) | ||
46 | |||
47 | /* The hidden bit is always the low bit of the exponent */ | ||
48 | #define Dbl_clear_exponent_set_hidden(srcdst) Deposit_dexponent(srcdst,1) | ||
49 | #define Dbl_clear_signexponent_set_hidden(srcdst) \ | ||
50 | Deposit_dsignexponent(srcdst,1) | ||
51 | #define Dbl_clear_sign(srcdst) Dallp1(srcdst) &= ~((unsigned int)1<<31) | ||
52 | #define Dbl_clear_signexponent(srcdst) \ | ||
53 | Dallp1(srcdst) &= Dmantissap1((unsigned int)-1) | ||
54 | |||
55 | /* Exponent field for doubles has already been cleared and may be | ||
56 | * included in the shift. Here we need to generate two double width | ||
57 | * variable shifts. The insignificant bits can be ignored. | ||
58 | * MTSAR f(varamount) | ||
59 | * VSHD srcdst.high,srcdst.low => srcdst.low | ||
60 | * VSHD 0,srcdst.high => srcdst.high | ||
61 | * This is very difficult to model with C expressions since the shift amount | ||
62 | * could exceed 32. */ | ||
63 | /* varamount must be less than 64 */ | ||
64 | #define Dbl_rightshift(srcdstA, srcdstB, varamount) \ | ||
65 | {if((varamount) >= 32) { \ | ||
66 | Dallp2(srcdstB) = Dallp1(srcdstA) >> (varamount-32); \ | ||
67 | Dallp1(srcdstA)=0; \ | ||
68 | } \ | ||
69 | else if(varamount > 0) { \ | ||
70 | Variable_shift_double(Dallp1(srcdstA), Dallp2(srcdstB), \ | ||
71 | (varamount), Dallp2(srcdstB)); \ | ||
72 | Dallp1(srcdstA) >>= varamount; \ | ||
73 | } } | ||
74 | /* varamount must be less than 64 */ | ||
75 | #define Dbl_rightshift_exponentmantissa(srcdstA, srcdstB, varamount) \ | ||
76 | {if((varamount) >= 32) { \ | ||
77 | Dallp2(srcdstB) = Dexponentmantissap1(srcdstA) >> (varamount-32); \ | ||
78 | Dallp1(srcdstA) &= ((unsigned int)1<<31); /* clear expmant field */ \ | ||
79 | } \ | ||
80 | else if(varamount > 0) { \ | ||
81 | Variable_shift_double(Dexponentmantissap1(srcdstA), Dallp2(srcdstB), \ | ||
82 | (varamount), Dallp2(srcdstB)); \ | ||
83 | Deposit_dexponentmantissap1(srcdstA, \ | ||
84 | (Dexponentmantissap1(srcdstA)>>varamount)); \ | ||
85 | } } | ||
86 | /* varamount must be less than 64 */ | ||
87 | #define Dbl_leftshift(srcdstA, srcdstB, varamount) \ | ||
88 | {if((varamount) >= 32) { \ | ||
89 | Dallp1(srcdstA) = Dallp2(srcdstB) << (varamount-32); \ | ||
90 | Dallp2(srcdstB)=0; \ | ||
91 | } \ | ||
92 | else { \ | ||
93 | if ((varamount) > 0) { \ | ||
94 | Dallp1(srcdstA) = (Dallp1(srcdstA) << (varamount)) | \ | ||
95 | (Dallp2(srcdstB) >> (32-(varamount))); \ | ||
96 | Dallp2(srcdstB) <<= varamount; \ | ||
97 | } \ | ||
98 | } } | ||
99 | #define Dbl_leftshiftby1_withextent(lefta,leftb,right,resulta,resultb) \ | ||
100 | Shiftdouble(Dallp1(lefta), Dallp2(leftb), 31, Dallp1(resulta)); \ | ||
101 | Shiftdouble(Dallp2(leftb), Extall(right), 31, Dallp2(resultb)) | ||
102 | |||
103 | #define Dbl_rightshiftby1_withextent(leftb,right,dst) \ | ||
104 | Extall(dst) = (Dallp2(leftb) << 31) | ((unsigned int)Extall(right) >> 1) | \ | ||
105 | Extlow(right) | ||
106 | |||
107 | #define Dbl_arithrightshiftby1(srcdstA,srcdstB) \ | ||
108 | Shiftdouble(Dallp1(srcdstA),Dallp2(srcdstB),1,Dallp2(srcdstB));\ | ||
109 | Dallp1(srcdstA) = (int)Dallp1(srcdstA) >> 1 | ||
110 | |||
111 | /* Sign extend the sign bit with an integer destination */ | ||
112 | #define Dbl_signextendedsign(value) Dsignedsign(value) | ||
113 | |||
114 | #define Dbl_isone_hidden(dbl_value) (Is_dhidden(dbl_value)!=0) | ||
115 | /* Singles and doubles may include the sign and exponent fields. The | ||
116 | * hidden bit and the hidden overflow must be included. */ | ||
117 | #define Dbl_increment(dbl_valueA,dbl_valueB) \ | ||
118 | if( (Dallp2(dbl_valueB) += 1) == 0 ) Dallp1(dbl_valueA) += 1 | ||
119 | #define Dbl_increment_mantissa(dbl_valueA,dbl_valueB) \ | ||
120 | if( (Dmantissap2(dbl_valueB) += 1) == 0 ) \ | ||
121 | Deposit_dmantissap1(dbl_valueA,dbl_valueA+1) | ||
122 | #define Dbl_decrement(dbl_valueA,dbl_valueB) \ | ||
123 | if( Dallp2(dbl_valueB) == 0 ) Dallp1(dbl_valueA) -= 1; \ | ||
124 | Dallp2(dbl_valueB) -= 1 | ||
125 | |||
126 | #define Dbl_isone_sign(dbl_value) (Is_dsign(dbl_value)!=0) | ||
127 | #define Dbl_isone_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)!=0) | ||
128 | #define Dbl_isone_lowmantissap1(dbl_valueA) (Is_dlowp1(dbl_valueA)!=0) | ||
129 | #define Dbl_isone_lowmantissap2(dbl_valueB) (Is_dlowp2(dbl_valueB)!=0) | ||
130 | #define Dbl_isone_signaling(dbl_value) (Is_dsignaling(dbl_value)!=0) | ||
131 | #define Dbl_is_signalingnan(dbl_value) (Dsignalingnan(dbl_value)==0xfff) | ||
132 | #define Dbl_isnotzero(dbl_valueA,dbl_valueB) \ | ||
133 | (Dallp1(dbl_valueA) || Dallp2(dbl_valueB)) | ||
134 | #define Dbl_isnotzero_hiddenhigh7mantissa(dbl_value) \ | ||
135 | (Dhiddenhigh7mantissa(dbl_value)!=0) | ||
136 | #define Dbl_isnotzero_exponent(dbl_value) (Dexponent(dbl_value)!=0) | ||
137 | #define Dbl_isnotzero_mantissa(dbl_valueA,dbl_valueB) \ | ||
138 | (Dmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB)) | ||
139 | #define Dbl_isnotzero_mantissap1(dbl_valueA) (Dmantissap1(dbl_valueA)!=0) | ||
140 | #define Dbl_isnotzero_mantissap2(dbl_valueB) (Dmantissap2(dbl_valueB)!=0) | ||
141 | #define Dbl_isnotzero_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
142 | (Dexponentmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB)) | ||
143 | #define Dbl_isnotzero_low4p2(dbl_value) (Dlow4p2(dbl_value)!=0) | ||
144 | #define Dbl_iszero(dbl_valueA,dbl_valueB) (Dallp1(dbl_valueA)==0 && \ | ||
145 | Dallp2(dbl_valueB)==0) | ||
146 | #define Dbl_iszero_allp1(dbl_value) (Dallp1(dbl_value)==0) | ||
147 | #define Dbl_iszero_allp2(dbl_value) (Dallp2(dbl_value)==0) | ||
148 | #define Dbl_iszero_hidden(dbl_value) (Is_dhidden(dbl_value)==0) | ||
149 | #define Dbl_iszero_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)==0) | ||
150 | #define Dbl_iszero_hiddenhigh3mantissa(dbl_value) \ | ||
151 | (Dhiddenhigh3mantissa(dbl_value)==0) | ||
152 | #define Dbl_iszero_hiddenhigh7mantissa(dbl_value) \ | ||
153 | (Dhiddenhigh7mantissa(dbl_value)==0) | ||
154 | #define Dbl_iszero_sign(dbl_value) (Is_dsign(dbl_value)==0) | ||
155 | #define Dbl_iszero_exponent(dbl_value) (Dexponent(dbl_value)==0) | ||
156 | #define Dbl_iszero_mantissa(dbl_valueA,dbl_valueB) \ | ||
157 | (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0) | ||
158 | #define Dbl_iszero_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
159 | (Dexponentmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0) | ||
160 | #define Dbl_isinfinity_exponent(dbl_value) \ | ||
161 | (Dexponent(dbl_value)==DBL_INFINITY_EXPONENT) | ||
162 | #define Dbl_isnotinfinity_exponent(dbl_value) \ | ||
163 | (Dexponent(dbl_value)!=DBL_INFINITY_EXPONENT) | ||
164 | #define Dbl_isinfinity(dbl_valueA,dbl_valueB) \ | ||
165 | (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \ | ||
166 | Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0) | ||
167 | #define Dbl_isnan(dbl_valueA,dbl_valueB) \ | ||
168 | (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \ | ||
169 | (Dmantissap1(dbl_valueA)!=0 || Dmantissap2(dbl_valueB)!=0)) | ||
170 | #define Dbl_isnotnan(dbl_valueA,dbl_valueB) \ | ||
171 | (Dexponent(dbl_valueA)!=DBL_INFINITY_EXPONENT || \ | ||
172 | (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)) | ||
173 | |||
174 | #define Dbl_islessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
175 | (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \ | ||
176 | (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ | ||
177 | Dallp2(dbl_op1b) < Dallp2(dbl_op2b))) | ||
178 | #define Dbl_isgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
179 | (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \ | ||
180 | (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ | ||
181 | Dallp2(dbl_op1b) > Dallp2(dbl_op2b))) | ||
182 | #define Dbl_isnotlessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
183 | (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \ | ||
184 | (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ | ||
185 | Dallp2(dbl_op1b) >= Dallp2(dbl_op2b))) | ||
186 | #define Dbl_isnotgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
187 | (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \ | ||
188 | (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ | ||
189 | Dallp2(dbl_op1b) <= Dallp2(dbl_op2b))) | ||
190 | #define Dbl_isequal(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
191 | ((Dallp1(dbl_op1a) == Dallp1(dbl_op2a)) && \ | ||
192 | (Dallp2(dbl_op1b) == Dallp2(dbl_op2b))) | ||
193 | |||
194 | #define Dbl_leftshiftby8(dbl_valueA,dbl_valueB) \ | ||
195 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),24,Dallp1(dbl_valueA)); \ | ||
196 | Dallp2(dbl_valueB) <<= 8 | ||
197 | #define Dbl_leftshiftby7(dbl_valueA,dbl_valueB) \ | ||
198 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),25,Dallp1(dbl_valueA)); \ | ||
199 | Dallp2(dbl_valueB) <<= 7 | ||
200 | #define Dbl_leftshiftby4(dbl_valueA,dbl_valueB) \ | ||
201 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),28,Dallp1(dbl_valueA)); \ | ||
202 | Dallp2(dbl_valueB) <<= 4 | ||
203 | #define Dbl_leftshiftby3(dbl_valueA,dbl_valueB) \ | ||
204 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),29,Dallp1(dbl_valueA)); \ | ||
205 | Dallp2(dbl_valueB) <<= 3 | ||
206 | #define Dbl_leftshiftby2(dbl_valueA,dbl_valueB) \ | ||
207 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),30,Dallp1(dbl_valueA)); \ | ||
208 | Dallp2(dbl_valueB) <<= 2 | ||
209 | #define Dbl_leftshiftby1(dbl_valueA,dbl_valueB) \ | ||
210 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),31,Dallp1(dbl_valueA)); \ | ||
211 | Dallp2(dbl_valueB) <<= 1 | ||
212 | |||
213 | #define Dbl_rightshiftby8(dbl_valueA,dbl_valueB) \ | ||
214 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),8,Dallp2(dbl_valueB)); \ | ||
215 | Dallp1(dbl_valueA) >>= 8 | ||
216 | #define Dbl_rightshiftby4(dbl_valueA,dbl_valueB) \ | ||
217 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),4,Dallp2(dbl_valueB)); \ | ||
218 | Dallp1(dbl_valueA) >>= 4 | ||
219 | #define Dbl_rightshiftby2(dbl_valueA,dbl_valueB) \ | ||
220 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),2,Dallp2(dbl_valueB)); \ | ||
221 | Dallp1(dbl_valueA) >>= 2 | ||
222 | #define Dbl_rightshiftby1(dbl_valueA,dbl_valueB) \ | ||
223 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),1,Dallp2(dbl_valueB)); \ | ||
224 | Dallp1(dbl_valueA) >>= 1 | ||
225 | |||
226 | /* This magnitude comparison uses the signless first words and | ||
227 | * the regular part2 words. The comparison is graphically: | ||
228 | * | ||
229 | * 1st greater? ------------- | ||
230 | * | | ||
231 | * 1st less?-----------------+--------- | ||
232 | * | | | ||
233 | * 2nd greater or equal----->| | | ||
234 | * False True | ||
235 | */ | ||
236 | #define Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \ | ||
237 | ((signlessleft <= signlessright) && \ | ||
238 | ( (signlessleft < signlessright) || (Dallp2(leftB)<Dallp2(rightB)) )) | ||
239 | |||
240 | #define Dbl_copytoint_exponentmantissap1(src,dest) \ | ||
241 | dest = Dexponentmantissap1(src) | ||
242 | |||
243 | /* A quiet NaN has the high mantissa bit clear and at least on other (in this | ||
244 | * case the adjacent bit) bit set. */ | ||
245 | #define Dbl_set_quiet(dbl_value) Deposit_dhigh2mantissa(dbl_value,1) | ||
246 | #define Dbl_set_exponent(dbl_value, exp) Deposit_dexponent(dbl_value,exp) | ||
247 | |||
248 | #define Dbl_set_mantissa(desta,destb,valuea,valueb) \ | ||
249 | Deposit_dmantissap1(desta,valuea); \ | ||
250 | Dmantissap2(destb) = Dmantissap2(valueb) | ||
251 | #define Dbl_set_mantissap1(desta,valuea) \ | ||
252 | Deposit_dmantissap1(desta,valuea) | ||
253 | #define Dbl_set_mantissap2(destb,valueb) \ | ||
254 | Dmantissap2(destb) = Dmantissap2(valueb) | ||
255 | |||
256 | #define Dbl_set_exponentmantissa(desta,destb,valuea,valueb) \ | ||
257 | Deposit_dexponentmantissap1(desta,valuea); \ | ||
258 | Dmantissap2(destb) = Dmantissap2(valueb) | ||
259 | #define Dbl_set_exponentmantissap1(dest,value) \ | ||
260 | Deposit_dexponentmantissap1(dest,value) | ||
261 | |||
262 | #define Dbl_copyfromptr(src,desta,destb) \ | ||
263 | Dallp1(desta) = src->wd0; \ | ||
264 | Dallp2(destb) = src->wd1 | ||
265 | #define Dbl_copytoptr(srca,srcb,dest) \ | ||
266 | dest->wd0 = Dallp1(srca); \ | ||
267 | dest->wd1 = Dallp2(srcb) | ||
268 | |||
269 | /* An infinity is represented with the max exponent and a zero mantissa */ | ||
270 | #define Dbl_setinfinity_exponent(dbl_value) \ | ||
271 | Deposit_dexponent(dbl_value,DBL_INFINITY_EXPONENT) | ||
272 | #define Dbl_setinfinity_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
273 | Deposit_dexponentmantissap1(dbl_valueA, \ | ||
274 | (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH)))); \ | ||
275 | Dmantissap2(dbl_valueB) = 0 | ||
276 | #define Dbl_setinfinitypositive(dbl_valueA,dbl_valueB) \ | ||
277 | Dallp1(dbl_valueA) \ | ||
278 | = (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \ | ||
279 | Dmantissap2(dbl_valueB) = 0 | ||
280 | #define Dbl_setinfinitynegative(dbl_valueA,dbl_valueB) \ | ||
281 | Dallp1(dbl_valueA) = ((unsigned int)1<<31) | \ | ||
282 | (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \ | ||
283 | Dmantissap2(dbl_valueB) = 0 | ||
284 | #define Dbl_setinfinity(dbl_valueA,dbl_valueB,sign) \ | ||
285 | Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \ | ||
286 | (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \ | ||
287 | Dmantissap2(dbl_valueB) = 0 | ||
288 | |||
289 | #define Dbl_sethigh4bits(dbl_value, extsign) Deposit_dhigh4p1(dbl_value,extsign) | ||
290 | #define Dbl_set_sign(dbl_value,sign) Deposit_dsign(dbl_value,sign) | ||
291 | #define Dbl_invert_sign(dbl_value) Deposit_dsign(dbl_value,~Dsign(dbl_value)) | ||
292 | #define Dbl_setone_sign(dbl_value) Deposit_dsign(dbl_value,1) | ||
293 | #define Dbl_setone_lowmantissap2(dbl_value) Deposit_dlowp2(dbl_value,1) | ||
294 | #define Dbl_setzero_sign(dbl_value) Dallp1(dbl_value) &= 0x7fffffff | ||
295 | #define Dbl_setzero_exponent(dbl_value) \ | ||
296 | Dallp1(dbl_value) &= 0x800fffff | ||
297 | #define Dbl_setzero_mantissa(dbl_valueA,dbl_valueB) \ | ||
298 | Dallp1(dbl_valueA) &= 0xfff00000; \ | ||
299 | Dallp2(dbl_valueB) = 0 | ||
300 | #define Dbl_setzero_mantissap1(dbl_value) Dallp1(dbl_value) &= 0xfff00000 | ||
301 | #define Dbl_setzero_mantissap2(dbl_value) Dallp2(dbl_value) = 0 | ||
302 | #define Dbl_setzero_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
303 | Dallp1(dbl_valueA) &= 0x80000000; \ | ||
304 | Dallp2(dbl_valueB) = 0 | ||
305 | #define Dbl_setzero_exponentmantissap1(dbl_valueA) \ | ||
306 | Dallp1(dbl_valueA) &= 0x80000000 | ||
307 | #define Dbl_setzero(dbl_valueA,dbl_valueB) \ | ||
308 | Dallp1(dbl_valueA) = 0; Dallp2(dbl_valueB) = 0 | ||
309 | #define Dbl_setzerop1(dbl_value) Dallp1(dbl_value) = 0 | ||
310 | #define Dbl_setzerop2(dbl_value) Dallp2(dbl_value) = 0 | ||
311 | #define Dbl_setnegativezero(dbl_value) \ | ||
312 | Dallp1(dbl_value) = (unsigned int)1 << 31; Dallp2(dbl_value) = 0 | ||
313 | #define Dbl_setnegativezerop1(dbl_value) Dallp1(dbl_value) = (unsigned int)1<<31 | ||
314 | |||
315 | /* Use the following macro for both overflow & underflow conditions */ | ||
316 | #define ovfl - | ||
317 | #define unfl + | ||
318 | #define Dbl_setwrapped_exponent(dbl_value,exponent,op) \ | ||
319 | Deposit_dexponent(dbl_value,(exponent op DBL_WRAP)) | ||
320 | |||
321 | #define Dbl_setlargestpositive(dbl_valueA,dbl_valueB) \ | ||
322 | Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \ | ||
323 | | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ); \ | ||
324 | Dallp2(dbl_valueB) = 0xFFFFFFFF | ||
325 | #define Dbl_setlargestnegative(dbl_valueA,dbl_valueB) \ | ||
326 | Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \ | ||
327 | | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ) \ | ||
328 | | ((unsigned int)1<<31); \ | ||
329 | Dallp2(dbl_valueB) = 0xFFFFFFFF | ||
330 | #define Dbl_setlargest_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
331 | Deposit_dexponentmantissap1(dbl_valueA, \ | ||
332 | (((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \ | ||
333 | | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ))); \ | ||
334 | Dallp2(dbl_valueB) = 0xFFFFFFFF | ||
335 | |||
336 | #define Dbl_setnegativeinfinity(dbl_valueA,dbl_valueB) \ | ||
337 | Dallp1(dbl_valueA) = ((1<<DBL_EXP_LENGTH) | DBL_INFINITY_EXPONENT) \ | ||
338 | << (32-(1+DBL_EXP_LENGTH)) ; \ | ||
339 | Dallp2(dbl_valueB) = 0 | ||
340 | #define Dbl_setlargest(dbl_valueA,dbl_valueB,sign) \ | ||
341 | Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \ | ||
342 | ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) | \ | ||
343 | ((1 << (32-(1+DBL_EXP_LENGTH))) - 1 ); \ | ||
344 | Dallp2(dbl_valueB) = 0xFFFFFFFF | ||
345 | |||
346 | |||
347 | /* The high bit is always zero so arithmetic or logical shifts will work. */ | ||
348 | #define Dbl_right_align(srcdstA,srcdstB,shift,extent) \ | ||
349 | if( shift >= 32 ) \ | ||
350 | { \ | ||
351 | /* Big shift requires examining the portion shift off \ | ||
352 | the end to properly set inexact. */ \ | ||
353 | if(shift < 64) \ | ||
354 | { \ | ||
355 | if(shift > 32) \ | ||
356 | { \ | ||
357 | Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB), \ | ||
358 | shift-32, Extall(extent)); \ | ||
359 | if(Dallp2(srcdstB) << 64 - (shift)) Ext_setone_low(extent); \ | ||
360 | } \ | ||
361 | else Extall(extent) = Dallp2(srcdstB); \ | ||
362 | Dallp2(srcdstB) = Dallp1(srcdstA) >> (shift - 32); \ | ||
363 | } \ | ||
364 | else \ | ||
365 | { \ | ||
366 | Extall(extent) = Dallp1(srcdstA); \ | ||
367 | if(Dallp2(srcdstB)) Ext_setone_low(extent); \ | ||
368 | Dallp2(srcdstB) = 0; \ | ||
369 | } \ | ||
370 | Dallp1(srcdstA) = 0; \ | ||
371 | } \ | ||
372 | else \ | ||
373 | { \ | ||
374 | /* Small alignment is simpler. Extension is easily set. */ \ | ||
375 | if (shift > 0) \ | ||
376 | { \ | ||
377 | Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \ | ||
378 | Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB),shift, \ | ||
379 | Dallp2(srcdstB)); \ | ||
380 | Dallp1(srcdstA) >>= shift; \ | ||
381 | } \ | ||
382 | else Extall(extent) = 0; \ | ||
383 | } | ||
384 | |||
385 | /* | ||
386 | * Here we need to shift the result right to correct for an overshift | ||
387 | * (due to the exponent becoming negative) during normalization. | ||
388 | */ | ||
389 | #define Dbl_fix_overshift(srcdstA,srcdstB,shift,extent) \ | ||
390 | Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \ | ||
391 | Dallp2(srcdstB) = (Dallp1(srcdstA) << 32 - (shift)) | \ | ||
392 | (Dallp2(srcdstB) >> (shift)); \ | ||
393 | Dallp1(srcdstA) = Dallp1(srcdstA) >> shift | ||
394 | |||
395 | #define Dbl_hiddenhigh3mantissa(dbl_value) Dhiddenhigh3mantissa(dbl_value) | ||
396 | #define Dbl_hidden(dbl_value) Dhidden(dbl_value) | ||
397 | #define Dbl_lowmantissap2(dbl_value) Dlowp2(dbl_value) | ||
398 | |||
399 | /* The left argument is never smaller than the right argument */ | ||
400 | #define Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb) \ | ||
401 | if( Dallp2(rightb) > Dallp2(leftb) ) Dallp1(lefta)--; \ | ||
402 | Dallp2(resultb) = Dallp2(leftb) - Dallp2(rightb); \ | ||
403 | Dallp1(resulta) = Dallp1(lefta) - Dallp1(righta) | ||
404 | |||
405 | /* Subtract right augmented with extension from left augmented with zeros and | ||
406 | * store into result and extension. */ | ||
407 | #define Dbl_subtract_withextension(lefta,leftb,righta,rightb,extent,resulta,resultb) \ | ||
408 | Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb); \ | ||
409 | if( (Extall(extent) = 0-Extall(extent)) ) \ | ||
410 | { \ | ||
411 | if((Dallp2(resultb)--) == 0) Dallp1(resulta)--; \ | ||
412 | } | ||
413 | |||
414 | #define Dbl_addition(lefta,leftb,righta,rightb,resulta,resultb) \ | ||
415 | /* If the sum of the low words is less than either source, then \ | ||
416 | * an overflow into the next word occurred. */ \ | ||
417 | Dallp1(resulta) = Dallp1(lefta) + Dallp1(righta); \ | ||
418 | if((Dallp2(resultb) = Dallp2(leftb) + Dallp2(rightb)) < Dallp2(rightb)) \ | ||
419 | Dallp1(resulta)++ | ||
420 | |||
421 | #define Dbl_xortointp1(left,right,result) \ | ||
422 | result = Dallp1(left) XOR Dallp1(right) | ||
423 | |||
424 | #define Dbl_xorfromintp1(left,right,result) \ | ||
425 | Dallp1(result) = left XOR Dallp1(right) | ||
426 | |||
427 | #define Dbl_swap_lower(left,right) \ | ||
428 | Dallp2(left) = Dallp2(left) XOR Dallp2(right); \ | ||
429 | Dallp2(right) = Dallp2(left) XOR Dallp2(right); \ | ||
430 | Dallp2(left) = Dallp2(left) XOR Dallp2(right) | ||
431 | |||
432 | /* Need to Initialize */ | ||
433 | #define Dbl_makequietnan(desta,destb) \ | ||
434 | Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \ | ||
435 | | (1<<(32-(1+DBL_EXP_LENGTH+2))); \ | ||
436 | Dallp2(destb) = 0 | ||
437 | #define Dbl_makesignalingnan(desta,destb) \ | ||
438 | Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \ | ||
439 | | (1<<(32-(1+DBL_EXP_LENGTH+1))); \ | ||
440 | Dallp2(destb) = 0 | ||
441 | |||
442 | #define Dbl_normalize(dbl_opndA,dbl_opndB,exponent) \ | ||
443 | while(Dbl_iszero_hiddenhigh7mantissa(dbl_opndA)) { \ | ||
444 | Dbl_leftshiftby8(dbl_opndA,dbl_opndB); \ | ||
445 | exponent -= 8; \ | ||
446 | } \ | ||
447 | if(Dbl_iszero_hiddenhigh3mantissa(dbl_opndA)) { \ | ||
448 | Dbl_leftshiftby4(dbl_opndA,dbl_opndB); \ | ||
449 | exponent -= 4; \ | ||
450 | } \ | ||
451 | while(Dbl_iszero_hidden(dbl_opndA)) { \ | ||
452 | Dbl_leftshiftby1(dbl_opndA,dbl_opndB); \ | ||
453 | exponent -= 1; \ | ||
454 | } | ||
455 | |||
456 | #define Twoword_add(src1dstA,src1dstB,src2A,src2B) \ | ||
457 | /* \ | ||
458 | * want this macro to generate: \ | ||
459 | * ADD src1dstB,src2B,src1dstB; \ | ||
460 | * ADDC src1dstA,src2A,src1dstA; \ | ||
461 | */ \ | ||
462 | if ((src1dstB) + (src2B) < (src1dstB)) Dallp1(src1dstA)++; \ | ||
463 | Dallp1(src1dstA) += (src2A); \ | ||
464 | Dallp2(src1dstB) += (src2B) | ||
465 | |||
466 | #define Twoword_subtract(src1dstA,src1dstB,src2A,src2B) \ | ||
467 | /* \ | ||
468 | * want this macro to generate: \ | ||
469 | * SUB src1dstB,src2B,src1dstB; \ | ||
470 | * SUBB src1dstA,src2A,src1dstA; \ | ||
471 | */ \ | ||
472 | if ((src1dstB) < (src2B)) Dallp1(src1dstA)--; \ | ||
473 | Dallp1(src1dstA) -= (src2A); \ | ||
474 | Dallp2(src1dstB) -= (src2B) | ||
475 | |||
476 | #define Dbl_setoverflow(resultA,resultB) \ | ||
477 | /* set result to infinity or largest number */ \ | ||
478 | switch (Rounding_mode()) { \ | ||
479 | case ROUNDPLUS: \ | ||
480 | if (Dbl_isone_sign(resultA)) { \ | ||
481 | Dbl_setlargestnegative(resultA,resultB); \ | ||
482 | } \ | ||
483 | else { \ | ||
484 | Dbl_setinfinitypositive(resultA,resultB); \ | ||
485 | } \ | ||
486 | break; \ | ||
487 | case ROUNDMINUS: \ | ||
488 | if (Dbl_iszero_sign(resultA)) { \ | ||
489 | Dbl_setlargestpositive(resultA,resultB); \ | ||
490 | } \ | ||
491 | else { \ | ||
492 | Dbl_setinfinitynegative(resultA,resultB); \ | ||
493 | } \ | ||
494 | break; \ | ||
495 | case ROUNDNEAREST: \ | ||
496 | Dbl_setinfinity_exponentmantissa(resultA,resultB); \ | ||
497 | break; \ | ||
498 | case ROUNDZERO: \ | ||
499 | Dbl_setlargest_exponentmantissa(resultA,resultB); \ | ||
500 | } | ||
501 | |||
502 | #define Dbl_denormalize(opndp1,opndp2,exponent,guard,sticky,inexact) \ | ||
503 | Dbl_clear_signexponent_set_hidden(opndp1); \ | ||
504 | if (exponent >= (1-DBL_P)) { \ | ||
505 | if (exponent >= -31) { \ | ||
506 | guard = (Dallp2(opndp2) >> -exponent) & 1; \ | ||
507 | if (exponent < 0) sticky |= Dallp2(opndp2) << (32+exponent); \ | ||
508 | if (exponent > -31) { \ | ||
509 | Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \ | ||
510 | Dallp1(opndp1) >>= 1-exponent; \ | ||
511 | } \ | ||
512 | else { \ | ||
513 | Dallp2(opndp2) = Dallp1(opndp1); \ | ||
514 | Dbl_setzerop1(opndp1); \ | ||
515 | } \ | ||
516 | } \ | ||
517 | else { \ | ||
518 | guard = (Dallp1(opndp1) >> -32-exponent) & 1; \ | ||
519 | if (exponent == -32) sticky |= Dallp2(opndp2); \ | ||
520 | else sticky |= (Dallp2(opndp2) | Dallp1(opndp1) << 64+exponent); \ | ||
521 | Dallp2(opndp2) = Dallp1(opndp1) >> -31-exponent; \ | ||
522 | Dbl_setzerop1(opndp1); \ | ||
523 | } \ | ||
524 | inexact = guard | sticky; \ | ||
525 | } \ | ||
526 | else { \ | ||
527 | guard = 0; \ | ||
528 | sticky |= (Dallp1(opndp1) | Dallp2(opndp2)); \ | ||
529 | Dbl_setzero(opndp1,opndp2); \ | ||
530 | inexact = sticky; \ | ||
531 | } | ||
532 | |||
533 | /* | ||
534 | * The fused multiply add instructions requires a double extended format, | ||
535 | * with 106 bits of mantissa. | ||
536 | */ | ||
537 | #define DBLEXT_THRESHOLD 106 | ||
538 | |||
539 | #define Dblext_setzero(valA,valB,valC,valD) \ | ||
540 | Dextallp1(valA) = 0; Dextallp2(valB) = 0; \ | ||
541 | Dextallp3(valC) = 0; Dextallp4(valD) = 0 | ||
542 | |||
543 | |||
544 | #define Dblext_isnotzero_mantissap3(valC) (Dextallp3(valC)!=0) | ||
545 | #define Dblext_isnotzero_mantissap4(valD) (Dextallp3(valD)!=0) | ||
546 | #define Dblext_isone_lowp2(val) (Dextlowp2(val)!=0) | ||
547 | #define Dblext_isone_highp3(val) (Dexthighp3(val)!=0) | ||
548 | #define Dblext_isnotzero_low31p3(val) (Dextlow31p3(val)!=0) | ||
549 | #define Dblext_iszero(valA,valB,valC,valD) (Dextallp1(valA)==0 && \ | ||
550 | Dextallp2(valB)==0 && Dextallp3(valC)==0 && Dextallp4(valD)==0) | ||
551 | |||
552 | #define Dblext_copy(srca,srcb,srcc,srcd,desta,destb,destc,destd) \ | ||
553 | Dextallp1(desta) = Dextallp4(srca); \ | ||
554 | Dextallp2(destb) = Dextallp4(srcb); \ | ||
555 | Dextallp3(destc) = Dextallp4(srcc); \ | ||
556 | Dextallp4(destd) = Dextallp4(srcd) | ||
557 | |||
558 | #define Dblext_swap_lower(leftp2,leftp3,leftp4,rightp2,rightp3,rightp4) \ | ||
559 | Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \ | ||
560 | Dextallp2(rightp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \ | ||
561 | Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \ | ||
562 | Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \ | ||
563 | Dextallp3(rightp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \ | ||
564 | Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \ | ||
565 | Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \ | ||
566 | Dextallp4(rightp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \ | ||
567 | Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4) | ||
568 | |||
569 | #define Dblext_setone_lowmantissap4(dbl_value) Deposit_dextlowp4(dbl_value,1) | ||
570 | |||
571 | /* The high bit is always zero so arithmetic or logical shifts will work. */ | ||
572 | #define Dblext_right_align(srcdstA,srcdstB,srcdstC,srcdstD,shift) \ | ||
573 | {int shiftamt, sticky; \ | ||
574 | shiftamt = shift % 32; \ | ||
575 | sticky = 0; \ | ||
576 | switch (shift/32) { \ | ||
577 | case 0: if (shiftamt > 0) { \ | ||
578 | sticky = Dextallp4(srcdstD) << 32 - (shiftamt); \ | ||
579 | Variable_shift_double(Dextallp3(srcdstC), \ | ||
580 | Dextallp4(srcdstD),shiftamt,Dextallp4(srcdstD)); \ | ||
581 | Variable_shift_double(Dextallp2(srcdstB), \ | ||
582 | Dextallp3(srcdstC),shiftamt,Dextallp3(srcdstC)); \ | ||
583 | Variable_shift_double(Dextallp1(srcdstA), \ | ||
584 | Dextallp2(srcdstB),shiftamt,Dextallp2(srcdstB)); \ | ||
585 | Dextallp1(srcdstA) >>= shiftamt; \ | ||
586 | } \ | ||
587 | break; \ | ||
588 | case 1: if (shiftamt > 0) { \ | ||
589 | sticky = (Dextallp3(srcdstC) << 31 - shiftamt) | \ | ||
590 | Dextallp4(srcdstD); \ | ||
591 | Variable_shift_double(Dextallp2(srcdstB), \ | ||
592 | Dextallp3(srcdstC),shiftamt,Dextallp4(srcdstD)); \ | ||
593 | Variable_shift_double(Dextallp1(srcdstA), \ | ||
594 | Dextallp2(srcdstB),shiftamt,Dextallp3(srcdstC)); \ | ||
595 | } \ | ||
596 | else { \ | ||
597 | sticky = Dextallp4(srcdstD); \ | ||
598 | Dextallp4(srcdstD) = Dextallp3(srcdstC); \ | ||
599 | Dextallp3(srcdstC) = Dextallp2(srcdstB); \ | ||
600 | } \ | ||
601 | Dextallp2(srcdstB) = Dextallp1(srcdstA) >> shiftamt; \ | ||
602 | Dextallp1(srcdstA) = 0; \ | ||
603 | break; \ | ||
604 | case 2: if (shiftamt > 0) { \ | ||
605 | sticky = (Dextallp2(srcdstB) << 31 - shiftamt) | \ | ||
606 | Dextallp3(srcdstC) | Dextallp4(srcdstD); \ | ||
607 | Variable_shift_double(Dextallp1(srcdstA), \ | ||
608 | Dextallp2(srcdstB),shiftamt,Dextallp4(srcdstD)); \ | ||
609 | } \ | ||
610 | else { \ | ||
611 | sticky = Dextallp3(srcdstC) | Dextallp4(srcdstD); \ | ||
612 | Dextallp4(srcdstD) = Dextallp2(srcdstB); \ | ||
613 | } \ | ||
614 | Dextallp3(srcdstC) = Dextallp1(srcdstA) >> shiftamt; \ | ||
615 | Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \ | ||
616 | break; \ | ||
617 | case 3: if (shiftamt > 0) { \ | ||
618 | sticky = (Dextallp1(srcdstA) << 31 - shiftamt) | \ | ||
619 | Dextallp2(srcdstB) | Dextallp3(srcdstC) | \ | ||
620 | Dextallp4(srcdstD); \ | ||
621 | } \ | ||
622 | else { \ | ||
623 | sticky = Dextallp2(srcdstB) | Dextallp3(srcdstC) | \ | ||
624 | Dextallp4(srcdstD); \ | ||
625 | } \ | ||
626 | Dextallp4(srcdstD) = Dextallp1(srcdstA) >> shiftamt; \ | ||
627 | Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \ | ||
628 | Dextallp3(srcdstC) = 0; \ | ||
629 | break; \ | ||
630 | } \ | ||
631 | if (sticky) Dblext_setone_lowmantissap4(srcdstD); \ | ||
632 | } | ||
633 | |||
634 | /* The left argument is never smaller than the right argument */ | ||
635 | #define Dblext_subtract(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \ | ||
636 | if( Dextallp4(rightd) > Dextallp4(leftd) ) \ | ||
637 | if( (Dextallp3(leftc)--) == 0) \ | ||
638 | if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \ | ||
639 | Dextallp4(resultd) = Dextallp4(leftd) - Dextallp4(rightd); \ | ||
640 | if( Dextallp3(rightc) > Dextallp3(leftc) ) \ | ||
641 | if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \ | ||
642 | Dextallp3(resultc) = Dextallp3(leftc) - Dextallp3(rightc); \ | ||
643 | if( Dextallp2(rightb) > Dextallp2(leftb) ) Dextallp1(lefta)--; \ | ||
644 | Dextallp2(resultb) = Dextallp2(leftb) - Dextallp2(rightb); \ | ||
645 | Dextallp1(resulta) = Dextallp1(lefta) - Dextallp1(righta) | ||
646 | |||
647 | #define Dblext_addition(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \ | ||
648 | /* If the sum of the low words is less than either source, then \ | ||
649 | * an overflow into the next word occurred. */ \ | ||
650 | if ((Dextallp4(resultd) = Dextallp4(leftd)+Dextallp4(rightd)) < \ | ||
651 | Dextallp4(rightd)) \ | ||
652 | if((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)+1) <= \ | ||
653 | Dextallp3(rightc)) \ | ||
654 | if((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \ | ||
655 | <= Dextallp2(rightb)) \ | ||
656 | Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ | ||
657 | else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \ | ||
658 | else \ | ||
659 | if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \ | ||
660 | Dextallp2(rightb)) \ | ||
661 | Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ | ||
662 | else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \ | ||
663 | else \ | ||
664 | if ((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)) < \ | ||
665 | Dextallp3(rightc)) \ | ||
666 | if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \ | ||
667 | <= Dextallp2(rightb)) \ | ||
668 | Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ | ||
669 | else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \ | ||
670 | else \ | ||
671 | if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \ | ||
672 | Dextallp2(rightb)) \ | ||
673 | Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ | ||
674 | else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta) | ||
675 | |||
676 | |||
677 | #define Dblext_arithrightshiftby1(srcdstA,srcdstB,srcdstC,srcdstD) \ | ||
678 | Shiftdouble(Dextallp3(srcdstC),Dextallp4(srcdstD),1,Dextallp4(srcdstD)); \ | ||
679 | Shiftdouble(Dextallp2(srcdstB),Dextallp3(srcdstC),1,Dextallp3(srcdstC)); \ | ||
680 | Shiftdouble(Dextallp1(srcdstA),Dextallp2(srcdstB),1,Dextallp2(srcdstB)); \ | ||
681 | Dextallp1(srcdstA) = (int)Dextallp1(srcdstA) >> 1 | ||
682 | |||
683 | #define Dblext_leftshiftby8(valA,valB,valC,valD) \ | ||
684 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),24,Dextallp1(valA)); \ | ||
685 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),24,Dextallp2(valB)); \ | ||
686 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),24,Dextallp3(valC)); \ | ||
687 | Dextallp4(valD) <<= 8 | ||
688 | #define Dblext_leftshiftby4(valA,valB,valC,valD) \ | ||
689 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),28,Dextallp1(valA)); \ | ||
690 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),28,Dextallp2(valB)); \ | ||
691 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),28,Dextallp3(valC)); \ | ||
692 | Dextallp4(valD) <<= 4 | ||
693 | #define Dblext_leftshiftby3(valA,valB,valC,valD) \ | ||
694 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),29,Dextallp1(valA)); \ | ||
695 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),29,Dextallp2(valB)); \ | ||
696 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),29,Dextallp3(valC)); \ | ||
697 | Dextallp4(valD) <<= 3 | ||
698 | #define Dblext_leftshiftby2(valA,valB,valC,valD) \ | ||
699 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),30,Dextallp1(valA)); \ | ||
700 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),30,Dextallp2(valB)); \ | ||
701 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),30,Dextallp3(valC)); \ | ||
702 | Dextallp4(valD) <<= 2 | ||
703 | #define Dblext_leftshiftby1(valA,valB,valC,valD) \ | ||
704 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),31,Dextallp1(valA)); \ | ||
705 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),31,Dextallp2(valB)); \ | ||
706 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),31,Dextallp3(valC)); \ | ||
707 | Dextallp4(valD) <<= 1 | ||
708 | |||
709 | #define Dblext_rightshiftby4(valueA,valueB,valueC,valueD) \ | ||
710 | Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),4,Dextallp4(valueD)); \ | ||
711 | Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),4,Dextallp3(valueC)); \ | ||
712 | Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),4,Dextallp2(valueB)); \ | ||
713 | Dextallp1(valueA) >>= 4 | ||
714 | #define Dblext_rightshiftby1(valueA,valueB,valueC,valueD) \ | ||
715 | Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),1,Dextallp4(valueD)); \ | ||
716 | Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),1,Dextallp3(valueC)); \ | ||
717 | Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),1,Dextallp2(valueB)); \ | ||
718 | Dextallp1(valueA) >>= 1 | ||
719 | |||
720 | #define Dblext_xortointp1(left,right,result) Dbl_xortointp1(left,right,result) | ||
721 | |||
722 | #define Dblext_xorfromintp1(left,right,result) \ | ||
723 | Dbl_xorfromintp1(left,right,result) | ||
724 | |||
725 | #define Dblext_copytoint_exponentmantissap1(src,dest) \ | ||
726 | Dbl_copytoint_exponentmantissap1(src,dest) | ||
727 | |||
728 | #define Dblext_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \ | ||
729 | Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright) | ||
730 | |||
731 | #define Dbl_copyto_dblext(src1,src2,dest1,dest2,dest3,dest4) \ | ||
732 | Dextallp1(dest1) = Dallp1(src1); Dextallp2(dest2) = Dallp2(src2); \ | ||
733 | Dextallp3(dest3) = 0; Dextallp4(dest4) = 0 | ||
734 | |||
735 | #define Dblext_set_sign(dbl_value,sign) Dbl_set_sign(dbl_value,sign) | ||
736 | #define Dblext_clear_signexponent_set_hidden(srcdst) \ | ||
737 | Dbl_clear_signexponent_set_hidden(srcdst) | ||
738 | #define Dblext_clear_signexponent(srcdst) Dbl_clear_signexponent(srcdst) | ||
739 | #define Dblext_clear_sign(srcdst) Dbl_clear_sign(srcdst) | ||
740 | #define Dblext_isone_hidden(dbl_value) Dbl_isone_hidden(dbl_value) | ||
741 | |||
742 | /* | ||
743 | * The Fourword_add() macro assumes that integers are 4 bytes in size. | ||
744 | * It will break if this is not the case. | ||
745 | */ | ||
746 | |||
747 | #define Fourword_add(src1dstA,src1dstB,src1dstC,src1dstD,src2A,src2B,src2C,src2D) \ | ||
748 | /* \ | ||
749 | * want this macro to generate: \ | ||
750 | * ADD src1dstD,src2D,src1dstD; \ | ||
751 | * ADDC src1dstC,src2C,src1dstC; \ | ||
752 | * ADDC src1dstB,src2B,src1dstB; \ | ||
753 | * ADDC src1dstA,src2A,src1dstA; \ | ||
754 | */ \ | ||
755 | if ((unsigned int)(src1dstD += (src2D)) < (unsigned int)(src2D)) { \ | ||
756 | if ((unsigned int)(src1dstC += (src2C) + 1) <= \ | ||
757 | (unsigned int)(src2C)) { \ | ||
758 | if ((unsigned int)(src1dstB += (src2B) + 1) <= \ | ||
759 | (unsigned int)(src2B)) src1dstA++; \ | ||
760 | } \ | ||
761 | else if ((unsigned int)(src1dstB += (src2B)) < \ | ||
762 | (unsigned int)(src2B)) src1dstA++; \ | ||
763 | } \ | ||
764 | else { \ | ||
765 | if ((unsigned int)(src1dstC += (src2C)) < \ | ||
766 | (unsigned int)(src2C)) { \ | ||
767 | if ((unsigned int)(src1dstB += (src2B) + 1) <= \ | ||
768 | (unsigned int)(src2B)) src1dstA++; \ | ||
769 | } \ | ||
770 | else if ((unsigned int)(src1dstB += (src2B)) < \ | ||
771 | (unsigned int)(src2B)) src1dstA++; \ | ||
772 | } \ | ||
773 | src1dstA += (src2A) | ||
774 | |||
775 | #define Dblext_denormalize(opndp1,opndp2,opndp3,opndp4,exponent,is_tiny) \ | ||
776 | {int shiftamt, sticky; \ | ||
777 | is_tiny = TRUE; \ | ||
778 | if (exponent == 0 && (Dextallp3(opndp3) || Dextallp4(opndp4))) { \ | ||
779 | switch (Rounding_mode()) { \ | ||
780 | case ROUNDPLUS: \ | ||
781 | if (Dbl_iszero_sign(opndp1)) { \ | ||
782 | Dbl_increment(opndp1,opndp2); \ | ||
783 | if (Dbl_isone_hiddenoverflow(opndp1)) \ | ||
784 | is_tiny = FALSE; \ | ||
785 | Dbl_decrement(opndp1,opndp2); \ | ||
786 | } \ | ||
787 | break; \ | ||
788 | case ROUNDMINUS: \ | ||
789 | if (Dbl_isone_sign(opndp1)) { \ | ||
790 | Dbl_increment(opndp1,opndp2); \ | ||
791 | if (Dbl_isone_hiddenoverflow(opndp1)) \ | ||
792 | is_tiny = FALSE; \ | ||
793 | Dbl_decrement(opndp1,opndp2); \ | ||
794 | } \ | ||
795 | break; \ | ||
796 | case ROUNDNEAREST: \ | ||
797 | if (Dblext_isone_highp3(opndp3) && \ | ||
798 | (Dblext_isone_lowp2(opndp2) || \ | ||
799 | Dblext_isnotzero_low31p3(opndp3))) { \ | ||
800 | Dbl_increment(opndp1,opndp2); \ | ||
801 | if (Dbl_isone_hiddenoverflow(opndp1)) \ | ||
802 | is_tiny = FALSE; \ | ||
803 | Dbl_decrement(opndp1,opndp2); \ | ||
804 | } \ | ||
805 | break; \ | ||
806 | } \ | ||
807 | } \ | ||
808 | Dblext_clear_signexponent_set_hidden(opndp1); \ | ||
809 | if (exponent >= (1-QUAD_P)) { \ | ||
810 | shiftamt = (1-exponent) % 32; \ | ||
811 | switch((1-exponent)/32) { \ | ||
812 | case 0: sticky = Dextallp4(opndp4) << 32-(shiftamt); \ | ||
813 | Variableshiftdouble(opndp3,opndp4,shiftamt,opndp4); \ | ||
814 | Variableshiftdouble(opndp2,opndp3,shiftamt,opndp3); \ | ||
815 | Variableshiftdouble(opndp1,opndp2,shiftamt,opndp2); \ | ||
816 | Dextallp1(opndp1) >>= shiftamt; \ | ||
817 | break; \ | ||
818 | case 1: sticky = (Dextallp3(opndp3) << 32-(shiftamt)) | \ | ||
819 | Dextallp4(opndp4); \ | ||
820 | Variableshiftdouble(opndp2,opndp3,shiftamt,opndp4); \ | ||
821 | Variableshiftdouble(opndp1,opndp2,shiftamt,opndp3); \ | ||
822 | Dextallp2(opndp2) = Dextallp1(opndp1) >> shiftamt; \ | ||
823 | Dextallp1(opndp1) = 0; \ | ||
824 | break; \ | ||
825 | case 2: sticky = (Dextallp2(opndp2) << 32-(shiftamt)) | \ | ||
826 | Dextallp3(opndp3) | Dextallp4(opndp4); \ | ||
827 | Variableshiftdouble(opndp1,opndp2,shiftamt,opndp4); \ | ||
828 | Dextallp3(opndp3) = Dextallp1(opndp1) >> shiftamt; \ | ||
829 | Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \ | ||
830 | break; \ | ||
831 | case 3: sticky = (Dextallp1(opndp1) << 32-(shiftamt)) | \ | ||
832 | Dextallp2(opndp2) | Dextallp3(opndp3) | \ | ||
833 | Dextallp4(opndp4); \ | ||
834 | Dextallp4(opndp4) = Dextallp1(opndp1) >> shiftamt; \ | ||
835 | Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \ | ||
836 | Dextallp3(opndp3) = 0; \ | ||
837 | break; \ | ||
838 | } \ | ||
839 | } \ | ||
840 | else { \ | ||
841 | sticky = Dextallp1(opndp1) | Dextallp2(opndp2) | \ | ||
842 | Dextallp3(opndp3) | Dextallp4(opndp4); \ | ||
843 | Dblext_setzero(opndp1,opndp2,opndp3,opndp4); \ | ||
844 | } \ | ||
845 | if (sticky) Dblext_setone_lowmantissap4(opndp4); \ | ||
846 | exponent = 0; \ | ||
847 | } | ||
diff --git a/arch/parisc/math-emu/decode_exc.c b/arch/parisc/math-emu/decode_exc.c new file mode 100644 index 000000000000..f84f2586672b --- /dev/null +++ b/arch/parisc/math-emu/decode_exc.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/fp/decode_exc.c $ Revision: $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * <<please update with a synopsis of the functionality provided by this file>> | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * <<the following list was autogenerated, please review>> | ||
32 | * decode_fpu(Fpu_register, trap_counts) | ||
33 | * | ||
34 | * Internal Interfaces: | ||
35 | * <<please update>> | ||
36 | * | ||
37 | * Theory: | ||
38 | * <<please update with a overview of the operation of this file>> | ||
39 | * | ||
40 | * END_DESC | ||
41 | */ | ||
42 | |||
43 | |||
44 | #include "float.h" | ||
45 | #include "sgl_float.h" | ||
46 | #include "dbl_float.h" | ||
47 | #include "cnv_float.h" | ||
48 | /* #include "types.h" */ | ||
49 | #include <asm/signal.h> | ||
50 | #include <asm/siginfo.h> | ||
51 | /* #include <machine/sys/mdep_private.h> */ | ||
52 | |||
53 | #undef Fpustatus_register | ||
54 | #define Fpustatus_register Fpu_register[0] | ||
55 | |||
56 | /* General definitions */ | ||
57 | #define DOESTRAP 1 | ||
58 | #define NOTRAP 0 | ||
59 | #define SIGNALCODE(signal, code) ((signal) << 24 | (code)); | ||
60 | #define copropbit 1<<31-2 /* bit position 2 */ | ||
61 | #define opclass 9 /* bits 21 & 22 */ | ||
62 | #define fmt 11 /* bits 19 & 20 */ | ||
63 | #define df 13 /* bits 17 & 18 */ | ||
64 | #define twobits 3 /* mask low-order 2 bits */ | ||
65 | #define fivebits 31 /* mask low-order 5 bits */ | ||
66 | #define MAX_EXCP_REG 7 /* number of excpeption registers to check */ | ||
67 | |||
68 | /* Exception register definitions */ | ||
69 | #define Excp_type(index) Exceptiontype(Fpu_register[index]) | ||
70 | #define Excp_instr(index) Instructionfield(Fpu_register[index]) | ||
71 | #define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0 | ||
72 | #define Excp_format() \ | ||
73 | (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits) | ||
74 | |||
75 | /* Miscellaneous definitions */ | ||
76 | #define Fpu_sgl(index) Fpu_register[index*2] | ||
77 | |||
78 | #define Fpu_dblp1(index) Fpu_register[index*2] | ||
79 | #define Fpu_dblp2(index) Fpu_register[(index*2)+1] | ||
80 | |||
81 | #define Fpu_quadp1(index) Fpu_register[index*2] | ||
82 | #define Fpu_quadp2(index) Fpu_register[(index*2)+1] | ||
83 | #define Fpu_quadp3(index) Fpu_register[(index*2)+2] | ||
84 | #define Fpu_quadp4(index) Fpu_register[(index*2)+3] | ||
85 | |||
86 | /* Single precision floating-point definitions */ | ||
87 | #ifndef Sgl_decrement | ||
88 | # define Sgl_decrement(sgl_value) Sall(sgl_value)-- | ||
89 | #endif | ||
90 | |||
91 | /* Double precision floating-point definitions */ | ||
92 | #ifndef Dbl_decrement | ||
93 | # define Dbl_decrement(dbl_valuep1,dbl_valuep2) \ | ||
94 | if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)-- | ||
95 | #endif | ||
96 | |||
97 | |||
98 | #define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) { \ | ||
99 | aflags=(Fpu_register[0])>>27; /* assumes zero fill. 32 bit */ \ | ||
100 | Fpu_register[0] |= bflags; \ | ||
101 | } | ||
102 | |||
103 | u_int | ||
104 | decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[]) | ||
105 | { | ||
106 | unsigned int current_ir, excp; | ||
107 | int target, exception_index = 1; | ||
108 | boolean inexact; | ||
109 | unsigned int aflags; | ||
110 | unsigned int bflags; | ||
111 | unsigned int excptype; | ||
112 | |||
113 | |||
114 | /* Keep stats on how many floating point exceptions (based on type) | ||
115 | * that happen. Want to keep this overhead low, but still provide | ||
116 | * some information to the customer. All exits from this routine | ||
117 | * need to restore Fpu_register[0] | ||
118 | */ | ||
119 | |||
120 | bflags=(Fpu_register[0] & 0xf8000000); | ||
121 | Fpu_register[0] &= 0x07ffffff; | ||
122 | |||
123 | /* exception_index is used to index the exception register queue. It | ||
124 | * always points at the last register that contains a valid exception. A | ||
125 | * zero value implies no exceptions (also the initialized value). Setting | ||
126 | * the T-bit resets the exception_index to zero. | ||
127 | */ | ||
128 | |||
129 | /* | ||
130 | * Check for reserved-op exception. A reserved-op exception does not | ||
131 | * set any exception registers nor does it set the T-bit. If the T-bit | ||
132 | * is not set then a reserved-op exception occurred. | ||
133 | * | ||
134 | * At some point, we may want to report reserved op exceptions as | ||
135 | * illegal instructions. | ||
136 | */ | ||
137 | |||
138 | if (!Is_tbit_set()) { | ||
139 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
140 | return SIGNALCODE(SIGILL, ILL_COPROC); | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * Is a coprocessor op. | ||
145 | * | ||
146 | * Now we need to determine what type of exception occurred. | ||
147 | */ | ||
148 | for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) { | ||
149 | current_ir = Excp_instr(exception_index); | ||
150 | /* | ||
151 | * On PA89: there are 5 different unimplemented exception | ||
152 | * codes: 0x1, 0x9, 0xb, 0x3, and 0x23. PA-RISC 2.0 adds | ||
153 | * another, 0x2b. Only these have the low order bit set. | ||
154 | */ | ||
155 | excptype = Excp_type(exception_index); | ||
156 | if (excptype & UNIMPLEMENTEDEXCEPTION) { | ||
157 | /* | ||
158 | * Clear T-bit and exception register so that | ||
159 | * we can tell if a trap really occurs while | ||
160 | * emulating the instruction. | ||
161 | */ | ||
162 | Clear_tbit(); | ||
163 | Clear_excp_register(exception_index); | ||
164 | /* | ||
165 | * Now emulate this instruction. If a trap occurs, | ||
166 | * fpudispatch will return a non-zero number | ||
167 | */ | ||
168 | excp = fpudispatch(current_ir,excptype,0,Fpu_register); | ||
169 | /* accumulate the status flags, don't lose them as in hpux */ | ||
170 | if (excp) { | ||
171 | /* | ||
172 | * We now need to make sure that the T-bit and the | ||
173 | * exception register contain the correct values | ||
174 | * before continuing. | ||
175 | */ | ||
176 | /* | ||
177 | * Set t-bit since it might still be needed for a | ||
178 | * subsequent real trap (I don't understand fully -PB) | ||
179 | */ | ||
180 | Set_tbit(); | ||
181 | /* some of the following code uses | ||
182 | * Excp_type(exception_index) so fix that up */ | ||
183 | Set_exceptiontype_and_instr_field(excp,current_ir, | ||
184 | Fpu_register[exception_index]); | ||
185 | if (excp == UNIMPLEMENTEDEXCEPTION) { | ||
186 | /* | ||
187 | * it is really unimplemented, so restore the | ||
188 | * TIMEX extended unimplemented exception code | ||
189 | */ | ||
190 | excp = excptype; | ||
191 | update_trap_counts(Fpu_register, aflags, bflags, | ||
192 | trap_counts); | ||
193 | return SIGNALCODE(SIGILL, ILL_COPROC); | ||
194 | } | ||
195 | /* some of the following code uses excptype, so | ||
196 | * fix that up too */ | ||
197 | excptype = excp; | ||
198 | } | ||
199 | /* handle exceptions other than the real UNIMPLIMENTED the | ||
200 | * same way as if the hardware had caused them */ | ||
201 | if (excp == NOEXCEPTION) | ||
202 | /* For now use 'break', should technically be 'continue' */ | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * In PA89, the underflow exception has been extended to encode | ||
208 | * additional information. The exception looks like pp01x0, | ||
209 | * where x is 1 if inexact and pp represent the inexact bit (I) | ||
210 | * and the round away bit (RA) | ||
211 | */ | ||
212 | if (excptype & UNDERFLOWEXCEPTION) { | ||
213 | /* check for underflow trap enabled */ | ||
214 | if (Is_underflowtrap_enabled()) { | ||
215 | update_trap_counts(Fpu_register, aflags, bflags, | ||
216 | trap_counts); | ||
217 | return SIGNALCODE(SIGFPE, FPE_FLTUND); | ||
218 | } else { | ||
219 | /* | ||
220 | * Isn't a real trap; we need to | ||
221 | * return the default value. | ||
222 | */ | ||
223 | target = current_ir & fivebits; | ||
224 | #ifndef lint | ||
225 | if (Ibit(Fpu_register[exception_index])) inexact = TRUE; | ||
226 | else inexact = FALSE; | ||
227 | #endif | ||
228 | switch (Excp_format()) { | ||
229 | case SGL: | ||
230 | /* | ||
231 | * If ra (round-away) is set, will | ||
232 | * want to undo the rounding done | ||
233 | * by the hardware. | ||
234 | */ | ||
235 | if (Rabit(Fpu_register[exception_index])) | ||
236 | Sgl_decrement(Fpu_sgl(target)); | ||
237 | |||
238 | /* now denormalize */ | ||
239 | sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode()); | ||
240 | break; | ||
241 | case DBL: | ||
242 | /* | ||
243 | * If ra (round-away) is set, will | ||
244 | * want to undo the rounding done | ||
245 | * by the hardware. | ||
246 | */ | ||
247 | if (Rabit(Fpu_register[exception_index])) | ||
248 | Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target)); | ||
249 | |||
250 | /* now denormalize */ | ||
251 | dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target), | ||
252 | &inexact,Rounding_mode()); | ||
253 | break; | ||
254 | } | ||
255 | if (inexact) Set_underflowflag(); | ||
256 | /* | ||
257 | * Underflow can generate an inexact | ||
258 | * exception. If inexact trap is enabled, | ||
259 | * want to do an inexact trap, otherwise | ||
260 | * set inexact flag. | ||
261 | */ | ||
262 | if (inexact && Is_inexacttrap_enabled()) { | ||
263 | /* | ||
264 | * Set exception field of exception register | ||
265 | * to inexact, parm field to zero. | ||
266 | * Underflow bit should be cleared. | ||
267 | */ | ||
268 | Set_exceptiontype(Fpu_register[exception_index], | ||
269 | INEXACTEXCEPTION); | ||
270 | Set_parmfield(Fpu_register[exception_index],0); | ||
271 | update_trap_counts(Fpu_register, aflags, bflags, | ||
272 | trap_counts); | ||
273 | return SIGNALCODE(SIGFPE, FPE_FLTRES); | ||
274 | } | ||
275 | else { | ||
276 | /* | ||
277 | * Exception register needs to be cleared. | ||
278 | * Inexact flag needs to be set if inexact. | ||
279 | */ | ||
280 | Clear_excp_register(exception_index); | ||
281 | if (inexact) Set_inexactflag(); | ||
282 | } | ||
283 | } | ||
284 | continue; | ||
285 | } | ||
286 | switch(Excp_type(exception_index)) { | ||
287 | case OVERFLOWEXCEPTION: | ||
288 | case OVERFLOWEXCEPTION | INEXACTEXCEPTION: | ||
289 | /* check for overflow trap enabled */ | ||
290 | update_trap_counts(Fpu_register, aflags, bflags, | ||
291 | trap_counts); | ||
292 | if (Is_overflowtrap_enabled()) { | ||
293 | update_trap_counts(Fpu_register, aflags, bflags, | ||
294 | trap_counts); | ||
295 | return SIGNALCODE(SIGFPE, FPE_FLTOVF); | ||
296 | } else { | ||
297 | /* | ||
298 | * Isn't a real trap; we need to | ||
299 | * return the default value. | ||
300 | */ | ||
301 | target = current_ir & fivebits; | ||
302 | switch (Excp_format()) { | ||
303 | case SGL: | ||
304 | Sgl_setoverflow(Fpu_sgl(target)); | ||
305 | break; | ||
306 | case DBL: | ||
307 | Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target)); | ||
308 | break; | ||
309 | } | ||
310 | Set_overflowflag(); | ||
311 | /* | ||
312 | * Overflow always generates an inexact | ||
313 | * exception. If inexact trap is enabled, | ||
314 | * want to do an inexact trap, otherwise | ||
315 | * set inexact flag. | ||
316 | */ | ||
317 | if (Is_inexacttrap_enabled()) { | ||
318 | /* | ||
319 | * Set exception field of exception | ||
320 | * register to inexact. Overflow | ||
321 | * bit should be cleared. | ||
322 | */ | ||
323 | Set_exceptiontype(Fpu_register[exception_index], | ||
324 | INEXACTEXCEPTION); | ||
325 | update_trap_counts(Fpu_register, aflags, bflags, | ||
326 | trap_counts); | ||
327 | return SIGNALCODE(SIGFPE, FPE_FLTRES); | ||
328 | } | ||
329 | else { | ||
330 | /* | ||
331 | * Exception register needs to be cleared. | ||
332 | * Inexact flag needs to be set. | ||
333 | */ | ||
334 | Clear_excp_register(exception_index); | ||
335 | Set_inexactflag(); | ||
336 | } | ||
337 | } | ||
338 | break; | ||
339 | case INVALIDEXCEPTION: | ||
340 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
341 | return SIGNALCODE(SIGFPE, FPE_FLTINV); | ||
342 | case DIVISIONBYZEROEXCEPTION: | ||
343 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
344 | return SIGNALCODE(SIGFPE, FPE_FLTDIV); | ||
345 | case INEXACTEXCEPTION: | ||
346 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
347 | return SIGNALCODE(SIGFPE, FPE_FLTRES); | ||
348 | default: | ||
349 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
350 | printk("%s(%d) Unknown FPU exception 0x%x\n", __FILE__, | ||
351 | __LINE__, Excp_type(exception_index)); | ||
352 | return SIGNALCODE(SIGILL, ILL_COPROC); | ||
353 | case NOEXCEPTION: /* no exception */ | ||
354 | /* | ||
355 | * Clear exception register in case | ||
356 | * other fields are non-zero. | ||
357 | */ | ||
358 | Clear_excp_register(exception_index); | ||
359 | break; | ||
360 | } | ||
361 | } | ||
362 | /* | ||
363 | * No real exceptions occurred. | ||
364 | */ | ||
365 | Clear_tbit(); | ||
366 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
367 | return(NOTRAP); | ||
368 | } | ||
diff --git a/arch/parisc/math-emu/denormal.c b/arch/parisc/math-emu/denormal.c new file mode 100644 index 000000000000..60687e13c34f --- /dev/null +++ b/arch/parisc/math-emu/denormal.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/fp/denormal.c $ Revision: $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * <<please update with a synopsis of the functionality provided by this file>> | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * <<the following list was autogenerated, please review>> | ||
32 | * dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode) | ||
33 | * sgl_denormalize(sgl_opnd,inexactflag,rmode) | ||
34 | * | ||
35 | * Internal Interfaces: | ||
36 | * <<please update>> | ||
37 | * | ||
38 | * Theory: | ||
39 | * <<please update with a overview of the operation of this file>> | ||
40 | * | ||
41 | * END_DESC | ||
42 | */ | ||
43 | |||
44 | |||
45 | |||
46 | #include "float.h" | ||
47 | #include "sgl_float.h" | ||
48 | #include "dbl_float.h" | ||
49 | #include "hppa.h" | ||
50 | #include <linux/kernel.h> | ||
51 | /* #include <machine/sys/mdep_private.h> */ | ||
52 | |||
53 | #undef Fpustatus_register | ||
54 | #define Fpustatus_register Fpu_register[0] | ||
55 | |||
56 | void | ||
57 | sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode) | ||
58 | { | ||
59 | unsigned int opnd; | ||
60 | int sign, exponent; | ||
61 | boolean guardbit = FALSE, stickybit, inexact; | ||
62 | |||
63 | opnd = *sgl_opnd; | ||
64 | stickybit = *inexactflag; | ||
65 | exponent = Sgl_exponent(opnd) - SGL_WRAP; | ||
66 | sign = Sgl_sign(opnd); | ||
67 | Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact); | ||
68 | if (inexact) { | ||
69 | switch (rmode) { | ||
70 | case ROUNDPLUS: | ||
71 | if (sign == 0) { | ||
72 | Sgl_increment(opnd); | ||
73 | } | ||
74 | break; | ||
75 | case ROUNDMINUS: | ||
76 | if (sign != 0) { | ||
77 | Sgl_increment(opnd); | ||
78 | } | ||
79 | break; | ||
80 | case ROUNDNEAREST: | ||
81 | if (guardbit && (stickybit || | ||
82 | Sgl_isone_lowmantissa(opnd))) { | ||
83 | Sgl_increment(opnd); | ||
84 | } | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | Sgl_set_sign(opnd,sign); | ||
89 | *sgl_opnd = opnd; | ||
90 | *inexactflag = inexact; | ||
91 | return; | ||
92 | } | ||
93 | |||
94 | void | ||
95 | dbl_denormalize(unsigned int *dbl_opndp1, | ||
96 | unsigned int * dbl_opndp2, | ||
97 | boolean *inexactflag, | ||
98 | int rmode) | ||
99 | { | ||
100 | unsigned int opndp1, opndp2; | ||
101 | int sign, exponent; | ||
102 | boolean guardbit = FALSE, stickybit, inexact; | ||
103 | |||
104 | opndp1 = *dbl_opndp1; | ||
105 | opndp2 = *dbl_opndp2; | ||
106 | stickybit = *inexactflag; | ||
107 | exponent = Dbl_exponent(opndp1) - DBL_WRAP; | ||
108 | sign = Dbl_sign(opndp1); | ||
109 | Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact); | ||
110 | if (inexact) { | ||
111 | switch (rmode) { | ||
112 | case ROUNDPLUS: | ||
113 | if (sign == 0) { | ||
114 | Dbl_increment(opndp1,opndp2); | ||
115 | } | ||
116 | break; | ||
117 | case ROUNDMINUS: | ||
118 | if (sign != 0) { | ||
119 | Dbl_increment(opndp1,opndp2); | ||
120 | } | ||
121 | break; | ||
122 | case ROUNDNEAREST: | ||
123 | if (guardbit && (stickybit || | ||
124 | Dbl_isone_lowmantissap2(opndp2))) { | ||
125 | Dbl_increment(opndp1,opndp2); | ||
126 | } | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | Dbl_set_sign(opndp1,sign); | ||
131 | *dbl_opndp1 = opndp1; | ||
132 | *dbl_opndp2 = opndp2; | ||
133 | *inexactflag = inexact; | ||
134 | return; | ||
135 | } | ||
diff --git a/arch/parisc/math-emu/dfadd.c b/arch/parisc/math-emu/dfadd.c new file mode 100644 index 000000000000..e147d7d3b0f4 --- /dev/null +++ b/arch/parisc/math-emu/dfadd.c | |||
@@ -0,0 +1,524 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/dfadd.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Double_add: add two double precision values. | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_fadd(leftptr, rightptr, dstptr, status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "dbl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Double_add: add two double precision values. | ||
47 | */ | ||
48 | dbl_fadd( | ||
49 | dbl_floating_point *leftptr, | ||
50 | dbl_floating_point *rightptr, | ||
51 | dbl_floating_point *dstptr, | ||
52 | unsigned int *status) | ||
53 | { | ||
54 | register unsigned int signless_upper_left, signless_upper_right, save; | ||
55 | register unsigned int leftp1, leftp2, rightp1, rightp2, extent; | ||
56 | register unsigned int resultp1 = 0, resultp2 = 0; | ||
57 | |||
58 | register int result_exponent, right_exponent, diff_exponent; | ||
59 | register int sign_save, jumpsize; | ||
60 | register boolean inexact = FALSE; | ||
61 | register boolean underflowtrap; | ||
62 | |||
63 | /* Create local copies of the numbers */ | ||
64 | Dbl_copyfromptr(leftptr,leftp1,leftp2); | ||
65 | Dbl_copyfromptr(rightptr,rightp1,rightp2); | ||
66 | |||
67 | /* A zero "save" helps discover equal operands (for later), * | ||
68 | * and is used in swapping operands (if needed). */ | ||
69 | Dbl_xortointp1(leftp1,rightp1,/*to*/save); | ||
70 | |||
71 | /* | ||
72 | * check first operand for NaN's or infinity | ||
73 | */ | ||
74 | if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT) | ||
75 | { | ||
76 | if (Dbl_iszero_mantissa(leftp1,leftp2)) | ||
77 | { | ||
78 | if (Dbl_isnotnan(rightp1,rightp2)) | ||
79 | { | ||
80 | if (Dbl_isinfinity(rightp1,rightp2) && save!=0) | ||
81 | { | ||
82 | /* | ||
83 | * invalid since operands are opposite signed infinity's | ||
84 | */ | ||
85 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
86 | Set_invalidflag(); | ||
87 | Dbl_makequietnan(resultp1,resultp2); | ||
88 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
89 | return(NOEXCEPTION); | ||
90 | } | ||
91 | /* | ||
92 | * return infinity | ||
93 | */ | ||
94 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
95 | return(NOEXCEPTION); | ||
96 | } | ||
97 | } | ||
98 | else | ||
99 | { | ||
100 | /* | ||
101 | * is NaN; signaling or quiet? | ||
102 | */ | ||
103 | if (Dbl_isone_signaling(leftp1)) | ||
104 | { | ||
105 | /* trap if INVALIDTRAP enabled */ | ||
106 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
107 | /* make NaN quiet */ | ||
108 | Set_invalidflag(); | ||
109 | Dbl_set_quiet(leftp1); | ||
110 | } | ||
111 | /* | ||
112 | * is second operand a signaling NaN? | ||
113 | */ | ||
114 | else if (Dbl_is_signalingnan(rightp1)) | ||
115 | { | ||
116 | /* trap if INVALIDTRAP enabled */ | ||
117 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
118 | /* make NaN quiet */ | ||
119 | Set_invalidflag(); | ||
120 | Dbl_set_quiet(rightp1); | ||
121 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
122 | return(NOEXCEPTION); | ||
123 | } | ||
124 | /* | ||
125 | * return quiet NaN | ||
126 | */ | ||
127 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
128 | return(NOEXCEPTION); | ||
129 | } | ||
130 | } /* End left NaN or Infinity processing */ | ||
131 | /* | ||
132 | * check second operand for NaN's or infinity | ||
133 | */ | ||
134 | if (Dbl_isinfinity_exponent(rightp1)) | ||
135 | { | ||
136 | if (Dbl_iszero_mantissa(rightp1,rightp2)) | ||
137 | { | ||
138 | /* return infinity */ | ||
139 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
140 | return(NOEXCEPTION); | ||
141 | } | ||
142 | /* | ||
143 | * is NaN; signaling or quiet? | ||
144 | */ | ||
145 | if (Dbl_isone_signaling(rightp1)) | ||
146 | { | ||
147 | /* trap if INVALIDTRAP enabled */ | ||
148 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
149 | /* make NaN quiet */ | ||
150 | Set_invalidflag(); | ||
151 | Dbl_set_quiet(rightp1); | ||
152 | } | ||
153 | /* | ||
154 | * return quiet NaN | ||
155 | */ | ||
156 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
157 | return(NOEXCEPTION); | ||
158 | } /* End right NaN or Infinity processing */ | ||
159 | |||
160 | /* Invariant: Must be dealing with finite numbers */ | ||
161 | |||
162 | /* Compare operands by removing the sign */ | ||
163 | Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left); | ||
164 | Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right); | ||
165 | |||
166 | /* sign difference selects add or sub operation. */ | ||
167 | if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right)) | ||
168 | { | ||
169 | /* Set the left operand to the larger one by XOR swap * | ||
170 | * First finish the first word using "save" */ | ||
171 | Dbl_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
172 | Dbl_xorfromintp1(save,leftp1,/*to*/leftp1); | ||
173 | Dbl_swap_lower(leftp2,rightp2); | ||
174 | result_exponent = Dbl_exponent(leftp1); | ||
175 | } | ||
176 | /* Invariant: left is not smaller than right. */ | ||
177 | |||
178 | if((right_exponent = Dbl_exponent(rightp1)) == 0) | ||
179 | { | ||
180 | /* Denormalized operands. First look for zeroes */ | ||
181 | if(Dbl_iszero_mantissa(rightp1,rightp2)) | ||
182 | { | ||
183 | /* right is zero */ | ||
184 | if(Dbl_iszero_exponentmantissa(leftp1,leftp2)) | ||
185 | { | ||
186 | /* Both operands are zeros */ | ||
187 | if(Is_rounding_mode(ROUNDMINUS)) | ||
188 | { | ||
189 | Dbl_or_signs(leftp1,/*with*/rightp1); | ||
190 | } | ||
191 | else | ||
192 | { | ||
193 | Dbl_and_signs(leftp1,/*with*/rightp1); | ||
194 | } | ||
195 | } | ||
196 | else | ||
197 | { | ||
198 | /* Left is not a zero and must be the result. Trapped | ||
199 | * underflows are signaled if left is denormalized. Result | ||
200 | * is always exact. */ | ||
201 | if( (result_exponent == 0) && Is_underflowtrap_enabled() ) | ||
202 | { | ||
203 | /* need to normalize results mantissa */ | ||
204 | sign_save = Dbl_signextendedsign(leftp1); | ||
205 | Dbl_leftshiftby1(leftp1,leftp2); | ||
206 | Dbl_normalize(leftp1,leftp2,result_exponent); | ||
207 | Dbl_set_sign(leftp1,/*using*/sign_save); | ||
208 | Dbl_setwrapped_exponent(leftp1,result_exponent,unfl); | ||
209 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
210 | /* inexact = FALSE */ | ||
211 | return(UNDERFLOWEXCEPTION); | ||
212 | } | ||
213 | } | ||
214 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
215 | return(NOEXCEPTION); | ||
216 | } | ||
217 | |||
218 | /* Neither are zeroes */ | ||
219 | Dbl_clear_sign(rightp1); /* Exponent is already cleared */ | ||
220 | if(result_exponent == 0 ) | ||
221 | { | ||
222 | /* Both operands are denormalized. The result must be exact | ||
223 | * and is simply calculated. A sum could become normalized and a | ||
224 | * difference could cancel to a true zero. */ | ||
225 | if( (/*signed*/int) save < 0 ) | ||
226 | { | ||
227 | Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2, | ||
228 | /*into*/resultp1,resultp2); | ||
229 | if(Dbl_iszero_mantissa(resultp1,resultp2)) | ||
230 | { | ||
231 | if(Is_rounding_mode(ROUNDMINUS)) | ||
232 | { | ||
233 | Dbl_setone_sign(resultp1); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | Dbl_setzero_sign(resultp1); | ||
238 | } | ||
239 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
240 | return(NOEXCEPTION); | ||
241 | } | ||
242 | } | ||
243 | else | ||
244 | { | ||
245 | Dbl_addition(leftp1,leftp2,rightp1,rightp2, | ||
246 | /*into*/resultp1,resultp2); | ||
247 | if(Dbl_isone_hidden(resultp1)) | ||
248 | { | ||
249 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
250 | return(NOEXCEPTION); | ||
251 | } | ||
252 | } | ||
253 | if(Is_underflowtrap_enabled()) | ||
254 | { | ||
255 | /* need to normalize result */ | ||
256 | sign_save = Dbl_signextendedsign(resultp1); | ||
257 | Dbl_leftshiftby1(resultp1,resultp2); | ||
258 | Dbl_normalize(resultp1,resultp2,result_exponent); | ||
259 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
260 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
261 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
262 | /* inexact = FALSE */ | ||
263 | return(UNDERFLOWEXCEPTION); | ||
264 | } | ||
265 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
266 | return(NOEXCEPTION); | ||
267 | } | ||
268 | right_exponent = 1; /* Set exponent to reflect different bias | ||
269 | * with denomalized numbers. */ | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | Dbl_clear_signexponent_set_hidden(rightp1); | ||
274 | } | ||
275 | Dbl_clear_exponent_set_hidden(leftp1); | ||
276 | diff_exponent = result_exponent - right_exponent; | ||
277 | |||
278 | /* | ||
279 | * Special case alignment of operands that would force alignment | ||
280 | * beyond the extent of the extension. A further optimization | ||
281 | * could special case this but only reduces the path length for this | ||
282 | * infrequent case. | ||
283 | */ | ||
284 | if(diff_exponent > DBL_THRESHOLD) | ||
285 | { | ||
286 | diff_exponent = DBL_THRESHOLD; | ||
287 | } | ||
288 | |||
289 | /* Align right operand by shifting to right */ | ||
290 | Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent, | ||
291 | /*and lower to*/extent); | ||
292 | |||
293 | /* Treat sum and difference of the operands separately. */ | ||
294 | if( (/*signed*/int) save < 0 ) | ||
295 | { | ||
296 | /* | ||
297 | * Difference of the two operands. Their can be no overflow. A | ||
298 | * borrow can occur out of the hidden bit and force a post | ||
299 | * normalization phase. | ||
300 | */ | ||
301 | Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2, | ||
302 | /*with*/extent,/*into*/resultp1,resultp2); | ||
303 | if(Dbl_iszero_hidden(resultp1)) | ||
304 | { | ||
305 | /* Handle normalization */ | ||
306 | /* A straight foward algorithm would now shift the result | ||
307 | * and extension left until the hidden bit becomes one. Not | ||
308 | * all of the extension bits need participate in the shift. | ||
309 | * Only the two most significant bits (round and guard) are | ||
310 | * needed. If only a single shift is needed then the guard | ||
311 | * bit becomes a significant low order bit and the extension | ||
312 | * must participate in the rounding. If more than a single | ||
313 | * shift is needed, then all bits to the right of the guard | ||
314 | * bit are zeros, and the guard bit may or may not be zero. */ | ||
315 | sign_save = Dbl_signextendedsign(resultp1); | ||
316 | Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2); | ||
317 | |||
318 | /* Need to check for a zero result. The sign and exponent | ||
319 | * fields have already been zeroed. The more efficient test | ||
320 | * of the full object can be used. | ||
321 | */ | ||
322 | if(Dbl_iszero(resultp1,resultp2)) | ||
323 | /* Must have been "x-x" or "x+(-x)". */ | ||
324 | { | ||
325 | if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1); | ||
326 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
327 | return(NOEXCEPTION); | ||
328 | } | ||
329 | result_exponent--; | ||
330 | /* Look to see if normalization is finished. */ | ||
331 | if(Dbl_isone_hidden(resultp1)) | ||
332 | { | ||
333 | if(result_exponent==0) | ||
334 | { | ||
335 | /* Denormalized, exponent should be zero. Left operand * | ||
336 | * was normalized, so extent (guard, round) was zero */ | ||
337 | goto underflow; | ||
338 | } | ||
339 | else | ||
340 | { | ||
341 | /* No further normalization is needed. */ | ||
342 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
343 | Ext_leftshiftby1(extent); | ||
344 | goto round; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | /* Check for denormalized, exponent should be zero. Left * | ||
349 | * operand was normalized, so extent (guard, round) was zero */ | ||
350 | if(!(underflowtrap = Is_underflowtrap_enabled()) && | ||
351 | result_exponent==0) goto underflow; | ||
352 | |||
353 | /* Shift extension to complete one bit of normalization and | ||
354 | * update exponent. */ | ||
355 | Ext_leftshiftby1(extent); | ||
356 | |||
357 | /* Discover first one bit to determine shift amount. Use a | ||
358 | * modified binary search. We have already shifted the result | ||
359 | * one position right and still not found a one so the remainder | ||
360 | * of the extension must be zero and simplifies rounding. */ | ||
361 | /* Scan bytes */ | ||
362 | while(Dbl_iszero_hiddenhigh7mantissa(resultp1)) | ||
363 | { | ||
364 | Dbl_leftshiftby8(resultp1,resultp2); | ||
365 | if((result_exponent -= 8) <= 0 && !underflowtrap) | ||
366 | goto underflow; | ||
367 | } | ||
368 | /* Now narrow it down to the nibble */ | ||
369 | if(Dbl_iszero_hiddenhigh3mantissa(resultp1)) | ||
370 | { | ||
371 | /* The lower nibble contains the normalizing one */ | ||
372 | Dbl_leftshiftby4(resultp1,resultp2); | ||
373 | if((result_exponent -= 4) <= 0 && !underflowtrap) | ||
374 | goto underflow; | ||
375 | } | ||
376 | /* Select case were first bit is set (already normalized) | ||
377 | * otherwise select the proper shift. */ | ||
378 | if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7) | ||
379 | { | ||
380 | /* Already normalized */ | ||
381 | if(result_exponent <= 0) goto underflow; | ||
382 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
383 | Dbl_set_exponent(resultp1,/*using*/result_exponent); | ||
384 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
385 | return(NOEXCEPTION); | ||
386 | } | ||
387 | Dbl_sethigh4bits(resultp1,/*using*/sign_save); | ||
388 | switch(jumpsize) | ||
389 | { | ||
390 | case 1: | ||
391 | { | ||
392 | Dbl_leftshiftby3(resultp1,resultp2); | ||
393 | result_exponent -= 3; | ||
394 | break; | ||
395 | } | ||
396 | case 2: | ||
397 | case 3: | ||
398 | { | ||
399 | Dbl_leftshiftby2(resultp1,resultp2); | ||
400 | result_exponent -= 2; | ||
401 | break; | ||
402 | } | ||
403 | case 4: | ||
404 | case 5: | ||
405 | case 6: | ||
406 | case 7: | ||
407 | { | ||
408 | Dbl_leftshiftby1(resultp1,resultp2); | ||
409 | result_exponent -= 1; | ||
410 | break; | ||
411 | } | ||
412 | } | ||
413 | if(result_exponent > 0) | ||
414 | { | ||
415 | Dbl_set_exponent(resultp1,/*using*/result_exponent); | ||
416 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
417 | return(NOEXCEPTION); /* Sign bit is already set */ | ||
418 | } | ||
419 | /* Fixup potential underflows */ | ||
420 | underflow: | ||
421 | if(Is_underflowtrap_enabled()) | ||
422 | { | ||
423 | Dbl_set_sign(resultp1,sign_save); | ||
424 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
425 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
426 | /* inexact = FALSE */ | ||
427 | return(UNDERFLOWEXCEPTION); | ||
428 | } | ||
429 | /* | ||
430 | * Since we cannot get an inexact denormalized result, | ||
431 | * we can now return. | ||
432 | */ | ||
433 | Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent); | ||
434 | Dbl_clear_signexponent(resultp1); | ||
435 | Dbl_set_sign(resultp1,sign_save); | ||
436 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
437 | return(NOEXCEPTION); | ||
438 | } /* end if(hidden...)... */ | ||
439 | /* Fall through and round */ | ||
440 | } /* end if(save < 0)... */ | ||
441 | else | ||
442 | { | ||
443 | /* Add magnitudes */ | ||
444 | Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2); | ||
445 | if(Dbl_isone_hiddenoverflow(resultp1)) | ||
446 | { | ||
447 | /* Prenormalization required. */ | ||
448 | Dbl_rightshiftby1_withextent(resultp2,extent,extent); | ||
449 | Dbl_arithrightshiftby1(resultp1,resultp2); | ||
450 | result_exponent++; | ||
451 | } /* end if hiddenoverflow... */ | ||
452 | } /* end else ...add magnitudes... */ | ||
453 | |||
454 | /* Round the result. If the extension is all zeros,then the result is | ||
455 | * exact. Otherwise round in the correct direction. No underflow is | ||
456 | * possible. If a postnormalization is necessary, then the mantissa is | ||
457 | * all zeros so no shift is needed. */ | ||
458 | round: | ||
459 | if(Ext_isnotzero(extent)) | ||
460 | { | ||
461 | inexact = TRUE; | ||
462 | switch(Rounding_mode()) | ||
463 | { | ||
464 | case ROUNDNEAREST: /* The default. */ | ||
465 | if(Ext_isone_sign(extent)) | ||
466 | { | ||
467 | /* at least 1/2 ulp */ | ||
468 | if(Ext_isnotzero_lower(extent) || | ||
469 | Dbl_isone_lowmantissap2(resultp2)) | ||
470 | { | ||
471 | /* either exactly half way and odd or more than 1/2ulp */ | ||
472 | Dbl_increment(resultp1,resultp2); | ||
473 | } | ||
474 | } | ||
475 | break; | ||
476 | |||
477 | case ROUNDPLUS: | ||
478 | if(Dbl_iszero_sign(resultp1)) | ||
479 | { | ||
480 | /* Round up positive results */ | ||
481 | Dbl_increment(resultp1,resultp2); | ||
482 | } | ||
483 | break; | ||
484 | |||
485 | case ROUNDMINUS: | ||
486 | if(Dbl_isone_sign(resultp1)) | ||
487 | { | ||
488 | /* Round down negative results */ | ||
489 | Dbl_increment(resultp1,resultp2); | ||
490 | } | ||
491 | |||
492 | case ROUNDZERO:; | ||
493 | /* truncate is simple */ | ||
494 | } /* end switch... */ | ||
495 | if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
496 | } | ||
497 | if(result_exponent == DBL_INFINITY_EXPONENT) | ||
498 | { | ||
499 | /* Overflow */ | ||
500 | if(Is_overflowtrap_enabled()) | ||
501 | { | ||
502 | Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
503 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
504 | if (inexact) | ||
505 | if (Is_inexacttrap_enabled()) | ||
506 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
507 | else Set_inexactflag(); | ||
508 | return(OVERFLOWEXCEPTION); | ||
509 | } | ||
510 | else | ||
511 | { | ||
512 | inexact = TRUE; | ||
513 | Set_overflowflag(); | ||
514 | Dbl_setoverflow(resultp1,resultp2); | ||
515 | } | ||
516 | } | ||
517 | else Dbl_set_exponent(resultp1,result_exponent); | ||
518 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
519 | if(inexact) | ||
520 | if(Is_inexacttrap_enabled()) | ||
521 | return(INEXACTEXCEPTION); | ||
522 | else Set_inexactflag(); | ||
523 | return(NOEXCEPTION); | ||
524 | } | ||
diff --git a/arch/parisc/math-emu/dfcmp.c b/arch/parisc/math-emu/dfcmp.c new file mode 100644 index 000000000000..59521267ffcc --- /dev/null +++ b/arch/parisc/math-emu/dfcmp.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/dfcmp.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * dbl_cmp: compare two values | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_fcmp(leftptr, rightptr, cond, status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | |||
43 | #include "float.h" | ||
44 | #include "dbl_float.h" | ||
45 | |||
46 | /* | ||
47 | * dbl_cmp: compare two values | ||
48 | */ | ||
49 | int | ||
50 | dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr, | ||
51 | unsigned int cond, unsigned int *status) | ||
52 | |||
53 | /* The predicate to be tested */ | ||
54 | |||
55 | { | ||
56 | register unsigned int leftp1, leftp2, rightp1, rightp2; | ||
57 | register int xorresult; | ||
58 | |||
59 | /* Create local copies of the numbers */ | ||
60 | Dbl_copyfromptr(leftptr,leftp1,leftp2); | ||
61 | Dbl_copyfromptr(rightptr,rightp1,rightp2); | ||
62 | /* | ||
63 | * Test for NaN | ||
64 | */ | ||
65 | if( (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) | ||
66 | || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) ) | ||
67 | { | ||
68 | /* Check if a NaN is involved. Signal an invalid exception when | ||
69 | * comparing a signaling NaN or when comparing quiet NaNs and the | ||
70 | * low bit of the condition is set */ | ||
71 | if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) | ||
72 | && Dbl_isnotzero_mantissa(leftp1,leftp2) | ||
73 | && (Exception(cond) || Dbl_isone_signaling(leftp1))) | ||
74 | || | ||
75 | ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) | ||
76 | && Dbl_isnotzero_mantissa(rightp1,rightp2) | ||
77 | && (Exception(cond) || Dbl_isone_signaling(rightp1))) ) | ||
78 | { | ||
79 | if( Is_invalidtrap_enabled() ) { | ||
80 | Set_status_cbit(Unordered(cond)); | ||
81 | return(INVALIDEXCEPTION); | ||
82 | } | ||
83 | else Set_invalidflag(); | ||
84 | Set_status_cbit(Unordered(cond)); | ||
85 | return(NOEXCEPTION); | ||
86 | } | ||
87 | /* All the exceptional conditions are handled, now special case | ||
88 | NaN compares */ | ||
89 | else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) | ||
90 | && Dbl_isnotzero_mantissa(leftp1,leftp2)) | ||
91 | || | ||
92 | ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) | ||
93 | && Dbl_isnotzero_mantissa(rightp1,rightp2)) ) | ||
94 | { | ||
95 | /* NaNs always compare unordered. */ | ||
96 | Set_status_cbit(Unordered(cond)); | ||
97 | return(NOEXCEPTION); | ||
98 | } | ||
99 | /* infinities will drop down to the normal compare mechanisms */ | ||
100 | } | ||
101 | /* First compare for unequal signs => less or greater or | ||
102 | * special equal case */ | ||
103 | Dbl_xortointp1(leftp1,rightp1,xorresult); | ||
104 | if( xorresult < 0 ) | ||
105 | { | ||
106 | /* left negative => less, left positive => greater. | ||
107 | * equal is possible if both operands are zeros. */ | ||
108 | if( Dbl_iszero_exponentmantissa(leftp1,leftp2) | ||
109 | && Dbl_iszero_exponentmantissa(rightp1,rightp2) ) | ||
110 | { | ||
111 | Set_status_cbit(Equal(cond)); | ||
112 | } | ||
113 | else if( Dbl_isone_sign(leftp1) ) | ||
114 | { | ||
115 | Set_status_cbit(Lessthan(cond)); | ||
116 | } | ||
117 | else | ||
118 | { | ||
119 | Set_status_cbit(Greaterthan(cond)); | ||
120 | } | ||
121 | } | ||
122 | /* Signs are the same. Treat negative numbers separately | ||
123 | * from the positives because of the reversed sense. */ | ||
124 | else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2)) | ||
125 | { | ||
126 | Set_status_cbit(Equal(cond)); | ||
127 | } | ||
128 | else if( Dbl_iszero_sign(leftp1) ) | ||
129 | { | ||
130 | /* Positive compare */ | ||
131 | if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) ) | ||
132 | { | ||
133 | Set_status_cbit(Lessthan(cond)); | ||
134 | } | ||
135 | else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) ) | ||
136 | { | ||
137 | Set_status_cbit(Greaterthan(cond)); | ||
138 | } | ||
139 | else | ||
140 | { | ||
141 | /* Equal first parts. Now we must use unsigned compares to | ||
142 | * resolve the two possibilities. */ | ||
143 | if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) ) | ||
144 | { | ||
145 | Set_status_cbit(Lessthan(cond)); | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | Set_status_cbit(Greaterthan(cond)); | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | /* Negative compare. Signed or unsigned compares | ||
156 | * both work the same. That distinction is only | ||
157 | * important when the sign bits differ. */ | ||
158 | if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) ) | ||
159 | { | ||
160 | Set_status_cbit(Lessthan(cond)); | ||
161 | } | ||
162 | else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) ) | ||
163 | { | ||
164 | Set_status_cbit(Greaterthan(cond)); | ||
165 | } | ||
166 | else | ||
167 | { | ||
168 | /* Equal first parts. Now we must use unsigned compares to | ||
169 | * resolve the two possibilities. */ | ||
170 | if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) ) | ||
171 | { | ||
172 | Set_status_cbit(Lessthan(cond)); | ||
173 | } | ||
174 | else | ||
175 | { | ||
176 | Set_status_cbit(Greaterthan(cond)); | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | return(NOEXCEPTION); | ||
181 | } | ||
diff --git a/arch/parisc/math-emu/dfdiv.c b/arch/parisc/math-emu/dfdiv.c new file mode 100644 index 000000000000..d7d4bec0e76f --- /dev/null +++ b/arch/parisc/math-emu/dfdiv.c | |||
@@ -0,0 +1,400 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/dfdiv.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Double Precision Floating-point Divide | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_fdiv(srcptr1,srcptr2,dstptr,status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "dbl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Double Precision Floating-point Divide | ||
47 | */ | ||
48 | |||
49 | int | ||
50 | dbl_fdiv (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2, | ||
51 | dbl_floating_point * dstptr, unsigned int *status) | ||
52 | { | ||
53 | register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; | ||
54 | register unsigned int opnd3p1, opnd3p2, resultp1, resultp2; | ||
55 | register int dest_exponent, count; | ||
56 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
57 | boolean is_tiny; | ||
58 | |||
59 | Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); | ||
60 | Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); | ||
61 | /* | ||
62 | * set sign bit of result | ||
63 | */ | ||
64 | if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) | ||
65 | Dbl_setnegativezerop1(resultp1); | ||
66 | else Dbl_setzerop1(resultp1); | ||
67 | /* | ||
68 | * check first operand for NaN's or infinity | ||
69 | */ | ||
70 | if (Dbl_isinfinity_exponent(opnd1p1)) { | ||
71 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
72 | if (Dbl_isnotnan(opnd2p1,opnd2p2)) { | ||
73 | if (Dbl_isinfinity(opnd2p1,opnd2p2)) { | ||
74 | /* | ||
75 | * invalid since both operands | ||
76 | * are infinity | ||
77 | */ | ||
78 | if (Is_invalidtrap_enabled()) | ||
79 | return(INVALIDEXCEPTION); | ||
80 | Set_invalidflag(); | ||
81 | Dbl_makequietnan(resultp1,resultp2); | ||
82 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
83 | return(NOEXCEPTION); | ||
84 | } | ||
85 | /* | ||
86 | * return infinity | ||
87 | */ | ||
88 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
89 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
90 | return(NOEXCEPTION); | ||
91 | } | ||
92 | } | ||
93 | else { | ||
94 | /* | ||
95 | * is NaN; signaling or quiet? | ||
96 | */ | ||
97 | if (Dbl_isone_signaling(opnd1p1)) { | ||
98 | /* trap if INVALIDTRAP enabled */ | ||
99 | if (Is_invalidtrap_enabled()) | ||
100 | return(INVALIDEXCEPTION); | ||
101 | /* make NaN quiet */ | ||
102 | Set_invalidflag(); | ||
103 | Dbl_set_quiet(opnd1p1); | ||
104 | } | ||
105 | /* | ||
106 | * is second operand a signaling NaN? | ||
107 | */ | ||
108 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
109 | /* trap if INVALIDTRAP enabled */ | ||
110 | if (Is_invalidtrap_enabled()) | ||
111 | return(INVALIDEXCEPTION); | ||
112 | /* make NaN quiet */ | ||
113 | Set_invalidflag(); | ||
114 | Dbl_set_quiet(opnd2p1); | ||
115 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
116 | return(NOEXCEPTION); | ||
117 | } | ||
118 | /* | ||
119 | * return quiet NaN | ||
120 | */ | ||
121 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
122 | return(NOEXCEPTION); | ||
123 | } | ||
124 | } | ||
125 | /* | ||
126 | * check second operand for NaN's or infinity | ||
127 | */ | ||
128 | if (Dbl_isinfinity_exponent(opnd2p1)) { | ||
129 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
130 | /* | ||
131 | * return zero | ||
132 | */ | ||
133 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
134 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
135 | return(NOEXCEPTION); | ||
136 | } | ||
137 | /* | ||
138 | * is NaN; signaling or quiet? | ||
139 | */ | ||
140 | if (Dbl_isone_signaling(opnd2p1)) { | ||
141 | /* trap if INVALIDTRAP enabled */ | ||
142 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
143 | /* make NaN quiet */ | ||
144 | Set_invalidflag(); | ||
145 | Dbl_set_quiet(opnd2p1); | ||
146 | } | ||
147 | /* | ||
148 | * return quiet NaN | ||
149 | */ | ||
150 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
151 | return(NOEXCEPTION); | ||
152 | } | ||
153 | /* | ||
154 | * check for division by zero | ||
155 | */ | ||
156 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
157 | if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { | ||
158 | /* invalid since both operands are zero */ | ||
159 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
160 | Set_invalidflag(); | ||
161 | Dbl_makequietnan(resultp1,resultp2); | ||
162 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
163 | return(NOEXCEPTION); | ||
164 | } | ||
165 | if (Is_divisionbyzerotrap_enabled()) | ||
166 | return(DIVISIONBYZEROEXCEPTION); | ||
167 | Set_divisionbyzeroflag(); | ||
168 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
169 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
170 | return(NOEXCEPTION); | ||
171 | } | ||
172 | /* | ||
173 | * Generate exponent | ||
174 | */ | ||
175 | dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS; | ||
176 | |||
177 | /* | ||
178 | * Generate mantissa | ||
179 | */ | ||
180 | if (Dbl_isnotzero_exponent(opnd1p1)) { | ||
181 | /* set hidden bit */ | ||
182 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
183 | } | ||
184 | else { | ||
185 | /* check for zero */ | ||
186 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
187 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
188 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
189 | return(NOEXCEPTION); | ||
190 | } | ||
191 | /* is denormalized, want to normalize */ | ||
192 | Dbl_clear_signexponent(opnd1p1); | ||
193 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
194 | Dbl_normalize(opnd1p1,opnd1p2,dest_exponent); | ||
195 | } | ||
196 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
197 | if (Dbl_isnotzero_exponent(opnd2p1)) { | ||
198 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
199 | } | ||
200 | else { | ||
201 | /* is denormalized; want to normalize */ | ||
202 | Dbl_clear_signexponent(opnd2p1); | ||
203 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
204 | while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) { | ||
205 | dest_exponent+=8; | ||
206 | Dbl_leftshiftby8(opnd2p1,opnd2p2); | ||
207 | } | ||
208 | if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) { | ||
209 | dest_exponent+=4; | ||
210 | Dbl_leftshiftby4(opnd2p1,opnd2p2); | ||
211 | } | ||
212 | while (Dbl_iszero_hidden(opnd2p1)) { | ||
213 | dest_exponent++; | ||
214 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | /* Divide the source mantissas */ | ||
219 | |||
220 | /* | ||
221 | * A non-restoring divide algorithm is used. | ||
222 | */ | ||
223 | Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); | ||
224 | Dbl_setzero(opnd3p1,opnd3p2); | ||
225 | for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) { | ||
226 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
227 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
228 | if (Dbl_iszero_sign(opnd1p1)) { | ||
229 | Dbl_setone_lowmantissap2(opnd3p2); | ||
230 | Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); | ||
231 | } | ||
232 | else { | ||
233 | Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2); | ||
234 | } | ||
235 | } | ||
236 | if (count <= DBL_P) { | ||
237 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
238 | Dbl_setone_lowmantissap2(opnd3p2); | ||
239 | Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count)); | ||
240 | if (Dbl_iszero_hidden(opnd3p1)) { | ||
241 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
242 | dest_exponent--; | ||
243 | } | ||
244 | } | ||
245 | else { | ||
246 | if (Dbl_iszero_hidden(opnd3p1)) { | ||
247 | /* need to get one more bit of result */ | ||
248 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
249 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
250 | if (Dbl_iszero_sign(opnd1p1)) { | ||
251 | Dbl_setone_lowmantissap2(opnd3p2); | ||
252 | Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); | ||
253 | } | ||
254 | else { | ||
255 | Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2); | ||
256 | } | ||
257 | dest_exponent--; | ||
258 | } | ||
259 | if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE; | ||
260 | stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2); | ||
261 | } | ||
262 | inexact = guardbit | stickybit; | ||
263 | |||
264 | /* | ||
265 | * round result | ||
266 | */ | ||
267 | if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) { | ||
268 | Dbl_clear_signexponent(opnd3p1); | ||
269 | switch (Rounding_mode()) { | ||
270 | case ROUNDPLUS: | ||
271 | if (Dbl_iszero_sign(resultp1)) | ||
272 | Dbl_increment(opnd3p1,opnd3p2); | ||
273 | break; | ||
274 | case ROUNDMINUS: | ||
275 | if (Dbl_isone_sign(resultp1)) | ||
276 | Dbl_increment(opnd3p1,opnd3p2); | ||
277 | break; | ||
278 | case ROUNDNEAREST: | ||
279 | if (guardbit && (stickybit || | ||
280 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
281 | Dbl_increment(opnd3p1,opnd3p2); | ||
282 | } | ||
283 | } | ||
284 | if (Dbl_isone_hidden(opnd3p1)) dest_exponent++; | ||
285 | } | ||
286 | Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2); | ||
287 | |||
288 | /* | ||
289 | * Test for overflow | ||
290 | */ | ||
291 | if (dest_exponent >= DBL_INFINITY_EXPONENT) { | ||
292 | /* trap if OVERFLOWTRAP enabled */ | ||
293 | if (Is_overflowtrap_enabled()) { | ||
294 | /* | ||
295 | * Adjust bias of result | ||
296 | */ | ||
297 | Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl); | ||
298 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
299 | if (inexact) | ||
300 | if (Is_inexacttrap_enabled()) | ||
301 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
302 | else Set_inexactflag(); | ||
303 | return(OVERFLOWEXCEPTION); | ||
304 | } | ||
305 | Set_overflowflag(); | ||
306 | /* set result to infinity or largest number */ | ||
307 | Dbl_setoverflow(resultp1,resultp2); | ||
308 | inexact = TRUE; | ||
309 | } | ||
310 | /* | ||
311 | * Test for underflow | ||
312 | */ | ||
313 | else if (dest_exponent <= 0) { | ||
314 | /* trap if UNDERFLOWTRAP enabled */ | ||
315 | if (Is_underflowtrap_enabled()) { | ||
316 | /* | ||
317 | * Adjust bias of result | ||
318 | */ | ||
319 | Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); | ||
320 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
321 | if (inexact) | ||
322 | if (Is_inexacttrap_enabled()) | ||
323 | return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
324 | else Set_inexactflag(); | ||
325 | return(UNDERFLOWEXCEPTION); | ||
326 | } | ||
327 | |||
328 | /* Determine if should set underflow flag */ | ||
329 | is_tiny = TRUE; | ||
330 | if (dest_exponent == 0 && inexact) { | ||
331 | switch (Rounding_mode()) { | ||
332 | case ROUNDPLUS: | ||
333 | if (Dbl_iszero_sign(resultp1)) { | ||
334 | Dbl_increment(opnd3p1,opnd3p2); | ||
335 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
336 | is_tiny = FALSE; | ||
337 | Dbl_decrement(opnd3p1,opnd3p2); | ||
338 | } | ||
339 | break; | ||
340 | case ROUNDMINUS: | ||
341 | if (Dbl_isone_sign(resultp1)) { | ||
342 | Dbl_increment(opnd3p1,opnd3p2); | ||
343 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
344 | is_tiny = FALSE; | ||
345 | Dbl_decrement(opnd3p1,opnd3p2); | ||
346 | } | ||
347 | break; | ||
348 | case ROUNDNEAREST: | ||
349 | if (guardbit && (stickybit || | ||
350 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
351 | Dbl_increment(opnd3p1,opnd3p2); | ||
352 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
353 | is_tiny = FALSE; | ||
354 | Dbl_decrement(opnd3p1,opnd3p2); | ||
355 | } | ||
356 | break; | ||
357 | } | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * denormalize result or set to signed zero | ||
362 | */ | ||
363 | stickybit = inexact; | ||
364 | Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit, | ||
365 | stickybit,inexact); | ||
366 | |||
367 | /* return rounded number */ | ||
368 | if (inexact) { | ||
369 | switch (Rounding_mode()) { | ||
370 | case ROUNDPLUS: | ||
371 | if (Dbl_iszero_sign(resultp1)) { | ||
372 | Dbl_increment(opnd3p1,opnd3p2); | ||
373 | } | ||
374 | break; | ||
375 | case ROUNDMINUS: | ||
376 | if (Dbl_isone_sign(resultp1)) { | ||
377 | Dbl_increment(opnd3p1,opnd3p2); | ||
378 | } | ||
379 | break; | ||
380 | case ROUNDNEAREST: | ||
381 | if (guardbit && (stickybit || | ||
382 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
383 | Dbl_increment(opnd3p1,opnd3p2); | ||
384 | } | ||
385 | break; | ||
386 | } | ||
387 | if (is_tiny) Set_underflowflag(); | ||
388 | } | ||
389 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2); | ||
390 | } | ||
391 | else Dbl_set_exponent(resultp1,dest_exponent); | ||
392 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
393 | |||
394 | /* check for inexact */ | ||
395 | if (inexact) { | ||
396 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
397 | else Set_inexactflag(); | ||
398 | } | ||
399 | return(NOEXCEPTION); | ||
400 | } | ||
diff --git a/arch/parisc/math-emu/dfmpy.c b/arch/parisc/math-emu/dfmpy.c new file mode 100644 index 000000000000..4380f5a62ad1 --- /dev/null +++ b/arch/parisc/math-emu/dfmpy.c | |||
@@ -0,0 +1,394 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/dfmpy.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Double Precision Floating-point Multiply | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_fmpy(srcptr1,srcptr2,dstptr,status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "dbl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Double Precision Floating-point Multiply | ||
47 | */ | ||
48 | |||
49 | int | ||
50 | dbl_fmpy( | ||
51 | dbl_floating_point *srcptr1, | ||
52 | dbl_floating_point *srcptr2, | ||
53 | dbl_floating_point *dstptr, | ||
54 | unsigned int *status) | ||
55 | { | ||
56 | register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; | ||
57 | register unsigned int opnd3p1, opnd3p2, resultp1, resultp2; | ||
58 | register int dest_exponent, count; | ||
59 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
60 | boolean is_tiny; | ||
61 | |||
62 | Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); | ||
63 | Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); | ||
64 | |||
65 | /* | ||
66 | * set sign bit of result | ||
67 | */ | ||
68 | if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) | ||
69 | Dbl_setnegativezerop1(resultp1); | ||
70 | else Dbl_setzerop1(resultp1); | ||
71 | /* | ||
72 | * check first operand for NaN's or infinity | ||
73 | */ | ||
74 | if (Dbl_isinfinity_exponent(opnd1p1)) { | ||
75 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
76 | if (Dbl_isnotnan(opnd2p1,opnd2p2)) { | ||
77 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
78 | /* | ||
79 | * invalid since operands are infinity | ||
80 | * and zero | ||
81 | */ | ||
82 | if (Is_invalidtrap_enabled()) | ||
83 | return(INVALIDEXCEPTION); | ||
84 | Set_invalidflag(); | ||
85 | Dbl_makequietnan(resultp1,resultp2); | ||
86 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
87 | return(NOEXCEPTION); | ||
88 | } | ||
89 | /* | ||
90 | * return infinity | ||
91 | */ | ||
92 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
93 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
94 | return(NOEXCEPTION); | ||
95 | } | ||
96 | } | ||
97 | else { | ||
98 | /* | ||
99 | * is NaN; signaling or quiet? | ||
100 | */ | ||
101 | if (Dbl_isone_signaling(opnd1p1)) { | ||
102 | /* trap if INVALIDTRAP enabled */ | ||
103 | if (Is_invalidtrap_enabled()) | ||
104 | return(INVALIDEXCEPTION); | ||
105 | /* make NaN quiet */ | ||
106 | Set_invalidflag(); | ||
107 | Dbl_set_quiet(opnd1p1); | ||
108 | } | ||
109 | /* | ||
110 | * is second operand a signaling NaN? | ||
111 | */ | ||
112 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
113 | /* trap if INVALIDTRAP enabled */ | ||
114 | if (Is_invalidtrap_enabled()) | ||
115 | return(INVALIDEXCEPTION); | ||
116 | /* make NaN quiet */ | ||
117 | Set_invalidflag(); | ||
118 | Dbl_set_quiet(opnd2p1); | ||
119 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
120 | return(NOEXCEPTION); | ||
121 | } | ||
122 | /* | ||
123 | * return quiet NaN | ||
124 | */ | ||
125 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
126 | return(NOEXCEPTION); | ||
127 | } | ||
128 | } | ||
129 | /* | ||
130 | * check second operand for NaN's or infinity | ||
131 | */ | ||
132 | if (Dbl_isinfinity_exponent(opnd2p1)) { | ||
133 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
134 | if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { | ||
135 | /* invalid since operands are zero & infinity */ | ||
136 | if (Is_invalidtrap_enabled()) | ||
137 | return(INVALIDEXCEPTION); | ||
138 | Set_invalidflag(); | ||
139 | Dbl_makequietnan(opnd2p1,opnd2p2); | ||
140 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
141 | return(NOEXCEPTION); | ||
142 | } | ||
143 | /* | ||
144 | * return infinity | ||
145 | */ | ||
146 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
147 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
148 | return(NOEXCEPTION); | ||
149 | } | ||
150 | /* | ||
151 | * is NaN; signaling or quiet? | ||
152 | */ | ||
153 | if (Dbl_isone_signaling(opnd2p1)) { | ||
154 | /* trap if INVALIDTRAP enabled */ | ||
155 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
156 | /* make NaN quiet */ | ||
157 | Set_invalidflag(); | ||
158 | Dbl_set_quiet(opnd2p1); | ||
159 | } | ||
160 | /* | ||
161 | * return quiet NaN | ||
162 | */ | ||
163 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
164 | return(NOEXCEPTION); | ||
165 | } | ||
166 | /* | ||
167 | * Generate exponent | ||
168 | */ | ||
169 | dest_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) -DBL_BIAS; | ||
170 | |||
171 | /* | ||
172 | * Generate mantissa | ||
173 | */ | ||
174 | if (Dbl_isnotzero_exponent(opnd1p1)) { | ||
175 | /* set hidden bit */ | ||
176 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
177 | } | ||
178 | else { | ||
179 | /* check for zero */ | ||
180 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
181 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
182 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
183 | return(NOEXCEPTION); | ||
184 | } | ||
185 | /* is denormalized, adjust exponent */ | ||
186 | Dbl_clear_signexponent(opnd1p1); | ||
187 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
188 | Dbl_normalize(opnd1p1,opnd1p2,dest_exponent); | ||
189 | } | ||
190 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
191 | if (Dbl_isnotzero_exponent(opnd2p1)) { | ||
192 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
193 | } | ||
194 | else { | ||
195 | /* check for zero */ | ||
196 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
197 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
198 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
199 | return(NOEXCEPTION); | ||
200 | } | ||
201 | /* is denormalized; want to normalize */ | ||
202 | Dbl_clear_signexponent(opnd2p1); | ||
203 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
204 | Dbl_normalize(opnd2p1,opnd2p2,dest_exponent); | ||
205 | } | ||
206 | |||
207 | /* Multiply two source mantissas together */ | ||
208 | |||
209 | /* make room for guard bits */ | ||
210 | Dbl_leftshiftby7(opnd2p1,opnd2p2); | ||
211 | Dbl_setzero(opnd3p1,opnd3p2); | ||
212 | /* | ||
213 | * Four bits at a time are inspected in each loop, and a | ||
214 | * simple shift and add multiply algorithm is used. | ||
215 | */ | ||
216 | for (count=1;count<=DBL_P;count+=4) { | ||
217 | stickybit |= Dlow4p2(opnd3p2); | ||
218 | Dbl_rightshiftby4(opnd3p1,opnd3p2); | ||
219 | if (Dbit28p2(opnd1p2)) { | ||
220 | /* Twoword_add should be an ADDC followed by an ADD. */ | ||
221 | Twoword_add(opnd3p1, opnd3p2, opnd2p1<<3 | opnd2p2>>29, | ||
222 | opnd2p2<<3); | ||
223 | } | ||
224 | if (Dbit29p2(opnd1p2)) { | ||
225 | Twoword_add(opnd3p1, opnd3p2, opnd2p1<<2 | opnd2p2>>30, | ||
226 | opnd2p2<<2); | ||
227 | } | ||
228 | if (Dbit30p2(opnd1p2)) { | ||
229 | Twoword_add(opnd3p1, opnd3p2, opnd2p1<<1 | opnd2p2>>31, | ||
230 | opnd2p2<<1); | ||
231 | } | ||
232 | if (Dbit31p2(opnd1p2)) { | ||
233 | Twoword_add(opnd3p1, opnd3p2, opnd2p1, opnd2p2); | ||
234 | } | ||
235 | Dbl_rightshiftby4(opnd1p1,opnd1p2); | ||
236 | } | ||
237 | if (Dbit3p1(opnd3p1)==0) { | ||
238 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
239 | } | ||
240 | else { | ||
241 | /* result mantissa >= 2. */ | ||
242 | dest_exponent++; | ||
243 | } | ||
244 | /* check for denormalized result */ | ||
245 | while (Dbit3p1(opnd3p1)==0) { | ||
246 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
247 | dest_exponent--; | ||
248 | } | ||
249 | /* | ||
250 | * check for guard, sticky and inexact bits | ||
251 | */ | ||
252 | stickybit |= Dallp2(opnd3p2) << 25; | ||
253 | guardbit = (Dallp2(opnd3p2) << 24) >> 31; | ||
254 | inexact = guardbit | stickybit; | ||
255 | |||
256 | /* align result mantissa */ | ||
257 | Dbl_rightshiftby8(opnd3p1,opnd3p2); | ||
258 | |||
259 | /* | ||
260 | * round result | ||
261 | */ | ||
262 | if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) { | ||
263 | Dbl_clear_signexponent(opnd3p1); | ||
264 | switch (Rounding_mode()) { | ||
265 | case ROUNDPLUS: | ||
266 | if (Dbl_iszero_sign(resultp1)) | ||
267 | Dbl_increment(opnd3p1,opnd3p2); | ||
268 | break; | ||
269 | case ROUNDMINUS: | ||
270 | if (Dbl_isone_sign(resultp1)) | ||
271 | Dbl_increment(opnd3p1,opnd3p2); | ||
272 | break; | ||
273 | case ROUNDNEAREST: | ||
274 | if (guardbit) { | ||
275 | if (stickybit || Dbl_isone_lowmantissap2(opnd3p2)) | ||
276 | Dbl_increment(opnd3p1,opnd3p2); | ||
277 | } | ||
278 | } | ||
279 | if (Dbl_isone_hidden(opnd3p1)) dest_exponent++; | ||
280 | } | ||
281 | Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2); | ||
282 | |||
283 | /* | ||
284 | * Test for overflow | ||
285 | */ | ||
286 | if (dest_exponent >= DBL_INFINITY_EXPONENT) { | ||
287 | /* trap if OVERFLOWTRAP enabled */ | ||
288 | if (Is_overflowtrap_enabled()) { | ||
289 | /* | ||
290 | * Adjust bias of result | ||
291 | */ | ||
292 | Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl); | ||
293 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
294 | if (inexact) | ||
295 | if (Is_inexacttrap_enabled()) | ||
296 | return (OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
297 | else Set_inexactflag(); | ||
298 | return (OVERFLOWEXCEPTION); | ||
299 | } | ||
300 | inexact = TRUE; | ||
301 | Set_overflowflag(); | ||
302 | /* set result to infinity or largest number */ | ||
303 | Dbl_setoverflow(resultp1,resultp2); | ||
304 | } | ||
305 | /* | ||
306 | * Test for underflow | ||
307 | */ | ||
308 | else if (dest_exponent <= 0) { | ||
309 | /* trap if UNDERFLOWTRAP enabled */ | ||
310 | if (Is_underflowtrap_enabled()) { | ||
311 | /* | ||
312 | * Adjust bias of result | ||
313 | */ | ||
314 | Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); | ||
315 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
316 | if (inexact) | ||
317 | if (Is_inexacttrap_enabled()) | ||
318 | return (UNDERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
319 | else Set_inexactflag(); | ||
320 | return (UNDERFLOWEXCEPTION); | ||
321 | } | ||
322 | |||
323 | /* Determine if should set underflow flag */ | ||
324 | is_tiny = TRUE; | ||
325 | if (dest_exponent == 0 && inexact) { | ||
326 | switch (Rounding_mode()) { | ||
327 | case ROUNDPLUS: | ||
328 | if (Dbl_iszero_sign(resultp1)) { | ||
329 | Dbl_increment(opnd3p1,opnd3p2); | ||
330 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
331 | is_tiny = FALSE; | ||
332 | Dbl_decrement(opnd3p1,opnd3p2); | ||
333 | } | ||
334 | break; | ||
335 | case ROUNDMINUS: | ||
336 | if (Dbl_isone_sign(resultp1)) { | ||
337 | Dbl_increment(opnd3p1,opnd3p2); | ||
338 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
339 | is_tiny = FALSE; | ||
340 | Dbl_decrement(opnd3p1,opnd3p2); | ||
341 | } | ||
342 | break; | ||
343 | case ROUNDNEAREST: | ||
344 | if (guardbit && (stickybit || | ||
345 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
346 | Dbl_increment(opnd3p1,opnd3p2); | ||
347 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
348 | is_tiny = FALSE; | ||
349 | Dbl_decrement(opnd3p1,opnd3p2); | ||
350 | } | ||
351 | break; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * denormalize result or set to signed zero | ||
357 | */ | ||
358 | stickybit = inexact; | ||
359 | Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit, | ||
360 | stickybit,inexact); | ||
361 | |||
362 | /* return zero or smallest number */ | ||
363 | if (inexact) { | ||
364 | switch (Rounding_mode()) { | ||
365 | case ROUNDPLUS: | ||
366 | if (Dbl_iszero_sign(resultp1)) { | ||
367 | Dbl_increment(opnd3p1,opnd3p2); | ||
368 | } | ||
369 | break; | ||
370 | case ROUNDMINUS: | ||
371 | if (Dbl_isone_sign(resultp1)) { | ||
372 | Dbl_increment(opnd3p1,opnd3p2); | ||
373 | } | ||
374 | break; | ||
375 | case ROUNDNEAREST: | ||
376 | if (guardbit && (stickybit || | ||
377 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
378 | Dbl_increment(opnd3p1,opnd3p2); | ||
379 | } | ||
380 | break; | ||
381 | } | ||
382 | if (is_tiny) Set_underflowflag(); | ||
383 | } | ||
384 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2); | ||
385 | } | ||
386 | else Dbl_set_exponent(resultp1,dest_exponent); | ||
387 | /* check for inexact */ | ||
388 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
389 | if (inexact) { | ||
390 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
391 | else Set_inexactflag(); | ||
392 | } | ||
393 | return(NOEXCEPTION); | ||
394 | } | ||
diff --git a/arch/parisc/math-emu/dfrem.c b/arch/parisc/math-emu/dfrem.c new file mode 100644 index 000000000000..b98378534677 --- /dev/null +++ b/arch/parisc/math-emu/dfrem.c | |||
@@ -0,0 +1,297 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/dfrem.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Double Precision Floating-point Remainder | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_frem(srcptr1,srcptr2,dstptr,status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | |||
43 | #include "float.h" | ||
44 | #include "dbl_float.h" | ||
45 | |||
46 | /* | ||
47 | * Double Precision Floating-point Remainder | ||
48 | */ | ||
49 | |||
50 | int | ||
51 | dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2, | ||
52 | dbl_floating_point * dstptr, unsigned int *status) | ||
53 | { | ||
54 | register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; | ||
55 | register unsigned int resultp1, resultp2; | ||
56 | register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount; | ||
57 | register boolean roundup = FALSE; | ||
58 | |||
59 | Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); | ||
60 | Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); | ||
61 | /* | ||
62 | * check first operand for NaN's or infinity | ||
63 | */ | ||
64 | if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) { | ||
65 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
66 | if (Dbl_isnotnan(opnd2p1,opnd2p2)) { | ||
67 | /* invalid since first operand is infinity */ | ||
68 | if (Is_invalidtrap_enabled()) | ||
69 | return(INVALIDEXCEPTION); | ||
70 | Set_invalidflag(); | ||
71 | Dbl_makequietnan(resultp1,resultp2); | ||
72 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
73 | return(NOEXCEPTION); | ||
74 | } | ||
75 | } | ||
76 | else { | ||
77 | /* | ||
78 | * is NaN; signaling or quiet? | ||
79 | */ | ||
80 | if (Dbl_isone_signaling(opnd1p1)) { | ||
81 | /* trap if INVALIDTRAP enabled */ | ||
82 | if (Is_invalidtrap_enabled()) | ||
83 | return(INVALIDEXCEPTION); | ||
84 | /* make NaN quiet */ | ||
85 | Set_invalidflag(); | ||
86 | Dbl_set_quiet(opnd1p1); | ||
87 | } | ||
88 | /* | ||
89 | * is second operand a signaling NaN? | ||
90 | */ | ||
91 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
92 | /* trap if INVALIDTRAP enabled */ | ||
93 | if (Is_invalidtrap_enabled()) | ||
94 | return(INVALIDEXCEPTION); | ||
95 | /* make NaN quiet */ | ||
96 | Set_invalidflag(); | ||
97 | Dbl_set_quiet(opnd2p1); | ||
98 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
99 | return(NOEXCEPTION); | ||
100 | } | ||
101 | /* | ||
102 | * return quiet NaN | ||
103 | */ | ||
104 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
105 | return(NOEXCEPTION); | ||
106 | } | ||
107 | } | ||
108 | /* | ||
109 | * check second operand for NaN's or infinity | ||
110 | */ | ||
111 | if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) { | ||
112 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
113 | /* | ||
114 | * return first operand | ||
115 | */ | ||
116 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
117 | return(NOEXCEPTION); | ||
118 | } | ||
119 | /* | ||
120 | * is NaN; signaling or quiet? | ||
121 | */ | ||
122 | if (Dbl_isone_signaling(opnd2p1)) { | ||
123 | /* trap if INVALIDTRAP enabled */ | ||
124 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
125 | /* make NaN quiet */ | ||
126 | Set_invalidflag(); | ||
127 | Dbl_set_quiet(opnd2p1); | ||
128 | } | ||
129 | /* | ||
130 | * return quiet NaN | ||
131 | */ | ||
132 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
133 | return(NOEXCEPTION); | ||
134 | } | ||
135 | /* | ||
136 | * check second operand for zero | ||
137 | */ | ||
138 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
139 | /* invalid since second operand is zero */ | ||
140 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
141 | Set_invalidflag(); | ||
142 | Dbl_makequietnan(resultp1,resultp2); | ||
143 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
144 | return(NOEXCEPTION); | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * get sign of result | ||
149 | */ | ||
150 | resultp1 = opnd1p1; | ||
151 | |||
152 | /* | ||
153 | * check for denormalized operands | ||
154 | */ | ||
155 | if (opnd1_exponent == 0) { | ||
156 | /* check for zero */ | ||
157 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
158 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
159 | return(NOEXCEPTION); | ||
160 | } | ||
161 | /* normalize, then continue */ | ||
162 | opnd1_exponent = 1; | ||
163 | Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent); | ||
164 | } | ||
165 | else { | ||
166 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
167 | } | ||
168 | if (opnd2_exponent == 0) { | ||
169 | /* normalize, then continue */ | ||
170 | opnd2_exponent = 1; | ||
171 | Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent); | ||
172 | } | ||
173 | else { | ||
174 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
175 | } | ||
176 | |||
177 | /* find result exponent and divide step loop count */ | ||
178 | dest_exponent = opnd2_exponent - 1; | ||
179 | stepcount = opnd1_exponent - opnd2_exponent; | ||
180 | |||
181 | /* | ||
182 | * check for opnd1/opnd2 < 1 | ||
183 | */ | ||
184 | if (stepcount < 0) { | ||
185 | /* | ||
186 | * check for opnd1/opnd2 > 1/2 | ||
187 | * | ||
188 | * In this case n will round to 1, so | ||
189 | * r = opnd1 - opnd2 | ||
190 | */ | ||
191 | if (stepcount == -1 && | ||
192 | Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { | ||
193 | /* set sign */ | ||
194 | Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1); | ||
195 | /* align opnd2 with opnd1 */ | ||
196 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
197 | Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2, | ||
198 | opnd2p1,opnd2p2); | ||
199 | /* now normalize */ | ||
200 | while (Dbl_iszero_hidden(opnd2p1)) { | ||
201 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
202 | dest_exponent--; | ||
203 | } | ||
204 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2); | ||
205 | goto testforunderflow; | ||
206 | } | ||
207 | /* | ||
208 | * opnd1/opnd2 <= 1/2 | ||
209 | * | ||
210 | * In this case n will round to zero, so | ||
211 | * r = opnd1 | ||
212 | */ | ||
213 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2); | ||
214 | dest_exponent = opnd1_exponent; | ||
215 | goto testforunderflow; | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * Generate result | ||
220 | * | ||
221 | * Do iterative subtract until remainder is less than operand 2. | ||
222 | */ | ||
223 | while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) { | ||
224 | if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { | ||
225 | Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2); | ||
226 | } | ||
227 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
228 | } | ||
229 | /* | ||
230 | * Do last subtract, then determine which way to round if remainder | ||
231 | * is exactly 1/2 of opnd2 | ||
232 | */ | ||
233 | if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { | ||
234 | Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2); | ||
235 | roundup = TRUE; | ||
236 | } | ||
237 | if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) { | ||
238 | /* division is exact, remainder is zero */ | ||
239 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
240 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
241 | return(NOEXCEPTION); | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Check for cases where opnd1/opnd2 < n | ||
246 | * | ||
247 | * In this case the result's sign will be opposite that of | ||
248 | * opnd1. The mantissa also needs some correction. | ||
249 | */ | ||
250 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
251 | if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { | ||
252 | Dbl_invert_sign(resultp1); | ||
253 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
254 | Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2); | ||
255 | } | ||
256 | /* check for remainder being exactly 1/2 of opnd2 */ | ||
257 | else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) { | ||
258 | Dbl_invert_sign(resultp1); | ||
259 | } | ||
260 | |||
261 | /* normalize result's mantissa */ | ||
262 | while (Dbl_iszero_hidden(opnd1p1)) { | ||
263 | dest_exponent--; | ||
264 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
265 | } | ||
266 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2); | ||
267 | |||
268 | /* | ||
269 | * Test for underflow | ||
270 | */ | ||
271 | testforunderflow: | ||
272 | if (dest_exponent <= 0) { | ||
273 | /* trap if UNDERFLOWTRAP enabled */ | ||
274 | if (Is_underflowtrap_enabled()) { | ||
275 | /* | ||
276 | * Adjust bias of result | ||
277 | */ | ||
278 | Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); | ||
279 | /* frem is always exact */ | ||
280 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
281 | return(UNDERFLOWEXCEPTION); | ||
282 | } | ||
283 | /* | ||
284 | * denormalize result or set to signed zero | ||
285 | */ | ||
286 | if (dest_exponent >= (1 - DBL_P)) { | ||
287 | Dbl_rightshift_exponentmantissa(resultp1,resultp2, | ||
288 | 1-dest_exponent); | ||
289 | } | ||
290 | else { | ||
291 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
292 | } | ||
293 | } | ||
294 | else Dbl_set_exponent(resultp1,dest_exponent); | ||
295 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
296 | return(NOEXCEPTION); | ||
297 | } | ||
diff --git a/arch/parisc/math-emu/dfsqrt.c b/arch/parisc/math-emu/dfsqrt.c new file mode 100644 index 000000000000..b6ed1066f1e4 --- /dev/null +++ b/arch/parisc/math-emu/dfsqrt.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/dfsqrt.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Double Floating-point Square Root | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_fsqrt(srcptr,nullptr,dstptr,status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "dbl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Double Floating-point Square Root | ||
47 | */ | ||
48 | |||
49 | /*ARGSUSED*/ | ||
50 | unsigned int | ||
51 | dbl_fsqrt( | ||
52 | dbl_floating_point *srcptr, | ||
53 | unsigned int *nullptr, | ||
54 | dbl_floating_point *dstptr, | ||
55 | unsigned int *status) | ||
56 | { | ||
57 | register unsigned int srcp1, srcp2, resultp1, resultp2; | ||
58 | register unsigned int newbitp1, newbitp2, sump1, sump2; | ||
59 | register int src_exponent; | ||
60 | register boolean guardbit = FALSE, even_exponent; | ||
61 | |||
62 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
63 | /* | ||
64 | * check source operand for NaN or infinity | ||
65 | */ | ||
66 | if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { | ||
67 | /* | ||
68 | * is signaling NaN? | ||
69 | */ | ||
70 | if (Dbl_isone_signaling(srcp1)) { | ||
71 | /* trap if INVALIDTRAP enabled */ | ||
72 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
73 | /* make NaN quiet */ | ||
74 | Set_invalidflag(); | ||
75 | Dbl_set_quiet(srcp1); | ||
76 | } | ||
77 | /* | ||
78 | * Return quiet NaN or positive infinity. | ||
79 | * Fall thru to negative test if negative infinity. | ||
80 | */ | ||
81 | if (Dbl_iszero_sign(srcp1) || | ||
82 | Dbl_isnotzero_mantissa(srcp1,srcp2)) { | ||
83 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
84 | return(NOEXCEPTION); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * check for zero source operand | ||
90 | */ | ||
91 | if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) { | ||
92 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
93 | return(NOEXCEPTION); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * check for negative source operand | ||
98 | */ | ||
99 | if (Dbl_isone_sign(srcp1)) { | ||
100 | /* trap if INVALIDTRAP enabled */ | ||
101 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
102 | /* make NaN quiet */ | ||
103 | Set_invalidflag(); | ||
104 | Dbl_makequietnan(srcp1,srcp2); | ||
105 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
106 | return(NOEXCEPTION); | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Generate result | ||
111 | */ | ||
112 | if (src_exponent > 0) { | ||
113 | even_exponent = Dbl_hidden(srcp1); | ||
114 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
115 | } | ||
116 | else { | ||
117 | /* normalize operand */ | ||
118 | Dbl_clear_signexponent(srcp1); | ||
119 | src_exponent++; | ||
120 | Dbl_normalize(srcp1,srcp2,src_exponent); | ||
121 | even_exponent = src_exponent & 1; | ||
122 | } | ||
123 | if (even_exponent) { | ||
124 | /* exponent is even */ | ||
125 | /* Add comment here. Explain why odd exponent needs correction */ | ||
126 | Dbl_leftshiftby1(srcp1,srcp2); | ||
127 | } | ||
128 | /* | ||
129 | * Add comment here. Explain following algorithm. | ||
130 | * | ||
131 | * Trust me, it works. | ||
132 | * | ||
133 | */ | ||
134 | Dbl_setzero(resultp1,resultp2); | ||
135 | Dbl_allp1(newbitp1) = 1 << (DBL_P - 32); | ||
136 | Dbl_setzero_mantissap2(newbitp2); | ||
137 | while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) { | ||
138 | Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2); | ||
139 | if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) { | ||
140 | Dbl_leftshiftby1(newbitp1,newbitp2); | ||
141 | /* update result */ | ||
142 | Dbl_addition(resultp1,resultp2,newbitp1,newbitp2, | ||
143 | resultp1,resultp2); | ||
144 | Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2); | ||
145 | Dbl_rightshiftby2(newbitp1,newbitp2); | ||
146 | } | ||
147 | else { | ||
148 | Dbl_rightshiftby1(newbitp1,newbitp2); | ||
149 | } | ||
150 | Dbl_leftshiftby1(srcp1,srcp2); | ||
151 | } | ||
152 | /* correct exponent for pre-shift */ | ||
153 | if (even_exponent) { | ||
154 | Dbl_rightshiftby1(resultp1,resultp2); | ||
155 | } | ||
156 | |||
157 | /* check for inexact */ | ||
158 | if (Dbl_isnotzero(srcp1,srcp2)) { | ||
159 | if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) { | ||
160 | Dbl_increment(resultp1,resultp2); | ||
161 | } | ||
162 | guardbit = Dbl_lowmantissap2(resultp2); | ||
163 | Dbl_rightshiftby1(resultp1,resultp2); | ||
164 | |||
165 | /* now round result */ | ||
166 | switch (Rounding_mode()) { | ||
167 | case ROUNDPLUS: | ||
168 | Dbl_increment(resultp1,resultp2); | ||
169 | break; | ||
170 | case ROUNDNEAREST: | ||
171 | /* stickybit is always true, so guardbit | ||
172 | * is enough to determine rounding */ | ||
173 | if (guardbit) { | ||
174 | Dbl_increment(resultp1,resultp2); | ||
175 | } | ||
176 | break; | ||
177 | } | ||
178 | /* increment result exponent by 1 if mantissa overflowed */ | ||
179 | if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2; | ||
180 | |||
181 | if (Is_inexacttrap_enabled()) { | ||
182 | Dbl_set_exponent(resultp1, | ||
183 | ((src_exponent-DBL_BIAS)>>1)+DBL_BIAS); | ||
184 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
185 | return(INEXACTEXCEPTION); | ||
186 | } | ||
187 | else Set_inexactflag(); | ||
188 | } | ||
189 | else { | ||
190 | Dbl_rightshiftby1(resultp1,resultp2); | ||
191 | } | ||
192 | Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS); | ||
193 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
194 | return(NOEXCEPTION); | ||
195 | } | ||
diff --git a/arch/parisc/math-emu/dfsub.c b/arch/parisc/math-emu/dfsub.c new file mode 100644 index 000000000000..87ebc60d465b --- /dev/null +++ b/arch/parisc/math-emu/dfsub.c | |||
@@ -0,0 +1,526 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/dfsub.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Double_subtract: subtract two double precision values. | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_fsub(leftptr, rightptr, dstptr, status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "dbl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Double_subtract: subtract two double precision values. | ||
47 | */ | ||
48 | int | ||
49 | dbl_fsub( | ||
50 | dbl_floating_point *leftptr, | ||
51 | dbl_floating_point *rightptr, | ||
52 | dbl_floating_point *dstptr, | ||
53 | unsigned int *status) | ||
54 | { | ||
55 | register unsigned int signless_upper_left, signless_upper_right, save; | ||
56 | register unsigned int leftp1, leftp2, rightp1, rightp2, extent; | ||
57 | register unsigned int resultp1 = 0, resultp2 = 0; | ||
58 | |||
59 | register int result_exponent, right_exponent, diff_exponent; | ||
60 | register int sign_save, jumpsize; | ||
61 | register boolean inexact = FALSE, underflowtrap; | ||
62 | |||
63 | /* Create local copies of the numbers */ | ||
64 | Dbl_copyfromptr(leftptr,leftp1,leftp2); | ||
65 | Dbl_copyfromptr(rightptr,rightp1,rightp2); | ||
66 | |||
67 | /* A zero "save" helps discover equal operands (for later), * | ||
68 | * and is used in swapping operands (if needed). */ | ||
69 | Dbl_xortointp1(leftp1,rightp1,/*to*/save); | ||
70 | |||
71 | /* | ||
72 | * check first operand for NaN's or infinity | ||
73 | */ | ||
74 | if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT) | ||
75 | { | ||
76 | if (Dbl_iszero_mantissa(leftp1,leftp2)) | ||
77 | { | ||
78 | if (Dbl_isnotnan(rightp1,rightp2)) | ||
79 | { | ||
80 | if (Dbl_isinfinity(rightp1,rightp2) && save==0) | ||
81 | { | ||
82 | /* | ||
83 | * invalid since operands are same signed infinity's | ||
84 | */ | ||
85 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
86 | Set_invalidflag(); | ||
87 | Dbl_makequietnan(resultp1,resultp2); | ||
88 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
89 | return(NOEXCEPTION); | ||
90 | } | ||
91 | /* | ||
92 | * return infinity | ||
93 | */ | ||
94 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
95 | return(NOEXCEPTION); | ||
96 | } | ||
97 | } | ||
98 | else | ||
99 | { | ||
100 | /* | ||
101 | * is NaN; signaling or quiet? | ||
102 | */ | ||
103 | if (Dbl_isone_signaling(leftp1)) | ||
104 | { | ||
105 | /* trap if INVALIDTRAP enabled */ | ||
106 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
107 | /* make NaN quiet */ | ||
108 | Set_invalidflag(); | ||
109 | Dbl_set_quiet(leftp1); | ||
110 | } | ||
111 | /* | ||
112 | * is second operand a signaling NaN? | ||
113 | */ | ||
114 | else if (Dbl_is_signalingnan(rightp1)) | ||
115 | { | ||
116 | /* trap if INVALIDTRAP enabled */ | ||
117 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
118 | /* make NaN quiet */ | ||
119 | Set_invalidflag(); | ||
120 | Dbl_set_quiet(rightp1); | ||
121 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
122 | return(NOEXCEPTION); | ||
123 | } | ||
124 | /* | ||
125 | * return quiet NaN | ||
126 | */ | ||
127 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
128 | return(NOEXCEPTION); | ||
129 | } | ||
130 | } /* End left NaN or Infinity processing */ | ||
131 | /* | ||
132 | * check second operand for NaN's or infinity | ||
133 | */ | ||
134 | if (Dbl_isinfinity_exponent(rightp1)) | ||
135 | { | ||
136 | if (Dbl_iszero_mantissa(rightp1,rightp2)) | ||
137 | { | ||
138 | /* return infinity */ | ||
139 | Dbl_invert_sign(rightp1); | ||
140 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
141 | return(NOEXCEPTION); | ||
142 | } | ||
143 | /* | ||
144 | * is NaN; signaling or quiet? | ||
145 | */ | ||
146 | if (Dbl_isone_signaling(rightp1)) | ||
147 | { | ||
148 | /* trap if INVALIDTRAP enabled */ | ||
149 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
150 | /* make NaN quiet */ | ||
151 | Set_invalidflag(); | ||
152 | Dbl_set_quiet(rightp1); | ||
153 | } | ||
154 | /* | ||
155 | * return quiet NaN | ||
156 | */ | ||
157 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
158 | return(NOEXCEPTION); | ||
159 | } /* End right NaN or Infinity processing */ | ||
160 | |||
161 | /* Invariant: Must be dealing with finite numbers */ | ||
162 | |||
163 | /* Compare operands by removing the sign */ | ||
164 | Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left); | ||
165 | Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right); | ||
166 | |||
167 | /* sign difference selects add or sub operation. */ | ||
168 | if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right)) | ||
169 | { | ||
170 | /* Set the left operand to the larger one by XOR swap * | ||
171 | * First finish the first word using "save" */ | ||
172 | Dbl_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
173 | Dbl_xorfromintp1(save,leftp1,/*to*/leftp1); | ||
174 | Dbl_swap_lower(leftp2,rightp2); | ||
175 | result_exponent = Dbl_exponent(leftp1); | ||
176 | Dbl_invert_sign(leftp1); | ||
177 | } | ||
178 | /* Invariant: left is not smaller than right. */ | ||
179 | |||
180 | if((right_exponent = Dbl_exponent(rightp1)) == 0) | ||
181 | { | ||
182 | /* Denormalized operands. First look for zeroes */ | ||
183 | if(Dbl_iszero_mantissa(rightp1,rightp2)) | ||
184 | { | ||
185 | /* right is zero */ | ||
186 | if(Dbl_iszero_exponentmantissa(leftp1,leftp2)) | ||
187 | { | ||
188 | /* Both operands are zeros */ | ||
189 | Dbl_invert_sign(rightp1); | ||
190 | if(Is_rounding_mode(ROUNDMINUS)) | ||
191 | { | ||
192 | Dbl_or_signs(leftp1,/*with*/rightp1); | ||
193 | } | ||
194 | else | ||
195 | { | ||
196 | Dbl_and_signs(leftp1,/*with*/rightp1); | ||
197 | } | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | /* Left is not a zero and must be the result. Trapped | ||
202 | * underflows are signaled if left is denormalized. Result | ||
203 | * is always exact. */ | ||
204 | if( (result_exponent == 0) && Is_underflowtrap_enabled() ) | ||
205 | { | ||
206 | /* need to normalize results mantissa */ | ||
207 | sign_save = Dbl_signextendedsign(leftp1); | ||
208 | Dbl_leftshiftby1(leftp1,leftp2); | ||
209 | Dbl_normalize(leftp1,leftp2,result_exponent); | ||
210 | Dbl_set_sign(leftp1,/*using*/sign_save); | ||
211 | Dbl_setwrapped_exponent(leftp1,result_exponent,unfl); | ||
212 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
213 | /* inexact = FALSE */ | ||
214 | return(UNDERFLOWEXCEPTION); | ||
215 | } | ||
216 | } | ||
217 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
218 | return(NOEXCEPTION); | ||
219 | } | ||
220 | |||
221 | /* Neither are zeroes */ | ||
222 | Dbl_clear_sign(rightp1); /* Exponent is already cleared */ | ||
223 | if(result_exponent == 0 ) | ||
224 | { | ||
225 | /* Both operands are denormalized. The result must be exact | ||
226 | * and is simply calculated. A sum could become normalized and a | ||
227 | * difference could cancel to a true zero. */ | ||
228 | if( (/*signed*/int) save >= 0 ) | ||
229 | { | ||
230 | Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2, | ||
231 | /*into*/resultp1,resultp2); | ||
232 | if(Dbl_iszero_mantissa(resultp1,resultp2)) | ||
233 | { | ||
234 | if(Is_rounding_mode(ROUNDMINUS)) | ||
235 | { | ||
236 | Dbl_setone_sign(resultp1); | ||
237 | } | ||
238 | else | ||
239 | { | ||
240 | Dbl_setzero_sign(resultp1); | ||
241 | } | ||
242 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
243 | return(NOEXCEPTION); | ||
244 | } | ||
245 | } | ||
246 | else | ||
247 | { | ||
248 | Dbl_addition(leftp1,leftp2,rightp1,rightp2, | ||
249 | /*into*/resultp1,resultp2); | ||
250 | if(Dbl_isone_hidden(resultp1)) | ||
251 | { | ||
252 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
253 | return(NOEXCEPTION); | ||
254 | } | ||
255 | } | ||
256 | if(Is_underflowtrap_enabled()) | ||
257 | { | ||
258 | /* need to normalize result */ | ||
259 | sign_save = Dbl_signextendedsign(resultp1); | ||
260 | Dbl_leftshiftby1(resultp1,resultp2); | ||
261 | Dbl_normalize(resultp1,resultp2,result_exponent); | ||
262 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
263 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
264 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
265 | /* inexact = FALSE */ | ||
266 | return(UNDERFLOWEXCEPTION); | ||
267 | } | ||
268 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
269 | return(NOEXCEPTION); | ||
270 | } | ||
271 | right_exponent = 1; /* Set exponent to reflect different bias | ||
272 | * with denomalized numbers. */ | ||
273 | } | ||
274 | else | ||
275 | { | ||
276 | Dbl_clear_signexponent_set_hidden(rightp1); | ||
277 | } | ||
278 | Dbl_clear_exponent_set_hidden(leftp1); | ||
279 | diff_exponent = result_exponent - right_exponent; | ||
280 | |||
281 | /* | ||
282 | * Special case alignment of operands that would force alignment | ||
283 | * beyond the extent of the extension. A further optimization | ||
284 | * could special case this but only reduces the path length for this | ||
285 | * infrequent case. | ||
286 | */ | ||
287 | if(diff_exponent > DBL_THRESHOLD) | ||
288 | { | ||
289 | diff_exponent = DBL_THRESHOLD; | ||
290 | } | ||
291 | |||
292 | /* Align right operand by shifting to right */ | ||
293 | Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent, | ||
294 | /*and lower to*/extent); | ||
295 | |||
296 | /* Treat sum and difference of the operands separately. */ | ||
297 | if( (/*signed*/int) save >= 0 ) | ||
298 | { | ||
299 | /* | ||
300 | * Difference of the two operands. Their can be no overflow. A | ||
301 | * borrow can occur out of the hidden bit and force a post | ||
302 | * normalization phase. | ||
303 | */ | ||
304 | Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2, | ||
305 | /*with*/extent,/*into*/resultp1,resultp2); | ||
306 | if(Dbl_iszero_hidden(resultp1)) | ||
307 | { | ||
308 | /* Handle normalization */ | ||
309 | /* A straight foward algorithm would now shift the result | ||
310 | * and extension left until the hidden bit becomes one. Not | ||
311 | * all of the extension bits need participate in the shift. | ||
312 | * Only the two most significant bits (round and guard) are | ||
313 | * needed. If only a single shift is needed then the guard | ||
314 | * bit becomes a significant low order bit and the extension | ||
315 | * must participate in the rounding. If more than a single | ||
316 | * shift is needed, then all bits to the right of the guard | ||
317 | * bit are zeros, and the guard bit may or may not be zero. */ | ||
318 | sign_save = Dbl_signextendedsign(resultp1); | ||
319 | Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2); | ||
320 | |||
321 | /* Need to check for a zero result. The sign and exponent | ||
322 | * fields have already been zeroed. The more efficient test | ||
323 | * of the full object can be used. | ||
324 | */ | ||
325 | if(Dbl_iszero(resultp1,resultp2)) | ||
326 | /* Must have been "x-x" or "x+(-x)". */ | ||
327 | { | ||
328 | if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1); | ||
329 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
330 | return(NOEXCEPTION); | ||
331 | } | ||
332 | result_exponent--; | ||
333 | /* Look to see if normalization is finished. */ | ||
334 | if(Dbl_isone_hidden(resultp1)) | ||
335 | { | ||
336 | if(result_exponent==0) | ||
337 | { | ||
338 | /* Denormalized, exponent should be zero. Left operand * | ||
339 | * was normalized, so extent (guard, round) was zero */ | ||
340 | goto underflow; | ||
341 | } | ||
342 | else | ||
343 | { | ||
344 | /* No further normalization is needed. */ | ||
345 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
346 | Ext_leftshiftby1(extent); | ||
347 | goto round; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | /* Check for denormalized, exponent should be zero. Left * | ||
352 | * operand was normalized, so extent (guard, round) was zero */ | ||
353 | if(!(underflowtrap = Is_underflowtrap_enabled()) && | ||
354 | result_exponent==0) goto underflow; | ||
355 | |||
356 | /* Shift extension to complete one bit of normalization and | ||
357 | * update exponent. */ | ||
358 | Ext_leftshiftby1(extent); | ||
359 | |||
360 | /* Discover first one bit to determine shift amount. Use a | ||
361 | * modified binary search. We have already shifted the result | ||
362 | * one position right and still not found a one so the remainder | ||
363 | * of the extension must be zero and simplifies rounding. */ | ||
364 | /* Scan bytes */ | ||
365 | while(Dbl_iszero_hiddenhigh7mantissa(resultp1)) | ||
366 | { | ||
367 | Dbl_leftshiftby8(resultp1,resultp2); | ||
368 | if((result_exponent -= 8) <= 0 && !underflowtrap) | ||
369 | goto underflow; | ||
370 | } | ||
371 | /* Now narrow it down to the nibble */ | ||
372 | if(Dbl_iszero_hiddenhigh3mantissa(resultp1)) | ||
373 | { | ||
374 | /* The lower nibble contains the normalizing one */ | ||
375 | Dbl_leftshiftby4(resultp1,resultp2); | ||
376 | if((result_exponent -= 4) <= 0 && !underflowtrap) | ||
377 | goto underflow; | ||
378 | } | ||
379 | /* Select case were first bit is set (already normalized) | ||
380 | * otherwise select the proper shift. */ | ||
381 | if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7) | ||
382 | { | ||
383 | /* Already normalized */ | ||
384 | if(result_exponent <= 0) goto underflow; | ||
385 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
386 | Dbl_set_exponent(resultp1,/*using*/result_exponent); | ||
387 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
388 | return(NOEXCEPTION); | ||
389 | } | ||
390 | Dbl_sethigh4bits(resultp1,/*using*/sign_save); | ||
391 | switch(jumpsize) | ||
392 | { | ||
393 | case 1: | ||
394 | { | ||
395 | Dbl_leftshiftby3(resultp1,resultp2); | ||
396 | result_exponent -= 3; | ||
397 | break; | ||
398 | } | ||
399 | case 2: | ||
400 | case 3: | ||
401 | { | ||
402 | Dbl_leftshiftby2(resultp1,resultp2); | ||
403 | result_exponent -= 2; | ||
404 | break; | ||
405 | } | ||
406 | case 4: | ||
407 | case 5: | ||
408 | case 6: | ||
409 | case 7: | ||
410 | { | ||
411 | Dbl_leftshiftby1(resultp1,resultp2); | ||
412 | result_exponent -= 1; | ||
413 | break; | ||
414 | } | ||
415 | } | ||
416 | if(result_exponent > 0) | ||
417 | { | ||
418 | Dbl_set_exponent(resultp1,/*using*/result_exponent); | ||
419 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
420 | return(NOEXCEPTION); /* Sign bit is already set */ | ||
421 | } | ||
422 | /* Fixup potential underflows */ | ||
423 | underflow: | ||
424 | if(Is_underflowtrap_enabled()) | ||
425 | { | ||
426 | Dbl_set_sign(resultp1,sign_save); | ||
427 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
428 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
429 | /* inexact = FALSE */ | ||
430 | return(UNDERFLOWEXCEPTION); | ||
431 | } | ||
432 | /* | ||
433 | * Since we cannot get an inexact denormalized result, | ||
434 | * we can now return. | ||
435 | */ | ||
436 | Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent); | ||
437 | Dbl_clear_signexponent(resultp1); | ||
438 | Dbl_set_sign(resultp1,sign_save); | ||
439 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
440 | return(NOEXCEPTION); | ||
441 | } /* end if(hidden...)... */ | ||
442 | /* Fall through and round */ | ||
443 | } /* end if(save >= 0)... */ | ||
444 | else | ||
445 | { | ||
446 | /* Subtract magnitudes */ | ||
447 | Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2); | ||
448 | if(Dbl_isone_hiddenoverflow(resultp1)) | ||
449 | { | ||
450 | /* Prenormalization required. */ | ||
451 | Dbl_rightshiftby1_withextent(resultp2,extent,extent); | ||
452 | Dbl_arithrightshiftby1(resultp1,resultp2); | ||
453 | result_exponent++; | ||
454 | } /* end if hiddenoverflow... */ | ||
455 | } /* end else ...subtract magnitudes... */ | ||
456 | |||
457 | /* Round the result. If the extension is all zeros,then the result is | ||
458 | * exact. Otherwise round in the correct direction. No underflow is | ||
459 | * possible. If a postnormalization is necessary, then the mantissa is | ||
460 | * all zeros so no shift is needed. */ | ||
461 | round: | ||
462 | if(Ext_isnotzero(extent)) | ||
463 | { | ||
464 | inexact = TRUE; | ||
465 | switch(Rounding_mode()) | ||
466 | { | ||
467 | case ROUNDNEAREST: /* The default. */ | ||
468 | if(Ext_isone_sign(extent)) | ||
469 | { | ||
470 | /* at least 1/2 ulp */ | ||
471 | if(Ext_isnotzero_lower(extent) || | ||
472 | Dbl_isone_lowmantissap2(resultp2)) | ||
473 | { | ||
474 | /* either exactly half way and odd or more than 1/2ulp */ | ||
475 | Dbl_increment(resultp1,resultp2); | ||
476 | } | ||
477 | } | ||
478 | break; | ||
479 | |||
480 | case ROUNDPLUS: | ||
481 | if(Dbl_iszero_sign(resultp1)) | ||
482 | { | ||
483 | /* Round up positive results */ | ||
484 | Dbl_increment(resultp1,resultp2); | ||
485 | } | ||
486 | break; | ||
487 | |||
488 | case ROUNDMINUS: | ||
489 | if(Dbl_isone_sign(resultp1)) | ||
490 | { | ||
491 | /* Round down negative results */ | ||
492 | Dbl_increment(resultp1,resultp2); | ||
493 | } | ||
494 | |||
495 | case ROUNDZERO:; | ||
496 | /* truncate is simple */ | ||
497 | } /* end switch... */ | ||
498 | if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
499 | } | ||
500 | if(result_exponent == DBL_INFINITY_EXPONENT) | ||
501 | { | ||
502 | /* Overflow */ | ||
503 | if(Is_overflowtrap_enabled()) | ||
504 | { | ||
505 | Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
506 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
507 | if (inexact) | ||
508 | if (Is_inexacttrap_enabled()) | ||
509 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
510 | else Set_inexactflag(); | ||
511 | return(OVERFLOWEXCEPTION); | ||
512 | } | ||
513 | else | ||
514 | { | ||
515 | inexact = TRUE; | ||
516 | Set_overflowflag(); | ||
517 | Dbl_setoverflow(resultp1,resultp2); | ||
518 | } | ||
519 | } | ||
520 | else Dbl_set_exponent(resultp1,result_exponent); | ||
521 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
522 | if(inexact) | ||
523 | if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
524 | else Set_inexactflag(); | ||
525 | return(NOEXCEPTION); | ||
526 | } | ||
diff --git a/arch/parisc/math-emu/driver.c b/arch/parisc/math-emu/driver.c new file mode 100644 index 000000000000..09ef4136c693 --- /dev/null +++ b/arch/parisc/math-emu/driver.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * linux/arch/math-emu/driver.c.c | ||
23 | * | ||
24 | * decodes and dispatches unimplemented FPU instructions | ||
25 | * | ||
26 | * Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org> | ||
27 | * Copyright (C) 2001 Hewlett-Packard <bame@debian.org> | ||
28 | */ | ||
29 | |||
30 | #include <linux/sched.h> | ||
31 | #include "float.h" | ||
32 | #include "math-emu.h" | ||
33 | |||
34 | |||
35 | #define fptpos 31 | ||
36 | #define fpr1pos 10 | ||
37 | #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) | ||
38 | |||
39 | #define FPUDEBUG 0 | ||
40 | |||
41 | /* Format of the floating-point exception registers. */ | ||
42 | struct exc_reg { | ||
43 | unsigned int exception : 6; | ||
44 | unsigned int ei : 26; | ||
45 | }; | ||
46 | |||
47 | /* Macros for grabbing bits of the instruction format from the 'ei' | ||
48 | field above. */ | ||
49 | /* Major opcode 0c and 0e */ | ||
50 | #define FP0CE_UID(i) (((i) >> 6) & 3) | ||
51 | #define FP0CE_CLASS(i) (((i) >> 9) & 3) | ||
52 | #define FP0CE_SUBOP(i) (((i) >> 13) & 7) | ||
53 | #define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */ | ||
54 | #define FP0C_FORMAT(i) (((i) >> 11) & 3) | ||
55 | #define FP0E_FORMAT(i) (((i) >> 11) & 1) | ||
56 | |||
57 | /* Major opcode 0c, uid 2 (performance monitoring) */ | ||
58 | #define FPPM_SUBOP(i) (((i) >> 9) & 0x1f) | ||
59 | |||
60 | /* Major opcode 2e (fused operations). */ | ||
61 | #define FP2E_SUBOP(i) (((i) >> 5) & 1) | ||
62 | #define FP2E_FORMAT(i) (((i) >> 11) & 1) | ||
63 | |||
64 | /* Major opcode 26 (FMPYSUB) */ | ||
65 | /* Major opcode 06 (FMPYADD) */ | ||
66 | #define FPx6_FORMAT(i) ((i) & 0x1f) | ||
67 | |||
68 | /* Flags and enable bits of the status word. */ | ||
69 | #define FPSW_FLAGS(w) ((w) >> 27) | ||
70 | #define FPSW_ENABLE(w) ((w) & 0x1f) | ||
71 | #define FPSW_V (1<<4) | ||
72 | #define FPSW_Z (1<<3) | ||
73 | #define FPSW_O (1<<2) | ||
74 | #define FPSW_U (1<<1) | ||
75 | #define FPSW_I (1<<0) | ||
76 | |||
77 | /* Handle a floating point exception. Return zero if the faulting | ||
78 | instruction can be completed successfully. */ | ||
79 | int | ||
80 | handle_fpe(struct pt_regs *regs) | ||
81 | { | ||
82 | extern void printbinary(unsigned long x, int nbits); | ||
83 | struct siginfo si; | ||
84 | unsigned int orig_sw, sw; | ||
85 | int signalcode; | ||
86 | /* need an intermediate copy of float regs because FPU emulation | ||
87 | * code expects an artificial last entry which contains zero | ||
88 | * | ||
89 | * also, the passed in fr registers contain one word that defines | ||
90 | * the fpu type. the fpu type information is constructed | ||
91 | * inside the emulation code | ||
92 | */ | ||
93 | __u64 frcopy[36]; | ||
94 | |||
95 | memcpy(frcopy, regs->fr, sizeof regs->fr); | ||
96 | frcopy[32] = 0; | ||
97 | |||
98 | memcpy(&orig_sw, frcopy, sizeof(orig_sw)); | ||
99 | |||
100 | if (FPUDEBUG) { | ||
101 | printk(KERN_DEBUG "FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->\n "); | ||
102 | printbinary(orig_sw, 32); | ||
103 | printk(KERN_DEBUG "\n"); | ||
104 | } | ||
105 | |||
106 | signalcode = decode_fpu(frcopy, 0x666); | ||
107 | |||
108 | /* Status word = FR0L. */ | ||
109 | memcpy(&sw, frcopy, sizeof(sw)); | ||
110 | if (FPUDEBUG) { | ||
111 | printk(KERN_DEBUG "VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%x\n", | ||
112 | signalcode >> 24, signalcode & 0xffffff); | ||
113 | printbinary(sw, 32); | ||
114 | printk(KERN_DEBUG "\n"); | ||
115 | } | ||
116 | |||
117 | memcpy(regs->fr, frcopy, sizeof regs->fr); | ||
118 | if (signalcode != 0) { | ||
119 | si.si_signo = signalcode >> 24; | ||
120 | si.si_errno = 0; | ||
121 | si.si_code = signalcode & 0xffffff; | ||
122 | si.si_addr = (void __user *) regs->iaoq[0]; | ||
123 | force_sig_info(si.si_signo, &si, current); | ||
124 | return -1; | ||
125 | } | ||
126 | |||
127 | return signalcode ? -1 : 0; | ||
128 | } | ||
diff --git a/arch/parisc/math-emu/fcnvff.c b/arch/parisc/math-emu/fcnvff.c new file mode 100644 index 000000000000..76c063f7d17c --- /dev/null +++ b/arch/parisc/math-emu/fcnvff.c | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/fcnvff.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single Floating-point to Double Floating-point | ||
29 | * Double Floating-point to Single Floating-point | ||
30 | * | ||
31 | * External Interfaces: | ||
32 | * dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status) | ||
33 | * sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status) | ||
34 | * | ||
35 | * Internal Interfaces: | ||
36 | * | ||
37 | * Theory: | ||
38 | * <<please update with a overview of the operation of this file>> | ||
39 | * | ||
40 | * END_DESC | ||
41 | */ | ||
42 | |||
43 | |||
44 | #include "float.h" | ||
45 | #include "sgl_float.h" | ||
46 | #include "dbl_float.h" | ||
47 | #include "cnv_float.h" | ||
48 | |||
49 | /* | ||
50 | * Single Floating-point to Double Floating-point | ||
51 | */ | ||
52 | /*ARGSUSED*/ | ||
53 | int | ||
54 | sgl_to_dbl_fcnvff( | ||
55 | sgl_floating_point *srcptr, | ||
56 | unsigned int *nullptr, | ||
57 | dbl_floating_point *dstptr, | ||
58 | unsigned int *status) | ||
59 | { | ||
60 | register unsigned int src, resultp1, resultp2; | ||
61 | register int src_exponent; | ||
62 | |||
63 | src = *srcptr; | ||
64 | src_exponent = Sgl_exponent(src); | ||
65 | Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */ | ||
66 | /* | ||
67 | * Test for NaN or infinity | ||
68 | */ | ||
69 | if (src_exponent == SGL_INFINITY_EXPONENT) { | ||
70 | /* | ||
71 | * determine if NaN or infinity | ||
72 | */ | ||
73 | if (Sgl_iszero_mantissa(src)) { | ||
74 | /* | ||
75 | * is infinity; want to return double infinity | ||
76 | */ | ||
77 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
78 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
79 | return(NOEXCEPTION); | ||
80 | } | ||
81 | else { | ||
82 | /* | ||
83 | * is NaN; signaling or quiet? | ||
84 | */ | ||
85 | if (Sgl_isone_signaling(src)) { | ||
86 | /* trap if INVALIDTRAP enabled */ | ||
87 | if (Is_invalidtrap_enabled()) | ||
88 | return(INVALIDEXCEPTION); | ||
89 | /* make NaN quiet */ | ||
90 | else { | ||
91 | Set_invalidflag(); | ||
92 | Sgl_set_quiet(src); | ||
93 | } | ||
94 | } | ||
95 | /* | ||
96 | * NaN is quiet, return as double NaN | ||
97 | */ | ||
98 | Dbl_setinfinity_exponent(resultp1); | ||
99 | Sgl_to_dbl_mantissa(src,resultp1,resultp2); | ||
100 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
101 | return(NOEXCEPTION); | ||
102 | } | ||
103 | } | ||
104 | /* | ||
105 | * Test for zero or denormalized | ||
106 | */ | ||
107 | if (src_exponent == 0) { | ||
108 | /* | ||
109 | * determine if zero or denormalized | ||
110 | */ | ||
111 | if (Sgl_isnotzero_mantissa(src)) { | ||
112 | /* | ||
113 | * is denormalized; want to normalize | ||
114 | */ | ||
115 | Sgl_clear_signexponent(src); | ||
116 | Sgl_leftshiftby1(src); | ||
117 | Sgl_normalize(src,src_exponent); | ||
118 | Sgl_to_dbl_exponent(src_exponent,resultp1); | ||
119 | Sgl_to_dbl_mantissa(src,resultp1,resultp2); | ||
120 | } | ||
121 | else { | ||
122 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
123 | } | ||
124 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
125 | return(NOEXCEPTION); | ||
126 | } | ||
127 | /* | ||
128 | * No special cases, just complete the conversion | ||
129 | */ | ||
130 | Sgl_to_dbl_exponent(src_exponent, resultp1); | ||
131 | Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2); | ||
132 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
133 | return(NOEXCEPTION); | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Double Floating-point to Single Floating-point | ||
138 | */ | ||
139 | /*ARGSUSED*/ | ||
140 | int | ||
141 | dbl_to_sgl_fcnvff( | ||
142 | dbl_floating_point *srcptr, | ||
143 | unsigned int *nullptr, | ||
144 | sgl_floating_point *dstptr, | ||
145 | unsigned int *status) | ||
146 | { | ||
147 | register unsigned int srcp1, srcp2, result; | ||
148 | register int src_exponent, dest_exponent, dest_mantissa; | ||
149 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
150 | register boolean lsb_odd = FALSE; | ||
151 | boolean is_tiny; | ||
152 | |||
153 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
154 | src_exponent = Dbl_exponent(srcp1); | ||
155 | Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */ | ||
156 | /* | ||
157 | * Test for NaN or infinity | ||
158 | */ | ||
159 | if (src_exponent == DBL_INFINITY_EXPONENT) { | ||
160 | /* | ||
161 | * determine if NaN or infinity | ||
162 | */ | ||
163 | if (Dbl_iszero_mantissa(srcp1,srcp2)) { | ||
164 | /* | ||
165 | * is infinity; want to return single infinity | ||
166 | */ | ||
167 | Sgl_setinfinity_exponentmantissa(result); | ||
168 | *dstptr = result; | ||
169 | return(NOEXCEPTION); | ||
170 | } | ||
171 | /* | ||
172 | * is NaN; signaling or quiet? | ||
173 | */ | ||
174 | if (Dbl_isone_signaling(srcp1)) { | ||
175 | /* trap if INVALIDTRAP enabled */ | ||
176 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
177 | else { | ||
178 | Set_invalidflag(); | ||
179 | /* make NaN quiet */ | ||
180 | Dbl_set_quiet(srcp1); | ||
181 | } | ||
182 | } | ||
183 | /* | ||
184 | * NaN is quiet, return as single NaN | ||
185 | */ | ||
186 | Sgl_setinfinity_exponent(result); | ||
187 | Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29); | ||
188 | if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result); | ||
189 | *dstptr = result; | ||
190 | return(NOEXCEPTION); | ||
191 | } | ||
192 | /* | ||
193 | * Generate result | ||
194 | */ | ||
195 | Dbl_to_sgl_exponent(src_exponent,dest_exponent); | ||
196 | if (dest_exponent > 0) { | ||
197 | Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit, | ||
198 | stickybit,lsb_odd); | ||
199 | } | ||
200 | else { | ||
201 | if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){ | ||
202 | Sgl_setzero_exponentmantissa(result); | ||
203 | *dstptr = result; | ||
204 | return(NOEXCEPTION); | ||
205 | } | ||
206 | if (Is_underflowtrap_enabled()) { | ||
207 | Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact, | ||
208 | guardbit,stickybit,lsb_odd); | ||
209 | } | ||
210 | else { | ||
211 | /* compute result, determine inexact info, | ||
212 | * and set Underflowflag if appropriate | ||
213 | */ | ||
214 | Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent, | ||
215 | dest_mantissa,inexact,guardbit,stickybit,lsb_odd, | ||
216 | is_tiny); | ||
217 | } | ||
218 | } | ||
219 | /* | ||
220 | * Now round result if not exact | ||
221 | */ | ||
222 | if (inexact) { | ||
223 | switch (Rounding_mode()) { | ||
224 | case ROUNDPLUS: | ||
225 | if (Sgl_iszero_sign(result)) dest_mantissa++; | ||
226 | break; | ||
227 | case ROUNDMINUS: | ||
228 | if (Sgl_isone_sign(result)) dest_mantissa++; | ||
229 | break; | ||
230 | case ROUNDNEAREST: | ||
231 | if (guardbit) { | ||
232 | if (stickybit || lsb_odd) dest_mantissa++; | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | Sgl_set_exponentmantissa(result,dest_mantissa); | ||
237 | |||
238 | /* | ||
239 | * check for mantissa overflow after rounding | ||
240 | */ | ||
241 | if ((dest_exponent>0 || Is_underflowtrap_enabled()) && | ||
242 | Sgl_isone_hidden(result)) dest_exponent++; | ||
243 | |||
244 | /* | ||
245 | * Test for overflow | ||
246 | */ | ||
247 | if (dest_exponent >= SGL_INFINITY_EXPONENT) { | ||
248 | /* trap if OVERFLOWTRAP enabled */ | ||
249 | if (Is_overflowtrap_enabled()) { | ||
250 | /* | ||
251 | * Check for gross overflow | ||
252 | */ | ||
253 | if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP) | ||
254 | return(UNIMPLEMENTEDEXCEPTION); | ||
255 | |||
256 | /* | ||
257 | * Adjust bias of result | ||
258 | */ | ||
259 | Sgl_setwrapped_exponent(result,dest_exponent,ovfl); | ||
260 | *dstptr = result; | ||
261 | if (inexact) | ||
262 | if (Is_inexacttrap_enabled()) | ||
263 | return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); | ||
264 | else Set_inexactflag(); | ||
265 | return(OVERFLOWEXCEPTION); | ||
266 | } | ||
267 | Set_overflowflag(); | ||
268 | inexact = TRUE; | ||
269 | /* set result to infinity or largest number */ | ||
270 | Sgl_setoverflow(result); | ||
271 | } | ||
272 | /* | ||
273 | * Test for underflow | ||
274 | */ | ||
275 | else if (dest_exponent <= 0) { | ||
276 | /* trap if UNDERFLOWTRAP enabled */ | ||
277 | if (Is_underflowtrap_enabled()) { | ||
278 | /* | ||
279 | * Check for gross underflow | ||
280 | */ | ||
281 | if (dest_exponent <= -(SGL_WRAP)) | ||
282 | return(UNIMPLEMENTEDEXCEPTION); | ||
283 | /* | ||
284 | * Adjust bias of result | ||
285 | */ | ||
286 | Sgl_setwrapped_exponent(result,dest_exponent,unfl); | ||
287 | *dstptr = result; | ||
288 | if (inexact) | ||
289 | if (Is_inexacttrap_enabled()) | ||
290 | return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION); | ||
291 | else Set_inexactflag(); | ||
292 | return(UNDERFLOWEXCEPTION); | ||
293 | } | ||
294 | /* | ||
295 | * result is denormalized or signed zero | ||
296 | */ | ||
297 | if (inexact && is_tiny) Set_underflowflag(); | ||
298 | |||
299 | } | ||
300 | else Sgl_set_exponent(result,dest_exponent); | ||
301 | *dstptr = result; | ||
302 | /* | ||
303 | * Trap if inexact trap is enabled | ||
304 | */ | ||
305 | if (inexact) | ||
306 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
307 | else Set_inexactflag(); | ||
308 | return(NOEXCEPTION); | ||
309 | } | ||
diff --git a/arch/parisc/math-emu/fcnvfu.c b/arch/parisc/math-emu/fcnvfu.c new file mode 100644 index 000000000000..7e8565537bf5 --- /dev/null +++ b/arch/parisc/math-emu/fcnvfu.c | |||
@@ -0,0 +1,536 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/fcnvfu.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Floating-point to Unsigned Fixed-point Converts | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status) | ||
32 | * dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status) | ||
33 | * sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status) | ||
34 | * sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status) | ||
35 | * | ||
36 | * Internal Interfaces: | ||
37 | * | ||
38 | * Theory: | ||
39 | * <<please update with a overview of the operation of this file>> | ||
40 | * | ||
41 | * END_DESC | ||
42 | */ | ||
43 | |||
44 | |||
45 | #include "float.h" | ||
46 | #include "sgl_float.h" | ||
47 | #include "dbl_float.h" | ||
48 | #include "cnv_float.h" | ||
49 | |||
50 | /************************************************************************ | ||
51 | * Floating-point to Unsigned Fixed-point Converts * | ||
52 | ************************************************************************/ | ||
53 | |||
54 | /* | ||
55 | * Single Floating-point to Single Unsigned Fixed | ||
56 | */ | ||
57 | /*ARGSUSED*/ | ||
58 | int | ||
59 | sgl_to_sgl_fcnvfu( | ||
60 | sgl_floating_point *srcptr, | ||
61 | unsigned int *nullptr, | ||
62 | unsigned int *dstptr, | ||
63 | unsigned int *status) | ||
64 | { | ||
65 | register unsigned int src, result; | ||
66 | register int src_exponent; | ||
67 | register boolean inexact = FALSE; | ||
68 | |||
69 | src = *srcptr; | ||
70 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
71 | |||
72 | /* | ||
73 | * Test for overflow | ||
74 | */ | ||
75 | if (src_exponent > SGL_FX_MAX_EXP + 1) { | ||
76 | if (Sgl_isone_sign(src)) { | ||
77 | result = 0; | ||
78 | } else { | ||
79 | result = 0xffffffff; | ||
80 | } | ||
81 | if (Is_invalidtrap_enabled()) { | ||
82 | return(INVALIDEXCEPTION); | ||
83 | } | ||
84 | Set_invalidflag(); | ||
85 | *dstptr = result; | ||
86 | return(NOEXCEPTION); | ||
87 | } | ||
88 | /* | ||
89 | * Generate result | ||
90 | */ | ||
91 | if (src_exponent >= 0) { | ||
92 | /* | ||
93 | * Check sign. | ||
94 | * If negative, trap unimplemented. | ||
95 | */ | ||
96 | if (Sgl_isone_sign(src)) { | ||
97 | result = 0; | ||
98 | if (Is_invalidtrap_enabled()) { | ||
99 | return(INVALIDEXCEPTION); | ||
100 | } | ||
101 | Set_invalidflag(); | ||
102 | *dstptr = result; | ||
103 | return(NOEXCEPTION); | ||
104 | } | ||
105 | Sgl_clear_signexponent_set_hidden(src); | ||
106 | Suint_from_sgl_mantissa(src,src_exponent,result); | ||
107 | |||
108 | /* check for inexact */ | ||
109 | if (Sgl_isinexact_to_unsigned(src,src_exponent)) { | ||
110 | inexact = TRUE; | ||
111 | /* round result */ | ||
112 | switch (Rounding_mode()) { | ||
113 | case ROUNDPLUS: | ||
114 | result++; | ||
115 | break; | ||
116 | case ROUNDMINUS: /* never negative */ | ||
117 | break; | ||
118 | case ROUNDNEAREST: | ||
119 | if (Sgl_isone_roundbit(src,src_exponent) && | ||
120 | (Sgl_isone_stickybit(src,src_exponent) || | ||
121 | (result & 1))) { | ||
122 | result++; | ||
123 | } | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | } else { | ||
128 | result = 0; | ||
129 | |||
130 | /* check for inexact */ | ||
131 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
132 | inexact = TRUE; | ||
133 | /* round result */ | ||
134 | switch (Rounding_mode()) { | ||
135 | case ROUNDPLUS: | ||
136 | if (Sgl_iszero_sign(src)) { | ||
137 | result++; | ||
138 | } | ||
139 | break; | ||
140 | case ROUNDMINUS: | ||
141 | if (Sgl_isone_sign(src)) { | ||
142 | result = 0; | ||
143 | if (Is_invalidtrap_enabled()) { | ||
144 | return(INVALIDEXCEPTION); | ||
145 | } | ||
146 | Set_invalidflag(); | ||
147 | inexact = FALSE; | ||
148 | } | ||
149 | break; | ||
150 | case ROUNDNEAREST: | ||
151 | if (src_exponent == -1 && | ||
152 | Sgl_isnotzero_mantissa(src)) { | ||
153 | if (Sgl_isone_sign(src)) { | ||
154 | result = 0; | ||
155 | if (Is_invalidtrap_enabled()) { | ||
156 | return(INVALIDEXCEPTION); | ||
157 | } | ||
158 | Set_invalidflag(); | ||
159 | inexact = FALSE; | ||
160 | } | ||
161 | else result++; | ||
162 | } | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | *dstptr = result; | ||
168 | if (inexact) { | ||
169 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
170 | else Set_inexactflag(); | ||
171 | } | ||
172 | return(NOEXCEPTION); | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Single Floating-point to Double Unsigned Fixed | ||
177 | */ | ||
178 | /*ARGSUSED*/ | ||
179 | int | ||
180 | sgl_to_dbl_fcnvfu( | ||
181 | sgl_floating_point *srcptr, | ||
182 | unsigned int *nullptr, | ||
183 | dbl_unsigned *dstptr, | ||
184 | unsigned int *status) | ||
185 | { | ||
186 | register int src_exponent; | ||
187 | register unsigned int src, resultp1, resultp2; | ||
188 | register boolean inexact = FALSE; | ||
189 | |||
190 | src = *srcptr; | ||
191 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
192 | |||
193 | /* | ||
194 | * Test for overflow | ||
195 | */ | ||
196 | if (src_exponent > DBL_FX_MAX_EXP + 1) { | ||
197 | if (Sgl_isone_sign(src)) { | ||
198 | resultp1 = resultp2 = 0; | ||
199 | } else { | ||
200 | resultp1 = resultp2 = 0xffffffff; | ||
201 | } | ||
202 | if (Is_invalidtrap_enabled()) { | ||
203 | return(INVALIDEXCEPTION); | ||
204 | } | ||
205 | Set_invalidflag(); | ||
206 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
207 | return(NOEXCEPTION); | ||
208 | } | ||
209 | /* | ||
210 | * Generate result | ||
211 | */ | ||
212 | if (src_exponent >= 0) { | ||
213 | /* | ||
214 | * Check sign. | ||
215 | * If negative, trap unimplemented. | ||
216 | */ | ||
217 | if (Sgl_isone_sign(src)) { | ||
218 | resultp1 = resultp2 = 0; | ||
219 | if (Is_invalidtrap_enabled()) { | ||
220 | return(INVALIDEXCEPTION); | ||
221 | } | ||
222 | Set_invalidflag(); | ||
223 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
224 | return(NOEXCEPTION); | ||
225 | } | ||
226 | Sgl_clear_signexponent_set_hidden(src); | ||
227 | Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2); | ||
228 | |||
229 | /* check for inexact */ | ||
230 | if (Sgl_isinexact_to_unsigned(src,src_exponent)) { | ||
231 | inexact = TRUE; | ||
232 | /* round result */ | ||
233 | switch (Rounding_mode()) { | ||
234 | case ROUNDPLUS: | ||
235 | Duint_increment(resultp1,resultp2); | ||
236 | break; | ||
237 | case ROUNDMINUS: /* never negative */ | ||
238 | break; | ||
239 | case ROUNDNEAREST: | ||
240 | if (Sgl_isone_roundbit(src,src_exponent) && | ||
241 | (Sgl_isone_stickybit(src,src_exponent) || | ||
242 | Duint_isone_lowp2(resultp2))) { | ||
243 | Duint_increment(resultp1,resultp2); | ||
244 | } | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | } else { | ||
249 | Duint_setzero(resultp1,resultp2); | ||
250 | |||
251 | /* check for inexact */ | ||
252 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
253 | inexact = TRUE; | ||
254 | /* round result */ | ||
255 | switch (Rounding_mode()) { | ||
256 | case ROUNDPLUS: | ||
257 | if (Sgl_iszero_sign(src)) { | ||
258 | Duint_increment(resultp1,resultp2); | ||
259 | } | ||
260 | break; | ||
261 | case ROUNDMINUS: | ||
262 | if (Sgl_isone_sign(src)) { | ||
263 | resultp1 = resultp2 = 0; | ||
264 | if (Is_invalidtrap_enabled()) { | ||
265 | return(INVALIDEXCEPTION); | ||
266 | } | ||
267 | Set_invalidflag(); | ||
268 | inexact = FALSE; | ||
269 | } | ||
270 | break; | ||
271 | case ROUNDNEAREST: | ||
272 | if (src_exponent == -1 && | ||
273 | Sgl_isnotzero_mantissa(src)) { | ||
274 | if (Sgl_isone_sign(src)) { | ||
275 | resultp1 = 0; | ||
276 | resultp2 = 0; | ||
277 | if (Is_invalidtrap_enabled()) { | ||
278 | return(INVALIDEXCEPTION); | ||
279 | } | ||
280 | Set_invalidflag(); | ||
281 | inexact = FALSE; | ||
282 | } | ||
283 | else Duint_increment(resultp1,resultp2); | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
289 | if (inexact) { | ||
290 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
291 | else Set_inexactflag(); | ||
292 | } | ||
293 | return(NOEXCEPTION); | ||
294 | } | ||
295 | |||
296 | /* | ||
297 | * Double Floating-point to Single Unsigned Fixed | ||
298 | */ | ||
299 | /*ARGSUSED*/ | ||
300 | int | ||
301 | dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr, | ||
302 | unsigned int *dstptr, unsigned int *status) | ||
303 | { | ||
304 | register unsigned int srcp1, srcp2, result; | ||
305 | register int src_exponent; | ||
306 | register boolean inexact = FALSE; | ||
307 | |||
308 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
309 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
310 | |||
311 | /* | ||
312 | * Test for overflow | ||
313 | */ | ||
314 | if (src_exponent > SGL_FX_MAX_EXP + 1) { | ||
315 | if (Dbl_isone_sign(srcp1)) { | ||
316 | result = 0; | ||
317 | } else { | ||
318 | result = 0xffffffff; | ||
319 | } | ||
320 | if (Is_invalidtrap_enabled()) { | ||
321 | return(INVALIDEXCEPTION); | ||
322 | } | ||
323 | Set_invalidflag(); | ||
324 | *dstptr = result; | ||
325 | return(NOEXCEPTION); | ||
326 | } | ||
327 | /* | ||
328 | * Generate result | ||
329 | */ | ||
330 | if (src_exponent >= 0) { | ||
331 | /* | ||
332 | * Check sign. | ||
333 | * If negative, trap unimplemented. | ||
334 | */ | ||
335 | if (Dbl_isone_sign(srcp1)) { | ||
336 | result = 0; | ||
337 | if (Is_invalidtrap_enabled()) { | ||
338 | return(INVALIDEXCEPTION); | ||
339 | } | ||
340 | Set_invalidflag(); | ||
341 | *dstptr = result; | ||
342 | return(NOEXCEPTION); | ||
343 | } | ||
344 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
345 | Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result); | ||
346 | |||
347 | /* check for inexact */ | ||
348 | if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { | ||
349 | inexact = TRUE; | ||
350 | /* round result */ | ||
351 | switch (Rounding_mode()) { | ||
352 | case ROUNDPLUS: | ||
353 | result++; | ||
354 | break; | ||
355 | case ROUNDMINUS: /* never negative */ | ||
356 | break; | ||
357 | case ROUNDNEAREST: | ||
358 | if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) && | ||
359 | (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)|| | ||
360 | result&1)) | ||
361 | result++; | ||
362 | break; | ||
363 | } | ||
364 | /* check for overflow */ | ||
365 | if (result == 0) { | ||
366 | result = 0xffffffff; | ||
367 | if (Is_invalidtrap_enabled()) { | ||
368 | return(INVALIDEXCEPTION); | ||
369 | } | ||
370 | Set_invalidflag(); | ||
371 | *dstptr = result; | ||
372 | return(NOEXCEPTION); | ||
373 | } | ||
374 | } | ||
375 | } else { | ||
376 | result = 0; | ||
377 | |||
378 | /* check for inexact */ | ||
379 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
380 | inexact = TRUE; | ||
381 | /* round result */ | ||
382 | switch (Rounding_mode()) { | ||
383 | case ROUNDPLUS: | ||
384 | if (Dbl_iszero_sign(srcp1)) result++; | ||
385 | break; | ||
386 | case ROUNDMINUS: | ||
387 | if (Dbl_isone_sign(srcp1)) { | ||
388 | result = 0; | ||
389 | if (Is_invalidtrap_enabled()) { | ||
390 | return(INVALIDEXCEPTION); | ||
391 | } | ||
392 | Set_invalidflag(); | ||
393 | inexact = FALSE; | ||
394 | } | ||
395 | break; | ||
396 | case ROUNDNEAREST: | ||
397 | if (src_exponent == -1 && | ||
398 | Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
399 | if (Dbl_isone_sign(srcp1)) { | ||
400 | result = 0; | ||
401 | if (Is_invalidtrap_enabled()) { | ||
402 | return(INVALIDEXCEPTION); | ||
403 | } | ||
404 | Set_invalidflag(); | ||
405 | inexact = FALSE; | ||
406 | } | ||
407 | else result++; | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | *dstptr = result; | ||
412 | if (inexact) { | ||
413 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
414 | else Set_inexactflag(); | ||
415 | } | ||
416 | return(NOEXCEPTION); | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * Double Floating-point to Double Unsigned Fixed | ||
421 | */ | ||
422 | /*ARGSUSED*/ | ||
423 | int | ||
424 | dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr, | ||
425 | dbl_unsigned * dstptr, unsigned int *status) | ||
426 | { | ||
427 | register int src_exponent; | ||
428 | register unsigned int srcp1, srcp2, resultp1, resultp2; | ||
429 | register boolean inexact = FALSE; | ||
430 | |||
431 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
432 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
433 | |||
434 | /* | ||
435 | * Test for overflow | ||
436 | */ | ||
437 | if (src_exponent > DBL_FX_MAX_EXP + 1) { | ||
438 | if (Dbl_isone_sign(srcp1)) { | ||
439 | resultp1 = resultp2 = 0; | ||
440 | } else { | ||
441 | resultp1 = resultp2 = 0xffffffff; | ||
442 | } | ||
443 | if (Is_invalidtrap_enabled()) { | ||
444 | return(INVALIDEXCEPTION); | ||
445 | } | ||
446 | Set_invalidflag(); | ||
447 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
448 | return(NOEXCEPTION); | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * Generate result | ||
453 | */ | ||
454 | if (src_exponent >= 0) { | ||
455 | /* | ||
456 | * Check sign. | ||
457 | * If negative, trap unimplemented. | ||
458 | */ | ||
459 | if (Dbl_isone_sign(srcp1)) { | ||
460 | resultp1 = resultp2 = 0; | ||
461 | if (Is_invalidtrap_enabled()) { | ||
462 | return(INVALIDEXCEPTION); | ||
463 | } | ||
464 | Set_invalidflag(); | ||
465 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
466 | return(NOEXCEPTION); | ||
467 | } | ||
468 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
469 | Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1, | ||
470 | resultp2); | ||
471 | |||
472 | /* check for inexact */ | ||
473 | if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { | ||
474 | inexact = TRUE; | ||
475 | /* round result */ | ||
476 | switch (Rounding_mode()) { | ||
477 | case ROUNDPLUS: | ||
478 | Duint_increment(resultp1,resultp2); | ||
479 | break; | ||
480 | case ROUNDMINUS: /* never negative */ | ||
481 | break; | ||
482 | case ROUNDNEAREST: | ||
483 | if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) | ||
484 | if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || | ||
485 | Duint_isone_lowp2(resultp2)) | ||
486 | Duint_increment(resultp1,resultp2); | ||
487 | } | ||
488 | } | ||
489 | } else { | ||
490 | Duint_setzero(resultp1,resultp2); | ||
491 | |||
492 | /* check for inexact */ | ||
493 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
494 | inexact = TRUE; | ||
495 | /* round result */ | ||
496 | switch (Rounding_mode()) { | ||
497 | case ROUNDPLUS: | ||
498 | if (Dbl_iszero_sign(srcp1)) { | ||
499 | Duint_increment(resultp1,resultp2); | ||
500 | } | ||
501 | break; | ||
502 | case ROUNDMINUS: | ||
503 | if (Dbl_isone_sign(srcp1)) { | ||
504 | resultp1 = resultp2 = 0; | ||
505 | if (Is_invalidtrap_enabled()) { | ||
506 | return(INVALIDEXCEPTION); | ||
507 | } | ||
508 | Set_invalidflag(); | ||
509 | inexact = FALSE; | ||
510 | } | ||
511 | break; | ||
512 | case ROUNDNEAREST: | ||
513 | if (src_exponent == -1 && | ||
514 | Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
515 | if (Dbl_iszero_sign(srcp1)) { | ||
516 | Duint_increment(resultp1,resultp2); | ||
517 | } else { | ||
518 | resultp1 = 0; | ||
519 | resultp2 = 0; | ||
520 | if (Is_invalidtrap_enabled()) { | ||
521 | return(INVALIDEXCEPTION); | ||
522 | } | ||
523 | Set_invalidflag(); | ||
524 | inexact = FALSE; | ||
525 | } | ||
526 | } | ||
527 | } | ||
528 | } | ||
529 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
530 | if (inexact) { | ||
531 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
532 | else Set_inexactflag(); | ||
533 | } | ||
534 | return(NOEXCEPTION); | ||
535 | } | ||
536 | |||
diff --git a/arch/parisc/math-emu/fcnvfut.c b/arch/parisc/math-emu/fcnvfut.c new file mode 100644 index 000000000000..4176a44ed750 --- /dev/null +++ b/arch/parisc/math-emu/fcnvfut.c | |||
@@ -0,0 +1,332 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/fcnvfut.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Floating-point to Unsigned Fixed-point Converts with Truncation | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status) | ||
32 | * dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status) | ||
33 | * sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status) | ||
34 | * sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status) | ||
35 | * | ||
36 | * Internal Interfaces: | ||
37 | * | ||
38 | * Theory: | ||
39 | * <<please update with a overview of the operation of this file>> | ||
40 | * | ||
41 | * END_DESC | ||
42 | */ | ||
43 | |||
44 | |||
45 | #include "float.h" | ||
46 | #include "sgl_float.h" | ||
47 | #include "dbl_float.h" | ||
48 | #include "cnv_float.h" | ||
49 | |||
50 | /************************************************************************ | ||
51 | * Floating-point to Unsigned Fixed-point Converts with Truncation * | ||
52 | ************************************************************************/ | ||
53 | |||
54 | /* | ||
55 | * Convert single floating-point to single fixed-point format | ||
56 | * with truncated result | ||
57 | */ | ||
58 | /*ARGSUSED*/ | ||
59 | int | ||
60 | sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr, | ||
61 | unsigned int *dstptr, unsigned int *status) | ||
62 | { | ||
63 | register unsigned int src, result; | ||
64 | register int src_exponent; | ||
65 | |||
66 | src = *srcptr; | ||
67 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
68 | |||
69 | /* | ||
70 | * Test for overflow | ||
71 | */ | ||
72 | if (src_exponent > SGL_FX_MAX_EXP + 1) { | ||
73 | if (Sgl_isone_sign(src)) { | ||
74 | result = 0; | ||
75 | } else { | ||
76 | result = 0xffffffff; | ||
77 | } | ||
78 | if (Is_invalidtrap_enabled()) { | ||
79 | return(INVALIDEXCEPTION); | ||
80 | } | ||
81 | Set_invalidflag(); | ||
82 | *dstptr = result; | ||
83 | return(NOEXCEPTION); | ||
84 | } | ||
85 | /* | ||
86 | * Generate result | ||
87 | */ | ||
88 | if (src_exponent >= 0) { | ||
89 | /* | ||
90 | * Check sign. | ||
91 | * If negative, trap unimplemented. | ||
92 | */ | ||
93 | if (Sgl_isone_sign(src)) { | ||
94 | result = 0; | ||
95 | if (Is_invalidtrap_enabled()) { | ||
96 | return(INVALIDEXCEPTION); | ||
97 | } | ||
98 | Set_invalidflag(); | ||
99 | *dstptr = result; | ||
100 | return(NOEXCEPTION); | ||
101 | } | ||
102 | Sgl_clear_signexponent_set_hidden(src); | ||
103 | Suint_from_sgl_mantissa(src,src_exponent,result); | ||
104 | *dstptr = result; | ||
105 | |||
106 | /* check for inexact */ | ||
107 | if (Sgl_isinexact_to_unsigned(src,src_exponent)) { | ||
108 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
109 | else Set_inexactflag(); | ||
110 | } | ||
111 | } | ||
112 | else { | ||
113 | *dstptr = 0; | ||
114 | |||
115 | /* check for inexact */ | ||
116 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
117 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
118 | else Set_inexactflag(); | ||
119 | } | ||
120 | } | ||
121 | return(NOEXCEPTION); | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Single Floating-point to Double Unsigned Fixed | ||
126 | */ | ||
127 | /*ARGSUSED*/ | ||
128 | int | ||
129 | sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr, | ||
130 | dbl_unsigned * dstptr, unsigned int *status) | ||
131 | { | ||
132 | register int src_exponent; | ||
133 | register unsigned int src, resultp1, resultp2; | ||
134 | |||
135 | src = *srcptr; | ||
136 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
137 | |||
138 | /* | ||
139 | * Test for overflow | ||
140 | */ | ||
141 | if (src_exponent > DBL_FX_MAX_EXP + 1) { | ||
142 | if (Sgl_isone_sign(src)) { | ||
143 | resultp1 = resultp2 = 0; | ||
144 | } else { | ||
145 | resultp1 = resultp2 = 0xffffffff; | ||
146 | } | ||
147 | if (Is_invalidtrap_enabled()) { | ||
148 | return(INVALIDEXCEPTION); | ||
149 | } | ||
150 | Set_invalidflag(); | ||
151 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
152 | return(NOEXCEPTION); | ||
153 | } | ||
154 | /* | ||
155 | * Generate result | ||
156 | */ | ||
157 | if (src_exponent >= 0) { | ||
158 | /* | ||
159 | * Check sign. | ||
160 | * If negative, trap unimplemented. | ||
161 | */ | ||
162 | if (Sgl_isone_sign(src)) { | ||
163 | resultp1 = resultp2 = 0; | ||
164 | if (Is_invalidtrap_enabled()) { | ||
165 | return(INVALIDEXCEPTION); | ||
166 | } | ||
167 | Set_invalidflag(); | ||
168 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
169 | return(NOEXCEPTION); | ||
170 | } | ||
171 | Sgl_clear_signexponent_set_hidden(src); | ||
172 | Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2); | ||
173 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
174 | |||
175 | /* check for inexact */ | ||
176 | if (Sgl_isinexact_to_unsigned(src,src_exponent)) { | ||
177 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
178 | else Set_inexactflag(); | ||
179 | } | ||
180 | } | ||
181 | else { | ||
182 | Duint_setzero(resultp1,resultp2); | ||
183 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
184 | |||
185 | /* check for inexact */ | ||
186 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
187 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
188 | else Set_inexactflag(); | ||
189 | } | ||
190 | } | ||
191 | return(NOEXCEPTION); | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * Double Floating-point to Single Unsigned Fixed | ||
196 | */ | ||
197 | /*ARGSUSED*/ | ||
198 | int | ||
199 | dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr, | ||
200 | unsigned int *dstptr, unsigned int *status) | ||
201 | { | ||
202 | register unsigned int srcp1, srcp2, result; | ||
203 | register int src_exponent; | ||
204 | |||
205 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
206 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
207 | |||
208 | /* | ||
209 | * Test for overflow | ||
210 | */ | ||
211 | if (src_exponent > SGL_FX_MAX_EXP + 1) { | ||
212 | if (Dbl_isone_sign(srcp1)) { | ||
213 | result = 0; | ||
214 | } else { | ||
215 | result = 0xffffffff; | ||
216 | } | ||
217 | if (Is_invalidtrap_enabled()) { | ||
218 | return(INVALIDEXCEPTION); | ||
219 | } | ||
220 | Set_invalidflag(); | ||
221 | *dstptr = result; | ||
222 | return(NOEXCEPTION); | ||
223 | } | ||
224 | /* | ||
225 | * Generate result | ||
226 | */ | ||
227 | if (src_exponent >= 0) { | ||
228 | /* | ||
229 | * Check sign. | ||
230 | * If negative, trap unimplemented. | ||
231 | */ | ||
232 | if (Dbl_isone_sign(srcp1)) { | ||
233 | result = 0; | ||
234 | if (Is_invalidtrap_enabled()) { | ||
235 | return(INVALIDEXCEPTION); | ||
236 | } | ||
237 | Set_invalidflag(); | ||
238 | *dstptr = result; | ||
239 | return(NOEXCEPTION); | ||
240 | } | ||
241 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
242 | Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result); | ||
243 | *dstptr = result; | ||
244 | |||
245 | /* check for inexact */ | ||
246 | if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { | ||
247 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
248 | else Set_inexactflag(); | ||
249 | } | ||
250 | } | ||
251 | else { | ||
252 | *dstptr = 0; | ||
253 | |||
254 | /* check for inexact */ | ||
255 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
256 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
257 | else Set_inexactflag(); | ||
258 | } | ||
259 | } | ||
260 | return(NOEXCEPTION); | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * Double Floating-point to Double Unsigned Fixed | ||
265 | */ | ||
266 | /*ARGSUSED*/ | ||
267 | int | ||
268 | dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr, | ||
269 | dbl_unsigned * dstptr, unsigned int *status) | ||
270 | { | ||
271 | register int src_exponent; | ||
272 | register unsigned int srcp1, srcp2, resultp1, resultp2; | ||
273 | |||
274 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
275 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
276 | |||
277 | /* | ||
278 | * Test for overflow | ||
279 | */ | ||
280 | if (src_exponent > DBL_FX_MAX_EXP + 1) { | ||
281 | if (Dbl_isone_sign(srcp1)) { | ||
282 | resultp1 = resultp2 = 0; | ||
283 | } else { | ||
284 | resultp1 = resultp2 = 0xffffffff; | ||
285 | } | ||
286 | if (Is_invalidtrap_enabled()) { | ||
287 | return(INVALIDEXCEPTION); | ||
288 | } | ||
289 | Set_invalidflag(); | ||
290 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
291 | return(NOEXCEPTION); | ||
292 | } | ||
293 | /* | ||
294 | * Generate result | ||
295 | */ | ||
296 | if (src_exponent >= 0) { | ||
297 | /* | ||
298 | * Check sign. | ||
299 | * If negative, trap unimplemented. | ||
300 | */ | ||
301 | if (Dbl_isone_sign(srcp1)) { | ||
302 | resultp1 = resultp2 = 0; | ||
303 | if (Is_invalidtrap_enabled()) { | ||
304 | return(INVALIDEXCEPTION); | ||
305 | } | ||
306 | Set_invalidflag(); | ||
307 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
308 | return(NOEXCEPTION); | ||
309 | } | ||
310 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
311 | Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent, | ||
312 | resultp1,resultp2); | ||
313 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
314 | |||
315 | /* check for inexact */ | ||
316 | if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { | ||
317 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
318 | else Set_inexactflag(); | ||
319 | } | ||
320 | } | ||
321 | else { | ||
322 | Duint_setzero(resultp1,resultp2); | ||
323 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
324 | |||
325 | /* check for inexact */ | ||
326 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
327 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
328 | else Set_inexactflag(); | ||
329 | } | ||
330 | } | ||
331 | return(NOEXCEPTION); | ||
332 | } | ||
diff --git a/arch/parisc/math-emu/fcnvfx.c b/arch/parisc/math-emu/fcnvfx.c new file mode 100644 index 000000000000..d6475bddb507 --- /dev/null +++ b/arch/parisc/math-emu/fcnvfx.c | |||
@@ -0,0 +1,501 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/fcnvfx.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single Floating-point to Single Fixed-point | ||
29 | * Single Floating-point to Double Fixed-point | ||
30 | * Double Floating-point to Single Fixed-point | ||
31 | * Double Floating-point to Double Fixed-point | ||
32 | * | ||
33 | * External Interfaces: | ||
34 | * dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) | ||
35 | * dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) | ||
36 | * sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) | ||
37 | * sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) | ||
38 | * | ||
39 | * Internal Interfaces: | ||
40 | * | ||
41 | * Theory: | ||
42 | * <<please update with a overview of the operation of this file>> | ||
43 | * | ||
44 | * END_DESC | ||
45 | */ | ||
46 | |||
47 | |||
48 | #include "float.h" | ||
49 | #include "sgl_float.h" | ||
50 | #include "dbl_float.h" | ||
51 | #include "cnv_float.h" | ||
52 | |||
53 | /* | ||
54 | * Single Floating-point to Single Fixed-point | ||
55 | */ | ||
56 | /*ARGSUSED*/ | ||
57 | int | ||
58 | sgl_to_sgl_fcnvfx( | ||
59 | sgl_floating_point *srcptr, | ||
60 | sgl_floating_point *nullptr, | ||
61 | int *dstptr, | ||
62 | sgl_floating_point *status) | ||
63 | { | ||
64 | register unsigned int src, temp; | ||
65 | register int src_exponent, result; | ||
66 | register boolean inexact = FALSE; | ||
67 | |||
68 | src = *srcptr; | ||
69 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
70 | |||
71 | /* | ||
72 | * Test for overflow | ||
73 | */ | ||
74 | if (src_exponent > SGL_FX_MAX_EXP) { | ||
75 | /* check for MININT */ | ||
76 | if ((src_exponent > SGL_FX_MAX_EXP + 1) || | ||
77 | Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { | ||
78 | if (Sgl_iszero_sign(src)) result = 0x7fffffff; | ||
79 | else result = 0x80000000; | ||
80 | |||
81 | if (Is_invalidtrap_enabled()) { | ||
82 | return(INVALIDEXCEPTION); | ||
83 | } | ||
84 | Set_invalidflag(); | ||
85 | *dstptr = result; | ||
86 | return(NOEXCEPTION); | ||
87 | } | ||
88 | } | ||
89 | /* | ||
90 | * Generate result | ||
91 | */ | ||
92 | if (src_exponent >= 0) { | ||
93 | temp = src; | ||
94 | Sgl_clear_signexponent_set_hidden(temp); | ||
95 | Int_from_sgl_mantissa(temp,src_exponent); | ||
96 | if (Sgl_isone_sign(src)) result = -Sgl_all(temp); | ||
97 | else result = Sgl_all(temp); | ||
98 | |||
99 | /* check for inexact */ | ||
100 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
101 | inexact = TRUE; | ||
102 | /* round result */ | ||
103 | switch (Rounding_mode()) { | ||
104 | case ROUNDPLUS: | ||
105 | if (Sgl_iszero_sign(src)) result++; | ||
106 | break; | ||
107 | case ROUNDMINUS: | ||
108 | if (Sgl_isone_sign(src)) result--; | ||
109 | break; | ||
110 | case ROUNDNEAREST: | ||
111 | if (Sgl_isone_roundbit(src,src_exponent)) { | ||
112 | if (Sgl_isone_stickybit(src,src_exponent) | ||
113 | || (Sgl_isone_lowmantissa(temp))) | ||
114 | if (Sgl_iszero_sign(src)) result++; | ||
115 | else result--; | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | else { | ||
121 | result = 0; | ||
122 | |||
123 | /* check for inexact */ | ||
124 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
125 | inexact = TRUE; | ||
126 | /* round result */ | ||
127 | switch (Rounding_mode()) { | ||
128 | case ROUNDPLUS: | ||
129 | if (Sgl_iszero_sign(src)) result++; | ||
130 | break; | ||
131 | case ROUNDMINUS: | ||
132 | if (Sgl_isone_sign(src)) result--; | ||
133 | break; | ||
134 | case ROUNDNEAREST: | ||
135 | if (src_exponent == -1) | ||
136 | if (Sgl_isnotzero_mantissa(src)) | ||
137 | if (Sgl_iszero_sign(src)) result++; | ||
138 | else result--; | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | *dstptr = result; | ||
143 | if (inexact) { | ||
144 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
145 | else Set_inexactflag(); | ||
146 | } | ||
147 | return(NOEXCEPTION); | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * Single Floating-point to Double Fixed-point | ||
152 | */ | ||
153 | /*ARGSUSED*/ | ||
154 | int | ||
155 | sgl_to_dbl_fcnvfx( | ||
156 | sgl_floating_point *srcptr, | ||
157 | unsigned int *nullptr, | ||
158 | dbl_integer *dstptr, | ||
159 | unsigned int *status) | ||
160 | { | ||
161 | register int src_exponent, resultp1; | ||
162 | register unsigned int src, temp, resultp2; | ||
163 | register boolean inexact = FALSE; | ||
164 | |||
165 | src = *srcptr; | ||
166 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
167 | |||
168 | /* | ||
169 | * Test for overflow | ||
170 | */ | ||
171 | if (src_exponent > DBL_FX_MAX_EXP) { | ||
172 | /* check for MININT */ | ||
173 | if ((src_exponent > DBL_FX_MAX_EXP + 1) || | ||
174 | Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { | ||
175 | if (Sgl_iszero_sign(src)) { | ||
176 | resultp1 = 0x7fffffff; | ||
177 | resultp2 = 0xffffffff; | ||
178 | } | ||
179 | else { | ||
180 | resultp1 = 0x80000000; | ||
181 | resultp2 = 0; | ||
182 | } | ||
183 | if (Is_invalidtrap_enabled()) { | ||
184 | return(INVALIDEXCEPTION); | ||
185 | } | ||
186 | Set_invalidflag(); | ||
187 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
188 | return(NOEXCEPTION); | ||
189 | } | ||
190 | Dint_set_minint(resultp1,resultp2); | ||
191 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
192 | return(NOEXCEPTION); | ||
193 | } | ||
194 | /* | ||
195 | * Generate result | ||
196 | */ | ||
197 | if (src_exponent >= 0) { | ||
198 | temp = src; | ||
199 | Sgl_clear_signexponent_set_hidden(temp); | ||
200 | Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2); | ||
201 | if (Sgl_isone_sign(src)) { | ||
202 | Dint_setone_sign(resultp1,resultp2); | ||
203 | } | ||
204 | |||
205 | /* check for inexact */ | ||
206 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
207 | inexact = TRUE; | ||
208 | /* round result */ | ||
209 | switch (Rounding_mode()) { | ||
210 | case ROUNDPLUS: | ||
211 | if (Sgl_iszero_sign(src)) { | ||
212 | Dint_increment(resultp1,resultp2); | ||
213 | } | ||
214 | break; | ||
215 | case ROUNDMINUS: | ||
216 | if (Sgl_isone_sign(src)) { | ||
217 | Dint_decrement(resultp1,resultp2); | ||
218 | } | ||
219 | break; | ||
220 | case ROUNDNEAREST: | ||
221 | if (Sgl_isone_roundbit(src,src_exponent)) | ||
222 | if (Sgl_isone_stickybit(src,src_exponent) || | ||
223 | (Dint_isone_lowp2(resultp2))) | ||
224 | if (Sgl_iszero_sign(src)) { | ||
225 | Dint_increment(resultp1,resultp2); | ||
226 | } | ||
227 | else { | ||
228 | Dint_decrement(resultp1,resultp2); | ||
229 | } | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | else { | ||
234 | Dint_setzero(resultp1,resultp2); | ||
235 | |||
236 | /* check for inexact */ | ||
237 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
238 | inexact = TRUE; | ||
239 | /* round result */ | ||
240 | switch (Rounding_mode()) { | ||
241 | case ROUNDPLUS: | ||
242 | if (Sgl_iszero_sign(src)) { | ||
243 | Dint_increment(resultp1,resultp2); | ||
244 | } | ||
245 | break; | ||
246 | case ROUNDMINUS: | ||
247 | if (Sgl_isone_sign(src)) { | ||
248 | Dint_decrement(resultp1,resultp2); | ||
249 | } | ||
250 | break; | ||
251 | case ROUNDNEAREST: | ||
252 | if (src_exponent == -1) | ||
253 | if (Sgl_isnotzero_mantissa(src)) | ||
254 | if (Sgl_iszero_sign(src)) { | ||
255 | Dint_increment(resultp1,resultp2); | ||
256 | } | ||
257 | else { | ||
258 | Dint_decrement(resultp1,resultp2); | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
264 | if (inexact) { | ||
265 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
266 | else Set_inexactflag(); | ||
267 | } | ||
268 | return(NOEXCEPTION); | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * Double Floating-point to Single Fixed-point | ||
273 | */ | ||
274 | /*ARGSUSED*/ | ||
275 | int | ||
276 | dbl_to_sgl_fcnvfx( | ||
277 | dbl_floating_point *srcptr, | ||
278 | unsigned int *nullptr, | ||
279 | int *dstptr, | ||
280 | unsigned int *status) | ||
281 | { | ||
282 | register unsigned int srcp1,srcp2, tempp1,tempp2; | ||
283 | register int src_exponent, result; | ||
284 | register boolean inexact = FALSE; | ||
285 | |||
286 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
287 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
288 | |||
289 | /* | ||
290 | * Test for overflow | ||
291 | */ | ||
292 | if (src_exponent > SGL_FX_MAX_EXP) { | ||
293 | /* check for MININT */ | ||
294 | if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) { | ||
295 | if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; | ||
296 | else result = 0x80000000; | ||
297 | |||
298 | if (Is_invalidtrap_enabled()) { | ||
299 | return(INVALIDEXCEPTION); | ||
300 | } | ||
301 | Set_invalidflag(); | ||
302 | *dstptr = result; | ||
303 | return(NOEXCEPTION); | ||
304 | } | ||
305 | } | ||
306 | /* | ||
307 | * Generate result | ||
308 | */ | ||
309 | if (src_exponent >= 0) { | ||
310 | tempp1 = srcp1; | ||
311 | tempp2 = srcp2; | ||
312 | Dbl_clear_signexponent_set_hidden(tempp1); | ||
313 | Int_from_dbl_mantissa(tempp1,tempp2,src_exponent); | ||
314 | if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP)) | ||
315 | result = -Dbl_allp1(tempp1); | ||
316 | else result = Dbl_allp1(tempp1); | ||
317 | |||
318 | /* check for inexact */ | ||
319 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
320 | inexact = TRUE; | ||
321 | /* round result */ | ||
322 | switch (Rounding_mode()) { | ||
323 | case ROUNDPLUS: | ||
324 | if (Dbl_iszero_sign(srcp1)) result++; | ||
325 | break; | ||
326 | case ROUNDMINUS: | ||
327 | if (Dbl_isone_sign(srcp1)) result--; | ||
328 | break; | ||
329 | case ROUNDNEAREST: | ||
330 | if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) | ||
331 | if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || | ||
332 | (Dbl_isone_lowmantissap1(tempp1))) | ||
333 | if (Dbl_iszero_sign(srcp1)) result++; | ||
334 | else result--; | ||
335 | } | ||
336 | /* check for overflow */ | ||
337 | if ((Dbl_iszero_sign(srcp1) && result < 0) || | ||
338 | (Dbl_isone_sign(srcp1) && result > 0)) { | ||
339 | |||
340 | if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; | ||
341 | else result = 0x80000000; | ||
342 | |||
343 | if (Is_invalidtrap_enabled()) { | ||
344 | return(INVALIDEXCEPTION); | ||
345 | } | ||
346 | Set_invalidflag(); | ||
347 | *dstptr = result; | ||
348 | return(NOEXCEPTION); | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | else { | ||
353 | result = 0; | ||
354 | |||
355 | /* check for inexact */ | ||
356 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
357 | inexact = TRUE; | ||
358 | /* round result */ | ||
359 | switch (Rounding_mode()) { | ||
360 | case ROUNDPLUS: | ||
361 | if (Dbl_iszero_sign(srcp1)) result++; | ||
362 | break; | ||
363 | case ROUNDMINUS: | ||
364 | if (Dbl_isone_sign(srcp1)) result--; | ||
365 | break; | ||
366 | case ROUNDNEAREST: | ||
367 | if (src_exponent == -1) | ||
368 | if (Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
369 | if (Dbl_iszero_sign(srcp1)) result++; | ||
370 | else result--; | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | *dstptr = result; | ||
375 | if (inexact) { | ||
376 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
377 | else Set_inexactflag(); | ||
378 | } | ||
379 | return(NOEXCEPTION); | ||
380 | } | ||
381 | |||
382 | /* | ||
383 | * Double Floating-point to Double Fixed-point | ||
384 | */ | ||
385 | /*ARGSUSED*/ | ||
386 | int | ||
387 | dbl_to_dbl_fcnvfx( | ||
388 | dbl_floating_point *srcptr, | ||
389 | unsigned int *nullptr, | ||
390 | dbl_integer *dstptr, | ||
391 | unsigned int *status) | ||
392 | { | ||
393 | register int src_exponent, resultp1; | ||
394 | register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2; | ||
395 | register boolean inexact = FALSE; | ||
396 | |||
397 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
398 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
399 | |||
400 | /* | ||
401 | * Test for overflow | ||
402 | */ | ||
403 | if (src_exponent > DBL_FX_MAX_EXP) { | ||
404 | /* check for MININT */ | ||
405 | if ((src_exponent > DBL_FX_MAX_EXP + 1) || | ||
406 | Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) { | ||
407 | if (Dbl_iszero_sign(srcp1)) { | ||
408 | resultp1 = 0x7fffffff; | ||
409 | resultp2 = 0xffffffff; | ||
410 | } | ||
411 | else { | ||
412 | resultp1 = 0x80000000; | ||
413 | resultp2 = 0; | ||
414 | } | ||
415 | if (Is_invalidtrap_enabled()) { | ||
416 | return(INVALIDEXCEPTION); | ||
417 | } | ||
418 | Set_invalidflag(); | ||
419 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
420 | return(NOEXCEPTION); | ||
421 | } | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * Generate result | ||
426 | */ | ||
427 | if (src_exponent >= 0) { | ||
428 | tempp1 = srcp1; | ||
429 | tempp2 = srcp2; | ||
430 | Dbl_clear_signexponent_set_hidden(tempp1); | ||
431 | Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1, | ||
432 | resultp2); | ||
433 | if (Dbl_isone_sign(srcp1)) { | ||
434 | Dint_setone_sign(resultp1,resultp2); | ||
435 | } | ||
436 | |||
437 | /* check for inexact */ | ||
438 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
439 | inexact = TRUE; | ||
440 | /* round result */ | ||
441 | switch (Rounding_mode()) { | ||
442 | case ROUNDPLUS: | ||
443 | if (Dbl_iszero_sign(srcp1)) { | ||
444 | Dint_increment(resultp1,resultp2); | ||
445 | } | ||
446 | break; | ||
447 | case ROUNDMINUS: | ||
448 | if (Dbl_isone_sign(srcp1)) { | ||
449 | Dint_decrement(resultp1,resultp2); | ||
450 | } | ||
451 | break; | ||
452 | case ROUNDNEAREST: | ||
453 | if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) | ||
454 | if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || | ||
455 | (Dint_isone_lowp2(resultp2))) | ||
456 | if (Dbl_iszero_sign(srcp1)) { | ||
457 | Dint_increment(resultp1,resultp2); | ||
458 | } | ||
459 | else { | ||
460 | Dint_decrement(resultp1,resultp2); | ||
461 | } | ||
462 | } | ||
463 | } | ||
464 | } | ||
465 | else { | ||
466 | Dint_setzero(resultp1,resultp2); | ||
467 | |||
468 | /* check for inexact */ | ||
469 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
470 | inexact = TRUE; | ||
471 | /* round result */ | ||
472 | switch (Rounding_mode()) { | ||
473 | case ROUNDPLUS: | ||
474 | if (Dbl_iszero_sign(srcp1)) { | ||
475 | Dint_increment(resultp1,resultp2); | ||
476 | } | ||
477 | break; | ||
478 | case ROUNDMINUS: | ||
479 | if (Dbl_isone_sign(srcp1)) { | ||
480 | Dint_decrement(resultp1,resultp2); | ||
481 | } | ||
482 | break; | ||
483 | case ROUNDNEAREST: | ||
484 | if (src_exponent == -1) | ||
485 | if (Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
486 | if (Dbl_iszero_sign(srcp1)) { | ||
487 | Dint_increment(resultp1,resultp2); | ||
488 | } | ||
489 | else { | ||
490 | Dint_decrement(resultp1,resultp2); | ||
491 | } | ||
492 | } | ||
493 | } | ||
494 | } | ||
495 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
496 | if (inexact) { | ||
497 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
498 | else Set_inexactflag(); | ||
499 | } | ||
500 | return(NOEXCEPTION); | ||
501 | } | ||
diff --git a/arch/parisc/math-emu/fcnvfxt.c b/arch/parisc/math-emu/fcnvfxt.c new file mode 100644 index 000000000000..8b9010c4690e --- /dev/null +++ b/arch/parisc/math-emu/fcnvfxt.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/fcnvfxt.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single Floating-point to Single Fixed-point /w truncated result | ||
29 | * Single Floating-point to Double Fixed-point /w truncated result | ||
30 | * Double Floating-point to Single Fixed-point /w truncated result | ||
31 | * Double Floating-point to Double Fixed-point /w truncated result | ||
32 | * | ||
33 | * External Interfaces: | ||
34 | * dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status) | ||
35 | * dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status) | ||
36 | * sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status) | ||
37 | * sgl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status) | ||
38 | * | ||
39 | * Internal Interfaces: | ||
40 | * | ||
41 | * Theory: | ||
42 | * <<please update with a overview of the operation of this file>> | ||
43 | * | ||
44 | * END_DESC | ||
45 | */ | ||
46 | |||
47 | |||
48 | #include "float.h" | ||
49 | #include "sgl_float.h" | ||
50 | #include "dbl_float.h" | ||
51 | #include "cnv_float.h" | ||
52 | |||
53 | /* | ||
54 | * Convert single floating-point to single fixed-point format | ||
55 | * with truncated result | ||
56 | */ | ||
57 | /*ARGSUSED*/ | ||
58 | int | ||
59 | sgl_to_sgl_fcnvfxt( | ||
60 | sgl_floating_point *srcptr, | ||
61 | unsigned int *nullptr, | ||
62 | int *dstptr, | ||
63 | unsigned int *status) | ||
64 | { | ||
65 | register unsigned int src, temp; | ||
66 | register int src_exponent, result; | ||
67 | |||
68 | src = *srcptr; | ||
69 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
70 | |||
71 | /* | ||
72 | * Test for overflow | ||
73 | */ | ||
74 | if (src_exponent > SGL_FX_MAX_EXP) { | ||
75 | /* check for MININT */ | ||
76 | if ((src_exponent > SGL_FX_MAX_EXP + 1) || | ||
77 | Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { | ||
78 | if (Sgl_iszero_sign(src)) result = 0x7fffffff; | ||
79 | else result = 0x80000000; | ||
80 | |||
81 | if (Is_invalidtrap_enabled()) { | ||
82 | return(INVALIDEXCEPTION); | ||
83 | } | ||
84 | Set_invalidflag(); | ||
85 | *dstptr = result; | ||
86 | return(NOEXCEPTION); | ||
87 | } | ||
88 | } | ||
89 | /* | ||
90 | * Generate result | ||
91 | */ | ||
92 | if (src_exponent >= 0) { | ||
93 | temp = src; | ||
94 | Sgl_clear_signexponent_set_hidden(temp); | ||
95 | Int_from_sgl_mantissa(temp,src_exponent); | ||
96 | if (Sgl_isone_sign(src)) result = -Sgl_all(temp); | ||
97 | else result = Sgl_all(temp); | ||
98 | *dstptr = result; | ||
99 | |||
100 | /* check for inexact */ | ||
101 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
102 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
103 | else Set_inexactflag(); | ||
104 | } | ||
105 | } | ||
106 | else { | ||
107 | *dstptr = 0; | ||
108 | |||
109 | /* check for inexact */ | ||
110 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
111 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
112 | else Set_inexactflag(); | ||
113 | } | ||
114 | } | ||
115 | return(NOEXCEPTION); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Single Floating-point to Double Fixed-point | ||
120 | */ | ||
121 | /*ARGSUSED*/ | ||
122 | int | ||
123 | sgl_to_dbl_fcnvfxt( | ||
124 | sgl_floating_point *srcptr, | ||
125 | unsigned int *nullptr, | ||
126 | dbl_integer *dstptr, | ||
127 | unsigned int *status) | ||
128 | { | ||
129 | register int src_exponent, resultp1; | ||
130 | register unsigned int src, temp, resultp2; | ||
131 | |||
132 | src = *srcptr; | ||
133 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
134 | |||
135 | /* | ||
136 | * Test for overflow | ||
137 | */ | ||
138 | if (src_exponent > DBL_FX_MAX_EXP) { | ||
139 | /* check for MININT */ | ||
140 | if ((src_exponent > DBL_FX_MAX_EXP + 1) || | ||
141 | Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { | ||
142 | if (Sgl_iszero_sign(src)) { | ||
143 | resultp1 = 0x7fffffff; | ||
144 | resultp2 = 0xffffffff; | ||
145 | } | ||
146 | else { | ||
147 | resultp1 = 0x80000000; | ||
148 | resultp2 = 0; | ||
149 | } | ||
150 | if (Is_invalidtrap_enabled()) { | ||
151 | return(INVALIDEXCEPTION); | ||
152 | } | ||
153 | Set_invalidflag(); | ||
154 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
155 | return(NOEXCEPTION); | ||
156 | } | ||
157 | Dint_set_minint(resultp1,resultp2); | ||
158 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
159 | return(NOEXCEPTION); | ||
160 | } | ||
161 | /* | ||
162 | * Generate result | ||
163 | */ | ||
164 | if (src_exponent >= 0) { | ||
165 | temp = src; | ||
166 | Sgl_clear_signexponent_set_hidden(temp); | ||
167 | Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2); | ||
168 | if (Sgl_isone_sign(src)) { | ||
169 | Dint_setone_sign(resultp1,resultp2); | ||
170 | } | ||
171 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
172 | |||
173 | /* check for inexact */ | ||
174 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
175 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
176 | else Set_inexactflag(); | ||
177 | } | ||
178 | } | ||
179 | else { | ||
180 | Dint_setzero(resultp1,resultp2); | ||
181 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
182 | |||
183 | /* check for inexact */ | ||
184 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
185 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
186 | else Set_inexactflag(); | ||
187 | } | ||
188 | } | ||
189 | return(NOEXCEPTION); | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * Double Floating-point to Single Fixed-point | ||
194 | */ | ||
195 | /*ARGSUSED*/ | ||
196 | int | ||
197 | dbl_to_sgl_fcnvfxt( | ||
198 | dbl_floating_point *srcptr, | ||
199 | unsigned int *nullptr, | ||
200 | int *dstptr, | ||
201 | unsigned int *status) | ||
202 | { | ||
203 | register unsigned int srcp1, srcp2, tempp1, tempp2; | ||
204 | register int src_exponent, result; | ||
205 | |||
206 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
207 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
208 | |||
209 | /* | ||
210 | * Test for overflow | ||
211 | */ | ||
212 | if (src_exponent > SGL_FX_MAX_EXP) { | ||
213 | /* check for MININT */ | ||
214 | if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) { | ||
215 | if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; | ||
216 | else result = 0x80000000; | ||
217 | |||
218 | if (Is_invalidtrap_enabled()) { | ||
219 | return(INVALIDEXCEPTION); | ||
220 | } | ||
221 | Set_invalidflag(); | ||
222 | *dstptr = result; | ||
223 | return(NOEXCEPTION); | ||
224 | } | ||
225 | } | ||
226 | /* | ||
227 | * Generate result | ||
228 | */ | ||
229 | if (src_exponent >= 0) { | ||
230 | tempp1 = srcp1; | ||
231 | tempp2 = srcp2; | ||
232 | Dbl_clear_signexponent_set_hidden(tempp1); | ||
233 | Int_from_dbl_mantissa(tempp1,tempp2,src_exponent); | ||
234 | if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP)) | ||
235 | result = -Dbl_allp1(tempp1); | ||
236 | else result = Dbl_allp1(tempp1); | ||
237 | *dstptr = result; | ||
238 | |||
239 | /* check for inexact */ | ||
240 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
241 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
242 | else Set_inexactflag(); | ||
243 | } | ||
244 | } | ||
245 | else { | ||
246 | *dstptr = 0; | ||
247 | |||
248 | /* check for inexact */ | ||
249 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
250 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
251 | else Set_inexactflag(); | ||
252 | } | ||
253 | } | ||
254 | return(NOEXCEPTION); | ||
255 | } | ||
256 | |||
257 | /* | ||
258 | * Double Floating-point to Double Fixed-point | ||
259 | */ | ||
260 | /*ARGSUSED*/ | ||
261 | int | ||
262 | dbl_to_dbl_fcnvfxt( | ||
263 | dbl_floating_point *srcptr, | ||
264 | unsigned int *nullptr, | ||
265 | dbl_integer *dstptr, | ||
266 | unsigned int *status) | ||
267 | { | ||
268 | register int src_exponent, resultp1; | ||
269 | register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2; | ||
270 | |||
271 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
272 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
273 | |||
274 | /* | ||
275 | * Test for overflow | ||
276 | */ | ||
277 | if (src_exponent > DBL_FX_MAX_EXP) { | ||
278 | /* check for MININT */ | ||
279 | if ((src_exponent > DBL_FX_MAX_EXP + 1) || | ||
280 | Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) { | ||
281 | if (Dbl_iszero_sign(srcp1)) { | ||
282 | resultp1 = 0x7fffffff; | ||
283 | resultp2 = 0xffffffff; | ||
284 | } | ||
285 | else { | ||
286 | resultp1 = 0x80000000; | ||
287 | resultp2 = 0; | ||
288 | } | ||
289 | if (Is_invalidtrap_enabled()) { | ||
290 | return(INVALIDEXCEPTION); | ||
291 | } | ||
292 | Set_invalidflag(); | ||
293 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
294 | return(NOEXCEPTION); | ||
295 | } | ||
296 | } | ||
297 | /* | ||
298 | * Generate result | ||
299 | */ | ||
300 | if (src_exponent >= 0) { | ||
301 | tempp1 = srcp1; | ||
302 | tempp2 = srcp2; | ||
303 | Dbl_clear_signexponent_set_hidden(tempp1); | ||
304 | Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent, | ||
305 | resultp1,resultp2); | ||
306 | if (Dbl_isone_sign(srcp1)) { | ||
307 | Dint_setone_sign(resultp1,resultp2); | ||
308 | } | ||
309 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
310 | |||
311 | /* check for inexact */ | ||
312 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
313 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
314 | else Set_inexactflag(); | ||
315 | } | ||
316 | } | ||
317 | else { | ||
318 | Dint_setzero(resultp1,resultp2); | ||
319 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
320 | |||
321 | /* check for inexact */ | ||
322 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
323 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
324 | else Set_inexactflag(); | ||
325 | } | ||
326 | } | ||
327 | return(NOEXCEPTION); | ||
328 | } | ||
diff --git a/arch/parisc/math-emu/fcnvuf.c b/arch/parisc/math-emu/fcnvuf.c new file mode 100644 index 000000000000..5e68189fee22 --- /dev/null +++ b/arch/parisc/math-emu/fcnvuf.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/fcnvuf.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Fixed point to Floating-point Converts | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) | ||
32 | * dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) | ||
33 | * sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) | ||
34 | * sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) | ||
35 | * | ||
36 | * Internal Interfaces: | ||
37 | * | ||
38 | * Theory: | ||
39 | * <<please update with a overview of the operation of this file>> | ||
40 | * | ||
41 | * END_DESC | ||
42 | */ | ||
43 | |||
44 | |||
45 | #include "float.h" | ||
46 | #include "sgl_float.h" | ||
47 | #include "dbl_float.h" | ||
48 | #include "cnv_float.h" | ||
49 | |||
50 | /************************************************************************ | ||
51 | * Fixed point to Floating-point Converts * | ||
52 | ************************************************************************/ | ||
53 | |||
54 | /* | ||
55 | * Convert Single Unsigned Fixed to Single Floating-point format | ||
56 | */ | ||
57 | |||
58 | int | ||
59 | sgl_to_sgl_fcnvuf( | ||
60 | unsigned int *srcptr, | ||
61 | unsigned int *nullptr, | ||
62 | sgl_floating_point *dstptr, | ||
63 | unsigned int *status) | ||
64 | { | ||
65 | register unsigned int src, result = 0; | ||
66 | register int dst_exponent; | ||
67 | |||
68 | src = *srcptr; | ||
69 | |||
70 | /* Check for zero */ | ||
71 | if (src == 0) { | ||
72 | Sgl_setzero(result); | ||
73 | *dstptr = result; | ||
74 | return(NOEXCEPTION); | ||
75 | } | ||
76 | /* | ||
77 | * Generate exponent and normalized mantissa | ||
78 | */ | ||
79 | dst_exponent = 16; /* initialize for normalization */ | ||
80 | /* | ||
81 | * Check word for most significant bit set. Returns | ||
82 | * a value in dst_exponent indicating the bit position, | ||
83 | * between -1 and 30. | ||
84 | */ | ||
85 | Find_ms_one_bit(src,dst_exponent); | ||
86 | /* left justify source, with msb at bit position 0 */ | ||
87 | src <<= dst_exponent+1; | ||
88 | Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH); | ||
89 | Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); | ||
90 | |||
91 | /* check for inexact */ | ||
92 | if (Suint_isinexact_to_sgl(src)) { | ||
93 | switch (Rounding_mode()) { | ||
94 | case ROUNDPLUS: | ||
95 | Sgl_increment(result); | ||
96 | break; | ||
97 | case ROUNDMINUS: /* never negative */ | ||
98 | break; | ||
99 | case ROUNDNEAREST: | ||
100 | Sgl_roundnearest_from_suint(src,result); | ||
101 | break; | ||
102 | } | ||
103 | if (Is_inexacttrap_enabled()) { | ||
104 | *dstptr = result; | ||
105 | return(INEXACTEXCEPTION); | ||
106 | } | ||
107 | else Set_inexactflag(); | ||
108 | } | ||
109 | *dstptr = result; | ||
110 | return(NOEXCEPTION); | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Single Unsigned Fixed to Double Floating-point | ||
115 | */ | ||
116 | |||
117 | int | ||
118 | sgl_to_dbl_fcnvuf( | ||
119 | unsigned int *srcptr, | ||
120 | unsigned int *nullptr, | ||
121 | dbl_floating_point *dstptr, | ||
122 | unsigned int *status) | ||
123 | { | ||
124 | register int dst_exponent; | ||
125 | register unsigned int src, resultp1 = 0, resultp2 = 0; | ||
126 | |||
127 | src = *srcptr; | ||
128 | |||
129 | /* Check for zero */ | ||
130 | if (src == 0) { | ||
131 | Dbl_setzero(resultp1,resultp2); | ||
132 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
133 | return(NOEXCEPTION); | ||
134 | } | ||
135 | /* | ||
136 | * Generate exponent and normalized mantissa | ||
137 | */ | ||
138 | dst_exponent = 16; /* initialize for normalization */ | ||
139 | /* | ||
140 | * Check word for most significant bit set. Returns | ||
141 | * a value in dst_exponent indicating the bit position, | ||
142 | * between -1 and 30. | ||
143 | */ | ||
144 | Find_ms_one_bit(src,dst_exponent); | ||
145 | /* left justify source, with msb at bit position 0 */ | ||
146 | src <<= dst_exponent+1; | ||
147 | Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH); | ||
148 | Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH)); | ||
149 | Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); | ||
150 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
151 | return(NOEXCEPTION); | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Double Unsigned Fixed to Single Floating-point | ||
156 | */ | ||
157 | |||
158 | int | ||
159 | dbl_to_sgl_fcnvuf( | ||
160 | dbl_unsigned *srcptr, | ||
161 | unsigned int *nullptr, | ||
162 | sgl_floating_point *dstptr, | ||
163 | unsigned int *status) | ||
164 | { | ||
165 | int dst_exponent; | ||
166 | unsigned int srcp1, srcp2, result = 0; | ||
167 | |||
168 | Duint_copyfromptr(srcptr,srcp1,srcp2); | ||
169 | |||
170 | /* Check for zero */ | ||
171 | if (srcp1 == 0 && srcp2 == 0) { | ||
172 | Sgl_setzero(result); | ||
173 | *dstptr = result; | ||
174 | return(NOEXCEPTION); | ||
175 | } | ||
176 | /* | ||
177 | * Generate exponent and normalized mantissa | ||
178 | */ | ||
179 | dst_exponent = 16; /* initialize for normalization */ | ||
180 | if (srcp1 == 0) { | ||
181 | /* | ||
182 | * Check word for most significant bit set. Returns | ||
183 | * a value in dst_exponent indicating the bit position, | ||
184 | * between -1 and 30. | ||
185 | */ | ||
186 | Find_ms_one_bit(srcp2,dst_exponent); | ||
187 | /* left justify source, with msb at bit position 0 */ | ||
188 | srcp1 = srcp2 << dst_exponent+1; | ||
189 | srcp2 = 0; | ||
190 | /* | ||
191 | * since msb set is in second word, need to | ||
192 | * adjust bit position count | ||
193 | */ | ||
194 | dst_exponent += 32; | ||
195 | } | ||
196 | else { | ||
197 | /* | ||
198 | * Check word for most significant bit set. Returns | ||
199 | * a value in dst_exponent indicating the bit position, | ||
200 | * between -1 and 30. | ||
201 | * | ||
202 | */ | ||
203 | Find_ms_one_bit(srcp1,dst_exponent); | ||
204 | /* left justify source, with msb at bit position 0 */ | ||
205 | if (dst_exponent >= 0) { | ||
206 | Variable_shift_double(srcp1,srcp2,(31-dst_exponent), | ||
207 | srcp1); | ||
208 | srcp2 <<= dst_exponent+1; | ||
209 | } | ||
210 | } | ||
211 | Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH); | ||
212 | Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); | ||
213 | |||
214 | /* check for inexact */ | ||
215 | if (Duint_isinexact_to_sgl(srcp1,srcp2)) { | ||
216 | switch (Rounding_mode()) { | ||
217 | case ROUNDPLUS: | ||
218 | Sgl_increment(result); | ||
219 | break; | ||
220 | case ROUNDMINUS: /* never negative */ | ||
221 | break; | ||
222 | case ROUNDNEAREST: | ||
223 | Sgl_roundnearest_from_duint(srcp1,srcp2,result); | ||
224 | break; | ||
225 | } | ||
226 | if (Is_inexacttrap_enabled()) { | ||
227 | *dstptr = result; | ||
228 | return(INEXACTEXCEPTION); | ||
229 | } | ||
230 | else Set_inexactflag(); | ||
231 | } | ||
232 | *dstptr = result; | ||
233 | return(NOEXCEPTION); | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | * Double Unsigned Fixed to Double Floating-point | ||
238 | */ | ||
239 | |||
240 | int | ||
241 | dbl_to_dbl_fcnvuf( | ||
242 | dbl_unsigned *srcptr, | ||
243 | unsigned int *nullptr, | ||
244 | dbl_floating_point *dstptr, | ||
245 | unsigned int *status) | ||
246 | { | ||
247 | register int dst_exponent; | ||
248 | register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0; | ||
249 | |||
250 | Duint_copyfromptr(srcptr,srcp1,srcp2); | ||
251 | |||
252 | /* Check for zero */ | ||
253 | if (srcp1 == 0 && srcp2 ==0) { | ||
254 | Dbl_setzero(resultp1,resultp2); | ||
255 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
256 | return(NOEXCEPTION); | ||
257 | } | ||
258 | /* | ||
259 | * Generate exponent and normalized mantissa | ||
260 | */ | ||
261 | dst_exponent = 16; /* initialize for normalization */ | ||
262 | if (srcp1 == 0) { | ||
263 | /* | ||
264 | * Check word for most significant bit set. Returns | ||
265 | * a value in dst_exponent indicating the bit position, | ||
266 | * between -1 and 30. | ||
267 | */ | ||
268 | Find_ms_one_bit(srcp2,dst_exponent); | ||
269 | /* left justify source, with msb at bit position 0 */ | ||
270 | srcp1 = srcp2 << dst_exponent+1; | ||
271 | srcp2 = 0; | ||
272 | /* | ||
273 | * since msb set is in second word, need to | ||
274 | * adjust bit position count | ||
275 | */ | ||
276 | dst_exponent += 32; | ||
277 | } | ||
278 | else { | ||
279 | /* | ||
280 | * Check word for most significant bit set. Returns | ||
281 | * a value in dst_exponent indicating the bit position, | ||
282 | * between -1 and 30. | ||
283 | */ | ||
284 | Find_ms_one_bit(srcp1,dst_exponent); | ||
285 | /* left justify source, with msb at bit position 0 */ | ||
286 | if (dst_exponent >= 0) { | ||
287 | Variable_shift_double(srcp1,srcp2,(31-dst_exponent), | ||
288 | srcp1); | ||
289 | srcp2 <<= dst_exponent+1; | ||
290 | } | ||
291 | } | ||
292 | Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH); | ||
293 | Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2); | ||
294 | Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); | ||
295 | |||
296 | /* check for inexact */ | ||
297 | if (Duint_isinexact_to_dbl(srcp2)) { | ||
298 | switch (Rounding_mode()) { | ||
299 | case ROUNDPLUS: | ||
300 | Dbl_increment(resultp1,resultp2); | ||
301 | break; | ||
302 | case ROUNDMINUS: /* never negative */ | ||
303 | break; | ||
304 | case ROUNDNEAREST: | ||
305 | Dbl_roundnearest_from_duint(srcp2,resultp1, | ||
306 | resultp2); | ||
307 | break; | ||
308 | } | ||
309 | if (Is_inexacttrap_enabled()) { | ||
310 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
311 | return(INEXACTEXCEPTION); | ||
312 | } | ||
313 | else Set_inexactflag(); | ||
314 | } | ||
315 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
316 | return(NOEXCEPTION); | ||
317 | } | ||
318 | |||
diff --git a/arch/parisc/math-emu/fcnvxf.c b/arch/parisc/math-emu/fcnvxf.c new file mode 100644 index 000000000000..05c7fadb3729 --- /dev/null +++ b/arch/parisc/math-emu/fcnvxf.c | |||
@@ -0,0 +1,386 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/fcnvxf.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single Fixed-point to Single Floating-point | ||
29 | * Single Fixed-point to Double Floating-point | ||
30 | * Double Fixed-point to Single Floating-point | ||
31 | * Double Fixed-point to Double Floating-point | ||
32 | * | ||
33 | * External Interfaces: | ||
34 | * dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) | ||
35 | * dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) | ||
36 | * sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) | ||
37 | * sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) | ||
38 | * | ||
39 | * Internal Interfaces: | ||
40 | * | ||
41 | * Theory: | ||
42 | * <<please update with a overview of the operation of this file>> | ||
43 | * | ||
44 | * END_DESC | ||
45 | */ | ||
46 | |||
47 | |||
48 | #include "float.h" | ||
49 | #include "sgl_float.h" | ||
50 | #include "dbl_float.h" | ||
51 | #include "cnv_float.h" | ||
52 | |||
53 | /* | ||
54 | * Convert single fixed-point to single floating-point format | ||
55 | */ | ||
56 | |||
57 | int | ||
58 | sgl_to_sgl_fcnvxf( | ||
59 | int *srcptr, | ||
60 | unsigned int *nullptr, | ||
61 | sgl_floating_point *dstptr, | ||
62 | unsigned int *status) | ||
63 | { | ||
64 | register int src, dst_exponent; | ||
65 | register unsigned int result = 0; | ||
66 | |||
67 | src = *srcptr; | ||
68 | /* | ||
69 | * set sign bit of result and get magnitude of source | ||
70 | */ | ||
71 | if (src < 0) { | ||
72 | Sgl_setone_sign(result); | ||
73 | Int_negate(src); | ||
74 | } | ||
75 | else { | ||
76 | Sgl_setzero_sign(result); | ||
77 | /* Check for zero */ | ||
78 | if (src == 0) { | ||
79 | Sgl_setzero(result); | ||
80 | *dstptr = result; | ||
81 | return(NOEXCEPTION); | ||
82 | } | ||
83 | } | ||
84 | /* | ||
85 | * Generate exponent and normalized mantissa | ||
86 | */ | ||
87 | dst_exponent = 16; /* initialize for normalization */ | ||
88 | /* | ||
89 | * Check word for most significant bit set. Returns | ||
90 | * a value in dst_exponent indicating the bit position, | ||
91 | * between -1 and 30. | ||
92 | */ | ||
93 | Find_ms_one_bit(src,dst_exponent); | ||
94 | /* left justify source, with msb at bit position 1 */ | ||
95 | if (dst_exponent >= 0) src <<= dst_exponent; | ||
96 | else src = 1 << 30; | ||
97 | Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1)); | ||
98 | Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); | ||
99 | |||
100 | /* check for inexact */ | ||
101 | if (Int_isinexact_to_sgl(src)) { | ||
102 | switch (Rounding_mode()) { | ||
103 | case ROUNDPLUS: | ||
104 | if (Sgl_iszero_sign(result)) | ||
105 | Sgl_increment(result); | ||
106 | break; | ||
107 | case ROUNDMINUS: | ||
108 | if (Sgl_isone_sign(result)) | ||
109 | Sgl_increment(result); | ||
110 | break; | ||
111 | case ROUNDNEAREST: | ||
112 | Sgl_roundnearest_from_int(src,result); | ||
113 | } | ||
114 | if (Is_inexacttrap_enabled()) { | ||
115 | *dstptr = result; | ||
116 | return(INEXACTEXCEPTION); | ||
117 | } | ||
118 | else Set_inexactflag(); | ||
119 | } | ||
120 | *dstptr = result; | ||
121 | return(NOEXCEPTION); | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Single Fixed-point to Double Floating-point | ||
126 | */ | ||
127 | |||
128 | int | ||
129 | sgl_to_dbl_fcnvxf( | ||
130 | int *srcptr, | ||
131 | unsigned int *nullptr, | ||
132 | dbl_floating_point *dstptr, | ||
133 | unsigned int *status) | ||
134 | { | ||
135 | register int src, dst_exponent; | ||
136 | register unsigned int resultp1 = 0, resultp2 = 0; | ||
137 | |||
138 | src = *srcptr; | ||
139 | /* | ||
140 | * set sign bit of result and get magnitude of source | ||
141 | */ | ||
142 | if (src < 0) { | ||
143 | Dbl_setone_sign(resultp1); | ||
144 | Int_negate(src); | ||
145 | } | ||
146 | else { | ||
147 | Dbl_setzero_sign(resultp1); | ||
148 | /* Check for zero */ | ||
149 | if (src == 0) { | ||
150 | Dbl_setzero(resultp1,resultp2); | ||
151 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
152 | return(NOEXCEPTION); | ||
153 | } | ||
154 | } | ||
155 | /* | ||
156 | * Generate exponent and normalized mantissa | ||
157 | */ | ||
158 | dst_exponent = 16; /* initialize for normalization */ | ||
159 | /* | ||
160 | * Check word for most significant bit set. Returns | ||
161 | * a value in dst_exponent indicating the bit position, | ||
162 | * between -1 and 30. | ||
163 | */ | ||
164 | Find_ms_one_bit(src,dst_exponent); | ||
165 | /* left justify source, with msb at bit position 1 */ | ||
166 | if (dst_exponent >= 0) src <<= dst_exponent; | ||
167 | else src = 1 << 30; | ||
168 | Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1); | ||
169 | Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH)); | ||
170 | Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); | ||
171 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
172 | return(NOEXCEPTION); | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Double Fixed-point to Single Floating-point | ||
177 | */ | ||
178 | |||
179 | int | ||
180 | dbl_to_sgl_fcnvxf( | ||
181 | dbl_integer *srcptr, | ||
182 | unsigned int *nullptr, | ||
183 | sgl_floating_point *dstptr, | ||
184 | unsigned int *status) | ||
185 | { | ||
186 | int dst_exponent, srcp1; | ||
187 | unsigned int result = 0, srcp2; | ||
188 | |||
189 | Dint_copyfromptr(srcptr,srcp1,srcp2); | ||
190 | /* | ||
191 | * set sign bit of result and get magnitude of source | ||
192 | */ | ||
193 | if (srcp1 < 0) { | ||
194 | Sgl_setone_sign(result); | ||
195 | Dint_negate(srcp1,srcp2); | ||
196 | } | ||
197 | else { | ||
198 | Sgl_setzero_sign(result); | ||
199 | /* Check for zero */ | ||
200 | if (srcp1 == 0 && srcp2 == 0) { | ||
201 | Sgl_setzero(result); | ||
202 | *dstptr = result; | ||
203 | return(NOEXCEPTION); | ||
204 | } | ||
205 | } | ||
206 | /* | ||
207 | * Generate exponent and normalized mantissa | ||
208 | */ | ||
209 | dst_exponent = 16; /* initialize for normalization */ | ||
210 | if (srcp1 == 0) { | ||
211 | /* | ||
212 | * Check word for most significant bit set. Returns | ||
213 | * a value in dst_exponent indicating the bit position, | ||
214 | * between -1 and 30. | ||
215 | */ | ||
216 | Find_ms_one_bit(srcp2,dst_exponent); | ||
217 | /* left justify source, with msb at bit position 1 */ | ||
218 | if (dst_exponent >= 0) { | ||
219 | srcp1 = srcp2 << dst_exponent; | ||
220 | srcp2 = 0; | ||
221 | } | ||
222 | else { | ||
223 | srcp1 = srcp2 >> 1; | ||
224 | srcp2 <<= 31; | ||
225 | } | ||
226 | /* | ||
227 | * since msb set is in second word, need to | ||
228 | * adjust bit position count | ||
229 | */ | ||
230 | dst_exponent += 32; | ||
231 | } | ||
232 | else { | ||
233 | /* | ||
234 | * Check word for most significant bit set. Returns | ||
235 | * a value in dst_exponent indicating the bit position, | ||
236 | * between -1 and 30. | ||
237 | * | ||
238 | */ | ||
239 | Find_ms_one_bit(srcp1,dst_exponent); | ||
240 | /* left justify source, with msb at bit position 1 */ | ||
241 | if (dst_exponent > 0) { | ||
242 | Variable_shift_double(srcp1,srcp2,(32-dst_exponent), | ||
243 | srcp1); | ||
244 | srcp2 <<= dst_exponent; | ||
245 | } | ||
246 | /* | ||
247 | * If dst_exponent = 0, we don't need to shift anything. | ||
248 | * If dst_exponent = -1, src = - 2**63 so we won't need to | ||
249 | * shift srcp2. | ||
250 | */ | ||
251 | else srcp1 >>= -(dst_exponent); | ||
252 | } | ||
253 | Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1); | ||
254 | Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); | ||
255 | |||
256 | /* check for inexact */ | ||
257 | if (Dint_isinexact_to_sgl(srcp1,srcp2)) { | ||
258 | switch (Rounding_mode()) { | ||
259 | case ROUNDPLUS: | ||
260 | if (Sgl_iszero_sign(result)) | ||
261 | Sgl_increment(result); | ||
262 | break; | ||
263 | case ROUNDMINUS: | ||
264 | if (Sgl_isone_sign(result)) | ||
265 | Sgl_increment(result); | ||
266 | break; | ||
267 | case ROUNDNEAREST: | ||
268 | Sgl_roundnearest_from_dint(srcp1,srcp2,result); | ||
269 | } | ||
270 | if (Is_inexacttrap_enabled()) { | ||
271 | *dstptr = result; | ||
272 | return(INEXACTEXCEPTION); | ||
273 | } | ||
274 | else Set_inexactflag(); | ||
275 | } | ||
276 | *dstptr = result; | ||
277 | return(NOEXCEPTION); | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * Double Fixed-point to Double Floating-point | ||
282 | */ | ||
283 | |||
284 | int | ||
285 | dbl_to_dbl_fcnvxf( | ||
286 | dbl_integer *srcptr, | ||
287 | unsigned int *nullptr, | ||
288 | dbl_floating_point *dstptr, | ||
289 | unsigned int *status) | ||
290 | { | ||
291 | register int srcp1, dst_exponent; | ||
292 | register unsigned int srcp2, resultp1 = 0, resultp2 = 0; | ||
293 | |||
294 | Dint_copyfromptr(srcptr,srcp1,srcp2); | ||
295 | /* | ||
296 | * set sign bit of result and get magnitude of source | ||
297 | */ | ||
298 | if (srcp1 < 0) { | ||
299 | Dbl_setone_sign(resultp1); | ||
300 | Dint_negate(srcp1,srcp2); | ||
301 | } | ||
302 | else { | ||
303 | Dbl_setzero_sign(resultp1); | ||
304 | /* Check for zero */ | ||
305 | if (srcp1 == 0 && srcp2 ==0) { | ||
306 | Dbl_setzero(resultp1,resultp2); | ||
307 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
308 | return(NOEXCEPTION); | ||
309 | } | ||
310 | } | ||
311 | /* | ||
312 | * Generate exponent and normalized mantissa | ||
313 | */ | ||
314 | dst_exponent = 16; /* initialize for normalization */ | ||
315 | if (srcp1 == 0) { | ||
316 | /* | ||
317 | * Check word for most significant bit set. Returns | ||
318 | * a value in dst_exponent indicating the bit position, | ||
319 | * between -1 and 30. | ||
320 | */ | ||
321 | Find_ms_one_bit(srcp2,dst_exponent); | ||
322 | /* left justify source, with msb at bit position 1 */ | ||
323 | if (dst_exponent >= 0) { | ||
324 | srcp1 = srcp2 << dst_exponent; | ||
325 | srcp2 = 0; | ||
326 | } | ||
327 | else { | ||
328 | srcp1 = srcp2 >> 1; | ||
329 | srcp2 <<= 31; | ||
330 | } | ||
331 | /* | ||
332 | * since msb set is in second word, need to | ||
333 | * adjust bit position count | ||
334 | */ | ||
335 | dst_exponent += 32; | ||
336 | } | ||
337 | else { | ||
338 | /* | ||
339 | * Check word for most significant bit set. Returns | ||
340 | * a value in dst_exponent indicating the bit position, | ||
341 | * between -1 and 30. | ||
342 | */ | ||
343 | Find_ms_one_bit(srcp1,dst_exponent); | ||
344 | /* left justify source, with msb at bit position 1 */ | ||
345 | if (dst_exponent > 0) { | ||
346 | Variable_shift_double(srcp1,srcp2,(32-dst_exponent), | ||
347 | srcp1); | ||
348 | srcp2 <<= dst_exponent; | ||
349 | } | ||
350 | /* | ||
351 | * If dst_exponent = 0, we don't need to shift anything. | ||
352 | * If dst_exponent = -1, src = - 2**63 so we won't need to | ||
353 | * shift srcp2. | ||
354 | */ | ||
355 | else srcp1 >>= -(dst_exponent); | ||
356 | } | ||
357 | Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1)); | ||
358 | Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2); | ||
359 | Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); | ||
360 | |||
361 | /* check for inexact */ | ||
362 | if (Dint_isinexact_to_dbl(srcp2)) { | ||
363 | switch (Rounding_mode()) { | ||
364 | case ROUNDPLUS: | ||
365 | if (Dbl_iszero_sign(resultp1)) { | ||
366 | Dbl_increment(resultp1,resultp2); | ||
367 | } | ||
368 | break; | ||
369 | case ROUNDMINUS: | ||
370 | if (Dbl_isone_sign(resultp1)) { | ||
371 | Dbl_increment(resultp1,resultp2); | ||
372 | } | ||
373 | break; | ||
374 | case ROUNDNEAREST: | ||
375 | Dbl_roundnearest_from_dint(srcp2,resultp1, | ||
376 | resultp2); | ||
377 | } | ||
378 | if (Is_inexacttrap_enabled()) { | ||
379 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
380 | return(INEXACTEXCEPTION); | ||
381 | } | ||
382 | else Set_inexactflag(); | ||
383 | } | ||
384 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
385 | return(NOEXCEPTION); | ||
386 | } | ||
diff --git a/arch/parisc/math-emu/float.h b/arch/parisc/math-emu/float.h new file mode 100644 index 000000000000..ce76f6dfa25b --- /dev/null +++ b/arch/parisc/math-emu/float.h | |||
@@ -0,0 +1,582 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/float.h $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * <<please update with a synopis of the functionality provided by this file>> | ||
29 | * | ||
30 | * BE header: no | ||
31 | * | ||
32 | * Shipped: yes | ||
33 | * /usr/conf/pa/spmath/float.h | ||
34 | * | ||
35 | * END_DESC | ||
36 | */ | ||
37 | |||
38 | #ifdef __NO_PA_HDRS | ||
39 | PA header file -- do not include this header file for non-PA builds. | ||
40 | #endif | ||
41 | |||
42 | #include "fpbits.h" | ||
43 | #include "hppa.h" | ||
44 | /* | ||
45 | * Want to pick up the FPU capability flags, not the PDC structures. | ||
46 | * 'LOCORE' isn't really true in this case, but we don't want the C structures | ||
47 | * so it suits our purposes | ||
48 | */ | ||
49 | #define LOCORE | ||
50 | #include "fpu.h" | ||
51 | |||
52 | /* | ||
53 | * Declare the basic structures for the 3 different | ||
54 | * floating-point precisions. | ||
55 | * | ||
56 | * Single number | ||
57 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
58 | * |s| exp | mantissa | | ||
59 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
60 | */ | ||
61 | #define Sall(object) (object) | ||
62 | #define Ssign(object) Bitfield_extract( 0, 1,object) | ||
63 | #define Ssignedsign(object) Bitfield_signed_extract( 0, 1,object) | ||
64 | #define Sexponent(object) Bitfield_extract( 1, 8,object) | ||
65 | #define Smantissa(object) Bitfield_mask( 9, 23,object) | ||
66 | #define Ssignaling(object) Bitfield_extract( 9, 1,object) | ||
67 | #define Ssignalingnan(object) Bitfield_extract( 1, 9,object) | ||
68 | #define Shigh2mantissa(object) Bitfield_extract( 9, 2,object) | ||
69 | #define Sexponentmantissa(object) Bitfield_mask( 1, 31,object) | ||
70 | #define Ssignexponent(object) Bitfield_extract( 0, 9,object) | ||
71 | #define Shidden(object) Bitfield_extract( 8, 1,object) | ||
72 | #define Shiddenoverflow(object) Bitfield_extract( 7, 1,object) | ||
73 | #define Shiddenhigh7mantissa(object) Bitfield_extract( 8, 8,object) | ||
74 | #define Shiddenhigh3mantissa(object) Bitfield_extract( 8, 4,object) | ||
75 | #define Slow(object) Bitfield_mask( 31, 1,object) | ||
76 | #define Slow4(object) Bitfield_mask( 28, 4,object) | ||
77 | #define Slow31(object) Bitfield_mask( 1, 31,object) | ||
78 | #define Shigh31(object) Bitfield_extract( 0, 31,object) | ||
79 | #define Ssignedhigh31(object) Bitfield_signed_extract( 0, 31,object) | ||
80 | #define Shigh4(object) Bitfield_extract( 0, 4,object) | ||
81 | #define Sbit24(object) Bitfield_extract( 24, 1,object) | ||
82 | #define Sbit28(object) Bitfield_extract( 28, 1,object) | ||
83 | #define Sbit29(object) Bitfield_extract( 29, 1,object) | ||
84 | #define Sbit30(object) Bitfield_extract( 30, 1,object) | ||
85 | #define Sbit31(object) Bitfield_mask( 31, 1,object) | ||
86 | |||
87 | #define Deposit_ssign(object,value) Bitfield_deposit(value,0,1,object) | ||
88 | #define Deposit_sexponent(object,value) Bitfield_deposit(value,1,8,object) | ||
89 | #define Deposit_smantissa(object,value) Bitfield_deposit(value,9,23,object) | ||
90 | #define Deposit_shigh2mantissa(object,value) Bitfield_deposit(value,9,2,object) | ||
91 | #define Deposit_sexponentmantissa(object,value) \ | ||
92 | Bitfield_deposit(value,1,31,object) | ||
93 | #define Deposit_ssignexponent(object,value) Bitfield_deposit(value,0,9,object) | ||
94 | #define Deposit_slow(object,value) Bitfield_deposit(value,31,1,object) | ||
95 | #define Deposit_shigh4(object,value) Bitfield_deposit(value,0,4,object) | ||
96 | |||
97 | #define Is_ssign(object) Bitfield_mask( 0, 1,object) | ||
98 | #define Is_ssignaling(object) Bitfield_mask( 9, 1,object) | ||
99 | #define Is_shidden(object) Bitfield_mask( 8, 1,object) | ||
100 | #define Is_shiddenoverflow(object) Bitfield_mask( 7, 1,object) | ||
101 | #define Is_slow(object) Bitfield_mask( 31, 1,object) | ||
102 | #define Is_sbit24(object) Bitfield_mask( 24, 1,object) | ||
103 | #define Is_sbit28(object) Bitfield_mask( 28, 1,object) | ||
104 | #define Is_sbit29(object) Bitfield_mask( 29, 1,object) | ||
105 | #define Is_sbit30(object) Bitfield_mask( 30, 1,object) | ||
106 | #define Is_sbit31(object) Bitfield_mask( 31, 1,object) | ||
107 | |||
108 | /* | ||
109 | * Double number. | ||
110 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
111 | * |s| exponent | mantissa part 1 | | ||
112 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
113 | * | ||
114 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
115 | * | mantissa part 2 | | ||
116 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
117 | */ | ||
118 | #define Dallp1(object) (object) | ||
119 | #define Dsign(object) Bitfield_extract( 0, 1,object) | ||
120 | #define Dsignedsign(object) Bitfield_signed_extract( 0, 1,object) | ||
121 | #define Dexponent(object) Bitfield_extract( 1, 11,object) | ||
122 | #define Dmantissap1(object) Bitfield_mask( 12, 20,object) | ||
123 | #define Dsignaling(object) Bitfield_extract( 12, 1,object) | ||
124 | #define Dsignalingnan(object) Bitfield_extract( 1, 12,object) | ||
125 | #define Dhigh2mantissa(object) Bitfield_extract( 12, 2,object) | ||
126 | #define Dexponentmantissap1(object) Bitfield_mask( 1, 31,object) | ||
127 | #define Dsignexponent(object) Bitfield_extract( 0, 12,object) | ||
128 | #define Dhidden(object) Bitfield_extract( 11, 1,object) | ||
129 | #define Dhiddenoverflow(object) Bitfield_extract( 10, 1,object) | ||
130 | #define Dhiddenhigh7mantissa(object) Bitfield_extract( 11, 8,object) | ||
131 | #define Dhiddenhigh3mantissa(object) Bitfield_extract( 11, 4,object) | ||
132 | #define Dlowp1(object) Bitfield_mask( 31, 1,object) | ||
133 | #define Dlow31p1(object) Bitfield_mask( 1, 31,object) | ||
134 | #define Dhighp1(object) Bitfield_extract( 0, 1,object) | ||
135 | #define Dhigh4p1(object) Bitfield_extract( 0, 4,object) | ||
136 | #define Dhigh31p1(object) Bitfield_extract( 0, 31,object) | ||
137 | #define Dsignedhigh31p1(object) Bitfield_signed_extract( 0, 31,object) | ||
138 | #define Dbit3p1(object) Bitfield_extract( 3, 1,object) | ||
139 | |||
140 | #define Deposit_dsign(object,value) Bitfield_deposit(value,0,1,object) | ||
141 | #define Deposit_dexponent(object,value) Bitfield_deposit(value,1,11,object) | ||
142 | #define Deposit_dmantissap1(object,value) Bitfield_deposit(value,12,20,object) | ||
143 | #define Deposit_dhigh2mantissa(object,value) Bitfield_deposit(value,12,2,object) | ||
144 | #define Deposit_dexponentmantissap1(object,value) \ | ||
145 | Bitfield_deposit(value,1,31,object) | ||
146 | #define Deposit_dsignexponent(object,value) Bitfield_deposit(value,0,12,object) | ||
147 | #define Deposit_dlowp1(object,value) Bitfield_deposit(value,31,1,object) | ||
148 | #define Deposit_dhigh4p1(object,value) Bitfield_deposit(value,0,4,object) | ||
149 | |||
150 | #define Is_dsign(object) Bitfield_mask( 0, 1,object) | ||
151 | #define Is_dsignaling(object) Bitfield_mask( 12, 1,object) | ||
152 | #define Is_dhidden(object) Bitfield_mask( 11, 1,object) | ||
153 | #define Is_dhiddenoverflow(object) Bitfield_mask( 10, 1,object) | ||
154 | #define Is_dlowp1(object) Bitfield_mask( 31, 1,object) | ||
155 | #define Is_dhighp1(object) Bitfield_mask( 0, 1,object) | ||
156 | #define Is_dbit3p1(object) Bitfield_mask( 3, 1,object) | ||
157 | |||
158 | #define Dallp2(object) (object) | ||
159 | #define Dmantissap2(object) (object) | ||
160 | #define Dlowp2(object) Bitfield_mask( 31, 1,object) | ||
161 | #define Dlow4p2(object) Bitfield_mask( 28, 4,object) | ||
162 | #define Dlow31p2(object) Bitfield_mask( 1, 31,object) | ||
163 | #define Dhighp2(object) Bitfield_extract( 0, 1,object) | ||
164 | #define Dhigh31p2(object) Bitfield_extract( 0, 31,object) | ||
165 | #define Dbit2p2(object) Bitfield_extract( 2, 1,object) | ||
166 | #define Dbit3p2(object) Bitfield_extract( 3, 1,object) | ||
167 | #define Dbit21p2(object) Bitfield_extract( 21, 1,object) | ||
168 | #define Dbit28p2(object) Bitfield_extract( 28, 1,object) | ||
169 | #define Dbit29p2(object) Bitfield_extract( 29, 1,object) | ||
170 | #define Dbit30p2(object) Bitfield_extract( 30, 1,object) | ||
171 | #define Dbit31p2(object) Bitfield_mask( 31, 1,object) | ||
172 | |||
173 | #define Deposit_dlowp2(object,value) Bitfield_deposit(value,31,1,object) | ||
174 | |||
175 | #define Is_dlowp2(object) Bitfield_mask( 31, 1,object) | ||
176 | #define Is_dhighp2(object) Bitfield_mask( 0, 1,object) | ||
177 | #define Is_dbit2p2(object) Bitfield_mask( 2, 1,object) | ||
178 | #define Is_dbit3p2(object) Bitfield_mask( 3, 1,object) | ||
179 | #define Is_dbit21p2(object) Bitfield_mask( 21, 1,object) | ||
180 | #define Is_dbit28p2(object) Bitfield_mask( 28, 1,object) | ||
181 | #define Is_dbit29p2(object) Bitfield_mask( 29, 1,object) | ||
182 | #define Is_dbit30p2(object) Bitfield_mask( 30, 1,object) | ||
183 | #define Is_dbit31p2(object) Bitfield_mask( 31, 1,object) | ||
184 | |||
185 | /* | ||
186 | * Quad number. | ||
187 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
188 | * |s| exponent | mantissa part 1 | | ||
189 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
190 | * | ||
191 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
192 | * | mantissa part 2 | | ||
193 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
194 | * | ||
195 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
196 | * | mantissa part 3 | | ||
197 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
198 | * | ||
199 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
200 | * | mantissa part 4 | | ||
201 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
202 | */ | ||
203 | typedef struct | ||
204 | { | ||
205 | union | ||
206 | { | ||
207 | struct { unsigned qallp1; } u_qallp1; | ||
208 | /* Not needed for now... | ||
209 | Bitfield_extract( 0, 1,u_qsign,qsign) | ||
210 | Bitfield_signed_extract( 0, 1,u_qsignedsign,qsignedsign) | ||
211 | Bitfield_extract( 1, 15,u_qexponent,qexponent) | ||
212 | Bitfield_extract(16, 16,u_qmantissap1,qmantissap1) | ||
213 | Bitfield_extract(16, 1,u_qsignaling,qsignaling) | ||
214 | Bitfield_extract(1, 16,u_qsignalingnan,qsignalingnan) | ||
215 | Bitfield_extract(16, 2,u_qhigh2mantissa,qhigh2mantissa) | ||
216 | Bitfield_extract( 1, 31,u_qexponentmantissap1,qexponentmantissap1) | ||
217 | Bitfield_extract( 0, 16,u_qsignexponent,qsignexponent) | ||
218 | Bitfield_extract(15, 1,u_qhidden,qhidden) | ||
219 | Bitfield_extract(14, 1,u_qhiddenoverflow,qhiddenoverflow) | ||
220 | Bitfield_extract(15, 8,u_qhiddenhigh7mantissa,qhiddenhigh7mantissa) | ||
221 | Bitfield_extract(15, 4,u_qhiddenhigh3mantissa,qhiddenhigh3mantissa) | ||
222 | Bitfield_extract(31, 1,u_qlowp1,qlowp1) | ||
223 | Bitfield_extract( 1, 31,u_qlow31p1,qlow31p1) | ||
224 | Bitfield_extract( 0, 1,u_qhighp1,qhighp1) | ||
225 | Bitfield_extract( 0, 4,u_qhigh4p1,qhigh4p1) | ||
226 | Bitfield_extract( 0, 31,u_qhigh31p1,qhigh31p1) | ||
227 | */ | ||
228 | } quad_u1; | ||
229 | union | ||
230 | { | ||
231 | struct { unsigned qallp2; } u_qallp2; | ||
232 | /* Not needed for now... | ||
233 | Bitfield_extract(31, 1,u_qlowp2,qlowp2) | ||
234 | Bitfield_extract( 1, 31,u_qlow31p2,qlow31p2) | ||
235 | Bitfield_extract( 0, 1,u_qhighp2,qhighp2) | ||
236 | Bitfield_extract( 0, 31,u_qhigh31p2,qhigh31p2) | ||
237 | */ | ||
238 | } quad_u2; | ||
239 | union | ||
240 | { | ||
241 | struct { unsigned qallp3; } u_qallp3; | ||
242 | /* Not needed for now... | ||
243 | Bitfield_extract(31, 1,u_qlowp3,qlowp3) | ||
244 | Bitfield_extract( 1, 31,u_qlow31p3,qlow31p3) | ||
245 | Bitfield_extract( 0, 1,u_qhighp3,qhighp3) | ||
246 | Bitfield_extract( 0, 31,u_qhigh31p3,qhigh31p3) | ||
247 | */ | ||
248 | } quad_u3; | ||
249 | union | ||
250 | { | ||
251 | struct { unsigned qallp4; } u_qallp4; | ||
252 | /* Not need for now... | ||
253 | Bitfield_extract(31, 1,u_qlowp4,qlowp4) | ||
254 | Bitfield_extract( 1, 31,u_qlow31p4,qlow31p4) | ||
255 | Bitfield_extract( 0, 1,u_qhighp4,qhighp4) | ||
256 | Bitfield_extract( 0, 31,u_qhigh31p4,qhigh31p4) | ||
257 | */ | ||
258 | } quad_u4; | ||
259 | } quad_floating_point; | ||
260 | |||
261 | /* Extension - An additional structure to hold the guard, round and | ||
262 | * sticky bits during computations. | ||
263 | */ | ||
264 | #define Extall(object) (object) | ||
265 | #define Extsign(object) Bitfield_extract( 0, 1,object) | ||
266 | #define Exthigh31(object) Bitfield_extract( 0, 31,object) | ||
267 | #define Extlow31(object) Bitfield_extract( 1, 31,object) | ||
268 | #define Extlow(object) Bitfield_extract( 31, 1,object) | ||
269 | |||
270 | /* | ||
271 | * Single extended - The upper word is just like single precision, | ||
272 | * but one additional word of mantissa is needed. | ||
273 | */ | ||
274 | #define Sextallp1(object) (object) | ||
275 | #define Sextallp2(object) (object) | ||
276 | #define Sextlowp1(object) Bitfield_extract( 31, 1,object) | ||
277 | #define Sexthighp2(object) Bitfield_extract( 0, 1,object) | ||
278 | #define Sextlow31p2(object) Bitfield_extract( 1, 31,object) | ||
279 | #define Sexthiddenoverflow(object) Bitfield_extract( 4, 1,object) | ||
280 | #define Is_sexthiddenoverflow(object) Bitfield_mask( 4, 1,object) | ||
281 | |||
282 | /* | ||
283 | * Double extended - The upper two words are just like double precision, | ||
284 | * but two additional words of mantissa are needed. | ||
285 | */ | ||
286 | #define Dextallp1(object) (object) | ||
287 | #define Dextallp2(object) (object) | ||
288 | #define Dextallp3(object) (object) | ||
289 | #define Dextallp4(object) (object) | ||
290 | #define Dextlowp2(object) Bitfield_extract( 31, 1,object) | ||
291 | #define Dexthighp3(object) Bitfield_extract( 0, 1,object) | ||
292 | #define Dextlow31p3(object) Bitfield_extract( 1, 31,object) | ||
293 | #define Dexthiddenoverflow(object) Bitfield_extract( 10, 1,object) | ||
294 | #define Is_dexthiddenoverflow(object) Bitfield_mask( 10, 1,object) | ||
295 | #define Deposit_dextlowp4(object,value) Bitfield_deposit(value,31,1,object) | ||
296 | |||
297 | /* | ||
298 | * Declare the basic structures for the 3 different | ||
299 | * fixed-point precisions. | ||
300 | * | ||
301 | * Single number | ||
302 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
303 | * |s| integer | | ||
304 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
305 | */ | ||
306 | typedef int sgl_integer; | ||
307 | |||
308 | /* | ||
309 | * Double number. | ||
310 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
311 | * |s| high integer | | ||
312 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
313 | * | ||
314 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
315 | * | low integer | | ||
316 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
317 | */ | ||
318 | struct dint { | ||
319 | int wd0; | ||
320 | unsigned int wd1; | ||
321 | }; | ||
322 | |||
323 | struct dblwd { | ||
324 | unsigned int wd0; | ||
325 | unsigned int wd1; | ||
326 | }; | ||
327 | |||
328 | /* | ||
329 | * Quad number. | ||
330 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
331 | * |s| integer part1 | | ||
332 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
333 | * | ||
334 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
335 | * | integer part 2 | | ||
336 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
337 | * | ||
338 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
339 | * | integer part 3 | | ||
340 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
341 | * | ||
342 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
343 | * | integer part 4 | | ||
344 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
345 | */ | ||
346 | |||
347 | struct quadwd { | ||
348 | int wd0; | ||
349 | unsigned int wd1; | ||
350 | unsigned int wd2; | ||
351 | unsigned int wd3; | ||
352 | }; | ||
353 | |||
354 | typedef struct quadwd quad_integer; | ||
355 | |||
356 | |||
357 | /* useful typedefs */ | ||
358 | typedef unsigned int sgl_floating_point; | ||
359 | typedef struct dblwd dbl_floating_point; | ||
360 | typedef struct dint dbl_integer; | ||
361 | typedef struct dblwd dbl_unsigned; | ||
362 | |||
363 | /* | ||
364 | * Define the different precisions' parameters. | ||
365 | */ | ||
366 | #define SGL_BITLENGTH 32 | ||
367 | #define SGL_EMAX 127 | ||
368 | #define SGL_EMIN (-126) | ||
369 | #define SGL_BIAS 127 | ||
370 | #define SGL_WRAP 192 | ||
371 | #define SGL_INFINITY_EXPONENT (SGL_EMAX+SGL_BIAS+1) | ||
372 | #define SGL_THRESHOLD 32 | ||
373 | #define SGL_EXP_LENGTH 8 | ||
374 | #define SGL_P 24 | ||
375 | |||
376 | #define DBL_BITLENGTH 64 | ||
377 | #define DBL_EMAX 1023 | ||
378 | #define DBL_EMIN (-1022) | ||
379 | #define DBL_BIAS 1023 | ||
380 | #define DBL_WRAP 1536 | ||
381 | #define DBL_INFINITY_EXPONENT (DBL_EMAX+DBL_BIAS+1) | ||
382 | #define DBL_THRESHOLD 64 | ||
383 | #define DBL_EXP_LENGTH 11 | ||
384 | #define DBL_P 53 | ||
385 | |||
386 | #define QUAD_BITLENGTH 128 | ||
387 | #define QUAD_EMAX 16383 | ||
388 | #define QUAD_EMIN (-16382) | ||
389 | #define QUAD_BIAS 16383 | ||
390 | #define QUAD_WRAP 24576 | ||
391 | #define QUAD_INFINITY_EXPONENT (QUAD_EMAX+QUAD_BIAS+1) | ||
392 | #define QUAD_P 113 | ||
393 | |||
394 | /* Boolean Values etc. */ | ||
395 | #define FALSE 0 | ||
396 | #define TRUE (!FALSE) | ||
397 | #define NOT ! | ||
398 | #define XOR ^ | ||
399 | |||
400 | /* other constants */ | ||
401 | #undef NULL | ||
402 | #define NULL 0 | ||
403 | #define NIL 0 | ||
404 | #define SGL 0 | ||
405 | #define DBL 1 | ||
406 | #define BADFMT 2 | ||
407 | #define QUAD 3 | ||
408 | |||
409 | |||
410 | /* Types */ | ||
411 | typedef int boolean; | ||
412 | typedef int FORMAT; | ||
413 | typedef int VOID; | ||
414 | |||
415 | |||
416 | /* Declare status register equivalent to FPUs architecture. | ||
417 | * | ||
418 | * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1 | ||
419 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
420 | * |V|Z|O|U|I|C| rsv | model | version |RM |rsv|T|r|V|Z|O|U|I| | ||
421 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
422 | */ | ||
423 | #define Cbit(object) Bitfield_extract( 5, 1,object) | ||
424 | #define Tbit(object) Bitfield_extract( 25, 1,object) | ||
425 | #define Roundingmode(object) Bitfield_extract( 21, 2,object) | ||
426 | #define Invalidtrap(object) Bitfield_extract( 27, 1,object) | ||
427 | #define Divisionbyzerotrap(object) Bitfield_extract( 28, 1,object) | ||
428 | #define Overflowtrap(object) Bitfield_extract( 29, 1,object) | ||
429 | #define Underflowtrap(object) Bitfield_extract( 30, 1,object) | ||
430 | #define Inexacttrap(object) Bitfield_extract( 31, 1,object) | ||
431 | #define Invalidflag(object) Bitfield_extract( 0, 1,object) | ||
432 | #define Divisionbyzeroflag(object) Bitfield_extract( 1, 1,object) | ||
433 | #define Overflowflag(object) Bitfield_extract( 2, 1,object) | ||
434 | #define Underflowflag(object) Bitfield_extract( 3, 1,object) | ||
435 | #define Inexactflag(object) Bitfield_extract( 4, 1,object) | ||
436 | #define Allflags(object) Bitfield_extract( 0, 5,object) | ||
437 | |||
438 | /* Definitions relevant to the status register */ | ||
439 | |||
440 | /* Rounding Modes */ | ||
441 | #define ROUNDNEAREST 0 | ||
442 | #define ROUNDZERO 1 | ||
443 | #define ROUNDPLUS 2 | ||
444 | #define ROUNDMINUS 3 | ||
445 | |||
446 | /* Exceptions */ | ||
447 | #define NOEXCEPTION 0x0 | ||
448 | #define INVALIDEXCEPTION 0x20 | ||
449 | #define DIVISIONBYZEROEXCEPTION 0x10 | ||
450 | #define OVERFLOWEXCEPTION 0x08 | ||
451 | #define UNDERFLOWEXCEPTION 0x04 | ||
452 | #define INEXACTEXCEPTION 0x02 | ||
453 | #define UNIMPLEMENTEDEXCEPTION 0x01 | ||
454 | |||
455 | /* New exceptions for the 2E Opcode */ | ||
456 | #define OPC_2E_INVALIDEXCEPTION 0x30 | ||
457 | #define OPC_2E_OVERFLOWEXCEPTION 0x18 | ||
458 | #define OPC_2E_UNDERFLOWEXCEPTION 0x0c | ||
459 | #define OPC_2E_INEXACTEXCEPTION 0x12 | ||
460 | |||
461 | /* Declare exception registers equivalent to FPUs architecture | ||
462 | * | ||
463 | * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1 | ||
464 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
465 | * |excepttype | r1 | r2/ext | operation |parm |n| t/cond | | ||
466 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
467 | */ | ||
468 | #define Allexception(object) (object) | ||
469 | #define Exceptiontype(object) Bitfield_extract( 0, 6,object) | ||
470 | #define Instructionfield(object) Bitfield_mask( 6,26,object) | ||
471 | #define Parmfield(object) Bitfield_extract( 23, 3,object) | ||
472 | #define Rabit(object) Bitfield_extract( 24, 1,object) | ||
473 | #define Ibit(object) Bitfield_extract( 25, 1,object) | ||
474 | |||
475 | #define Set_exceptiontype(object,value) Bitfield_deposit(value, 0, 6,object) | ||
476 | #define Set_parmfield(object,value) Bitfield_deposit(value, 23, 3,object) | ||
477 | #define Set_exceptiontype_and_instr_field(exception,instruction,object) \ | ||
478 | object = exception << 26 | instruction | ||
479 | |||
480 | /* Declare the condition field | ||
481 | * | ||
482 | * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1 | ||
483 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
484 | * | |G|L|E|U|X| | ||
485 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
486 | */ | ||
487 | #define Allexception(object) (object) | ||
488 | #define Greaterthanbit(object) Bitfield_extract( 27, 1,object) | ||
489 | #define Lessthanbit(object) Bitfield_extract( 28, 1,object) | ||
490 | #define Equalbit(object) Bitfield_extract( 29, 1,object) | ||
491 | #define Unorderedbit(object) Bitfield_extract( 30, 1,object) | ||
492 | #define Exceptionbit(object) Bitfield_extract( 31, 1,object) | ||
493 | |||
494 | /* An alias name for the status register */ | ||
495 | #define Fpustatus_register (*status) | ||
496 | |||
497 | /************************************************** | ||
498 | * Status register referencing and manipulation. * | ||
499 | **************************************************/ | ||
500 | |||
501 | /* Rounding mode */ | ||
502 | #define Rounding_mode() Roundingmode(Fpustatus_register) | ||
503 | #define Is_rounding_mode(rmode) \ | ||
504 | (Roundingmode(Fpustatus_register) == rmode) | ||
505 | #define Set_rounding_mode(value) \ | ||
506 | Bitfield_deposit(value,21,2,Fpustatus_register) | ||
507 | |||
508 | /* Boolean testing of the trap enable bits */ | ||
509 | #define Is_invalidtrap_enabled() Invalidtrap(Fpustatus_register) | ||
510 | #define Is_divisionbyzerotrap_enabled() Divisionbyzerotrap(Fpustatus_register) | ||
511 | #define Is_overflowtrap_enabled() Overflowtrap(Fpustatus_register) | ||
512 | #define Is_underflowtrap_enabled() Underflowtrap(Fpustatus_register) | ||
513 | #define Is_inexacttrap_enabled() Inexacttrap(Fpustatus_register) | ||
514 | |||
515 | /* Set the indicated flags in the status register */ | ||
516 | #define Set_invalidflag() Bitfield_deposit(1,0,1,Fpustatus_register) | ||
517 | #define Set_divisionbyzeroflag() Bitfield_deposit(1,1,1,Fpustatus_register) | ||
518 | #define Set_overflowflag() Bitfield_deposit(1,2,1,Fpustatus_register) | ||
519 | #define Set_underflowflag() Bitfield_deposit(1,3,1,Fpustatus_register) | ||
520 | #define Set_inexactflag() Bitfield_deposit(1,4,1,Fpustatus_register) | ||
521 | |||
522 | #define Clear_all_flags() Bitfield_deposit(0,0,5,Fpustatus_register) | ||
523 | |||
524 | /* Manipulate the trap and condition code bits (tbit and cbit) */ | ||
525 | #define Set_tbit() Bitfield_deposit(1,25,1,Fpustatus_register) | ||
526 | #define Clear_tbit() Bitfield_deposit(0,25,1,Fpustatus_register) | ||
527 | #define Is_tbit_set() Tbit(Fpustatus_register) | ||
528 | #define Is_cbit_set() Cbit(Fpustatus_register) | ||
529 | |||
530 | #define Set_status_cbit(value) \ | ||
531 | Bitfield_deposit(value,5,1,Fpustatus_register) | ||
532 | |||
533 | /******************************* | ||
534 | * Condition field referencing * | ||
535 | *******************************/ | ||
536 | #define Unordered(cond) Unorderedbit(cond) | ||
537 | #define Equal(cond) Equalbit(cond) | ||
538 | #define Lessthan(cond) Lessthanbit(cond) | ||
539 | #define Greaterthan(cond) Greaterthanbit(cond) | ||
540 | #define Exception(cond) Exceptionbit(cond) | ||
541 | |||
542 | |||
543 | /* Defines for the extension */ | ||
544 | #define Ext_isone_sign(extent) (Extsign(extent)) | ||
545 | #define Ext_isnotzero(extent) \ | ||
546 | (Extall(extent)) | ||
547 | #define Ext_isnotzero_lower(extent) \ | ||
548 | (Extlow31(extent)) | ||
549 | #define Ext_leftshiftby1(extent) \ | ||
550 | Extall(extent) <<= 1 | ||
551 | #define Ext_negate(extent) \ | ||
552 | (int )Extall(extent) = 0 - (int )Extall(extent) | ||
553 | #define Ext_setone_low(extent) Bitfield_deposit(1,31,1,extent) | ||
554 | #define Ext_setzero(extent) Extall(extent) = 0 | ||
555 | |||
556 | typedef int operation; | ||
557 | |||
558 | /* error messages */ | ||
559 | |||
560 | #define NONE 0 | ||
561 | #define UNDEFFPINST 1 | ||
562 | |||
563 | /* Function definitions: opcode, opclass */ | ||
564 | #define FTEST (1<<2) | 0 | ||
565 | #define FCPY (2<<2) | 0 | ||
566 | #define FABS (3<<2) | 0 | ||
567 | #define FSQRT (4<<2) | 0 | ||
568 | #define FRND (5<<2) | 0 | ||
569 | |||
570 | #define FCNVFF (0<<2) | 1 | ||
571 | #define FCNVXF (1<<2) | 1 | ||
572 | #define FCNVFX (2<<2) | 1 | ||
573 | #define FCNVFXT (3<<2) | 1 | ||
574 | |||
575 | #define FCMP (0<<2) | 2 | ||
576 | |||
577 | #define FADD (0<<2) | 3 | ||
578 | #define FSUB (1<<2) | 3 | ||
579 | #define FMPY (2<<2) | 3 | ||
580 | #define FDIV (3<<2) | 3 | ||
581 | #define FREM (4<<2) | 3 | ||
582 | |||
diff --git a/arch/parisc/math-emu/fmpyfadd.c b/arch/parisc/math-emu/fmpyfadd.c new file mode 100644 index 000000000000..5dd7f93a89be --- /dev/null +++ b/arch/parisc/math-emu/fmpyfadd.c | |||
@@ -0,0 +1,2655 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/fmpyfadd.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Double Floating-point Multiply Fused Add | ||
29 | * Double Floating-point Multiply Negate Fused Add | ||
30 | * Single Floating-point Multiply Fused Add | ||
31 | * Single Floating-point Multiply Negate Fused Add | ||
32 | * | ||
33 | * External Interfaces: | ||
34 | * dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
35 | * dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
36 | * sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
37 | * sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
38 | * | ||
39 | * Internal Interfaces: | ||
40 | * | ||
41 | * Theory: | ||
42 | * <<please update with a overview of the operation of this file>> | ||
43 | * | ||
44 | * END_DESC | ||
45 | */ | ||
46 | |||
47 | |||
48 | #include "float.h" | ||
49 | #include "sgl_float.h" | ||
50 | #include "dbl_float.h" | ||
51 | |||
52 | |||
53 | /* | ||
54 | * Double Floating-point Multiply Fused Add | ||
55 | */ | ||
56 | |||
57 | int | ||
58 | dbl_fmpyfadd( | ||
59 | dbl_floating_point *src1ptr, | ||
60 | dbl_floating_point *src2ptr, | ||
61 | dbl_floating_point *src3ptr, | ||
62 | unsigned int *status, | ||
63 | dbl_floating_point *dstptr) | ||
64 | { | ||
65 | unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2; | ||
66 | register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4; | ||
67 | unsigned int rightp1, rightp2, rightp3, rightp4; | ||
68 | unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0; | ||
69 | register int mpy_exponent, add_exponent, count; | ||
70 | boolean inexact = FALSE, is_tiny = FALSE; | ||
71 | |||
72 | unsigned int signlessleft1, signlessright1, save; | ||
73 | register int result_exponent, diff_exponent; | ||
74 | int sign_save, jumpsize; | ||
75 | |||
76 | Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2); | ||
77 | Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2); | ||
78 | Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2); | ||
79 | |||
80 | /* | ||
81 | * set sign bit of result of multiply | ||
82 | */ | ||
83 | if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) | ||
84 | Dbl_setnegativezerop1(resultp1); | ||
85 | else Dbl_setzerop1(resultp1); | ||
86 | |||
87 | /* | ||
88 | * Generate multiply exponent | ||
89 | */ | ||
90 | mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS; | ||
91 | |||
92 | /* | ||
93 | * check first operand for NaN's or infinity | ||
94 | */ | ||
95 | if (Dbl_isinfinity_exponent(opnd1p1)) { | ||
96 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
97 | if (Dbl_isnotnan(opnd2p1,opnd2p2) && | ||
98 | Dbl_isnotnan(opnd3p1,opnd3p2)) { | ||
99 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
100 | /* | ||
101 | * invalid since operands are infinity | ||
102 | * and zero | ||
103 | */ | ||
104 | if (Is_invalidtrap_enabled()) | ||
105 | return(OPC_2E_INVALIDEXCEPTION); | ||
106 | Set_invalidflag(); | ||
107 | Dbl_makequietnan(resultp1,resultp2); | ||
108 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
109 | return(NOEXCEPTION); | ||
110 | } | ||
111 | /* | ||
112 | * Check third operand for infinity with a | ||
113 | * sign opposite of the multiply result | ||
114 | */ | ||
115 | if (Dbl_isinfinity(opnd3p1,opnd3p2) && | ||
116 | (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { | ||
117 | /* | ||
118 | * invalid since attempting a magnitude | ||
119 | * subtraction of infinities | ||
120 | */ | ||
121 | if (Is_invalidtrap_enabled()) | ||
122 | return(OPC_2E_INVALIDEXCEPTION); | ||
123 | Set_invalidflag(); | ||
124 | Dbl_makequietnan(resultp1,resultp2); | ||
125 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
126 | return(NOEXCEPTION); | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * return infinity | ||
131 | */ | ||
132 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
133 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
134 | return(NOEXCEPTION); | ||
135 | } | ||
136 | } | ||
137 | else { | ||
138 | /* | ||
139 | * is NaN; signaling or quiet? | ||
140 | */ | ||
141 | if (Dbl_isone_signaling(opnd1p1)) { | ||
142 | /* trap if INVALIDTRAP enabled */ | ||
143 | if (Is_invalidtrap_enabled()) | ||
144 | return(OPC_2E_INVALIDEXCEPTION); | ||
145 | /* make NaN quiet */ | ||
146 | Set_invalidflag(); | ||
147 | Dbl_set_quiet(opnd1p1); | ||
148 | } | ||
149 | /* | ||
150 | * is second operand a signaling NaN? | ||
151 | */ | ||
152 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
153 | /* trap if INVALIDTRAP enabled */ | ||
154 | if (Is_invalidtrap_enabled()) | ||
155 | return(OPC_2E_INVALIDEXCEPTION); | ||
156 | /* make NaN quiet */ | ||
157 | Set_invalidflag(); | ||
158 | Dbl_set_quiet(opnd2p1); | ||
159 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
160 | return(NOEXCEPTION); | ||
161 | } | ||
162 | /* | ||
163 | * is third operand a signaling NaN? | ||
164 | */ | ||
165 | else if (Dbl_is_signalingnan(opnd3p1)) { | ||
166 | /* trap if INVALIDTRAP enabled */ | ||
167 | if (Is_invalidtrap_enabled()) | ||
168 | return(OPC_2E_INVALIDEXCEPTION); | ||
169 | /* make NaN quiet */ | ||
170 | Set_invalidflag(); | ||
171 | Dbl_set_quiet(opnd3p1); | ||
172 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
173 | return(NOEXCEPTION); | ||
174 | } | ||
175 | /* | ||
176 | * return quiet NaN | ||
177 | */ | ||
178 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
179 | return(NOEXCEPTION); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * check second operand for NaN's or infinity | ||
185 | */ | ||
186 | if (Dbl_isinfinity_exponent(opnd2p1)) { | ||
187 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
188 | if (Dbl_isnotnan(opnd3p1,opnd3p2)) { | ||
189 | if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { | ||
190 | /* | ||
191 | * invalid since multiply operands are | ||
192 | * zero & infinity | ||
193 | */ | ||
194 | if (Is_invalidtrap_enabled()) | ||
195 | return(OPC_2E_INVALIDEXCEPTION); | ||
196 | Set_invalidflag(); | ||
197 | Dbl_makequietnan(opnd2p1,opnd2p2); | ||
198 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
199 | return(NOEXCEPTION); | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * Check third operand for infinity with a | ||
204 | * sign opposite of the multiply result | ||
205 | */ | ||
206 | if (Dbl_isinfinity(opnd3p1,opnd3p2) && | ||
207 | (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { | ||
208 | /* | ||
209 | * invalid since attempting a magnitude | ||
210 | * subtraction of infinities | ||
211 | */ | ||
212 | if (Is_invalidtrap_enabled()) | ||
213 | return(OPC_2E_INVALIDEXCEPTION); | ||
214 | Set_invalidflag(); | ||
215 | Dbl_makequietnan(resultp1,resultp2); | ||
216 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
217 | return(NOEXCEPTION); | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * return infinity | ||
222 | */ | ||
223 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
224 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
225 | return(NOEXCEPTION); | ||
226 | } | ||
227 | } | ||
228 | else { | ||
229 | /* | ||
230 | * is NaN; signaling or quiet? | ||
231 | */ | ||
232 | if (Dbl_isone_signaling(opnd2p1)) { | ||
233 | /* trap if INVALIDTRAP enabled */ | ||
234 | if (Is_invalidtrap_enabled()) | ||
235 | return(OPC_2E_INVALIDEXCEPTION); | ||
236 | /* make NaN quiet */ | ||
237 | Set_invalidflag(); | ||
238 | Dbl_set_quiet(opnd2p1); | ||
239 | } | ||
240 | /* | ||
241 | * is third operand a signaling NaN? | ||
242 | */ | ||
243 | else if (Dbl_is_signalingnan(opnd3p1)) { | ||
244 | /* trap if INVALIDTRAP enabled */ | ||
245 | if (Is_invalidtrap_enabled()) | ||
246 | return(OPC_2E_INVALIDEXCEPTION); | ||
247 | /* make NaN quiet */ | ||
248 | Set_invalidflag(); | ||
249 | Dbl_set_quiet(opnd3p1); | ||
250 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
251 | return(NOEXCEPTION); | ||
252 | } | ||
253 | /* | ||
254 | * return quiet NaN | ||
255 | */ | ||
256 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
257 | return(NOEXCEPTION); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * check third operand for NaN's or infinity | ||
263 | */ | ||
264 | if (Dbl_isinfinity_exponent(opnd3p1)) { | ||
265 | if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { | ||
266 | /* return infinity */ | ||
267 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
268 | return(NOEXCEPTION); | ||
269 | } else { | ||
270 | /* | ||
271 | * is NaN; signaling or quiet? | ||
272 | */ | ||
273 | if (Dbl_isone_signaling(opnd3p1)) { | ||
274 | /* trap if INVALIDTRAP enabled */ | ||
275 | if (Is_invalidtrap_enabled()) | ||
276 | return(OPC_2E_INVALIDEXCEPTION); | ||
277 | /* make NaN quiet */ | ||
278 | Set_invalidflag(); | ||
279 | Dbl_set_quiet(opnd3p1); | ||
280 | } | ||
281 | /* | ||
282 | * return quiet NaN | ||
283 | */ | ||
284 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
285 | return(NOEXCEPTION); | ||
286 | } | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * Generate multiply mantissa | ||
291 | */ | ||
292 | if (Dbl_isnotzero_exponent(opnd1p1)) { | ||
293 | /* set hidden bit */ | ||
294 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
295 | } | ||
296 | else { | ||
297 | /* check for zero */ | ||
298 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
299 | /* | ||
300 | * Perform the add opnd3 with zero here. | ||
301 | */ | ||
302 | if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { | ||
303 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
304 | Dbl_or_signs(opnd3p1,resultp1); | ||
305 | } else { | ||
306 | Dbl_and_signs(opnd3p1,resultp1); | ||
307 | } | ||
308 | } | ||
309 | /* | ||
310 | * Now let's check for trapped underflow case. | ||
311 | */ | ||
312 | else if (Dbl_iszero_exponent(opnd3p1) && | ||
313 | Is_underflowtrap_enabled()) { | ||
314 | /* need to normalize results mantissa */ | ||
315 | sign_save = Dbl_signextendedsign(opnd3p1); | ||
316 | result_exponent = 0; | ||
317 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
318 | Dbl_normalize(opnd3p1,opnd3p2,result_exponent); | ||
319 | Dbl_set_sign(opnd3p1,/*using*/sign_save); | ||
320 | Dbl_setwrapped_exponent(opnd3p1,result_exponent, | ||
321 | unfl); | ||
322 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
323 | /* inexact = FALSE */ | ||
324 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
325 | } | ||
326 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
327 | return(NOEXCEPTION); | ||
328 | } | ||
329 | /* is denormalized, adjust exponent */ | ||
330 | Dbl_clear_signexponent(opnd1p1); | ||
331 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
332 | Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent); | ||
333 | } | ||
334 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
335 | if (Dbl_isnotzero_exponent(opnd2p1)) { | ||
336 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
337 | } | ||
338 | else { | ||
339 | /* check for zero */ | ||
340 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
341 | /* | ||
342 | * Perform the add opnd3 with zero here. | ||
343 | */ | ||
344 | if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { | ||
345 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
346 | Dbl_or_signs(opnd3p1,resultp1); | ||
347 | } else { | ||
348 | Dbl_and_signs(opnd3p1,resultp1); | ||
349 | } | ||
350 | } | ||
351 | /* | ||
352 | * Now let's check for trapped underflow case. | ||
353 | */ | ||
354 | else if (Dbl_iszero_exponent(opnd3p1) && | ||
355 | Is_underflowtrap_enabled()) { | ||
356 | /* need to normalize results mantissa */ | ||
357 | sign_save = Dbl_signextendedsign(opnd3p1); | ||
358 | result_exponent = 0; | ||
359 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
360 | Dbl_normalize(opnd3p1,opnd3p2,result_exponent); | ||
361 | Dbl_set_sign(opnd3p1,/*using*/sign_save); | ||
362 | Dbl_setwrapped_exponent(opnd3p1,result_exponent, | ||
363 | unfl); | ||
364 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
365 | /* inexact = FALSE */ | ||
366 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
367 | } | ||
368 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
369 | return(NOEXCEPTION); | ||
370 | } | ||
371 | /* is denormalized; want to normalize */ | ||
372 | Dbl_clear_signexponent(opnd2p1); | ||
373 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
374 | Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent); | ||
375 | } | ||
376 | |||
377 | /* Multiply the first two source mantissas together */ | ||
378 | |||
379 | /* | ||
380 | * The intermediate result will be kept in tmpres, | ||
381 | * which needs enough room for 106 bits of mantissa, | ||
382 | * so lets call it a Double extended. | ||
383 | */ | ||
384 | Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
385 | |||
386 | /* | ||
387 | * Four bits at a time are inspected in each loop, and a | ||
388 | * simple shift and add multiply algorithm is used. | ||
389 | */ | ||
390 | for (count = DBL_P-1; count >= 0; count -= 4) { | ||
391 | Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
392 | if (Dbit28p2(opnd1p2)) { | ||
393 | /* Fourword_add should be an ADD followed by 3 ADDC's */ | ||
394 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
395 | opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0); | ||
396 | } | ||
397 | if (Dbit29p2(opnd1p2)) { | ||
398 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
399 | opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0); | ||
400 | } | ||
401 | if (Dbit30p2(opnd1p2)) { | ||
402 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
403 | opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0); | ||
404 | } | ||
405 | if (Dbit31p2(opnd1p2)) { | ||
406 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
407 | opnd2p1, opnd2p2, 0, 0); | ||
408 | } | ||
409 | Dbl_rightshiftby4(opnd1p1,opnd1p2); | ||
410 | } | ||
411 | if (Is_dexthiddenoverflow(tmpresp1)) { | ||
412 | /* result mantissa >= 2 (mantissa overflow) */ | ||
413 | mpy_exponent++; | ||
414 | Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * Restore the sign of the mpy result which was saved in resultp1. | ||
419 | * The exponent will continue to be kept in mpy_exponent. | ||
420 | */ | ||
421 | Dblext_set_sign(tmpresp1,Dbl_sign(resultp1)); | ||
422 | |||
423 | /* | ||
424 | * No rounding is required, since the result of the multiply | ||
425 | * is exact in the extended format. | ||
426 | */ | ||
427 | |||
428 | /* | ||
429 | * Now we are ready to perform the add portion of the operation. | ||
430 | * | ||
431 | * The exponents need to be kept as integers for now, since the | ||
432 | * multiply result might not fit into the exponent field. We | ||
433 | * can't overflow or underflow because of this yet, since the | ||
434 | * add could bring the final result back into range. | ||
435 | */ | ||
436 | add_exponent = Dbl_exponent(opnd3p1); | ||
437 | |||
438 | /* | ||
439 | * Check for denormalized or zero add operand. | ||
440 | */ | ||
441 | if (add_exponent == 0) { | ||
442 | /* check for zero */ | ||
443 | if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { | ||
444 | /* right is zero */ | ||
445 | /* Left can't be zero and must be result. | ||
446 | * | ||
447 | * The final result is now in tmpres and mpy_exponent, | ||
448 | * and needs to be rounded and squeezed back into | ||
449 | * double precision format from double extended. | ||
450 | */ | ||
451 | result_exponent = mpy_exponent; | ||
452 | Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
453 | resultp1,resultp2,resultp3,resultp4); | ||
454 | sign_save = Dbl_signextendedsign(resultp1);/*save sign*/ | ||
455 | goto round; | ||
456 | } | ||
457 | |||
458 | /* | ||
459 | * Neither are zeroes. | ||
460 | * Adjust exponent and normalize add operand. | ||
461 | */ | ||
462 | sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */ | ||
463 | Dbl_clear_signexponent(opnd3p1); | ||
464 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
465 | Dbl_normalize(opnd3p1,opnd3p2,add_exponent); | ||
466 | Dbl_set_sign(opnd3p1,sign_save); /* restore sign */ | ||
467 | } else { | ||
468 | Dbl_clear_exponent_set_hidden(opnd3p1); | ||
469 | } | ||
470 | /* | ||
471 | * Copy opnd3 to the double extended variable called right. | ||
472 | */ | ||
473 | Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4); | ||
474 | |||
475 | /* | ||
476 | * A zero "save" helps discover equal operands (for later), | ||
477 | * and is used in swapping operands (if needed). | ||
478 | */ | ||
479 | Dblext_xortointp1(tmpresp1,rightp1,/*to*/save); | ||
480 | |||
481 | /* | ||
482 | * Compare magnitude of operands. | ||
483 | */ | ||
484 | Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1); | ||
485 | Dblext_copytoint_exponentmantissap1(rightp1,signlessright1); | ||
486 | if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && | ||
487 | Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){ | ||
488 | /* | ||
489 | * Set the left operand to the larger one by XOR swap. | ||
490 | * First finish the first word "save". | ||
491 | */ | ||
492 | Dblext_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
493 | Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); | ||
494 | Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4, | ||
495 | rightp2,rightp3,rightp4); | ||
496 | /* also setup exponents used in rest of routine */ | ||
497 | diff_exponent = add_exponent - mpy_exponent; | ||
498 | result_exponent = add_exponent; | ||
499 | } else { | ||
500 | /* also setup exponents used in rest of routine */ | ||
501 | diff_exponent = mpy_exponent - add_exponent; | ||
502 | result_exponent = mpy_exponent; | ||
503 | } | ||
504 | /* Invariant: left is not smaller than right. */ | ||
505 | |||
506 | /* | ||
507 | * Special case alignment of operands that would force alignment | ||
508 | * beyond the extent of the extension. A further optimization | ||
509 | * could special case this but only reduces the path length for | ||
510 | * this infrequent case. | ||
511 | */ | ||
512 | if (diff_exponent > DBLEXT_THRESHOLD) { | ||
513 | diff_exponent = DBLEXT_THRESHOLD; | ||
514 | } | ||
515 | |||
516 | /* Align right operand by shifting it to the right */ | ||
517 | Dblext_clear_sign(rightp1); | ||
518 | Dblext_right_align(rightp1,rightp2,rightp3,rightp4, | ||
519 | /*shifted by*/diff_exponent); | ||
520 | |||
521 | /* Treat sum and difference of the operands separately. */ | ||
522 | if ((int)save < 0) { | ||
523 | /* | ||
524 | * Difference of the two operands. Overflow can occur if the | ||
525 | * multiply overflowed. A borrow can occur out of the hidden | ||
526 | * bit and force a post normalization phase. | ||
527 | */ | ||
528 | Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
529 | rightp1,rightp2,rightp3,rightp4, | ||
530 | resultp1,resultp2,resultp3,resultp4); | ||
531 | sign_save = Dbl_signextendedsign(resultp1); | ||
532 | if (Dbl_iszero_hidden(resultp1)) { | ||
533 | /* Handle normalization */ | ||
534 | /* A straight foward algorithm would now shift the | ||
535 | * result and extension left until the hidden bit | ||
536 | * becomes one. Not all of the extension bits need | ||
537 | * participate in the shift. Only the two most | ||
538 | * significant bits (round and guard) are needed. | ||
539 | * If only a single shift is needed then the guard | ||
540 | * bit becomes a significant low order bit and the | ||
541 | * extension must participate in the rounding. | ||
542 | * If more than a single shift is needed, then all | ||
543 | * bits to the right of the guard bit are zeros, | ||
544 | * and the guard bit may or may not be zero. */ | ||
545 | Dblext_leftshiftby1(resultp1,resultp2,resultp3, | ||
546 | resultp4); | ||
547 | |||
548 | /* Need to check for a zero result. The sign and | ||
549 | * exponent fields have already been zeroed. The more | ||
550 | * efficient test of the full object can be used. | ||
551 | */ | ||
552 | if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){ | ||
553 | /* Must have been "x-x" or "x+(-x)". */ | ||
554 | if (Is_rounding_mode(ROUNDMINUS)) | ||
555 | Dbl_setone_sign(resultp1); | ||
556 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
557 | return(NOEXCEPTION); | ||
558 | } | ||
559 | result_exponent--; | ||
560 | |||
561 | /* Look to see if normalization is finished. */ | ||
562 | if (Dbl_isone_hidden(resultp1)) { | ||
563 | /* No further normalization is needed */ | ||
564 | goto round; | ||
565 | } | ||
566 | |||
567 | /* Discover first one bit to determine shift amount. | ||
568 | * Use a modified binary search. We have already | ||
569 | * shifted the result one position right and still | ||
570 | * not found a one so the remainder of the extension | ||
571 | * must be zero and simplifies rounding. */ | ||
572 | /* Scan bytes */ | ||
573 | while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) { | ||
574 | Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4); | ||
575 | result_exponent -= 8; | ||
576 | } | ||
577 | /* Now narrow it down to the nibble */ | ||
578 | if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) { | ||
579 | /* The lower nibble contains the | ||
580 | * normalizing one */ | ||
581 | Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4); | ||
582 | result_exponent -= 4; | ||
583 | } | ||
584 | /* Select case where first bit is set (already | ||
585 | * normalized) otherwise select the proper shift. */ | ||
586 | jumpsize = Dbl_hiddenhigh3mantissa(resultp1); | ||
587 | if (jumpsize <= 7) switch(jumpsize) { | ||
588 | case 1: | ||
589 | Dblext_leftshiftby3(resultp1,resultp2,resultp3, | ||
590 | resultp4); | ||
591 | result_exponent -= 3; | ||
592 | break; | ||
593 | case 2: | ||
594 | case 3: | ||
595 | Dblext_leftshiftby2(resultp1,resultp2,resultp3, | ||
596 | resultp4); | ||
597 | result_exponent -= 2; | ||
598 | break; | ||
599 | case 4: | ||
600 | case 5: | ||
601 | case 6: | ||
602 | case 7: | ||
603 | Dblext_leftshiftby1(resultp1,resultp2,resultp3, | ||
604 | resultp4); | ||
605 | result_exponent -= 1; | ||
606 | break; | ||
607 | } | ||
608 | } /* end if (hidden...)... */ | ||
609 | /* Fall through and round */ | ||
610 | } /* end if (save < 0)... */ | ||
611 | else { | ||
612 | /* Add magnitudes */ | ||
613 | Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
614 | rightp1,rightp2,rightp3,rightp4, | ||
615 | /*to*/resultp1,resultp2,resultp3,resultp4); | ||
616 | sign_save = Dbl_signextendedsign(resultp1); | ||
617 | if (Dbl_isone_hiddenoverflow(resultp1)) { | ||
618 | /* Prenormalization required. */ | ||
619 | Dblext_arithrightshiftby1(resultp1,resultp2,resultp3, | ||
620 | resultp4); | ||
621 | result_exponent++; | ||
622 | } /* end if hiddenoverflow... */ | ||
623 | } /* end else ...add magnitudes... */ | ||
624 | |||
625 | /* Round the result. If the extension and lower two words are | ||
626 | * all zeros, then the result is exact. Otherwise round in the | ||
627 | * correct direction. Underflow is possible. If a postnormalization | ||
628 | * is necessary, then the mantissa is all zeros so no shift is needed. | ||
629 | */ | ||
630 | round: | ||
631 | if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { | ||
632 | Dblext_denormalize(resultp1,resultp2,resultp3,resultp4, | ||
633 | result_exponent,is_tiny); | ||
634 | } | ||
635 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
636 | if (Dblext_isnotzero_mantissap3(resultp3) || | ||
637 | Dblext_isnotzero_mantissap4(resultp4)) { | ||
638 | inexact = TRUE; | ||
639 | switch(Rounding_mode()) { | ||
640 | case ROUNDNEAREST: /* The default. */ | ||
641 | if (Dblext_isone_highp3(resultp3)) { | ||
642 | /* at least 1/2 ulp */ | ||
643 | if (Dblext_isnotzero_low31p3(resultp3) || | ||
644 | Dblext_isnotzero_mantissap4(resultp4) || | ||
645 | Dblext_isone_lowp2(resultp2)) { | ||
646 | /* either exactly half way and odd or | ||
647 | * more than 1/2ulp */ | ||
648 | Dbl_increment(resultp1,resultp2); | ||
649 | } | ||
650 | } | ||
651 | break; | ||
652 | |||
653 | case ROUNDPLUS: | ||
654 | if (Dbl_iszero_sign(resultp1)) { | ||
655 | /* Round up positive results */ | ||
656 | Dbl_increment(resultp1,resultp2); | ||
657 | } | ||
658 | break; | ||
659 | |||
660 | case ROUNDMINUS: | ||
661 | if (Dbl_isone_sign(resultp1)) { | ||
662 | /* Round down negative results */ | ||
663 | Dbl_increment(resultp1,resultp2); | ||
664 | } | ||
665 | |||
666 | case ROUNDZERO:; | ||
667 | /* truncate is simple */ | ||
668 | } /* end switch... */ | ||
669 | if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
670 | } | ||
671 | if (result_exponent >= DBL_INFINITY_EXPONENT) { | ||
672 | /* trap if OVERFLOWTRAP enabled */ | ||
673 | if (Is_overflowtrap_enabled()) { | ||
674 | /* | ||
675 | * Adjust bias of result | ||
676 | */ | ||
677 | Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
678 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
679 | if (inexact) | ||
680 | if (Is_inexacttrap_enabled()) | ||
681 | return (OPC_2E_OVERFLOWEXCEPTION | | ||
682 | OPC_2E_INEXACTEXCEPTION); | ||
683 | else Set_inexactflag(); | ||
684 | return (OPC_2E_OVERFLOWEXCEPTION); | ||
685 | } | ||
686 | inexact = TRUE; | ||
687 | Set_overflowflag(); | ||
688 | /* set result to infinity or largest number */ | ||
689 | Dbl_setoverflow(resultp1,resultp2); | ||
690 | |||
691 | } else if (result_exponent <= 0) { /* underflow case */ | ||
692 | if (Is_underflowtrap_enabled()) { | ||
693 | /* | ||
694 | * Adjust bias of result | ||
695 | */ | ||
696 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
697 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
698 | if (inexact) | ||
699 | if (Is_inexacttrap_enabled()) | ||
700 | return (OPC_2E_UNDERFLOWEXCEPTION | | ||
701 | OPC_2E_INEXACTEXCEPTION); | ||
702 | else Set_inexactflag(); | ||
703 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
704 | } | ||
705 | else if (inexact && is_tiny) Set_underflowflag(); | ||
706 | } | ||
707 | else Dbl_set_exponent(resultp1,result_exponent); | ||
708 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
709 | if (inexact) | ||
710 | if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); | ||
711 | else Set_inexactflag(); | ||
712 | return(NOEXCEPTION); | ||
713 | } | ||
714 | |||
715 | /* | ||
716 | * Double Floating-point Multiply Negate Fused Add | ||
717 | */ | ||
718 | |||
719 | dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
720 | |||
721 | dbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; | ||
722 | unsigned int *status; | ||
723 | { | ||
724 | unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2; | ||
725 | register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4; | ||
726 | unsigned int rightp1, rightp2, rightp3, rightp4; | ||
727 | unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0; | ||
728 | register int mpy_exponent, add_exponent, count; | ||
729 | boolean inexact = FALSE, is_tiny = FALSE; | ||
730 | |||
731 | unsigned int signlessleft1, signlessright1, save; | ||
732 | register int result_exponent, diff_exponent; | ||
733 | int sign_save, jumpsize; | ||
734 | |||
735 | Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2); | ||
736 | Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2); | ||
737 | Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2); | ||
738 | |||
739 | /* | ||
740 | * set sign bit of result of multiply | ||
741 | */ | ||
742 | if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) | ||
743 | Dbl_setzerop1(resultp1); | ||
744 | else | ||
745 | Dbl_setnegativezerop1(resultp1); | ||
746 | |||
747 | /* | ||
748 | * Generate multiply exponent | ||
749 | */ | ||
750 | mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS; | ||
751 | |||
752 | /* | ||
753 | * check first operand for NaN's or infinity | ||
754 | */ | ||
755 | if (Dbl_isinfinity_exponent(opnd1p1)) { | ||
756 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
757 | if (Dbl_isnotnan(opnd2p1,opnd2p2) && | ||
758 | Dbl_isnotnan(opnd3p1,opnd3p2)) { | ||
759 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
760 | /* | ||
761 | * invalid since operands are infinity | ||
762 | * and zero | ||
763 | */ | ||
764 | if (Is_invalidtrap_enabled()) | ||
765 | return(OPC_2E_INVALIDEXCEPTION); | ||
766 | Set_invalidflag(); | ||
767 | Dbl_makequietnan(resultp1,resultp2); | ||
768 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
769 | return(NOEXCEPTION); | ||
770 | } | ||
771 | /* | ||
772 | * Check third operand for infinity with a | ||
773 | * sign opposite of the multiply result | ||
774 | */ | ||
775 | if (Dbl_isinfinity(opnd3p1,opnd3p2) && | ||
776 | (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { | ||
777 | /* | ||
778 | * invalid since attempting a magnitude | ||
779 | * subtraction of infinities | ||
780 | */ | ||
781 | if (Is_invalidtrap_enabled()) | ||
782 | return(OPC_2E_INVALIDEXCEPTION); | ||
783 | Set_invalidflag(); | ||
784 | Dbl_makequietnan(resultp1,resultp2); | ||
785 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
786 | return(NOEXCEPTION); | ||
787 | } | ||
788 | |||
789 | /* | ||
790 | * return infinity | ||
791 | */ | ||
792 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
793 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
794 | return(NOEXCEPTION); | ||
795 | } | ||
796 | } | ||
797 | else { | ||
798 | /* | ||
799 | * is NaN; signaling or quiet? | ||
800 | */ | ||
801 | if (Dbl_isone_signaling(opnd1p1)) { | ||
802 | /* trap if INVALIDTRAP enabled */ | ||
803 | if (Is_invalidtrap_enabled()) | ||
804 | return(OPC_2E_INVALIDEXCEPTION); | ||
805 | /* make NaN quiet */ | ||
806 | Set_invalidflag(); | ||
807 | Dbl_set_quiet(opnd1p1); | ||
808 | } | ||
809 | /* | ||
810 | * is second operand a signaling NaN? | ||
811 | */ | ||
812 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
813 | /* trap if INVALIDTRAP enabled */ | ||
814 | if (Is_invalidtrap_enabled()) | ||
815 | return(OPC_2E_INVALIDEXCEPTION); | ||
816 | /* make NaN quiet */ | ||
817 | Set_invalidflag(); | ||
818 | Dbl_set_quiet(opnd2p1); | ||
819 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
820 | return(NOEXCEPTION); | ||
821 | } | ||
822 | /* | ||
823 | * is third operand a signaling NaN? | ||
824 | */ | ||
825 | else if (Dbl_is_signalingnan(opnd3p1)) { | ||
826 | /* trap if INVALIDTRAP enabled */ | ||
827 | if (Is_invalidtrap_enabled()) | ||
828 | return(OPC_2E_INVALIDEXCEPTION); | ||
829 | /* make NaN quiet */ | ||
830 | Set_invalidflag(); | ||
831 | Dbl_set_quiet(opnd3p1); | ||
832 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
833 | return(NOEXCEPTION); | ||
834 | } | ||
835 | /* | ||
836 | * return quiet NaN | ||
837 | */ | ||
838 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
839 | return(NOEXCEPTION); | ||
840 | } | ||
841 | } | ||
842 | |||
843 | /* | ||
844 | * check second operand for NaN's or infinity | ||
845 | */ | ||
846 | if (Dbl_isinfinity_exponent(opnd2p1)) { | ||
847 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
848 | if (Dbl_isnotnan(opnd3p1,opnd3p2)) { | ||
849 | if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { | ||
850 | /* | ||
851 | * invalid since multiply operands are | ||
852 | * zero & infinity | ||
853 | */ | ||
854 | if (Is_invalidtrap_enabled()) | ||
855 | return(OPC_2E_INVALIDEXCEPTION); | ||
856 | Set_invalidflag(); | ||
857 | Dbl_makequietnan(opnd2p1,opnd2p2); | ||
858 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
859 | return(NOEXCEPTION); | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * Check third operand for infinity with a | ||
864 | * sign opposite of the multiply result | ||
865 | */ | ||
866 | if (Dbl_isinfinity(opnd3p1,opnd3p2) && | ||
867 | (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { | ||
868 | /* | ||
869 | * invalid since attempting a magnitude | ||
870 | * subtraction of infinities | ||
871 | */ | ||
872 | if (Is_invalidtrap_enabled()) | ||
873 | return(OPC_2E_INVALIDEXCEPTION); | ||
874 | Set_invalidflag(); | ||
875 | Dbl_makequietnan(resultp1,resultp2); | ||
876 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
877 | return(NOEXCEPTION); | ||
878 | } | ||
879 | |||
880 | /* | ||
881 | * return infinity | ||
882 | */ | ||
883 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
884 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
885 | return(NOEXCEPTION); | ||
886 | } | ||
887 | } | ||
888 | else { | ||
889 | /* | ||
890 | * is NaN; signaling or quiet? | ||
891 | */ | ||
892 | if (Dbl_isone_signaling(opnd2p1)) { | ||
893 | /* trap if INVALIDTRAP enabled */ | ||
894 | if (Is_invalidtrap_enabled()) | ||
895 | return(OPC_2E_INVALIDEXCEPTION); | ||
896 | /* make NaN quiet */ | ||
897 | Set_invalidflag(); | ||
898 | Dbl_set_quiet(opnd2p1); | ||
899 | } | ||
900 | /* | ||
901 | * is third operand a signaling NaN? | ||
902 | */ | ||
903 | else if (Dbl_is_signalingnan(opnd3p1)) { | ||
904 | /* trap if INVALIDTRAP enabled */ | ||
905 | if (Is_invalidtrap_enabled()) | ||
906 | return(OPC_2E_INVALIDEXCEPTION); | ||
907 | /* make NaN quiet */ | ||
908 | Set_invalidflag(); | ||
909 | Dbl_set_quiet(opnd3p1); | ||
910 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
911 | return(NOEXCEPTION); | ||
912 | } | ||
913 | /* | ||
914 | * return quiet NaN | ||
915 | */ | ||
916 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
917 | return(NOEXCEPTION); | ||
918 | } | ||
919 | } | ||
920 | |||
921 | /* | ||
922 | * check third operand for NaN's or infinity | ||
923 | */ | ||
924 | if (Dbl_isinfinity_exponent(opnd3p1)) { | ||
925 | if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { | ||
926 | /* return infinity */ | ||
927 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
928 | return(NOEXCEPTION); | ||
929 | } else { | ||
930 | /* | ||
931 | * is NaN; signaling or quiet? | ||
932 | */ | ||
933 | if (Dbl_isone_signaling(opnd3p1)) { | ||
934 | /* trap if INVALIDTRAP enabled */ | ||
935 | if (Is_invalidtrap_enabled()) | ||
936 | return(OPC_2E_INVALIDEXCEPTION); | ||
937 | /* make NaN quiet */ | ||
938 | Set_invalidflag(); | ||
939 | Dbl_set_quiet(opnd3p1); | ||
940 | } | ||
941 | /* | ||
942 | * return quiet NaN | ||
943 | */ | ||
944 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
945 | return(NOEXCEPTION); | ||
946 | } | ||
947 | } | ||
948 | |||
949 | /* | ||
950 | * Generate multiply mantissa | ||
951 | */ | ||
952 | if (Dbl_isnotzero_exponent(opnd1p1)) { | ||
953 | /* set hidden bit */ | ||
954 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
955 | } | ||
956 | else { | ||
957 | /* check for zero */ | ||
958 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
959 | /* | ||
960 | * Perform the add opnd3 with zero here. | ||
961 | */ | ||
962 | if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { | ||
963 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
964 | Dbl_or_signs(opnd3p1,resultp1); | ||
965 | } else { | ||
966 | Dbl_and_signs(opnd3p1,resultp1); | ||
967 | } | ||
968 | } | ||
969 | /* | ||
970 | * Now let's check for trapped underflow case. | ||
971 | */ | ||
972 | else if (Dbl_iszero_exponent(opnd3p1) && | ||
973 | Is_underflowtrap_enabled()) { | ||
974 | /* need to normalize results mantissa */ | ||
975 | sign_save = Dbl_signextendedsign(opnd3p1); | ||
976 | result_exponent = 0; | ||
977 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
978 | Dbl_normalize(opnd3p1,opnd3p2,result_exponent); | ||
979 | Dbl_set_sign(opnd3p1,/*using*/sign_save); | ||
980 | Dbl_setwrapped_exponent(opnd3p1,result_exponent, | ||
981 | unfl); | ||
982 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
983 | /* inexact = FALSE */ | ||
984 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
985 | } | ||
986 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
987 | return(NOEXCEPTION); | ||
988 | } | ||
989 | /* is denormalized, adjust exponent */ | ||
990 | Dbl_clear_signexponent(opnd1p1); | ||
991 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
992 | Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent); | ||
993 | } | ||
994 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
995 | if (Dbl_isnotzero_exponent(opnd2p1)) { | ||
996 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
997 | } | ||
998 | else { | ||
999 | /* check for zero */ | ||
1000 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
1001 | /* | ||
1002 | * Perform the add opnd3 with zero here. | ||
1003 | */ | ||
1004 | if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { | ||
1005 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
1006 | Dbl_or_signs(opnd3p1,resultp1); | ||
1007 | } else { | ||
1008 | Dbl_and_signs(opnd3p1,resultp1); | ||
1009 | } | ||
1010 | } | ||
1011 | /* | ||
1012 | * Now let's check for trapped underflow case. | ||
1013 | */ | ||
1014 | else if (Dbl_iszero_exponent(opnd3p1) && | ||
1015 | Is_underflowtrap_enabled()) { | ||
1016 | /* need to normalize results mantissa */ | ||
1017 | sign_save = Dbl_signextendedsign(opnd3p1); | ||
1018 | result_exponent = 0; | ||
1019 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
1020 | Dbl_normalize(opnd3p1,opnd3p2,result_exponent); | ||
1021 | Dbl_set_sign(opnd3p1,/*using*/sign_save); | ||
1022 | Dbl_setwrapped_exponent(opnd3p1,result_exponent, | ||
1023 | unfl); | ||
1024 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
1025 | /* inexact = FALSE */ | ||
1026 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
1027 | } | ||
1028 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
1029 | return(NOEXCEPTION); | ||
1030 | } | ||
1031 | /* is denormalized; want to normalize */ | ||
1032 | Dbl_clear_signexponent(opnd2p1); | ||
1033 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
1034 | Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent); | ||
1035 | } | ||
1036 | |||
1037 | /* Multiply the first two source mantissas together */ | ||
1038 | |||
1039 | /* | ||
1040 | * The intermediate result will be kept in tmpres, | ||
1041 | * which needs enough room for 106 bits of mantissa, | ||
1042 | * so lets call it a Double extended. | ||
1043 | */ | ||
1044 | Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
1045 | |||
1046 | /* | ||
1047 | * Four bits at a time are inspected in each loop, and a | ||
1048 | * simple shift and add multiply algorithm is used. | ||
1049 | */ | ||
1050 | for (count = DBL_P-1; count >= 0; count -= 4) { | ||
1051 | Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
1052 | if (Dbit28p2(opnd1p2)) { | ||
1053 | /* Fourword_add should be an ADD followed by 3 ADDC's */ | ||
1054 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
1055 | opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0); | ||
1056 | } | ||
1057 | if (Dbit29p2(opnd1p2)) { | ||
1058 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
1059 | opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0); | ||
1060 | } | ||
1061 | if (Dbit30p2(opnd1p2)) { | ||
1062 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
1063 | opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0); | ||
1064 | } | ||
1065 | if (Dbit31p2(opnd1p2)) { | ||
1066 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
1067 | opnd2p1, opnd2p2, 0, 0); | ||
1068 | } | ||
1069 | Dbl_rightshiftby4(opnd1p1,opnd1p2); | ||
1070 | } | ||
1071 | if (Is_dexthiddenoverflow(tmpresp1)) { | ||
1072 | /* result mantissa >= 2 (mantissa overflow) */ | ||
1073 | mpy_exponent++; | ||
1074 | Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
1075 | } | ||
1076 | |||
1077 | /* | ||
1078 | * Restore the sign of the mpy result which was saved in resultp1. | ||
1079 | * The exponent will continue to be kept in mpy_exponent. | ||
1080 | */ | ||
1081 | Dblext_set_sign(tmpresp1,Dbl_sign(resultp1)); | ||
1082 | |||
1083 | /* | ||
1084 | * No rounding is required, since the result of the multiply | ||
1085 | * is exact in the extended format. | ||
1086 | */ | ||
1087 | |||
1088 | /* | ||
1089 | * Now we are ready to perform the add portion of the operation. | ||
1090 | * | ||
1091 | * The exponents need to be kept as integers for now, since the | ||
1092 | * multiply result might not fit into the exponent field. We | ||
1093 | * can't overflow or underflow because of this yet, since the | ||
1094 | * add could bring the final result back into range. | ||
1095 | */ | ||
1096 | add_exponent = Dbl_exponent(opnd3p1); | ||
1097 | |||
1098 | /* | ||
1099 | * Check for denormalized or zero add operand. | ||
1100 | */ | ||
1101 | if (add_exponent == 0) { | ||
1102 | /* check for zero */ | ||
1103 | if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { | ||
1104 | /* right is zero */ | ||
1105 | /* Left can't be zero and must be result. | ||
1106 | * | ||
1107 | * The final result is now in tmpres and mpy_exponent, | ||
1108 | * and needs to be rounded and squeezed back into | ||
1109 | * double precision format from double extended. | ||
1110 | */ | ||
1111 | result_exponent = mpy_exponent; | ||
1112 | Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
1113 | resultp1,resultp2,resultp3,resultp4); | ||
1114 | sign_save = Dbl_signextendedsign(resultp1);/*save sign*/ | ||
1115 | goto round; | ||
1116 | } | ||
1117 | |||
1118 | /* | ||
1119 | * Neither are zeroes. | ||
1120 | * Adjust exponent and normalize add operand. | ||
1121 | */ | ||
1122 | sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */ | ||
1123 | Dbl_clear_signexponent(opnd3p1); | ||
1124 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
1125 | Dbl_normalize(opnd3p1,opnd3p2,add_exponent); | ||
1126 | Dbl_set_sign(opnd3p1,sign_save); /* restore sign */ | ||
1127 | } else { | ||
1128 | Dbl_clear_exponent_set_hidden(opnd3p1); | ||
1129 | } | ||
1130 | /* | ||
1131 | * Copy opnd3 to the double extended variable called right. | ||
1132 | */ | ||
1133 | Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4); | ||
1134 | |||
1135 | /* | ||
1136 | * A zero "save" helps discover equal operands (for later), | ||
1137 | * and is used in swapping operands (if needed). | ||
1138 | */ | ||
1139 | Dblext_xortointp1(tmpresp1,rightp1,/*to*/save); | ||
1140 | |||
1141 | /* | ||
1142 | * Compare magnitude of operands. | ||
1143 | */ | ||
1144 | Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1); | ||
1145 | Dblext_copytoint_exponentmantissap1(rightp1,signlessright1); | ||
1146 | if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && | ||
1147 | Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){ | ||
1148 | /* | ||
1149 | * Set the left operand to the larger one by XOR swap. | ||
1150 | * First finish the first word "save". | ||
1151 | */ | ||
1152 | Dblext_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
1153 | Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); | ||
1154 | Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4, | ||
1155 | rightp2,rightp3,rightp4); | ||
1156 | /* also setup exponents used in rest of routine */ | ||
1157 | diff_exponent = add_exponent - mpy_exponent; | ||
1158 | result_exponent = add_exponent; | ||
1159 | } else { | ||
1160 | /* also setup exponents used in rest of routine */ | ||
1161 | diff_exponent = mpy_exponent - add_exponent; | ||
1162 | result_exponent = mpy_exponent; | ||
1163 | } | ||
1164 | /* Invariant: left is not smaller than right. */ | ||
1165 | |||
1166 | /* | ||
1167 | * Special case alignment of operands that would force alignment | ||
1168 | * beyond the extent of the extension. A further optimization | ||
1169 | * could special case this but only reduces the path length for | ||
1170 | * this infrequent case. | ||
1171 | */ | ||
1172 | if (diff_exponent > DBLEXT_THRESHOLD) { | ||
1173 | diff_exponent = DBLEXT_THRESHOLD; | ||
1174 | } | ||
1175 | |||
1176 | /* Align right operand by shifting it to the right */ | ||
1177 | Dblext_clear_sign(rightp1); | ||
1178 | Dblext_right_align(rightp1,rightp2,rightp3,rightp4, | ||
1179 | /*shifted by*/diff_exponent); | ||
1180 | |||
1181 | /* Treat sum and difference of the operands separately. */ | ||
1182 | if ((int)save < 0) { | ||
1183 | /* | ||
1184 | * Difference of the two operands. Overflow can occur if the | ||
1185 | * multiply overflowed. A borrow can occur out of the hidden | ||
1186 | * bit and force a post normalization phase. | ||
1187 | */ | ||
1188 | Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
1189 | rightp1,rightp2,rightp3,rightp4, | ||
1190 | resultp1,resultp2,resultp3,resultp4); | ||
1191 | sign_save = Dbl_signextendedsign(resultp1); | ||
1192 | if (Dbl_iszero_hidden(resultp1)) { | ||
1193 | /* Handle normalization */ | ||
1194 | /* A straight foward algorithm would now shift the | ||
1195 | * result and extension left until the hidden bit | ||
1196 | * becomes one. Not all of the extension bits need | ||
1197 | * participate in the shift. Only the two most | ||
1198 | * significant bits (round and guard) are needed. | ||
1199 | * If only a single shift is needed then the guard | ||
1200 | * bit becomes a significant low order bit and the | ||
1201 | * extension must participate in the rounding. | ||
1202 | * If more than a single shift is needed, then all | ||
1203 | * bits to the right of the guard bit are zeros, | ||
1204 | * and the guard bit may or may not be zero. */ | ||
1205 | Dblext_leftshiftby1(resultp1,resultp2,resultp3, | ||
1206 | resultp4); | ||
1207 | |||
1208 | /* Need to check for a zero result. The sign and | ||
1209 | * exponent fields have already been zeroed. The more | ||
1210 | * efficient test of the full object can be used. | ||
1211 | */ | ||
1212 | if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) { | ||
1213 | /* Must have been "x-x" or "x+(-x)". */ | ||
1214 | if (Is_rounding_mode(ROUNDMINUS)) | ||
1215 | Dbl_setone_sign(resultp1); | ||
1216 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
1217 | return(NOEXCEPTION); | ||
1218 | } | ||
1219 | result_exponent--; | ||
1220 | |||
1221 | /* Look to see if normalization is finished. */ | ||
1222 | if (Dbl_isone_hidden(resultp1)) { | ||
1223 | /* No further normalization is needed */ | ||
1224 | goto round; | ||
1225 | } | ||
1226 | |||
1227 | /* Discover first one bit to determine shift amount. | ||
1228 | * Use a modified binary search. We have already | ||
1229 | * shifted the result one position right and still | ||
1230 | * not found a one so the remainder of the extension | ||
1231 | * must be zero and simplifies rounding. */ | ||
1232 | /* Scan bytes */ | ||
1233 | while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) { | ||
1234 | Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4); | ||
1235 | result_exponent -= 8; | ||
1236 | } | ||
1237 | /* Now narrow it down to the nibble */ | ||
1238 | if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) { | ||
1239 | /* The lower nibble contains the | ||
1240 | * normalizing one */ | ||
1241 | Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4); | ||
1242 | result_exponent -= 4; | ||
1243 | } | ||
1244 | /* Select case where first bit is set (already | ||
1245 | * normalized) otherwise select the proper shift. */ | ||
1246 | jumpsize = Dbl_hiddenhigh3mantissa(resultp1); | ||
1247 | if (jumpsize <= 7) switch(jumpsize) { | ||
1248 | case 1: | ||
1249 | Dblext_leftshiftby3(resultp1,resultp2,resultp3, | ||
1250 | resultp4); | ||
1251 | result_exponent -= 3; | ||
1252 | break; | ||
1253 | case 2: | ||
1254 | case 3: | ||
1255 | Dblext_leftshiftby2(resultp1,resultp2,resultp3, | ||
1256 | resultp4); | ||
1257 | result_exponent -= 2; | ||
1258 | break; | ||
1259 | case 4: | ||
1260 | case 5: | ||
1261 | case 6: | ||
1262 | case 7: | ||
1263 | Dblext_leftshiftby1(resultp1,resultp2,resultp3, | ||
1264 | resultp4); | ||
1265 | result_exponent -= 1; | ||
1266 | break; | ||
1267 | } | ||
1268 | } /* end if (hidden...)... */ | ||
1269 | /* Fall through and round */ | ||
1270 | } /* end if (save < 0)... */ | ||
1271 | else { | ||
1272 | /* Add magnitudes */ | ||
1273 | Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
1274 | rightp1,rightp2,rightp3,rightp4, | ||
1275 | /*to*/resultp1,resultp2,resultp3,resultp4); | ||
1276 | sign_save = Dbl_signextendedsign(resultp1); | ||
1277 | if (Dbl_isone_hiddenoverflow(resultp1)) { | ||
1278 | /* Prenormalization required. */ | ||
1279 | Dblext_arithrightshiftby1(resultp1,resultp2,resultp3, | ||
1280 | resultp4); | ||
1281 | result_exponent++; | ||
1282 | } /* end if hiddenoverflow... */ | ||
1283 | } /* end else ...add magnitudes... */ | ||
1284 | |||
1285 | /* Round the result. If the extension and lower two words are | ||
1286 | * all zeros, then the result is exact. Otherwise round in the | ||
1287 | * correct direction. Underflow is possible. If a postnormalization | ||
1288 | * is necessary, then the mantissa is all zeros so no shift is needed. | ||
1289 | */ | ||
1290 | round: | ||
1291 | if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { | ||
1292 | Dblext_denormalize(resultp1,resultp2,resultp3,resultp4, | ||
1293 | result_exponent,is_tiny); | ||
1294 | } | ||
1295 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
1296 | if (Dblext_isnotzero_mantissap3(resultp3) || | ||
1297 | Dblext_isnotzero_mantissap4(resultp4)) { | ||
1298 | inexact = TRUE; | ||
1299 | switch(Rounding_mode()) { | ||
1300 | case ROUNDNEAREST: /* The default. */ | ||
1301 | if (Dblext_isone_highp3(resultp3)) { | ||
1302 | /* at least 1/2 ulp */ | ||
1303 | if (Dblext_isnotzero_low31p3(resultp3) || | ||
1304 | Dblext_isnotzero_mantissap4(resultp4) || | ||
1305 | Dblext_isone_lowp2(resultp2)) { | ||
1306 | /* either exactly half way and odd or | ||
1307 | * more than 1/2ulp */ | ||
1308 | Dbl_increment(resultp1,resultp2); | ||
1309 | } | ||
1310 | } | ||
1311 | break; | ||
1312 | |||
1313 | case ROUNDPLUS: | ||
1314 | if (Dbl_iszero_sign(resultp1)) { | ||
1315 | /* Round up positive results */ | ||
1316 | Dbl_increment(resultp1,resultp2); | ||
1317 | } | ||
1318 | break; | ||
1319 | |||
1320 | case ROUNDMINUS: | ||
1321 | if (Dbl_isone_sign(resultp1)) { | ||
1322 | /* Round down negative results */ | ||
1323 | Dbl_increment(resultp1,resultp2); | ||
1324 | } | ||
1325 | |||
1326 | case ROUNDZERO:; | ||
1327 | /* truncate is simple */ | ||
1328 | } /* end switch... */ | ||
1329 | if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
1330 | } | ||
1331 | if (result_exponent >= DBL_INFINITY_EXPONENT) { | ||
1332 | /* Overflow */ | ||
1333 | if (Is_overflowtrap_enabled()) { | ||
1334 | /* | ||
1335 | * Adjust bias of result | ||
1336 | */ | ||
1337 | Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
1338 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
1339 | if (inexact) | ||
1340 | if (Is_inexacttrap_enabled()) | ||
1341 | return (OPC_2E_OVERFLOWEXCEPTION | | ||
1342 | OPC_2E_INEXACTEXCEPTION); | ||
1343 | else Set_inexactflag(); | ||
1344 | return (OPC_2E_OVERFLOWEXCEPTION); | ||
1345 | } | ||
1346 | inexact = TRUE; | ||
1347 | Set_overflowflag(); | ||
1348 | Dbl_setoverflow(resultp1,resultp2); | ||
1349 | } else if (result_exponent <= 0) { /* underflow case */ | ||
1350 | if (Is_underflowtrap_enabled()) { | ||
1351 | /* | ||
1352 | * Adjust bias of result | ||
1353 | */ | ||
1354 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
1355 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
1356 | if (inexact) | ||
1357 | if (Is_inexacttrap_enabled()) | ||
1358 | return (OPC_2E_UNDERFLOWEXCEPTION | | ||
1359 | OPC_2E_INEXACTEXCEPTION); | ||
1360 | else Set_inexactflag(); | ||
1361 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
1362 | } | ||
1363 | else if (inexact && is_tiny) Set_underflowflag(); | ||
1364 | } | ||
1365 | else Dbl_set_exponent(resultp1,result_exponent); | ||
1366 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
1367 | if (inexact) | ||
1368 | if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); | ||
1369 | else Set_inexactflag(); | ||
1370 | return(NOEXCEPTION); | ||
1371 | } | ||
1372 | |||
1373 | /* | ||
1374 | * Single Floating-point Multiply Fused Add | ||
1375 | */ | ||
1376 | |||
1377 | sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
1378 | |||
1379 | sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; | ||
1380 | unsigned int *status; | ||
1381 | { | ||
1382 | unsigned int opnd1, opnd2, opnd3; | ||
1383 | register unsigned int tmpresp1, tmpresp2; | ||
1384 | unsigned int rightp1, rightp2; | ||
1385 | unsigned int resultp1, resultp2 = 0; | ||
1386 | register int mpy_exponent, add_exponent, count; | ||
1387 | boolean inexact = FALSE, is_tiny = FALSE; | ||
1388 | |||
1389 | unsigned int signlessleft1, signlessright1, save; | ||
1390 | register int result_exponent, diff_exponent; | ||
1391 | int sign_save, jumpsize; | ||
1392 | |||
1393 | Sgl_copyfromptr(src1ptr,opnd1); | ||
1394 | Sgl_copyfromptr(src2ptr,opnd2); | ||
1395 | Sgl_copyfromptr(src3ptr,opnd3); | ||
1396 | |||
1397 | /* | ||
1398 | * set sign bit of result of multiply | ||
1399 | */ | ||
1400 | if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) | ||
1401 | Sgl_setnegativezero(resultp1); | ||
1402 | else Sgl_setzero(resultp1); | ||
1403 | |||
1404 | /* | ||
1405 | * Generate multiply exponent | ||
1406 | */ | ||
1407 | mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; | ||
1408 | |||
1409 | /* | ||
1410 | * check first operand for NaN's or infinity | ||
1411 | */ | ||
1412 | if (Sgl_isinfinity_exponent(opnd1)) { | ||
1413 | if (Sgl_iszero_mantissa(opnd1)) { | ||
1414 | if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) { | ||
1415 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
1416 | /* | ||
1417 | * invalid since operands are infinity | ||
1418 | * and zero | ||
1419 | */ | ||
1420 | if (Is_invalidtrap_enabled()) | ||
1421 | return(OPC_2E_INVALIDEXCEPTION); | ||
1422 | Set_invalidflag(); | ||
1423 | Sgl_makequietnan(resultp1); | ||
1424 | Sgl_copytoptr(resultp1,dstptr); | ||
1425 | return(NOEXCEPTION); | ||
1426 | } | ||
1427 | /* | ||
1428 | * Check third operand for infinity with a | ||
1429 | * sign opposite of the multiply result | ||
1430 | */ | ||
1431 | if (Sgl_isinfinity(opnd3) && | ||
1432 | (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { | ||
1433 | /* | ||
1434 | * invalid since attempting a magnitude | ||
1435 | * subtraction of infinities | ||
1436 | */ | ||
1437 | if (Is_invalidtrap_enabled()) | ||
1438 | return(OPC_2E_INVALIDEXCEPTION); | ||
1439 | Set_invalidflag(); | ||
1440 | Sgl_makequietnan(resultp1); | ||
1441 | Sgl_copytoptr(resultp1,dstptr); | ||
1442 | return(NOEXCEPTION); | ||
1443 | } | ||
1444 | |||
1445 | /* | ||
1446 | * return infinity | ||
1447 | */ | ||
1448 | Sgl_setinfinity_exponentmantissa(resultp1); | ||
1449 | Sgl_copytoptr(resultp1,dstptr); | ||
1450 | return(NOEXCEPTION); | ||
1451 | } | ||
1452 | } | ||
1453 | else { | ||
1454 | /* | ||
1455 | * is NaN; signaling or quiet? | ||
1456 | */ | ||
1457 | if (Sgl_isone_signaling(opnd1)) { | ||
1458 | /* trap if INVALIDTRAP enabled */ | ||
1459 | if (Is_invalidtrap_enabled()) | ||
1460 | return(OPC_2E_INVALIDEXCEPTION); | ||
1461 | /* make NaN quiet */ | ||
1462 | Set_invalidflag(); | ||
1463 | Sgl_set_quiet(opnd1); | ||
1464 | } | ||
1465 | /* | ||
1466 | * is second operand a signaling NaN? | ||
1467 | */ | ||
1468 | else if (Sgl_is_signalingnan(opnd2)) { | ||
1469 | /* trap if INVALIDTRAP enabled */ | ||
1470 | if (Is_invalidtrap_enabled()) | ||
1471 | return(OPC_2E_INVALIDEXCEPTION); | ||
1472 | /* make NaN quiet */ | ||
1473 | Set_invalidflag(); | ||
1474 | Sgl_set_quiet(opnd2); | ||
1475 | Sgl_copytoptr(opnd2,dstptr); | ||
1476 | return(NOEXCEPTION); | ||
1477 | } | ||
1478 | /* | ||
1479 | * is third operand a signaling NaN? | ||
1480 | */ | ||
1481 | else if (Sgl_is_signalingnan(opnd3)) { | ||
1482 | /* trap if INVALIDTRAP enabled */ | ||
1483 | if (Is_invalidtrap_enabled()) | ||
1484 | return(OPC_2E_INVALIDEXCEPTION); | ||
1485 | /* make NaN quiet */ | ||
1486 | Set_invalidflag(); | ||
1487 | Sgl_set_quiet(opnd3); | ||
1488 | Sgl_copytoptr(opnd3,dstptr); | ||
1489 | return(NOEXCEPTION); | ||
1490 | } | ||
1491 | /* | ||
1492 | * return quiet NaN | ||
1493 | */ | ||
1494 | Sgl_copytoptr(opnd1,dstptr); | ||
1495 | return(NOEXCEPTION); | ||
1496 | } | ||
1497 | } | ||
1498 | |||
1499 | /* | ||
1500 | * check second operand for NaN's or infinity | ||
1501 | */ | ||
1502 | if (Sgl_isinfinity_exponent(opnd2)) { | ||
1503 | if (Sgl_iszero_mantissa(opnd2)) { | ||
1504 | if (Sgl_isnotnan(opnd3)) { | ||
1505 | if (Sgl_iszero_exponentmantissa(opnd1)) { | ||
1506 | /* | ||
1507 | * invalid since multiply operands are | ||
1508 | * zero & infinity | ||
1509 | */ | ||
1510 | if (Is_invalidtrap_enabled()) | ||
1511 | return(OPC_2E_INVALIDEXCEPTION); | ||
1512 | Set_invalidflag(); | ||
1513 | Sgl_makequietnan(opnd2); | ||
1514 | Sgl_copytoptr(opnd2,dstptr); | ||
1515 | return(NOEXCEPTION); | ||
1516 | } | ||
1517 | |||
1518 | /* | ||
1519 | * Check third operand for infinity with a | ||
1520 | * sign opposite of the multiply result | ||
1521 | */ | ||
1522 | if (Sgl_isinfinity(opnd3) && | ||
1523 | (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { | ||
1524 | /* | ||
1525 | * invalid since attempting a magnitude | ||
1526 | * subtraction of infinities | ||
1527 | */ | ||
1528 | if (Is_invalidtrap_enabled()) | ||
1529 | return(OPC_2E_INVALIDEXCEPTION); | ||
1530 | Set_invalidflag(); | ||
1531 | Sgl_makequietnan(resultp1); | ||
1532 | Sgl_copytoptr(resultp1,dstptr); | ||
1533 | return(NOEXCEPTION); | ||
1534 | } | ||
1535 | |||
1536 | /* | ||
1537 | * return infinity | ||
1538 | */ | ||
1539 | Sgl_setinfinity_exponentmantissa(resultp1); | ||
1540 | Sgl_copytoptr(resultp1,dstptr); | ||
1541 | return(NOEXCEPTION); | ||
1542 | } | ||
1543 | } | ||
1544 | else { | ||
1545 | /* | ||
1546 | * is NaN; signaling or quiet? | ||
1547 | */ | ||
1548 | if (Sgl_isone_signaling(opnd2)) { | ||
1549 | /* trap if INVALIDTRAP enabled */ | ||
1550 | if (Is_invalidtrap_enabled()) | ||
1551 | return(OPC_2E_INVALIDEXCEPTION); | ||
1552 | /* make NaN quiet */ | ||
1553 | Set_invalidflag(); | ||
1554 | Sgl_set_quiet(opnd2); | ||
1555 | } | ||
1556 | /* | ||
1557 | * is third operand a signaling NaN? | ||
1558 | */ | ||
1559 | else if (Sgl_is_signalingnan(opnd3)) { | ||
1560 | /* trap if INVALIDTRAP enabled */ | ||
1561 | if (Is_invalidtrap_enabled()) | ||
1562 | return(OPC_2E_INVALIDEXCEPTION); | ||
1563 | /* make NaN quiet */ | ||
1564 | Set_invalidflag(); | ||
1565 | Sgl_set_quiet(opnd3); | ||
1566 | Sgl_copytoptr(opnd3,dstptr); | ||
1567 | return(NOEXCEPTION); | ||
1568 | } | ||
1569 | /* | ||
1570 | * return quiet NaN | ||
1571 | */ | ||
1572 | Sgl_copytoptr(opnd2,dstptr); | ||
1573 | return(NOEXCEPTION); | ||
1574 | } | ||
1575 | } | ||
1576 | |||
1577 | /* | ||
1578 | * check third operand for NaN's or infinity | ||
1579 | */ | ||
1580 | if (Sgl_isinfinity_exponent(opnd3)) { | ||
1581 | if (Sgl_iszero_mantissa(opnd3)) { | ||
1582 | /* return infinity */ | ||
1583 | Sgl_copytoptr(opnd3,dstptr); | ||
1584 | return(NOEXCEPTION); | ||
1585 | } else { | ||
1586 | /* | ||
1587 | * is NaN; signaling or quiet? | ||
1588 | */ | ||
1589 | if (Sgl_isone_signaling(opnd3)) { | ||
1590 | /* trap if INVALIDTRAP enabled */ | ||
1591 | if (Is_invalidtrap_enabled()) | ||
1592 | return(OPC_2E_INVALIDEXCEPTION); | ||
1593 | /* make NaN quiet */ | ||
1594 | Set_invalidflag(); | ||
1595 | Sgl_set_quiet(opnd3); | ||
1596 | } | ||
1597 | /* | ||
1598 | * return quiet NaN | ||
1599 | */ | ||
1600 | Sgl_copytoptr(opnd3,dstptr); | ||
1601 | return(NOEXCEPTION); | ||
1602 | } | ||
1603 | } | ||
1604 | |||
1605 | /* | ||
1606 | * Generate multiply mantissa | ||
1607 | */ | ||
1608 | if (Sgl_isnotzero_exponent(opnd1)) { | ||
1609 | /* set hidden bit */ | ||
1610 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
1611 | } | ||
1612 | else { | ||
1613 | /* check for zero */ | ||
1614 | if (Sgl_iszero_mantissa(opnd1)) { | ||
1615 | /* | ||
1616 | * Perform the add opnd3 with zero here. | ||
1617 | */ | ||
1618 | if (Sgl_iszero_exponentmantissa(opnd3)) { | ||
1619 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
1620 | Sgl_or_signs(opnd3,resultp1); | ||
1621 | } else { | ||
1622 | Sgl_and_signs(opnd3,resultp1); | ||
1623 | } | ||
1624 | } | ||
1625 | /* | ||
1626 | * Now let's check for trapped underflow case. | ||
1627 | */ | ||
1628 | else if (Sgl_iszero_exponent(opnd3) && | ||
1629 | Is_underflowtrap_enabled()) { | ||
1630 | /* need to normalize results mantissa */ | ||
1631 | sign_save = Sgl_signextendedsign(opnd3); | ||
1632 | result_exponent = 0; | ||
1633 | Sgl_leftshiftby1(opnd3); | ||
1634 | Sgl_normalize(opnd3,result_exponent); | ||
1635 | Sgl_set_sign(opnd3,/*using*/sign_save); | ||
1636 | Sgl_setwrapped_exponent(opnd3,result_exponent, | ||
1637 | unfl); | ||
1638 | Sgl_copytoptr(opnd3,dstptr); | ||
1639 | /* inexact = FALSE */ | ||
1640 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
1641 | } | ||
1642 | Sgl_copytoptr(opnd3,dstptr); | ||
1643 | return(NOEXCEPTION); | ||
1644 | } | ||
1645 | /* is denormalized, adjust exponent */ | ||
1646 | Sgl_clear_signexponent(opnd1); | ||
1647 | Sgl_leftshiftby1(opnd1); | ||
1648 | Sgl_normalize(opnd1,mpy_exponent); | ||
1649 | } | ||
1650 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
1651 | if (Sgl_isnotzero_exponent(opnd2)) { | ||
1652 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
1653 | } | ||
1654 | else { | ||
1655 | /* check for zero */ | ||
1656 | if (Sgl_iszero_mantissa(opnd2)) { | ||
1657 | /* | ||
1658 | * Perform the add opnd3 with zero here. | ||
1659 | */ | ||
1660 | if (Sgl_iszero_exponentmantissa(opnd3)) { | ||
1661 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
1662 | Sgl_or_signs(opnd3,resultp1); | ||
1663 | } else { | ||
1664 | Sgl_and_signs(opnd3,resultp1); | ||
1665 | } | ||
1666 | } | ||
1667 | /* | ||
1668 | * Now let's check for trapped underflow case. | ||
1669 | */ | ||
1670 | else if (Sgl_iszero_exponent(opnd3) && | ||
1671 | Is_underflowtrap_enabled()) { | ||
1672 | /* need to normalize results mantissa */ | ||
1673 | sign_save = Sgl_signextendedsign(opnd3); | ||
1674 | result_exponent = 0; | ||
1675 | Sgl_leftshiftby1(opnd3); | ||
1676 | Sgl_normalize(opnd3,result_exponent); | ||
1677 | Sgl_set_sign(opnd3,/*using*/sign_save); | ||
1678 | Sgl_setwrapped_exponent(opnd3,result_exponent, | ||
1679 | unfl); | ||
1680 | Sgl_copytoptr(opnd3,dstptr); | ||
1681 | /* inexact = FALSE */ | ||
1682 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
1683 | } | ||
1684 | Sgl_copytoptr(opnd3,dstptr); | ||
1685 | return(NOEXCEPTION); | ||
1686 | } | ||
1687 | /* is denormalized; want to normalize */ | ||
1688 | Sgl_clear_signexponent(opnd2); | ||
1689 | Sgl_leftshiftby1(opnd2); | ||
1690 | Sgl_normalize(opnd2,mpy_exponent); | ||
1691 | } | ||
1692 | |||
1693 | /* Multiply the first two source mantissas together */ | ||
1694 | |||
1695 | /* | ||
1696 | * The intermediate result will be kept in tmpres, | ||
1697 | * which needs enough room for 106 bits of mantissa, | ||
1698 | * so lets call it a Double extended. | ||
1699 | */ | ||
1700 | Sglext_setzero(tmpresp1,tmpresp2); | ||
1701 | |||
1702 | /* | ||
1703 | * Four bits at a time are inspected in each loop, and a | ||
1704 | * simple shift and add multiply algorithm is used. | ||
1705 | */ | ||
1706 | for (count = SGL_P-1; count >= 0; count -= 4) { | ||
1707 | Sglext_rightshiftby4(tmpresp1,tmpresp2); | ||
1708 | if (Sbit28(opnd1)) { | ||
1709 | /* Twoword_add should be an ADD followed by 2 ADDC's */ | ||
1710 | Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0); | ||
1711 | } | ||
1712 | if (Sbit29(opnd1)) { | ||
1713 | Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0); | ||
1714 | } | ||
1715 | if (Sbit30(opnd1)) { | ||
1716 | Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0); | ||
1717 | } | ||
1718 | if (Sbit31(opnd1)) { | ||
1719 | Twoword_add(tmpresp1, tmpresp2, opnd2, 0); | ||
1720 | } | ||
1721 | Sgl_rightshiftby4(opnd1); | ||
1722 | } | ||
1723 | if (Is_sexthiddenoverflow(tmpresp1)) { | ||
1724 | /* result mantissa >= 2 (mantissa overflow) */ | ||
1725 | mpy_exponent++; | ||
1726 | Sglext_rightshiftby4(tmpresp1,tmpresp2); | ||
1727 | } else { | ||
1728 | Sglext_rightshiftby3(tmpresp1,tmpresp2); | ||
1729 | } | ||
1730 | |||
1731 | /* | ||
1732 | * Restore the sign of the mpy result which was saved in resultp1. | ||
1733 | * The exponent will continue to be kept in mpy_exponent. | ||
1734 | */ | ||
1735 | Sglext_set_sign(tmpresp1,Sgl_sign(resultp1)); | ||
1736 | |||
1737 | /* | ||
1738 | * No rounding is required, since the result of the multiply | ||
1739 | * is exact in the extended format. | ||
1740 | */ | ||
1741 | |||
1742 | /* | ||
1743 | * Now we are ready to perform the add portion of the operation. | ||
1744 | * | ||
1745 | * The exponents need to be kept as integers for now, since the | ||
1746 | * multiply result might not fit into the exponent field. We | ||
1747 | * can't overflow or underflow because of this yet, since the | ||
1748 | * add could bring the final result back into range. | ||
1749 | */ | ||
1750 | add_exponent = Sgl_exponent(opnd3); | ||
1751 | |||
1752 | /* | ||
1753 | * Check for denormalized or zero add operand. | ||
1754 | */ | ||
1755 | if (add_exponent == 0) { | ||
1756 | /* check for zero */ | ||
1757 | if (Sgl_iszero_mantissa(opnd3)) { | ||
1758 | /* right is zero */ | ||
1759 | /* Left can't be zero and must be result. | ||
1760 | * | ||
1761 | * The final result is now in tmpres and mpy_exponent, | ||
1762 | * and needs to be rounded and squeezed back into | ||
1763 | * double precision format from double extended. | ||
1764 | */ | ||
1765 | result_exponent = mpy_exponent; | ||
1766 | Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2); | ||
1767 | sign_save = Sgl_signextendedsign(resultp1);/*save sign*/ | ||
1768 | goto round; | ||
1769 | } | ||
1770 | |||
1771 | /* | ||
1772 | * Neither are zeroes. | ||
1773 | * Adjust exponent and normalize add operand. | ||
1774 | */ | ||
1775 | sign_save = Sgl_signextendedsign(opnd3); /* save sign */ | ||
1776 | Sgl_clear_signexponent(opnd3); | ||
1777 | Sgl_leftshiftby1(opnd3); | ||
1778 | Sgl_normalize(opnd3,add_exponent); | ||
1779 | Sgl_set_sign(opnd3,sign_save); /* restore sign */ | ||
1780 | } else { | ||
1781 | Sgl_clear_exponent_set_hidden(opnd3); | ||
1782 | } | ||
1783 | /* | ||
1784 | * Copy opnd3 to the double extended variable called right. | ||
1785 | */ | ||
1786 | Sgl_copyto_sglext(opnd3,rightp1,rightp2); | ||
1787 | |||
1788 | /* | ||
1789 | * A zero "save" helps discover equal operands (for later), | ||
1790 | * and is used in swapping operands (if needed). | ||
1791 | */ | ||
1792 | Sglext_xortointp1(tmpresp1,rightp1,/*to*/save); | ||
1793 | |||
1794 | /* | ||
1795 | * Compare magnitude of operands. | ||
1796 | */ | ||
1797 | Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1); | ||
1798 | Sglext_copytoint_exponentmantissa(rightp1,signlessright1); | ||
1799 | if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && | ||
1800 | Sglext_ismagnitudeless(signlessleft1,signlessright1)) { | ||
1801 | /* | ||
1802 | * Set the left operand to the larger one by XOR swap. | ||
1803 | * First finish the first word "save". | ||
1804 | */ | ||
1805 | Sglext_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
1806 | Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); | ||
1807 | Sglext_swap_lower(tmpresp2,rightp2); | ||
1808 | /* also setup exponents used in rest of routine */ | ||
1809 | diff_exponent = add_exponent - mpy_exponent; | ||
1810 | result_exponent = add_exponent; | ||
1811 | } else { | ||
1812 | /* also setup exponents used in rest of routine */ | ||
1813 | diff_exponent = mpy_exponent - add_exponent; | ||
1814 | result_exponent = mpy_exponent; | ||
1815 | } | ||
1816 | /* Invariant: left is not smaller than right. */ | ||
1817 | |||
1818 | /* | ||
1819 | * Special case alignment of operands that would force alignment | ||
1820 | * beyond the extent of the extension. A further optimization | ||
1821 | * could special case this but only reduces the path length for | ||
1822 | * this infrequent case. | ||
1823 | */ | ||
1824 | if (diff_exponent > SGLEXT_THRESHOLD) { | ||
1825 | diff_exponent = SGLEXT_THRESHOLD; | ||
1826 | } | ||
1827 | |||
1828 | /* Align right operand by shifting it to the right */ | ||
1829 | Sglext_clear_sign(rightp1); | ||
1830 | Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent); | ||
1831 | |||
1832 | /* Treat sum and difference of the operands separately. */ | ||
1833 | if ((int)save < 0) { | ||
1834 | /* | ||
1835 | * Difference of the two operands. Overflow can occur if the | ||
1836 | * multiply overflowed. A borrow can occur out of the hidden | ||
1837 | * bit and force a post normalization phase. | ||
1838 | */ | ||
1839 | Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2, | ||
1840 | resultp1,resultp2); | ||
1841 | sign_save = Sgl_signextendedsign(resultp1); | ||
1842 | if (Sgl_iszero_hidden(resultp1)) { | ||
1843 | /* Handle normalization */ | ||
1844 | /* A straight foward algorithm would now shift the | ||
1845 | * result and extension left until the hidden bit | ||
1846 | * becomes one. Not all of the extension bits need | ||
1847 | * participate in the shift. Only the two most | ||
1848 | * significant bits (round and guard) are needed. | ||
1849 | * If only a single shift is needed then the guard | ||
1850 | * bit becomes a significant low order bit and the | ||
1851 | * extension must participate in the rounding. | ||
1852 | * If more than a single shift is needed, then all | ||
1853 | * bits to the right of the guard bit are zeros, | ||
1854 | * and the guard bit may or may not be zero. */ | ||
1855 | Sglext_leftshiftby1(resultp1,resultp2); | ||
1856 | |||
1857 | /* Need to check for a zero result. The sign and | ||
1858 | * exponent fields have already been zeroed. The more | ||
1859 | * efficient test of the full object can be used. | ||
1860 | */ | ||
1861 | if (Sglext_iszero(resultp1,resultp2)) { | ||
1862 | /* Must have been "x-x" or "x+(-x)". */ | ||
1863 | if (Is_rounding_mode(ROUNDMINUS)) | ||
1864 | Sgl_setone_sign(resultp1); | ||
1865 | Sgl_copytoptr(resultp1,dstptr); | ||
1866 | return(NOEXCEPTION); | ||
1867 | } | ||
1868 | result_exponent--; | ||
1869 | |||
1870 | /* Look to see if normalization is finished. */ | ||
1871 | if (Sgl_isone_hidden(resultp1)) { | ||
1872 | /* No further normalization is needed */ | ||
1873 | goto round; | ||
1874 | } | ||
1875 | |||
1876 | /* Discover first one bit to determine shift amount. | ||
1877 | * Use a modified binary search. We have already | ||
1878 | * shifted the result one position right and still | ||
1879 | * not found a one so the remainder of the extension | ||
1880 | * must be zero and simplifies rounding. */ | ||
1881 | /* Scan bytes */ | ||
1882 | while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) { | ||
1883 | Sglext_leftshiftby8(resultp1,resultp2); | ||
1884 | result_exponent -= 8; | ||
1885 | } | ||
1886 | /* Now narrow it down to the nibble */ | ||
1887 | if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) { | ||
1888 | /* The lower nibble contains the | ||
1889 | * normalizing one */ | ||
1890 | Sglext_leftshiftby4(resultp1,resultp2); | ||
1891 | result_exponent -= 4; | ||
1892 | } | ||
1893 | /* Select case where first bit is set (already | ||
1894 | * normalized) otherwise select the proper shift. */ | ||
1895 | jumpsize = Sgl_hiddenhigh3mantissa(resultp1); | ||
1896 | if (jumpsize <= 7) switch(jumpsize) { | ||
1897 | case 1: | ||
1898 | Sglext_leftshiftby3(resultp1,resultp2); | ||
1899 | result_exponent -= 3; | ||
1900 | break; | ||
1901 | case 2: | ||
1902 | case 3: | ||
1903 | Sglext_leftshiftby2(resultp1,resultp2); | ||
1904 | result_exponent -= 2; | ||
1905 | break; | ||
1906 | case 4: | ||
1907 | case 5: | ||
1908 | case 6: | ||
1909 | case 7: | ||
1910 | Sglext_leftshiftby1(resultp1,resultp2); | ||
1911 | result_exponent -= 1; | ||
1912 | break; | ||
1913 | } | ||
1914 | } /* end if (hidden...)... */ | ||
1915 | /* Fall through and round */ | ||
1916 | } /* end if (save < 0)... */ | ||
1917 | else { | ||
1918 | /* Add magnitudes */ | ||
1919 | Sglext_addition(tmpresp1,tmpresp2, | ||
1920 | rightp1,rightp2, /*to*/resultp1,resultp2); | ||
1921 | sign_save = Sgl_signextendedsign(resultp1); | ||
1922 | if (Sgl_isone_hiddenoverflow(resultp1)) { | ||
1923 | /* Prenormalization required. */ | ||
1924 | Sglext_arithrightshiftby1(resultp1,resultp2); | ||
1925 | result_exponent++; | ||
1926 | } /* end if hiddenoverflow... */ | ||
1927 | } /* end else ...add magnitudes... */ | ||
1928 | |||
1929 | /* Round the result. If the extension and lower two words are | ||
1930 | * all zeros, then the result is exact. Otherwise round in the | ||
1931 | * correct direction. Underflow is possible. If a postnormalization | ||
1932 | * is necessary, then the mantissa is all zeros so no shift is needed. | ||
1933 | */ | ||
1934 | round: | ||
1935 | if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { | ||
1936 | Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny); | ||
1937 | } | ||
1938 | Sgl_set_sign(resultp1,/*using*/sign_save); | ||
1939 | if (Sglext_isnotzero_mantissap2(resultp2)) { | ||
1940 | inexact = TRUE; | ||
1941 | switch(Rounding_mode()) { | ||
1942 | case ROUNDNEAREST: /* The default. */ | ||
1943 | if (Sglext_isone_highp2(resultp2)) { | ||
1944 | /* at least 1/2 ulp */ | ||
1945 | if (Sglext_isnotzero_low31p2(resultp2) || | ||
1946 | Sglext_isone_lowp1(resultp1)) { | ||
1947 | /* either exactly half way and odd or | ||
1948 | * more than 1/2ulp */ | ||
1949 | Sgl_increment(resultp1); | ||
1950 | } | ||
1951 | } | ||
1952 | break; | ||
1953 | |||
1954 | case ROUNDPLUS: | ||
1955 | if (Sgl_iszero_sign(resultp1)) { | ||
1956 | /* Round up positive results */ | ||
1957 | Sgl_increment(resultp1); | ||
1958 | } | ||
1959 | break; | ||
1960 | |||
1961 | case ROUNDMINUS: | ||
1962 | if (Sgl_isone_sign(resultp1)) { | ||
1963 | /* Round down negative results */ | ||
1964 | Sgl_increment(resultp1); | ||
1965 | } | ||
1966 | |||
1967 | case ROUNDZERO:; | ||
1968 | /* truncate is simple */ | ||
1969 | } /* end switch... */ | ||
1970 | if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
1971 | } | ||
1972 | if (result_exponent >= SGL_INFINITY_EXPONENT) { | ||
1973 | /* Overflow */ | ||
1974 | if (Is_overflowtrap_enabled()) { | ||
1975 | /* | ||
1976 | * Adjust bias of result | ||
1977 | */ | ||
1978 | Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
1979 | Sgl_copytoptr(resultp1,dstptr); | ||
1980 | if (inexact) | ||
1981 | if (Is_inexacttrap_enabled()) | ||
1982 | return (OPC_2E_OVERFLOWEXCEPTION | | ||
1983 | OPC_2E_INEXACTEXCEPTION); | ||
1984 | else Set_inexactflag(); | ||
1985 | return (OPC_2E_OVERFLOWEXCEPTION); | ||
1986 | } | ||
1987 | inexact = TRUE; | ||
1988 | Set_overflowflag(); | ||
1989 | Sgl_setoverflow(resultp1); | ||
1990 | } else if (result_exponent <= 0) { /* underflow case */ | ||
1991 | if (Is_underflowtrap_enabled()) { | ||
1992 | /* | ||
1993 | * Adjust bias of result | ||
1994 | */ | ||
1995 | Sgl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
1996 | Sgl_copytoptr(resultp1,dstptr); | ||
1997 | if (inexact) | ||
1998 | if (Is_inexacttrap_enabled()) | ||
1999 | return (OPC_2E_UNDERFLOWEXCEPTION | | ||
2000 | OPC_2E_INEXACTEXCEPTION); | ||
2001 | else Set_inexactflag(); | ||
2002 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
2003 | } | ||
2004 | else if (inexact && is_tiny) Set_underflowflag(); | ||
2005 | } | ||
2006 | else Sgl_set_exponent(resultp1,result_exponent); | ||
2007 | Sgl_copytoptr(resultp1,dstptr); | ||
2008 | if (inexact) | ||
2009 | if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); | ||
2010 | else Set_inexactflag(); | ||
2011 | return(NOEXCEPTION); | ||
2012 | } | ||
2013 | |||
2014 | /* | ||
2015 | * Single Floating-point Multiply Negate Fused Add | ||
2016 | */ | ||
2017 | |||
2018 | sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
2019 | |||
2020 | sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; | ||
2021 | unsigned int *status; | ||
2022 | { | ||
2023 | unsigned int opnd1, opnd2, opnd3; | ||
2024 | register unsigned int tmpresp1, tmpresp2; | ||
2025 | unsigned int rightp1, rightp2; | ||
2026 | unsigned int resultp1, resultp2 = 0; | ||
2027 | register int mpy_exponent, add_exponent, count; | ||
2028 | boolean inexact = FALSE, is_tiny = FALSE; | ||
2029 | |||
2030 | unsigned int signlessleft1, signlessright1, save; | ||
2031 | register int result_exponent, diff_exponent; | ||
2032 | int sign_save, jumpsize; | ||
2033 | |||
2034 | Sgl_copyfromptr(src1ptr,opnd1); | ||
2035 | Sgl_copyfromptr(src2ptr,opnd2); | ||
2036 | Sgl_copyfromptr(src3ptr,opnd3); | ||
2037 | |||
2038 | /* | ||
2039 | * set sign bit of result of multiply | ||
2040 | */ | ||
2041 | if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) | ||
2042 | Sgl_setzero(resultp1); | ||
2043 | else | ||
2044 | Sgl_setnegativezero(resultp1); | ||
2045 | |||
2046 | /* | ||
2047 | * Generate multiply exponent | ||
2048 | */ | ||
2049 | mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; | ||
2050 | |||
2051 | /* | ||
2052 | * check first operand for NaN's or infinity | ||
2053 | */ | ||
2054 | if (Sgl_isinfinity_exponent(opnd1)) { | ||
2055 | if (Sgl_iszero_mantissa(opnd1)) { | ||
2056 | if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) { | ||
2057 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
2058 | /* | ||
2059 | * invalid since operands are infinity | ||
2060 | * and zero | ||
2061 | */ | ||
2062 | if (Is_invalidtrap_enabled()) | ||
2063 | return(OPC_2E_INVALIDEXCEPTION); | ||
2064 | Set_invalidflag(); | ||
2065 | Sgl_makequietnan(resultp1); | ||
2066 | Sgl_copytoptr(resultp1,dstptr); | ||
2067 | return(NOEXCEPTION); | ||
2068 | } | ||
2069 | /* | ||
2070 | * Check third operand for infinity with a | ||
2071 | * sign opposite of the multiply result | ||
2072 | */ | ||
2073 | if (Sgl_isinfinity(opnd3) && | ||
2074 | (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { | ||
2075 | /* | ||
2076 | * invalid since attempting a magnitude | ||
2077 | * subtraction of infinities | ||
2078 | */ | ||
2079 | if (Is_invalidtrap_enabled()) | ||
2080 | return(OPC_2E_INVALIDEXCEPTION); | ||
2081 | Set_invalidflag(); | ||
2082 | Sgl_makequietnan(resultp1); | ||
2083 | Sgl_copytoptr(resultp1,dstptr); | ||
2084 | return(NOEXCEPTION); | ||
2085 | } | ||
2086 | |||
2087 | /* | ||
2088 | * return infinity | ||
2089 | */ | ||
2090 | Sgl_setinfinity_exponentmantissa(resultp1); | ||
2091 | Sgl_copytoptr(resultp1,dstptr); | ||
2092 | return(NOEXCEPTION); | ||
2093 | } | ||
2094 | } | ||
2095 | else { | ||
2096 | /* | ||
2097 | * is NaN; signaling or quiet? | ||
2098 | */ | ||
2099 | if (Sgl_isone_signaling(opnd1)) { | ||
2100 | /* trap if INVALIDTRAP enabled */ | ||
2101 | if (Is_invalidtrap_enabled()) | ||
2102 | return(OPC_2E_INVALIDEXCEPTION); | ||
2103 | /* make NaN quiet */ | ||
2104 | Set_invalidflag(); | ||
2105 | Sgl_set_quiet(opnd1); | ||
2106 | } | ||
2107 | /* | ||
2108 | * is second operand a signaling NaN? | ||
2109 | */ | ||
2110 | else if (Sgl_is_signalingnan(opnd2)) { | ||
2111 | /* trap if INVALIDTRAP enabled */ | ||
2112 | if (Is_invalidtrap_enabled()) | ||
2113 | return(OPC_2E_INVALIDEXCEPTION); | ||
2114 | /* make NaN quiet */ | ||
2115 | Set_invalidflag(); | ||
2116 | Sgl_set_quiet(opnd2); | ||
2117 | Sgl_copytoptr(opnd2,dstptr); | ||
2118 | return(NOEXCEPTION); | ||
2119 | } | ||
2120 | /* | ||
2121 | * is third operand a signaling NaN? | ||
2122 | */ | ||
2123 | else if (Sgl_is_signalingnan(opnd3)) { | ||
2124 | /* trap if INVALIDTRAP enabled */ | ||
2125 | if (Is_invalidtrap_enabled()) | ||
2126 | return(OPC_2E_INVALIDEXCEPTION); | ||
2127 | /* make NaN quiet */ | ||
2128 | Set_invalidflag(); | ||
2129 | Sgl_set_quiet(opnd3); | ||
2130 | Sgl_copytoptr(opnd3,dstptr); | ||
2131 | return(NOEXCEPTION); | ||
2132 | } | ||
2133 | /* | ||
2134 | * return quiet NaN | ||
2135 | */ | ||
2136 | Sgl_copytoptr(opnd1,dstptr); | ||
2137 | return(NOEXCEPTION); | ||
2138 | } | ||
2139 | } | ||
2140 | |||
2141 | /* | ||
2142 | * check second operand for NaN's or infinity | ||
2143 | */ | ||
2144 | if (Sgl_isinfinity_exponent(opnd2)) { | ||
2145 | if (Sgl_iszero_mantissa(opnd2)) { | ||
2146 | if (Sgl_isnotnan(opnd3)) { | ||
2147 | if (Sgl_iszero_exponentmantissa(opnd1)) { | ||
2148 | /* | ||
2149 | * invalid since multiply operands are | ||
2150 | * zero & infinity | ||
2151 | */ | ||
2152 | if (Is_invalidtrap_enabled()) | ||
2153 | return(OPC_2E_INVALIDEXCEPTION); | ||
2154 | Set_invalidflag(); | ||
2155 | Sgl_makequietnan(opnd2); | ||
2156 | Sgl_copytoptr(opnd2,dstptr); | ||
2157 | return(NOEXCEPTION); | ||
2158 | } | ||
2159 | |||
2160 | /* | ||
2161 | * Check third operand for infinity with a | ||
2162 | * sign opposite of the multiply result | ||
2163 | */ | ||
2164 | if (Sgl_isinfinity(opnd3) && | ||
2165 | (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { | ||
2166 | /* | ||
2167 | * invalid since attempting a magnitude | ||
2168 | * subtraction of infinities | ||
2169 | */ | ||
2170 | if (Is_invalidtrap_enabled()) | ||
2171 | return(OPC_2E_INVALIDEXCEPTION); | ||
2172 | Set_invalidflag(); | ||
2173 | Sgl_makequietnan(resultp1); | ||
2174 | Sgl_copytoptr(resultp1,dstptr); | ||
2175 | return(NOEXCEPTION); | ||
2176 | } | ||
2177 | |||
2178 | /* | ||
2179 | * return infinity | ||
2180 | */ | ||
2181 | Sgl_setinfinity_exponentmantissa(resultp1); | ||
2182 | Sgl_copytoptr(resultp1,dstptr); | ||
2183 | return(NOEXCEPTION); | ||
2184 | } | ||
2185 | } | ||
2186 | else { | ||
2187 | /* | ||
2188 | * is NaN; signaling or quiet? | ||
2189 | */ | ||
2190 | if (Sgl_isone_signaling(opnd2)) { | ||
2191 | /* trap if INVALIDTRAP enabled */ | ||
2192 | if (Is_invalidtrap_enabled()) | ||
2193 | return(OPC_2E_INVALIDEXCEPTION); | ||
2194 | /* make NaN quiet */ | ||
2195 | Set_invalidflag(); | ||
2196 | Sgl_set_quiet(opnd2); | ||
2197 | } | ||
2198 | /* | ||
2199 | * is third operand a signaling NaN? | ||
2200 | */ | ||
2201 | else if (Sgl_is_signalingnan(opnd3)) { | ||
2202 | /* trap if INVALIDTRAP enabled */ | ||
2203 | if (Is_invalidtrap_enabled()) | ||
2204 | return(OPC_2E_INVALIDEXCEPTION); | ||
2205 | /* make NaN quiet */ | ||
2206 | Set_invalidflag(); | ||
2207 | Sgl_set_quiet(opnd3); | ||
2208 | Sgl_copytoptr(opnd3,dstptr); | ||
2209 | return(NOEXCEPTION); | ||
2210 | } | ||
2211 | /* | ||
2212 | * return quiet NaN | ||
2213 | */ | ||
2214 | Sgl_copytoptr(opnd2,dstptr); | ||
2215 | return(NOEXCEPTION); | ||
2216 | } | ||
2217 | } | ||
2218 | |||
2219 | /* | ||
2220 | * check third operand for NaN's or infinity | ||
2221 | */ | ||
2222 | if (Sgl_isinfinity_exponent(opnd3)) { | ||
2223 | if (Sgl_iszero_mantissa(opnd3)) { | ||
2224 | /* return infinity */ | ||
2225 | Sgl_copytoptr(opnd3,dstptr); | ||
2226 | return(NOEXCEPTION); | ||
2227 | } else { | ||
2228 | /* | ||
2229 | * is NaN; signaling or quiet? | ||
2230 | */ | ||
2231 | if (Sgl_isone_signaling(opnd3)) { | ||
2232 | /* trap if INVALIDTRAP enabled */ | ||
2233 | if (Is_invalidtrap_enabled()) | ||
2234 | return(OPC_2E_INVALIDEXCEPTION); | ||
2235 | /* make NaN quiet */ | ||
2236 | Set_invalidflag(); | ||
2237 | Sgl_set_quiet(opnd3); | ||
2238 | } | ||
2239 | /* | ||
2240 | * return quiet NaN | ||
2241 | */ | ||
2242 | Sgl_copytoptr(opnd3,dstptr); | ||
2243 | return(NOEXCEPTION); | ||
2244 | } | ||
2245 | } | ||
2246 | |||
2247 | /* | ||
2248 | * Generate multiply mantissa | ||
2249 | */ | ||
2250 | if (Sgl_isnotzero_exponent(opnd1)) { | ||
2251 | /* set hidden bit */ | ||
2252 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
2253 | } | ||
2254 | else { | ||
2255 | /* check for zero */ | ||
2256 | if (Sgl_iszero_mantissa(opnd1)) { | ||
2257 | /* | ||
2258 | * Perform the add opnd3 with zero here. | ||
2259 | */ | ||
2260 | if (Sgl_iszero_exponentmantissa(opnd3)) { | ||
2261 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
2262 | Sgl_or_signs(opnd3,resultp1); | ||
2263 | } else { | ||
2264 | Sgl_and_signs(opnd3,resultp1); | ||
2265 | } | ||
2266 | } | ||
2267 | /* | ||
2268 | * Now let's check for trapped underflow case. | ||
2269 | */ | ||
2270 | else if (Sgl_iszero_exponent(opnd3) && | ||
2271 | Is_underflowtrap_enabled()) { | ||
2272 | /* need to normalize results mantissa */ | ||
2273 | sign_save = Sgl_signextendedsign(opnd3); | ||
2274 | result_exponent = 0; | ||
2275 | Sgl_leftshiftby1(opnd3); | ||
2276 | Sgl_normalize(opnd3,result_exponent); | ||
2277 | Sgl_set_sign(opnd3,/*using*/sign_save); | ||
2278 | Sgl_setwrapped_exponent(opnd3,result_exponent, | ||
2279 | unfl); | ||
2280 | Sgl_copytoptr(opnd3,dstptr); | ||
2281 | /* inexact = FALSE */ | ||
2282 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
2283 | } | ||
2284 | Sgl_copytoptr(opnd3,dstptr); | ||
2285 | return(NOEXCEPTION); | ||
2286 | } | ||
2287 | /* is denormalized, adjust exponent */ | ||
2288 | Sgl_clear_signexponent(opnd1); | ||
2289 | Sgl_leftshiftby1(opnd1); | ||
2290 | Sgl_normalize(opnd1,mpy_exponent); | ||
2291 | } | ||
2292 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
2293 | if (Sgl_isnotzero_exponent(opnd2)) { | ||
2294 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
2295 | } | ||
2296 | else { | ||
2297 | /* check for zero */ | ||
2298 | if (Sgl_iszero_mantissa(opnd2)) { | ||
2299 | /* | ||
2300 | * Perform the add opnd3 with zero here. | ||
2301 | */ | ||
2302 | if (Sgl_iszero_exponentmantissa(opnd3)) { | ||
2303 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
2304 | Sgl_or_signs(opnd3,resultp1); | ||
2305 | } else { | ||
2306 | Sgl_and_signs(opnd3,resultp1); | ||
2307 | } | ||
2308 | } | ||
2309 | /* | ||
2310 | * Now let's check for trapped underflow case. | ||
2311 | */ | ||
2312 | else if (Sgl_iszero_exponent(opnd3) && | ||
2313 | Is_underflowtrap_enabled()) { | ||
2314 | /* need to normalize results mantissa */ | ||
2315 | sign_save = Sgl_signextendedsign(opnd3); | ||
2316 | result_exponent = 0; | ||
2317 | Sgl_leftshiftby1(opnd3); | ||
2318 | Sgl_normalize(opnd3,result_exponent); | ||
2319 | Sgl_set_sign(opnd3,/*using*/sign_save); | ||
2320 | Sgl_setwrapped_exponent(opnd3,result_exponent, | ||
2321 | unfl); | ||
2322 | Sgl_copytoptr(opnd3,dstptr); | ||
2323 | /* inexact = FALSE */ | ||
2324 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
2325 | } | ||
2326 | Sgl_copytoptr(opnd3,dstptr); | ||
2327 | return(NOEXCEPTION); | ||
2328 | } | ||
2329 | /* is denormalized; want to normalize */ | ||
2330 | Sgl_clear_signexponent(opnd2); | ||
2331 | Sgl_leftshiftby1(opnd2); | ||
2332 | Sgl_normalize(opnd2,mpy_exponent); | ||
2333 | } | ||
2334 | |||
2335 | /* Multiply the first two source mantissas together */ | ||
2336 | |||
2337 | /* | ||
2338 | * The intermediate result will be kept in tmpres, | ||
2339 | * which needs enough room for 106 bits of mantissa, | ||
2340 | * so lets call it a Double extended. | ||
2341 | */ | ||
2342 | Sglext_setzero(tmpresp1,tmpresp2); | ||
2343 | |||
2344 | /* | ||
2345 | * Four bits at a time are inspected in each loop, and a | ||
2346 | * simple shift and add multiply algorithm is used. | ||
2347 | */ | ||
2348 | for (count = SGL_P-1; count >= 0; count -= 4) { | ||
2349 | Sglext_rightshiftby4(tmpresp1,tmpresp2); | ||
2350 | if (Sbit28(opnd1)) { | ||
2351 | /* Twoword_add should be an ADD followed by 2 ADDC's */ | ||
2352 | Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0); | ||
2353 | } | ||
2354 | if (Sbit29(opnd1)) { | ||
2355 | Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0); | ||
2356 | } | ||
2357 | if (Sbit30(opnd1)) { | ||
2358 | Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0); | ||
2359 | } | ||
2360 | if (Sbit31(opnd1)) { | ||
2361 | Twoword_add(tmpresp1, tmpresp2, opnd2, 0); | ||
2362 | } | ||
2363 | Sgl_rightshiftby4(opnd1); | ||
2364 | } | ||
2365 | if (Is_sexthiddenoverflow(tmpresp1)) { | ||
2366 | /* result mantissa >= 2 (mantissa overflow) */ | ||
2367 | mpy_exponent++; | ||
2368 | Sglext_rightshiftby4(tmpresp1,tmpresp2); | ||
2369 | } else { | ||
2370 | Sglext_rightshiftby3(tmpresp1,tmpresp2); | ||
2371 | } | ||
2372 | |||
2373 | /* | ||
2374 | * Restore the sign of the mpy result which was saved in resultp1. | ||
2375 | * The exponent will continue to be kept in mpy_exponent. | ||
2376 | */ | ||
2377 | Sglext_set_sign(tmpresp1,Sgl_sign(resultp1)); | ||
2378 | |||
2379 | /* | ||
2380 | * No rounding is required, since the result of the multiply | ||
2381 | * is exact in the extended format. | ||
2382 | */ | ||
2383 | |||
2384 | /* | ||
2385 | * Now we are ready to perform the add portion of the operation. | ||
2386 | * | ||
2387 | * The exponents need to be kept as integers for now, since the | ||
2388 | * multiply result might not fit into the exponent field. We | ||
2389 | * can't overflow or underflow because of this yet, since the | ||
2390 | * add could bring the final result back into range. | ||
2391 | */ | ||
2392 | add_exponent = Sgl_exponent(opnd3); | ||
2393 | |||
2394 | /* | ||
2395 | * Check for denormalized or zero add operand. | ||
2396 | */ | ||
2397 | if (add_exponent == 0) { | ||
2398 | /* check for zero */ | ||
2399 | if (Sgl_iszero_mantissa(opnd3)) { | ||
2400 | /* right is zero */ | ||
2401 | /* Left can't be zero and must be result. | ||
2402 | * | ||
2403 | * The final result is now in tmpres and mpy_exponent, | ||
2404 | * and needs to be rounded and squeezed back into | ||
2405 | * double precision format from double extended. | ||
2406 | */ | ||
2407 | result_exponent = mpy_exponent; | ||
2408 | Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2); | ||
2409 | sign_save = Sgl_signextendedsign(resultp1);/*save sign*/ | ||
2410 | goto round; | ||
2411 | } | ||
2412 | |||
2413 | /* | ||
2414 | * Neither are zeroes. | ||
2415 | * Adjust exponent and normalize add operand. | ||
2416 | */ | ||
2417 | sign_save = Sgl_signextendedsign(opnd3); /* save sign */ | ||
2418 | Sgl_clear_signexponent(opnd3); | ||
2419 | Sgl_leftshiftby1(opnd3); | ||
2420 | Sgl_normalize(opnd3,add_exponent); | ||
2421 | Sgl_set_sign(opnd3,sign_save); /* restore sign */ | ||
2422 | } else { | ||
2423 | Sgl_clear_exponent_set_hidden(opnd3); | ||
2424 | } | ||
2425 | /* | ||
2426 | * Copy opnd3 to the double extended variable called right. | ||
2427 | */ | ||
2428 | Sgl_copyto_sglext(opnd3,rightp1,rightp2); | ||
2429 | |||
2430 | /* | ||
2431 | * A zero "save" helps discover equal operands (for later), | ||
2432 | * and is used in swapping operands (if needed). | ||
2433 | */ | ||
2434 | Sglext_xortointp1(tmpresp1,rightp1,/*to*/save); | ||
2435 | |||
2436 | /* | ||
2437 | * Compare magnitude of operands. | ||
2438 | */ | ||
2439 | Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1); | ||
2440 | Sglext_copytoint_exponentmantissa(rightp1,signlessright1); | ||
2441 | if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && | ||
2442 | Sglext_ismagnitudeless(signlessleft1,signlessright1)) { | ||
2443 | /* | ||
2444 | * Set the left operand to the larger one by XOR swap. | ||
2445 | * First finish the first word "save". | ||
2446 | */ | ||
2447 | Sglext_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
2448 | Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); | ||
2449 | Sglext_swap_lower(tmpresp2,rightp2); | ||
2450 | /* also setup exponents used in rest of routine */ | ||
2451 | diff_exponent = add_exponent - mpy_exponent; | ||
2452 | result_exponent = add_exponent; | ||
2453 | } else { | ||
2454 | /* also setup exponents used in rest of routine */ | ||
2455 | diff_exponent = mpy_exponent - add_exponent; | ||
2456 | result_exponent = mpy_exponent; | ||
2457 | } | ||
2458 | /* Invariant: left is not smaller than right. */ | ||
2459 | |||
2460 | /* | ||
2461 | * Special case alignment of operands that would force alignment | ||
2462 | * beyond the extent of the extension. A further optimization | ||
2463 | * could special case this but only reduces the path length for | ||
2464 | * this infrequent case. | ||
2465 | */ | ||
2466 | if (diff_exponent > SGLEXT_THRESHOLD) { | ||
2467 | diff_exponent = SGLEXT_THRESHOLD; | ||
2468 | } | ||
2469 | |||
2470 | /* Align right operand by shifting it to the right */ | ||
2471 | Sglext_clear_sign(rightp1); | ||
2472 | Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent); | ||
2473 | |||
2474 | /* Treat sum and difference of the operands separately. */ | ||
2475 | if ((int)save < 0) { | ||
2476 | /* | ||
2477 | * Difference of the two operands. Overflow can occur if the | ||
2478 | * multiply overflowed. A borrow can occur out of the hidden | ||
2479 | * bit and force a post normalization phase. | ||
2480 | */ | ||
2481 | Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2, | ||
2482 | resultp1,resultp2); | ||
2483 | sign_save = Sgl_signextendedsign(resultp1); | ||
2484 | if (Sgl_iszero_hidden(resultp1)) { | ||
2485 | /* Handle normalization */ | ||
2486 | /* A straight foward algorithm would now shift the | ||
2487 | * result and extension left until the hidden bit | ||
2488 | * becomes one. Not all of the extension bits need | ||
2489 | * participate in the shift. Only the two most | ||
2490 | * significant bits (round and guard) are needed. | ||
2491 | * If only a single shift is needed then the guard | ||
2492 | * bit becomes a significant low order bit and the | ||
2493 | * extension must participate in the rounding. | ||
2494 | * If more than a single shift is needed, then all | ||
2495 | * bits to the right of the guard bit are zeros, | ||
2496 | * and the guard bit may or may not be zero. */ | ||
2497 | Sglext_leftshiftby1(resultp1,resultp2); | ||
2498 | |||
2499 | /* Need to check for a zero result. The sign and | ||
2500 | * exponent fields have already been zeroed. The more | ||
2501 | * efficient test of the full object can be used. | ||
2502 | */ | ||
2503 | if (Sglext_iszero(resultp1,resultp2)) { | ||
2504 | /* Must have been "x-x" or "x+(-x)". */ | ||
2505 | if (Is_rounding_mode(ROUNDMINUS)) | ||
2506 | Sgl_setone_sign(resultp1); | ||
2507 | Sgl_copytoptr(resultp1,dstptr); | ||
2508 | return(NOEXCEPTION); | ||
2509 | } | ||
2510 | result_exponent--; | ||
2511 | |||
2512 | /* Look to see if normalization is finished. */ | ||
2513 | if (Sgl_isone_hidden(resultp1)) { | ||
2514 | /* No further normalization is needed */ | ||
2515 | goto round; | ||
2516 | } | ||
2517 | |||
2518 | /* Discover first one bit to determine shift amount. | ||
2519 | * Use a modified binary search. We have already | ||
2520 | * shifted the result one position right and still | ||
2521 | * not found a one so the remainder of the extension | ||
2522 | * must be zero and simplifies rounding. */ | ||
2523 | /* Scan bytes */ | ||
2524 | while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) { | ||
2525 | Sglext_leftshiftby8(resultp1,resultp2); | ||
2526 | result_exponent -= 8; | ||
2527 | } | ||
2528 | /* Now narrow it down to the nibble */ | ||
2529 | if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) { | ||
2530 | /* The lower nibble contains the | ||
2531 | * normalizing one */ | ||
2532 | Sglext_leftshiftby4(resultp1,resultp2); | ||
2533 | result_exponent -= 4; | ||
2534 | } | ||
2535 | /* Select case where first bit is set (already | ||
2536 | * normalized) otherwise select the proper shift. */ | ||
2537 | jumpsize = Sgl_hiddenhigh3mantissa(resultp1); | ||
2538 | if (jumpsize <= 7) switch(jumpsize) { | ||
2539 | case 1: | ||
2540 | Sglext_leftshiftby3(resultp1,resultp2); | ||
2541 | result_exponent -= 3; | ||
2542 | break; | ||
2543 | case 2: | ||
2544 | case 3: | ||
2545 | Sglext_leftshiftby2(resultp1,resultp2); | ||
2546 | result_exponent -= 2; | ||
2547 | break; | ||
2548 | case 4: | ||
2549 | case 5: | ||
2550 | case 6: | ||
2551 | case 7: | ||
2552 | Sglext_leftshiftby1(resultp1,resultp2); | ||
2553 | result_exponent -= 1; | ||
2554 | break; | ||
2555 | } | ||
2556 | } /* end if (hidden...)... */ | ||
2557 | /* Fall through and round */ | ||
2558 | } /* end if (save < 0)... */ | ||
2559 | else { | ||
2560 | /* Add magnitudes */ | ||
2561 | Sglext_addition(tmpresp1,tmpresp2, | ||
2562 | rightp1,rightp2, /*to*/resultp1,resultp2); | ||
2563 | sign_save = Sgl_signextendedsign(resultp1); | ||
2564 | if (Sgl_isone_hiddenoverflow(resultp1)) { | ||
2565 | /* Prenormalization required. */ | ||
2566 | Sglext_arithrightshiftby1(resultp1,resultp2); | ||
2567 | result_exponent++; | ||
2568 | } /* end if hiddenoverflow... */ | ||
2569 | } /* end else ...add magnitudes... */ | ||
2570 | |||
2571 | /* Round the result. If the extension and lower two words are | ||
2572 | * all zeros, then the result is exact. Otherwise round in the | ||
2573 | * correct direction. Underflow is possible. If a postnormalization | ||
2574 | * is necessary, then the mantissa is all zeros so no shift is needed. | ||
2575 | */ | ||
2576 | round: | ||
2577 | if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { | ||
2578 | Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny); | ||
2579 | } | ||
2580 | Sgl_set_sign(resultp1,/*using*/sign_save); | ||
2581 | if (Sglext_isnotzero_mantissap2(resultp2)) { | ||
2582 | inexact = TRUE; | ||
2583 | switch(Rounding_mode()) { | ||
2584 | case ROUNDNEAREST: /* The default. */ | ||
2585 | if (Sglext_isone_highp2(resultp2)) { | ||
2586 | /* at least 1/2 ulp */ | ||
2587 | if (Sglext_isnotzero_low31p2(resultp2) || | ||
2588 | Sglext_isone_lowp1(resultp1)) { | ||
2589 | /* either exactly half way and odd or | ||
2590 | * more than 1/2ulp */ | ||
2591 | Sgl_increment(resultp1); | ||
2592 | } | ||
2593 | } | ||
2594 | break; | ||
2595 | |||
2596 | case ROUNDPLUS: | ||
2597 | if (Sgl_iszero_sign(resultp1)) { | ||
2598 | /* Round up positive results */ | ||
2599 | Sgl_increment(resultp1); | ||
2600 | } | ||
2601 | break; | ||
2602 | |||
2603 | case ROUNDMINUS: | ||
2604 | if (Sgl_isone_sign(resultp1)) { | ||
2605 | /* Round down negative results */ | ||
2606 | Sgl_increment(resultp1); | ||
2607 | } | ||
2608 | |||
2609 | case ROUNDZERO:; | ||
2610 | /* truncate is simple */ | ||
2611 | } /* end switch... */ | ||
2612 | if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
2613 | } | ||
2614 | if (result_exponent >= SGL_INFINITY_EXPONENT) { | ||
2615 | /* Overflow */ | ||
2616 | if (Is_overflowtrap_enabled()) { | ||
2617 | /* | ||
2618 | * Adjust bias of result | ||
2619 | */ | ||
2620 | Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
2621 | Sgl_copytoptr(resultp1,dstptr); | ||
2622 | if (inexact) | ||
2623 | if (Is_inexacttrap_enabled()) | ||
2624 | return (OPC_2E_OVERFLOWEXCEPTION | | ||
2625 | OPC_2E_INEXACTEXCEPTION); | ||
2626 | else Set_inexactflag(); | ||
2627 | return (OPC_2E_OVERFLOWEXCEPTION); | ||
2628 | } | ||
2629 | inexact = TRUE; | ||
2630 | Set_overflowflag(); | ||
2631 | Sgl_setoverflow(resultp1); | ||
2632 | } else if (result_exponent <= 0) { /* underflow case */ | ||
2633 | if (Is_underflowtrap_enabled()) { | ||
2634 | /* | ||
2635 | * Adjust bias of result | ||
2636 | */ | ||
2637 | Sgl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
2638 | Sgl_copytoptr(resultp1,dstptr); | ||
2639 | if (inexact) | ||
2640 | if (Is_inexacttrap_enabled()) | ||
2641 | return (OPC_2E_UNDERFLOWEXCEPTION | | ||
2642 | OPC_2E_INEXACTEXCEPTION); | ||
2643 | else Set_inexactflag(); | ||
2644 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
2645 | } | ||
2646 | else if (inexact && is_tiny) Set_underflowflag(); | ||
2647 | } | ||
2648 | else Sgl_set_exponent(resultp1,result_exponent); | ||
2649 | Sgl_copytoptr(resultp1,dstptr); | ||
2650 | if (inexact) | ||
2651 | if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); | ||
2652 | else Set_inexactflag(); | ||
2653 | return(NOEXCEPTION); | ||
2654 | } | ||
2655 | |||
diff --git a/arch/parisc/math-emu/fpbits.h b/arch/parisc/math-emu/fpbits.h new file mode 100644 index 000000000000..cefad064d74a --- /dev/null +++ b/arch/parisc/math-emu/fpbits.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifdef __NO_PA_HDRS | ||
23 | PA header file -- do not include this header file for non-PA builds. | ||
24 | #endif | ||
25 | |||
26 | |||
27 | /* | ||
28 | * These macros are designed to be portable to all machines that have | ||
29 | * a wordsize greater than or equal to 32 bits that support the portable | ||
30 | * C compiler and the standard C preprocessor. Wordsize (default 32) | ||
31 | * and bitfield assignment (default left-to-right, unlike VAX, PDP-11) | ||
32 | * should be predefined using the constants HOSTWDSZ and BITFRL and | ||
33 | * the C compiler "-D" flag (e.g., -DHOSTWDSZ=36 -DBITFLR for the DEC-20). | ||
34 | * Note that the macro arguments assume that the integer being referenced | ||
35 | * is a 32-bit integer (right-justified on the 20) and that bit 0 is the | ||
36 | * most significant bit. | ||
37 | */ | ||
38 | |||
39 | #ifndef HOSTWDSZ | ||
40 | #define HOSTWDSZ 32 | ||
41 | #endif | ||
42 | |||
43 | |||
44 | /*########################### Macros ######################################*/ | ||
45 | |||
46 | /*------------------------------------------------------------------------- | ||
47 | * NewDeclareBitField_Reference - Declare a structure similar to the simulator | ||
48 | * function "DeclBitfR" except its use is restricted to occur within a larger | ||
49 | * enclosing structure or union definition. This declaration is an unnamed | ||
50 | * structure with the argument, name, as the member name and the argument, | ||
51 | * uname, as the element name. | ||
52 | *----------------------------------------------------------------------- */ | ||
53 | #define Bitfield_extract(start, length, object) \ | ||
54 | ((object) >> (HOSTWDSZ - (start) - (length)) & \ | ||
55 | ((unsigned)-1 >> (HOSTWDSZ - (length)))) | ||
56 | |||
57 | #define Bitfield_signed_extract(start, length, object) \ | ||
58 | ((int)((object) << start) >> (HOSTWDSZ - (length))) | ||
59 | |||
60 | #define Bitfield_mask(start, len, object) \ | ||
61 | ((object) & (((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) | ||
62 | |||
63 | #define Bitfield_deposit(value,start,len,object) object = \ | ||
64 | ((object) & ~(((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) | \ | ||
65 | (((value) & ((unsigned)-1 >> (HOSTWDSZ-len))) << (HOSTWDSZ-start-len)) | ||
diff --git a/arch/parisc/math-emu/fpu.h b/arch/parisc/math-emu/fpu.h new file mode 100644 index 000000000000..0af5c3c88949 --- /dev/null +++ b/arch/parisc/math-emu/fpu.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/fp/fpu.h $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * <<please update with a synopis of the functionality provided by this file>> | ||
29 | * | ||
30 | * | ||
31 | * END_DESC | ||
32 | */ | ||
33 | |||
34 | #ifdef __NO_PA_HDRS | ||
35 | PA header file -- do not include this header file for non-PA builds. | ||
36 | #endif | ||
37 | |||
38 | |||
39 | #ifndef _MACHINE_FPU_INCLUDED /* allows multiple inclusion */ | ||
40 | #define _MACHINE_FPU_INCLUDED | ||
41 | |||
42 | #if 0 | ||
43 | #ifndef _SYS_STDSYMS_INCLUDED | ||
44 | # include <sys/stdsyms.h> | ||
45 | #endif /* _SYS_STDSYMS_INCLUDED */ | ||
46 | #include <machine/pdc/pdc_rqsts.h> | ||
47 | #endif | ||
48 | |||
49 | #define PA83_FPU_FLAG 0x00000001 | ||
50 | #define PA89_FPU_FLAG 0x00000002 | ||
51 | #define PA2_0_FPU_FLAG 0x00000010 | ||
52 | |||
53 | #define TIMEX_EXTEN_FLAG 0x00000004 | ||
54 | |||
55 | #define ROLEX_EXTEN_FLAG 0x00000008 | ||
56 | #define COPR_FP 0x00000080 /* Floating point -- Coprocessor 0 */ | ||
57 | #define SFU_MPY_DIVIDE 0x00008000 /* Multiply/Divide __ SFU 0 */ | ||
58 | |||
59 | |||
60 | #define EM_FPU_TYPE_OFFSET 272 | ||
61 | |||
62 | /* version of EMULATION software for COPR,0,0 instruction */ | ||
63 | #define EMULATION_VERSION 4 | ||
64 | |||
65 | /* | ||
66 | * The only was to differeniate between TIMEX and ROLEX (or PCX-S and PCX-T) | ||
67 | * is thorough the potential type field from the PDC_MODEL call. The | ||
68 | * following flags are used at assist this differeniation. | ||
69 | */ | ||
70 | |||
71 | #define ROLEX_POTENTIAL_KEY_FLAGS PDC_MODEL_CPU_KEY_WORD_TO_IO | ||
72 | #define TIMEX_POTENTIAL_KEY_FLAGS (PDC_MODEL_CPU_KEY_QUAD_STORE | \ | ||
73 | PDC_MODEL_CPU_KEY_RECIP_SQRT) | ||
74 | |||
75 | |||
76 | #endif /* ! _MACHINE_FPU_INCLUDED */ | ||
diff --git a/arch/parisc/math-emu/fpudispatch.c b/arch/parisc/math-emu/fpudispatch.c new file mode 100644 index 000000000000..6e28f9f4c620 --- /dev/null +++ b/arch/parisc/math-emu/fpudispatch.c | |||
@@ -0,0 +1,1442 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * <<please update with a synopsis of the functionality provided by this file>> | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * <<the following list was autogenerated, please review>> | ||
32 | * emfpudispatch(ir, dummy1, dummy2, fpregs) | ||
33 | * fpudispatch(ir, excp_code, holder, fpregs) | ||
34 | * | ||
35 | * Internal Interfaces: | ||
36 | * <<the following list was autogenerated, please review>> | ||
37 | * static u_int decode_06(u_int, u_int *) | ||
38 | * static u_int decode_0c(u_int, u_int, u_int, u_int *) | ||
39 | * static u_int decode_0e(u_int, u_int, u_int, u_int *) | ||
40 | * static u_int decode_26(u_int, u_int *) | ||
41 | * static u_int decode_2e(u_int, u_int *) | ||
42 | * static void update_status_cbit(u_int *, u_int, u_int, u_int) | ||
43 | * | ||
44 | * Theory: | ||
45 | * <<please update with a overview of the operation of this file>> | ||
46 | * | ||
47 | * END_DESC | ||
48 | */ | ||
49 | |||
50 | #define FPUDEBUG 0 | ||
51 | |||
52 | #include "float.h" | ||
53 | #include <linux/kernel.h> | ||
54 | #include <asm/processor.h> | ||
55 | /* #include <sys/debug.h> */ | ||
56 | /* #include <machine/sys/mdep_private.h> */ | ||
57 | |||
58 | #define COPR_INST 0x30000000 | ||
59 | |||
60 | /* | ||
61 | * definition of extru macro. If pos and len are constants, the compiler | ||
62 | * will generate an extru instruction when optimized | ||
63 | */ | ||
64 | #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) | ||
65 | /* definitions of bit field locations in the instruction */ | ||
66 | #define fpmajorpos 5 | ||
67 | #define fpr1pos 10 | ||
68 | #define fpr2pos 15 | ||
69 | #define fptpos 31 | ||
70 | #define fpsubpos 18 | ||
71 | #define fpclass1subpos 16 | ||
72 | #define fpclasspos 22 | ||
73 | #define fpfmtpos 20 | ||
74 | #define fpdfpos 18 | ||
75 | #define fpnulpos 26 | ||
76 | /* | ||
77 | * the following are the extra bits for the 0E major op | ||
78 | */ | ||
79 | #define fpxr1pos 24 | ||
80 | #define fpxr2pos 19 | ||
81 | #define fpxtpos 25 | ||
82 | #define fpxpos 23 | ||
83 | #define fp0efmtpos 20 | ||
84 | /* | ||
85 | * the following are for the multi-ops | ||
86 | */ | ||
87 | #define fprm1pos 10 | ||
88 | #define fprm2pos 15 | ||
89 | #define fptmpos 31 | ||
90 | #define fprapos 25 | ||
91 | #define fptapos 20 | ||
92 | #define fpmultifmt 26 | ||
93 | /* | ||
94 | * the following are for the fused FP instructions | ||
95 | */ | ||
96 | /* fprm1pos 10 */ | ||
97 | /* fprm2pos 15 */ | ||
98 | #define fpraupos 18 | ||
99 | #define fpxrm2pos 19 | ||
100 | /* fpfmtpos 20 */ | ||
101 | #define fpralpos 23 | ||
102 | #define fpxrm1pos 24 | ||
103 | /* fpxtpos 25 */ | ||
104 | #define fpfusedsubop 26 | ||
105 | /* fptpos 31 */ | ||
106 | |||
107 | /* | ||
108 | * offset to constant zero in the FP emulation registers | ||
109 | */ | ||
110 | #define fpzeroreg (32*sizeof(double)/sizeof(u_int)) | ||
111 | |||
112 | /* | ||
113 | * extract the major opcode from the instruction | ||
114 | */ | ||
115 | #define get_major(op) extru(op,fpmajorpos,6) | ||
116 | /* | ||
117 | * extract the two bit class field from the FP instruction. The class is at bit | ||
118 | * positions 21-22 | ||
119 | */ | ||
120 | #define get_class(op) extru(op,fpclasspos,2) | ||
121 | /* | ||
122 | * extract the 3 bit subop field. For all but class 1 instructions, it is | ||
123 | * located at bit positions 16-18 | ||
124 | */ | ||
125 | #define get_subop(op) extru(op,fpsubpos,3) | ||
126 | /* | ||
127 | * extract the 2 or 3 bit subop field from class 1 instructions. It is located | ||
128 | * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0) | ||
129 | */ | ||
130 | #define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */ | ||
131 | #define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */ | ||
132 | |||
133 | /* definitions of unimplemented exceptions */ | ||
134 | #define MAJOR_0C_EXCP 0x09 | ||
135 | #define MAJOR_0E_EXCP 0x0b | ||
136 | #define MAJOR_06_EXCP 0x03 | ||
137 | #define MAJOR_26_EXCP 0x23 | ||
138 | #define MAJOR_2E_EXCP 0x2b | ||
139 | #define PA83_UNIMP_EXCP 0x01 | ||
140 | |||
141 | /* | ||
142 | * Special Defines for TIMEX specific code | ||
143 | */ | ||
144 | |||
145 | #define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2) | ||
146 | #define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG) | ||
147 | |||
148 | /* | ||
149 | * Static function definitions | ||
150 | */ | ||
151 | #define _PROTOTYPES | ||
152 | #if defined(_PROTOTYPES) || defined(_lint) | ||
153 | static u_int decode_0c(u_int, u_int, u_int, u_int *); | ||
154 | static u_int decode_0e(u_int, u_int, u_int, u_int *); | ||
155 | static u_int decode_06(u_int, u_int *); | ||
156 | static u_int decode_26(u_int, u_int *); | ||
157 | static u_int decode_2e(u_int, u_int *); | ||
158 | static void update_status_cbit(u_int *, u_int, u_int, u_int); | ||
159 | #else /* !_PROTOTYPES&&!_lint */ | ||
160 | static u_int decode_0c(); | ||
161 | static u_int decode_0e(); | ||
162 | static u_int decode_06(); | ||
163 | static u_int decode_26(); | ||
164 | static u_int decode_2e(); | ||
165 | static void update_status_cbit(); | ||
166 | #endif /* _PROTOTYPES&&!_lint */ | ||
167 | |||
168 | #define VASSERT(x) | ||
169 | |||
170 | static void parisc_linux_get_fpu_type(u_int fpregs[]) | ||
171 | { | ||
172 | /* on pa-linux the fpu type is not filled in by the | ||
173 | * caller; it is constructed here | ||
174 | */ | ||
175 | if (boot_cpu_data.cpu_type == pcxs) | ||
176 | fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG; | ||
177 | else if (boot_cpu_data.cpu_type == pcxt || | ||
178 | boot_cpu_data.cpu_type == pcxt_) | ||
179 | fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG; | ||
180 | else if (boot_cpu_data.cpu_type >= pcxu) | ||
181 | fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG; | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * this routine will decode the excepting floating point instruction and | ||
186 | * call the approiate emulation routine. | ||
187 | * It is called by decode_fpu with the following parameters: | ||
188 | * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register) | ||
189 | * where current_ir is the instruction to be emulated, | ||
190 | * unimplemented_code is the exception_code that the hardware generated | ||
191 | * and &Fpu_register is the address of emulated FP reg 0. | ||
192 | */ | ||
193 | u_int | ||
194 | fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[]) | ||
195 | { | ||
196 | u_int class, subop; | ||
197 | u_int fpu_type_flags; | ||
198 | |||
199 | /* All FP emulation code assumes that ints are 4-bytes in length */ | ||
200 | VASSERT(sizeof(int) == 4); | ||
201 | |||
202 | parisc_linux_get_fpu_type(fpregs); | ||
203 | |||
204 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ | ||
205 | |||
206 | class = get_class(ir); | ||
207 | if (class == 1) { | ||
208 | if (fpu_type_flags & PA2_0_FPU_FLAG) | ||
209 | subop = get_subop1_PA2_0(ir); | ||
210 | else | ||
211 | subop = get_subop1_PA1_1(ir); | ||
212 | } | ||
213 | else | ||
214 | subop = get_subop(ir); | ||
215 | |||
216 | if (FPUDEBUG) printk("class %d subop %d\n", class, subop); | ||
217 | |||
218 | switch (excp_code) { | ||
219 | case MAJOR_0C_EXCP: | ||
220 | case PA83_UNIMP_EXCP: | ||
221 | return(decode_0c(ir,class,subop,fpregs)); | ||
222 | case MAJOR_0E_EXCP: | ||
223 | return(decode_0e(ir,class,subop,fpregs)); | ||
224 | case MAJOR_06_EXCP: | ||
225 | return(decode_06(ir,fpregs)); | ||
226 | case MAJOR_26_EXCP: | ||
227 | return(decode_26(ir,fpregs)); | ||
228 | case MAJOR_2E_EXCP: | ||
229 | return(decode_2e(ir,fpregs)); | ||
230 | default: | ||
231 | /* "crashme Night Gallery painting nr 2. (asm_crash.s). | ||
232 | * This was fixed for multi-user kernels, but | ||
233 | * workstation kernels had a panic here. This allowed | ||
234 | * any arbitrary user to panic the kernel by executing | ||
235 | * setting the FP exception registers to strange values | ||
236 | * and generating an emulation trap. The emulation and | ||
237 | * exception code must never be able to panic the | ||
238 | * kernel. | ||
239 | */ | ||
240 | return(UNIMPLEMENTEDEXCEPTION); | ||
241 | } | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * this routine is called by $emulation_trap to emulate a coprocessor | ||
246 | * instruction if one doesn't exist | ||
247 | */ | ||
248 | u_int | ||
249 | emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[]) | ||
250 | { | ||
251 | u_int class, subop, major; | ||
252 | u_int fpu_type_flags; | ||
253 | |||
254 | /* All FP emulation code assumes that ints are 4-bytes in length */ | ||
255 | VASSERT(sizeof(int) == 4); | ||
256 | |||
257 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ | ||
258 | |||
259 | major = get_major(ir); | ||
260 | class = get_class(ir); | ||
261 | if (class == 1) { | ||
262 | if (fpu_type_flags & PA2_0_FPU_FLAG) | ||
263 | subop = get_subop1_PA2_0(ir); | ||
264 | else | ||
265 | subop = get_subop1_PA1_1(ir); | ||
266 | } | ||
267 | else | ||
268 | subop = get_subop(ir); | ||
269 | switch (major) { | ||
270 | case 0x0C: | ||
271 | return(decode_0c(ir,class,subop,fpregs)); | ||
272 | case 0x0E: | ||
273 | return(decode_0e(ir,class,subop,fpregs)); | ||
274 | case 0x06: | ||
275 | return(decode_06(ir,fpregs)); | ||
276 | case 0x26: | ||
277 | return(decode_26(ir,fpregs)); | ||
278 | case 0x2E: | ||
279 | return(decode_2e(ir,fpregs)); | ||
280 | default: | ||
281 | return(PA83_UNIMP_EXCP); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | |||
286 | static u_int | ||
287 | decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[]) | ||
288 | { | ||
289 | u_int r1,r2,t; /* operand register offsets */ | ||
290 | u_int fmt; /* also sf for class 1 conversions */ | ||
291 | u_int df; /* for class 1 conversions */ | ||
292 | u_int *status; | ||
293 | u_int retval, local_status; | ||
294 | u_int fpu_type_flags; | ||
295 | |||
296 | if (ir == COPR_INST) { | ||
297 | fpregs[0] = EMULATION_VERSION << 11; | ||
298 | return(NOEXCEPTION); | ||
299 | } | ||
300 | status = &fpregs[0]; /* fp status register */ | ||
301 | local_status = fpregs[0]; /* and local copy */ | ||
302 | r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int); | ||
303 | if (r1 == 0) /* map fr0 source to constant zero */ | ||
304 | r1 = fpzeroreg; | ||
305 | t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); | ||
306 | if (t == 0 && class != 2) /* don't allow fr0 as a dest */ | ||
307 | return(MAJOR_0C_EXCP); | ||
308 | fmt = extru(ir,fpfmtpos,2); /* get fmt completer */ | ||
309 | |||
310 | switch (class) { | ||
311 | case 0: | ||
312 | switch (subop) { | ||
313 | case 0: /* COPR 0,0 emulated above*/ | ||
314 | case 1: | ||
315 | return(MAJOR_0C_EXCP); | ||
316 | case 2: /* FCPY */ | ||
317 | switch (fmt) { | ||
318 | case 2: /* illegal */ | ||
319 | return(MAJOR_0C_EXCP); | ||
320 | case 3: /* quad */ | ||
321 | t &= ~3; /* force to even reg #s */ | ||
322 | r1 &= ~3; | ||
323 | fpregs[t+3] = fpregs[r1+3]; | ||
324 | fpregs[t+2] = fpregs[r1+2]; | ||
325 | case 1: /* double */ | ||
326 | fpregs[t+1] = fpregs[r1+1]; | ||
327 | case 0: /* single */ | ||
328 | fpregs[t] = fpregs[r1]; | ||
329 | return(NOEXCEPTION); | ||
330 | } | ||
331 | case 3: /* FABS */ | ||
332 | switch (fmt) { | ||
333 | case 2: /* illegal */ | ||
334 | return(MAJOR_0C_EXCP); | ||
335 | case 3: /* quad */ | ||
336 | t &= ~3; /* force to even reg #s */ | ||
337 | r1 &= ~3; | ||
338 | fpregs[t+3] = fpregs[r1+3]; | ||
339 | fpregs[t+2] = fpregs[r1+2]; | ||
340 | case 1: /* double */ | ||
341 | fpregs[t+1] = fpregs[r1+1]; | ||
342 | case 0: /* single */ | ||
343 | /* copy and clear sign bit */ | ||
344 | fpregs[t] = fpregs[r1] & 0x7fffffff; | ||
345 | return(NOEXCEPTION); | ||
346 | } | ||
347 | case 6: /* FNEG */ | ||
348 | switch (fmt) { | ||
349 | case 2: /* illegal */ | ||
350 | return(MAJOR_0C_EXCP); | ||
351 | case 3: /* quad */ | ||
352 | t &= ~3; /* force to even reg #s */ | ||
353 | r1 &= ~3; | ||
354 | fpregs[t+3] = fpregs[r1+3]; | ||
355 | fpregs[t+2] = fpregs[r1+2]; | ||
356 | case 1: /* double */ | ||
357 | fpregs[t+1] = fpregs[r1+1]; | ||
358 | case 0: /* single */ | ||
359 | /* copy and invert sign bit */ | ||
360 | fpregs[t] = fpregs[r1] ^ 0x80000000; | ||
361 | return(NOEXCEPTION); | ||
362 | } | ||
363 | case 7: /* FNEGABS */ | ||
364 | switch (fmt) { | ||
365 | case 2: /* illegal */ | ||
366 | return(MAJOR_0C_EXCP); | ||
367 | case 3: /* quad */ | ||
368 | t &= ~3; /* force to even reg #s */ | ||
369 | r1 &= ~3; | ||
370 | fpregs[t+3] = fpregs[r1+3]; | ||
371 | fpregs[t+2] = fpregs[r1+2]; | ||
372 | case 1: /* double */ | ||
373 | fpregs[t+1] = fpregs[r1+1]; | ||
374 | case 0: /* single */ | ||
375 | /* copy and set sign bit */ | ||
376 | fpregs[t] = fpregs[r1] | 0x80000000; | ||
377 | return(NOEXCEPTION); | ||
378 | } | ||
379 | case 4: /* FSQRT */ | ||
380 | switch (fmt) { | ||
381 | case 0: | ||
382 | return(sgl_fsqrt(&fpregs[r1],0, | ||
383 | &fpregs[t],status)); | ||
384 | case 1: | ||
385 | return(dbl_fsqrt(&fpregs[r1],0, | ||
386 | &fpregs[t],status)); | ||
387 | case 2: | ||
388 | case 3: /* quad not implemented */ | ||
389 | return(MAJOR_0C_EXCP); | ||
390 | } | ||
391 | case 5: /* FRND */ | ||
392 | switch (fmt) { | ||
393 | case 0: | ||
394 | return(sgl_frnd(&fpregs[r1],0, | ||
395 | &fpregs[t],status)); | ||
396 | case 1: | ||
397 | return(dbl_frnd(&fpregs[r1],0, | ||
398 | &fpregs[t],status)); | ||
399 | case 2: | ||
400 | case 3: /* quad not implemented */ | ||
401 | return(MAJOR_0C_EXCP); | ||
402 | } | ||
403 | } /* end of switch (subop) */ | ||
404 | |||
405 | case 1: /* class 1 */ | ||
406 | df = extru(ir,fpdfpos,2); /* get dest format */ | ||
407 | if ((df & 2) || (fmt & 2)) { | ||
408 | /* | ||
409 | * fmt's 2 and 3 are illegal of not implemented | ||
410 | * quad conversions | ||
411 | */ | ||
412 | return(MAJOR_0C_EXCP); | ||
413 | } | ||
414 | /* | ||
415 | * encode source and dest formats into 2 bits. | ||
416 | * high bit is source, low bit is dest. | ||
417 | * bit = 1 --> double precision | ||
418 | */ | ||
419 | fmt = (fmt << 1) | df; | ||
420 | switch (subop) { | ||
421 | case 0: /* FCNVFF */ | ||
422 | switch(fmt) { | ||
423 | case 0: /* sgl/sgl */ | ||
424 | return(MAJOR_0C_EXCP); | ||
425 | case 1: /* sgl/dbl */ | ||
426 | return(sgl_to_dbl_fcnvff(&fpregs[r1],0, | ||
427 | &fpregs[t],status)); | ||
428 | case 2: /* dbl/sgl */ | ||
429 | return(dbl_to_sgl_fcnvff(&fpregs[r1],0, | ||
430 | &fpregs[t],status)); | ||
431 | case 3: /* dbl/dbl */ | ||
432 | return(MAJOR_0C_EXCP); | ||
433 | } | ||
434 | case 1: /* FCNVXF */ | ||
435 | switch(fmt) { | ||
436 | case 0: /* sgl/sgl */ | ||
437 | return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, | ||
438 | &fpregs[t],status)); | ||
439 | case 1: /* sgl/dbl */ | ||
440 | return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, | ||
441 | &fpregs[t],status)); | ||
442 | case 2: /* dbl/sgl */ | ||
443 | return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, | ||
444 | &fpregs[t],status)); | ||
445 | case 3: /* dbl/dbl */ | ||
446 | return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, | ||
447 | &fpregs[t],status)); | ||
448 | } | ||
449 | case 2: /* FCNVFX */ | ||
450 | switch(fmt) { | ||
451 | case 0: /* sgl/sgl */ | ||
452 | return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, | ||
453 | &fpregs[t],status)); | ||
454 | case 1: /* sgl/dbl */ | ||
455 | return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, | ||
456 | &fpregs[t],status)); | ||
457 | case 2: /* dbl/sgl */ | ||
458 | return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, | ||
459 | &fpregs[t],status)); | ||
460 | case 3: /* dbl/dbl */ | ||
461 | return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, | ||
462 | &fpregs[t],status)); | ||
463 | } | ||
464 | case 3: /* FCNVFXT */ | ||
465 | switch(fmt) { | ||
466 | case 0: /* sgl/sgl */ | ||
467 | return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, | ||
468 | &fpregs[t],status)); | ||
469 | case 1: /* sgl/dbl */ | ||
470 | return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, | ||
471 | &fpregs[t],status)); | ||
472 | case 2: /* dbl/sgl */ | ||
473 | return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, | ||
474 | &fpregs[t],status)); | ||
475 | case 3: /* dbl/dbl */ | ||
476 | return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, | ||
477 | &fpregs[t],status)); | ||
478 | } | ||
479 | case 5: /* FCNVUF (PA2.0 only) */ | ||
480 | switch(fmt) { | ||
481 | case 0: /* sgl/sgl */ | ||
482 | return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, | ||
483 | &fpregs[t],status)); | ||
484 | case 1: /* sgl/dbl */ | ||
485 | return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, | ||
486 | &fpregs[t],status)); | ||
487 | case 2: /* dbl/sgl */ | ||
488 | return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, | ||
489 | &fpregs[t],status)); | ||
490 | case 3: /* dbl/dbl */ | ||
491 | return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, | ||
492 | &fpregs[t],status)); | ||
493 | } | ||
494 | case 6: /* FCNVFU (PA2.0 only) */ | ||
495 | switch(fmt) { | ||
496 | case 0: /* sgl/sgl */ | ||
497 | return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, | ||
498 | &fpregs[t],status)); | ||
499 | case 1: /* sgl/dbl */ | ||
500 | return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, | ||
501 | &fpregs[t],status)); | ||
502 | case 2: /* dbl/sgl */ | ||
503 | return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, | ||
504 | &fpregs[t],status)); | ||
505 | case 3: /* dbl/dbl */ | ||
506 | return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, | ||
507 | &fpregs[t],status)); | ||
508 | } | ||
509 | case 7: /* FCNVFUT (PA2.0 only) */ | ||
510 | switch(fmt) { | ||
511 | case 0: /* sgl/sgl */ | ||
512 | return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, | ||
513 | &fpregs[t],status)); | ||
514 | case 1: /* sgl/dbl */ | ||
515 | return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, | ||
516 | &fpregs[t],status)); | ||
517 | case 2: /* dbl/sgl */ | ||
518 | return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, | ||
519 | &fpregs[t],status)); | ||
520 | case 3: /* dbl/dbl */ | ||
521 | return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, | ||
522 | &fpregs[t],status)); | ||
523 | } | ||
524 | case 4: /* undefined */ | ||
525 | return(MAJOR_0C_EXCP); | ||
526 | } /* end of switch subop */ | ||
527 | |||
528 | case 2: /* class 2 */ | ||
529 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; | ||
530 | r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int); | ||
531 | if (r2 == 0) | ||
532 | r2 = fpzeroreg; | ||
533 | if (fpu_type_flags & PA2_0_FPU_FLAG) { | ||
534 | /* FTEST if nullify bit set, otherwise FCMP */ | ||
535 | if (extru(ir, fpnulpos, 1)) { /* FTEST */ | ||
536 | switch (fmt) { | ||
537 | case 0: | ||
538 | /* | ||
539 | * arg0 is not used | ||
540 | * second param is the t field used for | ||
541 | * ftest,acc and ftest,rej | ||
542 | * third param is the subop (y-field) | ||
543 | */ | ||
544 | BUG(); | ||
545 | /* Unsupported | ||
546 | * return(ftest(0L,extru(ir,fptpos,5), | ||
547 | * &fpregs[0],subop)); | ||
548 | */ | ||
549 | case 1: | ||
550 | case 2: | ||
551 | case 3: | ||
552 | return(MAJOR_0C_EXCP); | ||
553 | } | ||
554 | } else { /* FCMP */ | ||
555 | switch (fmt) { | ||
556 | case 0: | ||
557 | retval = sgl_fcmp(&fpregs[r1], | ||
558 | &fpregs[r2],extru(ir,fptpos,5), | ||
559 | &local_status); | ||
560 | update_status_cbit(status,local_status, | ||
561 | fpu_type_flags, subop); | ||
562 | return(retval); | ||
563 | case 1: | ||
564 | retval = dbl_fcmp(&fpregs[r1], | ||
565 | &fpregs[r2],extru(ir,fptpos,5), | ||
566 | &local_status); | ||
567 | update_status_cbit(status,local_status, | ||
568 | fpu_type_flags, subop); | ||
569 | return(retval); | ||
570 | case 2: /* illegal */ | ||
571 | case 3: /* quad not implemented */ | ||
572 | return(MAJOR_0C_EXCP); | ||
573 | } | ||
574 | } | ||
575 | } /* end of if for PA2.0 */ | ||
576 | else { /* PA1.0 & PA1.1 */ | ||
577 | switch (subop) { | ||
578 | case 2: | ||
579 | case 3: | ||
580 | case 4: | ||
581 | case 5: | ||
582 | case 6: | ||
583 | case 7: | ||
584 | return(MAJOR_0C_EXCP); | ||
585 | case 0: /* FCMP */ | ||
586 | switch (fmt) { | ||
587 | case 0: | ||
588 | retval = sgl_fcmp(&fpregs[r1], | ||
589 | &fpregs[r2],extru(ir,fptpos,5), | ||
590 | &local_status); | ||
591 | update_status_cbit(status,local_status, | ||
592 | fpu_type_flags, subop); | ||
593 | return(retval); | ||
594 | case 1: | ||
595 | retval = dbl_fcmp(&fpregs[r1], | ||
596 | &fpregs[r2],extru(ir,fptpos,5), | ||
597 | &local_status); | ||
598 | update_status_cbit(status,local_status, | ||
599 | fpu_type_flags, subop); | ||
600 | return(retval); | ||
601 | case 2: /* illegal */ | ||
602 | case 3: /* quad not implemented */ | ||
603 | return(MAJOR_0C_EXCP); | ||
604 | } | ||
605 | case 1: /* FTEST */ | ||
606 | switch (fmt) { | ||
607 | case 0: | ||
608 | /* | ||
609 | * arg0 is not used | ||
610 | * second param is the t field used for | ||
611 | * ftest,acc and ftest,rej | ||
612 | * third param is the subop (y-field) | ||
613 | */ | ||
614 | BUG(); | ||
615 | /* unsupported | ||
616 | * return(ftest(0L,extru(ir,fptpos,5), | ||
617 | * &fpregs[0],subop)); | ||
618 | */ | ||
619 | case 1: | ||
620 | case 2: | ||
621 | case 3: | ||
622 | return(MAJOR_0C_EXCP); | ||
623 | } | ||
624 | } /* end of switch subop */ | ||
625 | } /* end of else for PA1.0 & PA1.1 */ | ||
626 | case 3: /* class 3 */ | ||
627 | r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int); | ||
628 | if (r2 == 0) | ||
629 | r2 = fpzeroreg; | ||
630 | switch (subop) { | ||
631 | case 5: | ||
632 | case 6: | ||
633 | case 7: | ||
634 | return(MAJOR_0C_EXCP); | ||
635 | |||
636 | case 0: /* FADD */ | ||
637 | switch (fmt) { | ||
638 | case 0: | ||
639 | return(sgl_fadd(&fpregs[r1],&fpregs[r2], | ||
640 | &fpregs[t],status)); | ||
641 | case 1: | ||
642 | return(dbl_fadd(&fpregs[r1],&fpregs[r2], | ||
643 | &fpregs[t],status)); | ||
644 | case 2: /* illegal */ | ||
645 | case 3: /* quad not implemented */ | ||
646 | return(MAJOR_0C_EXCP); | ||
647 | } | ||
648 | case 1: /* FSUB */ | ||
649 | switch (fmt) { | ||
650 | case 0: | ||
651 | return(sgl_fsub(&fpregs[r1],&fpregs[r2], | ||
652 | &fpregs[t],status)); | ||
653 | case 1: | ||
654 | return(dbl_fsub(&fpregs[r1],&fpregs[r2], | ||
655 | &fpregs[t],status)); | ||
656 | case 2: /* illegal */ | ||
657 | case 3: /* quad not implemented */ | ||
658 | return(MAJOR_0C_EXCP); | ||
659 | } | ||
660 | case 2: /* FMPY */ | ||
661 | switch (fmt) { | ||
662 | case 0: | ||
663 | return(sgl_fmpy(&fpregs[r1],&fpregs[r2], | ||
664 | &fpregs[t],status)); | ||
665 | case 1: | ||
666 | return(dbl_fmpy(&fpregs[r1],&fpregs[r2], | ||
667 | &fpregs[t],status)); | ||
668 | case 2: /* illegal */ | ||
669 | case 3: /* quad not implemented */ | ||
670 | return(MAJOR_0C_EXCP); | ||
671 | } | ||
672 | case 3: /* FDIV */ | ||
673 | switch (fmt) { | ||
674 | case 0: | ||
675 | return(sgl_fdiv(&fpregs[r1],&fpregs[r2], | ||
676 | &fpregs[t],status)); | ||
677 | case 1: | ||
678 | return(dbl_fdiv(&fpregs[r1],&fpregs[r2], | ||
679 | &fpregs[t],status)); | ||
680 | case 2: /* illegal */ | ||
681 | case 3: /* quad not implemented */ | ||
682 | return(MAJOR_0C_EXCP); | ||
683 | } | ||
684 | case 4: /* FREM */ | ||
685 | switch (fmt) { | ||
686 | case 0: | ||
687 | return(sgl_frem(&fpregs[r1],&fpregs[r2], | ||
688 | &fpregs[t],status)); | ||
689 | case 1: | ||
690 | return(dbl_frem(&fpregs[r1],&fpregs[r2], | ||
691 | &fpregs[t],status)); | ||
692 | case 2: /* illegal */ | ||
693 | case 3: /* quad not implemented */ | ||
694 | return(MAJOR_0C_EXCP); | ||
695 | } | ||
696 | } /* end of class 3 switch */ | ||
697 | } /* end of switch(class) */ | ||
698 | |||
699 | /* If we get here, something is really wrong! */ | ||
700 | return(MAJOR_0C_EXCP); | ||
701 | } | ||
702 | |||
703 | static u_int | ||
704 | decode_0e(ir,class,subop,fpregs) | ||
705 | u_int ir,class,subop; | ||
706 | u_int fpregs[]; | ||
707 | { | ||
708 | u_int r1,r2,t; /* operand register offsets */ | ||
709 | u_int fmt; /* also sf for class 1 conversions */ | ||
710 | u_int df; /* dest format for class 1 conversions */ | ||
711 | u_int *status; | ||
712 | u_int retval, local_status; | ||
713 | u_int fpu_type_flags; | ||
714 | |||
715 | status = &fpregs[0]; | ||
716 | local_status = fpregs[0]; | ||
717 | r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1))); | ||
718 | if (r1 == 0) | ||
719 | r1 = fpzeroreg; | ||
720 | t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); | ||
721 | if (t == 0 && class != 2) | ||
722 | return(MAJOR_0E_EXCP); | ||
723 | if (class < 2) /* class 0 or 1 has 2 bit fmt */ | ||
724 | fmt = extru(ir,fpfmtpos,2); | ||
725 | else /* class 2 and 3 have 1 bit fmt */ | ||
726 | fmt = extru(ir,fp0efmtpos,1); | ||
727 | /* | ||
728 | * An undefined combination, double precision accessing the | ||
729 | * right half of a FPR, can get us into trouble. | ||
730 | * Let's just force proper alignment on it. | ||
731 | */ | ||
732 | if (fmt == DBL) { | ||
733 | r1 &= ~1; | ||
734 | if (class != 1) | ||
735 | t &= ~1; | ||
736 | } | ||
737 | |||
738 | switch (class) { | ||
739 | case 0: | ||
740 | switch (subop) { | ||
741 | case 0: /* unimplemented */ | ||
742 | case 1: | ||
743 | return(MAJOR_0E_EXCP); | ||
744 | case 2: /* FCPY */ | ||
745 | switch (fmt) { | ||
746 | case 2: | ||
747 | case 3: | ||
748 | return(MAJOR_0E_EXCP); | ||
749 | case 1: /* double */ | ||
750 | fpregs[t+1] = fpregs[r1+1]; | ||
751 | case 0: /* single */ | ||
752 | fpregs[t] = fpregs[r1]; | ||
753 | return(NOEXCEPTION); | ||
754 | } | ||
755 | case 3: /* FABS */ | ||
756 | switch (fmt) { | ||
757 | case 2: | ||
758 | case 3: | ||
759 | return(MAJOR_0E_EXCP); | ||
760 | case 1: /* double */ | ||
761 | fpregs[t+1] = fpregs[r1+1]; | ||
762 | case 0: /* single */ | ||
763 | fpregs[t] = fpregs[r1] & 0x7fffffff; | ||
764 | return(NOEXCEPTION); | ||
765 | } | ||
766 | case 6: /* FNEG */ | ||
767 | switch (fmt) { | ||
768 | case 2: | ||
769 | case 3: | ||
770 | return(MAJOR_0E_EXCP); | ||
771 | case 1: /* double */ | ||
772 | fpregs[t+1] = fpregs[r1+1]; | ||
773 | case 0: /* single */ | ||
774 | fpregs[t] = fpregs[r1] ^ 0x80000000; | ||
775 | return(NOEXCEPTION); | ||
776 | } | ||
777 | case 7: /* FNEGABS */ | ||
778 | switch (fmt) { | ||
779 | case 2: | ||
780 | case 3: | ||
781 | return(MAJOR_0E_EXCP); | ||
782 | case 1: /* double */ | ||
783 | fpregs[t+1] = fpregs[r1+1]; | ||
784 | case 0: /* single */ | ||
785 | fpregs[t] = fpregs[r1] | 0x80000000; | ||
786 | return(NOEXCEPTION); | ||
787 | } | ||
788 | case 4: /* FSQRT */ | ||
789 | switch (fmt) { | ||
790 | case 0: | ||
791 | return(sgl_fsqrt(&fpregs[r1],0, | ||
792 | &fpregs[t], status)); | ||
793 | case 1: | ||
794 | return(dbl_fsqrt(&fpregs[r1],0, | ||
795 | &fpregs[t], status)); | ||
796 | case 2: | ||
797 | case 3: | ||
798 | return(MAJOR_0E_EXCP); | ||
799 | } | ||
800 | case 5: /* FRMD */ | ||
801 | switch (fmt) { | ||
802 | case 0: | ||
803 | return(sgl_frnd(&fpregs[r1],0, | ||
804 | &fpregs[t], status)); | ||
805 | case 1: | ||
806 | return(dbl_frnd(&fpregs[r1],0, | ||
807 | &fpregs[t], status)); | ||
808 | case 2: | ||
809 | case 3: | ||
810 | return(MAJOR_0E_EXCP); | ||
811 | } | ||
812 | } /* end of switch (subop */ | ||
813 | |||
814 | case 1: /* class 1 */ | ||
815 | df = extru(ir,fpdfpos,2); /* get dest format */ | ||
816 | /* | ||
817 | * Fix Crashme problem (writing to 31R in double precision) | ||
818 | * here too. | ||
819 | */ | ||
820 | if (df == DBL) { | ||
821 | t &= ~1; | ||
822 | } | ||
823 | if ((df & 2) || (fmt & 2)) | ||
824 | return(MAJOR_0E_EXCP); | ||
825 | |||
826 | fmt = (fmt << 1) | df; | ||
827 | switch (subop) { | ||
828 | case 0: /* FCNVFF */ | ||
829 | switch(fmt) { | ||
830 | case 0: /* sgl/sgl */ | ||
831 | return(MAJOR_0E_EXCP); | ||
832 | case 1: /* sgl/dbl */ | ||
833 | return(sgl_to_dbl_fcnvff(&fpregs[r1],0, | ||
834 | &fpregs[t],status)); | ||
835 | case 2: /* dbl/sgl */ | ||
836 | return(dbl_to_sgl_fcnvff(&fpregs[r1],0, | ||
837 | &fpregs[t],status)); | ||
838 | case 3: /* dbl/dbl */ | ||
839 | return(MAJOR_0E_EXCP); | ||
840 | } | ||
841 | case 1: /* FCNVXF */ | ||
842 | switch(fmt) { | ||
843 | case 0: /* sgl/sgl */ | ||
844 | return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, | ||
845 | &fpregs[t],status)); | ||
846 | case 1: /* sgl/dbl */ | ||
847 | return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, | ||
848 | &fpregs[t],status)); | ||
849 | case 2: /* dbl/sgl */ | ||
850 | return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, | ||
851 | &fpregs[t],status)); | ||
852 | case 3: /* dbl/dbl */ | ||
853 | return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, | ||
854 | &fpregs[t],status)); | ||
855 | } | ||
856 | case 2: /* FCNVFX */ | ||
857 | switch(fmt) { | ||
858 | case 0: /* sgl/sgl */ | ||
859 | return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, | ||
860 | &fpregs[t],status)); | ||
861 | case 1: /* sgl/dbl */ | ||
862 | return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, | ||
863 | &fpregs[t],status)); | ||
864 | case 2: /* dbl/sgl */ | ||
865 | return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, | ||
866 | &fpregs[t],status)); | ||
867 | case 3: /* dbl/dbl */ | ||
868 | return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, | ||
869 | &fpregs[t],status)); | ||
870 | } | ||
871 | case 3: /* FCNVFXT */ | ||
872 | switch(fmt) { | ||
873 | case 0: /* sgl/sgl */ | ||
874 | return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, | ||
875 | &fpregs[t],status)); | ||
876 | case 1: /* sgl/dbl */ | ||
877 | return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, | ||
878 | &fpregs[t],status)); | ||
879 | case 2: /* dbl/sgl */ | ||
880 | return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, | ||
881 | &fpregs[t],status)); | ||
882 | case 3: /* dbl/dbl */ | ||
883 | return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, | ||
884 | &fpregs[t],status)); | ||
885 | } | ||
886 | case 5: /* FCNVUF (PA2.0 only) */ | ||
887 | switch(fmt) { | ||
888 | case 0: /* sgl/sgl */ | ||
889 | return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, | ||
890 | &fpregs[t],status)); | ||
891 | case 1: /* sgl/dbl */ | ||
892 | return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, | ||
893 | &fpregs[t],status)); | ||
894 | case 2: /* dbl/sgl */ | ||
895 | return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, | ||
896 | &fpregs[t],status)); | ||
897 | case 3: /* dbl/dbl */ | ||
898 | return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, | ||
899 | &fpregs[t],status)); | ||
900 | } | ||
901 | case 6: /* FCNVFU (PA2.0 only) */ | ||
902 | switch(fmt) { | ||
903 | case 0: /* sgl/sgl */ | ||
904 | return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, | ||
905 | &fpregs[t],status)); | ||
906 | case 1: /* sgl/dbl */ | ||
907 | return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, | ||
908 | &fpregs[t],status)); | ||
909 | case 2: /* dbl/sgl */ | ||
910 | return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, | ||
911 | &fpregs[t],status)); | ||
912 | case 3: /* dbl/dbl */ | ||
913 | return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, | ||
914 | &fpregs[t],status)); | ||
915 | } | ||
916 | case 7: /* FCNVFUT (PA2.0 only) */ | ||
917 | switch(fmt) { | ||
918 | case 0: /* sgl/sgl */ | ||
919 | return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, | ||
920 | &fpregs[t],status)); | ||
921 | case 1: /* sgl/dbl */ | ||
922 | return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, | ||
923 | &fpregs[t],status)); | ||
924 | case 2: /* dbl/sgl */ | ||
925 | return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, | ||
926 | &fpregs[t],status)); | ||
927 | case 3: /* dbl/dbl */ | ||
928 | return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, | ||
929 | &fpregs[t],status)); | ||
930 | } | ||
931 | case 4: /* undefined */ | ||
932 | return(MAJOR_0C_EXCP); | ||
933 | } /* end of switch subop */ | ||
934 | case 2: /* class 2 */ | ||
935 | /* | ||
936 | * Be careful out there. | ||
937 | * Crashme can generate cases where FR31R is specified | ||
938 | * as the source or target of a double precision operation. | ||
939 | * Since we just pass the address of the floating-point | ||
940 | * register to the emulation routines, this can cause | ||
941 | * corruption of fpzeroreg. | ||
942 | */ | ||
943 | if (fmt == DBL) | ||
944 | r2 = (extru(ir,fpr2pos,5)<<1); | ||
945 | else | ||
946 | r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); | ||
947 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; | ||
948 | if (r2 == 0) | ||
949 | r2 = fpzeroreg; | ||
950 | if (fpu_type_flags & PA2_0_FPU_FLAG) { | ||
951 | /* FTEST if nullify bit set, otherwise FCMP */ | ||
952 | if (extru(ir, fpnulpos, 1)) { /* FTEST */ | ||
953 | /* not legal */ | ||
954 | return(MAJOR_0E_EXCP); | ||
955 | } else { /* FCMP */ | ||
956 | switch (fmt) { | ||
957 | /* | ||
958 | * fmt is only 1 bit long | ||
959 | */ | ||
960 | case 0: | ||
961 | retval = sgl_fcmp(&fpregs[r1], | ||
962 | &fpregs[r2],extru(ir,fptpos,5), | ||
963 | &local_status); | ||
964 | update_status_cbit(status,local_status, | ||
965 | fpu_type_flags, subop); | ||
966 | return(retval); | ||
967 | case 1: | ||
968 | retval = dbl_fcmp(&fpregs[r1], | ||
969 | &fpregs[r2],extru(ir,fptpos,5), | ||
970 | &local_status); | ||
971 | update_status_cbit(status,local_status, | ||
972 | fpu_type_flags, subop); | ||
973 | return(retval); | ||
974 | } | ||
975 | } | ||
976 | } /* end of if for PA2.0 */ | ||
977 | else { /* PA1.0 & PA1.1 */ | ||
978 | switch (subop) { | ||
979 | case 1: | ||
980 | case 2: | ||
981 | case 3: | ||
982 | case 4: | ||
983 | case 5: | ||
984 | case 6: | ||
985 | case 7: | ||
986 | return(MAJOR_0E_EXCP); | ||
987 | case 0: /* FCMP */ | ||
988 | switch (fmt) { | ||
989 | /* | ||
990 | * fmt is only 1 bit long | ||
991 | */ | ||
992 | case 0: | ||
993 | retval = sgl_fcmp(&fpregs[r1], | ||
994 | &fpregs[r2],extru(ir,fptpos,5), | ||
995 | &local_status); | ||
996 | update_status_cbit(status,local_status, | ||
997 | fpu_type_flags, subop); | ||
998 | return(retval); | ||
999 | case 1: | ||
1000 | retval = dbl_fcmp(&fpregs[r1], | ||
1001 | &fpregs[r2],extru(ir,fptpos,5), | ||
1002 | &local_status); | ||
1003 | update_status_cbit(status,local_status, | ||
1004 | fpu_type_flags, subop); | ||
1005 | return(retval); | ||
1006 | } | ||
1007 | } /* end of switch subop */ | ||
1008 | } /* end of else for PA1.0 & PA1.1 */ | ||
1009 | case 3: /* class 3 */ | ||
1010 | /* | ||
1011 | * Be careful out there. | ||
1012 | * Crashme can generate cases where FR31R is specified | ||
1013 | * as the source or target of a double precision operation. | ||
1014 | * Since we just pass the address of the floating-point | ||
1015 | * register to the emulation routines, this can cause | ||
1016 | * corruption of fpzeroreg. | ||
1017 | */ | ||
1018 | if (fmt == DBL) | ||
1019 | r2 = (extru(ir,fpr2pos,5)<<1); | ||
1020 | else | ||
1021 | r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); | ||
1022 | if (r2 == 0) | ||
1023 | r2 = fpzeroreg; | ||
1024 | switch (subop) { | ||
1025 | case 5: | ||
1026 | case 6: | ||
1027 | case 7: | ||
1028 | return(MAJOR_0E_EXCP); | ||
1029 | |||
1030 | /* | ||
1031 | * Note that fmt is only 1 bit for class 3 */ | ||
1032 | case 0: /* FADD */ | ||
1033 | switch (fmt) { | ||
1034 | case 0: | ||
1035 | return(sgl_fadd(&fpregs[r1],&fpregs[r2], | ||
1036 | &fpregs[t],status)); | ||
1037 | case 1: | ||
1038 | return(dbl_fadd(&fpregs[r1],&fpregs[r2], | ||
1039 | &fpregs[t],status)); | ||
1040 | } | ||
1041 | case 1: /* FSUB */ | ||
1042 | switch (fmt) { | ||
1043 | case 0: | ||
1044 | return(sgl_fsub(&fpregs[r1],&fpregs[r2], | ||
1045 | &fpregs[t],status)); | ||
1046 | case 1: | ||
1047 | return(dbl_fsub(&fpregs[r1],&fpregs[r2], | ||
1048 | &fpregs[t],status)); | ||
1049 | } | ||
1050 | case 2: /* FMPY or XMPYU */ | ||
1051 | /* | ||
1052 | * check for integer multiply (x bit set) | ||
1053 | */ | ||
1054 | if (extru(ir,fpxpos,1)) { | ||
1055 | /* | ||
1056 | * emulate XMPYU | ||
1057 | */ | ||
1058 | switch (fmt) { | ||
1059 | case 0: | ||
1060 | /* | ||
1061 | * bad instruction if t specifies | ||
1062 | * the right half of a register | ||
1063 | */ | ||
1064 | if (t & 1) | ||
1065 | return(MAJOR_0E_EXCP); | ||
1066 | BUG(); | ||
1067 | /* unsupported | ||
1068 | * impyu(&fpregs[r1],&fpregs[r2], | ||
1069 | * &fpregs[t]); | ||
1070 | */ | ||
1071 | return(NOEXCEPTION); | ||
1072 | case 1: | ||
1073 | return(MAJOR_0E_EXCP); | ||
1074 | } | ||
1075 | } | ||
1076 | else { /* FMPY */ | ||
1077 | switch (fmt) { | ||
1078 | case 0: | ||
1079 | return(sgl_fmpy(&fpregs[r1], | ||
1080 | &fpregs[r2],&fpregs[t],status)); | ||
1081 | case 1: | ||
1082 | return(dbl_fmpy(&fpregs[r1], | ||
1083 | &fpregs[r2],&fpregs[t],status)); | ||
1084 | } | ||
1085 | } | ||
1086 | case 3: /* FDIV */ | ||
1087 | switch (fmt) { | ||
1088 | case 0: | ||
1089 | return(sgl_fdiv(&fpregs[r1],&fpregs[r2], | ||
1090 | &fpregs[t],status)); | ||
1091 | case 1: | ||
1092 | return(dbl_fdiv(&fpregs[r1],&fpregs[r2], | ||
1093 | &fpregs[t],status)); | ||
1094 | } | ||
1095 | case 4: /* FREM */ | ||
1096 | switch (fmt) { | ||
1097 | case 0: | ||
1098 | return(sgl_frem(&fpregs[r1],&fpregs[r2], | ||
1099 | &fpregs[t],status)); | ||
1100 | case 1: | ||
1101 | return(dbl_frem(&fpregs[r1],&fpregs[r2], | ||
1102 | &fpregs[t],status)); | ||
1103 | } | ||
1104 | } /* end of class 3 switch */ | ||
1105 | } /* end of switch(class) */ | ||
1106 | |||
1107 | /* If we get here, something is really wrong! */ | ||
1108 | return(MAJOR_0E_EXCP); | ||
1109 | } | ||
1110 | |||
1111 | |||
1112 | /* | ||
1113 | * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction | ||
1114 | */ | ||
1115 | static u_int | ||
1116 | decode_06(ir,fpregs) | ||
1117 | u_int ir; | ||
1118 | u_int fpregs[]; | ||
1119 | { | ||
1120 | u_int rm1, rm2, tm, ra, ta; /* operands */ | ||
1121 | u_int fmt; | ||
1122 | u_int error = 0; | ||
1123 | u_int status; | ||
1124 | u_int fpu_type_flags; | ||
1125 | union { | ||
1126 | double dbl; | ||
1127 | float flt; | ||
1128 | struct { u_int i1; u_int i2; } ints; | ||
1129 | } mtmp, atmp; | ||
1130 | |||
1131 | |||
1132 | status = fpregs[0]; /* use a local copy of status reg */ | ||
1133 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ | ||
1134 | fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ | ||
1135 | if (fmt == 0) { /* DBL */ | ||
1136 | rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); | ||
1137 | if (rm1 == 0) | ||
1138 | rm1 = fpzeroreg; | ||
1139 | rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); | ||
1140 | if (rm2 == 0) | ||
1141 | rm2 = fpzeroreg; | ||
1142 | tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); | ||
1143 | if (tm == 0) | ||
1144 | return(MAJOR_06_EXCP); | ||
1145 | ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); | ||
1146 | ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); | ||
1147 | if (ta == 0) | ||
1148 | return(MAJOR_06_EXCP); | ||
1149 | |||
1150 | if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) { | ||
1151 | |||
1152 | if (ra == 0) { | ||
1153 | /* special case FMPYCFXT, see sgl case below */ | ||
1154 | if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2], | ||
1155 | &mtmp.ints.i1,&status)) | ||
1156 | error = 1; | ||
1157 | if (dbl_to_sgl_fcnvfxt(&fpregs[ta], | ||
1158 | &atmp.ints.i1,&atmp.ints.i1,&status)) | ||
1159 | error = 1; | ||
1160 | } | ||
1161 | else { | ||
1162 | |||
1163 | if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, | ||
1164 | &status)) | ||
1165 | error = 1; | ||
1166 | if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, | ||
1167 | &status)) | ||
1168 | error = 1; | ||
1169 | } | ||
1170 | } | ||
1171 | |||
1172 | else | ||
1173 | |||
1174 | { | ||
1175 | if (ra == 0) | ||
1176 | ra = fpzeroreg; | ||
1177 | |||
1178 | if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, | ||
1179 | &status)) | ||
1180 | error = 1; | ||
1181 | if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, | ||
1182 | &status)) | ||
1183 | error = 1; | ||
1184 | |||
1185 | } | ||
1186 | |||
1187 | if (error) | ||
1188 | return(MAJOR_06_EXCP); | ||
1189 | else { | ||
1190 | /* copy results */ | ||
1191 | fpregs[tm] = mtmp.ints.i1; | ||
1192 | fpregs[tm+1] = mtmp.ints.i2; | ||
1193 | fpregs[ta] = atmp.ints.i1; | ||
1194 | fpregs[ta+1] = atmp.ints.i2; | ||
1195 | fpregs[0] = status; | ||
1196 | return(NOEXCEPTION); | ||
1197 | } | ||
1198 | } | ||
1199 | else { /* SGL */ | ||
1200 | /* | ||
1201 | * calculate offsets for single precision numbers | ||
1202 | * See table 6-14 in PA-89 architecture for mapping | ||
1203 | */ | ||
1204 | rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ | ||
1205 | rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ | ||
1206 | |||
1207 | rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ | ||
1208 | rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ | ||
1209 | |||
1210 | tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ | ||
1211 | tm |= extru(ir,fptmpos-4,1); /* add right word offset */ | ||
1212 | |||
1213 | ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ | ||
1214 | ra |= extru(ir,fprapos-4,1); /* add right word offset */ | ||
1215 | |||
1216 | ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ | ||
1217 | ta |= extru(ir,fptapos-4,1); /* add right word offset */ | ||
1218 | |||
1219 | if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) { | ||
1220 | /* special case FMPYCFXT (really 0) | ||
1221 | * This instruction is only present on the Timex and | ||
1222 | * Rolex fpu's in so if it is the special case and | ||
1223 | * one of these fpu's we run the FMPYCFXT instruction | ||
1224 | */ | ||
1225 | if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, | ||
1226 | &status)) | ||
1227 | error = 1; | ||
1228 | if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1, | ||
1229 | &atmp.ints.i1,&status)) | ||
1230 | error = 1; | ||
1231 | } | ||
1232 | else { | ||
1233 | if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, | ||
1234 | &status)) | ||
1235 | error = 1; | ||
1236 | if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, | ||
1237 | &status)) | ||
1238 | error = 1; | ||
1239 | } | ||
1240 | if (error) | ||
1241 | return(MAJOR_06_EXCP); | ||
1242 | else { | ||
1243 | /* copy results */ | ||
1244 | fpregs[tm] = mtmp.ints.i1; | ||
1245 | fpregs[ta] = atmp.ints.i1; | ||
1246 | fpregs[0] = status; | ||
1247 | return(NOEXCEPTION); | ||
1248 | } | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | /* | ||
1253 | * routine to decode the 26 (FMPYSUB) instruction | ||
1254 | */ | ||
1255 | static u_int | ||
1256 | decode_26(ir,fpregs) | ||
1257 | u_int ir; | ||
1258 | u_int fpregs[]; | ||
1259 | { | ||
1260 | u_int rm1, rm2, tm, ra, ta; /* operands */ | ||
1261 | u_int fmt; | ||
1262 | u_int error = 0; | ||
1263 | u_int status; | ||
1264 | union { | ||
1265 | double dbl; | ||
1266 | float flt; | ||
1267 | struct { u_int i1; u_int i2; } ints; | ||
1268 | } mtmp, atmp; | ||
1269 | |||
1270 | |||
1271 | status = fpregs[0]; | ||
1272 | fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ | ||
1273 | if (fmt == 0) { /* DBL */ | ||
1274 | rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); | ||
1275 | if (rm1 == 0) | ||
1276 | rm1 = fpzeroreg; | ||
1277 | rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); | ||
1278 | if (rm2 == 0) | ||
1279 | rm2 = fpzeroreg; | ||
1280 | tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); | ||
1281 | if (tm == 0) | ||
1282 | return(MAJOR_26_EXCP); | ||
1283 | ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); | ||
1284 | if (ra == 0) | ||
1285 | return(MAJOR_26_EXCP); | ||
1286 | ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); | ||
1287 | if (ta == 0) | ||
1288 | return(MAJOR_26_EXCP); | ||
1289 | |||
1290 | if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) | ||
1291 | error = 1; | ||
1292 | if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) | ||
1293 | error = 1; | ||
1294 | if (error) | ||
1295 | return(MAJOR_26_EXCP); | ||
1296 | else { | ||
1297 | /* copy results */ | ||
1298 | fpregs[tm] = mtmp.ints.i1; | ||
1299 | fpregs[tm+1] = mtmp.ints.i2; | ||
1300 | fpregs[ta] = atmp.ints.i1; | ||
1301 | fpregs[ta+1] = atmp.ints.i2; | ||
1302 | fpregs[0] = status; | ||
1303 | return(NOEXCEPTION); | ||
1304 | } | ||
1305 | } | ||
1306 | else { /* SGL */ | ||
1307 | /* | ||
1308 | * calculate offsets for single precision numbers | ||
1309 | * See table 6-14 in PA-89 architecture for mapping | ||
1310 | */ | ||
1311 | rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ | ||
1312 | rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ | ||
1313 | |||
1314 | rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ | ||
1315 | rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ | ||
1316 | |||
1317 | tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ | ||
1318 | tm |= extru(ir,fptmpos-4,1); /* add right word offset */ | ||
1319 | |||
1320 | ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ | ||
1321 | ra |= extru(ir,fprapos-4,1); /* add right word offset */ | ||
1322 | |||
1323 | ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ | ||
1324 | ta |= extru(ir,fptapos-4,1); /* add right word offset */ | ||
1325 | |||
1326 | if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) | ||
1327 | error = 1; | ||
1328 | if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) | ||
1329 | error = 1; | ||
1330 | if (error) | ||
1331 | return(MAJOR_26_EXCP); | ||
1332 | else { | ||
1333 | /* copy results */ | ||
1334 | fpregs[tm] = mtmp.ints.i1; | ||
1335 | fpregs[ta] = atmp.ints.i1; | ||
1336 | fpregs[0] = status; | ||
1337 | return(NOEXCEPTION); | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | } | ||
1342 | |||
1343 | /* | ||
1344 | * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions | ||
1345 | */ | ||
1346 | static u_int | ||
1347 | decode_2e(ir,fpregs) | ||
1348 | u_int ir; | ||
1349 | u_int fpregs[]; | ||
1350 | { | ||
1351 | u_int rm1, rm2, ra, t; /* operands */ | ||
1352 | u_int fmt; | ||
1353 | |||
1354 | fmt = extru(ir,fpfmtpos,1); /* get fmt completer */ | ||
1355 | if (fmt == DBL) { /* DBL */ | ||
1356 | rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int); | ||
1357 | if (rm1 == 0) | ||
1358 | rm1 = fpzeroreg; | ||
1359 | rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int); | ||
1360 | if (rm2 == 0) | ||
1361 | rm2 = fpzeroreg; | ||
1362 | ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) * | ||
1363 | sizeof(double)/sizeof(u_int); | ||
1364 | if (ra == 0) | ||
1365 | ra = fpzeroreg; | ||
1366 | t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); | ||
1367 | if (t == 0) | ||
1368 | return(MAJOR_2E_EXCP); | ||
1369 | |||
1370 | if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ | ||
1371 | return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], | ||
1372 | &fpregs[ra], &fpregs[0], &fpregs[t])); | ||
1373 | } else { | ||
1374 | return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], | ||
1375 | &fpregs[ra], &fpregs[0], &fpregs[t])); | ||
1376 | } | ||
1377 | } /* end DBL */ | ||
1378 | else { /* SGL */ | ||
1379 | rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1)); | ||
1380 | if (rm1 == 0) | ||
1381 | rm1 = fpzeroreg; | ||
1382 | rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1)); | ||
1383 | if (rm2 == 0) | ||
1384 | rm2 = fpzeroreg; | ||
1385 | ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3); | ||
1386 | if (ra == 0) | ||
1387 | ra = fpzeroreg; | ||
1388 | t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); | ||
1389 | if (t == 0) | ||
1390 | return(MAJOR_2E_EXCP); | ||
1391 | |||
1392 | if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ | ||
1393 | return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], | ||
1394 | &fpregs[ra], &fpregs[0], &fpregs[t])); | ||
1395 | } else { | ||
1396 | return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], | ||
1397 | &fpregs[ra], &fpregs[0], &fpregs[t])); | ||
1398 | } | ||
1399 | } /* end SGL */ | ||
1400 | } | ||
1401 | |||
1402 | /* | ||
1403 | * update_status_cbit | ||
1404 | * | ||
1405 | * This routine returns the correct FP status register value in | ||
1406 | * *status, based on the C-bit & V-bit returned by the FCMP | ||
1407 | * emulation routine in new_status. The architecture type | ||
1408 | * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field | ||
1409 | * and the architecture type are used to determine what flavor | ||
1410 | * of FCMP is being emulated. | ||
1411 | */ | ||
1412 | static void | ||
1413 | update_status_cbit(status, new_status, fpu_type, y_field) | ||
1414 | u_int *status, new_status; | ||
1415 | u_int fpu_type; | ||
1416 | u_int y_field; | ||
1417 | { | ||
1418 | /* | ||
1419 | * For PA89 FPU's which implement the Compare Queue and | ||
1420 | * for PA2.0 FPU's, update the Compare Queue if the y-field = 0, | ||
1421 | * otherwise update the specified bit in the Compare Array. | ||
1422 | * Note that the y-field will always be 0 for non-PA2.0 FPU's. | ||
1423 | */ | ||
1424 | if ((fpu_type & TIMEX_EXTEN_FLAG) || | ||
1425 | (fpu_type & ROLEX_EXTEN_FLAG) || | ||
1426 | (fpu_type & PA2_0_FPU_FLAG)) { | ||
1427 | if (y_field == 0) { | ||
1428 | *status = ((*status & 0x04000000) >> 5) | /* old Cbit */ | ||
1429 | ((*status & 0x003ff000) >> 1) | /* old CQ */ | ||
1430 | (new_status & 0xffc007ff); /* all other bits*/ | ||
1431 | } else { | ||
1432 | *status = (*status & 0x04000000) | /* old Cbit */ | ||
1433 | ((new_status & 0x04000000) >> (y_field+4)) | | ||
1434 | (new_status & ~0x04000000 & /* other bits */ | ||
1435 | ~(0x04000000 >> (y_field+4))); | ||
1436 | } | ||
1437 | } | ||
1438 | /* if PA83, just update the C-bit */ | ||
1439 | else { | ||
1440 | *status = new_status; | ||
1441 | } | ||
1442 | } | ||
diff --git a/arch/parisc/math-emu/frnd.c b/arch/parisc/math-emu/frnd.c new file mode 100644 index 000000000000..904b3844bf26 --- /dev/null +++ b/arch/parisc/math-emu/frnd.c | |||
@@ -0,0 +1,252 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * Purpose: | ||
25 | * Single Floating-point Round to Integer | ||
26 | * Double Floating-point Round to Integer | ||
27 | * Quad Floating-point Round to Integer (returns unimplemented) | ||
28 | * | ||
29 | * External Interfaces: | ||
30 | * dbl_frnd(srcptr,nullptr,dstptr,status) | ||
31 | * sgl_frnd(srcptr,nullptr,dstptr,status) | ||
32 | * | ||
33 | * END_DESC | ||
34 | */ | ||
35 | |||
36 | |||
37 | #include "float.h" | ||
38 | #include "sgl_float.h" | ||
39 | #include "dbl_float.h" | ||
40 | #include "cnv_float.h" | ||
41 | |||
42 | /* | ||
43 | * Single Floating-point Round to Integer | ||
44 | */ | ||
45 | |||
46 | /*ARGSUSED*/ | ||
47 | int | ||
48 | sgl_frnd(sgl_floating_point *srcptr, | ||
49 | unsigned int *nullptr, | ||
50 | sgl_floating_point *dstptr, | ||
51 | unsigned int *status) | ||
52 | { | ||
53 | register unsigned int src, result; | ||
54 | register int src_exponent; | ||
55 | register boolean inexact = FALSE; | ||
56 | |||
57 | src = *srcptr; | ||
58 | /* | ||
59 | * check source operand for NaN or infinity | ||
60 | */ | ||
61 | if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { | ||
62 | /* | ||
63 | * is signaling NaN? | ||
64 | */ | ||
65 | if (Sgl_isone_signaling(src)) { | ||
66 | /* trap if INVALIDTRAP enabled */ | ||
67 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
68 | /* make NaN quiet */ | ||
69 | Set_invalidflag(); | ||
70 | Sgl_set_quiet(src); | ||
71 | } | ||
72 | /* | ||
73 | * return quiet NaN or infinity | ||
74 | */ | ||
75 | *dstptr = src; | ||
76 | return(NOEXCEPTION); | ||
77 | } | ||
78 | /* | ||
79 | * Need to round? | ||
80 | */ | ||
81 | if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) { | ||
82 | *dstptr = src; | ||
83 | return(NOEXCEPTION); | ||
84 | } | ||
85 | /* | ||
86 | * Generate result | ||
87 | */ | ||
88 | if (src_exponent >= 0) { | ||
89 | Sgl_clear_exponent_set_hidden(src); | ||
90 | result = src; | ||
91 | Sgl_rightshift(result,(SGL_P-1) - (src_exponent)); | ||
92 | /* check for inexact */ | ||
93 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
94 | inexact = TRUE; | ||
95 | /* round result */ | ||
96 | switch (Rounding_mode()) { | ||
97 | case ROUNDPLUS: | ||
98 | if (Sgl_iszero_sign(src)) Sgl_increment(result); | ||
99 | break; | ||
100 | case ROUNDMINUS: | ||
101 | if (Sgl_isone_sign(src)) Sgl_increment(result); | ||
102 | break; | ||
103 | case ROUNDNEAREST: | ||
104 | if (Sgl_isone_roundbit(src,src_exponent)) | ||
105 | if (Sgl_isone_stickybit(src,src_exponent) | ||
106 | || (Sgl_isone_lowmantissa(result))) | ||
107 | Sgl_increment(result); | ||
108 | } | ||
109 | } | ||
110 | Sgl_leftshift(result,(SGL_P-1) - (src_exponent)); | ||
111 | if (Sgl_isone_hiddenoverflow(result)) | ||
112 | Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1)); | ||
113 | else Sgl_set_exponent(result,src_exponent + SGL_BIAS); | ||
114 | } | ||
115 | else { | ||
116 | result = src; /* set sign */ | ||
117 | Sgl_setzero_exponentmantissa(result); | ||
118 | /* check for inexact */ | ||
119 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
120 | inexact = TRUE; | ||
121 | /* round result */ | ||
122 | switch (Rounding_mode()) { | ||
123 | case ROUNDPLUS: | ||
124 | if (Sgl_iszero_sign(src)) | ||
125 | Sgl_set_exponent(result,SGL_BIAS); | ||
126 | break; | ||
127 | case ROUNDMINUS: | ||
128 | if (Sgl_isone_sign(src)) | ||
129 | Sgl_set_exponent(result,SGL_BIAS); | ||
130 | break; | ||
131 | case ROUNDNEAREST: | ||
132 | if (src_exponent == -1) | ||
133 | if (Sgl_isnotzero_mantissa(src)) | ||
134 | Sgl_set_exponent(result,SGL_BIAS); | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | *dstptr = result; | ||
139 | if (inexact) { | ||
140 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
141 | else Set_inexactflag(); | ||
142 | } | ||
143 | return(NOEXCEPTION); | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * Double Floating-point Round to Integer | ||
148 | */ | ||
149 | |||
150 | /*ARGSUSED*/ | ||
151 | int | ||
152 | dbl_frnd( | ||
153 | dbl_floating_point *srcptr, | ||
154 | unsigned int *nullptr, | ||
155 | dbl_floating_point *dstptr, | ||
156 | unsigned int *status) | ||
157 | { | ||
158 | register unsigned int srcp1, srcp2, resultp1, resultp2; | ||
159 | register int src_exponent; | ||
160 | register boolean inexact = FALSE; | ||
161 | |||
162 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
163 | /* | ||
164 | * check source operand for NaN or infinity | ||
165 | */ | ||
166 | if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { | ||
167 | /* | ||
168 | * is signaling NaN? | ||
169 | */ | ||
170 | if (Dbl_isone_signaling(srcp1)) { | ||
171 | /* trap if INVALIDTRAP enabled */ | ||
172 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
173 | /* make NaN quiet */ | ||
174 | Set_invalidflag(); | ||
175 | Dbl_set_quiet(srcp1); | ||
176 | } | ||
177 | /* | ||
178 | * return quiet NaN or infinity | ||
179 | */ | ||
180 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
181 | return(NOEXCEPTION); | ||
182 | } | ||
183 | /* | ||
184 | * Need to round? | ||
185 | */ | ||
186 | if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) { | ||
187 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
188 | return(NOEXCEPTION); | ||
189 | } | ||
190 | /* | ||
191 | * Generate result | ||
192 | */ | ||
193 | if (src_exponent >= 0) { | ||
194 | Dbl_clear_exponent_set_hidden(srcp1); | ||
195 | resultp1 = srcp1; | ||
196 | resultp2 = srcp2; | ||
197 | Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); | ||
198 | /* check for inexact */ | ||
199 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
200 | inexact = TRUE; | ||
201 | /* round result */ | ||
202 | switch (Rounding_mode()) { | ||
203 | case ROUNDPLUS: | ||
204 | if (Dbl_iszero_sign(srcp1)) | ||
205 | Dbl_increment(resultp1,resultp2); | ||
206 | break; | ||
207 | case ROUNDMINUS: | ||
208 | if (Dbl_isone_sign(srcp1)) | ||
209 | Dbl_increment(resultp1,resultp2); | ||
210 | break; | ||
211 | case ROUNDNEAREST: | ||
212 | if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) | ||
213 | if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) | ||
214 | || (Dbl_isone_lowmantissap2(resultp2))) | ||
215 | Dbl_increment(resultp1,resultp2); | ||
216 | } | ||
217 | } | ||
218 | Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); | ||
219 | if (Dbl_isone_hiddenoverflow(resultp1)) | ||
220 | Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1)); | ||
221 | else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS); | ||
222 | } | ||
223 | else { | ||
224 | resultp1 = srcp1; /* set sign */ | ||
225 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
226 | /* check for inexact */ | ||
227 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
228 | inexact = TRUE; | ||
229 | /* round result */ | ||
230 | switch (Rounding_mode()) { | ||
231 | case ROUNDPLUS: | ||
232 | if (Dbl_iszero_sign(srcp1)) | ||
233 | Dbl_set_exponent(resultp1,DBL_BIAS); | ||
234 | break; | ||
235 | case ROUNDMINUS: | ||
236 | if (Dbl_isone_sign(srcp1)) | ||
237 | Dbl_set_exponent(resultp1,DBL_BIAS); | ||
238 | break; | ||
239 | case ROUNDNEAREST: | ||
240 | if (src_exponent == -1) | ||
241 | if (Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
242 | Dbl_set_exponent(resultp1,DBL_BIAS); | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
247 | if (inexact) { | ||
248 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
249 | else Set_inexactflag(); | ||
250 | } | ||
251 | return(NOEXCEPTION); | ||
252 | } | ||
diff --git a/arch/parisc/math-emu/hppa.h b/arch/parisc/math-emu/hppa.h new file mode 100644 index 000000000000..5d3d52f7323a --- /dev/null +++ b/arch/parisc/math-emu/hppa.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifdef __NO_PA_HDRS | ||
23 | PA header file -- do not include this header file for non-PA builds. | ||
24 | #endif | ||
25 | |||
26 | |||
27 | /* amount is assumed to be a constant between 0 and 32 (non-inclusive) */ | ||
28 | #define Shiftdouble(left,right,amount,dest) \ | ||
29 | /* int left, right, amount, dest; */ \ | ||
30 | dest = ((left) << (32-(amount))) | ((unsigned int)(right) >> (amount)) | ||
31 | |||
32 | /* amount must be less than 32 */ | ||
33 | #define Variableshiftdouble(left,right,amount,dest) \ | ||
34 | /* unsigned int left, right; int amount, dest; */ \ | ||
35 | if (amount == 0) dest = right; \ | ||
36 | else dest = ((((unsigned) left)&0x7fffffff) << (32-(amount))) | \ | ||
37 | ((unsigned) right >> (amount)) | ||
38 | |||
39 | /* amount must be between 0 and 32 (non-inclusive) */ | ||
40 | #define Variable_shift_double(left,right,amount,dest) \ | ||
41 | /* unsigned int left, right; int amount, dest; */ \ | ||
42 | dest = (left << (32-(amount))) | ((unsigned) right >> (amount)) | ||
diff --git a/arch/parisc/math-emu/math-emu.h b/arch/parisc/math-emu/math-emu.h new file mode 100644 index 000000000000..3a99f5929291 --- /dev/null +++ b/arch/parisc/math-emu/math-emu.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | #ifndef _PARISC_MATH_EMU_H | ||
22 | #define _PARISC_MATH_EMU_H | ||
23 | |||
24 | #include <asm/ptrace.h> | ||
25 | extern int handle_fpe(struct pt_regs *regs); | ||
26 | |||
27 | #endif | ||
diff --git a/arch/parisc/math-emu/sfadd.c b/arch/parisc/math-emu/sfadd.c new file mode 100644 index 000000000000..008d721b5d22 --- /dev/null +++ b/arch/parisc/math-emu/sfadd.c | |||
@@ -0,0 +1,518 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/sfadd.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single_add: add two single precision values. | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * sgl_fadd(leftptr, rightptr, dstptr, status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "sgl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Single_add: add two single precision values. | ||
47 | */ | ||
48 | int | ||
49 | sgl_fadd( | ||
50 | sgl_floating_point *leftptr, | ||
51 | sgl_floating_point *rightptr, | ||
52 | sgl_floating_point *dstptr, | ||
53 | unsigned int *status) | ||
54 | { | ||
55 | register unsigned int left, right, result, extent; | ||
56 | register unsigned int signless_upper_left, signless_upper_right, save; | ||
57 | |||
58 | |||
59 | register int result_exponent, right_exponent, diff_exponent; | ||
60 | register int sign_save, jumpsize; | ||
61 | register boolean inexact = FALSE; | ||
62 | register boolean underflowtrap; | ||
63 | |||
64 | /* Create local copies of the numbers */ | ||
65 | left = *leftptr; | ||
66 | right = *rightptr; | ||
67 | |||
68 | /* A zero "save" helps discover equal operands (for later), * | ||
69 | * and is used in swapping operands (if needed). */ | ||
70 | Sgl_xortointp1(left,right,/*to*/save); | ||
71 | |||
72 | /* | ||
73 | * check first operand for NaN's or infinity | ||
74 | */ | ||
75 | if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT) | ||
76 | { | ||
77 | if (Sgl_iszero_mantissa(left)) | ||
78 | { | ||
79 | if (Sgl_isnotnan(right)) | ||
80 | { | ||
81 | if (Sgl_isinfinity(right) && save!=0) | ||
82 | { | ||
83 | /* | ||
84 | * invalid since operands are opposite signed infinity's | ||
85 | */ | ||
86 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
87 | Set_invalidflag(); | ||
88 | Sgl_makequietnan(result); | ||
89 | *dstptr = result; | ||
90 | return(NOEXCEPTION); | ||
91 | } | ||
92 | /* | ||
93 | * return infinity | ||
94 | */ | ||
95 | *dstptr = left; | ||
96 | return(NOEXCEPTION); | ||
97 | } | ||
98 | } | ||
99 | else | ||
100 | { | ||
101 | /* | ||
102 | * is NaN; signaling or quiet? | ||
103 | */ | ||
104 | if (Sgl_isone_signaling(left)) | ||
105 | { | ||
106 | /* trap if INVALIDTRAP enabled */ | ||
107 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
108 | /* make NaN quiet */ | ||
109 | Set_invalidflag(); | ||
110 | Sgl_set_quiet(left); | ||
111 | } | ||
112 | /* | ||
113 | * is second operand a signaling NaN? | ||
114 | */ | ||
115 | else if (Sgl_is_signalingnan(right)) | ||
116 | { | ||
117 | /* trap if INVALIDTRAP enabled */ | ||
118 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
119 | /* make NaN quiet */ | ||
120 | Set_invalidflag(); | ||
121 | Sgl_set_quiet(right); | ||
122 | *dstptr = right; | ||
123 | return(NOEXCEPTION); | ||
124 | } | ||
125 | /* | ||
126 | * return quiet NaN | ||
127 | */ | ||
128 | *dstptr = left; | ||
129 | return(NOEXCEPTION); | ||
130 | } | ||
131 | } /* End left NaN or Infinity processing */ | ||
132 | /* | ||
133 | * check second operand for NaN's or infinity | ||
134 | */ | ||
135 | if (Sgl_isinfinity_exponent(right)) | ||
136 | { | ||
137 | if (Sgl_iszero_mantissa(right)) | ||
138 | { | ||
139 | /* return infinity */ | ||
140 | *dstptr = right; | ||
141 | return(NOEXCEPTION); | ||
142 | } | ||
143 | /* | ||
144 | * is NaN; signaling or quiet? | ||
145 | */ | ||
146 | if (Sgl_isone_signaling(right)) | ||
147 | { | ||
148 | /* trap if INVALIDTRAP enabled */ | ||
149 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
150 | /* make NaN quiet */ | ||
151 | Set_invalidflag(); | ||
152 | Sgl_set_quiet(right); | ||
153 | } | ||
154 | /* | ||
155 | * return quiet NaN | ||
156 | */ | ||
157 | *dstptr = right; | ||
158 | return(NOEXCEPTION); | ||
159 | } /* End right NaN or Infinity processing */ | ||
160 | |||
161 | /* Invariant: Must be dealing with finite numbers */ | ||
162 | |||
163 | /* Compare operands by removing the sign */ | ||
164 | Sgl_copytoint_exponentmantissa(left,signless_upper_left); | ||
165 | Sgl_copytoint_exponentmantissa(right,signless_upper_right); | ||
166 | |||
167 | /* sign difference selects add or sub operation. */ | ||
168 | if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right)) | ||
169 | { | ||
170 | /* Set the left operand to the larger one by XOR swap * | ||
171 | * First finish the first word using "save" */ | ||
172 | Sgl_xorfromintp1(save,right,/*to*/right); | ||
173 | Sgl_xorfromintp1(save,left,/*to*/left); | ||
174 | result_exponent = Sgl_exponent(left); | ||
175 | } | ||
176 | /* Invariant: left is not smaller than right. */ | ||
177 | |||
178 | if((right_exponent = Sgl_exponent(right)) == 0) | ||
179 | { | ||
180 | /* Denormalized operands. First look for zeroes */ | ||
181 | if(Sgl_iszero_mantissa(right)) | ||
182 | { | ||
183 | /* right is zero */ | ||
184 | if(Sgl_iszero_exponentmantissa(left)) | ||
185 | { | ||
186 | /* Both operands are zeros */ | ||
187 | if(Is_rounding_mode(ROUNDMINUS)) | ||
188 | { | ||
189 | Sgl_or_signs(left,/*with*/right); | ||
190 | } | ||
191 | else | ||
192 | { | ||
193 | Sgl_and_signs(left,/*with*/right); | ||
194 | } | ||
195 | } | ||
196 | else | ||
197 | { | ||
198 | /* Left is not a zero and must be the result. Trapped | ||
199 | * underflows are signaled if left is denormalized. Result | ||
200 | * is always exact. */ | ||
201 | if( (result_exponent == 0) && Is_underflowtrap_enabled() ) | ||
202 | { | ||
203 | /* need to normalize results mantissa */ | ||
204 | sign_save = Sgl_signextendedsign(left); | ||
205 | Sgl_leftshiftby1(left); | ||
206 | Sgl_normalize(left,result_exponent); | ||
207 | Sgl_set_sign(left,/*using*/sign_save); | ||
208 | Sgl_setwrapped_exponent(left,result_exponent,unfl); | ||
209 | *dstptr = left; | ||
210 | return(UNDERFLOWEXCEPTION); | ||
211 | } | ||
212 | } | ||
213 | *dstptr = left; | ||
214 | return(NOEXCEPTION); | ||
215 | } | ||
216 | |||
217 | /* Neither are zeroes */ | ||
218 | Sgl_clear_sign(right); /* Exponent is already cleared */ | ||
219 | if(result_exponent == 0 ) | ||
220 | { | ||
221 | /* Both operands are denormalized. The result must be exact | ||
222 | * and is simply calculated. A sum could become normalized and a | ||
223 | * difference could cancel to a true zero. */ | ||
224 | if( (/*signed*/int) save < 0 ) | ||
225 | { | ||
226 | Sgl_subtract(left,/*minus*/right,/*into*/result); | ||
227 | if(Sgl_iszero_mantissa(result)) | ||
228 | { | ||
229 | if(Is_rounding_mode(ROUNDMINUS)) | ||
230 | { | ||
231 | Sgl_setone_sign(result); | ||
232 | } | ||
233 | else | ||
234 | { | ||
235 | Sgl_setzero_sign(result); | ||
236 | } | ||
237 | *dstptr = result; | ||
238 | return(NOEXCEPTION); | ||
239 | } | ||
240 | } | ||
241 | else | ||
242 | { | ||
243 | Sgl_addition(left,right,/*into*/result); | ||
244 | if(Sgl_isone_hidden(result)) | ||
245 | { | ||
246 | *dstptr = result; | ||
247 | return(NOEXCEPTION); | ||
248 | } | ||
249 | } | ||
250 | if(Is_underflowtrap_enabled()) | ||
251 | { | ||
252 | /* need to normalize result */ | ||
253 | sign_save = Sgl_signextendedsign(result); | ||
254 | Sgl_leftshiftby1(result); | ||
255 | Sgl_normalize(result,result_exponent); | ||
256 | Sgl_set_sign(result,/*using*/sign_save); | ||
257 | Sgl_setwrapped_exponent(result,result_exponent,unfl); | ||
258 | *dstptr = result; | ||
259 | return(UNDERFLOWEXCEPTION); | ||
260 | } | ||
261 | *dstptr = result; | ||
262 | return(NOEXCEPTION); | ||
263 | } | ||
264 | right_exponent = 1; /* Set exponent to reflect different bias | ||
265 | * with denomalized numbers. */ | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | Sgl_clear_signexponent_set_hidden(right); | ||
270 | } | ||
271 | Sgl_clear_exponent_set_hidden(left); | ||
272 | diff_exponent = result_exponent - right_exponent; | ||
273 | |||
274 | /* | ||
275 | * Special case alignment of operands that would force alignment | ||
276 | * beyond the extent of the extension. A further optimization | ||
277 | * could special case this but only reduces the path length for this | ||
278 | * infrequent case. | ||
279 | */ | ||
280 | if(diff_exponent > SGL_THRESHOLD) | ||
281 | { | ||
282 | diff_exponent = SGL_THRESHOLD; | ||
283 | } | ||
284 | |||
285 | /* Align right operand by shifting to right */ | ||
286 | Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent, | ||
287 | /*and lower to*/extent); | ||
288 | |||
289 | /* Treat sum and difference of the operands separately. */ | ||
290 | if( (/*signed*/int) save < 0 ) | ||
291 | { | ||
292 | /* | ||
293 | * Difference of the two operands. Their can be no overflow. A | ||
294 | * borrow can occur out of the hidden bit and force a post | ||
295 | * normalization phase. | ||
296 | */ | ||
297 | Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result); | ||
298 | if(Sgl_iszero_hidden(result)) | ||
299 | { | ||
300 | /* Handle normalization */ | ||
301 | /* A straight foward algorithm would now shift the result | ||
302 | * and extension left until the hidden bit becomes one. Not | ||
303 | * all of the extension bits need participate in the shift. | ||
304 | * Only the two most significant bits (round and guard) are | ||
305 | * needed. If only a single shift is needed then the guard | ||
306 | * bit becomes a significant low order bit and the extension | ||
307 | * must participate in the rounding. If more than a single | ||
308 | * shift is needed, then all bits to the right of the guard | ||
309 | * bit are zeros, and the guard bit may or may not be zero. */ | ||
310 | sign_save = Sgl_signextendedsign(result); | ||
311 | Sgl_leftshiftby1_withextent(result,extent,result); | ||
312 | |||
313 | /* Need to check for a zero result. The sign and exponent | ||
314 | * fields have already been zeroed. The more efficient test | ||
315 | * of the full object can be used. | ||
316 | */ | ||
317 | if(Sgl_iszero(result)) | ||
318 | /* Must have been "x-x" or "x+(-x)". */ | ||
319 | { | ||
320 | if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result); | ||
321 | *dstptr = result; | ||
322 | return(NOEXCEPTION); | ||
323 | } | ||
324 | result_exponent--; | ||
325 | /* Look to see if normalization is finished. */ | ||
326 | if(Sgl_isone_hidden(result)) | ||
327 | { | ||
328 | if(result_exponent==0) | ||
329 | { | ||
330 | /* Denormalized, exponent should be zero. Left operand * | ||
331 | * was normalized, so extent (guard, round) was zero */ | ||
332 | goto underflow; | ||
333 | } | ||
334 | else | ||
335 | { | ||
336 | /* No further normalization is needed. */ | ||
337 | Sgl_set_sign(result,/*using*/sign_save); | ||
338 | Ext_leftshiftby1(extent); | ||
339 | goto round; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | /* Check for denormalized, exponent should be zero. Left * | ||
344 | * operand was normalized, so extent (guard, round) was zero */ | ||
345 | if(!(underflowtrap = Is_underflowtrap_enabled()) && | ||
346 | result_exponent==0) goto underflow; | ||
347 | |||
348 | /* Shift extension to complete one bit of normalization and | ||
349 | * update exponent. */ | ||
350 | Ext_leftshiftby1(extent); | ||
351 | |||
352 | /* Discover first one bit to determine shift amount. Use a | ||
353 | * modified binary search. We have already shifted the result | ||
354 | * one position right and still not found a one so the remainder | ||
355 | * of the extension must be zero and simplifies rounding. */ | ||
356 | /* Scan bytes */ | ||
357 | while(Sgl_iszero_hiddenhigh7mantissa(result)) | ||
358 | { | ||
359 | Sgl_leftshiftby8(result); | ||
360 | if((result_exponent -= 8) <= 0 && !underflowtrap) | ||
361 | goto underflow; | ||
362 | } | ||
363 | /* Now narrow it down to the nibble */ | ||
364 | if(Sgl_iszero_hiddenhigh3mantissa(result)) | ||
365 | { | ||
366 | /* The lower nibble contains the normalizing one */ | ||
367 | Sgl_leftshiftby4(result); | ||
368 | if((result_exponent -= 4) <= 0 && !underflowtrap) | ||
369 | goto underflow; | ||
370 | } | ||
371 | /* Select case were first bit is set (already normalized) | ||
372 | * otherwise select the proper shift. */ | ||
373 | if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7) | ||
374 | { | ||
375 | /* Already normalized */ | ||
376 | if(result_exponent <= 0) goto underflow; | ||
377 | Sgl_set_sign(result,/*using*/sign_save); | ||
378 | Sgl_set_exponent(result,/*using*/result_exponent); | ||
379 | *dstptr = result; | ||
380 | return(NOEXCEPTION); | ||
381 | } | ||
382 | Sgl_sethigh4bits(result,/*using*/sign_save); | ||
383 | switch(jumpsize) | ||
384 | { | ||
385 | case 1: | ||
386 | { | ||
387 | Sgl_leftshiftby3(result); | ||
388 | result_exponent -= 3; | ||
389 | break; | ||
390 | } | ||
391 | case 2: | ||
392 | case 3: | ||
393 | { | ||
394 | Sgl_leftshiftby2(result); | ||
395 | result_exponent -= 2; | ||
396 | break; | ||
397 | } | ||
398 | case 4: | ||
399 | case 5: | ||
400 | case 6: | ||
401 | case 7: | ||
402 | { | ||
403 | Sgl_leftshiftby1(result); | ||
404 | result_exponent -= 1; | ||
405 | break; | ||
406 | } | ||
407 | } | ||
408 | if(result_exponent > 0) | ||
409 | { | ||
410 | Sgl_set_exponent(result,/*using*/result_exponent); | ||
411 | *dstptr = result; | ||
412 | return(NOEXCEPTION); /* Sign bit is already set */ | ||
413 | } | ||
414 | /* Fixup potential underflows */ | ||
415 | underflow: | ||
416 | if(Is_underflowtrap_enabled()) | ||
417 | { | ||
418 | Sgl_set_sign(result,sign_save); | ||
419 | Sgl_setwrapped_exponent(result,result_exponent,unfl); | ||
420 | *dstptr = result; | ||
421 | /* inexact = FALSE; */ | ||
422 | return(UNDERFLOWEXCEPTION); | ||
423 | } | ||
424 | /* | ||
425 | * Since we cannot get an inexact denormalized result, | ||
426 | * we can now return. | ||
427 | */ | ||
428 | Sgl_right_align(result,/*by*/(1-result_exponent),extent); | ||
429 | Sgl_clear_signexponent(result); | ||
430 | Sgl_set_sign(result,sign_save); | ||
431 | *dstptr = result; | ||
432 | return(NOEXCEPTION); | ||
433 | } /* end if(hidden...)... */ | ||
434 | /* Fall through and round */ | ||
435 | } /* end if(save < 0)... */ | ||
436 | else | ||
437 | { | ||
438 | /* Add magnitudes */ | ||
439 | Sgl_addition(left,right,/*to*/result); | ||
440 | if(Sgl_isone_hiddenoverflow(result)) | ||
441 | { | ||
442 | /* Prenormalization required. */ | ||
443 | Sgl_rightshiftby1_withextent(result,extent,extent); | ||
444 | Sgl_arithrightshiftby1(result); | ||
445 | result_exponent++; | ||
446 | } /* end if hiddenoverflow... */ | ||
447 | } /* end else ...add magnitudes... */ | ||
448 | |||
449 | /* Round the result. If the extension is all zeros,then the result is | ||
450 | * exact. Otherwise round in the correct direction. No underflow is | ||
451 | * possible. If a postnormalization is necessary, then the mantissa is | ||
452 | * all zeros so no shift is needed. */ | ||
453 | round: | ||
454 | if(Ext_isnotzero(extent)) | ||
455 | { | ||
456 | inexact = TRUE; | ||
457 | switch(Rounding_mode()) | ||
458 | { | ||
459 | case ROUNDNEAREST: /* The default. */ | ||
460 | if(Ext_isone_sign(extent)) | ||
461 | { | ||
462 | /* at least 1/2 ulp */ | ||
463 | if(Ext_isnotzero_lower(extent) || | ||
464 | Sgl_isone_lowmantissa(result)) | ||
465 | { | ||
466 | /* either exactly half way and odd or more than 1/2ulp */ | ||
467 | Sgl_increment(result); | ||
468 | } | ||
469 | } | ||
470 | break; | ||
471 | |||
472 | case ROUNDPLUS: | ||
473 | if(Sgl_iszero_sign(result)) | ||
474 | { | ||
475 | /* Round up positive results */ | ||
476 | Sgl_increment(result); | ||
477 | } | ||
478 | break; | ||
479 | |||
480 | case ROUNDMINUS: | ||
481 | if(Sgl_isone_sign(result)) | ||
482 | { | ||
483 | /* Round down negative results */ | ||
484 | Sgl_increment(result); | ||
485 | } | ||
486 | |||
487 | case ROUNDZERO:; | ||
488 | /* truncate is simple */ | ||
489 | } /* end switch... */ | ||
490 | if(Sgl_isone_hiddenoverflow(result)) result_exponent++; | ||
491 | } | ||
492 | if(result_exponent == SGL_INFINITY_EXPONENT) | ||
493 | { | ||
494 | /* Overflow */ | ||
495 | if(Is_overflowtrap_enabled()) | ||
496 | { | ||
497 | Sgl_setwrapped_exponent(result,result_exponent,ovfl); | ||
498 | *dstptr = result; | ||
499 | if (inexact) | ||
500 | if (Is_inexacttrap_enabled()) | ||
501 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
502 | else Set_inexactflag(); | ||
503 | return(OVERFLOWEXCEPTION); | ||
504 | } | ||
505 | else | ||
506 | { | ||
507 | Set_overflowflag(); | ||
508 | inexact = TRUE; | ||
509 | Sgl_setoverflow(result); | ||
510 | } | ||
511 | } | ||
512 | else Sgl_set_exponent(result,result_exponent); | ||
513 | *dstptr = result; | ||
514 | if(inexact) | ||
515 | if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
516 | else Set_inexactflag(); | ||
517 | return(NOEXCEPTION); | ||
518 | } | ||
diff --git a/arch/parisc/math-emu/sfcmp.c b/arch/parisc/math-emu/sfcmp.c new file mode 100644 index 000000000000..1466fb46e4c0 --- /dev/null +++ b/arch/parisc/math-emu/sfcmp.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/sfcmp.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * sgl_cmp: compare two values | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * sgl_fcmp(leftptr, rightptr, cond, status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "sgl_float.h" | ||
44 | |||
45 | /* | ||
46 | * sgl_cmp: compare two values | ||
47 | */ | ||
48 | int | ||
49 | sgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr, | ||
50 | unsigned int cond, unsigned int *status) | ||
51 | |||
52 | /* The predicate to be tested */ | ||
53 | |||
54 | { | ||
55 | register unsigned int left, right; | ||
56 | register int xorresult; | ||
57 | |||
58 | /* Create local copies of the numbers */ | ||
59 | left = *leftptr; | ||
60 | right = *rightptr; | ||
61 | |||
62 | /* | ||
63 | * Test for NaN | ||
64 | */ | ||
65 | if( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT) | ||
66 | || (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) ) | ||
67 | { | ||
68 | /* Check if a NaN is involved. Signal an invalid exception when | ||
69 | * comparing a signaling NaN or when comparing quiet NaNs and the | ||
70 | * low bit of the condition is set */ | ||
71 | if( ( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT) | ||
72 | && Sgl_isnotzero_mantissa(left) | ||
73 | && (Exception(cond) || Sgl_isone_signaling(left))) | ||
74 | || | ||
75 | ( (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) | ||
76 | && Sgl_isnotzero_mantissa(right) | ||
77 | && (Exception(cond) || Sgl_isone_signaling(right)) ) ) | ||
78 | { | ||
79 | if( Is_invalidtrap_enabled() ) { | ||
80 | Set_status_cbit(Unordered(cond)); | ||
81 | return(INVALIDEXCEPTION); | ||
82 | } | ||
83 | else Set_invalidflag(); | ||
84 | Set_status_cbit(Unordered(cond)); | ||
85 | return(NOEXCEPTION); | ||
86 | } | ||
87 | /* All the exceptional conditions are handled, now special case | ||
88 | NaN compares */ | ||
89 | else if( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT) | ||
90 | && Sgl_isnotzero_mantissa(left)) | ||
91 | || | ||
92 | ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT) | ||
93 | && Sgl_isnotzero_mantissa(right)) ) | ||
94 | { | ||
95 | /* NaNs always compare unordered. */ | ||
96 | Set_status_cbit(Unordered(cond)); | ||
97 | return(NOEXCEPTION); | ||
98 | } | ||
99 | /* infinities will drop down to the normal compare mechanisms */ | ||
100 | } | ||
101 | /* First compare for unequal signs => less or greater or | ||
102 | * special equal case */ | ||
103 | Sgl_xortointp1(left,right,xorresult); | ||
104 | if( xorresult < 0 ) | ||
105 | { | ||
106 | /* left negative => less, left positive => greater. | ||
107 | * equal is possible if both operands are zeros. */ | ||
108 | if( Sgl_iszero_exponentmantissa(left) | ||
109 | && Sgl_iszero_exponentmantissa(right) ) | ||
110 | { | ||
111 | Set_status_cbit(Equal(cond)); | ||
112 | } | ||
113 | else if( Sgl_isone_sign(left) ) | ||
114 | { | ||
115 | Set_status_cbit(Lessthan(cond)); | ||
116 | } | ||
117 | else | ||
118 | { | ||
119 | Set_status_cbit(Greaterthan(cond)); | ||
120 | } | ||
121 | } | ||
122 | /* Signs are the same. Treat negative numbers separately | ||
123 | * from the positives because of the reversed sense. */ | ||
124 | else if( Sgl_all(left) == Sgl_all(right) ) | ||
125 | { | ||
126 | Set_status_cbit(Equal(cond)); | ||
127 | } | ||
128 | else if( Sgl_iszero_sign(left) ) | ||
129 | { | ||
130 | /* Positive compare */ | ||
131 | if( Sgl_all(left) < Sgl_all(right) ) | ||
132 | { | ||
133 | Set_status_cbit(Lessthan(cond)); | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | Set_status_cbit(Greaterthan(cond)); | ||
138 | } | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | /* Negative compare. Signed or unsigned compares | ||
143 | * both work the same. That distinction is only | ||
144 | * important when the sign bits differ. */ | ||
145 | if( Sgl_all(left) > Sgl_all(right) ) | ||
146 | { | ||
147 | Set_status_cbit(Lessthan(cond)); | ||
148 | } | ||
149 | else | ||
150 | { | ||
151 | Set_status_cbit(Greaterthan(cond)); | ||
152 | } | ||
153 | } | ||
154 | return(NOEXCEPTION); | ||
155 | } | ||
diff --git a/arch/parisc/math-emu/sfdiv.c b/arch/parisc/math-emu/sfdiv.c new file mode 100644 index 000000000000..3e2a4d6daa9c --- /dev/null +++ b/arch/parisc/math-emu/sfdiv.c | |||
@@ -0,0 +1,392 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/sfdiv.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single Precision Floating-point Divide | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * sgl_fdiv(srcptr1,srcptr2,dstptr,status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "sgl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Single Precision Floating-point Divide | ||
47 | */ | ||
48 | |||
49 | int | ||
50 | sgl_fdiv (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2, | ||
51 | sgl_floating_point * dstptr, unsigned int *status) | ||
52 | { | ||
53 | register unsigned int opnd1, opnd2, opnd3, result; | ||
54 | register int dest_exponent, count; | ||
55 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
56 | boolean is_tiny; | ||
57 | |||
58 | opnd1 = *srcptr1; | ||
59 | opnd2 = *srcptr2; | ||
60 | /* | ||
61 | * set sign bit of result | ||
62 | */ | ||
63 | if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result); | ||
64 | else Sgl_setzero(result); | ||
65 | /* | ||
66 | * check first operand for NaN's or infinity | ||
67 | */ | ||
68 | if (Sgl_isinfinity_exponent(opnd1)) { | ||
69 | if (Sgl_iszero_mantissa(opnd1)) { | ||
70 | if (Sgl_isnotnan(opnd2)) { | ||
71 | if (Sgl_isinfinity(opnd2)) { | ||
72 | /* | ||
73 | * invalid since both operands | ||
74 | * are infinity | ||
75 | */ | ||
76 | if (Is_invalidtrap_enabled()) | ||
77 | return(INVALIDEXCEPTION); | ||
78 | Set_invalidflag(); | ||
79 | Sgl_makequietnan(result); | ||
80 | *dstptr = result; | ||
81 | return(NOEXCEPTION); | ||
82 | } | ||
83 | /* | ||
84 | * return infinity | ||
85 | */ | ||
86 | Sgl_setinfinity_exponentmantissa(result); | ||
87 | *dstptr = result; | ||
88 | return(NOEXCEPTION); | ||
89 | } | ||
90 | } | ||
91 | else { | ||
92 | /* | ||
93 | * is NaN; signaling or quiet? | ||
94 | */ | ||
95 | if (Sgl_isone_signaling(opnd1)) { | ||
96 | /* trap if INVALIDTRAP enabled */ | ||
97 | if (Is_invalidtrap_enabled()) | ||
98 | return(INVALIDEXCEPTION); | ||
99 | /* make NaN quiet */ | ||
100 | Set_invalidflag(); | ||
101 | Sgl_set_quiet(opnd1); | ||
102 | } | ||
103 | /* | ||
104 | * is second operand a signaling NaN? | ||
105 | */ | ||
106 | else if (Sgl_is_signalingnan(opnd2)) { | ||
107 | /* trap if INVALIDTRAP enabled */ | ||
108 | if (Is_invalidtrap_enabled()) | ||
109 | return(INVALIDEXCEPTION); | ||
110 | /* make NaN quiet */ | ||
111 | Set_invalidflag(); | ||
112 | Sgl_set_quiet(opnd2); | ||
113 | *dstptr = opnd2; | ||
114 | return(NOEXCEPTION); | ||
115 | } | ||
116 | /* | ||
117 | * return quiet NaN | ||
118 | */ | ||
119 | *dstptr = opnd1; | ||
120 | return(NOEXCEPTION); | ||
121 | } | ||
122 | } | ||
123 | /* | ||
124 | * check second operand for NaN's or infinity | ||
125 | */ | ||
126 | if (Sgl_isinfinity_exponent(opnd2)) { | ||
127 | if (Sgl_iszero_mantissa(opnd2)) { | ||
128 | /* | ||
129 | * return zero | ||
130 | */ | ||
131 | Sgl_setzero_exponentmantissa(result); | ||
132 | *dstptr = result; | ||
133 | return(NOEXCEPTION); | ||
134 | } | ||
135 | /* | ||
136 | * is NaN; signaling or quiet? | ||
137 | */ | ||
138 | if (Sgl_isone_signaling(opnd2)) { | ||
139 | /* trap if INVALIDTRAP enabled */ | ||
140 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
141 | /* make NaN quiet */ | ||
142 | Set_invalidflag(); | ||
143 | Sgl_set_quiet(opnd2); | ||
144 | } | ||
145 | /* | ||
146 | * return quiet NaN | ||
147 | */ | ||
148 | *dstptr = opnd2; | ||
149 | return(NOEXCEPTION); | ||
150 | } | ||
151 | /* | ||
152 | * check for division by zero | ||
153 | */ | ||
154 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
155 | if (Sgl_iszero_exponentmantissa(opnd1)) { | ||
156 | /* invalid since both operands are zero */ | ||
157 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
158 | Set_invalidflag(); | ||
159 | Sgl_makequietnan(result); | ||
160 | *dstptr = result; | ||
161 | return(NOEXCEPTION); | ||
162 | } | ||
163 | if (Is_divisionbyzerotrap_enabled()) | ||
164 | return(DIVISIONBYZEROEXCEPTION); | ||
165 | Set_divisionbyzeroflag(); | ||
166 | Sgl_setinfinity_exponentmantissa(result); | ||
167 | *dstptr = result; | ||
168 | return(NOEXCEPTION); | ||
169 | } | ||
170 | /* | ||
171 | * Generate exponent | ||
172 | */ | ||
173 | dest_exponent = Sgl_exponent(opnd1) - Sgl_exponent(opnd2) + SGL_BIAS; | ||
174 | |||
175 | /* | ||
176 | * Generate mantissa | ||
177 | */ | ||
178 | if (Sgl_isnotzero_exponent(opnd1)) { | ||
179 | /* set hidden bit */ | ||
180 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
181 | } | ||
182 | else { | ||
183 | /* check for zero */ | ||
184 | if (Sgl_iszero_mantissa(opnd1)) { | ||
185 | Sgl_setzero_exponentmantissa(result); | ||
186 | *dstptr = result; | ||
187 | return(NOEXCEPTION); | ||
188 | } | ||
189 | /* is denormalized; want to normalize */ | ||
190 | Sgl_clear_signexponent(opnd1); | ||
191 | Sgl_leftshiftby1(opnd1); | ||
192 | Sgl_normalize(opnd1,dest_exponent); | ||
193 | } | ||
194 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
195 | if (Sgl_isnotzero_exponent(opnd2)) { | ||
196 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
197 | } | ||
198 | else { | ||
199 | /* is denormalized; want to normalize */ | ||
200 | Sgl_clear_signexponent(opnd2); | ||
201 | Sgl_leftshiftby1(opnd2); | ||
202 | while(Sgl_iszero_hiddenhigh7mantissa(opnd2)) { | ||
203 | Sgl_leftshiftby8(opnd2); | ||
204 | dest_exponent += 8; | ||
205 | } | ||
206 | if(Sgl_iszero_hiddenhigh3mantissa(opnd2)) { | ||
207 | Sgl_leftshiftby4(opnd2); | ||
208 | dest_exponent += 4; | ||
209 | } | ||
210 | while(Sgl_iszero_hidden(opnd2)) { | ||
211 | Sgl_leftshiftby1(opnd2); | ||
212 | dest_exponent += 1; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | /* Divide the source mantissas */ | ||
217 | |||
218 | /* | ||
219 | * A non_restoring divide algorithm is used. | ||
220 | */ | ||
221 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
222 | Sgl_setzero(opnd3); | ||
223 | for (count=1;count<=SGL_P && Sgl_all(opnd1);count++) { | ||
224 | Sgl_leftshiftby1(opnd1); | ||
225 | Sgl_leftshiftby1(opnd3); | ||
226 | if (Sgl_iszero_sign(opnd1)) { | ||
227 | Sgl_setone_lowmantissa(opnd3); | ||
228 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
229 | } | ||
230 | else Sgl_addition(opnd1,opnd2,opnd1); | ||
231 | } | ||
232 | if (count <= SGL_P) { | ||
233 | Sgl_leftshiftby1(opnd3); | ||
234 | Sgl_setone_lowmantissa(opnd3); | ||
235 | Sgl_leftshift(opnd3,SGL_P-count); | ||
236 | if (Sgl_iszero_hidden(opnd3)) { | ||
237 | Sgl_leftshiftby1(opnd3); | ||
238 | dest_exponent--; | ||
239 | } | ||
240 | } | ||
241 | else { | ||
242 | if (Sgl_iszero_hidden(opnd3)) { | ||
243 | /* need to get one more bit of result */ | ||
244 | Sgl_leftshiftby1(opnd1); | ||
245 | Sgl_leftshiftby1(opnd3); | ||
246 | if (Sgl_iszero_sign(opnd1)) { | ||
247 | Sgl_setone_lowmantissa(opnd3); | ||
248 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
249 | } | ||
250 | else Sgl_addition(opnd1,opnd2,opnd1); | ||
251 | dest_exponent--; | ||
252 | } | ||
253 | if (Sgl_iszero_sign(opnd1)) guardbit = TRUE; | ||
254 | stickybit = Sgl_all(opnd1); | ||
255 | } | ||
256 | inexact = guardbit | stickybit; | ||
257 | |||
258 | /* | ||
259 | * round result | ||
260 | */ | ||
261 | if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) { | ||
262 | Sgl_clear_signexponent(opnd3); | ||
263 | switch (Rounding_mode()) { | ||
264 | case ROUNDPLUS: | ||
265 | if (Sgl_iszero_sign(result)) | ||
266 | Sgl_increment_mantissa(opnd3); | ||
267 | break; | ||
268 | case ROUNDMINUS: | ||
269 | if (Sgl_isone_sign(result)) | ||
270 | Sgl_increment_mantissa(opnd3); | ||
271 | break; | ||
272 | case ROUNDNEAREST: | ||
273 | if (guardbit) { | ||
274 | if (stickybit || Sgl_isone_lowmantissa(opnd3)) | ||
275 | Sgl_increment_mantissa(opnd3); | ||
276 | } | ||
277 | } | ||
278 | if (Sgl_isone_hidden(opnd3)) dest_exponent++; | ||
279 | } | ||
280 | Sgl_set_mantissa(result,opnd3); | ||
281 | |||
282 | /* | ||
283 | * Test for overflow | ||
284 | */ | ||
285 | if (dest_exponent >= SGL_INFINITY_EXPONENT) { | ||
286 | /* trap if OVERFLOWTRAP enabled */ | ||
287 | if (Is_overflowtrap_enabled()) { | ||
288 | /* | ||
289 | * Adjust bias of result | ||
290 | */ | ||
291 | Sgl_setwrapped_exponent(result,dest_exponent,ovfl); | ||
292 | *dstptr = result; | ||
293 | if (inexact) | ||
294 | if (Is_inexacttrap_enabled()) | ||
295 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
296 | else Set_inexactflag(); | ||
297 | return(OVERFLOWEXCEPTION); | ||
298 | } | ||
299 | Set_overflowflag(); | ||
300 | /* set result to infinity or largest number */ | ||
301 | Sgl_setoverflow(result); | ||
302 | inexact = TRUE; | ||
303 | } | ||
304 | /* | ||
305 | * Test for underflow | ||
306 | */ | ||
307 | else if (dest_exponent <= 0) { | ||
308 | /* trap if UNDERFLOWTRAP enabled */ | ||
309 | if (Is_underflowtrap_enabled()) { | ||
310 | /* | ||
311 | * Adjust bias of result | ||
312 | */ | ||
313 | Sgl_setwrapped_exponent(result,dest_exponent,unfl); | ||
314 | *dstptr = result; | ||
315 | if (inexact) | ||
316 | if (Is_inexacttrap_enabled()) | ||
317 | return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
318 | else Set_inexactflag(); | ||
319 | return(UNDERFLOWEXCEPTION); | ||
320 | } | ||
321 | |||
322 | /* Determine if should set underflow flag */ | ||
323 | is_tiny = TRUE; | ||
324 | if (dest_exponent == 0 && inexact) { | ||
325 | switch (Rounding_mode()) { | ||
326 | case ROUNDPLUS: | ||
327 | if (Sgl_iszero_sign(result)) { | ||
328 | Sgl_increment(opnd3); | ||
329 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
330 | is_tiny = FALSE; | ||
331 | Sgl_decrement(opnd3); | ||
332 | } | ||
333 | break; | ||
334 | case ROUNDMINUS: | ||
335 | if (Sgl_isone_sign(result)) { | ||
336 | Sgl_increment(opnd3); | ||
337 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
338 | is_tiny = FALSE; | ||
339 | Sgl_decrement(opnd3); | ||
340 | } | ||
341 | break; | ||
342 | case ROUNDNEAREST: | ||
343 | if (guardbit && (stickybit || | ||
344 | Sgl_isone_lowmantissa(opnd3))) { | ||
345 | Sgl_increment(opnd3); | ||
346 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
347 | is_tiny = FALSE; | ||
348 | Sgl_decrement(opnd3); | ||
349 | } | ||
350 | break; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * denormalize result or set to signed zero | ||
356 | */ | ||
357 | stickybit = inexact; | ||
358 | Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact); | ||
359 | |||
360 | /* return rounded number */ | ||
361 | if (inexact) { | ||
362 | switch (Rounding_mode()) { | ||
363 | case ROUNDPLUS: | ||
364 | if (Sgl_iszero_sign(result)) { | ||
365 | Sgl_increment(opnd3); | ||
366 | } | ||
367 | break; | ||
368 | case ROUNDMINUS: | ||
369 | if (Sgl_isone_sign(result)) { | ||
370 | Sgl_increment(opnd3); | ||
371 | } | ||
372 | break; | ||
373 | case ROUNDNEAREST: | ||
374 | if (guardbit && (stickybit || | ||
375 | Sgl_isone_lowmantissa(opnd3))) { | ||
376 | Sgl_increment(opnd3); | ||
377 | } | ||
378 | break; | ||
379 | } | ||
380 | if (is_tiny) Set_underflowflag(); | ||
381 | } | ||
382 | Sgl_set_exponentmantissa(result,opnd3); | ||
383 | } | ||
384 | else Sgl_set_exponent(result,dest_exponent); | ||
385 | *dstptr = result; | ||
386 | /* check for inexact */ | ||
387 | if (inexact) { | ||
388 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
389 | else Set_inexactflag(); | ||
390 | } | ||
391 | return(NOEXCEPTION); | ||
392 | } | ||
diff --git a/arch/parisc/math-emu/sfmpy.c b/arch/parisc/math-emu/sfmpy.c new file mode 100644 index 000000000000..afa406983335 --- /dev/null +++ b/arch/parisc/math-emu/sfmpy.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/sfmpy.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single Precision Floating-point Multiply | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * sgl_fmpy(srcptr1,srcptr2,dstptr,status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "sgl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Single Precision Floating-point Multiply | ||
47 | */ | ||
48 | |||
49 | int | ||
50 | sgl_fmpy( | ||
51 | sgl_floating_point *srcptr1, | ||
52 | sgl_floating_point *srcptr2, | ||
53 | sgl_floating_point *dstptr, | ||
54 | unsigned int *status) | ||
55 | { | ||
56 | register unsigned int opnd1, opnd2, opnd3, result; | ||
57 | register int dest_exponent, count; | ||
58 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
59 | boolean is_tiny; | ||
60 | |||
61 | opnd1 = *srcptr1; | ||
62 | opnd2 = *srcptr2; | ||
63 | /* | ||
64 | * set sign bit of result | ||
65 | */ | ||
66 | if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result); | ||
67 | else Sgl_setzero(result); | ||
68 | /* | ||
69 | * check first operand for NaN's or infinity | ||
70 | */ | ||
71 | if (Sgl_isinfinity_exponent(opnd1)) { | ||
72 | if (Sgl_iszero_mantissa(opnd1)) { | ||
73 | if (Sgl_isnotnan(opnd2)) { | ||
74 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
75 | /* | ||
76 | * invalid since operands are infinity | ||
77 | * and zero | ||
78 | */ | ||
79 | if (Is_invalidtrap_enabled()) | ||
80 | return(INVALIDEXCEPTION); | ||
81 | Set_invalidflag(); | ||
82 | Sgl_makequietnan(result); | ||
83 | *dstptr = result; | ||
84 | return(NOEXCEPTION); | ||
85 | } | ||
86 | /* | ||
87 | * return infinity | ||
88 | */ | ||
89 | Sgl_setinfinity_exponentmantissa(result); | ||
90 | *dstptr = result; | ||
91 | return(NOEXCEPTION); | ||
92 | } | ||
93 | } | ||
94 | else { | ||
95 | /* | ||
96 | * is NaN; signaling or quiet? | ||
97 | */ | ||
98 | if (Sgl_isone_signaling(opnd1)) { | ||
99 | /* trap if INVALIDTRAP enabled */ | ||
100 | if (Is_invalidtrap_enabled()) | ||
101 | return(INVALIDEXCEPTION); | ||
102 | /* make NaN quiet */ | ||
103 | Set_invalidflag(); | ||
104 | Sgl_set_quiet(opnd1); | ||
105 | } | ||
106 | /* | ||
107 | * is second operand a signaling NaN? | ||
108 | */ | ||
109 | else if (Sgl_is_signalingnan(opnd2)) { | ||
110 | /* trap if INVALIDTRAP enabled */ | ||
111 | if (Is_invalidtrap_enabled()) | ||
112 | return(INVALIDEXCEPTION); | ||
113 | /* make NaN quiet */ | ||
114 | Set_invalidflag(); | ||
115 | Sgl_set_quiet(opnd2); | ||
116 | *dstptr = opnd2; | ||
117 | return(NOEXCEPTION); | ||
118 | } | ||
119 | /* | ||
120 | * return quiet NaN | ||
121 | */ | ||
122 | *dstptr = opnd1; | ||
123 | return(NOEXCEPTION); | ||
124 | } | ||
125 | } | ||
126 | /* | ||
127 | * check second operand for NaN's or infinity | ||
128 | */ | ||
129 | if (Sgl_isinfinity_exponent(opnd2)) { | ||
130 | if (Sgl_iszero_mantissa(opnd2)) { | ||
131 | if (Sgl_iszero_exponentmantissa(opnd1)) { | ||
132 | /* invalid since operands are zero & infinity */ | ||
133 | if (Is_invalidtrap_enabled()) | ||
134 | return(INVALIDEXCEPTION); | ||
135 | Set_invalidflag(); | ||
136 | Sgl_makequietnan(opnd2); | ||
137 | *dstptr = opnd2; | ||
138 | return(NOEXCEPTION); | ||
139 | } | ||
140 | /* | ||
141 | * return infinity | ||
142 | */ | ||
143 | Sgl_setinfinity_exponentmantissa(result); | ||
144 | *dstptr = result; | ||
145 | return(NOEXCEPTION); | ||
146 | } | ||
147 | /* | ||
148 | * is NaN; signaling or quiet? | ||
149 | */ | ||
150 | if (Sgl_isone_signaling(opnd2)) { | ||
151 | /* trap if INVALIDTRAP enabled */ | ||
152 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
153 | |||
154 | /* make NaN quiet */ | ||
155 | Set_invalidflag(); | ||
156 | Sgl_set_quiet(opnd2); | ||
157 | } | ||
158 | /* | ||
159 | * return quiet NaN | ||
160 | */ | ||
161 | *dstptr = opnd2; | ||
162 | return(NOEXCEPTION); | ||
163 | } | ||
164 | /* | ||
165 | * Generate exponent | ||
166 | */ | ||
167 | dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; | ||
168 | |||
169 | /* | ||
170 | * Generate mantissa | ||
171 | */ | ||
172 | if (Sgl_isnotzero_exponent(opnd1)) { | ||
173 | /* set hidden bit */ | ||
174 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
175 | } | ||
176 | else { | ||
177 | /* check for zero */ | ||
178 | if (Sgl_iszero_mantissa(opnd1)) { | ||
179 | Sgl_setzero_exponentmantissa(result); | ||
180 | *dstptr = result; | ||
181 | return(NOEXCEPTION); | ||
182 | } | ||
183 | /* is denormalized, adjust exponent */ | ||
184 | Sgl_clear_signexponent(opnd1); | ||
185 | Sgl_leftshiftby1(opnd1); | ||
186 | Sgl_normalize(opnd1,dest_exponent); | ||
187 | } | ||
188 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
189 | if (Sgl_isnotzero_exponent(opnd2)) { | ||
190 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
191 | } | ||
192 | else { | ||
193 | /* check for zero */ | ||
194 | if (Sgl_iszero_mantissa(opnd2)) { | ||
195 | Sgl_setzero_exponentmantissa(result); | ||
196 | *dstptr = result; | ||
197 | return(NOEXCEPTION); | ||
198 | } | ||
199 | /* is denormalized; want to normalize */ | ||
200 | Sgl_clear_signexponent(opnd2); | ||
201 | Sgl_leftshiftby1(opnd2); | ||
202 | Sgl_normalize(opnd2,dest_exponent); | ||
203 | } | ||
204 | |||
205 | /* Multiply two source mantissas together */ | ||
206 | |||
207 | Sgl_leftshiftby4(opnd2); /* make room for guard bits */ | ||
208 | Sgl_setzero(opnd3); | ||
209 | /* | ||
210 | * Four bits at a time are inspected in each loop, and a | ||
211 | * simple shift and add multiply algorithm is used. | ||
212 | */ | ||
213 | for (count=1;count<SGL_P;count+=4) { | ||
214 | stickybit |= Slow4(opnd3); | ||
215 | Sgl_rightshiftby4(opnd3); | ||
216 | if (Sbit28(opnd1)) Sall(opnd3) += (Sall(opnd2) << 3); | ||
217 | if (Sbit29(opnd1)) Sall(opnd3) += (Sall(opnd2) << 2); | ||
218 | if (Sbit30(opnd1)) Sall(opnd3) += (Sall(opnd2) << 1); | ||
219 | if (Sbit31(opnd1)) Sall(opnd3) += Sall(opnd2); | ||
220 | Sgl_rightshiftby4(opnd1); | ||
221 | } | ||
222 | /* make sure result is left-justified */ | ||
223 | if (Sgl_iszero_sign(opnd3)) { | ||
224 | Sgl_leftshiftby1(opnd3); | ||
225 | } | ||
226 | else { | ||
227 | /* result mantissa >= 2. */ | ||
228 | dest_exponent++; | ||
229 | } | ||
230 | /* check for denormalized result */ | ||
231 | while (Sgl_iszero_sign(opnd3)) { | ||
232 | Sgl_leftshiftby1(opnd3); | ||
233 | dest_exponent--; | ||
234 | } | ||
235 | /* | ||
236 | * check for guard, sticky and inexact bits | ||
237 | */ | ||
238 | stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1); | ||
239 | guardbit = Sbit24(opnd3); | ||
240 | inexact = guardbit | stickybit; | ||
241 | |||
242 | /* re-align mantissa */ | ||
243 | Sgl_rightshiftby8(opnd3); | ||
244 | |||
245 | /* | ||
246 | * round result | ||
247 | */ | ||
248 | if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) { | ||
249 | Sgl_clear_signexponent(opnd3); | ||
250 | switch (Rounding_mode()) { | ||
251 | case ROUNDPLUS: | ||
252 | if (Sgl_iszero_sign(result)) | ||
253 | Sgl_increment(opnd3); | ||
254 | break; | ||
255 | case ROUNDMINUS: | ||
256 | if (Sgl_isone_sign(result)) | ||
257 | Sgl_increment(opnd3); | ||
258 | break; | ||
259 | case ROUNDNEAREST: | ||
260 | if (guardbit) { | ||
261 | if (stickybit || Sgl_isone_lowmantissa(opnd3)) | ||
262 | Sgl_increment(opnd3); | ||
263 | } | ||
264 | } | ||
265 | if (Sgl_isone_hidden(opnd3)) dest_exponent++; | ||
266 | } | ||
267 | Sgl_set_mantissa(result,opnd3); | ||
268 | |||
269 | /* | ||
270 | * Test for overflow | ||
271 | */ | ||
272 | if (dest_exponent >= SGL_INFINITY_EXPONENT) { | ||
273 | /* trap if OVERFLOWTRAP enabled */ | ||
274 | if (Is_overflowtrap_enabled()) { | ||
275 | /* | ||
276 | * Adjust bias of result | ||
277 | */ | ||
278 | Sgl_setwrapped_exponent(result,dest_exponent,ovfl); | ||
279 | *dstptr = result; | ||
280 | if (inexact) | ||
281 | if (Is_inexacttrap_enabled()) | ||
282 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
283 | else Set_inexactflag(); | ||
284 | return(OVERFLOWEXCEPTION); | ||
285 | } | ||
286 | inexact = TRUE; | ||
287 | Set_overflowflag(); | ||
288 | /* set result to infinity or largest number */ | ||
289 | Sgl_setoverflow(result); | ||
290 | } | ||
291 | /* | ||
292 | * Test for underflow | ||
293 | */ | ||
294 | else if (dest_exponent <= 0) { | ||
295 | /* trap if UNDERFLOWTRAP enabled */ | ||
296 | if (Is_underflowtrap_enabled()) { | ||
297 | /* | ||
298 | * Adjust bias of result | ||
299 | */ | ||
300 | Sgl_setwrapped_exponent(result,dest_exponent,unfl); | ||
301 | *dstptr = result; | ||
302 | if (inexact) | ||
303 | if (Is_inexacttrap_enabled()) | ||
304 | return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
305 | else Set_inexactflag(); | ||
306 | return(UNDERFLOWEXCEPTION); | ||
307 | } | ||
308 | |||
309 | /* Determine if should set underflow flag */ | ||
310 | is_tiny = TRUE; | ||
311 | if (dest_exponent == 0 && inexact) { | ||
312 | switch (Rounding_mode()) { | ||
313 | case ROUNDPLUS: | ||
314 | if (Sgl_iszero_sign(result)) { | ||
315 | Sgl_increment(opnd3); | ||
316 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
317 | is_tiny = FALSE; | ||
318 | Sgl_decrement(opnd3); | ||
319 | } | ||
320 | break; | ||
321 | case ROUNDMINUS: | ||
322 | if (Sgl_isone_sign(result)) { | ||
323 | Sgl_increment(opnd3); | ||
324 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
325 | is_tiny = FALSE; | ||
326 | Sgl_decrement(opnd3); | ||
327 | } | ||
328 | break; | ||
329 | case ROUNDNEAREST: | ||
330 | if (guardbit && (stickybit || | ||
331 | Sgl_isone_lowmantissa(opnd3))) { | ||
332 | Sgl_increment(opnd3); | ||
333 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
334 | is_tiny = FALSE; | ||
335 | Sgl_decrement(opnd3); | ||
336 | } | ||
337 | break; | ||
338 | } | ||
339 | } | ||
340 | |||
341 | /* | ||
342 | * denormalize result or set to signed zero | ||
343 | */ | ||
344 | stickybit = inexact; | ||
345 | Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact); | ||
346 | |||
347 | /* return zero or smallest number */ | ||
348 | if (inexact) { | ||
349 | switch (Rounding_mode()) { | ||
350 | case ROUNDPLUS: | ||
351 | if (Sgl_iszero_sign(result)) { | ||
352 | Sgl_increment(opnd3); | ||
353 | } | ||
354 | break; | ||
355 | case ROUNDMINUS: | ||
356 | if (Sgl_isone_sign(result)) { | ||
357 | Sgl_increment(opnd3); | ||
358 | } | ||
359 | break; | ||
360 | case ROUNDNEAREST: | ||
361 | if (guardbit && (stickybit || | ||
362 | Sgl_isone_lowmantissa(opnd3))) { | ||
363 | Sgl_increment(opnd3); | ||
364 | } | ||
365 | break; | ||
366 | } | ||
367 | if (is_tiny) Set_underflowflag(); | ||
368 | } | ||
369 | Sgl_set_exponentmantissa(result,opnd3); | ||
370 | } | ||
371 | else Sgl_set_exponent(result,dest_exponent); | ||
372 | *dstptr = result; | ||
373 | |||
374 | /* check for inexact */ | ||
375 | if (inexact) { | ||
376 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
377 | else Set_inexactflag(); | ||
378 | } | ||
379 | return(NOEXCEPTION); | ||
380 | } | ||
diff --git a/arch/parisc/math-emu/sfrem.c b/arch/parisc/math-emu/sfrem.c new file mode 100644 index 000000000000..3a1b7a34d87a --- /dev/null +++ b/arch/parisc/math-emu/sfrem.c | |||
@@ -0,0 +1,290 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/sfrem.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single Precision Floating-point Remainder | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * sgl_frem(srcptr1,srcptr2,dstptr,status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | |||
43 | #include "float.h" | ||
44 | #include "sgl_float.h" | ||
45 | |||
46 | /* | ||
47 | * Single Precision Floating-point Remainder | ||
48 | */ | ||
49 | |||
50 | int | ||
51 | sgl_frem (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2, | ||
52 | sgl_floating_point * dstptr, unsigned int *status) | ||
53 | { | ||
54 | register unsigned int opnd1, opnd2, result; | ||
55 | register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount; | ||
56 | register boolean roundup = FALSE; | ||
57 | |||
58 | opnd1 = *srcptr1; | ||
59 | opnd2 = *srcptr2; | ||
60 | /* | ||
61 | * check first operand for NaN's or infinity | ||
62 | */ | ||
63 | if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) { | ||
64 | if (Sgl_iszero_mantissa(opnd1)) { | ||
65 | if (Sgl_isnotnan(opnd2)) { | ||
66 | /* invalid since first operand is infinity */ | ||
67 | if (Is_invalidtrap_enabled()) | ||
68 | return(INVALIDEXCEPTION); | ||
69 | Set_invalidflag(); | ||
70 | Sgl_makequietnan(result); | ||
71 | *dstptr = result; | ||
72 | return(NOEXCEPTION); | ||
73 | } | ||
74 | } | ||
75 | else { | ||
76 | /* | ||
77 | * is NaN; signaling or quiet? | ||
78 | */ | ||
79 | if (Sgl_isone_signaling(opnd1)) { | ||
80 | /* trap if INVALIDTRAP enabled */ | ||
81 | if (Is_invalidtrap_enabled()) | ||
82 | return(INVALIDEXCEPTION); | ||
83 | /* make NaN quiet */ | ||
84 | Set_invalidflag(); | ||
85 | Sgl_set_quiet(opnd1); | ||
86 | } | ||
87 | /* | ||
88 | * is second operand a signaling NaN? | ||
89 | */ | ||
90 | else if (Sgl_is_signalingnan(opnd2)) { | ||
91 | /* trap if INVALIDTRAP enabled */ | ||
92 | if (Is_invalidtrap_enabled()) | ||
93 | return(INVALIDEXCEPTION); | ||
94 | /* make NaN quiet */ | ||
95 | Set_invalidflag(); | ||
96 | Sgl_set_quiet(opnd2); | ||
97 | *dstptr = opnd2; | ||
98 | return(NOEXCEPTION); | ||
99 | } | ||
100 | /* | ||
101 | * return quiet NaN | ||
102 | */ | ||
103 | *dstptr = opnd1; | ||
104 | return(NOEXCEPTION); | ||
105 | } | ||
106 | } | ||
107 | /* | ||
108 | * check second operand for NaN's or infinity | ||
109 | */ | ||
110 | if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) { | ||
111 | if (Sgl_iszero_mantissa(opnd2)) { | ||
112 | /* | ||
113 | * return first operand | ||
114 | */ | ||
115 | *dstptr = opnd1; | ||
116 | return(NOEXCEPTION); | ||
117 | } | ||
118 | /* | ||
119 | * is NaN; signaling or quiet? | ||
120 | */ | ||
121 | if (Sgl_isone_signaling(opnd2)) { | ||
122 | /* trap if INVALIDTRAP enabled */ | ||
123 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
124 | /* make NaN quiet */ | ||
125 | Set_invalidflag(); | ||
126 | Sgl_set_quiet(opnd2); | ||
127 | } | ||
128 | /* | ||
129 | * return quiet NaN | ||
130 | */ | ||
131 | *dstptr = opnd2; | ||
132 | return(NOEXCEPTION); | ||
133 | } | ||
134 | /* | ||
135 | * check second operand for zero | ||
136 | */ | ||
137 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
138 | /* invalid since second operand is zero */ | ||
139 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
140 | Set_invalidflag(); | ||
141 | Sgl_makequietnan(result); | ||
142 | *dstptr = result; | ||
143 | return(NOEXCEPTION); | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * get sign of result | ||
148 | */ | ||
149 | result = opnd1; | ||
150 | |||
151 | /* | ||
152 | * check for denormalized operands | ||
153 | */ | ||
154 | if (opnd1_exponent == 0) { | ||
155 | /* check for zero */ | ||
156 | if (Sgl_iszero_mantissa(opnd1)) { | ||
157 | *dstptr = opnd1; | ||
158 | return(NOEXCEPTION); | ||
159 | } | ||
160 | /* normalize, then continue */ | ||
161 | opnd1_exponent = 1; | ||
162 | Sgl_normalize(opnd1,opnd1_exponent); | ||
163 | } | ||
164 | else { | ||
165 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
166 | } | ||
167 | if (opnd2_exponent == 0) { | ||
168 | /* normalize, then continue */ | ||
169 | opnd2_exponent = 1; | ||
170 | Sgl_normalize(opnd2,opnd2_exponent); | ||
171 | } | ||
172 | else { | ||
173 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
174 | } | ||
175 | |||
176 | /* find result exponent and divide step loop count */ | ||
177 | dest_exponent = opnd2_exponent - 1; | ||
178 | stepcount = opnd1_exponent - opnd2_exponent; | ||
179 | |||
180 | /* | ||
181 | * check for opnd1/opnd2 < 1 | ||
182 | */ | ||
183 | if (stepcount < 0) { | ||
184 | /* | ||
185 | * check for opnd1/opnd2 > 1/2 | ||
186 | * | ||
187 | * In this case n will round to 1, so | ||
188 | * r = opnd1 - opnd2 | ||
189 | */ | ||
190 | if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) { | ||
191 | Sgl_all(result) = ~Sgl_all(result); /* set sign */ | ||
192 | /* align opnd2 with opnd1 */ | ||
193 | Sgl_leftshiftby1(opnd2); | ||
194 | Sgl_subtract(opnd2,opnd1,opnd2); | ||
195 | /* now normalize */ | ||
196 | while (Sgl_iszero_hidden(opnd2)) { | ||
197 | Sgl_leftshiftby1(opnd2); | ||
198 | dest_exponent--; | ||
199 | } | ||
200 | Sgl_set_exponentmantissa(result,opnd2); | ||
201 | goto testforunderflow; | ||
202 | } | ||
203 | /* | ||
204 | * opnd1/opnd2 <= 1/2 | ||
205 | * | ||
206 | * In this case n will round to zero, so | ||
207 | * r = opnd1 | ||
208 | */ | ||
209 | Sgl_set_exponentmantissa(result,opnd1); | ||
210 | dest_exponent = opnd1_exponent; | ||
211 | goto testforunderflow; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * Generate result | ||
216 | * | ||
217 | * Do iterative subtract until remainder is less than operand 2. | ||
218 | */ | ||
219 | while (stepcount-- > 0 && Sgl_all(opnd1)) { | ||
220 | if (Sgl_isnotlessthan(opnd1,opnd2)) | ||
221 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
222 | Sgl_leftshiftby1(opnd1); | ||
223 | } | ||
224 | /* | ||
225 | * Do last subtract, then determine which way to round if remainder | ||
226 | * is exactly 1/2 of opnd2 | ||
227 | */ | ||
228 | if (Sgl_isnotlessthan(opnd1,opnd2)) { | ||
229 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
230 | roundup = TRUE; | ||
231 | } | ||
232 | if (stepcount > 0 || Sgl_iszero(opnd1)) { | ||
233 | /* division is exact, remainder is zero */ | ||
234 | Sgl_setzero_exponentmantissa(result); | ||
235 | *dstptr = result; | ||
236 | return(NOEXCEPTION); | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * Check for cases where opnd1/opnd2 < n | ||
241 | * | ||
242 | * In this case the result's sign will be opposite that of | ||
243 | * opnd1. The mantissa also needs some correction. | ||
244 | */ | ||
245 | Sgl_leftshiftby1(opnd1); | ||
246 | if (Sgl_isgreaterthan(opnd1,opnd2)) { | ||
247 | Sgl_invert_sign(result); | ||
248 | Sgl_subtract((opnd2<<1),opnd1,opnd1); | ||
249 | } | ||
250 | /* check for remainder being exactly 1/2 of opnd2 */ | ||
251 | else if (Sgl_isequal(opnd1,opnd2) && roundup) { | ||
252 | Sgl_invert_sign(result); | ||
253 | } | ||
254 | |||
255 | /* normalize result's mantissa */ | ||
256 | while (Sgl_iszero_hidden(opnd1)) { | ||
257 | dest_exponent--; | ||
258 | Sgl_leftshiftby1(opnd1); | ||
259 | } | ||
260 | Sgl_set_exponentmantissa(result,opnd1); | ||
261 | |||
262 | /* | ||
263 | * Test for underflow | ||
264 | */ | ||
265 | testforunderflow: | ||
266 | if (dest_exponent <= 0) { | ||
267 | /* trap if UNDERFLOWTRAP enabled */ | ||
268 | if (Is_underflowtrap_enabled()) { | ||
269 | /* | ||
270 | * Adjust bias of result | ||
271 | */ | ||
272 | Sgl_setwrapped_exponent(result,dest_exponent,unfl); | ||
273 | *dstptr = result; | ||
274 | /* frem is always exact */ | ||
275 | return(UNDERFLOWEXCEPTION); | ||
276 | } | ||
277 | /* | ||
278 | * denormalize result or set to signed zero | ||
279 | */ | ||
280 | if (dest_exponent >= (1 - SGL_P)) { | ||
281 | Sgl_rightshift_exponentmantissa(result,1-dest_exponent); | ||
282 | } | ||
283 | else { | ||
284 | Sgl_setzero_exponentmantissa(result); | ||
285 | } | ||
286 | } | ||
287 | else Sgl_set_exponent(result,dest_exponent); | ||
288 | *dstptr = result; | ||
289 | return(NOEXCEPTION); | ||
290 | } | ||
diff --git a/arch/parisc/math-emu/sfsqrt.c b/arch/parisc/math-emu/sfsqrt.c new file mode 100644 index 000000000000..cd3f6db1f6fb --- /dev/null +++ b/arch/parisc/math-emu/sfsqrt.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/sfsqrt.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single Floating-point Square Root | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * sgl_fsqrt(srcptr,nullptr,dstptr,status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "sgl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Single Floating-point Square Root | ||
47 | */ | ||
48 | |||
49 | /*ARGSUSED*/ | ||
50 | unsigned int | ||
51 | sgl_fsqrt( | ||
52 | sgl_floating_point *srcptr, | ||
53 | unsigned int *nullptr, | ||
54 | sgl_floating_point *dstptr, | ||
55 | unsigned int *status) | ||
56 | { | ||
57 | register unsigned int src, result; | ||
58 | register int src_exponent; | ||
59 | register unsigned int newbit, sum; | ||
60 | register boolean guardbit = FALSE, even_exponent; | ||
61 | |||
62 | src = *srcptr; | ||
63 | /* | ||
64 | * check source operand for NaN or infinity | ||
65 | */ | ||
66 | if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { | ||
67 | /* | ||
68 | * is signaling NaN? | ||
69 | */ | ||
70 | if (Sgl_isone_signaling(src)) { | ||
71 | /* trap if INVALIDTRAP enabled */ | ||
72 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
73 | /* make NaN quiet */ | ||
74 | Set_invalidflag(); | ||
75 | Sgl_set_quiet(src); | ||
76 | } | ||
77 | /* | ||
78 | * Return quiet NaN or positive infinity. | ||
79 | * Fall thru to negative test if negative infinity. | ||
80 | */ | ||
81 | if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) { | ||
82 | *dstptr = src; | ||
83 | return(NOEXCEPTION); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * check for zero source operand | ||
89 | */ | ||
90 | if (Sgl_iszero_exponentmantissa(src)) { | ||
91 | *dstptr = src; | ||
92 | return(NOEXCEPTION); | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * check for negative source operand | ||
97 | */ | ||
98 | if (Sgl_isone_sign(src)) { | ||
99 | /* trap if INVALIDTRAP enabled */ | ||
100 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
101 | /* make NaN quiet */ | ||
102 | Set_invalidflag(); | ||
103 | Sgl_makequietnan(src); | ||
104 | *dstptr = src; | ||
105 | return(NOEXCEPTION); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Generate result | ||
110 | */ | ||
111 | if (src_exponent > 0) { | ||
112 | even_exponent = Sgl_hidden(src); | ||
113 | Sgl_clear_signexponent_set_hidden(src); | ||
114 | } | ||
115 | else { | ||
116 | /* normalize operand */ | ||
117 | Sgl_clear_signexponent(src); | ||
118 | src_exponent++; | ||
119 | Sgl_normalize(src,src_exponent); | ||
120 | even_exponent = src_exponent & 1; | ||
121 | } | ||
122 | if (even_exponent) { | ||
123 | /* exponent is even */ | ||
124 | /* Add comment here. Explain why odd exponent needs correction */ | ||
125 | Sgl_leftshiftby1(src); | ||
126 | } | ||
127 | /* | ||
128 | * Add comment here. Explain following algorithm. | ||
129 | * | ||
130 | * Trust me, it works. | ||
131 | * | ||
132 | */ | ||
133 | Sgl_setzero(result); | ||
134 | newbit = 1 << SGL_P; | ||
135 | while (newbit && Sgl_isnotzero(src)) { | ||
136 | Sgl_addition(result,newbit,sum); | ||
137 | if(sum <= Sgl_all(src)) { | ||
138 | /* update result */ | ||
139 | Sgl_addition(result,(newbit<<1),result); | ||
140 | Sgl_subtract(src,sum,src); | ||
141 | } | ||
142 | Sgl_rightshiftby1(newbit); | ||
143 | Sgl_leftshiftby1(src); | ||
144 | } | ||
145 | /* correct exponent for pre-shift */ | ||
146 | if (even_exponent) { | ||
147 | Sgl_rightshiftby1(result); | ||
148 | } | ||
149 | |||
150 | /* check for inexact */ | ||
151 | if (Sgl_isnotzero(src)) { | ||
152 | if (!even_exponent && Sgl_islessthan(result,src)) | ||
153 | Sgl_increment(result); | ||
154 | guardbit = Sgl_lowmantissa(result); | ||
155 | Sgl_rightshiftby1(result); | ||
156 | |||
157 | /* now round result */ | ||
158 | switch (Rounding_mode()) { | ||
159 | case ROUNDPLUS: | ||
160 | Sgl_increment(result); | ||
161 | break; | ||
162 | case ROUNDNEAREST: | ||
163 | /* stickybit is always true, so guardbit | ||
164 | * is enough to determine rounding */ | ||
165 | if (guardbit) { | ||
166 | Sgl_increment(result); | ||
167 | } | ||
168 | break; | ||
169 | } | ||
170 | /* increment result exponent by 1 if mantissa overflowed */ | ||
171 | if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2; | ||
172 | |||
173 | if (Is_inexacttrap_enabled()) { | ||
174 | Sgl_set_exponent(result, | ||
175 | ((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); | ||
176 | *dstptr = result; | ||
177 | return(INEXACTEXCEPTION); | ||
178 | } | ||
179 | else Set_inexactflag(); | ||
180 | } | ||
181 | else { | ||
182 | Sgl_rightshiftby1(result); | ||
183 | } | ||
184 | Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); | ||
185 | *dstptr = result; | ||
186 | return(NOEXCEPTION); | ||
187 | } | ||
diff --git a/arch/parisc/math-emu/sfsub.c b/arch/parisc/math-emu/sfsub.c new file mode 100644 index 000000000000..24eef61c8e3b --- /dev/null +++ b/arch/parisc/math-emu/sfsub.c | |||
@@ -0,0 +1,521 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | /* | ||
22 | * BEGIN_DESC | ||
23 | * | ||
24 | * File: | ||
25 | * @(#) pa/spmath/sfsub.c $Revision: 1.1 $ | ||
26 | * | ||
27 | * Purpose: | ||
28 | * Single_subtract: subtract two single precision values. | ||
29 | * | ||
30 | * External Interfaces: | ||
31 | * sgl_fsub(leftptr, rightptr, dstptr, status) | ||
32 | * | ||
33 | * Internal Interfaces: | ||
34 | * | ||
35 | * Theory: | ||
36 | * <<please update with a overview of the operation of this file>> | ||
37 | * | ||
38 | * END_DESC | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include "float.h" | ||
43 | #include "sgl_float.h" | ||
44 | |||
45 | /* | ||
46 | * Single_subtract: subtract two single precision values. | ||
47 | */ | ||
48 | int | ||
49 | sgl_fsub( | ||
50 | sgl_floating_point *leftptr, | ||
51 | sgl_floating_point *rightptr, | ||
52 | sgl_floating_point *dstptr, | ||
53 | unsigned int *status) | ||
54 | { | ||
55 | register unsigned int left, right, result, extent; | ||
56 | register unsigned int signless_upper_left, signless_upper_right, save; | ||
57 | |||
58 | register int result_exponent, right_exponent, diff_exponent; | ||
59 | register int sign_save, jumpsize; | ||
60 | register boolean inexact = FALSE, underflowtrap; | ||
61 | |||
62 | /* Create local copies of the numbers */ | ||
63 | left = *leftptr; | ||
64 | right = *rightptr; | ||
65 | |||
66 | /* A zero "save" helps discover equal operands (for later), * | ||
67 | * and is used in swapping operands (if needed). */ | ||
68 | Sgl_xortointp1(left,right,/*to*/save); | ||
69 | |||
70 | /* | ||
71 | * check first operand for NaN's or infinity | ||
72 | */ | ||
73 | if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT) | ||
74 | { | ||
75 | if (Sgl_iszero_mantissa(left)) | ||
76 | { | ||
77 | if (Sgl_isnotnan(right)) | ||
78 | { | ||
79 | if (Sgl_isinfinity(right) && save==0) | ||
80 | { | ||
81 | /* | ||
82 | * invalid since operands are same signed infinity's | ||
83 | */ | ||
84 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
85 | Set_invalidflag(); | ||
86 | Sgl_makequietnan(result); | ||
87 | *dstptr = result; | ||
88 | return(NOEXCEPTION); | ||
89 | } | ||
90 | /* | ||
91 | * return infinity | ||
92 | */ | ||
93 | *dstptr = left; | ||
94 | return(NOEXCEPTION); | ||
95 | } | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | /* | ||
100 | * is NaN; signaling or quiet? | ||
101 | */ | ||
102 | if (Sgl_isone_signaling(left)) | ||
103 | { | ||
104 | /* trap if INVALIDTRAP enabled */ | ||
105 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
106 | /* make NaN quiet */ | ||
107 | Set_invalidflag(); | ||
108 | Sgl_set_quiet(left); | ||
109 | } | ||
110 | /* | ||
111 | * is second operand a signaling NaN? | ||
112 | */ | ||
113 | else if (Sgl_is_signalingnan(right)) | ||
114 | { | ||
115 | /* trap if INVALIDTRAP enabled */ | ||
116 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
117 | /* make NaN quiet */ | ||
118 | Set_invalidflag(); | ||
119 | Sgl_set_quiet(right); | ||
120 | *dstptr = right; | ||
121 | return(NOEXCEPTION); | ||
122 | } | ||
123 | /* | ||
124 | * return quiet NaN | ||
125 | */ | ||
126 | *dstptr = left; | ||
127 | return(NOEXCEPTION); | ||
128 | } | ||
129 | } /* End left NaN or Infinity processing */ | ||
130 | /* | ||
131 | * check second operand for NaN's or infinity | ||
132 | */ | ||
133 | if (Sgl_isinfinity_exponent(right)) | ||
134 | { | ||
135 | if (Sgl_iszero_mantissa(right)) | ||
136 | { | ||
137 | /* return infinity */ | ||
138 | Sgl_invert_sign(right); | ||
139 | *dstptr = right; | ||
140 | return(NOEXCEPTION); | ||
141 | } | ||
142 | /* | ||
143 | * is NaN; signaling or quiet? | ||
144 | */ | ||
145 | if (Sgl_isone_signaling(right)) | ||
146 | { | ||
147 | /* trap if INVALIDTRAP enabled */ | ||
148 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
149 | /* make NaN quiet */ | ||
150 | Set_invalidflag(); | ||
151 | Sgl_set_quiet(right); | ||
152 | } | ||
153 | /* | ||
154 | * return quiet NaN | ||
155 | */ | ||
156 | *dstptr = right; | ||
157 | return(NOEXCEPTION); | ||
158 | } /* End right NaN or Infinity processing */ | ||
159 | |||
160 | /* Invariant: Must be dealing with finite numbers */ | ||
161 | |||
162 | /* Compare operands by removing the sign */ | ||
163 | Sgl_copytoint_exponentmantissa(left,signless_upper_left); | ||
164 | Sgl_copytoint_exponentmantissa(right,signless_upper_right); | ||
165 | |||
166 | /* sign difference selects sub or add operation. */ | ||
167 | if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right)) | ||
168 | { | ||
169 | /* Set the left operand to the larger one by XOR swap * | ||
170 | * First finish the first word using "save" */ | ||
171 | Sgl_xorfromintp1(save,right,/*to*/right); | ||
172 | Sgl_xorfromintp1(save,left,/*to*/left); | ||
173 | result_exponent = Sgl_exponent(left); | ||
174 | Sgl_invert_sign(left); | ||
175 | } | ||
176 | /* Invariant: left is not smaller than right. */ | ||
177 | |||
178 | if((right_exponent = Sgl_exponent(right)) == 0) | ||
179 | { | ||
180 | /* Denormalized operands. First look for zeroes */ | ||
181 | if(Sgl_iszero_mantissa(right)) | ||
182 | { | ||
183 | /* right is zero */ | ||
184 | if(Sgl_iszero_exponentmantissa(left)) | ||
185 | { | ||
186 | /* Both operands are zeros */ | ||
187 | Sgl_invert_sign(right); | ||
188 | if(Is_rounding_mode(ROUNDMINUS)) | ||
189 | { | ||
190 | Sgl_or_signs(left,/*with*/right); | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | Sgl_and_signs(left,/*with*/right); | ||
195 | } | ||
196 | } | ||
197 | else | ||
198 | { | ||
199 | /* Left is not a zero and must be the result. Trapped | ||
200 | * underflows are signaled if left is denormalized. Result | ||
201 | * is always exact. */ | ||
202 | if( (result_exponent == 0) && Is_underflowtrap_enabled() ) | ||
203 | { | ||
204 | /* need to normalize results mantissa */ | ||
205 | sign_save = Sgl_signextendedsign(left); | ||
206 | Sgl_leftshiftby1(left); | ||
207 | Sgl_normalize(left,result_exponent); | ||
208 | Sgl_set_sign(left,/*using*/sign_save); | ||
209 | Sgl_setwrapped_exponent(left,result_exponent,unfl); | ||
210 | *dstptr = left; | ||
211 | /* inexact = FALSE */ | ||
212 | return(UNDERFLOWEXCEPTION); | ||
213 | } | ||
214 | } | ||
215 | *dstptr = left; | ||
216 | return(NOEXCEPTION); | ||
217 | } | ||
218 | |||
219 | /* Neither are zeroes */ | ||
220 | Sgl_clear_sign(right); /* Exponent is already cleared */ | ||
221 | if(result_exponent == 0 ) | ||
222 | { | ||
223 | /* Both operands are denormalized. The result must be exact | ||
224 | * and is simply calculated. A sum could become normalized and a | ||
225 | * difference could cancel to a true zero. */ | ||
226 | if( (/*signed*/int) save >= 0 ) | ||
227 | { | ||
228 | Sgl_subtract(left,/*minus*/right,/*into*/result); | ||
229 | if(Sgl_iszero_mantissa(result)) | ||
230 | { | ||
231 | if(Is_rounding_mode(ROUNDMINUS)) | ||
232 | { | ||
233 | Sgl_setone_sign(result); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | Sgl_setzero_sign(result); | ||
238 | } | ||
239 | *dstptr = result; | ||
240 | return(NOEXCEPTION); | ||
241 | } | ||
242 | } | ||
243 | else | ||
244 | { | ||
245 | Sgl_addition(left,right,/*into*/result); | ||
246 | if(Sgl_isone_hidden(result)) | ||
247 | { | ||
248 | *dstptr = result; | ||
249 | return(NOEXCEPTION); | ||
250 | } | ||
251 | } | ||
252 | if(Is_underflowtrap_enabled()) | ||
253 | { | ||
254 | /* need to normalize result */ | ||
255 | sign_save = Sgl_signextendedsign(result); | ||
256 | Sgl_leftshiftby1(result); | ||
257 | Sgl_normalize(result,result_exponent); | ||
258 | Sgl_set_sign(result,/*using*/sign_save); | ||
259 | Sgl_setwrapped_exponent(result,result_exponent,unfl); | ||
260 | *dstptr = result; | ||
261 | /* inexact = FALSE */ | ||
262 | return(UNDERFLOWEXCEPTION); | ||
263 | } | ||
264 | *dstptr = result; | ||
265 | return(NOEXCEPTION); | ||
266 | } | ||
267 | right_exponent = 1; /* Set exponent to reflect different bias | ||
268 | * with denomalized numbers. */ | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | Sgl_clear_signexponent_set_hidden(right); | ||
273 | } | ||
274 | Sgl_clear_exponent_set_hidden(left); | ||
275 | diff_exponent = result_exponent - right_exponent; | ||
276 | |||
277 | /* | ||
278 | * Special case alignment of operands that would force alignment | ||
279 | * beyond the extent of the extension. A further optimization | ||
280 | * could special case this but only reduces the path length for this | ||
281 | * infrequent case. | ||
282 | */ | ||
283 | if(diff_exponent > SGL_THRESHOLD) | ||
284 | { | ||
285 | diff_exponent = SGL_THRESHOLD; | ||
286 | } | ||
287 | |||
288 | /* Align right operand by shifting to right */ | ||
289 | Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent, | ||
290 | /*and lower to*/extent); | ||
291 | |||
292 | /* Treat sum and difference of the operands separately. */ | ||
293 | if( (/*signed*/int) save >= 0 ) | ||
294 | { | ||
295 | /* | ||
296 | * Difference of the two operands. Their can be no overflow. A | ||
297 | * borrow can occur out of the hidden bit and force a post | ||
298 | * normalization phase. | ||
299 | */ | ||
300 | Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result); | ||
301 | if(Sgl_iszero_hidden(result)) | ||
302 | { | ||
303 | /* Handle normalization */ | ||
304 | /* A straight foward algorithm would now shift the result | ||
305 | * and extension left until the hidden bit becomes one. Not | ||
306 | * all of the extension bits need participate in the shift. | ||
307 | * Only the two most significant bits (round and guard) are | ||
308 | * needed. If only a single shift is needed then the guard | ||
309 | * bit becomes a significant low order bit and the extension | ||
310 | * must participate in the rounding. If more than a single | ||
311 | * shift is needed, then all bits to the right of the guard | ||
312 | * bit are zeros, and the guard bit may or may not be zero. */ | ||
313 | sign_save = Sgl_signextendedsign(result); | ||
314 | Sgl_leftshiftby1_withextent(result,extent,result); | ||
315 | |||
316 | /* Need to check for a zero result. The sign and exponent | ||
317 | * fields have already been zeroed. The more efficient test | ||
318 | * of the full object can be used. | ||
319 | */ | ||
320 | if(Sgl_iszero(result)) | ||
321 | /* Must have been "x-x" or "x+(-x)". */ | ||
322 | { | ||
323 | if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result); | ||
324 | *dstptr = result; | ||
325 | return(NOEXCEPTION); | ||
326 | } | ||
327 | result_exponent--; | ||
328 | /* Look to see if normalization is finished. */ | ||
329 | if(Sgl_isone_hidden(result)) | ||
330 | { | ||
331 | if(result_exponent==0) | ||
332 | { | ||
333 | /* Denormalized, exponent should be zero. Left operand * | ||
334 | * was normalized, so extent (guard, round) was zero */ | ||
335 | goto underflow; | ||
336 | } | ||
337 | else | ||
338 | { | ||
339 | /* No further normalization is needed. */ | ||
340 | Sgl_set_sign(result,/*using*/sign_save); | ||
341 | Ext_leftshiftby1(extent); | ||
342 | goto round; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | /* Check for denormalized, exponent should be zero. Left * | ||
347 | * operand was normalized, so extent (guard, round) was zero */ | ||
348 | if(!(underflowtrap = Is_underflowtrap_enabled()) && | ||
349 | result_exponent==0) goto underflow; | ||
350 | |||
351 | /* Shift extension to complete one bit of normalization and | ||
352 | * update exponent. */ | ||
353 | Ext_leftshiftby1(extent); | ||
354 | |||
355 | /* Discover first one bit to determine shift amount. Use a | ||
356 | * modified binary search. We have already shifted the result | ||
357 | * one position right and still not found a one so the remainder | ||
358 | * of the extension must be zero and simplifies rounding. */ | ||
359 | /* Scan bytes */ | ||
360 | while(Sgl_iszero_hiddenhigh7mantissa(result)) | ||
361 | { | ||
362 | Sgl_leftshiftby8(result); | ||
363 | if((result_exponent -= 8) <= 0 && !underflowtrap) | ||
364 | goto underflow; | ||
365 | } | ||
366 | /* Now narrow it down to the nibble */ | ||
367 | if(Sgl_iszero_hiddenhigh3mantissa(result)) | ||
368 | { | ||
369 | /* The lower nibble contains the normalizing one */ | ||
370 | Sgl_leftshiftby4(result); | ||
371 | if((result_exponent -= 4) <= 0 && !underflowtrap) | ||
372 | goto underflow; | ||
373 | } | ||
374 | /* Select case were first bit is set (already normalized) | ||
375 | * otherwise select the proper shift. */ | ||
376 | if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7) | ||
377 | { | ||
378 | /* Already normalized */ | ||
379 | if(result_exponent <= 0) goto underflow; | ||
380 | Sgl_set_sign(result,/*using*/sign_save); | ||
381 | Sgl_set_exponent(result,/*using*/result_exponent); | ||
382 | *dstptr = result; | ||
383 | return(NOEXCEPTION); | ||
384 | } | ||
385 | Sgl_sethigh4bits(result,/*using*/sign_save); | ||
386 | switch(jumpsize) | ||
387 | { | ||
388 | case 1: | ||
389 | { | ||
390 | Sgl_leftshiftby3(result); | ||
391 | result_exponent -= 3; | ||
392 | break; | ||
393 | } | ||
394 | case 2: | ||
395 | case 3: | ||
396 | { | ||
397 | Sgl_leftshiftby2(result); | ||
398 | result_exponent -= 2; | ||
399 | break; | ||
400 | } | ||
401 | case 4: | ||
402 | case 5: | ||
403 | case 6: | ||
404 | case 7: | ||
405 | { | ||
406 | Sgl_leftshiftby1(result); | ||
407 | result_exponent -= 1; | ||
408 | break; | ||
409 | } | ||
410 | } | ||
411 | if(result_exponent > 0) | ||
412 | { | ||
413 | Sgl_set_exponent(result,/*using*/result_exponent); | ||
414 | *dstptr = result; /* Sign bit is already set */ | ||
415 | return(NOEXCEPTION); | ||
416 | } | ||
417 | /* Fixup potential underflows */ | ||
418 | underflow: | ||
419 | if(Is_underflowtrap_enabled()) | ||
420 | { | ||
421 | Sgl_set_sign(result,sign_save); | ||
422 | Sgl_setwrapped_exponent(result,result_exponent,unfl); | ||
423 | *dstptr = result; | ||
424 | /* inexact = FALSE */ | ||
425 | return(UNDERFLOWEXCEPTION); | ||
426 | } | ||
427 | /* | ||
428 | * Since we cannot get an inexact denormalized result, | ||
429 | * we can now return. | ||
430 | */ | ||
431 | Sgl_right_align(result,/*by*/(1-result_exponent),extent); | ||
432 | Sgl_clear_signexponent(result); | ||
433 | Sgl_set_sign(result,sign_save); | ||
434 | *dstptr = result; | ||
435 | return(NOEXCEPTION); | ||
436 | } /* end if(hidden...)... */ | ||
437 | /* Fall through and round */ | ||
438 | } /* end if(save >= 0)... */ | ||
439 | else | ||
440 | { | ||
441 | /* Add magnitudes */ | ||
442 | Sgl_addition(left,right,/*to*/result); | ||
443 | if(Sgl_isone_hiddenoverflow(result)) | ||
444 | { | ||
445 | /* Prenormalization required. */ | ||
446 | Sgl_rightshiftby1_withextent(result,extent,extent); | ||
447 | Sgl_arithrightshiftby1(result); | ||
448 | result_exponent++; | ||
449 | } /* end if hiddenoverflow... */ | ||
450 | } /* end else ...sub magnitudes... */ | ||
451 | |||
452 | /* Round the result. If the extension is all zeros,then the result is | ||
453 | * exact. Otherwise round in the correct direction. No underflow is | ||
454 | * possible. If a postnormalization is necessary, then the mantissa is | ||
455 | * all zeros so no shift is needed. */ | ||
456 | round: | ||
457 | if(Ext_isnotzero(extent)) | ||
458 | { | ||
459 | inexact = TRUE; | ||
460 | switch(Rounding_mode()) | ||
461 | { | ||
462 | case ROUNDNEAREST: /* The default. */ | ||
463 | if(Ext_isone_sign(extent)) | ||
464 | { | ||
465 | /* at least 1/2 ulp */ | ||
466 | if(Ext_isnotzero_lower(extent) || | ||
467 | Sgl_isone_lowmantissa(result)) | ||
468 | { | ||
469 | /* either exactly half way and odd or more than 1/2ulp */ | ||
470 | Sgl_increment(result); | ||
471 | } | ||
472 | } | ||
473 | break; | ||
474 | |||
475 | case ROUNDPLUS: | ||
476 | if(Sgl_iszero_sign(result)) | ||
477 | { | ||
478 | /* Round up positive results */ | ||
479 | Sgl_increment(result); | ||
480 | } | ||
481 | break; | ||
482 | |||
483 | case ROUNDMINUS: | ||
484 | if(Sgl_isone_sign(result)) | ||
485 | { | ||
486 | /* Round down negative results */ | ||
487 | Sgl_increment(result); | ||
488 | } | ||
489 | |||
490 | case ROUNDZERO:; | ||
491 | /* truncate is simple */ | ||
492 | } /* end switch... */ | ||
493 | if(Sgl_isone_hiddenoverflow(result)) result_exponent++; | ||
494 | } | ||
495 | if(result_exponent == SGL_INFINITY_EXPONENT) | ||
496 | { | ||
497 | /* Overflow */ | ||
498 | if(Is_overflowtrap_enabled()) | ||
499 | { | ||
500 | Sgl_setwrapped_exponent(result,result_exponent,ovfl); | ||
501 | *dstptr = result; | ||
502 | if (inexact) | ||
503 | if (Is_inexacttrap_enabled()) | ||
504 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
505 | else Set_inexactflag(); | ||
506 | return(OVERFLOWEXCEPTION); | ||
507 | } | ||
508 | else | ||
509 | { | ||
510 | Set_overflowflag(); | ||
511 | inexact = TRUE; | ||
512 | Sgl_setoverflow(result); | ||
513 | } | ||
514 | } | ||
515 | else Sgl_set_exponent(result,result_exponent); | ||
516 | *dstptr = result; | ||
517 | if(inexact) | ||
518 | if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
519 | else Set_inexactflag(); | ||
520 | return(NOEXCEPTION); | ||
521 | } | ||
diff --git a/arch/parisc/math-emu/sgl_float.h b/arch/parisc/math-emu/sgl_float.h new file mode 100644 index 000000000000..82519a5c2ba5 --- /dev/null +++ b/arch/parisc/math-emu/sgl_float.h | |||
@@ -0,0 +1,486 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * Floating-point emulation code | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifdef __NO_PA_HDRS | ||
23 | PA header file -- do not include this header file for non-PA builds. | ||
24 | #endif | ||
25 | |||
26 | /* 32-bit word grabing functions */ | ||
27 | #define Sgl_firstword(value) Sall(value) | ||
28 | #define Sgl_secondword(value) dummy_location | ||
29 | #define Sgl_thirdword(value) dummy_location | ||
30 | #define Sgl_fourthword(value) dummy_location | ||
31 | |||
32 | #define Sgl_sign(object) Ssign(object) | ||
33 | #define Sgl_exponent(object) Sexponent(object) | ||
34 | #define Sgl_signexponent(object) Ssignexponent(object) | ||
35 | #define Sgl_mantissa(object) Smantissa(object) | ||
36 | #define Sgl_exponentmantissa(object) Sexponentmantissa(object) | ||
37 | #define Sgl_all(object) Sall(object) | ||
38 | |||
39 | /* sgl_and_signs ands the sign bits of each argument and puts the result | ||
40 | * into the first argument. sgl_or_signs ors those same sign bits */ | ||
41 | #define Sgl_and_signs( src1dst, src2) \ | ||
42 | Sall(src1dst) = (Sall(src2)|~((unsigned int)1<<31)) & Sall(src1dst) | ||
43 | #define Sgl_or_signs( src1dst, src2) \ | ||
44 | Sall(src1dst) = (Sall(src2)&((unsigned int)1<<31)) | Sall(src1dst) | ||
45 | |||
46 | /* The hidden bit is always the low bit of the exponent */ | ||
47 | #define Sgl_clear_exponent_set_hidden(srcdst) Deposit_sexponent(srcdst,1) | ||
48 | #define Sgl_clear_signexponent_set_hidden(srcdst) \ | ||
49 | Deposit_ssignexponent(srcdst,1) | ||
50 | #define Sgl_clear_sign(srcdst) Sall(srcdst) &= ~((unsigned int)1<<31) | ||
51 | #define Sgl_clear_signexponent(srcdst) Sall(srcdst) &= 0x007fffff | ||
52 | |||
53 | /* varamount must be less than 32 for the next three functions */ | ||
54 | #define Sgl_rightshift(srcdst, varamount) \ | ||
55 | Sall(srcdst) >>= varamount | ||
56 | #define Sgl_leftshift(srcdst, varamount) \ | ||
57 | Sall(srcdst) <<= varamount | ||
58 | #define Sgl_rightshift_exponentmantissa(srcdst, varamount) \ | ||
59 | Sall(srcdst) = \ | ||
60 | (Sexponentmantissa(srcdst) >> varamount) | \ | ||
61 | (Sall(srcdst) & ((unsigned int)1<<31)) | ||
62 | |||
63 | #define Sgl_leftshiftby1_withextent(left,right,result) \ | ||
64 | Shiftdouble(Sall(left),Extall(right),31,Sall(result)) | ||
65 | |||
66 | #define Sgl_rightshiftby1_withextent(left,right,dst) \ | ||
67 | Shiftdouble(Sall(left),Extall(right),1,Extall(right)) | ||
68 | #define Sgl_arithrightshiftby1(srcdst) \ | ||
69 | Sall(srcdst) = (int)Sall(srcdst) >> 1 | ||
70 | |||
71 | /* Sign extend the sign bit with an integer destination */ | ||
72 | #define Sgl_signextendedsign(value) Ssignedsign(value) | ||
73 | |||
74 | #define Sgl_isone_hidden(sgl_value) (Shidden(sgl_value)) | ||
75 | #define Sgl_increment(sgl_value) Sall(sgl_value) += 1 | ||
76 | #define Sgl_increment_mantissa(sgl_value) \ | ||
77 | Deposit_smantissa(sgl_value,sgl_value+1) | ||
78 | #define Sgl_decrement(sgl_value) Sall(sgl_value) -= 1 | ||
79 | |||
80 | #define Sgl_isone_sign(sgl_value) (Is_ssign(sgl_value)!=0) | ||
81 | #define Sgl_isone_hiddenoverflow(sgl_value) \ | ||
82 | (Is_shiddenoverflow(sgl_value)!=0) | ||
83 | #define Sgl_isone_lowmantissa(sgl_value) (Is_slow(sgl_value)!=0) | ||
84 | #define Sgl_isone_signaling(sgl_value) (Is_ssignaling(sgl_value)!=0) | ||
85 | #define Sgl_is_signalingnan(sgl_value) (Ssignalingnan(sgl_value)==0x1ff) | ||
86 | #define Sgl_isnotzero(sgl_value) (Sall(sgl_value)!=0) | ||
87 | #define Sgl_isnotzero_hiddenhigh7mantissa(sgl_value) \ | ||
88 | (Shiddenhigh7mantissa(sgl_value)!=0) | ||
89 | #define Sgl_isnotzero_low4(sgl_value) (Slow4(sgl_value)!=0) | ||
90 | #define Sgl_isnotzero_exponent(sgl_value) (Sexponent(sgl_value)!=0) | ||
91 | #define Sgl_isnotzero_mantissa(sgl_value) (Smantissa(sgl_value)!=0) | ||
92 | #define Sgl_isnotzero_exponentmantissa(sgl_value) \ | ||
93 | (Sexponentmantissa(sgl_value)!=0) | ||
94 | #define Sgl_iszero(sgl_value) (Sall(sgl_value)==0) | ||
95 | #define Sgl_iszero_signaling(sgl_value) (Is_ssignaling(sgl_value)==0) | ||
96 | #define Sgl_iszero_hidden(sgl_value) (Is_shidden(sgl_value)==0) | ||
97 | #define Sgl_iszero_hiddenoverflow(sgl_value) \ | ||
98 | (Is_shiddenoverflow(sgl_value)==0) | ||
99 | #define Sgl_iszero_hiddenhigh3mantissa(sgl_value) \ | ||
100 | (Shiddenhigh3mantissa(sgl_value)==0) | ||
101 | #define Sgl_iszero_hiddenhigh7mantissa(sgl_value) \ | ||
102 | (Shiddenhigh7mantissa(sgl_value)==0) | ||
103 | #define Sgl_iszero_sign(sgl_value) (Is_ssign(sgl_value)==0) | ||
104 | #define Sgl_iszero_exponent(sgl_value) (Sexponent(sgl_value)==0) | ||
105 | #define Sgl_iszero_mantissa(sgl_value) (Smantissa(sgl_value)==0) | ||
106 | #define Sgl_iszero_exponentmantissa(sgl_value) \ | ||
107 | (Sexponentmantissa(sgl_value)==0) | ||
108 | #define Sgl_isinfinity_exponent(sgl_value) \ | ||
109 | (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT) | ||
110 | #define Sgl_isnotinfinity_exponent(sgl_value) \ | ||
111 | (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT) | ||
112 | #define Sgl_isinfinity(sgl_value) \ | ||
113 | (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \ | ||
114 | Sgl_mantissa(sgl_value)==0) | ||
115 | #define Sgl_isnan(sgl_value) \ | ||
116 | (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \ | ||
117 | Sgl_mantissa(sgl_value)!=0) | ||
118 | #define Sgl_isnotnan(sgl_value) \ | ||
119 | (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT || \ | ||
120 | Sgl_mantissa(sgl_value)==0) | ||
121 | #define Sgl_islessthan(sgl_op1,sgl_op2) \ | ||
122 | (Sall(sgl_op1) < Sall(sgl_op2)) | ||
123 | #define Sgl_isgreaterthan(sgl_op1,sgl_op2) \ | ||
124 | (Sall(sgl_op1) > Sall(sgl_op2)) | ||
125 | #define Sgl_isnotlessthan(sgl_op1,sgl_op2) \ | ||
126 | (Sall(sgl_op1) >= Sall(sgl_op2)) | ||
127 | #define Sgl_isequal(sgl_op1,sgl_op2) \ | ||
128 | (Sall(sgl_op1) == Sall(sgl_op2)) | ||
129 | |||
130 | #define Sgl_leftshiftby8(sgl_value) \ | ||
131 | Sall(sgl_value) <<= 8 | ||
132 | #define Sgl_leftshiftby4(sgl_value) \ | ||
133 | Sall(sgl_value) <<= 4 | ||
134 | #define Sgl_leftshiftby3(sgl_value) \ | ||
135 | Sall(sgl_value) <<= 3 | ||
136 | #define Sgl_leftshiftby2(sgl_value) \ | ||
137 | Sall(sgl_value) <<= 2 | ||
138 | #define Sgl_leftshiftby1(sgl_value) \ | ||
139 | Sall(sgl_value) <<= 1 | ||
140 | #define Sgl_rightshiftby1(sgl_value) \ | ||
141 | Sall(sgl_value) >>= 1 | ||
142 | #define Sgl_rightshiftby4(sgl_value) \ | ||
143 | Sall(sgl_value) >>= 4 | ||
144 | #define Sgl_rightshiftby8(sgl_value) \ | ||
145 | Sall(sgl_value) >>= 8 | ||
146 | |||
147 | #define Sgl_ismagnitudeless(signlessleft,signlessright) \ | ||
148 | /* unsigned int signlessleft, signlessright; */ \ | ||
149 | (signlessleft < signlessright) | ||
150 | |||
151 | |||
152 | #define Sgl_copytoint_exponentmantissa(source,dest) \ | ||
153 | dest = Sexponentmantissa(source) | ||
154 | |||
155 | /* A quiet NaN has the high mantissa bit clear and at least on other (in this | ||
156 | * case the adjacent bit) bit set. */ | ||
157 | #define Sgl_set_quiet(sgl_value) Deposit_shigh2mantissa(sgl_value,1) | ||
158 | #define Sgl_set_exponent(sgl_value,exp) Deposit_sexponent(sgl_value,exp) | ||
159 | |||
160 | #define Sgl_set_mantissa(dest,value) Deposit_smantissa(dest,value) | ||
161 | #define Sgl_set_exponentmantissa(dest,value) \ | ||
162 | Deposit_sexponentmantissa(dest,value) | ||
163 | |||
164 | /* An infinity is represented with the max exponent and a zero mantissa */ | ||
165 | #define Sgl_setinfinity_exponent(sgl_value) \ | ||
166 | Deposit_sexponent(sgl_value,SGL_INFINITY_EXPONENT) | ||
167 | #define Sgl_setinfinity_exponentmantissa(sgl_value) \ | ||
168 | Deposit_sexponentmantissa(sgl_value, \ | ||
169 | (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH)))) | ||
170 | #define Sgl_setinfinitypositive(sgl_value) \ | ||
171 | Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | ||
172 | #define Sgl_setinfinitynegative(sgl_value) \ | ||
173 | Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) \ | ||
174 | | ((unsigned int)1<<31) | ||
175 | #define Sgl_setinfinity(sgl_value,sign) \ | ||
176 | Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | \ | ||
177 | ((unsigned int)sign << 31) | ||
178 | #define Sgl_sethigh4bits(sgl_value, extsign) \ | ||
179 | Deposit_shigh4(sgl_value,extsign) | ||
180 | #define Sgl_set_sign(sgl_value,sign) Deposit_ssign(sgl_value,sign) | ||
181 | #define Sgl_invert_sign(sgl_value) \ | ||
182 | Deposit_ssign(sgl_value,~Ssign(sgl_value)) | ||
183 | #define Sgl_setone_sign(sgl_value) Deposit_ssign(sgl_value,1) | ||
184 | #define Sgl_setone_lowmantissa(sgl_value) Deposit_slow(sgl_value,1) | ||
185 | #define Sgl_setzero_sign(sgl_value) Sall(sgl_value) &= 0x7fffffff | ||
186 | #define Sgl_setzero_exponent(sgl_value) Sall(sgl_value) &= 0x807fffff | ||
187 | #define Sgl_setzero_mantissa(sgl_value) Sall(sgl_value) &= 0xff800000 | ||
188 | #define Sgl_setzero_exponentmantissa(sgl_value) Sall(sgl_value) &= 0x80000000 | ||
189 | #define Sgl_setzero(sgl_value) Sall(sgl_value) = 0 | ||
190 | #define Sgl_setnegativezero(sgl_value) Sall(sgl_value) = (unsigned int)1 << 31 | ||
191 | |||
192 | /* Use following macro for both overflow & underflow conditions */ | ||
193 | #define ovfl - | ||
194 | #define unfl + | ||
195 | #define Sgl_setwrapped_exponent(sgl_value,exponent,op) \ | ||
196 | Deposit_sexponent(sgl_value,(exponent op SGL_WRAP)) | ||
197 | |||
198 | #define Sgl_setlargestpositive(sgl_value) \ | ||
199 | Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ | ||
200 | | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 ) | ||
201 | #define Sgl_setlargestnegative(sgl_value) \ | ||
202 | Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ | ||
203 | | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 ) \ | ||
204 | | ((unsigned int)1<<31) | ||
205 | |||
206 | #define Sgl_setnegativeinfinity(sgl_value) \ | ||
207 | Sall(sgl_value) = \ | ||
208 | ((1<<SGL_EXP_LENGTH) | SGL_INFINITY_EXPONENT) << (32-(1+SGL_EXP_LENGTH)) | ||
209 | #define Sgl_setlargest(sgl_value,sign) \ | ||
210 | Sall(sgl_value) = (unsigned int)sign << 31 | \ | ||
211 | (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ | ||
212 | | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 )) | ||
213 | #define Sgl_setlargest_exponentmantissa(sgl_value) \ | ||
214 | Sall(sgl_value) = Sall(sgl_value) & ((unsigned int)1<<31) | \ | ||
215 | (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ | ||
216 | | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 )) | ||
217 | |||
218 | /* The high bit is always zero so arithmetic or logical shifts will work. */ | ||
219 | #define Sgl_right_align(srcdst,shift,extent) \ | ||
220 | /* sgl_floating_point srcdst; int shift; extension extent */ \ | ||
221 | if (shift < 32) { \ | ||
222 | Extall(extent) = Sall(srcdst) << (32-(shift)); \ | ||
223 | Sall(srcdst) >>= shift; \ | ||
224 | } \ | ||
225 | else { \ | ||
226 | Extall(extent) = Sall(srcdst); \ | ||
227 | Sall(srcdst) = 0; \ | ||
228 | } | ||
229 | #define Sgl_hiddenhigh3mantissa(sgl_value) Shiddenhigh3mantissa(sgl_value) | ||
230 | #define Sgl_hidden(sgl_value) Shidden(sgl_value) | ||
231 | #define Sgl_lowmantissa(sgl_value) Slow(sgl_value) | ||
232 | |||
233 | /* The left argument is never smaller than the right argument */ | ||
234 | #define Sgl_subtract(sgl_left,sgl_right,sgl_result) \ | ||
235 | Sall(sgl_result) = Sall(sgl_left) - Sall(sgl_right) | ||
236 | |||
237 | /* Subtract right augmented with extension from left augmented with zeros and | ||
238 | * store into result and extension. */ | ||
239 | #define Sgl_subtract_withextension(left,right,extent,result) \ | ||
240 | /* sgl_floating_point left,right,result; extension extent */ \ | ||
241 | Sgl_subtract(left,right,result); \ | ||
242 | if((Extall(extent) = 0-Extall(extent))) \ | ||
243 | Sall(result) = Sall(result)-1 | ||
244 | |||
245 | #define Sgl_addition(sgl_left,sgl_right,sgl_result) \ | ||
246 | Sall(sgl_result) = Sall(sgl_left) + Sall(sgl_right) | ||
247 | |||
248 | #define Sgl_xortointp1(left,right,result) \ | ||
249 | result = Sall(left) XOR Sall(right); | ||
250 | |||
251 | #define Sgl_xorfromintp1(left,right,result) \ | ||
252 | Sall(result) = left XOR Sall(right) | ||
253 | |||
254 | /* Need to Initialize */ | ||
255 | #define Sgl_makequietnan(dest) \ | ||
256 | Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \ | ||
257 | | (1<<(32-(1+SGL_EXP_LENGTH+2))) | ||
258 | #define Sgl_makesignalingnan(dest) \ | ||
259 | Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \ | ||
260 | | (1<<(32-(1+SGL_EXP_LENGTH+1))) | ||
261 | |||
262 | #define Sgl_normalize(sgl_opnd,exponent) \ | ||
263 | while(Sgl_iszero_hiddenhigh7mantissa(sgl_opnd)) { \ | ||
264 | Sgl_leftshiftby8(sgl_opnd); \ | ||
265 | exponent -= 8; \ | ||
266 | } \ | ||
267 | if(Sgl_iszero_hiddenhigh3mantissa(sgl_opnd)) { \ | ||
268 | Sgl_leftshiftby4(sgl_opnd); \ | ||
269 | exponent -= 4; \ | ||
270 | } \ | ||
271 | while(Sgl_iszero_hidden(sgl_opnd)) { \ | ||
272 | Sgl_leftshiftby1(sgl_opnd); \ | ||
273 | exponent -= 1; \ | ||
274 | } | ||
275 | |||
276 | #define Sgl_setoverflow(sgl_opnd) \ | ||
277 | /* set result to infinity or largest number */ \ | ||
278 | switch (Rounding_mode()) { \ | ||
279 | case ROUNDPLUS: \ | ||
280 | if (Sgl_isone_sign(sgl_opnd)) { \ | ||
281 | Sgl_setlargestnegative(sgl_opnd); \ | ||
282 | } \ | ||
283 | else { \ | ||
284 | Sgl_setinfinitypositive(sgl_opnd); \ | ||
285 | } \ | ||
286 | break; \ | ||
287 | case ROUNDMINUS: \ | ||
288 | if (Sgl_iszero_sign(sgl_opnd)) { \ | ||
289 | Sgl_setlargestpositive(sgl_opnd); \ | ||
290 | } \ | ||
291 | else { \ | ||
292 | Sgl_setinfinitynegative(sgl_opnd); \ | ||
293 | } \ | ||
294 | break; \ | ||
295 | case ROUNDNEAREST: \ | ||
296 | Sgl_setinfinity_exponentmantissa(sgl_opnd); \ | ||
297 | break; \ | ||
298 | case ROUNDZERO: \ | ||
299 | Sgl_setlargest_exponentmantissa(sgl_opnd); \ | ||
300 | } | ||
301 | |||
302 | #define Sgl_denormalize(opnd,exponent,guard,sticky,inexact) \ | ||
303 | Sgl_clear_signexponent_set_hidden(opnd); \ | ||
304 | if (exponent >= (1 - SGL_P)) { \ | ||
305 | guard = (Sall(opnd) >> -exponent) & 1; \ | ||
306 | if (exponent < 0) sticky |= Sall(opnd) << (32+exponent); \ | ||
307 | inexact = guard | sticky; \ | ||
308 | Sall(opnd) >>= (1-exponent); \ | ||
309 | } \ | ||
310 | else { \ | ||
311 | guard = 0; \ | ||
312 | sticky |= Sall(opnd); \ | ||
313 | inexact = sticky; \ | ||
314 | Sgl_setzero(opnd); \ | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * The fused multiply add instructions requires a single extended format, | ||
319 | * with 48 bits of mantissa. | ||
320 | */ | ||
321 | #define SGLEXT_THRESHOLD 48 | ||
322 | |||
323 | #define Sglext_setzero(valA,valB) \ | ||
324 | Sextallp1(valA) = 0; Sextallp2(valB) = 0 | ||
325 | |||
326 | #define Sglext_isnotzero_mantissap2(valB) (Sextallp2(valB)!=0) | ||
327 | #define Sglext_isone_lowp1(val) (Sextlowp1(val)!=0) | ||
328 | #define Sglext_isone_highp2(val) (Sexthighp2(val)!=0) | ||
329 | #define Sglext_isnotzero_low31p2(val) (Sextlow31p2(val)!=0) | ||
330 | #define Sglext_iszero(valA,valB) (Sextallp1(valA)==0 && Sextallp2(valB)==0) | ||
331 | |||
332 | #define Sgl_copytoptr(src,destptr) *destptr = src | ||
333 | #define Sgl_copyfromptr(srcptr,dest) dest = *srcptr | ||
334 | #define Sglext_copy(srca,srcb,desta,destb) \ | ||
335 | Sextallp1(desta) = Sextallp1(srca); \ | ||
336 | Sextallp2(destb) = Sextallp2(srcb) | ||
337 | #define Sgl_copyto_sglext(src1,dest1,dest2) \ | ||
338 | Sextallp1(dest1) = Sall(src1); Sextallp2(dest2) = 0 | ||
339 | |||
340 | #define Sglext_swap_lower(leftp2,rightp2) \ | ||
341 | Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \ | ||
342 | Sextallp2(rightp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \ | ||
343 | Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2) | ||
344 | |||
345 | #define Sglext_setone_lowmantissap2(value) Deposit_dlowp2(value,1) | ||
346 | |||
347 | /* The high bit is always zero so arithmetic or logical shifts will work. */ | ||
348 | #define Sglext_right_align(srcdstA,srcdstB,shift) \ | ||
349 | {int shiftamt, sticky; \ | ||
350 | shiftamt = shift % 32; \ | ||
351 | sticky = 0; \ | ||
352 | switch (shift/32) { \ | ||
353 | case 0: if (shiftamt > 0) { \ | ||
354 | sticky = Sextallp2(srcdstB) << 32 - (shiftamt); \ | ||
355 | Variable_shift_double(Sextallp1(srcdstA), \ | ||
356 | Sextallp2(srcdstB),shiftamt,Sextallp2(srcdstB)); \ | ||
357 | Sextallp1(srcdstA) >>= shiftamt; \ | ||
358 | } \ | ||
359 | break; \ | ||
360 | case 1: if (shiftamt > 0) { \ | ||
361 | sticky = (Sextallp1(srcdstA) << 32 - (shiftamt)) | \ | ||
362 | Sextallp2(srcdstB); \ | ||
363 | } \ | ||
364 | else { \ | ||
365 | sticky = Sextallp2(srcdstB); \ | ||
366 | } \ | ||
367 | Sextallp2(srcdstB) = Sextallp1(srcdstA) >> shiftamt; \ | ||
368 | Sextallp1(srcdstA) = 0; \ | ||
369 | break; \ | ||
370 | } \ | ||
371 | if (sticky) Sglext_setone_lowmantissap2(srcdstB); \ | ||
372 | } | ||
373 | |||
374 | /* The left argument is never smaller than the right argument */ | ||
375 | #define Sglext_subtract(lefta,leftb,righta,rightb,resulta,resultb) \ | ||
376 | if( Sextallp2(rightb) > Sextallp2(leftb) ) Sextallp1(lefta)--; \ | ||
377 | Sextallp2(resultb) = Sextallp2(leftb) - Sextallp2(rightb); \ | ||
378 | Sextallp1(resulta) = Sextallp1(lefta) - Sextallp1(righta) | ||
379 | |||
380 | #define Sglext_addition(lefta,leftb,righta,rightb,resulta,resultb) \ | ||
381 | /* If the sum of the low words is less than either source, then \ | ||
382 | * an overflow into the next word occurred. */ \ | ||
383 | if ((Sextallp2(resultb) = Sextallp2(leftb)+Sextallp2(rightb)) < \ | ||
384 | Sextallp2(rightb)) \ | ||
385 | Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)+1; \ | ||
386 | else Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta) | ||
387 | |||
388 | |||
389 | #define Sglext_arithrightshiftby1(srcdstA,srcdstB) \ | ||
390 | Shiftdouble(Sextallp1(srcdstA),Sextallp2(srcdstB),1,Sextallp2(srcdstB)); \ | ||
391 | Sextallp1(srcdstA) = (int)Sextallp1(srcdstA) >> 1 | ||
392 | |||
393 | #define Sglext_leftshiftby8(valA,valB) \ | ||
394 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),24,Sextallp1(valA)); \ | ||
395 | Sextallp2(valB) <<= 8 | ||
396 | #define Sglext_leftshiftby4(valA,valB) \ | ||
397 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),28,Sextallp1(valA)); \ | ||
398 | Sextallp2(valB) <<= 4 | ||
399 | #define Sglext_leftshiftby3(valA,valB) \ | ||
400 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),29,Sextallp1(valA)); \ | ||
401 | Sextallp2(valB) <<= 3 | ||
402 | #define Sglext_leftshiftby2(valA,valB) \ | ||
403 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),30,Sextallp1(valA)); \ | ||
404 | Sextallp2(valB) <<= 2 | ||
405 | #define Sglext_leftshiftby1(valA,valB) \ | ||
406 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),31,Sextallp1(valA)); \ | ||
407 | Sextallp2(valB) <<= 1 | ||
408 | |||
409 | #define Sglext_rightshiftby4(valueA,valueB) \ | ||
410 | Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),4,Sextallp2(valueB)); \ | ||
411 | Sextallp1(valueA) >>= 4 | ||
412 | #define Sglext_rightshiftby3(valueA,valueB) \ | ||
413 | Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),3,Sextallp2(valueB)); \ | ||
414 | Sextallp1(valueA) >>= 3 | ||
415 | #define Sglext_rightshiftby1(valueA,valueB) \ | ||
416 | Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),1,Sextallp2(valueB)); \ | ||
417 | Sextallp1(valueA) >>= 1 | ||
418 | |||
419 | #define Sglext_xortointp1(left,right,result) Sgl_xortointp1(left,right,result) | ||
420 | #define Sglext_xorfromintp1(left,right,result) \ | ||
421 | Sgl_xorfromintp1(left,right,result) | ||
422 | #define Sglext_copytoint_exponentmantissa(src,dest) \ | ||
423 | Sgl_copytoint_exponentmantissa(src,dest) | ||
424 | #define Sglext_ismagnitudeless(signlessleft,signlessright) \ | ||
425 | Sgl_ismagnitudeless(signlessleft,signlessright) | ||
426 | |||
427 | #define Sglext_set_sign(dbl_value,sign) Sgl_set_sign(dbl_value,sign) | ||
428 | #define Sglext_clear_signexponent_set_hidden(srcdst) \ | ||
429 | Sgl_clear_signexponent_set_hidden(srcdst) | ||
430 | #define Sglext_clear_signexponent(srcdst) Sgl_clear_signexponent(srcdst) | ||
431 | #define Sglext_clear_sign(srcdst) Sgl_clear_sign(srcdst) | ||
432 | #define Sglext_isone_hidden(dbl_value) Sgl_isone_hidden(dbl_value) | ||
433 | |||
434 | #define Sglext_denormalize(opndp1,opndp2,exponent,is_tiny) \ | ||
435 | {int sticky; \ | ||
436 | is_tiny = TRUE; \ | ||
437 | if (exponent == 0 && Sextallp2(opndp2)) { \ | ||
438 | switch (Rounding_mode()) { \ | ||
439 | case ROUNDPLUS: \ | ||
440 | if (Sgl_iszero_sign(opndp1)) \ | ||
441 | if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \ | ||
442 | is_tiny = FALSE; \ | ||
443 | break; \ | ||
444 | case ROUNDMINUS: \ | ||
445 | if (Sgl_isone_sign(opndp1)) { \ | ||
446 | if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \ | ||
447 | is_tiny = FALSE; \ | ||
448 | } \ | ||
449 | break; \ | ||
450 | case ROUNDNEAREST: \ | ||
451 | if (Sglext_isone_highp2(opndp2) && \ | ||
452 | (Sglext_isone_lowp1(opndp1) || \ | ||
453 | Sglext_isnotzero_low31p2(opndp2))) \ | ||
454 | if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \ | ||
455 | is_tiny = FALSE; \ | ||
456 | break; \ | ||
457 | } \ | ||
458 | } \ | ||
459 | Sglext_clear_signexponent_set_hidden(opndp1); \ | ||
460 | if (exponent >= (1-DBL_P)) { \ | ||
461 | if (exponent >= -31) { \ | ||
462 | if (exponent > -31) { \ | ||
463 | sticky = Sextallp2(opndp2) << 31+exponent; \ | ||
464 | Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \ | ||
465 | Sextallp1(opndp1) >>= 1-exponent; \ | ||
466 | } \ | ||
467 | else { \ | ||
468 | sticky = Sextallp2(opndp2); \ | ||
469 | Sextallp2(opndp2) = Sextallp1(opndp1); \ | ||
470 | Sextallp1(opndp1) = 0; \ | ||
471 | } \ | ||
472 | } \ | ||
473 | else { \ | ||
474 | sticky = (Sextallp1(opndp1) << 31+exponent) | \ | ||
475 | Sextallp2(opndp2); \ | ||
476 | Sextallp2(opndp2) = Sextallp1(opndp1) >> -31-exponent; \ | ||
477 | Sextallp1(opndp1) = 0; \ | ||
478 | } \ | ||
479 | } \ | ||
480 | else { \ | ||
481 | sticky = Sextallp1(opndp1) | Sextallp2(opndp2); \ | ||
482 | Sglext_setzero(opndp1,opndp2); \ | ||
483 | } \ | ||
484 | if (sticky) Sglext_setone_lowmantissap2(opndp2); \ | ||
485 | exponent = 0; \ | ||
486 | } | ||