ARM 指令集 - 更改 CPSR(S 位)
ARM Instruction Set - Changing the CPSR (S bit)
我想知道为什么 ARM 指令默认不设置 CPSR(如 x86),但在这些情况下必须使用 S 位?当指令不改变 CPSR 时提供更好的性能?例如,ADD 指令提供比 ADDS 更好的性能?或者什么是真正的交易?
I was wondering why does not ARM Instructions set the CPSR by default (like x86), but the S bit must be used in these cases?
这是一个选择,取决于上下文。额外的灵活性仅受程序员想象力的限制。
When Instructions don't change the CPSR offer better performance? For example an ADD
instruction offers better performance than ADDS
?
很可能永远不会注1。即,对于大多数 ARM CPU 和指令,未设置 CPSR 的指令不会执行得更快(更少的时钟)。
Or what is the real deal?
考虑一些 'C' 代码,
int i, sum;
char *p = array; /* passed in */
for(i = 0, sum = 0; i < 10 ; i++)
sum += arrary[i];
return sum;
这可以转化为,
mov r2, r0 ; get "array" to R2
mov r1, #10 ; counter (reverse direction)
mov r0, #0 ; sum = 0
1:
subs r1, #1 ; set conditions
add r0, [r2], #1 ; does not affect conditions.
bne 1b
bx lr
在这种情况下,循环体很简单。但是,如果循环中没有条件语句,那么编译器(或汇编程序员)可能会在他们喜欢的任何地方安排循环递减,并且仍然设置要在以后测试的条件。对于更复杂的逻辑以及 CPU 可能由于数据依赖性而停顿的情况,这可能更为重要。它对于条件执行也很重要。
可选的 'S' 比单个指令更多的是许多指令的特性。
注1:有人总能做出一个ARMCPU并做到这一点。您将不得不查看数据表。我不知道有哪个 CPU 需要更多时间来设置条件。
它是为了性能或者也许是。如果你总是改变标志,那么你很难在多条指令上使用一个标志,而没有一个分支会扰乱你的管道。
if(a==0)
{
b=b+1;
c=0;
}
else
{
b=0;
c=c+1;
}
传统上你必须用分支来实现它(伪代码不是真正的 asm)
cmp a,0
bne notzero
add b,b,1
mov c,0
b waszero
notzero:
mov b,0
add c,c,1
waszero:
所以无论如何你都要挨支
但有条件执行
cmp a,0
addeq b,b,1
moveq c,0
addne c,c,1
movne b,0
没有分支,您只需翻阅代码,现在唯一可行的方法是 1) 您可以选择每条指令根据标志有条件地执行,以及 2) 修改标志的指令可以选择不修改旗帜
取决于处理器 family/architecture add 甚至 mov 都会修改标志,因此您必须同时具有条件执行和不设置标志的选项。这就是为什么 arm 有一个 adds 和一个 add.
我认为他们用 64 位架构摆脱了所有这些,所以也许它既有趣又酷,也许它没有被充分使用或不值得,或者他们只需要这四位来保留 all/some 指令到 32 位。
我想知道为什么 ARM 指令默认不设置 CPSR(如 x86),但在这些情况下必须使用 S 位?当指令不改变 CPSR 时提供更好的性能?例如,ADD 指令提供比 ADDS 更好的性能?或者什么是真正的交易?
I was wondering why does not ARM Instructions set the CPSR by default (like x86), but the S bit must be used in these cases?
这是一个选择,取决于上下文。额外的灵活性仅受程序员想象力的限制。
When Instructions don't change the CPSR offer better performance? For example an
ADD
instruction offers better performance thanADDS
?
很可能永远不会注1。即,对于大多数 ARM CPU 和指令,未设置 CPSR 的指令不会执行得更快(更少的时钟)。
Or what is the real deal?
考虑一些 'C' 代码,
int i, sum;
char *p = array; /* passed in */
for(i = 0, sum = 0; i < 10 ; i++)
sum += arrary[i];
return sum;
这可以转化为,
mov r2, r0 ; get "array" to R2
mov r1, #10 ; counter (reverse direction)
mov r0, #0 ; sum = 0
1:
subs r1, #1 ; set conditions
add r0, [r2], #1 ; does not affect conditions.
bne 1b
bx lr
在这种情况下,循环体很简单。但是,如果循环中没有条件语句,那么编译器(或汇编程序员)可能会在他们喜欢的任何地方安排循环递减,并且仍然设置要在以后测试的条件。对于更复杂的逻辑以及 CPU 可能由于数据依赖性而停顿的情况,这可能更为重要。它对于条件执行也很重要。
可选的 'S' 比单个指令更多的是许多指令的特性。
注1:有人总能做出一个ARMCPU并做到这一点。您将不得不查看数据表。我不知道有哪个 CPU 需要更多时间来设置条件。
它是为了性能或者也许是。如果你总是改变标志,那么你很难在多条指令上使用一个标志,而没有一个分支会扰乱你的管道。
if(a==0)
{
b=b+1;
c=0;
}
else
{
b=0;
c=c+1;
}
传统上你必须用分支来实现它(伪代码不是真正的 asm)
cmp a,0
bne notzero
add b,b,1
mov c,0
b waszero
notzero:
mov b,0
add c,c,1
waszero:
所以无论如何你都要挨支
但有条件执行
cmp a,0
addeq b,b,1
moveq c,0
addne c,c,1
movne b,0
没有分支,您只需翻阅代码,现在唯一可行的方法是 1) 您可以选择每条指令根据标志有条件地执行,以及 2) 修改标志的指令可以选择不修改旗帜
取决于处理器 family/architecture add 甚至 mov 都会修改标志,因此您必须同时具有条件执行和不设置标志的选项。这就是为什么 arm 有一个 adds 和一个 add.
我认为他们用 64 位架构摆脱了所有这些,所以也许它既有趣又酷,也许它没有被充分使用或不值得,或者他们只需要这四位来保留 all/some 指令到 32 位。