MOVEP instruction
Ever needed to write to every other byte in memory? Or maybe dealing with
save data on an 8-bit SRAM? You could use bit shifts to split the bytes,
but that's cumbersome. However, the 68000 has an instruction just for
this purpose: movep
.
What does it do?
What the movep
instruction does is write every other
byte from a d0-d7
register into memory (or the other way,
read every other byte from memory into a register).
To give an idea of how it works, this
movep.l d0, 0(a0)
is equivalent to this (flags aside), except a lot faster:
rol.l #8, d0
move.b d0, 0(a0)
rol.l #8, d0
move.b d0, 2(a0)
rol.l #8, d0
move.b d0, 4(a0)
rol.l #8, d0
move.b d0, 6(a0)
Not hard to see the appeal, it makes the code simpler and faster.
This instruction comes in 16-bit and 32-bit variants, and has four possible combinations (where n is from 0 to 7 and nn is from -32768 to +32767):
movep.w dn, nn(an)
movep.w nn(an), dn
movep.l dn, nn(an)
movep.l nn(an), dn
Using movep
to build DMA commands
One of the most common uses for movep
on the Mega Drive is
when you're building up DMA commands. Source and length are multi-byte
values that are spread across multiple registers, and splitting them can
be a pain… unless you use movep
.
The idea here is, assuming that you're building the DMA commands in a
buffer somewhere in RAM (generally a good idea), you first write all the
register writes without their values, then use movep.l
to
store the source, then use movep.w
to store the length
(note that source is 3 bytes, so we use the length to overwrite the
excess byte).
It'd look like this (constants from VDP setup page):
; d0.l = source (in words)
; d1.w = length (in words)
; a0.l = pointer to buffer
move.l #(VDPREG_DMALEN_H<<16)|VDPREG_DMALEN_L, (a0)+
move.l #(VDPREG_DMASRC_H<<16)|VDPREG_DMASRC_M, (a0)+
move.w #VDPREG_DMASRC_L, (a0)+
movep.l d0, -7(a0)
movep.w d1, -9(a0)
That's a lot easier than trying to use bit shifts for the same job, isn't it?
Using movep
to read/write SRAM
The other obvious use is when your game has extra SRAM. More often than not, it's 8-bit SRAM, which means only every other byte is useful.
In short: if some value you're storing is larger than a byte, you can
use movep
to access it with little effort. For example, if
you're storing a high score table, each score is likely a 32-bit value —
in that case you could simply use a movep.l
for each score.