19

I'm "re-learning" 68000 assembly language and came across the "MOVEQ" command that is labeled "MOVE QUICK".

According to the NXP Programmers Reference Manual (reference below), the command MOVEQ (MOVE QUICK) is described as:

Moves a byte of immediate data to a 32-bit data register. The data in an 8-bit
field within the operation word is sign- extended to a long operand in the data
register as it is transferred.

I've searched the manual and cannot find why it's "quick".

Meaning, what's the difference (in performance) in the following instructions?

MOVEQ #100, D0
MOVE #100, D0

I gather the MOVEQ is a better fit for moving 8-bit data. Or, is it ONLY 8-bits of data as I cannot seem to confirm.

REF:

https://www.nxp.com/files-static/archives/doc/ref_manual/M68000PRM.pdf

29

The MOVE immediate instruction takes 8 cycles in byte and word modes. There are two memory reads, one for the instruction and one for the immediate value.

The MOVEQ instruction encodes the immediate value into the instruction op-code itself, so only takes 4 cycles and 1 memory read. It can only take a byte immediate value.

MOVEQ #1, D0 (4 clocks, 1 memory read)
MOVE.b #1, D0 (8 clocks, 2 memory reads)
MOVE.w #1000, D0 (8 clocks, 2 memory reads)

Note that the immediate value loaded for byte and word size moves overwrites the entire 32 bits of the register, and is sign extended.

As such, for loading values $00-$FF, it is twice as fast in instruction cycles and uses half as much memory bandwidth (important on systems where it is shared with DMA).

  • 7
    "for loading values 0-255..." - more precisely, it loads a 32 bit value between -128 and +127.This is 3 times faster than doing it the normal way with move.l #... – Bruce Abbott Jul 19 at 1:20
  • 1
    @BruceAbbott that's a good point, it does sign extend to 32 bits. – user Jul 19 at 7:54
  • 2
    Showing the actual hex codes of the three instructions will improve the answer. – Leo B. Jul 19 at 23:17
11

To give the exact cycle-by-cycle breakdown:

MOVEQ is a one word instruction so will nominally perform in four cycles; in practice it can occur immediately following operation decoding because all necessary information is within the instruction word. Four cycles are then expended fetching the next value to feed into the instruction prefetch queue.

Both MOVE.b MOVE.w are two-word instructions. The 68000 actually knows both words before either instruction begins, so both can occur pretty much immediately but both then require that a further two words be fetched to repopulate the instruction prefetch queue, which occupies eight cycles before the next instruction can begin.

MOVE.l is a three-word instruction. The 68000's prefetch queue is only two words long. So after decoding it can't actually be completed until a further word has been fetched, and after that fetch a further two will be needed to repopulate the queue. So twelve cycles total.

MOVEs are the most primitive operation available; the general rule is that the number of words needed to complete an operation plus the number needed then to [re]populate the prefetch queue is only a floor for cycle counting. See Yacht.txt for a more detailed summary of the work each instruction does; bear in mind that things like RTS are only one word long but imply two further prefetches since the whole queue needs to be replenished, and anything that might change the supervisor flag will often result in a refetch of data that's ostensibly already in the queue, in case the memory subsystem is designed to serve conditional results.

  • (obiter: this answer was offered despite the other answer already being present because I felt the fact of the prefetch queue makes it a different answer, technically. Even if very similar) – Tommy Jul 19 at 20:56
  • 1
    Comment only: Your last paragraph doesn't seem to quite 'scan' correctly - or I'm still half asleep :-). I think "that anything that things" contains at least one typo (but may not) and " in case the ..." may not say what you want as precisely as it could (but may :-) ). – Russell McMahon Jul 19 at 22:32
  • Are there any circumstances in which the time to execute a 68000 instruction would vary with context? For example, how would the timing of muls r0,r1 / moveq r0,#0 / rts compare to muls r0,r1 / move.l r0,#0 / rts? – supercat Jul 19 at 22:33
  • @supercat I can't think of anything, as every instruction is microcoded to make sure the prefetch queue is exactly full again within its execution time. It's not intelligent like, say, the instruction queue on an 8086. – Tommy Jul 20 at 13:40
  • @Tommy: I can't think of any advantage to waiting before the second fetch is complete before starting instruction execution, but could easily imagine that instruction execution decode couldn't start until the cycle after the first fetch was complete, starting the fetch of the second word immediately without regard for whether it's needed would allow it to begin a cycle or two sooner than would otherwise be possible. It may have been possible to design the 68000 shave two cycles off an RTS if the attached memory system could process a two-cycle "ignored value" read, but... – supercat Jul 20 at 16:34
7

I've searched the manual and cannot find why it's "quick".

Simply because MOVEQ is a single word (two byte) instruction, which can be fetched in a single memory cycle, while an equal constant move will be 2 (MOVE.W) or 3 words (MOVE.L) and need one/two additional memory cycles - each four clocks.

So effectively you'll get the following execution timing:

  • MOVEQ #5,D0 - 4 Clocks,
  • MOVE.B #5,D0 - 8 Clocks,
  • MOVE.W #5,D0 - 8 Clocks,
  • MOVE.L #5,D0 - 12 Clocks,

making MOVEQ about 50/66% faster.

MOVEQ even got it's own opcode (7) to squeeze all into a single word.

ADDQ and SUBQ works similar (*1) - except mixed into the Scc/DBcc/TRAPcc group (5).

I gather the MOVEQ is a better fit for moving 8-bit data. Or, is it ONLY 8-bits of data as I cannot seem to confirm.

Only. There is no room for more than 8 bits of constant within the 16 bit instruction word (*2), as the encoding is

|OPCODE|Dest.| Res || Data      |
|Group |Reg. |     ||           |
| 0111 | xxx |  0  || yyyy yyyy |

*1 - Not exactly like it as they may have additional parameters.

*2 - Well, in the original 68000 encoding there was one unused bit, but won't get far.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.