From a24e31e85d2980bf4863ad3dd371c6501810ae97 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sun, 15 Dec 2013 09:44:20 +0800 Subject: [PATCH] Fix signed integer division in ARM runtime ABI - fix computation of absolute value (clearing the sign bit does not since integers are encoded in 2's complement) - test sign of integer in a more conventional way (binary and with the high bit does not work for long long due to a bug in gtst) - spacing in include --- lib/armeabi.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/armeabi.c b/lib/armeabi.c index c00ace6..e787ec1 100644 --- a/lib/armeabi.c +++ b/lib/armeabi.c @@ -1,4 +1,4 @@ -#include +#include /* We rely on the little endianness and EABI calling convention for this to work */ @@ -325,22 +325,28 @@ static inline rettype aeabi_ ## name (type num, type den) \ } #define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \ -void __aeabi_ ## name(type numerator, type denominator) \ +void __aeabi_ ## name(type numerator, type denominator) \ { \ unsigned type num, den; \ urettype uxdiv_ret; \ rettype ret; \ \ - num = numerator & typemacro ## _MAX; \ - den = denominator & typemacro ## _MAX; \ + if (numerator >= 0) \ + num = numerator; \ + else \ + num = 0 - numerator; \ + if (denominator >= 0) \ + den = denominator; \ + else \ + den = 0 - denominator; \ uxdiv_ret = aeabi_ ## uiname(num, den); \ /* signs differ */ \ if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \ - ret.quot = uxdiv_ret.quot * -1; \ + ret.quot = 0 - uxdiv_ret.quot; \ else \ ret.quot = uxdiv_ret.quot; \ - if (numerator & typemacro ## _MIN) \ - ret.rem = uxdiv_ret.rem * -1; \ + if (numerator < 0) \ + ret.rem = 0 - uxdiv_ret.rem; \ else \ ret.rem = uxdiv_ret.rem; \ \ @@ -420,8 +426,14 @@ int __aeabi_idiv(int numerator, int denominator) unsigned num, den; uidiv_t ret; - num = numerator & INT_MAX; - den = denominator & INT_MAX; + if (numerator >= 0) + num = numerator; + else + num = 0 - numerator; + if (denominator >= 0) + den = denominator; + else + den = 0 - denominator; ret = aeabi_uidivmod(num, den); if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */ ret.quot *= -1;