Commit: e2453276e95165bf3b765d27781405c816821c15 Author: Ard Biesheuvel <ard.biesheu...@linaro.org> Mon, 11 Feb 2013 14:36:58 +0100 Parents: aa12cdc361b29b4050676763858b3cfa637be6cb Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=e2453276e95165bf3b765d27781405c816821c15 Log: Low-level ARM optimizations - added ARM versions of zend_mm_high_bit()/zend_mm_low_bit() - improved safe_address() Changed paths: M Zend/zend_alloc.c M Zend/zend_multiply.h Diff: diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 98ab6be..1c76bd4 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -678,6 +678,8 @@ static inline unsigned int zend_mm_high_bit(size_t _size) __asm { bsr eax, _size } +#elif defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) + return (8 * SIZEOF_SIZE_T - 1) - __builtin_clzl(_size); #else unsigned int n = 0; while (_size != 0) { @@ -704,6 +706,8 @@ static inline unsigned int zend_mm_low_bit(size_t _size) __asm { bsf eax, _size } +#elif defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) + return __builtin_ctzl(_size); #else static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0}; unsigned int n; @@ -2494,6 +2498,47 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) return res; } +#elif defined(__GNUC__) && defined(__arm__) + +static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) +{ + size_t res; + unsigned long overflow; + + __asm__ ("umlal %0,%1,%2,%3" + : "=r"(res), "=r"(overflow) + : "r"(nmemb), + "r"(size), + "0"(offset), + "1"(0)); + + if (UNEXPECTED(overflow)) { + zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset); + return 0; + } + return res; +} + +#elif defined(__GNUC__) && defined(__aarch64__) + +static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) +{ + size_t res; + unsigned long overflow; + + __asm__ ("mul %0,%2,%3\n\tumulh %1,%2,%3\n\tadds %0,%0,%4\n\tadc %1,%1,%1" + : "=&r"(res), "=&r"(overflow) + : "r"(nmemb), + "r"(size), + "r"(offset)); + + if (UNEXPECTED(overflow)) { + zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset); + return 0; + } + return res; +} + #elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64) static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h index c3c9657..e52956f 100644 --- a/Zend/zend_multiply.h +++ b/Zend/zend_multiply.h @@ -13,7 +13,7 @@ | lice...@zend.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Sascha Schumann <sas...@schumann.cx> | - | Ard Biesheuvel <a...@ard.nu> | + | Ard Biesheuvel <ard.biesheu...@linaro.org> | +----------------------------------------------------------------------+ */ @@ -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 -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php