Z80 instruction-set coverage
zenas covers three classes of instructions, verified by encoding a representative of every instruction family and comparing the bytes against established reference assemblers:
| Class | Forms | Reference |
|---|---|---|
| Documented Z80 | 468 | pasmo and sjasmplus |
| Undocumented IX/IY half registers (IXH/IXL/IYH/IYL) | 48 | pasmo and sjasmplus |
| Z80N (ZX Spectrum Next extensions) | 29 | sjasmplus |
| Total | 545 |
The documented and half-register forms (516 together) assemble byte-for-byte
identically to both pasmo and sjasmplus. The 29 Z80N instructions assemble identically to
sjasmplus, the de facto ZX Spectrum Next assembler and the reference
implementation of the Z80N encoding. Z80N is off by default and enabled with
--next / --cpu=Z80N.
The checks are reproducible:
tools/check_instr_coverage.sh- base Z80 (468 documented + 48 half-register) against a reference assembler (REF=pasmoby default).tools/check_z80n_coverage.sh- the 29 Z80N instructions (31 test forms, including theMUL/MIRRORbare-mnemonic aliases); uses sjasmplus as a live oracle when installed, otherwise the reference bytes intools/z80n_coverage.txt.tools/sjasmplus_compare.sh(alsomake test-sjasmplus) - the optional cross-check that builds sjasmplus from source and compares both sets against it.
The instruction lists are generated by tools/gen_instr_coverage.py
(tools/instr_coverage_list.txt) and held in tools/z80n_coverage.txt.
Covered families
| Family | Examples | Status |
|---|---|---|
| 8-bit load, register/immediate/(HL) | LD A,B, LD A,5, LD A,(HL), LD (HL),A, LD (HL),5 |
complete |
| 8-bit load, extended addressing | LD A,(BC), LD A,(DE), LD A,(nn), LD (nn),A |
complete |
| 16-bit load | LD BC,nn, LD HL,(nn), LD (nn),HL, LD SP,HL |
complete |
| Stack | PUSH/POP BC/DE/HL/AF |
complete |
| ALU register/immediate/(HL) | ADD A,r, ADC A,n, SUB (HL), AND r, XOR r, OR r, CP (HL) |
complete |
| INC/DEC 8-bit and 16-bit | INC r, DEC (HL), INC BC, DEC SP |
complete |
| 16-bit arithmetic | ADD HL,rr, ADC HL,rr, SBC HL,rr |
complete |
| Rotates / shifts | RLC/RRC/RL/RR/SLA/SRA/SRL r/(HL), RLCA/RRCA/RLA/RRA, RLD/RRD |
complete |
| Accumulator/flags | DAA, CPL, NEG, CCF, SCF |
complete |
| Bit ops | BIT/RES/SET b,r, BIT/RES/SET b,(HL) |
complete |
| Jumps / calls / returns | JP nn, JP cc,nn, JP (HL)/(IX)/(IY), JR e, JR cc,e, DJNZ e, CALL nn, CALL cc,nn, RET, RET cc, RETI, RETN |
complete |
| Restart / interrupt mode | RST n, IM 0/1/2 |
complete |
| Exchange | EX DE,HL, EX AF,AF', EXX, EX (SP),HL |
complete |
| Block transfer / search | LDI/LDD/LDIR/LDDR, CPI/CPD/CPIR/CPDR |
complete |
| Block I/O | INI/IND/INIR/INDR, OUTI/OUTD/OTIR/OTDR |
complete |
| Port I/O | IN A,(n), OUT (n),A, IN r,(C), OUT (C),r |
complete |
| Interrupt/refresh registers | LD A,I, LD A,R, LD I,A, LD R,A |
complete |
| IX/IY 16-bit | LD IX,nn, ADD IX,rr, INC/DEC IX, PUSH/POP IX, LD SP,IX, JP (IX) |
complete |
| IX/IY indexed | LD r,(IX+d), LD (IX+d),r, LD (IX+d),n, ADD A,(IX+d), INC/DEC (IX+d), CP (IX+d) |
complete |
| IX/IY half registers (undocumented) | LD IXH,A, LD A,IYH, LD IXH,5, INC IXL, ADD A,IYL, LD IXH,IXL |
complete |
Z80N extensions (--next) |
SWAPNIB, MIRROR, TEST n, BSLA/BSRA/BSRL/BSRF/BRLC DE,B, MUL, ADD rr,A, ADD rr,nn, PUSH nn, OUTINB, NEXTREG, PIXELDN/PIXELAD/SETAE, JP (C), LDIX/LDWS/LDDX/LDIRX/LDPIRX/LDDRX |
complete (opt-in) |
Index displacements accept a constant expression, including symbols
((IX+OFFSET)), evaluated at assembly time and range-checked to a signed byte.
Not implemented
The undocumented CB-prefixed indexed bit/shift forms with a register copy
(e.g. RLC (IX+d),B) and the duplicate SLL/SL1 shift are not encoded; no
target depends on them. Everything in the documented set is covered.
Undocumented IX/IY half registers
IXH/IXL/IYH/IYL are the high and low bytes of the index registers,
accessed via the DD/FD prefix that reinterprets H/L in the following
instruction. Because the single prefix governs the whole instruction, two
combinations are illegal and are rejected (matching a conforming assembler):
- mixing an IX half and an IY half in one instruction (
LD IXH,IYL); and - combining a half register with an indexed memory operand (
LD (IX+d),IXH).
All legal forms - 8-bit load (register/immediate/half-to-half within one index),
INC/DEC, and the ALU group - are encoded with the correct DD/FD prefix.