Ocean-240.2-Emulator/z80/c99/cpu.go

278 lines
4.8 KiB
Go

package c99
import (
"errors"
"okemu/z80"
)
const (
PushValueTypeDefault = iota
PushValueTypeCall
PushValueTypeRst
PushValueTypePush
PushValueTypeMaskableInt
PushValueTypeNonMaskableInt
)
type Z80 struct {
// cycle count (t-states)
cycleCount uint32
// special purpose registers
pc, sp, ix, iy uint16
// "wz" register
memPtr uint16
// main registers
a, b, c, d, e, h, l byte
// alternate registers
a_, b_, c_, d_, e_, h_, l_, f_ byte
// interrupt vector, memory refresh
i, r byte
// flags: sign, zero, yf, half-carry, xf, parity/overflow, negative, carry
sf, zf, yf, hf, xf, pf, nf, cf bool
iffDelay byte
interruptMode byte
intData byte
iff1 bool
iff2 bool
isHalted bool
intPending bool
nmiPending bool
core z80.MemIoRW
memAccess map[uint16]byte
codeCoverageEnabled bool
codeCoverage map[uint16]bool
extendedStackEnabled bool
extendedStack [65536]uint8
}
const (
MemAccessRead = 1
MemAccessWrite = 2
)
// New initializes a Z80 instance and return pointer to it
func New(core z80.MemIoRW) *Z80 {
z := Z80{}
z.core = core
z.cycleCount = 0
z.pc = 0
z.sp = 0xFFFF
z.ix = 0
z.iy = 0
z.memPtr = 0
z.a = 0xFF
z.b = 0
z.c = 0
z.d = 0
z.e = 0
z.h = 0
z.l = 0
z.a_ = 0
z.b_ = 0
z.c_ = 0
z.d_ = 0
z.e_ = 0
z.h_ = 0
z.l_ = 0
z.f_ = 0
z.i = 0
z.r = 0
z.sf = true
z.zf = true
z.yf = true
z.hf = true
z.xf = true
z.pf = true
z.nf = true
z.cf = true
z.iffDelay = 0
z.interruptMode = 0
z.iff1 = false
z.iff2 = false
z.isHalted = false
z.intPending = false
z.nmiPending = false
z.intData = 0
z.codeCoverageEnabled = false
z.codeCoverage = make(map[uint16]bool)
return &z
}
// RunInstruction executes the next instruction in memory + handles interrupts
func (z *Z80) RunInstruction() (uint32, *map[uint16]byte) {
z.memAccess = map[uint16]byte{}
if z.codeCoverageEnabled {
z.codeCoverage[z.pc] = true
}
pre := z.cycleCount
if z.isHalted {
z.execOpcode(0x00)
} else {
opcode := z.nextB()
z.execOpcode(opcode)
}
z.processInterrupts()
return z.cycleCount - pre, &z.memAccess
}
func (z *Z80) SetState(state *z80.CPU) {
z.cycleCount = 0
z.a = state.A
z.b = state.B
z.c = state.C
z.d = state.D
z.e = state.E
z.h = state.H
z.l = state.L
z.a_ = state.AAlt
z.b_ = state.BAlt
z.c_ = state.CAlt
z.d_ = state.DAlt
z.e_ = state.EAlt
z.h_ = state.HAlt
z.l_ = state.LAlt
z.pc = state.PC
z.sp = state.SP
z.ix = state.IX
z.iy = state.IY
z.i = state.I
z.r = state.R
z.memPtr = state.MemPtr
z.sf = state.Flags.S
z.zf = state.Flags.Z
z.yf = state.Flags.Y
z.hf = state.Flags.H
z.xf = state.Flags.X
z.pf = state.Flags.P
z.nf = state.Flags.N
z.cf = state.Flags.C
z.f_ = state.FlagsAlt.GetFlags()
//z.iff_delay = 0
z.interruptMode = state.IMode
z.iff1 = state.Iff1
z.iff2 = state.Iff2
z.isHalted = state.Halted
z.intPending = state.InterruptOccurred
z.nmiPending = false
z.intData = 0
}
func (z *Z80) GetState() *z80.CPU {
return &z80.CPU{
A: z.a,
B: z.b,
C: z.c,
D: z.d,
E: z.e,
H: z.h,
L: z.l,
AAlt: z.a_,
BAlt: z.b_,
CAlt: z.c_,
DAlt: z.d_,
EAlt: z.e_,
HAlt: z.h_,
LAlt: z.l_,
IX: z.ix,
IY: z.iy,
I: z.i,
R: z.r,
SP: z.sp,
PC: z.pc,
Flags: z.getFlags(),
FlagsAlt: z.getAltFlags(),
IMode: z.interruptMode,
Iff1: z.iff1,
Iff2: z.iff2,
Halted: z.isHalted,
DoDelayedDI: z.intPending,
DoDelayedEI: z.intPending,
CycleCount: z.cycleCount,
InterruptOccurred: z.intPending,
MemPtr: z.memPtr,
}
}
func (z *Z80) getFlags() z80.FlagsType {
return z80.FlagsType{
S: z.sf,
Z: z.zf,
Y: z.yf,
H: z.hf,
X: z.xf,
P: z.pf,
N: z.nf,
C: z.cf,
}
}
func (z *Z80) getAltFlags() z80.FlagsType {
return z80.FlagsType{
S: z.f_&0x80 != 0,
Z: z.f_&0x40 != 0,
Y: z.f_&0x20 != 0,
H: z.f_&0x10 != 0,
X: z.f_&0x08 != 0,
P: z.f_&0x04 != 0,
N: z.f_&0x02 != 0,
C: z.f_&0x01 != 0,
}
}
func (z *Z80) PC() uint16 {
return z.pc
}
func (z *Z80) ClearCodeCoverage() {
clear(z.codeCoverage)
}
func (z *Z80) SetCodeCoverage(enabled bool) {
z.codeCoverageEnabled = enabled
if !enabled {
clear(z.codeCoverage)
}
}
func (z *Z80) CodeCoverage() map[uint16]bool {
return z.codeCoverage
}
func (z *Z80) SetExtendedStack(enabled bool) {
z.extendedStackEnabled = enabled
if enabled {
for addr := 0; addr < 65536; addr++ {
z.extendedStack[addr] = PushValueTypeDefault
}
}
}
func (z *Z80) ExtendedStack() ([]byte, error) {
var err error
if !z.extendedStackEnabled {
err = errors.New("error, z80: ExtendedStack disabled")
}
return z.extendedStack[:], err
}