VirtualBox

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

Last change on this file since 12977 was 1, checked in by vboxsync, 55 years ago

import

File size: 16.5 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/*----------------------------------------------------------------------------
34| Underflow tininess-detection mode, statically initialized to default value.
35| (The declaration in `softfloat.h' must match the `int8' type here.)
36*----------------------------------------------------------------------------*/
37int8 float_detect_tininess = float_tininess_after_rounding;
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
49 STATUS(float_exception_flags) |= flags;
50
51}
52
53/*----------------------------------------------------------------------------
54| Internal canonical NaN format.
55*----------------------------------------------------------------------------*/
56typedef struct {
57 flag sign;
58 bits64 high, low;
59} commonNaNT;
60
61/*----------------------------------------------------------------------------
62| The pattern for a default generated single-precision NaN.
63*----------------------------------------------------------------------------*/
64#define float32_default_nan 0xFFC00000
65
66/*----------------------------------------------------------------------------
67| Returns 1 if the single-precision floating-point value `a' is a NaN;
68| otherwise returns 0.
69*----------------------------------------------------------------------------*/
70
71int float32_is_nan( float32 a )
72{
73
74 return ( 0xFF000000 < (bits32) ( a<<1 ) );
75
76}
77
78/*----------------------------------------------------------------------------
79| Returns 1 if the single-precision floating-point value `a' is a signaling
80| NaN; otherwise returns 0.
81*----------------------------------------------------------------------------*/
82
83int float32_is_signaling_nan( float32 a )
84{
85
86 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
87
88}
89
90/*----------------------------------------------------------------------------
91| Returns the result of converting the single-precision floating-point NaN
92| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
93| exception is raised.
94*----------------------------------------------------------------------------*/
95
96static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
97{
98 commonNaNT z;
99
100 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
101 z.sign = a>>31;
102 z.low = 0;
103 z.high = ( (bits64) a )<<41;
104 return z;
105
106}
107
108/*----------------------------------------------------------------------------
109| Returns the result of converting the canonical NaN `a' to the single-
110| precision floating-point format.
111*----------------------------------------------------------------------------*/
112
113static float32 commonNaNToFloat32( commonNaNT a )
114{
115
116 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
117
118}
119
120/*----------------------------------------------------------------------------
121| Takes two single-precision floating-point values `a' and `b', one of which
122| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
123| signaling NaN, the invalid exception is raised.
124*----------------------------------------------------------------------------*/
125
126static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
127{
128 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
129
130 aIsNaN = float32_is_nan( a );
131 aIsSignalingNaN = float32_is_signaling_nan( a );
132 bIsNaN = float32_is_nan( b );
133 bIsSignalingNaN = float32_is_signaling_nan( b );
134 a |= 0x00400000;
135 b |= 0x00400000;
136 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
137 if ( aIsSignalingNaN ) {
138 if ( bIsSignalingNaN ) goto returnLargerSignificand;
139 return bIsNaN ? b : a;
140 }
141 else if ( aIsNaN ) {
142 if ( bIsSignalingNaN | ! bIsNaN ) return a;
143 returnLargerSignificand:
144 if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
145 if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
146 return ( a < b ) ? a : b;
147 }
148 else {
149 return b;
150 }
151
152}
153
154/*----------------------------------------------------------------------------
155| The pattern for a default generated double-precision NaN.
156*----------------------------------------------------------------------------*/
157#define float64_default_nan LIT64( 0xFFF8000000000000 )
158
159/*----------------------------------------------------------------------------
160| Returns 1 if the double-precision floating-point value `a' is a NaN;
161| otherwise returns 0.
162*----------------------------------------------------------------------------*/
163
164int float64_is_nan( float64 a )
165{
166
167 return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
168
169}
170
171/*----------------------------------------------------------------------------
172| Returns 1 if the double-precision floating-point value `a' is a signaling
173| NaN; otherwise returns 0.
174*----------------------------------------------------------------------------*/
175
176int float64_is_signaling_nan( float64 a )
177{
178
179 return
180 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
181 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
182
183}
184
185/*----------------------------------------------------------------------------
186| Returns the result of converting the double-precision floating-point NaN
187| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
188| exception is raised.
189*----------------------------------------------------------------------------*/
190
191static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
192{
193 commonNaNT z;
194
195 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
196 z.sign = a>>63;
197 z.low = 0;
198 z.high = a<<12;
199 return z;
200
201}
202
203/*----------------------------------------------------------------------------
204| Returns the result of converting the canonical NaN `a' to the double-
205| precision floating-point format.
206*----------------------------------------------------------------------------*/
207
208static float64 commonNaNToFloat64( commonNaNT a )
209{
210
211 return
212 ( ( (bits64) a.sign )<<63 )
213 | LIT64( 0x7FF8000000000000 )
214 | ( a.high>>12 );
215
216}
217
218/*----------------------------------------------------------------------------
219| Takes two double-precision floating-point values `a' and `b', one of which
220| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
221| signaling NaN, the invalid exception is raised.
222*----------------------------------------------------------------------------*/
223
224static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
225{
226 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
227
228 aIsNaN = float64_is_nan( a );
229 aIsSignalingNaN = float64_is_signaling_nan( a );
230 bIsNaN = float64_is_nan( b );
231 bIsSignalingNaN = float64_is_signaling_nan( b );
232 a |= LIT64( 0x0008000000000000 );
233 b |= LIT64( 0x0008000000000000 );
234 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
235 if ( aIsSignalingNaN ) {
236 if ( bIsSignalingNaN ) goto returnLargerSignificand;
237 return bIsNaN ? b : a;
238 }
239 else if ( aIsNaN ) {
240 if ( bIsSignalingNaN | ! bIsNaN ) return a;
241 returnLargerSignificand:
242 if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
243 if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
244 return ( a < b ) ? a : b;
245 }
246 else {
247 return b;
248 }
249
250}
251
252#ifdef FLOATX80
253
254/*----------------------------------------------------------------------------
255| The pattern for a default generated extended double-precision NaN. The
256| `high' and `low' values hold the most- and least-significant bits,
257| respectively.
258*----------------------------------------------------------------------------*/
259#define floatx80_default_nan_high 0xFFFF
260#define floatx80_default_nan_low LIT64( 0xC000000000000000 )
261
262/*----------------------------------------------------------------------------
263| Returns 1 if the extended double-precision floating-point value `a' is a
264| NaN; otherwise returns 0.
265*----------------------------------------------------------------------------*/
266
267int floatx80_is_nan( floatx80 a )
268{
269
270 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
271
272}
273
274/*----------------------------------------------------------------------------
275| Returns 1 if the extended double-precision floating-point value `a' is a
276| signaling NaN; otherwise returns 0.
277*----------------------------------------------------------------------------*/
278
279int floatx80_is_signaling_nan( floatx80 a )
280{
281 bits64 aLow;
282
283 aLow = a.low & ~ LIT64( 0x4000000000000000 );
284 return
285 ( ( a.high & 0x7FFF ) == 0x7FFF )
286 && (bits64) ( aLow<<1 )
287 && ( a.low == aLow );
288
289}
290
291/*----------------------------------------------------------------------------
292| Returns the result of converting the extended double-precision floating-
293| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
294| invalid exception is raised.
295*----------------------------------------------------------------------------*/
296
297static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
298{
299 commonNaNT z;
300
301 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
302 z.sign = a.high>>15;
303 z.low = 0;
304 z.high = a.low<<1;
305 return z;
306
307}
308
309/*----------------------------------------------------------------------------
310| Returns the result of converting the canonical NaN `a' to the extended
311| double-precision floating-point format.
312*----------------------------------------------------------------------------*/
313
314static floatx80 commonNaNToFloatx80( commonNaNT a )
315{
316 floatx80 z;
317
318 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
319 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
320 return z;
321
322}
323
324/*----------------------------------------------------------------------------
325| Takes two extended double-precision floating-point values `a' and `b', one
326| of which is a NaN, and returns the appropriate NaN result. If either `a' or
327| `b' is a signaling NaN, the invalid exception is raised.
328*----------------------------------------------------------------------------*/
329
330static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
331{
332 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
333
334 aIsNaN = floatx80_is_nan( a );
335 aIsSignalingNaN = floatx80_is_signaling_nan( a );
336 bIsNaN = floatx80_is_nan( b );
337 bIsSignalingNaN = floatx80_is_signaling_nan( b );
338 a.low |= LIT64( 0xC000000000000000 );
339 b.low |= LIT64( 0xC000000000000000 );
340 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
341 if ( aIsSignalingNaN ) {
342 if ( bIsSignalingNaN ) goto returnLargerSignificand;
343 return bIsNaN ? b : a;
344 }
345 else if ( aIsNaN ) {
346 if ( bIsSignalingNaN | ! bIsNaN ) return a;
347 returnLargerSignificand:
348 if ( a.low < b.low ) return b;
349 if ( b.low < a.low ) return a;
350 return ( a.high < b.high ) ? a : b;
351 }
352 else {
353 return b;
354 }
355
356}
357
358#endif
359
360#ifdef FLOAT128
361
362/*----------------------------------------------------------------------------
363| The pattern for a default generated quadruple-precision NaN. The `high' and
364| `low' values hold the most- and least-significant bits, respectively.
365*----------------------------------------------------------------------------*/
366#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
367#define float128_default_nan_low LIT64( 0x0000000000000000 )
368
369/*----------------------------------------------------------------------------
370| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
371| otherwise returns 0.
372*----------------------------------------------------------------------------*/
373
374int float128_is_nan( float128 a )
375{
376
377 return
378 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
379 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
380
381}
382
383/*----------------------------------------------------------------------------
384| Returns 1 if the quadruple-precision floating-point value `a' is a
385| signaling NaN; otherwise returns 0.
386*----------------------------------------------------------------------------*/
387
388int float128_is_signaling_nan( float128 a )
389{
390
391 return
392 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
393 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
394
395}
396
397/*----------------------------------------------------------------------------
398| Returns the result of converting the quadruple-precision floating-point NaN
399| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
400| exception is raised.
401*----------------------------------------------------------------------------*/
402
403static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
404{
405 commonNaNT z;
406
407 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
408 z.sign = a.high>>63;
409 shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
410 return z;
411
412}
413
414/*----------------------------------------------------------------------------
415| Returns the result of converting the canonical NaN `a' to the quadruple-
416| precision floating-point format.
417*----------------------------------------------------------------------------*/
418
419static float128 commonNaNToFloat128( commonNaNT a )
420{
421 float128 z;
422
423 shift128Right( a.high, a.low, 16, &z.high, &z.low );
424 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
425 return z;
426
427}
428
429/*----------------------------------------------------------------------------
430| Takes two quadruple-precision floating-point values `a' and `b', one of
431| which is a NaN, and returns the appropriate NaN result. If either `a' or
432| `b' is a signaling NaN, the invalid exception is raised.
433*----------------------------------------------------------------------------*/
434
435static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
436{
437 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
438
439 aIsNaN = float128_is_nan( a );
440 aIsSignalingNaN = float128_is_signaling_nan( a );
441 bIsNaN = float128_is_nan( b );
442 bIsSignalingNaN = float128_is_signaling_nan( b );
443 a.high |= LIT64( 0x0000800000000000 );
444 b.high |= LIT64( 0x0000800000000000 );
445 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
446 if ( aIsSignalingNaN ) {
447 if ( bIsSignalingNaN ) goto returnLargerSignificand;
448 return bIsNaN ? b : a;
449 }
450 else if ( aIsNaN ) {
451 if ( bIsSignalingNaN | ! bIsNaN ) return a;
452 returnLargerSignificand:
453 if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
454 if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
455 return ( a.high < b.high ) ? a : b;
456 }
457 else {
458 return b;
459 }
460
461}
462
463#endif
464
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