| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 |  | 
|  | 2 | /* | 
|  | 3 | =============================================================================== | 
|  | 4 |  | 
|  | 5 | This C header file 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 | #ifndef __SOFTFLOAT_H__ | 
|  | 33 | #define __SOFTFLOAT_H__ | 
|  | 34 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 35 |  | 
|  | 36 | /* | 
|  | 37 | ------------------------------------------------------------------------------- | 
|  | 38 | The macro `FLOATX80' must be defined to enable the extended double-precision | 
|  | 39 | floating-point format `floatx80'.  If this macro is not defined, the | 
|  | 40 | `floatx80' type will not be defined, and none of the functions that either | 
|  | 41 | input or output the `floatx80' type will be defined. | 
|  | 42 | ------------------------------------------------------------------------------- | 
|  | 43 | */ | 
|  | 44 | #ifdef CONFIG_FPE_NWFPE_XP | 
|  | 45 | #define FLOATX80 | 
|  | 46 | #endif | 
|  | 47 |  | 
|  | 48 | /* | 
|  | 49 | ------------------------------------------------------------------------------- | 
|  | 50 | Software IEC/IEEE floating-point types. | 
|  | 51 | ------------------------------------------------------------------------------- | 
|  | 52 | */ | 
| Lennert Buytenhek | bedf142 | 2005-11-07 21:12:08 +0000 | [diff] [blame] | 53 | typedef u32 float32; | 
|  | 54 | typedef u64 float64; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 55 | typedef struct { | 
| Lennert Buytenhek | bedf142 | 2005-11-07 21:12:08 +0000 | [diff] [blame] | 56 | #ifdef __ARMEB__ | 
|  | 57 | u16 __padding; | 
|  | 58 | u16 high; | 
|  | 59 | #else | 
|  | 60 | u16 high; | 
|  | 61 | u16 __padding; | 
|  | 62 | #endif | 
|  | 63 | u64 low; | 
| Koen Kooi | a9da396 | 2006-07-13 13:04:24 +0100 | [diff] [blame] | 64 | }  __attribute__ ((packed,aligned(4))) floatx80; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 65 |  | 
|  | 66 | /* | 
|  | 67 | ------------------------------------------------------------------------------- | 
|  | 68 | Software IEC/IEEE floating-point underflow tininess-detection mode. | 
|  | 69 | ------------------------------------------------------------------------------- | 
|  | 70 | */ | 
|  | 71 | extern signed char float_detect_tininess; | 
|  | 72 | enum { | 
|  | 73 | float_tininess_after_rounding  = 0, | 
|  | 74 | float_tininess_before_rounding = 1 | 
|  | 75 | }; | 
|  | 76 |  | 
|  | 77 | /* | 
|  | 78 | ------------------------------------------------------------------------------- | 
|  | 79 | Software IEC/IEEE floating-point rounding mode. | 
|  | 80 | ------------------------------------------------------------------------------- | 
|  | 81 | */ | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 82 | //extern int8 float_rounding_mode; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 83 | enum { | 
|  | 84 | float_round_nearest_even = 0, | 
|  | 85 | float_round_to_zero      = 1, | 
|  | 86 | float_round_down         = 2, | 
|  | 87 | float_round_up           = 3 | 
|  | 88 | }; | 
|  | 89 |  | 
|  | 90 | /* | 
|  | 91 | ------------------------------------------------------------------------------- | 
|  | 92 | Software IEC/IEEE floating-point exception flags. | 
|  | 93 | ------------------------------------------------------------------------------- | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 94 | enum { | 
|  | 95 | float_flag_inexact   =  1, | 
|  | 96 | float_flag_underflow =  2, | 
|  | 97 | float_flag_overflow  =  4, | 
|  | 98 | float_flag_divbyzero =  8, | 
|  | 99 | float_flag_invalid   = 16 | 
|  | 100 | }; | 
|  | 101 |  | 
|  | 102 | ScottB: November 4, 1998 | 
|  | 103 | Changed the enumeration to match the bit order in the FPA11. | 
|  | 104 | */ | 
|  | 105 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 106 | enum { | 
|  | 107 | float_flag_invalid   =  1, | 
|  | 108 | float_flag_divbyzero =  2, | 
|  | 109 | float_flag_overflow  =  4, | 
|  | 110 | float_flag_underflow =  8, | 
|  | 111 | float_flag_inexact   = 16 | 
|  | 112 | }; | 
|  | 113 |  | 
|  | 114 | /* | 
|  | 115 | ------------------------------------------------------------------------------- | 
|  | 116 | Routine to raise any or all of the software IEC/IEEE floating-point | 
|  | 117 | exception flags. | 
|  | 118 | ------------------------------------------------------------------------------- | 
|  | 119 | */ | 
|  | 120 | void float_raise( signed char ); | 
|  | 121 |  | 
|  | 122 | /* | 
|  | 123 | ------------------------------------------------------------------------------- | 
|  | 124 | Software IEC/IEEE integer-to-floating-point conversion routines. | 
|  | 125 | ------------------------------------------------------------------------------- | 
|  | 126 | */ | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 127 | float32 int32_to_float32( struct roundingData *, signed int ); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 128 | float64 int32_to_float64( signed int ); | 
|  | 129 | #ifdef FLOATX80 | 
|  | 130 | floatx80 int32_to_floatx80( signed int ); | 
|  | 131 | #endif | 
|  | 132 |  | 
|  | 133 | /* | 
|  | 134 | ------------------------------------------------------------------------------- | 
|  | 135 | Software IEC/IEEE single-precision conversion routines. | 
|  | 136 | ------------------------------------------------------------------------------- | 
|  | 137 | */ | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 138 | signed int float32_to_int32( struct roundingData *, float32 ); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 139 | signed int float32_to_int32_round_to_zero( float32 ); | 
|  | 140 | float64 float32_to_float64( float32 ); | 
|  | 141 | #ifdef FLOATX80 | 
|  | 142 | floatx80 float32_to_floatx80( float32 ); | 
|  | 143 | #endif | 
|  | 144 |  | 
|  | 145 | /* | 
|  | 146 | ------------------------------------------------------------------------------- | 
|  | 147 | Software IEC/IEEE single-precision operations. | 
|  | 148 | ------------------------------------------------------------------------------- | 
|  | 149 | */ | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 150 | float32 float32_round_to_int( struct roundingData*, float32 ); | 
|  | 151 | float32 float32_add( struct roundingData *, float32, float32 ); | 
|  | 152 | float32 float32_sub( struct roundingData *, float32, float32 ); | 
|  | 153 | float32 float32_mul( struct roundingData *, float32, float32 ); | 
|  | 154 | float32 float32_div( struct roundingData *, float32, float32 ); | 
|  | 155 | float32 float32_rem( struct roundingData *, float32, float32 ); | 
|  | 156 | float32 float32_sqrt( struct roundingData*, float32 ); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 157 | char float32_eq( float32, float32 ); | 
|  | 158 | char float32_le( float32, float32 ); | 
|  | 159 | char float32_lt( float32, float32 ); | 
|  | 160 | char float32_eq_signaling( float32, float32 ); | 
|  | 161 | char float32_le_quiet( float32, float32 ); | 
|  | 162 | char float32_lt_quiet( float32, float32 ); | 
|  | 163 | char float32_is_signaling_nan( float32 ); | 
|  | 164 |  | 
|  | 165 | /* | 
|  | 166 | ------------------------------------------------------------------------------- | 
|  | 167 | Software IEC/IEEE double-precision conversion routines. | 
|  | 168 | ------------------------------------------------------------------------------- | 
|  | 169 | */ | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 170 | signed int float64_to_int32( struct roundingData *, float64 ); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 171 | signed int float64_to_int32_round_to_zero( float64 ); | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 172 | float32 float64_to_float32( struct roundingData *, float64 ); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 173 | #ifdef FLOATX80 | 
|  | 174 | floatx80 float64_to_floatx80( float64 ); | 
|  | 175 | #endif | 
|  | 176 |  | 
|  | 177 | /* | 
|  | 178 | ------------------------------------------------------------------------------- | 
|  | 179 | Software IEC/IEEE double-precision operations. | 
|  | 180 | ------------------------------------------------------------------------------- | 
|  | 181 | */ | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 182 | float64 float64_round_to_int( struct roundingData *, float64 ); | 
|  | 183 | float64 float64_add( struct roundingData *, float64, float64 ); | 
|  | 184 | float64 float64_sub( struct roundingData *, float64, float64 ); | 
|  | 185 | float64 float64_mul( struct roundingData *, float64, float64 ); | 
|  | 186 | float64 float64_div( struct roundingData *, float64, float64 ); | 
|  | 187 | float64 float64_rem( struct roundingData *, float64, float64 ); | 
|  | 188 | float64 float64_sqrt( struct roundingData *, float64 ); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 189 | char float64_eq( float64, float64 ); | 
|  | 190 | char float64_le( float64, float64 ); | 
|  | 191 | char float64_lt( float64, float64 ); | 
|  | 192 | char float64_eq_signaling( float64, float64 ); | 
|  | 193 | char float64_le_quiet( float64, float64 ); | 
|  | 194 | char float64_lt_quiet( float64, float64 ); | 
|  | 195 | char float64_is_signaling_nan( float64 ); | 
|  | 196 |  | 
|  | 197 | #ifdef FLOATX80 | 
|  | 198 |  | 
|  | 199 | /* | 
|  | 200 | ------------------------------------------------------------------------------- | 
|  | 201 | Software IEC/IEEE extended double-precision conversion routines. | 
|  | 202 | ------------------------------------------------------------------------------- | 
|  | 203 | */ | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 204 | signed int floatx80_to_int32( struct roundingData *, floatx80 ); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 205 | signed int floatx80_to_int32_round_to_zero( floatx80 ); | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 206 | float32 floatx80_to_float32( struct roundingData *, floatx80 ); | 
|  | 207 | float64 floatx80_to_float64( struct roundingData *, floatx80 ); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 208 |  | 
|  | 209 | /* | 
|  | 210 | ------------------------------------------------------------------------------- | 
|  | 211 | Software IEC/IEEE extended double-precision operations. | 
|  | 212 | ------------------------------------------------------------------------------- | 
|  | 213 | */ | 
| Richard Purdie | f148af2 | 2005-08-03 19:49:17 +0100 | [diff] [blame] | 214 | floatx80 floatx80_round_to_int( struct roundingData *, floatx80 ); | 
|  | 215 | floatx80 floatx80_add( struct roundingData *, floatx80, floatx80 ); | 
|  | 216 | floatx80 floatx80_sub( struct roundingData *, floatx80, floatx80 ); | 
|  | 217 | floatx80 floatx80_mul( struct roundingData *, floatx80, floatx80 ); | 
|  | 218 | floatx80 floatx80_div( struct roundingData *, floatx80, floatx80 ); | 
|  | 219 | floatx80 floatx80_rem( struct roundingData *, floatx80, floatx80 ); | 
|  | 220 | floatx80 floatx80_sqrt( struct roundingData *, floatx80 ); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 221 | char floatx80_eq( floatx80, floatx80 ); | 
|  | 222 | char floatx80_le( floatx80, floatx80 ); | 
|  | 223 | char floatx80_lt( floatx80, floatx80 ); | 
|  | 224 | char floatx80_eq_signaling( floatx80, floatx80 ); | 
|  | 225 | char floatx80_le_quiet( floatx80, floatx80 ); | 
|  | 226 | char floatx80_lt_quiet( floatx80, floatx80 ); | 
|  | 227 | char floatx80_is_signaling_nan( floatx80 ); | 
|  | 228 |  | 
|  | 229 | #endif | 
|  | 230 |  | 
|  | 231 | static inline flag extractFloat32Sign(float32 a) | 
|  | 232 | { | 
|  | 233 | return a >> 31; | 
|  | 234 | } | 
|  | 235 |  | 
|  | 236 | static inline flag float32_eq_nocheck(float32 a, float32 b) | 
|  | 237 | { | 
|  | 238 | return (a == b) || ((bits32) ((a | b) << 1) == 0); | 
|  | 239 | } | 
|  | 240 |  | 
|  | 241 | static inline flag float32_lt_nocheck(float32 a, float32 b) | 
|  | 242 | { | 
|  | 243 | flag aSign, bSign; | 
|  | 244 |  | 
|  | 245 | aSign = extractFloat32Sign(a); | 
|  | 246 | bSign = extractFloat32Sign(b); | 
|  | 247 | if (aSign != bSign) | 
|  | 248 | return aSign && ((bits32) ((a | b) << 1) != 0); | 
|  | 249 | return (a != b) && (aSign ^ (a < b)); | 
|  | 250 | } | 
|  | 251 |  | 
|  | 252 | static inline flag extractFloat64Sign(float64 a) | 
|  | 253 | { | 
|  | 254 | return a >> 63; | 
|  | 255 | } | 
|  | 256 |  | 
|  | 257 | static inline flag float64_eq_nocheck(float64 a, float64 b) | 
|  | 258 | { | 
|  | 259 | return (a == b) || ((bits64) ((a | b) << 1) == 0); | 
|  | 260 | } | 
|  | 261 |  | 
|  | 262 | static inline flag float64_lt_nocheck(float64 a, float64 b) | 
|  | 263 | { | 
|  | 264 | flag aSign, bSign; | 
|  | 265 |  | 
|  | 266 | aSign = extractFloat64Sign(a); | 
|  | 267 | bSign = extractFloat64Sign(b); | 
|  | 268 | if (aSign != bSign) | 
|  | 269 | return aSign && ((bits64) ((a | b) << 1) != 0); | 
|  | 270 | return (a != b) && (aSign ^ (a < b)); | 
|  | 271 | } | 
|  | 272 |  | 
| Ben Dooks | 6ec5e7f | 2005-10-12 19:58:10 +0100 | [diff] [blame] | 273 | extern flag float32_is_nan( float32 a ); | 
|  | 274 | extern flag float64_is_nan( float64 a ); | 
|  | 275 |  | 
| Ben Dooks | 1ff0828 | 2007-05-28 19:03:47 +0100 | [diff] [blame] | 276 | extern int32 float64_to_uint32( struct roundingData *roundData, float64 a ); | 
|  | 277 | extern int32 float64_to_uint32_round_to_zero( float64 a ); | 
|  | 278 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 279 | #endif |