aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorThomas Preud'homme <robotux@celest.fr>2014-02-05 19:47:15 +0800
committerThomas Preud'homme <robotux@celest.fr>2014-02-05 20:56:36 +0800
commit88c9f1bb4e64d9dab658061b058b8bedc2c66ac5 (patch)
tree276052c2e667df9b65c2e01ea5ad5b0c3a3dc4da /lib
parentd0295074941816351c15fe3d4326b5e98364ff9c (diff)
downloadtinycc-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.
Diffstat (limited to 'lib')
-rw-r--r--lib/armeabi.c25
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 { \