Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (12 kB)

1

    
2
/*
3
===============================================================================
4

    
5
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
6
Arithmetic Package, Release 2.
7

    
8
Written by John R. Hauser.  This work was made possible in part by the
9
International Computer Science Institute, located at Suite 600, 1947 Center
10
Street, Berkeley, California 94704.  Funding was partially provided by the
11
National Science Foundation under grant MIP-9311980.  The original version
12
of this code was written as part of a project to build a fixed-point vector
13
processor in collaboration with the University of California at Berkeley,
14
overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
15
is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
16
arithmetic/softfloat.html'.
17

    
18
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
19
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
20
TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
21
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
22
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
23

    
24
Derivative works are acceptable, even for commercial purposes, so long as
25
(1) they include prominent notice that the work is derivative, and (2) they
26
include prominent notice akin to these three paragraphs for those parts of
27
this code that are retained.
28

    
29
===============================================================================
30
*/
31

    
32
/*
33
-------------------------------------------------------------------------------
34
Underflow tininess-detection mode, statically initialized to default value.
35
(The declaration in `softfloat.h' must match the `int8' type here.)
36
-------------------------------------------------------------------------------
37
*/
38
int8 float_detect_tininess = float_tininess_after_rounding;
39

    
40
/*
41
-------------------------------------------------------------------------------
42
Raises the exceptions specified by `flags'.  Floating-point traps can be
43
defined here if desired.  It is currently not possible for such a trap to
44
substitute a result value.  If traps are not implemented, this routine
45
should be simply `float_exception_flags |= flags;'.
46

    
47
ScottB:  November 4, 1998
48
Moved this function out of softfloat-specialize into fpmodule.c.
49
This effectively isolates all the changes required for integrating with the
50
Linux kernel into fpmodule.c.  Porting to NetBSD should only require modifying
51
fpmodule.c to integrate with the NetBSD kernel (I hope!).
52
-------------------------------------------------------------------------------
53
*/
54
void float_raise( int8 flags )
55
{
56
    float_exception_flags |= flags;
57
}
58

    
59
/*
60
-------------------------------------------------------------------------------
61
Internal canonical NaN format.
62
-------------------------------------------------------------------------------
63
*/
64
typedef struct {
65
    flag sign;
66
    bits64 high, low;
67
} commonNaNT;
68

    
69
/*
70
-------------------------------------------------------------------------------
71
The pattern for a default generated single-precision NaN.
72
-------------------------------------------------------------------------------
73
*/
74
#define float32_default_nan 0xFFFFFFFF
75

    
76
/*
77
-------------------------------------------------------------------------------
78
Returns 1 if the single-precision floating-point value `a' is a NaN;
79
otherwise returns 0.
80
-------------------------------------------------------------------------------
81
*/
82
flag float32_is_nan( float32 a )
83
{
84

    
85
    return ( 0xFF000000 < (bits32) ( a<<1 ) );
86

    
87
}
88

    
89
/*
90
-------------------------------------------------------------------------------
91
Returns 1 if the single-precision floating-point value `a' is a signaling
92
NaN; otherwise returns 0.
93
-------------------------------------------------------------------------------
94
*/
95
flag float32_is_signaling_nan( float32 a )
96
{
97

    
98
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
99

    
100
}
101

    
102
/*
103
-------------------------------------------------------------------------------
104
Returns the result of converting the single-precision floating-point NaN
105
`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
106
exception is raised.
107
-------------------------------------------------------------------------------
108
*/
109
static commonNaNT float32ToCommonNaN( float32 a )
110
{
111
    commonNaNT z;
112

    
113
    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
114
    z.sign = a>>31;
115
    z.low = 0;
116
    z.high = ( (bits64) a )<<41;
117
    return z;
118

    
119
}
120

    
121
/*
122
-------------------------------------------------------------------------------
123
Returns the result of converting the canonical NaN `a' to the single-
124
precision floating-point format.
125
-------------------------------------------------------------------------------
126
*/
127
static float32 commonNaNToFloat32( commonNaNT a )
128
{
129

    
130
    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
131

    
132
}
133

    
134
/*
135
-------------------------------------------------------------------------------
136
Takes two single-precision floating-point values `a' and `b', one of which
137
is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
138
signaling NaN, the invalid exception is raised.
139
-------------------------------------------------------------------------------
140
*/
141
static float32 propagateFloat32NaN( float32 a, float32 b )
142
{
143
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
144

    
145
    aIsNaN = float32_is_nan( a );
146
    aIsSignalingNaN = float32_is_signaling_nan( a );
147
    bIsNaN = float32_is_nan( b );
148
    bIsSignalingNaN = float32_is_signaling_nan( b );
149
    a |= 0x00400000;
150
    b |= 0x00400000;
151
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
152
    if ( aIsNaN ) {
153
        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
154
    }
155
    else {
156
        return b;
157
    }
158

    
159
}
160

    
161
/*
162
-------------------------------------------------------------------------------
163
The pattern for a default generated double-precision NaN.
164
-------------------------------------------------------------------------------
165
*/
166
#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
167

    
168
/*
169
-------------------------------------------------------------------------------
170
Returns 1 if the double-precision floating-point value `a' is a NaN;
171
otherwise returns 0.
172
-------------------------------------------------------------------------------
173
*/
174
flag float64_is_nan( float64 a )
175
{
176

    
177
    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
178

    
179
}
180

    
181
/*
182
-------------------------------------------------------------------------------
183
Returns 1 if the double-precision floating-point value `a' is a signaling
184
NaN; otherwise returns 0.
185
-------------------------------------------------------------------------------
186
*/
187
flag float64_is_signaling_nan( float64 a )
188
{
189

    
190
    return
191
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
192
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
193

    
194
}
195

    
196
/*
197
-------------------------------------------------------------------------------
198
Returns the result of converting the double-precision floating-point NaN
199
`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
200
exception is raised.
201
-------------------------------------------------------------------------------
202
*/
203
static commonNaNT float64ToCommonNaN( float64 a )
204
{
205
    commonNaNT z;
206

    
207
    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
208
    z.sign = a>>63;
209
    z.low = 0;
210
    z.high = a<<12;
211
    return z;
212

    
213
}
214

    
215
/*
216
-------------------------------------------------------------------------------
217
Returns the result of converting the canonical NaN `a' to the double-
218
precision floating-point format.
219
-------------------------------------------------------------------------------
220
*/
221
static float64 commonNaNToFloat64( commonNaNT a )
222
{
223

    
224
    return
225
          ( ( (bits64) a.sign )<<63 )
226
        | LIT64( 0x7FF8000000000000 )
227
        | ( a.high>>12 );
228

    
229
}
230

    
231
/*
232
-------------------------------------------------------------------------------
233
Takes two double-precision floating-point values `a' and `b', one of which
234
is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
235
signaling NaN, the invalid exception is raised.
236
-------------------------------------------------------------------------------
237
*/
238
static float64 propagateFloat64NaN( float64 a, float64 b )
239
{
240
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
241

    
242
    aIsNaN = float64_is_nan( a );
243
    aIsSignalingNaN = float64_is_signaling_nan( a );
244
    bIsNaN = float64_is_nan( b );
245
    bIsSignalingNaN = float64_is_signaling_nan( b );
246
    a |= LIT64( 0x0008000000000000 );
247
    b |= LIT64( 0x0008000000000000 );
248
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
249
    if ( aIsNaN ) {
250
        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
251
    }
252
    else {
253
        return b;
254
    }
255

    
256
}
257

    
258
#ifdef FLOATX80
259

    
260
/*
261
-------------------------------------------------------------------------------
262
The pattern for a default generated extended double-precision NaN.  The
263
`high' and `low' values hold the most- and least-significant bits,
264
respectively.
265
-------------------------------------------------------------------------------
266
*/
267
#define floatx80_default_nan_high 0xFFFF
268
#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
269

    
270
/*
271
-------------------------------------------------------------------------------
272
Returns 1 if the extended double-precision floating-point value `a' is a
273
NaN; otherwise returns 0.
274
-------------------------------------------------------------------------------
275
*/
276
flag floatx80_is_nan( floatx80 a )
277
{
278

    
279
    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
280

    
281
}
282

    
283
/*
284
-------------------------------------------------------------------------------
285
Returns 1 if the extended double-precision floating-point value `a' is a
286
signaling NaN; otherwise returns 0.
287
-------------------------------------------------------------------------------
288
*/
289
flag floatx80_is_signaling_nan( floatx80 a )
290
{
291
    //register int lr;
292
    bits64 aLow;
293

    
294
    //__asm__("mov %0, lr" : : "g" (lr));
295
    //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr);
296
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
297
    return
298
           ( ( a.high & 0x7FFF ) == 0x7FFF )
299
        && (bits64) ( aLow<<1 )
300
        && ( a.low == aLow );
301

    
302
}
303

    
304
/*
305
-------------------------------------------------------------------------------
306
Returns the result of converting the extended double-precision floating-
307
point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
308
invalid exception is raised.
309
-------------------------------------------------------------------------------
310
*/
311
static commonNaNT floatx80ToCommonNaN( floatx80 a )
312
{
313
    commonNaNT z;
314

    
315
    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
316
    z.sign = a.high>>15;
317
    z.low = 0;
318
    z.high = a.low<<1;
319
    return z;
320

    
321
}
322

    
323
/*
324
-------------------------------------------------------------------------------
325
Returns the result of converting the canonical NaN `a' to the extended
326
double-precision floating-point format.
327
-------------------------------------------------------------------------------
328
*/
329
static floatx80 commonNaNToFloatx80( commonNaNT a )
330
{
331
    floatx80 z;
332

    
333
    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
334
    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
335
    return z;
336

    
337
}
338

    
339
/*
340
-------------------------------------------------------------------------------
341
Takes two extended double-precision floating-point values `a' and `b', one
342
of which is a NaN, and returns the appropriate NaN result.  If either `a' or
343
`b' is a signaling NaN, the invalid exception is raised.
344
-------------------------------------------------------------------------------
345
*/
346
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
347
{
348
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
349

    
350
    aIsNaN = floatx80_is_nan( a );
351
    aIsSignalingNaN = floatx80_is_signaling_nan( a );
352
    bIsNaN = floatx80_is_nan( b );
353
    bIsSignalingNaN = floatx80_is_signaling_nan( b );
354
    a.low |= LIT64( 0xC000000000000000 );
355
    b.low |= LIT64( 0xC000000000000000 );
356
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
357
    if ( aIsNaN ) {
358
        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
359
    }
360
    else {
361
        return b;
362
    }
363

    
364
}
365

    
366
#endif