]> git.sesse.net Git - pistorm/blob - softfloat/softfloat.h
Add Meson build files.
[pistorm] / softfloat / softfloat.h
1 #define SOFTFLOAT_68K
2 #define FLOATX80
3 #define FLOAT128
4 /*
5  * QEMU float support
6  *
7  * The code in this source file is derived from release 2a of the SoftFloat
8  * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
9  * some later contributions) are provided under that license, as detailed below.
10  * It has subsequently been modified by contributors to the QEMU Project,
11  * so some portions are provided under:
12  *  the SoftFloat-2a license
13  *  the BSD license
14  *  GPL-v2-or-later
15  *
16  * Any future contributions to this file after December 1st 2014 will be
17  * taken to be licensed under the Softfloat-2a license unless specifically
18  * indicated otherwise.
19  */
20
21 /*
22 ===============================================================================
23 This C header file is part of the SoftFloat IEC/IEEE Floating-point
24 Arithmetic Package, Release 2a.
25
26 Written by John R. Hauser.  This work was made possible in part by the
27 International Computer Science Institute, located at Suite 600, 1947 Center
28 Street, Berkeley, California 94704.  Funding was partially provided by the
29 National Science Foundation under grant MIP-9311980.  The original version
30 of this code was written as part of a project to build a fixed-point vector
31 processor in collaboration with the University of California at Berkeley,
32 overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
33 is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
34 arithmetic/SoftFloat.html'.
35
36 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
37 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
38 TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
39 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
40 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
41
42 Derivative works are acceptable, even for commercial purposes, so long as
43 (1) they include prominent notice that the work is derivative, and (2) they
44 include prominent notice akin to these four paragraphs for those parts of
45 this code that are retained.
46
47 ===============================================================================
48 */
49
50 /* BSD licensing:
51  * Copyright (c) 2006, Fabrice Bellard
52  * All rights reserved.
53  *
54  * Redistribution and use in source and binary forms, with or without
55  * modification, are permitted provided that the following conditions are met:
56  *
57  * 1. Redistributions of source code must retain the above copyright notice,
58  * this list of conditions and the following disclaimer.
59  *
60  * 2. Redistributions in binary form must reproduce the above copyright notice,
61  * this list of conditions and the following disclaimer in the documentation
62  * and/or other materials provided with the distribution.
63  *
64  * 3. Neither the name of the copyright holder nor the names of its contributors
65  * may be used to endorse or promote products derived from this software without
66  * specific prior written permission.
67  *
68  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
69  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
70  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
71  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
72  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
73  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
74  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
75  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
76  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
77  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
78  * THE POSSIBILITY OF SUCH DAMAGE.
79  */
80
81 /* Portions of this work are licensed under the terms of the GNU GPL,
82  * version 2 or later. See the COPYING file in the top-level directory.
83  */
84
85 #ifndef SOFTFLOAT_H
86 #define SOFTFLOAT_H
87
88 #if defined(CONFIG_SOLARIS) && defined(CONFIG_NEEDS_LIBSUNMATH)
89 #include <sunmath.h>
90 #endif
91
92
93 /* This 'flag' type must be able to hold at least 0 and 1. It should
94  * probably be replaced with 'bool' but the uses would need to be audited
95  * to check that they weren't accidentally relying on it being a larger type.
96  */
97
98 typedef uint64_t flag;
99 typedef uint8_t bool;
100
101 #define LIT64( a ) a##ULL
102
103 /*----------------------------------------------------------------------------
104 | Software IEC/IEEE floating-point ordering relations
105 *----------------------------------------------------------------------------*/
106 enum {
107     float_relation_less      = -1,
108     float_relation_equal     =  0,
109     float_relation_greater   =  1,
110     float_relation_unordered =  2
111 };
112
113 /*----------------------------------------------------------------------------
114 | Software IEC/IEEE floating-point types.
115 *----------------------------------------------------------------------------*/
116 /* Use structures for soft-float types.  This prevents accidentally mixing
117    them with native int/float types.  A sufficiently clever compiler and
118    sane ABI should be able to see though these structs.  However
119    x86/gcc 3.x seems to struggle a bit, so leave them disabled by default.  */
120 //#define USE_SOFTFLOAT_STRUCT_TYPES
121 #ifdef USE_SOFTFLOAT_STRUCT_TYPES
122 typedef struct {
123     uint16_t v;
124 } float16;
125 #define float16_val(x) (((float16)(x)).v)
126 #define make_float16(x) __extension__ ({ float16 f16_val = {x}; f16_val; })
127 #define const_float16(x) { x }
128 typedef struct {
129     uint32_t v;
130 } float32;
131 /* The cast ensures an error if the wrong type is passed.  */
132 #define float32_val(x) (((float32)(x)).v)
133 #define make_float32(x) __extension__ ({ float32 f32_val = {x}; f32_val; })
134 #define const_float32(x) { x }
135 typedef struct {
136     uint64_t v;
137 } float64;
138 #define float64_val(x) (((float64)(x)).v)
139 #define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; })
140 #define const_float64(x) { x }
141 #else
142 typedef uint16_t float16;
143 typedef uint32_t float32;
144 typedef uint64_t float64;
145 #define float16_val(x) (x)
146 #define float32_val(x) (x)
147 #define float64_val(x) (x)
148 #define make_float16(x) (x)
149 #define make_float32(x) (x)
150 #define make_float64(x) (x)
151 #define const_float16(x) (x)
152 #define const_float32(x) (x)
153 #define const_float64(x) (x)
154 #endif
155 typedef struct {
156     uint16_t high;
157     uint64_t low;
158 } floatx80;
159 typedef struct {
160 #ifdef HOST_WORDS_BIGENDIAN
161     uint64_t high, low;
162 #else
163     uint64_t low, high;
164 #endif
165 } float128;
166
167 /*----------------------------------------------------------------------------
168 | Software IEC/IEEE floating-point underflow tininess-detection mode.
169 *----------------------------------------------------------------------------*/
170 enum {
171     float_tininess_after_rounding  = 0,
172     float_tininess_before_rounding = 1
173 };
174
175 /*----------------------------------------------------------------------------
176 | Software IEC/IEEE floating-point rounding mode.
177 *----------------------------------------------------------------------------*/
178 enum {
179     float_round_nearest_even = 0,
180     float_round_down         = 1,
181     float_round_up           = 2,
182     float_round_to_zero      = 3,
183     float_round_ties_away    = 4,
184 };
185
186 /*----------------------------------------------------------------------------
187 | Software IEC/IEEE floating-point exception flags.
188 *----------------------------------------------------------------------------*/
189 enum {
190     float_flag_invalid   = 0x01,
191         float_flag_denormal  = 0x02,
192     float_flag_divbyzero = 0x04,
193     float_flag_overflow  = 0x08,
194     float_flag_underflow = 0x10,
195     float_flag_inexact   = 0x20,
196         float_flag_signaling = 0x40,
197         float_flag_decimal =   0x80
198 };
199
200 /*----------------------------------------------------------------------------
201  | Variables for storing sign, exponent and significand of overflowed or 
202  | underflowed extended double-precision floating-point value.
203  | Variables for storing sign, exponent and significand of internal extended 
204  | double-precision floating-point value for external use.
205  *----------------------------------------------------------------------------*/
206
207 extern flag floatx80_internal_sign;
208 extern int32_t floatx80_internal_exp;
209 extern uint64_t floatx80_internal_sig;
210 extern int32_t floatx80_internal_exp0;
211 extern uint64_t floatx80_internal_sig0;
212 extern uint64_t floatx80_internal_sig1;
213 extern int8_t floatx80_internal_precision;
214 extern int8_t floatx80_internal_mode;
215
216 typedef struct float_status {
217     signed char float_detect_tininess;
218     signed char float_rounding_mode;
219     uint8_t     float_exception_flags;
220     signed char floatx80_rounding_precision;
221     /* should denormalised results go to zero and set the inexact flag? */
222     flag flush_to_zero;
223     /* should denormalised inputs go to zero and set the input_denormal flag? */
224     flag flush_inputs_to_zero;
225     flag default_nan_mode;
226     flag snan_bit_is_one;
227         flag floatx80_special_flags;
228 } float_status;
229
230 /*----------------------------------------------------------------------------
231  | Function for getting sign, exponent and significand of extended
232  | double-precision floating-point intermediate result for external use.
233  *----------------------------------------------------------------------------*/
234 floatx80 getFloatInternalOverflow( void );
235 floatx80 getFloatInternalUnderflow( void );
236 floatx80 getFloatInternalRoundedAll( void );
237 floatx80 getFloatInternalRoundedSome( void );
238 floatx80 getFloatInternalUnrounded( void );
239 floatx80 getFloatInternalFloatx80( void );
240 uint64_t getFloatInternalGRS( void );
241
242 static inline void set_float_detect_tininess(int val, float_status *status)
243 {
244     status->float_detect_tininess = val;
245 }
246 static inline void set_float_rounding_mode(int val, float_status *status)
247 {
248     status->float_rounding_mode = val;
249 }
250 static inline void set_float_exception_flags(int val, float_status *status)
251 {
252     status->float_exception_flags = val;
253 }
254 static inline void set_floatx80_rounding_precision(int val,
255                                                    float_status *status)
256 {
257     status->floatx80_rounding_precision = val;
258 }
259 static inline void set_flush_to_zero(flag val, float_status *status)
260 {
261     status->flush_to_zero = val;
262 }
263 static inline void set_flush_inputs_to_zero(flag val, float_status *status)
264 {
265     status->flush_inputs_to_zero = val;
266 }
267 static inline void set_default_nan_mode(flag val, float_status *status)
268 {
269     status->default_nan_mode = val;
270 }
271 static inline void set_snan_bit_is_one(flag val, float_status *status)
272 {
273     status->snan_bit_is_one = val;
274 }
275 static inline int get_float_detect_tininess(float_status *status)
276 {
277     return status->float_detect_tininess;
278 }
279 static inline int get_float_rounding_mode(float_status *status)
280 {
281     return status->float_rounding_mode;
282 }
283 static inline int get_float_exception_flags(float_status *status)
284 {
285     return status->float_exception_flags;
286 }
287 static inline int get_floatx80_rounding_precision(float_status *status)
288 {
289     return status->floatx80_rounding_precision;
290 }
291 static inline flag get_flush_to_zero(float_status *status)
292 {
293     return status->flush_to_zero;
294 }
295 static inline flag get_flush_inputs_to_zero(float_status *status)
296 {
297     return status->flush_inputs_to_zero;
298 }
299 static inline flag get_default_nan_mode(float_status *status)
300 {
301     return status->default_nan_mode;
302 }
303
304 /*----------------------------------------------------------------------------
305 | Special flags for indicating some unique behavior is required.
306 *----------------------------------------------------------------------------*/
307 enum {
308         cmp_signed_nan = 0x01, addsub_swap_inf = 0x02, infinity_clear_intbit = 0x04
309 };
310
311 static inline void set_special_flags(uint8_t flags, float_status *status)
312 {
313         status->floatx80_special_flags = flags;
314 }
315 static inline int8_t fcmp_signed_nan(float_status *status)
316 {
317         return status->floatx80_special_flags & cmp_signed_nan;
318 }
319 static inline int8_t faddsub_swap_inf(float_status *status)
320 {
321         return status->floatx80_special_flags & addsub_swap_inf;
322 }
323 static inline int8_t inf_clear_intbit(float_status *status)
324 {
325         return status->floatx80_special_flags & infinity_clear_intbit;
326 }
327
328 /*----------------------------------------------------------------------------
329 | Routine to raise any or all of the software IEC/IEEE floating-point
330 | exception flags.
331 *----------------------------------------------------------------------------*/
332 void float_raise(uint8_t flags, float_status *status);
333
334
335 /*----------------------------------------------------------------------------
336  | The pattern for a default generated single-precision NaN.
337  *----------------------------------------------------------------------------*/
338 #define float32_default_nan 0x7FFFFFFF
339
340 /*----------------------------------------------------------------------------
341  | The pattern for a default generated double-precision NaN.
342  *----------------------------------------------------------------------------*/
343 #define float64_default_nan LIT64( 0x7FFFFFFFFFFFFFFF )
344
345 /*----------------------------------------------------------------------------
346  | The pattern for a default generated extended double-precision NaN.  The
347  | `high' and `low' values hold the most- and least-significant bits,
348  | respectively.
349  *----------------------------------------------------------------------------*/
350 #define floatx80_default_nan_high 0x7FFF
351 #define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
352
353 /*----------------------------------------------------------------------------
354  | The pattern for a default generated extended double-precision infinity.
355  *----------------------------------------------------------------------------*/
356 #define floatx80_default_infinity_low  LIT64( 0x0000000000000000 )
357
358 /*----------------------------------------------------------------------------
359 | If `a' is denormal and we are in flush-to-zero mode then set the
360 | input-denormal exception and return zero. Otherwise just return the value.
361 *----------------------------------------------------------------------------*/
362 float64 float64_squash_input_denormal(float64 a, float_status *status);
363
364 /*----------------------------------------------------------------------------
365 | Options to indicate which negations to perform in float*_muladd()
366 | Using these differs from negating an input or output before calling
367 | the muladd function in that this means that a NaN doesn't have its
368 | sign bit inverted before it is propagated.
369 | We also support halving the result before rounding, as a special
370 | case to support the ARM fused-sqrt-step instruction FRSQRTS.
371 *----------------------------------------------------------------------------*/
372 enum {
373     float_muladd_negate_c = 1,
374     float_muladd_negate_product = 2,
375     float_muladd_negate_result = 4,
376     float_muladd_halve_result = 8,
377 };
378
379 /*----------------------------------------------------------------------------
380 | Software IEC/IEEE integer-to-floating-point conversion routines.
381 *----------------------------------------------------------------------------*/
382
383 floatx80 int32_to_floatx80(int32_t);
384 floatx80 int64_to_floatx80(int64_t);
385
386 /*----------------------------------------------------------------------------
387 | Software IEC/IEEE single-precision conversion routines.
388 *----------------------------------------------------------------------------*/
389 floatx80 float32_to_floatx80(float32, float_status *status);
390 floatx80 float32_to_floatx80_allowunnormal(float32, float_status *status);
391
392 /*----------------------------------------------------------------------------
393 | Software IEC/IEEE double-precision conversion routines.
394 *----------------------------------------------------------------------------*/
395 floatx80 float64_to_floatx80(float64, float_status *status);
396
397 floatx80 float64_to_floatx80_allowunnormal( float64 a, float_status *status );
398
399 /*----------------------------------------------------------------------------
400 | Software IEC/IEEE extended double-precision conversion routines.
401 *----------------------------------------------------------------------------*/
402 int32_t floatx80_to_int32(floatx80, float_status *status);
403 #ifdef SOFTFLOAT_68K
404 int16_t floatx80_to_int16(floatx80, float_status *status);
405 int8_t floatx80_to_int8(floatx80, float_status *status);
406 #endif
407 int32_t floatx80_to_int32_round_to_zero(floatx80, float_status *status);
408 int64_t floatx80_to_int64(floatx80, float_status *status);
409 float32 floatx80_to_float32(floatx80, float_status *status);
410 float64 floatx80_to_float64(floatx80, float_status *status);
411 #ifdef SOFTFLOAT_68K
412 floatx80 floatx80_to_floatx80( floatx80, float_status *status);
413 floatx80 floatdecimal_to_floatx80(floatx80, float_status *status);
414 floatx80 floatx80_to_floatdecimal(floatx80, int32_t*, float_status *status);
415 #endif
416
417 uint64_t extractFloatx80Frac( floatx80 a );
418 int32_t extractFloatx80Exp( floatx80 a );
419 flag extractFloatx80Sign( floatx80 a );
420
421 floatx80 floatx80_round_to_int_toward_zero( floatx80 a, float_status *status);
422 floatx80 floatx80_round_to_float32( floatx80, float_status *status );
423 floatx80 floatx80_round_to_float64( floatx80, float_status *status );
424 floatx80 floatx80_round32( floatx80, float_status *status);
425 floatx80 floatx80_round64( floatx80, float_status *status);
426
427 flag floatx80_eq( floatx80, floatx80, float_status *status);
428 flag floatx80_le( floatx80, floatx80, float_status *status);
429 flag floatx80_lt( floatx80, floatx80, float_status *status);
430
431 #ifdef SOFTFLOAT_68K
432 // functions are in softfloat.c
433 floatx80 floatx80_move( floatx80 a, float_status *status );
434 floatx80 floatx80_abs( floatx80 a, float_status *status );
435 floatx80 floatx80_neg( floatx80 a, float_status *status );
436 floatx80 floatx80_getexp( floatx80 a, float_status *status );
437 floatx80 floatx80_getman( floatx80 a, float_status *status );
438 floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status );
439 floatx80 floatx80_rem( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_status *status );
440 floatx80 floatx80_mod( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_status *status );
441 floatx80 floatx80_sglmul( floatx80 a, floatx80 b, float_status *status );
442 floatx80 floatx80_sgldiv( floatx80 a, floatx80 b, float_status *status );
443 floatx80 floatx80_cmp( floatx80 a, floatx80 b, float_status *status );
444 floatx80 floatx80_tst( floatx80 a, float_status *status );
445
446 // functions are in softfloat_fpsp.c
447 floatx80 floatx80_acos(floatx80 a, float_status *status);
448 floatx80 floatx80_asin(floatx80 a, float_status *status);
449 floatx80 floatx80_atan(floatx80 a, float_status *status);
450 floatx80 floatx80_atanh(floatx80 a, float_status *status);
451 floatx80 floatx80_cos(floatx80 a, float_status *status);
452 floatx80 floatx80_cosh(floatx80 a, float_status *status);
453 floatx80 floatx80_etox(floatx80 a, float_status *status);
454 floatx80 floatx80_etoxm1(floatx80 a, float_status *status);
455 floatx80 floatx80_log10(floatx80 a, float_status *status);
456 floatx80 floatx80_log2(floatx80 a, float_status *status);
457 floatx80 floatx80_logn(floatx80 a, float_status *status);
458 floatx80 floatx80_lognp1(floatx80 a, float_status *status);
459 floatx80 floatx80_sin(floatx80 a, float_status *status);
460 floatx80 floatx80_sinh(floatx80 a, float_status *status);
461 floatx80 floatx80_tan(floatx80 a, float_status *status);
462 floatx80 floatx80_tanh(floatx80 a, float_status *status);
463 floatx80 floatx80_tentox(floatx80 a, float_status *status);
464 floatx80 floatx80_twotox(floatx80 a, float_status *status);
465 #endif
466
467 // functions originally internal to softfloat.c
468 void normalizeFloatx80Subnormal( uint64_t aSig, int32_t *zExpPtr, uint64_t *zSigPtr );
469 floatx80 packFloatx80( flag zSign, int32_t zExp, uint64_t zSig );
470 floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1, float_status *status);
471
472 /*----------------------------------------------------------------------------
473 | Software IEC/IEEE extended double-precision operations.
474 *----------------------------------------------------------------------------*/
475 floatx80 floatx80_round_to_int(floatx80, float_status *status);
476 floatx80 floatx80_add(floatx80, floatx80, float_status *status);
477 floatx80 floatx80_sub(floatx80, floatx80, float_status *status);
478 floatx80 floatx80_mul(floatx80, floatx80, float_status *status);
479 floatx80 floatx80_div(floatx80, floatx80, float_status *status);
480 floatx80 floatx80_sqrt(floatx80, float_status *status);
481 floatx80 floatx80_normalize(floatx80);
482 floatx80 floatx80_denormalize(floatx80, flag);
483
484 static inline int floatx80_is_zero_or_denormal(floatx80 a)
485 {
486     return (a.high & 0x7fff) == 0;
487 }
488
489 static inline int floatx80_is_any_nan(floatx80 a)
490 {
491     return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
492 }
493
494 /*----------------------------------------------------------------------------
495 | Return whether the given value is an invalid floatx80 encoding.
496 | Invalid floatx80 encodings arise when the integer bit is not set, but
497 | the exponent is not zero. The only times the integer bit is permitted to
498 | be zero is in subnormal numbers and the value zero.
499 | This includes what the Intel software developer's manual calls pseudo-NaNs,
500 | pseudo-infinities and un-normal numbers. It does not include
501 | pseudo-denormals, which must still be correctly handled as inputs even
502 | if they are never generated as outputs.
503 *----------------------------------------------------------------------------*/
504 static inline bool floatx80_invalid_encoding(floatx80 a)
505 {
506     return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0 && (a.high & 0x7FFF) != 0x7FFF;
507 }
508
509 #define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
510 #define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
511 #define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
512 #define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
513 #define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
514 #define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
515
516 #endif /* SOFTFLOAT_H */