xref: /freebsd/lib/libc/softfloat/templates/softfloat-specialize (revision aa24f48b361effe51163877d84f1b70d32b77e04)
1/* $FreeBSD$ */
2
3/*
4===============================================================================
5
6This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
7Arithmetic Package, Release 2a.
8
9Written by John R. Hauser.  This work was made possible in part by the
10International Computer Science Institute, located at Suite 600, 1947 Center
11Street, Berkeley, California 94704.  Funding was partially provided by the
12National Science Foundation under grant MIP-9311980.  The original version
13of this code was written as part of a project to build a fixed-point vector
14processor in collaboration with the University of California at Berkeley,
15overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
16is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
17arithmetic/SoftFloat.html'.
18
19THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
20has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
21TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
22PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
23AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
24
25Derivative works are acceptable, even for commercial purposes, so long as
26(1) they include prominent notice that the work is derivative, and (2) they
27include prominent notice akin to these four paragraphs for those parts of
28this code that are retained.
29
30===============================================================================
31*/
32
33/*
34-------------------------------------------------------------------------------
35Underflow tininess-detection mode, statically initialized to default value.
36(The declaration in `softfloat.h' must match the `int8' type here.)
37-------------------------------------------------------------------------------
38*/
39int8 float_detect_tininess = float_tininess_after_rounding;
40
41/*
42-------------------------------------------------------------------------------
43Raises the exceptions specified by `flags'.  Floating-point traps can be
44defined here if desired.  It is currently not possible for such a trap to
45substitute a result value.  If traps are not implemented, this routine
46should be simply `float_exception_flags |= flags;'.
47-------------------------------------------------------------------------------
48*/
49void float_raise( int8 flags )
50{
51
52    float_exception_flags |= flags;
53
54}
55
56/*
57-------------------------------------------------------------------------------
58Internal canonical NaN format.
59-------------------------------------------------------------------------------
60*/
61typedef struct {
62    flag sign;
63    bits64 high, low;
64} commonNaNT;
65
66/*
67-------------------------------------------------------------------------------
68The pattern for a default generated single-precision NaN.
69-------------------------------------------------------------------------------
70*/
71#define float32_default_nan 0xFFFFFFFF
72
73/*
74-------------------------------------------------------------------------------
75Returns 1 if the single-precision floating-point value `a' is a NaN;
76otherwise returns 0.
77-------------------------------------------------------------------------------
78*/
79flag float32_is_nan( float32 a )
80{
81
82    return ( 0xFF000000 < (bits32) ( a<<1 ) );
83
84}
85
86/*
87-------------------------------------------------------------------------------
88Returns 1 if the single-precision floating-point value `a' is a signaling
89NaN; otherwise returns 0.
90-------------------------------------------------------------------------------
91*/
92flag float32_is_signaling_nan( float32 a )
93{
94
95    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
96
97}
98
99/*
100-------------------------------------------------------------------------------
101Returns the result of converting the single-precision floating-point NaN
102`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
103exception is raised.
104-------------------------------------------------------------------------------
105*/
106static commonNaNT float32ToCommonNaN( float32 a )
107{
108    commonNaNT z;
109
110    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
111    z.sign = a>>31;
112    z.low = 0;
113    z.high = ( (bits64) a )<<41;
114    return z;
115
116}
117
118/*
119-------------------------------------------------------------------------------
120Returns the result of converting the canonical NaN `a' to the single-
121precision floating-point format.
122-------------------------------------------------------------------------------
123*/
124static float32 commonNaNToFloat32( commonNaNT a )
125{
126
127    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
128
129}
130
131/*
132-------------------------------------------------------------------------------
133Takes two single-precision floating-point values `a' and `b', one of which
134is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
135signaling NaN, the invalid exception is raised.
136-------------------------------------------------------------------------------
137*/
138static float32 propagateFloat32NaN( float32 a, float32 b )
139{
140    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
141
142    aIsNaN = float32_is_nan( a );
143    aIsSignalingNaN = float32_is_signaling_nan( a );
144    bIsNaN = float32_is_nan( b );
145    bIsSignalingNaN = float32_is_signaling_nan( b );
146    a |= 0x00400000;
147    b |= 0x00400000;
148    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
149    if ( aIsNaN ) {
150        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
151    }
152    else {
153        return b;
154    }
155
156}
157
158/*
159-------------------------------------------------------------------------------
160The pattern for a default generated double-precision NaN.
161-------------------------------------------------------------------------------
162*/
163#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
164
165/*
166-------------------------------------------------------------------------------
167Returns 1 if the double-precision floating-point value `a' is a NaN;
168otherwise returns 0.
169-------------------------------------------------------------------------------
170*/
171flag float64_is_nan( float64 a )
172{
173
174    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
175
176}
177
178/*
179-------------------------------------------------------------------------------
180Returns 1 if the double-precision floating-point value `a' is a signaling
181NaN; otherwise returns 0.
182-------------------------------------------------------------------------------
183*/
184flag float64_is_signaling_nan( float64 a )
185{
186
187    return
188           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
189        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
190
191}
192
193/*
194-------------------------------------------------------------------------------
195Returns the result of converting the double-precision floating-point NaN
196`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
197exception is raised.
198-------------------------------------------------------------------------------
199*/
200static commonNaNT float64ToCommonNaN( float64 a )
201{
202    commonNaNT z;
203
204    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
205    z.sign = a>>63;
206    z.low = 0;
207    z.high = a<<12;
208    return z;
209
210}
211
212/*
213-------------------------------------------------------------------------------
214Returns the result of converting the canonical NaN `a' to the double-
215precision floating-point format.
216-------------------------------------------------------------------------------
217*/
218static float64 commonNaNToFloat64( commonNaNT a )
219{
220
221    return
222          ( ( (bits64) a.sign )<<63 )
223        | LIT64( 0x7FF8000000000000 )
224        | ( a.high>>12 );
225
226}
227
228/*
229-------------------------------------------------------------------------------
230Takes two double-precision floating-point values `a' and `b', one of which
231is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
232signaling NaN, the invalid exception is raised.
233-------------------------------------------------------------------------------
234*/
235static float64 propagateFloat64NaN( float64 a, float64 b )
236{
237    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
238
239    aIsNaN = float64_is_nan( a );
240    aIsSignalingNaN = float64_is_signaling_nan( a );
241    bIsNaN = float64_is_nan( b );
242    bIsSignalingNaN = float64_is_signaling_nan( b );
243    a |= LIT64( 0x0008000000000000 );
244    b |= LIT64( 0x0008000000000000 );
245    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
246    if ( aIsNaN ) {
247        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
248    }
249    else {
250        return b;
251    }
252
253}
254
255#ifdef FLOATX80
256
257/*
258-------------------------------------------------------------------------------
259The pattern for a default generated extended double-precision NaN.  The
260`high' and `low' values hold the most- and least-significant bits,
261respectively.
262-------------------------------------------------------------------------------
263*/
264#define floatx80_default_nan_high 0xFFFF
265#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
266
267/*
268-------------------------------------------------------------------------------
269Returns 1 if the extended double-precision floating-point value `a' is a
270NaN; otherwise returns 0.
271-------------------------------------------------------------------------------
272*/
273flag floatx80_is_nan( floatx80 a )
274{
275
276    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
277
278}
279
280/*
281-------------------------------------------------------------------------------
282Returns 1 if the extended double-precision floating-point value `a' is a
283signaling NaN; otherwise returns 0.
284-------------------------------------------------------------------------------
285*/
286flag floatx80_is_signaling_nan( floatx80 a )
287{
288    bits64 aLow;
289
290    aLow = a.low & ~ LIT64( 0x4000000000000000 );
291    return
292           ( ( a.high & 0x7FFF ) == 0x7FFF )
293        && (bits64) ( aLow<<1 )
294        && ( a.low == aLow );
295
296}
297
298/*
299-------------------------------------------------------------------------------
300Returns the result of converting the extended double-precision floating-
301point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
302invalid exception is raised.
303-------------------------------------------------------------------------------
304*/
305static commonNaNT floatx80ToCommonNaN( floatx80 a )
306{
307    commonNaNT z;
308
309    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
310    z.sign = a.high>>15;
311    z.low = 0;
312    z.high = a.low<<1;
313    return z;
314
315}
316
317/*
318-------------------------------------------------------------------------------
319Returns the result of converting the canonical NaN `a' to the extended
320double-precision floating-point format.
321-------------------------------------------------------------------------------
322*/
323static floatx80 commonNaNToFloatx80( commonNaNT a )
324{
325    floatx80 z;
326
327    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
328    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
329    return z;
330
331}
332
333/*
334-------------------------------------------------------------------------------
335Takes two extended double-precision floating-point values `a' and `b', one
336of which is a NaN, and returns the appropriate NaN result.  If either `a' or
337`b' is a signaling NaN, the invalid exception is raised.
338-------------------------------------------------------------------------------
339*/
340static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
341{
342    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
343
344    aIsNaN = floatx80_is_nan( a );
345    aIsSignalingNaN = floatx80_is_signaling_nan( a );
346    bIsNaN = floatx80_is_nan( b );
347    bIsSignalingNaN = floatx80_is_signaling_nan( b );
348    a.low |= LIT64( 0xC000000000000000 );
349    b.low |= LIT64( 0xC000000000000000 );
350    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
351    if ( aIsNaN ) {
352        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
353    }
354    else {
355        return b;
356    }
357
358}
359
360#endif
361
362#ifdef FLOAT128
363
364/*
365-------------------------------------------------------------------------------
366The pattern for a default generated quadruple-precision NaN.  The `high' and
367`low' values hold the most- and least-significant bits, respectively.
368-------------------------------------------------------------------------------
369*/
370#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
371#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
372
373/*
374-------------------------------------------------------------------------------
375Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
376otherwise returns 0.
377-------------------------------------------------------------------------------
378*/
379flag float128_is_nan( float128 a )
380{
381
382    return
383           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
384        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
385
386}
387
388/*
389-------------------------------------------------------------------------------
390Returns 1 if the quadruple-precision floating-point value `a' is a
391signaling NaN; otherwise returns 0.
392-------------------------------------------------------------------------------
393*/
394flag float128_is_signaling_nan( float128 a )
395{
396
397    return
398           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
399        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
400
401}
402
403/*
404-------------------------------------------------------------------------------
405Returns the result of converting the quadruple-precision floating-point NaN
406`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
407exception is raised.
408-------------------------------------------------------------------------------
409*/
410static commonNaNT float128ToCommonNaN( float128 a )
411{
412    commonNaNT z;
413
414    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
415    z.sign = a.high>>63;
416    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
417    return z;
418
419}
420
421/*
422-------------------------------------------------------------------------------
423Returns the result of converting the canonical NaN `a' to the quadruple-
424precision floating-point format.
425-------------------------------------------------------------------------------
426*/
427static float128 commonNaNToFloat128( commonNaNT a )
428{
429    float128 z;
430
431    shift128Right( a.high, a.low, 16, &z.high, &z.low );
432    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
433    return z;
434
435}
436
437/*
438-------------------------------------------------------------------------------
439Takes two quadruple-precision floating-point values `a' and `b', one of
440which is a NaN, and returns the appropriate NaN result.  If either `a' or
441`b' is a signaling NaN, the invalid exception is raised.
442-------------------------------------------------------------------------------
443*/
444static float128 propagateFloat128NaN( float128 a, float128 b )
445{
446    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
447
448    aIsNaN = float128_is_nan( a );
449    aIsSignalingNaN = float128_is_signaling_nan( a );
450    bIsNaN = float128_is_nan( b );
451    bIsSignalingNaN = float128_is_signaling_nan( b );
452    a.high |= LIT64( 0x0000800000000000 );
453    b.high |= LIT64( 0x0000800000000000 );
454    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
455    if ( aIsNaN ) {
456        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
457    }
458    else {
459        return b;
460    }
461
462}
463
464#endif
465
466