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