README
¶
zog
Z80 diassembler/assembler/emulator in golang
Update: Sat 28 Oct 11:38:39 BST 2017
So the cpu core passes zexdoc and has a quick and dirty pass for timing correct T-states. Similarly quick and dirty Spectrum screen and keyboard support and 'z80' file format support are sufficient to:
-
boot the original spectrum 48K ROM to basic and run the Most Important Program:
10 PRINT "HELLO"
20 GOTO 10
-
Load and run Manic Miner and Jetpac at what seem to be the correct speed.
-
Fail to run Elite, perhaps due to lacking interrupt mode support.
I think I'm unlikely to take it any further, since the world doesn't need another spectrum emulator. However, this was a lot of fun and both rewarding and challenging. I'd obviously do things quite a lot differently if I did it again, but learning is kind of the point.
If by any chance you are here looking for a spectrum emulator, you will find better ones elsewhere. If you are looking for how to code an emulator, you will almost certainly find better code elsewhere. But if you are writing your own and want to share thoughts, please let me know :-)
Z80 diassembler/assembler/emulator in golang
Just revisiting the first bit of serious programming I ever did - a Z80 disassembler.
This code currently (June 2017) implements all the instruction decode logic and has a String() representation for instructions. There is also a basic assembler (using the github.com/pointlander/peg parser), so that the emulator tests can be written in assembly rather than machine code. This gives us bytes -> string -> bytes conversions.
I had ambitions of wiring an assembler which could parse the zexall code as a test suite, but a macro assembler is a bigger undertaking than I'd like to get into prior to actually having an emulator.
Instead, the zmac assembler can be used to build zexall and next steps are actually to write the emulator.
Documentation
¶
Index ¶
- Constants
- Variables
- func Decode(r io.Reader) (chan Instruction, chan error)
- func Encode(insts []Instruction) []byte
- func NewAccum(name string, l Loc8) *accum
- func NewRot(name string, l Loc8, cpy Loc8) *rot
- type ADC16
- type ADD16
- type AccumInfo
- type Assembly
- func (a *Assembly) Encode() ([]byte, error)
- func (a *Assembly) FindLabelAddr(name string) (uint16, error)
- func (a *Assembly) Init()
- func (a *Assembly) Instructions() []Instruction
- func (a *Assembly) ResolveAddresses() error
- func (a *Assembly) ResolveLoc16(l Loc16) error
- func (a *Assembly) ResolveLoc8(l Loc8) error
- func (a *Assembly) String() string
- type BIT
- type CALL
- type Conditional
- type Contents
- type Current
- func (c *Current) Accum(name string)
- func (c *Current) Adc16()
- func (c *Current) Add16()
- func (c *Current) Bit()
- func (c *Current) Call()
- func (c *Current) Conditional(cc Conditional)
- func (c *Current) Copy8()
- func (c *Current) Dec16()
- func (c *Current) Dec8()
- func (c *Current) DefByte()
- func (c *Current) DefSpace()
- func (c *Current) DefWord()
- func (c *Current) Disp0xHex(s string)
- func (c *Current) DispDecimal(s string)
- func (c *Current) DispHex(s string)
- func (c *Current) Djnz()
- func (c *Current) Dst16()
- func (c *Current) Dst8()
- func (c *Current) EDSimple(name string)
- func (c *Current) Emit()
- func (c *Current) Ex()
- func (c *Current) GetAssembly() *Assembly
- func (c *Current) IR16Contents()
- func (c *Current) In()
- func (c *Current) Inc16()
- func (c *Current) Inc8()
- func (c *Current) Init()
- func (c *Current) Jp()
- func (c *Current) Jr()
- func (c *Current) LD16()
- func (c *Current) LD8()
- func (c *Current) LabelDefn(label string)
- func (c *Current) Loc16()
- func (c *Current) Loc8()
- func (c *Current) NNContents()
- func (c *Current) NNLabel(label string)
- func (c *Current) NNhex(s string)
- func (c *Current) Ndec(s string)
- func (c *Current) Nhex(s string)
- func (c *Current) ODigit(s string)
- func (c *Current) Org()
- func (c *Current) Out()
- func (c *Current) Pop()
- func (c *Current) Push()
- func (c *Current) R16(s string)
- func (c *Current) R16Contents()
- func (c *Current) R8(s string)
- func (c *Current) Res()
- func (c *Current) Ret()
- func (c *Current) Rot(name string)
- func (c *Current) Rst()
- func (c *Current) Sbc16()
- func (c *Current) Set()
- func (c *Current) Simple(name string)
- func (c *Current) Src16()
- func (c *Current) Src8()
- type DEC16
- type DEC8
- type DJNZ
- type Data
- type DecodeTable
- type Disp
- type EDSimple
- type EX
- type FlagTest
- type IN
- type INC16
- type INC8
- type Imm16
- type Imm8
- type IndexedContents
- type InstBin16
- type InstBin8
- type InstU16
- type InstU8
- type Instruction
- type InterruptState
- type JP
- type JR
- type LD16
- type LD8
- type Label
- type LabelHolder
- type LabelledInstruction
- type Loc
- type Loc16
- type Loc8
- type Machine
- type Memory
- func (m *Memory) Clear()
- func (m *Memory) Copy(addr uint16, buf []byte) error
- func (m *Memory) Len() int
- func (m *Memory) Peek(addr uint16) (byte, error)
- func (m *Memory) Peek16(addr uint16) (uint16, error)
- func (m *Memory) PeekBuf(addr uint16, size int) ([]byte, error)
- func (m *Memory) Poke(addr uint16, n byte) error
- func (m *Memory) Poke16(addr uint16, nn uint16) error
- func (m *Memory) SetDebug(debug bool)
- func (m *Memory) SetWatchFunc(wf func(uint16, byte, byte))
- type Not
- type OUT
- type POP
- type PUSH
- type PegAssembler
- func (t *PegAssembler) AST() *node32
- func (t *PegAssembler) Add(rule pegRule, begin, end, index uint32)
- func (p *PegAssembler) Execute()
- func (p *PegAssembler) Init()
- func (p *PegAssembler) Parse(rule ...int) error
- func (t *PegAssembler) PrettyPrintSyntaxTree(buffer string)
- func (t *PegAssembler) Print()
- func (p *PegAssembler) PrintSyntaxTree()
- func (p *PegAssembler) Reset()
- func (t *PegAssembler) Tokens() []token32
- func (t *PegAssembler) Trim(length uint32)
- type R16
- type R8
- type RES
- type RET
- type RST
- type Region
- type Regions
- type Registers
- type RotInfo
- type SBC16
- type SET
- type Simple
- type TrueLogicConstant
- type Zog
- func (z *Zog) Clear()
- func (z *Zog) DoInterrupt()
- func (z *Zog) FlagString() string
- func (z *Zog) GetFlag(f flag) bool
- func (z *Zog) GetRegisters() Registers
- func (z *Zog) InterruptEnabled() bool
- func (z *Zog) Load(a *Assembly) error
- func (z *Zog) LoadBytes(addr uint16, buf []byte) error
- func (z *Zog) LoadFile(addr uint16, fname string, readonly bool) error
- func (z *Zog) LoadInterruptState(is InterruptState)
- func (z *Zog) LoadROMFile(addr uint16, fname string) error
- func (z *Zog) LoadRegisters(reg Registers)
- func (z *Zog) Read(buf []byte) (int, error)
- func (z *Zog) RegisterInputHandler(handler func(uint16) byte) error
- func (z *Zog) RegisterOutputHandler(handler func(uint16, byte)) error
- func (z *Zog) Run() (errRet error)
- func (z *Zog) RunAssembly(a *Assembly) error
- func (z *Zog) RunBytes(loadAddr uint16, buf []byte, runAddr uint16) error
- func (z *Zog) SetFlag(f flag, new bool)
- func (z *Zog) State() string
- func (z *Zog) TraceOnHalt(numHaltTraces int)
- func (z *Zog) TraceRegions(regions Regions) error
- func (z *Zog) WatchRegions(regions Regions) error
Constants ¶
const ( Immediate = 2 BCDEContents = 5 ImmediateContents = 6 )
const ( F_C flag = iota F_N F_PV F_3 F_H F_5 F_Z F_S )
const ClockHz = 3500000 / 2
const HL_RP_INDEX = 2
Variables ¶
var EDSimpleNames []edSimpleName = []edSimpleName{ {NEG, "NEG"}, {RETN, "RETN"}, {RETI, "RETI"}, {RRD, "RRD"}, {RLD, "RLD"}, {IM0, "IM 0"}, {IM1, "IM 1"}, {IM2, "IM 2"}, {LDI, "LDI"}, {CPI, "CPI"}, {LDD, "LDD"}, {CPD, "CPD"}, {LDIR, "LDIR"}, {CPIR, "CPIR"}, {LDDR, "LDDR"}, {CPDR, "CPDR"}, {INI, "INI"}, {OUTI, "OUTI"}, {IND, "IND"}, {OUTD, "OUTD"}, {INIR, "INIR"}, {OTIR, "OTIR"}, {INDR, "INDR"}, {OTDR, "OTDR"}, }
var ErrHalted = errors.New("HALT called")
var R16Names []r16name = []r16name{ {AF, "AF"}, {AF_PRIME, "AF'"}, {BC, "BC"}, {DE, "DE"}, {HL, "HL"}, {IX, "IX"}, {IY, "IY"}, {SP, "SP"}, }
Functions ¶
func Encode ¶
func Encode(insts []Instruction) []byte
Types ¶
type Assembly ¶
type Assembly struct { BaseAddr uint16 Linsts []LabelledInstruction Labels map[string]int // contains filtered or unexported fields }
func (*Assembly) Instructions ¶
func (a *Assembly) Instructions() []Instruction
func (*Assembly) ResolveAddresses ¶
func (*Assembly) ResolveLoc16 ¶
func (*Assembly) ResolveLoc8 ¶
type CALL ¶
type CALL struct { InstU16 // contains filtered or unexported fields }
func NewCALL ¶
func NewCALL(c Conditional, l Loc16) *CALL
type Conditional ¶
type Current ¶
type Current struct {
// contains filtered or unexported fields
}
func (*Current) Conditional ¶
func (c *Current) Conditional(cc Conditional)
func (*Current) DispDecimal ¶
func (*Current) GetAssembly ¶
func (*Current) IR16Contents ¶
func (c *Current) IR16Contents()
func (*Current) NNContents ¶
func (c *Current) NNContents()
func (*Current) R16Contents ¶
func (c *Current) R16Contents()
type DecodeTable ¶
type DecodeTable struct {
// contains filtered or unexported fields
}
func NewDecodeTable ¶
func NewDecodeTable(r io.Reader) *DecodeTable
func (*DecodeTable) LookupBLI ¶
func (t *DecodeTable) LookupBLI(a, b byte) Instruction
func (*DecodeTable) LookupR ¶
func (t *DecodeTable) LookupR(i byte) Loc8
func (*DecodeTable) LookupRP ¶
func (t *DecodeTable) LookupRP(i byte) Loc16
func (*DecodeTable) LookupRP2 ¶
func (t *DecodeTable) LookupRP2(i byte) Loc16
func (*DecodeTable) ResetPrefix ¶
func (t *DecodeTable) ResetPrefix(n byte)
type EDSimple ¶
type EDSimple byte
const ( NEG EDSimple = 0x44 RETN EDSimple = 0x45 RETI EDSimple = 0x4d RRD EDSimple = 0x67 RLD EDSimple = 0x6f IM0 EDSimple = 0x46 IM1 EDSimple = 0x56 IM2 EDSimple = 0x5e LDI EDSimple = 0xa0 CPI EDSimple = 0xa1 LDD EDSimple = 0xa8 CPD EDSimple = 0xa9 LDIR EDSimple = 0xb0 CPIR EDSimple = 0xb1 LDDR EDSimple = 0xb8 CPDR EDSimple = 0xb9 INI EDSimple = 0xa2 OUTI EDSimple = 0xa3 IND EDSimple = 0xaa OUTD EDSimple = 0xab INIR EDSimple = 0xb2 OTIR EDSimple = 0xb3 INDR EDSimple = 0xba OTDR EDSimple = 0xbb )
func LookupEDSimpleName ¶
type IndexedContents ¶
type IndexedContents struct {
// contains filtered or unexported fields
}
func (IndexedContents) String ¶
func (ic IndexedContents) String() string
type Instruction ¶
type Instruction interface { String() string Encode() []byte Resolve(a *Assembly) error Execute(z *Zog) error TStates(z *Zog) int }
func DecodeBytes ¶
func DecodeBytes(buf []byte) ([]Instruction, error)
type InterruptState ¶
type JP ¶
type JP struct { InstU16 // contains filtered or unexported fields }
func NewJP ¶
func NewJP(c Conditional, l Loc16) *JP
type Label ¶
type Label struct { // Default to the zero value because we need to encode // this location *before* it is resolved with an address // so that we can calculate instruction length. // See assemble/ResolveAddr Imm16 // contains filtered or unexported fields }
type LabelHolder ¶
type LabelHolder struct{}
func (*LabelHolder) Encode ¶
func (lh *LabelHolder) Encode() []byte
func (*LabelHolder) Execute ¶
func (lh *LabelHolder) Execute(z *Zog) error
func (*LabelHolder) Resolve ¶
func (lh *LabelHolder) Resolve(a *Assembly) error
func (*LabelHolder) String ¶
func (lh *LabelHolder) String() string
func (*LabelHolder) TStates ¶
func (lh *LabelHolder) TStates(z *Zog) int
type LabelledInstruction ¶
type LabelledInstruction struct { Label string Inst Instruction Addr uint16 }
type Loc ¶
type Loc interface { Read8(z *Zog) (byte, error) Write8(z *Zog, n byte) error Read16(z *Zog) (uint16, error) Write16(z *Zog, nn uint16) error String() string }
(HL), (BC), (SP) could refer to a byte addr or a word addr
type Memory ¶
type PegAssembler ¶
type PegAssembler struct { Current Buffer string Pretty bool // contains filtered or unexported fields }
func (*PegAssembler) Execute ¶
func (p *PegAssembler) Execute()
func (*PegAssembler) Init ¶
func (p *PegAssembler) Init()
func (*PegAssembler) Parse ¶
func (p *PegAssembler) Parse(rule ...int) error
func (*PegAssembler) PrettyPrintSyntaxTree ¶
func (t *PegAssembler) PrettyPrintSyntaxTree(buffer string)
func (*PegAssembler) PrintSyntaxTree ¶
func (p *PegAssembler) PrintSyntaxTree()
func (*PegAssembler) Reset ¶
func (p *PegAssembler) Reset()
type Registers ¶
type TrueLogicConstant ¶
type TrueLogicConstant struct{}
var True TrueLogicConstant
func (TrueLogicConstant) IsTrue ¶
func (l TrueLogicConstant) IsTrue(z *Zog) bool
func (TrueLogicConstant) String ¶
func (l TrueLogicConstant) String() string
type Zog ¶
type Zog struct { Mem *Memory // contains filtered or unexported fields }
func (*Zog) DoInterrupt ¶
func (z *Zog) DoInterrupt()
func (*Zog) FlagString ¶
func (*Zog) GetRegisters ¶
func (*Zog) InterruptEnabled ¶
func (*Zog) LoadInterruptState ¶
func (z *Zog) LoadInterruptState(is InterruptState)