mirror of
https://github.com/romychs/z80go.git
synced 2026-06-17 21:30:20 +03:00
Compare commits
No commits in common. "main" and "v1.0.6" have entirely different histories.
27
cpu.go
27
cpu.go
@ -14,7 +14,7 @@ func NewCPU(core MemIoRW) *CPU {
|
||||
z := CPU{}
|
||||
z.Reset()
|
||||
z.core = core
|
||||
z.TStates = 0
|
||||
z.cycleCount = 0
|
||||
z.codeCoverageEnabled = false
|
||||
// z.memAccess =
|
||||
z.codeCoverageEnabled = false
|
||||
@ -31,7 +31,7 @@ func (z *CPU) RunInstruction() (uint32, *map[uint16]byte) {
|
||||
if z.codeCoverageEnabled {
|
||||
z.codeCoverage[z.PC] = true
|
||||
}
|
||||
pre := z.TStates
|
||||
pre := z.cycleCount
|
||||
if z.Halted {
|
||||
z.execOpcode(0x00)
|
||||
} else {
|
||||
@ -39,7 +39,7 @@ func (z *CPU) RunInstruction() (uint32, *map[uint16]byte) {
|
||||
z.execOpcode(opcode)
|
||||
}
|
||||
z.processInterrupts()
|
||||
return z.TStates - pre, &z.memAccess
|
||||
return z.cycleCount - pre, &z.memAccess
|
||||
}
|
||||
|
||||
// SetState set current CPU state
|
||||
@ -71,18 +71,14 @@ func (z *CPU) SetState(state *CPU) {
|
||||
z.Flags = state.Flags
|
||||
z.FlagsAlt = state.FlagsAlt
|
||||
|
||||
z.TStates = state.TStates
|
||||
z.TStatesPart = state.TStatesPart
|
||||
z.MemPtr = state.MemPtr
|
||||
z.IMode = state.IMode
|
||||
z.Iff1 = state.Iff1
|
||||
z.Iff2 = state.Iff2
|
||||
z.Halted = state.Halted
|
||||
z.intData = state.intData
|
||||
z.intPending = state.intPending
|
||||
z.nmiPending = state.nmiPending
|
||||
z.IntOccurred = state.IntOccurred
|
||||
z.NmiOccurred = false
|
||||
}
|
||||
|
||||
func (z *CPU) GetState() *CPU {
|
||||
return &CPU{
|
||||
A: z.A,
|
||||
@ -113,16 +109,17 @@ func (z *CPU) GetState() *CPU {
|
||||
Iff1: z.Iff1,
|
||||
Iff2: z.Iff2,
|
||||
Halted: z.Halted,
|
||||
TStatesPart: z.TStatesPart,
|
||||
TStates: z.TStates,
|
||||
CycleCount: z.cycleCount,
|
||||
IntOccurred: z.IntOccurred,
|
||||
NmiOccurred: z.NmiOccurred,
|
||||
MemPtr: z.MemPtr,
|
||||
|
||||
intData: z.intData,
|
||||
intPending: z.intPending,
|
||||
nmiPending: z.nmiPending,
|
||||
}
|
||||
}
|
||||
|
||||
//func (z *CPU) PC() uint16 {
|
||||
// return z.PC
|
||||
//}
|
||||
|
||||
// ClearCodeCoverage - clears code coverage journal
|
||||
func (z *CPU) ClearCodeCoverage() {
|
||||
clear(z.codeCoverage)
|
||||
|
||||
@ -354,16 +354,15 @@ func (d *Disassembler) getRel() string {
|
||||
}
|
||||
|
||||
var shiftOps = []string{"RLC", "RRC", "RL", "RR", "SLA", "SRA", "SLL", "SRL"}
|
||||
var bitOps = []string{"BIT", "RES", "SET"}
|
||||
|
||||
// opocodeCB disassemble Z80 Opcodes, with CB first byte
|
||||
func (d *Disassembler) opocodeCB() string {
|
||||
op := ""
|
||||
opcode := d.getByte()
|
||||
if opcode <= 0x3F {
|
||||
op = shiftOps[opcode>>3&0x07] + sep + operands[opcode&0x7]
|
||||
op = shiftOps[opcode>>3&0x07] + operands[opcode&0x7]
|
||||
} else {
|
||||
op = bitOps[(opcode>>6&0x03)-1] + " " + string(rune(48+(opcode>>3)&0x07)) + sep + operands[opcode&0x7]
|
||||
op = shiftOps[(opcode>>6&0x03)-1] + operands[opcode&0x7]
|
||||
}
|
||||
return op
|
||||
}
|
||||
|
||||
@ -129,26 +129,3 @@ func Test_LD_r_IXn(t *testing.T) {
|
||||
t.Errorf("Error disassm LD_r_IXn, result '%s', expected '%s'", res, expected)
|
||||
}
|
||||
}
|
||||
|
||||
var testBITnH = []byte{0xcb, 0x64, 0xcb, 0xde, 0xcb, 0x95}
|
||||
|
||||
func Test_BIT_nn(t *testing.T) {
|
||||
expected := " 0000 BIT 4, H" // JR back
|
||||
setMemory(0x0000, testBITnH)
|
||||
res := disasm.Disassm(0x0000)
|
||||
if res != expected {
|
||||
t.Errorf("Error disassm BIT n,H, result '%s', expected '%s'", res, expected)
|
||||
}
|
||||
|
||||
expected = " 0002 SET 3, (HL)" // JR back
|
||||
res = disasm.Disassm(0x0002)
|
||||
if res != expected {
|
||||
t.Errorf("Error disassm SET n,(HL), result '%s', expected '%s'", res, expected)
|
||||
}
|
||||
|
||||
expected = " 0004 RES 2, L" // JR back
|
||||
res = disasm.Disassm(0x0004)
|
||||
if res != expected {
|
||||
t.Errorf("Error disassm RES n,(HL), result '%s', expected '%s'", res, expected)
|
||||
}
|
||||
}
|
||||
|
||||
31
helper.go
31
helper.go
@ -58,7 +58,6 @@ func (z *CPU) pushW(val uint16) {
|
||||
}
|
||||
|
||||
func (z *CPU) popW() uint16 {
|
||||
z.extendedStack[z.SP] = PushValueTypeDefault
|
||||
z.SP += 2
|
||||
return z.rw(z.SP - 2)
|
||||
}
|
||||
@ -75,17 +74,17 @@ func (z *CPU) nextW() uint16 {
|
||||
return w
|
||||
}
|
||||
|
||||
//func (z *CPU) BC() uint16 {
|
||||
// return (uint16(z.B) << 8) | uint16(z.C)
|
||||
//}
|
||||
//
|
||||
//func (z *CPU) DE() uint16 {
|
||||
// return (uint16(z.D) << 8) | uint16(z.E)
|
||||
//}
|
||||
//
|
||||
//func (z *CPU) HL() uint16 {
|
||||
// return (uint16(z.H) << 8) | uint16(z.L)
|
||||
//}
|
||||
func (z *CPU) bc() uint16 {
|
||||
return (uint16(z.B) << 8) | uint16(z.C)
|
||||
}
|
||||
|
||||
func (z *CPU) de() uint16 {
|
||||
return (uint16(z.D) << 8) | uint16(z.E)
|
||||
}
|
||||
|
||||
func (z *CPU) hl() uint16 {
|
||||
return (uint16(z.H) << 8) | uint16(z.L)
|
||||
}
|
||||
|
||||
func (z *CPU) setBC(val uint16) {
|
||||
z.B = byte(val >> 8)
|
||||
@ -179,15 +178,15 @@ func (z *CPU) updateXY(result byte) {
|
||||
|
||||
func (z *CPU) DebugOutput() {
|
||||
log.Debugf("PC: %04X, AF: %04X, BC: %04X, DE: %04X, HL: %04X, SP: %04X, IX: %04X, IY: %04X, I: %02X, R: %02X",
|
||||
z.PC, (uint16(z.A)<<8)|uint16(z.f()), z.GetBC(), z.GetDE(), z.GetHL(), z.SP,
|
||||
z.PC, (uint16(z.A)<<8)|uint16(z.f()), z.bc(), z.de(), z.hl(), z.SP,
|
||||
z.IX, z.IY, z.I, z.R)
|
||||
|
||||
log.Debugf("\t(%02X %02X %02X %02X), cycleCount: %d\n", z.rb(z.PC), z.rb(z.PC+1),
|
||||
z.rb(z.PC+2), z.rb(z.PC+3), z.TStates)
|
||||
z.rb(z.PC+2), z.rb(z.PC+3), z.cycleCount)
|
||||
}
|
||||
|
||||
func (z *CPU) Reset() {
|
||||
z.TStates = 0
|
||||
z.cycleCount = 0
|
||||
z.PC = 0
|
||||
z.SP = 0xFFFF
|
||||
z.IX = 0
|
||||
@ -221,5 +220,7 @@ func (z *CPU) Reset() {
|
||||
z.Iff1 = false
|
||||
z.Iff2 = false
|
||||
z.Halted = false
|
||||
z.IntOccurred = false
|
||||
z.NmiOccurred = false
|
||||
z.intData = 0
|
||||
}
|
||||
|
||||
260
opcodes.go
260
opcodes.go
@ -30,7 +30,7 @@ func (z *CPU) condCall(condition bool) {
|
||||
addr := z.nextW()
|
||||
if condition {
|
||||
z.call(addr)
|
||||
z.TStates += 7
|
||||
z.cycleCount += 7
|
||||
}
|
||||
z.MemPtr = addr
|
||||
}
|
||||
@ -45,7 +45,7 @@ func (z *CPU) ret() {
|
||||
func (z *CPU) condRet(condition bool) {
|
||||
if condition {
|
||||
z.ret()
|
||||
z.TStates += 6
|
||||
z.cycleCount += 6
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,20 +62,20 @@ func (z *CPU) condJr(condition bool) {
|
||||
b := z.nextB()
|
||||
if condition {
|
||||
z.jr(b)
|
||||
z.TStates += 5
|
||||
z.cycleCount += 5
|
||||
}
|
||||
}
|
||||
|
||||
func BToByte(cond bool) byte {
|
||||
func bToByte(cond bool) byte {
|
||||
if cond {
|
||||
return 1
|
||||
return byte(1)
|
||||
}
|
||||
return 0
|
||||
return byte(0)
|
||||
}
|
||||
|
||||
// ADD Byte: adds two bytes together
|
||||
func (z *CPU) addB(a byte, b byte, cy bool) byte {
|
||||
result := a + b + BToByte(cy)
|
||||
result := a + b + bToByte(cy)
|
||||
z.Flags.S = result&0x80 != 0
|
||||
z.Flags.Z = result == 0
|
||||
z.Flags.H = carry(4, uint16(a), uint16(b), cy)
|
||||
@ -99,17 +99,16 @@ func (z *CPU) subB(a byte, b byte, cy bool) byte {
|
||||
func (z *CPU) addW(a uint16, b uint16, cy bool) uint16 {
|
||||
lsb := z.addB(byte(a), byte(b), cy)
|
||||
msb := z.addB(byte(a>>8), byte(b>>8), z.Flags.C)
|
||||
return z.addSubRes(a, msb, lsb)
|
||||
result := (uint16(msb) << 8) | uint16(lsb)
|
||||
z.Flags.Z = result == 0
|
||||
z.MemPtr = a + 1
|
||||
return result
|
||||
}
|
||||
|
||||
// subW Subtracts two words (with optional carry)
|
||||
func (z *CPU) subW(a uint16, b uint16, cy bool) uint16 {
|
||||
lsb := z.subB(byte(a), byte(b), cy)
|
||||
msb := z.subB(byte(a>>8), byte(b>>8), z.Flags.C)
|
||||
return z.addSubRes(a, msb, lsb)
|
||||
}
|
||||
|
||||
func (z *CPU) addSubRes(a uint16, msb uint8, lsb uint8) uint16 {
|
||||
result := (uint16(msb) << 8) | uint16(lsb)
|
||||
z.Flags.Z = result == 0
|
||||
z.MemPtr = a + 1
|
||||
@ -121,7 +120,7 @@ func (z *CPU) addHL(val uint16) {
|
||||
sf := z.Flags.S
|
||||
zf := z.Flags.Z
|
||||
pf := z.Flags.P
|
||||
result := z.addW(z.GetHL(), val, false)
|
||||
result := z.addW(z.hl(), val, false)
|
||||
z.setHL(result)
|
||||
z.Flags.S = sf
|
||||
z.Flags.Z = zf
|
||||
@ -142,7 +141,7 @@ func (z *CPU) addIZ(reg *uint16, val uint16) {
|
||||
|
||||
// adcHL adds A word (+ carry) to HL
|
||||
func (z *CPU) adcHL(val uint16) {
|
||||
result := z.addW(z.GetHL(), val, z.Flags.C)
|
||||
result := z.addW(z.hl(), val, z.Flags.C)
|
||||
z.Flags.S = result&0x8000 != 0
|
||||
z.Flags.Z = result == 0
|
||||
z.setHL(result)
|
||||
@ -150,7 +149,7 @@ func (z *CPU) adcHL(val uint16) {
|
||||
|
||||
// sbcHL subtracts A word (+ carry) to HL
|
||||
func (z *CPU) sbcHL(val uint16) {
|
||||
result := z.subW(z.GetHL(), val, z.Flags.C)
|
||||
result := z.subW(z.hl(), val, z.Flags.C)
|
||||
z.Flags.S = result&0x8000 != 0
|
||||
z.Flags.Z = result == 0
|
||||
z.setHL(result)
|
||||
@ -175,25 +174,39 @@ func (z *CPU) dec(a byte) byte {
|
||||
// executes A logic "and" between register A and A byte, then stores the
|
||||
// result in register A
|
||||
func (z *CPU) lAnd(val byte) {
|
||||
z.lCmn(z.A&val, true)
|
||||
result := z.A & val
|
||||
z.Flags.S = result&0x80 != 0
|
||||
z.Flags.Z = result == 0
|
||||
z.Flags.H = true
|
||||
z.Flags.P = parity(result)
|
||||
z.Flags.N = false
|
||||
z.Flags.C = false
|
||||
z.updateXY(result)
|
||||
z.A = result
|
||||
}
|
||||
|
||||
// executes A logic "xor" between register A and A byte, then stores the
|
||||
// result in register A
|
||||
func (z *CPU) lXor(val byte) {
|
||||
z.lCmn(z.A^val, false)
|
||||
result := z.A ^ val
|
||||
z.Flags.S = result&0x80 != 0
|
||||
z.Flags.Z = result == 0
|
||||
z.Flags.H = false
|
||||
z.Flags.P = parity(result)
|
||||
z.Flags.N = false
|
||||
z.Flags.C = false
|
||||
z.updateXY(result)
|
||||
z.A = result
|
||||
}
|
||||
|
||||
// executes A logic "or" between register A and A byte, then stores the
|
||||
// result in register A
|
||||
func (z *CPU) lOr(val byte) {
|
||||
z.lCmn(z.A|val, false)
|
||||
}
|
||||
result := z.A | val
|
||||
|
||||
func (z *CPU) lCmn(result byte, hf bool) {
|
||||
z.Flags.S = result&0x80 != 0
|
||||
z.Flags.Z = result == 0
|
||||
z.Flags.H = hf
|
||||
z.Flags.H = false
|
||||
z.Flags.P = parity(result)
|
||||
z.Flags.N = false
|
||||
z.Flags.C = false
|
||||
@ -204,6 +217,11 @@ func (z *CPU) lCmn(result byte, hf bool) {
|
||||
// compares A value with register A
|
||||
func (z *CPU) cp(val byte) {
|
||||
z.subB(z.A, val, false)
|
||||
|
||||
// the only difference between cp and sub is that
|
||||
// the xf/yf are taken from the value to be subtracted,
|
||||
// not the result
|
||||
|
||||
z.updateXY(val)
|
||||
}
|
||||
|
||||
@ -240,7 +258,7 @@ func (z *CPU) cbRrc(val byte) byte {
|
||||
func (z *CPU) cbRl(val byte) byte {
|
||||
cf := z.Flags.C
|
||||
z.Flags.C = val>>7 != 0
|
||||
val = (val << 1) | BToByte(cf)
|
||||
val = (val << 1) | bToByte(cf)
|
||||
z.Flags.S = val&0x80 != 0
|
||||
z.Flags.Z = val == 0
|
||||
z.Flags.N = false
|
||||
@ -254,7 +272,7 @@ func (z *CPU) cbRl(val byte) byte {
|
||||
func (z *CPU) cbRr(val byte) byte {
|
||||
c := z.Flags.C
|
||||
z.Flags.C = (val & 1) != 0
|
||||
val = (val >> 1) | (BToByte(c) << 7)
|
||||
val = (val >> 1) | (bToByte(c) << 7)
|
||||
z.Flags.S = val&0x80 != 0
|
||||
z.Flags.Z = val == 0
|
||||
z.Flags.N = false
|
||||
@ -330,14 +348,14 @@ func (z *CPU) cbBit(val byte, n byte) byte {
|
||||
}
|
||||
|
||||
func (z *CPU) ldi() {
|
||||
de := z.GetDE()
|
||||
hl := z.GetHL()
|
||||
de := z.de()
|
||||
hl := z.hl()
|
||||
val := z.rb(hl)
|
||||
z.wb(de, val)
|
||||
|
||||
z.setHL(z.GetHL() + 1)
|
||||
z.setDE(z.GetDE() + 1)
|
||||
z.setBC(z.GetBC() - 1)
|
||||
z.setHL(z.hl() + 1)
|
||||
z.setDE(z.de() + 1)
|
||||
z.setBC(z.bc() - 1)
|
||||
|
||||
// see https://wikiti.brandonw.net/index.php?title=Z80_Instruction_Set
|
||||
// for the calculation of xf/yf on LDI
|
||||
@ -348,27 +366,27 @@ func (z *CPU) ldi() {
|
||||
|
||||
z.Flags.N = false
|
||||
z.Flags.H = false
|
||||
z.Flags.P = z.GetBC() > 0
|
||||
z.Flags.P = z.bc() > 0
|
||||
|
||||
}
|
||||
|
||||
func (z *CPU) ldd() {
|
||||
z.ldi()
|
||||
// same as ldi but HL and DE are decremented instead of incremented
|
||||
z.setHL(z.GetHL() - 2)
|
||||
z.setDE(z.GetDE() - 2)
|
||||
z.setHL(z.hl() - 2)
|
||||
z.setDE(z.de() - 2)
|
||||
}
|
||||
|
||||
func (z *CPU) cpi() {
|
||||
cf := z.Flags.C
|
||||
result := z.subB(z.A, z.rb(z.GetHL()), false)
|
||||
z.setHL(z.GetHL() + 1)
|
||||
z.setBC(z.GetBC() - 1)
|
||||
result := z.subB(z.A, z.rb(z.hl()), false)
|
||||
z.setHL(z.hl() + 1)
|
||||
z.setBC(z.bc() - 1)
|
||||
|
||||
val := result - BToByte(z.Flags.H)
|
||||
val := result - bToByte(z.Flags.H)
|
||||
z.Flags.X = val&0x08 != 0
|
||||
z.Flags.Y = val&0x02 != 0
|
||||
z.Flags.P = z.GetBC() != 0
|
||||
z.Flags.P = z.bc() != 0
|
||||
z.Flags.C = cf
|
||||
z.MemPtr += 1
|
||||
}
|
||||
@ -376,12 +394,12 @@ func (z *CPU) cpi() {
|
||||
func (z *CPU) cpd() {
|
||||
z.cpi()
|
||||
// same as cpi but HL is decremented instead of incremented
|
||||
z.setHL(z.GetHL() - 2)
|
||||
z.setHL(z.hl() - 2)
|
||||
z.MemPtr -= 2
|
||||
}
|
||||
|
||||
func (z *CPU) inRC(r *byte) {
|
||||
*r = z.core.IORead(z.GetBC())
|
||||
*r = z.core.IORead(z.bc())
|
||||
z.Flags.Z = *r == 0
|
||||
z.Flags.S = *r&0x80 != 0
|
||||
z.Flags.P = parity(*r)
|
||||
@ -390,9 +408,9 @@ func (z *CPU) inRC(r *byte) {
|
||||
}
|
||||
|
||||
func (z *CPU) ini() {
|
||||
val := z.core.IORead(z.GetBC())
|
||||
z.wb(z.GetHL(), val)
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
val := z.core.IORead(z.bc())
|
||||
z.wb(z.hl(), val)
|
||||
z.MemPtr = z.bc() + 1
|
||||
z.B--
|
||||
|
||||
other := val + z.C + 1
|
||||
@ -408,13 +426,13 @@ func (z *CPU) ini() {
|
||||
z.Flags.S = z.B&0x80 != 0
|
||||
z.Flags.Z = z.B == 0
|
||||
z.updateXY(z.B)
|
||||
z.setHL(z.GetHL() + 1)
|
||||
z.setHL(z.hl() + 1)
|
||||
}
|
||||
|
||||
func (z *CPU) ind() {
|
||||
val := z.core.IORead(z.GetBC())
|
||||
z.wb(z.GetHL(), val)
|
||||
z.MemPtr = z.GetBC() - 1
|
||||
val := z.core.IORead(z.bc())
|
||||
z.wb(z.hl(), val)
|
||||
z.MemPtr = z.bc() - 1
|
||||
z.B--
|
||||
|
||||
other := val + z.C - 1
|
||||
@ -431,7 +449,7 @@ func (z *CPU) ind() {
|
||||
z.Flags.S = z.B&0x80 != 0
|
||||
z.Flags.Z = z.B == 0
|
||||
z.updateXY(z.B)
|
||||
z.setHL(z.GetHL() - 1)
|
||||
z.setHL(z.hl() - 1)
|
||||
}
|
||||
func (z *CPU) outCmnFlags(val uint8) {
|
||||
other := val + z.L
|
||||
@ -450,20 +468,20 @@ func (z *CPU) outCmnFlags(val uint8) {
|
||||
}
|
||||
|
||||
func (z *CPU) outi() {
|
||||
val := z.rb(z.GetHL())
|
||||
val := z.rb(z.hl())
|
||||
z.B--
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.core.IOWrite(z.GetBC(), val)
|
||||
z.setHL(z.GetHL() + 1)
|
||||
z.MemPtr = z.bc() + 1
|
||||
z.core.IOWrite(z.bc(), val)
|
||||
z.setHL(z.hl() + 1)
|
||||
z.outCmnFlags(val)
|
||||
}
|
||||
|
||||
func (z *CPU) outd() {
|
||||
val := z.rb(z.GetHL())
|
||||
val := z.rb(z.hl())
|
||||
z.B--
|
||||
z.MemPtr = z.GetBC() - 1
|
||||
z.core.IOWrite(z.GetBC(), val)
|
||||
z.setHL(z.GetHL() - 1)
|
||||
z.MemPtr = z.bc() - 1
|
||||
z.core.IOWrite(z.bc(), val)
|
||||
z.setHL(z.hl() - 1)
|
||||
z.outCmnFlags(val)
|
||||
}
|
||||
|
||||
@ -520,37 +538,31 @@ func (z *CPU) processInterrupts() {
|
||||
|
||||
if z.nmiPending {
|
||||
z.nmiPending = false
|
||||
if z.Halted {
|
||||
z.PC++
|
||||
z.Halted = false
|
||||
}
|
||||
z.Halted = false
|
||||
z.Iff1 = false
|
||||
z.incR()
|
||||
|
||||
z.TStates += 11
|
||||
z.cycleCount += 11
|
||||
z.call(0x0066)
|
||||
return
|
||||
}
|
||||
|
||||
if z.intPending && z.Iff1 {
|
||||
z.intPending = false
|
||||
if z.Halted {
|
||||
z.PC++
|
||||
z.Halted = false
|
||||
}
|
||||
z.Halted = false
|
||||
z.Iff1 = false
|
||||
z.Iff2 = false
|
||||
z.incR()
|
||||
|
||||
switch z.IMode {
|
||||
case 0:
|
||||
z.TStates += 11
|
||||
z.cycleCount += 11
|
||||
z.execOpcode(z.intData)
|
||||
case 1:
|
||||
z.TStates += 13
|
||||
z.cycleCount += 13
|
||||
z.call(0x38)
|
||||
case 2:
|
||||
z.TStates += 19
|
||||
z.cycleCount += 19
|
||||
z.call(z.rw((uint16(z.I) << 8) | uint16(z.intData)))
|
||||
default:
|
||||
log.Errorf("Unsupported interrupt mode %d\n", z.IMode)
|
||||
@ -572,7 +584,7 @@ func (z *CPU) GenINT(data byte) {
|
||||
|
||||
// executes A non-prefixed opcode
|
||||
func (z *CPU) execOpcode(opcode byte) {
|
||||
z.TStates += uint32(cycles00[opcode])
|
||||
z.cycleCount += uint32(cycles00[opcode])
|
||||
z.incR()
|
||||
|
||||
switch opcode {
|
||||
@ -682,34 +694,34 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
//z.l = z.l // ld l,l
|
||||
|
||||
case 0x7E:
|
||||
z.A = z.rb(z.GetHL()) // ld a,(hl)
|
||||
z.A = z.rb(z.hl()) // ld a,(hl)
|
||||
case 0x46:
|
||||
z.B = z.rb(z.GetHL()) // ld b,(hl)
|
||||
z.B = z.rb(z.hl()) // ld b,(hl)
|
||||
case 0x4E:
|
||||
z.C = z.rb(z.GetHL()) // ld c,(hl)
|
||||
z.C = z.rb(z.hl()) // ld c,(hl)
|
||||
case 0x56:
|
||||
z.D = z.rb(z.GetHL()) // ld d,(hl)
|
||||
z.D = z.rb(z.hl()) // ld d,(hl)
|
||||
case 0x5E:
|
||||
z.E = z.rb(z.GetHL()) // ld e,(hl)
|
||||
z.E = z.rb(z.hl()) // ld e,(hl)
|
||||
case 0x66:
|
||||
z.H = z.rb(z.GetHL()) // ld h,(hl)
|
||||
z.H = z.rb(z.hl()) // ld h,(hl)
|
||||
case 0x6E:
|
||||
z.L = z.rb(z.GetHL()) // ld l,(hl)
|
||||
z.L = z.rb(z.hl()) // ld l,(hl)
|
||||
|
||||
case 0x77:
|
||||
z.wb(z.GetHL(), z.A) // ld (hl),a
|
||||
z.wb(z.hl(), z.A) // ld (hl),a
|
||||
case 0x70:
|
||||
z.wb(z.GetHL(), z.B) // ld (hl),b
|
||||
z.wb(z.hl(), z.B) // ld (hl),b
|
||||
case 0x71:
|
||||
z.wb(z.GetHL(), z.C) // ld (hl),c
|
||||
z.wb(z.hl(), z.C) // ld (hl),c
|
||||
case 0x72:
|
||||
z.wb(z.GetHL(), z.D) // ld (hl),d
|
||||
z.wb(z.hl(), z.D) // ld (hl),d
|
||||
case 0x73:
|
||||
z.wb(z.GetHL(), z.E) // ld (hl),e
|
||||
z.wb(z.hl(), z.E) // ld (hl),e
|
||||
case 0x74:
|
||||
z.wb(z.GetHL(), z.H) // ld (hl),h
|
||||
z.wb(z.hl(), z.H) // ld (hl),h
|
||||
case 0x75:
|
||||
z.wb(z.GetHL(), z.L) // ld (hl),l
|
||||
z.wb(z.hl(), z.L) // ld (hl),l
|
||||
|
||||
case 0x3E:
|
||||
z.A = z.nextB() // ld a,*
|
||||
@ -726,15 +738,15 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0x2E:
|
||||
z.L = z.nextB() // ld l,*
|
||||
case 0x36:
|
||||
z.wb(z.GetHL(), z.nextB()) // ld (hl),*
|
||||
z.wb(z.hl(), z.nextB()) // ld (hl),*
|
||||
case 0x0A:
|
||||
// ld a,(bc)
|
||||
z.A = z.rb(z.GetBC())
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.A = z.rb(z.bc())
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x1A:
|
||||
// ld a,(de)
|
||||
z.A = z.rb(z.GetDE())
|
||||
z.MemPtr = z.GetDE() + 1
|
||||
z.A = z.rb(z.de())
|
||||
z.MemPtr = z.de() + 1
|
||||
case 0x3A:
|
||||
// ld a,(**)
|
||||
addr := z.nextW()
|
||||
@ -742,12 +754,12 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
z.MemPtr = addr + 1
|
||||
case 0x02:
|
||||
// ld (bc),a
|
||||
z.wb(z.GetBC(), z.A)
|
||||
z.MemPtr = (uint16(z.A) << 8) | ((z.GetBC() + 1) & 0xFF)
|
||||
z.wb(z.bc(), z.A)
|
||||
z.MemPtr = (uint16(z.A) << 8) | ((z.bc() + 1) & 0xFF)
|
||||
case 0x12:
|
||||
// ld (de),a
|
||||
z.wb(z.GetDE(), z.A)
|
||||
z.MemPtr = (uint16(z.A) << 8) | ((z.GetDE() + 1) & 0xFF)
|
||||
z.wb(z.de(), z.A)
|
||||
z.MemPtr = (uint16(z.A) << 8) | ((z.de() + 1) & 0xFF)
|
||||
case 0x32:
|
||||
// ld (**),a
|
||||
addr := z.nextW()
|
||||
@ -770,20 +782,20 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0x22:
|
||||
// ld (**),hl
|
||||
addr := z.nextW()
|
||||
z.ww(addr, z.GetHL())
|
||||
z.ww(addr, z.hl())
|
||||
z.MemPtr = addr + 1
|
||||
case 0xF9:
|
||||
z.SP = z.GetHL() // ld sp,hl
|
||||
z.SP = z.hl() // ld sp,hl
|
||||
|
||||
case 0xEB:
|
||||
// ex de,hl
|
||||
de := z.GetDE()
|
||||
z.setDE(z.GetHL())
|
||||
de := z.de()
|
||||
z.setDE(z.hl())
|
||||
z.setHL(de)
|
||||
case 0xE3:
|
||||
// ex (sp),hl
|
||||
val := z.rw(z.SP)
|
||||
z.ww(z.SP, z.GetHL())
|
||||
z.ww(z.SP, z.hl())
|
||||
z.setHL(val)
|
||||
z.MemPtr = val
|
||||
case 0x87:
|
||||
@ -801,7 +813,7 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0x85:
|
||||
z.A = z.addB(z.A, z.L, false) // add a,l
|
||||
case 0x86:
|
||||
z.A = z.addB(z.A, z.rb(z.GetHL()), false) // add a,(hl)
|
||||
z.A = z.addB(z.A, z.rb(z.hl()), false) // add a,(hl)
|
||||
case 0xC6:
|
||||
z.A = z.addB(z.A, z.nextB(), false) // add a,*
|
||||
|
||||
@ -820,7 +832,7 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0x8D:
|
||||
z.A = z.addB(z.A, z.L, z.Flags.C) // adc a,l
|
||||
case 0x8E:
|
||||
z.A = z.addB(z.A, z.rb(z.GetHL()), z.Flags.C) // adc a,(hl)
|
||||
z.A = z.addB(z.A, z.rb(z.hl()), z.Flags.C) // adc a,(hl)
|
||||
case 0xCE:
|
||||
z.A = z.addB(z.A, z.nextB(), z.Flags.C) // adc a,*
|
||||
|
||||
@ -839,7 +851,7 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0x95:
|
||||
z.A = z.subB(z.A, z.L, false) // sub a,l
|
||||
case 0x96:
|
||||
z.A = z.subB(z.A, z.rb(z.GetHL()), false) // sub a,(hl)
|
||||
z.A = z.subB(z.A, z.rb(z.hl()), false) // sub a,(hl)
|
||||
case 0xD6:
|
||||
z.A = z.subB(z.A, z.nextB(), false) // sub a,*
|
||||
|
||||
@ -858,16 +870,16 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0x9D:
|
||||
z.A = z.subB(z.A, z.L, z.Flags.C) // sbc a,l
|
||||
case 0x9E:
|
||||
z.A = z.subB(z.A, z.rb(z.GetHL()), z.Flags.C) // sbc a,(hl)
|
||||
z.A = z.subB(z.A, z.rb(z.hl()), z.Flags.C) // sbc a,(hl)
|
||||
case 0xDE:
|
||||
z.A = z.subB(z.A, z.nextB(), z.Flags.C) // sbc a,*
|
||||
|
||||
case 0x09:
|
||||
z.addHL(z.GetBC()) // add hl,bc
|
||||
z.addHL(z.bc()) // add hl,bc
|
||||
case 0x19:
|
||||
z.addHL(z.GetDE()) // add hl,de
|
||||
z.addHL(z.de()) // add hl,de
|
||||
case 0x29:
|
||||
z.addHL(z.GetHL()) // add hl,hl
|
||||
z.addHL(z.hl()) // add hl,hl
|
||||
case 0x39:
|
||||
z.addHL(z.SP) // add hl,sp
|
||||
|
||||
@ -896,8 +908,8 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
z.L = z.inc(z.L)
|
||||
case 0x34:
|
||||
// inc (hl)
|
||||
result := z.inc(z.rb(z.GetHL()))
|
||||
z.wb(z.GetHL(), result)
|
||||
result := z.inc(z.rb(z.hl()))
|
||||
z.wb(z.hl(), result)
|
||||
case 0x3D:
|
||||
z.A = z.dec(z.A) // dec a
|
||||
case 0x05:
|
||||
@ -914,22 +926,22 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
z.L = z.dec(z.L) // dec l
|
||||
case 0x35:
|
||||
// dec (hl)
|
||||
result := z.dec(z.rb(z.GetHL()))
|
||||
z.wb(z.GetHL(), result)
|
||||
result := z.dec(z.rb(z.hl()))
|
||||
z.wb(z.hl(), result)
|
||||
case 0x03:
|
||||
z.setBC(z.GetBC() + 1) // inc bc
|
||||
z.setBC(z.bc() + 1) // inc bc
|
||||
case 0x13:
|
||||
z.setDE(z.GetDE() + 1) // inc de
|
||||
z.setDE(z.de() + 1) // inc de
|
||||
case 0x23:
|
||||
z.setHL(z.GetHL() + 1) // inc hl
|
||||
z.setHL(z.hl() + 1) // inc hl
|
||||
case 0x33:
|
||||
z.SP = z.SP + 1 // inc sp
|
||||
case 0x0B:
|
||||
z.setBC(z.GetBC() - 1) // dec bc
|
||||
z.setBC(z.bc() - 1) // dec bc
|
||||
case 0x1B:
|
||||
z.setDE(z.GetDE() - 1) // dec de
|
||||
z.setDE(z.de() - 1) // dec de
|
||||
case 0x2B:
|
||||
z.setHL(z.GetHL() - 1) // dec hl
|
||||
z.setHL(z.hl() - 1) // dec hl
|
||||
case 0x3B:
|
||||
z.SP = z.SP - 1 // dec sp
|
||||
case 0x27:
|
||||
@ -955,20 +967,20 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0x07:
|
||||
// Rotate left
|
||||
z.Flags.C = z.A&0x80 != 0
|
||||
z.A = (z.A << 1) | BToByte(z.Flags.C)
|
||||
z.A = (z.A << 1) | bToByte(z.Flags.C)
|
||||
z.Flags.N = false
|
||||
z.Flags.H = false
|
||||
z.updateXY(z.A)
|
||||
case 0x0F:
|
||||
// Rotate right
|
||||
z.Flags.C = z.A&1 != 0
|
||||
z.A = (z.A >> 1) | (BToByte(z.Flags.C) << 7)
|
||||
z.A = (z.A >> 1) | (bToByte(z.Flags.C) << 7)
|
||||
z.Flags.N = false
|
||||
z.Flags.H = false
|
||||
z.updateXY(z.A)
|
||||
case 0x17:
|
||||
// rla
|
||||
cy := BToByte(z.Flags.C)
|
||||
cy := bToByte(z.Flags.C)
|
||||
z.Flags.C = z.A&0x80 != 0
|
||||
z.A = (z.A << 1) | cy
|
||||
z.Flags.N = false
|
||||
@ -976,7 +988,7 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
z.updateXY(z.A)
|
||||
case 0x1F:
|
||||
// rra
|
||||
cy := BToByte(z.Flags.C)
|
||||
cy := bToByte(z.Flags.C)
|
||||
z.Flags.C = z.A&1 != 0
|
||||
z.A = (z.A >> 1) | (cy << 7)
|
||||
z.Flags.N = false
|
||||
@ -997,7 +1009,7 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0xA5:
|
||||
z.lAnd(z.L) // and l
|
||||
case 0xA6:
|
||||
z.lAnd(z.rb(z.GetHL())) // and (hl)
|
||||
z.lAnd(z.rb(z.hl())) // and (hl)
|
||||
case 0xE6:
|
||||
z.lAnd(z.nextB()) // and *
|
||||
|
||||
@ -1016,7 +1028,7 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0xAD:
|
||||
z.lXor(z.L) // xor l
|
||||
case 0xAE:
|
||||
z.lXor(z.rb(z.GetHL())) // xor (hl)
|
||||
z.lXor(z.rb(z.hl())) // xor (hl)
|
||||
case 0xEE:
|
||||
z.lXor(z.nextB()) // xor *
|
||||
|
||||
@ -1035,7 +1047,7 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0xB5:
|
||||
z.lOr(z.L) // or l
|
||||
case 0xB6:
|
||||
z.lOr(z.rb(z.GetHL())) // or (hl)
|
||||
z.lOr(z.rb(z.hl())) // or (hl)
|
||||
case 0xF6:
|
||||
z.lOr(z.nextB()) // or *
|
||||
|
||||
@ -1054,7 +1066,7 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
case 0xBD:
|
||||
z.cp(z.L)
|
||||
case 0xBE:
|
||||
z.cp(z.rb(z.GetHL())) // cp (hl)
|
||||
z.cp(z.rb(z.hl())) // cp (hl)
|
||||
case 0xFE:
|
||||
z.cp(z.nextB()) // cp *
|
||||
|
||||
@ -1099,7 +1111,7 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
z.condJr(z.Flags.C) // jr c, *
|
||||
|
||||
case 0xE9:
|
||||
z.PC = z.GetHL() // jp (hl)
|
||||
z.PC = z.hl() // jp (hl)
|
||||
case 0xCD:
|
||||
z.call(z.nextW()) // call
|
||||
|
||||
@ -1164,11 +1176,11 @@ func (z *CPU) execOpcode(opcode byte) {
|
||||
z.call(0x38) // rst 7
|
||||
z.extendedStack[z.SP] = PushValueTypeRst
|
||||
case 0xC5:
|
||||
z.pushW(z.GetBC()) // push bc
|
||||
z.pushW(z.bc()) // push bc
|
||||
case 0xD5:
|
||||
z.pushW(z.GetDE()) // push de
|
||||
z.pushW(z.de()) // push de
|
||||
case 0xE5:
|
||||
z.pushW(z.GetHL()) // push hl
|
||||
z.pushW(z.hl()) // push hl
|
||||
case 0xF5:
|
||||
z.pushW((uint16(z.A) << 8) | uint16(z.f())) // push af
|
||||
|
||||
|
||||
16
opcodesCB.go
16
opcodesCB.go
@ -4,7 +4,7 @@ import log "github.com/sirupsen/logrus"
|
||||
|
||||
// executes A CB opcode
|
||||
func (z *CPU) execOpcodeCB(opcode byte) {
|
||||
z.TStates += 8
|
||||
z.cycleCount += 8
|
||||
z.incR()
|
||||
|
||||
// decoding instructions from http://z80.info/decoding.htm#cb
|
||||
@ -29,7 +29,7 @@ func (z *CPU) execOpcodeCB(opcode byte) {
|
||||
case 5:
|
||||
reg = &z.L
|
||||
case 6:
|
||||
hl = z.rb(z.GetHL())
|
||||
hl = z.rb(z.hl())
|
||||
reg = &hl
|
||||
case 7:
|
||||
reg = &z.A
|
||||
@ -64,7 +64,7 @@ func (z *CPU) execOpcodeCB(opcode byte) {
|
||||
// in bit (hl), x/y flags are handled differently:
|
||||
if z_ == 6 {
|
||||
z.updateXY(byte(z.MemPtr >> 8))
|
||||
z.TStates += 4
|
||||
z.cycleCount += 4
|
||||
}
|
||||
|
||||
case 2:
|
||||
@ -74,11 +74,11 @@ func (z *CPU) execOpcodeCB(opcode byte) {
|
||||
}
|
||||
|
||||
if (x_ == 0 || x_ == 2 || x_ == 3) && z_ == 6 {
|
||||
z.TStates += 7
|
||||
z.cycleCount += 7
|
||||
}
|
||||
|
||||
if reg == &hl {
|
||||
z.wb(z.GetHL(), hl)
|
||||
z.wb(z.hl(), hl)
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +146,7 @@ func (z *CPU) execOpcodeDcb(opcode byte, addr uint16) {
|
||||
z.L = result
|
||||
// always false
|
||||
//case 6:
|
||||
// z.wb(z.GetHL(), result)
|
||||
// z.wb(z.hl(), result)
|
||||
case 7:
|
||||
z.A = result
|
||||
}
|
||||
@ -154,9 +154,9 @@ func (z *CPU) execOpcodeDcb(opcode byte, addr uint16) {
|
||||
|
||||
if x_ == 1 {
|
||||
// bit instructions take 20 cycles, others take 23
|
||||
z.TStates += 20
|
||||
z.cycleCount += 20
|
||||
} else {
|
||||
z.wb(addr, result)
|
||||
z.TStates += 23
|
||||
z.cycleCount += 23
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ package z80go
|
||||
|
||||
// executes A DD/FD opcode (IZ = IX or IY)
|
||||
func (z *CPU) execOpcodeDDFD(opcode byte, iz *uint16) {
|
||||
z.TStates += uint32(cyclesDDFD[opcode])
|
||||
z.cycleCount += uint32(cyclesDDFD[opcode])
|
||||
z.incR()
|
||||
|
||||
switch opcode {
|
||||
@ -15,9 +15,9 @@ func (z *CPU) execOpcodeDDFD(opcode byte, iz *uint16) {
|
||||
z.PC = *iz
|
||||
//z.jump(*iz)
|
||||
case 0x09:
|
||||
z.addIZ(iz, z.GetBC()) // add iz,bc
|
||||
z.addIZ(iz, z.bc()) // add iz,bc
|
||||
case 0x19:
|
||||
z.addIZ(iz, z.GetDE()) // add iz,de
|
||||
z.addIZ(iz, z.de()) // add iz,de
|
||||
case 0x29:
|
||||
z.addIZ(iz, *iz) // add iz,iz
|
||||
case 0x39:
|
||||
|
||||
104
opcodesED.go
104
opcodesED.go
@ -4,7 +4,7 @@ import log "github.com/sirupsen/logrus"
|
||||
|
||||
// executes A ED opcode
|
||||
func (z *CPU) execOpcodeED(opcode byte) {
|
||||
z.TStates += uint32(cyclesED[opcode])
|
||||
z.cycleCount += uint32(cyclesED[opcode])
|
||||
z.incR()
|
||||
switch opcode {
|
||||
case 0x47:
|
||||
@ -41,9 +41,9 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
{
|
||||
z.ldi()
|
||||
|
||||
if z.GetBC() != 0 {
|
||||
if z.bc() != 0 {
|
||||
z.PC -= 2
|
||||
z.TStates += 5
|
||||
z.cycleCount += 5
|
||||
z.MemPtr = z.PC + 1
|
||||
}
|
||||
} // ldir
|
||||
@ -54,9 +54,9 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
{
|
||||
z.ldd()
|
||||
|
||||
if z.GetBC() != 0 {
|
||||
if z.bc() != 0 {
|
||||
z.PC -= 2
|
||||
z.TStates += 5
|
||||
z.cycleCount += 5
|
||||
z.MemPtr = z.PC + 1
|
||||
}
|
||||
} // lddr
|
||||
@ -68,9 +68,9 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
case 0xB1:
|
||||
// cpir
|
||||
z.cpi()
|
||||
if z.GetBC() != 0 && !z.Flags.Z {
|
||||
if z.bc() != 0 && !z.Flags.Z {
|
||||
z.PC -= 2
|
||||
z.TStates += 5
|
||||
z.cycleCount += 5
|
||||
z.MemPtr = z.PC + 1
|
||||
} else {
|
||||
//z.mem_ptr++
|
||||
@ -79,18 +79,18 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
case 0xB9:
|
||||
// cpdr
|
||||
z.cpd()
|
||||
if z.GetBC() != 0 && !z.Flags.Z {
|
||||
if z.bc() != 0 && !z.Flags.Z {
|
||||
z.PC -= 2
|
||||
z.TStates += 5
|
||||
z.cycleCount += 5
|
||||
z.MemPtr = z.PC + 1
|
||||
} else {
|
||||
//z.mem_ptr++
|
||||
}
|
||||
case 0x40:
|
||||
z.inRC(&z.B) // in b, (c)
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x48:
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.MemPtr = z.bc() + 1
|
||||
z.inRC(&z.C) // in c, (c)
|
||||
z.updateXY(z.C)
|
||||
//case 0x4e:
|
||||
@ -98,28 +98,28 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
|
||||
case 0x50:
|
||||
z.inRC(&z.D) // in d, (c)
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x58:
|
||||
// in e, (c)
|
||||
z.inRC(&z.E)
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.MemPtr = z.bc() + 1
|
||||
z.updateXY(z.E)
|
||||
case 0x60:
|
||||
z.inRC(&z.H) // in h, (c)
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x68:
|
||||
z.inRC(&z.L) // in l, (c)
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.MemPtr = z.bc() + 1
|
||||
z.updateXY(z.L)
|
||||
case 0x70:
|
||||
// in (c)
|
||||
var val byte
|
||||
z.inRC(&val)
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x78:
|
||||
// in a, (c)
|
||||
z.inRC(&z.A)
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.MemPtr = z.bc() + 1
|
||||
z.updateXY(z.A)
|
||||
case 0xA2:
|
||||
z.ini() // ini
|
||||
@ -128,7 +128,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
z.ini()
|
||||
if z.B > 0 {
|
||||
z.PC -= 2
|
||||
z.TStates += 5
|
||||
z.cycleCount += 5
|
||||
}
|
||||
case 0xAA:
|
||||
// ind
|
||||
@ -138,33 +138,33 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
z.ind()
|
||||
if z.B > 0 {
|
||||
z.PC -= 2
|
||||
z.TStates += 5
|
||||
z.cycleCount += 5
|
||||
}
|
||||
case 0x41:
|
||||
z.core.IOWrite(z.GetBC(), z.B) // out (c), b
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.core.IOWrite(z.bc(), z.B) // out (c), b
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x49:
|
||||
z.core.IOWrite(z.GetBC(), z.C) // out (c), c
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.core.IOWrite(z.bc(), z.C) // out (c), c
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x51:
|
||||
z.core.IOWrite(z.GetBC(), z.D) // out (c), d
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.core.IOWrite(z.bc(), z.D) // out (c), d
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x59:
|
||||
z.core.IOWrite(z.GetBC(), z.E) // out (c), e
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.core.IOWrite(z.bc(), z.E) // out (c), e
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x61:
|
||||
z.core.IOWrite(z.GetBC(), z.H) // out (c), h
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.core.IOWrite(z.bc(), z.H) // out (c), h
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x69:
|
||||
z.core.IOWrite(z.GetBC(), z.L) // out (c), l
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.core.IOWrite(z.bc(), z.L) // out (c), l
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x71:
|
||||
z.core.IOWrite(z.GetBC(), 0) // out (c), 0
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.core.IOWrite(z.bc(), 0) // out (c), 0
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0x79:
|
||||
// out (c), a
|
||||
z.core.IOWrite(z.GetBC(), z.A)
|
||||
z.MemPtr = z.GetBC() + 1
|
||||
z.core.IOWrite(z.bc(), z.A)
|
||||
z.MemPtr = z.bc() + 1
|
||||
case 0xA3:
|
||||
z.outi() // outi
|
||||
case 0xB3:
|
||||
@ -172,7 +172,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
z.outi()
|
||||
if z.B > 0 {
|
||||
z.PC -= 2
|
||||
z.TStates += 5
|
||||
z.cycleCount += 5
|
||||
}
|
||||
case 0xAB:
|
||||
z.outd() // outd
|
||||
@ -180,40 +180,40 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
// otdr
|
||||
z.outd()
|
||||
if z.B > 0 {
|
||||
z.TStates += 5
|
||||
z.cycleCount += 5
|
||||
z.PC -= 2
|
||||
}
|
||||
|
||||
case 0x42:
|
||||
z.sbcHL(z.GetBC()) // sbc hl,bc
|
||||
z.sbcHL(z.bc()) // sbc hl,bc
|
||||
case 0x52:
|
||||
z.sbcHL(z.GetDE()) // sbc hl,de
|
||||
z.sbcHL(z.de()) // sbc hl,de
|
||||
case 0x62:
|
||||
z.sbcHL(z.GetHL()) // sbc hl,hl
|
||||
z.sbcHL(z.hl()) // sbc hl,hl
|
||||
case 0x72:
|
||||
z.sbcHL(z.SP) // sbc hl,sp
|
||||
case 0x4A:
|
||||
z.adcHL(z.GetBC()) // adc hl,bc
|
||||
z.adcHL(z.bc()) // adc hl,bc
|
||||
case 0x5A:
|
||||
z.adcHL(z.GetDE()) // adc hl,de
|
||||
z.adcHL(z.de()) // adc hl,de
|
||||
case 0x6A:
|
||||
z.adcHL(z.GetHL()) // adc hl,hl
|
||||
z.adcHL(z.hl()) // adc hl,hl
|
||||
case 0x7A:
|
||||
z.adcHL(z.SP) // adc hl,sp
|
||||
case 0x43:
|
||||
// ld (**), bc
|
||||
addr := z.nextW()
|
||||
z.ww(addr, z.GetBC())
|
||||
z.ww(addr, z.bc())
|
||||
z.MemPtr = addr + 1
|
||||
case 0x53:
|
||||
// ld (**), de
|
||||
addr := z.nextW()
|
||||
z.ww(addr, z.GetDE())
|
||||
z.ww(addr, z.de())
|
||||
z.MemPtr = addr + 1
|
||||
case 0x63:
|
||||
// ld (**), hl
|
||||
addr := z.nextW()
|
||||
z.ww(addr, z.GetHL())
|
||||
z.ww(addr, z.hl())
|
||||
z.MemPtr = addr + 1
|
||||
case 0x73:
|
||||
// ld (**), hl
|
||||
@ -251,9 +251,9 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
case 0x67:
|
||||
// rrd
|
||||
a := z.A
|
||||
val := z.rb(z.GetHL())
|
||||
val := z.rb(z.hl())
|
||||
z.A = (a & 0xF0) | (val & 0xF)
|
||||
z.wb(z.GetHL(), (val>>4)|(a<<4))
|
||||
z.wb(z.hl(), (val>>4)|(a<<4))
|
||||
|
||||
z.Flags.N = false
|
||||
z.Flags.H = false
|
||||
@ -261,20 +261,20 @@ func (z *CPU) execOpcodeED(opcode byte) {
|
||||
z.Flags.Z = z.A == 0
|
||||
z.Flags.S = z.A&0x80 != 0
|
||||
z.Flags.P = parity(z.A)
|
||||
z.MemPtr = z.GetHL() + 1
|
||||
z.MemPtr = z.hl() + 1
|
||||
case 0x6F:
|
||||
// rld
|
||||
a := z.A
|
||||
val := z.rb(z.GetHL())
|
||||
val := z.rb(z.hl())
|
||||
z.A = (a & 0xF0) | (val >> 4)
|
||||
z.wb(z.GetHL(), (val<<4)|(a&0xF))
|
||||
z.wb(z.hl(), (val<<4)|(a&0xF))
|
||||
z.Flags.N = false
|
||||
z.Flags.H = false
|
||||
z.updateXY(z.A)
|
||||
z.Flags.Z = z.A == 0
|
||||
z.Flags.S = z.A&0x80 != 0
|
||||
z.Flags.P = parity(z.A)
|
||||
z.MemPtr = z.GetHL() + 1
|
||||
z.MemPtr = z.hl() + 1
|
||||
default:
|
||||
log.Errorf("Unknown ED opcode: %02X\n", opcode)
|
||||
}
|
||||
|
||||
42
z80go.go
42
z80go.go
@ -43,11 +43,6 @@ type CPUInterface interface {
|
||||
SetState(state *CPU)
|
||||
// DebugOutput out current CPU state
|
||||
DebugOutput()
|
||||
// GenNMI Generate NMI
|
||||
GenNMI()
|
||||
// GenINT Generate INT,
|
||||
// data - data bus low address for IM2 mode
|
||||
GenINT(data byte)
|
||||
}
|
||||
|
||||
// FlagsType - Processor flags
|
||||
@ -106,19 +101,17 @@ type CPU struct {
|
||||
Iff1 bool `json:"iff1,omitempty"`
|
||||
Iff2 bool `json:"iff2,omitempty"`
|
||||
Halted bool `json:"halted,omitempty"`
|
||||
TStatesPart uint32 `json:"TStatesPart,omitempty"`
|
||||
|
||||
CycleCount uint32 `json:"cycleCount,omitempty"`
|
||||
IntOccurred bool `json:"intOccurred,omitempty"`
|
||||
NmiOccurred bool `json:"interruptOccurred,omitempty"`
|
||||
// mw hidden register
|
||||
MemPtr uint16
|
||||
|
||||
// methods to access CPU to memory and IO ports of computer
|
||||
core MemIoRW
|
||||
|
||||
// Data-Bus state for IM2 INT
|
||||
core MemIoRW
|
||||
intData byte
|
||||
// Total CPU cycle count (t-states)
|
||||
TStates uint32
|
||||
|
||||
cycleCount uint32
|
||||
// map of memory access
|
||||
memAccess map[uint16]byte
|
||||
// enable or disable code coverage marking
|
||||
@ -130,11 +123,8 @@ type CPU struct {
|
||||
// map of stack data marking
|
||||
extendedStack map[uint16]PushValueType
|
||||
|
||||
iffDelay byte
|
||||
// intPending is true if Interrupt is pending
|
||||
iffDelay byte
|
||||
intPending bool
|
||||
|
||||
// nmiPending is true if Interrupt is pending
|
||||
nmiPending bool
|
||||
}
|
||||
|
||||
@ -241,23 +231,3 @@ func (f *FlagsType) SetFlags(flags byte) {
|
||||
func (z *CPU) GetPC() uint16 {
|
||||
return z.PC
|
||||
}
|
||||
|
||||
// GetSP - return stack pointer
|
||||
func (z *CPU) GetSP() uint16 {
|
||||
return z.SP
|
||||
}
|
||||
|
||||
// GetBC - return BC register pair
|
||||
func (z *CPU) GetBC() uint16 {
|
||||
return (uint16(z.B) << 8) | uint16(z.C)
|
||||
}
|
||||
|
||||
// GetDE - return DE register pair
|
||||
func (z *CPU) GetDE() uint16 {
|
||||
return (uint16(z.D) << 8) | uint16(z.E)
|
||||
}
|
||||
|
||||
// GetHL - return HL register pair
|
||||
func (z *CPU) GetHL() uint16 {
|
||||
return (uint16(z.H) << 8) | uint16(z.L)
|
||||
}
|
||||
|
||||
@ -438,7 +438,9 @@ func setComputerState(test Z80TestIn) {
|
||||
Iff1: test.state.IFF1,
|
||||
Iff2: test.state.IFF2,
|
||||
Halted: test.state.isHalted,
|
||||
TStatesPart: 0,
|
||||
CycleCount: 0,
|
||||
IntOccurred: false,
|
||||
NmiOccurred: false,
|
||||
MemPtr: test.registers.MemPtr,
|
||||
}
|
||||
|
||||
@ -611,34 +613,3 @@ func TestZ80_JR_mnn(t *testing.T) {
|
||||
t.Errorf("Error JR -nn, result PC=0x%04X, expected: 0x%04X", computer.cpu.PC, expected)
|
||||
}
|
||||
}
|
||||
|
||||
var testEXSPHL = []byte{0x21, 0x55, 0x44, 0xE3, 0xC9}
|
||||
|
||||
func TestZ80_EXSPHL(t *testing.T) {
|
||||
setMemory(0x0000, testEXSPHL)
|
||||
state := computer.cpu.GetState()
|
||||
state.SP = 0x1122
|
||||
state.PC = 0x0000
|
||||
computer.MemWrite(state.SP, 0x88)
|
||||
computer.MemWrite(state.SP+1, 0x99)
|
||||
|
||||
computer.cpu.SetState(state)
|
||||
// Step 1: LD HL,0x4455
|
||||
computer.cpu.RunInstruction()
|
||||
expected := uint16(0x4455)
|
||||
if computer.cpu.GetHL() != expected {
|
||||
t.Errorf("Error LD HL,nnnn, result HL=0x%04X, expected: 0x%04X", computer.cpu.GetHL(), expected)
|
||||
}
|
||||
// Step 2: EX (SP), HL
|
||||
computer.cpu.RunInstruction()
|
||||
expected = uint16(0x9988)
|
||||
if computer.cpu.GetHL() != expected {
|
||||
t.Errorf("Error EX (SP),HL, result HL=0x%04X, expected: 0x%04X", computer.cpu.GetHL(), expected)
|
||||
}
|
||||
expected = uint16(0x4455)
|
||||
mem := uint16(computer.MemRead(state.SP)) | (uint16(computer.MemRead(state.SP+1)) << 8)
|
||||
if mem != expected {
|
||||
t.Errorf("Error EX (SP),HL, result (SP)=0x%04X, expected: 0x%04X", mem, expected)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user