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