diff --git a/main.go b/main.go index 4d20b6e..4dbfb1c 100644 --- a/main.go +++ b/main.go @@ -152,12 +152,12 @@ func screen(computer *okean240.ComputerType, raster *canvas.Raster, label *widge } } -const ticksPerTicker = 3 +const ticksPerTicker uint64 = 3 func emulator(computer *okean240.ComputerType) { ticker := time.NewTicker(66 * time.Nanosecond) - var ticks = 0 - var nextClock = ticks + ticksPerTicker + var ticks uint64 = 0 + var nextClock uint64 = ticks + ticksPerTicker //var ticksCPU = 3 for range ticker.C { //for { diff --git a/okean240/computer.go b/okean240/computer.go index 688b09a..ae62f34 100644 --- a/okean240/computer.go +++ b/okean240/computer.go @@ -8,14 +8,14 @@ import ( "okemu/okean240/pic" "okemu/okean240/pit" "okemu/okean240/usart" - "okemu/z80em" + "okemu/z80/js" "fyne.io/fyne/v2" log "github.com/sirupsen/logrus" ) type ComputerType struct { - cpu *z80em.Z80Type + cpu *js.Z80 memory Memory ioPorts [256]byte cycles uint64 @@ -73,7 +73,7 @@ func New(cfg *config.OkEmuConfig) *ComputerType { c.memory = Memory{} c.memory.Init(cfg.MonitorFile, cfg.CPMFile) - c.cpu = z80em.New(&c) + c.cpu = js.New(&c) c.cycles = 0 c.dd17EnableOut = false @@ -109,17 +109,17 @@ func (c *ComputerType) Reset() { } -func (c *ComputerType) Do() int { +func (c *ComputerType) Do() uint64 { //s := c.cpu.GetState() //if s.PC == 0xe0db { // log.Debugf("breakpoint") //} - ticks := uint64(c.cpu.RunInstruction()) + ticks := c.cpu.RunInstruction() c.cycles += ticks //if c.cpu.PC == 0xFF26 { // log.Debugf("%4X: H:%X L:%X A:%X B: %X C: %X D: %X E: %X", c.cpu.PC, c.cpu.H, c.cpu.L, c.cpu.A, c.cpu.B, c.cpu.C, c.cpu.D, c.cpu.E) //} - return int(ticks) + return ticks } func (c *ComputerType) GetPixel(x uint16, y uint16) color.RGBA { diff --git a/z80/constants.go b/z80/c99/constants.go similarity index 99% rename from z80/constants.go rename to z80/c99/constants.go index 922d7be..8f10c32 100644 --- a/z80/constants.go +++ b/z80/c99/constants.go @@ -1,4 +1,4 @@ -package z80 +package c99 var cyc_00 = [256]byte{ 4, 10, 7, 6, 4, 4, 7, 4, 4, 11, 7, 6, 4, 4, 7, 4, diff --git a/z80/c99/cpu.go b/z80/c99/cpu.go new file mode 100644 index 0000000..de65756 --- /dev/null +++ b/z80/c99/cpu.go @@ -0,0 +1,191 @@ +package c99 + +import "okemu/z80" + +type MemIoRW interface { + // M1MemRead Read byte from memory for specified address @ M1 cycle + M1MemRead(addr uint16) byte + // MemRead Read byte from memory for specified address + MemRead(addr uint16) byte + // MemWrite Write byte to memory to specified address + MemWrite(addr uint16, val byte) + // IORead Read byte from specified port + IORead(port uint16) byte + // IOWrite Write byte to specified port + IOWrite(port uint16, val byte) +} + +type CPUInterface interface { + // Reset CPU to initial state + Reset() + // RunInstruction Run single instruction, return number of CPU cycles + RunInstruction() byte + // GetState Get current CPU state + GetState() *Z80 + // SetState Set current CPU state + SetState(state *Z80) +} + +type Z80 struct { + + // cycle count (t-states) + cyc uint64 + inst_cyc byte + + // special purpose registers + pc, sp, ix, iy uint16 + + // "wz" register + mem_ptr uint16 + + // main registers + a, b, c, d, e, h, l byte + + // alternate registers + a_, b_, c_, d_, e_, h_, l_, f_ byte + + // interrupt vector, memory refresh + i, r byte + + // 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 + iff1 bool + iff2 bool + halted bool + int_pending bool + nmi_pending bool + + core MemIoRW +} + +// New initializes a Z80 instance and return pointer to it +func New(core MemIoRW) *Z80 { + z := Z80{} + z.core = core + + z.cyc = 0 + + z.pc = 0 + z.sp = 0xFFFF + z.ix = 0 + z.iy = 0 + z.mem_ptr = 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 + 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.iff_delay = 0 + z.interrupt_mode = 0 + z.iff1 = false + z.iff2 = false + z.halted = false + z.int_pending = false + z.nmi_pending = false + z.int_data = 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) + } else { + opcode := z.nextb() + z.exec_opcode(opcode) + } + z.process_interrupts() + return z.cyc - pre +} + +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.a_, + BAlt: z.b_, + CAlt: z.c_, + DAlt: z.d_, + EAlt: z.e_, + HAlt: z.h_, + LAlt: z.l_, + IX: z.ix, + IY: z.iy, + I: z.i, + R: z.r, + SP: z.sp, + PC: z.pc, + Flags: z.getFlags(), + FlagsAlt: z.getAltFlags(), + IMode: z.interrupt_mode, + Iff1: z.iff1, + Iff2: z.iff2, + Halted: z.halted, + DoDelayedDI: z.int_pending, + DoDelayedEI: z.int_pending, + CycleCounter: z.inst_cyc, + InterruptOccurred: false, + } +} + +func (z *Z80) getFlags() z80.FlagsType { + return z80.FlagsType{ + S: z.sf, + Z: z.zf, + Y: z.yf, + H: z.hf, + X: z.xf, + P: z.pf, + N: z.nf, + C: z.cf, + } +} + +func (z *Z80) getAltFlags() z80.FlagsType { + return z80.FlagsType{ + S: z.f_&0x80 != 0, + Z: z.f_&0x40 != 0, + Y: z.f_&0x20 != 0, + H: z.f_&0x10 != 0, + X: z.f_&0x08 != 0, + P: z.f_&0x04 != 0, + N: z.f_&0x02 != 0, + C: z.f_&0x01 != 0, + } +} diff --git a/z80/helper.go b/z80/c99/helper.go similarity index 98% rename from z80/helper.go rename to z80/c99/helper.go index f21ca5d..6cf3020 100644 --- a/z80/helper.go +++ b/z80/c99/helper.go @@ -1,4 +1,4 @@ -package z80 +package c99 import log "github.com/sirupsen/logrus" @@ -155,7 +155,7 @@ func (z *Z80) updateXY(result byte) { z.xf = result&0x08 != 0 } -func (z *Z80) debug_output() { +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.ix, z.iy, z.i, z.r) diff --git a/z80/opcodes.go b/z80/c99/opcodes.go similarity index 99% rename from z80/opcodes.go rename to z80/c99/opcodes.go index 4f1cbce..379f196 100644 --- a/z80/opcodes.go +++ b/z80/c99/opcodes.go @@ -1,4 +1,4 @@ -package z80 +package c99 import log "github.com/sirupsen/logrus" diff --git a/z80/opcodesCB.go b/z80/c99/opcodesCB.go similarity index 99% rename from z80/opcodesCB.go rename to z80/c99/opcodesCB.go index d2c6ad4..6cf3180 100644 --- a/z80/opcodesCB.go +++ b/z80/c99/opcodesCB.go @@ -1,4 +1,4 @@ -package z80 +package c99 import log "github.com/sirupsen/logrus" diff --git a/z80/opcodesDDFD.go b/z80/c99/opcodesDDFD.go similarity index 99% rename from z80/opcodesDDFD.go rename to z80/c99/opcodesDDFD.go index 6d74423..77bea54 100644 --- a/z80/opcodesDDFD.go +++ b/z80/c99/opcodesDDFD.go @@ -1,4 +1,4 @@ -package z80 +package c99 // executes a DD/FD opcode (IZ = IX or IY) func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) { diff --git a/z80/opcodesED.go b/z80/c99/opcodesED.go similarity index 99% rename from z80/opcodesED.go rename to z80/c99/opcodesED.go index e323949..27991a7 100644 --- a/z80/opcodesED.go +++ b/z80/c99/opcodesED.go @@ -1,4 +1,4 @@ -package z80 +package c99 import log "github.com/sirupsen/logrus" diff --git a/z80/cpu.go b/z80/cpu.go index e31f028..99e771d 100644 --- a/z80/cpu.go +++ b/z80/cpu.go @@ -17,158 +17,56 @@ type CPUInterface interface { // Reset CPU to initial state Reset() // RunInstruction Run single instruction, return number of CPU cycles - RunInstruction() byte + RunInstruction() uint64 // GetState Get current CPU state - GetState() *Z80 + GetState() *Z80CPU // SetState Set current CPU state - SetState(state *Z80) + SetState(state *Z80CPU) } -type Z80 struct { - - // cycle count (t-states) - cyc uint64 - - // special purpose registers - pc, sp, ix, iy uint16 - - // "wz" register - mem_ptr uint16 - - // main registers - a, b, c, d, e, h, l byte - - // alternate registers - a_, b_, c_, d_, e_, h_, l_, f_ byte - - // interrupt vector, memory refresh - i, r byte - - // 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 - iff1 bool - iff2 bool - halted bool - int_pending bool - nmi_pending bool - - core MemIoRW +// FlagsType - Processor flags +type FlagsType struct { + S bool + Z bool + Y bool + H bool + X bool + P bool + N bool + C bool } -// New initializes a Z80 instance and return pointer to it -func New(core MemIoRW) *Z80 { - z := Z80{} - z.core = core - - z.cyc = 0 - - z.pc = 0 - z.sp = 0xFFFF - z.ix = 0 - z.iy = 0 - z.mem_ptr = 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 - 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.iff_delay = 0 - z.interrupt_mode = 0 - z.iff1 = false - z.iff2 = false - z.halted = false - z.int_pending = false - z.nmi_pending = false - z.int_data = 0 - return &z -} - -// RunInstruction executes the next instruction in memory + handles interrupts -func (z *Z80) RunInstruction() { - if z.halted { - z.exec_opcode(0x00) - } else { - opcode := z.nextb() - z.exec_opcode(opcode) - } - z.process_interrupts() -} - -func (z *Z80) GetState() *Z80 { - return &Z80{ - cyc: z.cyc, - pc: z.pc, - sp: z.sp, - ix: z.ix, - iy: z.iy, - mem_ptr: z.mem_ptr, - - a: z.a, - b: z.b, - c: z.c, - d: z.d, - e: z.e, - h: z.h, - l: z.l, - a_: z.a_, - b_: z.b_, - c_: z.c_, - d_: z.d_, - e_: z.e_, - h_: z.h_, - l_: z.l_, - f_: z.f_, - - i: z.i, - r: z.r, - - sf: z.sf, - zf: z.zf, - yf: z.yf, - hf: z.hf, - xf: z.xf, - pf: z.pf, - nf: z.nf, - cf: z.cf, - - iff1: z.iff1, - iff2: z.iff2, - - iff_delay: z.iff_delay, - interrupt_mode: z.interrupt_mode, - halted: z.halted, - int_pending: z.int_pending, - nmi_pending: z.nmi_pending, - core: z.core, - } +// Z80CPU - Processor state +type Z80CPU struct { + A byte + B byte + C byte + D byte + E byte + H byte + L byte + AAlt byte + BAlt byte + CAlt byte + DAlt byte + EAlt byte + HAlt byte + LAlt byte + IX uint16 + IY uint16 + I byte + R byte + SP uint16 + PC uint16 + Flags FlagsType + FlagsAlt FlagsType + IMode byte + Iff1 bool + Iff2 bool + Halted bool + DoDelayedDI bool + DoDelayedEI bool + CycleCounter byte + InterruptOccurred bool + //core MemIoRW } diff --git a/z80em/constants.go b/z80/js/constants.go similarity index 99% rename from z80em/constants.go rename to z80/js/constants.go index fe99814..b9ce480 100644 --- a/z80em/constants.go +++ b/z80/js/constants.go @@ -1,4 +1,4 @@ -package z80em +package js const OpHalt = 0x76 const OpLdBB = 0x40 diff --git a/z80em/z80em.go b/z80/js/cpu.go similarity index 75% rename from z80em/z80em.go rename to z80/js/cpu.go index 6104b0a..5e30c69 100644 --- a/z80em/z80em.go +++ b/z80/js/cpu.go @@ -1,81 +1,19 @@ -package z80em +package js -import "fmt" +import ( + "fmt" + "okemu/z80" -//const SpDefault uint16 = 0xffff + log "github.com/sirupsen/logrus" +) -// FlagsType - Processor flags -type FlagsType struct { - S bool - Z bool - Y bool - H bool - X bool - P bool - N bool - C bool +// const SpDefault uint16 = 0xffff +type Z80 struct { + z80.Z80CPU + core z80.MemIoRW } -// Z80Type - Processor state -type Z80Type struct { - A byte - B byte - C byte - D byte - E byte - H byte - L byte - AAlt byte - BAlt byte - CAlt byte - DAlt byte - EAlt byte - HAlt byte - LAlt byte - IX uint16 - IY uint16 - I byte - R byte - SP uint16 - PC uint16 - Flags FlagsType - FlagsAlt FlagsType - IMode byte - Iff1 byte - Iff2 byte - Halted bool - DoDelayedDI bool - DoDelayedEI bool - CycleCounter byte - interruptOccurred bool - core MemIoRW -} - -type MemIoRW interface { - // M1MemRead Read byte from memory for specified address @ M1 cycle - M1MemRead(addr uint16) byte - // MemRead Read byte from memory for specified address - MemRead(addr uint16) byte - // MemWrite Write byte to memory to specified address - MemWrite(addr uint16, val byte) - // IORead Read byte from specified port - IORead(port uint16) byte - // IOWrite Write byte to specified port - IOWrite(port uint16, val byte) -} - -type CPUInterface interface { - // Reset CPU to initial state - Reset() - // RunInstruction Run single instruction, return number of CPU cycles - RunInstruction() byte - // GetState Get current CPU state - GetState() *Z80Type - // SetState Set current CPU state - SetState(state *Z80Type) -} - -func (z *Z80Type) Reset() { +func (z *Z80) Reset() { z.A = 0 z.R = 0 z.SP = 0xff @@ -83,9 +21,9 @@ func (z *Z80Type) Reset() { z.setFlagsRegister(0xff) // Interrupts disabled z.IMode = 0 - z.Iff1 = 0 - z.Iff2 = 0 - z.interruptOccurred = false + z.Iff1 = false + z.Iff2 = false + z.InterruptOccurred = false // Start not halted z.Halted = false @@ -96,8 +34,8 @@ func (z *Z80Type) Reset() { fmt.Println("CPUInterface State Reset") } -func (z *Z80Type) GetState() *Z80Type { - return &Z80Type{ +func (z *Z80) GetState() *z80.Z80CPU { + return &z80.Z80CPU{ A: z.A, B: z.B, C: z.C, @@ -128,7 +66,7 @@ func (z *Z80Type) GetState() *Z80Type { } } -func (z *Z80Type) SetState(state *Z80Type) { +func (z *Z80) SetState(state *Z80) { z.A = state.A z.B = state.B z.C = state.C @@ -160,43 +98,45 @@ func (z *Z80Type) SetState(state *Z80Type) { } // New Create new -func New(memIoRW MemIoRW) *Z80Type { - return &Z80Type{ - 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, +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: FlagsType{true, true, true, true, true, true, true, true}, - FlagsAlt: FlagsType{true, true, true, true, true, true, true, true}, - IMode: 0, - Iff1: 0, - Iff2: 0, - Halted: false, - DoDelayedDI: false, - DoDelayedEI: false, - CycleCounter: 0, - interruptOccurred: false, - core: memIoRW, + 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 *Z80Type) RunInstruction() byte { +func (z *Z80) RunInstruction() uint64 { z.incR() @@ -225,18 +165,18 @@ func (z *Z80Type) RunInstruction() byte { // Actually do the delayed interrupt disable/enable if we have one. if doingDelayedDi { - z.Iff1 = 0 - z.Iff2 = 0 + z.Iff1 = false + z.Iff2 = false } else if doingDelayedEi { - z.Iff1 = 1 - z.Iff2 = 1 + 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 cycleCounter + return uint64(cycleCounter) } // HALTED @@ -250,7 +190,7 @@ func (z *Z80Type) RunInstruction() byte { // // nonMaskable - true if this is a non-maskable interrupt // data - the value to be placed on the data bus, if needed -func (z *Z80Type) interrupt(nonMaskable bool, data byte) { +func (z *Z80) interrupt(nonMaskable bool, data byte) { if nonMaskable { // An interrupt, if halted, does increase the PC if z.Halted { @@ -267,12 +207,12 @@ func (z *Z80Type) interrupt(nonMaskable bool, data byte) { z.Halted = false z.Iff2 = z.Iff1 - z.Iff1 = 0 + z.Iff1 = false z.pushWord(z.PC) z.PC = 0x66 z.CycleCounter += 11 - } else if z.Iff1 != 0 { + } else if z.Iff1 { // An interrupt, if halted, does increase the PC if z.Halted { z.PC++ @@ -283,8 +223,8 @@ func (z *Z80Type) interrupt(nonMaskable bool, data byte) { z.incR() z.Halted = false - z.Iff1 = 0 - z.Iff2 = 0 + z.Iff1 = false + z.Iff2 = false if z.IMode == 0 { // In the 8080-compatible interrupt mode, @@ -312,19 +252,19 @@ func (z *Z80Type) interrupt(nonMaskable bool, data byte) { 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 + z.InterruptOccurred = true } } } -func (z *Z80Type) pushWord(operand uint16) { +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 *Z80Type) getOperand(opcode byte) byte { +func (z *Z80) getOperand(opcode byte) byte { switch opcode & 0x07 { case 0: return z.B @@ -345,7 +285,7 @@ func (z *Z80Type) getOperand(opcode byte) byte { } } -func (z *Z80Type) decodeInstruction(opcode byte) { +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 { @@ -363,7 +303,7 @@ func (z *Z80Type) decodeInstruction(opcode byte) { z.CycleCounter += CycleCounts[opcode] } -func (z *Z80Type) load8bit(opcode byte, operand byte) { +func (z *Z80) load8bit(opcode byte, operand byte) { switch (opcode & 0x38) >> 3 { case 0: z.B = operand @@ -385,7 +325,7 @@ func (z *Z80Type) load8bit(opcode byte, operand byte) { } // alu8bit Handle ALU Operations, ADD, ADC SUB, SBC, AND, XOR, OR -func (z *Z80Type) alu8bit(opcode byte, operand byte) { +func (z *Z80) alu8bit(opcode byte, operand byte) { switch (opcode & 0x38) >> 3 { case 0: z.doAdd(operand) @@ -407,16 +347,16 @@ func (z *Z80Type) alu8bit(opcode byte, operand byte) { } // getFlagsRegister return whole F register -func (z *Z80Type) getFlagsRegister() byte { +func (z *Z80) getFlagsRegister() byte { return getFlags(&z.Flags) } // getFlagsRegister return whole F' register -func (z *Z80Type) getFlagsPrimeRegister() byte { +func (z *Z80) getFlagsPrimeRegister() byte { return getFlags(&z.FlagsAlt) } -func getFlags(f *FlagsType) byte { +func getFlags(f *z80.FlagsType) byte { var flags byte = 0 if f.S { flags |= 0x80 @@ -446,15 +386,15 @@ func getFlags(f *FlagsType) byte { } -func (z *Z80Type) setFlagsRegister(flags byte) { +func (z *Z80) setFlagsRegister(flags byte) { setFlags(flags, &z.Flags) } -func (z *Z80Type) setFlagsPrimeRegister(flags byte) { +func (z *Z80) setFlagsPrimeRegister(flags byte) { setFlags(flags, &z.FlagsAlt) } -func setFlags(flags byte, f *FlagsType) { +func setFlags(flags byte, f *z80.FlagsType) { f.S = flags&0x80 != 0 f.Z = flags&0x40 != 0 f.Y = flags&0x20 != 0 @@ -466,13 +406,13 @@ func setFlags(flags byte, f *FlagsType) { } // updateXYFlags Set flags X and Y based on result bits -func (z *Z80Type) updateXYFlags(result byte) { +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 *Z80Type) PushWord(operand uint16) { +func (z *Z80) PushWord(operand uint16) { z.SP-- z.core.MemWrite(z.SP, byte((operand&0xff00)>>8)) z.SP-- @@ -480,7 +420,7 @@ func (z *Z80Type) PushWord(operand uint16) { } // PopWord - Get word value from top of stack and increment stack pointer -func (z *Z80Type) PopWord() uint16 { +func (z *Z80) PopWord() uint16 { result := uint16(z.core.MemRead(z.SP)) z.SP++ result |= uint16(z.core.MemRead(z.SP)) << 8 @@ -489,7 +429,7 @@ func (z *Z80Type) PopWord() uint16 { } // doConditionalAbsoluteJump - Implements the JP [condition],nn instructions. -func (z *Z80Type) doConditionalAbsoluteJump(condition bool) { +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, @@ -505,7 +445,7 @@ func (z *Z80Type) doConditionalAbsoluteJump(condition bool) { } // doConditionalRelativeJump - Implements the JR [condition],nn instructions. -func (z *Z80Type) doConditionalRelativeJump(condition bool) { +func (z *Z80) doConditionalRelativeJump(condition bool) { if condition { // We need a few more cycles to actually take the jump. z.CycleCounter += 5 @@ -524,7 +464,7 @@ func (z *Z80Type) doConditionalRelativeJump(condition bool) { } // doConditionalCall - Implements CALL [condition],nn instructions. -func (z *Z80Type) doConditionalCall(condition bool) { +func (z *Z80) doConditionalCall(condition bool) { if condition { z.CycleCounter += 7 z.PushWord(z.PC + 3) @@ -535,7 +475,7 @@ func (z *Z80Type) doConditionalCall(condition bool) { } } -func (z *Z80Type) doConditionalReturn(condition bool) { +func (z *Z80) doConditionalReturn(condition bool) { if condition { z.CycleCounter += 6 z.PC = z.PopWord() - 1 @@ -543,13 +483,13 @@ func (z *Z80Type) doConditionalReturn(condition bool) { } // doReset - Implements RST [address] instructions. -func (z *Z80Type) doReset(address uint16) { +func (z *Z80) doReset(address uint16) { z.PushWord(z.PC + 1) z.PC = address - 1 } // doAdd Handle ADD A, [operand] instructions. -func (z *Z80Type) doAdd(operand byte) { +func (z *Z80) doAdd(operand byte) { var result = uint16(z.A) + uint16(operand) z.Flags.S = result&0x80 != 0 @@ -564,7 +504,7 @@ func (z *Z80Type) doAdd(operand byte) { } // doAdc Handle ADC A, [operand] instructions. -func (z *Z80Type) doAdc(operand byte) { +func (z *Z80) doAdc(operand byte) { add := byte(0) if z.Flags.C { add = 1 @@ -583,7 +523,7 @@ func (z *Z80Type) doAdc(operand byte) { } // doSub Handle SUB A, [operand] instructions. -func (z *Z80Type) doSub(operand byte) { +func (z *Z80) doSub(operand byte) { var result = uint16(z.A) - uint16(operand) z.Flags.S = result&0x80 != 0 @@ -598,7 +538,7 @@ func (z *Z80Type) doSub(operand byte) { } // doSbc Handle SBC A, [operand] instructions. -func (z *Z80Type) doSbc(operand byte) { +func (z *Z80) doSbc(operand byte) { sub := byte(0) if z.Flags.C { sub = 1 @@ -617,7 +557,7 @@ func (z *Z80Type) doSbc(operand byte) { } // setLogicFlags Set common flags for logic ALU Ops -func (z *Z80Type) setLogicFlags() { +func (z *Z80) setLogicFlags() { z.Flags.S = z.A&0x80 != 0 z.Flags.Z = z.A == 0 z.Flags.P = ParityBits[z.A] @@ -626,7 +566,7 @@ func (z *Z80Type) setLogicFlags() { } // doAnd handle AND [operand] instructions. -func (z *Z80Type) doAnd(operand byte) { +func (z *Z80) doAnd(operand byte) { z.A &= operand z.setLogicFlags() z.Flags.H = true @@ -634,7 +574,7 @@ func (z *Z80Type) doAnd(operand byte) { } // doXor handle XOR [operand] instructions. -func (z *Z80Type) doXor(operand byte) { +func (z *Z80) doXor(operand byte) { z.A ^= operand z.setLogicFlags() z.Flags.H = false @@ -642,7 +582,7 @@ func (z *Z80Type) doXor(operand byte) { } // doOr handle OR [operand] instructions. -func (z *Z80Type) doOr(operand byte) { +func (z *Z80) doOr(operand byte) { z.A |= operand z.setLogicFlags() z.Flags.H = false @@ -650,7 +590,7 @@ func (z *Z80Type) doOr(operand byte) { } // doCp handle CP [operand] instructions. -func (z *Z80Type) doCp(operand byte) { +func (z *Z80) doCp(operand byte) { tmp := z.A z.doSub(operand) z.A = tmp @@ -658,7 +598,7 @@ func (z *Z80Type) doCp(operand byte) { } // doInc handle INC [operand] instructions. -func (z *Z80Type) doInc(operand byte) byte { +func (z *Z80) doInc(operand byte) byte { var result = uint16(operand) + 1 r8 := byte(result & 0xff) @@ -673,7 +613,7 @@ func (z *Z80Type) doInc(operand byte) byte { } // doDec handle DEC [operand] instructions. -func (z *Z80Type) doDec(operand byte) byte { +func (z *Z80) doDec(operand byte) byte { var result = uint16(operand) - 1 r8 := byte(result & 0xff) @@ -688,7 +628,7 @@ func (z *Z80Type) doDec(operand byte) byte { } // doHlAdd handle ADD HL,[operand] instructions. -func (z *Z80Type) doHlAdd(operand uint16) { +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) @@ -705,7 +645,7 @@ func (z *Z80Type) doHlAdd(operand uint16) { } // doHlAdc handle ADC HL,[operand] instructions. -func (z *Z80Type) doHlAdc(operand uint16) { +func (z *Z80) doHlAdc(operand uint16) { if z.Flags.C { operand++ } @@ -728,7 +668,7 @@ func (z *Z80Type) doHlAdc(operand uint16) { } // doHlSbc handle SBC HL,[operand] instructions. -func (z *Z80Type) doHlSbc(operand uint16) { +func (z *Z80) doHlSbc(operand uint16) { if z.Flags.C { operand++ } @@ -750,7 +690,7 @@ func (z *Z80Type) doHlSbc(operand uint16) { z.updateXYFlags(z.H) } -func (z *Z80Type) doIn(port uint16) byte { +func (z *Z80) doIn(port uint16) byte { var result = z.core.IORead(port) z.Flags.S = result&0x80 != 0 @@ -762,7 +702,7 @@ func (z *Z80Type) doIn(port uint16) byte { return result } -func (z *Z80Type) doNeg() { +func (z *Z80) doNeg() { // This instruction is defined to not alter the register if it === 0x80. a := int8(z.A) if z.A != 0x80 { @@ -778,7 +718,7 @@ func (z *Z80Type) doNeg() { z.updateXYFlags(z.A) } -func (z *Z80Type) doLdi() { +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) @@ -794,14 +734,14 @@ func (z *Z80Type) doLdi() { z.Flags.X = ((z.A+readValue)&0x08)>>3 != 0 } -func (z *Z80Type) fhv() byte { +func (z *Z80) fhv() byte { if z.Flags.H { return 1 } return 0 } -func (z *Z80Type) doCpi() { +func (z *Z80) doCpi() { tempCarry := z.Flags.C readValue := z.core.MemRead(z.hl()) z.doCp(readValue) @@ -815,21 +755,21 @@ func (z *Z80Type) doCpi() { z.Flags.P = (z.B | z.C) != 0 } -func (z *Z80Type) doIni() { +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 *Z80Type) doOuti() { +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 *Z80Type) doLdd() { +func (z *Z80) doLdd() { z.Flags.N = false z.Flags.H = false readValue := z.core.MemRead(z.hl()) @@ -842,7 +782,7 @@ func (z *Z80Type) doLdd() { z.Flags.X = ((z.A + readValue) & 0x08) != 0 } -func (z *Z80Type) doCpd() { +func (z *Z80) doCpd() { tempCarry := z.Flags.C readValue := z.core.MemRead(z.hl()) z.doCp(readValue) @@ -860,14 +800,14 @@ func (z *Z80Type) doCpd() { z.Flags.P = (z.B | z.C) != 0 } -func (z *Z80Type) doInd() { +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 *Z80Type) doOutd() { +func (z *Z80) doOutd() { z.B = z.doDec(z.B) z.core.IOWrite(z.bc(), z.core.MemRead(z.hl())) z.decHl() @@ -876,7 +816,7 @@ func (z *Z80Type) doOutd() { type OpShift func(operand byte) byte -func (z *Z80Type) doRlc(operand byte) byte { +func (z *Z80) doRlc(operand byte) byte { z.Flags.C = operand&0x80 != 0 var fc byte = 0 if z.Flags.C { @@ -887,7 +827,7 @@ func (z *Z80Type) doRlc(operand byte) byte { return operand } -func (z *Z80Type) doRrc(operand byte) byte { +func (z *Z80) doRrc(operand byte) byte { z.Flags.C = operand&1 != 0 var fc byte = 0 if z.Flags.C { @@ -898,7 +838,7 @@ func (z *Z80Type) doRrc(operand byte) byte { return operand } -func (z *Z80Type) doRl(operand byte) byte { +func (z *Z80) doRl(operand byte) byte { var fc byte = 0 if z.Flags.C { fc = 1 @@ -909,7 +849,7 @@ func (z *Z80Type) doRl(operand byte) byte { return operand } -func (z *Z80Type) doRr(operand byte) byte { +func (z *Z80) doRr(operand byte) byte { var fc byte = 0 if z.Flags.C { fc = 0x80 @@ -920,28 +860,28 @@ func (z *Z80Type) doRr(operand byte) byte { return operand } -func (z *Z80Type) doSla(operand byte) byte { +func (z *Z80) doSla(operand byte) byte { z.Flags.C = operand&0x80 != 0 operand = operand << 1 z.setShiftFlags(operand) return operand } -func (z *Z80Type) doSra(operand byte) byte { +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 *Z80Type) doSll(operand byte) byte { +func (z *Z80) doSll(operand byte) byte { z.Flags.C = operand&0x80 != 0 operand = (operand << 1) | 1 z.setShiftFlags(operand) return operand } -func (z *Z80Type) doSrl(operand byte) byte { +func (z *Z80) doSrl(operand byte) byte { z.Flags.C = operand&1 != 0 operand = (operand >> 1) & 0x7f z.setShiftFlags(operand) @@ -949,7 +889,7 @@ func (z *Z80Type) doSrl(operand byte) byte { return operand } -func (z *Z80Type) doIxAdd(operand uint16) { +func (z *Z80) doIxAdd(operand uint16) { z.Flags.N = false result := uint32(z.IX) + uint32(operand) z.Flags.C = result > 0xffff @@ -959,7 +899,7 @@ func (z *Z80Type) doIxAdd(operand uint16) { z.IX = uint16(result & 0xffff) } -func (z *Z80Type) setShiftFlags(operand byte) { +func (z *Z80) setShiftFlags(operand byte) { z.Flags.N = false z.Flags.H = false z.Flags.Z = operand == 0 @@ -970,55 +910,55 @@ func (z *Z80Type) setShiftFlags(operand byte) { // ============== get register pairs -func (z *Z80Type) bc() uint16 { +func (z *Z80) bc() uint16 { return (uint16(z.B) << 8) | uint16(z.C) } -func (z *Z80Type) de() uint16 { +func (z *Z80) de() uint16 { return (uint16(z.D) << 8) | uint16(z.E) } -func (z *Z80Type) hl() uint16 { +func (z *Z80) hl() uint16 { return (uint16(z.H) << 8) | uint16(z.L) } // ============ helper fn -func (z *Z80Type) incBc() { +func (z *Z80) incBc() { z.setBc(z.bc() + 1) } -func (z *Z80Type) decBc() { +func (z *Z80) decBc() { z.setBc(z.bc() - 1) } -func (z *Z80Type) incDe() { +func (z *Z80) incDe() { z.setDe(z.de() + 1) } -func (z *Z80Type) decDe() { +func (z *Z80) decDe() { z.setDe(z.de() - 1) } -func (z *Z80Type) incHl() { +func (z *Z80) incHl() { z.setHl(z.hl() + 1) } -func (z *Z80Type) decHl() { +func (z *Z80) decHl() { z.setHl(z.hl() - 1) } -func (z *Z80Type) setHl(val uint16) { +func (z *Z80) setHl(val uint16) { z.L = byte(val & 0xff) z.H = byte(val >> 8) } -func (z *Z80Type) setDe(val uint16) { +func (z *Z80) setDe(val uint16) { z.E = byte(val & 0xff) z.D = byte(val >> 8) } -func (z *Z80Type) setBc(val uint16) { +func (z *Z80) setBc(val uint16) { z.C = byte(val & 0xff) z.B = byte(val >> 8) } @@ -1027,16 +967,25 @@ func (z *Z80Type) setBc(val uint16) { // 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 *Z80Type) incR() { +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 *Z80Type) getWord(address uint16) uint16 { +func (z *Z80) getWord(address uint16) uint16 { return (uint16(z.core.MemRead(address+1)) << 8) | uint16(z.core.MemRead(address)) } -func (z *Z80Type) setWord(address uint16, value uint16) { +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.getFlagsRegister()), 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/z80em/opcode.go b/z80/js/opcode.go similarity index 74% rename from z80em/opcode.go rename to z80/js/opcode.go index fda8fcb..8b3fe5b 100644 --- a/z80em/opcode.go +++ b/z80/js/opcode.go @@ -1,40 +1,40 @@ -package z80em +package js -var instructions = []func(s *Z80Type){ +var instructions = []func(s *Z80){ // NOP - 0x00: func(s *Z80Type) { + 0x00: func(s *Z80) { // NOP }, // LD BC, nn - 0x01: func(s *Z80Type) { + 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 *Z80Type) { + 0x02: func(s *Z80) { s.core.MemWrite(s.bc(), s.A) }, // 0x03 : INC BC - 0x03: func(s *Z80Type) { + 0x03: func(s *Z80) { s.incBc() }, // 0x04 : INC B - 0x04: func(s *Z80Type) { + 0x04: func(s *Z80) { s.B = s.doInc(s.B) }, // 0x05 : DEC B - 0x05: func(s *Z80Type) { + 0x05: func(s *Z80) { s.B = s.doDec(s.B) }, // 0x06 : LD B, n - 0x06: func(s *Z80Type) { + 0x06: func(s *Z80) { s.PC++ s.B = s.core.MemRead(s.PC) }, // 0x07 : RLCA - 0x07: func(s *Z80Type) { + 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. @@ -48,39 +48,39 @@ var instructions = []func(s *Z80Type){ s.Flags.P = tempP }, // 0x08 : EX AF, AF' - 0x08: func(s *Z80Type) { + 0x08: func(s *Z80) { s.A, s.AAlt = s.AAlt, s.A temp := s.getFlagsRegister() s.setFlagsRegister(s.getFlagsPrimeRegister()) s.setFlagsPrimeRegister(temp) }, // 0x09 : ADD HL, BC - 0x09: func(s *Z80Type) { + 0x09: func(s *Z80) { s.doHlAdd(s.bc()) }, // 0x0a : LD A, (BC) - 0x0A: func(s *Z80Type) { + 0x0A: func(s *Z80) { s.A = s.core.MemRead(s.bc()) }, // 0x0b : DEC BC - 0x0B: func(s *Z80Type) { + 0x0B: func(s *Z80) { s.decBc() }, // 0x0c : INC C - 0x0C: func(s *Z80Type) { + 0x0C: func(s *Z80) { s.C = s.doInc(s.C) }, // 0x0d : DEC C - 0x0D: func(s *Z80Type) { + 0x0D: func(s *Z80) { s.C = s.doDec(s.C) }, // 0x0e : LD C, n - 0x0E: func(s *Z80Type) { + 0x0E: func(s *Z80) { s.PC++ s.C = s.core.MemRead(s.PC) }, // 0x0f : RRCA - 0x0F: func(s *Z80Type) { + 0x0F: func(s *Z80) { tempS := s.Flags.S tempZ := s.Flags.Z tempP := s.Flags.P @@ -90,40 +90,40 @@ var instructions = []func(s *Z80Type){ s.Flags.P = tempP }, // 0x10 : DJNZ nn - 0x10: func(s *Z80Type) { + 0x10: func(s *Z80) { s.B-- s.doConditionalRelativeJump(s.B != 0) }, // 0x11 : LD DE, nn - 0x11: func(s *Z80Type) { + 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 *Z80Type) { + 0x12: func(s *Z80) { s.core.MemWrite(s.de(), s.A) }, // 0x13 : INC DE - 0x13: func(s *Z80Type) { + 0x13: func(s *Z80) { s.incDe() }, // 0x14 : INC D - 0x14: func(s *Z80Type) { + 0x14: func(s *Z80) { s.D = s.doInc(s.D) }, // 0x15 : DEC D - 0x15: func(s *Z80Type) { + 0x15: func(s *Z80) { s.D = s.doDec(s.D) }, // 0x16 : LD D, n - 0x16: func(s *Z80Type) { + 0x16: func(s *Z80) { s.PC++ s.D = s.core.MemRead(s.PC) }, // 0x17 : RLA - 0x17: func(s *Z80Type) { + 0x17: func(s *Z80) { tempS := s.Flags.S tempZ := s.Flags.Z tempP := s.Flags.P @@ -133,7 +133,7 @@ var instructions = []func(s *Z80Type){ s.Flags.P = tempP }, // 0x18 : JR n - 0x18: func(s *Z80Type) { + 0x18: func(s *Z80) { var o = int8(s.core.MemRead(s.PC + 1)) if o > 0 { s.PC += uint16(o) @@ -143,32 +143,32 @@ var instructions = []func(s *Z80Type){ s.PC++ }, // 0x19 : ADD HL, DE - 0x19: func(s *Z80Type) { + 0x19: func(s *Z80) { s.doHlAdd(s.de()) }, // 0x1a : LD A, (DE) - 0x1A: func(s *Z80Type) { + 0x1A: func(s *Z80) { s.A = s.core.MemRead(s.de()) }, // 0x1b : DEC DE - 0x1B: func(s *Z80Type) { + 0x1B: func(s *Z80) { s.decDe() }, // 0x1c : INC E - 0x1C: func(s *Z80Type) { + 0x1C: func(s *Z80) { s.E = s.doInc(s.E) }, // 0x1d : DEC E - 0x1D: func(s *Z80Type) { + 0x1D: func(s *Z80) { s.E = s.doDec(s.E) }, // 0x1e : LD E, n - 0x1E: func(s *Z80Type) { + 0x1E: func(s *Z80) { s.PC++ s.E = s.core.MemRead(s.PC) }, // 0x1f : RRA - 0x1F: func(s *Z80Type) { + 0x1F: func(s *Z80) { tempS := s.Flags.S tempZ := s.Flags.Z tempP := s.Flags.P @@ -178,41 +178,41 @@ var instructions = []func(s *Z80Type){ s.Flags.P = tempP }, // 0x20 : JR NZ, n - 0x20: func(s *Z80Type) { + 0x20: func(s *Z80) { s.doConditionalRelativeJump(!s.Flags.Z) }, // 0x21 : LD HL, nn - 0x21: func(s *Z80Type) { + 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 *Z80Type) { + 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 *Z80Type) { + 0x23: func(s *Z80) { s.incHl() }, // 0x24 : INC H - 0x24: func(s *Z80Type) { + 0x24: func(s *Z80) { s.H = s.doInc(s.H) }, // 0x25 : DEC H - 0x25: func(s *Z80Type) { + 0x25: func(s *Z80) { s.H = s.doDec(s.H) }, // 0x26 : LD H, n - 0x26: func(s *Z80Type) { + 0x26: func(s *Z80) { s.PC++ s.H = s.core.MemRead(s.PC) }, // 0x27 : DAA - 0x27: func(s *Z80Type) { + 0x27: func(s *Z80) { temp := s.A if !s.Flags.N { if s.Flags.H || ((s.A & 0x0f) > 9) { @@ -243,231 +243,231 @@ var instructions = []func(s *Z80Type){ s.updateXYFlags(s.A) }, // 0x28 : JR Z, n - 0x28: func(s *Z80Type) { + 0x28: func(s *Z80) { s.doConditionalRelativeJump(s.Flags.Z) }, // 0x29 : ADD HL, HL - 0x29: func(s *Z80Type) { + 0x29: func(s *Z80) { s.doHlAdd(s.hl()) }, // 0x2a : LD HL, (nn) - 0x2A: func(s *Z80Type) { + 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 *Z80Type) { + 0x2B: func(s *Z80) { s.decHl() }, // 0x2c : INC L - 0x2C: func(s *Z80Type) { + 0x2C: func(s *Z80) { s.L = s.doInc(s.L) }, // 0x2d : DEC L - 0x2D: func(s *Z80Type) { + 0x2D: func(s *Z80) { s.L = s.doDec(s.L) }, // 0x2e : LD L, n - 0x2E: func(s *Z80Type) { + 0x2E: func(s *Z80) { s.PC++ s.L = s.core.MemRead(s.PC) }, // 0x2f : CPL - 0x2F: func(s *Z80Type) { + 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 *Z80Type) { + 0x30: func(s *Z80) { s.doConditionalRelativeJump(!s.Flags.C) }, // 0x31 : LD SP, nn - 0x31: func(s *Z80Type) { + 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 *Z80Type) { + 0x32: func(s *Z80) { s.core.MemWrite(s.nextWord(), s.A) }, // 0x33 : INC SP - 0x33: func(s *Z80Type) { + 0x33: func(s *Z80) { s.SP++ }, // 0x34 : INC (HL) - 0x34: func(s *Z80Type) { + 0x34: func(s *Z80) { s.core.MemWrite(s.hl(), s.doInc(s.core.MemRead(s.hl()))) }, // 0x35 : DEC (HL) - 0x35: func(s *Z80Type) { + 0x35: func(s *Z80) { s.core.MemWrite(s.hl(), s.doDec(s.core.MemRead(s.hl()))) }, // 0x36 : LD (HL), n - 0x36: func(s *Z80Type) { + 0x36: func(s *Z80) { s.PC++ s.core.MemWrite(s.hl(), s.core.MemRead(s.PC)) }, // 0x37 : SCF - 0x37: func(s *Z80Type) { + 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 *Z80Type) { + 0x38: func(s *Z80) { s.doConditionalRelativeJump(s.Flags.C) }, // 0x39 : ADD HL, SP - 0x39: func(s *Z80Type) { + 0x39: func(s *Z80) { s.doHlAdd(s.SP) }, // 0x3a : LD A, (nn) - 0x3A: func(s *Z80Type) { + 0x3A: func(s *Z80) { s.A = s.core.MemRead(s.nextWord()) }, // 0x3b : DEC SP - 0x3B: func(s *Z80Type) { + 0x3B: func(s *Z80) { s.SP-- }, // 0x3c : INC A - 0x3C: func(s *Z80Type) { + 0x3C: func(s *Z80) { s.A = s.doInc(s.A) }, // 0x3d : DEC A - 0x3D: func(s *Z80Type) { + 0x3D: func(s *Z80) { s.A = s.doDec(s.A) }, // 0x3e : LD A, n - 0x3E: func(s *Z80Type) { + 0x3E: func(s *Z80) { s.PC++ s.A = s.core.MemRead(s.PC) }, // 0x3f : CCF - 0x3F: func(s *Z80Type) { + 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 *Z80Type) { + 0xC0: func(s *Z80) { s.doConditionalReturn(!s.Flags.Z) }, // 0xc1 : POP BC - 0xC1: func(s *Z80Type) { + 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 *Z80Type) { + 0xC2: func(s *Z80) { s.doConditionalAbsoluteJump(!s.Flags.Z) }, // 0xc3 : JP nn - 0xC3: func(s *Z80Type) { + 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 *Z80Type) { + 0xC4: func(s *Z80) { s.doConditionalCall(!s.Flags.Z) }, // 0xc5 : PUSH BC - 0xC5: func(s *Z80Type) { + 0xC5: func(s *Z80) { s.pushWord((uint16(s.B) << 8) | uint16(s.C)) }, // 0xc6 : ADD A, n - 0xC6: func(s *Z80Type) { + 0xC6: func(s *Z80) { s.PC++ s.doAdd(s.core.MemRead(s.PC)) }, // 0xc7 : RST 00h - 0xC7: func(s *Z80Type) { + 0xC7: func(s *Z80) { s.doReset(0x0000) }, // 0xc8 : RET Z - 0xC8: func(s *Z80Type) { + 0xC8: func(s *Z80) { s.doConditionalReturn(s.Flags.Z) }, // 0xc9 : RET - 0xC9: func(s *Z80Type) { + 0xC9: func(s *Z80) { s.PC = s.PopWord() - 1 }, // 0xca : JP Z, nn - 0xCA: func(s *Z80Type) { + 0xCA: func(s *Z80) { s.doConditionalAbsoluteJump(s.Flags.Z) }, // 0xcb : CB Prefix - 0xCB: func(s *Z80Type) { + 0xCB: func(s *Z80) { s.opcodeCB() }, // 0xcc : CALL Z, nn - 0xCC: func(s *Z80Type) { + 0xCC: func(s *Z80) { s.doConditionalCall(s.Flags.Z) }, // 0xcd : CALL nn - 0xCD: func(s *Z80Type) { + 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 *Z80Type) { + 0xCE: func(s *Z80) { s.PC++ s.doAdc(s.core.MemRead(s.PC)) }, // 0xcf : RST 08h - 0xCF: func(s *Z80Type) { + 0xCF: func(s *Z80) { s.doReset(0x0008) }, // 0xd0 : RET NC - 0xD0: func(s *Z80Type) { + 0xD0: func(s *Z80) { s.doConditionalReturn(!s.Flags.C) }, // 0xd1 : POP DE - 0xD1: func(s *Z80Type) { + 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 *Z80Type) { + 0xD2: func(s *Z80) { s.doConditionalAbsoluteJump(!s.Flags.C) }, // 0xd3 : OUT (n), A - 0xD3: func(s *Z80Type) { + 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 *Z80Type) { + 0xD4: func(s *Z80) { s.doConditionalCall(!s.Flags.C) }, // 0xd5 : PUSH DE - 0xD5: func(s *Z80Type) { + 0xD5: func(s *Z80) { s.pushWord((uint16(s.D) << 8) | uint16(s.E)) }, // 0xd6 : SUB n - 0xD6: func(s *Z80Type) { + 0xD6: func(s *Z80) { s.PC++ s.doSub(s.core.MemRead(s.PC)) }, // 0xd7 : RST 10h - 0xD7: func(s *Z80Type) { + 0xD7: func(s *Z80) { s.doReset(0x0010) }, // 0xd8 : RET C - 0xD8: func(s *Z80Type) { + 0xD8: func(s *Z80) { s.doConditionalReturn(s.Flags.C) }, // 0xd9 : EXX - 0xD9: func(s *Z80Type) { + 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 @@ -476,47 +476,47 @@ var instructions = []func(s *Z80Type){ s.L, s.LAlt = s.LAlt, s.L }, // 0xda : JP C, nn - 0xDA: func(s *Z80Type) { + 0xDA: func(s *Z80) { s.doConditionalAbsoluteJump(s.Flags.C) }, // 0xdb : IN A, (n) - 0xDB: func(s *Z80Type) { + 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 *Z80Type) { + 0xDC: func(s *Z80) { s.doConditionalCall(s.Flags.C) }, // 0xdd : DD Prefix (IX instructions) - 0xDD: func(s *Z80Type) { + 0xDD: func(s *Z80) { s.opcodeDD() }, // 0xde : SBC n - 0xDE: func(s *Z80Type) { + 0xDE: func(s *Z80) { s.PC++ s.doSbc(s.core.MemRead(s.PC)) }, // 0xdf : RST 18h - 0xDF: func(s *Z80Type) { + 0xDF: func(s *Z80) { s.doReset(0x0018) }, // 0xe0 : RET PO - 0xE0: func(s *Z80Type) { + 0xE0: func(s *Z80) { s.doConditionalReturn(!s.Flags.P) }, // 0xe1 : POP HL - 0xE1: func(s *Z80Type) { + 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 *Z80Type) { + 0xE2: func(s *Z80) { s.doConditionalAbsoluteJump(!s.Flags.P) }, // 0xe3 : EX (SP), HL - 0xE3: func(s *Z80Type) { + 0xE3: func(s *Z80) { temp := s.core.MemRead(s.SP) s.core.MemWrite(s.SP, s.L) s.L = temp @@ -525,130 +525,130 @@ var instructions = []func(s *Z80Type){ s.H = temp }, // 0xe4 : CALL PO, nn - 0xE4: func(s *Z80Type) { + 0xE4: func(s *Z80) { s.doConditionalCall(!s.Flags.P) }, // 0xe5 : PUSH HL - 0xE5: func(s *Z80Type) { + 0xE5: func(s *Z80) { s.pushWord((uint16(s.H) << 8) | uint16(s.L)) }, // 0xe6 : AND n - 0xE6: func(s *Z80Type) { + 0xE6: func(s *Z80) { s.PC++ s.doAnd(s.core.MemRead(s.PC)) }, // 0xe7 : RST 20h - 0xE7: func(s *Z80Type) { + 0xE7: func(s *Z80) { s.doReset(0x0020) }, // 0xe8 : RET PE - 0xE8: func(s *Z80Type) { + 0xE8: func(s *Z80) { s.doConditionalReturn(s.Flags.P) }, // 0xe9 : JP (HL) - 0xE9: func(s *Z80Type) { + 0xE9: func(s *Z80) { s.PC = uint16(s.H)<<8 | uint16(s.L) s.PC-- }, // 0xea : JP PE, nn - 0xEA: func(s *Z80Type) { + 0xEA: func(s *Z80) { s.doConditionalAbsoluteJump(s.Flags.P) }, // 0xeb : EX DE, HL - 0xEB: func(s *Z80Type) { + 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 *Z80Type) { + 0xEC: func(s *Z80) { s.doConditionalCall(s.Flags.P) }, // 0xed : ED Prefix - 0xED: func(s *Z80Type) { + 0xED: func(s *Z80) { s.opcodeED() }, // 0xee : XOR n - 0xEE: func(s *Z80Type) { + 0xEE: func(s *Z80) { s.PC++ s.doXor(s.core.MemRead(s.PC)) }, // 0xef : RST 28h - 0xEF: func(s *Z80Type) { + 0xEF: func(s *Z80) { s.doReset(0x0028) }, // 0xf0 : RET P - 0xF0: func(s *Z80Type) { + 0xF0: func(s *Z80) { s.doConditionalReturn(!s.Flags.S) }, // 0xf1 : POP AF - 0xF1: func(s *Z80Type) { + 0xF1: func(s *Z80) { var result = s.PopWord() s.setFlagsRegister(byte(result & 0xff)) s.A = byte((result & 0xff00) >> 8) }, // 0xf2 : JP P, nn - 0xF2: func(s *Z80Type) { + 0xF2: func(s *Z80) { s.doConditionalAbsoluteJump(!s.Flags.S) }, // 0xf3 : DI - 0xF3: func(s *Z80Type) { + 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 *Z80Type) { + 0xF4: func(s *Z80) { s.doConditionalCall(!s.Flags.S) }, // 0xf5 : PUSH AF - 0xF5: func(s *Z80Type) { + 0xF5: func(s *Z80) { s.pushWord(uint16(s.getFlagsRegister()) | (uint16(s.A) << 8)) }, // 0xf6 : OR n - 0xF6: func(s *Z80Type) { + 0xF6: func(s *Z80) { s.PC++ s.doOr(s.core.MemRead(s.PC)) }, // 0xf7 : RST 30h - 0xF7: func(s *Z80Type) { + 0xF7: func(s *Z80) { s.doReset(0x0030) }, // 0xf8 : RET M - 0xF8: func(s *Z80Type) { + 0xF8: func(s *Z80) { s.doConditionalReturn(s.Flags.S) }, // 0xf9 : LD SP, HL - 0xF9: func(s *Z80Type) { + 0xF9: func(s *Z80) { s.SP = uint16(s.H)<<8 | uint16(s.L) }, // 0xfa : JP M, nn - 0xFA: func(s *Z80Type) { + 0xFA: func(s *Z80) { s.doConditionalAbsoluteJump(s.Flags.S) }, // 0xfb : EI - 0xFB: func(s *Z80Type) { + 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 *Z80Type) { + 0xFC: func(s *Z80) { s.doConditionalCall(s.Flags.S) }, // 0xfd : FD Prefix (IY instructions) - 0xFD: func(s *Z80Type) { + 0xFD: func(s *Z80) { s.opcodeFD() }, // 0xfe : CP n - 0xFE: func(s *Z80Type) { + 0xFE: func(s *Z80) { s.PC++ s.doCp(s.core.MemRead(s.PC)) }, // 0xff : RST 38h - 0xFF: func(s *Z80Type) { + 0xFF: func(s *Z80) { s.doReset(0x0038) }, } -func (z *Z80Type) nextWord() uint16 { +func (z *Z80) nextWord() uint16 { z.PC++ word := uint16(z.core.MemRead(z.PC)) z.PC++ diff --git a/z80em/opcodeCB.go b/z80/js/opcodeCB.go similarity index 98% rename from z80em/opcodeCB.go rename to z80/js/opcodeCB.go index 7d8fc42..c5d9039 100644 --- a/z80em/opcodeCB.go +++ b/z80/js/opcodeCB.go @@ -1,6 +1,6 @@ -package z80em +package js -func (z *Z80Type) opcodeCB() { +func (z *Z80) opcodeCB() { z.incR() z.PC++ opcode := z.core.M1MemRead(z.PC) diff --git a/z80em/opcodeDD.go b/z80/js/opcodeDD.go similarity index 78% rename from z80em/opcodeDD.go rename to z80/js/opcodeDD.go index f6ce39a..6d87033 100644 --- a/z80em/opcodeDD.go +++ b/z80/js/opcodeDD.go @@ -1,361 +1,361 @@ -package z80em +package js -var ddInstructions = []func(s *Z80Type){ +var ddInstructions = []func(s *Z80){ // 0x09 : ADD IX, BC - 0x09: func(s *Z80Type) { + 0x09: func(s *Z80) { s.doIxAdd(s.bc()) }, // 0x19 : ADD IX, DE - 0x19: func(s *Z80Type) { + 0x19: func(s *Z80) { s.doIxAdd(s.de()) }, // 0x21 : LD IX, nn - 0x21: func(s *Z80Type) { + 0x21: func(s *Z80) { s.IX = s.nextWord() }, // 0x22 : LD (nn), IX - 0x22: func(s *Z80Type) { + 0x22: func(s *Z80) { s.setWord(s.nextWord(), s.IX) }, // 0x23 : INC IX - 0x23: func(s *Z80Type) { + 0x23: func(s *Z80) { s.IX++ }, // 0x24 : INC IXH (Undocumented) - 0x24: func(s *Z80Type) { + 0x24: func(s *Z80) { s.IX = (uint16(s.doInc(byte(s.IX>>8))) << 8) | (s.IX & 0x00ff) }, // 0x25 : DEC IXH (Undocumented) - 0x25: func(s *Z80Type) { + 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 *Z80Type) { + 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 *Z80Type) { + 0x29: func(s *Z80) { s.doIxAdd(s.IX) }, // 0x2a : LD IX, (nn) - 0x2A: func(s *Z80Type) { + 0x2A: func(s *Z80) { s.IX = s.getWord(s.nextWord()) }, // 0x2b : DEC IX - 0x2B: func(s *Z80Type) { + 0x2B: func(s *Z80) { s.IX-- }, // 0x2c : INC IXL (Undocumented) - 0x2C: func(s *Z80Type) { + 0x2C: func(s *Z80) { s.IX = (uint16(s.doInc(byte(s.IX & 0x00ff)))) | (s.IX & 0xff00) }, // 0x2d : DEC IXL (Undocumented) - 0x2D: func(s *Z80Type) { + 0x2D: func(s *Z80) { s.IX = (uint16(s.doDec(byte(s.IX & 0x00ff)))) | (s.IX & 0xff00) }, // 0x2e : LD IXL, n (Undocumented) - 0x2E: func(s *Z80Type) { + 0x2E: func(s *Z80) { s.PC++ s.IX = (uint16(s.core.MemRead(s.PC))) | (s.IX & 0xff00) }, // 0x34 : INC (IX+n) - 0x34: func(s *Z80Type) { + 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 *Z80Type) { + 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 *Z80Type) { + 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 *Z80Type) { + 0x39: func(s *Z80) { s.doIxAdd(s.SP) }, // 0x44 : LD B, IXH (Undocumented) - 0x44: func(s *Z80Type) { + 0x44: func(s *Z80) { s.B = byte(s.IX >> 8) }, // 0x45 : LD B, IXL (Undocumented) - 0x45: func(s *Z80Type) { + 0x45: func(s *Z80) { s.B = byte(s.IX & 0x00ff) }, // 0x46 : LD B, (IX+n) - 0x46: func(s *Z80Type) { + 0x46: func(s *Z80) { s.B = s.core.MemRead(s.getOffset(s.IX)) }, // 0x4c : LD C, IXH (Undocumented) - 0x4C: func(s *Z80Type) { + 0x4C: func(s *Z80) { s.C = byte(s.IX >> 8) }, // 0x4d : LD C, IXL (Undocumented) - 0x4D: func(s *Z80Type) { + 0x4D: func(s *Z80) { s.C = byte(s.IX & 0x00ff) }, // 0x4e : LD C, (IX+n) - 0x4E: func(s *Z80Type) { + 0x4E: func(s *Z80) { s.C = s.core.MemRead(s.getOffset(s.IX)) }, // 0x54 : LD D, IXH (Undocumented) - 0x54: func(s *Z80Type) { + 0x54: func(s *Z80) { s.D = byte(s.IX >> 8) }, // 0x55 : LD D, IXL (Undocumented) - 0x55: func(s *Z80Type) { + 0x55: func(s *Z80) { s.D = byte(s.IX) }, // 0x56 : LD D, (IX+n) - 0x56: func(s *Z80Type) { + 0x56: func(s *Z80) { offset := s.getOffset(s.IX) s.D = s.core.MemRead(offset) }, // 0x5d : LD E, IXL (Undocumented) - 0x5D: func(s *Z80Type) { + 0x5D: func(s *Z80) { s.E = byte(s.IX) }, // 0x5e : LD E, (IX+n) - 0x5E: func(s *Z80Type) { + 0x5E: func(s *Z80) { s.E = s.core.MemRead(s.getOffset(s.IX)) }, // 0x60 : LD IXH, B (Undocumented) - 0x60: func(s *Z80Type) { + 0x60: func(s *Z80) { s.IX = uint16(s.B)<<8 | s.IX&0x00ff }, // 0x61 : LD IXH, C (Undocumented) - 0x61: func(s *Z80Type) { + 0x61: func(s *Z80) { s.IX = uint16(s.C)<<8 | s.IX&0x00ff }, // 0x62 : LD IXH, D (Undocumented) - 0x62: func(s *Z80Type) { + 0x62: func(s *Z80) { s.IX = uint16(s.D)<<8 | s.IX&0x00ff }, // 0x63 : LD IXH, E (Undocumented) - 0x63: func(s *Z80Type) { + 0x63: func(s *Z80) { s.IX = uint16(s.E)<<8 | s.IX&0x00ff }, // 0x64 : LD IXH, IXH (Undocumented) - 0x64: func(s *Z80Type) { + 0x64: func(s *Z80) { // NOP }, // 0x65 : LD IXH, IXL (Undocumented) - 0x65: func(s *Z80Type) { + 0x65: func(s *Z80) { s.IX = (s.IX << 8) | (s.IX & 0x00ff) }, // 0x66 : LD H, (IX+n) - 0x66: func(s *Z80Type) { + 0x66: func(s *Z80) { s.H = s.core.MemRead(s.getOffset(s.IX)) }, // 0x67 : LD IXH, A (Undocumented) - 0x67: func(s *Z80Type) { + 0x67: func(s *Z80) { s.IX = (uint16(s.A) << 8) | (s.IX & 0x00ff) }, // 0x68 : LD IXL, B (Undocumented) - 0x68: func(s *Z80Type) { + 0x68: func(s *Z80) { s.IX = (s.IX & 0xff00) | uint16(s.B) }, // 0x69 : LD IXL, C (Undocumented) - 0x69: func(s *Z80Type) { + 0x69: func(s *Z80) { s.IX = (s.IX & 0xff00) | uint16(s.C) }, // 0x6a : LD IXL, D (Undocumented) - 0x6a: func(s *Z80Type) { + 0x6a: func(s *Z80) { s.IX = (s.IX & 0xff00) | uint16(s.D) }, // 0x6b : LD IXL, E (Undocumented) - 0x6b: func(s *Z80Type) { + 0x6b: func(s *Z80) { s.IX = (s.IX & 0xff00) | uint16(s.E) }, // 0x6c : LD IXL, IXH (Undocumented) - 0x6c: func(s *Z80Type) { + 0x6c: func(s *Z80) { s.IX = (s.IX >> 8) | (s.IX & 0xff00) }, // 0x6d : LD IXL, IXL (Undocumented) - 0x6d: func(s *Z80Type) { + 0x6d: func(s *Z80) { // NOP }, // 0x6e : LD L, (IX+n) - 0x6e: func(s *Z80Type) { + 0x6e: func(s *Z80) { s.L = s.core.MemRead(s.getOffset(s.IX)) }, // 0x6f : LD IXL, A (Undocumented) - 0x6f: func(s *Z80Type) { + 0x6f: func(s *Z80) { s.IX = uint16(s.A) | (s.IX & 0xff00) }, // 0x70 : LD (IX+n), B - 0x70: func(s *Z80Type) { + 0x70: func(s *Z80) { s.core.MemWrite(s.getOffset(s.IX), s.B) }, // 0x71 : LD (IX+n), C - 0x71: func(s *Z80Type) { + 0x71: func(s *Z80) { s.core.MemWrite(s.getOffset(s.IX), s.C) }, // 0x72 : LD (IX+n), D - 0x72: func(s *Z80Type) { + 0x72: func(s *Z80) { s.core.MemWrite(s.getOffset(s.IX), s.D) }, // 0x73 : LD (IX+n), E - 0x73: func(s *Z80Type) { + 0x73: func(s *Z80) { s.core.MemWrite(s.getOffset(s.IX), s.E) }, // 0x74 : LD (IX+n), H - 0x74: func(s *Z80Type) { + 0x74: func(s *Z80) { s.core.MemWrite(s.getOffset(s.IX), s.H) }, // 0x75 : LD (IX+n), L - 0x75: func(s *Z80Type) { + 0x75: func(s *Z80) { s.core.MemWrite(s.getOffset(s.IX), s.L) }, // 0x77 : LD (IX+n), A - 0x77: func(s *Z80Type) { + 0x77: func(s *Z80) { s.core.MemWrite(s.getOffset(s.IX), s.A) }, // 0x7c : LD A, IXH (Undocumented) - 0x7C: func(s *Z80Type) { + 0x7C: func(s *Z80) { s.A = byte(s.IX >> 8) }, // 0x7d : LD A, IXL (Undocumented) - 0x7D: func(s *Z80Type) { + 0x7D: func(s *Z80) { s.A = byte(s.IX & 0x00ff) }, // 0x7e : LD A, (IX+n) - 0x7E: func(s *Z80Type) { + 0x7E: func(s *Z80) { s.A = s.core.MemRead(s.getOffset(s.IX)) }, // 0x84 : ADD A, IXH (Undocumented) - 0x84: func(s *Z80Type) { + 0x84: func(s *Z80) { s.doAdd(byte(s.IX >> 8)) }, // 0x85 : ADD A, IXL (Undocumented) - 0x85: func(s *Z80Type) { + 0x85: func(s *Z80) { s.doAdd(byte(s.IX)) }, // 0x86 : ADD A, (IX+n) - 0x86: func(s *Z80Type) { + 0x86: func(s *Z80) { s.doAdd(s.core.MemRead(s.getOffset(s.IX))) }, // 0x8c : ADC A, IXH (Undocumented) - 0x8C: func(s *Z80Type) { + 0x8C: func(s *Z80) { s.doAdc(byte(s.IX >> 8)) }, // 0x8d : ADC A, IXL (Undocumented) - 0x8D: func(s *Z80Type) { + 0x8D: func(s *Z80) { s.doAdc(byte(s.IX)) }, // 0x8e : ADC A, (IX+n) - 0x8E: func(s *Z80Type) { + 0x8E: func(s *Z80) { s.doAdc(s.core.MemRead(s.getOffset(s.IX))) }, // 0x94 : SUB IXH (Undocumented) - 0x94: func(s *Z80Type) { + 0x94: func(s *Z80) { s.doSub(byte(s.IX >> 8)) }, // 0x95 : SUB IXL (Undocumented) - 0x95: func(s *Z80Type) { + 0x95: func(s *Z80) { s.doSub(byte(s.IX)) }, // 0x96 : SUB A, (IX+n) - 0x96: func(s *Z80Type) { + 0x96: func(s *Z80) { s.doSub(s.core.MemRead(s.getOffset(s.IX))) }, // 0x9c : SBC IXH (Undocumented) - 0x9C: func(s *Z80Type) { + 0x9C: func(s *Z80) { s.doSbc(byte(s.IX >> 8)) }, // 0x9d : SBC IXL (Undocumented) - 0x9D: func(s *Z80Type) { + 0x9D: func(s *Z80) { s.doSbc(byte(s.IX)) }, // 0x9e : SBC A, (IX+n) - 0x9E: func(s *Z80Type) { + 0x9E: func(s *Z80) { s.doSbc(s.core.MemRead(s.getOffset(s.IX))) }, // 0xa4 : AND IXH (Undocumented) - 0xA4: func(s *Z80Type) { + 0xA4: func(s *Z80) { s.doAnd(byte(s.IX >> 8)) }, // 0xa5 : AND IXL (Undocumented) - 0xA5: func(s *Z80Type) { + 0xA5: func(s *Z80) { s.doAnd(byte(s.IX)) }, // 0xa6 : AND A, (IX+n) - 0xA6: func(s *Z80Type) { + 0xA6: func(s *Z80) { s.doAnd(s.core.MemRead(s.getOffset(s.IX))) }, // 0xac : XOR IXH (Undocumented) - 0xAC: func(s *Z80Type) { + 0xAC: func(s *Z80) { s.doXor(byte(s.IX >> 8)) }, // 0xad : XOR IXL (Undocumented) - 0xAD: func(s *Z80Type) { + 0xAD: func(s *Z80) { s.doXor(byte(s.IX)) }, // 0xae : XOR A, (IX+n) - 0xAE: func(s *Z80Type) { + 0xAE: func(s *Z80) { s.doXor(s.core.MemRead(s.getOffset(s.IX))) }, // 0xb4 : OR IXH (Undocumented) - 0xB4: func(s *Z80Type) { + 0xB4: func(s *Z80) { s.doOr(byte(s.IX >> 8)) }, // 0xb5 : OR IXL (Undocumented) - 0xB5: func(s *Z80Type) { + 0xB5: func(s *Z80) { s.doOr(byte(s.IX)) }, // 0xb6 : OR A, (IX+n) - 0xB6: func(s *Z80Type) { + 0xB6: func(s *Z80) { s.doOr(s.core.MemRead(s.getOffset(s.IX))) }, // 0xbc : CP IXH (Undocumented) - 0xBC: func(s *Z80Type) { + 0xBC: func(s *Z80) { s.doCp(byte(s.IX >> 8)) }, // 0xbd : CP IXL (Undocumented) - 0xBD: func(s *Z80Type) { + 0xBD: func(s *Z80) { s.doCp(byte(s.IX)) }, // 0xbe : CP A, (IX+n) - 0xBE: func(s *Z80Type) { + 0xBE: func(s *Z80) { s.doCp(s.core.MemRead(s.getOffset(s.IX))) }, // 0xcb : CB Prefix (IX bit instructions) - 0xCB: func(s *Z80Type) { + 0xCB: func(s *Z80) { s.opcodeDDCB() }, // 0xe1 : POP IX - 0xE1: func(s *Z80Type) { + 0xE1: func(s *Z80) { s.IX = s.PopWord() }, // 0xe3 : EX (SP), IX - 0xE3: func(s *Z80Type) { + 0xE3: func(s *Z80) { ix := s.IX s.IX = s.getWord(s.SP) s.setWord(s.SP, ix) }, // 0xe5 : PUSH IX - 0xE5: func(s *Z80Type) { + 0xE5: func(s *Z80) { s.pushWord(s.IX) }, // 0xe9 : JP (IX) - 0xE9: func(s *Z80Type) { + 0xE9: func(s *Z80) { s.PC = s.IX - 1 }, // 0xf9 : LD SP, IX - 0xf9: func(s *Z80Type) { + 0xf9: func(s *Z80) { s.SP = s.IX }, } // ===================================================== -func (z *Z80Type) getOffset(reg uint16) uint16 { +func (z *Z80) getOffset(reg uint16) uint16 { z.PC++ offset := z.core.MemRead(z.PC) if offset < 0 { @@ -366,7 +366,7 @@ func (z *Z80Type) getOffset(reg uint16) uint16 { return reg } -func (z *Z80Type) opcodeDD() { +func (z *Z80) opcodeDD() { z.incR() z.PC++ opcode := z.core.M1MemRead(z.PC) @@ -387,7 +387,7 @@ func (z *Z80Type) opcodeDD() { } } -func (z *Z80Type) opcodeDDCB() { +func (z *Z80) opcodeDDCB() { offset := z.getOffset(z.IX) z.PC++ @@ -456,7 +456,7 @@ func (z *Z80Type) opcodeDDCB() { } // opcodeFD do same for IY as for IX (DD prefix) -func (z *Z80Type) opcodeFD() { +func (z *Z80) opcodeFD() { z.incR() z.PC++ opcode := z.core.M1MemRead(z.PC) diff --git a/z80em/opcodeED.go b/z80/js/opcodeED.go similarity index 70% rename from z80em/opcodeED.go rename to z80/js/opcodeED.go index 7afbb13..5a4f865 100644 --- a/z80em/opcodeED.go +++ b/z80/js/opcodeED.go @@ -1,182 +1,182 @@ -package z80em +package js -var edInstructions = []func(s *Z80Type){ +var edInstructions = []func(s *Z80){ // 0x40 : IN B, (C) - 0x40: func(s *Z80Type) { + 0x40: func(s *Z80) { s.B = s.doIn(s.bc()) }, // 0x41 : OUT (C), B - 0x41: func(s *Z80Type) { + 0x41: func(s *Z80) { s.core.IOWrite(s.bc(), s.B) }, // 0x42 : SBC HL, BC - 0x42: func(s *Z80Type) { + 0x42: func(s *Z80) { s.doHlSbc(s.bc()) }, // 0x43 : LD (nn), BC - 0x43: func(s *Z80Type) { + 0x43: func(s *Z80) { s.setWord(s.nextWord(), s.bc()) }, // 0x44 : NEG - 0x44: func(s *Z80Type) { + 0x44: func(s *Z80) { s.doNeg() }, // 0x45 : RETN - 0x45: func(s *Z80Type) { + 0x45: func(s *Z80) { s.PC = s.PopWord() - 1 s.Iff1 = s.Iff2 }, // 0x46 : IM 0 - 0x46: func(s *Z80Type) { + 0x46: func(s *Z80) { s.IMode = 0 }, // 0x47 : LD I, A - 0x47: func(s *Z80Type) { + 0x47: func(s *Z80) { s.I = s.A }, // 0x48 : IN C, (C) - 0x48: func(s *Z80Type) { + 0x48: func(s *Z80) { s.C = s.doIn(s.bc()) }, // 0x49 : OUT (C), C - 0x49: func(s *Z80Type) { + 0x49: func(s *Z80) { s.core.IOWrite(s.bc(), s.C) }, // 0x4a : ADC HL, BC - 0x4A: func(s *Z80Type) { + 0x4A: func(s *Z80) { s.doHlAdc(s.bc()) }, // 0x4b : LD BC, (nn) - 0x4B: func(s *Z80Type) { + 0x4B: func(s *Z80) { s.setBc(s.getWord(s.nextWord())) }, // 0x4c : NEG (Undocumented) - 0x4C: func(s *Z80Type) { + 0x4C: func(s *Z80) { s.doNeg() }, // 0x4d : RETI - 0x4D: func(s *Z80Type) { + 0x4D: func(s *Z80) { s.PC = s.PopWord() - 1 }, // 0x4e : IM 0 (Undocumented) - 0x4E: func(s *Z80Type) { + 0x4E: func(s *Z80) { s.IMode = 0 }, // 0x4f : LD R, A - 0x4F: func(s *Z80Type) { + 0x4F: func(s *Z80) { s.R = s.A }, // 0x50 : IN D, (C) - 0x50: func(s *Z80Type) { + 0x50: func(s *Z80) { s.D = s.doIn(s.bc()) }, // 0x51 : OUT (C), D - 0x51: func(s *Z80Type) { + 0x51: func(s *Z80) { s.core.IOWrite(s.bc(), s.D) }, // 0x52 : SBC HL, DE - 0x52: func(s *Z80Type) { + 0x52: func(s *Z80) { s.doHlSbc(s.de()) }, // 0x53 : LD (nn), DE - 0x53: func(s *Z80Type) { + 0x53: func(s *Z80) { s.setWord(s.nextWord(), s.de()) }, // 0x54 : NEG (Undocumented) - 0x54: func(s *Z80Type) { + 0x54: func(s *Z80) { s.doNeg() }, // 0x55 : RETN - 0x55: func(s *Z80Type) { + 0x55: func(s *Z80) { s.PC = s.PopWord() - 1 s.Iff1 = s.Iff2 }, // 0x56 : IM 1 - 0x56: func(s *Z80Type) { + 0x56: func(s *Z80) { s.IMode = 1 }, // 0x57 : LD A, I - 0x57: func(s *Z80Type) { + 0x57: func(s *Z80) { s.A = s.I s.Flags.S = s.A&0x80 != 0 s.Flags.Z = s.A == 0 s.Flags.H = false - s.Flags.P = s.Iff2 != 0 + s.Flags.P = s.Iff2 s.Flags.N = false s.updateXYFlags(s.A) }, // 0x58 : IN E, (C) - 0x58: func(s *Z80Type) { + 0x58: func(s *Z80) { s.E = s.doIn(s.bc()) }, // 0x59 : OUT (C), E - 0x59: func(s *Z80Type) { + 0x59: func(s *Z80) { s.core.IOWrite(s.bc(), s.E) }, // 0x5a : ADC HL, DE - 0x5A: func(s *Z80Type) { + 0x5A: func(s *Z80) { s.doHlAdc(s.de()) }, // 0x5b : LD DE, (nn) - 0x5B: func(s *Z80Type) { + 0x5B: func(s *Z80) { s.setDe(s.getWord(s.nextWord())) }, // 0x5c : NEG (Undocumented) - 0x5C: func(s *Z80Type) { + 0x5C: func(s *Z80) { s.doNeg() }, // 0x5d : RETN - 0x5D: func(s *Z80Type) { + 0x5D: func(s *Z80) { s.PC = s.PopWord() - 1 s.Iff1 = s.Iff2 }, // 0x5e : IM 2 - 0x5E: func(s *Z80Type) { + 0x5E: func(s *Z80) { s.IMode = 2 }, // 0x5f : LD A, R - 0x5F: func(s *Z80Type) { + 0x5F: func(s *Z80) { s.A = s.R s.Flags.S = s.A&0x80 != 0 s.Flags.Z = s.A == 0 s.Flags.H = false - s.Flags.P = s.Iff2 != 0 + s.Flags.P = s.Iff2 s.Flags.N = false s.updateXYFlags(s.A) }, // 0x60 : IN H, (C) - 0x60: func(s *Z80Type) { + 0x60: func(s *Z80) { s.H = s.doIn(s.bc()) }, // 0x61 : OUT (C), H - 0x61: func(s *Z80Type) { + 0x61: func(s *Z80) { s.core.IOWrite(s.bc(), s.H) }, // 0x62 : SBC HL, HL - 0x62: func(s *Z80Type) { + 0x62: func(s *Z80) { s.doHlSbc(s.hl()) }, // 0x63 : LD (nn), HL (Undocumented) - 0x63: func(s *Z80Type) { + 0x63: func(s *Z80) { s.setWord(s.nextWord(), s.hl()) }, // 0x64 : NEG (Undocumented) - 0x64: func(s *Z80Type) { + 0x64: func(s *Z80) { s.doNeg() }, // 0x65 : RETN - 0x65: func(s *Z80Type) { + 0x65: func(s *Z80) { s.PC = s.PopWord() - 1 s.Iff1 = s.Iff2 }, // 0x66 : IM 0 - 0x66: func(s *Z80Type) { + 0x66: func(s *Z80) { s.IMode = 0 }, // 0x67 : RRD - 0x67: func(s *Z80Type) { + 0x67: func(s *Z80) { hlValue := s.core.M1MemRead(s.hl()) temp1 := hlValue & 0x0f temp2 := s.A & 0x0f @@ -192,36 +192,36 @@ var edInstructions = []func(s *Z80Type){ }, // 0x68 : IN L, (C) - 0x68: func(s *Z80Type) { + 0x68: func(s *Z80) { s.L = s.doIn(s.bc()) }, // 0x69 : OUT (C), L - 0x69: func(s *Z80Type) { + 0x69: func(s *Z80) { s.core.IOWrite(s.bc(), s.L) }, // 0x6a : ADC HL, HL - 0x6A: func(s *Z80Type) { + 0x6A: func(s *Z80) { s.doHlAdc(s.hl()) }, // 0x6b : LD HL, (nn) (Undocumented) - 0x6B: func(s *Z80Type) { + 0x6B: func(s *Z80) { s.setHl(s.getWord(s.nextWord())) }, // 0x6C : NEG (Undocumented) - 0x6C: func(s *Z80Type) { + 0x6C: func(s *Z80) { s.doNeg() }, // 0x6D : RETN - 0x6D: func(s *Z80Type) { + 0x6D: func(s *Z80) { s.PC = s.PopWord() - 1 s.Iff1 = s.Iff2 }, // 0x6E : IM 0 - 0x6E: func(s *Z80Type) { + 0x6E: func(s *Z80) { s.IMode = 0 }, // 0x6f : RLD - 0x6F: func(s *Z80Type) { + 0x6F: func(s *Z80) { hlValue := s.core.MemRead(s.hl()) temp1 := hlValue & 0xf0 temp2 := s.A & 0x0f @@ -237,97 +237,97 @@ var edInstructions = []func(s *Z80Type){ s.updateXYFlags(s.A) }, // 0x70 : INF - 0x70: func(s *Z80Type) { + 0x70: func(s *Z80) { s.doIn(s.bc()) }, // 0x71 : OUT (C), 0 (Undocumented) - 0x71: func(s *Z80Type) { + 0x71: func(s *Z80) { s.core.IOWrite(s.bc(), 0) }, // 0x72 : SBC HL, SP - 0x72: func(s *Z80Type) { + 0x72: func(s *Z80) { s.doHlSbc(s.SP) }, // 0x73 : LD (nn), SP - 0x73: func(s *Z80Type) { + 0x73: func(s *Z80) { s.setWord(s.nextWord(), s.SP) }, // 0x74 : NEG (Undocumented) - 0x74: func(s *Z80Type) { + 0x74: func(s *Z80) { s.doNeg() }, // 0x75 : RETN - 0x75: func(s *Z80Type) { + 0x75: func(s *Z80) { s.PC = s.PopWord() - 1 s.Iff1 = s.Iff2 }, // 0x76 : IM 1 - 0x76: func(s *Z80Type) { + 0x76: func(s *Z80) { s.IMode = 1 }, // 0x78 : IN A, (C) - 0x78: func(s *Z80Type) { + 0x78: func(s *Z80) { s.A = s.core.IORead(s.bc()) }, // 0x79 : OUT (C), A - 0x79: func(s *Z80Type) { + 0x79: func(s *Z80) { s.core.IOWrite(s.bc(), s.A) }, // 0x7a : ADC HL, SP - 0x7A: func(s *Z80Type) { + 0x7A: func(s *Z80) { s.doHlAdc(s.SP) }, // 0x7b : LD SP, (nn) - 0x7B: func(s *Z80Type) { + 0x7B: func(s *Z80) { s.SP = s.getWord(s.nextWord()) }, // 0x7c : NEG (Undocumented) - 0x7C: func(s *Z80Type) { + 0x7C: func(s *Z80) { s.doNeg() }, // 0x7d : RETN - 0x7D: func(s *Z80Type) { + 0x7D: func(s *Z80) { s.PC = s.PopWord() - 1 s.Iff1 = s.Iff2 }, // 0x7e : IM 2 - 0x7E: func(s *Z80Type) { + 0x7E: func(s *Z80) { s.IMode = 2 }, // 0xa0 : LDI - 0xA0: func(s *Z80Type) { + 0xA0: func(s *Z80) { s.doLdi() }, // 0xa1 : CPI - 0xA1: func(s *Z80Type) { + 0xA1: func(s *Z80) { s.doCpi() }, // 0xa2 : INI - 0xA2: func(s *Z80Type) { + 0xA2: func(s *Z80) { s.doIni() }, // 0xa3 : OUTI - 0xA3: func(s *Z80Type) { + 0xA3: func(s *Z80) { s.doOuti() }, // 0xa8 : LDD - 0xA8: func(s *Z80Type) { + 0xA8: func(s *Z80) { s.doLdd() }, // 0xa9 : CPD - 0xA9: func(s *Z80Type) { + 0xA9: func(s *Z80) { s.doCpd() }, // 0xaa : IND - 0xAA: func(s *Z80Type) { + 0xAA: func(s *Z80) { s.doInd() }, // 0xab : OUTD - 0xAB: func(s *Z80Type) { + 0xAB: func(s *Z80) { s.doOutd() }, // 0xb0 : LDIR - 0xB0: func(s *Z80Type) { + 0xB0: func(s *Z80) { s.doLdi() if (s.B | s.C) != 0 { s.CycleCounter += 5 @@ -335,7 +335,7 @@ var edInstructions = []func(s *Z80Type){ } }, // 0xb1 : CPIR - 0xB1: func(s *Z80Type) { + 0xB1: func(s *Z80) { s.doCpi() if !s.Flags.Z && (s.B|s.C) != 0 { s.CycleCounter += 5 @@ -343,7 +343,7 @@ var edInstructions = []func(s *Z80Type){ } }, // 0xb2 : INIR - 0xB2: func(s *Z80Type) { + 0xB2: func(s *Z80) { s.doIni() if s.B != 0 { s.CycleCounter += 5 @@ -351,7 +351,7 @@ var edInstructions = []func(s *Z80Type){ } }, // 0xb3 : OTIR - 0xB3: func(s *Z80Type) { + 0xB3: func(s *Z80) { s.doOuti() if s.B != 0 { s.CycleCounter += 5 @@ -359,7 +359,7 @@ var edInstructions = []func(s *Z80Type){ } }, // 0xb8 : LDDR - 0xB8: func(s *Z80Type) { + 0xB8: func(s *Z80) { s.doLdd() if (s.B | s.C) != 0 { s.CycleCounter += 5 @@ -367,7 +367,7 @@ var edInstructions = []func(s *Z80Type){ } }, // 0xb9 : CPDR - 0xB9: func(s *Z80Type) { + 0xB9: func(s *Z80) { s.doCpd() if !s.Flags.Z && (s.B|s.C) != 0 { s.CycleCounter += 5 @@ -375,7 +375,7 @@ var edInstructions = []func(s *Z80Type){ } }, // 0xba : INDR - 0xBA: func(s *Z80Type) { + 0xBA: func(s *Z80) { s.doInd() if s.B != 0 { s.CycleCounter += 5 @@ -383,7 +383,7 @@ var edInstructions = []func(s *Z80Type){ } }, // 0xbb : OTDR - 0xBB: func(s *Z80Type) { + 0xBB: func(s *Z80) { s.doOutd() if s.B != 0 { s.CycleCounter += 5 @@ -392,7 +392,7 @@ var edInstructions = []func(s *Z80Type){ }, } -func (z *Z80Type) opcodeED() { +func (z *Z80) opcodeED() { z.incR() z.PC++