Reputation: 15810
We recently upgraded the code to gcc4.3.3
from gcc4.2.4
.
void testAndSet( volatile int* s, int* val )
{
__asm__ __volatile__ ( "btsl $0, %0\n "
"jc bitSet\n "
"movl $0, %1\n "
"jmp returnVector\n"
"bitSet:\n "
"movl $1, %1\n"
"returnVector: " : "=m"(*s), "=m"(*val) );
}
Our code now fails with the following errors,
lock.cxx: Assembler messages:
lock.cxx:59: Error: symbol `bitSet' is already defined
lock.cxx:61: Error: symbol `returnVector' is already defined
lock.cxx:59: Error: symbol `bitSet' is already defined
lock.cxx:61: Error: symbol `returnVector' is already defined
Those symbols weren't found anywhere else. (Renaming them causes the same error with the new name).
What's up with this? why do I get the errors twice?
Upvotes: 2
Views: 3005
Reputation: 21
Also you may use local label names by adding %= after each local label:
"loop%=:" "\n\t"
Upvotes: 2
Reputation: 400592
This is unrelated to your error, but you could improve your code and avoid branches simply using the setCC instruction:
__asm__ __volatile__ ( "btsl $0, %0\n "
"mov $0, %1\n"
"setc %1\n" : "=m"(*s), "=m"(*val) );
The setCC
instruction (where CC is one of the condition code flags, analogous to the jCC
instruction) sets a byte to 0 or 1 depending on whether or not the given condition was satisfied. Since the destination is a 4-byte value, you need to either preload it with 0 or use the MOVZX instruction to make the upper 3 bytes 0.
Upvotes: 5
Reputation: 11102
Probably the optimizer has changed and is now inlining your testAndSet() function into 2 places. Because you are using global names for your labels, this does not work. You should use local names instead. E.g:
__asm__ __volatile__ ( "btsl $0, %0\n "
"jc 0f\n "
"movl $0, %1\n "
"jmp 1f\n"
"0:\n "
"movl $1, %1\n"
"1: " : "=m"(*s), "=m"(*val) );
Local labels are just numbers; to disambiguate cases where there are many labels called "0" you need to use "jmp 0f
" for forward jumps and "jmp 0b
" for backward jumps.
Upvotes: 10