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