I read a couple of articles including question here in SO Why does the ARM PC register point to the instruction after the next one to be executed?, that pc register value is actually current executing instruction address plus 2 instructions ahead, so in ARM state it's +8 byte (2*32bits).
My question is that, for thumb state, there could be 16bits or 32bits instructions, does it mean that the fetching pc address could be an offset of +4 bytes OR +8 bytes for 16/32bits instructions respectively?
For example:
279ae6: f8df 9338 ldr.w r9, [pc, #824] --> pc value= 279aea or 279aee
279aea: f44f 7380 mov.w r3, #256
279aee: 48cd ldr r0, [pc, #820]
I did more test with following code:
1598: 467b mov r3, pc
159a: f8bf 4000 ldrh.w r4, [pc] ; 159c
159e: 46f9 mov r9, pc
15a0: f83f 5001 ldrh.w r5, [pc, #-1] ; 15a3
15a4: f83f 6002 ldrh.w r6, [pc, #-2] ; 15a6
15a8: f83f 7003 ldrh.w r7, [pc, #-3] ; 15a9
15ac: f83f 8004 ldrh.w r8, [pc, #-4] ; 15ac
15b0: f04f 0908 mov.w r9, #8
15b4: f8d9 0008 ldr.w r0, [r9, #8] ; Trigger crash to check registers
Upon crash, registers are:
I/DEBUG ( 2632): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x10
I/DEBUG ( 2632): r0 b8ef4fc0 r1 aca6bb6c r2 00000000 r3 aca7c59c
I/DEBUG ( 2632): r4 00004000 r5 00003f50 r6 00006002 r7 000003f8
I/DEBUG ( 2632): r8 0000f83f r9 00000008 sl 00000000 fp aca6bbc0
I/DEBUG ( 2632): ip aca7c591 sp aca6bb40 lr acab722d pc aca7c5b4 cpsr 60070030
The addresses shown in above code comments(159c/15a3/15a6/15a9/15ac) are generated by objdump, I checked these positions' contents with registers', seem all right.
for 16 bit instrucion:
1598: 467b mov r3, pc ; // r3 = 1598 + 4 = 159c, correct for +4 theory
While for 32bit thumb instruction:
159a: f8bf 4000 ldrh.w r4, [pc] ; // ld addr = 159a + 2 = 159c, where the content is 4000(hw), exactly r4 shows
; // Inconsistent with +4 theory
By this, for 32 bit instruction, pc read = pc executing +2. Am I missing anything?? Now I'm really confused about pc offset.
BTW, this is armv7a platform using thumb2.
Thank you guys.