softfloat-specialize revision 1.10 1 1.10 riastrad /* $NetBSD: softfloat-specialize,v 1.10 2025/04/27 15:23:27 riastradh 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.10 riastrad #include "reentrant.h"
40 1.10 riastrad
41 1.1 bjh21 /*
42 1.1 bjh21 -------------------------------------------------------------------------------
43 1.1 bjh21 Underflow tininess-detection mode, statically initialized to default value.
44 1.1 bjh21 (The declaration in `softfloat.h' must match the `int8' type here.)
45 1.1 bjh21 -------------------------------------------------------------------------------
46 1.1 bjh21 */
47 1.1 bjh21 #ifdef SOFTFLOAT_FOR_GCC
48 1.1 bjh21 static
49 1.1 bjh21 #endif
50 1.1 bjh21 int8 float_detect_tininess = float_tininess_after_rounding;
51 1.1 bjh21
52 1.1 bjh21 /*
53 1.1 bjh21 -------------------------------------------------------------------------------
54 1.1 bjh21 Raises the exceptions specified by `flags'. Floating-point traps can be
55 1.1 bjh21 defined here if desired. It is currently not possible for such a trap to
56 1.1 bjh21 substitute a result value. If traps are not implemented, this routine
57 1.1 bjh21 should be simply `float_exception_flags |= flags;'.
58 1.1 bjh21 -------------------------------------------------------------------------------
59 1.1 bjh21 */
60 1.6 martin #ifdef SOFTFLOAT_FOR_GCC
61 1.8 matt #ifndef set_float_exception_mask
62 1.6 martin #define float_exception_mask _softfloat_float_exception_mask
63 1.6 martin #endif
64 1.8 matt #endif
65 1.8 matt #ifndef set_float_exception_mask
66 1.3 bjh21 fp_except float_exception_mask = 0;
67 1.8 matt #endif
68 1.8 matt void
69 1.10 riastrad float_raise( fp_except newflags )
70 1.1 bjh21 {
71 1.5 martin siginfo_t info;
72 1.10 riastrad struct sigaction sa;
73 1.10 riastrad sigset_t sigmask, osigmask;
74 1.10 riastrad fp_except flags;
75 1.1 bjh21
76 1.10 riastrad for (;;) {
77 1.8 matt #ifdef set_float_exception_mask
78 1.10 riastrad flags = newflags | set_float_exception_flags(newflags, 0);
79 1.8 matt #else
80 1.10 riastrad float_exception_flags |= newflags;
81 1.10 riastrad flags = float_exception_flags;
82 1.8 matt #endif
83 1.1 bjh21
84 1.10 riastrad /*
85 1.10 riastrad * If none of the sticky flags are trapped (i.e., enabled in
86 1.10 riastrad * float_exception_mask), we're done. Trapping is unusual and
87 1.10 riastrad * costly anyway, so take the non-trapping path as the fast
88 1.10 riastrad * path.
89 1.10 riastrad */
90 1.10 riastrad flags &= float_exception_mask;
91 1.10 riastrad if (__predict_true(flags == 0))
92 1.10 riastrad break;
93 1.10 riastrad
94 1.10 riastrad /*
95 1.10 riastrad * Block all signals while we figure out how to deliver a
96 1.10 riastrad * non-maskable (as a signal), non-ignorable SIGFPE, and obtain
97 1.10 riastrad * the current signal mask.
98 1.10 riastrad */
99 1.10 riastrad sigfillset(&sigmask);
100 1.10 riastrad thr_sigsetmask(SIG_BLOCK, &sigmask, &osigmask);
101 1.10 riastrad
102 1.10 riastrad /*
103 1.10 riastrad * Find the current signal disposition of SIGFPE.
104 1.10 riastrad */
105 1.10 riastrad sigaction(SIGFPE, NULL, &sa);
106 1.10 riastrad
107 1.10 riastrad /*
108 1.10 riastrad * If SIGFPE is masked or ignored, unmask it and reset it to
109 1.10 riastrad * the default disposition to deliver the signal.
110 1.10 riastrad */
111 1.10 riastrad if (sigismember(&osigmask, SIGFPE) ||
112 1.10 riastrad ((sa.sa_flags & SA_SIGINFO) == 0 &&
113 1.10 riastrad sa.sa_handler == SIG_IGN)) {
114 1.10 riastrad /*
115 1.10 riastrad * Prepare to unmask SIGFPE. This will take effect
116 1.10 riastrad * when we use thr_sigsetmask(SIG_SETMASK, ...) below,
117 1.10 riastrad * once the signal has been queued, so that it happens
118 1.10 riastrad * atomically with respect to other signal delivery.
119 1.10 riastrad */
120 1.10 riastrad sigdelset(&osigmask, SIGFPE);
121 1.10 riastrad
122 1.10 riastrad /*
123 1.10 riastrad * Reset SIGFPE to the default disposition, which is to
124 1.10 riastrad * terminate the process.
125 1.10 riastrad */
126 1.10 riastrad memset(&sa, 0, sizeof(sa));
127 1.10 riastrad sa.sa_handler = SIG_DFL;
128 1.10 riastrad sigemptyset(&sa.sa_mask);
129 1.10 riastrad sa.sa_flags = 0;
130 1.10 riastrad sigaction(SIGFPE, &sa, NULL);
131 1.10 riastrad }
132 1.10 riastrad
133 1.10 riastrad /*
134 1.10 riastrad * Queue the signal for delivery. It won't trigger the signal
135 1.10 riastrad * handler yet, because it's still masked, but as soon as we
136 1.10 riastrad * unmask it either the process will terminate or the signal
137 1.10 riastrad * handler will be called.
138 1.10 riastrad */
139 1.5 martin memset(&info, 0, sizeof info);
140 1.5 martin info.si_signo = SIGFPE;
141 1.5 martin info.si_pid = getpid();
142 1.5 martin info.si_uid = geteuid();
143 1.5 martin if (flags & float_flag_underflow)
144 1.5 martin info.si_code = FPE_FLTUND;
145 1.5 martin else if (flags & float_flag_overflow)
146 1.5 martin info.si_code = FPE_FLTOVF;
147 1.5 martin else if (flags & float_flag_divbyzero)
148 1.5 martin info.si_code = FPE_FLTDIV;
149 1.5 martin else if (flags & float_flag_invalid)
150 1.5 martin info.si_code = FPE_FLTINV;
151 1.5 martin else if (flags & float_flag_inexact)
152 1.5 martin info.si_code = FPE_FLTRES;
153 1.5 martin sigqueueinfo(getpid(), &info);
154 1.10 riastrad
155 1.10 riastrad /*
156 1.10 riastrad * Restore the old signal mask, except with SIGFPE unmasked
157 1.10 riastrad * even if it was masked before.
158 1.10 riastrad *
159 1.10 riastrad * At this point, either the process will terminate (if SIGFPE
160 1.10 riastrad * had or now has the default disposition) or the signal
161 1.10 riastrad * handler will be called (if SIGFPE had a non-default,
162 1.10 riastrad * non-ignored disposition).
163 1.10 riastrad *
164 1.10 riastrad * If the signal handler returns, it can't change the set of
165 1.10 riastrad * exceptions raised by this floating-point operation -- but it
166 1.10 riastrad * can change the sticky set from previous operations, and it
167 1.10 riastrad * can change the set of exceptions that are trapped, so loop
168 1.10 riastrad * around; next time we might make progress instead of calling
169 1.10 riastrad * the signal handler again.
170 1.10 riastrad */
171 1.10 riastrad thr_sigsetmask(SIG_SETMASK, &osigmask, NULL);
172 1.3 bjh21 }
173 1.1 bjh21 }
174 1.6 martin #undef float_exception_mask
175 1.1 bjh21
176 1.1 bjh21 /*
177 1.1 bjh21 -------------------------------------------------------------------------------
178 1.1 bjh21 Internal canonical NaN format.
179 1.1 bjh21 -------------------------------------------------------------------------------
180 1.1 bjh21 */
181 1.1 bjh21 typedef struct {
182 1.1 bjh21 flag sign;
183 1.1 bjh21 bits64 high, low;
184 1.1 bjh21 } commonNaNT;
185 1.1 bjh21
186 1.1 bjh21 /*
187 1.1 bjh21 -------------------------------------------------------------------------------
188 1.1 bjh21 The pattern for a default generated single-precision NaN.
189 1.1 bjh21 -------------------------------------------------------------------------------
190 1.1 bjh21 */
191 1.1 bjh21 #define float32_default_nan 0xFFFFFFFF
192 1.1 bjh21
193 1.1 bjh21 /*
194 1.1 bjh21 -------------------------------------------------------------------------------
195 1.1 bjh21 Returns 1 if the single-precision floating-point value `a' is a NaN;
196 1.1 bjh21 otherwise returns 0.
197 1.1 bjh21 -------------------------------------------------------------------------------
198 1.1 bjh21 */
199 1.1 bjh21 #ifdef SOFTFLOAT_FOR_GCC
200 1.1 bjh21 static
201 1.1 bjh21 #endif
202 1.1 bjh21 flag float32_is_nan( float32 a )
203 1.1 bjh21 {
204 1.1 bjh21
205 1.7 christos return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );
206 1.1 bjh21
207 1.1 bjh21 }
208 1.1 bjh21
209 1.1 bjh21 /*
210 1.1 bjh21 -------------------------------------------------------------------------------
211 1.1 bjh21 Returns 1 if the single-precision floating-point value `a' is a signaling
212 1.1 bjh21 NaN; otherwise returns 0.
213 1.1 bjh21 -------------------------------------------------------------------------------
214 1.1 bjh21 */
215 1.9 matt #if defined(SOFTFLOAT_FOR_GCC) \
216 1.9 matt && !defined(SOFTFLOATAARCH64_FOR_GCC) \
217 1.9 matt && !defined(SOFTFLOATSPARC64_FOR_GCC) \
218 1.9 matt && !defined(SOFTFLOATM68K_FOR_GCC)
219 1.1 bjh21 static
220 1.1 bjh21 #endif
221 1.1 bjh21 flag float32_is_signaling_nan( float32 a )
222 1.1 bjh21 {
223 1.1 bjh21
224 1.1 bjh21 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
225 1.1 bjh21
226 1.1 bjh21 }
227 1.1 bjh21
228 1.1 bjh21 /*
229 1.1 bjh21 -------------------------------------------------------------------------------
230 1.1 bjh21 Returns the result of converting the single-precision floating-point NaN
231 1.1 bjh21 `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
232 1.1 bjh21 exception is raised.
233 1.1 bjh21 -------------------------------------------------------------------------------
234 1.1 bjh21 */
235 1.1 bjh21 static commonNaNT float32ToCommonNaN( float32 a )
236 1.1 bjh21 {
237 1.1 bjh21 commonNaNT z;
238 1.1 bjh21
239 1.1 bjh21 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
240 1.1 bjh21 z.sign = a>>31;
241 1.1 bjh21 z.low = 0;
242 1.1 bjh21 z.high = ( (bits64) a )<<41;
243 1.1 bjh21 return z;
244 1.1 bjh21
245 1.1 bjh21 }
246 1.1 bjh21
247 1.1 bjh21 /*
248 1.1 bjh21 -------------------------------------------------------------------------------
249 1.1 bjh21 Returns the result of converting the canonical NaN `a' to the single-
250 1.1 bjh21 precision floating-point format.
251 1.1 bjh21 -------------------------------------------------------------------------------
252 1.1 bjh21 */
253 1.1 bjh21 static float32 commonNaNToFloat32( commonNaNT a )
254 1.1 bjh21 {
255 1.1 bjh21
256 1.7 christos return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
257 1.1 bjh21
258 1.1 bjh21 }
259 1.1 bjh21
260 1.1 bjh21 /*
261 1.1 bjh21 -------------------------------------------------------------------------------
262 1.1 bjh21 Takes two single-precision floating-point values `a' and `b', one of which
263 1.1 bjh21 is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
264 1.1 bjh21 signaling NaN, the invalid exception is raised.
265 1.1 bjh21 -------------------------------------------------------------------------------
266 1.1 bjh21 */
267 1.1 bjh21 static float32 propagateFloat32NaN( float32 a, float32 b )
268 1.1 bjh21 {
269 1.1 bjh21 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
270 1.1 bjh21
271 1.1 bjh21 aIsNaN = float32_is_nan( a );
272 1.1 bjh21 aIsSignalingNaN = float32_is_signaling_nan( a );
273 1.1 bjh21 bIsNaN = float32_is_nan( b );
274 1.1 bjh21 bIsSignalingNaN = float32_is_signaling_nan( b );
275 1.1 bjh21 a |= 0x00400000;
276 1.1 bjh21 b |= 0x00400000;
277 1.1 bjh21 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
278 1.1 bjh21 if ( aIsNaN ) {
279 1.1 bjh21 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
280 1.1 bjh21 }
281 1.1 bjh21 else {
282 1.1 bjh21 return b;
283 1.1 bjh21 }
284 1.1 bjh21
285 1.1 bjh21 }
286 1.1 bjh21
287 1.1 bjh21 /*
288 1.1 bjh21 -------------------------------------------------------------------------------
289 1.1 bjh21 The pattern for a default generated double-precision NaN.
290 1.1 bjh21 -------------------------------------------------------------------------------
291 1.1 bjh21 */
292 1.1 bjh21 #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
293 1.1 bjh21
294 1.1 bjh21 /*
295 1.1 bjh21 -------------------------------------------------------------------------------
296 1.1 bjh21 Returns 1 if the double-precision floating-point value `a' is a NaN;
297 1.1 bjh21 otherwise returns 0.
298 1.1 bjh21 -------------------------------------------------------------------------------
299 1.1 bjh21 */
300 1.1 bjh21 #ifdef SOFTFLOAT_FOR_GCC
301 1.1 bjh21 static
302 1.1 bjh21 #endif
303 1.1 bjh21 flag float64_is_nan( float64 a )
304 1.1 bjh21 {
305 1.1 bjh21
306 1.7 christos return ( (bits64)LIT64( 0xFFE0000000000000 ) <
307 1.1 bjh21 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
308 1.1 bjh21
309 1.1 bjh21 }
310 1.1 bjh21
311 1.1 bjh21 /*
312 1.1 bjh21 -------------------------------------------------------------------------------
313 1.1 bjh21 Returns 1 if the double-precision floating-point value `a' is a signaling
314 1.1 bjh21 NaN; otherwise returns 0.
315 1.1 bjh21 -------------------------------------------------------------------------------
316 1.1 bjh21 */
317 1.9 matt #if defined(SOFTFLOAT_FOR_GCC) \
318 1.9 matt && !defined(SOFTFLOATAARCH64_FOR_GCC) \
319 1.9 matt && !defined(SOFTFLOATSPARC64_FOR_GCC) \
320 1.9 matt && !defined(SOFTFLOATM68K_FOR_GCC)
321 1.1 bjh21 static
322 1.1 bjh21 #endif
323 1.1 bjh21 flag float64_is_signaling_nan( float64 a )
324 1.1 bjh21 {
325 1.1 bjh21
326 1.1 bjh21 return
327 1.1 bjh21 ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
328 1.1 bjh21 && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
329 1.1 bjh21
330 1.1 bjh21 }
331 1.1 bjh21
332 1.1 bjh21 /*
333 1.1 bjh21 -------------------------------------------------------------------------------
334 1.1 bjh21 Returns the result of converting the double-precision floating-point NaN
335 1.1 bjh21 `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
336 1.1 bjh21 exception is raised.
337 1.1 bjh21 -------------------------------------------------------------------------------
338 1.1 bjh21 */
339 1.1 bjh21 static commonNaNT float64ToCommonNaN( float64 a )
340 1.1 bjh21 {
341 1.1 bjh21 commonNaNT z;
342 1.1 bjh21
343 1.1 bjh21 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
344 1.7 christos z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63);
345 1.1 bjh21 z.low = 0;
346 1.1 bjh21 z.high = FLOAT64_DEMANGLE(a)<<12;
347 1.1 bjh21 return z;
348 1.1 bjh21
349 1.1 bjh21 }
350 1.1 bjh21
351 1.1 bjh21 /*
352 1.1 bjh21 -------------------------------------------------------------------------------
353 1.1 bjh21 Returns the result of converting the canonical NaN `a' to the double-
354 1.1 bjh21 precision floating-point format.
355 1.1 bjh21 -------------------------------------------------------------------------------
356 1.1 bjh21 */
357 1.1 bjh21 static float64 commonNaNToFloat64( commonNaNT a )
358 1.1 bjh21 {
359 1.1 bjh21
360 1.1 bjh21 return FLOAT64_MANGLE(
361 1.1 bjh21 ( ( (bits64) a.sign )<<63 )
362 1.1 bjh21 | LIT64( 0x7FF8000000000000 )
363 1.1 bjh21 | ( a.high>>12 ) );
364 1.1 bjh21
365 1.1 bjh21 }
366 1.1 bjh21
367 1.1 bjh21 /*
368 1.1 bjh21 -------------------------------------------------------------------------------
369 1.1 bjh21 Takes two double-precision floating-point values `a' and `b', one of which
370 1.1 bjh21 is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
371 1.1 bjh21 signaling NaN, the invalid exception is raised.
372 1.1 bjh21 -------------------------------------------------------------------------------
373 1.1 bjh21 */
374 1.1 bjh21 static float64 propagateFloat64NaN( float64 a, float64 b )
375 1.1 bjh21 {
376 1.1 bjh21 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
377 1.1 bjh21
378 1.1 bjh21 aIsNaN = float64_is_nan( a );
379 1.1 bjh21 aIsSignalingNaN = float64_is_signaling_nan( a );
380 1.1 bjh21 bIsNaN = float64_is_nan( b );
381 1.1 bjh21 bIsSignalingNaN = float64_is_signaling_nan( b );
382 1.1 bjh21 a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
383 1.1 bjh21 b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
384 1.1 bjh21 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
385 1.1 bjh21 if ( aIsNaN ) {
386 1.1 bjh21 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
387 1.1 bjh21 }
388 1.1 bjh21 else {
389 1.1 bjh21 return b;
390 1.1 bjh21 }
391 1.1 bjh21
392 1.1 bjh21 }
393 1.1 bjh21
394 1.1 bjh21 #ifdef FLOATX80
395 1.1 bjh21
396 1.1 bjh21 /*
397 1.1 bjh21 -------------------------------------------------------------------------------
398 1.1 bjh21 The pattern for a default generated extended double-precision NaN. The
399 1.1 bjh21 `high' and `low' values hold the most- and least-significant bits,
400 1.1 bjh21 respectively.
401 1.1 bjh21 -------------------------------------------------------------------------------
402 1.1 bjh21 */
403 1.1 bjh21 #define floatx80_default_nan_high 0xFFFF
404 1.1 bjh21 #define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
405 1.1 bjh21
406 1.1 bjh21 /*
407 1.1 bjh21 -------------------------------------------------------------------------------
408 1.1 bjh21 Returns 1 if the extended double-precision floating-point value `a' is a
409 1.1 bjh21 NaN; otherwise returns 0.
410 1.1 bjh21 -------------------------------------------------------------------------------
411 1.1 bjh21 */
412 1.1 bjh21 flag floatx80_is_nan( floatx80 a )
413 1.1 bjh21 {
414 1.1 bjh21
415 1.1 bjh21 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
416 1.1 bjh21
417 1.1 bjh21 }
418 1.1 bjh21
419 1.1 bjh21 /*
420 1.1 bjh21 -------------------------------------------------------------------------------
421 1.1 bjh21 Returns 1 if the extended double-precision floating-point value `a' is a
422 1.1 bjh21 signaling NaN; otherwise returns 0.
423 1.1 bjh21 -------------------------------------------------------------------------------
424 1.1 bjh21 */
425 1.1 bjh21 flag floatx80_is_signaling_nan( floatx80 a )
426 1.1 bjh21 {
427 1.1 bjh21 bits64 aLow;
428 1.1 bjh21
429 1.1 bjh21 aLow = a.low & ~ LIT64( 0x4000000000000000 );
430 1.1 bjh21 return
431 1.1 bjh21 ( ( a.high & 0x7FFF ) == 0x7FFF )
432 1.1 bjh21 && (bits64) ( aLow<<1 )
433 1.1 bjh21 && ( a.low == aLow );
434 1.1 bjh21
435 1.1 bjh21 }
436 1.1 bjh21
437 1.1 bjh21 /*
438 1.1 bjh21 -------------------------------------------------------------------------------
439 1.1 bjh21 Returns the result of converting the extended double-precision floating-
440 1.1 bjh21 point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
441 1.1 bjh21 invalid exception is raised.
442 1.1 bjh21 -------------------------------------------------------------------------------
443 1.1 bjh21 */
444 1.1 bjh21 static commonNaNT floatx80ToCommonNaN( floatx80 a )
445 1.1 bjh21 {
446 1.1 bjh21 commonNaNT z;
447 1.1 bjh21
448 1.1 bjh21 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
449 1.1 bjh21 z.sign = a.high>>15;
450 1.1 bjh21 z.low = 0;
451 1.1 bjh21 z.high = a.low<<1;
452 1.1 bjh21 return z;
453 1.1 bjh21
454 1.1 bjh21 }
455 1.1 bjh21
456 1.1 bjh21 /*
457 1.1 bjh21 -------------------------------------------------------------------------------
458 1.1 bjh21 Returns the result of converting the canonical NaN `a' to the extended
459 1.1 bjh21 double-precision floating-point format.
460 1.1 bjh21 -------------------------------------------------------------------------------
461 1.1 bjh21 */
462 1.1 bjh21 static floatx80 commonNaNToFloatx80( commonNaNT a )
463 1.1 bjh21 {
464 1.1 bjh21 floatx80 z;
465 1.1 bjh21
466 1.1 bjh21 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
467 1.1 bjh21 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
468 1.1 bjh21 return z;
469 1.1 bjh21
470 1.1 bjh21 }
471 1.1 bjh21
472 1.1 bjh21 /*
473 1.1 bjh21 -------------------------------------------------------------------------------
474 1.1 bjh21 Takes two extended double-precision floating-point values `a' and `b', one
475 1.1 bjh21 of which is a NaN, and returns the appropriate NaN result. If either `a' or
476 1.1 bjh21 `b' is a signaling NaN, the invalid exception is raised.
477 1.1 bjh21 -------------------------------------------------------------------------------
478 1.1 bjh21 */
479 1.1 bjh21 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
480 1.1 bjh21 {
481 1.1 bjh21 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
482 1.1 bjh21
483 1.1 bjh21 aIsNaN = floatx80_is_nan( a );
484 1.1 bjh21 aIsSignalingNaN = floatx80_is_signaling_nan( a );
485 1.1 bjh21 bIsNaN = floatx80_is_nan( b );
486 1.1 bjh21 bIsSignalingNaN = floatx80_is_signaling_nan( b );
487 1.1 bjh21 a.low |= LIT64( 0xC000000000000000 );
488 1.1 bjh21 b.low |= LIT64( 0xC000000000000000 );
489 1.1 bjh21 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
490 1.1 bjh21 if ( aIsNaN ) {
491 1.1 bjh21 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
492 1.1 bjh21 }
493 1.1 bjh21 else {
494 1.1 bjh21 return b;
495 1.1 bjh21 }
496 1.1 bjh21
497 1.1 bjh21 }
498 1.1 bjh21
499 1.1 bjh21 #endif
500 1.1 bjh21
501 1.1 bjh21 #ifdef FLOAT128
502 1.1 bjh21
503 1.1 bjh21 /*
504 1.1 bjh21 -------------------------------------------------------------------------------
505 1.1 bjh21 The pattern for a default generated quadruple-precision NaN. The `high' and
506 1.1 bjh21 `low' values hold the most- and least-significant bits, respectively.
507 1.1 bjh21 -------------------------------------------------------------------------------
508 1.1 bjh21 */
509 1.1 bjh21 #define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
510 1.1 bjh21 #define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
511 1.1 bjh21
512 1.1 bjh21 /*
513 1.1 bjh21 -------------------------------------------------------------------------------
514 1.1 bjh21 Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
515 1.1 bjh21 otherwise returns 0.
516 1.1 bjh21 -------------------------------------------------------------------------------
517 1.1 bjh21 */
518 1.1 bjh21 flag float128_is_nan( float128 a )
519 1.1 bjh21 {
520 1.1 bjh21
521 1.1 bjh21 return
522 1.7 christos ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
523 1.1 bjh21 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
524 1.1 bjh21
525 1.1 bjh21 }
526 1.1 bjh21
527 1.1 bjh21 /*
528 1.1 bjh21 -------------------------------------------------------------------------------
529 1.1 bjh21 Returns 1 if the quadruple-precision floating-point value `a' is a
530 1.1 bjh21 signaling NaN; otherwise returns 0.
531 1.1 bjh21 -------------------------------------------------------------------------------
532 1.1 bjh21 */
533 1.1 bjh21 flag float128_is_signaling_nan( float128 a )
534 1.1 bjh21 {
535 1.1 bjh21
536 1.1 bjh21 return
537 1.1 bjh21 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
538 1.1 bjh21 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
539 1.1 bjh21
540 1.1 bjh21 }
541 1.1 bjh21
542 1.1 bjh21 /*
543 1.1 bjh21 -------------------------------------------------------------------------------
544 1.1 bjh21 Returns the result of converting the quadruple-precision floating-point NaN
545 1.1 bjh21 `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
546 1.1 bjh21 exception is raised.
547 1.1 bjh21 -------------------------------------------------------------------------------
548 1.1 bjh21 */
549 1.1 bjh21 static commonNaNT float128ToCommonNaN( float128 a )
550 1.1 bjh21 {
551 1.1 bjh21 commonNaNT z;
552 1.1 bjh21
553 1.1 bjh21 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
554 1.7 christos z.sign = (flag)(a.high>>63);
555 1.1 bjh21 shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
556 1.1 bjh21 return z;
557 1.1 bjh21
558 1.1 bjh21 }
559 1.1 bjh21
560 1.1 bjh21 /*
561 1.1 bjh21 -------------------------------------------------------------------------------
562 1.1 bjh21 Returns the result of converting the canonical NaN `a' to the quadruple-
563 1.1 bjh21 precision floating-point format.
564 1.1 bjh21 -------------------------------------------------------------------------------
565 1.1 bjh21 */
566 1.1 bjh21 static float128 commonNaNToFloat128( commonNaNT a )
567 1.1 bjh21 {
568 1.1 bjh21 float128 z;
569 1.1 bjh21
570 1.1 bjh21 shift128Right( a.high, a.low, 16, &z.high, &z.low );
571 1.1 bjh21 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
572 1.1 bjh21 return z;
573 1.1 bjh21
574 1.1 bjh21 }
575 1.1 bjh21
576 1.1 bjh21 /*
577 1.1 bjh21 -------------------------------------------------------------------------------
578 1.1 bjh21 Takes two quadruple-precision floating-point values `a' and `b', one of
579 1.1 bjh21 which is a NaN, and returns the appropriate NaN result. If either `a' or
580 1.1 bjh21 `b' is a signaling NaN, the invalid exception is raised.
581 1.1 bjh21 -------------------------------------------------------------------------------
582 1.1 bjh21 */
583 1.1 bjh21 static float128 propagateFloat128NaN( float128 a, float128 b )
584 1.1 bjh21 {
585 1.1 bjh21 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
586 1.1 bjh21
587 1.1 bjh21 aIsNaN = float128_is_nan( a );
588 1.1 bjh21 aIsSignalingNaN = float128_is_signaling_nan( a );
589 1.1 bjh21 bIsNaN = float128_is_nan( b );
590 1.1 bjh21 bIsSignalingNaN = float128_is_signaling_nan( b );
591 1.1 bjh21 a.high |= LIT64( 0x0000800000000000 );
592 1.1 bjh21 b.high |= LIT64( 0x0000800000000000 );
593 1.1 bjh21 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
594 1.1 bjh21 if ( aIsNaN ) {
595 1.1 bjh21 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
596 1.1 bjh21 }
597 1.1 bjh21 else {
598 1.1 bjh21 return b;
599 1.1 bjh21 }
600 1.1 bjh21
601 1.1 bjh21 }
602 1.1 bjh21
603 1.1 bjh21 #endif
604 1.1 bjh21
605