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
float32_is_signaling_nan(float32 a)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
tme_ieee754_default_nan_single_to_common(tme_uint32_t a,struct tme_ieee754_nan * z)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
float32ToCommonNaN(float32 a)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
tme_ieee754_default_nan_common_to_single(const struct tme_ieee754_nan * z,tme_uint32_t * a)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
commonNaNToFloat32(commonNaNT a)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
propagateFloat32NaN(float32 a,float32 b)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
float64_is_signaling_nan(float64 a)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
tme_ieee754_default_nan_double_to_common(const union tme_value64 * a,struct tme_ieee754_nan * z)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
float64ToCommonNaN(float64 a)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
tme_ieee754_default_nan_common_to_double(const struct tme_ieee754_nan * a,union tme_value64 * z)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
commonNaNToFloat64(commonNaNT a)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
propagateFloat64NaN(float64 a,float64 b)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
floatx80_is_signaling_nan(floatx80 a)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
tme_ieee754_default_nan_extended80_to_common(const struct tme_float_ieee754_extended80 * a,struct tme_ieee754_nan * z)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
floatx80ToCommonNaN(floatx80 a)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
tme_ieee754_default_nan_common_to_extended80(const struct tme_ieee754_nan * a,struct tme_float_ieee754_extended80 * z)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
commonNaNToFloatx80(commonNaNT a)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
propagateFloatx80NaN(floatx80 a,floatx80 b)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
float128_is_signaling_nan(float128 a)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
tme_ieee754_default_nan_quad_to_common(const struct tme_float_ieee754_quad * a,struct tme_ieee754_nan * z)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
float128ToCommonNaN(float128 a)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
tme_ieee754_default_nan_common_to_quad(const struct tme_ieee754_nan * a,struct tme_float_ieee754_quad * z)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
commonNaNToFloat128(commonNaNT a)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
propagateFloat128NaN(float128 a,float128 b)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 */
573