diff --git a/main.go b/main.go index c6898ee..ddb1fab 100644 --- a/main.go +++ b/main.go @@ -157,7 +157,7 @@ func screen(computer *okean240.ComputerType, raster *canvas.Raster, label *widge } } -const ticksPerTact uint64 = 3 +const ticksPerTact uint64 = 4 func emulator(computer *okean240.ComputerType) { ticker := time.NewTicker(66 * time.Nanosecond) @@ -174,7 +174,7 @@ func emulator(computer *okean240.ComputerType) { computer.Do() } else { if ticks >= nextClock { - nextClock = ticks + computer.Do()*ticksPerTact + nextClock = ticks + uint64(computer.Do())*ticksPerTact } } //computer.Do() diff --git a/okean240/computer.go b/okean240/computer.go index 03e8a55..14a97ea 100644 --- a/okean240/computer.go +++ b/okean240/computer.go @@ -114,9 +114,9 @@ func (c *ComputerType) Reset() { } -func (c *ComputerType) Do() uint64 { +func (c *ComputerType) Do() uint32 { ticks := c.cpu.RunInstruction() - c.cycles += ticks + c.cycles += uint64(ticks) //pc := c.cpu.GetState().PC //if pc >= 0xfea3 && pc <= 0xff25 { // c.cpu.DebugOutput() diff --git a/z80/c99/constants.go b/z80/c99/constants.go index 8f10c32..fa34a5c 100644 --- a/z80/c99/constants.go +++ b/z80/c99/constants.go @@ -1,6 +1,6 @@ package c99 -var cyc_00 = [256]byte{ +var cycles00 = [256]byte{ 4, 10, 7, 6, 4, 4, 7, 4, 4, 11, 7, 6, 4, 4, 7, 4, 8, 10, 7, 6, 4, 4, 7, 4, 12, 11, 7, 6, 4, 4, 7, 4, 7, 10, 16, 6, 4, 4, 7, 4, 7, 11, 16, 6, 4, 4, 7, 4, @@ -19,7 +19,7 @@ var cyc_00 = [256]byte{ 5, 10, 10, 4, 10, 11, 7, 11, 5, 6, 10, 4, 10, 0, 7, 11, } -var cyc_ed = [256]byte{ +var cyclesED = [256]byte{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, @@ -38,7 +38,7 @@ var cyc_ed = [256]byte{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, } -var cyc_ddfd = [256]byte{ +var cyclesDDFD = [256]byte{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 15, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 15, 4, 4, 4, 4, 4, 4, 4, 14, 20, 10, 8, 8, 11, 4, 4, 15, 20, 10, 8, 8, 11, 4, diff --git a/z80/c99/cpu.go b/z80/c99/cpu.go index d9e7f3a..3a43a84 100644 --- a/z80/c99/cpu.go +++ b/z80/c99/cpu.go @@ -5,14 +5,13 @@ import "okemu/z80" type Z80 struct { // cycle count (t-states) - cyc uint64 - inst_cyc byte + cycleCount uint32 // special purpose registers pc, sp, ix, iy uint16 // "wz" register - mem_ptr uint16 + memPtr uint16 // main registers a, b, c, d, e, h, l byte @@ -25,14 +24,14 @@ type Z80 struct { // flags: sign, zero, yf, half-carry, xf, parity/overflow, negative, carry sf, zf, yf, hf, xf, pf, nf, cf bool - iff_delay byte - interrupt_mode byte - int_data byte + iffDelay byte + interruptMode byte + intData byte iff1 bool iff2 bool - halted bool - int_pending bool - nmi_pending bool + isHalted bool + intPending bool + nmiPending bool core z80.MemIoRW } @@ -42,16 +41,14 @@ func New(core z80.MemIoRW) *Z80 { z := Z80{} z.core = core - z.cyc = 0 + z.cycleCount = 0 z.pc = 0 z.sp = 0xFFFF z.ix = 0 z.iy = 0 - z.mem_ptr = 0 + z.memPtr = 0 - // af and sp are set to 0xFFFF after reset, - // and the other values are undefined (z80-documented) z.a = 0xFF z.b = 0 z.c = 0 @@ -81,32 +78,32 @@ func New(core z80.MemIoRW) *Z80 { z.nf = true z.cf = true - z.iff_delay = 0 - z.interrupt_mode = 0 + z.iffDelay = 0 + z.interruptMode = 0 z.iff1 = false z.iff2 = false - z.halted = false - z.int_pending = false - z.nmi_pending = false - z.int_data = 0 + z.isHalted = false + z.intPending = false + z.nmiPending = false + z.intData = 0 return &z } // RunInstruction executes the next instruction in memory + handles interrupts -func (z *Z80) RunInstruction() uint64 { - pre := z.cyc - if z.halted { - z.exec_opcode(0x00) +func (z *Z80) RunInstruction() uint32 { + pre := z.cycleCount + if z.isHalted { + z.execOpcode(0x00) } else { - opcode := z.nextb() - z.exec_opcode(opcode) + opcode := z.nextB() + z.execOpcode(opcode) } - z.process_interrupts() - return z.cyc - pre + z.processInterrupts() + return z.cycleCount - pre } func (z *Z80) SetState(state *z80.Z80CPU) { - z.cyc = 0 + z.cycleCount = 0 z.a = state.A z.b = state.B z.c = state.C @@ -129,7 +126,7 @@ func (z *Z80) SetState(state *z80.Z80CPU) { z.iy = state.IY z.i = state.I z.r = state.R - z.mem_ptr = state.MemPtr + z.memPtr = state.MemPtr z.sf = state.Flags.S z.zf = state.Flags.Z @@ -143,13 +140,13 @@ func (z *Z80) SetState(state *z80.Z80CPU) { z.f_ = state.FlagsAlt.GetFlags() //z.iff_delay = 0 - z.interrupt_mode = state.IMode + z.interruptMode = state.IMode z.iff1 = state.Iff1 z.iff2 = state.Iff2 - z.halted = state.Halted - z.int_pending = state.InterruptOccurred - z.nmi_pending = false - z.int_data = 0 + z.isHalted = state.Halted + z.intPending = state.InterruptOccurred + z.nmiPending = false + z.intData = 0 } func (z *Z80) GetState() *z80.Z80CPU { return &z80.Z80CPU{ @@ -177,15 +174,15 @@ func (z *Z80) GetState() *z80.Z80CPU { Flags: z.getFlags(), FlagsAlt: z.getAltFlags(), - IMode: z.interrupt_mode, + IMode: z.interruptMode, Iff1: z.iff1, Iff2: z.iff2, - Halted: z.halted, - DoDelayedDI: z.int_pending, - DoDelayedEI: z.int_pending, - CycleCounter: z.inst_cyc, - InterruptOccurred: z.int_pending, - MemPtr: z.mem_ptr, + Halted: z.isHalted, + DoDelayedDI: z.intPending, + DoDelayedEI: z.intPending, + CycleCount: z.cycleCount, + InterruptOccurred: z.intPending, + MemPtr: z.memPtr, } } diff --git a/z80/c99/helper.go b/z80/c99/helper.go index 00b83c8..044a25b 100644 --- a/z80/c99/helper.go +++ b/z80/c99/helper.go @@ -19,56 +19,56 @@ func (z *Z80) ww(addr uint16, val uint16) { z.core.MemWrite(addr+1, byte(val>>8)) } -func (z *Z80) pushw(val uint16) { +func (z *Z80) pushW(val uint16) { z.sp -= 2 z.ww(z.sp, val) } -func (z *Z80) popw() uint16 { +func (z *Z80) popW() uint16 { z.sp += 2 return z.rw(z.sp - 2) } -func (z *Z80) nextb() byte { +func (z *Z80) nextB() byte { b := z.rb(z.pc) z.pc++ return b } -func (z *Z80) nextw() uint16 { +func (z *Z80) nextW() uint16 { w := z.rw(z.pc) z.pc += 2 return w } -func (z *Z80) get_bc() uint16 { +func (z *Z80) bc() uint16 { return (uint16(z.b) << 8) | uint16(z.c) } -func (z *Z80) get_de() uint16 { +func (z *Z80) de() uint16 { return (uint16(z.d) << 8) | uint16(z.e) } -func (z *Z80) get_hl() uint16 { +func (z *Z80) hl() uint16 { return (uint16(z.h) << 8) | uint16(z.l) } -func (z *Z80) set_bc(val uint16) { +func (z *Z80) setBC(val uint16) { z.b = byte(val >> 8) z.c = byte(val) } -func (z *Z80) set_de(val uint16) { +func (z *Z80) setDE(val uint16) { z.d = byte(val >> 8) z.e = byte(val) } -func (z *Z80) set_hl(val uint16) { +func (z *Z80) setHL(val uint16) { z.h = byte(val >> 8) z.l = byte(val) } -func (z *Z80) get_f() byte { +func (z *Z80) f() byte { val := byte(0) if z.cf { val |= 0x01 @@ -97,7 +97,7 @@ func (z *Z80) get_f() byte { return val } -func (z *Z80) set_f(val byte) { +func (z *Z80) setF(val byte) { z.cf = val&1 != 0 z.nf = (val>>1)&1 != 0 z.pf = (val>>2)&1 != 0 @@ -109,7 +109,7 @@ func (z *Z80) set_f(val byte) { } // increments R, keeping the highest byte intact -func (z *Z80) inc_r() { +func (z *Z80) incR() { z.r = (z.r & 0x80) | ((z.r + 1) & 0x7f) } @@ -122,10 +122,10 @@ func boolToInt32(b bool) int32 { // returns if there was a carry between bit "bit_no" and "bit_no - 1" when // executing "a + b + cy" -func carry(bit_no int, a uint16, b uint16, cy bool) bool { +func carry(bitNo int, a uint16, b uint16, cy bool) bool { result := int32(a) + int32(b) + boolToInt32(cy) carry := result ^ int32(a) ^ int32(b) - return (carry & (1 << bit_no)) != 0 + return (carry & (1 << bitNo)) != 0 } // returns the parity of byte: 0 if number of 1 bits in `val` is odd, else 1 @@ -137,6 +137,7 @@ func parity(val byte) bool { return (ones & 1) == 0 } +// updateXY set undocumented 3rd (X) and 5th (Y) flags func (z *Z80) updateXY(result byte) { z.yf = result&0x20 != 0 z.xf = result&0x08 != 0 @@ -144,13 +145,56 @@ func (z *Z80) updateXY(result byte) { func (z *Z80) DebugOutput() { 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.get_f()), z.get_bc(), z.get_de(), z.get_hl(), 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) - log.Debugf("\t(%02X %02X %02X %02X), cyc: %d\n", z.rb(z.pc), z.rb(z.pc+1), - z.rb(z.pc+2), z.rb(z.pc+3), z.cyc) + 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) } func (z *Z80) Reset() { + z.cycleCount = 0 + z.pc = 0 + z.sp = 0xFFFF + z.ix = 0 + z.iy = 0 + z.memPtr = 0 + z.a = 0xFF + z.b = 0 + z.c = 0 + z.d = 0 + z.e = 0 + z.h = 0 + z.l = 0 + + z.a_ = 0 + z.b_ = 0 + z.c_ = 0 + z.d_ = 0 + z.e_ = 0 + z.h_ = 0 + z.l_ = 0 + z.f_ = 0 + + z.i = 0 + z.r = 0 + + z.sf = true + z.zf = true + z.yf = true + z.hf = true + z.xf = true + z.pf = true + z.nf = true + z.cf = true + + z.iffDelay = 0 + z.interruptMode = 0 + z.iff1 = false + z.iff2 = false + z.isHalted = false + z.intPending = false + z.nmiPending = false + z.intData = 0 } diff --git a/z80/c99/opcodes.go b/z80/c99/opcodes.go index 0a09167..f7c0e98 100644 --- a/z80/c99/opcodes.go +++ b/z80/c99/opcodes.go @@ -5,46 +5,46 @@ import log "github.com/sirupsen/logrus" // jumps to an address func (z *Z80) jump(addr uint16) { z.pc = addr - z.mem_ptr = addr + z.memPtr = addr } // jumps to next word in memory if condition is true func (z *Z80) cond_jump(condition bool) { - addr := z.nextw() + addr := z.nextW() if condition { z.jump(addr) } - z.mem_ptr = addr + z.memPtr = addr } // calls to next word in memory func (z *Z80) call(addr uint16) { - z.pushw(z.pc) + z.pushW(z.pc) z.pc = addr - z.mem_ptr = addr + z.memPtr = addr } // calls to next word in memory if condition is true func (z *Z80) cond_call(condition bool) { - addr := z.nextw() + addr := z.nextW() if condition { z.call(addr) - z.cyc += 7 + z.cycleCount += 7 } - z.mem_ptr = addr + z.memPtr = addr } // returns from subroutine func (z *Z80) ret() { - z.pc = z.popw() - z.mem_ptr = z.pc + z.pc = z.popW() + z.memPtr = z.pc } // returns from subroutine if condition is true func (z *Z80) cond_ret(condition bool) { if condition { z.ret() - z.cyc += 6 + z.cycleCount += 6 } } @@ -54,14 +54,14 @@ func (z *Z80) jr(offset byte) { } else { z.pc += uint16(offset) } - z.mem_ptr = z.pc + z.memPtr = z.pc } func (z *Z80) cond_jr(condition bool) { - b := z.nextb() + b := z.nextB() if condition { z.jr(b) - z.cyc += 5 + z.cycleCount += 5 } } @@ -100,7 +100,7 @@ func (z *Z80) addw(a uint16, b uint16, cy bool) uint16 { msb := z.addb(byte(a>>8), byte(b>>8), z.cf) result := (uint16(msb) << 8) | uint16(lsb) z.zf = result == 0 - z.mem_ptr = a + 1 + z.memPtr = a + 1 return result } @@ -110,7 +110,7 @@ func (z *Z80) subw(a uint16, b uint16, cy bool) uint16 { msb := z.subb(byte(a>>8), byte(b>>8), z.cf) result := (uint16(msb) << 8) | uint16(lsb) z.zf = result == 0 - z.mem_ptr = a + 1 + z.memPtr = a + 1 return result } @@ -119,8 +119,8 @@ func (z *Z80) addhl(val uint16) { sf := z.sf zf := z.zf pf := z.pf - result := z.addw(z.get_hl(), val, false) - z.set_hl(result) + result := z.addw(z.hl(), val, false) + z.setHL(result) z.sf = sf z.zf = zf z.pf = pf @@ -140,18 +140,18 @@ func (z *Z80) addiz(reg *uint16, val uint16) { // adchl adds a word (+ carry) to HL func (z *Z80) adchl(val uint16) { - result := z.addw(z.get_hl(), val, z.cf) + result := z.addw(z.hl(), val, z.cf) z.sf = result&0x8000 != 0 z.zf = result == 0 - z.set_hl(result) + z.setHL(result) } // sbchl subtracts a word (+ carry) to HL func (z *Z80) sbchl(val uint16) { - result := z.subw(z.get_hl(), val, z.cf) + result := z.subw(z.hl(), val, z.cf) z.sf = result&0x8000 != 0 z.zf = result == 0 - z.set_hl(result) + z.setHL(result) } // increments a byte value @@ -347,14 +347,14 @@ func (z *Z80) cb_bit(val byte, n byte) byte { } func (z *Z80) ldi() { - de := z.get_de() - hl := z.get_hl() + de := z.de() + hl := z.hl() val := z.rb(hl) z.wb(de, val) - z.set_hl(z.get_hl() + 1) - z.set_de(z.get_de() + 1) - z.set_bc(z.get_bc() - 1) + z.setHL(z.hl() + 1) + z.setDE(z.de() + 1) + z.setBC(z.bc() - 1) // see https://wikiti.brandonw.net/index.php?title=Z80_Instruction_Set // for the calculation of xf/yf on LDI @@ -365,67 +365,42 @@ func (z *Z80) ldi() { z.nf = false z.hf = false - z.pf = z.get_bc() > 0 + z.pf = z.bc() > 0 } func (z *Z80) ldd() { z.ldi() // same as ldi but HL and DE are decremented instead of incremented - z.set_hl(z.get_hl() - 2) - z.set_de(z.get_de() - 2) + z.setHL(z.hl() - 2) + z.setDE(z.de() - 2) } func (z *Z80) cpi() { cf := z.cf - result := z.subb(z.a, z.rb(z.get_hl()), false) - z.set_hl(z.get_hl() + 1) - z.set_bc(z.get_bc() - 1) + result := z.subb(z.a, z.rb(z.hl()), false) + z.setHL(z.hl() + 1) + z.setBC(z.bc() - 1) val := result - bToByte(z.hf) z.xf = val&0x08 != 0 z.yf = val&0x02 != 0 - z.pf = z.get_bc() != 0 + z.pf = z.bc() != 0 z.cf = cf - z.mem_ptr += 1 + z.memPtr += 1 } func (z *Z80) cpd() { z.cpi() // same as cpi but HL is decremented instead of incremented - z.set_hl(z.get_hl() - 2) - z.mem_ptr -= 2 + z.setHL(z.hl() - 2) + z.memPtr -= 2 } -var halfCarrySubTable = []bool{false, false, true, false, true, false, true, true} +//var halfCarrySubTable = []bool{false, false, true, false, true, false, true, true} -func (z *Z80) cpir() { - value := z.rb(z.get_hl()) - diff := uint8(uint16(z.a) - uint16(value)) - lookup := ((z.a & 0x08) >> 3) | ((value & 0x08) >> 2) | ((diff & 0x08) >> 1) - z.set_bc(z.get_bc() - 1) - z.hf = halfCarrySubTable[lookup] - z.pf = z.get_bc() != 0 // V=P - z.nf = true - z.zf = diff == 0 - z.sf = diff&0x80 != 0 - if z.hf { - diff-- - } - z.xf = (diff & 0x08) != 0 - z.yf = (diff & 0x02) != 0 - if z.pf && !z.zf { - z.cyc += 5 - z.pc -= 2 - z.mem_ptr = z.pc + 1 - } else { - z.mem_ptr++ - } - z.set_hl(z.get_hl() + 1) -} - -func (z *Z80) in_r_c(r *byte) { - *r = z.core.IORead(z.get_bc()) +func (z *Z80) inRC(r *byte) { + *r = z.core.IORead(z.bc()) z.zf = *r == 0 z.sf = *r&0x80 != 0 z.pf = parity(*r) @@ -434,9 +409,9 @@ func (z *Z80) in_r_c(r *byte) { } func (z *Z80) ini() { - val := z.core.IORead(z.get_bc()) - z.wb(z.get_hl(), val) - z.mem_ptr = z.get_bc() + 1 + val := z.core.IORead(z.bc()) + z.wb(z.hl(), val) + z.memPtr = z.bc() + 1 z.b-- other := val + z.c + 1 @@ -452,13 +427,13 @@ func (z *Z80) ini() { z.sf = z.b&0x80 != 0 z.zf = z.b == 0 z.updateXY(z.b) - z.set_hl(z.get_hl() + 1) + z.setHL(z.hl() + 1) } func (z *Z80) ind() { - val := z.core.IORead(z.get_bc()) - z.wb(z.get_hl(), val) - z.mem_ptr = z.get_bc() - 1 + val := z.core.IORead(z.bc()) + z.wb(z.hl(), val) + z.memPtr = z.bc() - 1 z.b-- other := val + z.c - 1 @@ -475,15 +450,15 @@ func (z *Z80) ind() { z.sf = z.b&0x80 != 0 z.zf = z.b == 0 z.updateXY(z.b) - z.set_hl(z.get_hl() - 1) + z.setHL(z.hl() - 1) } func (z *Z80) outi() { - val := z.rb(z.get_hl()) + val := z.rb(z.hl()) z.b-- - z.mem_ptr = z.get_bc() + 1 - z.core.IOWrite(z.get_bc(), val) - z.set_hl(z.get_hl() + 1) + z.memPtr = z.bc() + 1 + z.core.IOWrite(z.bc(), val) + z.setHL(z.hl() + 1) other := val + z.l z.nf = val&0x80 != 0 if other < val { @@ -500,11 +475,11 @@ func (z *Z80) outi() { } func (z *Z80) outd() { - val := z.rb(z.get_hl()) + val := z.rb(z.hl()) z.b-- - z.mem_ptr = z.get_bc() - 1 - z.core.IOWrite(z.get_bc(), val) - z.set_hl(z.get_hl() - 1) + z.memPtr = z.bc() - 1 + z.core.IOWrite(z.bc(), val) + z.setHL(z.hl() - 1) other := val + z.l z.nf = val&0x80 != 0 if other < val { @@ -555,80 +530,80 @@ func (z *Z80) daa() { z.updateXY(z.a) } -func (z *Z80) displace(base_addr uint16, offset byte) uint16 { - addr := base_addr +func (z *Z80) displace(baseAddr uint16, offset byte) uint16 { + addr := baseAddr if offset&0x80 == 0x80 { addr += 0xff00 | uint16(offset) } else { addr += uint16(offset) } - //addr := base_addr + uint16(displacement) - z.mem_ptr = addr + //addr := baseAddr + uint16(displacement) + z.memPtr = addr return addr } -func (z *Z80) process_interrupts() { +func (z *Z80) processInterrupts() { // "When an EI instruction is executed, any pending interrupt request // is not accepted until after the instruction following EI is executed." - if z.iff_delay > 0 { - z.iff_delay -= 1 - if z.iff_delay == 0 { + if z.iffDelay > 0 { + z.iffDelay -= 1 + if z.iffDelay == 0 { z.iff1 = true z.iff2 = true } return } - if z.nmi_pending { - z.nmi_pending = false - z.halted = false + if z.nmiPending { + z.nmiPending = false + z.isHalted = false z.iff1 = false - z.inc_r() + z.incR() - z.cyc += 11 + z.cycleCount += 11 z.call(0x0066) return } - if z.int_pending && z.iff1 { - z.int_pending = false - z.halted = false + if z.intPending && z.iff1 { + z.intPending = false + z.isHalted = false z.iff1 = false z.iff2 = false - z.inc_r() + z.incR() - switch z.interrupt_mode { + switch z.interruptMode { case 0: - z.cyc += 11 - z.exec_opcode(z.int_data) + z.cycleCount += 11 + z.execOpcode(z.intData) case 1: - z.cyc += 13 + z.cycleCount += 13 z.call(0x38) case 2: - z.cyc += 19 - z.call(z.rw((uint16(z.i) << 8) | uint16(z.int_data))) + z.cycleCount += 19 + z.call(z.rw((uint16(z.i) << 8) | uint16(z.intData))) default: - log.Errorf("Unsupported interrupt mode %d\n", z.interrupt_mode) + log.Errorf("Unsupported interrupt mode %d\n", z.interruptMode) } return } } -// z80_gen_nmi function to call when an NMI is to be serviced -func (z *Z80) z80_gen_nmi() { - z.nmi_pending = true +// GenNMI function to call when an NMI is to be serviced +func (z *Z80) GenNMI() { + z.nmiPending = true } -// z80_gen_int function to call when an INT is to be serviced -func (z *Z80) z80_gen_int(data byte) { - z.int_pending = true - z.int_data = data +// GenINT function to call when an INT is to be serviced +func (z *Z80) GenINT(data byte) { + z.intPending = true + z.intData = data } // executes a non-prefixed opcode -func (z *Z80) exec_opcode(opcode byte) { - z.cyc += uint64(cyc_00[opcode]) - z.inc_r() +func (z *Z80) execOpcode(opcode byte) { + z.cycleCount += uint32(cycles00[opcode]) + z.incR() switch opcode { case 0x7F: @@ -737,110 +712,110 @@ func (z *Z80) exec_opcode(opcode byte) { z.l = z.l // ld l,l case 0x7E: - z.a = z.rb(z.get_hl()) // ld a,(hl) + z.a = z.rb(z.hl()) // ld a,(hl) case 0x46: - z.b = z.rb(z.get_hl()) // ld b,(hl) + z.b = z.rb(z.hl()) // ld b,(hl) case 0x4E: - z.c = z.rb(z.get_hl()) // ld c,(hl) + z.c = z.rb(z.hl()) // ld c,(hl) case 0x56: - z.d = z.rb(z.get_hl()) // ld d,(hl) + z.d = z.rb(z.hl()) // ld d,(hl) case 0x5E: - z.e = z.rb(z.get_hl()) // ld e,(hl) + z.e = z.rb(z.hl()) // ld e,(hl) case 0x66: - z.h = z.rb(z.get_hl()) // ld h,(hl) + z.h = z.rb(z.hl()) // ld h,(hl) case 0x6E: - z.l = z.rb(z.get_hl()) // ld l,(hl) + z.l = z.rb(z.hl()) // ld l,(hl) case 0x77: - z.wb(z.get_hl(), z.a) // ld (hl),a + z.wb(z.hl(), z.a) // ld (hl),a case 0x70: - z.wb(z.get_hl(), z.b) // ld (hl),b + z.wb(z.hl(), z.b) // ld (hl),b case 0x71: - z.wb(z.get_hl(), z.c) // ld (hl),c + z.wb(z.hl(), z.c) // ld (hl),c case 0x72: - z.wb(z.get_hl(), z.d) // ld (hl),d + z.wb(z.hl(), z.d) // ld (hl),d case 0x73: - z.wb(z.get_hl(), z.e) // ld (hl),e + z.wb(z.hl(), z.e) // ld (hl),e case 0x74: - z.wb(z.get_hl(), z.h) // ld (hl),h + z.wb(z.hl(), z.h) // ld (hl),h case 0x75: - z.wb(z.get_hl(), z.l) // ld (hl),l + z.wb(z.hl(), z.l) // ld (hl),l case 0x3E: - z.a = z.nextb() // ld a,* + z.a = z.nextB() // ld a,* case 0x06: - z.b = z.nextb() // ld b,* + z.b = z.nextB() // ld b,* case 0x0E: - z.c = z.nextb() // ld c,* + z.c = z.nextB() // ld c,* case 0x16: - z.d = z.nextb() // ld d,* + z.d = z.nextB() // ld d,* case 0x1E: - z.e = z.nextb() // ld e,* + z.e = z.nextB() // ld e,* case 0x26: - z.h = z.nextb() // ld h,* + z.h = z.nextB() // ld h,* case 0x2E: - z.l = z.nextb() // ld l,* + z.l = z.nextB() // ld l,* case 0x36: - z.wb(z.get_hl(), z.nextb()) // ld (hl),* + z.wb(z.hl(), z.nextB()) // ld (hl),* case 0x0A: // ld a,(bc) - z.a = z.rb(z.get_bc()) - z.mem_ptr = z.get_bc() + 1 + z.a = z.rb(z.bc()) + z.memPtr = z.bc() + 1 case 0x1A: // ld a,(de) - z.a = z.rb(z.get_de()) - z.mem_ptr = z.get_de() + 1 + z.a = z.rb(z.de()) + z.memPtr = z.de() + 1 case 0x3A: // ld a,(**) - addr := z.nextw() + addr := z.nextW() z.a = z.rb(addr) - z.mem_ptr = addr + 1 + z.memPtr = addr + 1 case 0x02: // ld (bc),a - z.wb(z.get_bc(), z.a) - z.mem_ptr = (uint16(z.a) << 8) | ((z.get_bc() + 1) & 0xFF) + z.wb(z.bc(), z.a) + z.memPtr = (uint16(z.a) << 8) | ((z.bc() + 1) & 0xFF) case 0x12: // ld (de),a - z.wb(z.get_de(), z.a) - z.mem_ptr = (uint16(z.a) << 8) | ((z.get_de() + 1) & 0xFF) + z.wb(z.de(), z.a) + z.memPtr = (uint16(z.a) << 8) | ((z.de() + 1) & 0xFF) case 0x32: // ld (**),a - addr := z.nextw() + addr := z.nextW() z.wb(addr, z.a) - z.mem_ptr = (uint16(z.a) << 8) | ((addr + 1) & 0xFF) + z.memPtr = (uint16(z.a) << 8) | ((addr + 1) & 0xFF) case 0x01: - z.set_bc(z.nextw()) // ld bc,** + z.setBC(z.nextW()) // ld bc,** case 0x11: - z.set_de(z.nextw()) // ld de,** + z.setDE(z.nextW()) // ld de,** case 0x21: - z.set_hl(z.nextw()) // ld hl,** + z.setHL(z.nextW()) // ld hl,** case 0x31: - z.sp = z.nextw() // ld sp,** + z.sp = z.nextW() // ld sp,** case 0x2A: // ld hl,(**) - addr := z.nextw() - z.set_hl(z.rw(addr)) - z.mem_ptr = addr + 1 + addr := z.nextW() + z.setHL(z.rw(addr)) + z.memPtr = addr + 1 case 0x22: // ld (**),hl - addr := z.nextw() - z.ww(addr, z.get_hl()) - z.mem_ptr = addr + 1 + addr := z.nextW() + z.ww(addr, z.hl()) + z.memPtr = addr + 1 case 0xF9: - z.sp = z.get_hl() // ld sp,hl + z.sp = z.hl() // ld sp,hl case 0xEB: // ex de,hl - de := z.get_de() - z.set_de(z.get_hl()) - z.set_hl(de) + de := z.de() + z.setDE(z.hl()) + z.setHL(de) case 0xE3: // ex (sp),hl val := z.rw(z.sp) - z.ww(z.sp, z.get_hl()) - z.set_hl(val) - z.mem_ptr = val + z.ww(z.sp, z.hl()) + z.setHL(val) + z.memPtr = val case 0x87: z.a = z.addb(z.a, z.a, false) // add a,a case 0x80: @@ -856,9 +831,9 @@ func (z *Z80) exec_opcode(opcode byte) { case 0x85: z.a = z.addb(z.a, z.l, false) // add a,l case 0x86: - z.a = z.addb(z.a, z.rb(z.get_hl()), false) // add a,(hl) + z.a = z.addb(z.a, z.rb(z.hl()), false) // add a,(hl) case 0xC6: - z.a = z.addb(z.a, z.nextb(), false) // add a,* + z.a = z.addb(z.a, z.nextB(), false) // add a,* case 0x8F: z.a = z.addb(z.a, z.a, z.cf) // adc a,a @@ -875,9 +850,9 @@ func (z *Z80) exec_opcode(opcode byte) { case 0x8D: z.a = z.addb(z.a, z.l, z.cf) // adc a,l case 0x8E: - z.a = z.addb(z.a, z.rb(z.get_hl()), z.cf) // adc a,(hl) + z.a = z.addb(z.a, z.rb(z.hl()), z.cf) // adc a,(hl) case 0xCE: - z.a = z.addb(z.a, z.nextb(), z.cf) // adc a,* + z.a = z.addb(z.a, z.nextB(), z.cf) // adc a,* case 0x97: z.a = z.subb(z.a, z.a, false) // sub a,a @@ -894,9 +869,9 @@ func (z *Z80) exec_opcode(opcode byte) { case 0x95: z.a = z.subb(z.a, z.l, false) // sub a,l case 0x96: - z.a = z.subb(z.a, z.rb(z.get_hl()), false) // sub a,(hl) + z.a = z.subb(z.a, z.rb(z.hl()), false) // sub a,(hl) case 0xD6: - z.a = z.subb(z.a, z.nextb(), false) // sub a,* + z.a = z.subb(z.a, z.nextB(), false) // sub a,* case 0x9F: z.a = z.subb(z.a, z.a, z.cf) // sbc a,a @@ -913,16 +888,16 @@ func (z *Z80) exec_opcode(opcode byte) { case 0x9D: z.a = z.subb(z.a, z.l, z.cf) // sbc a,l case 0x9E: - z.a = z.subb(z.a, z.rb(z.get_hl()), z.cf) // sbc a,(hl) + z.a = z.subb(z.a, z.rb(z.hl()), z.cf) // sbc a,(hl) case 0xDE: - z.a = z.subb(z.a, z.nextb(), z.cf) // sbc a,* + z.a = z.subb(z.a, z.nextB(), z.cf) // sbc a,* case 0x09: - z.addhl(z.get_bc()) // add hl,bc + z.addhl(z.bc()) // add hl,bc case 0x19: - z.addhl(z.get_de()) // add hl,de + z.addhl(z.de()) // add hl,de case 0x29: - z.addhl(z.get_hl()) // add hl,hl + z.addhl(z.hl()) // add hl,hl case 0x39: z.addhl(z.sp) // add hl,sp @@ -930,10 +905,10 @@ func (z *Z80) exec_opcode(opcode byte) { z.iff1 = false z.iff2 = false // di case 0xFB: - z.iff_delay = 1 // ei + z.iffDelay = 1 // ei case 0x00: // nop case 0x76: - z.halted = true // halt + z.isHalted = true // halt z.pc-- case 0x3C: z.a = z.inc(z.a) // inc a @@ -951,8 +926,8 @@ func (z *Z80) exec_opcode(opcode byte) { z.l = z.inc(z.l) // inc l case 0x34: // inc (hl) - result := z.inc(z.rb(z.get_hl())) - z.wb(z.get_hl(), result) + result := z.inc(z.rb(z.hl())) + z.wb(z.hl(), result) case 0x3D: z.a = z.dec(z.a) // dec a case 0x05: @@ -969,22 +944,22 @@ func (z *Z80) exec_opcode(opcode byte) { z.l = z.dec(z.l) // dec l case 0x35: // dec (hl) - result := z.dec(z.rb(z.get_hl())) - z.wb(z.get_hl(), result) + result := z.dec(z.rb(z.hl())) + z.wb(z.hl(), result) case 0x03: - z.set_bc(z.get_bc() + 1) // inc bc + z.setBC(z.bc() + 1) // inc bc case 0x13: - z.set_de(z.get_de() + 1) // inc de + z.setDE(z.de() + 1) // inc de case 0x23: - z.set_hl(z.get_hl() + 1) // inc hl + z.setHL(z.hl() + 1) // inc hl case 0x33: z.sp = z.sp + 1 // inc sp case 0x0B: - z.set_bc(z.get_bc() - 1) // dec bc + z.setBC(z.bc() - 1) // dec bc case 0x1B: - z.set_de(z.get_de() - 1) // dec de + z.setDE(z.de() - 1) // dec de case 0x2B: - z.set_hl(z.get_hl() - 1) // dec hl + z.setHL(z.hl() - 1) // dec hl case 0x3B: z.sp = z.sp - 1 // dec sp case 0x27: @@ -1000,13 +975,13 @@ func (z *Z80) exec_opcode(opcode byte) { z.cf = true z.nf = false z.hf = false - z.updateXY(z.a | z.get_f()) + z.updateXY(z.a | z.f()) case 0x3F: // ccf z.hf = z.cf z.cf = !z.cf z.nf = false - z.updateXY(z.a | z.get_f()) + z.updateXY(z.a | z.f()) case 0x07: // rlca (rotate left) z.cf = z.a&0x80 != 0 @@ -1052,9 +1027,9 @@ func (z *Z80) exec_opcode(opcode byte) { case 0xA5: z.land(z.l) // and l case 0xA6: - z.land(z.rb(z.get_hl())) // and (hl) + z.land(z.rb(z.hl())) // and (hl) case 0xE6: - z.land(z.nextb()) // and * + z.land(z.nextB()) // and * case 0xAF: z.lxor(z.a) // xor a @@ -1071,9 +1046,9 @@ func (z *Z80) exec_opcode(opcode byte) { case 0xAD: z.lxor(z.l) // xor l case 0xAE: - z.lxor(z.rb(z.get_hl())) // xor (hl) + z.lxor(z.rb(z.hl())) // xor (hl) case 0xEE: - z.lxor(z.nextb()) // xor * + z.lxor(z.nextB()) // xor * case 0xB7: z.lor(z.a) // or a @@ -1090,9 +1065,9 @@ func (z *Z80) exec_opcode(opcode byte) { case 0xB5: z.lor(z.l) // or l case 0xB6: - z.lor(z.rb(z.get_hl())) // or (hl) + z.lor(z.rb(z.hl())) // or (hl) case 0xF6: - z.lor(z.nextb()) // or * + z.lor(z.nextB()) // or * case 0xBF: z.cp(z.a) // cp a @@ -1109,12 +1084,12 @@ func (z *Z80) exec_opcode(opcode byte) { case 0xBD: z.cp(z.l) // cp l case 0xBE: - z.cp(z.rb(z.get_hl())) // cp (hl) + z.cp(z.rb(z.hl())) // cp (hl) case 0xFE: - z.cp(z.nextb()) // cp * + z.cp(z.nextB()) // cp * case 0xC3: - z.jump(z.nextw()) // jm ** + z.jump(z.nextW()) // jm ** case 0xC2: z.cond_jump(!z.zf) // jp nz, ** case 0xCA: @@ -1136,8 +1111,8 @@ func (z *Z80) exec_opcode(opcode byte) { z.b-- z.cond_jr(z.b != 0) // djnz * case 0x18: - z.pc += uint16(z.nextb()) // jr * - z.mem_ptr = z.pc + z.pc += uint16(z.nextB()) // jr * + z.memPtr = z.pc case 0x20: z.cond_jr(!z.zf) // jr nz, * case 0x28: @@ -1148,9 +1123,9 @@ func (z *Z80) exec_opcode(opcode byte) { z.cond_jr(z.cf) // jr c, * case 0xE9: - z.pc = z.get_hl() // jp (hl) + z.pc = z.hl() // jp (hl) case 0xCD: - z.call(z.nextw()) // call + z.call(z.nextW()) // call case 0xC4: z.cond_call(!z.zf) // cnz @@ -1206,42 +1181,42 @@ func (z *Z80) exec_opcode(opcode byte) { z.call(0x38) // rst 7 case 0xC5: - z.pushw(z.get_bc()) // push bc + z.pushW(z.bc()) // push bc case 0xD5: - z.pushw(z.get_de()) // push de + z.pushW(z.de()) // push de case 0xE5: - z.pushw(z.get_hl()) // push hl + z.pushW(z.hl()) // push hl case 0xF5: - z.pushw((uint16(z.a) << 8) | uint16(z.get_f())) // push af + z.pushW((uint16(z.a) << 8) | uint16(z.f())) // push af case 0xC1: - z.set_bc(z.popw()) // pop bc + z.setBC(z.popW()) // pop bc case 0xD1: - z.set_de(z.popw()) // pop de + z.setDE(z.popW()) // pop de case 0xE1: - z.set_hl(z.popw()) // pop hl + z.setHL(z.popW()) // pop hl case 0xF1: // pop af - val := z.popw() + val := z.popW() z.a = byte(val >> 8) - z.set_f(byte(val)) + z.setF(byte(val)) case 0xDB: // in a,(n) - port := (uint16(z.a) << 8) | uint16(z.nextb()) + port := (uint16(z.a) << 8) | uint16(z.nextB()) z.a = z.core.IORead(port) - z.mem_ptr = port + 1 // (uint16(a) << 8) | (uint16(z.a+1) & 0x00ff) + z.memPtr = port + 1 // (uint16(a) << 8) | (uint16(z.a+1) & 0x00ff) case 0xD3: // out (n), a - port := uint16(z.nextb()) + port := uint16(z.nextB()) z.core.IOWrite(port, z.a) - z.mem_ptr = ((port + 1) & 0x00ff) | (uint16(z.a) << 8) + z.memPtr = ((port + 1) & 0x00ff) | (uint16(z.a) << 8) case 0x08: // ex af,af' a := z.a - f := z.get_f() + f := z.f() z.a = z.a_ - z.set_f(z.f_) + z.setF(z.f_) z.a_ = a z.f_ = f @@ -1268,13 +1243,13 @@ func (z *Z80) exec_opcode(opcode byte) { z.h_ = h z.l_ = l case 0xCB: - z.exec_opcode_cb(z.nextb()) + z.execOpcodeCB(z.nextB()) case 0xED: - z.exec_opcode_ed(z.nextb()) + z.execOpcodeED(z.nextB()) case 0xDD: - z.exec_opcode_ddfd(z.nextb(), &z.ix) + z.execOpcodeDDFD(z.nextB(), &z.ix) case 0xFD: - z.exec_opcode_ddfd(z.nextb(), &z.iy) + z.execOpcodeDDFD(z.nextB(), &z.iy) default: log.Errorf("Unknown opcode %02X\n", opcode) diff --git a/z80/c99/opcodesCB.go b/z80/c99/opcodesCB.go index 6cf3180..c972e4f 100644 --- a/z80/c99/opcodesCB.go +++ b/z80/c99/opcodesCB.go @@ -3,9 +3,9 @@ package c99 import log "github.com/sirupsen/logrus" // executes a CB opcode -func (z *Z80) exec_opcode_cb(opcode byte) { - z.cyc += 8 - z.inc_r() +func (z *Z80) execOpcodeCB(opcode byte) { + z.cycleCount += 8 + z.incR() // decoding instructions from http://z80.info/decoding.htm#cb x_ := (opcode >> 6) & 3 // 0b11 @@ -29,7 +29,7 @@ func (z *Z80) exec_opcode_cb(opcode byte) { case 5: reg = &z.l case 6: - hl = z.rb(z.get_hl()) + hl = z.rb(z.hl()) reg = &hl case 7: reg = &z.a @@ -63,8 +63,8 @@ func (z *Z80) exec_opcode_cb(opcode byte) { // in bit (hl), x/y flags are handled differently: if z_ == 6 { - z.updateXY(byte(z.mem_ptr >> 8)) - z.cyc += 4 + z.updateXY(byte(z.memPtr >> 8)) + z.cycleCount += 4 } case 2: @@ -74,11 +74,11 @@ func (z *Z80) exec_opcode_cb(opcode byte) { } if (x_ == 0 || x_ == 2 || x_ == 3) && z_ == 6 { - z.cyc += 7 + z.cycleCount += 7 } if reg == &hl { - z.wb(z.get_hl(), hl) + z.wb(z.hl(), hl) } } @@ -146,7 +146,7 @@ func (z *Z80) exec_opcode_dcb(opcode byte, addr uint16) { z.l = result // always false //case 6: - // z.wb(z.get_hl(), result) + // z.wb(z.hl(), result) case 7: z.a = result } @@ -154,9 +154,9 @@ func (z *Z80) exec_opcode_dcb(opcode byte, addr uint16) { if x_ == 1 { // bit instructions take 20 cycles, others take 23 - z.cyc += 20 + z.cycleCount += 20 } else { z.wb(addr, result) - z.cyc += 23 + z.cycleCount += 23 } } diff --git a/z80/c99/opcodesDDFD.go b/z80/c99/opcodesDDFD.go index 391cb36..3c1f4ef 100644 --- a/z80/c99/opcodesDDFD.go +++ b/z80/c99/opcodesDDFD.go @@ -1,23 +1,23 @@ package c99 // executes a DD/FD opcode (IZ = IX or IY) -func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) { - z.cyc += uint64(cyc_ddfd[opcode]) - z.inc_r() +func (z *Z80) execOpcodeDDFD(opcode byte, iz *uint16) { + z.cycleCount += uint32(cyclesDDFD[opcode]) + z.incR() switch opcode { case 0xE1: - *iz = z.popw() // pop iz + *iz = z.popW() // pop iz case 0xE5: - z.pushw(*iz) // push iz + z.pushW(*iz) // push iz case 0xE9: // jp iz z.pc = *iz //z.jump(*iz) case 0x09: - z.addiz(iz, z.get_bc()) // add iz,bc + z.addiz(iz, z.bc()) // add iz,bc case 0x19: - z.addiz(iz, z.get_de()) // add iz,de + z.addiz(iz, z.de()) // add iz,de case 0x29: z.addiz(iz, *iz) // add iz,iz case 0x39: @@ -32,13 +32,13 @@ func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) { case 0x8D: z.a = z.addb(z.a, byte(*iz), z.cf) // adc a,izl case 0x86: - z.a = z.addb(z.a, z.rb(z.displace(*iz, z.nextb())), false) // add a,(iz+*) + z.a = z.addb(z.a, z.rb(z.displace(*iz, z.nextB())), false) // add a,(iz+*) case 0x8E: - z.a = z.addb(z.a, z.rb(z.displace(*iz, z.nextb())), z.cf) // adc a,(iz+*) + z.a = z.addb(z.a, z.rb(z.displace(*iz, z.nextB())), z.cf) // adc a,(iz+*) case 0x96: - z.a = z.subb(z.a, z.rb(z.displace(*iz, z.nextb())), false) // sub (iz+*) + z.a = z.subb(z.a, z.rb(z.displace(*iz, z.nextB())), false) // sub (iz+*) case 0x9E: - z.a = z.subb(z.a, z.rb(z.displace(*iz, z.nextb())), z.cf) // sbc (iz+*) + z.a = z.subb(z.a, z.rb(z.displace(*iz, z.nextB())), z.cf) // sbc (iz+*) case 0x94: z.a = z.subb(z.a, byte(*iz>>8), false) // sub izh case 0x95: @@ -49,26 +49,26 @@ func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) { z.a = z.subb(z.a, byte(*iz), z.cf) // sbc izl case 0xA6: - z.land(z.rb(z.displace(*iz, z.nextb()))) // and (iz+*) + z.land(z.rb(z.displace(*iz, z.nextB()))) // and (iz+*) case 0xA4: z.land(byte(*iz >> 8)) // and izh case 0xA5: z.land(byte(*iz)) // and izl case 0xAE: - z.lxor(z.rb(z.displace(*iz, z.nextb()))) // xor (iz+*) + z.lxor(z.rb(z.displace(*iz, z.nextB()))) // xor (iz+*) case 0xAC: z.lxor(byte(*iz >> 8)) // xor izh case 0xAD: z.lxor(byte(*iz)) // xor izl case 0xB6: - z.lor(z.rb(z.displace(*iz, z.nextb()))) // or (iz+*) + z.lor(z.rb(z.displace(*iz, z.nextB()))) // or (iz+*) case 0xB4: z.lor(byte(*iz >> 8)) // or izh case 0xB5: z.lor(byte(*iz)) // or izl case 0xBE: - z.cp(z.rb(z.displace(*iz, z.nextb()))) // cp (iz+*) + z.cp(z.rb(z.displace(*iz, z.nextB()))) // cp (iz+*) case 0xBC: z.cp(byte(*iz >> 8)) // cp izh case 0xBD: @@ -79,11 +79,11 @@ func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) { *iz -= 1 // dec iz case 0x34: // inc (iz+*) - addr := z.displace(*iz, z.nextb()) + addr := z.displace(*iz, z.nextB()) z.wb(addr, z.inc(z.rb(addr))) case 0x35: // dec (iz+*) - addr := z.displace(*iz, z.nextb()) + addr := z.displace(*iz, z.nextB()) z.wb(addr, z.dec(z.rb(addr))) case 0x24: *iz = (*iz & 0x00ff) | (uint16(z.inc(byte(*iz>>8))) << 8) // inc izh @@ -94,47 +94,47 @@ func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) { case 0x2D: *iz = (*iz & 0xff00) | uint16(z.dec(byte(*iz))) // dec izl case 0x2A: - addr := z.nextw() + addr := z.nextW() *iz = z.rw(addr) // ld iz,(**) - z.mem_ptr = addr + 1 + z.memPtr = addr + 1 case 0x22: - addr := z.nextw() + addr := z.nextW() z.ww(addr, *iz) // ld (**),iz - z.mem_ptr = addr + 1 + z.memPtr = addr + 1 case 0x21: - *iz = z.nextw() // ld iz,** + *iz = z.nextW() // ld iz,** case 0x36: // ld (iz+*),* - addr := z.displace(*iz, z.nextb()) - z.wb(addr, z.nextb()) + addr := z.displace(*iz, z.nextB()) + z.wb(addr, z.nextB()) case 0x70: - z.wb(z.displace(*iz, z.nextb()), z.b) // ld (iz+*),b + z.wb(z.displace(*iz, z.nextB()), z.b) // ld (iz+*),b case 0x71: - z.wb(z.displace(*iz, z.nextb()), z.c) // ld (iz+*),c + z.wb(z.displace(*iz, z.nextB()), z.c) // ld (iz+*),c case 0x72: - z.wb(z.displace(*iz, z.nextb()), z.d) // ld (iz+*),d + z.wb(z.displace(*iz, z.nextB()), z.d) // ld (iz+*),d case 0x73: - z.wb(z.displace(*iz, z.nextb()), z.e) // ld (iz+*),e + z.wb(z.displace(*iz, z.nextB()), z.e) // ld (iz+*),e case 0x74: - z.wb(z.displace(*iz, z.nextb()), z.h) // ld (iz+*),h + z.wb(z.displace(*iz, z.nextB()), z.h) // ld (iz+*),h case 0x75: - z.wb(z.displace(*iz, z.nextb()), z.l) // ld (iz+*),l + z.wb(z.displace(*iz, z.nextB()), z.l) // ld (iz+*),l case 0x77: - z.wb(z.displace(*iz, z.nextb()), z.a) // ld (iz+*),a + z.wb(z.displace(*iz, z.nextB()), z.a) // ld (iz+*),a case 0x46: - z.b = z.rb(z.displace(*iz, z.nextb())) // ld b,(iz+*) + z.b = z.rb(z.displace(*iz, z.nextB())) // ld b,(iz+*) case 0x4E: - z.c = z.rb(z.displace(*iz, z.nextb())) // ld c,(iz+*) + z.c = z.rb(z.displace(*iz, z.nextB())) // ld c,(iz+*) case 0x56: - z.d = z.rb(z.displace(*iz, z.nextb())) // ld d,(iz+*) + z.d = z.rb(z.displace(*iz, z.nextB())) // ld d,(iz+*) case 0x5E: - z.e = z.rb(z.displace(*iz, z.nextb())) // ld e,(iz+*) + z.e = z.rb(z.displace(*iz, z.nextB())) // ld e,(iz+*) case 0x66: - z.h = z.rb(z.displace(*iz, z.nextb())) // ld h,(iz+*) + z.h = z.rb(z.displace(*iz, z.nextB())) // ld h,(iz+*) case 0x6E: - z.l = z.rb(z.displace(*iz, z.nextb())) // ld l,(iz+*) + z.l = z.rb(z.displace(*iz, z.nextB())) // ld l,(iz+*) case 0x7E: - z.a = z.rb(z.displace(*iz, z.nextb())) // ld a,(iz+*) + z.a = z.rb(z.displace(*iz, z.nextB())) // ld a,(iz+*) case 0x44: z.b = byte(*iz >> 8) // ld b,izh case 0x4C: @@ -169,7 +169,7 @@ func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) { case 0x67: *iz = (uint16(z.a) << 8) | (*iz & 0x00ff) // ld izh,a case 0x26: - *iz = (uint16(z.nextb()) << 8) | (*iz & 0x00ff) // ld izh,* + *iz = (uint16(z.nextB()) << 8) | (*iz & 0x00ff) // ld izh,* case 0x68: *iz = (*iz & 0xff00) | uint16(z.b) // ld izl,b case 0x69: @@ -184,7 +184,7 @@ func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) { case 0x6F: *iz = (*iz & 0xff00) | uint16(z.a) // ld izl,a case 0x2E: - *iz = (*iz & 0xff00) | uint16(z.nextb()) // ld izl,* + *iz = (*iz & 0xff00) | uint16(z.nextB()) // ld izl,* case 0xF9: z.sp = *iz // ld sp,iz case 0xE3: @@ -192,15 +192,15 @@ func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) { val := z.rw(z.sp) z.ww(z.sp, *iz) *iz = val - z.mem_ptr = val + z.memPtr = val case 0xCB: - addr := z.displace(*iz, z.nextb()) - op := z.nextb() + addr := z.displace(*iz, z.nextB()) + op := z.nextB() z.exec_opcode_dcb(op, addr) default: // any other FD/DD opcode behaves as a non-prefixed opcode: - z.exec_opcode(opcode) + z.execOpcode(opcode) // R should not be incremented twice: - z.inc_r() + z.incR() } } diff --git a/z80/c99/opcodesED.go b/z80/c99/opcodesED.go index b872b48..9bba34e 100644 --- a/z80/c99/opcodesED.go +++ b/z80/c99/opcodesED.go @@ -3,9 +3,9 @@ package c99 import log "github.com/sirupsen/logrus" // executes a ED opcode -func (z *Z80) exec_opcode_ed(opcode byte) { - z.cyc += uint64(cyc_ed[opcode]) - z.inc_r() +func (z *Z80) execOpcodeED(opcode byte) { + z.cycleCount += uint32(cyclesED[opcode]) + z.incR() switch opcode { case 0x47: z.i = z.a // ld i,a @@ -41,10 +41,10 @@ func (z *Z80) exec_opcode_ed(opcode byte) { { z.ldi() - if z.get_bc() != 0 { + if z.bc() != 0 { z.pc -= 2 - z.cyc += 5 - z.mem_ptr = z.pc + 1 + z.cycleCount += 5 + z.memPtr = z.pc + 1 } } // ldir @@ -54,10 +54,10 @@ func (z *Z80) exec_opcode_ed(opcode byte) { { z.ldd() - if z.get_bc() != 0 { + if z.bc() != 0 { z.pc -= 2 - z.cyc += 5 - z.mem_ptr = z.pc + 1 + z.cycleCount += 5 + z.memPtr = z.pc + 1 } } // lddr @@ -68,10 +68,10 @@ func (z *Z80) exec_opcode_ed(opcode byte) { case 0xB1: // cpir z.cpi() - if z.get_bc() != 0 && !z.zf { + if z.bc() != 0 && !z.zf { z.pc -= 2 - z.cyc += 5 - z.mem_ptr = z.pc + 1 + z.cycleCount += 5 + z.memPtr = z.pc + 1 } else { //z.mem_ptr++ } @@ -79,47 +79,47 @@ func (z *Z80) exec_opcode_ed(opcode byte) { case 0xB9: // cpdr z.cpd() - if z.get_bc() != 0 && !z.zf { + if z.bc() != 0 && !z.zf { z.pc -= 2 - z.cyc += 5 - z.mem_ptr = z.pc + 1 + z.cycleCount += 5 + z.memPtr = z.pc + 1 } else { //z.mem_ptr++ } case 0x40: - z.in_r_c(&z.b) // in b, (c) - z.mem_ptr = z.get_bc() + 1 + z.inRC(&z.b) // in b, (c) + z.memPtr = z.bc() + 1 case 0x48: - z.mem_ptr = z.get_bc() + 1 - z.in_r_c(&z.c) // in c, (c) + z.memPtr = z.bc() + 1 + z.inRC(&z.c) // in c, (c) z.updateXY(z.c) //case 0x4e: // ld c,(iy+dd) case 0x50: - z.in_r_c(&z.d) // in d, (c) - z.mem_ptr = z.get_bc() + 1 + z.inRC(&z.d) // in d, (c) + z.memPtr = z.bc() + 1 case 0x58: // in e, (c) - z.in_r_c(&z.e) - z.mem_ptr = z.get_bc() + 1 + z.inRC(&z.e) + z.memPtr = z.bc() + 1 z.updateXY(z.e) case 0x60: - z.in_r_c(&z.h) // in h, (c) - z.mem_ptr = z.get_bc() + 1 + z.inRC(&z.h) // in h, (c) + z.memPtr = z.bc() + 1 case 0x68: - z.in_r_c(&z.l) // in l, (c) - z.mem_ptr = z.get_bc() + 1 + z.inRC(&z.l) // in l, (c) + z.memPtr = z.bc() + 1 z.updateXY(z.l) case 0x70: // in (c) var val byte - z.in_r_c(&val) - z.mem_ptr = z.get_bc() + 1 + z.inRC(&val) + z.memPtr = z.bc() + 1 case 0x78: // in a, (c) - z.in_r_c(&z.a) - z.mem_ptr = z.get_bc() + 1 + z.inRC(&z.a) + z.memPtr = z.bc() + 1 z.updateXY(z.a) case 0xA2: z.ini() // ini @@ -128,7 +128,7 @@ func (z *Z80) exec_opcode_ed(opcode byte) { z.ini() if z.b > 0 { z.pc -= 2 - z.cyc += 5 + z.cycleCount += 5 } case 0xAA: // ind @@ -138,33 +138,33 @@ func (z *Z80) exec_opcode_ed(opcode byte) { z.ind() if z.b > 0 { z.pc -= 2 - z.cyc += 5 + z.cycleCount += 5 } case 0x41: - z.core.IOWrite(z.get_bc(), z.b) // out (c), b - z.mem_ptr = z.get_bc() + 1 + z.core.IOWrite(z.bc(), z.b) // out (c), b + z.memPtr = z.bc() + 1 case 0x49: - z.core.IOWrite(z.get_bc(), z.c) // out (c), c - z.mem_ptr = z.get_bc() + 1 + z.core.IOWrite(z.bc(), z.c) // out (c), c + z.memPtr = z.bc() + 1 case 0x51: - z.core.IOWrite(z.get_bc(), z.d) // out (c), d - z.mem_ptr = z.get_bc() + 1 + z.core.IOWrite(z.bc(), z.d) // out (c), d + z.memPtr = z.bc() + 1 case 0x59: - z.core.IOWrite(z.get_bc(), z.e) // out (c), e - z.mem_ptr = z.get_bc() + 1 + z.core.IOWrite(z.bc(), z.e) // out (c), e + z.memPtr = z.bc() + 1 case 0x61: - z.core.IOWrite(z.get_bc(), z.h) // out (c), h - z.mem_ptr = z.get_bc() + 1 + z.core.IOWrite(z.bc(), z.h) // out (c), h + z.memPtr = z.bc() + 1 case 0x69: - z.core.IOWrite(z.get_bc(), z.l) // out (c), l - z.mem_ptr = z.get_bc() + 1 + z.core.IOWrite(z.bc(), z.l) // out (c), l + z.memPtr = z.bc() + 1 case 0x71: - z.core.IOWrite(z.get_bc(), 0) // out (c), 0 - z.mem_ptr = z.get_bc() + 1 + z.core.IOWrite(z.bc(), 0) // out (c), 0 + z.memPtr = z.bc() + 1 case 0x79: // out (c), a - z.core.IOWrite(z.get_bc(), z.a) - z.mem_ptr = z.get_bc() + 1 + z.core.IOWrite(z.bc(), z.a) + z.memPtr = z.bc() + 1 case 0xA3: z.outi() // outi case 0xB3: @@ -172,7 +172,7 @@ func (z *Z80) exec_opcode_ed(opcode byte) { z.outi() if z.b > 0 { z.pc -= 2 - z.cyc += 5 + z.cycleCount += 5 } case 0xAB: z.outd() // outd @@ -180,80 +180,80 @@ func (z *Z80) exec_opcode_ed(opcode byte) { // otdr z.outd() if z.b > 0 { - z.cyc += 5 + z.cycleCount += 5 z.pc -= 2 } case 0x42: - z.sbchl(z.get_bc()) // sbc hl,bc + z.sbchl(z.bc()) // sbc hl,bc case 0x52: - z.sbchl(z.get_de()) // sbc hl,de + z.sbchl(z.de()) // sbc hl,de case 0x62: - z.sbchl(z.get_hl()) // sbc hl,hl + z.sbchl(z.hl()) // sbc hl,hl case 0x72: z.sbchl(z.sp) // sbc hl,sp case 0x4A: - z.adchl(z.get_bc()) // adc hl,bc + z.adchl(z.bc()) // adc hl,bc case 0x5A: - z.adchl(z.get_de()) // adc hl,de + z.adchl(z.de()) // adc hl,de case 0x6A: - z.adchl(z.get_hl()) // adc hl,hl + z.adchl(z.hl()) // adc hl,hl case 0x7A: z.adchl(z.sp) // adc hl,sp case 0x43: // ld (**), bc - addr := z.nextw() - z.ww(addr, z.get_bc()) - z.mem_ptr = addr + 1 + addr := z.nextW() + z.ww(addr, z.bc()) + z.memPtr = addr + 1 case 0x53: // ld (**), de - addr := z.nextw() - z.ww(addr, z.get_de()) - z.mem_ptr = addr + 1 + addr := z.nextW() + z.ww(addr, z.de()) + z.memPtr = addr + 1 case 0x63: // ld (**), hl - addr := z.nextw() - z.ww(addr, z.get_hl()) - z.mem_ptr = addr + 1 + addr := z.nextW() + z.ww(addr, z.hl()) + z.memPtr = addr + 1 case 0x73: // ld (**), hl - addr := z.nextw() + addr := z.nextW() z.ww(addr, z.sp) - z.mem_ptr = addr + 1 + z.memPtr = addr + 1 case 0x4B: // ld bc, (**) - addr := z.nextw() - z.set_bc(z.rw(addr)) - z.mem_ptr = addr + 1 + addr := z.nextW() + z.setBC(z.rw(addr)) + z.memPtr = addr + 1 case 0x5B: // ld de, (**) - addr := z.nextw() - z.set_de(z.rw(addr)) - z.mem_ptr = addr + 1 + addr := z.nextW() + z.setDE(z.rw(addr)) + z.memPtr = addr + 1 case 0x6B: // ld hl, (**) - addr := z.nextw() - z.set_hl(z.rw(addr)) - z.mem_ptr = addr + 1 + addr := z.nextW() + z.setHL(z.rw(addr)) + z.memPtr = addr + 1 case 0x7B: // ld sp,(**) - addr := z.nextw() + addr := z.nextW() z.sp = z.rw(addr) - z.mem_ptr = addr + 1 + z.memPtr = addr + 1 case 0x44, 0x54, 0x64, 0x74, 0x4C, 0x5C, 0x6C, 0x7C: z.a = z.subb(0, z.a, false) // neg case 0x46, 0x4e, 0x66, 0x6e: - z.interrupt_mode = 0 // im 0 + z.interruptMode = 0 // im 0 case 0x56, 0x76: - z.interrupt_mode = 1 // im 1 + z.interruptMode = 1 // im 1 case 0x5E, 0x7E: - z.interrupt_mode = 2 // im 2 + z.interruptMode = 2 // im 2 case 0x67: // rrd a := z.a - val := z.rb(z.get_hl()) + val := z.rb(z.hl()) z.a = (a & 0xF0) | (val & 0xF) - z.wb(z.get_hl(), (val>>4)|(a<<4)) + z.wb(z.hl(), (val>>4)|(a<<4)) z.nf = false z.hf = false @@ -261,20 +261,20 @@ func (z *Z80) exec_opcode_ed(opcode byte) { z.zf = z.a == 0 z.sf = z.a&0x80 != 0 z.pf = parity(z.a) - z.mem_ptr = z.get_hl() + 1 + z.memPtr = z.hl() + 1 case 0x6F: // rld a := z.a - val := z.rb(z.get_hl()) + val := z.rb(z.hl()) z.a = (a & 0xF0) | (val >> 4) - z.wb(z.get_hl(), (val<<4)|(a&0xF)) + z.wb(z.hl(), (val<<4)|(a&0xF)) z.nf = false z.hf = false z.updateXY(z.a) z.zf = z.a == 0 z.sf = z.a&0x80 != 0 z.pf = parity(z.a) - z.mem_ptr = z.get_hl() + 1 + z.memPtr = z.hl() + 1 default: log.Errorf("Unknown ED opcode: %02X\n", opcode) } diff --git a/z80/cpu.go b/z80/cpu.go index e2ba65c..4e0e25c 100644 --- a/z80/cpu.go +++ b/z80/cpu.go @@ -17,7 +17,7 @@ type CPUInterface interface { // Reset CPU to initial state Reset() // RunInstruction Run single instruction, return number of CPU cycles - RunInstruction() uint64 + RunInstruction() uint32 // GetState Get current CPU state GetState() *Z80CPU // SetState Set current CPU state @@ -68,7 +68,7 @@ type Z80CPU struct { Halted bool DoDelayedDI bool DoDelayedEI bool - CycleCounter byte + CycleCount uint32 InterruptOccurred bool MemPtr uint16 //core MemIoRW diff --git a/z80/cpu_test.go b/z80/cpu_test.go index a101c5f..7d436d3 100644 --- a/z80/cpu_test.go +++ b/z80/cpu_test.go @@ -6,8 +6,6 @@ import ( _ "embed" "okemu/z80" "okemu/z80/c99" - - // "okemu/z80/c99" "strconv" "strings" "testing" @@ -17,7 +15,7 @@ import ( const ( ScanNone int = iota - ScanDescr + ScanDesc ScanEvent ScanRegs ScanState @@ -157,7 +155,7 @@ func parseTestExpected() { } } if ScanNone == scanState { - scanState = ScanDescr + scanState = ScanDesc } else if len(line) > 0 && line[0] == ' ' { scanState = ScanEvent } @@ -168,7 +166,7 @@ func parseTestExpected() { //} switch scanState { - case ScanDescr: + case ScanDesc: testName = line scanState = ScanRegs case ScanEvent: @@ -214,12 +212,12 @@ func parseTestIn() { continue } if ScanNone == scanState { - scanState = ScanDescr + scanState = ScanDesc } else if line == "-1" { scanState = ScanEnd } switch scanState { - case ScanDescr: + case ScanDesc: testName = line scanState = ScanRegs case ScanRegs: @@ -401,28 +399,21 @@ func TestZ80Fuse(t *testing.T) { t.Logf("Fuse-type Z80 emulator test") computer.cpu.Reset() for _, name := range testNames { - z80Test := z80TestsIn[name] - //t.Logf("Run test: %s", name) - setComputerState(z80Test) - //if name == "edb9" { - // t.Logf("stop test") - //} - + setComputerState(z80TestsIn[name]) exp, exists := z80TestsExpected[name] if !exists { t.Errorf("Expected values for test %s not exists!", name) return } - cy := uint64(0) + cy := uint32(0) for { cy += computer.cpu.RunInstruction() - if cy >= uint64(exp.state.tStates) { + if cy >= uint32(exp.state.tStates) { break } } checkComputerState(t, name) } - } func setComputerState(test Z80TestIn) { @@ -455,7 +446,7 @@ func setComputerState(test Z80TestIn) { Halted: test.state.isHalted, DoDelayedDI: false, DoDelayedEI: false, - CycleCounter: 0, + CycleCount: 0, InterruptOccurred: false, MemPtr: test.registers.MemPtr, } diff --git a/z80/js/constants.go b/z80/js/constants.go deleted file mode 100644 index b9ce480..0000000 --- a/z80/js/constants.go +++ /dev/null @@ -1,101 +0,0 @@ -package js - -const OpHalt = 0x76 -const OpLdBB = 0x40 -const OpAddAB = 0x80 -const OpRetNz = 0xc0 - -var CycleCounts = []byte{ - 4, 10, 7, 6, 4, 4, 7, 4, 4, 11, 7, 6, 4, 4, 7, 4, - 8, 10, 7, 6, 4, 4, 7, 4, 12, 11, 7, 6, 4, 4, 7, 4, - 7, 10, 16, 6, 4, 4, 7, 4, 7, 11, 16, 6, 4, 4, 7, 4, - 7, 10, 13, 6, 11, 11, 10, 4, 7, 11, 13, 6, 4, 4, 7, 4, - 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, - 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, - 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, - 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, - 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, - 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, - 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, - 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, - 5, 10, 10, 10, 10, 11, 7, 11, 5, 10, 10, 0, 10, 17, 7, 11, - 5, 10, 10, 11, 10, 11, 7, 11, 5, 4, 10, 11, 10, 0, 7, 11, - 5, 10, 10, 19, 10, 11, 7, 11, 5, 4, 10, 4, 10, 0, 7, 11, - 5, 10, 10, 4, 10, 11, 7, 11, 5, 6, 10, 4, 10, 0, 7, 11, -} - -var CycleCountsCb = []byte{ - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, - 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, - 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, - 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, - 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, 8, 8, 8, 8, 15, 8, -} - -var CycleCountsDd = []byte{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, - 0, 14, 20, 10, 8, 8, 11, 0, 0, 15, 20, 10, 8, 8, 11, 0, - 0, 0, 0, 0, 23, 23, 19, 0, 0, 15, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 8, 8, 19, 0, 0, 0, 0, 0, 8, 8, 19, 0, - 0, 0, 0, 0, 8, 8, 19, 0, 0, 0, 0, 0, 8, 8, 19, 0, - 8, 8, 8, 8, 8, 8, 19, 8, 8, 8, 8, 8, 8, 8, 19, 8, - 19, 19, 19, 19, 19, 19, 0, 19, 0, 0, 0, 0, 8, 8, 19, 0, - 0, 0, 0, 0, 8, 8, 19, 0, 0, 0, 0, 0, 8, 8, 19, 0, - 0, 0, 0, 0, 8, 8, 19, 0, 0, 0, 0, 0, 8, 8, 19, 0, - 0, 0, 0, 0, 8, 8, 19, 0, 0, 0, 0, 0, 8, 8, 19, 0, - 0, 0, 0, 0, 8, 8, 19, 0, 0, 0, 0, 0, 8, 8, 19, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 14, 0, 23, 0, 15, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, -} - -var CycleCountsEd = []byte{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 12, 12, 15, 20, 8, 14, 8, 9, 12, 12, 15, 20, 8, 14, 8, 9, - 12, 12, 15, 20, 8, 14, 8, 9, 12, 12, 15, 20, 8, 14, 8, 9, - 12, 12, 15, 20, 8, 14, 8, 18, 12, 12, 15, 20, 8, 14, 8, 18, - 12, 12, 15, 20, 8, 14, 8, 0, 12, 12, 15, 20, 8, 14, 8, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16, 16, 16, 16, 0, 0, 0, 0, 16, 16, 16, 16, 0, 0, 0, 0, - 16, 16, 16, 16, 0, 0, 0, 0, 16, 16, 16, 16, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -} - -var ParityBits = []bool{ - true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, - false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, - false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, - true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, - false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, - true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, - true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, - false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, - false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, - true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, - true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, - false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, - true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, - false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, - false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, - true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, -} diff --git a/z80/js/cpu.go b/z80/js/cpu.go deleted file mode 100644 index 9e113c5..0000000 --- a/z80/js/cpu.go +++ /dev/null @@ -1,899 +0,0 @@ -package js - -import ( - "fmt" - "okemu/z80" - - log "github.com/sirupsen/logrus" -) - -type Z80 struct { - z80.Z80CPU - core z80.MemIoRW -} - -func (z *Z80) Reset() { - z.A = 0 - z.R = 0 - z.SP = 0xff - z.PC = 0 - z.Flags.SetFlags(0xff) - // Interrupts disabled - z.IMode = 0 - z.Iff1 = false - z.Iff2 = false - z.InterruptOccurred = false - - // Start not halted - z.Halted = false - z.DoDelayedDI = false - z.DoDelayedEI = false - // no cycles - z.CycleCounter = 0 - fmt.Println("CPUInterface State Reset") -} - -func (z *Z80) GetState() *z80.Z80CPU { - return &z80.Z80CPU{ - A: z.A, - B: z.B, - C: z.C, - D: z.D, - E: z.E, - H: z.H, - L: z.L, - AAlt: z.AAlt, - BAlt: z.BAlt, - CAlt: z.CAlt, - DAlt: z.DAlt, - EAlt: z.EAlt, - HAlt: z.HAlt, - IX: z.IX, - IY: z.IY, - R: z.R, - SP: z.SP, - PC: z.PC, - Flags: z.Flags, - FlagsAlt: z.FlagsAlt, - IMode: z.IMode, - Iff1: z.Iff1, - Iff2: z.Iff2, - Halted: z.Halted, - DoDelayedDI: z.DoDelayedDI, - DoDelayedEI: z.DoDelayedEI, - CycleCounter: z.CycleCounter, - } -} - -func (z *Z80) SetState(state *Z80) { - z.A = state.A - z.B = state.B - z.C = state.C - z.D = state.D - z.E = state.E - z.H = state.H - z.L = state.L - z.AAlt = state.AAlt - z.BAlt = state.BAlt - z.CAlt = state.CAlt - z.DAlt = state.DAlt - z.EAlt = state.EAlt - z.HAlt = state.HAlt - z.IX = state.IX - z.IY = state.IY - z.I = state.I - z.R = state.R - z.SP = state.SP - z.PC = state.PC - z.Flags = state.Flags - z.FlagsAlt = state.FlagsAlt - z.IMode = state.IMode - z.Iff1 = state.Iff1 - z.Iff2 = state.Iff2 - z.Halted = state.Halted - z.DoDelayedDI = state.DoDelayedDI - z.DoDelayedEI = state.DoDelayedEI - z.CycleCounter = state.CycleCounter -} - -// New Create new -func New(memIoRW z80.MemIoRW) *Z80 { - return &Z80{ - Z80CPU: z80.Z80CPU{ - A: 0, - B: 0, - C: 0, - D: 0, - E: 0, - H: 0, - L: 0, - AAlt: 0, - BAlt: 0, - CAlt: 0, - DAlt: 0, - EAlt: 0, - HAlt: 0, - IX: 0, - IY: 0, - - I: 0, - R: 0, - SP: 0xffff, - PC: 0, - - Flags: z80.FlagsType{S: true, Z: true, Y: true, H: true, X: true, P: true, N: true, C: true}, - FlagsAlt: z80.FlagsType{S: true, Z: true, Y: true, H: true, X: true, P: true, N: true, C: true}, - - IMode: 0, - Iff1: false, - Iff2: false, - Halted: false, - DoDelayedDI: false, - DoDelayedEI: false, - CycleCounter: 0, - InterruptOccurred: false, - }, - core: memIoRW, - } -} - -func (z *Z80) RunInstruction() uint64 { - z.incR() - if !z.Halted { - // If the previous instruction was a DI or an EI, - // we'll need to disable or enable interrupts - // after whatever instruction we're about to run is finished. - doingDelayedDi := false - doingDelayedEi := false - if z.DoDelayedDI { - z.DoDelayedDI = false - doingDelayedDi = true - } else if z.DoDelayedEI { - z.DoDelayedEI = false - doingDelayedEi = true - } - // Read the byte at the PC and run the instruction it encodes. - opcode := z.core.M1MemRead(z.PC) - z.decodeInstruction(opcode) - // HALT does not increase the PC - if !z.Halted { - z.PC++ - } - // Actually do the delayed interrupt disable/enable if we have one. - if doingDelayedDi { - z.Iff1 = false - z.Iff2 = false - } else if doingDelayedEi { - z.Iff1 = true - z.Iff2 = true - } - // And finally clear out the cycle counter for the next instruction - // before returning it to the emulator core. - cycleCounter := z.CycleCounter - z.CycleCounter = 0 - return uint64(cycleCounter) - } - // HALTED - // During HALT, NOPs are executed which is 4T - z.core.M1MemRead(z.PC) // HALT does a normal M1 fetch to keep the memory refresh active. The result is ignored (NOP). - return 4 -} - -// Simulates pulsing the processor's INT (or NMI) pin -// -// nonMaskable - true if this is a non-maskable interrupt -// data - the value to be placed on the data bus, if needed -func (z *Z80) interrupt(nonMaskable bool, data byte) { - if nonMaskable { - // An interrupt, if halted, does increase the PC - if z.Halted { - z.PC++ - } - - // The high bit of R is not affected by this increment, - // it can only be changed using the LD R, A instruction. - z.incR() - - // Non-maskable interrupts are always handled the same way; - // clear IFF1 and then do a CALL 0x0066. - // Also, all interrupts reset the HALT state. - - z.Halted = false - z.Iff2 = z.Iff1 - z.Iff1 = false - z.pushWord(z.PC) - z.PC = 0x66 - - z.CycleCounter += 11 - } else if z.Iff1 { - // An interrupt, if halted, does increase the PC - if z.Halted { - z.PC++ - } - - // The high bit of R is not affected by this increment, - // it can only be changed using the LD R,A instruction. - z.incR() - - z.Halted = false - z.Iff1 = false - z.Iff2 = false - - if z.IMode == 0 { - // In the 8080-compatible interrupt mode, - // decode the content of the data bus as an instruction and run it. - // it'z probably a RST instruction, which pushes (PC+1) onto the stack - // so we should decrement PC before we decode the instruction - z.PC-- - z.decodeInstruction(data) - z.PC++ // increment PC upon return - z.CycleCounter += 2 - } else if z.IMode == 1 { - // Mode 1 is always just RST 0x38. - z.pushWord(z.PC) - z.PC = 0x0038 - z.CycleCounter += 13 - } else if z.IMode == 2 { - // Mode 2 uses the value on the data bus as in index - // into the vector table pointer to by the I register. - z.pushWord(z.PC) - - // The Z80 manual says that this address must be 2-byte aligned, - // but it doesn't appear that this is actually the case on the hardware, - // so we don't attempt to enforce that here. - vectorAddress := (uint16(z.I) << 8) | uint16(data) - z.PC = z.getWord(vectorAddress) //uint16( z.core.MemRead(vectorAddress)) | (uint16(z.core.MemRead(vectorAddress+1)) << 8) - z.CycleCounter += 19 - // A "notification" is generated so that the calling program can break on it. - z.InterruptOccurred = true - } - } -} - -func (z *Z80) pushWord(operand uint16) { - z.SP-- - z.core.MemWrite(z.SP, byte(operand>>8)) - z.SP-- - z.core.MemWrite(z.SP, byte(operand&0x00ff)) -} - -func (z *Z80) getOperand(opcode byte) byte { - switch opcode & 0x07 { - case 0: - return z.B - case 1: - return z.C - case 2: - return z.D - case 3: - return z.E - case 4: - return z.H - case 5: - return z.L - case 6: - return z.core.MemRead(z.hl()) - default: - return z.A - } -} - -func (z *Z80) decodeInstruction(opcode byte) { - // Handle HALT right up front, because it fouls up our LD decoding - // by falling where LD (HL), (HL) ought to be. - if opcode == OpHalt { - z.Halted = true - } else if opcode >= OpLdBB && opcode < OpAddAB { - // 8-bit register loads. - z.load8bit(opcode, z.getOperand(opcode)) - } else if (opcode >= OpAddAB) && (opcode < OpRetNz) { - // 8-bit register ALU instructions. - z.alu8bit(opcode, z.getOperand(opcode)) - } else { - fun := instructions[opcode] - fun(z) - } - z.CycleCounter += CycleCounts[opcode] -} - -func (z *Z80) load8bit(opcode byte, operand byte) { - switch (opcode & 0x38) >> 3 { - case 0: - z.B = operand - case 1: - z.C = operand - case 2: - z.D = operand - case 3: - z.E = operand - case 4: - z.H = operand - case 5: - z.L = operand - case 6: - z.core.MemWrite(z.hl(), operand) - default: - z.A = operand - } -} - -// alu8bit Handle ALU Operations, ADD, ADC SUB, SBC, AND, XOR, OR -func (z *Z80) alu8bit(opcode byte, operand byte) { - switch (opcode & 0x38) >> 3 { - case 0: - z.doAdd(operand) - case 1: - z.doAdc(operand) - case 2: - z.doSub(operand) - case 3: - z.doSbc(operand) - case 4: - z.doAnd(operand) - case 5: - z.doXor(operand) - case 6: - z.doOr(operand) - default: - z.doCp(operand) - } -} - -// updateXYFlags Set flags X and Y based on result bits -func (z *Z80) updateXYFlags(result byte) { - z.Flags.Y = result&0x20 != 0 - z.Flags.X = result&0x08 != 0 -} - -// PushWord - Decrement stack pointer and put specified word value to stack -func (z *Z80) PushWord(operand uint16) { - z.SP-- - z.core.MemWrite(z.SP, byte((operand&0xff00)>>8)) - z.SP-- - z.core.MemWrite(z.SP, byte(operand&0x00ff)) -} - -// PopWord - Get word value from top of stack and increment stack pointer -func (z *Z80) PopWord() uint16 { - result := uint16(z.core.MemRead(z.SP)) - z.SP++ - result |= uint16(z.core.MemRead(z.SP)) << 8 - z.SP++ - return result -} - -// doConditionalAbsoluteJump - Implements the JP [condition],nn instructions. -func (z *Z80) doConditionalAbsoluteJump(condition bool) { - if condition { - // We're taking this jump, so write the new PC, - // and then decrement the thing we just wrote, - // because the instruction decoder increments the PC - // unconditionally at the end of every instruction, - // and we need to counteract that so we end up at the jump target. - z.PC = z.getWord(z.PC + 1) //uint16( z.core.MemRead(z.PC+1)) | (uint16(z.core.MemRead(z.PC+2)) << 8) - z.PC-- - } else { - // We're not taking this jump, just move the PC past the operand. - z.PC += 2 - } -} - -// doConditionalRelativeJump - Implements the JR [condition],nn instructions. -func (z *Z80) doConditionalRelativeJump(condition bool) { - if condition { - // We need a few more cycles to actually take the jump. - z.CycleCounter += 5 - // Calculate the offset specified by our operand. - offset := z.core.MemRead(z.PC + 1) - - // Add the offset to the PC, also skipping past this instruction. - if offset < 0 { - z.PC = z.PC - uint16(-offset) - } else { - z.PC = z.PC + uint16(offset) - } - } - z.PC++ -} - -// doConditionalCall - Implements CALL [condition],nn instructions. -func (z *Z80) doConditionalCall(condition bool) { - if condition { - z.CycleCounter += 7 - z.PushWord(z.PC + 3) - z.PC = z.getWord(z.PC + 1) // uint16( z.core.MemRead(z.PC+1)) | (uint16(z.core.MemRead(z.PC+2)) << 8) - z.PC-- - } else { - z.PC += 2 - } -} - -func (z *Z80) doConditionalReturn(condition bool) { - if condition { - z.CycleCounter += 6 - z.PC = z.PopWord() - 1 - } -} - -// doReset - Implements RST [address] instructions. -func (z *Z80) doReset(address uint16) { - z.PushWord(z.PC + 1) - z.PC = address - 1 -} - -// doAdd Handle ADD A, [operand] instructions. -func (z *Z80) doAdd(operand byte) { - var result = uint16(z.A) + uint16(operand) - z.Flags.S = result&0x80 != 0 - z.Flags.Z = result&0x00ff == 0 - z.Flags.H = (((operand & 0x0f) + (z.A & 0x0f)) & 0x10) != 0 - z.Flags.P = ((z.A & 0x80) == (operand & 0x80)) && (z.A&0x80 != byte(result&0x80)) - z.Flags.N = false - z.Flags.C = result&0x0100 != 0 - z.A = byte(result & 0xff) - z.updateXYFlags(z.A) -} - -// doAdc Handle ADC A, [operand] instructions. -func (z *Z80) doAdc(operand byte) { - add := byte(0) - if z.Flags.C { - add = 1 - } - var result = uint16(z.A) + uint16(operand) + uint16(add) - z.Flags.S = result&0x80 != 0 - z.Flags.Z = result&0x00ff == 0 - z.Flags.H = (((operand & 0x0f) + (z.A & 0x0f) + add) & 0x10) != 0 - z.Flags.P = ((z.A & 0x80) == (operand & 0x80)) && (z.A&0x80 != byte(result&0x80)) - z.Flags.N = false - z.Flags.C = result&0x0100 != 0 - z.A = byte(result & 0xff) - z.updateXYFlags(z.A) -} - -// doSub Handle SUB A, [operand] instructions. -func (z *Z80) doSub(operand byte) { - var result = uint16(z.A) - uint16(operand) - z.Flags.S = result&0x80 != 0 - z.Flags.Z = result&0x00ff == 0 - z.Flags.H = (((z.A & 0x0f) - (operand & 0x0f)) & 0x10) != 0 - z.Flags.P = ((z.A & 0x80) != (operand & 0x80)) && ((z.A & 0x80) != byte(result&0x80)) - z.Flags.N = true - z.Flags.C = result&0x0100 != 0 - z.A = byte(result & 0xff) - z.updateXYFlags(z.A) -} - -// doSbc Handle SBC A, [operand] instructions. -func (z *Z80) doSbc(operand byte) { - sub := byte(0) - if z.Flags.C { - sub = 1 - } - var result = uint16(z.A) - uint16(operand) - uint16(sub) - z.Flags.S = result&0x80 != 0 - z.Flags.Z = result&0x00ff == 0 - z.Flags.H = (((z.A & 0x0f) - (operand & 0x0f) - sub) & 0x10) != 0 - z.Flags.P = ((z.A & 0x80) != (operand & 0x80)) && (z.A&0x80 != byte(result&0x80)) - z.Flags.N = true - z.Flags.C = result&0x0100 != 0 - z.A = byte(result & 0xff) - z.updateXYFlags(z.A) -} - -// setLogicFlags Set common flags for logic ALU Ops -func (z *Z80) setLogicFlags() { - z.Flags.S = z.A&0x80 != 0 - z.Flags.Z = z.A == 0 - z.Flags.P = ParityBits[z.A] - z.Flags.N = false - z.Flags.C = false -} - -// doAnd handle AND [operand] instructions. -func (z *Z80) doAnd(operand byte) { - z.A &= operand - z.setLogicFlags() - z.Flags.H = true - z.updateXYFlags(z.A) -} - -// doXor handle XOR [operand] instructions. -func (z *Z80) doXor(operand byte) { - z.A ^= operand - z.setLogicFlags() - z.Flags.H = false - z.updateXYFlags(z.A) -} - -// doOr handle OR [operand] instructions. -func (z *Z80) doOr(operand byte) { - z.A |= operand - z.setLogicFlags() - z.Flags.H = false - z.updateXYFlags(z.A) -} - -// doCp handle CP [operand] instructions. -func (z *Z80) doCp(operand byte) { - tmp := z.A - z.doSub(operand) - z.A = tmp - z.updateXYFlags(operand) -} - -// doInc handle INC [operand] instructions. -func (z *Z80) doInc(operand byte) byte { - var result = uint16(operand) + 1 - r8 := byte(result & 0xff) - z.Flags.S = r8&0x80 != 0 - z.Flags.Z = r8 == 0 - z.Flags.H = (operand & 0x0f) == 0x0f - z.Flags.P = operand == 0x7f - z.Flags.N = false - z.updateXYFlags(r8) - return r8 -} - -// doDec handle DEC [operand] instructions. -func (z *Z80) doDec(operand byte) byte { - var result = uint16(operand) - 1 - r8 := byte(result & 0xff) - z.Flags.S = r8&0x80 != 0 - z.Flags.Z = r8 == 0 - z.Flags.H = (operand & 0x0f) == 0x00 - z.Flags.P = operand == 0x80 - z.Flags.N = true - z.updateXYFlags(r8) - return r8 -} - -// doHlAdd handle ADD HL,[operand] instructions. -func (z *Z80) doHlAdd(operand uint16) { - // The HL arithmetic instructions are the same as the A ones, - // just with twice as many bits happening. - hl := z.hl() //uint16(z.L) | (uint16(z.H) << 8) - result := uint32(hl) + uint32(operand) - z.Flags.N = false - z.Flags.C = result > 0xffff - z.Flags.H = ((hl&0x0fff)+(operand&0x0fff))&0x1000 > 0 - z.setHl(uint16(result)) - z.updateXYFlags(z.H) -} - -// doHlAdc handle ADC HL,[operand] instructions. -func (z *Z80) doHlAdc(operand uint16) { - if z.Flags.C { - operand++ - } - hl := z.hl() - result := uint32(hl) + uint32(operand) - z.Flags.S = (result & 0x8000) != 0 - z.Flags.Z = result&0xffff == 0 - z.Flags.H = (((hl & 0x0fff) + (operand & 0x0fff)) & 0x1000) != 0 - z.Flags.P = ((hl & 0x8000) == (operand & 0x8000)) && (uint16(result&0x8000) != (hl & 0x8000)) - z.Flags.N = false - z.Flags.C = result > 0xffff - z.setHl(uint16(result)) - z.updateXYFlags(z.H) -} - -// doHlSbc handle SBC HL,[operand] instructions. -func (z *Z80) doHlSbc(operand uint16) { - if z.Flags.C { - operand++ - } - - hl := z.hl() //uint16(z.L) | (uint16(z.H) << 8) - result := uint32(hl) - uint32(operand) - - z.Flags.S = (result & 0x8000) != 0 - z.Flags.Z = result&0xffff == 0 - z.Flags.H = (((hl & 0x0fff) - (operand & 0x0fff)) & 0x1000) != 0 - z.Flags.P = ((hl & 0x8000) != (operand & 0x8000)) && (uint16(result&0x8000) != (hl & 0x8000)) - z.Flags.N = true - z.Flags.C = result > 0xffff - - z.setHl(uint16(result)) - - z.updateXYFlags(z.H) -} - -func (z *Z80) doIn(port uint16) byte { - var result = z.core.IORead(port) - - z.Flags.S = result&0x80 != 0 - z.Flags.Z = result == 0 - z.Flags.H = false - z.Flags.P = ParityBits[result] - z.Flags.N = false - z.updateXYFlags(result) - return result -} - -func (z *Z80) doNeg() { - // This instruction is defined to not alter the register if it === 0x80. - a := int8(z.A) - if z.A != 0x80 { - // This is a signed operation, so convert A to a signed value. - z.A = byte(-a) - } - z.Flags.S = z.A&0x80 != 0 - z.Flags.Z = z.A == 0 - z.Flags.H = ((-a) & 0x0f) > 0 - z.Flags.P = z.A == 0x80 - z.Flags.N = true - z.Flags.C = z.A != 0 - z.updateXYFlags(z.A) -} - -func (z *Z80) doLdi() { - // Copy the value that we're supposed to copy. - readValue := z.core.MemRead(z.hl()) - z.core.MemWrite(z.de(), readValue) - - z.incDe() - z.incHl() - z.decBc() - - z.Flags.H = false - z.Flags.P = (z.C | z.B) != 0 - z.Flags.N = false - z.Flags.Y = ((z.A+readValue)&0x02)>>1 != 0 - z.Flags.X = ((z.A+readValue)&0x08)>>3 != 0 -} - -func (z *Z80) fhv() byte { - if z.Flags.H { - return 1 - } - return 0 -} - -func (z *Z80) doCpi() { - tempCarry := z.Flags.C - readValue := z.core.MemRead(z.hl()) - z.doCp(readValue) - - z.Flags.C = tempCarry - fh := z.fhv() - z.Flags.Y = ((z.A - readValue - fh) & 0x02) != 0 - z.Flags.X = ((z.A - readValue - fh) & 0x08) != 0 - z.incHl() - z.decBc() - z.Flags.P = (z.B | z.C) != 0 -} - -func (z *Z80) doIni() { - z.core.MemWrite(z.hl(), z.core.IORead(z.bc())) - z.incHl() - z.B = z.doDec(z.B) - z.Flags.N = true -} - -func (z *Z80) doOuti() { - z.B = z.doDec(z.B) - z.core.IOWrite(z.bc(), z.core.MemRead(z.hl())) - z.incHl() - z.Flags.N = true -} - -func (z *Z80) doLdd() { - z.Flags.N = false - z.Flags.H = false - readValue := z.core.MemRead(z.hl()) - z.core.MemWrite(z.de(), readValue) - z.decDe() - z.decHl() - z.decBc() - z.Flags.P = (z.C | z.B) != 0 - z.Flags.Y = ((z.A + readValue) & 0x02) != 0 - z.Flags.X = ((z.A + readValue) & 0x08) != 0 -} - -func (z *Z80) doCpd() { - tempCarry := z.Flags.C - readValue := z.core.MemRead(z.hl()) - z.doCp(readValue) - - z.Flags.C = tempCarry - - fh := z.fhv() - - z.Flags.Y = ((z.A-readValue-fh)&0x02)>>1 != 0 - z.Flags.X = ((z.A-readValue-fh)&0x08)>>3 != 0 - - z.decHl() - z.decBc() - - z.Flags.P = (z.B | z.C) != 0 -} - -func (z *Z80) doInd() { - z.core.MemWrite(z.hl(), z.core.IORead(z.bc())) - z.decHl() - z.B = z.doDec(z.B) - z.Flags.N = true -} - -func (z *Z80) doOutd() { - z.B = z.doDec(z.B) - z.core.IOWrite(z.bc(), z.core.MemRead(z.hl())) - z.decHl() - z.Flags.N = true -} - -type OpShift func(operand byte) byte - -func (z *Z80) doRlc(operand byte) byte { - z.Flags.C = operand&0x80 != 0 - var fc byte = 0 - if z.Flags.C { - fc = 1 - } - operand = (operand << 1) | fc - z.setShiftFlags(operand) - return operand -} - -func (z *Z80) doRrc(operand byte) byte { - z.Flags.C = operand&1 != 0 - var fc byte = 0 - if z.Flags.C { - fc = 0x80 - } - operand = ((operand >> 1) & 0x7f) | fc - z.setShiftFlags(operand) - return operand -} - -func (z *Z80) doRl(operand byte) byte { - var fc byte = 0 - if z.Flags.C { - fc = 1 - } - z.Flags.C = operand&0x80 != 0 - operand = (operand << 1) | fc - z.setShiftFlags(operand) - return operand -} - -func (z *Z80) doRr(operand byte) byte { - var fc byte = 0 - if z.Flags.C { - fc = 0x80 - } - z.Flags.C = operand&1 != 0 - operand = ((operand >> 1) & 0x7f) | fc - z.setShiftFlags(operand) - return operand -} - -func (z *Z80) doSla(operand byte) byte { - z.Flags.C = operand&0x80 != 0 - operand = operand << 1 - z.setShiftFlags(operand) - return operand -} - -func (z *Z80) doSra(operand byte) byte { - z.Flags.C = operand&1 != 0 - operand = ((operand >> 1) & 0x7f) | (operand & 0x80) - z.setShiftFlags(operand) - return operand -} - -func (z *Z80) doSll(operand byte) byte { - z.Flags.C = operand&0x80 != 0 - operand = (operand << 1) | 1 - z.setShiftFlags(operand) - return operand -} - -func (z *Z80) doSrl(operand byte) byte { - z.Flags.C = operand&1 != 0 - operand = (operand >> 1) & 0x7f - z.setShiftFlags(operand) - z.Flags.S = false - return operand -} - -func (z *Z80) doIxAdd(operand uint16) { - z.Flags.N = false - result := uint32(z.IX) + uint32(operand) - z.Flags.C = result > 0xffff - z.Flags.H = (((z.IX & 0xfff) + (operand & 0xfff)) & 0x1000) != 0 - - z.updateXYFlags(byte((result & 0xff00) >> 8)) - z.IX = uint16(result & 0xffff) -} - -func (z *Z80) setShiftFlags(operand byte) { - z.Flags.N = false - z.Flags.H = false - z.Flags.Z = operand == 0 - z.Flags.P = ParityBits[operand] - z.Flags.S = (operand & 0x80) != 0 - z.updateXYFlags(operand) -} - -// ============== get register pairs - -func (z *Z80) bc() uint16 { - return (uint16(z.B) << 8) | uint16(z.C) -} - -func (z *Z80) de() uint16 { - return (uint16(z.D) << 8) | uint16(z.E) -} - -func (z *Z80) hl() uint16 { - return (uint16(z.H) << 8) | uint16(z.L) -} - -// ============ helper fn - -func (z *Z80) incBc() { - z.setBc(z.bc() + 1) -} - -func (z *Z80) decBc() { - z.setBc(z.bc() - 1) -} - -func (z *Z80) incDe() { - z.setDe(z.de() + 1) -} - -func (z *Z80) decDe() { - z.setDe(z.de() - 1) -} - -func (z *Z80) incHl() { - z.setHl(z.hl() + 1) -} - -func (z *Z80) decHl() { - z.setHl(z.hl() - 1) -} - -func (z *Z80) setHl(val uint16) { - z.L = byte(val & 0xff) - z.H = byte(val >> 8) -} - -func (z *Z80) setDe(val uint16) { - z.E = byte(val & 0xff) - z.D = byte(val >> 8) -} - -func (z *Z80) setBc(val uint16) { - z.C = byte(val & 0xff) - z.B = byte(val >> 8) -} - -// incR Increment R at the start of every instruction cycle. -// The high bit of R is not affected by this increment, -// it can only be changed using the LD R, A instruction. -// Note: also a HALT does increment the R register. -func (z *Z80) incR() { - z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f) -} - -// getWord Return 16bit value from memory by specified address -func (z *Z80) getWord(address uint16) uint16 { - return (uint16(z.core.MemRead(address+1)) << 8) | uint16(z.core.MemRead(address)) -} - -func (z *Z80) setWord(address uint16, value uint16) { - z.core.MemWrite(address, byte(value)) - z.core.MemWrite(address+1, byte(value>>8)) -} - -func (z *Z80) debugOutput() { - 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.Flags.GetFlags()), z.bc(), z.de(), z.hl(), z.SP, z.IX, z.IY, z.I, z.R) - - log.Debugf("\t(%02X %02X %02X %02X), cyc: %d\n", z.core.MemRead(z.PC), z.core.MemRead(z.PC+1), - z.core.MemRead(z.PC+2), z.core.MemRead(z.PC+3), z.CycleCounter) -} diff --git a/z80/js/opcode.go b/z80/js/opcode.go deleted file mode 100644 index fb1d936..0000000 --- a/z80/js/opcode.go +++ /dev/null @@ -1,657 +0,0 @@ -package js - -var instructions = []func(s *Z80){ - // NOP - 0x00: func(s *Z80) { - // NOP - }, - // LD BC, nn - 0x01: func(s *Z80) { - s.PC++ - s.C = s.core.MemRead(s.PC) - s.PC++ - s.B = s.core.MemRead(s.PC) - }, - // LD (BC), A - 0x02: func(s *Z80) { - s.core.MemWrite(s.bc(), s.A) - }, - // 0x03 : INC BC - 0x03: func(s *Z80) { - s.incBc() - }, - // 0x04 : INC B - 0x04: func(s *Z80) { - s.B = s.doInc(s.B) - }, - // 0x05 : DEC B - 0x05: func(s *Z80) { - s.B = s.doDec(s.B) - }, - // 0x06 : LD B, n - 0x06: func(s *Z80) { - s.PC++ - s.B = s.core.MemRead(s.PC) - }, - // 0x07 : RLCA - 0x07: func(s *Z80) { - // This instruction is implemented as a special case of the - // more general Z80-specific RLC instruction. - // Specifially, RLCA is a version of RLC A that affects fewer flags. - // The same applies to RRCA, RLA, and RRA. - tempS := s.Flags.S - tempZ := s.Flags.Z - tempP := s.Flags.P - s.A = s.doRlc(s.A) - s.Flags.S = tempS - s.Flags.Z = tempZ - s.Flags.P = tempP - }, - // 0x08 : EX AF, AF' - 0x08: func(s *Z80) { - s.A, s.AAlt = s.AAlt, s.A - temp := s.Flags.GetFlags() - s.Flags.SetFlags(s.FlagsAlt.GetFlags()) //setFlagsRegister(s.getFlagsPrimeRegister()) - s.FlagsAlt.SetFlags(temp) - }, - // 0x09 : ADD HL, BC - 0x09: func(s *Z80) { - s.doHlAdd(s.bc()) - }, - // 0x0a : LD A, (BC) - 0x0A: func(s *Z80) { - s.A = s.core.MemRead(s.bc()) - }, - // 0x0b : DEC BC - 0x0B: func(s *Z80) { - s.decBc() - }, - // 0x0c : INC C - 0x0C: func(s *Z80) { - s.C = s.doInc(s.C) - }, - // 0x0d : DEC C - 0x0D: func(s *Z80) { - s.C = s.doDec(s.C) - }, - // 0x0e : LD C, n - 0x0E: func(s *Z80) { - s.PC++ - s.C = s.core.MemRead(s.PC) - }, - // 0x0f : RRCA - 0x0F: func(s *Z80) { - tempS := s.Flags.S - tempZ := s.Flags.Z - tempP := s.Flags.P - s.A = s.doRrc(s.A) - s.Flags.S = tempS - s.Flags.Z = tempZ - s.Flags.P = tempP - }, - // 0x10 : DJNZ nn - 0x10: func(s *Z80) { - s.B-- - s.doConditionalRelativeJump(s.B != 0) - }, - // 0x11 : LD DE, nn - 0x11: func(s *Z80) { - s.PC++ - s.E = s.core.MemRead(s.PC) - s.PC++ - s.D = s.core.MemRead(s.PC) - }, - // 0x12 : LD (DE), A - 0x12: func(s *Z80) { - s.core.MemWrite(s.de(), s.A) - }, - // 0x13 : INC DE - 0x13: func(s *Z80) { - s.incDe() - }, - // 0x14 : INC D - 0x14: func(s *Z80) { - s.D = s.doInc(s.D) - }, - // 0x15 : DEC D - 0x15: func(s *Z80) { - s.D = s.doDec(s.D) - }, - // 0x16 : LD D, n - 0x16: func(s *Z80) { - s.PC++ - s.D = s.core.MemRead(s.PC) - }, - // 0x17 : RLA - 0x17: func(s *Z80) { - tempS := s.Flags.S - tempZ := s.Flags.Z - tempP := s.Flags.P - s.A = s.doRl(s.A) - s.Flags.S = tempS - s.Flags.Z = tempZ - s.Flags.P = tempP - }, - // 0x18 : JR n - 0x18: func(s *Z80) { - var o = int8(s.core.MemRead(s.PC + 1)) - if o > 0 { - s.PC += uint16(o) - } else { - s.PC -= uint16(-o) - } - s.PC++ - }, - // 0x19 : ADD HL, DE - 0x19: func(s *Z80) { - s.doHlAdd(s.de()) - }, - // 0x1a : LD A, (DE) - 0x1A: func(s *Z80) { - s.A = s.core.MemRead(s.de()) - }, - // 0x1b : DEC DE - 0x1B: func(s *Z80) { - s.decDe() - }, - // 0x1c : INC E - 0x1C: func(s *Z80) { - s.E = s.doInc(s.E) - }, - // 0x1d : DEC E - 0x1D: func(s *Z80) { - s.E = s.doDec(s.E) - }, - // 0x1e : LD E, n - 0x1E: func(s *Z80) { - s.PC++ - s.E = s.core.MemRead(s.PC) - }, - // 0x1f : RRA - 0x1F: func(s *Z80) { - tempS := s.Flags.S - tempZ := s.Flags.Z - tempP := s.Flags.P - s.A = s.doRr(s.A) - s.Flags.S = tempS - s.Flags.Z = tempZ - s.Flags.P = tempP - }, - // 0x20 : JR NZ, n - 0x20: func(s *Z80) { - s.doConditionalRelativeJump(!s.Flags.Z) - }, - // 0x21 : LD HL, nn - 0x21: func(s *Z80) { - s.PC++ - s.L = s.core.MemRead(s.PC) - s.PC++ - s.H = s.core.MemRead(s.PC) - }, - // 0x22 : LD (nn), HL - 0x22: func(s *Z80) { - addr := s.nextWord() - s.core.MemWrite(addr, s.L) - s.core.MemWrite(addr+1, s.H) - }, - // 0x23 : INC HL - 0x23: func(s *Z80) { - s.incHl() - }, - // 0x24 : INC H - 0x24: func(s *Z80) { - s.H = s.doInc(s.H) - }, - // 0x25 : DEC H - 0x25: func(s *Z80) { - s.H = s.doDec(s.H) - }, - // 0x26 : LD H, n - 0x26: func(s *Z80) { - s.PC++ - s.H = s.core.MemRead(s.PC) - }, - // 0x27 : DAA - 0x27: func(s *Z80) { - temp := s.A - if !s.Flags.N { - if s.Flags.H || ((s.A & 0x0f) > 9) { - temp += 0x06 - } - if s.Flags.C || (s.A > 0x99) { - temp += 0x60 - } - } else { - if s.Flags.H || ((s.A & 0x0f) > 9) { - temp -= 0x06 - } - if s.Flags.C || (s.A > 0x99) { - temp -= 0x60 - } - } - - s.Flags.S = (temp & 0x80) != 0 - s.Flags.Z = temp == 0 - s.Flags.H = ((s.A & 0x10) ^ (temp & 0x10)) != 0 - s.Flags.P = ParityBits[temp] - // DAA never clears the carry flag if it was already set, - // but it is able to set the carry flag if it was clear. - // Don't ask me, I don't know. - // Note also that we check for a BCD carry, instead of the usual. - s.Flags.C = s.Flags.C || (s.A > 0x99) - s.A = temp - s.updateXYFlags(s.A) - }, - // 0x28 : JR Z, n - 0x28: func(s *Z80) { - s.doConditionalRelativeJump(s.Flags.Z) - }, - // 0x29 : ADD HL, HL - 0x29: func(s *Z80) { - s.doHlAdd(s.hl()) - }, - // 0x2a : LD HL, (nn) - 0x2A: func(s *Z80) { - addr := s.nextWord() - s.L = s.core.MemRead(addr) - s.H = s.core.MemRead(addr + 1) - }, - // 0x2b : DEC HL - 0x2B: func(s *Z80) { - s.decHl() - }, - // 0x2c : INC L - 0x2C: func(s *Z80) { - s.L = s.doInc(s.L) - }, - // 0x2d : DEC L - 0x2D: func(s *Z80) { - s.L = s.doDec(s.L) - }, - // 0x2e : LD L, n - 0x2E: func(s *Z80) { - s.PC++ - s.L = s.core.MemRead(s.PC) - }, - // 0x2f : CPL - 0x2F: func(s *Z80) { - s.A = ^s.A - s.Flags.N = true - s.Flags.H = true - s.updateXYFlags(s.A) - }, - // 0x30 : JR NC, n - 0x30: func(s *Z80) { - s.doConditionalRelativeJump(!s.Flags.C) - }, - // 0x31 : LD SP, nn - 0x31: func(s *Z80) { - s.PC++ - lo := s.core.MemRead(s.PC) - s.PC++ - s.SP = (uint16(s.core.MemRead(s.PC)) << 8) | uint16(lo) - }, - // 0x32 : LD (nn), A - 0x32: func(s *Z80) { - s.core.MemWrite(s.nextWord(), s.A) - }, - // 0x33 : INC SP - 0x33: func(s *Z80) { - s.SP++ - }, - // 0x34 : INC (HL) - 0x34: func(s *Z80) { - s.core.MemWrite(s.hl(), s.doInc(s.core.MemRead(s.hl()))) - }, - // 0x35 : DEC (HL) - 0x35: func(s *Z80) { - s.core.MemWrite(s.hl(), s.doDec(s.core.MemRead(s.hl()))) - }, - // 0x36 : LD (HL), n - 0x36: func(s *Z80) { - s.PC++ - s.core.MemWrite(s.hl(), s.core.MemRead(s.PC)) - }, - // 0x37 : SCF - 0x37: func(s *Z80) { - s.Flags.N = false - s.Flags.H = false - s.Flags.C = true - s.updateXYFlags(s.A) - }, - // 0x38 : JR C, n - 0x38: func(s *Z80) { - s.doConditionalRelativeJump(s.Flags.C) - }, - // 0x39 : ADD HL, SP - 0x39: func(s *Z80) { - s.doHlAdd(s.SP) - }, - // 0x3a : LD A, (nn) - 0x3A: func(s *Z80) { - s.A = s.core.MemRead(s.nextWord()) - }, - // 0x3b : DEC SP - 0x3B: func(s *Z80) { - s.SP-- - }, - // 0x3c : INC A - 0x3C: func(s *Z80) { - s.A = s.doInc(s.A) - }, - // 0x3d : DEC A - 0x3D: func(s *Z80) { - s.A = s.doDec(s.A) - }, - // 0x3e : LD A, n - 0x3E: func(s *Z80) { - s.PC++ - s.A = s.core.MemRead(s.PC) - }, - // 0x3f : CCF - 0x3F: func(s *Z80) { - s.Flags.N = false - s.Flags.H = s.Flags.C - s.Flags.C = !s.Flags.C - s.updateXYFlags(s.A) - }, - // 0xc0 : RET NZ - 0xC0: func(s *Z80) { - s.doConditionalReturn(!s.Flags.Z) - }, - // 0xc1 : POP BC - 0xC1: func(s *Z80) { - result := s.PopWord() - s.C = byte(result & 0xff) - s.B = byte((result & 0xff00) >> 8) - }, - // 0xc2 : JP NZ, nn - 0xC2: func(s *Z80) { - s.doConditionalAbsoluteJump(!s.Flags.Z) - }, - // 0xc3 : JP nn - 0xC3: func(s *Z80) { - s.PC = uint16(s.core.MemRead(s.PC+1)) | (uint16(s.core.MemRead(s.PC+2)) << 8) - s.PC-- - }, - // 0xc4 : CALL NZ, nn - 0xC4: func(s *Z80) { - s.doConditionalCall(!s.Flags.Z) - }, - // 0xc5 : PUSH BC - 0xC5: func(s *Z80) { - s.pushWord((uint16(s.B) << 8) | uint16(s.C)) - }, - // 0xc6 : ADD A, n - 0xC6: func(s *Z80) { - s.PC++ - s.doAdd(s.core.MemRead(s.PC)) - }, - // 0xc7 : RST 00h - 0xC7: func(s *Z80) { - s.doReset(0x0000) - }, - // 0xc8 : RET Z - 0xC8: func(s *Z80) { - s.doConditionalReturn(s.Flags.Z) - }, - // 0xc9 : RET - 0xC9: func(s *Z80) { - s.PC = s.PopWord() - 1 - }, - // 0xca : JP Z, nn - 0xCA: func(s *Z80) { - s.doConditionalAbsoluteJump(s.Flags.Z) - }, - // 0xcb : CB Prefix - 0xCB: func(s *Z80) { - s.opcodeCB() - }, - // 0xcc : CALL Z, nn - 0xCC: func(s *Z80) { - s.doConditionalCall(s.Flags.Z) - }, - // 0xcd : CALL nn - 0xCD: func(s *Z80) { - s.pushWord(s.PC + 3) - s.PC = uint16(s.core.MemRead(s.PC+1)) | (uint16(s.core.MemRead(s.PC+2)) << 8) - s.PC-- - }, - // 0xce : ADC A, n - 0xCE: func(s *Z80) { - s.PC++ - s.doAdc(s.core.MemRead(s.PC)) - }, - // 0xcf : RST 08h - 0xCF: func(s *Z80) { - s.doReset(0x0008) - }, - // 0xd0 : RET NC - 0xD0: func(s *Z80) { - s.doConditionalReturn(!s.Flags.C) - }, - // 0xd1 : POP DE - 0xD1: func(s *Z80) { - result := s.PopWord() - s.E = byte(result & 0xff) - s.D = byte((result & 0xff00) >> 8) - }, - // 0xd2 : JP NC, nn - 0xD2: func(s *Z80) { - s.doConditionalAbsoluteJump(!s.Flags.C) - }, - // 0xd3 : OUT (n), A - 0xD3: func(s *Z80) { - s.PC++ - s.core.IOWrite((uint16(s.A)<<8)|uint16(s.core.MemRead(s.PC)), s.A) - }, - // 0xd4 : CALL NC, nn - 0xD4: func(s *Z80) { - s.doConditionalCall(!s.Flags.C) - }, - // 0xd5 : PUSH DE - 0xD5: func(s *Z80) { - s.pushWord((uint16(s.D) << 8) | uint16(s.E)) - }, - // 0xd6 : SUB n - 0xD6: func(s *Z80) { - s.PC++ - s.doSub(s.core.MemRead(s.PC)) - }, - // 0xd7 : RST 10h - 0xD7: func(s *Z80) { - s.doReset(0x0010) - }, - // 0xd8 : RET C - 0xD8: func(s *Z80) { - s.doConditionalReturn(s.Flags.C) - }, - // 0xd9 : EXX - 0xD9: func(s *Z80) { - s.B, s.BAlt = s.BAlt, s.B - s.C, s.CAlt = s.CAlt, s.C - s.D, s.DAlt = s.DAlt, s.D - s.E, s.EAlt = s.EAlt, s.E - s.H, s.HAlt = s.HAlt, s.H - s.L, s.LAlt = s.LAlt, s.L - }, - // 0xda : JP C, nn - 0xDA: func(s *Z80) { - s.doConditionalAbsoluteJump(s.Flags.C) - }, - // 0xdb : IN A, (n) - 0xDB: func(s *Z80) { - s.PC++ - s.A = s.core.IORead((uint16(s.A) << 8) | uint16(s.core.MemRead(s.PC))) - }, - // 0xdc : CALL C, nn - 0xDC: func(s *Z80) { - s.doConditionalCall(s.Flags.C) - }, - // 0xdd : DD Prefix (IX instructions) - 0xDD: func(s *Z80) { - s.opcodeDD() - }, - // 0xde : SBC n - 0xDE: func(s *Z80) { - s.PC++ - s.doSbc(s.core.MemRead(s.PC)) - }, - // 0xdf : RST 18h - 0xDF: func(s *Z80) { - s.doReset(0x0018) - }, - // 0xe0 : RET PO - 0xE0: func(s *Z80) { - s.doConditionalReturn(!s.Flags.P) - }, - // 0xe1 : POP HL - 0xE1: func(s *Z80) { - result := s.PopWord() - s.L = byte(result & 0xff) - s.H = byte((result & 0xff00) >> 8) - }, - // 0xe2 : JP PO, (nn) - 0xE2: func(s *Z80) { - s.doConditionalAbsoluteJump(!s.Flags.P) - }, - // 0xe3 : EX (SP), HL - 0xE3: func(s *Z80) { - temp := s.core.MemRead(s.SP) - s.core.MemWrite(s.SP, s.L) - s.L = temp - temp = s.core.MemRead(s.SP + 1) - s.core.MemWrite(s.SP+1, s.H) - s.H = temp - }, - // 0xe4 : CALL PO, nn - 0xE4: func(s *Z80) { - s.doConditionalCall(!s.Flags.P) - }, - // 0xe5 : PUSH HL - 0xE5: func(s *Z80) { - s.pushWord((uint16(s.H) << 8) | uint16(s.L)) - }, - // 0xe6 : AND n - 0xE6: func(s *Z80) { - s.PC++ - s.doAnd(s.core.MemRead(s.PC)) - }, - // 0xe7 : RST 20h - 0xE7: func(s *Z80) { - s.doReset(0x0020) - }, - // 0xe8 : RET PE - 0xE8: func(s *Z80) { - s.doConditionalReturn(s.Flags.P) - }, - // 0xe9 : JP (HL) - 0xE9: func(s *Z80) { - s.PC = uint16(s.H)<<8 | uint16(s.L) - s.PC-- - }, - // 0xea : JP PE, nn - 0xEA: func(s *Z80) { - s.doConditionalAbsoluteJump(s.Flags.P) - }, - // 0xeb : EX DE, HL - 0xEB: func(s *Z80) { - s.D, s.H = s.H, s.D - s.E, s.L = s.L, s.E - }, - // 0xec : CALL PE, nn - 0xEC: func(s *Z80) { - s.doConditionalCall(s.Flags.P) - }, - // 0xed : ED Prefix - 0xED: func(s *Z80) { - s.opcodeED() - }, - // 0xee : XOR n - 0xEE: func(s *Z80) { - s.PC++ - s.doXor(s.core.MemRead(s.PC)) - }, - // 0xef : RST 28h - 0xEF: func(s *Z80) { - s.doReset(0x0028) - }, - // 0xf0 : RET P - 0xF0: func(s *Z80) { - s.doConditionalReturn(!s.Flags.S) - }, - // 0xf1 : POP AF - 0xF1: func(s *Z80) { - var result = s.PopWord() - s.Flags.SetFlags(byte(result & 0xff)) - s.A = byte((result & 0xff00) >> 8) - }, - // 0xf2 : JP P, nn - 0xF2: func(s *Z80) { - s.doConditionalAbsoluteJump(!s.Flags.S) - }, - // 0xf3 : DI - 0xF3: func(s *Z80) { - // DI doesn't actually take effect until after the next instruction. - s.DoDelayedDI = true - }, - // 0xf4 : CALL P, nn - 0xF4: func(s *Z80) { - s.doConditionalCall(!s.Flags.S) - }, - // 0xf5 : PUSH AF - 0xF5: func(s *Z80) { - s.pushWord(uint16(s.Flags.GetFlags()) | (uint16(s.A) << 8)) - }, - // 0xf6 : OR n - 0xF6: func(s *Z80) { - s.PC++ - s.doOr(s.core.MemRead(s.PC)) - }, - // 0xf7 : RST 30h - 0xF7: func(s *Z80) { - s.doReset(0x0030) - }, - // 0xf8 : RET M - 0xF8: func(s *Z80) { - s.doConditionalReturn(s.Flags.S) - }, - // 0xf9 : LD SP, HL - 0xF9: func(s *Z80) { - s.SP = uint16(s.H)<<8 | uint16(s.L) - }, - // 0xfa : JP M, nn - 0xFA: func(s *Z80) { - s.doConditionalAbsoluteJump(s.Flags.S) - }, - // 0xfb : EI - 0xFB: func(s *Z80) { - // EI doesn't actually take effect until after the next instruction. - s.DoDelayedEI = true - }, - // 0xfc : CALL M, nn - 0xFC: func(s *Z80) { - s.doConditionalCall(s.Flags.S) - }, - // 0xfd : FD Prefix (IY instructions) - 0xFD: func(s *Z80) { - s.opcodeFD() - }, - // 0xfe : CP n - 0xFE: func(s *Z80) { - s.PC++ - s.doCp(s.core.MemRead(s.PC)) - }, - // 0xff : RST 38h - 0xFF: func(s *Z80) { - s.doReset(0x0038) - }, -} - -func (z *Z80) nextWord() uint16 { - z.PC++ - word := uint16(z.core.MemRead(z.PC)) - z.PC++ - word |= uint16(z.core.MemRead(z.PC)) << 8 - return word -} diff --git a/z80/js/opcodeCB.go b/z80/js/opcodeCB.go deleted file mode 100644 index c5d9039..0000000 --- a/z80/js/opcodeCB.go +++ /dev/null @@ -1,108 +0,0 @@ -package js - -func (z *Z80) opcodeCB() { - z.incR() - z.PC++ - opcode := z.core.M1MemRead(z.PC) - bitNumber := (opcode & 0x38) >> 3 - regCode := opcode & 0x07 - if opcode < 0x40 { - // Shift/rotate instructions - opArray := []OpShift{z.doRlc, z.doRrc, z.doRl, z.doRr, z.doSla, z.doSra, z.doSll, z.doSrl} - switch regCode { - case 0: - z.B = opArray[bitNumber](z.B) - case 1: - z.C = opArray[bitNumber](z.C) - case 2: - z.D = opArray[bitNumber](z.D) - case 3: - z.E = opArray[bitNumber](z.E) - case 4: - z.H = opArray[bitNumber](z.H) - case 5: - z.L = opArray[bitNumber](z.L) - case 6: - z.core.MemWrite(z.hl(), opArray[bitNumber](z.core.MemRead(z.hl()))) - default: - z.A = opArray[bitNumber](z.A) - } - } else if opcode < 0x80 { - // BIT instructions - mask := byte(1 << bitNumber) - switch regCode { - case 0: - z.Flags.Z = z.B&mask == 0 - case 1: - z.Flags.Z = z.C&mask == 0 - case 2: - z.Flags.Z = z.D&mask == 0 - case 3: - z.Flags.Z = z.E&mask == 0 - case 4: - z.Flags.Z = z.H&mask == 0 - case 5: - z.Flags.Z = z.L&mask == 0 - case 6: - z.Flags.Z = z.core.MemRead(z.hl())&mask == 0 - default: - z.Flags.Z = z.A&mask == 0 - } - z.Flags.N = false - z.Flags.H = true - z.Flags.P = z.Flags.Z - z.Flags.S = (bitNumber == 7) && !z.Flags.Z - // TODO: ZXALL fail this - // For the BIT n, (HL) instruction, the X and Y flags are obtained - // from what is apparently an internal temporary register used for - // some of the 16-bit arithmetic instructions. - // I haven't implemented that register here, - // so for now we'll set X and Y the same way for every BIT opcode, - // which means that they will usually be wrong for BIT n, (HL). - z.Flags.Y = (bitNumber == 5) && !z.Flags.Z - z.Flags.X = (bitNumber == 3) && !z.Flags.Z - } else if opcode < 0xC0 { - // RES instructions - negMask := byte(^(1 << bitNumber)) - switch regCode { - case 0: - z.B &= negMask - case 1: - z.C &= negMask - case 2: - z.D &= negMask - case 3: - z.E &= negMask - case 4: - z.H &= negMask - case 5: - z.L &= negMask - case 6: - z.core.MemWrite(z.hl(), z.core.MemRead(z.hl())&negMask) - default: - z.A &= negMask - } - } else { - // SET instructions - mask := byte(1 << bitNumber) - switch regCode { - case 0: - z.B |= mask - case 1: - z.C |= mask - case 2: - z.D |= mask - case 3: - z.E |= mask - case 4: - z.H |= mask - case 5: - z.L |= mask - case 6: - z.core.MemWrite(z.hl(), z.core.MemRead(z.hl())|mask) - default: - z.A |= mask - } - } - z.CycleCounter += CycleCountsCb[opcode] -} diff --git a/z80/js/opcodeDD.go b/z80/js/opcodeDD.go deleted file mode 100644 index 6d87033..0000000 --- a/z80/js/opcodeDD.go +++ /dev/null @@ -1,475 +0,0 @@ -package js - -var ddInstructions = []func(s *Z80){ - // 0x09 : ADD IX, BC - 0x09: func(s *Z80) { - s.doIxAdd(s.bc()) - }, - // 0x19 : ADD IX, DE - 0x19: func(s *Z80) { - s.doIxAdd(s.de()) - }, - // 0x21 : LD IX, nn - 0x21: func(s *Z80) { - s.IX = s.nextWord() - }, - // 0x22 : LD (nn), IX - 0x22: func(s *Z80) { - s.setWord(s.nextWord(), s.IX) - }, - // 0x23 : INC IX - 0x23: func(s *Z80) { - s.IX++ - }, - // 0x24 : INC IXH (Undocumented) - 0x24: func(s *Z80) { - s.IX = (uint16(s.doInc(byte(s.IX>>8))) << 8) | (s.IX & 0x00ff) - }, - // 0x25 : DEC IXH (Undocumented) - 0x25: func(s *Z80) { - s.IX = (uint16(s.doDec(byte(s.IX>>8))) << 8) | (s.IX & 0x00ff) - }, - // 0x26 : LD IXH, n (Undocumented) - 0x26: func(s *Z80) { - s.PC++ - s.IX = (uint16(s.core.MemRead(s.PC)) << 8) | (s.IX & 0x00ff) - }, - // 0x29 : ADD IX, IX - 0x29: func(s *Z80) { - s.doIxAdd(s.IX) - }, - // 0x2a : LD IX, (nn) - 0x2A: func(s *Z80) { - s.IX = s.getWord(s.nextWord()) - }, - // 0x2b : DEC IX - 0x2B: func(s *Z80) { - s.IX-- - }, - // 0x2c : INC IXL (Undocumented) - 0x2C: func(s *Z80) { - s.IX = (uint16(s.doInc(byte(s.IX & 0x00ff)))) | (s.IX & 0xff00) - }, - // 0x2d : DEC IXL (Undocumented) - 0x2D: func(s *Z80) { - s.IX = (uint16(s.doDec(byte(s.IX & 0x00ff)))) | (s.IX & 0xff00) - }, - // 0x2e : LD IXL, n (Undocumented) - 0x2E: func(s *Z80) { - s.PC++ - s.IX = (uint16(s.core.MemRead(s.PC))) | (s.IX & 0xff00) - }, - // 0x34 : INC (IX+n) - 0x34: func(s *Z80) { - offset := s.getOffset(s.IX) - value := s.core.MemRead(offset) - s.core.MemWrite(offset, s.doInc(value)) - }, - // 0x35 : DEC (IX+n) - 0x35: func(s *Z80) { - offset := s.getOffset(s.IX) - value := s.core.MemRead(offset) - s.core.MemWrite(offset, s.doDec(value)) - }, - // 0x36 : LD (IX+n), n - 0x36: func(s *Z80) { - offset := s.getOffset(s.IX) - s.PC++ - s.core.MemWrite(offset, s.core.MemRead(s.PC)) - }, - // 0x39 : ADD IX, SP - 0x39: func(s *Z80) { - s.doIxAdd(s.SP) - }, - // 0x44 : LD B, IXH (Undocumented) - 0x44: func(s *Z80) { - s.B = byte(s.IX >> 8) - }, - // 0x45 : LD B, IXL (Undocumented) - 0x45: func(s *Z80) { - s.B = byte(s.IX & 0x00ff) - }, - // 0x46 : LD B, (IX+n) - 0x46: func(s *Z80) { - s.B = s.core.MemRead(s.getOffset(s.IX)) - }, - // 0x4c : LD C, IXH (Undocumented) - 0x4C: func(s *Z80) { - s.C = byte(s.IX >> 8) - }, - // 0x4d : LD C, IXL (Undocumented) - 0x4D: func(s *Z80) { - s.C = byte(s.IX & 0x00ff) - }, - // 0x4e : LD C, (IX+n) - 0x4E: func(s *Z80) { - s.C = s.core.MemRead(s.getOffset(s.IX)) - }, - // 0x54 : LD D, IXH (Undocumented) - 0x54: func(s *Z80) { - s.D = byte(s.IX >> 8) - }, - // 0x55 : LD D, IXL (Undocumented) - 0x55: func(s *Z80) { - s.D = byte(s.IX) - }, - // 0x56 : LD D, (IX+n) - 0x56: func(s *Z80) { - offset := s.getOffset(s.IX) - s.D = s.core.MemRead(offset) - }, - // 0x5d : LD E, IXL (Undocumented) - 0x5D: func(s *Z80) { - s.E = byte(s.IX) - }, - // 0x5e : LD E, (IX+n) - 0x5E: func(s *Z80) { - s.E = s.core.MemRead(s.getOffset(s.IX)) - }, - // 0x60 : LD IXH, B (Undocumented) - 0x60: func(s *Z80) { - s.IX = uint16(s.B)<<8 | s.IX&0x00ff - }, - // 0x61 : LD IXH, C (Undocumented) - 0x61: func(s *Z80) { - s.IX = uint16(s.C)<<8 | s.IX&0x00ff - }, - // 0x62 : LD IXH, D (Undocumented) - 0x62: func(s *Z80) { - s.IX = uint16(s.D)<<8 | s.IX&0x00ff - }, - // 0x63 : LD IXH, E (Undocumented) - 0x63: func(s *Z80) { - s.IX = uint16(s.E)<<8 | s.IX&0x00ff - }, - // 0x64 : LD IXH, IXH (Undocumented) - 0x64: func(s *Z80) { - // NOP - }, - // 0x65 : LD IXH, IXL (Undocumented) - 0x65: func(s *Z80) { - s.IX = (s.IX << 8) | (s.IX & 0x00ff) - }, - // 0x66 : LD H, (IX+n) - 0x66: func(s *Z80) { - s.H = s.core.MemRead(s.getOffset(s.IX)) - }, - // 0x67 : LD IXH, A (Undocumented) - 0x67: func(s *Z80) { - s.IX = (uint16(s.A) << 8) | (s.IX & 0x00ff) - }, - // 0x68 : LD IXL, B (Undocumented) - 0x68: func(s *Z80) { - s.IX = (s.IX & 0xff00) | uint16(s.B) - }, - // 0x69 : LD IXL, C (Undocumented) - 0x69: func(s *Z80) { - s.IX = (s.IX & 0xff00) | uint16(s.C) - }, - // 0x6a : LD IXL, D (Undocumented) - 0x6a: func(s *Z80) { - s.IX = (s.IX & 0xff00) | uint16(s.D) - }, - // 0x6b : LD IXL, E (Undocumented) - 0x6b: func(s *Z80) { - s.IX = (s.IX & 0xff00) | uint16(s.E) - }, - // 0x6c : LD IXL, IXH (Undocumented) - 0x6c: func(s *Z80) { - s.IX = (s.IX >> 8) | (s.IX & 0xff00) - }, - // 0x6d : LD IXL, IXL (Undocumented) - 0x6d: func(s *Z80) { - // NOP - }, - // 0x6e : LD L, (IX+n) - 0x6e: func(s *Z80) { - s.L = s.core.MemRead(s.getOffset(s.IX)) - }, - // 0x6f : LD IXL, A (Undocumented) - 0x6f: func(s *Z80) { - s.IX = uint16(s.A) | (s.IX & 0xff00) - }, - // 0x70 : LD (IX+n), B - 0x70: func(s *Z80) { - s.core.MemWrite(s.getOffset(s.IX), s.B) - }, - // 0x71 : LD (IX+n), C - 0x71: func(s *Z80) { - s.core.MemWrite(s.getOffset(s.IX), s.C) - }, - // 0x72 : LD (IX+n), D - 0x72: func(s *Z80) { - s.core.MemWrite(s.getOffset(s.IX), s.D) - }, - // 0x73 : LD (IX+n), E - 0x73: func(s *Z80) { - s.core.MemWrite(s.getOffset(s.IX), s.E) - }, - // 0x74 : LD (IX+n), H - 0x74: func(s *Z80) { - s.core.MemWrite(s.getOffset(s.IX), s.H) - }, - // 0x75 : LD (IX+n), L - 0x75: func(s *Z80) { - s.core.MemWrite(s.getOffset(s.IX), s.L) - }, - // 0x77 : LD (IX+n), A - 0x77: func(s *Z80) { - s.core.MemWrite(s.getOffset(s.IX), s.A) - }, - // 0x7c : LD A, IXH (Undocumented) - 0x7C: func(s *Z80) { - s.A = byte(s.IX >> 8) - }, - // 0x7d : LD A, IXL (Undocumented) - 0x7D: func(s *Z80) { - s.A = byte(s.IX & 0x00ff) - }, - // 0x7e : LD A, (IX+n) - 0x7E: func(s *Z80) { - s.A = s.core.MemRead(s.getOffset(s.IX)) - }, - // 0x84 : ADD A, IXH (Undocumented) - 0x84: func(s *Z80) { - s.doAdd(byte(s.IX >> 8)) - }, - // 0x85 : ADD A, IXL (Undocumented) - 0x85: func(s *Z80) { - s.doAdd(byte(s.IX)) - }, - // 0x86 : ADD A, (IX+n) - 0x86: func(s *Z80) { - s.doAdd(s.core.MemRead(s.getOffset(s.IX))) - }, - // 0x8c : ADC A, IXH (Undocumented) - 0x8C: func(s *Z80) { - s.doAdc(byte(s.IX >> 8)) - }, - // 0x8d : ADC A, IXL (Undocumented) - 0x8D: func(s *Z80) { - s.doAdc(byte(s.IX)) - }, - // 0x8e : ADC A, (IX+n) - 0x8E: func(s *Z80) { - s.doAdc(s.core.MemRead(s.getOffset(s.IX))) - }, - // 0x94 : SUB IXH (Undocumented) - 0x94: func(s *Z80) { - s.doSub(byte(s.IX >> 8)) - }, - // 0x95 : SUB IXL (Undocumented) - 0x95: func(s *Z80) { - s.doSub(byte(s.IX)) - }, - // 0x96 : SUB A, (IX+n) - 0x96: func(s *Z80) { - s.doSub(s.core.MemRead(s.getOffset(s.IX))) - }, - // 0x9c : SBC IXH (Undocumented) - 0x9C: func(s *Z80) { - s.doSbc(byte(s.IX >> 8)) - }, - // 0x9d : SBC IXL (Undocumented) - 0x9D: func(s *Z80) { - s.doSbc(byte(s.IX)) - }, - // 0x9e : SBC A, (IX+n) - 0x9E: func(s *Z80) { - s.doSbc(s.core.MemRead(s.getOffset(s.IX))) - }, - // 0xa4 : AND IXH (Undocumented) - 0xA4: func(s *Z80) { - s.doAnd(byte(s.IX >> 8)) - }, - // 0xa5 : AND IXL (Undocumented) - 0xA5: func(s *Z80) { - s.doAnd(byte(s.IX)) - }, - // 0xa6 : AND A, (IX+n) - 0xA6: func(s *Z80) { - s.doAnd(s.core.MemRead(s.getOffset(s.IX))) - }, - // 0xac : XOR IXH (Undocumented) - 0xAC: func(s *Z80) { - s.doXor(byte(s.IX >> 8)) - }, - // 0xad : XOR IXL (Undocumented) - 0xAD: func(s *Z80) { - s.doXor(byte(s.IX)) - }, - // 0xae : XOR A, (IX+n) - 0xAE: func(s *Z80) { - s.doXor(s.core.MemRead(s.getOffset(s.IX))) - }, - // 0xb4 : OR IXH (Undocumented) - 0xB4: func(s *Z80) { - s.doOr(byte(s.IX >> 8)) - }, - // 0xb5 : OR IXL (Undocumented) - 0xB5: func(s *Z80) { - s.doOr(byte(s.IX)) - }, - // 0xb6 : OR A, (IX+n) - 0xB6: func(s *Z80) { - s.doOr(s.core.MemRead(s.getOffset(s.IX))) - }, - // 0xbc : CP IXH (Undocumented) - 0xBC: func(s *Z80) { - s.doCp(byte(s.IX >> 8)) - }, - // 0xbd : CP IXL (Undocumented) - 0xBD: func(s *Z80) { - s.doCp(byte(s.IX)) - }, - // 0xbe : CP A, (IX+n) - 0xBE: func(s *Z80) { - s.doCp(s.core.MemRead(s.getOffset(s.IX))) - }, - // 0xcb : CB Prefix (IX bit instructions) - 0xCB: func(s *Z80) { - s.opcodeDDCB() - }, - // 0xe1 : POP IX - 0xE1: func(s *Z80) { - s.IX = s.PopWord() - }, - // 0xe3 : EX (SP), IX - 0xE3: func(s *Z80) { - ix := s.IX - s.IX = s.getWord(s.SP) - s.setWord(s.SP, ix) - }, - // 0xe5 : PUSH IX - 0xE5: func(s *Z80) { - s.pushWord(s.IX) - }, - // 0xe9 : JP (IX) - 0xE9: func(s *Z80) { - s.PC = s.IX - 1 - }, - // 0xf9 : LD SP, IX - 0xf9: func(s *Z80) { - s.SP = s.IX - }, -} - -// ===================================================== -func (z *Z80) getOffset(reg uint16) uint16 { - z.PC++ - offset := z.core.MemRead(z.PC) - if offset < 0 { - reg -= uint16(-offset) - } else { - reg += uint16(offset) - } - return reg -} - -func (z *Z80) opcodeDD() { - z.incR() - z.PC++ - opcode := z.core.M1MemRead(z.PC) - - fun := ddInstructions[opcode] - if fun != nil { - fun(z) - z.CycleCounter += CycleCountsDd[opcode] - } else { - // Apparently if a DD opcode doesn't exist, - // it gets treated as an unprefixed opcode. - // What we'll do to handle that is just back up the - // program counter, so that this byte gets decoded - // as a normal instruction. - z.PC-- - // And we'll add in the cycle count for a NOP. - z.CycleCounter += CycleCounts[0] - } -} - -func (z *Z80) opcodeDDCB() { - - offset := z.getOffset(z.IX) - z.PC++ - - opcode := z.core.MemRead(z.PC) - - value := byte(0) - bitTestOp := false - - // As with the "normal" CB prefix, we implement the DDCB prefix - // by decoding the opcode directly, rather than using a table. - if opcode < 0x40 { - // Shift and rotate instructions. - ddcbFunctions := []OpShift{z.doRlc, z.doRrc, z.doRl, z.doRr, z.doSla, z.doSra, z.doSll, z.doSrl} - // Most of the opcodes in this range are not valid, - // so we map this opcode onto one of the ones that is. - fun := ddcbFunctions[(opcode&0x38)>>3] - value = fun(z.core.MemRead(offset)) - z.core.MemWrite(offset, value) - } else { - bitNumber := (opcode & 0x38) >> 3 - if opcode < 0x80 { - // bit test - bitTestOp = true - z.Flags.N = false - z.Flags.H = true - z.Flags.Z = z.core.MemRead(offset)&(1<> 4) | (temp2 << 4) - s.A = (s.A & 0xf0) | temp1 - s.core.MemWrite(s.hl(), hlValue) - s.Flags.S = s.A&0x80 != 0 - s.Flags.Z = s.A == 0 - s.Flags.H = false - s.Flags.P = ParityBits[s.A] - s.Flags.N = false - s.updateXYFlags(s.A) - - }, - // 0x68 : IN L, (C) - 0x68: func(s *Z80) { - s.L = s.doIn(s.bc()) - }, - // 0x69 : OUT (C), L - 0x69: func(s *Z80) { - s.core.IOWrite(s.bc(), s.L) - }, - // 0x6a : ADC HL, HL - 0x6A: func(s *Z80) { - s.doHlAdc(s.hl()) - }, - // 0x6b : LD HL, (nn) (Undocumented) - 0x6B: func(s *Z80) { - s.setHl(s.getWord(s.nextWord())) - }, - // 0x6C : NEG (Undocumented) - 0x6C: func(s *Z80) { - s.doNeg() - }, - // 0x6D : RETN - 0x6D: func(s *Z80) { - s.PC = s.PopWord() - 1 - s.Iff1 = s.Iff2 - }, - // 0x6E : IM 0 - 0x6E: func(s *Z80) { - s.IMode = 0 - }, - // 0x6f : RLD - 0x6F: func(s *Z80) { - hlValue := s.core.MemRead(s.hl()) - temp1 := hlValue & 0xf0 - temp2 := s.A & 0x0f - hlValue = ((hlValue & 0x0f) << 4) | temp2 - s.A = (s.A & 0xf0) | (temp1 >> 4) - s.core.MemWrite(s.hl(), hlValue) - - s.Flags.S = s.A&0x80 != 0 - s.Flags.Z = s.A == 0 - s.Flags.H = false - s.Flags.P = ParityBits[s.A] - s.Flags.N = false - s.updateXYFlags(s.A) - }, - // 0x70 : INF - 0x70: func(s *Z80) { - s.doIn(s.bc()) - }, - // 0x71 : OUT (C), 0 (Undocumented) - 0x71: func(s *Z80) { - s.core.IOWrite(s.bc(), 0) - }, - // 0x72 : SBC HL, SP - 0x72: func(s *Z80) { - s.doHlSbc(s.SP) - }, - // 0x73 : LD (nn), SP - 0x73: func(s *Z80) { - s.setWord(s.nextWord(), s.SP) - }, - // 0x74 : NEG (Undocumented) - 0x74: func(s *Z80) { - s.doNeg() - }, - // 0x75 : RETN - 0x75: func(s *Z80) { - s.PC = s.PopWord() - 1 - s.Iff1 = s.Iff2 - }, - // 0x76 : IM 1 - 0x76: func(s *Z80) { - s.IMode = 1 - }, - // 0x78 : IN A, (C) - 0x78: func(s *Z80) { - s.A = s.core.IORead(s.bc()) - }, - // 0x79 : OUT (C), A - 0x79: func(s *Z80) { - s.core.IOWrite(s.bc(), s.A) - }, - // 0x7a : ADC HL, SP - 0x7A: func(s *Z80) { - s.doHlAdc(s.SP) - }, - // 0x7b : LD SP, (nn) - 0x7B: func(s *Z80) { - s.SP = s.getWord(s.nextWord()) - }, - // 0x7c : NEG (Undocumented) - 0x7C: func(s *Z80) { - s.doNeg() - }, - // 0x7d : RETN - 0x7D: func(s *Z80) { - s.PC = s.PopWord() - 1 - s.Iff1 = s.Iff2 - }, - // 0x7e : IM 2 - 0x7E: func(s *Z80) { - s.IMode = 2 - }, - // 0xa0 : LDI - 0xA0: func(s *Z80) { - s.doLdi() - }, - // 0xa1 : CPI - 0xA1: func(s *Z80) { - s.doCpi() - }, - // 0xa2 : INI - 0xA2: func(s *Z80) { - s.doIni() - }, - // 0xa3 : OUTI - 0xA3: func(s *Z80) { - s.doOuti() - }, - // 0xa8 : LDD - 0xA8: func(s *Z80) { - s.doLdd() - }, - // 0xa9 : CPD - 0xA9: func(s *Z80) { - s.doCpd() - }, - // 0xaa : IND - 0xAA: func(s *Z80) { - s.doInd() - }, - // 0xab : OUTD - 0xAB: func(s *Z80) { - s.doOutd() - }, - // 0xb0 : LDIR - 0xB0: func(s *Z80) { - s.doLdi() - if (s.B | s.C) != 0 { - s.CycleCounter += 5 - s.PC -= 2 - } - }, - // 0xb1 : CPIR - 0xB1: func(s *Z80) { - s.doCpi() - if !s.Flags.Z && (s.B|s.C) != 0 { - s.CycleCounter += 5 - s.PC -= 2 - } - }, - // 0xb2 : INIR - 0xB2: func(s *Z80) { - s.doIni() - if s.B != 0 { - s.CycleCounter += 5 - s.PC -= 2 - } - }, - // 0xb3 : OTIR - 0xB3: func(s *Z80) { - s.doOuti() - if s.B != 0 { - s.CycleCounter += 5 - s.PC -= 2 - } - }, - // 0xb8 : LDDR - 0xB8: func(s *Z80) { - s.doLdd() - if (s.B | s.C) != 0 { - s.CycleCounter += 5 - s.PC -= 2 - } - }, - // 0xb9 : CPDR - 0xB9: func(s *Z80) { - s.doCpd() - if !s.Flags.Z && (s.B|s.C) != 0 { - s.CycleCounter += 5 - s.PC -= 2 - } - }, - // 0xba : INDR - 0xBA: func(s *Z80) { - s.doInd() - if s.B != 0 { - s.CycleCounter += 5 - s.PC -= 2 - } - }, - // 0xbb : OTDR - 0xBB: func(s *Z80) { - s.doOutd() - if s.B != 0 { - s.CycleCounter += 5 - s.PC -= 2 - } - }, -} - -func (z *Z80) opcodeED() { - z.incR() - z.PC++ - - opcode := z.core.M1MemRead(z.PC) - - fun := edInstructions[opcode] - if fun != nil { - fun(z) - z.CycleCounter += CycleCountsEd[opcode] - } else { - z.PC-- - z.CycleCounter += CycleCounts[0] - } - -}