mirror of
https://github.com/romychs/z80go.git
synced 2026-05-08 10:44:06 +03:00
try to fix reti
This commit is contained in:
parent
c0d6642eab
commit
57b18ccda0
27
cpu.go
27
cpu.go
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
62
opcodes.go
62
opcodes.go
@ -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
|
||||
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
|
||||
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 {
|
||||
|
||||
10
opcodesCB.go
10
opcodesCB.go
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
18
opcodesED.go
18
opcodesED.go
@ -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
|
||||
}
|
||||
|
||||
|
||||
13
z80go.go
13
z80go.go
@ -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
|
||||
|
||||
// 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
|
||||
@ -129,7 +131,10 @@ type CPU struct {
|
||||
extendedStack map[uint16]PushValueType
|
||||
|
||||
iffDelay byte
|
||||
// intPending is true if Interrupt is pending
|
||||
intPending bool
|
||||
|
||||
// nmiPending is true if Interrupt is pending
|
||||
nmiPending bool
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user