mirror of
https://github.com/romychs/Ocean-240.2-Emulator.git
synced 2026-04-21 11:03:21 +03:00
zx80c99 implemented
This commit is contained in:
parent
9cb2af2145
commit
0742e9969c
4
main.go
4
main.go
@ -50,7 +50,7 @@ func main() {
|
||||
w, raster, label := mainWindow(computer)
|
||||
|
||||
go emulator(computer)
|
||||
go screen(computer, raster, label, conf)
|
||||
go screen(computer, raster, label)
|
||||
(*w).ShowAndRun()
|
||||
}
|
||||
|
||||
@ -131,7 +131,7 @@ func mainWindow(computer *okean240.ComputerType) (*fyne.Window, *canvas.Raster,
|
||||
return &w, raster, label
|
||||
}
|
||||
|
||||
func screen(computer *okean240.ComputerType, raster *canvas.Raster, label *widget.Label, emuConfig *config.OkEmuConfig) {
|
||||
func screen(computer *okean240.ComputerType, raster *canvas.Raster, label *widget.Label) {
|
||||
ticker := time.NewTicker(20 * time.Millisecond)
|
||||
frame := 0
|
||||
var pre uint64 = 0
|
||||
|
||||
@ -1,19 +1,17 @@
|
||||
// Package usart
|
||||
// Universal Serial Asynchronous Receiver/Transmitter
|
||||
// i8051, MSM82C51, КР580ВВ51
|
||||
// By Romych, 2025.03.04
|
||||
package usart
|
||||
|
||||
import log "github.com/sirupsen/logrus"
|
||||
|
||||
/**
|
||||
Universal Serial Asynchronous Receiver/Transmitter
|
||||
i8051, MSM82C51, КР580ВВ51
|
||||
//const I8251DSRFlag = 0x80
|
||||
//const I8251SynDetFlag = 0x40
|
||||
//const I8251FrameErrorFlag = 0x20
|
||||
//const I8251OverrunErrorFlag = 0x10
|
||||
//const I8251ParityErrorFlag = 0x08
|
||||
|
||||
By Romych, 2025.03.04
|
||||
*/
|
||||
|
||||
const I8251DSRFlag = 0x80
|
||||
const I8251SynDetFlag = 0x40
|
||||
const I8251FrameErrorFlag = 0x20
|
||||
const I8251OverrunErrorFlag = 0x10
|
||||
const I8251ParityErrorFlag = 0x08
|
||||
const I8251TxEnableFlag = 0x04
|
||||
const I8251RxReadyFlag = 0x02
|
||||
const I8251TxReadyFlag = 0x01
|
||||
@ -131,20 +129,22 @@ func (s *I8251) Command(value byte) {
|
||||
func (s *I8251) Send(value byte) {
|
||||
if s.txe {
|
||||
s.bufferTx = append(s.bufferTx, value)
|
||||
log.Debugf("Send byte: %x", value)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *I8251) Receive() byte {
|
||||
|
||||
if s.rxe {
|
||||
if len(s.bufferRx) > 0 {
|
||||
res := s.bufferRx[0]
|
||||
s.bufferRx = s.bufferRx[1:]
|
||||
log.Debugf("ReceiveByte: %x", res)
|
||||
log.Debugf("Receive: %x", res)
|
||||
return res
|
||||
}
|
||||
log.Debugf("Receive: empty buffer")
|
||||
} else {
|
||||
log.Debugf("Receive: receiver disabled")
|
||||
}
|
||||
log.Debugf("ReceiveByte: empty buffer")
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
58
z80/constants.go
Normal file
58
z80/constants.go
Normal file
@ -0,0 +1,58 @@
|
||||
package z80
|
||||
|
||||
var cyc_00 = [256]byte{
|
||||
4, 10, 7, 6, 4, 4, 7, 4, 4, 11, 7, 6, 4, 4, 7, 4,
|
||||
8, 10, 7, 6, 4, 4, 7, 4, 12, 11, 7, 6, 4, 4, 7, 4,
|
||||
7, 10, 16, 6, 4, 4, 7, 4, 7, 11, 16, 6, 4, 4, 7, 4,
|
||||
7, 10, 13, 6, 11, 11, 10, 4, 7, 11, 13, 6, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
5, 10, 10, 10, 10, 11, 7, 11, 5, 10, 10, 0, 10, 17, 7, 11,
|
||||
5, 10, 10, 11, 10, 11, 7, 11, 5, 4, 10, 11, 10, 0, 7, 11,
|
||||
5, 10, 10, 19, 10, 11, 7, 11, 5, 4, 10, 4, 10, 0, 7, 11,
|
||||
5, 10, 10, 4, 10, 11, 7, 11, 5, 6, 10, 4, 10, 0, 7, 11,
|
||||
}
|
||||
|
||||
var cyc_ed = [256]byte{
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
12, 12, 15, 20, 8, 14, 8, 9, 12, 12, 15, 20, 8, 14, 8, 9,
|
||||
12, 12, 15, 20, 8, 14, 8, 9, 12, 12, 15, 20, 8, 14, 8, 9,
|
||||
12, 12, 15, 20, 8, 14, 8, 18, 12, 12, 15, 20, 8, 14, 8, 18,
|
||||
12, 12, 15, 20, 8, 14, 8, 8, 12, 12, 15, 20, 8, 14, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
16, 16, 16, 16, 8, 8, 8, 8, 16, 16, 16, 16, 8, 8, 8, 8,
|
||||
16, 16, 16, 16, 8, 8, 8, 8, 16, 16, 16, 16, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
}
|
||||
|
||||
var cyc_ddfd = [256]byte{
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 15, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 15, 4, 4, 4, 4, 4, 4,
|
||||
4, 14, 20, 10, 8, 8, 11, 4, 4, 15, 20, 10, 8, 8, 11, 4,
|
||||
4, 4, 4, 4, 23, 23, 19, 4, 4, 15, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 8, 8, 19, 4, 4, 4, 4, 4, 8, 8, 19, 4,
|
||||
4, 4, 4, 4, 8, 8, 19, 4, 4, 4, 4, 4, 8, 8, 19, 4,
|
||||
8, 8, 8, 8, 8, 8, 19, 8, 8, 8, 8, 8, 8, 8, 19, 8,
|
||||
19, 19, 19, 19, 19, 19, 4, 19, 4, 4, 4, 4, 8, 8, 19, 4,
|
||||
4, 4, 4, 4, 8, 8, 19, 4, 4, 4, 4, 4, 8, 8, 19, 4,
|
||||
4, 4, 4, 4, 8, 8, 19, 4, 4, 4, 4, 4, 8, 8, 19, 4,
|
||||
4, 4, 4, 4, 8, 8, 19, 4, 4, 4, 4, 4, 8, 8, 19, 4,
|
||||
4, 4, 4, 4, 8, 8, 19, 4, 4, 4, 4, 4, 8, 8, 19, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 14, 4, 23, 4, 15, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 10, 4, 4, 4, 4, 4, 4,
|
||||
}
|
||||
174
z80/cpu.go
Normal file
174
z80/cpu.go
Normal file
@ -0,0 +1,174 @@
|
||||
package 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
|
||||
|
||||
// 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() {
|
||||
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,
|
||||
}
|
||||
}
|
||||
165
z80/helper.go
Normal file
165
z80/helper.go
Normal file
@ -0,0 +1,165 @@
|
||||
package z80
|
||||
|
||||
import log "github.com/sirupsen/logrus"
|
||||
|
||||
// GetBit return bit "n" from byte "val"
|
||||
func getBit(n byte, val byte) byte {
|
||||
return ((val) >> (n)) & 1
|
||||
}
|
||||
|
||||
func getBit3(val byte) bool {
|
||||
return (val & 0x08) != 0
|
||||
}
|
||||
|
||||
func getBit5(val byte) bool {
|
||||
return (val & 0x20) != 0
|
||||
}
|
||||
|
||||
func (z *Z80) rb(addr uint16) byte {
|
||||
return z.core.MemRead(addr)
|
||||
}
|
||||
|
||||
func (z *Z80) wb(addr uint16, val byte) {
|
||||
z.core.MemWrite(addr, val)
|
||||
}
|
||||
|
||||
func (z *Z80) rw(addr uint16) uint16 {
|
||||
return (uint16(z.core.MemRead(addr+1)) << 8) | uint16(z.core.MemRead(addr))
|
||||
}
|
||||
|
||||
func (z *Z80) ww(addr uint16, val uint16) {
|
||||
z.core.MemWrite(addr, byte(val))
|
||||
z.core.MemWrite(addr+1, byte(val>>8))
|
||||
}
|
||||
|
||||
func (z *Z80) pushw(val uint16) {
|
||||
z.sp -= 2
|
||||
z.ww(z.sp, val)
|
||||
}
|
||||
|
||||
func (z *Z80) popw() uint16 {
|
||||
z.sp += 2
|
||||
return z.rw(z.sp - 2)
|
||||
}
|
||||
|
||||
func (z *Z80) nextb() byte {
|
||||
b := z.rb(z.pc)
|
||||
z.pc++
|
||||
return b
|
||||
}
|
||||
|
||||
func (z *Z80) nextw() uint16 {
|
||||
w := z.rw(z.pc)
|
||||
z.pc += 2
|
||||
return w
|
||||
}
|
||||
|
||||
func (z *Z80) get_bc() uint16 {
|
||||
return (uint16(z.b) << 8) | uint16(z.c)
|
||||
}
|
||||
|
||||
func (z *Z80) get_de() uint16 {
|
||||
return (uint16(z.d) << 8) | uint16(z.e)
|
||||
}
|
||||
|
||||
func (z *Z80) get_hl() uint16 {
|
||||
return (uint16(z.h) << 8) | uint16(z.l)
|
||||
}
|
||||
|
||||
func (z *Z80) set_bc(val uint16) {
|
||||
z.b = byte(val >> 8)
|
||||
z.c = byte(val)
|
||||
}
|
||||
|
||||
func (z *Z80) set_de(val uint16) {
|
||||
z.d = byte(val >> 8)
|
||||
z.e = byte(val)
|
||||
}
|
||||
|
||||
func (z *Z80) set_hl(val uint16) {
|
||||
z.h = byte(val >> 8)
|
||||
z.l = byte(val)
|
||||
}
|
||||
|
||||
func (z *Z80) get_f() byte {
|
||||
val := byte(0)
|
||||
if z.cf {
|
||||
val |= 0x01
|
||||
}
|
||||
if z.nf {
|
||||
val |= 0x02
|
||||
}
|
||||
if z.pf {
|
||||
val |= 0x04
|
||||
}
|
||||
if z.xf {
|
||||
val |= 0x08
|
||||
}
|
||||
if z.hf {
|
||||
val |= 0x10
|
||||
}
|
||||
if z.yf {
|
||||
val |= 0x20
|
||||
}
|
||||
if z.zf {
|
||||
val |= 0x40
|
||||
}
|
||||
if z.sf {
|
||||
val |= 0x80
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func (z *Z80) set_f(val byte) {
|
||||
z.cf = val&1 != 0
|
||||
z.nf = (val>>1)&1 != 0
|
||||
z.pf = (val>>2)&1 != 0
|
||||
z.xf = (val>>3)&1 != 0
|
||||
z.hf = (val>>4)&1 != 0
|
||||
z.yf = (val>>5)&1 != 0
|
||||
z.zf = (val>>6)&1 != 0
|
||||
z.sf = (val>>7)&1 != 0
|
||||
}
|
||||
|
||||
// increments R, keeping the highest byte intact
|
||||
func (z *Z80) inc_r() {
|
||||
z.r = (z.r & 0x80) | ((z.r + 1) & 0x7f)
|
||||
}
|
||||
|
||||
func boolToInt32(b bool) int32 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// returns if there was a carry between bit "bit_no" and "bit_no - 1" when
|
||||
// executing "a + b + cy"
|
||||
func carry(bit_no int, a uint16, b uint16, cy bool) bool {
|
||||
result := int32(a) + int32(b) + boolToInt32(cy)
|
||||
carry := result ^ int32(a) ^ int32(b)
|
||||
return (carry & (1 << bit_no)) != 0
|
||||
}
|
||||
|
||||
// returns the parity of byte: 0 if number of 1 bits in `val` is odd, else 1
|
||||
func parity(val byte) bool {
|
||||
ones := byte(0)
|
||||
for i := 0; i < 8; i++ {
|
||||
ones += (val >> i) & 1
|
||||
}
|
||||
return (ones & 1) == 0
|
||||
}
|
||||
|
||||
func (z *Z80) updateXY(result byte) {
|
||||
z.yf = result&0x20 != 0
|
||||
z.xf = result&0x08 != 0
|
||||
}
|
||||
|
||||
func (z *Z80) debug_output() {
|
||||
log.Debugf("PC: %04X, AF: %04X, BC: %04X, DE: %04X, HL: %04X, SP: %04X, IX: %04X, IY: %04X, I: %02X, R: %02X",
|
||||
z.pc, (uint16(z.a)<<8)|uint16(z.get_f()), z.get_bc(), z.get_de(), z.get_hl(), z.sp,
|
||||
z.ix, z.iy, z.i, z.r)
|
||||
|
||||
log.Debugf("\t(%02X %02X %02X %02X), cyc: %d\n", z.rb(z.pc), z.rb(z.pc+1),
|
||||
z.rb(z.pc+2), z.rb(z.pc+3), z.cyc)
|
||||
}
|
||||
1188
z80/opcodes.go
Normal file
1188
z80/opcodes.go
Normal file
File diff suppressed because it is too large
Load Diff
162
z80/opcodesCB.go
Normal file
162
z80/opcodesCB.go
Normal file
@ -0,0 +1,162 @@
|
||||
package z80
|
||||
|
||||
import log "github.com/sirupsen/logrus"
|
||||
|
||||
// executes a CB opcode
|
||||
func (z *Z80) exec_opcode_cb(opcode byte) {
|
||||
z.cyc += 8
|
||||
z.inc_r()
|
||||
|
||||
// decoding instructions from http://z80.info/decoding.htm#cb
|
||||
x_ := (opcode >> 6) & 3 // 0b11
|
||||
y_ := (opcode >> 3) & 7 // 0b111
|
||||
z_ := opcode & 7 // 0b111
|
||||
|
||||
var hl byte
|
||||
v := byte(0)
|
||||
reg := &v
|
||||
switch z_ {
|
||||
case 0:
|
||||
reg = &z.b
|
||||
case 1:
|
||||
reg = &z.c
|
||||
case 2:
|
||||
reg = &z.d
|
||||
case 3:
|
||||
reg = &z.e
|
||||
case 4:
|
||||
reg = &z.h
|
||||
case 5:
|
||||
reg = &z.l
|
||||
case 6:
|
||||
hl = z.rb(z.get_hl())
|
||||
reg = &hl
|
||||
case 7:
|
||||
reg = &z.a
|
||||
}
|
||||
|
||||
switch x_ {
|
||||
case 0:
|
||||
// rot[y] r[z]
|
||||
switch y_ {
|
||||
case 0:
|
||||
*reg = z.cb_rlc(*reg)
|
||||
case 1:
|
||||
*reg = z.cb_rrc(*reg)
|
||||
case 2:
|
||||
*reg = z.cb_rl(*reg)
|
||||
case 3:
|
||||
*reg = z.cb_rr(*reg)
|
||||
case 4:
|
||||
*reg = z.cb_sla(*reg)
|
||||
case 5:
|
||||
*reg = z.cb_sra(*reg)
|
||||
case 6:
|
||||
*reg = z.cb_sll(*reg)
|
||||
case 7:
|
||||
*reg = z.cb_srl(*reg)
|
||||
}
|
||||
|
||||
case 1:
|
||||
// BIT y, r[z]
|
||||
z.cb_bit(*reg, y_)
|
||||
|
||||
// in bit (hl), x/y flags are handled differently:
|
||||
if z_ == 6 {
|
||||
z.updateXY(byte(z.mem_ptr >> 8))
|
||||
z.cyc += 4
|
||||
}
|
||||
|
||||
case 2:
|
||||
*reg &= ^(1 << y_) // RES y, r[z]
|
||||
case 3:
|
||||
*reg |= 1 << y_ // SET y, r[z]
|
||||
}
|
||||
|
||||
if (x_ == 0 || x_ == 2 || x_ == 3) && z_ == 6 {
|
||||
z.cyc += 7
|
||||
}
|
||||
|
||||
if reg == &hl {
|
||||
z.wb(z.get_hl(), hl)
|
||||
}
|
||||
}
|
||||
|
||||
// exec_opcode_dcb executes a displaced CB opcode (DDCB or FDCB)
|
||||
func (z *Z80) exec_opcode_dcb(opcode byte, addr uint16) {
|
||||
val := z.rb(addr)
|
||||
result := byte(0)
|
||||
|
||||
// decoding instructions from http://z80.info/decoding.htm#ddcb
|
||||
x_ := (opcode >> 6) & 3 // 0b11
|
||||
y_ := (opcode >> 3) & 7 // 0b111
|
||||
z_ := opcode & 7 // 0b111
|
||||
|
||||
switch x_ {
|
||||
case 0:
|
||||
// rot[y] (iz+d)
|
||||
switch y_ {
|
||||
case 0:
|
||||
result = z.cb_rlc(val)
|
||||
case 1:
|
||||
result = z.cb_rrc(val)
|
||||
case 2:
|
||||
result = z.cb_rl(val)
|
||||
case 3:
|
||||
result = z.cb_rr(val)
|
||||
case 4:
|
||||
result = z.cb_sla(val)
|
||||
case 5:
|
||||
result = z.cb_sra(val)
|
||||
case 6:
|
||||
result = z.cb_sll(val)
|
||||
case 7:
|
||||
result = z.cb_srl(val)
|
||||
}
|
||||
|
||||
case 1:
|
||||
// bit y,(iz+d)
|
||||
result = z.cb_bit(val, y_)
|
||||
z.updateXY(byte(addr >> 8))
|
||||
case 2:
|
||||
result = val & ^(1 << y_) // res y, (iz+d)
|
||||
case 3:
|
||||
result = val | (1 << y_) // set y, (iz+d)
|
||||
|
||||
default:
|
||||
log.Errorf("Unknown XYCB opcode: %02X\n", opcode)
|
||||
}
|
||||
|
||||
// ld r[z], rot[y] (iz+d)
|
||||
// ld r[z], res y,(iz+d)
|
||||
// ld r[z], set y,(iz+d)
|
||||
if x_ != 1 && z_ != 6 {
|
||||
switch z_ {
|
||||
case 0:
|
||||
z.b = result
|
||||
case 1:
|
||||
z.c = result
|
||||
case 2:
|
||||
z.d = result
|
||||
case 3:
|
||||
z.e = result
|
||||
case 4:
|
||||
z.h = result
|
||||
case 5:
|
||||
z.l = result
|
||||
// always false
|
||||
//case 6:
|
||||
// z.wb(z.get_hl(), result)
|
||||
case 7:
|
||||
z.a = result
|
||||
}
|
||||
}
|
||||
|
||||
if x_ == 1 {
|
||||
// bit instructions take 20 cycles, others take 23
|
||||
z.cyc += 20
|
||||
} else {
|
||||
z.wb(addr, result)
|
||||
z.cyc += 23
|
||||
}
|
||||
}
|
||||
202
z80/opcodesDDFD.go
Normal file
202
z80/opcodesDDFD.go
Normal file
@ -0,0 +1,202 @@
|
||||
package z80
|
||||
|
||||
// executes a DD/FD opcode (IZ = IX or IY)
|
||||
func (z *Z80) exec_opcode_ddfd(opcode byte, iz *uint16) {
|
||||
z.cyc += uint64(cyc_ddfd[opcode])
|
||||
z.inc_r()
|
||||
|
||||
switch opcode {
|
||||
case 0xE1:
|
||||
*iz = z.popw() // pop iz
|
||||
case 0xE5:
|
||||
z.pushw(*iz) // push iz
|
||||
|
||||
case 0xE9:
|
||||
z.jump(*iz) // jp iz
|
||||
|
||||
case 0x09:
|
||||
z.addiz(iz, z.get_bc()) // add iz,bc
|
||||
case 0x19:
|
||||
z.addiz(iz, z.get_de()) // add iz,de
|
||||
case 0x29:
|
||||
z.addiz(iz, *iz) // add iz,iz
|
||||
case 0x39:
|
||||
z.addiz(iz, z.sp) // add iz,sp
|
||||
|
||||
case 0x84:
|
||||
z.a = z.addb(z.a, byte(*iz>>8), false) // add a,izh
|
||||
case 0x85:
|
||||
z.a = z.addb(z.a, byte(*iz), false) // add a,izl
|
||||
case 0x8C:
|
||||
z.a = z.addb(z.a, byte(*iz>>8), z.cf) // adc a,izh
|
||||
case 0x8D:
|
||||
z.a = z.addb(z.a, byte(*iz), z.cf) // adc a,izl
|
||||
case 0x86:
|
||||
z.a = z.addb(z.a, z.rb(z.displace(*iz, z.nextb())), false) // add a,(iz+*)
|
||||
case 0x8E:
|
||||
z.a = z.addb(z.a, z.rb(z.displace(*iz, z.nextb())), z.cf) // adc a,(iz+*)
|
||||
case 0x96:
|
||||
z.a = z.subb(z.a, z.rb(z.displace(*iz, z.nextb())), false) // sub (iz+*)
|
||||
case 0x9E:
|
||||
z.a = z.subb(z.a, z.rb(z.displace(*iz, z.nextb())), z.cf) // sbc (iz+*)
|
||||
case 0x94:
|
||||
z.a = z.subb(z.a, byte(*iz>>8), false) // sub izh
|
||||
case 0x95:
|
||||
z.a = z.subb(z.a, byte(*iz), false) // sub izl
|
||||
case 0x9C:
|
||||
z.a = z.subb(z.a, byte(*iz>>8), z.cf) // sbc izh
|
||||
case 0x9D:
|
||||
z.a = z.subb(z.a, byte(*iz), z.cf) // sbc izl
|
||||
|
||||
case 0xA6:
|
||||
z.land(z.rb(z.displace(*iz, z.nextb()))) // and (iz+*)
|
||||
case 0xA4:
|
||||
z.land(byte(*iz >> 8)) // and izh
|
||||
case 0xA5:
|
||||
z.land(byte(*iz)) // and izl
|
||||
|
||||
case 0xAE:
|
||||
z.lxor(z.rb(z.displace(*iz, z.nextb()))) // xor (iz+*)
|
||||
case 0xAC:
|
||||
z.lxor(byte(*iz >> 8)) // xor izh
|
||||
case 0xAD:
|
||||
z.lxor(byte(*iz)) // xor izl
|
||||
case 0xB6:
|
||||
z.lor(z.rb(z.displace(*iz, z.nextb()))) // or (iz+*)
|
||||
case 0xB4:
|
||||
z.lor(byte(*iz >> 8)) // or izh
|
||||
case 0xB5:
|
||||
z.lor(byte(*iz)) // or izl
|
||||
case 0xBE:
|
||||
z.cp(z.rb(z.displace(*iz, z.nextb()))) // cp (iz+*)
|
||||
case 0xBC:
|
||||
z.cp(byte(*iz >> 8)) // cp izh
|
||||
case 0xBD:
|
||||
z.cp(byte(*iz)) // cp izl
|
||||
case 0x23:
|
||||
*iz += 1 // inc iz
|
||||
case 0x2B:
|
||||
*iz -= 1 // dec iz
|
||||
case 0x34:
|
||||
// inc (iz+*)
|
||||
addr := z.displace(*iz, z.nextb())
|
||||
z.wb(addr, z.inc(z.rb(addr)))
|
||||
case 0x35:
|
||||
// dec (iz+*)
|
||||
addr := z.displace(*iz, z.nextb())
|
||||
z.wb(addr, z.dec(z.rb(addr)))
|
||||
case 0x24:
|
||||
*iz = (*iz & 0x00ff) | (uint16(z.inc(byte(*iz>>8))) << 8) // inc izh
|
||||
case 0x25:
|
||||
*iz = (*iz & 0x00ff) | (uint16(z.dec(byte(*iz>>8))) << 8) // dec izh
|
||||
case 0x2C:
|
||||
*iz = (*iz & 0xff00) | uint16(z.inc(byte(*iz))) // inc izl
|
||||
case 0x2D:
|
||||
*iz = (*iz & 0xff00) | uint16(z.dec(byte(*iz))) // dec izl
|
||||
case 0x2A:
|
||||
*iz = z.rw(z.nextw()) // ld iz,(**)
|
||||
case 0x22:
|
||||
z.ww(z.nextw(), *iz) // ld (**),iz
|
||||
case 0x21:
|
||||
*iz = z.nextw() // ld iz,**
|
||||
case 0x36:
|
||||
// ld (iz+*),*
|
||||
addr := z.displace(*iz, z.nextb())
|
||||
z.wb(addr, z.nextb())
|
||||
case 0x70:
|
||||
z.wb(z.displace(*iz, z.nextb()), z.b) // ld (iz+*),b
|
||||
case 0x71:
|
||||
z.wb(z.displace(*iz, z.nextb()), z.c) // ld (iz+*),c
|
||||
case 0x72:
|
||||
z.wb(z.displace(*iz, z.nextb()), z.d) // ld (iz+*),d
|
||||
case 0x73:
|
||||
z.wb(z.displace(*iz, z.nextb()), z.e) // ld (iz+*),e
|
||||
case 0x74:
|
||||
z.wb(z.displace(*iz, z.nextb()), z.h) // ld (iz+*),h
|
||||
case 0x75:
|
||||
z.wb(z.displace(*iz, z.nextb()), z.l) // ld (iz+*),l
|
||||
case 0x77:
|
||||
z.wb(z.displace(*iz, z.nextb()), z.a) // ld (iz+*),a
|
||||
case 0x46:
|
||||
z.b = z.rb(z.displace(*iz, z.nextb())) // ld b,(iz+*)
|
||||
case 0x4E:
|
||||
z.c = z.rb(z.displace(*iz, z.nextb())) // ld c,(iz+*)
|
||||
case 0x56:
|
||||
z.d = z.rb(z.displace(*iz, z.nextb())) // ld d,(iz+*)
|
||||
case 0x5E:
|
||||
z.e = z.rb(z.displace(*iz, z.nextb())) // ld e,(iz+*)
|
||||
case 0x66:
|
||||
z.h = z.rb(z.displace(*iz, z.nextb())) // ld h,(iz+*)
|
||||
case 0x6E:
|
||||
z.l = z.rb(z.displace(*iz, z.nextb())) // ld l,(iz+*)
|
||||
case 0x7E:
|
||||
z.a = z.rb(z.displace(*iz, z.nextb())) // ld a,(iz+*)
|
||||
case 0x44:
|
||||
z.b = byte(*iz >> 8) // ld b,izh
|
||||
case 0x4C:
|
||||
z.c = byte(*iz >> 8) // ld c,izh
|
||||
case 0x54:
|
||||
z.d = byte(*iz >> 8) // ld d,izh
|
||||
case 0x5C:
|
||||
z.e = byte(*iz >> 8) // ld e,izh
|
||||
case 0x7C:
|
||||
z.a = byte(*iz >> 8) // ld a,izh
|
||||
case 0x45:
|
||||
z.b = byte(*iz) // ld b,izl
|
||||
case 0x4D:
|
||||
z.c = byte(*iz) // ld c,izl
|
||||
case 0x55:
|
||||
z.d = byte(*iz) // ld d,izl
|
||||
case 0x5D:
|
||||
z.e = byte(*iz) // ld e,izl
|
||||
case 0x7D:
|
||||
z.a = byte(*iz) // ld a,izl
|
||||
case 0x60:
|
||||
*iz = (*iz & 0x00ff) | (uint16(z.b) << 8) // ld izh,b
|
||||
case 0x61:
|
||||
*iz = (*iz & 0x00ff) | (uint16(z.c) << 8) // ld izh,c
|
||||
case 0x62:
|
||||
*iz = (*iz & 0x00ff) | (uint16(z.d) << 8) // ld izh,d
|
||||
case 0x63:
|
||||
*iz = (*iz & 0x00ff) | (uint16(z.e) << 8) // ld izh,e
|
||||
case 0x64: // ld izh,izh
|
||||
case 0x65:
|
||||
*iz = ((*iz & 0x00ff) << 8) | (*iz & 0x00ff) // ld izh,izl
|
||||
case 0x67:
|
||||
*iz = (uint16(z.a) << 8) | (*iz & 0x00ff) // ld izh,a
|
||||
case 0x26:
|
||||
*iz = (uint16(z.nextb()) << 8) | (*iz & 0x00ff) // ld izh,*
|
||||
case 0x68:
|
||||
*iz = (*iz & 0xff00) | uint16(z.b) // ld izl,b
|
||||
case 0x69:
|
||||
*iz = (*iz & 0xff00) | uint16(z.c) // ld izl,c
|
||||
case 0x6A:
|
||||
*iz = (*iz & 0xff00) | uint16(z.d) // ld izl,d
|
||||
case 0x6B:
|
||||
*iz = (*iz & 0xff00) | uint16(z.e) // ld izl,e
|
||||
case 0x6C:
|
||||
*iz = (*iz & 0xff00) | (*iz >> 8) // ld izl,izh
|
||||
case 0x6D: // ld izl,izl
|
||||
case 0x6F:
|
||||
*iz = (*iz & 0xff00) | uint16(z.a) // ld izl,a
|
||||
case 0x2E:
|
||||
*iz = (*iz & 0xff00) | uint16(z.nextb()) // ld izl,*
|
||||
case 0xF9:
|
||||
z.sp = *iz // ld sp,iz
|
||||
case 0xE3:
|
||||
// ex (sp),iz
|
||||
val := z.rw(z.sp)
|
||||
z.ww(z.sp, *iz)
|
||||
*iz = val
|
||||
z.mem_ptr = val
|
||||
case 0xCB:
|
||||
addr := z.displace(*iz, z.nextb())
|
||||
op := z.nextb()
|
||||
z.exec_opcode_dcb(op, addr)
|
||||
default:
|
||||
// any other FD/DD opcode behaves as a non-prefixed opcode:
|
||||
z.exec_opcode(opcode)
|
||||
// R should not be incremented twice:
|
||||
z.inc_r()
|
||||
}
|
||||
}
|
||||
257
z80/opcodesED.go
Normal file
257
z80/opcodesED.go
Normal file
@ -0,0 +1,257 @@
|
||||
package z80
|
||||
|
||||
import log "github.com/sirupsen/logrus"
|
||||
|
||||
// executes a ED opcode
|
||||
func (z *Z80) exec_opcode_ed(opcode byte) {
|
||||
z.cyc += uint64(cyc_ed[opcode])
|
||||
z.inc_r()
|
||||
switch opcode {
|
||||
case 0x47:
|
||||
z.i = z.a // ld i,a
|
||||
case 0x4F:
|
||||
z.r = z.a // ld r,a
|
||||
case 0x57:
|
||||
// ld a,i
|
||||
z.a = z.i
|
||||
z.sf = z.a&0x80 != 0
|
||||
z.zf = z.a == 0
|
||||
z.hf = false
|
||||
z.nf = false
|
||||
z.pf = z.iff2
|
||||
case 0x5F:
|
||||
// ld a,r
|
||||
z.a = z.r
|
||||
z.sf = z.a&0x80 != 0
|
||||
z.zf = z.a == 0
|
||||
z.hf = false
|
||||
z.nf = false
|
||||
z.pf = z.iff2
|
||||
case 0x45, 0x55, 0x5D, 0x65, 0x6D, 0x75, 0x7D:
|
||||
// retn
|
||||
z.iff1 = z.iff2
|
||||
z.ret()
|
||||
case 0x4D:
|
||||
z.ret() // reti
|
||||
|
||||
case 0xA0:
|
||||
z.ldi() // ldi
|
||||
case 0xB0:
|
||||
{
|
||||
z.ldi()
|
||||
|
||||
if z.get_bc() != 0 {
|
||||
z.pc -= 2
|
||||
z.cyc += 5
|
||||
z.mem_ptr = z.pc + 1
|
||||
}
|
||||
} // ldir
|
||||
|
||||
case 0xA8:
|
||||
z.ldd() // ldd
|
||||
case 0xB8:
|
||||
{
|
||||
z.ldd()
|
||||
|
||||
if z.get_bc() != 0 {
|
||||
z.pc -= 2
|
||||
z.cyc += 5
|
||||
z.mem_ptr = z.pc + 1
|
||||
}
|
||||
} // lddr
|
||||
|
||||
case 0xA1:
|
||||
z.cpi() // cpi
|
||||
case 0xA9:
|
||||
z.cpd() // cpd
|
||||
case 0xB1:
|
||||
{
|
||||
z.cpi()
|
||||
if z.get_bc() != 0 && !z.zf {
|
||||
z.pc -= 2
|
||||
z.cyc += 5
|
||||
z.mem_ptr = z.pc + 1
|
||||
} else {
|
||||
z.mem_ptr += 1
|
||||
}
|
||||
} // cpir
|
||||
case 0xB9:
|
||||
{
|
||||
z.cpd()
|
||||
if z.get_bc() != 0 && !z.zf {
|
||||
z.pc -= 2
|
||||
z.cyc += 5
|
||||
} else {
|
||||
z.mem_ptr += 1
|
||||
}
|
||||
} // cpdr
|
||||
|
||||
case 0x40:
|
||||
z.in_r_c(&z.b) // in b, (c)
|
||||
case 0x48:
|
||||
z.in_r_c(&z.c) // in c, (c)
|
||||
case 0x50:
|
||||
z.in_r_c(&z.d) // in d, (c)
|
||||
case 0x58:
|
||||
z.in_r_c(&z.e) // in e, (c)
|
||||
case 0x60:
|
||||
z.in_r_c(&z.h) // in h, (c)
|
||||
case 0x68:
|
||||
z.in_r_c(&z.l) // in l, (c)
|
||||
case 0x70:
|
||||
// in (c)
|
||||
var val byte
|
||||
z.in_r_c(&val)
|
||||
case 0x78:
|
||||
// in a, (c)
|
||||
z.in_r_c(&z.a)
|
||||
z.mem_ptr = z.get_bc() + 1
|
||||
case 0xA2:
|
||||
z.ini() // ini
|
||||
case 0xB2:
|
||||
// inir
|
||||
z.ini()
|
||||
if z.b > 0 {
|
||||
z.pc -= 2
|
||||
z.cyc += 5
|
||||
}
|
||||
case 0xAA:
|
||||
z.ind() // ind
|
||||
case 0xBA:
|
||||
// indr
|
||||
z.ind()
|
||||
if z.b > 0 {
|
||||
z.pc -= 2
|
||||
z.cyc += 5
|
||||
}
|
||||
case 0x41:
|
||||
z.core.IOWrite(z.get_bc(), z.b) // out (c), b
|
||||
case 0x49:
|
||||
z.core.IOWrite(z.get_bc(), z.c) // out (c), c
|
||||
case 0x51:
|
||||
z.core.IOWrite(z.get_bc(), z.d) // out (c), d
|
||||
case 0x59:
|
||||
z.core.IOWrite(z.get_bc(), z.e) // out (c), e
|
||||
case 0x61:
|
||||
z.core.IOWrite(z.get_bc(), z.h) // out (c), h
|
||||
case 0x69:
|
||||
z.core.IOWrite(z.get_bc(), z.l) // out (c), l
|
||||
case 0x71:
|
||||
z.core.IOWrite(z.get_bc(), 0) // out (c), 0
|
||||
case 0x79:
|
||||
// out (c), a
|
||||
z.core.IOWrite(z.get_bc(), z.a)
|
||||
z.mem_ptr = z.get_bc() + 1
|
||||
case 0xA3:
|
||||
z.outi() // outi
|
||||
case 0xB3:
|
||||
// otir
|
||||
z.outi()
|
||||
if z.b > 0 {
|
||||
z.pc -= 2
|
||||
z.cyc += 5
|
||||
}
|
||||
case 0xAB:
|
||||
z.outd() // outd
|
||||
case 0xBB:
|
||||
// otdr
|
||||
z.outd()
|
||||
if z.b > 0 {
|
||||
z.pc -= 2
|
||||
}
|
||||
|
||||
case 0x42:
|
||||
z.sbchl(z.get_bc()) // sbc hl,bc
|
||||
case 0x52:
|
||||
z.sbchl(z.get_de()) // sbc hl,de
|
||||
case 0x62:
|
||||
z.sbchl(z.get_hl()) // sbc hl,hl
|
||||
case 0x72:
|
||||
z.sbchl(z.sp) // sbc hl,sp
|
||||
case 0x4A:
|
||||
z.adchl(z.get_bc()) // adc hl,bc
|
||||
case 0x5A:
|
||||
z.adchl(z.get_de()) // adc hl,de
|
||||
case 0x6A:
|
||||
z.adchl(z.get_hl()) // adc hl,hl
|
||||
case 0x7A:
|
||||
z.adchl(z.sp) // adc hl,sp
|
||||
case 0x43:
|
||||
// ld (**), bc
|
||||
addr := z.nextw()
|
||||
z.ww(addr, z.get_bc())
|
||||
z.mem_ptr = addr + 1
|
||||
case 0x53:
|
||||
// ld (**), de
|
||||
addr := z.nextw()
|
||||
z.ww(addr, z.get_de())
|
||||
z.mem_ptr = addr + 1
|
||||
case 0x63:
|
||||
// ld (**), hl
|
||||
addr := z.nextw()
|
||||
z.ww(addr, z.get_hl())
|
||||
z.mem_ptr = addr + 1
|
||||
case 0x73:
|
||||
// ld (**), hl
|
||||
addr := z.nextw()
|
||||
z.ww(addr, z.sp)
|
||||
z.mem_ptr = addr + 1
|
||||
case 0x4B:
|
||||
// ld bc, (**)
|
||||
addr := z.nextw()
|
||||
z.set_bc(z.rw(addr))
|
||||
z.mem_ptr = addr + 1
|
||||
case 0x5B:
|
||||
// ld de, (**)
|
||||
addr := z.nextw()
|
||||
z.set_de(z.rw(addr))
|
||||
z.mem_ptr = addr + 1
|
||||
case 0x6B:
|
||||
// ld hl, (**)
|
||||
addr := z.nextw()
|
||||
z.set_hl(z.rw(addr))
|
||||
z.mem_ptr = addr + 1
|
||||
case 0x7B:
|
||||
// ld sp,(**)
|
||||
addr := z.nextw()
|
||||
z.sp = z.rw(addr)
|
||||
z.mem_ptr = addr + 1
|
||||
case 0x44, 0x54, 0x64, 0x74, 0x4C, 0x5C, 0x6C, 0x7C:
|
||||
z.a = z.subb(0, z.a, false) // neg
|
||||
case 0x46, 0x66:
|
||||
z.interrupt_mode = 0 // im 0
|
||||
case 0x56, 0x76:
|
||||
z.interrupt_mode = 1 // im 1
|
||||
case 0x5E, 0x7E:
|
||||
z.interrupt_mode = 2 // im 2
|
||||
case 0x67:
|
||||
// rrd
|
||||
a := z.a
|
||||
val := z.rb(z.get_hl())
|
||||
z.a = (a & 0xF0) | (val & 0xF)
|
||||
z.wb(z.get_hl(), (val>>4)|(a<<4))
|
||||
|
||||
z.nf = false
|
||||
z.hf = false
|
||||
z.updateXY(z.a)
|
||||
z.zf = z.a == 0
|
||||
z.sf = z.a&0x80 != 0
|
||||
z.pf = parity(z.a)
|
||||
z.mem_ptr = z.get_hl() + 1
|
||||
case 0x6F:
|
||||
// rld
|
||||
a := z.a
|
||||
val := z.rb(z.get_hl())
|
||||
z.a = (a & 0xF0) | (val >> 4)
|
||||
z.wb(z.get_hl(), (val<<4)|(a&0xF))
|
||||
z.nf = false
|
||||
z.hf = false
|
||||
z.updateXY(z.a)
|
||||
z.zf = z.a == 0
|
||||
z.sf = z.a&0x80 != 0
|
||||
z.pf = parity(z.a)
|
||||
z.mem_ptr = z.get_hl() + 1
|
||||
default:
|
||||
log.Errorf("Unknown ED opcode: %02X\n", opcode)
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@ package z80em
|
||||
|
||||
import "fmt"
|
||||
|
||||
const SpDefault uint16 = 0xdff0
|
||||
//const SpDefault uint16 = 0xffff
|
||||
|
||||
// FlagsType - Processor flags
|
||||
type FlagsType struct {
|
||||
@ -78,9 +78,9 @@ type CPUInterface interface {
|
||||
func (z *Z80Type) Reset() {
|
||||
z.A = 0
|
||||
z.R = 0
|
||||
z.SP = SpDefault
|
||||
z.SP = 0xff
|
||||
z.PC = 0
|
||||
z.setFlagsRegister(0)
|
||||
z.setFlagsRegister(0xff)
|
||||
// Interrupts disabled
|
||||
z.IMode = 0
|
||||
z.Iff1 = 0
|
||||
@ -180,10 +180,10 @@ func New(memIoRW MemIoRW) *Z80Type {
|
||||
I: 0,
|
||||
|
||||
R: 0,
|
||||
SP: SpDefault,
|
||||
SP: 0xffff,
|
||||
PC: 0,
|
||||
Flags: FlagsType{false, false, false, false, false, false, false, false},
|
||||
FlagsAlt: FlagsType{false, false, false, false, false, false, false, false},
|
||||
Flags: FlagsType{true, true, true, true, true, true, true, true},
|
||||
FlagsAlt: FlagsType{true, true, true, true, true, true, true, true},
|
||||
IMode: 0,
|
||||
Iff1: 0,
|
||||
Iff2: 0,
|
||||
@ -808,8 +808,8 @@ func (z *Z80Type) doCpi() {
|
||||
|
||||
z.Flags.C = tempCarry
|
||||
fh := z.fhv()
|
||||
z.Flags.Y = ((z.A-readValue-fh)&0x02)>>1 != 0
|
||||
z.Flags.X = ((z.A-readValue-fh)&0x08)>>3 != 0
|
||||
z.Flags.Y = ((z.A - readValue - fh) & 0x02) != 0
|
||||
z.Flags.X = ((z.A - readValue - fh) & 0x08) != 0
|
||||
z.incHl()
|
||||
z.decBc()
|
||||
z.Flags.P = (z.B | z.C) != 0
|
||||
@ -838,8 +838,8 @@ func (z *Z80Type) doLdd() {
|
||||
z.decHl()
|
||||
z.decBc()
|
||||
z.Flags.P = (z.C | z.B) != 0
|
||||
z.Flags.Y = ((z.A+readValue)&0x02)>>1 != 0
|
||||
z.Flags.X = ((z.A+readValue)&0x08)>>3 != 0
|
||||
z.Flags.Y = ((z.A + readValue) & 0x02) != 0
|
||||
z.Flags.X = ((z.A + readValue) & 0x08) != 0
|
||||
}
|
||||
|
||||
func (z *Z80Type) doCpd() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user