]> granicus.if.org Git - php/commitdiff
Improve x86 inline assembler
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Mon, 11 Feb 2013 12:53:27 +0000 (13:53 +0100)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Mon, 11 Feb 2013 12:53:27 +0000 (13:53 +0100)
- added cc annotation to inline asm that clobbers the condition
  flags
- remove hardcoded constants (IS_LONG,IS_DOUBLE)
- remove hardcoded offsets (zval->value, zval->type)

Zend/zend_alloc.c
Zend/zend_operators.h

index 1cc2c678334f96b13e0e1ee656e11a9c054a59b9..98ab6bea36ba0d5e5758f2b203b39f663af63149 100644 (file)
@@ -667,12 +667,12 @@ static inline unsigned int zend_mm_high_bit(size_t _size)
 #if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
        unsigned int n;
 
-       __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm"  (_size));
+       __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm"  (_size) : "cc");
        return n;
 #elif defined(__GNUC__) && defined(__x86_64__)
        unsigned long n;
 
-        __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm"  (_size));
+        __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm"  (_size) : "cc");
         return (unsigned int)n;
 #elif defined(_MSC_VER) && defined(_M_IX86)
        __asm {
@@ -693,17 +693,17 @@ static inline unsigned int zend_mm_low_bit(size_t _size)
 #if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
        unsigned int n;
 
-       __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm"  (_size));
+       __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm"  (_size) : "cc");
        return n;
 #elif defined(__GNUC__) && defined(__x86_64__)
         unsigned long n;
 
-        __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm"  (_size));
+        __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm"  (_size) : "cc");
         return (unsigned int)n;
 #elif defined(_MSC_VER) && defined(_M_IX86)
        __asm {
                bsf eax, _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;
index e395fd39ccc86faca12aee6d5a831a39004d6530..93c60e49015232721adcf2a67613843f1ad63c7f 100644 (file)
@@ -477,6 +477,10 @@ ZEND_API void zend_update_current_locale(void);
 #define zend_update_current_locale()
 #endif
 
+/* The offset in bytes between the value and type fields of a zval */
+#define ZVAL_OFFSETOF_TYPE     \
+       (__builtin_offsetof(zval,type) - __builtin_offsetof(zval,value))
+
 static zend_always_inline int fast_increment_function(zval *op1)
 {
        if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
@@ -486,20 +490,26 @@ static zend_always_inline int fast_increment_function(zval *op1)
                        "jno  0f\n\t"
                        "movl $0x0, (%0)\n\t"
                        "movl $0x41e00000, 0x4(%0)\n\t"
-                       "movb $0x2,0xc(%0)\n"
+                       "movb %1, %c2(%0)\n"
                        "0:"
                        :
-                       : "r"(op1));
+                       : "r"(&op1->value),
+                         "n"(IS_DOUBLE),
+                         "n"(ZVAL_OFFSETOF_TYPE)
+                       : "cc");
 #elif defined(__GNUC__) && defined(__x86_64__)
                __asm__(
                        "incq (%0)\n\t"
                        "jno  0f\n\t"
                        "movl $0x0, (%0)\n\t"
                        "movl $0x43e00000, 0x4(%0)\n\t"
-                       "movb $0x2,0x14(%0)\n"
+                       "movb %1, %c2(%0)\n"
                        "0:"
                        :
-                       : "r"(op1));
+                       : "r"(&op1->value),
+                         "n"(IS_DOUBLE),
+                         "n"(ZVAL_OFFSETOF_TYPE)
+                       : "cc");
 #else
                if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MAX)) {
                        /* switch to double */
@@ -523,20 +533,26 @@ static zend_always_inline int fast_decrement_function(zval *op1)
                        "jno  0f\n\t"
                        "movl $0x00200000, (%0)\n\t"
                        "movl $0xc1e00000, 0x4(%0)\n\t"
-                       "movb $0x2,0xc(%0)\n"
+                       "movb %1,%c2(%0)\n"
                        "0:"
                        :
-                       : "r"(op1));
+                       : "r"(&op1->value),
+                         "n"(IS_DOUBLE),
+                         "n"(ZVAL_OFFSETOF_TYPE)
+                       : "cc");
 #elif defined(__GNUC__) && defined(__x86_64__)
                __asm__(
                        "decq (%0)\n\t"
                        "jno  0f\n\t"
                        "movl $0x00000000, (%0)\n\t"
                        "movl $0xc3e00000, 0x4(%0)\n\t"
-                       "movb $0x2,0x14(%0)\n"
+                       "movb %1,%c2(%0)\n"
                        "0:"
                        :
-                       : "r"(op1));
+                       : "r"(&op1->value),
+                         "n"(IS_DOUBLE),
+                         "n"(ZVAL_OFFSETOF_TYPE)
+                       : "cc");
 #else
                if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MIN)) {
                        /* switch to double */
@@ -561,40 +577,46 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
                        "addl   (%2), %%eax\n\t"
                        "jo     0f\n\t"     
                        "movl   %%eax, (%0)\n\t"
-                       "movb   $0x1,0xc(%0)\n\t"
+                       "movb   %3, %c5(%0)\n\t"
                        "jmp    1f\n"
                        "0:\n\t"
                        "fildl  (%1)\n\t"
                        "fildl  (%2)\n\t"
                        "faddp  %%st, %%st(1)\n\t"
-                       "movb   $0x2,0xc(%0)\n\t"
+                       "movb   %4, %c5(%0)\n\t"
                        "fstpl  (%0)\n"
                        "1:"
                        : 
-                       : "r"(result),
-                         "r"(op1),
-                         "r"(op2)
-                       : "eax");
+                       : "r"(&result->value),
+                         "r"(&op1->value),
+                         "r"(&op2->value),
+                         "n"(IS_LONG),
+                         "n"(IS_DOUBLE),
+                         "n"(ZVAL_OFFSETOF_TYPE)
+                       : "eax","cc");
 #elif defined(__GNUC__) && defined(__x86_64__)
                __asm__(
                        "movq   (%1), %%rax\n\t"
                        "addq   (%2), %%rax\n\t"
                        "jo     0f\n\t"     
                        "movq   %%rax, (%0)\n\t"
-                       "movb   $0x1,0x14(%0)\n\t"
+                       "movb   %3, %c5(%0)\n\t"
                        "jmp    1f\n"
                        "0:\n\t"
                        "fildq  (%1)\n\t"
                        "fildq  (%2)\n\t"
                        "faddp  %%st, %%st(1)\n\t"
-                       "movb   $0x2,0x14(%0)\n\t"
+                       "movb   %4, %c5(%0)\n\t"
                        "fstpl  (%0)\n"
                        "1:"
                        : 
-                       : "r"(result),
-                         "r"(op1),
-                         "r"(op2)
-                       : "rax");
+                       : "r"(&result->value),
+                         "r"(&op1->value),
+                         "r"(&op2->value),
+                         "n"(IS_LONG),
+                         "n"(IS_DOUBLE),
+                         "n"(ZVAL_OFFSETOF_TYPE)
+                       : "rax","cc");
 #else
                        Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2);
 
@@ -636,7 +658,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
                        "subl   (%2), %%eax\n\t"
                        "jo     0f\n\t"     
                        "movl   %%eax, (%0)\n\t"
-                       "movb   $0x1,0xc(%0)\n\t"
+                       "movb   %3, %c5(%0)\n\t"
                        "jmp    1f\n"
                        "0:\n\t"
                        "fildl  (%2)\n\t"
@@ -646,21 +668,24 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
 #else
                        "fsubp  %%st, %%st(1)\n\t"
 #endif
-                       "movb   $0x2,0xc(%0)\n\t"
+                       "movb   %4, %c5(%0)\n\t"
                        "fstpl  (%0)\n"
                        "1:"
                        : 
-                       : "r"(result),
-                         "r"(op1),
-                         "r"(op2)
-                       : "eax");
+                       : "r"(&result->value),
+                         "r"(&op1->value),
+                         "r"(&op2->value),
+                         "n"(IS_LONG),
+                         "n"(IS_DOUBLE),
+                         "n"(ZVAL_OFFSETOF_TYPE)
+                       : "eax","cc");
 #elif defined(__GNUC__) && defined(__x86_64__)
                __asm__(
                        "movq   (%1), %%rax\n\t"
                        "subq   (%2), %%rax\n\t"
                        "jo     0f\n\t"     
                        "movq   %%rax, (%0)\n\t"
-                       "movb   $0x1,0x14(%0)\n\t"
+                       "movb   %3, %c5(%0)\n\t"
                        "jmp    1f\n"
                        "0:\n\t"
                        "fildq  (%2)\n\t"
@@ -670,14 +695,17 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
 #else
                        "fsubp  %%st, %%st(1)\n\t"
 #endif
-                       "movb   $0x2,0x14(%0)\n\t"
+                       "movb   %4, %c5(%0)\n\t"
                        "fstpl  (%0)\n"
                        "1:"
                        : 
-                       : "r"(result),
-                         "r"(op1),
-                         "r"(op2)
-                       : "rax");
+                       : "r"(&result->value),
+                         "r"(&op1->value),
+                         "r"(&op2->value),
+                         "n"(IS_LONG),
+                         "n"(IS_DOUBLE),
+                         "n"(ZVAL_OFFSETOF_TYPE)
+                       : "rax","cc");
 #else
                        Z_LVAL_P(result) = Z_LVAL_P(op1) - Z_LVAL_P(op2);