与硬件循环不同,软件分支使用显式指令来执行分支操作。 软件分支包括以下指令:
分支指令的目标地址可以指定为寄存器间接或 PC 相对偏移量。 PC 相对偏移量通常小于 32 位,但可以通过使用目标操作数中的适当语法(第 7.3.4 节)将其指定为 32 位。
分支指令可以是无条件的或有条件的,条件指令的执行由条件表达式控制。
软件分支指令
语法 | 描述 |
---|---|
[if (pred_expr)] jump label [if (pred_expr)] jumpr Rs | 跳转到由寄存器 Rs 或 PC 相对偏移量指定的地址。可以有条件地执行。 |
[if (pred_expr)] call label [if (pred_expr)] callr Rs | 跳转到由寄存器 Rs 或 PC 相对偏移量指定的地址。 将子程序返回地址存储在链接寄存器 LR 中。 可以有条件地执行。 |
[if (pred_expr)] jumpr LR | 跳转到链接寄存器 LR 中包含的子程序返回地址。 可以有条件地执行。 |
跳转指令将程序流更改为可以由寄存器或 PC 相关立即值指定的目标地址。 跳转指令可以基于条件表达式的值是有条件的。
跳转指令
语法 | 描述 |
---|---|
jump label | 直接跳转。 分支到标签指定的地址。 标签被编码为与 PC 相关的有符号立即数。 |
jumpr Rs | 间接跳转。 跳转到包含在通用寄存器 Rs 中的地址。 |
if ([!]Ps) jump label if ([!]Ps) jumpr Rs | 条件跳转。 如果条件表达式的计算结果为真,则执行跳转。 |
注意 条件跳转可以指定为推测性的。
调用指令用于跳转到子程序。 该指令执行到目标地址的跳转,并将返回地址存储在链接寄存器 LR 中。
调用的形式在功能上类似于跳转指令,包括无条件和有条件形式的 PC 相对和寄存器间接。
调用指令
语法 | 描述 |
---|---|
call label | 直接子程序调用。 跳转到标签指定的地址,并将返回地址存储在寄存器中。 LR 标签被编码为 PC 相关的有符号立即数 |
callr Rs | 间接子程序调用。跳转到通用寄存器 Rs 中包含的地址,并将返回地址存储在寄存器 LR 中。 |
if ([!]Ps) call label if ([!]Ps) callr Rs | 有条件的调用。 如果条件表达式的计算结果为真,则对指定的目标地址执行子程序调用。 |
返回指令用于从子程序返回。 该指令执行间接跳转到存储在链接寄存器 LR 中的子程序返回地址。
返回实现为跳转寄存器间接指令,并支持无条件和条件形式。
返回指令
语法 | 描述 |
---|---|
jumpr LR | 子程序返回。 跳转到链接寄存器 LR 中包含的子程序返回地址。 |
if ([!]Ps) jumpr LR | 有条件的子程序返回。 如果表达式的计算结果为真,则执行子程序返回到指定的目标地址。 |
dealloc_return | 子程序返回堆栈帧解除分配。 执行deallocframe 操作(第8.5 节),然后执行子程序从链接寄存器返回deallocframe 加载的目标地址。 |
if ([!]Ps) dealloc_return | 有条件的子例程返回堆栈帧解除分配。 如果表达式的计算结果为真,则执行deallocframe,然后子程序从链接寄存器返回deallocframe 加载的目标地址。 |
注意 链接寄存器 LR 是通用寄存器 R31 的别名。 因此,子程序返回可以通过指令跳转器 R31 来执行。 条件子程序返回(包括 dealloc_return)可以指定为推测性的
当跳转或调用指令将 PC 相对偏移量指定为分支目标时,偏移量值通常以明显小于 32 位的形式编码。 这可能会限制程序指定跨越处理器内存地址空间的大范围的“长”分支的能力。
为了支持长分支,跳转和调用指令具有特殊版本,它们将完整的 32 位值编码为 PC 相对偏移量。
注意 此类指令使用一个额外的字来存储 32 位偏移量。
相对于 PC 的分支偏移量的大小用汇编语言表示,方法是可选地在目标标签前加上符号“##”或“#”:
例如:
jump ##label // 32-bit offset
call #label // non 32-bit offset
jump label // offset size determined by assembler
指令包是原子的:即使它们包含多条指令,也只能通过包中第一条指令的地址来引用它们。 因此,到包的分支只能针对包的第一条指令。
数据包最多可以包含两个分支。 分支目的地可以针对当前数据包或另一个数据包的开头。
分支不会中断当前数据包的执行:数据包中的所有指令都会被执行,即使它们出现在分支指令之后的汇编源代码中也是如此。
如果数据包位于硬件循环的末尾,则它不能包含分支指令。