Fault when loading a literal value and then branching to it
Article ID: 103488014
Published date: 31 Jan 2018
Last updated: -
Applies to: Cortex-M
Why do I get a fault when I load a literal value and then branch to it?
Various ARM architectures support 'interworking', which is the ability to switch between instruction sets (traditional ARM 32-bit instruction set or compressed 16-bit Thumb, possibly including extended Thumb-2 instruction set), at certain kinds of branches. This allows code routines implemented in alternate instruction sets to inter-operate, by informing the processor of the change of instruction set at the branch.
The mechanism for switching makes use of the fact that all instructions must be (at least) halfword-aligned. Therefore, bit of the branch target address is redundant and this bit can be reused to indicate the target instruction set at that address. '0' means ARM, a '1' means Thumb (or Thumb-2).
For example, consider the instruction:
If the value in 'lr' is 0x20000000 then the processor will branch to the instruction at 0x20000000 and interpret it as an ARM 32-bit instruction.
If the value in 'lr' is 0x20000001 then the processor will branch to the instruction at 0x20000000 but will interpret the instruction found there as a Thumb or Thumb-2 opcode.
ARM tools ensure that all branch target label addresses have bit set correctly to represent the type of opcode found at that address. However, if the programmer created an address manually, for example by loading a literal constant into the register and then branching to it, they must take care to ensure that bit is correctly set to represent the opcode type of that branch target.
Cortex-M processors support only the Thumb-2 instruction set (a superset of traditional Thumb). Therefore all branch targets should be indicated as odd numbers, having bit set to '1' for interworking, indicating Thumb-style opcodes.
Manually created branch targets must therefore be manually set to the actual target address + 1.
Attempting to branch to an even numbered address on a Cortex-M3 processor, using an interworking branch instruction, will result in a Usage Fault of type INVSTATE.