light cleanup and refactoring

This commit is contained in:
Роман Бойков 2026-04-20 16:39:17 +03:00
parent fec7798be9
commit c0d6642eab
7 changed files with 214 additions and 157 deletions

View File

@ -58,6 +58,7 @@ 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)
} }
@ -74,17 +75,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)
@ -178,7 +179,7 @@ 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.bc(), z.de(), z.hl(), z.SP, z.PC, (uint16(z.A)<<8)|uint16(z.f()), z.GetBC(), z.GetDE(), z.GetHL(), 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),

View File

@ -66,16 +66,16 @@ func (z *CPU) condJr(condition bool) {
} }
} }
func bToByte(cond bool) byte { func BToByte(cond bool) byte {
if cond { if cond {
return byte(1) return 1
} }
return byte(0) return 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)
@ -120,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.hl(), val, false) result := z.addW(z.GetHL(), val, false)
z.setHL(result) z.setHL(result)
z.Flags.S = sf z.Flags.S = sf
z.Flags.Z = zf z.Flags.Z = zf
@ -141,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.hl(), val, z.Flags.C) result := z.addW(z.GetHL(), 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)
@ -149,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.hl(), val, z.Flags.C) result := z.subW(z.GetHL(), 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)
@ -258,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
@ -272,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
@ -348,14 +348,14 @@ func (z *CPU) cbBit(val byte, n byte) byte {
} }
func (z *CPU) ldi() { func (z *CPU) ldi() {
de := z.de() de := z.GetDE()
hl := z.hl() hl := z.GetHL()
val := z.rb(hl) val := z.rb(hl)
z.wb(de, val) z.wb(de, val)
z.setHL(z.hl() + 1) z.setHL(z.GetHL() + 1)
z.setDE(z.de() + 1) z.setDE(z.GetDE() + 1)
z.setBC(z.bc() - 1) z.setBC(z.GetBC() - 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
@ -366,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.bc() > 0 z.Flags.P = z.GetBC() > 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.hl() - 2) z.setHL(z.GetHL() - 2)
z.setDE(z.de() - 2) z.setDE(z.GetDE() - 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.hl()), false) result := z.subB(z.A, z.rb(z.GetHL()), false)
z.setHL(z.hl() + 1) z.setHL(z.GetHL() + 1)
z.setBC(z.bc() - 1) z.setBC(z.GetBC() - 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.bc() != 0 z.Flags.P = z.GetBC() != 0
z.Flags.C = cf z.Flags.C = cf
z.MemPtr += 1 z.MemPtr += 1
} }
@ -394,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.hl() - 2) z.setHL(z.GetHL() - 2)
z.MemPtr -= 2 z.MemPtr -= 2
} }
func (z *CPU) inRC(r *byte) { func (z *CPU) inRC(r *byte) {
*r = z.core.IORead(z.bc()) *r = z.core.IORead(z.GetBC())
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)
@ -408,9 +408,9 @@ func (z *CPU) inRC(r *byte) {
} }
func (z *CPU) ini() { func (z *CPU) ini() {
val := z.core.IORead(z.bc()) val := z.core.IORead(z.GetBC())
z.wb(z.hl(), val) z.wb(z.GetHL(), val)
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
z.B-- z.B--
other := val + z.C + 1 other := val + z.C + 1
@ -426,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.hl() + 1) z.setHL(z.GetHL() + 1)
} }
func (z *CPU) ind() { func (z *CPU) ind() {
val := z.core.IORead(z.bc()) val := z.core.IORead(z.GetBC())
z.wb(z.hl(), val) z.wb(z.GetHL(), val)
z.MemPtr = z.bc() - 1 z.MemPtr = z.GetBC() - 1
z.B-- z.B--
other := val + z.C - 1 other := val + z.C - 1
@ -449,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.hl() - 1) z.setHL(z.GetHL() - 1)
} }
func (z *CPU) outCmnFlags(val uint8) { func (z *CPU) outCmnFlags(val uint8) {
other := val + z.L other := val + z.L
@ -468,20 +468,20 @@ func (z *CPU) outCmnFlags(val uint8) {
} }
func (z *CPU) outi() { func (z *CPU) outi() {
val := z.rb(z.hl()) val := z.rb(z.GetHL())
z.B-- z.B--
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
z.core.IOWrite(z.bc(), val) z.core.IOWrite(z.GetBC(), val)
z.setHL(z.hl() + 1) z.setHL(z.GetHL() + 1)
z.outCmnFlags(val) z.outCmnFlags(val)
} }
func (z *CPU) outd() { func (z *CPU) outd() {
val := z.rb(z.hl()) val := z.rb(z.GetHL())
z.B-- z.B--
z.MemPtr = z.bc() - 1 z.MemPtr = z.GetBC() - 1
z.core.IOWrite(z.bc(), val) z.core.IOWrite(z.GetBC(), val)
z.setHL(z.hl() - 1) z.setHL(z.GetHL() - 1)
z.outCmnFlags(val) z.outCmnFlags(val)
} }
@ -694,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.hl()) // ld a,(hl) z.A = z.rb(z.GetHL()) // ld a,(hl)
case 0x46: case 0x46:
z.B = z.rb(z.hl()) // ld b,(hl) z.B = z.rb(z.GetHL()) // ld b,(hl)
case 0x4E: case 0x4E:
z.C = z.rb(z.hl()) // ld c,(hl) z.C = z.rb(z.GetHL()) // ld c,(hl)
case 0x56: case 0x56:
z.D = z.rb(z.hl()) // ld d,(hl) z.D = z.rb(z.GetHL()) // ld d,(hl)
case 0x5E: case 0x5E:
z.E = z.rb(z.hl()) // ld e,(hl) z.E = z.rb(z.GetHL()) // ld e,(hl)
case 0x66: case 0x66:
z.H = z.rb(z.hl()) // ld h,(hl) z.H = z.rb(z.GetHL()) // ld h,(hl)
case 0x6E: case 0x6E:
z.L = z.rb(z.hl()) // ld l,(hl) z.L = z.rb(z.GetHL()) // ld l,(hl)
case 0x77: case 0x77:
z.wb(z.hl(), z.A) // ld (hl),a z.wb(z.GetHL(), z.A) // ld (hl),a
case 0x70: case 0x70:
z.wb(z.hl(), z.B) // ld (hl),b z.wb(z.GetHL(), z.B) // ld (hl),b
case 0x71: case 0x71:
z.wb(z.hl(), z.C) // ld (hl),c z.wb(z.GetHL(), z.C) // ld (hl),c
case 0x72: case 0x72:
z.wb(z.hl(), z.D) // ld (hl),d z.wb(z.GetHL(), z.D) // ld (hl),d
case 0x73: case 0x73:
z.wb(z.hl(), z.E) // ld (hl),e z.wb(z.GetHL(), z.E) // ld (hl),e
case 0x74: case 0x74:
z.wb(z.hl(), z.H) // ld (hl),h z.wb(z.GetHL(), z.H) // ld (hl),h
case 0x75: case 0x75:
z.wb(z.hl(), z.L) // ld (hl),l z.wb(z.GetHL(), z.L) // ld (hl),l
case 0x3E: case 0x3E:
z.A = z.nextB() // ld a,* z.A = z.nextB() // ld a,*
@ -738,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.hl(), z.nextB()) // ld (hl),* z.wb(z.GetHL(), z.nextB()) // ld (hl),*
case 0x0A: case 0x0A:
// ld a,(bc) // ld a,(bc)
z.A = z.rb(z.bc()) z.A = z.rb(z.GetBC())
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x1A: case 0x1A:
// ld a,(de) // ld a,(de)
z.A = z.rb(z.de()) z.A = z.rb(z.GetDE())
z.MemPtr = z.de() + 1 z.MemPtr = z.GetDE() + 1
case 0x3A: case 0x3A:
// ld a,(**) // ld a,(**)
addr := z.nextW() addr := z.nextW()
@ -754,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.bc(), z.A) z.wb(z.GetBC(), z.A)
z.MemPtr = (uint16(z.A) << 8) | ((z.bc() + 1) & 0xFF) z.MemPtr = (uint16(z.A) << 8) | ((z.GetBC() + 1) & 0xFF)
case 0x12: case 0x12:
// ld (de),a // ld (de),a
z.wb(z.de(), z.A) z.wb(z.GetDE(), z.A)
z.MemPtr = (uint16(z.A) << 8) | ((z.de() + 1) & 0xFF) z.MemPtr = (uint16(z.A) << 8) | ((z.GetDE() + 1) & 0xFF)
case 0x32: case 0x32:
// ld (**),a // ld (**),a
addr := z.nextW() addr := z.nextW()
@ -782,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.hl()) z.ww(addr, z.GetHL())
z.MemPtr = addr + 1 z.MemPtr = addr + 1
case 0xF9: case 0xF9:
z.SP = z.hl() // ld sp,hl z.SP = z.GetHL() // ld sp,hl
case 0xEB: case 0xEB:
// ex de,hl // ex de,hl
de := z.de() de := z.GetDE()
z.setDE(z.hl()) z.setDE(z.GetHL())
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.hl()) z.ww(z.SP, z.GetHL())
z.setHL(val) z.setHL(val)
z.MemPtr = val z.MemPtr = val
case 0x87: case 0x87:
@ -813,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.hl()), false) // add a,(hl) z.A = z.addB(z.A, z.rb(z.GetHL()), 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,*
@ -832,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.hl()), z.Flags.C) // adc a,(hl) z.A = z.addB(z.A, z.rb(z.GetHL()), 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,*
@ -851,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.hl()), false) // sub a,(hl) z.A = z.subB(z.A, z.rb(z.GetHL()), 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,*
@ -870,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.hl()), z.Flags.C) // sbc a,(hl) z.A = z.subB(z.A, z.rb(z.GetHL()), 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.bc()) // add hl,bc z.addHL(z.GetBC()) // add hl,bc
case 0x19: case 0x19:
z.addHL(z.de()) // add hl,de z.addHL(z.GetDE()) // add hl,de
case 0x29: case 0x29:
z.addHL(z.hl()) // add hl,hl z.addHL(z.GetHL()) // add hl,hl
case 0x39: case 0x39:
z.addHL(z.SP) // add hl,sp z.addHL(z.SP) // add hl,sp
@ -908,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.hl())) result := z.inc(z.rb(z.GetHL()))
z.wb(z.hl(), result) z.wb(z.GetHL(), 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:
@ -926,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.hl())) result := z.dec(z.rb(z.GetHL()))
z.wb(z.hl(), result) z.wb(z.GetHL(), result)
case 0x03: case 0x03:
z.setBC(z.bc() + 1) // inc bc z.setBC(z.GetBC() + 1) // inc bc
case 0x13: case 0x13:
z.setDE(z.de() + 1) // inc de z.setDE(z.GetDE() + 1) // inc de
case 0x23: case 0x23:
z.setHL(z.hl() + 1) // inc hl z.setHL(z.GetHL() + 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.bc() - 1) // dec bc z.setBC(z.GetBC() - 1) // dec bc
case 0x1B: case 0x1B:
z.setDE(z.de() - 1) // dec de z.setDE(z.GetDE() - 1) // dec de
case 0x2B: case 0x2B:
z.setHL(z.hl() - 1) // dec hl z.setHL(z.GetHL() - 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:
@ -967,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
@ -988,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
@ -1009,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.hl())) // and (hl) z.lAnd(z.rb(z.GetHL())) // and (hl)
case 0xE6: case 0xE6:
z.lAnd(z.nextB()) // and * z.lAnd(z.nextB()) // and *
@ -1028,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.hl())) // xor (hl) z.lXor(z.rb(z.GetHL())) // xor (hl)
case 0xEE: case 0xEE:
z.lXor(z.nextB()) // xor * z.lXor(z.nextB()) // xor *
@ -1047,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.hl())) // or (hl) z.lOr(z.rb(z.GetHL())) // or (hl)
case 0xF6: case 0xF6:
z.lOr(z.nextB()) // or * z.lOr(z.nextB()) // or *
@ -1066,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.hl())) // cp (hl) z.cp(z.rb(z.GetHL())) // cp (hl)
case 0xFE: case 0xFE:
z.cp(z.nextB()) // cp * z.cp(z.nextB()) // cp *
@ -1111,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.hl() // jp (hl) z.PC = z.GetHL() // jp (hl)
case 0xCD: case 0xCD:
z.call(z.nextW()) // call z.call(z.nextW()) // call
@ -1176,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.bc()) // push bc z.pushW(z.GetBC()) // push bc
case 0xD5: case 0xD5:
z.pushW(z.de()) // push de z.pushW(z.GetDE()) // push de
case 0xE5: case 0xE5:
z.pushW(z.hl()) // push hl z.pushW(z.GetHL()) // 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

@ -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.hl()) hl = z.rb(z.GetHL())
reg = &hl reg = &hl
case 7: case 7:
reg = &z.A reg = &z.A
@ -78,7 +78,7 @@ func (z *CPU) execOpcodeCB(opcode byte) {
} }
if reg == &hl { if reg == &hl {
z.wb(z.hl(), hl) z.wb(z.GetHL(), 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.hl(), result) // z.wb(z.GetHL(), result)
case 7: case 7:
z.A = result z.A = result
} }

View File

@ -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.bc()) // add iz,bc z.addIZ(iz, z.GetBC()) // add iz,bc
case 0x19: case 0x19:
z.addIZ(iz, z.de()) // add iz,de z.addIZ(iz, z.GetDE()) // 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

@ -41,7 +41,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
{ {
z.ldi() z.ldi()
if z.bc() != 0 { if z.GetBC() != 0 {
z.PC -= 2 z.PC -= 2
z.cycleCount += 5 z.cycleCount += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
@ -54,7 +54,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
{ {
z.ldd() z.ldd()
if z.bc() != 0 { if z.GetBC() != 0 {
z.PC -= 2 z.PC -= 2
z.cycleCount += 5 z.cycleCount += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
@ -68,7 +68,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
case 0xB1: case 0xB1:
// cpir // cpir
z.cpi() z.cpi()
if z.bc() != 0 && !z.Flags.Z { if z.GetBC() != 0 && !z.Flags.Z {
z.PC -= 2 z.PC -= 2
z.cycleCount += 5 z.cycleCount += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
@ -79,7 +79,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
case 0xB9: case 0xB9:
// cpdr // cpdr
z.cpd() z.cpd()
if z.bc() != 0 && !z.Flags.Z { if z.GetBC() != 0 && !z.Flags.Z {
z.PC -= 2 z.PC -= 2
z.cycleCount += 5 z.cycleCount += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
@ -88,9 +88,9 @@ func (z *CPU) execOpcodeED(opcode byte) {
} }
case 0x40: case 0x40:
z.inRC(&z.B) // in b, (c) z.inRC(&z.B) // in b, (c)
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x48: case 0x48:
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 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.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x58: case 0x58:
// in e, (c) // in e, (c)
z.inRC(&z.E) z.inRC(&z.E)
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 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.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x68: case 0x68:
z.inRC(&z.L) // in l, (c) z.inRC(&z.L) // in l, (c)
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 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.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x78: case 0x78:
// in a, (c) // in a, (c)
z.inRC(&z.A) z.inRC(&z.A)
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
z.updateXY(z.A) z.updateXY(z.A)
case 0xA2: case 0xA2:
z.ini() // ini z.ini() // ini
@ -141,30 +141,30 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.cycleCount += 5 z.cycleCount += 5
} }
case 0x41: case 0x41:
z.core.IOWrite(z.bc(), z.B) // out (c), b z.core.IOWrite(z.GetBC(), z.B) // out (c), b
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x49: case 0x49:
z.core.IOWrite(z.bc(), z.C) // out (c), c z.core.IOWrite(z.GetBC(), z.C) // out (c), c
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x51: case 0x51:
z.core.IOWrite(z.bc(), z.D) // out (c), d z.core.IOWrite(z.GetBC(), z.D) // out (c), d
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x59: case 0x59:
z.core.IOWrite(z.bc(), z.E) // out (c), e z.core.IOWrite(z.GetBC(), z.E) // out (c), e
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x61: case 0x61:
z.core.IOWrite(z.bc(), z.H) // out (c), h z.core.IOWrite(z.GetBC(), z.H) // out (c), h
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x69: case 0x69:
z.core.IOWrite(z.bc(), z.L) // out (c), l z.core.IOWrite(z.GetBC(), z.L) // out (c), l
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x71: case 0x71:
z.core.IOWrite(z.bc(), 0) // out (c), 0 z.core.IOWrite(z.GetBC(), 0) // out (c), 0
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0x79: case 0x79:
// out (c), a // out (c), a
z.core.IOWrite(z.bc(), z.A) z.core.IOWrite(z.GetBC(), z.A)
z.MemPtr = z.bc() + 1 z.MemPtr = z.GetBC() + 1
case 0xA3: case 0xA3:
z.outi() // outi z.outi() // outi
case 0xB3: case 0xB3:
@ -185,35 +185,35 @@ func (z *CPU) execOpcodeED(opcode byte) {
} }
case 0x42: case 0x42:
z.sbcHL(z.bc()) // sbc hl,bc z.sbcHL(z.GetBC()) // sbc hl,bc
case 0x52: case 0x52:
z.sbcHL(z.de()) // sbc hl,de z.sbcHL(z.GetDE()) // sbc hl,de
case 0x62: case 0x62:
z.sbcHL(z.hl()) // sbc hl,hl z.sbcHL(z.GetHL()) // 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.bc()) // adc hl,bc z.adcHL(z.GetBC()) // adc hl,bc
case 0x5A: case 0x5A:
z.adcHL(z.de()) // adc hl,de z.adcHL(z.GetDE()) // adc hl,de
case 0x6A: case 0x6A:
z.adcHL(z.hl()) // adc hl,hl z.adcHL(z.GetHL()) // 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.bc()) z.ww(addr, z.GetBC())
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.de()) z.ww(addr, z.GetDE())
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.hl()) z.ww(addr, z.GetHL())
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.hl()) val := z.rb(z.GetHL())
z.A = (a & 0xF0) | (val & 0xF) z.A = (a & 0xF0) | (val & 0xF)
z.wb(z.hl(), (val>>4)|(a<<4)) z.wb(z.GetHL(), (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.hl() + 1 z.MemPtr = z.GetHL() + 1
case 0x6F: case 0x6F:
// rld // rld
a := z.A a := z.A
val := z.rb(z.hl()) val := z.rb(z.GetHL())
z.A = (a & 0xF0) | (val >> 4) z.A = (a & 0xF0) | (val >> 4)
z.wb(z.hl(), (val<<4)|(a&0xF)) z.wb(z.GetHL(), (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.hl() + 1 z.MemPtr = z.GetHL() + 1
default: default:
log.Errorf("Unknown ED opcode: %02X\n", opcode) log.Errorf("Unknown ED opcode: %02X\n", opcode)
} }

View File

@ -43,6 +43,11 @@ 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
@ -231,3 +236,23 @@ 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

@ -613,3 +613,34 @@ 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)
}
}