Finishes removal of x86_32 (XCC)
[akaros.git] / kern / arch / riscv / softfloat-specialize.h
1
2 /*============================================================================
3
4 This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
5 Arithmetic Package, Release 2b.
6
7 Written by John R. Hauser.  This work was made possible in part by the
8 International Computer Science Institute, located at Suite 600, 1947 Center
9 Street, Berkeley, California 94704.  Funding was partially provided by the
10 National Science Foundation under grant MIP-9311980.  The original version
11 of this code was written as part of a project to build a fixed-point vector
12 processor in collaboration with the University of California at Berkeley,
13 overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
14 is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
15 arithmetic/SoftFloat.html'.
16
17 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
18 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
19 RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
20 AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
21 COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
22 EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
23 INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
24 OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
25
26 Derivative works are acceptable, even for commercial purposes, so long as
27 (1) the source code for the derivative work includes prominent notice that
28 the work is derivative, and (2) the source code includes prominent notice with
29 these four paragraphs for those parts of this code that are retained.
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 //int8 float_detect_tininess = float_tininess_before_rounding;
38
39 /*----------------------------------------------------------------------------
40 | Raises the exceptions specified by `flags'.  Floating-point traps can be
41 | defined here if desired.  It is currently not possible for such a trap
42 | to substitute a result value.  If traps are not implemented, this routine
43 | should be simply `float_exception_flags |= flags;'.
44 *----------------------------------------------------------------------------*/
45
46 INLINE void float_raise( softfloat_t* sf, int flags )
47 {
48   sf->float_exception_flags |= flags;
49 }
50
51 /*----------------------------------------------------------------------------
52 | The pattern for a default generated single-precision NaN.
53 *----------------------------------------------------------------------------*/
54 #define float32_default_nan 0x7FFFFFFF
55
56 /*----------------------------------------------------------------------------
57 | Returns 1 if the single-precision floating-point value `a' is a NaN;
58 | otherwise returns 0.
59 *----------------------------------------------------------------------------*/
60
61 INLINE flag float32_is_nan( softfloat_t* sf, float32 a )
62 {
63
64     return ( 0xFF000000 < (bits32) ( a<<1 ) );
65
66 }
67
68 /*----------------------------------------------------------------------------
69 | Returns 1 if the single-precision floating-point value `a' is a signaling
70 | NaN; otherwise returns 0.
71 *----------------------------------------------------------------------------*/
72
73 INLINE flag float32_is_signaling_nan( softfloat_t* sf, float32 a )
74 {
75
76     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
77
78 }
79
80 /*----------------------------------------------------------------------------
81 | Returns the result of converting the single-precision floating-point NaN
82 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
83 | exception is raised.
84 *----------------------------------------------------------------------------*/
85
86 commonNaNT float32ToCommonNaN( softfloat_t* sf, float32 a )
87 {
88     commonNaNT z;
89
90     if ( float32_is_signaling_nan( sf, a ) ) float_raise( sf, float_flag_invalid );
91     z.sign = a>>31;
92     z.low = 0;
93     z.high = ( (bits64) a )<<41;
94     return z;
95
96 }
97
98 /*----------------------------------------------------------------------------
99 | Returns the result of converting the canonical NaN `a' to the single-
100 | precision floating-point format.
101 *----------------------------------------------------------------------------*/
102
103 float32 commonNaNToFloat32( softfloat_t* sf, commonNaNT a )
104 {
105
106     return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
107
108 }
109
110 /*----------------------------------------------------------------------------
111 | Takes two single-precision floating-point values `a' and `b', one of which
112 | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
113 | signaling NaN, the invalid exception is raised.
114 *----------------------------------------------------------------------------*/
115
116 float32 propagateFloat32NaN( softfloat_t* sf, float32 a, float32 b )
117 {
118     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
119
120     aIsNaN = float32_is_nan( sf, a );
121     aIsSignalingNaN = float32_is_signaling_nan( sf, a );
122     bIsNaN = float32_is_nan( sf, b );
123     bIsSignalingNaN = float32_is_signaling_nan( sf, b );
124     a |= 0x00400000;
125     b |= 0x00400000;
126     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( sf, float_flag_invalid );
127     return bIsSignalingNaN ? b : aIsSignalingNaN ? a : bIsNaN ? b : a;
128
129 }
130
131 /*----------------------------------------------------------------------------
132 | The pattern for a default generated double-precision NaN.
133 *----------------------------------------------------------------------------*/
134 #define float64_default_nan LIT64( 0x7FFFFFFFFFFFFFFF )
135
136 /*----------------------------------------------------------------------------
137 | Returns 1 if the double-precision floating-point value `a' is a NaN;
138 | otherwise returns 0.
139 *----------------------------------------------------------------------------*/
140
141 flag float64_is_nan( softfloat_t* sf, float64 a )
142 {
143
144     return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
145
146 }
147
148 /*----------------------------------------------------------------------------
149 | Returns 1 if the double-precision floating-point value `a' is a signaling
150 | NaN; otherwise returns 0.
151 *----------------------------------------------------------------------------*/
152
153 flag float64_is_signaling_nan( softfloat_t* sf, float64 a )
154 {
155
156     return
157            ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
158         && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
159
160 }
161
162 /*----------------------------------------------------------------------------
163 | Returns the result of converting the double-precision floating-point NaN
164 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
165 | exception is raised.
166 *----------------------------------------------------------------------------*/
167
168 commonNaNT float64ToCommonNaN( softfloat_t* sf, float64 a )
169 {
170     commonNaNT z;
171
172     if ( float64_is_signaling_nan( sf, a ) ) float_raise( sf, float_flag_invalid );
173     z.sign = a>>63;
174     z.low = 0;
175     z.high = a<<12;
176     return z;
177
178 }
179
180 /*----------------------------------------------------------------------------
181 | Returns the result of converting the canonical NaN `a' to the double-
182 | precision floating-point format.
183 *----------------------------------------------------------------------------*/
184
185 float64 commonNaNToFloat64( softfloat_t* sf, commonNaNT a )
186 {
187
188     return
189           ( ( (bits64) a.sign )<<63 )
190         | LIT64( 0x7FF8000000000000 )
191         | ( a.high>>12 );
192
193 }
194
195 /*----------------------------------------------------------------------------
196 | Takes two double-precision floating-point values `a' and `b', one of which
197 | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
198 | signaling NaN, the invalid exception is raised.
199 *----------------------------------------------------------------------------*/
200
201 float64 propagateFloat64NaN( softfloat_t* sf, float64 a, float64 b )
202 {
203     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
204
205     aIsNaN = float64_is_nan( sf, a );
206     aIsSignalingNaN = float64_is_signaling_nan( sf, a );
207     bIsNaN = float64_is_nan( sf, b );
208     bIsSignalingNaN = float64_is_signaling_nan( sf, b );
209     a |= LIT64( 0x0008000000000000 );
210     b |= LIT64( 0x0008000000000000 );
211     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( sf, float_flag_invalid );
212     return bIsSignalingNaN ? b : aIsSignalingNaN ? a : bIsNaN ? b : a;
213
214 }
215
216 #ifdef FLOATX80
217
218 /*----------------------------------------------------------------------------
219 | The pattern for a default generated extended double-precision NaN.  The
220 | `high' and `low' values hold the most- and least-significant bits,
221 | respectively.
222 *----------------------------------------------------------------------------*/
223 #define floatx80_default_nan_high 0x7FFF
224 #define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
225
226 /*----------------------------------------------------------------------------
227 | Returns 1 if the extended double-precision floating-point value `a' is a
228 | NaN; otherwise returns 0.
229 *----------------------------------------------------------------------------*/
230
231 flag floatx80_is_nan( softfloat_t* sf, floatx80 a )
232 {
233
234     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
235
236 }
237
238 /*----------------------------------------------------------------------------
239 | Returns 1 if the extended double-precision floating-point value `a' is a
240 | signaling NaN; otherwise returns 0.
241 *----------------------------------------------------------------------------*/
242
243 flag floatx80_is_signaling_nan( softfloat_t* sf, floatx80 a )
244 {
245     bits64 aLow;
246
247     aLow = a.low & ~ LIT64( 0x4000000000000000 );
248     return
249            ( ( a.high & 0x7FFF ) == 0x7FFF )
250         && (bits64) ( aLow<<1 )
251         && ( a.low == aLow );
252
253 }
254
255 /*----------------------------------------------------------------------------
256 | Returns the result of converting the extended double-precision floating-
257 | point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
258 | invalid exception is raised.
259 *----------------------------------------------------------------------------*/
260
261 commonNaNT floatx80ToCommonNaN( softfloat_t* sf, floatx80 a )
262 {
263     commonNaNT z;
264
265     if ( floatx80_is_signaling_nan( sf, a ) ) float_raise( sf, float_flag_invalid );
266     z.sign = a.high>>15;
267     z.low = 0;
268     z.high = a.low<<1;
269     return z;
270
271 }
272
273 /*----------------------------------------------------------------------------
274 | Returns the result of converting the canonical NaN `a' to the extended
275 | double-precision floating-point format.
276 *----------------------------------------------------------------------------*/
277
278 floatx80 commonNaNToFloatx80( softfloat_t* sf, commonNaNT a )
279 {
280     floatx80 z;
281
282     z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
283     z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
284     return z;
285
286 }
287
288 /*----------------------------------------------------------------------------
289 | Takes two extended double-precision floating-point values `a' and `b', one
290 | of which is a NaN, and returns the appropriate NaN result.  If either `a' or
291 | `b' is a signaling NaN, the invalid exception is raised.
292 *----------------------------------------------------------------------------*/
293
294 floatx80 propagateFloatx80NaN( softfloat_t* sf, floatx80 a, floatx80 b )
295 {
296     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
297
298     aIsNaN = floatx80_is_nan( sf, a );
299     aIsSignalingNaN = floatx80_is_signaling_nan( sf, a );
300     bIsNaN = floatx80_is_nan( sf, b );
301     bIsSignalingNaN = floatx80_is_signaling_nan( sf, b );
302     a.low |= LIT64( 0xC000000000000000 );
303     b.low |= LIT64( 0xC000000000000000 );
304     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( sf, float_flag_invalid );
305     return bIsSignalingNaN ? b : aIsSignalingNaN ? a : bIsNaN ? b : a;
306
307 }
308
309 #endif
310
311 #ifdef FLOAT128
312
313 /*----------------------------------------------------------------------------
314 | The pattern for a default generated quadruple-precision NaN.  The `high' and
315 | `low' values hold the most- and least-significant bits, respectively.
316 *----------------------------------------------------------------------------*/
317 #define float128_default_nan_high LIT64( 0x7FFFFFFFFFFFFFFF )
318 #define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
319
320 /*----------------------------------------------------------------------------
321 | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
322 | otherwise returns 0.
323 *----------------------------------------------------------------------------*/
324
325 flag float128_is_nan( softfloat_t* sf, float128 a )
326 {
327
328     return
329            ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
330         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
331
332 }
333
334 /*----------------------------------------------------------------------------
335 | Returns 1 if the quadruple-precision floating-point value `a' is a
336 | signaling NaN; otherwise returns 0.
337 *----------------------------------------------------------------------------*/
338
339 flag float128_is_signaling_nan( softfloat_t* sf, float128 a )
340 {
341
342     return
343            ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
344         && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
345
346 }
347
348 /*----------------------------------------------------------------------------
349 | Returns the result of converting the quadruple-precision floating-point NaN
350 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
351 | exception is raised.
352 *----------------------------------------------------------------------------*/
353
354 commonNaNT float128ToCommonNaN( softfloat_t* sf, float128 a )
355 {
356     commonNaNT z;
357
358     if ( float128_is_signaling_nan( sf, a ) ) float_raise( sf, float_flag_invalid );
359     z.sign = a.high>>63;
360     shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
361     return z;
362
363 }
364
365 /*----------------------------------------------------------------------------
366 | Returns the result of converting the canonical NaN `a' to the quadruple-
367 | precision floating-point format.
368 *----------------------------------------------------------------------------*/
369
370 float128 commonNaNToFloat128( softfloat_t* sf, commonNaNT a )
371 {
372     float128 z;
373
374     shift128Right( a.high, a.low, 16, &z.high, &z.low );
375     z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
376     return z;
377
378 }
379
380 /*----------------------------------------------------------------------------
381 | Takes two quadruple-precision floating-point values `a' and `b', one of
382 | which is a NaN, and returns the appropriate NaN result.  If either `a' or
383 | `b' is a signaling NaN, the invalid exception is raised.
384 *----------------------------------------------------------------------------*/
385
386 float128 propagateFloat128NaN( softfloat_t* sf, float128 a, float128 b )
387 {
388     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
389
390     aIsNaN = float128_is_nan( sf, a );
391     aIsSignalingNaN = float128_is_signaling_nan( sf, a );
392     bIsNaN = float128_is_nan( sf, b );
393     bIsSignalingNaN = float128_is_signaling_nan( sf, b );
394     a.high |= LIT64( 0x0000800000000000 );
395     b.high |= LIT64( 0x0000800000000000 );
396     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( sf, float_flag_invalid );
397     return bIsSignalingNaN ? b : aIsSignalingNaN ? a : bIsNaN ? b : a;
398
399 }
400
401 #endif
402