My understanding is that the "memory" clobber is enough to warn the compiler that that _q_value might be modified ... though I'm not a tool expert so I could be wrong there.
Alternatively, remove both constraints and just use "Q" instead. If we're actually using the constraint in instructions, "m" is wrong because we can't handle pre/post increment/decrement addressing, and no offset is allowed in ARM so "o" wouldn't be correct either:
I notice that _q_value is referenced twice in the constraints.
Can we get rid of the reference causing the problem, i.e.:
asm volatile("0:\n"
"ldrex %[newValue], [%[_q_value]]\n"
"sub %[newValue], %[newValue], #1\n"
"strex %[result], %[newValue], [%[_q_value]]\n"
"teq %[result], #0\n"
"bne 0b\n"
[result] "=&r" (result),
: [newValue] "=&r" (newValue),
: [_q_value] "r" (&_q_value)
: "cc", "memory");
My understanding is that the "memory" clobber is enough to warn the compiler that that _q_value might be modified ... though I'm not a tool expert so I could be wrong there.
Alternatively, remove both constraints and just use "Q" instead. If we're actually using the constraint in instructions, "m" is wrong because we can't handle pre/post increment/decrement addressing, and no offset is allowed in ARM so "o" wouldn't be correct either:
asm volatile("0:\n"
"ldrex %[newValue], %[_q_value]\n"
"sub %[newValue], %[newValue], #1\n"
"strex %[result], %[newValue], %[_q_value]\n"
"teq %[result], #0\n"
"bne 0b\n"
[_ q_value] "+Q" (_q_value),
[result] "=&r" (result),
: [newValue] "=&r" (newValue),
:: "cc", "memory");
I don't have a suitable toolchain to test this with right now, though... can someone else see if it makes any difference?