A64中的条件执行
在A64指令集中,有一些指令的执行是有条件的。有条件的执行的意思是:当条件判定为false时,PC往前执行,但是不会产生任何效果。(即当条件判定为false时,该指令相当于NOP)。
条件分支指令B.cond
就是一个带条件的执行指令。条件代码以.
为分隔符被追加在指令的后面,例如:B.EQ。
有一些根据Z
条件标志位的条件分支指令,不能像它追加条件代码:
- CBNZ
- CBZ
- TBNZ
- TBZ
还有一些A64指令是无条件执行的,但是使用条件代码序偶为源操作数。这些指令总是执行,但是操作取决于条件代码的值。这些指令可以分为以下几类:
- 条件数据处理指令。例如:CSEL
- 条件比较指令。例如:CCMN、CCMP
在这些指令中,可以再最后的操作数位置指定条件代码。例如:CSEL Wd,Wm,Wn,NE
条件标志
条件标志位N、Z、C、V保存在APSR中。
标志位的设置和清除:
N
当操作结果为负数时,设置为1,否则为0。
Z
当操作结果为0时,设置为1,否则为0。
C
当操作结果发生进位或者减法结果无借位时,设置为1,否则设置为0。
V
当操作导致溢出时,设置为1,否则设置为0。
C标志位在以下几种情况下将会被设置:
- 对于加法,包括比较指令CMN,如果加法产生进位(无符号溢出),则C被设置为1,否则设置为0。
- 对于减法,包括比较指令CMP,如果减法产生一个借位(无符号下溢),则C被设置为1,否则设置为0。
- 对于包含移位操作的非加减操作,将C设置为移位操作移出值的最后一位。
- 对于其他费加减操作,C通常保持不变,但是对于特殊情况,请参阅个别指令说明。
如果加法、减法或者比较的结果大于或者等于231,或者小于-231,则会发生溢出。
更新A64代码中的条件标志位
在AArch64状态中,N、Z、C、V条件标志位保存在NZCV系统寄存器中,它是进程状态的一部分,可以通过MSR和MRS指令进行访问。
注意:
只有在指定了S后缀之后,指令才会更新条件标志位,CMP、CMN、CCMP、CCMN和TST指令除外,因为他们总是更新条件标志位。这些指令还确定更新哪些标志位。如果条件指令不执行,它不会影响标志位。
例如:
这个例子展示了改变A64代码中一些条件标志的读、修改、写过程。
1 | MRS X1,NZCV ;复制N、Z、C、V标志位的值到通用寄存器X1 |
更新条件标志的浮点指令
所有的A64浮点比较指令都可以更新条件标志。这些指令直接更新NZCV寄存器中的标志。
进位标志位(C)
当操作的结果会产生进位或者当一个减法操作没有产生借位时,进位标志位(C)将会被设置为1,否则为0。
C标志位的设置方式:
- 对于加法,包括比较指令CMN,如果加法产生进位(无符号溢出),则C设置为1,否则设置为0。
- 对于减法,包括比较指令CMP和负指令NEGS和NGCS,如果减法产生了借位(即无符号下溢),则将C设置为0,否则设置为1。
- 对于整数和浮点条件比较指令CCMP、CCMN、FCCMP和FCCMPE, C和其他条件标志要么设置为比较的结果,要么直接设置为直接值。
- 对于浮点比较指令,将FCMP和FCMPE、C和其他条件标志设置为比较的结果。
- 对于其他指令,C通常保持不变,但对于任何特殊情况,请参见个别指令说明。
溢出标志位(V)
加法、减法和比较运算可能发生溢出。
在使用64位X寄存器的A64指令中,如果操作的结果大于或等于263,或小于-263,就会发生溢出。
在使用32位W寄存器的A64指令中,如果操作的结果大于或等于231,或小于- 231,就会发生溢出。
状态码后缀
可以是有条件的指令有一个可选的双字符条件码后缀。
条件代码在语法描述中显示为{cond}。下表为可以使用的条件码:
后缀 | 含义 |
---|---|
EQ | 等于(Equal) |
NE | 不等于(Not Equal) |
CS | 进位(与HS相同) |
HS | 无符号数大于或等于(与CS相同) |
CC | C标志位置0(和LO相同) |
LO | 无符号小于(和CC相同) |
MI | 负的或者负的结果(Minus or negative result) |
PL | 正或零的结果 |
VS | 溢出 |
VC | 没有溢出 |
HI | 无符号大于 |
LS | 无符号小于或等于 |
GE | 有符号大于或等于 |
LT | 有符号小于 |
GT | 有符号大于 |
LE | 有符号小于或等于 |
AL | 总是(默认值) |
注意
其中一些条件代码的含义取决于最后更新条件标志的指令是浮点指令还是整数指令。
条件代码后缀和相关的标志位
条件码后缀定义了执行指令必须满足的条件。
下表显示了可以使用的条件代码和它们所依赖的标志设置:
后缀 | 标志位 | 含义 |
---|---|---|
EQ | Z 置1 | 等于 |
NE | Z 置0 | 不等于 |
CS或HS | C 置1 | 大于等于(无符号>=) |
CC或LO | C 置0 | 小于(无符号<) |
MI | N 置1 | 负数 |
PL | N 置0 | 大于或等于 |
VS | V 置1 | 溢出 |
VC | V 置0 | 没有溢出 |
HI | C 置1 且 Z 置0 | 大于(无符号>) |
LS | C 置0 且Z 置1 | 小于或等于(无符号<=) |
GE | N和V相同 | 有符号>= |
LT | N和V不同 | 有符号< |
GT | Z 置0,N和V相同 | 有符号> |
LE | Z 置1,N和V不同 | 有符号<= |
AL | 任意 | 这个后缀通常省略。 |
在A32指令和A64指令中,可选条件代码在语法描述中显示为{cond}。对于Thumb32指令,条件编码在IT指令之前。只有当条件标志满足指定条件时,才执行带有条件码的指令。
下面是A32代码条件执行的一个例子:
1 | ADD r0,r1,r2 ;r0 = r1 + R2,不要更新标志位 |
执行速度的优化
要优化代码的执行速度,就必须详细了解目标系统的指令时间、分支预测逻辑和缓存行为。
更多信息,请参阅处理器的技术参考手册。