Public Access
1
0

First split

This commit is contained in:
2025-09-25 14:18:22 +03:00
parent d85961bea5
commit 34f1254a85
17 changed files with 11805 additions and 1 deletions

View File

@@ -1,2 +1,57 @@
# emuz80disasmgo # Z80 Disassembler
A Go package for disassembling Z80 processor instructions.
## Overview
This package provides a Z80 disassembler implementation that can decode Z80 machine code into human-readable assembly mnemonics. It supports all standard Z80 instructions including:
- Unprefixed instructions
- CB-prefixed instructions (bit manipulation, rotation, and shifting)
- DD-prefixed instructions (IX register indexing)
- ED-prefixed instructions (extended instructions)
- FD-prefixed instructions (IY register indexing)
## Installation
```bash
go get github.com/kiltum/emuz80/z80disasm
```
## Usage
```go
package main
import (
"fmt"
"github.com/kiltum/emuz80/z80disasm"
)
func main() {
// Create a new disassembler
d := disasm.New()
// Decode a simple instruction (NOP)
data := []byte{0x00}
instruction, err := d.Decode(data)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Mnemonic: %s\n", instruction.Mnemonic)
fmt.Printf("Length: %d bytes\n", instruction.Length)
}
```
## Features
- Complete Z80 instruction set support
- Detailed instruction information including length and address operands
- Error handling for malformed or incomplete instructions
- Comprehensive test suite
## License
This project is licensed under the MIT License.

125
cb_test.go Normal file
View File

@@ -0,0 +1,125 @@
// Package disasm provides tests for the Z80 disassembler implementation
package disasm
import (
"testing"
)
// TestDecodeCB tests decoding of CB-prefixed Z80 instructions
func TestDecodeCB(t *testing.T) {
d := New()
tests := []struct {
name string
data []byte
expected Instruction
hasError bool
}{
{
name: "RLC B",
data: []byte{0xCB, 0x00},
expected: Instruction{
Mnemonic: "RLC B",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RLC C",
data: []byte{0xCB, 0x01},
expected: Instruction{
Mnemonic: "RLC C",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RLC D",
data: []byte{0xCB, 0x02},
expected: Instruction{
Mnemonic: "RLC D",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RLC E",
data: []byte{0xCB, 0x03},
expected: Instruction{
Mnemonic: "RLC E",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RLC H",
data: []byte{0xCB, 0x04},
expected: Instruction{
Mnemonic: "RLC H",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RLC L",
data: []byte{0xCB, 0x05},
expected: Instruction{
Mnemonic: "RLC L",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RLC (HL)",
data: []byte{0xCB, 0x06},
expected: Instruction{
Mnemonic: "RLC (HL)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RLC A",
data: []byte{0xCB, 0x07},
expected: Instruction{
Mnemonic: "RLC A",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "Insufficient data for CB prefix",
data: []byte{0xCB},
hasError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := d.Decode(tt.data)
if tt.hasError {
if err == nil {
t.Errorf("expected error but got none")
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.Mnemonic != tt.expected.Mnemonic {
t.Errorf("mnemonic mismatch: got %q, want %q", result.Mnemonic, tt.expected.Mnemonic)
}
if result.Length != tt.expected.Length {
t.Errorf("length mismatch: got %d, want %d", result.Length, tt.expected.Length)
}
if result.Address != tt.expected.Address {
t.Errorf("address mismatch: got 0x%04X, want 0x%04X", result.Address, tt.expected.Address)
}
})
}
}

823
dd_test.go Normal file
View File

@@ -0,0 +1,823 @@
// Package disasm provides tests for the Z80 disassembler implementation
package disasm
import (
"testing"
)
// TestDecodeDD tests decoding of DD-prefixed Z80 instructions
func TestDecodeDD(t *testing.T) {
d := New()
tests := []struct {
name string
data []byte
expected Instruction
hasError bool
}{
{
name: "LD IX, nn",
data: []byte{0xDD, 0x21, 0x34, 0x12},
expected: Instruction{
Mnemonic: "LD IX, $1234",
Length: 4,
Address: 0x1234,
},
},
{
name: "ADD IX, BC",
data: []byte{0xDD, 0x09},
expected: Instruction{
Mnemonic: "ADD IX, BC",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADD IX, DE",
data: []byte{0xDD, 0x19},
expected: Instruction{
Mnemonic: "ADD IX, DE",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD (nn), IX",
data: []byte{0xDD, 0x22, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD ($3412), IX",
Length: 4,
Address: 0x3412,
},
},
{
name: "INC IX",
data: []byte{0xDD, 0x23},
expected: Instruction{
Mnemonic: "INC IX",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "INC IXH",
data: []byte{0xDD, 0x24},
expected: Instruction{
Mnemonic: "INC IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "DEC IXH",
data: []byte{0xDD, 0x25},
expected: Instruction{
Mnemonic: "DEC IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXH, n",
data: []byte{0xDD, 0x26, 0x42},
expected: Instruction{
Mnemonic: "LD IXH, $42",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "ADD IX, IX",
data: []byte{0xDD, 0x29},
expected: Instruction{
Mnemonic: "ADD IX, IX",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IX, (nn)",
data: []byte{0xDD, 0x2A, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD IX, ($3412)",
Length: 4,
Address: 0x3412,
},
},
{
name: "DEC IX",
data: []byte{0xDD, 0x2B},
expected: Instruction{
Mnemonic: "DEC IX",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "INC IXL",
data: []byte{0xDD, 0x2C},
expected: Instruction{
Mnemonic: "INC IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "DEC IXL",
data: []byte{0xDD, 0x2D},
expected: Instruction{
Mnemonic: "DEC IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXL, n",
data: []byte{0xDD, 0x2E, 0x42},
expected: Instruction{
Mnemonic: "LD IXL, $42",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "INC (IX+d)",
data: []byte{0xDD, 0x34, 0x05},
expected: Instruction{
Mnemonic: "INC (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "DEC (IX+d)",
data: []byte{0xDD, 0x35, 0x05},
expected: Instruction{
Mnemonic: "DEC (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IX+d), n",
data: []byte{0xDD, 0x36, 0x05, 0x42},
expected: Instruction{
Mnemonic: "LD (IX+$05), $42",
Length: 4,
Address: 0xFFFF,
},
},
{
name: "ADD IX, SP",
data: []byte{0xDD, 0x39},
expected: Instruction{
Mnemonic: "ADD IX, SP",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD B, IXH",
data: []byte{0xDD, 0x44},
expected: Instruction{
Mnemonic: "LD B, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD B, IXL",
data: []byte{0xDD, 0x45},
expected: Instruction{
Mnemonic: "LD B, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD B, (IX+d)",
data: []byte{0xDD, 0x46, 0x05},
expected: Instruction{
Mnemonic: "LD B, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD C, IXH",
data: []byte{0xDD, 0x4C},
expected: Instruction{
Mnemonic: "LD C, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD C, IXL",
data: []byte{0xDD, 0x4D},
expected: Instruction{
Mnemonic: "LD C, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD C, (IX+d)",
data: []byte{0xDD, 0x4E, 0x05},
expected: Instruction{
Mnemonic: "LD C, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD D, IXH",
data: []byte{0xDD, 0x54},
expected: Instruction{
Mnemonic: "LD D, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD D, IXL",
data: []byte{0xDD, 0x55},
expected: Instruction{
Mnemonic: "LD D, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD D, (IX+d)",
data: []byte{0xDD, 0x56, 0x05},
expected: Instruction{
Mnemonic: "LD D, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD E, IXH",
data: []byte{0xDD, 0x5C},
expected: Instruction{
Mnemonic: "LD E, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD E, IXL",
data: []byte{0xDD, 0x5D},
expected: Instruction{
Mnemonic: "LD E, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD E, (IX+d)",
data: []byte{0xDD, 0x5E, 0x05},
expected: Instruction{
Mnemonic: "LD E, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD IXH, B",
data: []byte{0xDD, 0x60},
expected: Instruction{
Mnemonic: "LD IXH, B",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXH, C",
data: []byte{0xDD, 0x61},
expected: Instruction{
Mnemonic: "LD IXH, C",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXH, D",
data: []byte{0xDD, 0x62},
expected: Instruction{
Mnemonic: "LD IXH, D",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXH, E",
data: []byte{0xDD, 0x63},
expected: Instruction{
Mnemonic: "LD IXH, E",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXH, IXH",
data: []byte{0xDD, 0x64},
expected: Instruction{
Mnemonic: "LD IXH, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXH, IXL",
data: []byte{0xDD, 0x65},
expected: Instruction{
Mnemonic: "LD IXH, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD H, (IX+d)",
data: []byte{0xDD, 0x66, 0x05},
expected: Instruction{
Mnemonic: "LD H, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD IXH, A",
data: []byte{0xDD, 0x67},
expected: Instruction{
Mnemonic: "LD IXH, A",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXL, B",
data: []byte{0xDD, 0x68},
expected: Instruction{
Mnemonic: "LD IXL, B",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXL, C",
data: []byte{0xDD, 0x69},
expected: Instruction{
Mnemonic: "LD IXL, C",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXL, D",
data: []byte{0xDD, 0x6A},
expected: Instruction{
Mnemonic: "LD IXL, D",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXL, E",
data: []byte{0xDD, 0x6B},
expected: Instruction{
Mnemonic: "LD IXL, E",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXL, IXH",
data: []byte{0xDD, 0x6C},
expected: Instruction{
Mnemonic: "LD IXL, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IXL, IXL",
data: []byte{0xDD, 0x6D},
expected: Instruction{
Mnemonic: "LD IXL, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD L, (IX+d)",
data: []byte{0xDD, 0x6E, 0x05},
expected: Instruction{
Mnemonic: "LD L, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD IXL, A",
data: []byte{0xDD, 0x6F},
expected: Instruction{
Mnemonic: "LD IXL, A",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD (IX+d), B",
data: []byte{0xDD, 0x70, 0x05},
expected: Instruction{
Mnemonic: "LD (IX+$05), B",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IX+d), C",
data: []byte{0xDD, 0x71, 0x05},
expected: Instruction{
Mnemonic: "LD (IX+$05), C",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IX+d), D",
data: []byte{0xDD, 0x72, 0x05},
expected: Instruction{
Mnemonic: "LD (IX+$05), D",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IX+d), E",
data: []byte{0xDD, 0x73, 0x05},
expected: Instruction{
Mnemonic: "LD (IX+$05), E",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IX+d), H",
data: []byte{0xDD, 0x74, 0x05},
expected: Instruction{
Mnemonic: "LD (IX+$05), H",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IX+d), L",
data: []byte{0xDD, 0x75, 0x05},
expected: Instruction{
Mnemonic: "LD (IX+$05), L",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IX+d), A",
data: []byte{0xDD, 0x77, 0x05},
expected: Instruction{
Mnemonic: "LD (IX+$05), A",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD A, IXH",
data: []byte{0xDD, 0x7C},
expected: Instruction{
Mnemonic: "LD A, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD A, IXL",
data: []byte{0xDD, 0x7D},
expected: Instruction{
Mnemonic: "LD A, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD A, (IX+d)",
data: []byte{0xDD, 0x7E, 0x05},
expected: Instruction{
Mnemonic: "LD A, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "ADD A, IXH",
data: []byte{0xDD, 0x84},
expected: Instruction{
Mnemonic: "ADD A, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADD A, IXL",
data: []byte{0xDD, 0x85},
expected: Instruction{
Mnemonic: "ADD A, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADD A, (IX+d)",
data: []byte{0xDD, 0x86, 0x05},
expected: Instruction{
Mnemonic: "ADD A, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "ADC A, IXH",
data: []byte{0xDD, 0x8C},
expected: Instruction{
Mnemonic: "ADC A, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADC A, IXL",
data: []byte{0xDD, 0x8D},
expected: Instruction{
Mnemonic: "ADC A, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADC A, (IX+d)",
data: []byte{0xDD, 0x8E, 0x05},
expected: Instruction{
Mnemonic: "ADC A, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "SUB IXH",
data: []byte{0xDD, 0x94},
expected: Instruction{
Mnemonic: "SUB IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SUB IXL",
data: []byte{0xDD, 0x95},
expected: Instruction{
Mnemonic: "SUB IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SUB (IX+d)",
data: []byte{0xDD, 0x96, 0x05},
expected: Instruction{
Mnemonic: "SUB (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "SBC A, IXH",
data: []byte{0xDD, 0x9C},
expected: Instruction{
Mnemonic: "SBC A, IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SBC A, IXL",
data: []byte{0xDD, 0x9D},
expected: Instruction{
Mnemonic: "SBC A, IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SBC A, (IX+d)",
data: []byte{0xDD, 0x9E, 0x05},
expected: Instruction{
Mnemonic: "SBC A, (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "AND IXH",
data: []byte{0xDD, 0xA4},
expected: Instruction{
Mnemonic: "AND IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "AND IXL",
data: []byte{0xDD, 0xA5},
expected: Instruction{
Mnemonic: "AND IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "AND (IX+d)",
data: []byte{0xDD, 0xA6, 0x05},
expected: Instruction{
Mnemonic: "AND (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "XOR IXH",
data: []byte{0xDD, 0xAC},
expected: Instruction{
Mnemonic: "XOR IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "XOR IXL",
data: []byte{0xDD, 0xAD},
expected: Instruction{
Mnemonic: "XOR IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "XOR (IX+d)",
data: []byte{0xDD, 0xAE, 0x05},
expected: Instruction{
Mnemonic: "XOR (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "OR IXH",
data: []byte{0xDD, 0xB4},
expected: Instruction{
Mnemonic: "OR IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OR IXL",
data: []byte{0xDD, 0xB5},
expected: Instruction{
Mnemonic: "OR IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OR (IX+d)",
data: []byte{0xDD, 0xB6, 0x05},
expected: Instruction{
Mnemonic: "OR (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "CP IXH",
data: []byte{0xDD, 0xBC},
expected: Instruction{
Mnemonic: "CP IXH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "CP IXL",
data: []byte{0xDD, 0xBD},
expected: Instruction{
Mnemonic: "CP IXL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "CP (IX+d)",
data: []byte{0xDD, 0xBE, 0x05},
expected: Instruction{
Mnemonic: "CP (IX+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "POP IX",
data: []byte{0xDD, 0xE1},
expected: Instruction{
Mnemonic: "POP IX",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "EX (SP), IX",
data: []byte{0xDD, 0xE3},
expected: Instruction{
Mnemonic: "EX (SP), IX",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "PUSH IX",
data: []byte{0xDD, 0xE5},
expected: Instruction{
Mnemonic: "PUSH IX",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "JP (IX)",
data: []byte{0xDD, 0xE9},
expected: Instruction{
Mnemonic: "JP (IX)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD SP, IX",
data: []byte{0xDD, 0xF9},
expected: Instruction{
Mnemonic: "LD SP, IX",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "Insufficient data for DD prefix",
data: []byte{0xDD},
hasError: true,
},
{
name: "Insufficient data for LD IX, nn",
data: []byte{0xDD, 0x21, 0x34},
hasError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := d.Decode(tt.data)
if tt.hasError {
if err == nil {
t.Errorf("expected error but got none")
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.Mnemonic != tt.expected.Mnemonic {
t.Errorf("mnemonic mismatch: got %q, want %q", result.Mnemonic, tt.expected.Mnemonic)
}
if result.Length != tt.expected.Length {
t.Errorf("length mismatch: got %d, want %d", result.Length, tt.expected.Length)
}
if result.Address != tt.expected.Address {
t.Errorf("address mismatch: got 0x%04X, want 0x%04X", result.Address, tt.expected.Address)
}
})
}
}

2399
ddcb_test.go Normal file

File diff suppressed because it is too large Load Diff

554
decode_cb.go Normal file
View File

@@ -0,0 +1,554 @@
package disasm
import (
"fmt"
)
// decodeCB decodes CB-prefixed instructions
func (d *Disassembler) decodeCB(data []byte) (*Instruction, error) {
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for CB prefix")
}
opcode := data[1]
// Handle CB prefixed instructions
switch opcode {
// RLC r / RLC (HL)
case 0x00:
return &Instruction{Mnemonic: "RLC B", Length: 2, Address: 0xFFFF}, nil
case 0x01:
return &Instruction{Mnemonic: "RLC C", Length: 2, Address: 0xFFFF}, nil
case 0x02:
return &Instruction{Mnemonic: "RLC D", Length: 2, Address: 0xFFFF}, nil
case 0x03:
return &Instruction{Mnemonic: "RLC E", Length: 2, Address: 0xFFFF}, nil
case 0x04:
return &Instruction{Mnemonic: "RLC H", Length: 2, Address: 0xFFFF}, nil
case 0x05:
return &Instruction{Mnemonic: "RLC L", Length: 2, Address: 0xFFFF}, nil
case 0x06:
return &Instruction{Mnemonic: "RLC (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x07:
return &Instruction{Mnemonic: "RLC A", Length: 2, Address: 0xFFFF}, nil
// RRC r / RRC (HL)
case 0x08:
return &Instruction{Mnemonic: "RRC B", Length: 2, Address: 0xFFFF}, nil
case 0x09:
return &Instruction{Mnemonic: "RRC C", Length: 2, Address: 0xFFFF}, nil
case 0x0A:
return &Instruction{Mnemonic: "RRC D", Length: 2, Address: 0xFFFF}, nil
case 0x0B:
return &Instruction{Mnemonic: "RRC E", Length: 2, Address: 0xFFFF}, nil
case 0x0C:
return &Instruction{Mnemonic: "RRC H", Length: 2, Address: 0xFFFF}, nil
case 0x0D:
return &Instruction{Mnemonic: "RRC L", Length: 2, Address: 0xFFFF}, nil
case 0x0E:
return &Instruction{Mnemonic: "RRC (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x0F:
return &Instruction{Mnemonic: "RRC A", Length: 2, Address: 0xFFFF}, nil
// RL r / RL (HL)
case 0x10:
return &Instruction{Mnemonic: "RL B", Length: 2, Address: 0xFFFF}, nil
case 0x11:
return &Instruction{Mnemonic: "RL C", Length: 2, Address: 0xFFFF}, nil
case 0x12:
return &Instruction{Mnemonic: "RL D", Length: 2, Address: 0xFFFF}, nil
case 0x13:
return &Instruction{Mnemonic: "RL E", Length: 2, Address: 0xFFFF}, nil
case 0x14:
return &Instruction{Mnemonic: "RL H", Length: 2, Address: 0xFFFF}, nil
case 0x15:
return &Instruction{Mnemonic: "RL L", Length: 2, Address: 0xFFFF}, nil
case 0x16:
return &Instruction{Mnemonic: "RL (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x17:
return &Instruction{Mnemonic: "RL A", Length: 2, Address: 0xFFFF}, nil
// RR r / RR (HL)
case 0x18:
return &Instruction{Mnemonic: "RR B", Length: 2, Address: 0xFFFF}, nil
case 0x19:
return &Instruction{Mnemonic: "RR C", Length: 2, Address: 0xFFFF}, nil
case 0x1A:
return &Instruction{Mnemonic: "RR D", Length: 2, Address: 0xFFFF}, nil
case 0x1B:
return &Instruction{Mnemonic: "RR E", Length: 2, Address: 0xFFFF}, nil
case 0x1C:
return &Instruction{Mnemonic: "RR H", Length: 2, Address: 0xFFFF}, nil
case 0x1D:
return &Instruction{Mnemonic: "RR L", Length: 2, Address: 0xFFFF}, nil
case 0x1E:
return &Instruction{Mnemonic: "RR (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x1F:
return &Instruction{Mnemonic: "RR A", Length: 2, Address: 0xFFFF}, nil
// SLA r / SLA (HL)
case 0x20:
return &Instruction{Mnemonic: "SLA B", Length: 2, Address: 0xFFFF}, nil
case 0x21:
return &Instruction{Mnemonic: "SLA C", Length: 2, Address: 0xFFFF}, nil
case 0x22:
return &Instruction{Mnemonic: "SLA D", Length: 2, Address: 0xFFFF}, nil
case 0x23:
return &Instruction{Mnemonic: "SLA E", Length: 2, Address: 0xFFFF}, nil
case 0x24:
return &Instruction{Mnemonic: "SLA H", Length: 2, Address: 0xFFFF}, nil
case 0x25:
return &Instruction{Mnemonic: "SLA L", Length: 2, Address: 0xFFFF}, nil
case 0x26:
return &Instruction{Mnemonic: "SLA (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x27:
return &Instruction{Mnemonic: "SLA A", Length: 2, Address: 0xFFFF}, nil
// SRA r / SRA (HL)
case 0x28:
return &Instruction{Mnemonic: "SRA B", Length: 2, Address: 0xFFFF}, nil
case 0x29:
return &Instruction{Mnemonic: "SRA C", Length: 2, Address: 0xFFFF}, nil
case 0x2A:
return &Instruction{Mnemonic: "SRA D", Length: 2, Address: 0xFFFF}, nil
case 0x2B:
return &Instruction{Mnemonic: "SRA E", Length: 2, Address: 0xFFFF}, nil
case 0x2C:
return &Instruction{Mnemonic: "SRA H", Length: 2, Address: 0xFFFF}, nil
case 0x2D:
return &Instruction{Mnemonic: "SRA L", Length: 2, Address: 0xFFFF}, nil
case 0x2E:
return &Instruction{Mnemonic: "SRA (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x2F:
return &Instruction{Mnemonic: "SRA A", Length: 2, Address: 0xFFFF}, nil
// SLL r / SLL (HL) (Undocumented)
case 0x30:
return &Instruction{Mnemonic: "SLL B", Length: 2, Address: 0xFFFF}, nil
case 0x31:
return &Instruction{Mnemonic: "SLL C", Length: 2, Address: 0xFFFF}, nil
case 0x32:
return &Instruction{Mnemonic: "SLL D", Length: 2, Address: 0xFFFF}, nil
case 0x33:
return &Instruction{Mnemonic: "SLL E", Length: 2, Address: 0xFFFF}, nil
case 0x34:
return &Instruction{Mnemonic: "SLL H", Length: 2, Address: 0xFFFF}, nil
case 0x35:
return &Instruction{Mnemonic: "SLL L", Length: 2, Address: 0xFFFF}, nil
case 0x36:
return &Instruction{Mnemonic: "SLL (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x37:
return &Instruction{Mnemonic: "SLL A", Length: 2, Address: 0xFFFF}, nil
// SRL r / SRL (HL)
case 0x38:
return &Instruction{Mnemonic: "SRL B", Length: 2, Address: 0xFFFF}, nil
case 0x39:
return &Instruction{Mnemonic: "SRL C", Length: 2, Address: 0xFFFF}, nil
case 0x3A:
return &Instruction{Mnemonic: "SRL D", Length: 2, Address: 0xFFFF}, nil
case 0x3B:
return &Instruction{Mnemonic: "SRL E", Length: 2, Address: 0xFFFF}, nil
case 0x3C:
return &Instruction{Mnemonic: "SRL H", Length: 2, Address: 0xFFFF}, nil
case 0x3D:
return &Instruction{Mnemonic: "SRL L", Length: 2, Address: 0xFFFF}, nil
case 0x3E:
return &Instruction{Mnemonic: "SRL (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x3F:
return &Instruction{Mnemonic: "SRL A", Length: 2, Address: 0xFFFF}, nil
// BIT b, r / BIT b, (HL)
case 0x40: // BIT 0, B
return &Instruction{Mnemonic: "BIT 0, B", Length: 2, Address: 0xFFFF}, nil
case 0x41: // BIT 0, C
return &Instruction{Mnemonic: "BIT 0, C", Length: 2, Address: 0xFFFF}, nil
case 0x42: // BIT 0, D
return &Instruction{Mnemonic: "BIT 0, D", Length: 2, Address: 0xFFFF}, nil
case 0x43: // BIT 0, E
return &Instruction{Mnemonic: "BIT 0, E", Length: 2, Address: 0xFFFF}, nil
case 0x44: // BIT 0, H
return &Instruction{Mnemonic: "BIT 0, H", Length: 2, Address: 0xFFFF}, nil
case 0x45: // BIT 0, L
return &Instruction{Mnemonic: "BIT 0, L", Length: 2, Address: 0xFFFF}, nil
case 0x46: // BIT 0, (HL)
return &Instruction{Mnemonic: "BIT 0, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x47: // BIT 0, A
return &Instruction{Mnemonic: "BIT 0, A", Length: 2, Address: 0xFFFF}, nil
case 0x48: // BIT 1, B
return &Instruction{Mnemonic: "BIT 1, B", Length: 2, Address: 0xFFFF}, nil
case 0x49: // BIT 1, C
return &Instruction{Mnemonic: "BIT 1, C", Length: 2, Address: 0xFFFF}, nil
case 0x4A: // BIT 1, D
return &Instruction{Mnemonic: "BIT 1, D", Length: 2, Address: 0xFFFF}, nil
case 0x4B: // BIT 1, E
return &Instruction{Mnemonic: "BIT 1, E", Length: 2, Address: 0xFFFF}, nil
case 0x4C: // BIT 1, H
return &Instruction{Mnemonic: "BIT 1, H", Length: 2, Address: 0xFFFF}, nil
case 0x4D: // BIT 1, L
return &Instruction{Mnemonic: "BIT 1, L", Length: 2, Address: 0xFFFF}, nil
case 0x4E: // BIT 1, (HL)
return &Instruction{Mnemonic: "BIT 1, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x4F: // BIT 1, A
return &Instruction{Mnemonic: "BIT 1, A", Length: 2, Address: 0xFFFF}, nil
case 0x50: // BIT 2, B
return &Instruction{Mnemonic: "BIT 2, B", Length: 2, Address: 0xFFFF}, nil
case 0x51: // BIT 2, C
return &Instruction{Mnemonic: "BIT 2, C", Length: 2, Address: 0xFFFF}, nil
case 0x52: // BIT 2, D
return &Instruction{Mnemonic: "BIT 2, D", Length: 2, Address: 0xFFFF}, nil
case 0x53: // BIT 2, E
return &Instruction{Mnemonic: "BIT 2, E", Length: 2, Address: 0xFFFF}, nil
case 0x54: // BIT 2, H
return &Instruction{Mnemonic: "BIT 2, H", Length: 2, Address: 0xFFFF}, nil
case 0x55: // BIT 2, L
return &Instruction{Mnemonic: "BIT 2, L", Length: 2, Address: 0xFFFF}, nil
case 0x56: // BIT 2, (HL)
return &Instruction{Mnemonic: "BIT 2, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x57: // BIT 2, A
return &Instruction{Mnemonic: "BIT 2, A", Length: 2, Address: 0xFFFF}, nil
case 0x58: // BIT 3, B
return &Instruction{Mnemonic: "BIT 3, B", Length: 2, Address: 0xFFFF}, nil
case 0x59: // BIT 3, C
return &Instruction{Mnemonic: "BIT 3, C", Length: 2, Address: 0xFFFF}, nil
case 0x5A: // BIT 3, D
return &Instruction{Mnemonic: "BIT 3, D", Length: 2, Address: 0xFFFF}, nil
case 0x5B: // BIT 3, E
return &Instruction{Mnemonic: "BIT 3, E", Length: 2, Address: 0xFFFF}, nil
case 0x5C: // BIT 3, H
return &Instruction{Mnemonic: "BIT 3, H", Length: 2, Address: 0xFFFF}, nil
case 0x5D: // BIT 3, L
return &Instruction{Mnemonic: "BIT 3, L", Length: 2, Address: 0xFFFF}, nil
case 0x5E: // BIT 3, (HL)
return &Instruction{Mnemonic: "BIT 3, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x5F: // BIT 3, A
return &Instruction{Mnemonic: "BIT 3, A", Length: 2, Address: 0xFFFF}, nil
case 0x60: // BIT 4, B
return &Instruction{Mnemonic: "BIT 4, B", Length: 2, Address: 0xFFFF}, nil
case 0x61: // BIT 4, C
return &Instruction{Mnemonic: "BIT 4, C", Length: 2, Address: 0xFFFF}, nil
case 0x62: // BIT 4, D
return &Instruction{Mnemonic: "BIT 4, D", Length: 2, Address: 0xFFFF}, nil
case 0x63: // BIT 4, E
return &Instruction{Mnemonic: "BIT 4, E", Length: 2, Address: 0xFFFF}, nil
case 0x64: // BIT 4, H
return &Instruction{Mnemonic: "BIT 4, H", Length: 2, Address: 0xFFFF}, nil
case 0x65: // BIT 4, L
return &Instruction{Mnemonic: "BIT 4, L", Length: 2, Address: 0xFFFF}, nil
case 0x66: // BIT 4, (HL)
return &Instruction{Mnemonic: "BIT 4, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x67: // BIT 4, A
return &Instruction{Mnemonic: "BIT 4, A", Length: 2, Address: 0xFFFF}, nil
case 0x68: // BIT 5, B
return &Instruction{Mnemonic: "BIT 5, B", Length: 2, Address: 0xFFFF}, nil
case 0x69: // BIT 5, C
return &Instruction{Mnemonic: "BIT 5, C", Length: 2, Address: 0xFFFF}, nil
case 0x6A: // BIT 5, D
return &Instruction{Mnemonic: "BIT 5, D", Length: 2, Address: 0xFFFF}, nil
case 0x6B: // BIT 5, E
return &Instruction{Mnemonic: "BIT 5, E", Length: 2, Address: 0xFFFF}, nil
case 0x6C: // BIT 5, H
return &Instruction{Mnemonic: "BIT 5, H", Length: 2, Address: 0xFFFF}, nil
case 0x6D: // BIT 5, L
return &Instruction{Mnemonic: "BIT 5, L", Length: 2, Address: 0xFFFF}, nil
case 0x6E: // BIT 5, (HL)
return &Instruction{Mnemonic: "BIT 5, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x6F: // BIT 5, A
return &Instruction{Mnemonic: "BIT 5, A", Length: 2, Address: 0xFFFF}, nil
case 0x70: // BIT 6, B
return &Instruction{Mnemonic: "BIT 6, B", Length: 2, Address: 0xFFFF}, nil
case 0x71: // BIT 6, C
return &Instruction{Mnemonic: "BIT 6, C", Length: 2, Address: 0xFFFF}, nil
case 0x72: // BIT 6, D
return &Instruction{Mnemonic: "BIT 6, D", Length: 2, Address: 0xFFFF}, nil
case 0x73: // BIT 6, E
return &Instruction{Mnemonic: "BIT 6, E", Length: 2, Address: 0xFFFF}, nil
case 0x74: // BIT 6, H
return &Instruction{Mnemonic: "BIT 6, H", Length: 2, Address: 0xFFFF}, nil
case 0x75: // BIT 6, L
return &Instruction{Mnemonic: "BIT 6, L", Length: 2, Address: 0xFFFF}, nil
case 0x76: // BIT 6, (HL)
return &Instruction{Mnemonic: "BIT 6, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x77: // BIT 6, A
return &Instruction{Mnemonic: "BIT 6, A", Length: 2, Address: 0xFFFF}, nil
case 0x78: // BIT 7, B
return &Instruction{Mnemonic: "BIT 7, B", Length: 2, Address: 0xFFFF}, nil
case 0x79: // BIT 7, C
return &Instruction{Mnemonic: "BIT 7, C", Length: 2, Address: 0xFFFF}, nil
case 0x7A: // BIT 7, D
return &Instruction{Mnemonic: "BIT 7, D", Length: 2, Address: 0xFFFF}, nil
case 0x7B: // BIT 7, E
return &Instruction{Mnemonic: "BIT 7, E", Length: 2, Address: 0xFFFF}, nil
case 0x7C: // BIT 7, H
return &Instruction{Mnemonic: "BIT 7, H", Length: 2, Address: 0xFFFF}, nil
case 0x7D: // BIT 7, L
return &Instruction{Mnemonic: "BIT 7, L", Length: 2, Address: 0xFFFF}, nil
case 0x7E: // BIT 7, (HL)
return &Instruction{Mnemonic: "BIT 7, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x7F: // BIT 7, A
return &Instruction{Mnemonic: "BIT 7, A", Length: 2, Address: 0xFFFF}, nil
// RES b, r / RES b, (HL)
case 0x80: // RES 0, B
return &Instruction{Mnemonic: "RES 0, B", Length: 2, Address: 0xFFFF}, nil
case 0x81: // RES 0, C
return &Instruction{Mnemonic: "RES 0, C", Length: 2, Address: 0xFFFF}, nil
case 0x82: // RES 0, D
return &Instruction{Mnemonic: "RES 0, D", Length: 2, Address: 0xFFFF}, nil
case 0x83: // RES 0, E
return &Instruction{Mnemonic: "RES 0, E", Length: 2, Address: 0xFFFF}, nil
case 0x84: // RES 0, H
return &Instruction{Mnemonic: "RES 0, H", Length: 2, Address: 0xFFFF}, nil
case 0x85: // RES 0, L
return &Instruction{Mnemonic: "RES 0, L", Length: 2, Address: 0xFFFF}, nil
case 0x86: // RES 0, (HL)
return &Instruction{Mnemonic: "RES 0, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x87: // RES 0, A
return &Instruction{Mnemonic: "RES 0, A", Length: 2, Address: 0xFFFF}, nil
case 0x88: // RES 1, B
return &Instruction{Mnemonic: "RES 1, B", Length: 2, Address: 0xFFFF}, nil
case 0x89: // RES 1, C
return &Instruction{Mnemonic: "RES 1, C", Length: 2, Address: 0xFFFF}, nil
case 0x8A: // RES 1, D
return &Instruction{Mnemonic: "RES 1, D", Length: 2, Address: 0xFFFF}, nil
case 0x8B: // RES 1, E
return &Instruction{Mnemonic: "RES 1, E", Length: 2, Address: 0xFFFF}, nil
case 0x8C: // RES 1, H
return &Instruction{Mnemonic: "RES 1, H", Length: 2, Address: 0xFFFF}, nil
case 0x8D: // RES 1, L
return &Instruction{Mnemonic: "RES 1, L", Length: 2, Address: 0xFFFF}, nil
case 0x8E: // RES 1, (HL)
return &Instruction{Mnemonic: "RES 1, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x8F: // RES 1, A
return &Instruction{Mnemonic: "RES 1, A", Length: 2, Address: 0xFFFF}, nil
case 0x90: // RES 2, B
return &Instruction{Mnemonic: "RES 2, B", Length: 2, Address: 0xFFFF}, nil
case 0x91: // RES 2, C
return &Instruction{Mnemonic: "RES 2, C", Length: 2, Address: 0xFFFF}, nil
case 0x92: // RES 2, D
return &Instruction{Mnemonic: "RES 2, D", Length: 2, Address: 0xFFFF}, nil
case 0x93: // RES 2, E
return &Instruction{Mnemonic: "RES 2, E", Length: 2, Address: 0xFFFF}, nil
case 0x94: // RES 2, H
return &Instruction{Mnemonic: "RES 2, H", Length: 2, Address: 0xFFFF}, nil
case 0x95: // RES 2, L
return &Instruction{Mnemonic: "RES 2, L", Length: 2, Address: 0xFFFF}, nil
case 0x96: // RES 2, (HL)
return &Instruction{Mnemonic: "RES 2, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x97: // RES 2, A
return &Instruction{Mnemonic: "RES 2, A", Length: 2, Address: 0xFFFF}, nil
case 0x98: // RES 3, B
return &Instruction{Mnemonic: "RES 3, B", Length: 2, Address: 0xFFFF}, nil
case 0x99: // RES 3, C
return &Instruction{Mnemonic: "RES 3, C", Length: 2, Address: 0xFFFF}, nil
case 0x9A: // RES 3, D
return &Instruction{Mnemonic: "RES 3, D", Length: 2, Address: 0xFFFF}, nil
case 0x9B: // RES 3, E
return &Instruction{Mnemonic: "RES 3, E", Length: 2, Address: 0xFFFF}, nil
case 0x9C: // RES 3, H
return &Instruction{Mnemonic: "RES 3, H", Length: 2, Address: 0xFFFF}, nil
case 0x9D: // RES 3, L
return &Instruction{Mnemonic: "RES 3, L", Length: 2, Address: 0xFFFF}, nil
case 0x9E: // RES 3, (HL)
return &Instruction{Mnemonic: "RES 3, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0x9F: // RES 3, A
return &Instruction{Mnemonic: "RES 3, A", Length: 2, Address: 0xFFFF}, nil
case 0xA0: // RES 4, B
return &Instruction{Mnemonic: "RES 4, B", Length: 2, Address: 0xFFFF}, nil
case 0xA1: // RES 4, C
return &Instruction{Mnemonic: "RES 4, C", Length: 2, Address: 0xFFFF}, nil
case 0xA2: // RES 4, D
return &Instruction{Mnemonic: "RES 4, D", Length: 2, Address: 0xFFFF}, nil
case 0xA3: // RES 4, E
return &Instruction{Mnemonic: "RES 4, E", Length: 2, Address: 0xFFFF}, nil
case 0xA4: // RES 4, H
return &Instruction{Mnemonic: "RES 4, H", Length: 2, Address: 0xFFFF}, nil
case 0xA5: // RES 4, L
return &Instruction{Mnemonic: "RES 4, L", Length: 2, Address: 0xFFFF}, nil
case 0xA6: // RES 4, (HL)
return &Instruction{Mnemonic: "RES 4, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xA7: // RES 4, A
return &Instruction{Mnemonic: "RES 4, A", Length: 2, Address: 0xFFFF}, nil
case 0xA8: // RES 5, B
return &Instruction{Mnemonic: "RES 5, B", Length: 2, Address: 0xFFFF}, nil
case 0xA9: // RES 5, C
return &Instruction{Mnemonic: "RES 5, C", Length: 2, Address: 0xFFFF}, nil
case 0xAA: // RES 5, D
return &Instruction{Mnemonic: "RES 5, D", Length: 2, Address: 0xFFFF}, nil
case 0xAB: // RES 5, E
return &Instruction{Mnemonic: "RES 5, E", Length: 2, Address: 0xFFFF}, nil
case 0xAC: // RES 5, H
return &Instruction{Mnemonic: "RES 5, H", Length: 2, Address: 0xFFFF}, nil
case 0xAD: // RES 5, L
return &Instruction{Mnemonic: "RES 5, L", Length: 2, Address: 0xFFFF}, nil
case 0xAE: // RES 5, (HL)
return &Instruction{Mnemonic: "RES 5, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xAF: // RES 5, A
return &Instruction{Mnemonic: "RES 5, A", Length: 2, Address: 0xFFFF}, nil
case 0xB0: // RES 6, B
return &Instruction{Mnemonic: "RES 6, B", Length: 2, Address: 0xFFFF}, nil
case 0xB1: // RES 6, C
return &Instruction{Mnemonic: "RES 6, C", Length: 2, Address: 0xFFFF}, nil
case 0xB2: // RES 6, D
return &Instruction{Mnemonic: "RES 6, D", Length: 2, Address: 0xFFFF}, nil
case 0xB3: // RES 6, E
return &Instruction{Mnemonic: "RES 6, E", Length: 2, Address: 0xFFFF}, nil
case 0xB4: // RES 6, H
return &Instruction{Mnemonic: "RES 6, H", Length: 2, Address: 0xFFFF}, nil
case 0xB5: // RES 6, L
return &Instruction{Mnemonic: "RES 6, L", Length: 2, Address: 0xFFFF}, nil
case 0xB6: // RES 6, (HL)
return &Instruction{Mnemonic: "RES 6, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xB7: // RES 6, A
return &Instruction{Mnemonic: "RES 6, A", Length: 2, Address: 0xFFFF}, nil
case 0xB8: // RES 7, B
return &Instruction{Mnemonic: "RES 7, B", Length: 2, Address: 0xFFFF}, nil
case 0xB9: // RES 7, C
return &Instruction{Mnemonic: "RES 7, C", Length: 2, Address: 0xFFFF}, nil
case 0xBA: // RES 7, D
return &Instruction{Mnemonic: "RES 7, D", Length: 2, Address: 0xFFFF}, nil
case 0xBB: // RES 7, E
return &Instruction{Mnemonic: "RES 7, E", Length: 2, Address: 0xFFFF}, nil
case 0xBC: // RES 7, H
return &Instruction{Mnemonic: "RES 7, H", Length: 2, Address: 0xFFFF}, nil
case 0xBD: // RES 7, L
return &Instruction{Mnemonic: "RES 7, L", Length: 2, Address: 0xFFFF}, nil
case 0xBE: // RES 7, (HL)
return &Instruction{Mnemonic: "RES 7, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xBF: // RES 7, A
return &Instruction{Mnemonic: "RES 7, A", Length: 2, Address: 0xFFFF}, nil
// SET b, r / SET b, (HL)
case 0xC0: // SET 0, B
return &Instruction{Mnemonic: "SET 0, B", Length: 2, Address: 0xFFFF}, nil
case 0xC1: // SET 0, C
return &Instruction{Mnemonic: "SET 0, C", Length: 2, Address: 0xFFFF}, nil
case 0xC2: // SET 0, D
return &Instruction{Mnemonic: "SET 0, D", Length: 2, Address: 0xFFFF}, nil
case 0xC3: // SET 0, E
return &Instruction{Mnemonic: "SET 0, E", Length: 2, Address: 0xFFFF}, nil
case 0xC4: // SET 0, H
return &Instruction{Mnemonic: "SET 0, H", Length: 2, Address: 0xFFFF}, nil
case 0xC5: // SET 0, L
return &Instruction{Mnemonic: "SET 0, L", Length: 2, Address: 0xFFFF}, nil
case 0xC6: // SET 0, (HL)
return &Instruction{Mnemonic: "SET 0, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xC7: // SET 0, A
return &Instruction{Mnemonic: "SET 0, A", Length: 2, Address: 0xFFFF}, nil
case 0xC8: // SET 1, B
return &Instruction{Mnemonic: "SET 1, B", Length: 2, Address: 0xFFFF}, nil
case 0xC9: // SET 1, C
return &Instruction{Mnemonic: "SET 1, C", Length: 2, Address: 0xFFFF}, nil
case 0xCA: // SET 1, D
return &Instruction{Mnemonic: "SET 1, D", Length: 2, Address: 0xFFFF}, nil
case 0xCB: // SET 1, E
return &Instruction{Mnemonic: "SET 1, E", Length: 2, Address: 0xFFFF}, nil
case 0xCC: // SET 1, H
return &Instruction{Mnemonic: "SET 1, H", Length: 2, Address: 0xFFFF}, nil
case 0xCD: // SET 1, L
return &Instruction{Mnemonic: "SET 1, L", Length: 2, Address: 0xFFFF}, nil
case 0xCE: // SET 1, (HL)
return &Instruction{Mnemonic: "SET 1, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xCF: // SET 1, A
return &Instruction{Mnemonic: "SET 1, A", Length: 2, Address: 0xFFFF}, nil
case 0xD0: // SET 2, B
return &Instruction{Mnemonic: "SET 2, B", Length: 2, Address: 0xFFFF}, nil
case 0xD1: // SET 2, C
return &Instruction{Mnemonic: "SET 2, C", Length: 2, Address: 0xFFFF}, nil
case 0xD2: // SET 2, D
return &Instruction{Mnemonic: "SET 2, D", Length: 2, Address: 0xFFFF}, nil
case 0xD3: // SET 2, E
return &Instruction{Mnemonic: "SET 2, E", Length: 2, Address: 0xFFFF}, nil
case 0xD4: // SET 2, H
return &Instruction{Mnemonic: "SET 2, H", Length: 2, Address: 0xFFFF}, nil
case 0xD5: // SET 2, L
return &Instruction{Mnemonic: "SET 2, L", Length: 2, Address: 0xFFFF}, nil
case 0xD6: // SET 2, (HL)
return &Instruction{Mnemonic: "SET 2, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xD7: // SET 2, A
return &Instruction{Mnemonic: "SET 2, A", Length: 2, Address: 0xFFFF}, nil
case 0xD8: // SET 3, B
return &Instruction{Mnemonic: "SET 3, B", Length: 2, Address: 0xFFFF}, nil
case 0xD9: // SET 3, C
return &Instruction{Mnemonic: "SET 3, C", Length: 2, Address: 0xFFFF}, nil
case 0xDA: // SET 3, D
return &Instruction{Mnemonic: "SET 3, D", Length: 2, Address: 0xFFFF}, nil
case 0xDB: // SET 3, E
return &Instruction{Mnemonic: "SET 3, E", Length: 2, Address: 0xFFFF}, nil
case 0xDC: // SET 3, H
return &Instruction{Mnemonic: "SET 3, H", Length: 2, Address: 0xFFFF}, nil
case 0xDD: // SET 3, L
return &Instruction{Mnemonic: "SET 3, L", Length: 2, Address: 0xFFFF}, nil
case 0xDE: // SET 3, (HL)
return &Instruction{Mnemonic: "SET 3, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xDF: // SET 3, A
return &Instruction{Mnemonic: "SET 3, A", Length: 2, Address: 0xFFFF}, nil
case 0xE0: // SET 4, B
return &Instruction{Mnemonic: "SET 4, B", Length: 2, Address: 0xFFFF}, nil
case 0xE1: // SET 4, C
return &Instruction{Mnemonic: "SET 4, C", Length: 2, Address: 0xFFFF}, nil
case 0xE2: // SET 4, D
return &Instruction{Mnemonic: "SET 4, D", Length: 2, Address: 0xFFFF}, nil
case 0xE3: // SET 4, E
return &Instruction{Mnemonic: "SET 4, E", Length: 2, Address: 0xFFFF}, nil
case 0xE4: // SET 4, H
return &Instruction{Mnemonic: "SET 4, H", Length: 2, Address: 0xFFFF}, nil
case 0xE5: // SET 4, L
return &Instruction{Mnemonic: "SET 4, L", Length: 2, Address: 0xFFFF}, nil
case 0xE6: // SET 4, (HL)
return &Instruction{Mnemonic: "SET 4, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xE7: // SET 4, A
return &Instruction{Mnemonic: "SET 4, A", Length: 2, Address: 0xFFFF}, nil
case 0xE8: // SET 5, B
return &Instruction{Mnemonic: "SET 5, B", Length: 2, Address: 0xFFFF}, nil
case 0xE9: // SET 5, C
return &Instruction{Mnemonic: "SET 5, C", Length: 2, Address: 0xFFFF}, nil
case 0xEA: // SET 5, D
return &Instruction{Mnemonic: "SET 5, D", Length: 2, Address: 0xFFFF}, nil
case 0xEB: // SET 5, E
return &Instruction{Mnemonic: "SET 5, E", Length: 2, Address: 0xFFFF}, nil
case 0xEC: // SET 5, H
return &Instruction{Mnemonic: "SET 5, H", Length: 2, Address: 0xFFFF}, nil
case 0xED: // SET 5, L
return &Instruction{Mnemonic: "SET 5, L", Length: 2, Address: 0xFFFF}, nil
case 0xEE: // SET 5, (HL)
return &Instruction{Mnemonic: "SET 5, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xEF: // SET 5, A
return &Instruction{Mnemonic: "SET 5, A", Length: 2, Address: 0xFFFF}, nil
case 0xF0: // SET 6, B
return &Instruction{Mnemonic: "SET 6, B", Length: 2, Address: 0xFFFF}, nil
case 0xF1: // SET 6, C
return &Instruction{Mnemonic: "SET 6, C", Length: 2, Address: 0xFFFF}, nil
case 0xF2: // SET 6, D
return &Instruction{Mnemonic: "SET 6, D", Length: 2, Address: 0xFFFF}, nil
case 0xF3: // SET 6, E
return &Instruction{Mnemonic: "SET 6, E", Length: 2, Address: 0xFFFF}, nil
case 0xF4: // SET 6, H
return &Instruction{Mnemonic: "SET 6, H", Length: 2, Address: 0xFFFF}, nil
case 0xF5: // SET 6, L
return &Instruction{Mnemonic: "SET 6, L", Length: 2, Address: 0xFFFF}, nil
case 0xF6: // SET 6, (HL)
return &Instruction{Mnemonic: "SET 6, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xF7: // SET 6, A
return &Instruction{Mnemonic: "SET 6, A", Length: 2, Address: 0xFFFF}, nil
case 0xF8: // SET 7, B
return &Instruction{Mnemonic: "SET 7, B", Length: 2, Address: 0xFFFF}, nil
case 0xF9: // SET 7, C
return &Instruction{Mnemonic: "SET 7, C", Length: 2, Address: 0xFFFF}, nil
case 0xFA: // SET 7, D
return &Instruction{Mnemonic: "SET 7, D", Length: 2, Address: 0xFFFF}, nil
case 0xFB: // SET 7, E
return &Instruction{Mnemonic: "SET 7, E", Length: 2, Address: 0xFFFF}, nil
case 0xFC: // SET 7, H
return &Instruction{Mnemonic: "SET 7, H", Length: 2, Address: 0xFFFF}, nil
case 0xFD: // SET 7, L
return &Instruction{Mnemonic: "SET 7, L", Length: 2, Address: 0xFFFF}, nil
case 0xFE: // SET 7, (HL)
return &Instruction{Mnemonic: "SET 7, (HL)", Length: 2, Address: 0xFFFF}, nil
case 0xFF: // SET 7, A
return &Instruction{Mnemonic: "SET 7, A", Length: 2, Address: 0xFFFF}, nil
default:
return &Instruction{Mnemonic: fmt.Sprintf("CB $%02X", opcode), Length: 2, Address: 0xFFFF}, nil
}
}

1141
decode_dd.go Normal file

File diff suppressed because it is too large Load Diff

222
decode_ed.go Normal file
View File

@@ -0,0 +1,222 @@
package disasm
import (
"fmt"
)
// decodeED decodes ED-prefixed instructions
func (d *Disassembler) decodeED(data []byte) (*Instruction, error) {
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for ED prefix")
}
opcode := data[1]
// Handle ED prefixed instructions
switch opcode {
// ED40-ED4F range
case 0x40:
return &Instruction{Mnemonic: "IN B, (C)", Length: 2, Address: 0xFFFF}, nil
case 0x41:
return &Instruction{Mnemonic: "OUT (C), B", Length: 2, Address: 0xFFFF}, nil
case 0x42:
return &Instruction{Mnemonic: "SBC HL, BC", Length: 2, Address: 0xFFFF}, nil
case 0x43:
if len(data) < 4 {
return nil, fmt.Errorf("insufficient data for LD (nn), BC")
}
nn := uint16(data[3])<<8 | uint16(data[2])
return &Instruction{Mnemonic: fmt.Sprintf("LD ($%04X), BC", nn), Length: 4, Address: nn}, nil
case 0x44:
return &Instruction{Mnemonic: "NEG", Length: 2, Address: 0xFFFF}, nil
case 0x45:
return &Instruction{Mnemonic: "RETN", Length: 2, Address: 0xFFFF}, nil
case 0x46:
return &Instruction{Mnemonic: "IM 0", Length: 2, Address: 0xFFFF}, nil
case 0x47:
return &Instruction{Mnemonic: "LD I, A", Length: 2, Address: 0xFFFF}, nil
case 0x48:
return &Instruction{Mnemonic: "IN C, (C)", Length: 2, Address: 0xFFFF}, nil
case 0x49:
return &Instruction{Mnemonic: "OUT (C), C", Length: 2, Address: 0xFFFF}, nil
case 0x4A:
return &Instruction{Mnemonic: "ADC HL, BC", Length: 2, Address: 0xFFFF}, nil
case 0x4B:
if len(data) < 4 {
return nil, fmt.Errorf("insufficient data for LD BC, (nn)")
}
nn := uint16(data[3])<<8 | uint16(data[2])
return &Instruction{Mnemonic: fmt.Sprintf("LD BC, ($%04X)", nn), Length: 4, Address: nn}, nil
case 0x4C:
return &Instruction{Mnemonic: "NEG", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x44
case 0x4D:
return &Instruction{Mnemonic: "RETI", Length: 2, Address: 0xFFFF}, nil
case 0x4E:
return &Instruction{Mnemonic: "IM 0", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x46
case 0x4F:
return &Instruction{Mnemonic: "LD R, A", Length: 2, Address: 0xFFFF}, nil
// ED50-ED5F range
case 0x50:
return &Instruction{Mnemonic: "IN D, (C)", Length: 2, Address: 0xFFFF}, nil
case 0x51:
return &Instruction{Mnemonic: "OUT (C), D", Length: 2, Address: 0xFFFF}, nil
case 0x52:
return &Instruction{Mnemonic: "SBC HL, DE", Length: 2, Address: 0xFFFF}, nil
case 0x53:
if len(data) < 4 {
return nil, fmt.Errorf("insufficient data for LD (nn), DE")
}
nn := uint16(data[3])<<8 | uint16(data[2])
return &Instruction{Mnemonic: fmt.Sprintf("LD ($%04X), DE", nn), Length: 4, Address: nn}, nil
case 0x54:
return &Instruction{Mnemonic: "NEG", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x44
case 0x55:
return &Instruction{Mnemonic: "RETN", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x45
case 0x56:
return &Instruction{Mnemonic: "IM 1", Length: 2, Address: 0xFFFF}, nil
case 0x57:
return &Instruction{Mnemonic: "LD A, I", Length: 2, Address: 0xFFFF}, nil
case 0x58:
return &Instruction{Mnemonic: "IN E, (C)", Length: 2, Address: 0xFFFF}, nil
case 0x59:
return &Instruction{Mnemonic: "OUT (C), E", Length: 2, Address: 0xFFFF}, nil
case 0x5A:
return &Instruction{Mnemonic: "ADC HL, DE", Length: 2, Address: 0xFFFF}, nil
case 0x5B:
if len(data) < 4 {
return nil, fmt.Errorf("insufficient data for LD DE, (nn)")
}
nn := uint16(data[3])<<8 | uint16(data[2])
return &Instruction{Mnemonic: fmt.Sprintf("LD DE, ($%04X)", nn), Length: 4, Address: nn}, nil
case 0x5C:
return &Instruction{Mnemonic: "NEG", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x44
case 0x5D:
return &Instruction{Mnemonic: "RETN", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x45
case 0x5E:
return &Instruction{Mnemonic: "IM 2", Length: 2, Address: 0xFFFF}, nil
case 0x5F:
return &Instruction{Mnemonic: "LD A, R", Length: 2, Address: 0xFFFF}, nil
// ED60-ED6F range
case 0x60:
return &Instruction{Mnemonic: "IN H, (C)", Length: 2, Address: 0xFFFF}, nil
case 0x61:
return &Instruction{Mnemonic: "OUT (C), H", Length: 2, Address: 0xFFFF}, nil
case 0x62:
return &Instruction{Mnemonic: "SBC HL, HL", Length: 2, Address: 0xFFFF}, nil
case 0x63:
if len(data) < 4 {
return nil, fmt.Errorf("insufficient data for LD (nn), HL")
}
nn := uint16(data[3])<<8 | uint16(data[2])
return &Instruction{Mnemonic: fmt.Sprintf("LD ($%04X), HL", nn), Length: 4, Address: nn}, nil
case 0x64:
return &Instruction{Mnemonic: "NEG", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x44
case 0x65:
return &Instruction{Mnemonic: "RETN", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x45
case 0x66:
return &Instruction{Mnemonic: "IM 0", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x46
case 0x67:
return &Instruction{Mnemonic: "RRD", Length: 2, Address: 0xFFFF}, nil
case 0x68:
return &Instruction{Mnemonic: "IN L, (C)", Length: 2, Address: 0xFFFF}, nil
case 0x69:
return &Instruction{Mnemonic: "OUT (C), L", Length: 2, Address: 0xFFFF}, nil
case 0x6A:
return &Instruction{Mnemonic: "ADC HL, HL", Length: 2, Address: 0xFFFF}, nil
case 0x6B:
if len(data) < 4 {
return nil, fmt.Errorf("insufficient data for LD HL, (nn)")
}
nn := uint16(data[3])<<8 | uint16(data[2])
return &Instruction{Mnemonic: fmt.Sprintf("LD HL, ($%04X)", nn), Length: 4, Address: nn}, nil
case 0x6C:
return &Instruction{Mnemonic: "NEG", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x44
case 0x6D:
return &Instruction{Mnemonic: "RETN", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x45
case 0x6E:
return &Instruction{Mnemonic: "IM 0", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x46
case 0x6F:
return &Instruction{Mnemonic: "RLD", Length: 2, Address: 0xFFFF}, nil
// ED70-ED7F range
case 0x70:
return &Instruction{Mnemonic: "IN F, (C)", Length: 2, Address: 0xFFFF}, nil
case 0x71:
return &Instruction{Mnemonic: "OUT (C), 0", Length: 2, Address: 0xFFFF}, nil
case 0x72:
return &Instruction{Mnemonic: "SBC HL, SP", Length: 2, Address: 0xFFFF}, nil
case 0x73:
if len(data) < 4 {
return nil, fmt.Errorf("insufficient data for LD (nn), SP")
}
nn := uint16(data[3])<<8 | uint16(data[2])
return &Instruction{Mnemonic: fmt.Sprintf("LD ($%04X), SP", nn), Length: 4, Address: nn}, nil
case 0x74:
return &Instruction{Mnemonic: "NEG", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x44
case 0x75:
return &Instruction{Mnemonic: "RETN", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x45
case 0x76:
return &Instruction{Mnemonic: "IM 1", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x56
case 0x77:
return &Instruction{Mnemonic: "NOP", Length: 2, Address: 0xFFFF}, nil
case 0x78:
return &Instruction{Mnemonic: "IN A, (C)", Length: 2, Address: 0xFFFF}, nil
case 0x79:
return &Instruction{Mnemonic: "OUT (C), A", Length: 2, Address: 0xFFFF}, nil
case 0x7A:
return &Instruction{Mnemonic: "ADC HL, SP", Length: 2, Address: 0xFFFF}, nil
case 0x7B:
if len(data) < 4 {
return nil, fmt.Errorf("insufficient data for LD SP, (nn)")
}
nn := uint16(data[3])<<8 | uint16(data[2])
return &Instruction{Mnemonic: fmt.Sprintf("LD SP, ($%04X)", nn), Length: 4, Address: nn}, nil
case 0x7C:
return &Instruction{Mnemonic: "NEG", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x44
case 0x7D:
return &Instruction{Mnemonic: "RETN", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x45
case 0x7E:
return &Instruction{Mnemonic: "IM 2", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x5E
case 0x7F:
return &Instruction{Mnemonic: "NOP", Length: 2, Address: 0xFFFF}, nil // Duplicate of 0x77
// Block instructions
case 0xA0:
return &Instruction{Mnemonic: "LDI", Length: 2, Address: 0xFFFF}, nil
case 0xA1:
return &Instruction{Mnemonic: "CPI", Length: 2, Address: 0xFFFF}, nil
case 0xA2:
return &Instruction{Mnemonic: "INI", Length: 2, Address: 0xFFFF}, nil
case 0xA3:
return &Instruction{Mnemonic: "OUTI", Length: 2, Address: 0xFFFF}, nil
case 0xA8:
return &Instruction{Mnemonic: "LDD", Length: 2, Address: 0xFFFF}, nil
case 0xA9:
return &Instruction{Mnemonic: "CPD", Length: 2, Address: 0xFFFF}, nil
case 0xAA:
return &Instruction{Mnemonic: "IND", Length: 2, Address: 0xFFFF}, nil
case 0xAB:
return &Instruction{Mnemonic: "OUTD", Length: 2, Address: 0xFFFF}, nil
case 0xB0:
return &Instruction{Mnemonic: "LDIR", Length: 2, Address: 0xFFFF}, nil
case 0xB1:
return &Instruction{Mnemonic: "CPIR", Length: 2, Address: 0xFFFF}, nil
case 0xB2:
return &Instruction{Mnemonic: "INIR", Length: 2, Address: 0xFFFF}, nil
case 0xB3:
return &Instruction{Mnemonic: "OTIR", Length: 2, Address: 0xFFFF}, nil
case 0xB8:
return &Instruction{Mnemonic: "LDDR", Length: 2, Address: 0xFFFF}, nil
case 0xB9:
return &Instruction{Mnemonic: "CPDR", Length: 2, Address: 0xFFFF}, nil
case 0xBA:
return &Instruction{Mnemonic: "INDR", Length: 2, Address: 0xFFFF}, nil
case 0xBB:
return &Instruction{Mnemonic: "OTDR", Length: 2, Address: 0xFFFF}, nil
default:
return &Instruction{Mnemonic: fmt.Sprintf("ED $%02X", opcode), Length: 2, Address: 0xFFFF}, nil
}
}

1141
decode_fd.go Normal file

File diff suppressed because it is too large Load Diff

768
decode_unprefixed.go Normal file
View File

@@ -0,0 +1,768 @@
package disasm
import (
"fmt"
)
// decodeUnprefixed decodes unprefixed Z80 instructions
func (d *Disassembler) decodeUnprefixed(opcode byte, data []byte) (*Instruction, error) {
switch opcode {
// 8-bit load group
case 0x00:
return &Instruction{Mnemonic: "NOP", Length: 1, Address: 0xFFFF}, nil
case 0x01:
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for LD BC, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("LD BC, $%04X", nn), Length: 3, Address: nn}, nil
case 0x02:
return &Instruction{Mnemonic: "LD (BC), A", Length: 1, Address: 0xFFFF}, nil
case 0x03:
return &Instruction{Mnemonic: "INC BC", Length: 1, Address: 0xFFFF}, nil
case 0x04:
return &Instruction{Mnemonic: "INC B", Length: 1, Address: 0xFFFF}, nil
case 0x05:
return &Instruction{Mnemonic: "DEC B", Length: 1, Address: 0xFFFF}, nil
case 0x06:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for LD B, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("LD B, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0x07:
return &Instruction{Mnemonic: "RLCA", Length: 1, Address: 0xFFFF}, nil
case 0x08:
return &Instruction{Mnemonic: "EX AF, AF'", Length: 1, Address: 0xFFFF}, nil
case 0x09:
return &Instruction{Mnemonic: "ADD HL, BC", Length: 1, Address: 0xFFFF}, nil
case 0x0A:
return &Instruction{Mnemonic: "LD A, (BC)", Length: 1, Address: 0xFFFF}, nil
case 0x0B:
return &Instruction{Mnemonic: "DEC BC", Length: 1, Address: 0xFFFF}, nil
case 0x0C:
return &Instruction{Mnemonic: "INC C", Length: 1, Address: 0xFFFF}, nil
case 0x0D:
return &Instruction{Mnemonic: "DEC C", Length: 1, Address: 0xFFFF}, nil
case 0x0E:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for LD C, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("LD C, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0x0F:
return &Instruction{Mnemonic: "RRCA", Length: 1, Address: 0xFFFF}, nil
case 0x10:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for DJNZ e")
}
e := int8(data[1])
if e >= 0 {
return &Instruction{Mnemonic: fmt.Sprintf("DJNZ $%02X", e), Length: 2, Address: 0xFFFF}, nil
} else {
return &Instruction{Mnemonic: fmt.Sprintf("DJNZ -$%02X", -e), Length: 2, Address: 0xFFFF}, nil
}
case 0x11:
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for LD DE, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("LD DE, $%04X", nn), Length: 3, Address: nn}, nil
case 0x12:
return &Instruction{Mnemonic: "LD (DE), A", Length: 1, Address: 0xFFFF}, nil
case 0x13:
return &Instruction{Mnemonic: "INC DE", Length: 1, Address: 0xFFFF}, nil
case 0x14:
return &Instruction{Mnemonic: "INC D", Length: 1, Address: 0xFFFF}, nil
case 0x15:
return &Instruction{Mnemonic: "DEC D", Length: 1, Address: 0xFFFF}, nil
case 0x16:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for LD D, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("LD D, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0x17:
return &Instruction{Mnemonic: "RLA", Length: 1, Address: 0xFFFF}, nil
case 0x18:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for JR e")
}
e := int8(data[1])
if e >= 0 {
return &Instruction{Mnemonic: fmt.Sprintf("JR $%02X", e), Length: 2, Address: 0xFFFF}, nil
} else {
return &Instruction{Mnemonic: fmt.Sprintf("JR -$%02X", -e), Length: 2, Address: 0xFFFF}, nil
}
case 0x19:
return &Instruction{Mnemonic: "ADD HL, DE", Length: 1, Address: 0xFFFF}, nil
case 0x1A:
return &Instruction{Mnemonic: "LD A, (DE)", Length: 1, Address: 0xFFFF}, nil
case 0x1B:
return &Instruction{Mnemonic: "DEC DE", Length: 1, Address: 0xFFFF}, nil
case 0x1C:
return &Instruction{Mnemonic: "INC E", Length: 1, Address: 0xFFFF}, nil
case 0x1D:
return &Instruction{Mnemonic: "DEC E", Length: 1, Address: 0xFFFF}, nil
case 0x1E:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for LD E, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("LD E, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0x1F:
return &Instruction{Mnemonic: "RRA", Length: 1, Address: 0xFFFF}, nil
case 0x20:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for JR NZ, e")
}
e := int8(data[1])
if e >= 0 {
return &Instruction{Mnemonic: fmt.Sprintf("JR NZ, $%02X", e), Length: 2, Address: 0xFFFF}, nil
} else {
return &Instruction{Mnemonic: fmt.Sprintf("JR NZ, -$%02X", -e), Length: 2, Address: 0xFFFF}, nil
}
case 0x21:
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for LD HL, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("LD HL, $%04X", nn), Length: 3, Address: nn}, nil
case 0x22:
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for LD (nn), HL")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("LD ($%04X), HL", nn), Length: 3, Address: nn}, nil
case 0x23:
return &Instruction{Mnemonic: "INC HL", Length: 1, Address: 0xFFFF}, nil
case 0x24:
return &Instruction{Mnemonic: "INC H", Length: 1, Address: 0xFFFF}, nil
case 0x25:
return &Instruction{Mnemonic: "DEC H", Length: 1, Address: 0xFFFF}, nil
case 0x26:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for LD H, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("LD H, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0x27:
return &Instruction{Mnemonic: "DAA", Length: 1, Address: 0xFFFF}, nil
case 0x28:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for JR Z, e")
}
e := int8(data[1])
if e >= 0 {
return &Instruction{Mnemonic: fmt.Sprintf("JR Z, $%02X", e), Length: 2, Address: 0xFFFF}, nil
} else {
return &Instruction{Mnemonic: fmt.Sprintf("JR Z, -$%02X", -e), Length: 2, Address: 0xFFFF}, nil
}
case 0x29:
return &Instruction{Mnemonic: "ADD HL, HL", Length: 1, Address: 0xFFFF}, nil
case 0x2A:
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for LD HL, (nn)")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("LD HL, ($%04X)", nn), Length: 3, Address: nn}, nil
case 0x2B:
return &Instruction{Mnemonic: "DEC HL", Length: 1, Address: 0xFFFF}, nil
case 0x2C:
return &Instruction{Mnemonic: "INC L", Length: 1, Address: 0xFFFF}, nil
case 0x2D:
return &Instruction{Mnemonic: "DEC L", Length: 1, Address: 0xFFFF}, nil
case 0x2E:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for LD L, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("LD L, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0x2F:
return &Instruction{Mnemonic: "CPL", Length: 1, Address: 0xFFFF}, nil
case 0x30:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for JR NC, e")
}
e := int8(data[1])
if e >= 0 {
return &Instruction{Mnemonic: fmt.Sprintf("JR NC, $%02X", e), Length: 2, Address: 0xFFFF}, nil
} else {
return &Instruction{Mnemonic: fmt.Sprintf("JR NC, -$%02X", -e), Length: 2, Address: 0xFFFF}, nil
}
case 0x31:
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for LD SP, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("LD SP, $%04X", nn), Length: 3, Address: nn}, nil
case 0x32:
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for LD (nn), A")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("LD ($%04X), A", nn), Length: 3, Address: nn}, nil
case 0x33:
return &Instruction{Mnemonic: "INC SP", Length: 1, Address: 0xFFFF}, nil
case 0x34:
return &Instruction{Mnemonic: "INC (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x35:
return &Instruction{Mnemonic: "DEC (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x36:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for LD (HL), n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("LD (HL), $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0x37:
return &Instruction{Mnemonic: "SCF", Length: 1, Address: 0xFFFF}, nil
case 0x38:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for JR C, e")
}
e := int8(data[1])
if e >= 0 {
return &Instruction{Mnemonic: fmt.Sprintf("JR C, $%02X", e), Length: 2, Address: 0xFFFF}, nil
} else {
return &Instruction{Mnemonic: fmt.Sprintf("JR C, -$%02X", -e), Length: 2, Address: 0xFFFF}, nil
}
case 0x39:
return &Instruction{Mnemonic: "ADD HL, SP", Length: 1, Address: 0xFFFF}, nil
case 0x3A:
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for LD A, (nn)")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("LD A, ($%04X)", nn), Length: 3, Address: nn}, nil
case 0x3B:
return &Instruction{Mnemonic: "DEC SP", Length: 1, Address: 0xFFFF}, nil
case 0x3C:
return &Instruction{Mnemonic: "INC A", Length: 1, Address: 0xFFFF}, nil
case 0x3D:
return &Instruction{Mnemonic: "DEC A", Length: 1, Address: 0xFFFF}, nil
case 0x3E:
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for LD A, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("LD A, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0x3F:
return &Instruction{Mnemonic: "CCF", Length: 1, Address: 0xFFFF}, nil
// LD r, r' instructions (0x40-0x7F)
case 0x40: // LD B, B
return &Instruction{Mnemonic: "LD B, B", Length: 1, Address: 0xFFFF}, nil
case 0x41: // LD B, C
return &Instruction{Mnemonic: "LD B, C", Length: 1, Address: 0xFFFF}, nil
case 0x42: // LD B, D
return &Instruction{Mnemonic: "LD B, D", Length: 1, Address: 0xFFFF}, nil
case 0x43: // LD B, E
return &Instruction{Mnemonic: "LD B, E", Length: 1, Address: 0xFFFF}, nil
case 0x44: // LD B, H
return &Instruction{Mnemonic: "LD B, H", Length: 1, Address: 0xFFFF}, nil
case 0x45: // LD B, L
return &Instruction{Mnemonic: "LD B, L", Length: 1, Address: 0xFFFF}, nil
case 0x46: // LD B, (HL)
return &Instruction{Mnemonic: "LD B, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x47: // LD B, A
return &Instruction{Mnemonic: "LD B, A", Length: 1, Address: 0xFFFF}, nil
case 0x48: // LD C, B
return &Instruction{Mnemonic: "LD C, B", Length: 1, Address: 0xFFFF}, nil
case 0x49: // LD C, C
return &Instruction{Mnemonic: "LD C, C", Length: 1, Address: 0xFFFF}, nil
case 0x4A: // LD C, D
return &Instruction{Mnemonic: "LD C, D", Length: 1, Address: 0xFFFF}, nil
case 0x4B: // LD C, E
return &Instruction{Mnemonic: "LD C, E", Length: 1, Address: 0xFFFF}, nil
case 0x4C: // LD C, H
return &Instruction{Mnemonic: "LD C, H", Length: 1, Address: 0xFFFF}, nil
case 0x4D: // LD C, L
return &Instruction{Mnemonic: "LD C, L", Length: 1, Address: 0xFFFF}, nil
case 0x4E: // LD C, (HL)
return &Instruction{Mnemonic: "LD C, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x4F: // LD C, A
return &Instruction{Mnemonic: "LD C, A", Length: 1, Address: 0xFFFF}, nil
case 0x50: // LD D, B
return &Instruction{Mnemonic: "LD D, B", Length: 1, Address: 0xFFFF}, nil
case 0x51: // LD D, C
return &Instruction{Mnemonic: "LD D, C", Length: 1, Address: 0xFFFF}, nil
case 0x52: // LD D, D
return &Instruction{Mnemonic: "LD D, D", Length: 1, Address: 0xFFFF}, nil
case 0x53: // LD D, E
return &Instruction{Mnemonic: "LD D, E", Length: 1, Address: 0xFFFF}, nil
case 0x54: // LD D, H
return &Instruction{Mnemonic: "LD D, H", Length: 1, Address: 0xFFFF}, nil
case 0x55: // LD D, L
return &Instruction{Mnemonic: "LD D, L", Length: 1, Address: 0xFFFF}, nil
case 0x56: // LD D, (HL)
return &Instruction{Mnemonic: "LD D, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x57: // LD D, A
return &Instruction{Mnemonic: "LD D, A", Length: 1, Address: 0xFFFF}, nil
case 0x58: // LD E, B
return &Instruction{Mnemonic: "LD E, B", Length: 1, Address: 0xFFFF}, nil
case 0x59: // LD E, C
return &Instruction{Mnemonic: "LD E, C", Length: 1, Address: 0xFFFF}, nil
case 0x5A: // LD E, D
return &Instruction{Mnemonic: "LD E, D", Length: 1, Address: 0xFFFF}, nil
case 0x5B: // LD E, E
return &Instruction{Mnemonic: "LD E, E", Length: 1, Address: 0xFFFF}, nil
case 0x5C: // LD E, H
return &Instruction{Mnemonic: "LD E, H", Length: 1, Address: 0xFFFF}, nil
case 0x5D: // LD E, L
return &Instruction{Mnemonic: "LD E, L", Length: 1, Address: 0xFFFF}, nil
case 0x5E: // LD E, (HL)
return &Instruction{Mnemonic: "LD E, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x5F: // LD E, A
return &Instruction{Mnemonic: "LD E, A", Length: 1, Address: 0xFFFF}, nil
case 0x60: // LD H, B
return &Instruction{Mnemonic: "LD H, B", Length: 1, Address: 0xFFFF}, nil
case 0x61: // LD H, C
return &Instruction{Mnemonic: "LD H, C", Length: 1, Address: 0xFFFF}, nil
case 0x62: // LD H, D
return &Instruction{Mnemonic: "LD H, D", Length: 1, Address: 0xFFFF}, nil
case 0x63: // LD H, E
return &Instruction{Mnemonic: "LD H, E", Length: 1, Address: 0xFFFF}, nil
case 0x64: // LD H, H
return &Instruction{Mnemonic: "LD H, H", Length: 1, Address: 0xFFFF}, nil
case 0x65: // LD H, L
return &Instruction{Mnemonic: "LD H, L", Length: 1, Address: 0xFFFF}, nil
case 0x66: // LD H, (HL)
return &Instruction{Mnemonic: "LD H, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x67: // LD H, A
return &Instruction{Mnemonic: "LD H, A", Length: 1, Address: 0xFFFF}, nil
case 0x68: // LD L, B
return &Instruction{Mnemonic: "LD L, B", Length: 1, Address: 0xFFFF}, nil
case 0x69: // LD L, C
return &Instruction{Mnemonic: "LD L, C", Length: 1, Address: 0xFFFF}, nil
case 0x6A: // LD L, D
return &Instruction{Mnemonic: "LD L, D", Length: 1, Address: 0xFFFF}, nil
case 0x6B: // LD L, E
return &Instruction{Mnemonic: "LD L, E", Length: 1, Address: 0xFFFF}, nil
case 0x6C: // LD L, H
return &Instruction{Mnemonic: "LD L, H", Length: 1, Address: 0xFFFF}, nil
case 0x6D: // LD L, L
return &Instruction{Mnemonic: "LD L, L", Length: 1, Address: 0xFFFF}, nil
case 0x6E: // LD L, (HL)
return &Instruction{Mnemonic: "LD L, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x6F: // LD L, A
return &Instruction{Mnemonic: "LD L, A", Length: 1, Address: 0xFFFF}, nil
case 0x70: // LD (HL), B
return &Instruction{Mnemonic: "LD (HL), B", Length: 1, Address: 0xFFFF}, nil
case 0x71: // LD (HL), C
return &Instruction{Mnemonic: "LD (HL), C", Length: 1, Address: 0xFFFF}, nil
case 0x72: // LD (HL), D
return &Instruction{Mnemonic: "LD (HL), D", Length: 1, Address: 0xFFFF}, nil
case 0x73: // LD (HL), E
return &Instruction{Mnemonic: "LD (HL), E", Length: 1, Address: 0xFFFF}, nil
case 0x74: // LD (HL), H
return &Instruction{Mnemonic: "LD (HL), H", Length: 1, Address: 0xFFFF}, nil
case 0x75: // LD (HL), L
return &Instruction{Mnemonic: "LD (HL), L", Length: 1, Address: 0xFFFF}, nil
case 0x76: // HALT
return &Instruction{Mnemonic: "HALT", Length: 1, Address: 0xFFFF}, nil
case 0x77: // LD (HL), A
return &Instruction{Mnemonic: "LD (HL), A", Length: 1, Address: 0xFFFF}, nil
case 0x78: // LD A, B
return &Instruction{Mnemonic: "LD A, B", Length: 1, Address: 0xFFFF}, nil
case 0x79: // LD A, C
return &Instruction{Mnemonic: "LD A, C", Length: 1, Address: 0xFFFF}, nil
case 0x7A: // LD A, D
return &Instruction{Mnemonic: "LD A, D", Length: 1, Address: 0xFFFF}, nil
case 0x7B: // LD A, E
return &Instruction{Mnemonic: "LD A, E", Length: 1, Address: 0xFFFF}, nil
case 0x7C: // LD A, H
return &Instruction{Mnemonic: "LD A, H", Length: 1, Address: 0xFFFF}, nil
case 0x7D: // LD A, L
return &Instruction{Mnemonic: "LD A, L", Length: 1, Address: 0xFFFF}, nil
case 0x7E: // LD A, (HL)
return &Instruction{Mnemonic: "LD A, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x7F: // LD A, A
return &Instruction{Mnemonic: "LD A, A", Length: 1, Address: 0xFFFF}, nil
// ALU operations (0x80-0xBF)
case 0x80: // ADD A, B
return &Instruction{Mnemonic: "ADD A, B", Length: 1, Address: 0xFFFF}, nil
case 0x81: // ADD A, C
return &Instruction{Mnemonic: "ADD A, C", Length: 1, Address: 0xFFFF}, nil
case 0x82: // ADD A, D
return &Instruction{Mnemonic: "ADD A, D", Length: 1, Address: 0xFFFF}, nil
case 0x83: // ADD A, E
return &Instruction{Mnemonic: "ADD A, E", Length: 1, Address: 0xFFFF}, nil
case 0x84: // ADD A, H
return &Instruction{Mnemonic: "ADD A, H", Length: 1, Address: 0xFFFF}, nil
case 0x85: // ADD A, L
return &Instruction{Mnemonic: "ADD A, L", Length: 1, Address: 0xFFFF}, nil
case 0x86: // ADD A, (HL)
return &Instruction{Mnemonic: "ADD A, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x87: // ADD A, A
return &Instruction{Mnemonic: "ADD A, A", Length: 1, Address: 0xFFFF}, nil
case 0x88: // ADC A, B
return &Instruction{Mnemonic: "ADC A, B", Length: 1, Address: 0xFFFF}, nil
case 0x89: // ADC A, C
return &Instruction{Mnemonic: "ADC A, C", Length: 1, Address: 0xFFFF}, nil
case 0x8A: // ADC A, D
return &Instruction{Mnemonic: "ADC A, D", Length: 1, Address: 0xFFFF}, nil
case 0x8B: // ADC A, E
return &Instruction{Mnemonic: "ADC A, E", Length: 1, Address: 0xFFFF}, nil
case 0x8C: // ADC A, H
return &Instruction{Mnemonic: "ADC A, H", Length: 1, Address: 0xFFFF}, nil
case 0x8D: // ADC A, L
return &Instruction{Mnemonic: "ADC A, L", Length: 1, Address: 0xFFFF}, nil
case 0x8E: // ADC A, (HL)
return &Instruction{Mnemonic: "ADC A, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x8F: // ADC A, A
return &Instruction{Mnemonic: "ADC A, A", Length: 1, Address: 0xFFFF}, nil
case 0x90: // SUB B
return &Instruction{Mnemonic: "SUB B", Length: 1, Address: 0xFFFF}, nil
case 0x91: // SUB C
return &Instruction{Mnemonic: "SUB C", Length: 1, Address: 0xFFFF}, nil
case 0x92: // SUB D
return &Instruction{Mnemonic: "SUB D", Length: 1, Address: 0xFFFF}, nil
case 0x93: // SUB E
return &Instruction{Mnemonic: "SUB E", Length: 1, Address: 0xFFFF}, nil
case 0x94: // SUB H
return &Instruction{Mnemonic: "SUB H", Length: 1, Address: 0xFFFF}, nil
case 0x95: // SUB L
return &Instruction{Mnemonic: "SUB L", Length: 1, Address: 0xFFFF}, nil
case 0x96: // SUB (HL)
return &Instruction{Mnemonic: "SUB (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x97: // SUB A
return &Instruction{Mnemonic: "SUB A", Length: 1, Address: 0xFFFF}, nil
case 0x98: // SBC A, B
return &Instruction{Mnemonic: "SBC A, B", Length: 1, Address: 0xFFFF}, nil
case 0x99: // SBC A, C
return &Instruction{Mnemonic: "SBC A, C", Length: 1, Address: 0xFFFF}, nil
case 0x9A: // SBC A, D
return &Instruction{Mnemonic: "SBC A, D", Length: 1, Address: 0xFFFF}, nil
case 0x9B: // SBC A, E
return &Instruction{Mnemonic: "SBC A, E", Length: 1, Address: 0xFFFF}, nil
case 0x9C: // SBC A, H
return &Instruction{Mnemonic: "SBC A, H", Length: 1, Address: 0xFFFF}, nil
case 0x9D: // SBC A, L
return &Instruction{Mnemonic: "SBC A, L", Length: 1, Address: 0xFFFF}, nil
case 0x9E: // SBC A, (HL)
return &Instruction{Mnemonic: "SBC A, (HL)", Length: 1, Address: 0xFFFF}, nil
case 0x9F: // SBC A, A
return &Instruction{Mnemonic: "SBC A, A", Length: 1, Address: 0xFFFF}, nil
case 0xA0: // AND B
return &Instruction{Mnemonic: "AND B", Length: 1, Address: 0xFFFF}, nil
case 0xA1: // AND C
return &Instruction{Mnemonic: "AND C", Length: 1, Address: 0xFFFF}, nil
case 0xA2: // AND D
return &Instruction{Mnemonic: "AND D", Length: 1, Address: 0xFFFF}, nil
case 0xA3: // AND E
return &Instruction{Mnemonic: "AND E", Length: 1, Address: 0xFFFF}, nil
case 0xA4: // AND H
return &Instruction{Mnemonic: "AND H", Length: 1, Address: 0xFFFF}, nil
case 0xA5: // AND L
return &Instruction{Mnemonic: "AND L", Length: 1, Address: 0xFFFF}, nil
case 0xA6: // AND (HL)
return &Instruction{Mnemonic: "AND (HL)", Length: 1, Address: 0xFFFF}, nil
case 0xA7: // AND A
return &Instruction{Mnemonic: "AND A", Length: 1, Address: 0xFFFF}, nil
case 0xA8: // XOR B
return &Instruction{Mnemonic: "XOR B", Length: 1, Address: 0xFFFF}, nil
case 0xA9: // XOR C
return &Instruction{Mnemonic: "XOR C", Length: 1, Address: 0xFFFF}, nil
case 0xAA: // XOR D
return &Instruction{Mnemonic: "XOR D", Length: 1, Address: 0xFFFF}, nil
case 0xAB: // XOR E
return &Instruction{Mnemonic: "XOR E", Length: 1, Address: 0xFFFF}, nil
case 0xAC: // XOR H
return &Instruction{Mnemonic: "XOR H", Length: 1, Address: 0xFFFF}, nil
case 0xAD: // XOR L
return &Instruction{Mnemonic: "XOR L", Length: 1, Address: 0xFFFF}, nil
case 0xAE: // XOR (HL)
return &Instruction{Mnemonic: "XOR (HL)", Length: 1, Address: 0xFFFF}, nil
case 0xAF: // XOR A
return &Instruction{Mnemonic: "XOR A", Length: 1, Address: 0xFFFF}, nil
case 0xB0: // OR B
return &Instruction{Mnemonic: "OR B", Length: 1, Address: 0xFFFF}, nil
case 0xB1: // OR C
return &Instruction{Mnemonic: "OR C", Length: 1, Address: 0xFFFF}, nil
case 0xB2: // OR D
return &Instruction{Mnemonic: "OR D", Length: 1, Address: 0xFFFF}, nil
case 0xB3: // OR E
return &Instruction{Mnemonic: "OR E", Length: 1, Address: 0xFFFF}, nil
case 0xB4: // OR H
return &Instruction{Mnemonic: "OR H", Length: 1, Address: 0xFFFF}, nil
case 0xB5: // OR L
return &Instruction{Mnemonic: "OR L", Length: 1, Address: 0xFFFF}, nil
case 0xB6: // OR (HL)
return &Instruction{Mnemonic: "OR (HL)", Length: 1, Address: 0xFFFF}, nil
case 0xB7: // OR A
return &Instruction{Mnemonic: "OR A", Length: 1, Address: 0xFFFF}, nil
case 0xB8: // CP B
return &Instruction{Mnemonic: "CP B", Length: 1, Address: 0xFFFF}, nil
case 0xB9: // CP C
return &Instruction{Mnemonic: "CP C", Length: 1, Address: 0xFFFF}, nil
case 0xBA: // CP D
return &Instruction{Mnemonic: "CP D", Length: 1, Address: 0xFFFF}, nil
case 0xBB: // CP E
return &Instruction{Mnemonic: "CP E", Length: 1, Address: 0xFFFF}, nil
case 0xBC: // CP H
return &Instruction{Mnemonic: "CP H", Length: 1, Address: 0xFFFF}, nil
case 0xBD: // CP L
return &Instruction{Mnemonic: "CP L", Length: 1, Address: 0xFFFF}, nil
case 0xBE: // CP (HL)
return &Instruction{Mnemonic: "CP (HL)", Length: 1, Address: 0xFFFF}, nil
case 0xBF: // CP A
return &Instruction{Mnemonic: "CP A", Length: 1, Address: 0xFFFF}, nil
// RET cc instructions (0xC0-0xC7)
case 0xC0: // RET NZ
return &Instruction{Mnemonic: "RET NZ", Length: 1, Address: 0xFFFF}, nil
case 0xC1: // POP BC
return &Instruction{Mnemonic: "POP BC", Length: 1, Address: 0xFFFF}, nil
case 0xC2: // JP NZ, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for JP NZ, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("JP NZ, $%04X", nn), Length: 3, Address: nn}, nil
case 0xC3: // JP nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for JP nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("JP $%04X", nn), Length: 3, Address: nn}, nil
case 0xC4: // CALL NZ, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for CALL NZ, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("CALL NZ, $%04X", nn), Length: 3, Address: nn}, nil
case 0xC5: // PUSH BC
return &Instruction{Mnemonic: "PUSH BC", Length: 1, Address: 0xFFFF}, nil
case 0xC6: // ADD A, n
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for ADD A, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("ADD A, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0xC7: // RST 00H
return &Instruction{Mnemonic: "RST 00H", Length: 1, Address: 0x0000}, nil
case 0xC8: // RET Z
return &Instruction{Mnemonic: "RET Z", Length: 1, Address: 0xFFFF}, nil
case 0xC9: // RET
return &Instruction{Mnemonic: "RET", Length: 1, Address: 0xFFFF}, nil
case 0xCA: // JP Z, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for JP Z, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("JP Z, $%04X", nn), Length: 3, Address: nn}, nil
case 0xCB: // PREFIX CB
// This should be handled in the main Decode function
return &Instruction{Mnemonic: "PREFIX CB", Length: 1, Address: 0xFFFF}, nil
case 0xCC: // CALL Z, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for CALL Z, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("CALL Z, $%04X", nn), Length: 3, Address: nn}, nil
case 0xCD: // CALL nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for CALL nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("CALL $%04X", nn), Length: 3, Address: nn}, nil
case 0xCE: // ADC A, n
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for ADC A, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("ADC A, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0xCF: // RST 08H
return &Instruction{Mnemonic: "RST 08H", Length: 1, Address: 0x0008}, nil
// Conditional operations (0xD0-0xDF)
case 0xD0: // RET NC
return &Instruction{Mnemonic: "RET NC", Length: 1, Address: 0xFFFF}, nil
case 0xD1: // POP DE
return &Instruction{Mnemonic: "POP DE", Length: 1, Address: 0xFFFF}, nil
case 0xD2: // JP NC, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for JP NC, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("JP NC, $%04X", nn), Length: 3, Address: nn}, nil
case 0xD3: // OUT (n), A
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for OUT (n), A")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("OUT ($%02X), A", n), Length: 2, Address: 0xFFFF}, nil
case 0xD4: // CALL NC, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for CALL NC, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("CALL NC, $%04X", nn), Length: 3, Address: nn}, nil
case 0xD5: // PUSH DE
return &Instruction{Mnemonic: "PUSH DE", Length: 1, Address: 0xFFFF}, nil
case 0xD6: // SUB n
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for SUB n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("SUB $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0xD7: // RST 10H
return &Instruction{Mnemonic: "RST 10H", Length: 1, Address: 0x0010}, nil
case 0xD8: // RET C
return &Instruction{Mnemonic: "RET C", Length: 1, Address: 0xFFFF}, nil
case 0xD9: // EXX
return &Instruction{Mnemonic: "EXX", Length: 1, Address: 0xFFFF}, nil
case 0xDA: // JP C, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for JP C, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("JP C, $%04X", nn), Length: 3, Address: nn}, nil
case 0xDB: // IN A, (n)
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for IN A, (n)")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("IN A, ($%02X)", n), Length: 2, Address: 0xFFFF}, nil
case 0xDC: // CALL C, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for CALL C, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("CALL C, $%04X", nn), Length: 3, Address: nn}, nil
case 0xDD: // PREFIX DD
// This should be handled in the main Decode function
return &Instruction{Mnemonic: "PREFIX DD", Length: 1, Address: 0xFFFF}, nil
case 0xDE: // SBC A, n
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for SBC A, n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("SBC A, $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0xDF: // RST 18H
return &Instruction{Mnemonic: "RST 18H", Length: 1, Address: 0x0018}, nil
// Conditional operations (0xE0-0xEF)
case 0xE0: // RET PO
return &Instruction{Mnemonic: "RET PO", Length: 1, Address: 0xFFFF}, nil
case 0xE1: // POP HL
return &Instruction{Mnemonic: "POP HL", Length: 1, Address: 0xFFFF}, nil
case 0xE2: // JP PO, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for JP PO, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("JP PO, $%04X", nn), Length: 3, Address: nn}, nil
case 0xE3: // EX (SP), HL
return &Instruction{Mnemonic: "EX (SP), HL", Length: 1, Address: 0xFFFF}, nil
case 0xE4: // CALL PO, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for CALL PO, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("CALL PO, $%04X", nn), Length: 3, Address: nn}, nil
case 0xE5: // PUSH HL
return &Instruction{Mnemonic: "PUSH HL", Length: 1, Address: 0xFFFF}, nil
case 0xE6: // AND n
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for AND n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("AND $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0xE7: // RST 20H
return &Instruction{Mnemonic: "RST 20H", Length: 1, Address: 0x0020}, nil
case 0xE8: // RET PE
return &Instruction{Mnemonic: "RET PE", Length: 1, Address: 0xFFFF}, nil
case 0xE9: // JP (HL)
return &Instruction{Mnemonic: "JP (HL)", Length: 1, Address: 0xFFFF}, nil
case 0xEA: // JP PE, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for JP PE, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("JP PE, $%04X", nn), Length: 3, Address: nn}, nil
case 0xEB: // EX DE, HL
return &Instruction{Mnemonic: "EX DE, HL", Length: 1, Address: 0xFFFF}, nil
case 0xEC: // CALL PE, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for CALL PE, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("CALL PE, $%04X", nn), Length: 3, Address: nn}, nil
case 0xED: // PREFIX ED
// This should be handled in the main Decode function
return &Instruction{Mnemonic: "PREFIX ED", Length: 1, Address: 0xFFFF}, nil
case 0xEE: // XOR n
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for XOR n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("XOR $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0xEF: // RST 28H
return &Instruction{Mnemonic: "RST 28H", Length: 1, Address: 0x0028}, nil
// Conditional operations (0xF0-0xFF)
case 0xF0: // RET P
return &Instruction{Mnemonic: "RET P", Length: 1, Address: 0xFFFF}, nil
case 0xF1: // POP AF
return &Instruction{Mnemonic: "POP AF", Length: 1, Address: 0xFFFF}, nil
case 0xF2: // JP P, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for JP P, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("JP P, $%04X", nn), Length: 3, Address: nn}, nil
case 0xF3: // DI
return &Instruction{Mnemonic: "DI", Length: 1, Address: 0xFFFF}, nil
case 0xF4: // CALL P, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for CALL P, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("CALL P, $%04X", nn), Length: 3, Address: nn}, nil
case 0xF5: // PUSH AF
return &Instruction{Mnemonic: "PUSH AF", Length: 1, Address: 0xFFFF}, nil
case 0xF6: // OR n
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for OR n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("OR $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0xF7: // RST 30H
return &Instruction{Mnemonic: "RST 30H", Length: 1, Address: 0x0030}, nil
case 0xF8: // RET M
return &Instruction{Mnemonic: "RET M", Length: 1, Address: 0xFFFF}, nil
case 0xF9: // LD SP, HL
return &Instruction{Mnemonic: "LD SP, HL", Length: 1, Address: 0xFFFF}, nil
case 0xFA: // JP M, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for JP M, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("JP M, $%04X", nn), Length: 3, Address: nn}, nil
case 0xFB: // EI
return &Instruction{Mnemonic: "EI", Length: 1, Address: 0xFFFF}, nil
case 0xFC: // CALL M, nn
if len(data) < 3 {
return nil, fmt.Errorf("insufficient data for CALL M, nn")
}
nn := uint16(data[2])<<8 | uint16(data[1])
return &Instruction{Mnemonic: fmt.Sprintf("CALL M, $%04X", nn), Length: 3, Address: nn}, nil
case 0xFD: // PREFIX FD
// This should be handled in the main Decode function
return &Instruction{Mnemonic: "PREFIX FD", Length: 1, Address: 0xFFFF}, nil
case 0xFE: // CP n
if len(data) < 2 {
return nil, fmt.Errorf("insufficient data for CP n")
}
n := data[1]
return &Instruction{Mnemonic: fmt.Sprintf("CP $%02X", n), Length: 2, Address: 0xFFFF}, nil
case 0xFF: // RST 38H
return &Instruction{Mnemonic: "RST 38H", Length: 1, Address: 0x0038}, nil
// Default case for unimplemented opcodes
default:
return &Instruction{Mnemonic: fmt.Sprintf("DB $%02X", opcode), Length: 1, Address: 0xFFFF}, nil
}
}

46
disasm.go Normal file
View File

@@ -0,0 +1,46 @@
// Package disasm provides a Z80 disassembler implementation
package disasm
import (
"fmt"
)
// Instruction represents a decoded Z80 instruction
type Instruction struct {
Mnemonic string // Human-readable instruction mnemonic
Length int // Number of bytes the instruction occupies
Address uint16 // Address operand for jump/load instructions, 0xFFFF if not applicable
}
// Disassembler represents a Z80 disassembler
type Disassembler struct{}
// New creates a new Z80 disassembler
func New() *Disassembler {
return &Disassembler{}
}
// Decode decodes a single Z80 instruction from a byte slice
// It returns the decoded instruction and any error encountered
func (d *Disassembler) Decode(data []byte) (*Instruction, error) {
if len(data) == 0 {
return nil, fmt.Errorf("no data to decode")
}
// Get the first opcode byte
opcode := data[0]
// Handle prefixed instructions (CB, DD, ED, FD prefixes)
switch opcode {
case 0xCB:
return d.decodeCB(data)
case 0xDD:
return d.decodeDD(data)
case 0xED:
return d.decodeED(data)
case 0xFD:
return d.decodeFD(data)
default:
return d.decodeUnprefixed(opcode, data)
}
}

778
ed_test.go Normal file
View File

@@ -0,0 +1,778 @@
// Package disasm provides tests for the Z80 disassembler implementation
package disasm
import (
"testing"
)
// TestDecodeED tests decoding of ED-prefixed Z80 instructions
func TestDecodeED(t *testing.T) {
d := New()
tests := []struct {
name string
data []byte
expected Instruction
hasError bool
}{
{
name: "IN B, (C)",
data: []byte{0xED, 0x40},
expected: Instruction{
Mnemonic: "IN B, (C)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUT (C), B",
data: []byte{0xED, 0x41},
expected: Instruction{
Mnemonic: "OUT (C), B",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SBC HL, BC",
data: []byte{0xED, 0x42},
expected: Instruction{
Mnemonic: "SBC HL, BC",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD (nn), BC",
data: []byte{0xED, 0x43, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD ($3412), BC",
Length: 4,
Address: 0x3412,
},
},
{
name: "NEG",
data: []byte{0xED, 0x44},
expected: Instruction{
Mnemonic: "NEG",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RETN",
data: []byte{0xED, 0x45},
expected: Instruction{
Mnemonic: "RETN",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IM 0",
data: []byte{0xED, 0x46},
expected: Instruction{
Mnemonic: "IM 0",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD I, A",
data: []byte{0xED, 0x47},
expected: Instruction{
Mnemonic: "LD I, A",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IN C, (C)",
data: []byte{0xED, 0x48},
expected: Instruction{
Mnemonic: "IN C, (C)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUT (C), C",
data: []byte{0xED, 0x49},
expected: Instruction{
Mnemonic: "OUT (C), C",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADC HL, BC",
data: []byte{0xED, 0x4A},
expected: Instruction{
Mnemonic: "ADC HL, BC",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD BC, (nn)",
data: []byte{0xED, 0x4B, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD BC, ($3412)",
Length: 4,
Address: 0x3412,
},
},
{
name: "NEG (duplicate)",
data: []byte{0xED, 0x4C},
expected: Instruction{
Mnemonic: "NEG",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RETI",
data: []byte{0xED, 0x4D},
expected: Instruction{
Mnemonic: "RETI",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IM 0 (duplicate)",
data: []byte{0xED, 0x4E},
expected: Instruction{
Mnemonic: "IM 0",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD R, A",
data: []byte{0xED, 0x4F},
expected: Instruction{
Mnemonic: "LD R, A",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IN D, (C)",
data: []byte{0xED, 0x50},
expected: Instruction{
Mnemonic: "IN D, (C)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUT (C), D",
data: []byte{0xED, 0x51},
expected: Instruction{
Mnemonic: "OUT (C), D",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SBC HL, DE",
data: []byte{0xED, 0x52},
expected: Instruction{
Mnemonic: "SBC HL, DE",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD (nn), DE",
data: []byte{0xED, 0x53, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD ($3412), DE",
Length: 4,
Address: 0x3412,
},
},
{
name: "NEG (duplicate 2)",
data: []byte{0xED, 0x54},
expected: Instruction{
Mnemonic: "NEG",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RETN (duplicate)",
data: []byte{0xED, 0x55},
expected: Instruction{
Mnemonic: "RETN",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IM 1",
data: []byte{0xED, 0x56},
expected: Instruction{
Mnemonic: "IM 1",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD A, I",
data: []byte{0xED, 0x57},
expected: Instruction{
Mnemonic: "LD A, I",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IN E, (C)",
data: []byte{0xED, 0x58},
expected: Instruction{
Mnemonic: "IN E, (C)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUT (C), E",
data: []byte{0xED, 0x59},
expected: Instruction{
Mnemonic: "OUT (C), E",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADC HL, DE",
data: []byte{0xED, 0x5A},
expected: Instruction{
Mnemonic: "ADC HL, DE",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD DE, (nn)",
data: []byte{0xED, 0x5B, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD DE, ($3412)",
Length: 4,
Address: 0x3412,
},
},
{
name: "NEG (duplicate 3)",
data: []byte{0xED, 0x5C},
expected: Instruction{
Mnemonic: "NEG",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RETN (duplicate 2)",
data: []byte{0xED, 0x5D},
expected: Instruction{
Mnemonic: "RETN",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IM 2",
data: []byte{0xED, 0x5E},
expected: Instruction{
Mnemonic: "IM 2",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD A, R",
data: []byte{0xED, 0x5F},
expected: Instruction{
Mnemonic: "LD A, R",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IN H, (C)",
data: []byte{0xED, 0x60},
expected: Instruction{
Mnemonic: "IN H, (C)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUT (C), H",
data: []byte{0xED, 0x61},
expected: Instruction{
Mnemonic: "OUT (C), H",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SBC HL, HL",
data: []byte{0xED, 0x62},
expected: Instruction{
Mnemonic: "SBC HL, HL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD (nn), HL",
data: []byte{0xED, 0x63, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD ($3412), HL",
Length: 4,
Address: 0x3412,
},
},
{
name: "NEG (duplicate 4)",
data: []byte{0xED, 0x64},
expected: Instruction{
Mnemonic: "NEG",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RETN (duplicate 3)",
data: []byte{0xED, 0x65},
expected: Instruction{
Mnemonic: "RETN",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IM 0 (duplicate 2)",
data: []byte{0xED, 0x66},
expected: Instruction{
Mnemonic: "IM 0",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RRD",
data: []byte{0xED, 0x67},
expected: Instruction{
Mnemonic: "RRD",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IN L, (C)",
data: []byte{0xED, 0x68},
expected: Instruction{
Mnemonic: "IN L, (C)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUT (C), L",
data: []byte{0xED, 0x69},
expected: Instruction{
Mnemonic: "OUT (C), L",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADC HL, HL",
data: []byte{0xED, 0x6A},
expected: Instruction{
Mnemonic: "ADC HL, HL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD HL, (nn)",
data: []byte{0xED, 0x6B, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD HL, ($3412)",
Length: 4,
Address: 0x3412,
},
},
{
name: "NEG (duplicate 5)",
data: []byte{0xED, 0x6C},
expected: Instruction{
Mnemonic: "NEG",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RETN (duplicate 4)",
data: []byte{0xED, 0x6D},
expected: Instruction{
Mnemonic: "RETN",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IM 0 (duplicate 3)",
data: []byte{0xED, 0x6E},
expected: Instruction{
Mnemonic: "IM 0",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RLD",
data: []byte{0xED, 0x6F},
expected: Instruction{
Mnemonic: "RLD",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IN F, (C)",
data: []byte{0xED, 0x70},
expected: Instruction{
Mnemonic: "IN F, (C)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUT (C), 0",
data: []byte{0xED, 0x71},
expected: Instruction{
Mnemonic: "OUT (C), 0",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SBC HL, SP",
data: []byte{0xED, 0x72},
expected: Instruction{
Mnemonic: "SBC HL, SP",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD (nn), SP",
data: []byte{0xED, 0x73, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD ($3412), SP",
Length: 4,
Address: 0x3412,
},
},
{
name: "NEG (duplicate 6)",
data: []byte{0xED, 0x74},
expected: Instruction{
Mnemonic: "NEG",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RETN (duplicate 5)",
data: []byte{0xED, 0x75},
expected: Instruction{
Mnemonic: "RETN",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IM 1 (duplicate)",
data: []byte{0xED, 0x76},
expected: Instruction{
Mnemonic: "IM 1",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "NOP",
data: []byte{0xED, 0x77},
expected: Instruction{
Mnemonic: "NOP",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IN A, (C)",
data: []byte{0xED, 0x78},
expected: Instruction{
Mnemonic: "IN A, (C)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUT (C), A",
data: []byte{0xED, 0x79},
expected: Instruction{
Mnemonic: "OUT (C), A",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADC HL, SP",
data: []byte{0xED, 0x7A},
expected: Instruction{
Mnemonic: "ADC HL, SP",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD SP, (nn)",
data: []byte{0xED, 0x7B, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD SP, ($3412)",
Length: 4,
Address: 0x3412,
},
},
{
name: "NEG (duplicate 7)",
data: []byte{0xED, 0x7C},
expected: Instruction{
Mnemonic: "NEG",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RETN (duplicate 6)",
data: []byte{0xED, 0x7D},
expected: Instruction{
Mnemonic: "RETN",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IM 2 (duplicate)",
data: []byte{0xED, 0x7E},
expected: Instruction{
Mnemonic: "IM 2",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "NOP (duplicate)",
data: []byte{0xED, 0x7F},
expected: Instruction{
Mnemonic: "NOP",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LDI",
data: []byte{0xED, 0xA0},
expected: Instruction{
Mnemonic: "LDI",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "CPI",
data: []byte{0xED, 0xA1},
expected: Instruction{
Mnemonic: "CPI",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "INI",
data: []byte{0xED, 0xA2},
expected: Instruction{
Mnemonic: "INI",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUTI",
data: []byte{0xED, 0xA3},
expected: Instruction{
Mnemonic: "OUTI",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LDD",
data: []byte{0xED, 0xA8},
expected: Instruction{
Mnemonic: "LDD",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "CPD",
data: []byte{0xED, 0xA9},
expected: Instruction{
Mnemonic: "CPD",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "IND",
data: []byte{0xED, 0xAA},
expected: Instruction{
Mnemonic: "IND",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OUTD",
data: []byte{0xED, 0xAB},
expected: Instruction{
Mnemonic: "OUTD",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LDIR",
data: []byte{0xED, 0xB0},
expected: Instruction{
Mnemonic: "LDIR",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "CPIR",
data: []byte{0xED, 0xB1},
expected: Instruction{
Mnemonic: "CPIR",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "INIR",
data: []byte{0xED, 0xB2},
expected: Instruction{
Mnemonic: "INIR",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OTIR",
data: []byte{0xED, 0xB3},
expected: Instruction{
Mnemonic: "OTIR",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LDDR",
data: []byte{0xED, 0xB8},
expected: Instruction{
Mnemonic: "LDDR",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "CPDR",
data: []byte{0xED, 0xB9},
expected: Instruction{
Mnemonic: "CPDR",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "INDR",
data: []byte{0xED, 0xBA},
expected: Instruction{
Mnemonic: "INDR",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OTDR",
data: []byte{0xED, 0xBB},
expected: Instruction{
Mnemonic: "OTDR",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "Insufficient data for ED prefix",
data: []byte{0xED},
hasError: true,
},
{
name: "Insufficient data for LD (nn), BC",
data: []byte{0xED, 0x43, 0x12},
hasError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := d.Decode(tt.data)
if tt.hasError {
if err == nil {
t.Errorf("expected error but got none")
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.Mnemonic != tt.expected.Mnemonic {
t.Errorf("mnemonic mismatch: got %q, want %q", result.Mnemonic, tt.expected.Mnemonic)
}
if result.Length != tt.expected.Length {
t.Errorf("length mismatch: got %d, want %d", result.Length, tt.expected.Length)
}
if result.Address != tt.expected.Address {
t.Errorf("address mismatch: got 0x%04X, want 0x%04X", result.Address, tt.expected.Address)
}
})
}
}

15
empty_test.go Normal file
View File

@@ -0,0 +1,15 @@
// Package disasm provides tests for the Z80 disassembler implementation
package disasm
import (
"testing"
)
// TestEmptyData tests handling of empty data
func TestEmptyData(t *testing.T) {
d := New()
_, err := d.Decode([]byte{})
if err == nil {
t.Errorf("expected error for empty data but got none")
}
}

823
fd_test.go Normal file
View File

@@ -0,0 +1,823 @@
// Package disasm provides tests for the Z80 disassembler implementation
package disasm
import (
"testing"
)
// TestDecodeFD tests decoding of FD-prefixed Z80 instructions
func TestDecodeFD(t *testing.T) {
d := New()
tests := []struct {
name string
data []byte
expected Instruction
hasError bool
}{
{
name: "LD IY, nn",
data: []byte{0xFD, 0x21, 0x34, 0x12},
expected: Instruction{
Mnemonic: "LD IY, $1234",
Length: 4,
Address: 0x1234,
},
},
{
name: "ADD IY, BC",
data: []byte{0xFD, 0x09},
expected: Instruction{
Mnemonic: "ADD IY, BC",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADD IY, DE",
data: []byte{0xFD, 0x19},
expected: Instruction{
Mnemonic: "ADD IY, DE",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD (nn), IY",
data: []byte{0xFD, 0x22, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD ($3412), IY",
Length: 4,
Address: 0x3412,
},
},
{
name: "INC IY",
data: []byte{0xFD, 0x23},
expected: Instruction{
Mnemonic: "INC IY",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "INC IYH",
data: []byte{0xFD, 0x24},
expected: Instruction{
Mnemonic: "INC IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "DEC IYH",
data: []byte{0xFD, 0x25},
expected: Instruction{
Mnemonic: "DEC IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYH, n",
data: []byte{0xFD, 0x26, 0x42},
expected: Instruction{
Mnemonic: "LD IYH, $42",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "ADD IY, IY",
data: []byte{0xFD, 0x29},
expected: Instruction{
Mnemonic: "ADD IY, IY",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IY, (nn)",
data: []byte{0xFD, 0x2A, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD IY, ($3412)",
Length: 4,
Address: 0x3412,
},
},
{
name: "DEC IY",
data: []byte{0xFD, 0x2B},
expected: Instruction{
Mnemonic: "DEC IY",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "INC IYL",
data: []byte{0xFD, 0x2C},
expected: Instruction{
Mnemonic: "INC IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "DEC IYL",
data: []byte{0xFD, 0x2D},
expected: Instruction{
Mnemonic: "DEC IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYL, n",
data: []byte{0xFD, 0x2E, 0x42},
expected: Instruction{
Mnemonic: "LD IYL, $42",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "INC (IY+d)",
data: []byte{0xFD, 0x34, 0x05},
expected: Instruction{
Mnemonic: "INC (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "DEC (IY+d)",
data: []byte{0xFD, 0x35, 0x05},
expected: Instruction{
Mnemonic: "DEC (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IY+d), n",
data: []byte{0xFD, 0x36, 0x05, 0x42},
expected: Instruction{
Mnemonic: "LD (IY+$05), $42",
Length: 4,
Address: 0xFFFF,
},
},
{
name: "ADD IY, SP",
data: []byte{0xFD, 0x39},
expected: Instruction{
Mnemonic: "ADD IY, SP",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD B, IYH",
data: []byte{0xFD, 0x44},
expected: Instruction{
Mnemonic: "LD B, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD B, IYL",
data: []byte{0xFD, 0x45},
expected: Instruction{
Mnemonic: "LD B, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD B, (IY+d)",
data: []byte{0xFD, 0x46, 0x05},
expected: Instruction{
Mnemonic: "LD B, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD C, IYH",
data: []byte{0xFD, 0x4C},
expected: Instruction{
Mnemonic: "LD C, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD C, IYL",
data: []byte{0xFD, 0x4D},
expected: Instruction{
Mnemonic: "LD C, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD C, (IY+d)",
data: []byte{0xFD, 0x4E, 0x05},
expected: Instruction{
Mnemonic: "LD C, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD D, IYH",
data: []byte{0xFD, 0x54},
expected: Instruction{
Mnemonic: "LD D, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD D, IYL",
data: []byte{0xFD, 0x55},
expected: Instruction{
Mnemonic: "LD D, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD D, (IY+d)",
data: []byte{0xFD, 0x56, 0x05},
expected: Instruction{
Mnemonic: "LD D, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD E, IYH",
data: []byte{0xFD, 0x5C},
expected: Instruction{
Mnemonic: "LD E, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD E, IYL",
data: []byte{0xFD, 0x5D},
expected: Instruction{
Mnemonic: "LD E, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD E, (IY+d)",
data: []byte{0xFD, 0x5E, 0x05},
expected: Instruction{
Mnemonic: "LD E, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD IYH, B",
data: []byte{0xFD, 0x60},
expected: Instruction{
Mnemonic: "LD IYH, B",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYH, C",
data: []byte{0xFD, 0x61},
expected: Instruction{
Mnemonic: "LD IYH, C",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYH, D",
data: []byte{0xFD, 0x62},
expected: Instruction{
Mnemonic: "LD IYH, D",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYH, E",
data: []byte{0xFD, 0x63},
expected: Instruction{
Mnemonic: "LD IYH, E",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYH, IYH",
data: []byte{0xFD, 0x64},
expected: Instruction{
Mnemonic: "LD IYH, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYH, IYL",
data: []byte{0xFD, 0x65},
expected: Instruction{
Mnemonic: "LD IYH, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD H, (IY+d)",
data: []byte{0xFD, 0x66, 0x05},
expected: Instruction{
Mnemonic: "LD H, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD IYH, A",
data: []byte{0xFD, 0x67},
expected: Instruction{
Mnemonic: "LD IYH, A",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYL, B",
data: []byte{0xFD, 0x68},
expected: Instruction{
Mnemonic: "LD IYL, B",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYL, C",
data: []byte{0xFD, 0x69},
expected: Instruction{
Mnemonic: "LD IYL, C",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYL, D",
data: []byte{0xFD, 0x6A},
expected: Instruction{
Mnemonic: "LD IYL, D",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYL, E",
data: []byte{0xFD, 0x6B},
expected: Instruction{
Mnemonic: "LD IYL, E",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYL, IYH",
data: []byte{0xFD, 0x6C},
expected: Instruction{
Mnemonic: "LD IYL, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD IYL, IYL",
data: []byte{0xFD, 0x6D},
expected: Instruction{
Mnemonic: "LD IYL, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD L, (IY+d)",
data: []byte{0xFD, 0x6E, 0x05},
expected: Instruction{
Mnemonic: "LD L, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD IYL, A",
data: []byte{0xFD, 0x6F},
expected: Instruction{
Mnemonic: "LD IYL, A",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD (IY+d), B",
data: []byte{0xFD, 0x70, 0x05},
expected: Instruction{
Mnemonic: "LD (IY+$05), B",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IY+d), C",
data: []byte{0xFD, 0x71, 0x05},
expected: Instruction{
Mnemonic: "LD (IY+$05), C",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IY+d), D",
data: []byte{0xFD, 0x72, 0x05},
expected: Instruction{
Mnemonic: "LD (IY+$05), D",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IY+d), E",
data: []byte{0xFD, 0x73, 0x05},
expected: Instruction{
Mnemonic: "LD (IY+$05), E",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IY+d), H",
data: []byte{0xFD, 0x74, 0x05},
expected: Instruction{
Mnemonic: "LD (IY+$05), H",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IY+d), L",
data: []byte{0xFD, 0x75, 0x05},
expected: Instruction{
Mnemonic: "LD (IY+$05), L",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD (IY+d), A",
data: []byte{0xFD, 0x77, 0x05},
expected: Instruction{
Mnemonic: "LD (IY+$05), A",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "LD A, IYH",
data: []byte{0xFD, 0x7C},
expected: Instruction{
Mnemonic: "LD A, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD A, IYL",
data: []byte{0xFD, 0x7D},
expected: Instruction{
Mnemonic: "LD A, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD A, (IY+d)",
data: []byte{0xFD, 0x7E, 0x05},
expected: Instruction{
Mnemonic: "LD A, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "ADD A, IYH",
data: []byte{0xFD, 0x84},
expected: Instruction{
Mnemonic: "ADD A, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADD A, IYL",
data: []byte{0xFD, 0x85},
expected: Instruction{
Mnemonic: "ADD A, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADD A, (IY+d)",
data: []byte{0xFD, 0x86, 0x05},
expected: Instruction{
Mnemonic: "ADD A, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "ADC A, IYH",
data: []byte{0xFD, 0x8C},
expected: Instruction{
Mnemonic: "ADC A, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADC A, IYL",
data: []byte{0xFD, 0x8D},
expected: Instruction{
Mnemonic: "ADC A, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "ADC A, (IY+d)",
data: []byte{0xFD, 0x8E, 0x05},
expected: Instruction{
Mnemonic: "ADC A, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "SUB IYH",
data: []byte{0xFD, 0x94},
expected: Instruction{
Mnemonic: "SUB IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SUB IYL",
data: []byte{0xFD, 0x95},
expected: Instruction{
Mnemonic: "SUB IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SUB (IY+d)",
data: []byte{0xFD, 0x96, 0x05},
expected: Instruction{
Mnemonic: "SUB (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "SBC A, IYH",
data: []byte{0xFD, 0x9C},
expected: Instruction{
Mnemonic: "SBC A, IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SBC A, IYL",
data: []byte{0xFD, 0x9D},
expected: Instruction{
Mnemonic: "SBC A, IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "SBC A, (IY+d)",
data: []byte{0xFD, 0x9E, 0x05},
expected: Instruction{
Mnemonic: "SBC A, (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "AND IYH",
data: []byte{0xFD, 0xA4},
expected: Instruction{
Mnemonic: "AND IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "AND IYL",
data: []byte{0xFD, 0xA5},
expected: Instruction{
Mnemonic: "AND IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "AND (IY+d)",
data: []byte{0xFD, 0xA6, 0x05},
expected: Instruction{
Mnemonic: "AND (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "XOR IYH",
data: []byte{0xFD, 0xAC},
expected: Instruction{
Mnemonic: "XOR IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "XOR IYL",
data: []byte{0xFD, 0xAD},
expected: Instruction{
Mnemonic: "XOR IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "XOR (IY+d)",
data: []byte{0xFD, 0xAE, 0x05},
expected: Instruction{
Mnemonic: "XOR (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "OR IYH",
data: []byte{0xFD, 0xB4},
expected: Instruction{
Mnemonic: "OR IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OR IYL",
data: []byte{0xFD, 0xB5},
expected: Instruction{
Mnemonic: "OR IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "OR (IY+d)",
data: []byte{0xFD, 0xB6, 0x05},
expected: Instruction{
Mnemonic: "OR (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "CP IYH",
data: []byte{0xFD, 0xBC},
expected: Instruction{
Mnemonic: "CP IYH",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "CP IYL",
data: []byte{0xFD, 0xBD},
expected: Instruction{
Mnemonic: "CP IYL",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "CP (IY+d)",
data: []byte{0xFD, 0xBE, 0x05},
expected: Instruction{
Mnemonic: "CP (IY+$05)",
Length: 3,
Address: 0xFFFF,
},
},
{
name: "POP IY",
data: []byte{0xFD, 0xE1},
expected: Instruction{
Mnemonic: "POP IY",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "EX (SP), IY",
data: []byte{0xFD, 0xE3},
expected: Instruction{
Mnemonic: "EX (SP), IY",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "PUSH IY",
data: []byte{0xFD, 0xE5},
expected: Instruction{
Mnemonic: "PUSH IY",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "JP (IY)",
data: []byte{0xFD, 0xE9},
expected: Instruction{
Mnemonic: "JP (IY)",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD SP, IY",
data: []byte{0xFD, 0xF9},
expected: Instruction{
Mnemonic: "LD SP, IY",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "Insufficient data for FD prefix",
data: []byte{0xFD},
hasError: true,
},
{
name: "Insufficient data for LD IY, nn",
data: []byte{0xFD, 0x21, 0x34},
hasError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := d.Decode(tt.data)
if tt.hasError {
if err == nil {
t.Errorf("expected error but got none")
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.Mnemonic != tt.expected.Mnemonic {
t.Errorf("mnemonic mismatch: got %q, want %q", result.Mnemonic, tt.expected.Mnemonic)
}
if result.Length != tt.expected.Length {
t.Errorf("length mismatch: got %d, want %d", result.Length, tt.expected.Length)
}
if result.Address != tt.expected.Address {
t.Errorf("address mismatch: got 0x%04X, want 0x%04X", result.Address, tt.expected.Address)
}
})
}
}

2399
fdcb_test.go Normal file

File diff suppressed because it is too large Load Diff

3
go.mod Normal file
View File

@@ -0,0 +1,3 @@
module git.tygh.ru/kiltum/emuz80disasmgo
go 1.25.1

0
go.sum Normal file
View File

512
unprefixed_test.go Normal file
View File

@@ -0,0 +1,512 @@
// Package disasm provides tests for the Z80 disassembler implementation
package disasm
import (
"testing"
)
// TestDecodeUnprefixed tests decoding of unprefixed Z80 instructions
func TestDecodeUnprefixed(t *testing.T) {
d := New()
tests := []struct {
name string
data []byte
expected Instruction
hasError bool
}{
{
name: "NOP",
data: []byte{0x00},
expected: Instruction{
Mnemonic: "NOP",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "LD BC, nn",
data: []byte{0x01, 0x34, 0x12},
expected: Instruction{
Mnemonic: "LD BC, $1234",
Length: 3,
Address: 0x1234,
},
},
{
name: "LD (BC), A",
data: []byte{0x02},
expected: Instruction{
Mnemonic: "LD (BC), A",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "INC BC",
data: []byte{0x03},
expected: Instruction{
Mnemonic: "INC BC",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "INC B",
data: []byte{0x04},
expected: Instruction{
Mnemonic: "INC B",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "DEC B",
data: []byte{0x05},
expected: Instruction{
Mnemonic: "DEC B",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "LD B, n",
data: []byte{0x06, 0x42},
expected: Instruction{
Mnemonic: "LD B, $42",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RLCA",
data: []byte{0x07},
expected: Instruction{
Mnemonic: "RLCA",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "EX AF, AF'",
data: []byte{0x08},
expected: Instruction{
Mnemonic: "EX AF, AF'",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "ADD HL, BC",
data: []byte{0x09},
expected: Instruction{
Mnemonic: "ADD HL, BC",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "LD A, (BC)",
data: []byte{0x0A},
expected: Instruction{
Mnemonic: "LD A, (BC)",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "DEC BC",
data: []byte{0x0B},
expected: Instruction{
Mnemonic: "DEC BC",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "INC C",
data: []byte{0x0C},
expected: Instruction{
Mnemonic: "INC C",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "DEC C",
data: []byte{0x0D},
expected: Instruction{
Mnemonic: "DEC C",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "LD C, n",
data: []byte{0x0E, 0xAB},
expected: Instruction{
Mnemonic: "LD C, $AB",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "RRCA",
data: []byte{0x0F},
expected: Instruction{
Mnemonic: "RRCA",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "DJNZ e",
data: []byte{0x10, 0x05},
expected: Instruction{
Mnemonic: "DJNZ $05",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "JR e",
data: []byte{0x18, 0x0A},
expected: Instruction{
Mnemonic: "JR $0A",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "JR NZ, e",
data: []byte{0x20, 0x05},
expected: Instruction{
Mnemonic: "JR NZ, $05",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "JR Z, e",
data: []byte{0x28, 0x05},
expected: Instruction{
Mnemonic: "JR Z, $05",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "JR NC, e",
data: []byte{0x30, 0x05},
expected: Instruction{
Mnemonic: "JR NC, $05",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "JR C, e",
data: []byte{0x38, 0x05},
expected: Instruction{
Mnemonic: "JR C, $05",
Length: 2,
Address: 0xFFFF,
},
},
{
name: "LD HL, nn",
data: []byte{0x21, 0xCD, 0xAB},
expected: Instruction{
Mnemonic: "LD HL, $ABCD",
Length: 3,
Address: 0xABCD,
},
},
{
name: "LD (nn), HL",
data: []byte{0x22, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD ($3412), HL",
Length: 3,
Address: 0x3412,
},
},
{
name: "LD HL, (nn)",
data: []byte{0x2A, 0x12, 0x34},
expected: Instruction{
Mnemonic: "LD HL, ($3412)",
Length: 3,
Address: 0x3412,
},
},
{
name: "INC DE",
data: []byte{0x13},
expected: Instruction{
Mnemonic: "INC DE",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "INC HL",
data: []byte{0x23},
expected: Instruction{
Mnemonic: "INC HL",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "INC SP",
data: []byte{0x33},
expected: Instruction{
Mnemonic: "INC SP",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "DEC DE",
data: []byte{0x1B},
expected: Instruction{
Mnemonic: "DEC DE",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "DEC HL",
data: []byte{0x2B},
expected: Instruction{
Mnemonic: "DEC HL",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "DEC SP",
data: []byte{0x3B},
expected: Instruction{
Mnemonic: "DEC SP",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "JP nn",
data: []byte{0xC3, 0x12, 0x34},
expected: Instruction{
Mnemonic: "JP $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "JP NZ, nn",
data: []byte{0xC2, 0x12, 0x34},
expected: Instruction{
Mnemonic: "JP NZ, $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "JP Z, nn",
data: []byte{0xCA, 0x12, 0x34},
expected: Instruction{
Mnemonic: "JP Z, $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "JP NC, nn",
data: []byte{0xD2, 0x12, 0x34},
expected: Instruction{
Mnemonic: "JP NC, $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "JP C, nn",
data: []byte{0xDA, 0x12, 0x34},
expected: Instruction{
Mnemonic: "JP C, $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "JP PO, nn",
data: []byte{0xE2, 0x12, 0x34},
expected: Instruction{
Mnemonic: "JP PO, $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "JP PE, nn",
data: []byte{0xEA, 0x12, 0x34},
expected: Instruction{
Mnemonic: "JP PE, $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "JP P, nn",
data: []byte{0xF2, 0x12, 0x34},
expected: Instruction{
Mnemonic: "JP P, $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "JP M, nn",
data: []byte{0xFA, 0x12, 0x34},
expected: Instruction{
Mnemonic: "JP M, $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "CALL nn",
data: []byte{0xCD, 0x12, 0x34},
expected: Instruction{
Mnemonic: "CALL $3412",
Length: 3,
Address: 0x3412,
},
},
{
name: "RET",
data: []byte{0xC9},
expected: Instruction{
Mnemonic: "RET",
Length: 1,
Address: 0xFFFF,
},
},
{
name: "RST 00H",
data: []byte{0xC7},
expected: Instruction{
Mnemonic: "RST 00H",
Length: 1,
Address: 0x0000,
},
},
{
name: "RST 08H",
data: []byte{0xCF},
expected: Instruction{
Mnemonic: "RST 08H",
Length: 1,
Address: 0x0008,
},
},
{
name: "RST 10H",
data: []byte{0xD7},
expected: Instruction{
Mnemonic: "RST 10H",
Length: 1,
Address: 0x0010,
},
},
{
name: "RST 18H",
data: []byte{0xDF},
expected: Instruction{
Mnemonic: "RST 18H",
Length: 1,
Address: 0x0018,
},
},
{
name: "RST 20H",
data: []byte{0xE7},
expected: Instruction{
Mnemonic: "RST 20H",
Length: 1,
Address: 0x0020,
},
},
{
name: "RST 28H",
data: []byte{0xEF},
expected: Instruction{
Mnemonic: "RST 28H",
Length: 1,
Address: 0x0028,
},
},
{
name: "RST 30H",
data: []byte{0xF7},
expected: Instruction{
Mnemonic: "RST 30H",
Length: 1,
Address: 0x0030,
},
},
{
name: "RST 38H",
data: []byte{0xFF},
expected: Instruction{
Mnemonic: "RST 38H",
Length: 1,
Address: 0x0038,
},
},
{
name: "Insufficient data for LD BC, nn",
data: []byte{0x01, 0x34},
hasError: true,
},
{
name: "Unknown opcode",
data: []byte{0xFF},
expected: Instruction{
Mnemonic: "RST 38H",
Length: 1,
Address: 0x0038,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := d.Decode(tt.data)
if tt.hasError {
if err == nil {
t.Errorf("expected error but got none")
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.Mnemonic != tt.expected.Mnemonic {
t.Errorf("mnemonic mismatch: got %q, want %q", result.Mnemonic, tt.expected.Mnemonic)
}
if result.Length != tt.expected.Length {
t.Errorf("length mismatch: got %d, want %d", result.Length, tt.expected.Length)
}
if result.Address != tt.expected.Address {
t.Errorf("address mismatch: got 0x%04X, want 0x%04X", result.Address, tt.expected.Address)
}
})
}
}