On 02/11/2013 04:53 AM, Ard Biesheuvel wrote:
Commit:    aa12cdc361b29b4050676763858b3cfa637be6cb
Author:    Ard Biesheuvel <ard.biesheu...@linaro.org>         Mon, 11 Feb 2013 
13:53:27 +0100
Parents:   5bfdf4f069975514a358473f7e7fee3710e50597
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=aa12cdc361b29b4050676763858b3cfa637be6cb

Log:
Improve x86 inline assembler

- 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)

Changed paths:
   M  Zend/zend_alloc.c
   M  Zend/zend_operators.h



Hi Ard,

The changes to zend_operators.h break compilation with GCC 3.  Can you
review https://bugs.php.net/bug.php?id=64780 ?

Even if GCC 3 is pretty much gone there might still be someone who
wants to build PHP 5.5 with it e.g. as a step during a platform
migration.  Since retaining the old assembler code in an #ifdef is
painless to do, it won't hurt PHP to keep it a bit longer.

Chris






Diff:
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 1cc2c67..98ab6be 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -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;
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index e395fd3..93c60e4 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -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);



--
christopher.jo...@oracle.com  http://twitter.com/ghrd
Newly updated, free PHP & Oracle book:
http://www.oracle.com/technetwork/topics/php/underground-php-oracle-manual-098250.html

--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to