]> git.proxmox.com Git - qemu.git/blob - fpu/softfloat-specialize.h
Assortment of soft-float fixes, by Aurelien Jarno.
[qemu.git] / fpu / softfloat-specialize.h
1
2 /*============================================================================
3
4 This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
5 Arithmetic Package, Release 2b.
6
7 Written by John R. Hauser. This work was made possible in part by the
8 International Computer Science Institute, located at Suite 600, 1947 Center
9 Street, Berkeley, California 94704. Funding was partially provided by the
10 National Science Foundation under grant MIP-9311980. The original version
11 of this code was written as part of a project to build a fixed-point vector
12 processor in collaboration with the University of California at Berkeley,
13 overseen by Profs. Nelson Morgan and John Wawrzynek. More information
14 is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
15 arithmetic/SoftFloat.html'.
16
17 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
18 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
19 RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
20 AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
21 COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
22 EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
23 INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
24 OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
25
26 Derivative works are acceptable, even for commercial purposes, so long as
27 (1) the source code for the derivative work includes prominent notice that
28 the work is derivative, and (2) the source code includes prominent notice with
29 these four paragraphs for those parts of this code that are retained.
30
31 =============================================================================*/
32
33 #if defined(TARGET_MIPS) || defined(TARGET_HPPA)
34 #define SNAN_BIT_IS_ONE 1
35 #else
36 #define SNAN_BIT_IS_ONE 0
37 #endif
38
39 /*----------------------------------------------------------------------------
40 | Underflow tininess-detection mode, statically initialized to default value.
41 | (The declaration in `softfloat.h' must match the `int8' type here.)
42 *----------------------------------------------------------------------------*/
43 int8 float_detect_tininess = float_tininess_after_rounding;
44
45 /*----------------------------------------------------------------------------
46 | Raises the exceptions specified by `flags'. Floating-point traps can be
47 | defined here if desired. It is currently not possible for such a trap
48 | to substitute a result value. If traps are not implemented, this routine
49 | should be simply `float_exception_flags |= flags;'.
50 *----------------------------------------------------------------------------*/
51
52 void float_raise( int8 flags STATUS_PARAM )
53 {
54 STATUS(float_exception_flags) |= flags;
55 }
56
57 /*----------------------------------------------------------------------------
58 | Internal canonical NaN format.
59 *----------------------------------------------------------------------------*/
60 typedef struct {
61 flag sign;
62 bits64 high, low;
63 } commonNaNT;
64
65 /*----------------------------------------------------------------------------
66 | The pattern for a default generated single-precision NaN.
67 *----------------------------------------------------------------------------*/
68 #if defined(TARGET_SPARC)
69 #define float32_default_nan make_float32(0x7FFFFFFF)
70 #elif defined(TARGET_POWERPC)
71 #define float32_default_nan make_float32(0x7FC00000)
72 #elif defined(TARGET_HPPA)
73 #define float32_default_nan make_float32(0x7FA00000)
74 #elif SNAN_BIT_IS_ONE
75 #define float32_default_nan make_float32(0x7FBFFFFF)
76 #else
77 #define float32_default_nan make_float32(0xFFC00000)
78 #endif
79
80 /*----------------------------------------------------------------------------
81 | Returns 1 if the single-precision floating-point value `a' is a quiet
82 | NaN; otherwise returns 0.
83 *----------------------------------------------------------------------------*/
84
85 int float32_is_nan( float32 a_ )
86 {
87 uint32_t a = float32_val(a_);
88 #if SNAN_BIT_IS_ONE
89 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
90 #else
91 return ( 0xFF800000 <= (bits32) ( a<<1 ) );
92 #endif
93 }
94
95 /*----------------------------------------------------------------------------
96 | Returns 1 if the single-precision floating-point value `a' is a signaling
97 | NaN; otherwise returns 0.
98 *----------------------------------------------------------------------------*/
99
100 int float32_is_signaling_nan( float32 a_ )
101 {
102 uint32_t a = float32_val(a_);
103 #if SNAN_BIT_IS_ONE
104 return ( 0xFF800000 <= (bits32) ( a<<1 ) );
105 #else
106 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
107 #endif
108 }
109
110 /*----------------------------------------------------------------------------
111 | Returns the result of converting the single-precision floating-point NaN
112 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
113 | exception is raised.
114 *----------------------------------------------------------------------------*/
115
116 static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
117 {
118 commonNaNT z;
119
120 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
121 z.sign = float32_val(a)>>31;
122 z.low = 0;
123 z.high = ( (bits64) float32_val(a) )<<41;
124 return z;
125 }
126
127 /*----------------------------------------------------------------------------
128 | Returns the result of converting the canonical NaN `a' to the single-
129 | precision floating-point format.
130 *----------------------------------------------------------------------------*/
131
132 static float32 commonNaNToFloat32( commonNaNT a )
133 {
134 bits32 mantissa = a.high>>41;
135 if ( mantissa )
136 return make_float32(
137 ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
138 else
139 return float32_default_nan;
140 }
141
142 /*----------------------------------------------------------------------------
143 | Takes two single-precision floating-point values `a' and `b', one of which
144 | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
145 | signaling NaN, the invalid exception is raised.
146 *----------------------------------------------------------------------------*/
147
148 static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
149 {
150 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
151 bits32 av, bv, res;
152
153 aIsNaN = float32_is_nan( a );
154 aIsSignalingNaN = float32_is_signaling_nan( a );
155 bIsNaN = float32_is_nan( b );
156 bIsSignalingNaN = float32_is_signaling_nan( b );
157 av = float32_val(a);
158 bv = float32_val(b);
159 #if SNAN_BIT_IS_ONE
160 av &= ~0x00400000;
161 bv &= ~0x00400000;
162 #else
163 av |= 0x00400000;
164 bv |= 0x00400000;
165 #endif
166 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
167 if ( aIsSignalingNaN ) {
168 if ( bIsSignalingNaN ) goto returnLargerSignificand;
169 res = bIsNaN ? bv : av;
170 }
171 else if ( aIsNaN ) {
172 if ( bIsSignalingNaN | ! bIsNaN )
173 res = av;
174 else {
175 returnLargerSignificand:
176 if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
177 res = bv;
178 else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
179 res = av;
180 else
181 res = ( av < bv ) ? av : bv;
182 }
183 }
184 else {
185 res = bv;
186 }
187 return make_float32(res);
188 }
189
190 /*----------------------------------------------------------------------------
191 | The pattern for a default generated double-precision NaN.
192 *----------------------------------------------------------------------------*/
193 #if defined(TARGET_SPARC)
194 #define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
195 #elif defined(TARGET_POWERPC)
196 #define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
197 #elif defined(TARGET_HPPA)
198 #define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
199 #elif SNAN_BIT_IS_ONE
200 #define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
201 #else
202 #define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
203 #endif
204
205 /*----------------------------------------------------------------------------
206 | Returns 1 if the double-precision floating-point value `a' is a quiet
207 | NaN; otherwise returns 0.
208 *----------------------------------------------------------------------------*/
209
210 int float64_is_nan( float64 a_ )
211 {
212 bits64 a = float64_val(a_);
213 #if SNAN_BIT_IS_ONE
214 return
215 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
216 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
217 #else
218 return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
219 #endif
220 }
221
222 /*----------------------------------------------------------------------------
223 | Returns 1 if the double-precision floating-point value `a' is a signaling
224 | NaN; otherwise returns 0.
225 *----------------------------------------------------------------------------*/
226
227 int float64_is_signaling_nan( float64 a_ )
228 {
229 bits64 a = float64_val(a_);
230 #if SNAN_BIT_IS_ONE
231 return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
232 #else
233 return
234 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
235 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
236 #endif
237 }
238
239 /*----------------------------------------------------------------------------
240 | Returns the result of converting the double-precision floating-point NaN
241 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
242 | exception is raised.
243 *----------------------------------------------------------------------------*/
244
245 static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
246 {
247 commonNaNT z;
248
249 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
250 z.sign = float64_val(a)>>63;
251 z.low = 0;
252 z.high = float64_val(a)<<12;
253 return z;
254 }
255
256 /*----------------------------------------------------------------------------
257 | Returns the result of converting the canonical NaN `a' to the double-
258 | precision floating-point format.
259 *----------------------------------------------------------------------------*/
260
261 static float64 commonNaNToFloat64( commonNaNT a )
262 {
263 bits64 mantissa = a.high>>12;
264
265 if ( mantissa )
266 return make_float64(
267 ( ( (bits64) a.sign )<<63 )
268 | LIT64( 0x7FF0000000000000 )
269 | ( a.high>>12 ));
270 else
271 return float64_default_nan;
272 }
273
274 /*----------------------------------------------------------------------------
275 | Takes two double-precision floating-point values `a' and `b', one of which
276 | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
277 | signaling NaN, the invalid exception is raised.
278 *----------------------------------------------------------------------------*/
279
280 static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
281 {
282 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
283 bits64 av, bv, res;
284
285 aIsNaN = float64_is_nan( a );
286 aIsSignalingNaN = float64_is_signaling_nan( a );
287 bIsNaN = float64_is_nan( b );
288 bIsSignalingNaN = float64_is_signaling_nan( b );
289 av = float64_val(a);
290 bv = float64_val(b);
291 #if SNAN_BIT_IS_ONE
292 av &= ~LIT64( 0x0008000000000000 );
293 bv &= ~LIT64( 0x0008000000000000 );
294 #else
295 av |= LIT64( 0x0008000000000000 );
296 bv |= LIT64( 0x0008000000000000 );
297 #endif
298 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
299 if ( aIsSignalingNaN ) {
300 if ( bIsSignalingNaN ) goto returnLargerSignificand;
301 res = bIsNaN ? bv : av;
302 }
303 else if ( aIsNaN ) {
304 if ( bIsSignalingNaN | ! bIsNaN )
305 res = av;
306 else {
307 returnLargerSignificand:
308 if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
309 res = bv;
310 else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
311 res = av;
312 else
313 res = ( av < bv ) ? av : bv;
314 }
315 }
316 else {
317 res = bv;
318 }
319 return make_float64(res);
320 }
321
322 #ifdef FLOATX80
323
324 /*----------------------------------------------------------------------------
325 | The pattern for a default generated extended double-precision NaN. The
326 | `high' and `low' values hold the most- and least-significant bits,
327 | respectively.
328 *----------------------------------------------------------------------------*/
329 #if SNAN_BIT_IS_ONE
330 #define floatx80_default_nan_high 0x7FFF
331 #define floatx80_default_nan_low LIT64( 0xBFFFFFFFFFFFFFFF )
332 #else
333 #define floatx80_default_nan_high 0xFFFF
334 #define floatx80_default_nan_low LIT64( 0xC000000000000000 )
335 #endif
336
337 /*----------------------------------------------------------------------------
338 | Returns 1 if the extended double-precision floating-point value `a' is a
339 | quiet NaN; otherwise returns 0.
340 *----------------------------------------------------------------------------*/
341
342 int floatx80_is_nan( floatx80 a )
343 {
344 #if SNAN_BIT_IS_ONE
345 bits64 aLow;
346
347 aLow = a.low & ~ LIT64( 0x4000000000000000 );
348 return
349 ( ( a.high & 0x7FFF ) == 0x7FFF )
350 && (bits64) ( aLow<<1 )
351 && ( a.low == aLow );
352 #else
353 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
354 #endif
355 }
356
357 /*----------------------------------------------------------------------------
358 | Returns 1 if the extended double-precision floating-point value `a' is a
359 | signaling NaN; otherwise returns 0.
360 *----------------------------------------------------------------------------*/
361
362 int floatx80_is_signaling_nan( floatx80 a )
363 {
364 #if SNAN_BIT_IS_ONE
365 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
366 #else
367 bits64 aLow;
368
369 aLow = a.low & ~ LIT64( 0x4000000000000000 );
370 return
371 ( ( a.high & 0x7FFF ) == 0x7FFF )
372 && (bits64) ( aLow<<1 )
373 && ( a.low == aLow );
374 #endif
375 }
376
377 /*----------------------------------------------------------------------------
378 | Returns the result of converting the extended double-precision floating-
379 | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
380 | invalid exception is raised.
381 *----------------------------------------------------------------------------*/
382
383 static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
384 {
385 commonNaNT z;
386
387 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
388 z.sign = a.high>>15;
389 z.low = 0;
390 z.high = a.low;
391 return z;
392 }
393
394 /*----------------------------------------------------------------------------
395 | Returns the result of converting the canonical NaN `a' to the extended
396 | double-precision floating-point format.
397 *----------------------------------------------------------------------------*/
398
399 static floatx80 commonNaNToFloatx80( commonNaNT a )
400 {
401 floatx80 z;
402
403 if (a.high)
404 z.low = a.high;
405 else
406 z.low = floatx80_default_nan_low;
407 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
408 return z;
409 }
410
411 /*----------------------------------------------------------------------------
412 | Takes two extended double-precision floating-point values `a' and `b', one
413 | of which is a NaN, and returns the appropriate NaN result. If either `a' or
414 | `b' is a signaling NaN, the invalid exception is raised.
415 *----------------------------------------------------------------------------*/
416
417 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
418 {
419 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
420
421 aIsNaN = floatx80_is_nan( a );
422 aIsSignalingNaN = floatx80_is_signaling_nan( a );
423 bIsNaN = floatx80_is_nan( b );
424 bIsSignalingNaN = floatx80_is_signaling_nan( b );
425 #if SNAN_BIT_IS_ONE
426 a.low &= ~LIT64( 0xC000000000000000 );
427 b.low &= ~LIT64( 0xC000000000000000 );
428 #else
429 a.low |= LIT64( 0xC000000000000000 );
430 b.low |= LIT64( 0xC000000000000000 );
431 #endif
432 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
433 if ( aIsSignalingNaN ) {
434 if ( bIsSignalingNaN ) goto returnLargerSignificand;
435 return bIsNaN ? b : a;
436 }
437 else if ( aIsNaN ) {
438 if ( bIsSignalingNaN | ! bIsNaN ) return a;
439 returnLargerSignificand:
440 if ( a.low < b.low ) return b;
441 if ( b.low < a.low ) return a;
442 return ( a.high < b.high ) ? a : b;
443 }
444 else {
445 return b;
446 }
447 }
448
449 #endif
450
451 #ifdef FLOAT128
452
453 /*----------------------------------------------------------------------------
454 | The pattern for a default generated quadruple-precision NaN. The `high' and
455 | `low' values hold the most- and least-significant bits, respectively.
456 *----------------------------------------------------------------------------*/
457 #if SNAN_BIT_IS_ONE
458 #define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
459 #define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
460 #else
461 #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
462 #define float128_default_nan_low LIT64( 0x0000000000000000 )
463 #endif
464
465 /*----------------------------------------------------------------------------
466 | Returns 1 if the quadruple-precision floating-point value `a' is a quiet
467 | NaN; otherwise returns 0.
468 *----------------------------------------------------------------------------*/
469
470 int float128_is_nan( float128 a )
471 {
472 #if SNAN_BIT_IS_ONE
473 return
474 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
475 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
476 #else
477 return
478 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
479 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
480 #endif
481 }
482
483 /*----------------------------------------------------------------------------
484 | Returns 1 if the quadruple-precision floating-point value `a' is a
485 | signaling NaN; otherwise returns 0.
486 *----------------------------------------------------------------------------*/
487
488 int float128_is_signaling_nan( float128 a )
489 {
490 #if SNAN_BIT_IS_ONE
491 return
492 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
493 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
494 #else
495 return
496 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
497 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
498 #endif
499 }
500
501 /*----------------------------------------------------------------------------
502 | Returns the result of converting the quadruple-precision floating-point NaN
503 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
504 | exception is raised.
505 *----------------------------------------------------------------------------*/
506
507 static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
508 {
509 commonNaNT z;
510
511 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
512 z.sign = a.high>>63;
513 shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
514 return z;
515 }
516
517 /*----------------------------------------------------------------------------
518 | Returns the result of converting the canonical NaN `a' to the quadruple-
519 | precision floating-point format.
520 *----------------------------------------------------------------------------*/
521
522 static float128 commonNaNToFloat128( commonNaNT a )
523 {
524 float128 z;
525
526 shift128Right( a.high, a.low, 16, &z.high, &z.low );
527 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
528 return z;
529 }
530
531 /*----------------------------------------------------------------------------
532 | Takes two quadruple-precision floating-point values `a' and `b', one of
533 | which is a NaN, and returns the appropriate NaN result. If either `a' or
534 | `b' is a signaling NaN, the invalid exception is raised.
535 *----------------------------------------------------------------------------*/
536
537 static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
538 {
539 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
540
541 aIsNaN = float128_is_nan( a );
542 aIsSignalingNaN = float128_is_signaling_nan( a );
543 bIsNaN = float128_is_nan( b );
544 bIsSignalingNaN = float128_is_signaling_nan( b );
545 #if SNAN_BIT_IS_ONE
546 a.high &= ~LIT64( 0x0000800000000000 );
547 b.high &= ~LIT64( 0x0000800000000000 );
548 #else
549 a.high |= LIT64( 0x0000800000000000 );
550 b.high |= LIT64( 0x0000800000000000 );
551 #endif
552 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
553 if ( aIsSignalingNaN ) {
554 if ( bIsSignalingNaN ) goto returnLargerSignificand;
555 return bIsNaN ? b : a;
556 }
557 else if ( aIsNaN ) {
558 if ( bIsSignalingNaN | ! bIsNaN ) return a;
559 returnLargerSignificand:
560 if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
561 if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
562 return ( a.high < b.high ) ? a : b;
563 }
564 else {
565 return b;
566 }
567 }
568
569 #endif