Annotation of sys/arch/hppa/spmath/sfsub.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sfsub.c,v 1.6 2002/11/29 09:27:34 deraadt 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: /* @(#)sfsub.c: Revision: 2.7.88.1 Date: 93/12/07 15:07:15 */
16:
17: #include "float.h"
18: #include "sgl_float.h"
19:
20: /*
21: * Single_subtract: subtract two single precision values.
22: */
23: int
24: sgl_fsub(leftptr, rightptr, dstptr, status)
25: sgl_floating_point *leftptr, *rightptr, *dstptr;
26: unsigned int *status;
27: {
28: register unsigned int left, right, result, extent;
29: register unsigned int signless_upper_left, signless_upper_right, save;
30:
31: register int result_exponent, right_exponent, diff_exponent;
32: register int sign_save, jumpsize;
33: register int inexact = FALSE, underflowtrap;
34:
35: /* Create local copies of the numbers */
36: left = *leftptr;
37: right = *rightptr;
38:
39: /* A zero "save" helps discover equal operands (for later), *
40: * and is used in swapping operands (if needed). */
41: Sgl_xortointp1(left,right,/*to*/save);
42:
43: /*
44: * check first operand for NaN's or infinity
45: */
46: if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
47: {
48: if (Sgl_iszero_mantissa(left))
49: {
50: if (Sgl_isnotnan(right))
51: {
52: if (Sgl_isinfinity(right) && save==0)
53: {
54: /*
55: * invalid since operands are same signed infinity's
56: */
57: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
58: Set_invalidflag();
59: Sgl_makequietnan(result);
60: *dstptr = result;
61: return(NOEXCEPTION);
62: }
63: /*
64: * return infinity
65: */
66: *dstptr = left;
67: return(NOEXCEPTION);
68: }
69: }
70: else
71: {
72: /*
73: * is NaN; signaling or quiet?
74: */
75: if (Sgl_isone_signaling(left))
76: {
77: /* trap if INVALIDTRAP enabled */
78: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
79: /* make NaN quiet */
80: Set_invalidflag();
81: Sgl_set_quiet(left);
82: }
83: /*
84: * is second operand a signaling NaN?
85: */
86: else if (Sgl_is_signalingnan(right))
87: {
88: /* trap if INVALIDTRAP enabled */
89: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
90: /* make NaN quiet */
91: Set_invalidflag();
92: Sgl_set_quiet(right);
93: *dstptr = right;
94: return(NOEXCEPTION);
95: }
96: /*
97: * return quiet NaN
98: */
99: *dstptr = left;
100: return(NOEXCEPTION);
101: }
102: } /* End left NaN or Infinity processing */
103: /*
104: * check second operand for NaN's or infinity
105: */
106: if (Sgl_isinfinity_exponent(right))
107: {
108: if (Sgl_iszero_mantissa(right))
109: {
110: /* return infinity */
111: Sgl_invert_sign(right);
112: *dstptr = right;
113: return(NOEXCEPTION);
114: }
115: /*
116: * is NaN; signaling or quiet?
117: */
118: if (Sgl_isone_signaling(right))
119: {
120: /* trap if INVALIDTRAP enabled */
121: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
122: /* make NaN quiet */
123: Set_invalidflag();
124: Sgl_set_quiet(right);
125: }
126: /*
127: * return quiet NaN
128: */
129: *dstptr = right;
130: return(NOEXCEPTION);
131: } /* End right NaN or Infinity processing */
132:
133: /* Invariant: Must be dealing with finite numbers */
134:
135: /* Compare operands by removing the sign */
136: Sgl_copytoint_exponentmantissa(left,signless_upper_left);
137: Sgl_copytoint_exponentmantissa(right,signless_upper_right);
138:
139: /* sign difference selects sub or add operation. */
140: if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
141: {
142: /* Set the left operand to the larger one by XOR swap *
143: * First finish the first word using "save" */
144: Sgl_xorfromintp1(save,right,/*to*/right);
145: Sgl_xorfromintp1(save,left,/*to*/left);
146: result_exponent = Sgl_exponent(left);
147: Sgl_invert_sign(left);
148: }
149: /* Invariant: left is not smaller than right. */
150:
151: if((right_exponent = Sgl_exponent(right)) == 0)
152: {
153: /* Denormalized operands. First look for zeroes */
154: if(Sgl_iszero_mantissa(right))
155: {
156: /* right is zero */
157: if(Sgl_iszero_exponentmantissa(left))
158: {
159: /* Both operands are zeros */
160: Sgl_invert_sign(right);
161: if(Is_rounding_mode(ROUNDMINUS))
162: {
163: Sgl_or_signs(left,/*with*/right);
164: }
165: else
166: {
167: Sgl_and_signs(left,/*with*/right);
168: }
169: }
170: else
171: {
172: /* Left is not a zero and must be the result. Trapped
173: * underflows are signaled if left is denormalized. Result
174: * is always exact. */
175: if( (result_exponent == 0) && Is_underflowtrap_enabled() )
176: {
177: /* need to normalize results mantissa */
178: sign_save = Sgl_signextendedsign(left);
179: Sgl_leftshiftby1(left);
180: Sgl_normalize(left,result_exponent);
181: Sgl_set_sign(left,/*using*/sign_save);
182: Sgl_setwrapped_exponent(left,result_exponent,unfl);
183: *dstptr = left;
184: /* inexact = FALSE */
185: return(UNDERFLOWEXCEPTION);
186: }
187: }
188: *dstptr = left;
189: return(NOEXCEPTION);
190: }
191:
192: /* Neither are zeroes */
193: Sgl_clear_sign(right); /* Exponent is already cleared */
194: if(result_exponent == 0 )
195: {
196: /* Both operands are denormalized. The result must be exact
197: * and is simply calculated. A sum could become normalized and a
198: * difference could cancel to a true zero. */
199: if( (/*signed*/int) save >= 0 )
200: {
201: Sgl_subtract(left,/*minus*/right,/*into*/result);
202: if(Sgl_iszero_mantissa(result))
203: {
204: if(Is_rounding_mode(ROUNDMINUS))
205: {
206: Sgl_setone_sign(result);
207: }
208: else
209: {
210: Sgl_setzero_sign(result);
211: }
212: *dstptr = result;
213: return(NOEXCEPTION);
214: }
215: }
216: else
217: {
218: Sgl_addition(left,right,/*into*/result);
219: if(Sgl_isone_hidden(result))
220: {
221: *dstptr = result;
222: return(NOEXCEPTION);
223: }
224: }
225: if(Is_underflowtrap_enabled())
226: {
227: /* need to normalize result */
228: sign_save = Sgl_signextendedsign(result);
229: Sgl_leftshiftby1(result);
230: Sgl_normalize(result,result_exponent);
231: Sgl_set_sign(result,/*using*/sign_save);
232: Sgl_setwrapped_exponent(result,result_exponent,unfl);
233: *dstptr = result;
234: /* inexact = FALSE */
235: return(UNDERFLOWEXCEPTION);
236: }
237: *dstptr = result;
238: return(NOEXCEPTION);
239: }
240: right_exponent = 1; /* Set exponent to reflect different bias
241: * with denomalized numbers. */
242: }
243: else
244: {
245: Sgl_clear_signexponent_set_hidden(right);
246: }
247: Sgl_clear_exponent_set_hidden(left);
248: diff_exponent = result_exponent - right_exponent;
249:
250: /*
251: * Special case alignment of operands that would force alignment
252: * beyond the extent of the extension. A further optimization
253: * could special case this but only reduces the path length for this
254: * infrequent case.
255: */
256: if(diff_exponent > SGL_THRESHOLD)
257: {
258: diff_exponent = SGL_THRESHOLD;
259: }
260:
261: /* Align right operand by shifting to right */
262: Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
263: /*and lower to*/extent);
264:
265: /* Treat sum and difference of the operands separately. */
266: if( (/*signed*/int) save >= 0 )
267: {
268: /*
269: * Difference of the two operands. Their can be no overflow. A
270: * borrow can occur out of the hidden bit and force a post
271: * normalization phase.
272: */
273: Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
274: if(Sgl_iszero_hidden(result))
275: {
276: /* Handle normalization */
277: /* A straight forward algorithm would now shift the result
278: * and extension left until the hidden bit becomes one. Not
279: * all of the extension bits need participate in the shift.
280: * Only the two most significant bits (round and guard) are
281: * needed. If only a single shift is needed then the guard
282: * bit becomes a significant low order bit and the extension
283: * must participate in the rounding. If more than a single
284: * shift is needed, then all bits to the right of the guard
285: * bit are zeros, and the guard bit may or may not be zero. */
286: sign_save = Sgl_signextendedsign(result);
287: Sgl_leftshiftby1_withextent(result,extent,result);
288:
289: /* Need to check for a zero result. The sign and exponent
290: * fields have already been zeroed. The more efficient test
291: * of the full object can be used.
292: */
293: if(Sgl_iszero(result))
294: /* Must have been "x-x" or "x+(-x)". */
295: {
296: if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
297: *dstptr = result;
298: return(NOEXCEPTION);
299: }
300: result_exponent--;
301: /* Look to see if normalization is finished. */
302: if(Sgl_isone_hidden(result))
303: {
304: if(result_exponent==0)
305: {
306: /* Denormalized, exponent should be zero. Left operand *
307: * was normalized, so extent (guard, round) was zero */
308: goto underflow;
309: }
310: else
311: {
312: /* No further normalization is needed. */
313: Sgl_set_sign(result,/*using*/sign_save);
314: Ext_leftshiftby1(extent);
315: goto round;
316: }
317: }
318:
319: /* Check for denormalized, exponent should be zero. Left *
320: * operand was normalized, so extent (guard, round) was zero */
321: if(!(underflowtrap = Is_underflowtrap_enabled()) &&
322: result_exponent==0) goto underflow;
323:
324: /* Shift extension to complete one bit of normalization and
325: * update exponent. */
326: Ext_leftshiftby1(extent);
327:
328: /* Discover first one bit to determine shift amount. Use a
329: * modified binary search. We have already shifted the result
330: * one position right and still not found a one so the remainder
331: * of the extension must be zero and simplifies rounding. */
332: /* Scan bytes */
333: while(Sgl_iszero_hiddenhigh7mantissa(result))
334: {
335: Sgl_leftshiftby8(result);
336: if((result_exponent -= 8) <= 0 && !underflowtrap)
337: goto underflow;
338: }
339: /* Now narrow it down to the nibble */
340: if(Sgl_iszero_hiddenhigh3mantissa(result))
341: {
342: /* The lower nibble contains the normalizing one */
343: Sgl_leftshiftby4(result);
344: if((result_exponent -= 4) <= 0 && !underflowtrap)
345: goto underflow;
346: }
347: /* Select case were first bit is set (already normalized)
348: * otherwise select the proper shift. */
349: if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
350: {
351: /* Already normalized */
352: if(result_exponent <= 0) goto underflow;
353: Sgl_set_sign(result,/*using*/sign_save);
354: Sgl_set_exponent(result,/*using*/result_exponent);
355: *dstptr = result;
356: return(NOEXCEPTION);
357: }
358: Sgl_sethigh4bits(result,/*using*/sign_save);
359: switch(jumpsize)
360: {
361: case 1:
362: {
363: Sgl_leftshiftby3(result);
364: result_exponent -= 3;
365: break;
366: }
367: case 2:
368: case 3:
369: {
370: Sgl_leftshiftby2(result);
371: result_exponent -= 2;
372: break;
373: }
374: case 4:
375: case 5:
376: case 6:
377: case 7:
378: {
379: Sgl_leftshiftby1(result);
380: result_exponent -= 1;
381: break;
382: }
383: }
384: if(result_exponent > 0)
385: {
386: Sgl_set_exponent(result,/*using*/result_exponent);
387: *dstptr = result; /* Sign bit is already set */
388: return(NOEXCEPTION);
389: }
390: /* Fixup potential underflows */
391: underflow:
392: if(Is_underflowtrap_enabled())
393: {
394: Sgl_set_sign(result,sign_save);
395: Sgl_setwrapped_exponent(result,result_exponent,unfl);
396: *dstptr = result;
397: /* inexact = FALSE */
398: return(UNDERFLOWEXCEPTION);
399: }
400: /*
401: * Since we cannot get an inexact denormalized result,
402: * we can now return.
403: */
404: Sgl_right_align(result,/*by*/(1-result_exponent),extent);
405: Sgl_clear_signexponent(result);
406: Sgl_set_sign(result,sign_save);
407: *dstptr = result;
408: return(NOEXCEPTION);
409: } /* end if(hidden...)... */
410: /* Fall through and round */
411: } /* end if(save >= 0)... */
412: else
413: {
414: /* Add magnitudes */
415: Sgl_addition(left,right,/*to*/result);
416: if(Sgl_isone_hiddenoverflow(result))
417: {
418: /* Prenormalization required. */
419: Sgl_rightshiftby1_withextent(result,extent,extent);
420: Sgl_arithrightshiftby1(result);
421: result_exponent++;
422: } /* end if hiddenoverflow... */
423: } /* end else ...sub magnitudes... */
424:
425: /* Round the result. If the extension is all zeros,then the result is
426: * exact. Otherwise round in the correct direction. No underflow is
427: * possible. If a postnormalization is necessary, then the mantissa is
428: * all zeros so no shift is needed. */
429: round:
430: if(Ext_isnotzero(extent))
431: {
432: inexact = TRUE;
433: switch(Rounding_mode())
434: {
435: case ROUNDNEAREST: /* The default. */
436: if(Ext_isone_sign(extent))
437: {
438: /* at least 1/2 ulp */
439: if(Ext_isnotzero_lower(extent) ||
440: Sgl_isone_lowmantissa(result))
441: {
442: /* either exactly half way and odd or more than 1/2ulp */
443: Sgl_increment(result);
444: }
445: }
446: break;
447:
448: case ROUNDPLUS:
449: if(Sgl_iszero_sign(result))
450: {
451: /* Round up positive results */
452: Sgl_increment(result);
453: }
454: break;
455:
456: case ROUNDMINUS:
457: if(Sgl_isone_sign(result))
458: {
459: /* Round down negative results */
460: Sgl_increment(result);
461: }
462:
463: case ROUNDZERO:;
464: /* truncate is simple */
465: } /* end switch... */
466: if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
467: }
468: if(result_exponent == SGL_INFINITY_EXPONENT)
469: {
470: /* Overflow */
471: if(Is_overflowtrap_enabled())
472: {
473: Sgl_setwrapped_exponent(result,result_exponent,ovfl);
474: *dstptr = result;
475: if (inexact) {
476: if (Is_inexacttrap_enabled())
477: return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
478: else Set_inexactflag();
479: }
480: return(OVERFLOWEXCEPTION);
481: }
482: else
483: {
484: Set_overflowflag();
485: inexact = TRUE;
486: Sgl_setoverflow(result);
487: }
488: }
489: else Sgl_set_exponent(result,result_exponent);
490: *dstptr = result;
491: if(inexact) {
492: if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
493: else Set_inexactflag();
494: }
495: return(NOEXCEPTION);
496: }
CVSweb