try to fix reti

This commit is contained in:
Роман Бойков 2026-04-23 22:41:11 +03:00
parent c0d6642eab
commit 57b18ccda0
8 changed files with 71 additions and 79 deletions

29
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.cycleCount = 0 z.TStates = 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.cycleCount pre := z.TStates
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.cycleCount - pre, &z.memAccess return z.TStates - pre, &z.memAccess
} }
// SetState set current CPU state // SetState set current CPU state
@ -71,14 +71,18 @@ 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.IntOccurred = state.IntOccurred z.intData = state.intData
z.NmiOccurred = false z.intPending = state.intPending
z.nmiPending = state.nmiPending
} }
func (z *CPU) GetState() *CPU { func (z *CPU) GetState() *CPU {
return &CPU{ return &CPU{
A: z.A, A: z.A,
@ -109,16 +113,15 @@ func (z *CPU) GetState() *CPU {
Iff1: z.Iff1, Iff1: z.Iff1,
Iff2: z.Iff2, Iff2: z.Iff2,
Halted: z.Halted, Halted: z.Halted,
CycleCount: z.cycleCount, TStatesPart: z.TStatesPart,
IntOccurred: z.IntOccurred, TStates: z.TStates,
NmiOccurred: z.NmiOccurred,
MemPtr: z.MemPtr, MemPtr: z.MemPtr,
}
}
//func (z *CPU) PC() uint16 { intData: z.intData,
// return z.PC intPending: z.intPending,
//} nmiPending: z.nmiPending,
}
}
// ClearCodeCoverage - clears code coverage journal // ClearCodeCoverage - clears code coverage journal
func (z *CPU) ClearCodeCoverage() { func (z *CPU) ClearCodeCoverage() {

View File

@ -183,11 +183,11 @@ func (z *CPU) DebugOutput() {
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.cycleCount) z.rb(z.PC+2), z.rb(z.PC+3), z.TStates)
} }
func (z *CPU) Reset() { func (z *CPU) Reset() {
z.cycleCount = 0 z.TStates = 0
z.PC = 0 z.PC = 0
z.SP = 0xFFFF z.SP = 0xFFFF
z.IX = 0 z.IX = 0
@ -221,7 +221,5 @@ 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.cycleCount += 7 z.TStates += 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.cycleCount += 6 z.TStates += 6
} }
} }
@ -62,7 +62,7 @@ func (z *CPU) condJr(condition bool) {
b := z.nextB() b := z.nextB()
if condition { if condition {
z.jr(b) z.jr(b)
z.cycleCount += 5 z.TStates += 5
} }
} }
@ -99,16 +99,17 @@ 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)
result := (uint16(msb) << 8) | uint16(lsb) return z.addSubRes(a, msb, 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
@ -174,39 +175,25 @@ 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) {
result := z.A & val z.lCmn(z.A&val, true)
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) {
result := z.A ^ val z.lCmn(z.A^val, false)
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) {
result := z.A | val z.lCmn(z.A|val, false)
}
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 = false z.Flags.H = hf
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
@ -217,11 +204,6 @@ func (z *CPU) lOr(val byte) {
// 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)
} }
@ -538,31 +520,37 @@ func (z *CPU) processInterrupts() {
if z.nmiPending { if z.nmiPending {
z.nmiPending = false z.nmiPending = false
if z.Halted {
z.PC++
z.Halted = false z.Halted = false
}
z.Iff1 = false z.Iff1 = false
z.incR() z.incR()
z.cycleCount += 11 z.TStates += 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.PC++
z.Halted = false 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.cycleCount += 11 z.TStates += 11
z.execOpcode(z.intData) z.execOpcode(z.intData)
case 1: case 1:
z.cycleCount += 13 z.TStates += 13
z.call(0x38) z.call(0x38)
case 2: case 2:
z.cycleCount += 19 z.TStates += 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)
@ -584,7 +572,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.cycleCount += uint32(cycles00[opcode]) z.TStates += uint32(cycles00[opcode])
z.incR() z.incR()
switch opcode { switch opcode {

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.cycleCount += 8 z.TStates += 8
z.incR() z.incR()
// decoding instructions from http://z80.info/decoding.htm#cb // decoding instructions from http://z80.info/decoding.htm#cb
@ -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.cycleCount += 4 z.TStates += 4
} }
case 2: case 2:
@ -74,7 +74,7 @@ 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.cycleCount += 7 z.TStates += 7
} }
if reg == &hl { if reg == &hl {
@ -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.cycleCount += 20 z.TStates += 20
} else { } else {
z.wb(addr, result) z.wb(addr, result)
z.cycleCount += 23 z.TStates += 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.cycleCount += uint32(cyclesDDFD[opcode]) z.TStates += uint32(cyclesDDFD[opcode])
z.incR() z.incR()
switch opcode { switch opcode {

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.cycleCount += uint32(cyclesED[opcode]) z.TStates += uint32(cyclesED[opcode])
z.incR() z.incR()
switch opcode { switch opcode {
case 0x47: case 0x47:
@ -43,7 +43,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
if z.GetBC() != 0 { if z.GetBC() != 0 {
z.PC -= 2 z.PC -= 2
z.cycleCount += 5 z.TStates += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
} }
} // ldir } // ldir
@ -56,7 +56,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
if z.GetBC() != 0 { if z.GetBC() != 0 {
z.PC -= 2 z.PC -= 2
z.cycleCount += 5 z.TStates += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
} }
} // lddr } // lddr
@ -70,7 +70,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.cpi() z.cpi()
if z.GetBC() != 0 && !z.Flags.Z { if z.GetBC() != 0 && !z.Flags.Z {
z.PC -= 2 z.PC -= 2
z.cycleCount += 5 z.TStates += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
} else { } else {
//z.mem_ptr++ //z.mem_ptr++
@ -81,7 +81,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.cpd() z.cpd()
if z.GetBC() != 0 && !z.Flags.Z { if z.GetBC() != 0 && !z.Flags.Z {
z.PC -= 2 z.PC -= 2
z.cycleCount += 5 z.TStates += 5
z.MemPtr = z.PC + 1 z.MemPtr = z.PC + 1
} else { } else {
//z.mem_ptr++ //z.mem_ptr++
@ -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.cycleCount += 5 z.TStates += 5
} }
case 0xAA: case 0xAA:
// ind // ind
@ -138,7 +138,7 @@ 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.cycleCount += 5 z.TStates += 5
} }
case 0x41: case 0x41:
z.core.IOWrite(z.GetBC(), z.B) // out (c), b z.core.IOWrite(z.GetBC(), z.B) // out (c), b
@ -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.cycleCount += 5 z.TStates += 5
} }
case 0xAB: case 0xAB:
z.outd() // outd z.outd() // outd
@ -180,7 +180,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
// otdr // otdr
z.outd() z.outd()
if z.B > 0 { if z.B > 0 {
z.cycleCount += 5 z.TStates += 5
z.PC -= 2 z.PC -= 2
} }

View File

@ -106,17 +106,19 @@ 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"`
CycleCount uint32 `json:"cycleCount,omitempty"` TStatesPart uint32 `json:"TStatesPart,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)
cycleCount uint32 TStates 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
@ -129,7 +131,10 @@ type CPU struct {
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
} }

View File

@ -438,9 +438,7 @@ 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,
CycleCount: 0, TStatesPart: 0,
IntOccurred: false,
NmiOccurred: false,
MemPtr: test.registers.MemPtr, MemPtr: test.registers.MemPtr,
} }