Commit 1d6bda356153c82e100680d9f2165e32c8fb1330
1 parent
53cd6637
added abs, chs and compare functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1338 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
204 additions
and
0 deletions
fpu/softfloat.c
| ... | ... | @@ -54,6 +54,11 @@ void set_float_rounding_mode(int val STATUS_PARAM) |
| 54 | 54 | STATUS(float_rounding_mode) = val; |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | +void set_float_exception_flags(int val STATUS_PARAM) | |
| 58 | +{ | |
| 59 | + STATUS(float_exception_flags) = val; | |
| 60 | +} | |
| 61 | + | |
| 57 | 62 | #ifdef FLOATX80 |
| 58 | 63 | void set_floatx80_rounding_precision(int val STATUS_PARAM) |
| 59 | 64 | { |
| ... | ... | @@ -5183,3 +5188,133 @@ flag float128_lt_quiet( float128 a, float128 b STATUS_PARAM ) |
| 5183 | 5188 | |
| 5184 | 5189 | #endif |
| 5185 | 5190 | |
| 5191 | +/* misc functions */ | |
| 5192 | +float32 uint32_to_float32( unsigned int a STATUS_PARAM ) | |
| 5193 | +{ | |
| 5194 | + return int64_to_float32(a STATUS_VAR); | |
| 5195 | +} | |
| 5196 | + | |
| 5197 | +float64 uint32_to_float64( unsigned int a STATUS_PARAM ) | |
| 5198 | +{ | |
| 5199 | + return int64_to_float64(a STATUS_VAR); | |
| 5200 | +} | |
| 5201 | + | |
| 5202 | +unsigned int float32_to_uint32( float32 a STATUS_PARAM ) | |
| 5203 | +{ | |
| 5204 | + int64_t v; | |
| 5205 | + unsigned int res; | |
| 5206 | + | |
| 5207 | + v = float32_to_int64(a STATUS_VAR); | |
| 5208 | + if (v < 0) { | |
| 5209 | + res = 0; | |
| 5210 | + float_raise( float_flag_invalid STATUS_VAR); | |
| 5211 | + } else if (v > 0xffffffff) { | |
| 5212 | + res = 0xffffffff; | |
| 5213 | + float_raise( float_flag_invalid STATUS_VAR); | |
| 5214 | + } else { | |
| 5215 | + res = v; | |
| 5216 | + } | |
| 5217 | + return res; | |
| 5218 | +} | |
| 5219 | + | |
| 5220 | +unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM ) | |
| 5221 | +{ | |
| 5222 | + int64_t v; | |
| 5223 | + unsigned int res; | |
| 5224 | + | |
| 5225 | + v = float32_to_int64_round_to_zero(a STATUS_VAR); | |
| 5226 | + if (v < 0) { | |
| 5227 | + res = 0; | |
| 5228 | + float_raise( float_flag_invalid STATUS_VAR); | |
| 5229 | + } else if (v > 0xffffffff) { | |
| 5230 | + res = 0xffffffff; | |
| 5231 | + float_raise( float_flag_invalid STATUS_VAR); | |
| 5232 | + } else { | |
| 5233 | + res = v; | |
| 5234 | + } | |
| 5235 | + return res; | |
| 5236 | +} | |
| 5237 | + | |
| 5238 | +unsigned int float64_to_uint32( float64 a STATUS_PARAM ) | |
| 5239 | +{ | |
| 5240 | + int64_t v; | |
| 5241 | + unsigned int res; | |
| 5242 | + | |
| 5243 | + v = float64_to_int64(a STATUS_VAR); | |
| 5244 | + if (v < 0) { | |
| 5245 | + res = 0; | |
| 5246 | + float_raise( float_flag_invalid STATUS_VAR); | |
| 5247 | + } else if (v > 0xffffffff) { | |
| 5248 | + res = 0xffffffff; | |
| 5249 | + float_raise( float_flag_invalid STATUS_VAR); | |
| 5250 | + } else { | |
| 5251 | + res = v; | |
| 5252 | + } | |
| 5253 | + return res; | |
| 5254 | +} | |
| 5255 | + | |
| 5256 | +unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM ) | |
| 5257 | +{ | |
| 5258 | + int64_t v; | |
| 5259 | + unsigned int res; | |
| 5260 | + | |
| 5261 | + v = float64_to_int64_round_to_zero(a STATUS_VAR); | |
| 5262 | + if (v < 0) { | |
| 5263 | + res = 0; | |
| 5264 | + float_raise( float_flag_invalid STATUS_VAR); | |
| 5265 | + } else if (v > 0xffffffff) { | |
| 5266 | + res = 0xffffffff; | |
| 5267 | + float_raise( float_flag_invalid STATUS_VAR); | |
| 5268 | + } else { | |
| 5269 | + res = v; | |
| 5270 | + } | |
| 5271 | + return res; | |
| 5272 | +} | |
| 5273 | + | |
| 5274 | +#define COMPARE(s, nan_exp) \ | |
| 5275 | +INLINE char float ## s ## _compare_internal( float ## s a, float ## s b, \ | |
| 5276 | + int is_quiet STATUS_PARAM ) \ | |
| 5277 | +{ \ | |
| 5278 | + flag aSign, bSign; \ | |
| 5279 | + \ | |
| 5280 | + if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \ | |
| 5281 | + extractFloat ## s ## Frac( a ) ) || \ | |
| 5282 | + ( ( extractFloat ## s ## Exp( b ) == nan_exp ) && \ | |
| 5283 | + extractFloat ## s ## Frac( b ) )) { \ | |
| 5284 | + if (!is_quiet || \ | |
| 5285 | + float ## s ## _is_signaling_nan( a ) || \ | |
| 5286 | + float ## s ## _is_signaling_nan( b ) ) { \ | |
| 5287 | + float_raise( float_flag_invalid STATUS_VAR); \ | |
| 5288 | + } \ | |
| 5289 | + return float_relation_unordered; \ | |
| 5290 | + } \ | |
| 5291 | + aSign = extractFloat ## s ## Sign( a ); \ | |
| 5292 | + bSign = extractFloat ## s ## Sign( b ); \ | |
| 5293 | + if ( aSign != bSign ) { \ | |
| 5294 | + if ( (bits ## s) ( ( a | b )<<1 ) == 0 ) { \ | |
| 5295 | + /* zero case */ \ | |
| 5296 | + return float_relation_equal; \ | |
| 5297 | + } else { \ | |
| 5298 | + return 1 - (2 * aSign); \ | |
| 5299 | + } \ | |
| 5300 | + } else { \ | |
| 5301 | + if (a == b) { \ | |
| 5302 | + return float_relation_equal; \ | |
| 5303 | + } else { \ | |
| 5304 | + return 1 - 2 * (aSign ^ ( a < b )); \ | |
| 5305 | + } \ | |
| 5306 | + } \ | |
| 5307 | +} \ | |
| 5308 | + \ | |
| 5309 | +char float ## s ## _compare( float ## s a, float ## s b STATUS_PARAM ) \ | |
| 5310 | +{ \ | |
| 5311 | + return float ## s ## _compare_internal(a, b, 0 STATUS_VAR); \ | |
| 5312 | +} \ | |
| 5313 | + \ | |
| 5314 | +char float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \ | |
| 5315 | +{ \ | |
| 5316 | + return float ## s ## _compare_internal(a, b, 1 STATUS_VAR); \ | |
| 5317 | +} | |
| 5318 | + | |
| 5319 | +COMPARE(32, 0xff) | |
| 5320 | +COMPARE(64, 0x7ff) | ... | ... |
fpu/softfloat.h
| ... | ... | @@ -93,6 +93,16 @@ typedef int64_t sbits64; |
| 93 | 93 | #define STATUS(field) status->field |
| 94 | 94 | #define STATUS_VAR , status |
| 95 | 95 | |
| 96 | +/*---------------------------------------------------------------------------- | |
| 97 | +| Software IEC/IEEE floating-point ordering relations | |
| 98 | +*----------------------------------------------------------------------------*/ | |
| 99 | +enum { | |
| 100 | + float_relation_less = -1, | |
| 101 | + float_relation_equal = 0, | |
| 102 | + float_relation_greater = 1, | |
| 103 | + float_relation_unordered = 2 | |
| 104 | +}; | |
| 105 | + | |
| 96 | 106 | #ifdef CONFIG_SOFTFLOAT |
| 97 | 107 | /*---------------------------------------------------------------------------- |
| 98 | 108 | | Software IEC/IEEE floating-point types. |
| ... | ... | @@ -154,6 +164,11 @@ typedef struct float_status { |
| 154 | 164 | } float_status; |
| 155 | 165 | |
| 156 | 166 | void set_float_rounding_mode(int val STATUS_PARAM); |
| 167 | +void set_float_exception_flags(int val STATUS_PARAM); | |
| 168 | +INLINE int get_float_exception_flags(float_status *status) | |
| 169 | +{ | |
| 170 | + return STATUS(float_exception_flags); | |
| 171 | +} | |
| 157 | 172 | #ifdef FLOATX80 |
| 158 | 173 | void set_floatx80_rounding_precision(int val STATUS_PARAM); |
| 159 | 174 | #endif |
| ... | ... | @@ -169,6 +184,8 @@ void float_raise( signed char STATUS_PARAM); |
| 169 | 184 | *----------------------------------------------------------------------------*/ |
| 170 | 185 | float32 int32_to_float32( int STATUS_PARAM ); |
| 171 | 186 | float64 int32_to_float64( int STATUS_PARAM ); |
| 187 | +float32 uint32_to_float32( unsigned int STATUS_PARAM ); | |
| 188 | +float64 uint32_to_float64( unsigned int STATUS_PARAM ); | |
| 172 | 189 | #ifdef FLOATX80 |
| 173 | 190 | floatx80 int32_to_floatx80( int STATUS_PARAM ); |
| 174 | 191 | #endif |
| ... | ... | @@ -189,6 +206,8 @@ float128 int64_to_float128( int64_t STATUS_PARAM ); |
| 189 | 206 | *----------------------------------------------------------------------------*/ |
| 190 | 207 | int float32_to_int32( float32 STATUS_PARAM ); |
| 191 | 208 | int float32_to_int32_round_to_zero( float32 STATUS_PARAM ); |
| 209 | +unsigned int float32_to_uint32( float32 STATUS_PARAM ); | |
| 210 | +unsigned int float32_to_uint32_round_to_zero( float32 STATUS_PARAM ); | |
| 192 | 211 | int64_t float32_to_int64( float32 STATUS_PARAM ); |
| 193 | 212 | int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM ); |
| 194 | 213 | float64 float32_to_float64( float32 STATUS_PARAM ); |
| ... | ... | @@ -215,13 +234,27 @@ char float32_lt( float32, float32 STATUS_PARAM ); |
| 215 | 234 | char float32_eq_signaling( float32, float32 STATUS_PARAM ); |
| 216 | 235 | char float32_le_quiet( float32, float32 STATUS_PARAM ); |
| 217 | 236 | char float32_lt_quiet( float32, float32 STATUS_PARAM ); |
| 237 | +char float32_compare( float32, float32 STATUS_PARAM ); | |
| 238 | +char float32_compare_quiet( float32, float32 STATUS_PARAM ); | |
| 218 | 239 | char float32_is_signaling_nan( float32 ); |
| 219 | 240 | |
| 241 | +INLINE float32 float32_abs(float32 a) | |
| 242 | +{ | |
| 243 | + return a & 0x7fffffff; | |
| 244 | +} | |
| 245 | + | |
| 246 | +INLINE float32 float32_chs(float32 a) | |
| 247 | +{ | |
| 248 | + return a ^ 0x80000000; | |
| 249 | +} | |
| 250 | + | |
| 220 | 251 | /*---------------------------------------------------------------------------- |
| 221 | 252 | | Software IEC/IEEE double-precision conversion routines. |
| 222 | 253 | *----------------------------------------------------------------------------*/ |
| 223 | 254 | int float64_to_int32( float64 STATUS_PARAM ); |
| 224 | 255 | int float64_to_int32_round_to_zero( float64 STATUS_PARAM ); |
| 256 | +unsigned int float64_to_uint32( float64 STATUS_PARAM ); | |
| 257 | +unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM ); | |
| 225 | 258 | int64_t float64_to_int64( float64 STATUS_PARAM ); |
| 226 | 259 | int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM ); |
| 227 | 260 | float32 float64_to_float32( float64 STATUS_PARAM ); |
| ... | ... | @@ -248,8 +281,20 @@ char float64_lt( float64, float64 STATUS_PARAM ); |
| 248 | 281 | char float64_eq_signaling( float64, float64 STATUS_PARAM ); |
| 249 | 282 | char float64_le_quiet( float64, float64 STATUS_PARAM ); |
| 250 | 283 | char float64_lt_quiet( float64, float64 STATUS_PARAM ); |
| 284 | +char float64_compare( float64, float64 STATUS_PARAM ); | |
| 285 | +char float64_compare_quiet( float64, float64 STATUS_PARAM ); | |
| 251 | 286 | char float64_is_signaling_nan( float64 ); |
| 252 | 287 | |
| 288 | +INLINE float64 float64_abs(float64 a) | |
| 289 | +{ | |
| 290 | + return a & 0x7fffffffffffffffLL; | |
| 291 | +} | |
| 292 | + | |
| 293 | +INLINE float64 float64_chs(float64 a) | |
| 294 | +{ | |
| 295 | + return a ^ 0x8000000000000000LL; | |
| 296 | +} | |
| 297 | + | |
| 253 | 298 | #ifdef FLOATX80 |
| 254 | 299 | |
| 255 | 300 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -283,6 +328,18 @@ char floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM ); |
| 283 | 328 | char floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM ); |
| 284 | 329 | char floatx80_is_signaling_nan( floatx80 ); |
| 285 | 330 | |
| 331 | +INLINE floatx80 floatx80_abs(floatx80 a) | |
| 332 | +{ | |
| 333 | + a.high &= 0x7fff; | |
| 334 | + return a; | |
| 335 | +} | |
| 336 | + | |
| 337 | +INLINE floatx80 floatx80_chs(floatx80 a) | |
| 338 | +{ | |
| 339 | + a.high ^= 0x8000; | |
| 340 | + return a; | |
| 341 | +} | |
| 342 | + | |
| 286 | 343 | #endif |
| 287 | 344 | |
| 288 | 345 | #ifdef FLOAT128 |
| ... | ... | @@ -318,6 +375,18 @@ char float128_le_quiet( float128, float128 STATUS_PARAM ); |
| 318 | 375 | char float128_lt_quiet( float128, float128 STATUS_PARAM ); |
| 319 | 376 | char float128_is_signaling_nan( float128 ); |
| 320 | 377 | |
| 378 | +INLINE float128 float128_abs(float128 a) | |
| 379 | +{ | |
| 380 | + a.high &= 0x7fffffffffffffffLL; | |
| 381 | + return a; | |
| 382 | +} | |
| 383 | + | |
| 384 | +INLINE float128 float128_chs(float128 a) | |
| 385 | +{ | |
| 386 | + a.high ^= 0x8000000000000000LL; | |
| 387 | + return a; | |
| 388 | +} | |
| 389 | + | |
| 321 | 390 | #endif |
| 322 | 391 | |
| 323 | 392 | #else /* CONFIG_SOFTFLOAT */ | ... | ... |