Post-indexed addressing modes in Arm Cortex M refer to addressing modes where the address is calculated first before being used, and then the address register is updated after. This allows efficient accessing of data structures like arrays or buffers where you want to increment the address after each access. The key benefit is that the updated address is available for the next instruction without needing an extra ADD instruction.
Background on Arm Addressing Modes
The Arm architecture supports a flexible set of addressing modes for load and store instructions to access memory. These work by using a base register, an offset register, a shift amount, and an offset constant to calculate the memory address. The three main types of addressing are:
- Offset – The address is the sum of a base register and an optionally shifted offset register.
- Pre-indexed – The base register is updated with the offset before using the address.
- Post-indexed – The address is calculated first before the base register is updated with the offset.
Post-indexed addressing is useful for sequentially accessing data structures because you get the updated base register pointing to the next element without needing a separate ADD instruction. The Arm Cortex-M processors like Cortex-M3, Cortex-M4, and Cortex-M7 support several post-indexed addressing modes for loads and stores.
Post-Indexed Addressing Modes in Arm Cortex M
Here are the main post-indexed addressing modes supported on Cortex-M processors:
Post-Indexed Addressing with Offset
This uses the base register value as the address for the load/store. After completing the memory access, the offset register value is added to the base register. For example: LDR R0, [R1], R2
Loads from the address in R1, then does R1 = R1 + R2. This allows efficiently stepping through arrays or buffers.
Post-Indexed Addressing with Immediate Offset
Same as above but with an immediate constant offset instead of a register. For example: LDR R0, [R1], #8
Loads from R1 then does R1 = R1 + 8. Useful for accessing fields of structured data.
Post-Indexed Addressing with Register and Shift
Supports shifted register offsets for the post-increment step. For example: LDR R0, [R1], R2, LSL #3
Loads from R1, then does R1 = R1 + (R2 << 3) to increment the base address.
Post-Indexed Addressing with Scaled Register Offset
A specialized mode to support efficient array access. The index register is automatically scaled by the data size. For example: LDR R0, [R1], R2, LSL #2
Loads from R1, then does R1 = R1 + (R2 * 4) to move to the next array element.
Use Cases for Post-Indexed Addressing
Here are some typical use cases where post-indexed addressing is useful on Cortex-M:
Accessing Array Data
Post-indexed array addressing like LDR R0, [R1], R2, LSL #2 is very efficient for array access in a loop since it handles the index increment automatically.
Stepping Through Buffers or Linked Lists
Post-increment with the offset register is ideal for sequentially going through a buffer or linked list data structure.
Structured Data Access
The immediate offset post-indexed mode allows accessing different fields of a struct or object and automatically advancing to the next field.
Memory Block Copy
Post-increment load and store instructions can be used together to implement an efficient memory block copy routine.
Comparison to Pre-Indexed Addressing
Pre-indexed addressing updates the base register first before doing the memory access. This causes a subtle change in behavior for things like array access. With pre-indexing, the updated base is used for the current access which means it points to the next element. With post-indexing, the original base is used meaning it points to the current element.
So post-indexed addressing is better suited for sequential access patterns where you want to access the current element before stepping to the next.
Defining Post-Indexed Addressing in Assembly
Here are some examples of using post-indexed addressing modes in Arm assembly on Cortex-M: LDR R0, [R1], R2 ; Post-indexed offset register LDR R0, [R1], #8 ; Post-indexed immediate offset LDR R0, [R1], R2, LSL #3 ; Post-indexed shifted register offset LDR R0, [R1], R2, LSL #2 ; Post-indexed scaled array indexing
The assembly syntax is straightforward – the increment step comes after the base register in square brackets. This clearly indicates the post-increment behavior.
Post-Indexed Addressing and Multicore Compatibility
Post-indexed addressing modes are supported across all profiles of the Arm architecture including both Cortex-M and Cortex-A series processors. This makes post-indexing suitable for software targeting multiple Arm core types. The specific opcodes differ but the fundamental behavior is consistent.
In summary, post-indexed addressing is useful for:
- Efficient array access without extra ADD instructions
- Stepping through data structures like buffers and lists
- Structured data field access
- Memory block copy operations
The post-increment happens after the memory access which sets up the base register for the next sequential access. Post-indexing is straightforward to use in assembly code and supported on all Arm profiles so is widely usable across Arm-based software.