]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmSoftFloatLib/softfloat-specialize
ArmPkg/DebugAgentSymbolsBaseLib: remove exception handling
[mirror_edk2.git] / ArmPkg / Library / ArmSoftFloatLib / softfloat-specialize
CommitLineData
1dbda2b4
AB
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
1dbda2b4
AB
35/*\r
36-------------------------------------------------------------------------------\r
37Underflow tininess-detection mode, statically initialized to default value.\r
38(The declaration in `softfloat.h' must match the `int8' type here.)\r
39-------------------------------------------------------------------------------\r
40*/\r
41#ifdef SOFTFLOAT_FOR_GCC\r
42static\r
43#endif\r
44int8 float_detect_tininess = float_tininess_after_rounding;\r
45\r
46/*\r
47-------------------------------------------------------------------------------\r
48Raises the exceptions specified by `flags'. Floating-point traps can be\r
49defined here if desired. It is currently not possible for such a trap to\r
50substitute a result value. If traps are not implemented, this routine\r
51should be simply `float_exception_flags |= flags;'.\r
52-------------------------------------------------------------------------------\r
53*/\r
54#ifdef SOFTFLOAT_FOR_GCC\r
55#ifndef set_float_exception_mask\r
56#define float_exception_mask _softfloat_float_exception_mask\r
57#endif\r
58#endif\r
59#ifndef set_float_exception_mask\r
60fp_except float_exception_mask = 0;\r
61#endif\r
62void\r
63float_raise( fp_except flags )\r
64{\r
65\r
66#if 0 // Don't raise exceptions\r
67 siginfo_t info;\r
68 fp_except mask = float_exception_mask;\r
69\r
70#ifdef set_float_exception_mask\r
71 flags |= set_float_exception_flags(flags, 0);\r
72#else\r
73 float_exception_flags |= flags;\r
74 flags = float_exception_flags;\r
75#endif\r
76\r
77 flags &= mask;\r
78 if ( flags ) {\r
79 memset(&info, 0, sizeof info);\r
80 info.si_signo = SIGFPE;\r
81 info.si_pid = getpid();\r
82 info.si_uid = geteuid();\r
83 if (flags & float_flag_underflow)\r
84 info.si_code = FPE_FLTUND;\r
85 else if (flags & float_flag_overflow)\r
86 info.si_code = FPE_FLTOVF;\r
87 else if (flags & float_flag_divbyzero)\r
88 info.si_code = FPE_FLTDIV;\r
89 else if (flags & float_flag_invalid)\r
90 info.si_code = FPE_FLTINV;\r
91 else if (flags & float_flag_inexact)\r
92 info.si_code = FPE_FLTRES;\r
93 sigqueueinfo(getpid(), &info);\r
94 }\r
95#else // Don't raise exceptions\r
96 float_exception_flags |= flags;\r
97#endif // Don't raise exceptions\r
98}\r
99#undef float_exception_mask\r
100\r
101/*\r
102-------------------------------------------------------------------------------\r
103Internal canonical NaN format.\r
104-------------------------------------------------------------------------------\r
105*/\r
106typedef struct {\r
107 flag sign;\r
108 bits64 high, low;\r
109} commonNaNT;\r
110\r
111/*\r
112-------------------------------------------------------------------------------\r
113The pattern for a default generated single-precision NaN.\r
114-------------------------------------------------------------------------------\r
115*/\r
116#define float32_default_nan 0xFFFFFFFF\r
117\r
118/*\r
119-------------------------------------------------------------------------------\r
120Returns 1 if the single-precision floating-point value `a' is a NaN;\r
121otherwise returns 0.\r
122-------------------------------------------------------------------------------\r
123*/\r
124#ifdef SOFTFLOAT_FOR_GCC\r
125static\r
126#endif\r
127flag float32_is_nan( float32 a )\r
128{\r
129\r
130 return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );\r
131\r
132}\r
133\r
134/*\r
135-------------------------------------------------------------------------------\r
136Returns 1 if the single-precision floating-point value `a' is a signaling\r
137NaN; otherwise returns 0.\r
138-------------------------------------------------------------------------------\r
139*/\r
140#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \\r
141 !defined(SOFTFLOAT_M68K_FOR_GCC)\r
142static\r
143#endif\r
144flag float32_is_signaling_nan( float32 a )\r
145{\r
146\r
147 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );\r
148\r
149}\r
150\r
151/*\r
152-------------------------------------------------------------------------------\r
153Returns the result of converting the single-precision floating-point NaN\r
154`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid\r
155exception is raised.\r
156-------------------------------------------------------------------------------\r
157*/\r
158static commonNaNT float32ToCommonNaN( float32 a )\r
159{\r
160 commonNaNT z;\r
161\r
162 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );\r
163 z.sign = a>>31;\r
164 z.low = 0;\r
165 z.high = ( (bits64) a )<<41;\r
166 return z;\r
167\r
168}\r
169\r
170/*\r
171-------------------------------------------------------------------------------\r
172Returns the result of converting the canonical NaN `a' to the single-\r
173precision floating-point format.\r
174-------------------------------------------------------------------------------\r
175*/\r
176static float32 commonNaNToFloat32( commonNaNT a )\r
177{\r
178\r
179 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );\r
180\r
181}\r
182\r
183/*\r
184-------------------------------------------------------------------------------\r
185Takes two single-precision floating-point values `a' and `b', one of which\r
186is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a\r
187signaling NaN, the invalid exception is raised.\r
188-------------------------------------------------------------------------------\r
189*/\r
190static float32 propagateFloat32NaN( float32 a, float32 b )\r
191{\r
192 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;\r
193\r
194 aIsNaN = float32_is_nan( a );\r
195 aIsSignalingNaN = float32_is_signaling_nan( a );\r
196 bIsNaN = float32_is_nan( b );\r
197 bIsSignalingNaN = float32_is_signaling_nan( b );\r
198 a |= 0x00400000;\r
199 b |= 0x00400000;\r
200 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );\r
201 if ( aIsNaN ) {\r
202 return ( aIsSignalingNaN & bIsNaN ) ? b : a;\r
203 }\r
204 else {\r
205 return b;\r
206 }\r
207\r
208}\r
209\r
210/*\r
211-------------------------------------------------------------------------------\r
212The pattern for a default generated double-precision NaN.\r
213-------------------------------------------------------------------------------\r
214*/\r
215#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )\r
216\r
217/*\r
218-------------------------------------------------------------------------------\r
219Returns 1 if the double-precision floating-point value `a' is a NaN;\r
220otherwise returns 0.\r
221-------------------------------------------------------------------------------\r
222*/\r
223#ifdef SOFTFLOAT_FOR_GCC\r
224static\r
225#endif\r
226flag float64_is_nan( float64 a )\r
227{\r
228\r
229 return ( (bits64)LIT64( 0xFFE0000000000000 ) <\r
230 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );\r
231\r
232}\r
233\r
234/*\r
235-------------------------------------------------------------------------------\r
236Returns 1 if the double-precision floating-point value `a' is a signaling\r
237NaN; otherwise returns 0.\r
238-------------------------------------------------------------------------------\r
239*/\r
240#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \\r
241 !defined(SOFTFLOATM68K_FOR_GCC)\r
242static\r
243#endif\r
244flag float64_is_signaling_nan( float64 a )\r
245{\r
246\r
247 return\r
248 ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )\r
249 && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );\r
250\r
251}\r
252\r
253/*\r
254-------------------------------------------------------------------------------\r
255Returns the result of converting the double-precision floating-point NaN\r
256`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid\r
257exception is raised.\r
258-------------------------------------------------------------------------------\r
259*/\r
260static commonNaNT float64ToCommonNaN( float64 a )\r
261{\r
262 commonNaNT z;\r
263\r
264 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );\r
265 z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63);\r
266 z.low = 0;\r
267 z.high = FLOAT64_DEMANGLE(a)<<12;\r
268 return z;\r
269\r
270}\r
271\r
272/*\r
273-------------------------------------------------------------------------------\r
274Returns the result of converting the canonical NaN `a' to the double-\r
275precision floating-point format.\r
276-------------------------------------------------------------------------------\r
277*/\r
278static float64 commonNaNToFloat64( commonNaNT a )\r
279{\r
280\r
281 return FLOAT64_MANGLE(\r
282 ( ( (bits64) a.sign )<<63 )\r
283 | LIT64( 0x7FF8000000000000 )\r
284 | ( a.high>>12 ) );\r
285\r
286}\r
287\r
288/*\r
289-------------------------------------------------------------------------------\r
290Takes two double-precision floating-point values `a' and `b', one of which\r
291is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a\r
292signaling NaN, the invalid exception is raised.\r
293-------------------------------------------------------------------------------\r
294*/\r
295static float64 propagateFloat64NaN( float64 a, float64 b )\r
296{\r
297 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;\r
298\r
299 aIsNaN = float64_is_nan( a );\r
300 aIsSignalingNaN = float64_is_signaling_nan( a );\r
301 bIsNaN = float64_is_nan( b );\r
302 bIsSignalingNaN = float64_is_signaling_nan( b );\r
303 a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));\r
304 b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));\r
305 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );\r
306 if ( aIsNaN ) {\r
307 return ( aIsSignalingNaN & bIsNaN ) ? b : a;\r
308 }\r
309 else {\r
310 return b;\r
311 }\r
312\r
313}\r
314\r
315#ifdef FLOATX80\r
316\r
317/*\r
318-------------------------------------------------------------------------------\r
319The pattern for a default generated extended double-precision NaN. The\r
320`high' and `low' values hold the most- and least-significant bits,\r
321respectively.\r
322-------------------------------------------------------------------------------\r
323*/\r
324#define floatx80_default_nan_high 0xFFFF\r
325#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )\r
326\r
327/*\r
328-------------------------------------------------------------------------------\r
329Returns 1 if the extended double-precision floating-point value `a' is a\r
330NaN; otherwise returns 0.\r
331-------------------------------------------------------------------------------\r
332*/\r
333flag floatx80_is_nan( floatx80 a )\r
334{\r
335\r
336 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );\r
337\r
338}\r
339\r
340/*\r
341-------------------------------------------------------------------------------\r
342Returns 1 if the extended double-precision floating-point value `a' is a\r
343signaling NaN; otherwise returns 0.\r
344-------------------------------------------------------------------------------\r
345*/\r
346flag floatx80_is_signaling_nan( floatx80 a )\r
347{\r
348 bits64 aLow;\r
349\r
350 aLow = a.low & ~ LIT64( 0x4000000000000000 );\r
351 return\r
352 ( ( a.high & 0x7FFF ) == 0x7FFF )\r
353 && (bits64) ( aLow<<1 )\r
354 && ( a.low == aLow );\r
355\r
356}\r
357\r
358/*\r
359-------------------------------------------------------------------------------\r
360Returns the result of converting the extended double-precision floating-\r
361point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the\r
362invalid exception is raised.\r
363-------------------------------------------------------------------------------\r
364*/\r
365static commonNaNT floatx80ToCommonNaN( floatx80 a )\r
366{\r
367 commonNaNT z;\r
368\r
369 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );\r
370 z.sign = a.high>>15;\r
371 z.low = 0;\r
372 z.high = a.low<<1;\r
373 return z;\r
374\r
375}\r
376\r
377/*\r
378-------------------------------------------------------------------------------\r
379Returns the result of converting the canonical NaN `a' to the extended\r
380double-precision floating-point format.\r
381-------------------------------------------------------------------------------\r
382*/\r
383static floatx80 commonNaNToFloatx80( commonNaNT a )\r
384{\r
385 floatx80 z;\r
386\r
387 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );\r
388 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;\r
389 return z;\r
390\r
391}\r
392\r
393/*\r
394-------------------------------------------------------------------------------\r
395Takes two extended double-precision floating-point values `a' and `b', one\r
396of which is a NaN, and returns the appropriate NaN result. If either `a' or\r
397`b' is a signaling NaN, the invalid exception is raised.\r
398-------------------------------------------------------------------------------\r
399*/\r
400static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )\r
401{\r
402 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;\r
403\r
404 aIsNaN = floatx80_is_nan( a );\r
405 aIsSignalingNaN = floatx80_is_signaling_nan( a );\r
406 bIsNaN = floatx80_is_nan( b );\r
407 bIsSignalingNaN = floatx80_is_signaling_nan( b );\r
408 a.low |= LIT64( 0xC000000000000000 );\r
409 b.low |= LIT64( 0xC000000000000000 );\r
410 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );\r
411 if ( aIsNaN ) {\r
412 return ( aIsSignalingNaN & bIsNaN ) ? b : a;\r
413 }\r
414 else {\r
415 return b;\r
416 }\r
417\r
418}\r
419\r
420#endif\r
421\r
422#ifdef FLOAT128\r
423\r
424/*\r
425-------------------------------------------------------------------------------\r
426The pattern for a default generated quadruple-precision NaN. The `high' and\r
427`low' values hold the most- and least-significant bits, respectively.\r
428-------------------------------------------------------------------------------\r
429*/\r
430#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )\r
431#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )\r
432\r
433/*\r
434-------------------------------------------------------------------------------\r
435Returns 1 if the quadruple-precision floating-point value `a' is a NaN;\r
436otherwise returns 0.\r
437-------------------------------------------------------------------------------\r
438*/\r
439flag float128_is_nan( float128 a )\r
440{\r
441\r
442 return\r
443 ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )\r
444 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );\r
445\r
446}\r
447\r
448/*\r
449-------------------------------------------------------------------------------\r
450Returns 1 if the quadruple-precision floating-point value `a' is a\r
451signaling NaN; otherwise returns 0.\r
452-------------------------------------------------------------------------------\r
453*/\r
454flag float128_is_signaling_nan( float128 a )\r
455{\r
456\r
457 return\r
458 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )\r
459 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );\r
460\r
461}\r
462\r
463/*\r
464-------------------------------------------------------------------------------\r
465Returns the result of converting the quadruple-precision floating-point NaN\r
466`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid\r
467exception is raised.\r
468-------------------------------------------------------------------------------\r
469*/\r
470static commonNaNT float128ToCommonNaN( float128 a )\r
471{\r
472 commonNaNT z;\r
473\r
474 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );\r
475 z.sign = (flag)(a.high>>63);\r
476 shortShift128Left( a.high, a.low, 16, &z.high, &z.low );\r
477 return z;\r
478\r
479}\r
480\r
481/*\r
482-------------------------------------------------------------------------------\r
483Returns the result of converting the canonical NaN `a' to the quadruple-\r
484precision floating-point format.\r
485-------------------------------------------------------------------------------\r
486*/\r
487static float128 commonNaNToFloat128( commonNaNT a )\r
488{\r
489 float128 z;\r
490\r
491 shift128Right( a.high, a.low, 16, &z.high, &z.low );\r
492 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );\r
493 return z;\r
494\r
495}\r
496\r
497/*\r
498-------------------------------------------------------------------------------\r
499Takes two quadruple-precision floating-point values `a' and `b', one of\r
500which is a NaN, and returns the appropriate NaN result. If either `a' or\r
501`b' is a signaling NaN, the invalid exception is raised.\r
502-------------------------------------------------------------------------------\r
503*/\r
504static float128 propagateFloat128NaN( float128 a, float128 b )\r
505{\r
506 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;\r
507\r
508 aIsNaN = float128_is_nan( a );\r
509 aIsSignalingNaN = float128_is_signaling_nan( a );\r
510 bIsNaN = float128_is_nan( b );\r
511 bIsSignalingNaN = float128_is_signaling_nan( b );\r
512 a.high |= LIT64( 0x0000800000000000 );\r
513 b.high |= LIT64( 0x0000800000000000 );\r
514 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );\r
515 if ( aIsNaN ) {\r
516 return ( aIsSignalingNaN & bIsNaN ) ? b : a;\r
517 }\r
518 else {\r
519 return b;\r
520 }\r
521\r
522}\r
523\r
524#endif\r
525\r