|
|
1.1 root 1: /* $Id: softfloat-tme.c,v 1.2 2005/05/14 01:42:28 fredette Exp $ */
2:
3: /* ic/ieee754/softfloat-tme.c - this glues tme to SoftFloat: */
4:
5: /*
6: * Copyright (c) 2004 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: /*============================================================================
37:
38: This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
39: Package, Release 2b.
40:
41: This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
42: Arithmetic Package, Release 2b.
43:
44: Written by John R. Hauser. This work was made possible in part by the
45: International Computer Science Institute, located at Suite 600, 1947 Center
46: Street, Berkeley, California 94704. Funding was partially provided by the
47: National Science Foundation under grant MIP-9311980. The original version
48: of this code was written as part of a project to build a fixed-point vector
49: processor in collaboration with the University of California at Berkeley,
50: overseen by Profs. Nelson Morgan and John Wawrzynek. More information
51: is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
52: arithmetic/SoftFloat.html'.
53:
54: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
55: been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
56: RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
57: AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
58: COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
59: EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
60: INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
61: OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
62:
63: Derivative works are acceptable, even for commercial purposes, so long as
64: (1) the source code for the derivative work includes prominent notice that
65: the work is derivative, and (2) the source code includes prominent notice with
66: these four paragraphs for those parts of this code that are retained.
67:
68: =============================================================================*/
69:
70: #include <tme/common.h>
71: _TME_RCSID("$Id: softfloat-tme.c,v 1.2 2005/05/14 01:42:28 fredette Exp $");
72:
73: /* includes: */
74: #define _TME_IEEE754_SOFTFLOAT_GLUE
75: #include "softfloat-tme.h"
76:
77: /* types: */
78: typedef struct tme_ieee754_nan commonNaNT;
79:
80: /* globals: */
81:
82: /* the softfloat lock: */
83: tme_mutex_t tme_ieee754_global_mutex;
84:
85: /* the softfloat global control: */
86: struct tme_ieee754_ctl *tme_ieee754_global_ctl;
87:
88: /* the softfloat global exceptions: */
89: tme_int8_t tme_ieee754_global_exceptions;
90:
91: #ifdef TME_HAVE_INT64_T
92: /*----------------------------------------------------------------------------
93: | The `LIT64' macro takes as its argument a textual integer literal and
94: | if necessary ``marks'' the literal as having a 64-bit integer type.
95: | For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
96: | appended with the letters `LL' standing for `long long', which is `gcc's
97: | name for the 64-bit integer type. Some compilers may allow `LIT64' to be
98: | defined as the identity macro: `#define LIT64( a ) a'.
99: *----------------------------------------------------------------------------*/
100: #if defined(__GNUC__) && (_TME_SIZEOF_LONG == 4)
101: #define LIT64( a ) a##LL
102: #else
103: #define LIT64( a ) a
104: #endif
105: #endif /* TME_HAVE_INT64_T */
106:
107: /*----------------------------------------------------------------------------
108: | The macro `INLINE' can be used before functions that should be inlined. If
109: | a compiler does not support explicit inlining, this macro should be defined
110: | to be `static'.
111: *----------------------------------------------------------------------------*/
112: #define INLINE static inline
113:
114: /*----------------------------------------------------------------------------
115: | Software IEC/IEEE floating-point underflow tininess-detection mode.
116: *----------------------------------------------------------------------------*/
117: #define float_detect_tininess (tme_ieee754_global_ctl->tme_ieee754_ctl_detect_tininess)
118: #define float_tininess_after_rounding TME_IEEE754_CTL_DETECT_TININESS_AFTER_ROUNDING
119: #define float_tininess_before_rounding TME_IEEE754_CTL_DETECT_TININESS_BEFORE_ROUNDING
120:
121: /*----------------------------------------------------------------------------
122: | Software IEC/IEEE floating-point rounding mode.
123: *----------------------------------------------------------------------------*/
124: #define float_rounding_mode (tme_ieee754_global_ctl->tme_ieee754_ctl_rounding_mode)
125: #define float_round_nearest_even TME_FLOAT_ROUND_NEAREST_EVEN
126: #define float_round_down TME_FLOAT_ROUND_DOWN
127: #define float_round_up TME_FLOAT_ROUND_UP
128: #define float_round_to_zero TME_FLOAT_ROUND_TO_ZERO
129:
130: /*----------------------------------------------------------------------------
131: | Software IEC/IEEE floating-point exception flags.
132: *----------------------------------------------------------------------------*/
133: #define float_exception_flags tme_ieee754_global_exceptions
134: #define float_flag_invalid TME_FLOAT_EXCEPTION_INVALID
135: #define float_flag_divbyzero TME_FLOAT_EXCEPTION_DIVBYZERO
136: #define float_flag_overflow TME_FLOAT_EXCEPTION_OVERFLOW
137: #define float_flag_underflow TME_FLOAT_EXCEPTION_UNDERFLOW
138: #define float_flag_inexact TME_FLOAT_EXCEPTION_INEXACT
139:
140: /*----------------------------------------------------------------------------
141: | Routine to raise any or all of the software IEC/IEEE floating-point
142: | exception flags.
143: *----------------------------------------------------------------------------*/
144: #define float_raise(excp) \
145: do { \
146: tme_ieee754_global_exceptions |= (excp); \
147: (*tme_ieee754_global_ctl->tme_ieee754_ctl_exception)(tme_ieee754_global_ctl, tme_ieee754_global_exceptions);\
148: } while (/* CONSTCOND */ 0)
149:
150: /*----------------------------------------------------------------------------
151: | Software IEC/IEEE extended double-precision rounding precision. Valid
152: | values are 32, 64, and 80.
153: *----------------------------------------------------------------------------*/
154: #define floatx80_rounding_precision (tme_ieee754_global_ctl->tme_ieee754_ctl_extended80_rounding_precision)
155:
156: /* include either the 32-bit or 64-bit SoftFloat macros: */
157: #ifdef TME_HAVE_INT64_T
158: #include "dist/softfloat/softfloat/bits64/softfloat-macros"
159: #else /* !TME_HAVE_INT64_T */
160: #include "dist/softfloat/softfloat/bits32/softfloat-macros"
161: #endif /* !TME_HAVE_INT64_T */
162:
163: /*----------------------------------------------------------------------------
164: | The pattern for a default generated single-precision NaN.
165: *----------------------------------------------------------------------------*/
166:
167: #define float32_default_nan (tme_ieee754_global_ctl->tme_ieee754_ctl_default_nan_single)
168:
169: /*----------------------------------------------------------------------------
170: | Returns 1 if the single-precision floating-point value `a' is a signaling
171: | NaN; otherwise returns 0.
172: *----------------------------------------------------------------------------*/
173:
174: INLINE flag
175: float32_is_signaling_nan( float32 a )
176: {
177: return ((*tme_ieee754_global_ctl->tme_ieee754_ctl_is_snan_single)(&a));
178: }
179:
180: /*----------------------------------------------------------------------------
181: | Returns the result of converting the single-precision floating-point NaN
182: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
183: | exception is raised.
184: *----------------------------------------------------------------------------*/
185:
186: void
187: tme_ieee754_default_nan_single_to_common(tme_uint32_t a,
188: struct tme_ieee754_nan *z)
189: {
190: z->tme_ieee754_nan_sign = a >> 31;
191: z->tme_ieee754_nan_hi.tme_value64_uint32_hi = a << 9;
192: z->tme_ieee754_nan_hi.tme_value64_uint32_lo = 0;
193: z->tme_ieee754_nan_lo.tme_value64_uint32_hi = 0;
194: z->tme_ieee754_nan_lo.tme_value64_uint32_lo = 0;
195: }
196:
197: INLINE commonNaNT
198: float32ToCommonNaN( float32 a )
199: {
200: commonNaNT z;
201:
202: if (tme_ieee754_global_ctl->tme_ieee754_ctl_check_snan_on_conversion
203: && (*tme_ieee754_global_ctl->tme_ieee754_ctl_is_snan_single)(&a)) {
204: float_raise( float_flag_invalid );
205: }
206: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_single_to_common)(a, &z);
207: return (z);
208: }
209:
210: /*----------------------------------------------------------------------------
211: | Returns the result of converting the canonical NaN `a' to the single-
212: | precision floating-point format.
213: *----------------------------------------------------------------------------*/
214:
215: void
216: tme_ieee754_default_nan_common_to_single(const struct tme_ieee754_nan *z,
217: tme_uint32_t *a)
218: {
219: *a = ((((bits32) z->tme_ieee754_nan_sign) << 31)
220: | 0x7FC00000
221: | (z->tme_ieee754_nan_hi.tme_value64_uint32_hi >> 9)
222: );
223: }
224:
225: INLINE float32
226: commonNaNToFloat32( commonNaNT a )
227: {
228: float32 z;
229:
230: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_common_to_single)(&a, &z);
231: return (z);
232: }
233:
234: /*----------------------------------------------------------------------------
235: | Takes two single-precision floating-point values `a' and `b', one of which
236: | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
237: | signaling NaN, the invalid exception is raised.
238: *----------------------------------------------------------------------------*/
239:
240: INLINE float32
241: propagateFloat32NaN( float32 a, float32 b )
242: {
243: float32 z;
244:
245: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_from_nans_single)(tme_ieee754_global_ctl, &a, &b, &z);
246: return (z);
247: }
248:
249: /*----------------------------------------------------------------------------
250: | The pattern for a default generated double-precision NaN.
251: *----------------------------------------------------------------------------*/
252: #ifdef TME_HAVE_INT64_T
253: #define float64_default_nan (tme_ieee754_global_ctl->tme_ieee754_ctl_default_nan_double.tme_value64_uint)
254: #else /* !TME_HAVE_INT64_T */
255: #define float64_default_nan_high (tme_ieee754_global_ctl->tme_ieee754_ctl_default_nan_double.tme_value64_uint32_hi)
256: #define float64_default_nan_low (tme_ieee754_global_ctl->tme_ieee754_ctl_default_nan_double.tme_value64_uint32_lo)
257: #endif /* !TME_HAVE_INT64_T */
258:
259: #define TME_FLOAT64_OUT(a) ((union tme_value64 *) (&(a)))
260:
261: /*----------------------------------------------------------------------------
262: | Returns 1 if the double-precision floating-point value `a' is a signaling
263: | NaN; otherwise returns 0.
264: *----------------------------------------------------------------------------*/
265:
266: INLINE flag
267: float64_is_signaling_nan( float64 a )
268: {
269: return ((*tme_ieee754_global_ctl->tme_ieee754_ctl_is_snan_double)(TME_FLOAT64_OUT(a)));
270: }
271:
272: /*----------------------------------------------------------------------------
273: | Returns the result of converting the double-precision floating-point NaN
274: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
275: | exception is raised.
276: *----------------------------------------------------------------------------*/
277:
278: void
279: tme_ieee754_default_nan_double_to_common(const union tme_value64 *a,
280: struct tme_ieee754_nan *z)
281: {
282: z->tme_ieee754_nan_sign = a->tme_value64_uint32_hi >> 31;
283: #ifdef TME_HAVE_INT64_T
284: z->tme_ieee754_nan_hi.tme_value64_uint = a->tme_value64_uint << 12;
285: #else /* !TME_HAVE_INT64_T */
286: shortShift64Left( a->tme_value64_uint32_hi,
287: a->tme_value64_uint32_lo,
288: 12,
289: &z->tme_ieee754_nan_hi.tme_value64_uint32_hi,
290: &z->tme_ieee754_nan_hi.tme_value64_uint32_lo );
291: #endif /* !TME_HAVE_INT64_T */
292: z->tme_ieee754_nan_lo.tme_value64_uint32_hi = 0;
293: z->tme_ieee754_nan_lo.tme_value64_uint32_lo = 0;
294: }
295:
296: INLINE commonNaNT
297: float64ToCommonNaN( float64 a )
298: {
299: commonNaNT z;
300:
301: if (tme_ieee754_global_ctl->tme_ieee754_ctl_check_snan_on_conversion
302: && (*tme_ieee754_global_ctl->tme_ieee754_ctl_is_snan_double)(TME_FLOAT64_OUT(a))) {
303: float_raise( float_flag_invalid );
304: }
305: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_double_to_common)(TME_FLOAT64_OUT(a), &z);
306: return (z);
307: }
308:
309: /*----------------------------------------------------------------------------
310: | Returns the result of converting the canonical NaN `a' to the double-
311: | precision floating-point format.
312: *----------------------------------------------------------------------------*/
313:
314: void
315: tme_ieee754_default_nan_common_to_double(const struct tme_ieee754_nan *a,
316: union tme_value64 *z)
317: {
318: #ifdef TME_HAVE_INT64_T
319: z->tme_value64_uint = a->tme_ieee754_nan_hi.tme_value64_uint >> 12;
320: #else /* TME_HAVE_INT64_T */
321: shift64Right( a->tme_ieee754_nan_hi.tme_value64_uint32_hi,
322: a->tme_ieee754_nan_hi.tme_value64_uint32_lo,
323: 12,
324: &z->tme_value64_uint32_hi,
325: &z->tme_value64_uint32_lo );
326: #endif /* TME_HAVE_INT64_T */
327: z->tme_value64_uint32_hi |= ( ( (bits32) a->tme_ieee754_nan_sign ) << 31 ) | 0x7FF80000;
328: }
329:
330: INLINE float64
331: commonNaNToFloat64( commonNaNT a )
332: {
333: float64 z;
334:
335: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_common_to_double)(&a, TME_FLOAT64_OUT(z));
336: return (z);
337: }
338:
339: /*----------------------------------------------------------------------------
340: | Takes two double-precision floating-point values `a' and `b', one of which
341: | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
342: | signaling NaN, the invalid exception is raised.
343: *----------------------------------------------------------------------------*/
344:
345: INLINE float64
346: propagateFloat64NaN( float64 a, float64 b )
347: {
348: float64 z;
349:
350: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_from_nans_double)(tme_ieee754_global_ctl,
351: TME_FLOAT64_OUT(a),
352: TME_FLOAT64_OUT(b),
353: TME_FLOAT64_OUT(z));
354: return (z);
355: }
356:
357: #ifdef FLOATX80
358:
359: /*----------------------------------------------------------------------------
360: | The pattern for a default generated extended double-precision NaN. The
361: | `high' and `low' values hold the most- and least-significant bits,
362: | respectively.
363: *----------------------------------------------------------------------------*/
364: #define floatx80_default_nan_high (tme_ieee754_global_ctl->tme_ieee754_ctl_default_nan_extended80.tme_float_ieee754_extended80_sexp)
365: #define floatx80_default_nan_low (tme_ieee754_global_ctl->tme_ieee754_ctl_default_nan_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint)
366:
367: #define TME_FLOATX80_OUT(a) ((struct tme_float_ieee754_extended80 *) &(a))
368:
369: /*----------------------------------------------------------------------------
370: | Returns 1 if the extended double-precision floating-point value `a' is a
371: | signaling NaN; otherwise returns 0.
372: *----------------------------------------------------------------------------*/
373:
374: INLINE flag
375: floatx80_is_signaling_nan( floatx80 a )
376: {
377: return ((*tme_ieee754_global_ctl->tme_ieee754_ctl_is_snan_extended80)(TME_FLOATX80_OUT(a)));
378: }
379:
380: /*----------------------------------------------------------------------------
381: | Returns the result of converting the extended double-precision floating-
382: | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
383: | invalid exception is raised.
384: *----------------------------------------------------------------------------*/
385:
386: void
387: tme_ieee754_default_nan_extended80_to_common(const struct tme_float_ieee754_extended80 *a,
388: struct tme_ieee754_nan *z)
389: {
390: z->tme_ieee754_nan_sign = a->tme_float_ieee754_extended80_sexp >> 15;
391: #ifdef TME_HAVE_INT64_T
392: z->tme_ieee754_nan_hi.tme_value64_uint = a->tme_float_ieee754_extended80_significand.tme_value64_uint << 1;
393: #else /* !TME_HAVE_INT64_T */
394: shortShift64Left(a->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi,
395: a->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo,
396: 1,
397: &z->tme_ieee754_nan_hi.tme_value64_uint32_hi,
398: &z->tme_ieee754_nan_hi.tme_value64_uint32_lo);
399: #endif /* !TME_HAVE_INT64_T */
400: z->tme_ieee754_nan_lo.tme_value64_uint32_hi = 0;
401: z->tme_ieee754_nan_lo.tme_value64_uint32_lo = 0;
402: }
403:
404: INLINE commonNaNT
405: floatx80ToCommonNaN( floatx80 a )
406: {
407: commonNaNT z;
408:
409: if (tme_ieee754_global_ctl->tme_ieee754_ctl_check_snan_on_conversion
410: && (*tme_ieee754_global_ctl->tme_ieee754_ctl_is_snan_extended80)(TME_FLOATX80_OUT(a))) {
411: float_raise( float_flag_invalid );
412: }
413: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_extended80_to_common)(TME_FLOATX80_OUT(a), &z);
414: return (z);
415: }
416:
417: /*----------------------------------------------------------------------------
418: | Returns the result of converting the canonical NaN `a' to the extended
419: | double-precision floating-point format.
420: *----------------------------------------------------------------------------*/
421:
422: void
423: tme_ieee754_default_nan_common_to_extended80(const struct tme_ieee754_nan *a,
424: struct tme_float_ieee754_extended80 *z)
425: {
426: z->tme_float_ieee754_extended80_sexp = (((tme_uint16_t) a->tme_ieee754_nan_sign) << 15) | 0x7FFF;
427: #ifdef TME_HAVE_INT64_T
428: z->tme_float_ieee754_extended80_significand.tme_value64_uint = a->tme_ieee754_nan_hi.tme_value64_uint >> 1;
429: #else /* !TME_HAVE_INT64_T */
430: shift64Right(a->tme_ieee754_nan_hi.tme_value64_uint32_hi,
431: a->tme_ieee754_nan_hi.tme_value64_uint32_lo,
432: 1,
433: z->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi,
434: z->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo);
435: #endif /* !TME_HAVE_INT64_T */
436: z->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi |= 0xC0000000;
437: }
438:
439: INLINE floatx80
440: commonNaNToFloatx80( commonNaNT a )
441: {
442: floatx80 z;
443:
444: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_common_to_extended80)(&a, TME_FLOATX80_OUT(z));
445: return (z);
446: }
447:
448: /*----------------------------------------------------------------------------
449: | Takes two extended double-precision floating-point values `a' and `b', one
450: | of which is a NaN, and returns the appropriate NaN result. If either `a' or
451: | `b' is a signaling NaN, the invalid exception is raised.
452: *----------------------------------------------------------------------------*/
453:
454: INLINE floatx80
455: propagateFloatx80NaN( floatx80 a, floatx80 b )
456: {
457: floatx80 z;
458:
459: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_from_nans_extended80)(tme_ieee754_global_ctl,
460: TME_FLOATX80_OUT(a),
461: TME_FLOATX80_OUT(b),
462: TME_FLOATX80_OUT(z));
463: return (z);
464: }
465:
466: #endif /* FLOATX80 */
467:
468: #ifdef FLOAT128
469:
470: /*----------------------------------------------------------------------------
471: | The pattern for a default generated quadruple-precision NaN. The `high' and
472: | `low' values hold the most- and least-significant bits, respectively.
473: *----------------------------------------------------------------------------*/
474: #define float128_default_nan_high (tme_ieee754_global_ctl->tme_ieee754_ctl_default_nan_quad.tme_float_ieee754_quad_hi.tme_value64_uint)
475: #define float128_default_nan_low (tme_ieee754_global_ctl->tme_ieee754_ctl_default_nan_quad.tme_float_ieee754_quad_lo.tme_value64_uint)
476:
477: #define TME_FLOAT128_OUT(a) ((struct tme_float_ieee754_quad *) &(a))
478:
479: /*----------------------------------------------------------------------------
480: | Returns 1 if the quadruple-precision floating-point value `a' is a
481: | signaling NaN; otherwise returns 0.
482: *----------------------------------------------------------------------------*/
483:
484: INLINE flag
485: float128_is_signaling_nan( float128 a )
486: {
487: return ((*tme_ieee754_global_ctl->tme_ieee754_ctl_is_snan_quad)(TME_FLOAT128_OUT(a)));
488: }
489:
490: /*----------------------------------------------------------------------------
491: | Returns the result of converting the quadruple-precision floating-point NaN
492: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
493: | exception is raised.
494: *----------------------------------------------------------------------------*/
495:
496: void
497: tme_ieee754_default_nan_quad_to_common(const struct tme_float_ieee754_quad *a,
498: struct tme_ieee754_nan *z)
499: {
500: z->tme_ieee754_nan_sign = a->tme_float_ieee754_quad_hi.tme_value64_uint32_hi >> 31;
501: shortShift128Left( a->tme_float_ieee754_quad_hi.tme_value64_uint,
502: a->tme_float_ieee754_quad_lo.tme_value64_uint,
503: 16,
504: &z->tme_ieee754_nan_hi.tme_value64_uint,
505: &z->tme_ieee754_nan_lo.tme_value64_uint );
506: }
507:
508: INLINE commonNaNT
509: float128ToCommonNaN( float128 a )
510: {
511: commonNaNT z;
512:
513: if (tme_ieee754_global_ctl->tme_ieee754_ctl_check_snan_on_conversion
514: && (*tme_ieee754_global_ctl->tme_ieee754_ctl_is_snan_quad)(TME_FLOAT128_OUT(a))) {
515: float_raise( float_flag_invalid );
516: }
517: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_quad_to_common)(TME_FLOAT128_OUT(a), &z);
518: return (z);
519: }
520:
521: /*----------------------------------------------------------------------------
522: | Returns the result of converting the canonical NaN `a' to the quadruple-
523: | precision floating-point format.
524: *----------------------------------------------------------------------------*/
525:
526: void
527: tme_ieee754_default_nan_common_to_quad(const struct tme_ieee754_nan *a,
528: struct tme_float_ieee754_quad *z)
529: {
530: shift128Right( a->tme_ieee754_nan_hi.tme_value64_uint,
531: a->tme_ieee754_nan_lo.tme_value64_uint,
532: 16,
533: &z->tme_float_ieee754_quad_hi.tme_value64_uint,
534: &z->tme_float_ieee754_quad_lo.tme_value64_uint );
535: z->tme_float_ieee754_quad_hi.tme_value64_uint32_hi |= (((tme_uint32_t) a->tme_ieee754_nan_sign) << 31) | 0x7FFF8000;
536: }
537:
538: INLINE float128
539: commonNaNToFloat128( commonNaNT a )
540: {
541: float128 z;
542:
543: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_common_to_quad)(&a, TME_FLOAT128_OUT(z));
544: return (z);
545: }
546:
547: /*----------------------------------------------------------------------------
548: | Takes two quadruple-precision floating-point values `a' and `b', one of
549: | which is a NaN, and returns the appropriate NaN result. If either `a' or
550: | `b' is a signaling NaN, the invalid exception is raised.
551: *----------------------------------------------------------------------------*/
552:
553: INLINE float128
554: propagateFloat128NaN( float128 a, float128 b )
555: {
556: float128 z;
557:
558: (*tme_ieee754_global_ctl->tme_ieee754_ctl_nan_from_nans_quad)(tme_ieee754_global_ctl,
559: TME_FLOAT128_OUT(a),
560: TME_FLOAT128_OUT(b),
561: TME_FLOAT128_OUT(z));
562: return (z);
563: }
564:
565: #endif /* FLOAT128 */
566:
567: /* include either the 32-bit or 64-bit SoftFloat implementation: */
568: #ifdef TME_HAVE_INT64_T
569: #include "dist/softfloat/softfloat/bits64/softfloat.c"
570: #else /* !TME_HAVE_INT64_T */
571: #include "dist/softfloat/softfloat/bits32/softfloat.c"
572: #endif /* !TME_HAVE_INT64_T */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.