Reputation: 632
The ARM docs for the ldmdb
instruction seem to contradict themselves.
Under the description of addr_mode
, the docs state that the DB address corresponds to "Decrement address Before each access".
Further down in the Operation section, the docs state that "the memory addresses used for the accesses are at 4-byte intervals ranging from Rn
to Rn-4*(n-1)
.
I'm confused as to how these two statements are not in direct conflict: if the address (stored in Rn
) is decremented before each access, wouldn't the first (highest) accessed address be Rn - 4
?
Based on behavior I've observed from running some code, it seems like the address is actually decremented after each access (consistent with the 2nd behavior).
Am I interpreting this wrong? What is the actual behavior of ldm
/stm
with the DB addressing mode?
Upvotes: 1
Views: 1749
Reputation: 71586
Seems pretty clear to me:
LDMDB/LDMEA)
address = R[n] - 4*BitCount(registers);
for i = 0 to 14
if registers<i> == '1' then
R[i] = MemA[address,4]; address = address + 4;
if registers<15> == '1' then
LoadWritePC(MemA[address,4]);
if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
LDM(LDMIA/LDMFD)
address = R[n];
for i = 0 to 14
if registers<i> == '1' then
R[i] = MemA[address,4]; address = address + 4;
if registers<15> == '1' then
LoadWritePC(MemA[address,4]);
if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
so if r5 = 0x1000
ldmdb r5,{r2,r1}
the end result is:
r2 = mem[0x0FFC]
r1 = mem[0x0FF8]
from the pseudocode
address = 0x1000 - (2*4) = 0x0FF8, then for each register flag in the list
mem[address] = r1, address += 4
mem[address] = r2, address += 4
I think of DB meaning there wont be anything written to the starting address (0x1000 in this example).
if r5 = 0x1000
ldmia r5,{r1,r2}
the end result is
r1 = mem[0x1000]
r2 = mem[0x1004]
From the pseudocode
address = 0x1000
for each register flag enabled
r1 = mem[address] address += 4
r2 = mem[address] address += 4
I think of increment after meaning start using that address then increment. decrement before, start at the prior (word) address, then continue downward running the registers backward.
Or you could simply try the instruction on a processor or a simulator, and examine the memory.
If it doesn't make sense find one of the alternate/compatible ARM architectural reference manuals, and read that description. ARM re-writes their descriptions from time to time...
It is quite possible that there are errors in the documentation.
Yes, this text looks to be completely wrong:
For LDMDB, LDMEA, STMDB, and STMFD the memory addresses used for the accesses are at 4-byte intervals ranging from Rn to Rn - 4 * (n-1), where n is the number of registers in reglist. The accesses happen in order of decreasing register numbers, with the highest numbered register using the highest memory address and the lowest number register using the lowest memory address. If the writeback suffix is specified, the value of Rn - 4 * (n-1) is written back to Rn.
should be rn - 4 to rn - (4 * n) and rn - (4*n)
Note the architectural reference manuals and the technical reference manuals are pretty good. More recently they have been making flavors of other manuals in this case users guide, there are some programmers manuals. Seems like these are not good, I stopped looking at them after similar confusion by folks lead to me looking at it lead to me seeing how bad it was lead to me never bothering again.
Upvotes: 2