在原始的 Thumb 指令集中,BL
指令由两条 16 位指令组成,编码如下:
1111 HOOO OOOO OOOO BL <label>
| |
| \.. long branch and link offset high/low
\............... low/high offset
0 -- offset high
1 -- offset low
两条指令中的第一条必须将 H 位设置为 0。11 位偏移量左移 12,添加到PC
并放入LR
登记。
LR = PC + (offset << 12)
两条指令中的第二条指令必须将 H 位设置为 1。 11 位偏移量左移 1,添加到LR
注册,并用作分支目标。这LR
寄存器设置为返回地址。
temp = next instruction address
PC = LR + (offset << 1)
LR = temp | 1
对于 ARMv5T,Thumb 编码BLX
添加了指令,允许 Thumb 代码调用 ARM 代码。这是通过在后半部分*定义一个新的拇指位来完成的。BL
操作说明。
111T 1OOO OOOO OOOO BL/BLX <label> (second half)
| |
| \.. long branch link exchange offset low
\................. thumb bit
0 -- BLX is encoded
1 -- BL is encoded
的运作BLX
与后半部分类似BL
指令,但偏移量必须是偶数。该函数在 ARM 状态而不是 Thumb 状态下调用。
temp = next instruction address
PC = (LR + (offset << 1)) & 0xfffffffc
LR = temp | 1
CSPR T bit = 0
请注意,总共 22 个立即位给出半字偏移量,可实现观察到的 ±4 MiB 的分支偏移量。
将两半放在一起,我们还可以看到BL
and BLX
作为 32 位指令,编码如下:
1111 0OOO OOOO OOOO 111T 1OOO OOOO OOOO BL/BLX <label>
| | |
| | \.. 22 bit offset (low half)
| \................. thumb bit
\....................... 22 bit offset (high half)
In Thumb2, this scheme was extended. BL
and BLX
became proper 32 bit instructions and their halves must be given consecutively.† Some bits of the second instruction word were defined to extend the branch offset to ±16 MiB.
1111 0SOO OOOO OOOO 11AT BOOO OOOO OOOO BL/BLX <label>
| | || | |
| | || | \.. 21 bit offset (low half)
| | || \............... additional bit J2
| | |\................. thumb bit
| | \.................. additional bit J1
| \....................... 21 bit offset (high half)
\................................... sign bit
如果设置了拇指位,则BL
指令被编码。如果清楚的话,则BLX
指令被编码。在后一种情况下,21 位偏移必须是偶数。然后分支偏移计算如下:
I1 = !(J1 ^ S)
I2 = !(J2 ^ S)
imm32 = (S ? 0xffff << 24 : 0) | (I1 << 23) | (I2 << 22) | (imm21 << 1)
temp = next instruction address
PC = LR + offset
LR = temp | 1
if thumb bit clear
CSPR T bit = 0
虽然对附加偏移位进行编码的方案一开始看起来很复杂,但这只是将两个附加位编码到分支偏移中同时与分支偏移的现有编码兼容的最简单方法。BL
and BLX
指示。
See the ARM 架构参考手册,ARMv7-A 和 ARMv7-R 版, the ARM7TDMI 数据表,以及ARM架构参考手册ARMv5 供进一步阅读。
* 相关编码1110 0OOO OOOO OOOO
编码16位无条件分支指令B <label>
.
† 在 Thumb2 之前,a 的两部分BL
or BLX
这些指令是独立的指令,可以与其他指令穿插发出,甚至可以单独发出,但强烈建议按连续顺序发出。中断也可能发生在一个的两半之间BL
or BLX
指令,使临时内容LR
注册可观察的。在包括 ARMv6-M 在内的 Thumb2 目标上,这不再可能,并且BL
and BLX
表现为 32 位指令。