VirtualBox

source: vbox/trunk/src/recompiler/fpu/softfloat-specialize.h@ 24345

Last change on this file since 24345 was 21292, checked in by vboxsync, 15 years ago

svn:eol-style native

  • Property svn:eol-style set to native
File size: 20.2 KB
Line 
1
2/*============================================================================
3
4This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
5Arithmetic Package, Release 2b.
6
7Written by John R. Hauser. This work was made possible in part by the
8International Computer Science Institute, located at Suite 600, 1947 Center
9Street, Berkeley, California 94704. Funding was partially provided by the
10National Science Foundation under grant MIP-9311980. The original version
11of this code was written as part of a project to build a fixed-point vector
12processor in collaboration with the University of California at Berkeley,
13overseen by Profs. Nelson Morgan and John Wawrzynek. More information
14is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
15arithmetic/SoftFloat.html'.
16
17THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
18been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
19RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
20AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
21COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
22EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
23INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
24OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
25
26Derivative works are acceptable, even for commercial purposes, so long as
27(1) the source code for the derivative work includes prominent notice that
28the work is derivative, and (2) the source code includes prominent notice with
29these 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| Raises the exceptions specified by `flags'. Floating-point traps can be
41| defined here if desired. It is currently not possible for such a trap
42| to substitute a result value. If traps are not implemented, this routine
43| should be simply `float_exception_flags |= flags;'.
44*----------------------------------------------------------------------------*/
45
46void float_raise( int8 flags STATUS_PARAM )
47{
48 STATUS(float_exception_flags) |= flags;
49}
50
51/*----------------------------------------------------------------------------
52| Internal canonical NaN format.
53*----------------------------------------------------------------------------*/
54typedef struct {
55 flag sign;
56 bits64 high, low;
57} commonNaNT;
58
59/*----------------------------------------------------------------------------
60| The pattern for a default generated single-precision NaN.
61*----------------------------------------------------------------------------*/
62#if defined(TARGET_SPARC)
63#define float32_default_nan make_float32(0x7FFFFFFF)
64#elif defined(TARGET_POWERPC) || defined(TARGET_ARM)
65#define float32_default_nan make_float32(0x7FC00000)
66#elif defined(TARGET_HPPA)
67#define float32_default_nan make_float32(0x7FA00000)
68#elif SNAN_BIT_IS_ONE
69#define float32_default_nan make_float32(0x7FBFFFFF)
70#else
71#define float32_default_nan make_float32(0xFFC00000)
72#endif
73
74/*----------------------------------------------------------------------------
75| Returns 1 if the single-precision floating-point value `a' is a quiet
76| NaN; otherwise returns 0.
77*----------------------------------------------------------------------------*/
78
79int float32_is_nan( float32 a_ )
80{
81 uint32_t a = float32_val(a_);
82#if SNAN_BIT_IS_ONE
83 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
84#else
85 return ( 0xFF800000 <= (bits32) ( a<<1 ) );
86#endif
87}
88
89/*----------------------------------------------------------------------------
90| Returns 1 if the single-precision floating-point value `a' is a signaling
91| NaN; otherwise returns 0.
92*----------------------------------------------------------------------------*/
93
94int float32_is_signaling_nan( float32 a_ )
95{
96 uint32_t a = float32_val(a_);
97#if SNAN_BIT_IS_ONE
98 return ( 0xFF800000 <= (bits32) ( a<<1 ) );
99#else
100 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
101#endif
102}
103
104/*----------------------------------------------------------------------------
105| Returns the result of converting the single-precision floating-point NaN
106| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
107| exception is raised.
108*----------------------------------------------------------------------------*/
109
110static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
111{
112 commonNaNT z;
113
114 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
115 z.sign = float32_val(a)>>31;
116 z.low = 0;
117 z.high = ( (bits64) float32_val(a) )<<41;
118 return z;
119}
120
121/*----------------------------------------------------------------------------
122| Returns the result of converting the canonical NaN `a' to the single-
123| precision floating-point format.
124*----------------------------------------------------------------------------*/
125
126static float32 commonNaNToFloat32( commonNaNT a )
127{
128 bits32 mantissa = a.high>>41;
129 if ( mantissa )
130 return make_float32(
131 ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
132 else
133 return float32_default_nan;
134}
135
136/*----------------------------------------------------------------------------
137| Takes two single-precision floating-point values `a' and `b', one of which
138| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
139| signaling NaN, the invalid exception is raised.
140*----------------------------------------------------------------------------*/
141
142static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
143{
144 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
145 bits32 av, bv, res;
146
147 if ( STATUS(default_nan_mode) )
148 return float32_default_nan;
149
150 aIsNaN = float32_is_nan( a );
151 aIsSignalingNaN = float32_is_signaling_nan( a );
152 bIsNaN = float32_is_nan( b );
153 bIsSignalingNaN = float32_is_signaling_nan( b );
154 av = float32_val(a);
155 bv = float32_val(b);
156#if SNAN_BIT_IS_ONE
157 av &= ~0x00400000;
158 bv &= ~0x00400000;
159#else
160 av |= 0x00400000;
161 bv |= 0x00400000;
162#endif
163 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
164 if ( aIsSignalingNaN ) {
165 if ( bIsSignalingNaN ) goto returnLargerSignificand;
166 res = bIsNaN ? bv : av;
167 }
168 else if ( aIsNaN ) {
169 if ( bIsSignalingNaN | ! bIsNaN )
170 res = av;
171 else {
172 returnLargerSignificand:
173 if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
174 res = bv;
175 else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
176 res = av;
177 else
178 res = ( av < bv ) ? av : bv;
179 }
180 }
181 else {
182 res = bv;
183 }
184 return make_float32(res);
185}
186
187/*----------------------------------------------------------------------------
188| The pattern for a default generated double-precision NaN.
189*----------------------------------------------------------------------------*/
190#if defined(TARGET_SPARC)
191#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
192#elif defined(TARGET_POWERPC) || defined(TARGET_ARM)
193#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
194#elif defined(TARGET_HPPA)
195#define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
196#elif SNAN_BIT_IS_ONE
197#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
198#else
199#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
200#endif
201
202/*----------------------------------------------------------------------------
203| Returns 1 if the double-precision floating-point value `a' is a quiet
204| NaN; otherwise returns 0.
205*----------------------------------------------------------------------------*/
206
207int float64_is_nan( float64 a_ )
208{
209 bits64 a = float64_val(a_);
210#if SNAN_BIT_IS_ONE
211 return
212 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
213 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
214#else
215 return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
216#endif
217}
218
219/*----------------------------------------------------------------------------
220| Returns 1 if the double-precision floating-point value `a' is a signaling
221| NaN; otherwise returns 0.
222*----------------------------------------------------------------------------*/
223
224int float64_is_signaling_nan( float64 a_ )
225{
226 bits64 a = float64_val(a_);
227#if SNAN_BIT_IS_ONE
228 return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
229#else
230 return
231 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
232 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
233#endif
234}
235
236/*----------------------------------------------------------------------------
237| Returns the result of converting the double-precision floating-point NaN
238| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
239| exception is raised.
240*----------------------------------------------------------------------------*/
241
242static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
243{
244 commonNaNT z;
245
246 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
247 z.sign = float64_val(a)>>63;
248 z.low = 0;
249 z.high = float64_val(a)<<12;
250 return z;
251}
252
253/*----------------------------------------------------------------------------
254| Returns the result of converting the canonical NaN `a' to the double-
255| precision floating-point format.
256*----------------------------------------------------------------------------*/
257
258static float64 commonNaNToFloat64( commonNaNT a )
259{
260 bits64 mantissa = a.high>>12;
261
262 if ( mantissa )
263 return make_float64(
264 ( ( (bits64) a.sign )<<63 )
265 | LIT64( 0x7FF0000000000000 )
266 | ( a.high>>12 ));
267 else
268 return float64_default_nan;
269}
270
271/*----------------------------------------------------------------------------
272| Takes two double-precision floating-point values `a' and `b', one of which
273| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
274| signaling NaN, the invalid exception is raised.
275*----------------------------------------------------------------------------*/
276
277static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
278{
279 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
280 bits64 av, bv, res;
281
282 if ( STATUS(default_nan_mode) )
283 return float64_default_nan;
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
342int 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
362int 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
383static 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
399static 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
417static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
418{
419 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
420
421 if ( STATUS(default_nan_mode) ) {
422 a.low = floatx80_default_nan_low;
423 a.high = floatx80_default_nan_high;
424 return a;
425 }
426
427 aIsNaN = floatx80_is_nan( a );
428 aIsSignalingNaN = floatx80_is_signaling_nan( a );
429 bIsNaN = floatx80_is_nan( b );
430 bIsSignalingNaN = floatx80_is_signaling_nan( b );
431#if SNAN_BIT_IS_ONE
432 a.low &= ~LIT64( 0xC000000000000000 );
433 b.low &= ~LIT64( 0xC000000000000000 );
434#else
435 a.low |= LIT64( 0xC000000000000000 );
436 b.low |= LIT64( 0xC000000000000000 );
437#endif
438 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
439 if ( aIsSignalingNaN ) {
440 if ( bIsSignalingNaN ) goto returnLargerSignificand;
441 return bIsNaN ? b : a;
442 }
443 else if ( aIsNaN ) {
444 if ( bIsSignalingNaN | ! bIsNaN ) return a;
445 returnLargerSignificand:
446 if ( a.low < b.low ) return b;
447 if ( b.low < a.low ) return a;
448 return ( a.high < b.high ) ? a : b;
449 }
450 else {
451 return b;
452 }
453}
454
455#endif
456
457#ifdef FLOAT128
458
459/*----------------------------------------------------------------------------
460| The pattern for a default generated quadruple-precision NaN. The `high' and
461| `low' values hold the most- and least-significant bits, respectively.
462*----------------------------------------------------------------------------*/
463#if SNAN_BIT_IS_ONE
464#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
465#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
466#else
467#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
468#define float128_default_nan_low LIT64( 0x0000000000000000 )
469#endif
470
471/*----------------------------------------------------------------------------
472| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
473| NaN; otherwise returns 0.
474*----------------------------------------------------------------------------*/
475
476int float128_is_nan( float128 a )
477{
478#if SNAN_BIT_IS_ONE
479 return
480 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
481 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
482#else
483 return
484 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
485 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
486#endif
487}
488
489/*----------------------------------------------------------------------------
490| Returns 1 if the quadruple-precision floating-point value `a' is a
491| signaling NaN; otherwise returns 0.
492*----------------------------------------------------------------------------*/
493
494int float128_is_signaling_nan( float128 a )
495{
496#if SNAN_BIT_IS_ONE
497 return
498 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
499 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
500#else
501 return
502 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
503 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
504#endif
505}
506
507/*----------------------------------------------------------------------------
508| Returns the result of converting the quadruple-precision floating-point NaN
509| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
510| exception is raised.
511*----------------------------------------------------------------------------*/
512
513static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
514{
515 commonNaNT z;
516
517 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
518 z.sign = a.high>>63;
519 shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
520 return z;
521}
522
523/*----------------------------------------------------------------------------
524| Returns the result of converting the canonical NaN `a' to the quadruple-
525| precision floating-point format.
526*----------------------------------------------------------------------------*/
527
528static float128 commonNaNToFloat128( commonNaNT a )
529{
530 float128 z;
531
532 shift128Right( a.high, a.low, 16, &z.high, &z.low );
533 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
534 return z;
535}
536
537/*----------------------------------------------------------------------------
538| Takes two quadruple-precision floating-point values `a' and `b', one of
539| which is a NaN, and returns the appropriate NaN result. If either `a' or
540| `b' is a signaling NaN, the invalid exception is raised.
541*----------------------------------------------------------------------------*/
542
543static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
544{
545 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
546
547 if ( STATUS(default_nan_mode) ) {
548 a.low = float128_default_nan_low;
549 a.high = float128_default_nan_high;
550 return a;
551 }
552
553 aIsNaN = float128_is_nan( a );
554 aIsSignalingNaN = float128_is_signaling_nan( a );
555 bIsNaN = float128_is_nan( b );
556 bIsSignalingNaN = float128_is_signaling_nan( b );
557#if SNAN_BIT_IS_ONE
558 a.high &= ~LIT64( 0x0000800000000000 );
559 b.high &= ~LIT64( 0x0000800000000000 );
560#else
561 a.high |= LIT64( 0x0000800000000000 );
562 b.high |= LIT64( 0x0000800000000000 );
563#endif
564 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
565 if ( aIsSignalingNaN ) {
566 if ( bIsSignalingNaN ) goto returnLargerSignificand;
567 return bIsNaN ? b : a;
568 }
569 else if ( aIsNaN ) {
570 if ( bIsSignalingNaN | ! bIsNaN ) return a;
571 returnLargerSignificand:
572 if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
573 if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
574 return ( a.high < b.high ) ? a : b;
575 }
576 else {
577 return b;
578 }
579}
580
581#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette