From: Ard Biesheuvel Date: Thu, 17 Jan 2013 16:51:12 +0000 (+0100) Subject: Added ARM accelerated implementations for ZEND_SIGNED_MULTIPLY_LONG() X-Git-Tag: php-5.6.0alpha1~582^2~27^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0b8ec19629083de65310f0a136320e8e79a1c8ef;p=php Added ARM accelerated implementations for ZEND_SIGNED_MULTIPLY_LONG() Added inline assembler implementations: - for 32-bit ARM, as the existing C implementation uses 64-bit integer arithmetic, which relies on software emulation by libgcc; - for 64-bit ARM, as the existing C implementation uses long doubles to check for overflow before using the integer result. Also updated my email address and fixed some whitespace --- diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h index c3c9657f3b..e52956f417 100644 --- a/Zend/zend_multiply.h +++ b/Zend/zend_multiply.h @@ -13,7 +13,7 @@ | license@zend.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Sascha Schumann | - | Ard Biesheuvel | + | Ard Biesheuvel | +----------------------------------------------------------------------+ */ @@ -43,6 +43,31 @@ else (lval) = __tmpvar; \ } while (0) +#elif defined(__arm__) && defined(__GNUC__) + +#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ + long __tmpvar; \ + __asm__("smull %0, %1, %2, %3\n" \ + "sub %1, %1, %0, asr #31" \ + : "=r"(__tmpvar), "=r"(usedval) \ + : "r"(a), "r"(b)); \ + if (usedval) (dval) = (double) (a) * (double) (b); \ + else (lval) = __tmpvar; \ +} while (0) + +#elif defined(__aarch64__) && defined(__GNUC__) + +#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ + long __tmpvar; \ + __asm__("mul %0, %2, %3\n" \ + "smulh %1, %2, %3\n" \ + "sub %1, %1, %0, asr #63\n" \ + : "=X"(__tmpvar), "=X"(usedval) \ + : "X"(a), "X"(b)); \ + if (usedval) (dval) = (double) (a) * (double) (b); \ + else (lval) = __tmpvar; \ +} while (0) + #elif SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64) #define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ @@ -58,15 +83,15 @@ #else -#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ - long __lres = (a) * (b); \ - long double __dres = (long double)(a) * (long double)(b); \ - long double __delta = (long double) __lres - __dres; \ - if ( ((usedval) = (( __dres + __delta ) != __dres))) { \ - (dval) = __dres; \ - } else { \ - (lval) = __lres; \ - } \ +#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ + long __lres = (a) * (b); \ + long double __dres = (long double)(a) * (long double)(b); \ + long double __delta = (long double) __lres - __dres; \ + if ( ((usedval) = (( __dres + __delta ) != __dres))) { \ + (dval) = __dres; \ + } else { \ + (lval) = __lres; \ + } \ } while (0) #endif