From 99802f0c1498b0630949e75f69afe1cc0c89c4d4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 8 Jan 2012 20:45:11 -0200 Subject: Fix the 64-bit i386 atomic according to assembly output The assembly output showed that GCC was generating some wrong code in some conditions, so update the constraints so it will do the right thing: the expectedValue constraint needs to be in/out with early clobber. In/out because cmpxchg8b really does produce output and, even if we don't care about it, GCC needs to be told that the registers used (EAX:EDX) were modified. The early clobber is necessary so it won't schedule EAX or EDX to be the same as the EBX_reg (the register we'll xchg EBX with). Since EAX and EDX are in/out and EBX can't be used, the only remaining low register for the "sete" instruction is CL. So use it directly and set ECX to be in/out too. For whatever reason, it can't find enough registers in debug mode and this expansion doesn't work. It looks like a bug though, since this requires 4 registers and one memory operand and in debug mode it must have EAX, ECX, EDX, ESI and EDI free for use. One of ESI or EDI is used to xchg EBX with, which means there must be at least one more free general register. Change-Id: I1f11e68d776bf9ad216b34ca316a53129122fabe Reviewed-by: Bradley T. Hughes --- src/corelib/arch/qatomic_i386.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/corelib/arch') diff --git a/src/corelib/arch/qatomic_i386.h b/src/corelib/arch/qatomic_i386.h index 4d9d810318..61d835a7d4 100644 --- a/src/corelib/arch/qatomic_i386.h +++ b/src/corelib/arch/qatomic_i386.h @@ -322,17 +322,17 @@ template <> struct QBasicAtomicOps<8>: QGenericAtomicOps > # define EBX_reg "b" # define EBX_load(reg) #endif - unsigned char ret; + quint32 highExpectedValue = quint32(newValue >> 32); // ECX asm volatile(EBX_load("%3") "lock\n" "cmpxchg8b %0\n" EBX_load("%3") - "sete %1\n" - : "+m" (_q_value), "=qm" (ret), - "+A" (expectedValue) - : EBX_reg (quint32(newValue & 0xffffffff)), "c" (quint32(newValue >> 32)) + "sete %%cl\n" + : "+m" (_q_value), "+c" (highExpectedValue), "+&A" (expectedValue) + : EBX_reg (quint32(newValue & 0xffffffff)) : "memory"); - return ret != 0; + // if the comparison failed, expectedValue here contains the current value + return quint8(highExpectedValue) != 0; #undef EBX_reg #undef EBX_load } -- cgit v1.2.3