aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/math-emu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/parisc/math-emu
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/parisc/math-emu')
-rw-r--r--arch/parisc/math-emu/Makefile19
-rw-r--r--arch/parisc/math-emu/README11
-rw-r--r--arch/parisc/math-emu/cnv_float.h377
-rw-r--r--arch/parisc/math-emu/dbl_float.h847
-rw-r--r--arch/parisc/math-emu/decode_exc.c368
-rw-r--r--arch/parisc/math-emu/denormal.c135
-rw-r--r--arch/parisc/math-emu/dfadd.c524
-rw-r--r--arch/parisc/math-emu/dfcmp.c181
-rw-r--r--arch/parisc/math-emu/dfdiv.c400
-rw-r--r--arch/parisc/math-emu/dfmpy.c394
-rw-r--r--arch/parisc/math-emu/dfrem.c297
-rw-r--r--arch/parisc/math-emu/dfsqrt.c195
-rw-r--r--arch/parisc/math-emu/dfsub.c526
-rw-r--r--arch/parisc/math-emu/driver.c128
-rw-r--r--arch/parisc/math-emu/fcnvff.c309
-rw-r--r--arch/parisc/math-emu/fcnvfu.c536
-rw-r--r--arch/parisc/math-emu/fcnvfut.c332
-rw-r--r--arch/parisc/math-emu/fcnvfx.c501
-rw-r--r--arch/parisc/math-emu/fcnvfxt.c328
-rw-r--r--arch/parisc/math-emu/fcnvuf.c318
-rw-r--r--arch/parisc/math-emu/fcnvxf.c386
-rw-r--r--arch/parisc/math-emu/float.h582
-rw-r--r--arch/parisc/math-emu/fmpyfadd.c2655
-rw-r--r--arch/parisc/math-emu/fpbits.h65
-rw-r--r--arch/parisc/math-emu/fpu.h76
-rw-r--r--arch/parisc/math-emu/fpudispatch.c1442
-rw-r--r--arch/parisc/math-emu/frnd.c252
-rw-r--r--arch/parisc/math-emu/hppa.h42
-rw-r--r--arch/parisc/math-emu/math-emu.h27
-rw-r--r--arch/parisc/math-emu/sfadd.c518
-rw-r--r--arch/parisc/math-emu/sfcmp.c155
-rw-r--r--arch/parisc/math-emu/sfdiv.c392
-rw-r--r--arch/parisc/math-emu/sfmpy.c380
-rw-r--r--arch/parisc/math-emu/sfrem.c290
-rw-r--r--arch/parisc/math-emu/sfsqrt.c187
-rw-r--r--arch/parisc/math-emu/sfsub.c521
-rw-r--r--arch/parisc/math-emu/sgl_float.h486
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
6CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \
7 -Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \
8 -Wno-implicit-int
9
10obj-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
19obj-$(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 @@
1All files except driver.c are snapshots from the HP-UX kernel. They've
2been modified as little as possible. Even though they don't fit the
3Linux coding style, please leave them in their funny format just in case
4someone in the future, with access to HP-UX source code, is generous
5enough to update our copies with later changes from HP-UX -- it'll
6make their 'diff' job easier if our code is relatively unmodified.
7
8Required Disclaimer: Hewlett-Packard makes no implied or expressed
9warranties about this code nor any promises to maintain or test it
10in any way. This copy of this snapshot is no longer the property
11of 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
103u_int
104decode_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
56void
57sgl_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
94void
95dbl_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 */
48dbl_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 */
49int
50dbl_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
49int
50dbl_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
49int
50dbl_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
50int
51dbl_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*/
50unsigned int
51dbl_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 */
48int
49dbl_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. */
42struct 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. */
79int
80handle_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*/
53int
54sgl_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*/
140int
141dbl_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*/
58int
59sgl_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*/
179int
180sgl_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*/
300int
301dbl_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*/
423int
424dbl_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*/
59int
60sgl_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*/
128int
129sgl_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*/
198int
199dbl_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*/
267int
268dbl_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*/
57int
58sgl_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*/
154int
155sgl_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*/
275int
276dbl_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*/
386int
387dbl_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*/
58int
59sgl_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*/
122int
123sgl_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*/
196int
197dbl_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*/
261int
262dbl_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
58int
59sgl_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
117int
118sgl_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
158int
159dbl_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
240int
241dbl_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
57int
58sgl_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
128int
129sgl_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
179int
180dbl_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
284int
285dbl_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 */
203typedef 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 */
306typedef int sgl_integer;
307
308/*
309 * Double number.
310 * +-------+-------+-------+-------+-------+-------+-------+-------+
311 * |s| high integer |
312 * +-------+-------+-------+-------+-------+-------+-------+-------+
313 *
314 * +-------+-------+-------+-------+-------+-------+-------+-------+
315 * | low integer |
316 * +-------+-------+-------+-------+-------+-------+-------+-------+
317 */
318struct dint {
319 int wd0;
320 unsigned int wd1;
321};
322
323struct 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
347struct quadwd {
348 int wd0;
349 unsigned int wd1;
350 unsigned int wd2;
351 unsigned int wd3;
352};
353
354typedef struct quadwd quad_integer;
355
356
357/* useful typedefs */
358typedef unsigned int sgl_floating_point;
359typedef struct dblwd dbl_floating_point;
360typedef struct dint dbl_integer;
361typedef 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 */
411typedef int boolean;
412typedef int FORMAT;
413typedef 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
556typedef 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
57int
58dbl_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
719dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
720
721dbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
722unsigned 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
1377sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
1378
1379sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
1380unsigned 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
2018sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
2019
2020sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
2021unsigned 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)
153static u_int decode_0c(u_int, u_int, u_int, u_int *);
154static u_int decode_0e(u_int, u_int, u_int, u_int *);
155static u_int decode_06(u_int, u_int *);
156static u_int decode_26(u_int, u_int *);
157static u_int decode_2e(u_int, u_int *);
158static void update_status_cbit(u_int *, u_int, u_int, u_int);
159#else /* !_PROTOTYPES&&!_lint */
160static u_int decode_0c();
161static u_int decode_0e();
162static u_int decode_06();
163static u_int decode_26();
164static u_int decode_2e();
165static void update_status_cbit();
166#endif /* _PROTOTYPES&&!_lint */
167
168#define VASSERT(x)
169
170static 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 */
193u_int
194fpudispatch(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 */
248u_int
249emfpudispatch(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
286static u_int
287decode_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
703static u_int
704decode_0e(ir,class,subop,fpregs)
705u_int ir,class,subop;
706u_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 */
1115static u_int
1116decode_06(ir,fpregs)
1117u_int ir;
1118u_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 */
1255static u_int
1256decode_26(ir,fpregs)
1257u_int ir;
1258u_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 */
1346static u_int
1347decode_2e(ir,fpregs)
1348u_int ir;
1349u_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 */
1412static void
1413update_status_cbit(status, new_status, fpu_type, y_field)
1414u_int *status, new_status;
1415u_int fpu_type;
1416u_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*/
47int
48sgl_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*/
151int
152dbl_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>
25extern 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 */
48int
49sgl_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 */
48int
49sgl_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
49int
50sgl_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
49int
50sgl_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
50int
51sgl_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*/
50unsigned int
51sgl_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 */
48int
49sgl_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 }