diff options
| author | Thomas Preud'homme <robotux@celest.fr> | 2014-02-05 19:47:15 +0800 |
|---|---|---|
| committer | Thomas Preud'homme <robotux@celest.fr> | 2014-02-05 20:56:36 +0800 |
| commit | 88c9f1bb4e64d9dab658061b058b8bedc2c66ac5 (patch) | |
| tree | 276052c2e667df9b65c2e01ea5ad5b0c3a3dc4da | |
| parent | d0295074941816351c15fe3d4326b5e98364ff9c (diff) | |
| download | tinycc-88c9f1bb4e64d9dab658061b058b8bedc2c66ac5.tar.gz tinycc-88c9f1bb4e64d9dab658061b058b8bedc2c66ac5.tar.bz2 | |
Round mode of ll -> float conversion to nearest
Change rounding mode of long long to float conversion to nearest in
libtcc1.
| -rw-r--r-- | lib/armeabi.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/lib/armeabi.c b/lib/armeabi.c index bf5e07a..ce5e232 100644 --- a/lib/armeabi.c +++ b/lib/armeabi.c @@ -170,7 +170,7 @@ DEFINE__AEABI_D2XLZ(d2lz, 1) #define DEFINE__AEABI_XL2F(name, with_sign) \ unsigned __aeabi_ ## name(unsigned long long v) \ { \ - int s /* shift */, sign = 0; \ + int s /* shift */, flb /* first lost bit */, sign = 0; \ unsigned p = 0 /* power */, ret; \ double_unsigned_struct val; \ \ @@ -188,20 +188,28 @@ unsigned __aeabi_ ## name(unsigned long long v) \ if (s < FLOAT_FRAC_BITS) { \ ret <<= FLOAT_FRAC_BITS - s; \ ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \ - } else \ + flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \ + } else { \ + flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \ ret >>= s - FLOAT_FRAC_BITS; \ + } \ s += 32; \ } else { \ for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \ if (p) { \ ret = val.low & (p - 1); \ - if (s <= FLOAT_FRAC_BITS) \ + if (s <= FLOAT_FRAC_BITS) { \ ret <<= FLOAT_FRAC_BITS - s; \ - else \ + flb = 0; \ + } else { \ + flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \ ret >>= s - FLOAT_FRAC_BITS; \ + } \ } else \ return 0; \ } \ + if (flb) \ + ret++; \ \ /* fill exponent bits */ \ ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \ @@ -222,7 +230,7 @@ DEFINE__AEABI_XL2F(l2f, 1) #define __AEABI_XL2D(name, with_sign) \ void __aeabi_ ## name(unsigned long long v) \ { \ - int s, high_shift, sign = 0; \ + int s /* shift */, high_shift, sign = 0; \ unsigned tmp, p = 0; \ double_unsigned_struct val, ret; \ \ @@ -248,6 +256,13 @@ void __aeabi_ ## name(unsigned long long v) \ ret.high = tmp >> high_shift; \ ret.low = tmp << (32 - high_shift); \ ret.low |= val.low >> high_shift; \ + if ((val.low >> (high_shift - 1)) & 1) { \ + if (ret.low == UINT_MAX) { \ + ret.high++; \ + ret.low = 0; \ + } else \ + ret.low++; \ + } \ } \ s += 32; \ } else { \ |
