Compare commits

..

No commits in common. "main" and "v1.0.7" have entirely different histories.
main ... v1.0.7

8 changed files with 236 additions and 285 deletions

27
cpu.go
View File

@ -14,7 +14,7 @@ func NewCPU(core MemIoRW) *CPU {
z := CPU{} z := CPU{}
z.Reset() z.Reset()
z.core = core z.core = core
z.TStates = 0 z.cycleCount = 0
z.codeCoverageEnabled = false z.codeCoverageEnabled = false
// z.memAccess = // z.memAccess =
z.codeCoverageEnabled = false z.codeCoverageEnabled = false
@ -31,7 +31,7 @@ func (z *CPU) RunInstruction() (uint32, *map[uint16]byte) {
if z.codeCoverageEnabled { if z.codeCoverageEnabled {
z.codeCoverage[z.PC] = true z.codeCoverage[z.PC] = true
} }
pre := z.TStates pre := z.cycleCount
if z.Halted { if z.Halted {
z.execOpcode(0x00) z.execOpcode(0x00)
} else { } else {
@ -39,7 +39,7 @@ func (z *CPU) RunInstruction() (uint32, *map[uint16]byte) {
z.execOpcode(opcode) z.execOpcode(opcode)
} }
z.processInterrupts() z.processInterrupts()
return z.TStates - pre, &z.memAccess return z.cycleCount - pre, &z.memAccess
} }
// SetState set current CPU state // SetState set current CPU state
@ -71,18 +71,14 @@ func (z *CPU) SetState(state *CPU) {
z.Flags = state.Flags z.Flags = state.Flags
z.FlagsAlt = state.FlagsAlt z.FlagsAlt = state.FlagsAlt
z.TStates = state.TStates
z.TStatesPart = state.TStatesPart
z.MemPtr = state.MemPtr z.MemPtr = state.MemPtr
z.IMode = state.IMode z.IMode = state.IMode
z.Iff1 = state.Iff1 z.Iff1 = state.Iff1
z.Iff2 = state.Iff2 z.Iff2 = state.Iff2
z.Halted = state.Halted z.Halted = state.Halted
z.intData = state.intData z.IntOccurred = state.IntOccurred
z.intPending = state.intPending z.NmiOccurred = false
z.nmiPending = state.nmiPending
} }
func (z *CPU) GetState() *CPU { func (z *CPU) GetState() *CPU {
return &CPU{ return &CPU{
A: z.A, A: z.A,
@ -113,16 +109,17 @@ func (z *CPU) GetState() *CPU {
Iff1: z.Iff1, Iff1: z.Iff1,
Iff2: z.Iff2, Iff2: z.Iff2,
Halted: z.Halted, Halted: z.Halted,
TStatesPart: z.TStatesPart, CycleCount: z.cycleCount,
TStates: z.TStates, IntOccurred: z.IntOccurred,
NmiOccurred: z.NmiOccurred,
MemPtr: z.MemPtr, 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 // ClearCodeCoverage - clears code coverage journal
func (z *CPU) ClearCodeCoverage() { func (z *CPU) ClearCodeCoverage() {
clear(z.codeCoverage) clear(z.codeCoverage)

View File

@ -58,7 +58,6 @@ func (z *CPU) pushW(val uint16) {
} }
func (z *CPU) popW() uint16 { func (z *CPU) popW() uint16 {
z.extendedStack[z.SP] = PushValueTypeDefault
z.SP += 2 z.SP += 2
return z.rw(z.SP - 2) return z.rw(z.SP - 2)
} }
@ -75,17 +74,17 @@ func (z *CPU) nextW() uint16 {
return w return w
} }
//func (z *CPU) BC() uint16 { func (z *CPU) bc() uint16 {
// return (uint16(z.B) << 8) | uint16(z.C) return (uint16(z.B) << 8) | uint16(z.C)
//} }
//
//func (z *CPU) DE() uint16 { func (z *CPU) de() uint16 {
// return (uint16(z.D) << 8) | uint16(z.E) return (uint16(z.D) << 8) | uint16(z.E)
//} }
//
//func (z *CPU) HL() uint16 { func (z *CPU) hl() uint16 {
// return (uint16(z.H) << 8) | uint16(z.L) return (uint16(z.H) << 8) | uint16(z.L)
//} }
func (z *CPU) setBC(val uint16) { func (z *CPU) setBC(val uint16) {
z.B = byte(val >> 8) z.B = byte(val >> 8)
@ -179,15 +178,15 @@ func (z *CPU) updateXY(result byte) {
func (z *CPU) DebugOutput() { 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", 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) 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), 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() { func (z *CPU) Reset() {
z.TStates = 0 z.cycleCount = 0
z.PC = 0 z.PC = 0
z.SP = 0xFFFF z.SP = 0xFFFF
z.IX = 0 z.IX = 0
@ -221,5 +220,7 @@ func (z *CPU) Reset() {
z.Iff1 = false z.Iff1 = false
z.Iff2 = false z.Iff2 = false
z.Halted = false z.Halted = false
z.IntOccurred = false
z.NmiOccurred = false
z.intData = 0 z.intData = 0
} }

View File

@ -30,7 +30,7 @@ func (z *CPU) condCall(condition bool) {
addr := z.nextW() addr := z.nextW()
if condition { if condition {
z.call(addr) z.call(addr)
z.TStates += 7 z.cycleCount += 7
} }
z.MemPtr = addr z.MemPtr = addr
} }
@ -45,7 +45,7 @@ func (z *CPU) ret() {
func (z *CPU) condRet(condition bool) { func (z *CPU) condRet(condition bool) {
if condition { if condition {
z.ret() z.ret()
z.TStates += 6 z.cycleCount += 6
} }
} }
@ -62,20 +62,20 @@ func (z *CPU) condJr(condition bool) {
b := z.nextB() b := z.nextB()
if condition { if condition {
z.jr(b) z.jr(b)
z.TStates += 5 z.cycleCount += 5
} }
} }
func BToByte(cond bool) byte { func bToByte(cond bool) byte {
if cond { if cond {
return 1 return byte(1)
} }
return 0 return byte(0)
} }
// ADD Byte: adds two bytes together // ADD Byte: adds two bytes together
func (z *CPU) addB(a byte, b byte, cy bool) byte { 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.S = result&0x80 != 0
z.Flags.Z = result == 0 z.Flags.Z = result == 0
z.Flags.H = carry(4, uint16(a), uint16(b), cy) 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 { func (z *CPU) addW(a uint16, b uint16, cy bool) uint16 {
lsb := z.addB(byte(a), byte(b), cy) lsb := z.addB(byte(a), byte(b), cy)
msb := z.addB(byte(a>>8), byte(b>>8), z.Flags.C) 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) // subW Subtracts two words (with optional carry)
func (z *CPU) subW(a uint16, b uint16, cy bool) uint16 { func (z *CPU) subW(a uint16, b uint16, cy bool) uint16 {
lsb := z.subB(byte(a), byte(b), cy) lsb := z.subB(byte(a), byte(b), cy)
msb := z.subB(byte(a>>8), byte(b>>8), z.Flags.C) 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) result := (uint16(msb) << 8) | uint16(lsb)
z.Flags.Z = result == 0 z.Flags.Z = result == 0
z.MemPtr = a + 1 z.MemPtr = a + 1
@ -121,7 +120,7 @@ func (z *CPU) addHL(val uint16) {
sf := z.Flags.S sf := z.Flags.S
zf := z.Flags.Z zf := z.Flags.Z
pf := z.Flags.P pf := z.Flags.P
result := z.addW(z.GetHL(), val, false) result := z.addW(z.hl(), val, false)
z.setHL(result) z.setHL(result)
z.Flags.S = sf z.Flags.S = sf
z.Flags.Z = zf z.Flags.Z = zf
@ -142,7 +141,7 @@ func (z *CPU) addIZ(reg *uint16, val uint16) {
// adcHL adds A word (+ carry) to HL // adcHL adds A word (+ carry) to HL
func (z *CPU) adcHL(val uint16) { 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.S = result&0x8000 != 0
z.Flags.Z = result == 0 z.Flags.Z = result == 0
z.setHL(result) z.setHL(result)
@ -150,7 +149,7 @@ func (z *CPU) adcHL(val uint16) {
// sbcHL subtracts A word (+ carry) to HL // sbcHL subtracts A word (+ carry) to HL
func (z *CPU) sbcHL(val uint16) { 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.S = result&0x8000 != 0
z.Flags.Z = result == 0 z.Flags.Z = result == 0
z.setHL(result) 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 // executes A logic "and" between register A and A byte, then stores the
// result in register A // result in register A
func (z *CPU) lAnd(val byte) { 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 // executes A logic "xor" between register A and A byte, then stores the
// result in register A // result in register A
func (z *CPU) lXor(val byte) { 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 // executes A logic "or" between register A and A byte, then stores the
// result in register A // result in register A
func (z *CPU) lOr(val byte) { 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.S = result&0x80 != 0
z.Flags.Z = result == 0 z.Flags.Z = result == 0
z.Flags.H = hf z.Flags.H = false
z.Flags.P = parity(result) z.Flags.P = parity(result)
z.Flags.N = false z.Flags.N = false
z.Flags.C = false z.Flags.C = false
@ -204,6 +217,11 @@ func (z *CPU) lCmn(result byte, hf bool) {
// compares A value with register A // compares A value with register A
func (z *CPU) cp(val byte) { func (z *CPU) cp(val byte) {
z.subB(z.A, val, false) 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) z.updateXY(val)
} }
@ -240,7 +258,7 @@ func (z *CPU) cbRrc(val byte) byte {
func (z *CPU) cbRl(val byte) byte { func (z *CPU) cbRl(val byte) byte {
cf := z.Flags.C cf := z.Flags.C
z.Flags.C = val>>7 != 0 z.Flags.C = val>>7 != 0
val = (val << 1) | BToByte(cf) val = (val << 1) | bToByte(cf)
z.Flags.S = val&0x80 != 0 z.Flags.S = val&0x80 != 0
z.Flags.Z = val == 0 z.Flags.Z = val == 0
z.Flags.N = false z.Flags.N = false
@ -254,7 +272,7 @@ func (z *CPU) cbRl(val byte) byte {
func (z *CPU) cbRr(val byte) byte { func (z *CPU) cbRr(val byte) byte {
c := z.Flags.C c := z.Flags.C
z.Flags.C = (val & 1) != 0 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.S = val&0x80 != 0
z.Flags.Z = val == 0 z.Flags.Z = val == 0
z.Flags.N = false z.Flags.N = false
@ -330,14 +348,14 @@ func (z *CPU) cbBit(val byte, n byte) byte {
} }
func (z *CPU) ldi() { func (z *CPU) ldi() {
de := z.GetDE() de := z.de()
hl := z.GetHL() hl := z.hl()
val := z.rb(hl) val := z.rb(hl)
z.wb(de, val) z.wb(de, val)
z.setHL(z.GetHL() + 1) z.setHL(z.hl() + 1)
z.setDE(z.GetDE() + 1) z.setDE(z.de() + 1)
z.setBC(z.GetBC() - 1) z.setBC(z.bc() - 1)
// see https://wikiti.brandonw.net/index.php?title=Z80_Instruction_Set // see https://wikiti.brandonw.net/index.php?title=Z80_Instruction_Set
// for the calculation of xf/yf on LDI // for the calculation of xf/yf on LDI
@ -348,27 +366,27 @@ func (z *CPU) ldi() {
z.Flags.N = false z.Flags.N = false
z.Flags.H = false z.Flags.H = false
z.Flags.P = z.GetBC() > 0 z.Flags.P = z.bc() > 0
} }
func (z *CPU) ldd() { func (z *CPU) ldd() {
z.ldi() z.ldi()
// same as ldi but HL and DE are decremented instead of incremented // same as ldi but HL and DE are decremented instead of incremented
z.setHL(z.GetHL() - 2) z.setHL(z.hl() - 2)
z.setDE(z.GetDE() - 2) z.setDE(z.de() - 2)
} }
func (z *CPU) cpi() { func (z *CPU) cpi() {
cf := z.Flags.C cf := z.Flags.C
result := z.subB(z.A, z.rb(z.GetHL()), false) result := z.subB(z.A, z.rb(z.hl()), false)
z.setHL(z.GetHL() + 1) z.setHL(z.hl() + 1)
z.setBC(z.GetBC() - 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.X = val&0x08 != 0
z.Flags.Y = val&0x02 != 0 z.Flags.Y = val&0x02 != 0
z.Flags.P = z.GetBC() != 0 z.Flags.P = z.bc() != 0
z.Flags.C = cf z.Flags.C = cf
z.MemPtr += 1 z.MemPtr += 1
} }
@ -376,12 +394,12 @@ func (z *CPU) cpi() {
func (z *CPU) cpd() { func (z *CPU) cpd() {
z.cpi() z.cpi()
// same as cpi but HL is decremented instead of incremented // same as cpi but HL is decremented instead of incremented
z.setHL(z.GetHL() - 2) z.setHL(z.hl() - 2)
z.MemPtr -= 2 z.MemPtr -= 2
} }
func (z *CPU) inRC(r *byte) { 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.Z = *r == 0
z.Flags.S = *r&0x80 != 0 z.Flags.S = *r&0x80 != 0
z.Flags.P = parity(*r) z.Flags.P = parity(*r)
@ -390,9 +408,9 @@ func (z *CPU) inRC(r *byte) {
} }
func (z *CPU) ini() { func (z *CPU) ini() {
val := z.core.IORead(z.GetBC()) val := z.core.IORead(z.bc())
z.wb(z.GetHL(), val) z.wb(z.hl(), val)
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
z.B-- z.B--
other := val + z.C + 1 other := val + z.C + 1
@ -408,13 +426,13 @@ func (z *CPU) ini() {
z.Flags.S = z.B&0x80 != 0 z.Flags.S = z.B&0x80 != 0
z.Flags.Z = z.B == 0 z.Flags.Z = z.B == 0
z.updateXY(z.B) z.updateXY(z.B)
z.setHL(z.GetHL() + 1) z.setHL(z.hl() + 1)
} }
func (z *CPU) ind() { func (z *CPU) ind() {
val := z.core.IORead(z.GetBC()) val := z.core.IORead(z.bc())
z.wb(z.GetHL(), val) z.wb(z.hl(), val)
z.MemPtr = z.GetBC() - 1 z.MemPtr = z.bc() - 1
z.B-- z.B--
other := val + z.C - 1 other := val + z.C - 1
@ -431,7 +449,7 @@ func (z *CPU) ind() {
z.Flags.S = z.B&0x80 != 0 z.Flags.S = z.B&0x80 != 0
z.Flags.Z = z.B == 0 z.Flags.Z = z.B == 0
z.updateXY(z.B) z.updateXY(z.B)
z.setHL(z.GetHL() - 1) z.setHL(z.hl() - 1)
} }
func (z *CPU) outCmnFlags(val uint8) { func (z *CPU) outCmnFlags(val uint8) {
other := val + z.L other := val + z.L
@ -450,20 +468,20 @@ func (z *CPU) outCmnFlags(val uint8) {
} }
func (z *CPU) outi() { func (z *CPU) outi() {
val := z.rb(z.GetHL()) val := z.rb(z.hl())
z.B-- z.B--
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
z.core.IOWrite(z.GetBC(), val) z.core.IOWrite(z.bc(), val)
z.setHL(z.GetHL() + 1) z.setHL(z.hl() + 1)
z.outCmnFlags(val) z.outCmnFlags(val)
} }
func (z *CPU) outd() { func (z *CPU) outd() {
val := z.rb(z.GetHL()) val := z.rb(z.hl())
z.B-- z.B--
z.MemPtr = z.GetBC() - 1 z.MemPtr = z.bc() - 1
z.core.IOWrite(z.GetBC(), val) z.core.IOWrite(z.bc(), val)
z.setHL(z.GetHL() - 1) z.setHL(z.hl() - 1)
z.outCmnFlags(val) z.outCmnFlags(val)
} }
@ -520,37 +538,31 @@ func (z *CPU) processInterrupts() {
if z.nmiPending { if z.nmiPending {
z.nmiPending = false z.nmiPending = false
if z.Halted { z.Halted = false
z.PC++
z.Halted = false
}
z.Iff1 = false z.Iff1 = false
z.incR() z.incR()
z.TStates += 11 z.cycleCount += 11
z.call(0x0066) z.call(0x0066)
return return
} }
if z.intPending && z.Iff1 { if z.intPending && z.Iff1 {
z.intPending = false z.intPending = false
if z.Halted { z.Halted = false
z.PC++
z.Halted = false
}
z.Iff1 = false z.Iff1 = false
z.Iff2 = false z.Iff2 = false
z.incR() z.incR()
switch z.IMode { switch z.IMode {
case 0: case 0:
z.TStates += 11 z.cycleCount += 11
z.execOpcode(z.intData) z.execOpcode(z.intData)
case 1: case 1:
z.TStates += 13 z.cycleCount += 13
z.call(0x38) z.call(0x38)
case 2: case 2:
z.TStates += 19 z.cycleCount += 19
z.call(z.rw((uint16(z.I) << 8) | uint16(z.intData))) z.call(z.rw((uint16(z.I) << 8) | uint16(z.intData)))
default: default:
log.Errorf("Unsupported interrupt mode %d\n", z.IMode) log.Errorf("Unsupported interrupt mode %d\n", z.IMode)
@ -572,7 +584,7 @@ func (z *CPU) GenINT(data byte) {
// executes A non-prefixed opcode // executes A non-prefixed opcode
func (z *CPU) execOpcode(opcode byte) { func (z *CPU) execOpcode(opcode byte) {
z.TStates += uint32(cycles00[opcode]) z.cycleCount += uint32(cycles00[opcode])
z.incR() z.incR()
switch opcode { switch opcode {
@ -682,34 +694,34 @@ func (z *CPU) execOpcode(opcode byte) {
//z.l = z.l // ld l,l //z.l = z.l // ld l,l
case 0x7E: case 0x7E:
z.A = z.rb(z.GetHL()) // ld a,(hl) z.A = z.rb(z.hl()) // ld a,(hl)
case 0x46: case 0x46:
z.B = z.rb(z.GetHL()) // ld b,(hl) z.B = z.rb(z.hl()) // ld b,(hl)
case 0x4E: case 0x4E:
z.C = z.rb(z.GetHL()) // ld c,(hl) z.C = z.rb(z.hl()) // ld c,(hl)
case 0x56: case 0x56:
z.D = z.rb(z.GetHL()) // ld d,(hl) z.D = z.rb(z.hl()) // ld d,(hl)
case 0x5E: case 0x5E:
z.E = z.rb(z.GetHL()) // ld e,(hl) z.E = z.rb(z.hl()) // ld e,(hl)
case 0x66: case 0x66:
z.H = z.rb(z.GetHL()) // ld h,(hl) z.H = z.rb(z.hl()) // ld h,(hl)
case 0x6E: case 0x6E:
z.L = z.rb(z.GetHL()) // ld l,(hl) z.L = z.rb(z.hl()) // ld l,(hl)
case 0x77: case 0x77:
z.wb(z.GetHL(), z.A) // ld (hl),a z.wb(z.hl(), z.A) // ld (hl),a
case 0x70: case 0x70:
z.wb(z.GetHL(), z.B) // ld (hl),b z.wb(z.hl(), z.B) // ld (hl),b
case 0x71: case 0x71:
z.wb(z.GetHL(), z.C) // ld (hl),c z.wb(z.hl(), z.C) // ld (hl),c
case 0x72: case 0x72:
z.wb(z.GetHL(), z.D) // ld (hl),d z.wb(z.hl(), z.D) // ld (hl),d
case 0x73: case 0x73:
z.wb(z.GetHL(), z.E) // ld (hl),e z.wb(z.hl(), z.E) // ld (hl),e
case 0x74: case 0x74:
z.wb(z.GetHL(), z.H) // ld (hl),h z.wb(z.hl(), z.H) // ld (hl),h
case 0x75: case 0x75:
z.wb(z.GetHL(), z.L) // ld (hl),l z.wb(z.hl(), z.L) // ld (hl),l
case 0x3E: case 0x3E:
z.A = z.nextB() // ld a,* z.A = z.nextB() // ld a,*
@ -726,15 +738,15 @@ func (z *CPU) execOpcode(opcode byte) {
case 0x2E: case 0x2E:
z.L = z.nextB() // ld l,* z.L = z.nextB() // ld l,*
case 0x36: case 0x36:
z.wb(z.GetHL(), z.nextB()) // ld (hl),* z.wb(z.hl(), z.nextB()) // ld (hl),*
case 0x0A: case 0x0A:
// ld a,(bc) // ld a,(bc)
z.A = z.rb(z.GetBC()) z.A = z.rb(z.bc())
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x1A: case 0x1A:
// ld a,(de) // ld a,(de)
z.A = z.rb(z.GetDE()) z.A = z.rb(z.de())
z.MemPtr = z.GetDE() + 1 z.MemPtr = z.de() + 1
case 0x3A: case 0x3A:
// ld a,(**) // ld a,(**)
addr := z.nextW() addr := z.nextW()
@ -742,12 +754,12 @@ func (z *CPU) execOpcode(opcode byte) {
z.MemPtr = addr + 1 z.MemPtr = addr + 1
case 0x02: case 0x02:
// ld (bc),a // ld (bc),a
z.wb(z.GetBC(), z.A) z.wb(z.bc(), z.A)
z.MemPtr = (uint16(z.A) << 8) | ((z.GetBC() + 1) & 0xFF) z.MemPtr = (uint16(z.A) << 8) | ((z.bc() + 1) & 0xFF)
case 0x12: case 0x12:
// ld (de),a // ld (de),a
z.wb(z.GetDE(), z.A) z.wb(z.de(), z.A)
z.MemPtr = (uint16(z.A) << 8) | ((z.GetDE() + 1) & 0xFF) z.MemPtr = (uint16(z.A) << 8) | ((z.de() + 1) & 0xFF)
case 0x32: case 0x32:
// ld (**),a // ld (**),a
addr := z.nextW() addr := z.nextW()
@ -770,20 +782,20 @@ func (z *CPU) execOpcode(opcode byte) {
case 0x22: case 0x22:
// ld (**),hl // ld (**),hl
addr := z.nextW() addr := z.nextW()
z.ww(addr, z.GetHL()) z.ww(addr, z.hl())
z.MemPtr = addr + 1 z.MemPtr = addr + 1
case 0xF9: case 0xF9:
z.SP = z.GetHL() // ld sp,hl z.SP = z.hl() // ld sp,hl
case 0xEB: case 0xEB:
// ex de,hl // ex de,hl
de := z.GetDE() de := z.de()
z.setDE(z.GetHL()) z.setDE(z.hl())
z.setHL(de) z.setHL(de)
case 0xE3: case 0xE3:
// ex (sp),hl // ex (sp),hl
val := z.rw(z.SP) val := z.rw(z.SP)
z.ww(z.SP, z.GetHL()) z.ww(z.SP, z.hl())
z.setHL(val) z.setHL(val)
z.MemPtr = val z.MemPtr = val
case 0x87: case 0x87:
@ -801,7 +813,7 @@ func (z *CPU) execOpcode(opcode byte) {
case 0x85: case 0x85:
z.A = z.addB(z.A, z.L, false) // add a,l z.A = z.addB(z.A, z.L, false) // add a,l
case 0x86: 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: case 0xC6:
z.A = z.addB(z.A, z.nextB(), false) // add a,* z.A = z.addB(z.A, z.nextB(), false) // add a,*
@ -820,7 +832,7 @@ func (z *CPU) execOpcode(opcode byte) {
case 0x8D: case 0x8D:
z.A = z.addB(z.A, z.L, z.Flags.C) // adc a,l z.A = z.addB(z.A, z.L, z.Flags.C) // adc a,l
case 0x8E: 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: case 0xCE:
z.A = z.addB(z.A, z.nextB(), z.Flags.C) // adc a,* 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: case 0x95:
z.A = z.subB(z.A, z.L, false) // sub a,l z.A = z.subB(z.A, z.L, false) // sub a,l
case 0x96: 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: case 0xD6:
z.A = z.subB(z.A, z.nextB(), false) // sub a,* z.A = z.subB(z.A, z.nextB(), false) // sub a,*
@ -858,16 +870,16 @@ func (z *CPU) execOpcode(opcode byte) {
case 0x9D: case 0x9D:
z.A = z.subB(z.A, z.L, z.Flags.C) // sbc a,l z.A = z.subB(z.A, z.L, z.Flags.C) // sbc a,l
case 0x9E: 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: case 0xDE:
z.A = z.subB(z.A, z.nextB(), z.Flags.C) // sbc a,* z.A = z.subB(z.A, z.nextB(), z.Flags.C) // sbc a,*
case 0x09: case 0x09:
z.addHL(z.GetBC()) // add hl,bc z.addHL(z.bc()) // add hl,bc
case 0x19: case 0x19:
z.addHL(z.GetDE()) // add hl,de z.addHL(z.de()) // add hl,de
case 0x29: case 0x29:
z.addHL(z.GetHL()) // add hl,hl z.addHL(z.hl()) // add hl,hl
case 0x39: case 0x39:
z.addHL(z.SP) // add hl,sp z.addHL(z.SP) // add hl,sp
@ -896,8 +908,8 @@ func (z *CPU) execOpcode(opcode byte) {
z.L = z.inc(z.L) z.L = z.inc(z.L)
case 0x34: case 0x34:
// inc (hl) // inc (hl)
result := z.inc(z.rb(z.GetHL())) result := z.inc(z.rb(z.hl()))
z.wb(z.GetHL(), result) z.wb(z.hl(), result)
case 0x3D: case 0x3D:
z.A = z.dec(z.A) // dec a z.A = z.dec(z.A) // dec a
case 0x05: case 0x05:
@ -914,22 +926,22 @@ func (z *CPU) execOpcode(opcode byte) {
z.L = z.dec(z.L) // dec l z.L = z.dec(z.L) // dec l
case 0x35: case 0x35:
// dec (hl) // dec (hl)
result := z.dec(z.rb(z.GetHL())) result := z.dec(z.rb(z.hl()))
z.wb(z.GetHL(), result) z.wb(z.hl(), result)
case 0x03: case 0x03:
z.setBC(z.GetBC() + 1) // inc bc z.setBC(z.bc() + 1) // inc bc
case 0x13: case 0x13:
z.setDE(z.GetDE() + 1) // inc de z.setDE(z.de() + 1) // inc de
case 0x23: case 0x23:
z.setHL(z.GetHL() + 1) // inc hl z.setHL(z.hl() + 1) // inc hl
case 0x33: case 0x33:
z.SP = z.SP + 1 // inc sp z.SP = z.SP + 1 // inc sp
case 0x0B: case 0x0B:
z.setBC(z.GetBC() - 1) // dec bc z.setBC(z.bc() - 1) // dec bc
case 0x1B: case 0x1B:
z.setDE(z.GetDE() - 1) // dec de z.setDE(z.de() - 1) // dec de
case 0x2B: case 0x2B:
z.setHL(z.GetHL() - 1) // dec hl z.setHL(z.hl() - 1) // dec hl
case 0x3B: case 0x3B:
z.SP = z.SP - 1 // dec sp z.SP = z.SP - 1 // dec sp
case 0x27: case 0x27:
@ -955,20 +967,20 @@ func (z *CPU) execOpcode(opcode byte) {
case 0x07: case 0x07:
// Rotate left // Rotate left
z.Flags.C = z.A&0x80 != 0 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.N = false
z.Flags.H = false z.Flags.H = false
z.updateXY(z.A) z.updateXY(z.A)
case 0x0F: case 0x0F:
// Rotate right // Rotate right
z.Flags.C = z.A&1 != 0 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.N = false
z.Flags.H = false z.Flags.H = false
z.updateXY(z.A) z.updateXY(z.A)
case 0x17: case 0x17:
// rla // rla
cy := BToByte(z.Flags.C) cy := bToByte(z.Flags.C)
z.Flags.C = z.A&0x80 != 0 z.Flags.C = z.A&0x80 != 0
z.A = (z.A << 1) | cy z.A = (z.A << 1) | cy
z.Flags.N = false z.Flags.N = false
@ -976,7 +988,7 @@ func (z *CPU) execOpcode(opcode byte) {
z.updateXY(z.A) z.updateXY(z.A)
case 0x1F: case 0x1F:
// rra // rra
cy := BToByte(z.Flags.C) cy := bToByte(z.Flags.C)
z.Flags.C = z.A&1 != 0 z.Flags.C = z.A&1 != 0
z.A = (z.A >> 1) | (cy << 7) z.A = (z.A >> 1) | (cy << 7)
z.Flags.N = false z.Flags.N = false
@ -997,7 +1009,7 @@ func (z *CPU) execOpcode(opcode byte) {
case 0xA5: case 0xA5:
z.lAnd(z.L) // and l z.lAnd(z.L) // and l
case 0xA6: case 0xA6:
z.lAnd(z.rb(z.GetHL())) // and (hl) z.lAnd(z.rb(z.hl())) // and (hl)
case 0xE6: case 0xE6:
z.lAnd(z.nextB()) // and * z.lAnd(z.nextB()) // and *
@ -1016,7 +1028,7 @@ func (z *CPU) execOpcode(opcode byte) {
case 0xAD: case 0xAD:
z.lXor(z.L) // xor l z.lXor(z.L) // xor l
case 0xAE: case 0xAE:
z.lXor(z.rb(z.GetHL())) // xor (hl) z.lXor(z.rb(z.hl())) // xor (hl)
case 0xEE: case 0xEE:
z.lXor(z.nextB()) // xor * z.lXor(z.nextB()) // xor *
@ -1035,7 +1047,7 @@ func (z *CPU) execOpcode(opcode byte) {
case 0xB5: case 0xB5:
z.lOr(z.L) // or l z.lOr(z.L) // or l
case 0xB6: case 0xB6:
z.lOr(z.rb(z.GetHL())) // or (hl) z.lOr(z.rb(z.hl())) // or (hl)
case 0xF6: case 0xF6:
z.lOr(z.nextB()) // or * z.lOr(z.nextB()) // or *
@ -1054,7 +1066,7 @@ func (z *CPU) execOpcode(opcode byte) {
case 0xBD: case 0xBD:
z.cp(z.L) z.cp(z.L)
case 0xBE: case 0xBE:
z.cp(z.rb(z.GetHL())) // cp (hl) z.cp(z.rb(z.hl())) // cp (hl)
case 0xFE: case 0xFE:
z.cp(z.nextB()) // cp * z.cp(z.nextB()) // cp *
@ -1099,7 +1111,7 @@ func (z *CPU) execOpcode(opcode byte) {
z.condJr(z.Flags.C) // jr c, * z.condJr(z.Flags.C) // jr c, *
case 0xE9: case 0xE9:
z.PC = z.GetHL() // jp (hl) z.PC = z.hl() // jp (hl)
case 0xCD: case 0xCD:
z.call(z.nextW()) // call z.call(z.nextW()) // call
@ -1164,11 +1176,11 @@ func (z *CPU) execOpcode(opcode byte) {
z.call(0x38) // rst 7 z.call(0x38) // rst 7
z.extendedStack[z.SP] = PushValueTypeRst z.extendedStack[z.SP] = PushValueTypeRst
case 0xC5: case 0xC5:
z.pushW(z.GetBC()) // push bc z.pushW(z.bc()) // push bc
case 0xD5: case 0xD5:
z.pushW(z.GetDE()) // push de z.pushW(z.de()) // push de
case 0xE5: case 0xE5:
z.pushW(z.GetHL()) // push hl z.pushW(z.hl()) // push hl
case 0xF5: case 0xF5:
z.pushW((uint16(z.A) << 8) | uint16(z.f())) // push af z.pushW((uint16(z.A) << 8) | uint16(z.f())) // push af

View File

@ -4,7 +4,7 @@ import log "github.com/sirupsen/logrus"
// executes A CB opcode // executes A CB opcode
func (z *CPU) execOpcodeCB(opcode byte) { func (z *CPU) execOpcodeCB(opcode byte) {
z.TStates += 8 z.cycleCount += 8
z.incR() z.incR()
// decoding instructions from http://z80.info/decoding.htm#cb // decoding instructions from http://z80.info/decoding.htm#cb
@ -29,7 +29,7 @@ func (z *CPU) execOpcodeCB(opcode byte) {
case 5: case 5:
reg = &z.L reg = &z.L
case 6: case 6:
hl = z.rb(z.GetHL()) hl = z.rb(z.hl())
reg = &hl reg = &hl
case 7: case 7:
reg = &z.A reg = &z.A
@ -64,7 +64,7 @@ func (z *CPU) execOpcodeCB(opcode byte) {
// in bit (hl), x/y flags are handled differently: // in bit (hl), x/y flags are handled differently:
if z_ == 6 { if z_ == 6 {
z.updateXY(byte(z.MemPtr >> 8)) z.updateXY(byte(z.MemPtr >> 8))
z.TStates += 4 z.cycleCount += 4
} }
case 2: case 2:
@ -74,11 +74,11 @@ func (z *CPU) execOpcodeCB(opcode byte) {
} }
if (x_ == 0 || x_ == 2 || x_ == 3) && z_ == 6 { if (x_ == 0 || x_ == 2 || x_ == 3) && z_ == 6 {
z.TStates += 7 z.cycleCount += 7
} }
if reg == &hl { 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 z.L = result
// always false // always false
//case 6: //case 6:
// z.wb(z.GetHL(), result) // z.wb(z.hl(), result)
case 7: case 7:
z.A = result z.A = result
} }
@ -154,9 +154,9 @@ func (z *CPU) execOpcodeDcb(opcode byte, addr uint16) {
if x_ == 1 { if x_ == 1 {
// bit instructions take 20 cycles, others take 23 // bit instructions take 20 cycles, others take 23
z.TStates += 20 z.cycleCount += 20
} else { } else {
z.wb(addr, result) z.wb(addr, result)
z.TStates += 23 z.cycleCount += 23
} }
} }

View File

@ -2,7 +2,7 @@ package z80go
// executes A DD/FD opcode (IZ = IX or IY) // executes A DD/FD opcode (IZ = IX or IY)
func (z *CPU) execOpcodeDDFD(opcode byte, iz *uint16) { func (z *CPU) execOpcodeDDFD(opcode byte, iz *uint16) {
z.TStates += uint32(cyclesDDFD[opcode]) z.cycleCount += uint32(cyclesDDFD[opcode])
z.incR() z.incR()
switch opcode { switch opcode {
@ -15,9 +15,9 @@ func (z *CPU) execOpcodeDDFD(opcode byte, iz *uint16) {
z.PC = *iz z.PC = *iz
//z.jump(*iz) //z.jump(*iz)
case 0x09: case 0x09:
z.addIZ(iz, z.GetBC()) // add iz,bc z.addIZ(iz, z.bc()) // add iz,bc
case 0x19: case 0x19:
z.addIZ(iz, z.GetDE()) // add iz,de z.addIZ(iz, z.de()) // add iz,de
case 0x29: case 0x29:
z.addIZ(iz, *iz) // add iz,iz z.addIZ(iz, *iz) // add iz,iz
case 0x39: case 0x39:

View File

@ -4,7 +4,7 @@ import log "github.com/sirupsen/logrus"
// executes A ED opcode // executes A ED opcode
func (z *CPU) execOpcodeED(opcode byte) { func (z *CPU) execOpcodeED(opcode byte) {
z.TStates += uint32(cyclesED[opcode]) z.cycleCount += uint32(cyclesED[opcode])
z.incR() z.incR()
switch opcode { switch opcode {
case 0x47: case 0x47:
@ -41,9 +41,9 @@ func (z *CPU) execOpcodeED(opcode byte) {
{ {
z.ldi() z.ldi()
if z.GetBC() != 0 { if z.bc() != 0 {
z.PC -= 2 z.PC -= 2
z.TStates += 5 z.cycleCount += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
} }
} // ldir } // ldir
@ -54,9 +54,9 @@ func (z *CPU) execOpcodeED(opcode byte) {
{ {
z.ldd() z.ldd()
if z.GetBC() != 0 { if z.bc() != 0 {
z.PC -= 2 z.PC -= 2
z.TStates += 5 z.cycleCount += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
} }
} // lddr } // lddr
@ -68,9 +68,9 @@ func (z *CPU) execOpcodeED(opcode byte) {
case 0xB1: case 0xB1:
// cpir // cpir
z.cpi() z.cpi()
if z.GetBC() != 0 && !z.Flags.Z { if z.bc() != 0 && !z.Flags.Z {
z.PC -= 2 z.PC -= 2
z.TStates += 5 z.cycleCount += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
} else { } else {
//z.mem_ptr++ //z.mem_ptr++
@ -79,18 +79,18 @@ func (z *CPU) execOpcodeED(opcode byte) {
case 0xB9: case 0xB9:
// cpdr // cpdr
z.cpd() z.cpd()
if z.GetBC() != 0 && !z.Flags.Z { if z.bc() != 0 && !z.Flags.Z {
z.PC -= 2 z.PC -= 2
z.TStates += 5 z.cycleCount += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
} else { } else {
//z.mem_ptr++ //z.mem_ptr++
} }
case 0x40: case 0x40:
z.inRC(&z.B) // in b, (c) z.inRC(&z.B) // in b, (c)
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x48: case 0x48:
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
z.inRC(&z.C) // in c, (c) z.inRC(&z.C) // in c, (c)
z.updateXY(z.C) z.updateXY(z.C)
//case 0x4e: //case 0x4e:
@ -98,28 +98,28 @@ func (z *CPU) execOpcodeED(opcode byte) {
case 0x50: case 0x50:
z.inRC(&z.D) // in d, (c) z.inRC(&z.D) // in d, (c)
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x58: case 0x58:
// in e, (c) // in e, (c)
z.inRC(&z.E) z.inRC(&z.E)
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
z.updateXY(z.E) z.updateXY(z.E)
case 0x60: case 0x60:
z.inRC(&z.H) // in h, (c) z.inRC(&z.H) // in h, (c)
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x68: case 0x68:
z.inRC(&z.L) // in l, (c) z.inRC(&z.L) // in l, (c)
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
z.updateXY(z.L) z.updateXY(z.L)
case 0x70: case 0x70:
// in (c) // in (c)
var val byte var val byte
z.inRC(&val) z.inRC(&val)
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x78: case 0x78:
// in a, (c) // in a, (c)
z.inRC(&z.A) z.inRC(&z.A)
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
z.updateXY(z.A) z.updateXY(z.A)
case 0xA2: case 0xA2:
z.ini() // ini z.ini() // ini
@ -128,7 +128,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.ini() z.ini()
if z.B > 0 { if z.B > 0 {
z.PC -= 2 z.PC -= 2
z.TStates += 5 z.cycleCount += 5
} }
case 0xAA: case 0xAA:
// ind // ind
@ -138,33 +138,33 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.ind() z.ind()
if z.B > 0 { if z.B > 0 {
z.PC -= 2 z.PC -= 2
z.TStates += 5 z.cycleCount += 5
} }
case 0x41: case 0x41:
z.core.IOWrite(z.GetBC(), z.B) // out (c), b z.core.IOWrite(z.bc(), z.B) // out (c), b
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x49: case 0x49:
z.core.IOWrite(z.GetBC(), z.C) // out (c), c z.core.IOWrite(z.bc(), z.C) // out (c), c
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x51: case 0x51:
z.core.IOWrite(z.GetBC(), z.D) // out (c), d z.core.IOWrite(z.bc(), z.D) // out (c), d
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x59: case 0x59:
z.core.IOWrite(z.GetBC(), z.E) // out (c), e z.core.IOWrite(z.bc(), z.E) // out (c), e
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x61: case 0x61:
z.core.IOWrite(z.GetBC(), z.H) // out (c), h z.core.IOWrite(z.bc(), z.H) // out (c), h
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x69: case 0x69:
z.core.IOWrite(z.GetBC(), z.L) // out (c), l z.core.IOWrite(z.bc(), z.L) // out (c), l
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x71: case 0x71:
z.core.IOWrite(z.GetBC(), 0) // out (c), 0 z.core.IOWrite(z.bc(), 0) // out (c), 0
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0x79: case 0x79:
// out (c), a // out (c), a
z.core.IOWrite(z.GetBC(), z.A) z.core.IOWrite(z.bc(), z.A)
z.MemPtr = z.GetBC() + 1 z.MemPtr = z.bc() + 1
case 0xA3: case 0xA3:
z.outi() // outi z.outi() // outi
case 0xB3: case 0xB3:
@ -172,7 +172,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.outi() z.outi()
if z.B > 0 { if z.B > 0 {
z.PC -= 2 z.PC -= 2
z.TStates += 5 z.cycleCount += 5
} }
case 0xAB: case 0xAB:
z.outd() // outd z.outd() // outd
@ -180,40 +180,40 @@ func (z *CPU) execOpcodeED(opcode byte) {
// otdr // otdr
z.outd() z.outd()
if z.B > 0 { if z.B > 0 {
z.TStates += 5 z.cycleCount += 5
z.PC -= 2 z.PC -= 2
} }
case 0x42: case 0x42:
z.sbcHL(z.GetBC()) // sbc hl,bc z.sbcHL(z.bc()) // sbc hl,bc
case 0x52: case 0x52:
z.sbcHL(z.GetDE()) // sbc hl,de z.sbcHL(z.de()) // sbc hl,de
case 0x62: case 0x62:
z.sbcHL(z.GetHL()) // sbc hl,hl z.sbcHL(z.hl()) // sbc hl,hl
case 0x72: case 0x72:
z.sbcHL(z.SP) // sbc hl,sp z.sbcHL(z.SP) // sbc hl,sp
case 0x4A: case 0x4A:
z.adcHL(z.GetBC()) // adc hl,bc z.adcHL(z.bc()) // adc hl,bc
case 0x5A: case 0x5A:
z.adcHL(z.GetDE()) // adc hl,de z.adcHL(z.de()) // adc hl,de
case 0x6A: case 0x6A:
z.adcHL(z.GetHL()) // adc hl,hl z.adcHL(z.hl()) // adc hl,hl
case 0x7A: case 0x7A:
z.adcHL(z.SP) // adc hl,sp z.adcHL(z.SP) // adc hl,sp
case 0x43: case 0x43:
// ld (**), bc // ld (**), bc
addr := z.nextW() addr := z.nextW()
z.ww(addr, z.GetBC()) z.ww(addr, z.bc())
z.MemPtr = addr + 1 z.MemPtr = addr + 1
case 0x53: case 0x53:
// ld (**), de // ld (**), de
addr := z.nextW() addr := z.nextW()
z.ww(addr, z.GetDE()) z.ww(addr, z.de())
z.MemPtr = addr + 1 z.MemPtr = addr + 1
case 0x63: case 0x63:
// ld (**), hl // ld (**), hl
addr := z.nextW() addr := z.nextW()
z.ww(addr, z.GetHL()) z.ww(addr, z.hl())
z.MemPtr = addr + 1 z.MemPtr = addr + 1
case 0x73: case 0x73:
// ld (**), hl // ld (**), hl
@ -251,9 +251,9 @@ func (z *CPU) execOpcodeED(opcode byte) {
case 0x67: case 0x67:
// rrd // rrd
a := z.A a := z.A
val := z.rb(z.GetHL()) val := z.rb(z.hl())
z.A = (a & 0xF0) | (val & 0xF) 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.N = false
z.Flags.H = false z.Flags.H = false
@ -261,20 +261,20 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.Flags.Z = z.A == 0 z.Flags.Z = z.A == 0
z.Flags.S = z.A&0x80 != 0 z.Flags.S = z.A&0x80 != 0
z.Flags.P = parity(z.A) z.Flags.P = parity(z.A)
z.MemPtr = z.GetHL() + 1 z.MemPtr = z.hl() + 1
case 0x6F: case 0x6F:
// rld // rld
a := z.A a := z.A
val := z.rb(z.GetHL()) val := z.rb(z.hl())
z.A = (a & 0xF0) | (val >> 4) 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.N = false
z.Flags.H = false z.Flags.H = false
z.updateXY(z.A) z.updateXY(z.A)
z.Flags.Z = z.A == 0 z.Flags.Z = z.A == 0
z.Flags.S = z.A&0x80 != 0 z.Flags.S = z.A&0x80 != 0
z.Flags.P = parity(z.A) z.Flags.P = parity(z.A)
z.MemPtr = z.GetHL() + 1 z.MemPtr = z.hl() + 1
default: default:
log.Errorf("Unknown ED opcode: %02X\n", opcode) log.Errorf("Unknown ED opcode: %02X\n", opcode)
} }

View File

@ -43,11 +43,6 @@ type CPUInterface interface {
SetState(state *CPU) SetState(state *CPU)
// DebugOutput out current CPU state // DebugOutput out current CPU state
DebugOutput() DebugOutput()
// GenNMI Generate NMI
GenNMI()
// GenINT Generate INT,
// data - data bus low address for IM2 mode
GenINT(data byte)
} }
// FlagsType - Processor flags // FlagsType - Processor flags
@ -106,19 +101,17 @@ type CPU struct {
Iff1 bool `json:"iff1,omitempty"` Iff1 bool `json:"iff1,omitempty"`
Iff2 bool `json:"iff2,omitempty"` Iff2 bool `json:"iff2,omitempty"`
Halted bool `json:"halted,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 // mw hidden register
MemPtr uint16 MemPtr uint16
// methods to access CPU to memory and IO ports of computer // methods to access CPU to memory and IO ports of computer
core MemIoRW core MemIoRW
// Data-Bus state for IM2 INT
intData byte intData byte
// Total CPU cycle count (t-states) // Total CPU cycle count (t-states)
TStates uint32 cycleCount uint32
// map of memory access // map of memory access
memAccess map[uint16]byte memAccess map[uint16]byte
// enable or disable code coverage marking // enable or disable code coverage marking
@ -130,11 +123,8 @@ type CPU struct {
// map of stack data marking // map of stack data marking
extendedStack map[uint16]PushValueType extendedStack map[uint16]PushValueType
iffDelay byte iffDelay byte
// intPending is true if Interrupt is pending
intPending bool intPending bool
// nmiPending is true if Interrupt is pending
nmiPending bool nmiPending bool
} }
@ -241,23 +231,3 @@ func (f *FlagsType) SetFlags(flags byte) {
func (z *CPU) GetPC() uint16 { func (z *CPU) GetPC() uint16 {
return z.PC 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)
}

View File

@ -438,7 +438,9 @@ func setComputerState(test Z80TestIn) {
Iff1: test.state.IFF1, Iff1: test.state.IFF1,
Iff2: test.state.IFF2, Iff2: test.state.IFF2,
Halted: test.state.isHalted, Halted: test.state.isHalted,
TStatesPart: 0, CycleCount: 0,
IntOccurred: false,
NmiOccurred: false,
MemPtr: test.registers.MemPtr, 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) 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)
}
}