在ARM手册中BL指令如下描述(其后跟立即数的描述如下,跟寄存器直接看手册很简单):
其中比较难理解的就是J1,J2的获取,在手册中有描述,请看如下所示:
I1,I2就是立即数的bit[23:22]两个bit位。
# imm32表示立即数
I2 = imm32 & (0x01 << 22)
I1 = imm32 & (0x01 << 23)
S:表示符号最高为topbit(x)
# offset 带符号的立即数
S = (0x01 << 26) if offset < 0 else 0
则J1,J2的可以按如下计算
J1, J2 = (1 if I1 else 0, 1 if I2 else 0) if S else (0 if I1 else 1, 0 if I2 else 1)
J2 <<= 11
J1 <<= 13
1. 算法1
def signExtend(address, entry):
offset = entry - address - 4
imm32 = offset & 0x7fffffff
# contains the sign bit
S = (0x01 << 26) if offset < 0 else 0
imm11 = (imm32 & 0x00000FFE) >> 1 # [11: 1]
imm10 = (imm32 & 0x003FF000) >> 12 << 16 # [21: 12]
I2 = imm32 & (0x01 << 22)
I1 = imm32 & (0x01 << 23)
J1, J2 = (1 if I1 else 0, 1 if I2 else 0) if S else (0 if I1 else 1, 0 if I2 else 1)
J2 <<= 11
J1 <<= 13
code = 0xF0000000 # [31: 27], BL
instr = code | S | imm10 | 0x0000C000 | J1 | 0x00001000 | J2 | imm11
imm32 = ((instr & 0xffff) << 16) | ((instr >> 16) & 0xffff)
return imm32
2. 算法2
def signExtend2(address, entry):
imm32 = (entry - address - 4) // 2
low = 0xF800 | (imm32 & 0x7FF)
high = 0xF000 | (0x03 << 9) | ((imm32 >> 11) & 0x1FF)
return ((low << 16) | high)
3. 算法3
def signExtend3(address, entry):
offset = ( entry - address - 4 ) & 0x007fffff
high = 0xF000 | offset >> 12
low = 0xF800 | (offset & 0x00000fff) >> 1
imm32 = (low << 16) | high
return imm32
测试示例:
data = signExtend(0x20001580, 0x20000074)
data2 = signExtend2(0x20001580, 0x20000074)
data3 = signExtend3(0x20001580, 0x20000074)
print('0x{:08X}'.format(data))
print('0x{:08X}'.format(data2))
print('0x{:08X}'.format(data3))
输出:
0xFD78F7FE
0xFD78F7FE
0xFD78F7FE
# instr = 0xFD78F7FE
# print(bin(instr))
# 11110 1 1111111110 11 1 1 1 10101111000
# S imm10 J1 J2 imm11
另外说明一下,对于小系统来说,S, J1, J2,受限于内存,三者在算法1中,都能得到,所以才有2,3的简化算法取值;