ARM Cortex M0/M3/M4:Why PC is always Even number in Thumb State

4.8k views Asked by At

As far as I understand it, ARM Cortex-M CPUs are always in Thumb state, which means:

Thumb state indicated by program counter being odd (LSB = 1). Branching to an even address will cause an exception, since switching back to ARM state is not allowed.

However, while I am using CortexM0 and M4 CPU, the PC is always even. Each time I branch, the LR records PC+1 and each time I return, the PC gives LR-1.

For example, if lr = 0x0000_01D5,

Execute

BX lr

Then PC should be 0x0000_01D5, whereas it gives 0x0000_01D4.

Isn't this impossible?

Any comment will be appreciated.

3

There are 3 answers

0
auselen On BEST ANSWER

From Cortex-M4 Technical Reference Manual:

2.3.1 Program counter

Register R15 is the Program Counter (PC).

Bit [0] is always 0, so instructions are always aligned to word or halfword boundaries.

Reading from PC shouldn't return an odd address. However when you write to PC, LSB of value is loaded into the EPSR T-bit. From Cortex-M3 Devices Generic User Guide - 2.1.3. Core registers

Thumb state

The Cortex-M3 processor only supports execution of instructions in Thumb state. The following can clear the T bit to 0:

instructions BLX, BX and POP{PC}

restoration from the stacked xPSR value on an exception return

bit[0] of the vector value on an exception entry or reset.

Attempting to execute instructions when the T bit is 0 results in a fault or lockup. See Lockup for more information.

In other words, you can read even values from PC but can't write such values under normal circumstances.

0
old_timer On

I had that confusion as well. The lsbit is set for situations where the address is going to be used by a BX. The lsbit is stripped when it goes into the pc itself. If you disassemble some simple pc relative addressing that will demonstrate what is going on.

1
Alan Campbell On

While there are 4,294,967,296 [2^32] memory locations, the actual data bus is only 8 bits wide.

For 16-bit instructions, you need 2 memory accesses per instruction load: that's where arguments about "Endian" start. Whichever way you order it, 2 bytes get read in with the 1st byte at an address ending in 0.

[sigh] If the ARM data bus was 16 [or 32] bits wide, you could forget about bits in the PC - and have double [or quadruple] the instruction space.