Annotation of sys/arch/hppa/spmath/dfdiv.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: dfdiv.c,v 1.5 2002/05/07 22:19:30 mickey Exp $ */
2: /*
3: (c) Copyright 1986 HEWLETT-PACKARD COMPANY
4: To anyone who acknowledges that this file is provided "AS IS"
5: without any express or implied warranty:
6: permission to use, copy, modify, and distribute this file
7: for any purpose is hereby granted without fee, provided that
8: the above copyright notice and this notice appears in all
9: copies, and that the name of Hewlett-Packard Company not be
10: used in advertising or publicity pertaining to distribution
11: of the software without specific, written prior permission.
12: Hewlett-Packard Company makes no representations about the
13: suitability of this software for any purpose.
14: */
15: /* @(#)dfdiv.c: Revision: 2.11.88.1 Date: 93/12/07 15:05:39 */
16:
17: #include "float.h"
18: #include "dbl_float.h"
19:
20: /*
21: * Double Precision Floating-point Divide
22: */
23:
24: int
25: dbl_fdiv(srcptr1,srcptr2,dstptr,status)
26: dbl_floating_point *srcptr1, *srcptr2, *dstptr;
27: unsigned int *status;
28: {
29: register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
30: register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
31: register int dest_exponent, count;
32: register int inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
33: int is_tiny;
34:
35: Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
36: Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
37: /*
38: * set sign bit of result
39: */
40: if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
41: Dbl_setnegativezerop1(resultp1);
42: else Dbl_setzerop1(resultp1);
43: /*
44: * check first operand for NaN's or infinity
45: */
46: if (Dbl_isinfinity_exponent(opnd1p1)) {
47: if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
48: if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
49: if (Dbl_isinfinity(opnd2p1,opnd2p2)) {
50: /*
51: * invalid since both operands
52: * are infinity
53: */
54: if (Is_invalidtrap_enabled())
55: return(INVALIDEXCEPTION);
56: Set_invalidflag();
57: Dbl_makequietnan(resultp1,resultp2);
58: Dbl_copytoptr(resultp1,resultp2,dstptr);
59: return(NOEXCEPTION);
60: }
61: /*
62: * return infinity
63: */
64: Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
65: Dbl_copytoptr(resultp1,resultp2,dstptr);
66: return(NOEXCEPTION);
67: }
68: }
69: else {
70: /*
71: * is NaN; signaling or quiet?
72: */
73: if (Dbl_isone_signaling(opnd1p1)) {
74: /* trap if INVALIDTRAP enabled */
75: if (Is_invalidtrap_enabled())
76: return(INVALIDEXCEPTION);
77: /* make NaN quiet */
78: Set_invalidflag();
79: Dbl_set_quiet(opnd1p1);
80: }
81: /*
82: * is second operand a signaling NaN?
83: */
84: else if (Dbl_is_signalingnan(opnd2p1)) {
85: /* trap if INVALIDTRAP enabled */
86: if (Is_invalidtrap_enabled())
87: return(INVALIDEXCEPTION);
88: /* make NaN quiet */
89: Set_invalidflag();
90: Dbl_set_quiet(opnd2p1);
91: Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
92: return(NOEXCEPTION);
93: }
94: /*
95: * return quiet NaN
96: */
97: Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
98: return(NOEXCEPTION);
99: }
100: }
101: /*
102: * check second operand for NaN's or infinity
103: */
104: if (Dbl_isinfinity_exponent(opnd2p1)) {
105: if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
106: /*
107: * return zero
108: */
109: Dbl_setzero_exponentmantissa(resultp1,resultp2);
110: Dbl_copytoptr(resultp1,resultp2,dstptr);
111: return(NOEXCEPTION);
112: }
113: /*
114: * is NaN; signaling or quiet?
115: */
116: if (Dbl_isone_signaling(opnd2p1)) {
117: /* trap if INVALIDTRAP enabled */
118: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
119: /* make NaN quiet */
120: Set_invalidflag();
121: Dbl_set_quiet(opnd2p1);
122: }
123: /*
124: * return quiet NaN
125: */
126: Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
127: return(NOEXCEPTION);
128: }
129: /*
130: * check for division by zero
131: */
132: if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
133: if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
134: /* invalid since both operands are zero */
135: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
136: Set_invalidflag();
137: Dbl_makequietnan(resultp1,resultp2);
138: Dbl_copytoptr(resultp1,resultp2,dstptr);
139: return(NOEXCEPTION);
140: }
141: if (Is_divisionbyzerotrap_enabled())
142: return(DIVISIONBYZEROEXCEPTION);
143: Set_divisionbyzeroflag();
144: Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
145: Dbl_copytoptr(resultp1,resultp2,dstptr);
146: return(NOEXCEPTION);
147: }
148: /*
149: * Generate exponent
150: */
151: dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS;
152:
153: /*
154: * Generate mantissa
155: */
156: if (Dbl_isnotzero_exponent(opnd1p1)) {
157: /* set hidden bit */
158: Dbl_clear_signexponent_set_hidden(opnd1p1);
159: }
160: else {
161: /* check for zero */
162: if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
163: Dbl_setzero_exponentmantissa(resultp1,resultp2);
164: Dbl_copytoptr(resultp1,resultp2,dstptr);
165: return(NOEXCEPTION);
166: }
167: /* is denormalized, want to normalize */
168: Dbl_clear_signexponent(opnd1p1);
169: Dbl_leftshiftby1(opnd1p1,opnd1p2);
170: Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
171: }
172: /* opnd2 needs to have hidden bit set with msb in hidden bit */
173: if (Dbl_isnotzero_exponent(opnd2p1)) {
174: Dbl_clear_signexponent_set_hidden(opnd2p1);
175: }
176: else {
177: /* is denormalized; want to normalize */
178: Dbl_clear_signexponent(opnd2p1);
179: Dbl_leftshiftby1(opnd2p1,opnd2p2);
180: while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) {
181: dest_exponent+=8;
182: Dbl_leftshiftby8(opnd2p1,opnd2p2);
183: }
184: if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) {
185: dest_exponent+=4;
186: Dbl_leftshiftby4(opnd2p1,opnd2p2);
187: }
188: while (Dbl_iszero_hidden(opnd2p1)) {
189: dest_exponent++;
190: Dbl_leftshiftby1(opnd2p1,opnd2p2);
191: }
192: }
193:
194: /* Divide the source mantissas */
195:
196: /*
197: * A non-restoring divide algorithm is used.
198: */
199: Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
200: Dbl_setzero(opnd3p1,opnd3p2);
201: for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) {
202: Dbl_leftshiftby1(opnd1p1,opnd1p2);
203: Dbl_leftshiftby1(opnd3p1,opnd3p2);
204: if (Dbl_iszero_sign(opnd1p1)) {
205: Dbl_setone_lowmantissap2(opnd3p2);
206: Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
207: }
208: else {
209: Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2);
210: }
211: }
212: if (count <= DBL_P) {
213: Dbl_leftshiftby1(opnd3p1,opnd3p2);
214: Dbl_setone_lowmantissap2(opnd3p2);
215: Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count));
216: if (Dbl_iszero_hidden(opnd3p1)) {
217: Dbl_leftshiftby1(opnd3p1,opnd3p2);
218: dest_exponent--;
219: }
220: }
221: else {
222: if (Dbl_iszero_hidden(opnd3p1)) {
223: /* need to get one more bit of result */
224: Dbl_leftshiftby1(opnd1p1,opnd1p2);
225: Dbl_leftshiftby1(opnd3p1,opnd3p2);
226: if (Dbl_iszero_sign(opnd1p1)) {
227: Dbl_setone_lowmantissap2(opnd3p2);
228: Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
229: }
230: else {
231: Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
232: }
233: dest_exponent--;
234: }
235: if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE;
236: stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2);
237: }
238: inexact = guardbit | stickybit;
239:
240: /*
241: * round result
242: */
243: if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
244: Dbl_clear_signexponent(opnd3p1);
245: switch (Rounding_mode()) {
246: case ROUNDPLUS:
247: if (Dbl_iszero_sign(resultp1))
248: Dbl_increment(opnd3p1,opnd3p2);
249: break;
250: case ROUNDMINUS:
251: if (Dbl_isone_sign(resultp1))
252: Dbl_increment(opnd3p1,opnd3p2);
253: break;
254: case ROUNDNEAREST:
255: if (guardbit && (stickybit ||
256: Dbl_isone_lowmantissap2(opnd3p2))) {
257: Dbl_increment(opnd3p1,opnd3p2);
258: }
259: }
260: if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
261: }
262: Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
263:
264: /*
265: * Test for overflow
266: */
267: if (dest_exponent >= DBL_INFINITY_EXPONENT) {
268: /* trap if OVERFLOWTRAP enabled */
269: if (Is_overflowtrap_enabled()) {
270: /*
271: * Adjust bias of result
272: */
273: Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
274: Dbl_copytoptr(resultp1,resultp2,dstptr);
275: if (inexact) {
276: if (Is_inexacttrap_enabled())
277: return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
278: else
279: Set_inexactflag();
280: }
281: return(OVERFLOWEXCEPTION);
282: }
283: Set_overflowflag();
284: /* set result to infinity or largest number */
285: Dbl_setoverflow(resultp1,resultp2);
286: inexact = TRUE;
287: }
288: /*
289: * Test for underflow
290: */
291: else if (dest_exponent <= 0) {
292: /* trap if UNDERFLOWTRAP enabled */
293: if (Is_underflowtrap_enabled()) {
294: /*
295: * Adjust bias of result
296: */
297: Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
298: Dbl_copytoptr(resultp1,resultp2,dstptr);
299: if (inexact) {
300: if (Is_inexacttrap_enabled())
301: return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
302: else
303: Set_inexactflag();
304: }
305: return(UNDERFLOWEXCEPTION);
306: }
307:
308: /* Determine if should set underflow flag */
309: is_tiny = TRUE;
310: if (dest_exponent == 0 && inexact) {
311: switch (Rounding_mode()) {
312: case ROUNDPLUS:
313: if (Dbl_iszero_sign(resultp1)) {
314: Dbl_increment(opnd3p1,opnd3p2);
315: if (Dbl_isone_hiddenoverflow(opnd3p1))
316: is_tiny = FALSE;
317: Dbl_decrement(opnd3p1,opnd3p2);
318: }
319: break;
320: case ROUNDMINUS:
321: if (Dbl_isone_sign(resultp1)) {
322: Dbl_increment(opnd3p1,opnd3p2);
323: if (Dbl_isone_hiddenoverflow(opnd3p1))
324: is_tiny = FALSE;
325: Dbl_decrement(opnd3p1,opnd3p2);
326: }
327: break;
328: case ROUNDNEAREST:
329: if (guardbit && (stickybit ||
330: Dbl_isone_lowmantissap2(opnd3p2))) {
331: Dbl_increment(opnd3p1,opnd3p2);
332: if (Dbl_isone_hiddenoverflow(opnd3p1))
333: is_tiny = FALSE;
334: Dbl_decrement(opnd3p1,opnd3p2);
335: }
336: break;
337: }
338: }
339:
340: /*
341: * denormalize result or set to signed zero
342: */
343: stickybit = inexact;
344: Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
345: stickybit,inexact);
346:
347: /* return rounded number */
348: if (inexact) {
349: switch (Rounding_mode()) {
350: case ROUNDPLUS:
351: if (Dbl_iszero_sign(resultp1)) {
352: Dbl_increment(opnd3p1,opnd3p2);
353: }
354: break;
355: case ROUNDMINUS:
356: if (Dbl_isone_sign(resultp1)) {
357: Dbl_increment(opnd3p1,opnd3p2);
358: }
359: break;
360: case ROUNDNEAREST:
361: if (guardbit && (stickybit ||
362: Dbl_isone_lowmantissap2(opnd3p2))) {
363: Dbl_increment(opnd3p1,opnd3p2);
364: }
365: break;
366: }
367: if (is_tiny)
368: Set_underflowflag();
369: }
370: Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
371: }
372: else Dbl_set_exponent(resultp1,dest_exponent);
373: Dbl_copytoptr(resultp1,resultp2,dstptr);
374:
375: /* check for inexact */
376: if (inexact) {
377: if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
378: else Set_inexactflag();
379: }
380: return(NOEXCEPTION);
381: }
CVSweb