Statistics
| Branch: | Revision:

root / target-arm / nwfpe / softfloat-specialize @ 157777ef

History | View | Annotate | Download (12 kB)

1 00406dff bellard
2 00406dff bellard
/*
3 00406dff bellard
===============================================================================
4 00406dff bellard
5 00406dff bellard
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
6 00406dff bellard
Arithmetic Package, Release 2.
7 00406dff bellard
8 00406dff bellard
Written by John R. Hauser.  This work was made possible in part by the
9 00406dff bellard
International Computer Science Institute, located at Suite 600, 1947 Center
10 00406dff bellard
Street, Berkeley, California 94704.  Funding was partially provided by the
11 00406dff bellard
National Science Foundation under grant MIP-9311980.  The original version
12 00406dff bellard
of this code was written as part of a project to build a fixed-point vector
13 00406dff bellard
processor in collaboration with the University of California at Berkeley,
14 00406dff bellard
overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
15 00406dff bellard
is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
16 00406dff bellard
arithmetic/softfloat.html'.
17 00406dff bellard
18 00406dff bellard
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
19 00406dff bellard
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
20 00406dff bellard
TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
21 00406dff bellard
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
22 00406dff bellard
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
23 00406dff bellard
24 00406dff bellard
Derivative works are acceptable, even for commercial purposes, so long as
25 00406dff bellard
(1) they include prominent notice that the work is derivative, and (2) they
26 00406dff bellard
include prominent notice akin to these three paragraphs for those parts of
27 00406dff bellard
this code that are retained.
28 00406dff bellard
29 00406dff bellard
===============================================================================
30 00406dff bellard
*/
31 00406dff bellard
32 00406dff bellard
/*
33 00406dff bellard
-------------------------------------------------------------------------------
34 00406dff bellard
Underflow tininess-detection mode, statically initialized to default value.
35 00406dff bellard
(The declaration in `softfloat.h' must match the `int8' type here.)
36 00406dff bellard
-------------------------------------------------------------------------------
37 00406dff bellard
*/
38 00406dff bellard
int8 float_detect_tininess = float_tininess_after_rounding;
39 00406dff bellard
40 00406dff bellard
/*
41 00406dff bellard
-------------------------------------------------------------------------------
42 00406dff bellard
Raises the exceptions specified by `flags'.  Floating-point traps can be
43 00406dff bellard
defined here if desired.  It is currently not possible for such a trap to
44 00406dff bellard
substitute a result value.  If traps are not implemented, this routine
45 00406dff bellard
should be simply `float_exception_flags |= flags;'.
46 00406dff bellard
47 00406dff bellard
ScottB:  November 4, 1998
48 00406dff bellard
Moved this function out of softfloat-specialize into fpmodule.c.
49 00406dff bellard
This effectively isolates all the changes required for integrating with the
50 00406dff bellard
Linux kernel into fpmodule.c.  Porting to NetBSD should only require modifying
51 00406dff bellard
fpmodule.c to integrate with the NetBSD kernel (I hope!).
52 00406dff bellard
-------------------------------------------------------------------------------
53 00406dff bellard
*/
54 00406dff bellard
void float_raise( int8 flags )
55 00406dff bellard
{
56 00406dff bellard
    float_exception_flags |= flags;
57 00406dff bellard
}
58 00406dff bellard
59 00406dff bellard
/*
60 00406dff bellard
-------------------------------------------------------------------------------
61 00406dff bellard
Internal canonical NaN format.
62 00406dff bellard
-------------------------------------------------------------------------------
63 00406dff bellard
*/
64 00406dff bellard
typedef struct {
65 00406dff bellard
    flag sign;
66 00406dff bellard
    bits64 high, low;
67 00406dff bellard
} commonNaNT;
68 00406dff bellard
69 00406dff bellard
/*
70 00406dff bellard
-------------------------------------------------------------------------------
71 00406dff bellard
The pattern for a default generated single-precision NaN.
72 00406dff bellard
-------------------------------------------------------------------------------
73 00406dff bellard
*/
74 00406dff bellard
#define float32_default_nan 0xFFFFFFFF
75 00406dff bellard
76 00406dff bellard
/*
77 00406dff bellard
-------------------------------------------------------------------------------
78 00406dff bellard
Returns 1 if the single-precision floating-point value `a' is a NaN;
79 00406dff bellard
otherwise returns 0.
80 00406dff bellard
-------------------------------------------------------------------------------
81 00406dff bellard
*/
82 00406dff bellard
flag float32_is_nan( float32 a )
83 00406dff bellard
{
84 00406dff bellard
85 00406dff bellard
    return ( 0xFF000000 < (bits32) ( a<<1 ) );
86 00406dff bellard
87 00406dff bellard
}
88 00406dff bellard
89 00406dff bellard
/*
90 00406dff bellard
-------------------------------------------------------------------------------
91 00406dff bellard
Returns 1 if the single-precision floating-point value `a' is a signaling
92 00406dff bellard
NaN; otherwise returns 0.
93 00406dff bellard
-------------------------------------------------------------------------------
94 00406dff bellard
*/
95 00406dff bellard
flag float32_is_signaling_nan( float32 a )
96 00406dff bellard
{
97 00406dff bellard
98 00406dff bellard
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
99 00406dff bellard
100 00406dff bellard
}
101 00406dff bellard
102 00406dff bellard
/*
103 00406dff bellard
-------------------------------------------------------------------------------
104 00406dff bellard
Returns the result of converting the single-precision floating-point NaN
105 00406dff bellard
`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
106 00406dff bellard
exception is raised.
107 00406dff bellard
-------------------------------------------------------------------------------
108 00406dff bellard
*/
109 00406dff bellard
static commonNaNT float32ToCommonNaN( float32 a )
110 00406dff bellard
{
111 00406dff bellard
    commonNaNT z;
112 00406dff bellard
113 00406dff bellard
    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
114 00406dff bellard
    z.sign = a>>31;
115 00406dff bellard
    z.low = 0;
116 00406dff bellard
    z.high = ( (bits64) a )<<41;
117 00406dff bellard
    return z;
118 00406dff bellard
119 00406dff bellard
}
120 00406dff bellard
121 00406dff bellard
/*
122 00406dff bellard
-------------------------------------------------------------------------------
123 00406dff bellard
Returns the result of converting the canonical NaN `a' to the single-
124 00406dff bellard
precision floating-point format.
125 00406dff bellard
-------------------------------------------------------------------------------
126 00406dff bellard
*/
127 00406dff bellard
static float32 commonNaNToFloat32( commonNaNT a )
128 00406dff bellard
{
129 00406dff bellard
130 00406dff bellard
    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
131 00406dff bellard
132 00406dff bellard
}
133 00406dff bellard
134 00406dff bellard
/*
135 00406dff bellard
-------------------------------------------------------------------------------
136 00406dff bellard
Takes two single-precision floating-point values `a' and `b', one of which
137 00406dff bellard
is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
138 00406dff bellard
signaling NaN, the invalid exception is raised.
139 00406dff bellard
-------------------------------------------------------------------------------
140 00406dff bellard
*/
141 00406dff bellard
static float32 propagateFloat32NaN( float32 a, float32 b )
142 00406dff bellard
{
143 00406dff bellard
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
144 00406dff bellard
145 00406dff bellard
    aIsNaN = float32_is_nan( a );
146 00406dff bellard
    aIsSignalingNaN = float32_is_signaling_nan( a );
147 00406dff bellard
    bIsNaN = float32_is_nan( b );
148 00406dff bellard
    bIsSignalingNaN = float32_is_signaling_nan( b );
149 00406dff bellard
    a |= 0x00400000;
150 00406dff bellard
    b |= 0x00400000;
151 00406dff bellard
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
152 00406dff bellard
    if ( aIsNaN ) {
153 00406dff bellard
        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
154 00406dff bellard
    }
155 00406dff bellard
    else {
156 00406dff bellard
        return b;
157 00406dff bellard
    }
158 00406dff bellard
159 00406dff bellard
}
160 00406dff bellard
161 00406dff bellard
/*
162 00406dff bellard
-------------------------------------------------------------------------------
163 00406dff bellard
The pattern for a default generated double-precision NaN.
164 00406dff bellard
-------------------------------------------------------------------------------
165 00406dff bellard
*/
166 00406dff bellard
#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
167 00406dff bellard
168 00406dff bellard
/*
169 00406dff bellard
-------------------------------------------------------------------------------
170 00406dff bellard
Returns 1 if the double-precision floating-point value `a' is a NaN;
171 00406dff bellard
otherwise returns 0.
172 00406dff bellard
-------------------------------------------------------------------------------
173 00406dff bellard
*/
174 00406dff bellard
flag float64_is_nan( float64 a )
175 00406dff bellard
{
176 00406dff bellard
177 00406dff bellard
    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
178 00406dff bellard
179 00406dff bellard
}
180 00406dff bellard
181 00406dff bellard
/*
182 00406dff bellard
-------------------------------------------------------------------------------
183 00406dff bellard
Returns 1 if the double-precision floating-point value `a' is a signaling
184 00406dff bellard
NaN; otherwise returns 0.
185 00406dff bellard
-------------------------------------------------------------------------------
186 00406dff bellard
*/
187 00406dff bellard
flag float64_is_signaling_nan( float64 a )
188 00406dff bellard
{
189 00406dff bellard
190 00406dff bellard
    return
191 00406dff bellard
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
192 00406dff bellard
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
193 00406dff bellard
194 00406dff bellard
}
195 00406dff bellard
196 00406dff bellard
/*
197 00406dff bellard
-------------------------------------------------------------------------------
198 00406dff bellard
Returns the result of converting the double-precision floating-point NaN
199 00406dff bellard
`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
200 00406dff bellard
exception is raised.
201 00406dff bellard
-------------------------------------------------------------------------------
202 00406dff bellard
*/
203 00406dff bellard
static commonNaNT float64ToCommonNaN( float64 a )
204 00406dff bellard
{
205 00406dff bellard
    commonNaNT z;
206 00406dff bellard
207 00406dff bellard
    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
208 00406dff bellard
    z.sign = a>>63;
209 00406dff bellard
    z.low = 0;
210 00406dff bellard
    z.high = a<<12;
211 00406dff bellard
    return z;
212 00406dff bellard
213 00406dff bellard
}
214 00406dff bellard
215 00406dff bellard
/*
216 00406dff bellard
-------------------------------------------------------------------------------
217 00406dff bellard
Returns the result of converting the canonical NaN `a' to the double-
218 00406dff bellard
precision floating-point format.
219 00406dff bellard
-------------------------------------------------------------------------------
220 00406dff bellard
*/
221 00406dff bellard
static float64 commonNaNToFloat64( commonNaNT a )
222 00406dff bellard
{
223 00406dff bellard
224 00406dff bellard
    return
225 00406dff bellard
          ( ( (bits64) a.sign )<<63 )
226 00406dff bellard
        | LIT64( 0x7FF8000000000000 )
227 00406dff bellard
        | ( a.high>>12 );
228 00406dff bellard
229 00406dff bellard
}
230 00406dff bellard
231 00406dff bellard
/*
232 00406dff bellard
-------------------------------------------------------------------------------
233 00406dff bellard
Takes two double-precision floating-point values `a' and `b', one of which
234 00406dff bellard
is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
235 00406dff bellard
signaling NaN, the invalid exception is raised.
236 00406dff bellard
-------------------------------------------------------------------------------
237 00406dff bellard
*/
238 00406dff bellard
static float64 propagateFloat64NaN( float64 a, float64 b )
239 00406dff bellard
{
240 00406dff bellard
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
241 00406dff bellard
242 00406dff bellard
    aIsNaN = float64_is_nan( a );
243 00406dff bellard
    aIsSignalingNaN = float64_is_signaling_nan( a );
244 00406dff bellard
    bIsNaN = float64_is_nan( b );
245 00406dff bellard
    bIsSignalingNaN = float64_is_signaling_nan( b );
246 00406dff bellard
    a |= LIT64( 0x0008000000000000 );
247 00406dff bellard
    b |= LIT64( 0x0008000000000000 );
248 00406dff bellard
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
249 00406dff bellard
    if ( aIsNaN ) {
250 00406dff bellard
        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
251 00406dff bellard
    }
252 00406dff bellard
    else {
253 00406dff bellard
        return b;
254 00406dff bellard
    }
255 00406dff bellard
256 00406dff bellard
}
257 00406dff bellard
258 00406dff bellard
#ifdef FLOATX80
259 00406dff bellard
260 00406dff bellard
/*
261 00406dff bellard
-------------------------------------------------------------------------------
262 00406dff bellard
The pattern for a default generated extended double-precision NaN.  The
263 00406dff bellard
`high' and `low' values hold the most- and least-significant bits,
264 00406dff bellard
respectively.
265 00406dff bellard
-------------------------------------------------------------------------------
266 00406dff bellard
*/
267 00406dff bellard
#define floatx80_default_nan_high 0xFFFF
268 00406dff bellard
#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
269 00406dff bellard
270 00406dff bellard
/*
271 00406dff bellard
-------------------------------------------------------------------------------
272 00406dff bellard
Returns 1 if the extended double-precision floating-point value `a' is a
273 00406dff bellard
NaN; otherwise returns 0.
274 00406dff bellard
-------------------------------------------------------------------------------
275 00406dff bellard
*/
276 00406dff bellard
flag floatx80_is_nan( floatx80 a )
277 00406dff bellard
{
278 00406dff bellard
279 00406dff bellard
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
280 00406dff bellard
281 00406dff bellard
}
282 00406dff bellard
283 00406dff bellard
/*
284 00406dff bellard
-------------------------------------------------------------------------------
285 00406dff bellard
Returns 1 if the extended double-precision floating-point value `a' is a
286 00406dff bellard
signaling NaN; otherwise returns 0.
287 00406dff bellard
-------------------------------------------------------------------------------
288 00406dff bellard
*/
289 00406dff bellard
flag floatx80_is_signaling_nan( floatx80 a )
290 00406dff bellard
{
291 00406dff bellard
    //register int lr;
292 00406dff bellard
    bits64 aLow;
293 00406dff bellard
294 00406dff bellard
    //__asm__("mov %0, lr" : : "g" (lr));
295 00406dff bellard
    //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr);
296 00406dff bellard
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
297 00406dff bellard
    return
298 00406dff bellard
           ( ( a.high & 0x7FFF ) == 0x7FFF )
299 00406dff bellard
        && (bits64) ( aLow<<1 )
300 00406dff bellard
        && ( a.low == aLow );
301 00406dff bellard
302 00406dff bellard
}
303 00406dff bellard
304 00406dff bellard
/*
305 00406dff bellard
-------------------------------------------------------------------------------
306 00406dff bellard
Returns the result of converting the extended double-precision floating-
307 00406dff bellard
point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
308 00406dff bellard
invalid exception is raised.
309 00406dff bellard
-------------------------------------------------------------------------------
310 00406dff bellard
*/
311 00406dff bellard
static commonNaNT floatx80ToCommonNaN( floatx80 a )
312 00406dff bellard
{
313 00406dff bellard
    commonNaNT z;
314 00406dff bellard
315 00406dff bellard
    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
316 00406dff bellard
    z.sign = a.high>>15;
317 00406dff bellard
    z.low = 0;
318 00406dff bellard
    z.high = a.low<<1;
319 00406dff bellard
    return z;
320 00406dff bellard
321 00406dff bellard
}
322 00406dff bellard
323 00406dff bellard
/*
324 00406dff bellard
-------------------------------------------------------------------------------
325 00406dff bellard
Returns the result of converting the canonical NaN `a' to the extended
326 00406dff bellard
double-precision floating-point format.
327 00406dff bellard
-------------------------------------------------------------------------------
328 00406dff bellard
*/
329 00406dff bellard
static floatx80 commonNaNToFloatx80( commonNaNT a )
330 00406dff bellard
{
331 00406dff bellard
    floatx80 z;
332 00406dff bellard
333 00406dff bellard
    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
334 00406dff bellard
    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
335 00406dff bellard
    return z;
336 00406dff bellard
337 00406dff bellard
}
338 00406dff bellard
339 00406dff bellard
/*
340 00406dff bellard
-------------------------------------------------------------------------------
341 00406dff bellard
Takes two extended double-precision floating-point values `a' and `b', one
342 00406dff bellard
of which is a NaN, and returns the appropriate NaN result.  If either `a' or
343 00406dff bellard
`b' is a signaling NaN, the invalid exception is raised.
344 00406dff bellard
-------------------------------------------------------------------------------
345 00406dff bellard
*/
346 00406dff bellard
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
347 00406dff bellard
{
348 00406dff bellard
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
349 00406dff bellard
350 00406dff bellard
    aIsNaN = floatx80_is_nan( a );
351 00406dff bellard
    aIsSignalingNaN = floatx80_is_signaling_nan( a );
352 00406dff bellard
    bIsNaN = floatx80_is_nan( b );
353 00406dff bellard
    bIsSignalingNaN = floatx80_is_signaling_nan( b );
354 00406dff bellard
    a.low |= LIT64( 0xC000000000000000 );
355 00406dff bellard
    b.low |= LIT64( 0xC000000000000000 );
356 00406dff bellard
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
357 00406dff bellard
    if ( aIsNaN ) {
358 00406dff bellard
        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
359 00406dff bellard
    }
360 00406dff bellard
    else {
361 00406dff bellard
        return b;
362 00406dff bellard
    }
363 00406dff bellard
364 00406dff bellard
}
365 00406dff bellard
366 00406dff bellard
#endif