|
|
1.1 root 1: /*============================================================================
2:
3: This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
4: Package, Release 2b.
5:
6: Written by John R. Hauser. This work was made possible in part by the
7: International Computer Science Institute, located at Suite 600, 1947 Center
8: Street, Berkeley, California 94704. Funding was partially provided by the
9: National Science Foundation under grant MIP-9311980. The original version
10: of this code was written as part of a project to build a fixed-point vector
11: processor in collaboration with the University of California at Berkeley,
12: overseen by Profs. Nelson Morgan and John Wawrzynek. More information
13: is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
14: arithmetic/SoftFloat.html'.
15:
16: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
17: been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
18: RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
19: AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
20: COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
21: EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
22: INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
23: OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
24:
25: Derivative works are acceptable, even for commercial purposes, so long as
26: (1) the source code for the derivative work includes prominent notice that
27: the work is derivative, and (2) the source code includes prominent notice with
28: these four paragraphs for those parts of this code that are retained.
29:
30: =============================================================================*/
31:
32: #ifndef SOFTFLOAT_H
33: #define SOFTFLOAT_H
34:
1.1.1.4 ! root 35: #if defined(HOST_SOLARIS) && defined(NEEDS_LIBSUNMATH)
! 36: #include <sunmath.h>
! 37: #endif
! 38:
1.1 root 39: #include <inttypes.h>
40: #include "config.h"
41:
42: /*----------------------------------------------------------------------------
43: | Each of the following `typedef's defines the most convenient type that holds
44: | integers of at least as many bits as specified. For example, `uint8' should
45: | be the most convenient type that can hold unsigned integers of as many as
46: | 8 bits. The `flag' type must be able to hold either a 0 or 1. For most
47: | implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
48: | to the same as `int'.
49: *----------------------------------------------------------------------------*/
1.1.1.3 root 50: typedef uint8_t flag;
1.1 root 51: typedef uint8_t uint8;
52: typedef int8_t int8;
53: typedef int uint16;
54: typedef int int16;
55: typedef unsigned int uint32;
56: typedef signed int int32;
57: typedef uint64_t uint64;
58: typedef int64_t int64;
59:
60: /*----------------------------------------------------------------------------
61: | Each of the following `typedef's defines a type that holds integers
62: | of _exactly_ the number of bits specified. For instance, for most
63: | implementation of C, `bits16' and `sbits16' should be `typedef'ed to
64: | `unsigned short int' and `signed short int' (or `short int'), respectively.
65: *----------------------------------------------------------------------------*/
66: typedef uint8_t bits8;
67: typedef int8_t sbits8;
68: typedef uint16_t bits16;
69: typedef int16_t sbits16;
70: typedef uint32_t bits32;
71: typedef int32_t sbits32;
72: typedef uint64_t bits64;
73: typedef int64_t sbits64;
74:
75: #define LIT64( a ) a##LL
76: #define INLINE static inline
77:
78: /*----------------------------------------------------------------------------
79: | The macro `FLOATX80' must be defined to enable the extended double-precision
80: | floating-point format `floatx80'. If this macro is not defined, the
81: | `floatx80' type will not be defined, and none of the functions that either
82: | input or output the `floatx80' type will be defined. The same applies to
83: | the `FLOAT128' macro and the quadruple-precision format `float128'.
84: *----------------------------------------------------------------------------*/
85: #ifdef CONFIG_SOFTFLOAT
86: /* bit exact soft float support */
87: #define FLOATX80
88: #define FLOAT128
89: #else
90: /* native float support */
91: #if (defined(__i386__) || defined(__x86_64__)) && !defined(_BSD)
92: #define FLOATX80
93: #endif
94: #endif /* !CONFIG_SOFTFLOAT */
95:
96: #define STATUS_PARAM , float_status *status
97: #define STATUS(field) status->field
98: #define STATUS_VAR , status
99:
100: /*----------------------------------------------------------------------------
101: | Software IEC/IEEE floating-point ordering relations
102: *----------------------------------------------------------------------------*/
103: enum {
104: float_relation_less = -1,
105: float_relation_equal = 0,
106: float_relation_greater = 1,
107: float_relation_unordered = 2
108: };
109:
110: #ifdef CONFIG_SOFTFLOAT
111: /*----------------------------------------------------------------------------
112: | Software IEC/IEEE floating-point types.
113: *----------------------------------------------------------------------------*/
1.1.1.4 ! root 114: /* Use structures for soft-float types. This prevents accidentally mixing
! 115: them with native int/float types. A sufficiently clever compiler and
! 116: sane ABI should be able to see though these structs. However
! 117: x86/gcc 3.x seems to struggle a bit, so leave them disabled by default. */
! 118: //#define USE_SOFTFLOAT_STRUCT_TYPES
! 119: #ifdef USE_SOFTFLOAT_STRUCT_TYPES
! 120: typedef struct {
! 121: uint32_t v;
! 122: } float32;
! 123: /* The cast ensures an error if the wrong type is passed. */
! 124: #define float32_val(x) (((float32)(x)).v)
! 125: #define make_float32(x) __extension__ ({ float32 f32_val = {x}; f32_val; })
! 126: typedef struct {
! 127: uint64_t v;
! 128: } float64;
! 129: #define float64_val(x) (((float64)(x)).v)
! 130: #define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; })
! 131: #else
1.1 root 132: typedef uint32_t float32;
133: typedef uint64_t float64;
1.1.1.4 ! root 134: #define float32_val(x) (x)
! 135: #define float64_val(x) (x)
! 136: #define make_float32(x) (x)
! 137: #define make_float64(x) (x)
! 138: #endif
1.1 root 139: #ifdef FLOATX80
140: typedef struct {
141: uint64_t low;
142: uint16_t high;
143: } floatx80;
144: #endif
145: #ifdef FLOAT128
146: typedef struct {
147: #ifdef WORDS_BIGENDIAN
148: uint64_t high, low;
149: #else
150: uint64_t low, high;
151: #endif
152: } float128;
153: #endif
154:
155: /*----------------------------------------------------------------------------
156: | Software IEC/IEEE floating-point underflow tininess-detection mode.
157: *----------------------------------------------------------------------------*/
158: enum {
159: float_tininess_after_rounding = 0,
160: float_tininess_before_rounding = 1
161: };
162:
163: /*----------------------------------------------------------------------------
164: | Software IEC/IEEE floating-point rounding mode.
165: *----------------------------------------------------------------------------*/
166: enum {
167: float_round_nearest_even = 0,
168: float_round_down = 1,
169: float_round_up = 2,
170: float_round_to_zero = 3
171: };
172:
173: /*----------------------------------------------------------------------------
174: | Software IEC/IEEE floating-point exception flags.
175: *----------------------------------------------------------------------------*/
176: enum {
177: float_flag_invalid = 1,
178: float_flag_divbyzero = 4,
179: float_flag_overflow = 8,
180: float_flag_underflow = 16,
181: float_flag_inexact = 32
182: };
183:
184: typedef struct float_status {
185: signed char float_detect_tininess;
186: signed char float_rounding_mode;
187: signed char float_exception_flags;
188: #ifdef FLOATX80
189: signed char floatx80_rounding_precision;
190: #endif
191: } float_status;
192:
193: void set_float_rounding_mode(int val STATUS_PARAM);
194: void set_float_exception_flags(int val STATUS_PARAM);
195: INLINE int get_float_exception_flags(float_status *status)
196: {
197: return STATUS(float_exception_flags);
198: }
199: #ifdef FLOATX80
200: void set_floatx80_rounding_precision(int val STATUS_PARAM);
201: #endif
202:
203: /*----------------------------------------------------------------------------
204: | Routine to raise any or all of the software IEC/IEEE floating-point
205: | exception flags.
206: *----------------------------------------------------------------------------*/
1.1.1.2 root 207: void float_raise( int8 flags STATUS_PARAM);
1.1 root 208:
209: /*----------------------------------------------------------------------------
210: | Software IEC/IEEE integer-to-floating-point conversion routines.
211: *----------------------------------------------------------------------------*/
212: float32 int32_to_float32( int STATUS_PARAM );
213: float64 int32_to_float64( int STATUS_PARAM );
214: float32 uint32_to_float32( unsigned int STATUS_PARAM );
215: float64 uint32_to_float64( unsigned int STATUS_PARAM );
216: #ifdef FLOATX80
217: floatx80 int32_to_floatx80( int STATUS_PARAM );
218: #endif
219: #ifdef FLOAT128
220: float128 int32_to_float128( int STATUS_PARAM );
221: #endif
222: float32 int64_to_float32( int64_t STATUS_PARAM );
1.1.1.4 ! root 223: float32 uint64_to_float32( uint64_t STATUS_PARAM );
1.1 root 224: float64 int64_to_float64( int64_t STATUS_PARAM );
1.1.1.4 ! root 225: float64 uint64_to_float64( uint64_t STATUS_PARAM );
1.1 root 226: #ifdef FLOATX80
227: floatx80 int64_to_floatx80( int64_t STATUS_PARAM );
228: #endif
229: #ifdef FLOAT128
230: float128 int64_to_float128( int64_t STATUS_PARAM );
231: #endif
232:
233: /*----------------------------------------------------------------------------
234: | Software IEC/IEEE single-precision conversion routines.
235: *----------------------------------------------------------------------------*/
236: int float32_to_int32( float32 STATUS_PARAM );
237: int float32_to_int32_round_to_zero( float32 STATUS_PARAM );
238: unsigned int float32_to_uint32( float32 STATUS_PARAM );
239: unsigned int float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
240: int64_t float32_to_int64( float32 STATUS_PARAM );
241: int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM );
242: float64 float32_to_float64( float32 STATUS_PARAM );
243: #ifdef FLOATX80
244: floatx80 float32_to_floatx80( float32 STATUS_PARAM );
245: #endif
246: #ifdef FLOAT128
247: float128 float32_to_float128( float32 STATUS_PARAM );
248: #endif
249:
250: /*----------------------------------------------------------------------------
251: | Software IEC/IEEE single-precision operations.
252: *----------------------------------------------------------------------------*/
253: float32 float32_round_to_int( float32 STATUS_PARAM );
254: float32 float32_add( float32, float32 STATUS_PARAM );
255: float32 float32_sub( float32, float32 STATUS_PARAM );
256: float32 float32_mul( float32, float32 STATUS_PARAM );
257: float32 float32_div( float32, float32 STATUS_PARAM );
258: float32 float32_rem( float32, float32 STATUS_PARAM );
259: float32 float32_sqrt( float32 STATUS_PARAM );
1.1.1.3 root 260: int float32_eq( float32, float32 STATUS_PARAM );
261: int float32_le( float32, float32 STATUS_PARAM );
262: int float32_lt( float32, float32 STATUS_PARAM );
263: int float32_eq_signaling( float32, float32 STATUS_PARAM );
264: int float32_le_quiet( float32, float32 STATUS_PARAM );
265: int float32_lt_quiet( float32, float32 STATUS_PARAM );
266: int float32_compare( float32, float32 STATUS_PARAM );
267: int float32_compare_quiet( float32, float32 STATUS_PARAM );
1.1.1.4 ! root 268: int float32_is_nan( float32 );
1.1.1.3 root 269: int float32_is_signaling_nan( float32 );
1.1.1.4 ! root 270: float32 float32_scalbn( float32, int STATUS_PARAM );
1.1 root 271:
272: INLINE float32 float32_abs(float32 a)
273: {
1.1.1.4 ! root 274: return make_float32(float32_val(a) & 0x7fffffff);
1.1 root 275: }
276:
277: INLINE float32 float32_chs(float32 a)
278: {
1.1.1.4 ! root 279: return make_float32(float32_val(a) ^ 0x80000000);
1.1 root 280: }
281:
1.1.1.4 ! root 282: #define float32_zero make_float32(0)
! 283:
1.1 root 284: /*----------------------------------------------------------------------------
285: | Software IEC/IEEE double-precision conversion routines.
286: *----------------------------------------------------------------------------*/
287: int float64_to_int32( float64 STATUS_PARAM );
288: int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
289: unsigned int float64_to_uint32( float64 STATUS_PARAM );
290: unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
291: int64_t float64_to_int64( float64 STATUS_PARAM );
292: int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
1.1.1.4 ! root 293: uint64_t float64_to_uint64 (float64 a STATUS_PARAM);
! 294: uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM);
1.1 root 295: float32 float64_to_float32( float64 STATUS_PARAM );
296: #ifdef FLOATX80
297: floatx80 float64_to_floatx80( float64 STATUS_PARAM );
298: #endif
299: #ifdef FLOAT128
300: float128 float64_to_float128( float64 STATUS_PARAM );
301: #endif
302:
303: /*----------------------------------------------------------------------------
304: | Software IEC/IEEE double-precision operations.
305: *----------------------------------------------------------------------------*/
306: float64 float64_round_to_int( float64 STATUS_PARAM );
1.1.1.3 root 307: float64 float64_trunc_to_int( float64 STATUS_PARAM );
1.1 root 308: float64 float64_add( float64, float64 STATUS_PARAM );
309: float64 float64_sub( float64, float64 STATUS_PARAM );
310: float64 float64_mul( float64, float64 STATUS_PARAM );
311: float64 float64_div( float64, float64 STATUS_PARAM );
312: float64 float64_rem( float64, float64 STATUS_PARAM );
313: float64 float64_sqrt( float64 STATUS_PARAM );
1.1.1.3 root 314: int float64_eq( float64, float64 STATUS_PARAM );
315: int float64_le( float64, float64 STATUS_PARAM );
316: int float64_lt( float64, float64 STATUS_PARAM );
317: int float64_eq_signaling( float64, float64 STATUS_PARAM );
318: int float64_le_quiet( float64, float64 STATUS_PARAM );
319: int float64_lt_quiet( float64, float64 STATUS_PARAM );
320: int float64_compare( float64, float64 STATUS_PARAM );
321: int float64_compare_quiet( float64, float64 STATUS_PARAM );
1.1.1.4 ! root 322: int float64_is_nan( float64 a );
1.1.1.3 root 323: int float64_is_signaling_nan( float64 );
1.1.1.4 ! root 324: float64 float64_scalbn( float64, int STATUS_PARAM );
1.1 root 325:
326: INLINE float64 float64_abs(float64 a)
327: {
1.1.1.4 ! root 328: return make_float64(float64_val(a) & 0x7fffffffffffffffLL);
1.1 root 329: }
330:
331: INLINE float64 float64_chs(float64 a)
332: {
1.1.1.4 ! root 333: return make_float64(float64_val(a) ^ 0x8000000000000000LL);
1.1 root 334: }
335:
1.1.1.4 ! root 336: #define float64_zero make_float64(0)
! 337:
1.1 root 338: #ifdef FLOATX80
339:
340: /*----------------------------------------------------------------------------
341: | Software IEC/IEEE extended double-precision conversion routines.
342: *----------------------------------------------------------------------------*/
343: int floatx80_to_int32( floatx80 STATUS_PARAM );
344: int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
345: int64_t floatx80_to_int64( floatx80 STATUS_PARAM );
346: int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM );
347: float32 floatx80_to_float32( floatx80 STATUS_PARAM );
348: float64 floatx80_to_float64( floatx80 STATUS_PARAM );
349: #ifdef FLOAT128
350: float128 floatx80_to_float128( floatx80 STATUS_PARAM );
351: #endif
352:
353: /*----------------------------------------------------------------------------
354: | Software IEC/IEEE extended double-precision operations.
355: *----------------------------------------------------------------------------*/
356: floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM );
357: floatx80 floatx80_add( floatx80, floatx80 STATUS_PARAM );
358: floatx80 floatx80_sub( floatx80, floatx80 STATUS_PARAM );
359: floatx80 floatx80_mul( floatx80, floatx80 STATUS_PARAM );
360: floatx80 floatx80_div( floatx80, floatx80 STATUS_PARAM );
361: floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
362: floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
1.1.1.3 root 363: int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
364: int floatx80_le( floatx80, floatx80 STATUS_PARAM );
365: int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
366: int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
367: int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
368: int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
1.1.1.4 ! root 369: int floatx80_is_nan( floatx80 );
1.1.1.3 root 370: int floatx80_is_signaling_nan( floatx80 );
1.1.1.4 ! root 371: floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM );
1.1 root 372:
373: INLINE floatx80 floatx80_abs(floatx80 a)
374: {
375: a.high &= 0x7fff;
376: return a;
377: }
378:
379: INLINE floatx80 floatx80_chs(floatx80 a)
380: {
381: a.high ^= 0x8000;
382: return a;
383: }
384:
385: #endif
386:
387: #ifdef FLOAT128
388:
389: /*----------------------------------------------------------------------------
390: | Software IEC/IEEE quadruple-precision conversion routines.
391: *----------------------------------------------------------------------------*/
392: int float128_to_int32( float128 STATUS_PARAM );
393: int float128_to_int32_round_to_zero( float128 STATUS_PARAM );
394: int64_t float128_to_int64( float128 STATUS_PARAM );
395: int64_t float128_to_int64_round_to_zero( float128 STATUS_PARAM );
396: float32 float128_to_float32( float128 STATUS_PARAM );
397: float64 float128_to_float64( float128 STATUS_PARAM );
398: #ifdef FLOATX80
399: floatx80 float128_to_floatx80( float128 STATUS_PARAM );
400: #endif
401:
402: /*----------------------------------------------------------------------------
403: | Software IEC/IEEE quadruple-precision operations.
404: *----------------------------------------------------------------------------*/
405: float128 float128_round_to_int( float128 STATUS_PARAM );
406: float128 float128_add( float128, float128 STATUS_PARAM );
407: float128 float128_sub( float128, float128 STATUS_PARAM );
408: float128 float128_mul( float128, float128 STATUS_PARAM );
409: float128 float128_div( float128, float128 STATUS_PARAM );
410: float128 float128_rem( float128, float128 STATUS_PARAM );
411: float128 float128_sqrt( float128 STATUS_PARAM );
1.1.1.3 root 412: int float128_eq( float128, float128 STATUS_PARAM );
413: int float128_le( float128, float128 STATUS_PARAM );
414: int float128_lt( float128, float128 STATUS_PARAM );
415: int float128_eq_signaling( float128, float128 STATUS_PARAM );
416: int float128_le_quiet( float128, float128 STATUS_PARAM );
417: int float128_lt_quiet( float128, float128 STATUS_PARAM );
1.1.1.4 ! root 418: int float128_compare( float128, float128 STATUS_PARAM );
! 419: int float128_compare_quiet( float128, float128 STATUS_PARAM );
! 420: int float128_is_nan( float128 );
1.1.1.3 root 421: int float128_is_signaling_nan( float128 );
1.1.1.4 ! root 422: float128 float128_scalbn( float128, int STATUS_PARAM );
1.1 root 423:
424: INLINE float128 float128_abs(float128 a)
425: {
426: a.high &= 0x7fffffffffffffffLL;
427: return a;
428: }
429:
430: INLINE float128 float128_chs(float128 a)
431: {
432: a.high ^= 0x8000000000000000LL;
433: return a;
434: }
435:
436: #endif
437:
438: #else /* CONFIG_SOFTFLOAT */
439:
440: #include "softfloat-native.h"
441:
442: #endif /* !CONFIG_SOFTFLOAT */
443:
444: #endif /* !SOFTFLOAT_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.