3

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?

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Justin Ethier
  • 131,333
  • 52
  • 229
  • 284

9 Answers9

7

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!

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
GJ.
  • 10,810
  • 2
  • 45
  • 62
  • Intel 8080 doesn't have a DJNZ instruction, it's specific to Z80. The opcode for DJNZ is a NOP on 8080. LOOP on x86 also have entirely different opcodes than DJNZ. – Sedat Kapanoglu Jan 06 '21 at 06:56
3

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

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
3

That was a fairly common instruction on machines of that era, and occurs in many other places as well.

And so on

dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
3

PowerPC has a bdnz instruction with a special count-down register ctr. Decrementing ctr and conditionally branching is on top of the regular condition test, so you can add a condition, eg bdnzt eq, label will branch if the less-than bit is set AND ctr is positive after decrement.

Ironically, ctr is also used for indirect function call addresses. So, bdnz becomes rather useless in a loop with an indirect call, because the special advantage of the ctr register is outweighed by the cost of saving and restoring it. An encoding exists for the instruction, "decrement ctr and branch to its new value if not zero," but this is specifically forbidden and trapped. (It wouldn't check for a NULL pointer anyway.)

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
2

Some PIC microcontrollers like the PIC18 have a DECFSZ (Decrement File and Skip if Zero) instruction. I have often put a DECFSZ followed by branch.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
2

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
  • 143,651
  • 25
  • 248
  • 329
1

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
  • 4,526
  • 1
  • 22
  • 25
  • 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.) –  May 03 '10 at 21:07
1

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
  • 2,142
  • 11
  • 10
0

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
  • 11,819
  • 2
  • 39
  • 40
  • CBZ/CBNZ? That's half of it. My ARM is a bit rusty though... this might not be available in all modes? –  May 03 '10 at 21:13