]> granicus.if.org Git - php/commitdiff
Added ARM accelerated implementations for ZEND_SIGNED_MULTIPLY_LONG()
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Thu, 17 Jan 2013 16:51:12 +0000 (17:51 +0100)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Thu, 17 Jan 2013 17:04:05 +0000 (18:04 +0100)
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

Zend/zend_multiply.h

index c3c9657f3b25e987d43748bdb96327c244012d3f..e52956f417627f4433238a7c052fb4a1245ea8f7 100644 (file)
@@ -13,7 +13,7 @@
    | license@zend.com so we can mail you a copy immediately.              |
    +----------------------------------------------------------------------+
    | Authors: Sascha Schumann <sascha@schumann.cx>                        |
-   |          Ard Biesheuvel <ard@ard.nu>                                 |
+   |          Ard Biesheuvel <ard.biesheuvel@linaro.org>                  |
    +----------------------------------------------------------------------+
 */
 
        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 {      \
 
 #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