Comment 27 for bug 675347

Dave Martin (dave-martin-arm) wrote :

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"
                 : [newValue] "=&r" (newValue),
                   [result] "=&r" (result),
                 : [_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"
                 : [newValue] "=&r" (newValue),
                   [_q_value] "+Q" (_q_value),
                   [result] "=&r" (result),
                 :: "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?