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