The code is running on a Cortex M0+. I am trying to calculate the addresses of LDR PC-related loads and am finding the addresses are not always consistent.
This LDR PC-related load does not follow any of the other LDR PC-related loads I have calculated so far. How was this address calculated step-by-step? Kindly, please provide supporting documentation as I have not seen this documented anywhere.
"Add 4 here", "Add 8 here", "use the next PC" are the typical answers however I am finding those answers do not provide consistent or correct results.
Here is the (Thumb) LDR instruction
ldr r3, [pc, #4] ;
Thumb instruction definition for a PC-relative load (ignore the highlight)
Edit:
Here are correct calculations.
Example 1: 0x1000'0306: LDR.N R4, [PC, #0xc0]
Wrong Calculated Address: 0x1000'0306 + 0x4 + 0xc0 = 0x1000'03CA
Correct Calculated Address: 0x1000'0306->clear bit[0]->0x1000'0304 + 0x4 + 0xc0 = 0x1000'03C8
Example 2: 0x1000'0306: LDR.N R4, [PC, #0xc8]
Wrong Calculated Address: 0x1000'0306 + 0x4 + 0xc8 = 0x1000'03D2
Correct Calculated Address: 0x1000'0306->clear bit[0]->0x1000'0304 + 0x4 + 0xc8 = 0x1000'03D0
The excerpt you quote seems to explain it pretty clearly, paying attention to the Notes: Add 4 to the address of the ldr
instruction, clear bit 1 of the result, and add the immediate.
In this example:
The instruction is at address 0x1000451c.
Add 4 to get 0x10004520.
Clear bit 1 of this value. Here it's already 0, so nothing happens. (Or to phrase it another way, round down to a multiple of 4. Since 0x10004520 is already a multiple of 4, nothing happens.)
Add 4 (the value of the immediate) to get 0x10004524.
Which agrees with what the disassembler is telling you.