Z80 Assembly - Instructions: Hardware Related

Handling interrupts

These are the instructions that deal with controlling the interrupts.

DI

There are no operands. When di is executed, the (maskable) interrupts are disabled. The flags are preserved.

EI

There are no operands. When ei is executed, the (maskable) interrupts are enabled. The flags are preserved.

RETI

This instruction returns from the interrupt routine. From the programmer's point of view it is no more than a simple ret, but it has to be used to properly handle the interrupt. Note that you cannot use conditions with reti. The flags are not affected.

RETN

Basically the same as reti, but this one is used to return from the nonmaskable interrupt (NMI).

IM

Syntax: im mode where mode is 0, 1 or 2

Setting the interrupt mode. The flags are not affected. Mode 0 means that only external devices generate interrupts, and the devices send instructions (mostly rst) to the CPU to execute. (this is not used in the TI calculators). When mode 1 is active, interrupts are generated by the internal circuitry of the processor, and each time this occurs, rst $38 is executed. The frequency of these interrupts is 200 per second on a ZX Spectrum, but it depends on the state of the batteries in the case of TI calculators (probably varies between 100 and 150). Mode 2 causes the user interrupt to be executed instead of rst $38. You can read more about this process in the Interrupts section.

RST

Syntax: rst address where address is $00, $08, $10, $18, $20, $28, $30 or $38

The long name of this instruction is Restart; it is basically a call to the given address. The action taken by the rst's depends on what kind of hardware you have. On the TI calculators they are equivalent to some of the most important ROM calls. Another example from the Spectrum: rst $28 activates the built-in floating point calculator. The rst instruction does not affect the flags either.

Handling ports

With these instructions, the CPU can communicate with other pieces of hardware present in the computer. The functions of the ports again depend on the hardware itself.

IN

Syntax: in a,(n) (n is a byte) or in reg8,(c) (where reg8 is A, B, C, D, E, H or L)

Reading from the port marked by the second operand, and storing the result into the first operand. The carry is preserved, N is cleared, P/V is parity and the other flags are affected by definition. There exists an undocumented version as well: in (c) (or in f,(c) depending on what you compile your programs with), which does not store the result anywhere, but still alters the flags.

OUT

Syntax: out (n),a (n is a byte) or out (c),reg8 (where reg8 is A, B, C, D, E, H or L)

Writing the value of the second operand to the port given in the first operand. The flags are preserved. Similarly to in there is an undocumented combination: out (c),0 can be used, too.

INI

There are no operands. Reads the (C) port and writes the result to (HL), then increments HL and decrements B (not BC!). The carry is preserved, the N flag is reset, while S, H and P/V are undefined. Z is set if B becomes zero after decrementing, otherwise it is reset.

IND

The same as ini with the minor difference that HL is decremented.

INIR

This is ini repeated until B becomes zero. Therefore the Z flag is always set on leaving the instruction.

INDR

The same as inir, but the memory is naturally filled backwards.

OUTI

There are no operands. Reads the byte at (HL) and outputs it to the (C) port, then increments HL and decrements B. The carry is preserved, the N flag is reset, while S, H and P/V are undefined. Z is set if B becomes zero after decrementing, otherwise it is reset.

OUTD

The same as outi with the minor difference that HL is decremented.

OTIR

This is outi repeated until B becomes zero. Therefore the Z flag is always set on leaving the instruction.

OTDR

The same as otir, but the memory is naturally filled backwards.

Suspending the execution

These are the two instructions that do almost nothing. Neither of them needs any operands, and they do not alter the flags either.

NOP

This instruction waits for an elementary amount of time: 4 clock cycles, and does nothing else.

HALT

The execution of instructions is suspended and the CPU enters the low power state until an interrupt occurs. Note: when the calculator is switched off, it is actually running a series of halt's while waiting for On to be pressed.

Undocumented instructions

The reason why these instructions were put into the hardware section is that although they were not documented for a long time, they worked because their existence comes from the structure of the inner circuitry of the Z80 processor. Most of these instructions were already listed in the previous sections, but it is useful to see them listed together.

IXH/IXL/IYH/IYL instructions

All the instructions that take advantage of these registers: ld and the 8-bit arithmetic and logical operations (add, sub, xor etc.); these special registers are officially supported in later CPU generations, but you have to be aware that the instructions accessing them are slower than the normal ones. Do not forget that you cannot use them with the shifting, the res and the set instructions!

Dummy port accesses

The in (c)/in f,(c) and out (c),0 instructions.

The SLL instruction

It is important to mention again, that if you use sll in your code, your program will behave unexpectedly on the next generations of the Z80 (e. g. they are redefined in the Z380). Of course, it must work on all the TI calculators and on the ZX Spectrum as well.

The autocopy instructions

The instructions of this group were not yet mentioned. They are based on the shift/set/res instructions. What they do is besides modifying the contents of (ix/iy+n), they copy the result into an 8-bit register (only into A, B, C, D, E, H or L). There exist various notations for these special instructions. If the base instruction was ins ops (ins is sla, sra, sll, srl, rl, rr, rlc, rrc, set or res and ops denotes its operands), the resulting instruction is: ins reg8,ops, ins reg8=ops or ld reg8,ins ops depending on which assembler you use. So for example you can use srl b,(ix+$48) (or srl b=(ix+$48) or ld b,srl (ix+$48)), which is srl (ix+$48) followed by ld b,(ix+$48). Another example: res d,5,(iy-$12) which is res 5,(iy-$12) followed by ld d,(iy-$12). The time needed to execute these instructions is exactly the same as if there was no autocopy! The only drawback is that you can only use them with (ix/iy+n), as I mentioned above.

Back to the index