Program Counter
Posted: Thu Feb 06, 2025 11:24 am
J. Yiu states for both the M0+ (RP2040) and M33 (RP2350) that the program counter (PC) is the address of the current instruction plus 4 [1][2]. The Astrobe docs say that the RP2040's PC is four bytes ahead of the current instruction, while the RP2350 is eight bytes ahead. The Arm v8-M manual says the PC holds the address of the current instruction [3].
Now, consider this test code (distilled from "real code"):
Partial assembly listing for the RP2040 (module body):
With the RP2040, the global at relative address 52 is loaded at 34 using an offset of 16, and at 38 using an offset of 12. 52 - 16 = 36, 52 - 12 = 40. Hence in this case we have a PC that's two bytes ahead of the current instruction. If the current instruction were 32-bit wide, we'd have a PC that's four bytes ahead. So the PC is not always four bytes ahead, but at the address of the next instruction.
Partial assembly listing for the RP2350 (module body):
With the RP2350, the same loads use offsets of 20 (at relative address 30) and 12 (address 36). 52 - 20 = 32, 52 - 12 = 40. The latter shows the PC to be four bytes ahead, but the former to point to the "second half" of the current instruction (32).
I find the load at address 30 particularly confusing. I know this is not a question regarding Astrobe per se, but since you have written the compiler, and therefore probably know everything about the PC, :) I was hoping you could shed some light on this. Thanks.
[1] Jopeph Yiu, The Definitive Guide to Arm Cortex-M0 and Cortex-M0+ Processors
[2] Jopeph Yiu, The Definitive Guide to Arm Cortex-M23 and Cortex-M33 Processors
[3] Arm v8-M Architecture Reference Manual
Now, consider this test code (distilled from "real code"):
Code: Select all
MODULE M1;
TYPE DM = RECORD x, y: INTEGER END;
VAR dm: DM;
PROCEDURE* p(i, j: INTEGER); END p;
BEGIN
p(dm.x, dm.y)
END M1.
Code: Select all
. 32 020H 0B500H push { lr }
p(dm.x, dm.y)
. 34 022H 04804H ldr r0,[pc,#16] -> 52
. 36 024H 06800H ldr r0,[r0]
. 38 026H 04903H ldr r1,[pc,#12] -> 52
. 40 028H 06849H ldr r1,[r1,#4]
. 42 02AH 0F7FFFFF5H bl.w -22 -> 24
. 46 02EH 0E000H b 0 -> 50
. 48 <LineNo: 10>
. 50 032H 0BD00H pop { pc }
. 52 <Global: 000080000H 080000H>
Partial assembly listing for the RP2350 (module body):
Code: Select all
. 28 01CH 0B500H push { lr }
p(dm.x, dm.y)
. 30 01EH 0F8DF0014H ldr.w r0,[pc,#20] -> 52
. 34 022H 06800H ldr r0,[r0]
. 36 024H 0F8DF100CH ldr.w r1,[pc,#12] -> 52
. 40 028H 06849H ldr r1,[r1,#4]
. 42 02AH 0F7FFFFF5H bl.w -22 -> 24
. 46 02EH 0E000H b 0 -> 50
. 48 <LineNo: 10>
. 50 032H 0BD00H pop { pc }
. 52 <Global: 000080000H 080000H>
I find the load at address 30 particularly confusing. I know this is not a question regarding Astrobe per se, but since you have written the compiler, and therefore probably know everything about the PC, :) I was hoping you could shed some light on this. Thanks.
[1] Jopeph Yiu, The Definitive Guide to Arm Cortex-M0 and Cortex-M0+ Processors
[2] Jopeph Yiu, The Definitive Guide to Arm Cortex-M23 and Cortex-M33 Processors
[3] Arm v8-M Architecture Reference Manual