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 位。