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>
__asm__ (
"bt %[index], %[var] \n"
"setc %[bit]"
- : [bit] "=rm" (bit)
+ : [bit] "=qQm" (bit)
: [index] "rI" (index), [var] "r" (*var)
: "cc"
);
__asm__ (
"bt %[index], %[var] \n"
"setc %[bit]"
- : [bit] "=rm" (bit)
+ : [bit] "=qQm" (bit)
: [index] "rJ" (index), [var] "r" (*var)
: "cc"
);
__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)
__asm__ (
"btr %2, %1;"
"setc %0"
- : "=rm" (bit), "+m" (*(volatile uint32 *)var)
+ : "=qQm" (bit), "+m" (*(volatile uint32 *)var)
: "rI" (index)
: "cc"
);
__asm__ (
"btc %2, %1;"
"setc %0"
- : "=rm" (bit), "+m" (*(volatile uint32 *)var)
+ : "=qQm" (bit), "+m" (*(volatile uint32 *)var)
: "rI" (index)
: "cc"
);
__asm__ (
"bt %2, %1;"
"setc %0"
- : "=rm" (bit)
+ : "=qQm" (bit)
: "m" (*(const uint32 *)var), "rI" (index)
: "cc"
);