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 */ | ... | ... |