1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
41
42
43
44
45
46void float_raise( int8 flags STATUS_PARAM )
47{
48 STATUS(float_exception_flags) |= flags;
49}
50
51
52
53
54typedef struct {
55 flag sign;
56 bits64 high, low;
57} commonNaNT;
58
59
60
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
76
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
91
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
106
107
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
123
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
138
139
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
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
204
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
221
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
238
239
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
255
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
273
274
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
326
327
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
339
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
359
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
379
380
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
396
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
413
414
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
461
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
473
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
491
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
509
510
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
525
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
539
540
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
582