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:

    move.b  d0, 0(a0)
    ror.l   #8, d0
    move.b  d0, 2(a0)
    ror.l   #8, d0
    move.b  d0, 4(a0)
    ror.l   #8, d0
    move.b  d0, 6(a0)
    ror.l   #8, d0

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):

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.