← back to zen80

Implementation Summary Notes

Current Implementation Status:

The Z80 emulator has matured significantly with comprehensive instruction coverage, accurate flag handling, and proper timing. All major instruction groups are implemented with careful attention to undocumented behaviors.

Key Improvements Since v1:

  1. X/Y Flag Handling: Fixed throughout - now correctly set from result for most operations, from operand for CP, and from WZ high byte for BIT n,(HL)
  2. Interrupt Mode 0: Proper implementation with instruction buffer execution via InterruptController interface
  3. R Register: Correctly incremented on M1 cycles including post-prefix fetches
  4. Prefix Interactions: DD→ED, FD→DD, etc. properly handled with correct cycle additions
  5. Block Instructions: Enhanced flag calculations for INI/IND/OUTI/OUTD with accurate undocumented behavior
  6. IXH/IXL/IYH/IYL: Fully implemented undocumented register access via DD/FD prefixes

Remaining Minor Issues:

  1. ED Undefined Opcodes: Comprehensive switch statement handles most, but could be more elegant
  2. Cycle Verification: VerifyInstructionTiming() exists but only called when DEBUG_TIMING is true
  3. Mode 0 Complexity: While functional, Mode 0 implementation is complex with two-phase execution

Correctly Implemented Features:

  1. All Documented Instructions: Complete Z80 instruction set
  2. Undocumented Instructions: SLL, IXH/IXL/IYH/IYL access, DDCB/FDCB register copy
  3. Undocumented Flags: X and Y flags with proper behavior for all instruction types
  4. Interrupt Handling: All three modes with proper timing and edge detection
  5. WZ Register: Correctly maintained for flag calculations
  6. Prefix Chains: Complex prefix sequences handled correctly
  7. Block Instructions: Full implementation with proper flag calculations

zen80 Z80 Implementation Function Mapping

Implementation Status Legend

Main Instructions (Unprefixed)

Opcode Instruction Coverage Implementation Function Location
00 NOP FULL executeBlock0() case 0, y=0
01 LD BC,nn FULL executeBlock0() case 1, q=0, p=0
02 LD (BC),A FULL executeBlock0() case 2, y=0
03 INC BC FULL executeBlock0() case 3, q=0, p=0
04 INC B FULL executeBlock0() case 4 + inc8()
05 DEC B FULL executeBlock0() case 5 + dec8()
06 LD B,n FULL executeBlock0() case 6
07 RLCA FULL executeBlock0() case 7, y=0 + rlc8()
08 EX AF,AF' FULL executeBlock0() case 0, y=1
09 ADD HL,BC FULL executeBlock0() case 1, q=1 + add16()
0A LD A,(BC) FULL executeBlock0() case 2, y=1
0B DEC BC FULL executeBlock0() case 3, q=1, p=0
0C INC C FULL executeBlock0() case 4 + inc8()
0D DEC C FULL executeBlock0() case 5 + dec8()
0E LD C,n FULL executeBlock0() case 6
0F RRCA FULL executeBlock0() case 7, y=1 + rrc8()
10 DJNZ d FULL executeBlock0() case 0, y=2
11 LD DE,nn FULL executeBlock0() case 1, q=0, p=1
12 LD (DE),A FULL executeBlock0() case 2, y=2
13 INC DE FULL executeBlock0() case 3, q=0, p=1
14 INC D FULL executeBlock0() case 4 + inc8()
15 DEC D FULL executeBlock0() case 5 + dec8()
16 LD D,n FULL executeBlock0() case 6
17 RLA FULL executeBlock0() case 7, y=2 + rl8()
18 JR d FULL executeBlock0() case 0, y=3
19 ADD HL,DE FULL executeBlock0() case 1, q=1 + add16()
1A LD A,(DE) FULL executeBlock0() case 2, y=3
1B DEC DE FULL executeBlock0() case 3, q=1, p=1
1C INC E FULL executeBlock0() case 4 + inc8()
1D DEC E FULL executeBlock0() case 5 + dec8()
1E LD E,n FULL executeBlock0() case 6
1F RRA FULL executeBlock0() case 7, y=3 + rr8()
20 JR NZ,d FULL executeBlock0() case 0, y=4 + testCondition()
21 LD HL,nn FULL executeBlock0() case 1, q=0, p=2
22 LD (nn),HL FULL executeBlock0() case 2, y=4
23 INC HL FULL executeBlock0() case 3, q=0, p=2
24 INC H FULL executeBlock0() case 4 + inc8()
25 DEC H FULL executeBlock0() case 5 + dec8()
26 LD H,n FULL executeBlock0() case 6
27 DAA FULL executeBlock0() case 7, y=4 + daa()
28 JR Z,d FULL executeBlock0() case 0, y=5 + testCondition()
29 ADD HL,HL FULL executeBlock0() case 1, q=1 + add16()
2A LD HL,(nn) FULL executeBlock0() case 2, y=5
2B DEC HL FULL executeBlock0() case 3, q=1, p=2
2C INC L FULL executeBlock0() case 4 + inc8()
2D DEC L FULL executeBlock0() case 5 + dec8()
2E LD L,n FULL executeBlock0() case 6
2F CPL FULL executeBlock0() case 7, y=5 (X/Y from A)
30 JR NC,d FULL executeBlock0() case 0, y=6 + testCondition()
31 LD SP,nn FULL executeBlock0() case 1, q=0, p=3
32 LD (nn),A FULL executeBlock0() case 2, y=6
33 INC SP FULL executeBlock0() case 3, q=0, p=3
34 INC (HL) FULL executeBlock0() case 4, y=6 + inc8()
35 DEC (HL) FULL executeBlock0() case 5, y=6 + dec8()
36 LD (HL),n FULL executeBlock0() case 6, y=6
37 SCF FULL executeBlock0() case 7, y=6 (X/Y from A)
38 JR C,d FULL executeBlock0() case 0, y=7 + testCondition()
39 ADD HL,SP FULL executeBlock0() case 1, q=1 + add16()
3A LD A,(nn) FULL executeBlock0() case 2, y=7
3B DEC SP FULL executeBlock0() case 3, q=1, p=3
3C INC A FULL executeBlock0() case 4 + inc8()
3D DEC A FULL executeBlock0() case 5 + dec8()
3E LD A,n FULL executeBlock0() case 6
3F CCF FULL executeBlock0() case 7, y=7 (X/Y from A)
40-75,77-7F LD r,r' FULL executeBlock1()
76 HALT FULL executeBlock1() opcode=0x76
80-87 ADD A,r FULL executeBlock2() y=0 + add8()
88-8F ADC A,r FULL executeBlock2() y=1 + adc8()
90-97 SUB r FULL executeBlock2() y=2 + sub8()
98-9F SBC A,r FULL executeBlock2() y=3 + sbc8()
A0-A7 AND r FULL executeBlock2() y=4 + and8()
A8-AF XOR r FULL executeBlock2() y=5 + xor8()
B0-B7 OR r FULL executeBlock2() y=6 + or8()
B8-BF CP r FULL executeBlock2() y=7 + cp8() (X/Y from operand)
C0-FF Various FULL executeBlock3() all cases

CB-Prefixed Instructions

Opcode Range Instruction Coverage Implementation Function Location
CB 00-07 RLC r FULL executeCB() x=0, y=0 + rlc8()
CB 08-0F RRC r FULL executeCB() x=0, y=1 + rrc8()
CB 10-17 RL r FULL executeCB() x=0, y=2 + rl8()
CB 18-1F RR r FULL executeCB() x=0, y=3 + rr8()
CB 20-27 SLA r FULL executeCB() x=0, y=4 + sla8()
CB 28-2F SRA r FULL executeCB() x=0, y=5 + sra8()
CB 30-37 SLL r UNDOC executeCB() x=0, y=6 + sll8()
CB 38-3F SRL r FULL executeCB() x=0, y=7 + srl8()
CB 40-7F BIT n,r FULL executeCB() x=1 + bit() (WZ properly set for (HL), X/Y from WZ high)
CB 80-BF RES n,r FULL executeCB() x=2
CB C0-FF SET n,r FULL executeCB() x=3

ED-Prefixed Instructions

Opcode Instruction Coverage Implementation Function Location
ED 00-3F Undefined NOP executeED() explicit switch cases
ED 40 IN B,(C) FULL executeED() x=1, z=0, y=0
ED 41 OUT (C),B FULL executeED() x=1, z=1, y=0
ED 42 SBC HL,BC FULL executeED() x=1, z=2, q=0 + sbc16()
ED 43 LD (nn),BC FULL executeED() x=1, z=3, q=0
ED 44 NEG FULL executeED() x=1, z=4 + neg()
ED 45 RETN FULL executeED() x=1, z=5 (IFF2→IFF1)
ED 46 IM 0 FULL executeED() x=1, z=6, y=0
ED 47 LD I,A FULL executeED() x=1, z=7, y=0
ED 48 IN C,(C) FULL executeED() x=1, z=0, y=1
ED 49 OUT (C),C FULL executeED() x=1, z=1, y=1
ED 4A ADC HL,BC FULL executeED() x=1, z=2, q=1 + adc16()
ED 4B LD BC,(nn) FULL executeED() x=1, z=3, q=1
ED 4C NEG FULL executeED() duplicate handling
ED 4D RETI FULL executeED() x=1, z=5
ED 4E IM 0/1 FULL executeED() duplicate handling
ED 4F LD R,A FULL executeED() x=1, z=7, y=1
ED 50-5F Various FULL executeED() all implemented
ED 60-6F Various FULL executeED() all implemented
ED 67 RRD FULL executeED() + rrd()
ED 6F RLD FULL executeED() + rld()
ED 70-7F Various FULL executeED() all implemented
ED 80-9F Undefined NOP executeED() explicit switch cases
ED A0 LDI ENHANCED ldi() with complex X/Y flag calculation
ED A1 CPI ENHANCED cpi() with complex X/Y flag calculation
ED A2 INI ENHANCED ini() with full undocumented flag behavior
ED A3 OUTI ENHANCED outi() with full undocumented flag behavior
ED A4-A7 Undefined NOP executeED() explicit switch cases
ED A8 LDD ENHANCED ldd() with complex X/Y flag calculation
ED A9 CPD ENHANCED cpd() with complex X/Y flag calculation
ED AA IND ENHANCED ind() with full undocumented flag behavior
ED AB OUTD ENHANCED outd() with full undocumented flag behavior
ED AC-AF Undefined NOP executeED() explicit switch cases
ED B0 LDIR ENHANCED ldir() with repeat logic and R increment
ED B1 CPIR ENHANCED cpir() with repeat logic and R increment
ED B2 INIR ENHANCED inir() with repeat logic and R increment
ED B3 OTIR ENHANCED otir() with repeat logic and R increment
ED B4-B7 Undefined NOP executeED() explicit switch cases
ED B8 LDDR ENHANCED lddr() with repeat logic and R increment
ED B9 CPDR ENHANCED cpdr() with repeat logic and R increment
ED BA INDR ENHANCED indr() with repeat logic and R increment
ED BB OTDR ENHANCED otdr() with repeat logic and R increment
ED BC-FF Undefined NOP executeED() explicit switch cases

DD-Prefixed (IX) Instructions

Opcode Instruction Coverage Implementation Function Location
DD 09 ADD IX,BC FULL executeDDFDInstruction() with HL substitution
DD 19 ADD IX,DE FULL executeDDFDInstruction() with HL substitution
DD 21 LD IX,nn FULL executeDDFDInstruction() with HL substitution
DD 22 LD (nn),IX FULL executeDDFDInstruction() with HL substitution
DD 23 INC IX FULL executeDDFDInstruction() with HL substitution
DD 24 INC IXH UNDOC handleIXHIXL() + inc8()
DD 25 DEC IXH UNDOC handleIXHIXL() + dec8()
DD 26 LD IXH,n UNDOC handleIXHIXL()
DD 29 ADD IX,IX FULL executeDDFDInstruction() with HL substitution
DD 2A LD IX,(nn) FULL executeDDFDInstruction() with HL substitution
DD 2B DEC IX FULL executeDDFDInstruction() with HL substitution
DD 2C INC IXL UNDOC handleIXHIXL() + inc8()
DD 2D DEC IXL UNDOC handleIXHIXL() + dec8()
DD 2E LD IXL,n UNDOC handleIXHIXL()
DD 34 INC (IX+d) FULL executeDD() special case handling
DD 35 DEC (IX+d) FULL executeDD() special case handling
DD 36 LD (IX+d),n FULL executeDD() special case handling
DD 39 ADD IX,SP FULL executeDDFDInstruction() with HL substitution
DD 44-45,4C-4D,54-55,5C-5D,60-65,67-6D LD with IXH/IXL UNDOC handleIXHIXL() full register access
DD 46-7E LD r,(IX+d) FULL executeDD() special case handling
DD 70-77 LD (IX+d),r FULL executeDD() special case handling
DD 84-85,8C-8D,94-95,9C-9D,A4-A5,AC-AD,B4-B5,BC-BD ALU with IXH/IXL UNDOC handleIXHIXL() full ALU operations
DD 86-BE ALU ops (IX+d) FULL executeDD() special case handling
DD CB DDCB prefix HANDLED executeDD()executeDDCB()
DD DD Double DD NOP executeDD() returns 4
DD E1 POP IX FULL executeDDFDInstruction() with HL substitution
DD E3 EX (SP),IX FULL executeDDFDInstruction() with HL substitution
DD E5 PUSH IX FULL executeDDFDInstruction() with HL substitution
DD E9 JP (IX) FULL executeDDFDInstruction() with HL substitution
DD ED ED after DD HANDLED executeDD()executeED() + 4
DD F9 LD SP,IX FULL executeDDFDInstruction() with HL substitution
DD FD FD after DD HANDLED executeDD()executeFD() + 4

FD-Prefixed (IY) Instructions

Opcode Instruction Coverage Implementation Function Location
FD 24 INC IYH UNDOC handleIYHIYL() + inc8()
FD 25 DEC IYH UNDOC handleIYHIYL() + dec8()
FD 26 LD IYH,n UNDOC handleIYHIYL()
FD 2C INC IYL UNDOC handleIYHIYL() + inc8()
FD 2D DEC IYL UNDOC handleIYHIYL() + dec8()
FD 2E LD IYL,n UNDOC handleIYHIYL()
FD 44-45,4C-4D,54-55,5C-5D,60-65,67-6D LD with IYH/IYL UNDOC handleIYHIYL() full register access
FD 84-85,8C-8D,94-95,9C-9D,A4-A5,AC-AD,B4-B5,BC-BD ALU with IYH/IYL UNDOC handleIYHIYL() full ALU operations
FD 09-F9 All IY ops FULL executeFD() mirrors executeDD() logic
FD CB FDCB prefix HANDLED executeFD()executeFDCB()
FD DD DD after FD HANDLED executeFD()executeDD() + 4
FD ED ED after FD HANDLED executeFD()executeED() + 4
FD FD Double FD NOP executeFD() returns 4

DDCB-Prefixed Instructions

Opcode Range Instruction Coverage Implementation Function Location
DDCB d 00-3F Shift/Rotate (IX+d) FULL executeDDFDCBOperation() x=0
DDCB d 40-7F BIT n,(IX+d) FULL executeDDFDCBOperation() x=1 (X/Y from WZ high)
DDCB d 80-BF RES n,(IX+d) FULL executeDDFDCBOperation() x=2
DDCB d C0-FF SET n,(IX+d) FULL executeDDFDCBOperation() x=3
DDCB undoc Register copy UNDOC executeDDFDCBOperation() copies result to register

FDCB-Prefixed Instructions

Opcode Range Instruction Coverage Implementation Function Location
FDCB d 00-FF All (IY+d) bit ops FULL executeDDFDCBOperation()
FDCB undoc Register copy UNDOC executeDDFDCBOperation() copies result to register

Support Functions

Function Purpose File Notes
execute() Main instruction decoder decode.go Tracks prefix for verification
executeBlock0() Opcodes 0x00-0x3F decoder decode.go
executeBlock1() Opcodes 0x40-0x7F decoder decode.go
executeBlock2() Opcodes 0x80-0xBF decoder decode.go
executeBlock3() Opcodes 0xC0-0xFF decoder decode.go
executeCB() CB prefix handler prefix_cb.go Fixed: WZ set for (HL), X/Y from WZ high for BIT
executeED() ED prefix handler prefix_ed.go Comprehensive undefined opcode handling
executeDD() DD prefix handler prefix_ddfd.go Full IXH/IXL register access implemented
executeFD() FD prefix handler prefix_ddfd.go Full IYH/IYL register access implemented
executeDDCB() DDCB prefix handler prefix_ddfd.go R not incremented (correct - not M1)
executeFDCB() FDCB prefix handler prefix_ddfd.go R not incremented (correct - not M1)
executeDDFDInstruction() IX/IY instruction executor prefix_ddfd.go
executeDDFDCBOperation() DDCB/FDCB operation executor prefix_ddfd.go
executeBlockInstruction() ED block instruction dispatcher prefix_ed.go
handleIXHIXL() IXH/IXL register access prefix_ddfd.go Full implementation
handleIYHIYL() IYH/IYL register access prefix_ddfd.go Full implementation
getRegisterForIX() IX register mapping prefix_ddfd.go Maps H→IXH, L→IXL
getRegisterForIY() IY register mapping prefix_ddfd.go Maps H→IYH, L→IYL
getIXHIXLCycles() IXH/IXL timing prefix_ddfd.go
getIYHIYLCycles() IYH/IYL timing prefix_ddfd.go
add8(), adc8(), sub8(), sbc8() 8-bit arithmetic alu.go Fixed: X/Y from result
and8(), or8(), xor8() 8-bit logic alu.go Fixed: X/Y from result
cp8() Compare alu.go Fixed: X/Y from operand
inc8(), dec8() 8-bit increment/decrement alu.go Fixed: X/Y from result
add16(), adc16(), sbc16() 16-bit arithmetic alu.go Fixed: X/Y from high byte, WZ=HL+1
rlc8(), rrc8(), rl8(), rr8() Rotation operations alu.go Fixed: X/Y from result
sla8(), sra8(), sll8(), srl8() Shift operations alu.go Fixed: X/Y from result
daa() Decimal adjust alu.go Fixed: X/Y from result
neg() Negate accumulator prefix_ed.go
rrd(), rld() Rotate decimal prefix_ed.go X/Y from A, WZ=HL+1
bit() Bit test prefix_cb.go X/Y from value (overridden for (HL))
ldi(), ldd(), ldir(), lddr() Block transfer prefix_ed.go Enhanced: Complex X/Y flag calculation
cpi(), cpd(), cpir(), cpdr() Block search prefix_ed.go Enhanced: Complex X/Y flag calculation
ini(), ind(), inir(), indr() Block input prefix_ed.go Enhanced: Full undocumented flag behavior
outi(), outd(), otir(), otdr() Block output prefix_ed.go Enhanced: Full undocumented flag behavior
testCondition() Conditional test z80.go
getRegister8() Register access decode.go
involvesHL() HL instruction check prefix_ddfd.go Correctly identifies HL-using instructions
parity() Parity calculation alu.go
push(), pop() Stack operations z80.go
fetchByte(), fetchWord() Memory fetch z80.go Supports Mode 0 buffer
readWord(), writeWord() Memory access z80.go
handleInterrupts() Interrupt handler z80.go Full Mode 0 with instruction buffer
executeMode0Instruction() Mode 0 executor z80.go Two-phase execution
VerifyInstructionTiming() Cycle verification timing_fixes.go Called when DEBUG_TIMING=true

Special Registers and Features

Feature Coverage Implementation Function Location
A,F,B,C,D,E,H,L FULL Direct fields in Z80 struct
A',F',B',C',D',E',H',L' FULL Direct fields in Z80 struct
IXH,IXL UNDOC Direct fields, full opcode access via DD prefix
IYH,IYL UNDOC Direct fields, full opcode access via FD prefix
I,R FULL Direct fields, R increments on M1
SP,PC FULL Direct fields in Z80 struct
WZ (MEMPTR) FULL Direct field, properly maintained
IFF1,IFF2 FULL Direct fields in Z80 struct
IM FULL Direct field in Z80 struct
Halted FULL Direct field in Z80 struct
pendingEI,pendingDI FULL Direct fields in Z80 struct
NMI,INT FULL Direct fields in Z80 struct
nmiEdge FULL Edge detection for NMI
mode0Buffer FULL Instruction buffer for Mode 0
mode0Index FULL Current position in Mode 0 buffer
mode0Active FULL Mode 0 execution state
M1Hook FULL Debug hook for M1 cycles

Interrupt Implementation

Feature Coverage Implementation Function Location
NMI handling FULL handleInterrupts() edge-triggered
INT Mode 0 FULL handleInterrupts() with InterruptController interface
INT Mode 1 FULL handleInterrupts() jumps to 0x0038
INT Mode 2 FULL handleInterrupts() vectored via I register
EI delay FULL Step() with pendingEI flag
DI delay FULL Step() with pendingDI flag
R increment on INT FULL Incremented for interrupt acknowledge M1

Flag Implementation

Flag Bit Coverage Implementation Functions
Carry (C) 0 FULL All ALU functions
Add/Subtract (N) 1 FULL All ALU functions
Parity/Overflow (P/V) 2 FULL Context-dependent in ALU
X (undocumented) 3 UNDOC Correct behavior throughout
Half-carry (H) 4 FULL All ALU functions
Y (undocumented) 5 UNDOC Correct behavior throughout
Zero (Z) 6 FULL All ALU functions
Sign (S) 7 FULL All ALU functions

Test Coverage Analysis

Test Category Status Coverage Notes
Unit Tests Comprehensive All instruction groups tested
Flag Tests Complete Including undocumented X/Y flags
Timing Tests Extensive Conditional branches, block ops
Interrupt Tests Full All modes, EI delay, HALT interaction
Prefix Tests Complete DD/FD/ED/CB and combinations
Block Op Tests Enhanced Complex flag calculations verified
Integration Tests Multiple ZEXDOC, Spectrum ROM
Edge Cases Well covered R register, WZ, prefix chains

Performance and Quality Metrics

Metric Status Details
Instruction Coverage 100% All documented Z80 instructions
Undocumented Coverage High Major undocumented features implemented
Test Pass Rate 100% All unit tests passing
ZEXDOC Compatibility Runs CP/M test suite
Spectrum ROM Boot Successfully boots 48K and 128K ROMs
Debugging Support M1 hooks, cycle verification

Summary

The zen80 Z80 emulator has evolved into a mature, comprehensive implementation with: - Complete instruction set: All documented instructions plus major undocumented features - Accurate flag handling: Including proper X/Y flag behavior for all cases - Full interrupt support: All three modes with correct behavior - Extensive testing: Unit tests, integration tests, and real-world ROM execution

The emulator successfully runs both synthetic test suites (ZEXDOC) and real-world software (Spectrum ROMs), demonstrating both theoretical correctness and practical compatibility.