I am writing an RTOS and there is something I don't understand. My context switch, written in assembly, has the line:
STMDB r0!,{r4-r11}
Where r0 is being used to store the current process stack pointer (PSP). Since this is in a handler and running in handler mode, the MSP is being used for the function, so I can't just push.
For the sake of argument let us say that r0 stores the address 0x64 (I am aware this is not reasonable, but it is not relevant to the discussion below).
Do I understand this correctly: the first register to be stored, r4, will be placed at 0x60, since the decrement before part means that r0 is first decremented by one 32-bit word, then the storage takes place?
'''TL-DR;''' 'DB' stands for 'decrement before'.
[stm|ldm][modifier] Rn!, {reg_list}
Rn! is the 'address register'
There are two mutually exclusive options for auto-index memory via the modifier.
Letter | Note |
---|---|
I | Increment the address register (ie, 3 register -> 12 bytes increment) |
D | Decrement the address register |
B | Before store/load operation |
A | After store/load operation |
You can have variants of a full/empty decrementing/incrementing stack. Ie, stack grows down/up and stack is empty/full. Decrement before would mean the stack is at a 'full' element and you grow down.
Of course, the same operations can be used for buffers. If you have a ring buffer, it can typically point to an empty or full element. This is a design choice. You would use the 'before' or 'after' versions and for ring buffers, we usually increment memory.
LDM and STM can come in all these four flavors.
If you don't modify the address register, then these modifiers don't make sense. Ie, you need ldmxx Rn!, {reglist}
or stmxx Rn!, {reglist}
. The single word versions have a different syntax.
See: ARM increment register, University of Regina lecture
Probably a good keyword is 'fully descending stack' for searches. Some assemblers will offer alternatives like,
stmfd
- store multiple fully descending; alias stmdb
.stmed
- store multiple empty descending; alias stmda
.I would just stick to the 'i','d', 'b' and 'a' permutations.
What exactly is decremented and when?
It is always the leading address register that is modified. It is either before or after the register list is transferred as to when this occurs. Hopefully the above describes data structures where this is useful.
It is always a single word that is empty/full and not the whole register list. Register list is ordered numerically for access. Ie, the CPU always writes/reads R0 first and R15 (if possible) last. You can just include/exclude a 'reg list' bit in the opcode.