mirror of
https://github.com/romychs/z80go.git
synced 2026-04-16 08:44:20 +03:00
z80go: v1.0.0
This commit is contained in:
parent
d05db31cd2
commit
ff2e10afdb
@ -1,5 +1,6 @@
|
|||||||
# Z80 processor emulator and disassembler
|
# Z80 processor emulator and disassembler
|
||||||
|
|
||||||
Pass ZEXALL tests. Undocumented instructions supported.
|
CPU emulator pass all ZEXALL test and Fuse Z80 test suite.
|
||||||
|
Undocumented instructions and flags supported.
|
||||||
|
|
||||||
Based on ideas of [Superzazu Z80 emulator](https://github.com/superzazu/z80)
|
Based on ideas of [Superzazu Z80 emulator](https://github.com/superzazu/z80)
|
||||||
@ -354,7 +354,6 @@ func (d *Disassembler) getRel() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var shiftOps = []string{"RLC", "RRC", "RL", "RR", "SLA", "SRA", "SLL", "SRL"}
|
var shiftOps = []string{"RLC", "RRC", "RL", "RR", "SLA", "SRA", "SLL", "SRL"}
|
||||||
var bitOps = []string{"BIT", "RES", "SET"}
|
|
||||||
|
|
||||||
// opocodeCB disassemble Z80 Opcodes, with CB first byte
|
// opocodeCB disassemble Z80 Opcodes, with CB first byte
|
||||||
func (d *Disassembler) opocodeCB() string {
|
func (d *Disassembler) opocodeCB() string {
|
||||||
@ -470,6 +469,8 @@ func (d *Disassembler) opocodeDD(op byte) string {
|
|||||||
return strings.ReplaceAll(result, "ii", reg)
|
return strings.ReplaceAll(result, "ii", reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//var bitOps = []string{"BIT", "RES", "SET"}
|
||||||
|
|
||||||
func (d *Disassembler) opocodeDDCB(op1 byte, op2 byte) string {
|
func (d *Disassembler) opocodeDDCB(op1 byte, op2 byte) string {
|
||||||
opcode := d.getByte()
|
opcode := d.getByte()
|
||||||
result := ""
|
result := ""
|
||||||
|
|||||||
@ -24,7 +24,7 @@ func (t *TestComp) IORead(port uint16) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestComp) IOWrite(port uint16, val byte) {
|
func (t *TestComp) IOWrite(port uint16, val byte) {
|
||||||
//
|
print("PORT[0x%04X]=0x%04X\n", port, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
var testComp *TestComp
|
var testComp *TestComp
|
||||||
@ -51,7 +51,7 @@ func Test_LD_SP_nn(t *testing.T) {
|
|||||||
setMemory(0x100, test)
|
setMemory(0x100, test)
|
||||||
res := disasm.Disassm(0x100)
|
res := disasm.Disassm(0x100)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
t.Errorf("Error disasm LD SP, nn, result '%s', expected '%s'", res, expected)
|
t.Errorf("Error disassm LD SP, nn, result '%s', expected '%s'", res, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ func Test_LD_DE_nn(t *testing.T) {
|
|||||||
setMemory(0x100, test)
|
setMemory(0x100, test)
|
||||||
res := disasm.Disassm(0x103)
|
res := disasm.Disassm(0x103)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
t.Errorf("Error disasm LD DE, nn, result '%s', expected '%s'", res, expected)
|
t.Errorf("Error disassm LD DE, nn, result '%s', expected '%s'", res, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ func Test_LD_C_n(t *testing.T) {
|
|||||||
setMemory(0x100, test)
|
setMemory(0x100, test)
|
||||||
res := disasm.Disassm(0x106)
|
res := disasm.Disassm(0x106)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
t.Errorf("Error disasm LD C, n, result '%s', expected '%s'", res, expected)
|
t.Errorf("Error disassm LD C, n, result '%s', expected '%s'", res, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ func Test_CALL_nn(t *testing.T) {
|
|||||||
setMemory(0x100, test)
|
setMemory(0x100, test)
|
||||||
res := disasm.Disassm(0x108)
|
res := disasm.Disassm(0x108)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
t.Errorf("Error disasm CALL nn, result '%s', expected '%s'", res, expected)
|
t.Errorf("Error disassm CALL nn, result '%s', expected '%s'", res, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +87,6 @@ func Test_JP_nn(t *testing.T) {
|
|||||||
setMemory(0x100, test)
|
setMemory(0x100, test)
|
||||||
res := disasm.Disassm(0x10b)
|
res := disasm.Disassm(0x10b)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
t.Errorf("Error disasm JP nn, result '%s', expected '%s'", res, expected)
|
t.Errorf("Error disassm JP nn, result '%s', expected '%s'", res, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
go.mod
5
go.mod
@ -2,9 +2,6 @@ module github.com/romychs/z80go
|
|||||||
|
|
||||||
go 1.25
|
go 1.25
|
||||||
|
|
||||||
require (
|
require github.com/sirupsen/logrus v1.9.4
|
||||||
github.com/sirupsen/logrus v1.9.4
|
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
|
||||||
)
|
|
||||||
|
|
||||||
require golang.org/x/sys v0.13.0 // indirect
|
require golang.org/x/sys v0.13.0 // indirect
|
||||||
|
|||||||
8
go.sum
8
go.sum
@ -1,6 +1,12 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
40
opcodes.go
40
opcodes.go
@ -86,7 +86,7 @@ func (z *CPU) addB(a byte, b byte, cy bool) byte {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUBtract Byte: subtracts two bytes (with optional carry)
|
// subB Subtract two bytes (with optional carry)
|
||||||
func (z *CPU) subB(a byte, b byte, cy bool) byte {
|
func (z *CPU) subB(a byte, b byte, cy bool) byte {
|
||||||
val := z.addB(a, ^b, !cy)
|
val := z.addB(a, ^b, !cy)
|
||||||
z.Flags.C = !z.Flags.C
|
z.Flags.C = !z.Flags.C
|
||||||
@ -95,7 +95,7 @@ func (z *CPU) subB(a byte, b byte, cy bool) byte {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD Word: adds two words together
|
// addW Adds two words together
|
||||||
func (z *CPU) addW(a uint16, b uint16, cy bool) uint16 {
|
func (z *CPU) addW(a uint16, b uint16, cy bool) uint16 {
|
||||||
lsb := z.addB(byte(a), byte(b), cy)
|
lsb := z.addB(byte(a), byte(b), cy)
|
||||||
msb := z.addB(byte(a>>8), byte(b>>8), z.Flags.C)
|
msb := z.addB(byte(a>>8), byte(b>>8), z.Flags.C)
|
||||||
@ -105,7 +105,7 @@ func (z *CPU) addW(a uint16, b uint16, cy bool) uint16 {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUBtract Word: subtracts two words (with optional carry)
|
// subW Subtracts two words (with optional carry)
|
||||||
func (z *CPU) subW(a uint16, b uint16, cy bool) uint16 {
|
func (z *CPU) subW(a uint16, b uint16, cy bool) uint16 {
|
||||||
lsb := z.subB(byte(a), byte(b), cy)
|
lsb := z.subB(byte(a), byte(b), cy)
|
||||||
msb := z.subB(byte(a>>8), byte(b>>8), z.Flags.C)
|
msb := z.subB(byte(a>>8), byte(b>>8), z.Flags.C)
|
||||||
@ -115,7 +115,7 @@ func (z *CPU) subW(a uint16, b uint16, cy bool) uint16 {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds A word to HL
|
// addHL Adds A word to HL
|
||||||
func (z *CPU) addHL(val uint16) {
|
func (z *CPU) addHL(val uint16) {
|
||||||
sf := z.Flags.S
|
sf := z.Flags.S
|
||||||
zf := z.Flags.Z
|
zf := z.Flags.Z
|
||||||
@ -893,19 +893,19 @@ func (z *CPU) execOpcode(opcode byte) {
|
|||||||
z.Halted = true // halt
|
z.Halted = true // halt
|
||||||
z.PC--
|
z.PC--
|
||||||
case 0x3C:
|
case 0x3C:
|
||||||
z.A = z.inc(z.A) // inc a
|
z.A = z.inc(z.A)
|
||||||
case 0x04:
|
case 0x04:
|
||||||
z.B = z.inc(z.B) // inc b
|
z.B = z.inc(z.B)
|
||||||
case 0x0C:
|
case 0x0C:
|
||||||
z.C = z.inc(z.C) // inc c
|
z.C = z.inc(z.C)
|
||||||
case 0x14:
|
case 0x14:
|
||||||
z.D = z.inc(z.D) // inc d
|
z.D = z.inc(z.D)
|
||||||
case 0x1C:
|
case 0x1C:
|
||||||
z.E = z.inc(z.E) // inc e
|
z.E = z.inc(z.E)
|
||||||
case 0x24:
|
case 0x24:
|
||||||
z.H = z.inc(z.H) // inc h
|
z.H = z.inc(z.H)
|
||||||
case 0x2C:
|
case 0x2C:
|
||||||
z.L = z.inc(z.L) // inc l
|
z.L = z.inc(z.L)
|
||||||
case 0x34:
|
case 0x34:
|
||||||
// inc (hl)
|
// inc (hl)
|
||||||
result := z.inc(z.rb(z.hl()))
|
result := z.inc(z.rb(z.hl()))
|
||||||
@ -965,14 +965,14 @@ func (z *CPU) execOpcode(opcode byte) {
|
|||||||
z.Flags.N = false
|
z.Flags.N = false
|
||||||
z.updateXY(z.A | z.f())
|
z.updateXY(z.A | z.f())
|
||||||
case 0x07:
|
case 0x07:
|
||||||
// rlca (rotate left)
|
// Rotate left
|
||||||
z.Flags.C = z.A&0x80 != 0
|
z.Flags.C = z.A&0x80 != 0
|
||||||
z.A = (z.A << 1) | bToByte(z.Flags.C)
|
z.A = (z.A << 1) | bToByte(z.Flags.C)
|
||||||
z.Flags.N = false
|
z.Flags.N = false
|
||||||
z.Flags.H = false
|
z.Flags.H = false
|
||||||
z.updateXY(z.A)
|
z.updateXY(z.A)
|
||||||
case 0x0F:
|
case 0x0F:
|
||||||
// rrca (rotate right)
|
// Rotate right
|
||||||
z.Flags.C = z.A&1 != 0
|
z.Flags.C = z.A&1 != 0
|
||||||
z.A = (z.A >> 1) | (bToByte(z.Flags.C) << 7)
|
z.A = (z.A >> 1) | (bToByte(z.Flags.C) << 7)
|
||||||
z.Flags.N = false
|
z.Flags.N = false
|
||||||
@ -1052,19 +1052,19 @@ func (z *CPU) execOpcode(opcode byte) {
|
|||||||
z.lOr(z.nextB()) // or *
|
z.lOr(z.nextB()) // or *
|
||||||
|
|
||||||
case 0xBF:
|
case 0xBF:
|
||||||
z.cp(z.A) // cp a
|
z.cp(z.A)
|
||||||
case 0xB8:
|
case 0xB8:
|
||||||
z.cp(z.B) // cp b
|
z.cp(z.B)
|
||||||
case 0xB9:
|
case 0xB9:
|
||||||
z.cp(z.C) // cp c
|
z.cp(z.C)
|
||||||
case 0xBA:
|
case 0xBA:
|
||||||
z.cp(z.D) // cp d
|
z.cp(z.D)
|
||||||
case 0xBB:
|
case 0xBB:
|
||||||
z.cp(z.E) // cp e
|
z.cp(z.E)
|
||||||
case 0xBC:
|
case 0xBC:
|
||||||
z.cp(z.H) // cp h
|
z.cp(z.H)
|
||||||
case 0xBD:
|
case 0xBD:
|
||||||
z.cp(z.L) // cp l
|
z.cp(z.L)
|
||||||
case 0xBE:
|
case 0xBE:
|
||||||
z.cp(z.rb(z.hl())) // cp (hl)
|
z.cp(z.rb(z.hl())) // cp (hl)
|
||||||
case 0xFE:
|
case 0xFE:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user