我做了一些ARM内联汇编代码。
在Semaphore.s中,我看到gcc对两个变量都使用了寄存器r3:“success”和“change”。我想知道我的约束是否有问题?
最相关的第一行代码:
asm内联:
"1: MVN %[success], #0 @ success=TRUE=~FALSE\n\t"
"LDREX %[value], %[signal] @ try to get exclusive access\n\t"
"ADDS %[newValue], %[value], %[change] @ new value = value + change\n\t"
限制条件:
: [signal] "+m" (signal), [success] "=r" (success), [locked] "=r" (locked), [newValue] "=r" (newValue), [value] "=r" (value)
: [borderValue] "r" (borderValue), [change] "r" (change)
: "cc"
符号文件:
1: MVN r3, #0 @ success=TRUE=~FALSE
LDREX r0, [r7, #12] @ try to get exclusive access
ADDS r1, r0, r3 @ new value = value + change
更多来源和生成的符号如下。
BOOLEAN Semaphore_exclusiveChange (INT32U * signal, INT32S change, INT32U borderValue)
{
BOOLEAN success;
INT32U locked;// exclusive status
INT32U newValue;
INT32U value;
asm (
"1: MVN %[success], #0 @ success=TRUE=~FALSE\n\t"
"LDREX %[value], %[signal] @ new to get exclusive access\n\t"
"ADDS %[newValue], %[value], %[change] @ new value = value + change\n\t"
"ITE MI @ if (new value<0) \n\t"
" SUBSMI %[newValue], %[newValue] @ (new value<0): new value=0, set zero flag \n\t"
"@ else\n\t"
" CMPPL %[newValue], %[borderValue] @ (new value>=0): if new value > border value \n\t"
"\n\t@ zero flag is either: new value=0 or =bordervalue\n\t"
"ITE HI @ if new signal level > border value \n\t" //
" MOVHI %[success], #0 @ fail to raise signal, success=FALSE \n\t"
"\t@ else\n\t"
" MOVLS %[value], %[newValue] @ use new value \n\t" // ok
"STREX %[locked], %[value], %[signal] @ new exclusive store of value\n\t"
"TST %[locked],%[locked] @ is locked? \n\t"
"IT NE @ if locked \n\t"
"BNE 1b @ try again\n\t"
"DMB @ memory barrier\n\t" //
: [signal] "+m" (signal), [success] "=r" (success), [locked] "=r" (locked), [newValue] "=r" (newValue), [value] "=r" (value)
: [borderValue] "r" (borderValue), [change] "r" (change)
: "cc" );
return success;
}
符号文件中的相关文本:
Semaphore_exclusiveChange:
.LFB2:
.loc 1 10 0
@ args = 0, pretend = 0, frame = 32
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
push {r7}
.LCFI0:
sub sp, sp, #36
.LCFI1:
add r7, sp, #0
.LCFI2:
str r0, [r7, #12]
str r1, [r7, #8]
str r2, [r7, #4]
.loc 1 16 0
ldr r2, [r7, #4]
ldr r3, [r7, #8]
@ 16 "../drivers/Semaphore.c" 1
1: MVN r3, #0 @ success=TRUE=~FALSE
LDREX r0, [r7, #12] @ new to get exclusive access
ADDS r1, r0, r3 @ new value = value + change
ITE MI @ if (new value<0)
SUBSMI r1, r1 @ (new value<0): new value=0, set zero flag
@ else
CMPPL r1, r2 @ (new value>=0): if new value > border value
@ zero flag is either: new value=0 or =bordervalue
ITE HI @ if new signal level > border value
MOVHI r3, #0 @ fail to raise signal, success=FALSE
@ else
MOVLS r0, r1 @ use new value
STREX r2, r0, [r7, #12] @ new exclusive store of value
TST r2,r2 @ is locked?
IT NE @ if locked
BNE 1b @ try again
DMB @ memory barrier
@ 0 "" 2
.thumb
strb r3, [r7, #19]
str r2, [r7, #20]
str r1, [r7, #24]
str r0, [r7, #28]
.loc 1 38 0
ldrb r3, [r7, #19] @ zero_extendqisi2
.loc 1 39 0
mov r0, r3
add r7, r7, #36
mov sp, r7
pop {r7}
bx lr
最佳答案
你需要用“&”来进一步限制“成功”:
: [signal] "+m" (signal), [success] "=&r" (success), [locked] "=r" (locked), [newValue] "=r" (newValue), [value] "=r" (value)
这标志着它是一个“早期的打击者”。否则,编译器将假定所有输出都是在所有输入都被消耗之后产生的,并且可以自由地对不同的输出和输入使用相同的寄存器。
如果有“输入/输出”值,则需要使用“重复值”约束。