x86: remove misconceptions about "sti" and halting
[akaros.git] / kern / arch / riscv / softfloat.h
1 #pragma once
2
3 #ifdef __cplusplus
4   extern "C" {
5 #endif
6
7 /*============================================================================
8
9 This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
10 Package, Release 2b.
11
12 Written by John R. Hauser.  This work was made possible in part by the
13 International Computer Science Institute, located at Suite 600, 1947 Center
14 Street, Berkeley, California 94704.  Funding was partially provided by the
15 National Science Foundation under grant MIP-9311980.  The original version
16 of this code was written as part of a project to build a fixed-point vector
17 processor in collaboration with the University of California at Berkeley,
18 overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
19 is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
20 arithmetic/SoftFloat.html'.
21
22 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
23 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
24 RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
25 AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
26 COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
27 EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
28 INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
29 OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
30
31 Derivative works are acceptable, even for commercial purposes, so long as
32 (1) the source code for the derivative work includes prominent notice that
33 the work is derivative, and (2) the source code includes prominent notice with
34 these four paragraphs for those parts of this code that are retained.
35
36 =============================================================================*/
37
38 /*----------------------------------------------------------------------------
39 | The macro `FLOATX80' must be defined to enable the extended double-precision
40 | floating-point format `floatx80'.  If this macro is not defined, the
41 | `floatx80' type will not be defined, and none of the functions that either
42 | input or output the `floatx80' type will be defined.  The same applies to
43 | the `FLOAT128' macro and the quadruple-precision format `float128'.
44 *----------------------------------------------------------------------------*/
45 #define FLOATX80
46 #define FLOAT128
47
48 #include <arch/types.h>
49
50 /* asw */
51 typedef uint8_t flag;
52 typedef uint8_t bits8;
53 typedef int8_t sbits8;
54 typedef uint16_t bits16;
55 typedef int16_t sbits16;
56 typedef uint32_t bits32;
57 typedef int32_t sbits32;
58 typedef uint64_t bits64;
59 typedef int64_t sbits64;
60
61 #define INLINE
62 #define LIT64( a ) a##LL
63
64 /*----------------------------------------------------------------------------
65 | Software IEC/IEEE floating-point types.
66 *----------------------------------------------------------------------------*/
67 typedef unsigned int float32;
68 typedef unsigned long long float64;
69 #ifdef FLOATX80
70 typedef struct {
71     unsigned short high;
72     unsigned long long low;
73 } floatx80;
74 #endif
75 #ifdef FLOAT128
76 typedef struct {
77     unsigned long long high, low;
78 } float128;
79 #endif
80
81 /*----------------------------------------------------------------------------
82 | Internal canonical NaN format.
83 *----------------------------------------------------------------------------*/
84 typedef struct {
85     flag sign;
86     bits64 high, low;
87 } commonNaNT;
88
89 INLINE bits32 extractFloat32Frac( float32 a );
90 INLINE int16_t extractFloat32Exp( float32 a );
91 INLINE flag extractFloat32Sign( float32 a );
92 INLINE float32 packFloat32( flag zSign, int16_t zExp, bits32 zSig );
93 INLINE bits64 extractFloat64Frac( float64 a );
94 INLINE int16_t extractFloat64Exp( float64 a );
95 INLINE flag extractFloat64Sign( float64 a );
96 INLINE float64 packFloat64( flag zSign, int16_t zExp, bits64 zSig );
97 INLINE bits64 extractFloatx80Frac( floatx80 a );
98 INLINE int32_t extractFloatx80Exp( floatx80 a );
99 INLINE flag extractFloatx80Sign( floatx80 a );
100 INLINE floatx80 packFloatx80( flag zSign, int32_t zExp, bits64 zSig );
101 INLINE bits64 extractFloat128Frac1( float128 a );
102 INLINE bits64 extractFloat128Frac0( float128 a );
103 INLINE int32_t extractFloat128Exp( float128 a );
104 INLINE flag extractFloat128Sign( float128 a );
105 INLINE float128 packFloat128( flag zSign, int32_t zExp, bits64 zSig0, bits64 zSig1 );
106
107 typedef struct
108 {
109   int8_t float_detect_tininess;
110   int8_t float_rounding_mode;
111   int8_t float_exception_flags;
112   #ifdef FLOATX80
113     int floatx80_rounding_precision;
114   #endif
115 } softfloat_t;
116
117 float32 subFloat32Sigs( softfloat_t* sf, float32 a, float32 b, flag zSign );
118 float64 subFloat64Sigs( softfloat_t* sf, float64 a, float64 b, flag zSign );
119 floatx80 subFloatx80Sigs( softfloat_t* sf, floatx80 a, floatx80 b, flag zSign );
120 float128 subFloat128Sigs( softfloat_t* sf, float128 a, float128 b, flag zSign );
121 float32 addFloat32Sigs( softfloat_t* sf, float32 a, float32 b, flag zSign );
122 float64 addFloat64Sigs( softfloat_t* sf, float64 a, float64 b, flag zSign );
123 floatx80 addFloatx80Sigs( softfloat_t* sf, floatx80 a, floatx80 b, flag zSign );
124 float128 addFloat128Sigs( softfloat_t* sf, float128 a, float128 b, flag zSign );
125 float32 normalizeRoundAndPackFloat32( softfloat_t* sf, flag zSign, int16_t zExp, bits32 zSig );
126 float64 normalizeRoundAndPackFloat64( softfloat_t* sf, flag zSign, int16_t zExp, bits64 zSig );
127 floatx80 normalizeRoundAndPackFloatx80( softfloat_t* sf,
128      int8_t roundingPrecision, flag zSign, int32_t zExp, bits64 zSig0, bits64 zSig1);
129 float128 normalizeRoundAndPackFloat128( softfloat_t* sf,
130      flag zSign, int32_t zExp, bits64 zSig0, bits64 zSig1 );
131 int32_t roundAndPackInt32( softfloat_t* sf, flag zSign, bits64 absZ );
132 int64_t roundAndPackInt64( softfloat_t* sf, flag zSign, bits64 absZ0, bits64 absZ1 );
133 float32 roundAndPackFloat32( softfloat_t* sf, flag zSign, int16_t zExp, bits32 zSig );
134 float64 roundAndPackFloat64( softfloat_t* sf, flag zSign, int16_t zExp, bits64 zSig );
135 floatx80 roundAndPackFloatx80( softfloat_t* sf,
136      int8_t roundingPrecision, flag zSign, int32_t zExp, bits64 zSig0, bits64 zSig1);
137 float128 roundAndPackFloat128( softfloat_t* sf,
138      flag zSign, int32_t zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 );
139 void normalizeFloat32Subnormal( bits32 aSig, int16_t *zExpPtr, bits32 *zSigPtr );
140 void normalizeFloat64Subnormal( bits64 aSig, int16_t *zExpPtr, bits64 *zSigPtr );
141 void normalizeFloatx80Subnormal( bits64 aSig, int32_t *zExpPtr, bits64 *zSigPtr );
142 void normalizeFloat128Subnormal(
143      bits64 aSig0,
144      bits64 aSig1,
145      int32_t *zExpPtr,
146      bits64 *zSig0Ptr,
147      bits64 *zSig1Ptr
148  );
149
150 INLINE flag float32_is_nan( softfloat_t* sf, float32 a );
151 commonNaNT float32ToCommonNaN( softfloat_t* sf, float32 a );
152 float32 commonNaNToFloat32( softfloat_t* sf, commonNaNT a );
153 float32 propagateFloat32NaN( softfloat_t* sf, float32 a, float32 b );
154 flag float64_is_nan( softfloat_t* sf, float64 a );
155 commonNaNT float64ToCommonNaN( softfloat_t* sf, float64 a );
156 float64 commonNaNToFloat64( softfloat_t* sf, commonNaNT a );
157 float64 propagateFloat64NaN( softfloat_t* sf, float64 a, float64 b );
158 flag floatx80_is_nan( softfloat_t* sf, floatx80 a );
159 commonNaNT floatx80ToCommonNaN( softfloat_t* sf, floatx80 a );
160 floatx80 commonNaNToFloatx80( softfloat_t* sf, commonNaNT a );
161 floatx80 propagateFloatx80NaN( softfloat_t* sf, floatx80 a, floatx80 b );
162 flag float128_is_nan( softfloat_t* sf, float128 a );
163 commonNaNT float128ToCommonNaN( softfloat_t* sf, float128 a );
164 float128 commonNaNToFloat128( softfloat_t* sf, commonNaNT a );
165 float128 propagateFloat128NaN( softfloat_t* sf, float128 a, float128 b );
166
167 /*----------------------------------------------------------------------------
168 | Routine to raise any or all of the software IEC/IEEE floating-point
169 | exception flags.
170 *----------------------------------------------------------------------------*/
171 INLINE void float_raise( softfloat_t* sf, int );
172
173 /*----------------------------------------------------------------------------
174 | Software IEC/IEEE integer-to-floating-point conversion routines.
175 *----------------------------------------------------------------------------*/
176 float32 int32_to_float32( softfloat_t* sf, int );
177 float64 int32_to_float64( softfloat_t* sf, int );
178 #ifdef FLOATX80
179 floatx80 int32_to_floatx80( softfloat_t* sf, int );
180 #endif
181 #ifdef FLOAT128
182 float128 int32_to_float128( softfloat_t* sf, int );
183 #endif
184 float32 int64_to_float32( softfloat_t* sf, long long );
185 float64 int64_to_float64( softfloat_t* sf, long long );
186 #ifdef FLOATX80
187 floatx80 int64_to_floatx80( softfloat_t* sf, long long );
188 #endif
189 #ifdef FLOAT128
190 float128 int64_to_float128( softfloat_t* sf, long long );
191 #endif
192
193 /*----------------------------------------------------------------------------
194 | Software IEC/IEEE single-precision conversion routines.
195 *----------------------------------------------------------------------------*/
196 int float32_to_int32( softfloat_t* sf, float32 );
197 int float32_to_int32_round_to_zero( softfloat_t* sf, float32 );
198 long long float32_to_int64( softfloat_t* sf, float32 );
199 long long float32_to_int64_round_to_zero( softfloat_t* sf, float32 );
200 float64 float32_to_float64( softfloat_t* sf, float32 );
201 #ifdef FLOATX80
202 floatx80 float32_to_floatx80( softfloat_t* sf, float32 );
203 #endif
204 #ifdef FLOAT128
205 float128 float32_to_float128( softfloat_t* sf, float32 );
206 #endif
207
208 /*----------------------------------------------------------------------------
209 | Software IEC/IEEE single-precision operations.
210 *----------------------------------------------------------------------------*/
211 float32 float32_round_to_int( softfloat_t* sf, float32 );
212 float32 float32_add( softfloat_t* sf, float32, float32 );
213 float32 float32_sub( softfloat_t* sf, float32, float32 );
214 float32 float32_mul( softfloat_t* sf, float32, float32 );
215 float32 float32_div( softfloat_t* sf, float32, float32 );
216 float32 float32_rem( softfloat_t* sf, float32, float32 );
217 float32 float32_sqrt( softfloat_t* sf, float32 );
218 flag float32_eq( softfloat_t* sf, float32, float32 );
219 flag float32_le( softfloat_t* sf, float32, float32 );
220 flag float32_lt( softfloat_t* sf, float32, float32 );
221 flag float32_eq_signaling( softfloat_t* sf, float32, float32 );
222 flag float32_le_quiet( softfloat_t* sf, float32, float32 );
223 flag float32_lt_quiet( softfloat_t* sf, float32, float32 );
224 flag float32_is_signaling_nan( softfloat_t* sf, float32 );
225
226 /*----------------------------------------------------------------------------
227 | Software IEC/IEEE double-precision conversion routines.
228 *----------------------------------------------------------------------------*/
229 int float64_to_int32( softfloat_t* sf, float64 );
230 int float64_to_int32_round_to_zero( softfloat_t* sf, float64 );
231 long long float64_to_int64( softfloat_t* sf, float64 );
232 long long float64_to_int64_round_to_zero( softfloat_t* sf, float64 );
233 float32 float64_to_float32( softfloat_t* sf, float64 );
234 #ifdef FLOATX80
235 floatx80 float64_to_floatx80( softfloat_t* sf, float64 );
236 #endif
237 #ifdef FLOAT128
238 float128 float64_to_float128( softfloat_t* sf, float64 );
239 #endif
240
241 /*----------------------------------------------------------------------------
242 | Software IEC/IEEE double-precision operations.
243 *----------------------------------------------------------------------------*/
244 float64 float64_round_to_int( softfloat_t* sf, float64 );
245 float64 float64_add( softfloat_t* sf, float64, float64 );
246 float64 float64_sub( softfloat_t* sf, float64, float64 );
247 float64 float64_mul( softfloat_t* sf, float64, float64 );
248 float64 float64_div( softfloat_t* sf, float64, float64 );
249 float64 float64_rem( softfloat_t* sf, float64, float64 );
250 float64 float64_sqrt( softfloat_t* sf, float64 );
251 flag float64_eq( softfloat_t* sf, float64, float64 );
252 flag float64_le( softfloat_t* sf, float64, float64 );
253 flag float64_lt( softfloat_t* sf, float64, float64 );
254 flag float64_eq_signaling( softfloat_t* sf, float64, float64 );
255 flag float64_le_quiet( softfloat_t* sf, float64, float64 );
256 flag float64_lt_quiet( softfloat_t* sf, float64, float64 );
257 flag float64_is_signaling_nan( softfloat_t* sf, float64 );
258
259 #ifdef FLOATX80
260
261 /*----------------------------------------------------------------------------
262 | Software IEC/IEEE extended double-precision conversion routines.
263 *----------------------------------------------------------------------------*/
264 int floatx80_to_int32( softfloat_t* sf, floatx80 );
265 int floatx80_to_int32_round_to_zero( softfloat_t* sf, floatx80 );
266 long long floatx80_to_int64( softfloat_t* sf, floatx80 );
267 long long floatx80_to_int64_round_to_zero( softfloat_t* sf, floatx80 );
268 float32 floatx80_to_float32( softfloat_t* sf, floatx80 );
269 float64 floatx80_to_float64( softfloat_t* sf, floatx80 );
270 #ifdef FLOAT128
271 float128 floatx80_to_float128( softfloat_t* sf, floatx80 );
272 #endif
273
274 #endif
275
276 #ifdef FLOATX80
277 /*----------------------------------------------------------------------------
278 | Software IEC/IEEE extended double-precision operations.
279 *----------------------------------------------------------------------------*/
280 floatx80 floatx80_round_to_int( softfloat_t* sf, floatx80 );
281 floatx80 floatx80_add( softfloat_t* sf, floatx80, floatx80 );
282 floatx80 floatx80_sub( softfloat_t* sf, floatx80, floatx80 );
283 floatx80 floatx80_mul( softfloat_t* sf, floatx80, floatx80 );
284 floatx80 floatx80_div( softfloat_t* sf, floatx80, floatx80 );
285 floatx80 floatx80_rem( softfloat_t* sf, floatx80, floatx80 );
286 floatx80 floatx80_sqrt( softfloat_t* sf, floatx80 );
287 flag floatx80_eq( softfloat_t* sf, floatx80, floatx80 );
288 flag floatx80_le( softfloat_t* sf, floatx80, floatx80 );
289 flag floatx80_lt( softfloat_t* sf, floatx80, floatx80 );
290 flag floatx80_eq_signaling( softfloat_t* sf, floatx80, floatx80 );
291 flag floatx80_le_quiet( softfloat_t* sf, floatx80, floatx80 );
292 flag floatx80_lt_quiet( softfloat_t* sf, floatx80, floatx80 );
293 flag floatx80_is_signaling_nan( softfloat_t* sf, floatx80 );
294 #endif
295
296 #ifdef FLOAT128
297
298 /*----------------------------------------------------------------------------
299 | Software IEC/IEEE quadruple-precision conversion routines.
300 *----------------------------------------------------------------------------*/
301 int float128_to_int32( softfloat_t* sf, float128 );
302 int float128_to_int32_round_to_zero( softfloat_t* sf, float128 );
303 long long float128_to_int64( softfloat_t* sf, float128 );
304 long long float128_to_int64_round_to_zero( softfloat_t* sf, float128 );
305 float32 float128_to_float32( softfloat_t* sf, float128 );
306 float64 float128_to_float64( softfloat_t* sf, float128 );
307 #ifdef FLOATX80
308 floatx80 float128_to_floatx80( softfloat_t* sf, float128 );
309 #endif
310
311 /*----------------------------------------------------------------------------
312 | Software IEC/IEEE quadruple-precision operations.
313 *----------------------------------------------------------------------------*/
314 float128 float128_round_to_int( softfloat_t* sf, float128 );
315 float128 float128_add( softfloat_t* sf, float128, float128 );
316 float128 float128_sub( softfloat_t* sf, float128, float128 );
317 float128 float128_mul( softfloat_t* sf, float128, float128 );
318 float128 float128_div( softfloat_t* sf, float128, float128 );
319 float128 float128_rem( softfloat_t* sf, float128, float128 );
320 float128 float128_sqrt( softfloat_t* sf, float128 );
321 flag float128_eq( softfloat_t* sf, float128, float128 );
322 flag float128_le( softfloat_t* sf, float128, float128 );
323 flag float128_lt( softfloat_t* sf, float128, float128 );
324 flag float128_eq_signaling( softfloat_t* sf, float128, float128 );
325 flag float128_le_quiet( softfloat_t* sf, float128, float128 );
326 flag float128_lt_quiet( softfloat_t* sf, float128, float128 );
327 flag float128_is_signaling_nan( softfloat_t* sf, float128 );
328
329 #endif
330
331 void softfloat_init(softfloat_t* sf);
332
333 enum {
334     float_tininess_after_rounding  = 0,
335     float_tininess_before_rounding = 1
336 };
337
338 enum {
339     float_round_nearest_even = 0,
340     float_round_to_zero      = 1,
341     float_round_down         = 2,
342     float_round_up           = 3
343 };
344
345 enum {
346     float_flag_inexact   =  1,
347     float_flag_underflow =  4,
348     float_flag_overflow  =  8,
349     float_flag_divbyzero =  2,
350     float_flag_invalid   = 16
351 };
352
353 #ifdef __cplusplus
354  }
355 #endif