Annotation of sys/arch/hppa/spmath/sfdiv.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sfdiv.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: /* @(#)sfdiv.c: Revision: 2.9.88.1 Date: 93/12/07 15:07:05 */
16:
17: #include "float.h"
18: #include "sgl_float.h"
19:
20: /*
21: * Single Precision Floating-point Divide
22: */
23: int
24: sgl_fdiv(srcptr1,srcptr2,dstptr,status)
25: sgl_floating_point *srcptr1, *srcptr2, *dstptr;
26: unsigned int *status;
27: {
28: register unsigned int opnd1, opnd2, opnd3, result;
29: register int dest_exponent, count;
30: register int inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
31: int is_tiny;
32:
33: opnd1 = *srcptr1;
34: opnd2 = *srcptr2;
35: /*
36: * set sign bit of result
37: */
38: if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);
39: else Sgl_setzero(result);
40: /*
41: * check first operand for NaN's or infinity
42: */
43: if (Sgl_isinfinity_exponent(opnd1)) {
44: if (Sgl_iszero_mantissa(opnd1)) {
45: if (Sgl_isnotnan(opnd2)) {
46: if (Sgl_isinfinity(opnd2)) {
47: /*
48: * invalid since both operands
49: * are infinity
50: */
51: if (Is_invalidtrap_enabled())
52: return(INVALIDEXCEPTION);
53: Set_invalidflag();
54: Sgl_makequietnan(result);
55: *dstptr = result;
56: return(NOEXCEPTION);
57: }
58: /*
59: * return infinity
60: */
61: Sgl_setinfinity_exponentmantissa(result);
62: *dstptr = result;
63: return(NOEXCEPTION);
64: }
65: }
66: else {
67: /*
68: * is NaN; signaling or quiet?
69: */
70: if (Sgl_isone_signaling(opnd1)) {
71: /* trap if INVALIDTRAP enabled */
72: if (Is_invalidtrap_enabled())
73: return(INVALIDEXCEPTION);
74: /* make NaN quiet */
75: Set_invalidflag();
76: Sgl_set_quiet(opnd1);
77: }
78: /*
79: * is second operand a signaling NaN?
80: */
81: else if (Sgl_is_signalingnan(opnd2)) {
82: /* trap if INVALIDTRAP enabled */
83: if (Is_invalidtrap_enabled())
84: return(INVALIDEXCEPTION);
85: /* make NaN quiet */
86: Set_invalidflag();
87: Sgl_set_quiet(opnd2);
88: *dstptr = opnd2;
89: return(NOEXCEPTION);
90: }
91: /*
92: * return quiet NaN
93: */
94: *dstptr = opnd1;
95: return(NOEXCEPTION);
96: }
97: }
98: /*
99: * check second operand for NaN's or infinity
100: */
101: if (Sgl_isinfinity_exponent(opnd2)) {
102: if (Sgl_iszero_mantissa(opnd2)) {
103: /*
104: * return zero
105: */
106: Sgl_setzero_exponentmantissa(result);
107: *dstptr = result;
108: return(NOEXCEPTION);
109: }
110: /*
111: * is NaN; signaling or quiet?
112: */
113: if (Sgl_isone_signaling(opnd2)) {
114: /* trap if INVALIDTRAP enabled */
115: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
116: /* make NaN quiet */
117: Set_invalidflag();
118: Sgl_set_quiet(opnd2);
119: }
120: /*
121: * return quiet NaN
122: */
123: *dstptr = opnd2;
124: return(NOEXCEPTION);
125: }
126: /*
127: * check for division by zero
128: */
129: if (Sgl_iszero_exponentmantissa(opnd2)) {
130: if (Sgl_iszero_exponentmantissa(opnd1)) {
131: /* invalid since both operands are zero */
132: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
133: Set_invalidflag();
134: Sgl_makequietnan(result);
135: *dstptr = result;
136: return(NOEXCEPTION);
137: }
138: if (Is_divisionbyzerotrap_enabled())
139: return(DIVISIONBYZEROEXCEPTION);
140: Set_divisionbyzeroflag();
141: Sgl_setinfinity_exponentmantissa(result);
142: *dstptr = result;
143: return(NOEXCEPTION);
144: }
145: /*
146: * Generate exponent
147: */
148: dest_exponent = Sgl_exponent(opnd1) - Sgl_exponent(opnd2) + SGL_BIAS;
149:
150: /*
151: * Generate mantissa
152: */
153: if (Sgl_isnotzero_exponent(opnd1)) {
154: /* set hidden bit */
155: Sgl_clear_signexponent_set_hidden(opnd1);
156: }
157: else {
158: /* check for zero */
159: if (Sgl_iszero_mantissa(opnd1)) {
160: Sgl_setzero_exponentmantissa(result);
161: *dstptr = result;
162: return(NOEXCEPTION);
163: }
164: /* is denormalized; want to normalize */
165: Sgl_clear_signexponent(opnd1);
166: Sgl_leftshiftby1(opnd1);
167: Sgl_normalize(opnd1,dest_exponent);
168: }
169: /* opnd2 needs to have hidden bit set with msb in hidden bit */
170: if (Sgl_isnotzero_exponent(opnd2)) {
171: Sgl_clear_signexponent_set_hidden(opnd2);
172: }
173: else {
174: /* is denormalized; want to normalize */
175: Sgl_clear_signexponent(opnd2);
176: Sgl_leftshiftby1(opnd2);
177: while(Sgl_iszero_hiddenhigh7mantissa(opnd2)) {
178: Sgl_leftshiftby8(opnd2);
179: dest_exponent += 8;
180: }
181: if(Sgl_iszero_hiddenhigh3mantissa(opnd2)) {
182: Sgl_leftshiftby4(opnd2);
183: dest_exponent += 4;
184: }
185: while(Sgl_iszero_hidden(opnd2)) {
186: Sgl_leftshiftby1(opnd2);
187: dest_exponent += 1;
188: }
189: }
190:
191: /* Divide the source mantissas */
192:
193: /*
194: * A non_restoring divide algorithm is used.
195: */
196: Sgl_subtract(opnd1,opnd2,opnd1);
197: Sgl_setzero(opnd3);
198: for (count=1;count<=SGL_P && Sgl_all(opnd1);count++) {
199: Sgl_leftshiftby1(opnd1);
200: Sgl_leftshiftby1(opnd3);
201: if (Sgl_iszero_sign(opnd1)) {
202: Sgl_setone_lowmantissa(opnd3);
203: Sgl_subtract(opnd1,opnd2,opnd1);
204: }
205: else Sgl_addition(opnd1,opnd2,opnd1);
206: }
207: if (count <= SGL_P) {
208: Sgl_leftshiftby1(opnd3);
209: Sgl_setone_lowmantissa(opnd3);
210: Sgl_leftshift(opnd3,SGL_P-count);
211: if (Sgl_iszero_hidden(opnd3)) {
212: Sgl_leftshiftby1(opnd3);
213: dest_exponent--;
214: }
215: }
216: else {
217: if (Sgl_iszero_hidden(opnd3)) {
218: /* need to get one more bit of result */
219: Sgl_leftshiftby1(opnd1);
220: Sgl_leftshiftby1(opnd3);
221: if (Sgl_iszero_sign(opnd1)) {
222: Sgl_setone_lowmantissa(opnd3);
223: Sgl_subtract(opnd1,opnd2,opnd1);
224: }
225: else Sgl_addition(opnd1,opnd2,opnd1);
226: dest_exponent--;
227: }
228: if (Sgl_iszero_sign(opnd1)) guardbit = TRUE;
229: stickybit = Sgl_all(opnd1);
230: }
231: inexact = guardbit | stickybit;
232:
233: /*
234: * round result
235: */
236: if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
237: Sgl_clear_signexponent(opnd3);
238: switch (Rounding_mode()) {
239: case ROUNDPLUS:
240: if (Sgl_iszero_sign(result))
241: Sgl_increment_mantissa(opnd3);
242: break;
243: case ROUNDMINUS:
244: if (Sgl_isone_sign(result))
245: Sgl_increment_mantissa(opnd3);
246: break;
247: case ROUNDNEAREST:
248: if (guardbit &&
249: (stickybit || Sgl_isone_lowmantissa(opnd3)))
250: Sgl_increment_mantissa(opnd3);
251: }
252: if (Sgl_isone_hidden(opnd3)) dest_exponent++;
253: }
254: Sgl_set_mantissa(result,opnd3);
255:
256: /*
257: * Test for overflow
258: */
259: if (dest_exponent >= SGL_INFINITY_EXPONENT) {
260: /* trap if OVERFLOWTRAP enabled */
261: if (Is_overflowtrap_enabled()) {
262: /*
263: * Adjust bias of result
264: */
265: Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
266: *dstptr = result;
267: if (inexact) {
268: if (Is_inexacttrap_enabled())
269: return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
270: else Set_inexactflag();
271: }
272: return(OVERFLOWEXCEPTION);
273: }
274: Set_overflowflag();
275: /* set result to infinity or largest number */
276: Sgl_setoverflow(result);
277: inexact = TRUE;
278: }
279: /*
280: * Test for underflow
281: */
282: else if (dest_exponent <= 0) {
283: /* trap if UNDERFLOWTRAP enabled */
284: if (Is_underflowtrap_enabled()) {
285: /*
286: * Adjust bias of result
287: */
288: Sgl_setwrapped_exponent(result,dest_exponent,unfl);
289: *dstptr = result;
290: if (inexact) {
291: if (Is_inexacttrap_enabled())
292: return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
293: else Set_inexactflag();
294: }
295: return(UNDERFLOWEXCEPTION);
296: }
297:
298: /* Determine if should set underflow flag */
299: is_tiny = TRUE;
300: if (dest_exponent == 0 && inexact) {
301: switch (Rounding_mode()) {
302: case ROUNDPLUS:
303: if (Sgl_iszero_sign(result)) {
304: Sgl_increment(opnd3);
305: if (Sgl_isone_hiddenoverflow(opnd3))
306: is_tiny = FALSE;
307: Sgl_decrement(opnd3);
308: }
309: break;
310: case ROUNDMINUS:
311: if (Sgl_isone_sign(result)) {
312: Sgl_increment(opnd3);
313: if (Sgl_isone_hiddenoverflow(opnd3))
314: is_tiny = FALSE;
315: Sgl_decrement(opnd3);
316: }
317: break;
318: case ROUNDNEAREST:
319: if (guardbit && (stickybit ||
320: Sgl_isone_lowmantissa(opnd3))) {
321: Sgl_increment(opnd3);
322: if (Sgl_isone_hiddenoverflow(opnd3))
323: is_tiny = FALSE;
324: Sgl_decrement(opnd3);
325: }
326: break;
327: }
328: }
329:
330: /*
331: * denormalize result or set to signed zero
332: */
333: stickybit = inexact;
334: Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
335:
336: /* return rounded number */
337: if (inexact) {
338: switch (Rounding_mode()) {
339: case ROUNDPLUS:
340: if (Sgl_iszero_sign(result)) {
341: Sgl_increment(opnd3);
342: }
343: break;
344: case ROUNDMINUS:
345: if (Sgl_isone_sign(result)) {
346: Sgl_increment(opnd3);
347: }
348: break;
349: case ROUNDNEAREST:
350: if (guardbit && (stickybit ||
351: Sgl_isone_lowmantissa(opnd3))) {
352: Sgl_increment(opnd3);
353: }
354: break;
355: }
356: if (is_tiny) Set_underflowflag();
357: }
358: Sgl_set_exponentmantissa(result,opnd3);
359: }
360: else Sgl_set_exponent(result,dest_exponent);
361: *dstptr = result;
362: /* check for inexact */
363: if (inexact) {
364: if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
365: else Set_inexactflag();
366: }
367: return(NOEXCEPTION);
368: }
CVSweb