summaryrefslogtreecommitdiffstats
path: root/src/corelib/arch
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-01-08 20:45:11 -0200
committerQt by Nokia <qt-info@nokia.com>2012-03-26 14:54:08 +0200
commit99802f0c1498b0630949e75f69afe1cc0c89c4d4 (patch)
tree2b3f0b1b8a9cb316c01e309a3a6b8eeda396d8c4 /src/corelib/arch
parentfe778b94bd58c12949d763f428d214e8c16d144e (diff)
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 <bradley.hughes@nokia.com>
Diffstat (limited to 'src/corelib/arch')
-rw-r--r--src/corelib/arch/qatomic_i386.h12
1 files changed, 6 insertions, 6 deletions
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<QBasicAtomicOps<8> >
# 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
}