mjspier
mjspier

Reputation: 6526

ARMv7a BL instruction, calculate target address

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

Answers (1)

Michael
Michael

Reputation: 58427

From the ARM ARM (document number DDI 0100E):

The branch target address is calculated by:

  1. Sign-extending the 24-bit signed (two's complement) immediate to 32 bits.

  2. Shifting the result left two bits.

  3. 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

Related Questions