]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Fix asm constraint for Set/Test/ClearBitVector
authorVMware, Inc <>
Thu, 2 Aug 2012 05:29:55 +0000 (22:29 -0700)
committerDmitry Torokhov <dtor@vmware.com>
Thu, 2 Aug 2012 18:08:33 +0000 (11:08 -0700)
Compiling this assembly with gcc-4.4.3 in i686 results in a
compilation error stating that %dil is not a valid register.

GCC experts state that the compiler is correct and the
problem is in the assembly constraints:
https://bugzilla.redhat.com/show_bug.cgi?id=625263
(Summary for uninitiated: %dil is the low 8 bits of %edi,
which is addressible in x86_64 but NOT in ia32)

Slightly more detail: the setc instruction takes an 8-bit
operand. Which means any register chosen must also be
an 8-bit register (ia32: al, bl, cl, dl). The 'q' constraint
means "any register addressible with the -l suffix", which
is the correct constraint. At Jim's suggetion, I'm also adding
'Q' (ia32: ah, bh, ch, dh). Note that in x86_64, 'q' covers
all registers, so 'q' vs. 'r' does not hurt x86_64.

I also note that bts specifically alters CF (and we are indeed
using setc to read it!), but "cc" is not on the clobber list.
It was present on the clobber list of all the other assembly
fragments, so I suspect this was an oversight.

Why didn't we see this before?
- These BitTest funcs tend to be used only in VMX
- The only VMX that builds with gcc-4.4.3 today is ESX's, which ix x86_64
- The Linux Workstation vmx32 uses gcc-4.1.2
- (I'm experimenting with bumping Workstation Linux's gcc)
There are no correctness concerns; if constraints were wrong, the
code would fail to compile entirely due to incorrect register
selection.

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/lib/include/vm_basic_asm.h

index 180bd157ab528a2dfbb4bb79bced9cdbc6780655..881a13c2825587e659ff9cb0e09ad913110939cd 100644 (file)
@@ -1086,7 +1086,7 @@ TestBit32(const uint32 *var, uint32 index)
    __asm__ (
       "bt %[index], %[var] \n"
       "setc %[bit]"
-      : [bit] "=rm" (bit)
+      : [bit] "=qQm" (bit)
       : [index] "rI" (index), [var] "r" (*var)
       : "cc"
    );
@@ -1104,7 +1104,7 @@ TestBit64(const uint64 *var, uint64 index)
    __asm__ (
       "bt %[index], %[var] \n"
       "setc %[bit]"
-      : [bit] "=rm" (bit)
+      : [bit] "=qQm" (bit)
       : [index] "rJ" (index), [var] "r" (*var)
       : "cc"
    );
@@ -1137,9 +1137,9 @@ SetBitVector(void *var, int32 index)
    __asm__ (
       "bts %2, %1;"
       "setc %0"
-      : "=rm" (bit), "+m" (*(volatile uint32 *)var)
+      : "=qQm" (bit), "+m" (*(volatile uint32 *)var)
       : "rI" (index)
-      : "memory"
+      : "memory", "cc"
    );
    return bit;
 #elif defined(_MSC_VER)
@@ -1157,7 +1157,7 @@ ClearBitVector(void *var, int32 index)
    __asm__ (
       "btr %2, %1;"
       "setc %0"
-      : "=rm" (bit), "+m" (*(volatile uint32 *)var)
+      : "=qQm" (bit), "+m" (*(volatile uint32 *)var)
       : "rI" (index)
       : "cc"
    );
@@ -1177,7 +1177,7 @@ ComplementBitVector(void *var, int32 index)
    __asm__ (
       "btc %2, %1;"
       "setc %0"
-      : "=rm" (bit), "+m" (*(volatile uint32 *)var)
+      : "=qQm" (bit), "+m" (*(volatile uint32 *)var)
       : "rI" (index)
       : "cc"
    );
@@ -1197,7 +1197,7 @@ TestBitVector(const void *var, int32 index)
    __asm__ (
       "bt %2, %1;"
       "setc %0"
-      : "=rm" (bit)
+      : "=qQm" (bit)
       : "m" (*(const uint32 *)var), "rI" (index)
       : "cc"
    );