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

27
cpu.go
View File

@ -14,7 +14,7 @@ func NewCPU(core MemIoRW) *CPU {
z := CPU{}
z.Reset()
z.core = core
z.cycleCount = 0
z.TStates = 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.cycleCount
pre := z.TStates
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.cycleCount - pre, &z.memAccess
return z.TStates - pre, &z.memAccess
}
// SetState set current CPU state
@ -71,14 +71,18 @@ 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.IntOccurred = state.IntOccurred
z.NmiOccurred = false
z.intData = state.intData
z.intPending = state.intPending
z.nmiPending = state.nmiPending
}
func (z *CPU) GetState() *CPU {
return &CPU{
A: z.A,
@ -109,17 +113,16 @@ func (z *CPU) GetState() *CPU {
Iff1: z.Iff1,
Iff2: z.Iff2,
Halted: z.Halted,
CycleCount: z.cycleCount,
IntOccurred: z.IntOccurred,
NmiOccurred: z.NmiOccurred,
TStatesPart: z.TStatesPart,
TStates: z.TStates,
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)

View File

@ -183,11 +183,11 @@ func (z *CPU) DebugOutput() {
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.cycleCount)
z.rb(z.PC+2), z.rb(z.PC+3), z.TStates)
}
func (z *CPU) Reset() {
z.cycleCount = 0
z.TStates = 0
z.PC = 0
z.SP = 0xFFFF
z.IX = 0
@ -221,7 +221,5 @@ func (z *CPU) Reset() {
z.Iff1 = false
z.Iff2 = false
z.Halted = false
z.IntOccurred = false
z.NmiOccurred = false
z.intData = 0
}

View File

@ -30,7 +30,7 @@ func (z *CPU) condCall(condition bool) {
addr := z.nextW()
if condition {
z.call(addr)
z.cycleCount += 7
z.TStates += 7
}
z.MemPtr = addr
}
@ -45,7 +45,7 @@ func (z *CPU) ret() {
func (z *CPU) condRet(condition bool) {
if condition {
z.ret()
z.cycleCount += 6
z.TStates += 6
}
}
@ -62,7 +62,7 @@ func (z *CPU) condJr(condition bool) {
b := z.nextB()
if condition {
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 {
lsb := z.addB(byte(a), byte(b), cy)
msb := z.addB(byte(a>>8), byte(b>>8), z.Flags.C)
result := (uint16(msb) << 8) | uint16(lsb)
z.Flags.Z = result == 0
z.MemPtr = a + 1
return result
return z.addSubRes(a, msb, lsb)
}
// 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
@ -174,39 +175,25 @@ 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) {
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
z.lCmn(z.A&val, true)
}
// executes A logic "xor" between register A and A byte, then stores the
// result in register A
func (z *CPU) lXor(val byte) {
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
z.lCmn(z.A^val, false)
}
// executes A logic "or" between register A and A byte, then stores the
// result in register A
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.Z = result == 0
z.Flags.H = false
z.Flags.H = hf
z.Flags.P = parity(result)
z.Flags.N = false
z.Flags.C = false
@ -217,11 +204,6 @@ func (z *CPU) lOr(val byte) {
// 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)
}
@ -538,31 +520,37 @@ func (z *CPU) processInterrupts() {
if z.nmiPending {
z.nmiPending = false
z.Halted = false
if z.Halted {
z.PC++
z.Halted = false
}
z.Iff1 = false
z.incR()
z.cycleCount += 11
z.TStates += 11
z.call(0x0066)
return
}
if z.intPending && z.Iff1 {
z.intPending = false
z.Halted = false
if z.Halted {
z.PC++
z.Halted = false
}
z.Iff1 = false
z.Iff2 = false
z.incR()
switch z.IMode {
case 0:
z.cycleCount += 11
z.TStates += 11
z.execOpcode(z.intData)
case 1:
z.cycleCount += 13
z.TStates += 13
z.call(0x38)
case 2:
z.cycleCount += 19
z.TStates += 19
z.call(z.rw((uint16(z.I) << 8) | uint16(z.intData)))
default:
log.Errorf("Unsupported interrupt mode %d\n", z.IMode)
@ -584,7 +572,7 @@ func (z *CPU) GenINT(data byte) {
// executes A non-prefixed opcode
func (z *CPU) execOpcode(opcode byte) {
z.cycleCount += uint32(cycles00[opcode])
z.TStates += uint32(cycles00[opcode])
z.incR()
switch opcode {

View File

@ -4,7 +4,7 @@ import log "github.com/sirupsen/logrus"
// executes A CB opcode
func (z *CPU) execOpcodeCB(opcode byte) {
z.cycleCount += 8
z.TStates += 8
z.incR()
// 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:
if z_ == 6 {
z.updateXY(byte(z.MemPtr >> 8))
z.cycleCount += 4
z.TStates += 4
}
case 2:
@ -74,7 +74,7 @@ func (z *CPU) execOpcodeCB(opcode byte) {
}
if (x_ == 0 || x_ == 2 || x_ == 3) && z_ == 6 {
z.cycleCount += 7
z.TStates += 7
}
if reg == &hl {
@ -154,9 +154,9 @@ func (z *CPU) execOpcodeDcb(opcode byte, addr uint16) {
if x_ == 1 {
// bit instructions take 20 cycles, others take 23
z.cycleCount += 20
z.TStates += 20
} else {
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)
func (z *CPU) execOpcodeDDFD(opcode byte, iz *uint16) {
z.cycleCount += uint32(cyclesDDFD[opcode])
z.TStates += uint32(cyclesDDFD[opcode])
z.incR()
switch opcode {

View File

@ -4,7 +4,7 @@ import log "github.com/sirupsen/logrus"
// executes A ED opcode
func (z *CPU) execOpcodeED(opcode byte) {
z.cycleCount += uint32(cyclesED[opcode])
z.TStates += uint32(cyclesED[opcode])
z.incR()
switch opcode {
case 0x47:
@ -43,7 +43,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
if z.GetBC() != 0 {
z.PC -= 2
z.cycleCount += 5
z.TStates += 5
z.MemPtr = z.PC + 1
}
} // ldir
@ -56,7 +56,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
if z.GetBC() != 0 {
z.PC -= 2
z.cycleCount += 5
z.TStates += 5
z.MemPtr = z.PC + 1
}
} // lddr
@ -70,7 +70,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.cpi()
if z.GetBC() != 0 && !z.Flags.Z {
z.PC -= 2
z.cycleCount += 5
z.TStates += 5
z.MemPtr = z.PC + 1
} else {
//z.mem_ptr++
@ -81,7 +81,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.cpd()
if z.GetBC() != 0 && !z.Flags.Z {
z.PC -= 2
z.cycleCount += 5
z.TStates += 5
z.MemPtr = z.PC + 1
} else {
//z.mem_ptr++
@ -128,7 +128,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.ini()
if z.B > 0 {
z.PC -= 2
z.cycleCount += 5
z.TStates += 5
}
case 0xAA:
// ind
@ -138,7 +138,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.ind()
if z.B > 0 {
z.PC -= 2
z.cycleCount += 5
z.TStates += 5
}
case 0x41:
z.core.IOWrite(z.GetBC(), z.B) // out (c), b
@ -172,7 +172,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
z.outi()
if z.B > 0 {
z.PC -= 2
z.cycleCount += 5
z.TStates += 5
}
case 0xAB:
z.outd() // outd
@ -180,7 +180,7 @@ func (z *CPU) execOpcodeED(opcode byte) {
// otdr
z.outd()
if z.B > 0 {
z.cycleCount += 5
z.TStates += 5
z.PC -= 2
}

View File

@ -106,17 +106,19 @@ type CPU struct {
Iff1 bool `json:"iff1,omitempty"`
Iff2 bool `json:"iff2,omitempty"`
Halted bool `json:"halted,omitempty"`
CycleCount uint32 `json:"cycleCount,omitempty"`
IntOccurred bool `json:"intOccurred,omitempty"`
NmiOccurred bool `json:"interruptOccurred,omitempty"`
TStatesPart uint32 `json:"TStatesPart,omitempty"`
// mw hidden register
MemPtr uint16
// methods to access CPU to memory and IO ports of computer
core MemIoRW
core MemIoRW
// Data-Bus state for IM2 INT
intData byte
// Total CPU cycle count (t-states)
cycleCount uint32
TStates uint32
// map of memory access
memAccess map[uint16]byte
// enable or disable code coverage marking
@ -128,8 +130,11 @@ type CPU struct {
// map of stack data marking
extendedStack map[uint16]PushValueType
iffDelay byte
iffDelay byte
// intPending is true if Interrupt is pending
intPending bool
// nmiPending is true if Interrupt is pending
nmiPending bool
}

View File

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