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