Reputation: 6526
I try to understand how the target address is calculated in a BL instruction ARMv7a.
I created a simple example program and compiled and linked it. The object file (elf) has the following instructions.
...
14: e3400000 movt r0, #0
18: eb00000f bl 5c <test>
1c: e50b0008 str r0, [fp, #-8]
...
0000005c <test>:
5c: e52db004 push {fp} ; (str fp, [sp, #-4]!)
60: e28db000 add fp, sp, #0
If I understand BL correct, I should get 5c as target address.
From the reference manual I found the following description:
imm32 = SignExtend(imm24:'00', 32);
targetAddress = PC + imm32;
Where imm24 are the 24 right bits of the instruction. In my case 0x000000f.
If I calculate the target address this way, I don't get 5c though.
// PC = 0x18 (where we find the BL instruction)
uint32_t imm24 = 0x00000f;
uint32_t imm32 = imm24 << 2;
// imm32 = 0x3c
uint32_t targetAddress = PC + imm32;
// targetAddress = 0x18 + 0x3c = 0x54
Do I miss something?
I used a arm-none-eabi crosscompiler with the following flags:
CFLAGS=-Wall -O0 -march=armv7-a -mtune=cortex-a7 -marm
Upvotes: 1
Views: 1055
Reputation: 58427
From the ARM ARM (document number DDI 0100E):
The branch target address is calculated by:
Sign-extending the 24-bit signed (two's complement) immediate to 32 bits.
Shifting the result left two bits.
Adding this to the contents of the PC, which contains the address of the branch instruction plus 8.
As for why this is, see 2.7.4 Prefetching and self-modifying code in the same document.
Upvotes: 2