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,6 +54,11 @@ void set_float_rounding_mode(int val STATUS_PARAM) | ||
54 | STATUS(float_rounding_mode) = val; | 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 | #ifdef FLOATX80 | 62 | #ifdef FLOATX80 |
58 | void set_floatx80_rounding_precision(int val STATUS_PARAM) | 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,3 +5188,133 @@ flag float128_lt_quiet( float128 a, float128 b STATUS_PARAM ) | ||
5183 | 5188 | ||
5184 | #endif | 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,6 +93,16 @@ typedef int64_t sbits64; | ||
93 | #define STATUS(field) status->field | 93 | #define STATUS(field) status->field |
94 | #define STATUS_VAR , status | 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 | #ifdef CONFIG_SOFTFLOAT | 106 | #ifdef CONFIG_SOFTFLOAT |
97 | /*---------------------------------------------------------------------------- | 107 | /*---------------------------------------------------------------------------- |
98 | | Software IEC/IEEE floating-point types. | 108 | | Software IEC/IEEE floating-point types. |
@@ -154,6 +164,11 @@ typedef struct float_status { | @@ -154,6 +164,11 @@ typedef struct float_status { | ||
154 | } float_status; | 164 | } float_status; |
155 | 165 | ||
156 | void set_float_rounding_mode(int val STATUS_PARAM); | 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 | #ifdef FLOATX80 | 172 | #ifdef FLOATX80 |
158 | void set_floatx80_rounding_precision(int val STATUS_PARAM); | 173 | void set_floatx80_rounding_precision(int val STATUS_PARAM); |
159 | #endif | 174 | #endif |
@@ -169,6 +184,8 @@ void float_raise( signed char STATUS_PARAM); | @@ -169,6 +184,8 @@ void float_raise( signed char STATUS_PARAM); | ||
169 | *----------------------------------------------------------------------------*/ | 184 | *----------------------------------------------------------------------------*/ |
170 | float32 int32_to_float32( int STATUS_PARAM ); | 185 | float32 int32_to_float32( int STATUS_PARAM ); |
171 | float64 int32_to_float64( int STATUS_PARAM ); | 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 | #ifdef FLOATX80 | 189 | #ifdef FLOATX80 |
173 | floatx80 int32_to_floatx80( int STATUS_PARAM ); | 190 | floatx80 int32_to_floatx80( int STATUS_PARAM ); |
174 | #endif | 191 | #endif |
@@ -189,6 +206,8 @@ float128 int64_to_float128( int64_t STATUS_PARAM ); | @@ -189,6 +206,8 @@ float128 int64_to_float128( int64_t STATUS_PARAM ); | ||
189 | *----------------------------------------------------------------------------*/ | 206 | *----------------------------------------------------------------------------*/ |
190 | int float32_to_int32( float32 STATUS_PARAM ); | 207 | int float32_to_int32( float32 STATUS_PARAM ); |
191 | int float32_to_int32_round_to_zero( float32 STATUS_PARAM ); | 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 | int64_t float32_to_int64( float32 STATUS_PARAM ); | 211 | int64_t float32_to_int64( float32 STATUS_PARAM ); |
193 | int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM ); | 212 | int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM ); |
194 | float64 float32_to_float64( float32 STATUS_PARAM ); | 213 | float64 float32_to_float64( float32 STATUS_PARAM ); |
@@ -215,13 +234,27 @@ char float32_lt( float32, float32 STATUS_PARAM ); | @@ -215,13 +234,27 @@ char float32_lt( float32, float32 STATUS_PARAM ); | ||
215 | char float32_eq_signaling( float32, float32 STATUS_PARAM ); | 234 | char float32_eq_signaling( float32, float32 STATUS_PARAM ); |
216 | char float32_le_quiet( float32, float32 STATUS_PARAM ); | 235 | char float32_le_quiet( float32, float32 STATUS_PARAM ); |
217 | char float32_lt_quiet( float32, float32 STATUS_PARAM ); | 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 | char float32_is_signaling_nan( float32 ); | 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 | | Software IEC/IEEE double-precision conversion routines. | 252 | | Software IEC/IEEE double-precision conversion routines. |
222 | *----------------------------------------------------------------------------*/ | 253 | *----------------------------------------------------------------------------*/ |
223 | int float64_to_int32( float64 STATUS_PARAM ); | 254 | int float64_to_int32( float64 STATUS_PARAM ); |
224 | int float64_to_int32_round_to_zero( float64 STATUS_PARAM ); | 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 | int64_t float64_to_int64( float64 STATUS_PARAM ); | 258 | int64_t float64_to_int64( float64 STATUS_PARAM ); |
226 | int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM ); | 259 | int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM ); |
227 | float32 float64_to_float32( float64 STATUS_PARAM ); | 260 | float32 float64_to_float32( float64 STATUS_PARAM ); |
@@ -248,8 +281,20 @@ char float64_lt( float64, float64 STATUS_PARAM ); | @@ -248,8 +281,20 @@ char float64_lt( float64, float64 STATUS_PARAM ); | ||
248 | char float64_eq_signaling( float64, float64 STATUS_PARAM ); | 281 | char float64_eq_signaling( float64, float64 STATUS_PARAM ); |
249 | char float64_le_quiet( float64, float64 STATUS_PARAM ); | 282 | char float64_le_quiet( float64, float64 STATUS_PARAM ); |
250 | char float64_lt_quiet( float64, float64 STATUS_PARAM ); | 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 | char float64_is_signaling_nan( float64 ); | 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 | #ifdef FLOATX80 | 298 | #ifdef FLOATX80 |
254 | 299 | ||
255 | /*---------------------------------------------------------------------------- | 300 | /*---------------------------------------------------------------------------- |
@@ -283,6 +328,18 @@ char floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM ); | @@ -283,6 +328,18 @@ char floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM ); | ||
283 | char floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM ); | 328 | char floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM ); |
284 | char floatx80_is_signaling_nan( floatx80 ); | 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 | #endif | 343 | #endif |
287 | 344 | ||
288 | #ifdef FLOAT128 | 345 | #ifdef FLOAT128 |
@@ -318,6 +375,18 @@ char float128_le_quiet( float128, float128 STATUS_PARAM ); | @@ -318,6 +375,18 @@ char float128_le_quiet( float128, float128 STATUS_PARAM ); | ||
318 | char float128_lt_quiet( float128, float128 STATUS_PARAM ); | 375 | char float128_lt_quiet( float128, float128 STATUS_PARAM ); |
319 | char float128_is_signaling_nan( float128 ); | 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 | #endif | 390 | #endif |
322 | 391 | ||
323 | #else /* CONFIG_SOFTFLOAT */ | 392 | #else /* CONFIG_SOFTFLOAT */ |