views:

307

answers:

8

First a little background. The z80 CPU has an instruction called DJNZ which can be used in a similar manner as a for loop. Basically DJNZ decrements the B register and jumps to a label if not zero. For example:

    ld      b,96                    ; erase all of the line
disp_version_erase_loop:
    call    _vputblank              ; erase pixels at cursor (uses b reg)
    djnz    disp_version_erase_loop ; loop 

Of course you can do the same thing using regular comparison and jump instructions, but often it is handy to use the single instruction.

With that out of the way, my question is, do other CPU architectures include a similar control instruction?

+3  A: 

IA-32 has various REP* instructions which use CX as their counter

Ignacio Vazquez-Abrams
+1  A: 

There exist single instruction set computers, which aren't actually used. But one of the single instruction set machines is the "subtract and branch if less than or equal to zero" (subleq) machine. Wikipedia has more on this

I'm not aware of any other real machines that have an instruction exactly like this though. I like RISC machines, and really don't see a need for it either.

McPherrinM
It's useful because the test of the loop counter doesn't use any flags. No need to mess about if the flags are being used for something in the loop/there's only one set of flags anyway/the register dependency management isn't very clever (e.g., POWER chips can have only 1 rename for the condition register). The decrement is just a handy bonus for the common case. (ARM just has the compare-and-branch-if-zero/not-zero bit for example.) (MIPS, as an alternative example, has no flags register. That's another way around this sort of problem.)
brone
+2  A: 
dmckee
+1  A: 

The PDP-11 (circa 1970) predated the Z-80 by about 5 years, and at least some models (though probably not the early ones) had a subtract-one-and-branch instruction:

sob R, offset
DigitalRoss
+2  A: 

PowerPC has bdnz and a special count-down register ctr. Decrementing ctr and conditionally branching is independent of the actual condition test, so you can add a condition on top of bdnz, eg bdnzlt cr5, label (if memory serves) will check if the less-than bit stored in cr5 and either AND or OR that with the condition of ctr becoming 0.

Ironically, ctr is also used to store any indirect function call destination. So it's possible to code the instruction "decrement ctr and branch to its new value if not zero", but this is specifically forbidden. (It wouldn't check for a NULL pointer anyway.) Somewhat significantly, bdnz becomes rather useless in a loop with an indirect call.

Potatoswatter
+4  A: 

Actualy in IA-32 direct equivalent for DJNZ is LOOPcc (LOOPZ). Remember the Z80 and 8086 have the same predecessor Intel 8080. So all x86 CPUs directly inherit DJNZ instruction!

GJ
A: 

The Z80 was a CISC processor. DJNZ is a classic example of a complex instruction. The modern fashion is towards RISC instruction sets which prefer smaller, simpler, faster instructions but can process them more quickly - especially with advanced pipelining features. I don't think you get anything like this on the ARM family, for example.

crazyscot
CBZ/CBNZ? That's half of it. My ARM is a bit rusty though... this might not be available in all modes?
brone
+1  A: 

On x86 there is the LOOP instruction that does exactly the same thing (with counter in ECX). There is also the JECXZ instruction (Jump if ECX is Zero) which is meant to be used together with LOOP - you place it BEFORE the loop so that you can skip the entire loop if the count was zero in the beginning.

Like this:

  ;number of iterations in ECX
  JECXZ end
start:
  ;loop body
  LOOP start
end:

But note that those instructions are horribly inefficient on contemporary CPUs. It's much better to use regular CMP/SUB and Jcc instructions. On a side note - the Intel Core2 CPUs are actually able to treat a compare+jump instruction pair as if it were a single instruction - they call it "macro-op fusion".

slacker