diff --git a/Makefile b/Makefile index 0fe4f8a..97de449 100644 --- a/Makefile +++ b/Makefile @@ -41,4 +41,10 @@ clean: zexdoc: $(MAKE) -C cmd/zexdoc run +switch.go: op_*.go gen_switch.go ./cmd/gen_switch/*.go + rm -f switch.go switch.go.new + cp switch.go.dummy switch.go + go run ./cmd/gen_switch | goimports > switch.go.new + mv switch.go.new switch.go + # based on: github.com/koron-go/_skeleton/Makefile diff --git a/cmd/extractf/README.md b/cmd/extractf/README.md new file mode 100644 index 0000000..50cb5d0 --- /dev/null +++ b/cmd/extractf/README.md @@ -0,0 +1,5 @@ +# extractf + +Tool to extract `F` filed of `OPcode` as top-level function. + +`OPCode` の `F` を独立した関数に抜き出すツール diff --git a/cmd/extractf/main.go b/cmd/extractf/main.go new file mode 100644 index 0000000..bb2d427 --- /dev/null +++ b/cmd/extractf/main.go @@ -0,0 +1,170 @@ +package main + +import ( + "bufio" + "bytes" + "flag" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "regexp" + "strings" +) + +func invalidRune(r rune) bool { + // valid: 0-9 A-Z a-z + // invalid: others + return r < '0' || + (r > '9' && r < 'A') || + (r > 'Z' && r < 'a') || + r > 'z' +} + +func mapping(r rune) rune { + if r == ')' { + return 'P' + } + if invalidRune(r) { + return -1 + } + return r +} + +func mangleN(s string) string { + return "op" + strings.Map(mapping, s) +} + +type item struct { + n string + f []string +} + +func extractF(w *bufio.Writer, r *bufio.Reader) error { + var items []*item + +L: + for { + var ( + n string + f []string + indent string + fEnd string + ) + for { + s, err := r.ReadString('\n') + if err != nil { + if err == io.EOF { + break L + } + return err + } + _, err = w.WriteString(s) + if err != nil { + return err + } + m := rxN.FindStringSubmatch(s) + if len(m) > 0 { + n = mangleN(m[1]) + break + } + } + for { + s, err := r.ReadString('\n') + if err != nil { + return err + } + m := rxF.FindStringSubmatch(s) + if len(m) > 0 { + indent = m[1] + fEnd = indent + "},\n" + break + } + _, err = w.WriteString(s) + if err != nil { + return err + } + } + _, err := fmt.Fprintf(w, "%sF: %s,\n", indent, n) + if err != nil { + return err + } + + for { + s, err := r.ReadString('\n') + if err != nil { + return err + } + if s == fEnd { + break + } + f = append(f, s[len(indent):]) + } + items = append(items, &item{n: n, f: f}) + } + + for _, i := range items { + _, err := fmt.Fprintf(w, "\nfunc %s(cpu *CPU, codes []uint8) {\n", i.n) + if err != nil { + return err + } + for _, f := range i.f { + _, err := fmt.Fprint(w, f) + if err != nil { + return err + } + } + _, err = w.WriteString("}\n") + if err != nil { + return err + } + } + + return w.Flush() +} + +func (i item) name() string { + return strings.Map(mapping, i.n) +} + +var rxN = regexp.MustCompile(`^\s*N: "([^"]*)",`) + +var rxF = regexp.MustCompile(`^(\t+)F: func\(.*\) \{\n$`) + +func rewrite(name string) error { + in, err := ioutil.ReadFile(name) + if err != nil { + return err + } + r := bufio.NewReader(bytes.NewBuffer(in)) + + out := &bytes.Buffer{} + w := bufio.NewWriter(out) + err = extractF(w, r) + if err != nil { + return err + } + + return ioutil.WriteFile(name, out.Bytes(), 0666) +} + +func main() { + flag.Parse() + + if flag.NArg() == 0 { + r := bufio.NewReader(os.Stdin) + w := bufio.NewWriter(os.Stdout) + err := extractF(w, r) + if err != nil { + log.Fatal(err) + } + } + + for _, name := range flag.Args() { + err := rewrite(name) + if err != nil { + log.Fatal(err) + } + } +} diff --git a/cmd/gen_switch/main.go b/cmd/gen_switch/main.go new file mode 100644 index 0000000..1c46ae6 --- /dev/null +++ b/cmd/gen_switch/main.go @@ -0,0 +1,15 @@ +package main + +import ( + "log" + "os" + + "github.com/koron-go/z80" +) + +func main() { + err := z80.GenerateSwitchDecoder(os.Stdout) + if err != nil { + log.Fatal(err) + } +} diff --git a/decode.go b/decode.go index 980139b..0a8ebbe 100644 --- a/decode.go +++ b/decode.go @@ -152,37 +152,3 @@ func DumpDecodeLayer(w io.Writer) error { e.SetIndent("", " ") return e.Encode(defaultDecodeLayer().mapTo()) } - -func decode(l *decodeLayer, buf []byte, f fetcher) (*OPCode, []uint8, error) { - var op *OPCode - for l != nil { - b, err := f.fetch() - if err != nil { - return nil, buf, fmt.Errorf("fetch failed: %w", err) - } - buf = append(buf, b) - n := l.get(b) - if n == nil { - break - } - if n.opcode != nil { - op = n.opcode - for len(buf) < len(op.C) { - b, err := f.fetch() - if err != nil { - return nil, buf, fmt.Errorf("fetch remains failed: %w", err) - } - buf = append(buf, b) - } - break - } - l = n.next - } - if op == nil { - return nil, buf, ErrInvalidCodes - } - if op.F == nil { - return nil, buf, fmt.Errorf("OPCode:%s %w", op.N, ErrNotImplemented) - } - return op, buf, nil -} diff --git a/decode_test.go b/decode_test.go index f024b3d..06064b7 100644 --- a/decode_test.go +++ b/decode_test.go @@ -39,15 +39,3 @@ func TestDecodeLayer_CheckAllOPCodes(t *testing.T) { t.Errorf("unseen OPCode: %s", c) } } - -func TestDecodeLayer_DD7E00(t *testing.T) { - f := memSrc{0xdd, 0x7e, 0x00} - l := defaultDecodeLayer() - c, _, err := decode(l, nil, &f) - if err != nil { - t.Fatal(err) - } - if c.N != "LD r, (IX+d)" { - t.Fatalf("unexpected opcode: %s", c.N) - } -} diff --git a/fetcher.go b/fetcher.go new file mode 100644 index 0000000..a0f6c55 --- /dev/null +++ b/fetcher.go @@ -0,0 +1,21 @@ +package z80 + +type fetcher interface { + fetch() uint8 + fetchLabel() string +} + +type memSrc []uint8 + +func (m *memSrc) fetch() uint8 { + if len(*m) == 0 { + return 0 + } + var b uint8 + b, *m = (*m)[0], (*m)[1:] + return b +} + +func (m *memSrc) fetchLabel() string { + return "IM0" +} diff --git a/gen_switch.go b/gen_switch.go new file mode 100644 index 0000000..d47362e --- /dev/null +++ b/gen_switch.go @@ -0,0 +1,112 @@ +package z80 + +import ( + "bufio" + "fmt" + "io" + + "github.com/koron-go/z80/internal/opname" +) + +// GenerateSwitchDecoder generate decoder `switch` statements. +func GenerateSwitchDecoder(w io.Writer) error { + bw := bufio.NewWriter(w) + _, err := bw.WriteString(`package z80 + +func decodeExec(cpu *CPU, f fetcher) error { + var b uint8 + buf := cpu.decodeBuf[:4]`) + if err != nil { + return err + } + l := defaultDecodeLayer() + nr := 0 + err = writeLayerCode(bw, l, nr) + if err != nil { + return err + } + _, err = fmt.Fprintf(bw, "\n}\n") + if err != nil { + return err + } + return bw.Flush() +} + +type nextItem struct { + d uint8 + l *decodeLayer +} + +func writeLayerCode(w *bufio.Writer, l *decodeLayer, nr int) error { + if l.anyNode != nil { + fmt.Fprintf(w, "\nbuf[%d] = f.fetch()", nr) + if l.anyNode.next == nil { + return fmt.Errorf("invalid any node: %+v", l.anyNode) + } + return writeLayerCode(w, l.anyNode.next, nr+1) + } + + fmt.Fprintf(w, ` +b = f.fetch() +buf[%d] = b`, nr) + nr++ + w.WriteString("\nswitch b {") + + var singleOps []*OPCode + var codesMap = map[string][]uint8{} + var nexts []*nextItem + for i, n := range l.nodes { + if n == nil { + continue + } + if n.next != nil { + nexts = append(nexts, &nextItem{d: uint8(i), l: n.next}) + continue + } + if n.opcode == nil { + return fmt.Errorf("node without opcode: %+v", n) + } + // store opcode to group. + op := n.opcode + codes, ok := codesMap[op.N] + if !ok { + singleOps = append(singleOps, op) + } + codes = append(codes, uint8(i)) + codesMap[op.N] = codes + } + + for _, op := range singleOps { + codes, ok := codesMap[op.N] + if !ok || len(codes) == 0 { + panic("something wrong: failed to build codesMap") + } + w.WriteString("\ncase") + for i, code := range codes { + fmt.Fprintf(w, " 0x%02x", code) + if i+1 < len(codes) { + w.WriteRune(',') + } else { + w.WriteRune(':') + } + } + if d := len(op.C) - nr; d > 0 { + for i := 0; i < d; i++ { + fmt.Fprintf(w, "\nbuf[%d] = f.fetch()", nr+i) + } + } + name := opname.Mangle(op.N) + fmt.Fprintf(w, "\n%s(cpu, buf[:%d])\nreturn nil", name, len(op.C)) + } + + for _, n := range nexts { + fmt.Fprintf(w, "\ncase 0x%02x:", n.d) + writeLayerCode(w, n.l, nr) + } + + w.WriteString(` +default: + return ErrInvalidCodes +}`) + return nil +} diff --git a/internal/opname/opname.go b/internal/opname/opname.go new file mode 100644 index 0000000..24a4486 --- /dev/null +++ b/internal/opname/opname.go @@ -0,0 +1,27 @@ +package opname + +import "strings" + +func invalidRune(r rune) bool { + // valid: 0-9 A-Z a-z + // invalid: others + return r < '0' || + (r > '9' && r < 'A') || + (r > 'Z' && r < 'a') || + r > 'z' +} + +func mapping(r rune) rune { + if r == ')' { + return 'P' + } + if invalidRune(r) { + return -1 + } + return r +} + +// Mangle mangles OPCode name +func Mangle(s string) string { + return "op" + strings.Map(mapping, s) +} diff --git a/op_arith16.go b/op_arith16.go index 7d16863..200a1b4 100644 --- a/op_arith16.go +++ b/op_arith16.go @@ -8,11 +8,7 @@ var arith16 = []*OPCode{ {0x09, 0x30, vReg16_4}, }, T: []int{4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.HL.U16() - x := cpu.reg16ss(codes[0] >> 4).U16() - cpu.HL.SetU16(cpu.addU16(a, x)) - }, + F: opADDHLss, }, { @@ -22,11 +18,7 @@ var arith16 = []*OPCode{ {0x4a, 0x30, vReg16_4}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.HL.U16() - x := cpu.reg16ss(codes[1] >> 4).U16() - cpu.HL.SetU16(cpu.adcU16(a, x)) - }, + F: opADCHLss, }, { @@ -36,11 +28,7 @@ var arith16 = []*OPCode{ {0x42, 0x30, vReg16_4}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.HL.U16() - x := cpu.reg16ss(codes[1] >> 4).U16() - cpu.HL.SetU16(cpu.sbcU16(a, x)) - }, + F: opSBCHLss, }, { @@ -50,11 +38,7 @@ var arith16 = []*OPCode{ {0x09, 0x30, vReg16_4}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.IX - x := cpu.reg16pp(codes[1] >> 4) - cpu.IX = cpu.addU16(a, x) - }, + F: opADDIXpp, }, { @@ -64,11 +48,7 @@ var arith16 = []*OPCode{ {0x09, 0x30, vReg16_4}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.IY - x := cpu.reg16rr(codes[1] >> 4) - cpu.IY = cpu.addU16(a, x) - }, + F: opADDIYrr, }, { @@ -77,10 +57,7 @@ var arith16 = []*OPCode{ {0x03, 0x30, vReg16_4}, }, T: []int{6}, - F: func(cpu *CPU, codes []uint8) { - ss := cpu.reg16ss(codes[0] >> 4) - ss.SetU16(cpu.incU16(ss.U16())) - }, + F: opINCss, }, { @@ -90,9 +67,7 @@ var arith16 = []*OPCode{ {0x23, 0x00, nil}, }, T: []int{4, 6}, - F: func(cpu *CPU, codes []uint8) { - cpu.IX = cpu.incU16(cpu.IX) - }, + F: opINCIX, }, { @@ -102,9 +77,7 @@ var arith16 = []*OPCode{ {0x23, 0x00, nil}, }, T: []int{4, 6}, - F: func(cpu *CPU, codes []uint8) { - cpu.IY = cpu.incU16(cpu.IY) - }, + F: opINCIY, }, { @@ -113,10 +86,7 @@ var arith16 = []*OPCode{ {0x0b, 0x30, vReg16_4}, }, T: []int{6}, - F: func(cpu *CPU, codes []uint8) { - ss := cpu.reg16ss(codes[0] >> 4) - ss.SetU16(cpu.decU16(ss.U16())) - }, + F: opDECss, }, { @@ -126,9 +96,7 @@ var arith16 = []*OPCode{ {0x2b, 0x00, nil}, }, T: []int{4, 6}, - F: func(cpu *CPU, codes []uint8) { - cpu.IX = cpu.decU16(cpu.IX) - }, + F: opDECIX, }, { @@ -138,8 +106,62 @@ var arith16 = []*OPCode{ {0x2b, 0x00, nil}, }, T: []int{4, 6}, - F: func(cpu *CPU, codes []uint8) { - cpu.IY = cpu.decU16(cpu.IY) - }, + F: opDECIY, }, } + +func opADDHLss(cpu *CPU, codes []uint8) { + a := cpu.HL.U16() + x := cpu.reg16ss(codes[0] >> 4).U16() + cpu.HL.SetU16(cpu.addU16(a, x)) +} + +func opADCHLss(cpu *CPU, codes []uint8) { + a := cpu.HL.U16() + x := cpu.reg16ss(codes[1] >> 4).U16() + cpu.HL.SetU16(cpu.adcU16(a, x)) +} + +func opSBCHLss(cpu *CPU, codes []uint8) { + a := cpu.HL.U16() + x := cpu.reg16ss(codes[1] >> 4).U16() + cpu.HL.SetU16(cpu.sbcU16(a, x)) +} + +func opADDIXpp(cpu *CPU, codes []uint8) { + a := cpu.IX + x := cpu.reg16pp(codes[1] >> 4) + cpu.IX = cpu.addU16(a, x) +} + +func opADDIYrr(cpu *CPU, codes []uint8) { + a := cpu.IY + x := cpu.reg16rr(codes[1] >> 4) + cpu.IY = cpu.addU16(a, x) +} + +func opINCss(cpu *CPU, codes []uint8) { + ss := cpu.reg16ss(codes[0] >> 4) + ss.SetU16(cpu.incU16(ss.U16())) +} + +func opINCIX(cpu *CPU, codes []uint8) { + cpu.IX = cpu.incU16(cpu.IX) +} + +func opINCIY(cpu *CPU, codes []uint8) { + cpu.IY = cpu.incU16(cpu.IY) +} + +func opDECss(cpu *CPU, codes []uint8) { + ss := cpu.reg16ss(codes[0] >> 4) + ss.SetU16(cpu.decU16(ss.U16())) +} + +func opDECIX(cpu *CPU, codes []uint8) { + cpu.IX = cpu.decU16(cpu.IX) +} + +func opDECIY(cpu *CPU, codes []uint8) { + cpu.IY = cpu.decU16(cpu.IY) +} diff --git a/op_arith8.go b/op_arith8.go index 9c2b27c..490b920 100644 --- a/op_arith8.go +++ b/op_arith8.go @@ -8,11 +8,7 @@ var arith8 = []*OPCode{ {0x80, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := *cpu.regP(codes[0]) - cpu.AF.Hi = cpu.addU8(a, x) - }, + F: opADDAr, }, { @@ -22,11 +18,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - n := codes[1] - cpu.AF.Hi = cpu.addU8(a, n) - }, + F: opADDAn, }, { @@ -35,11 +27,7 @@ var arith8 = []*OPCode{ {0x86, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.Memory.Get(cpu.HL.U16()) - cpu.AF.Hi = cpu.addU8(a, x) - }, + F: opADDAHLP, }, { @@ -50,13 +38,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - //fmt.Printf("a=%02x p=%04x x=%02x ix=%04x\n", a, p, x, cpu.IX) - cpu.AF.Hi = cpu.addU8(a, x) - }, + F: opADDAIXdP, }, { @@ -67,12 +49,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.addU8(a, x) - }, + F: opADDAIYdP, }, { @@ -81,11 +58,7 @@ var arith8 = []*OPCode{ {0x88, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := *cpu.regP(codes[0]) - cpu.AF.Hi = cpu.adcU8(a, x) - }, + F: opADCAr, }, { @@ -95,11 +68,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - n := codes[1] - cpu.AF.Hi = cpu.adcU8(a, n) - }, + F: opADCAn, }, { @@ -108,11 +77,7 @@ var arith8 = []*OPCode{ {0x8e, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.Memory.Get(cpu.HL.U16()) - cpu.AF.Hi = cpu.adcU8(a, x) - }, + F: opADCAHLP, }, { @@ -123,12 +88,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.adcU8(a, x) - }, + F: opADCAIXdP, }, { @@ -139,12 +99,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.adcU8(a, x) - }, + F: opADCAIYdP, }, { @@ -153,11 +108,7 @@ var arith8 = []*OPCode{ {0x90, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := *cpu.regP(codes[0]) - cpu.AF.Hi = cpu.subU8(a, x) - }, + F: opSUBAr, }, { @@ -167,11 +118,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - n := codes[1] - cpu.AF.Hi = cpu.subU8(a, n) - }, + F: opSUBAn, }, { @@ -180,11 +127,7 @@ var arith8 = []*OPCode{ {0x96, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.Memory.Get(cpu.HL.U16()) - cpu.AF.Hi = cpu.subU8(a, x) - }, + F: opSUBAHLP, }, { @@ -195,12 +138,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.subU8(a, x) - }, + F: opSUBAIXdP, }, { @@ -211,12 +149,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.subU8(a, x) - }, + F: opSUBAIYdP, }, { @@ -225,11 +158,7 @@ var arith8 = []*OPCode{ {0x98, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := *cpu.regP(codes[0]) - cpu.AF.Hi = cpu.sbcU8(a, x) - }, + F: opSBCAr, }, { @@ -239,11 +168,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - n := codes[1] - cpu.AF.Hi = cpu.sbcU8(a, n) - }, + F: opSBCAn, }, { @@ -252,11 +177,7 @@ var arith8 = []*OPCode{ {0x9e, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.Memory.Get(cpu.HL.U16()) - cpu.AF.Hi = cpu.sbcU8(a, x) - }, + F: opSBCAHLP, }, { @@ -267,12 +188,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.sbcU8(a, x) - }, + F: opSBCAIXdP, }, { @@ -283,12 +199,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.sbcU8(a, x) - }, + F: opSBCAIYdP, }, { @@ -297,11 +208,7 @@ var arith8 = []*OPCode{ {0xa0, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := *cpu.regP(codes[0]) - cpu.AF.Hi = cpu.andU8(a, x) - }, + F: opANDr, }, { @@ -311,11 +218,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - n := codes[1] - cpu.AF.Hi = cpu.andU8(a, n) - }, + F: opANDn, }, { @@ -324,11 +227,7 @@ var arith8 = []*OPCode{ {0xa6, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.Memory.Get(cpu.HL.U16()) - cpu.AF.Hi = cpu.andU8(a, x) - }, + F: opANDHLP, }, { @@ -339,12 +238,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.andU8(a, x) - }, + F: opANDIXdP, }, { @@ -355,12 +249,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.andU8(a, x) - }, + F: opANDIYdP, }, { @@ -369,11 +258,7 @@ var arith8 = []*OPCode{ {0xb0, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := *cpu.regP(codes[0]) - cpu.AF.Hi = cpu.orU8(a, x) - }, + F: opORr, }, { @@ -383,11 +268,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - n := codes[1] - cpu.AF.Hi = cpu.orU8(a, n) - }, + F: opORn, }, { @@ -396,11 +277,7 @@ var arith8 = []*OPCode{ {0xb6, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.Memory.Get(cpu.HL.U16()) - cpu.AF.Hi = cpu.orU8(a, x) - }, + F: opORHLP, }, { @@ -411,12 +288,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.orU8(a, x) - }, + F: opORIXdP, }, { @@ -427,12 +299,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.orU8(a, x) - }, + F: opORIYdP, }, { @@ -441,11 +308,7 @@ var arith8 = []*OPCode{ {0xa8, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := *cpu.regP(codes[0]) - cpu.AF.Hi = cpu.xorU8(a, x) - }, + F: opXORr, }, { @@ -455,11 +318,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - n := codes[1] - cpu.AF.Hi = cpu.xorU8(a, n) - }, + F: opXORn, }, { @@ -468,11 +327,7 @@ var arith8 = []*OPCode{ {0xae, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.Memory.Get(cpu.HL.U16()) - cpu.AF.Hi = cpu.xorU8(a, x) - }, + F: opXORHLP, }, { @@ -483,12 +338,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.xorU8(a, x) - }, + F: opXORIXdP, }, { @@ -499,12 +349,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.AF.Hi = cpu.xorU8(a, x) - }, + F: opXORIYdP, }, { @@ -513,11 +358,7 @@ var arith8 = []*OPCode{ {0xb8, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := *cpu.regP(codes[0]) - cpu.subU8(a, x) - }, + F: opCPr, }, { @@ -527,11 +368,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - n := codes[1] - cpu.subU8(a, n) - }, + F: opCPn, }, { @@ -540,11 +377,7 @@ var arith8 = []*OPCode{ {0xbe, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.Memory.Get(cpu.HL.U16()) - cpu.subU8(a, x) - }, + F: opCPHLP, }, { @@ -555,12 +388,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - cpu.subU8(a, x) - }, + F: opCPIXdP, }, { @@ -571,12 +399,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.subU8(a, x) - }, + F: opCPIYdP, }, { @@ -585,10 +408,7 @@ var arith8 = []*OPCode{ {0x04, 0x38, vReg8_3}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[0] >> 3) - *r = cpu.incU8(*r) - }, + F: opINCr, }, { @@ -597,11 +417,7 @@ var arith8 = []*OPCode{ {0x34, 0x00, nil}, }, T: []int{4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - x := cpu.Memory.Get(p) - cpu.Memory.Set(p, cpu.incU8(x)) - }, + F: opINCHLP, }, { @@ -612,11 +428,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - cpu.Memory.Set(p, cpu.incU8(x)) - }, + F: opINCIXdP, }, { @@ -627,11 +439,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.Memory.Set(p, cpu.incU8(x)) - }, + F: opINCIYdP, }, { @@ -640,10 +448,7 @@ var arith8 = []*OPCode{ {0x05, 0x38, vReg8_3}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[0] >> 3) - *r = cpu.decU8(*r) - }, + F: opDECr, }, { @@ -652,11 +457,7 @@ var arith8 = []*OPCode{ {0x35, 0x00, nil}, }, T: []int{4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - x := cpu.Memory.Get(p) - cpu.Memory.Set(p, cpu.decU8(x)) - }, + F: opDECHLP, }, { @@ -667,11 +468,7 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - x := cpu.Memory.Get(p) - cpu.Memory.Set(p, cpu.decU8(x)) - }, + F: opDECIXdP, }, { @@ -682,10 +479,309 @@ var arith8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - x := cpu.Memory.Get(p) - cpu.Memory.Set(p, cpu.decU8(x)) - }, + F: opDECIYdP, }, } + +func opADDAr(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := *cpu.regP(codes[0]) + cpu.AF.Hi = cpu.addU8(a, x) +} + +func opADDAn(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + n := codes[1] + cpu.AF.Hi = cpu.addU8(a, n) +} + +func opADDAHLP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.Memory.Get(cpu.HL.U16()) + cpu.AF.Hi = cpu.addU8(a, x) +} + +func opADDAIXdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + //fmt.Printf("a=%02x p=%04x x=%02x ix=%04x\n", a, p, x, cpu.IX) + cpu.AF.Hi = cpu.addU8(a, x) +} + +func opADDAIYdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.addU8(a, x) +} + +func opADCAr(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := *cpu.regP(codes[0]) + cpu.AF.Hi = cpu.adcU8(a, x) +} + +func opADCAn(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + n := codes[1] + cpu.AF.Hi = cpu.adcU8(a, n) +} + +func opADCAHLP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.Memory.Get(cpu.HL.U16()) + cpu.AF.Hi = cpu.adcU8(a, x) +} + +func opADCAIXdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.adcU8(a, x) +} + +func opADCAIYdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.adcU8(a, x) +} + +func opSUBAr(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := *cpu.regP(codes[0]) + cpu.AF.Hi = cpu.subU8(a, x) +} + +func opSUBAn(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + n := codes[1] + cpu.AF.Hi = cpu.subU8(a, n) +} + +func opSUBAHLP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.Memory.Get(cpu.HL.U16()) + cpu.AF.Hi = cpu.subU8(a, x) +} + +func opSUBAIXdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.subU8(a, x) +} + +func opSUBAIYdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.subU8(a, x) +} + +func opSBCAr(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := *cpu.regP(codes[0]) + cpu.AF.Hi = cpu.sbcU8(a, x) +} + +func opSBCAn(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + n := codes[1] + cpu.AF.Hi = cpu.sbcU8(a, n) +} + +func opSBCAHLP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.Memory.Get(cpu.HL.U16()) + cpu.AF.Hi = cpu.sbcU8(a, x) +} + +func opSBCAIXdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.sbcU8(a, x) +} + +func opSBCAIYdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.sbcU8(a, x) +} + +func opANDr(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := *cpu.regP(codes[0]) + cpu.AF.Hi = cpu.andU8(a, x) +} + +func opANDn(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + n := codes[1] + cpu.AF.Hi = cpu.andU8(a, n) +} + +func opANDHLP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.Memory.Get(cpu.HL.U16()) + cpu.AF.Hi = cpu.andU8(a, x) +} + +func opANDIXdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.andU8(a, x) +} + +func opANDIYdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.andU8(a, x) +} + +func opORr(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := *cpu.regP(codes[0]) + cpu.AF.Hi = cpu.orU8(a, x) +} + +func opORn(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + n := codes[1] + cpu.AF.Hi = cpu.orU8(a, n) +} + +func opORHLP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.Memory.Get(cpu.HL.U16()) + cpu.AF.Hi = cpu.orU8(a, x) +} + +func opORIXdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.orU8(a, x) +} + +func opORIYdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.orU8(a, x) +} + +func opXORr(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := *cpu.regP(codes[0]) + cpu.AF.Hi = cpu.xorU8(a, x) +} + +func opXORn(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + n := codes[1] + cpu.AF.Hi = cpu.xorU8(a, n) +} + +func opXORHLP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.Memory.Get(cpu.HL.U16()) + cpu.AF.Hi = cpu.xorU8(a, x) +} + +func opXORIXdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.xorU8(a, x) +} + +func opXORIYdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.AF.Hi = cpu.xorU8(a, x) +} + +func opCPr(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := *cpu.regP(codes[0]) + cpu.subU8(a, x) +} + +func opCPn(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + n := codes[1] + cpu.subU8(a, n) +} + +func opCPHLP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.Memory.Get(cpu.HL.U16()) + cpu.subU8(a, x) +} + +func opCPIXdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + cpu.subU8(a, x) +} + +func opCPIYdP(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.subU8(a, x) +} + +func opINCr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[0] >> 3) + *r = cpu.incU8(*r) +} + +func opINCHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + x := cpu.Memory.Get(p) + cpu.Memory.Set(p, cpu.incU8(x)) +} + +func opINCIXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + cpu.Memory.Set(p, cpu.incU8(x)) +} + +func opINCIYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.Memory.Set(p, cpu.incU8(x)) +} + +func opDECr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[0] >> 3) + *r = cpu.decU8(*r) +} + +func opDECHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + x := cpu.Memory.Get(p) + cpu.Memory.Set(p, cpu.decU8(x)) +} + +func opDECIXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + x := cpu.Memory.Get(p) + cpu.Memory.Set(p, cpu.decU8(x)) +} + +func opDECIYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + x := cpu.Memory.Get(p) + cpu.Memory.Set(p, cpu.decU8(x)) +} diff --git a/op_bitop.go b/op_bitop.go index def9a73..0057bdb 100644 --- a/op_bitop.go +++ b/op_bitop.go @@ -9,11 +9,7 @@ var bitop = []*OPCode{ {0x40, 0x3f, vBit3Reg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[1] >> 3) & 0x07 - r := cpu.regP(codes[1]) - cpu.bitchk8(b, *r) - }, + F: opBITbr, }, { @@ -23,12 +19,7 @@ var bitop = []*OPCode{ {0x46, 0x38, vBit3_3}, }, T: []int{4, 4, 4}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[1] >> 3) & 0x07 - p := cpu.HL.U16() - v := cpu.Memory.Get(p) - cpu.bitchk8(b, v) - }, + F: opBITbHLP, }, { @@ -40,12 +31,7 @@ var bitop = []*OPCode{ {0x46, 0x38, vBit3_3}, }, T: []int{4, 4, 3, 5, 4}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[3] >> 3) & 0x07 - p := addrOff(cpu.IX, codes[2]) - v := cpu.Memory.Get(p) - cpu.bitchk8(b, v) - }, + F: opBITbIXdP, }, { @@ -57,12 +43,7 @@ var bitop = []*OPCode{ {0x46, 0x38, vBit3_3}, }, T: []int{4, 4, 3, 5, 4}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[3] >> 3) & 0x07 - p := addrOff(cpu.IY, codes[2]) - v := cpu.Memory.Get(p) - cpu.bitchk8(b, v) - }, + F: opBITbIYdP, }, { @@ -72,11 +53,7 @@ var bitop = []*OPCode{ {0xc0, 0x3f, vBit3Reg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[1] >> 3) & 0x07 - r := cpu.regP(codes[1]) - *r = cpu.bitset8(b, *r) - }, + F: opSETbr, }, { @@ -86,13 +63,7 @@ var bitop = []*OPCode{ {0xc6, 0x38, vBit3_3}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[1] >> 3) & 0x07 - p := cpu.HL.U16() - v := cpu.Memory.Get(p) - v = cpu.bitset8(b, v) - cpu.Memory.Set(p, v) - }, + F: opSETbHLP, }, { @@ -104,13 +75,7 @@ var bitop = []*OPCode{ {0xc6, 0x38, vBit3_3}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[3] >> 3) & 0x07 - p := addrOff(cpu.IX, codes[2]) - v := cpu.Memory.Get(p) - v = cpu.bitset8(b, v) - cpu.Memory.Set(p, v) - }, + F: opSETbIXdP, }, { @@ -122,13 +87,7 @@ var bitop = []*OPCode{ {0xc6, 0x38, vBit3_3}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[3] >> 3) & 0x07 - p := addrOff(cpu.IY, codes[2]) - v := cpu.Memory.Get(p) - v = cpu.bitset8(b, v) - cpu.Memory.Set(p, v) - }, + F: opSETbIYdP, }, { @@ -138,11 +97,7 @@ var bitop = []*OPCode{ {0x80, 0x3f, vBit3Reg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[1] >> 3) & 0x07 - r := cpu.regP(codes[1]) - *r = cpu.bitres8(b, *r) - }, + F: opRESbr, }, { @@ -152,13 +107,7 @@ var bitop = []*OPCode{ {0x86, 0x38, vBit3_3}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[1] >> 3) & 0x07 - p := cpu.HL.U16() - v := cpu.Memory.Get(p) - v = cpu.bitres8(b, v) - cpu.Memory.Set(p, v) - }, + F: opRESbHLP, }, { @@ -170,13 +119,7 @@ var bitop = []*OPCode{ {0x86, 0x38, vBit3_3}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[3] >> 3) & 0x07 - p := addrOff(cpu.IX, codes[2]) - v := cpu.Memory.Get(p) - v = cpu.bitres8(b, v) - cpu.Memory.Set(p, v) - }, + F: opRESbIXdP, }, { @@ -188,12 +131,93 @@ var bitop = []*OPCode{ {0x86, 0x38, vBit3_3}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - b := (codes[3] >> 3) & 0x07 - p := addrOff(cpu.IY, codes[2]) - v := cpu.Memory.Get(p) - v = cpu.bitres8(b, v) - cpu.Memory.Set(p, v) - }, + F: opRESbIYdP, }, } + +func opBITbr(cpu *CPU, codes []uint8) { + b := (codes[1] >> 3) & 0x07 + r := cpu.regP(codes[1]) + cpu.bitchk8(b, *r) +} + +func opBITbHLP(cpu *CPU, codes []uint8) { + b := (codes[1] >> 3) & 0x07 + p := cpu.HL.U16() + v := cpu.Memory.Get(p) + cpu.bitchk8(b, v) +} + +func opBITbIXdP(cpu *CPU, codes []uint8) { + b := (codes[3] >> 3) & 0x07 + p := addrOff(cpu.IX, codes[2]) + v := cpu.Memory.Get(p) + cpu.bitchk8(b, v) +} + +func opBITbIYdP(cpu *CPU, codes []uint8) { + b := (codes[3] >> 3) & 0x07 + p := addrOff(cpu.IY, codes[2]) + v := cpu.Memory.Get(p) + cpu.bitchk8(b, v) +} + +func opSETbr(cpu *CPU, codes []uint8) { + b := (codes[1] >> 3) & 0x07 + r := cpu.regP(codes[1]) + *r = cpu.bitset8(b, *r) +} + +func opSETbHLP(cpu *CPU, codes []uint8) { + b := (codes[1] >> 3) & 0x07 + p := cpu.HL.U16() + v := cpu.Memory.Get(p) + v = cpu.bitset8(b, v) + cpu.Memory.Set(p, v) +} + +func opSETbIXdP(cpu *CPU, codes []uint8) { + b := (codes[3] >> 3) & 0x07 + p := addrOff(cpu.IX, codes[2]) + v := cpu.Memory.Get(p) + v = cpu.bitset8(b, v) + cpu.Memory.Set(p, v) +} + +func opSETbIYdP(cpu *CPU, codes []uint8) { + b := (codes[3] >> 3) & 0x07 + p := addrOff(cpu.IY, codes[2]) + v := cpu.Memory.Get(p) + v = cpu.bitset8(b, v) + cpu.Memory.Set(p, v) +} + +func opRESbr(cpu *CPU, codes []uint8) { + b := (codes[1] >> 3) & 0x07 + r := cpu.regP(codes[1]) + *r = cpu.bitres8(b, *r) +} + +func opRESbHLP(cpu *CPU, codes []uint8) { + b := (codes[1] >> 3) & 0x07 + p := cpu.HL.U16() + v := cpu.Memory.Get(p) + v = cpu.bitres8(b, v) + cpu.Memory.Set(p, v) +} + +func opRESbIXdP(cpu *CPU, codes []uint8) { + b := (codes[3] >> 3) & 0x07 + p := addrOff(cpu.IX, codes[2]) + v := cpu.Memory.Get(p) + v = cpu.bitres8(b, v) + cpu.Memory.Set(p, v) +} + +func opRESbIYdP(cpu *CPU, codes []uint8) { + b := (codes[3] >> 3) & 0x07 + p := addrOff(cpu.IY, codes[2]) + v := cpu.Memory.Get(p) + v = cpu.bitres8(b, v) + cpu.Memory.Set(p, v) +} diff --git a/op_callret.go b/op_callret.go index 78ba1dd..90ab38e 100644 --- a/op_callret.go +++ b/op_callret.go @@ -1,30 +1,23 @@ package z80 -var opRETI = &OPCode{ +var opcRETI = &OPCode{ N: "RETI", C: []Code{ {0xed, 0x00, nil}, {0x4d, 0x00, nil}, }, T: []int{4, 4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.PC = cpu.readU16(cpu.SP) - cpu.SP += 2 - }, + F: opRETI, } -var opRETN = &OPCode{ +var opcRETN = &OPCode{ N: "RETN", C: []Code{ {0xed, 0x00, nil}, {0x45, 0x00, nil}, }, T: []int{4, 4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.PC = cpu.readU16(cpu.SP) - cpu.SP += 2 - cpu.IFF1 = cpu.IFF2 - }, + F: opRETN, } var callret = []*OPCode{ @@ -37,11 +30,7 @@ var callret = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.SP -= 2 - cpu.writeU16(cpu.SP, cpu.PC) - cpu.PC = toU16(codes[1], codes[2]) - }, + F: opCALLnn, }, { @@ -53,13 +42,7 @@ var callret = []*OPCode{ }, T: []int{4, 3, 4, 3, 3}, T2: []int{4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - if cpu.flagCC(codes[0] >> 3) { - cpu.SP -= 2 - cpu.writeU16(cpu.SP, cpu.PC) - cpu.PC = toU16(codes[1], codes[2]) - } - }, + F: opCALLccnn, }, { @@ -68,10 +51,7 @@ var callret = []*OPCode{ {0xc9, 0x00, nil}, }, T: []int{4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.PC = cpu.readU16(cpu.SP) - cpu.SP += 2 - }, + F: opRET, }, { @@ -81,17 +61,12 @@ var callret = []*OPCode{ }, T: []int{5, 3, 3}, T2: []int{5}, - F: func(cpu *CPU, codes []uint8) { - if cpu.flagCC(codes[0] >> 3) { - cpu.PC = cpu.readU16(cpu.SP) - cpu.SP += 2 - } - }, + F: opRETcc, }, - opRETI, + opcRETI, - opRETN, + opcRETN, { N: "RST p", @@ -99,10 +74,49 @@ var callret = []*OPCode{ {0xc7, 0x38, vRSTp3_3}, }, T: []int{5, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.SP -= 2 - cpu.writeU16(cpu.SP, cpu.PC) - cpu.PC = uint16(codes[0] & 0x38) - }, + F: opRSTp, }, } + +func opRETI(cpu *CPU, codes []uint8) { + cpu.PC = cpu.readU16(cpu.SP) + cpu.SP += 2 +} + +func opRETN(cpu *CPU, codes []uint8) { + cpu.PC = cpu.readU16(cpu.SP) + cpu.SP += 2 + cpu.IFF1 = cpu.IFF2 +} + +func opCALLnn(cpu *CPU, codes []uint8) { + cpu.SP -= 2 + cpu.writeU16(cpu.SP, cpu.PC) + cpu.PC = toU16(codes[1], codes[2]) +} + +func opCALLccnn(cpu *CPU, codes []uint8) { + if cpu.flagCC(codes[0] >> 3) { + cpu.SP -= 2 + cpu.writeU16(cpu.SP, cpu.PC) + cpu.PC = toU16(codes[1], codes[2]) + } +} + +func opRET(cpu *CPU, codes []uint8) { + cpu.PC = cpu.readU16(cpu.SP) + cpu.SP += 2 +} + +func opRETcc(cpu *CPU, codes []uint8) { + if cpu.flagCC(codes[0] >> 3) { + cpu.PC = cpu.readU16(cpu.SP) + cpu.SP += 2 + } +} + +func opRSTp(cpu *CPU, codes []uint8) { + cpu.SP -= 2 + cpu.writeU16(cpu.SP, cpu.PC) + cpu.PC = uint16(codes[0] & 0x38) +} diff --git a/op_ctrl.go b/op_ctrl.go index ce9d2dc..04d8ac9 100644 --- a/op_ctrl.go +++ b/op_ctrl.go @@ -2,27 +2,22 @@ package z80 import "math/bits" -var opHALT = &OPCode{ +var opcHALT = &OPCode{ N: "HALT", C: []Code{ {0x76, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - // nothing todo. - }, + F: opHALT, } -var opEI = &OPCode{ +var opcEI = &OPCode{ N: "EI", C: []Code{ {0xfb, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - cpu.IFF1 = true - cpu.IFF2 = true - }, + F: opEI, } var ctrl = []*OPCode{ @@ -42,10 +37,7 @@ var ctrl = []*OPCode{ {0x2F, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - cpu.AF.Hi = ^cpu.AF.Hi - cpu.flagUpdate(FlagOp{}.Set(H).Set(N)) - }, + F: opCPL, }, { @@ -55,18 +47,7 @@ var ctrl = []*OPCode{ {0x44, 0x00, nil}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - v := ^a + 1 - cpu.AF.Hi = v - cpu.flagUpdate(FlagOp{}. - Put(S, v&0x80 != 0). - Put(Z, v == 0). - Put(H, a&0x0f != 0). - Put(PV, a == 0x80). - Set(N). - Put(C, a != 0)) - }, + F: opNEG, }, { @@ -75,10 +56,7 @@ var ctrl = []*OPCode{ {0x3f, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - c := cpu.flag(C) - cpu.flagUpdate(FlagOp{}.Put(H, c).Reset(N).Put(C, !c)) - }, + F: opCCF, }, { @@ -87,9 +65,7 @@ var ctrl = []*OPCode{ {0x37, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - cpu.flagUpdate(FlagOp{}.Reset(H).Reset(N).Set(C)) - }, + F: opSCF, }, { @@ -98,12 +74,10 @@ var ctrl = []*OPCode{ {0x00, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - // do nothing. - }, + F: opNOP, }, - opHALT, + opcHALT, { N: "DI", @@ -111,13 +85,10 @@ var ctrl = []*OPCode{ {0xf3, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - cpu.IFF1 = false - cpu.IFF2 = false - }, + F: opDI, }, - opEI, + opcEI, { N: "IM 0", @@ -126,9 +97,7 @@ var ctrl = []*OPCode{ {0x46, 0x00, nil}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.IM = 0 - }, + F: opIM0, }, { @@ -138,9 +107,7 @@ var ctrl = []*OPCode{ {0x56, 0x00, nil}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.IM = 1 - }, + F: opIM1, }, { @@ -150,9 +117,7 @@ var ctrl = []*OPCode{ {0x5e, 0x00, nil}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.IM = 2 - }, + F: opIM2, }, } @@ -185,3 +150,60 @@ func opDAA(cpu *CPU, codes []uint8) { Put(C, c || cpu.AF.Hi > 0x99)) cpu.AF.Hi = r } + +func opHALT(cpu *CPU, codes []uint8) { + // nothing todo. +} + +func opEI(cpu *CPU, codes []uint8) { + cpu.IFF1 = true + cpu.IFF2 = true +} + +func opCPL(cpu *CPU, codes []uint8) { + cpu.AF.Hi = ^cpu.AF.Hi + cpu.flagUpdate(FlagOp{}.Set(H).Set(N)) +} + +func opNEG(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + v := ^a + 1 + cpu.AF.Hi = v + cpu.flagUpdate(FlagOp{}. + Put(S, v&0x80 != 0). + Put(Z, v == 0). + Put(H, a&0x0f != 0). + Put(PV, a == 0x80). + Set(N). + Put(C, a != 0)) +} + +func opCCF(cpu *CPU, codes []uint8) { + c := cpu.flag(C) + cpu.flagUpdate(FlagOp{}.Put(H, c).Reset(N).Put(C, !c)) +} + +func opSCF(cpu *CPU, codes []uint8) { + cpu.flagUpdate(FlagOp{}.Reset(H).Reset(N).Set(C)) +} + +func opNOP(cpu *CPU, codes []uint8) { + // do nothing. +} + +func opDI(cpu *CPU, codes []uint8) { + cpu.IFF1 = false + cpu.IFF2 = false +} + +func opIM0(cpu *CPU, codes []uint8) { + cpu.IM = 0 +} + +func opIM1(cpu *CPU, codes []uint8) { + cpu.IM = 1 +} + +func opIM2(cpu *CPU, codes []uint8) { + cpu.IM = 2 +} diff --git a/op_exbtsg.go b/op_exbtsg.go index 5285263..c1733d8 100644 --- a/op_exbtsg.go +++ b/op_exbtsg.go @@ -8,9 +8,7 @@ var exbtsg = []*OPCode{ {0xeb, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - cpu.HL, cpu.DE = cpu.DE, cpu.HL - }, + F: opEXDEHL, }, { @@ -19,9 +17,7 @@ var exbtsg = []*OPCode{ {0x08, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - cpu.AF, cpu.Alternate.AF = cpu.Alternate.AF, cpu.AF - }, + F: opEXAFAF, }, { @@ -30,11 +26,7 @@ var exbtsg = []*OPCode{ {0xd9, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - cpu.BC, cpu.Alternate.BC = cpu.Alternate.BC, cpu.BC - cpu.DE, cpu.Alternate.DE = cpu.Alternate.DE, cpu.DE - cpu.HL, cpu.Alternate.HL = cpu.Alternate.HL, cpu.HL - }, + F: opEXX, }, { @@ -43,11 +35,7 @@ var exbtsg = []*OPCode{ {0xe3, 0x00, nil}, }, T: []int{4, 3, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - v := cpu.readU16(cpu.SP) - cpu.writeU16(cpu.SP, cpu.HL.U16()) - cpu.HL.SetU16(v) - }, + F: opEXSPPHL, }, { @@ -57,11 +45,7 @@ var exbtsg = []*OPCode{ {0xe3, 0x00, nil}, }, T: []int{4, 4, 3, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - v := cpu.readU16(cpu.SP) - cpu.writeU16(cpu.SP, cpu.IX) - cpu.IX = v - }, + F: opEXSPPIX, }, { @@ -71,11 +55,7 @@ var exbtsg = []*OPCode{ {0xe3, 0x00, nil}, }, T: []int{4, 4, 3, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - v := cpu.readU16(cpu.SP) - cpu.writeU16(cpu.SP, cpu.IY) - cpu.IY = v - }, + F: opEXSPPIY, }, { @@ -85,19 +65,7 @@ var exbtsg = []*OPCode{ {0xa0, 0x00, nil}, }, T: []int{4, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - de := cpu.DE.U16() - hl := cpu.HL.U16() - cpu.Memory.Set(de, cpu.Memory.Get(hl)) - cpu.DE.SetU16(de + 1) - cpu.HL.SetU16(hl + 1) - bc := cpu.BC.U16() - 1 - cpu.BC.SetU16(bc) - cpu.flagUpdate(FlagOp{}. - Reset(H). - Put(PV, bc != 0). - Reset(N)) - }, + F: opLDI, }, { @@ -108,22 +76,7 @@ var exbtsg = []*OPCode{ }, T: []int{4, 4, 3, 5, 5}, T2: []int{4, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - de := cpu.DE.U16() - hl := cpu.HL.U16() - cpu.Memory.Set(de, cpu.Memory.Get(hl)) - cpu.DE.SetU16(de + 1) - cpu.HL.SetU16(hl + 1) - bc := cpu.BC.U16() - 1 - cpu.BC.SetU16(bc) - cpu.flagUpdate(FlagOp{}. - Reset(H). - Put(PV, bc != 0). - Reset(N)) - if bc != 0 { - cpu.PC -= 2 - } - }, + F: opLDIR, }, { @@ -133,19 +86,7 @@ var exbtsg = []*OPCode{ {0xa8, 0x00, nil}, }, T: []int{4, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - de := cpu.DE.U16() - hl := cpu.HL.U16() - cpu.Memory.Set(de, cpu.Memory.Get(hl)) - cpu.DE.SetU16(de - 1) - cpu.HL.SetU16(hl - 1) - bc := cpu.BC.U16() - 1 - cpu.BC.SetU16(bc) - cpu.flagUpdate(FlagOp{}. - Reset(H). - Put(PV, bc != 0). - Reset(N)) - }, + F: opLDD, }, { @@ -156,22 +97,7 @@ var exbtsg = []*OPCode{ }, T: []int{4, 4, 3, 5, 5}, T2: []int{4, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - de := cpu.DE.U16() - hl := cpu.HL.U16() - cpu.Memory.Set(de, cpu.Memory.Get(hl)) - cpu.DE.SetU16(de - 1) - cpu.HL.SetU16(hl - 1) - bc := cpu.BC.U16() - 1 - cpu.BC.SetU16(bc) - cpu.flagUpdate(FlagOp{}. - Reset(H). - Put(PV, bc != 0). - Reset(N)) - if bc != 0 { - cpu.PC -= 2 - } - }, + F: opLDDR, }, { @@ -181,21 +107,7 @@ var exbtsg = []*OPCode{ {0xa1, 0x00, nil}, }, T: []int{4, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - hl := cpu.HL.U16() - x := cpu.Memory.Get(hl) - v := a - x - cpu.HL.SetU16(hl + 1) - bc := cpu.BC.U16() - 1 - cpu.BC.SetU16(bc) - cpu.flagUpdate(FlagOp{}. - Put(S, v&0x80 != 0). - Put(Z, v == 0). - Put(H, a&0x0f < x&0x0f). - Put(PV, bc != 0). - Set(N)) - }, + F: opCPI, }, { @@ -206,24 +118,7 @@ var exbtsg = []*OPCode{ }, T: []int{4, 4, 3, 5, 5}, T2: []int{4, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - hl := cpu.HL.U16() - x := cpu.Memory.Get(hl) - v := a - x - cpu.HL.SetU16(hl + 1) - bc := cpu.BC.U16() - 1 - cpu.BC.SetU16(bc) - cpu.flagUpdate(FlagOp{}. - Put(S, v&0x80 != 0). - Put(Z, v == 0). - Put(H, a&0x0f < x&0x0f). - Put(PV, bc != 0). - Set(N)) - if bc != 0 && v != 0 { - cpu.PC -= 2 - } - }, + F: opCPIR, }, { @@ -233,21 +128,7 @@ var exbtsg = []*OPCode{ {0xa9, 0x00, nil}, }, T: []int{4, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - hl := cpu.HL.U16() - x := cpu.Memory.Get(hl) - v := a - x - cpu.HL.SetU16(hl - 1) - bc := cpu.BC.U16() - 1 - cpu.BC.SetU16(bc) - cpu.flagUpdate(FlagOp{}. - Put(S, v&0x80 != 0). - Put(Z, v == 0). - Put(H, a&0x0f < x&0x0f). - Put(PV, bc != 0). - Set(N)) - }, + F: opCPD, }, { @@ -258,23 +139,170 @@ var exbtsg = []*OPCode{ }, T: []int{4, 4, 3, 5, 5}, T2: []int{4, 4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - hl := cpu.HL.U16() - x := cpu.Memory.Get(hl) - v := a - x - cpu.HL.SetU16(hl - 1) - bc := cpu.BC.U16() - 1 - cpu.BC.SetU16(bc) - cpu.flagUpdate(FlagOp{}. - Put(S, v&0x80 != 0). - Put(Z, v == 0). - Put(H, a&0x0f < x&0x0f). - Put(PV, bc != 0). - Set(N)) - if bc != 0 && v != 0 { - cpu.PC -= 2 - } - }, + F: opCPDR, }, } + +func opEXDEHL(cpu *CPU, codes []uint8) { + cpu.HL, cpu.DE = cpu.DE, cpu.HL +} + +func opEXAFAF(cpu *CPU, codes []uint8) { + cpu.AF, cpu.Alternate.AF = cpu.Alternate.AF, cpu.AF +} + +func opEXX(cpu *CPU, codes []uint8) { + cpu.BC, cpu.Alternate.BC = cpu.Alternate.BC, cpu.BC + cpu.DE, cpu.Alternate.DE = cpu.Alternate.DE, cpu.DE + cpu.HL, cpu.Alternate.HL = cpu.Alternate.HL, cpu.HL +} + +func opEXSPPHL(cpu *CPU, codes []uint8) { + v := cpu.readU16(cpu.SP) + cpu.writeU16(cpu.SP, cpu.HL.U16()) + cpu.HL.SetU16(v) +} + +func opEXSPPIX(cpu *CPU, codes []uint8) { + v := cpu.readU16(cpu.SP) + cpu.writeU16(cpu.SP, cpu.IX) + cpu.IX = v +} + +func opEXSPPIY(cpu *CPU, codes []uint8) { + v := cpu.readU16(cpu.SP) + cpu.writeU16(cpu.SP, cpu.IY) + cpu.IY = v +} + +func opLDI(cpu *CPU, codes []uint8) { + de := cpu.DE.U16() + hl := cpu.HL.U16() + cpu.Memory.Set(de, cpu.Memory.Get(hl)) + cpu.DE.SetU16(de + 1) + cpu.HL.SetU16(hl + 1) + bc := cpu.BC.U16() - 1 + cpu.BC.SetU16(bc) + cpu.flagUpdate(FlagOp{}. + Reset(H). + Put(PV, bc != 0). + Reset(N)) +} + +func opLDIR(cpu *CPU, codes []uint8) { + de := cpu.DE.U16() + hl := cpu.HL.U16() + cpu.Memory.Set(de, cpu.Memory.Get(hl)) + cpu.DE.SetU16(de + 1) + cpu.HL.SetU16(hl + 1) + bc := cpu.BC.U16() - 1 + cpu.BC.SetU16(bc) + cpu.flagUpdate(FlagOp{}. + Reset(H). + Put(PV, bc != 0). + Reset(N)) + if bc != 0 { + cpu.PC -= 2 + } +} + +func opLDD(cpu *CPU, codes []uint8) { + de := cpu.DE.U16() + hl := cpu.HL.U16() + cpu.Memory.Set(de, cpu.Memory.Get(hl)) + cpu.DE.SetU16(de - 1) + cpu.HL.SetU16(hl - 1) + bc := cpu.BC.U16() - 1 + cpu.BC.SetU16(bc) + cpu.flagUpdate(FlagOp{}. + Reset(H). + Put(PV, bc != 0). + Reset(N)) +} + +func opLDDR(cpu *CPU, codes []uint8) { + de := cpu.DE.U16() + hl := cpu.HL.U16() + cpu.Memory.Set(de, cpu.Memory.Get(hl)) + cpu.DE.SetU16(de - 1) + cpu.HL.SetU16(hl - 1) + bc := cpu.BC.U16() - 1 + cpu.BC.SetU16(bc) + cpu.flagUpdate(FlagOp{}. + Reset(H). + Put(PV, bc != 0). + Reset(N)) + if bc != 0 { + cpu.PC -= 2 + } +} + +func opCPI(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + hl := cpu.HL.U16() + x := cpu.Memory.Get(hl) + v := a - x + cpu.HL.SetU16(hl + 1) + bc := cpu.BC.U16() - 1 + cpu.BC.SetU16(bc) + cpu.flagUpdate(FlagOp{}. + Put(S, v&0x80 != 0). + Put(Z, v == 0). + Put(H, a&0x0f < x&0x0f). + Put(PV, bc != 0). + Set(N)) +} + +func opCPIR(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + hl := cpu.HL.U16() + x := cpu.Memory.Get(hl) + v := a - x + cpu.HL.SetU16(hl + 1) + bc := cpu.BC.U16() - 1 + cpu.BC.SetU16(bc) + cpu.flagUpdate(FlagOp{}. + Put(S, v&0x80 != 0). + Put(Z, v == 0). + Put(H, a&0x0f < x&0x0f). + Put(PV, bc != 0). + Set(N)) + if bc != 0 && v != 0 { + cpu.PC -= 2 + } +} + +func opCPD(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + hl := cpu.HL.U16() + x := cpu.Memory.Get(hl) + v := a - x + cpu.HL.SetU16(hl - 1) + bc := cpu.BC.U16() - 1 + cpu.BC.SetU16(bc) + cpu.flagUpdate(FlagOp{}. + Put(S, v&0x80 != 0). + Put(Z, v == 0). + Put(H, a&0x0f < x&0x0f). + Put(PV, bc != 0). + Set(N)) +} + +func opCPDR(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + hl := cpu.HL.U16() + x := cpu.Memory.Get(hl) + v := a - x + cpu.HL.SetU16(hl - 1) + bc := cpu.BC.U16() - 1 + cpu.BC.SetU16(bc) + cpu.flagUpdate(FlagOp{}. + Put(S, v&0x80 != 0). + Put(Z, v == 0). + Put(H, a&0x0f < x&0x0f). + Put(PV, bc != 0). + Set(N)) + if bc != 0 && v != 0 { + cpu.PC -= 2 + } +} diff --git a/op_inout.go b/op_inout.go index 93b248c..0216710 100644 --- a/op_inout.go +++ b/op_inout.go @@ -11,9 +11,7 @@ var inout = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.AF.Hi = cpu.ioIn(codes[1]) - }, + F: opINAnP, }, { @@ -23,18 +21,7 @@ var inout = []*OPCode{ {0x40, 0x38, vReg8_3}, }, T: []int{4, 4, 4}, - F: func(cpu *CPU, codes []uint8) { - v := cpu.ioIn(cpu.BC.Lo) - // FIXME: support 0x06 to apply flags only. - r := cpu.regP(codes[1] >> 3) - *r = v - cpu.flagUpdate(FlagOp{}. - Put(S, v&0x80 != 0). - Put(Z, v == 0). - Reset(H). - Put(PV, bits.OnesCount8(v)%2 == 0). - Reset(N)) - }, + F: opINrCP, }, { @@ -44,14 +31,7 @@ var inout = []*OPCode{ {0xa2, 0x00, nil}, }, T: []int{4, 5, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.Memory.Set(cpu.HL.U16(), cpu.ioIn(cpu.BC.Hi)) - cpu.BC.Hi-- - cpu.HL.SetU16(cpu.HL.U16() + 1) - cpu.flagUpdate(FlagOp{}. - Put(Z, cpu.BC.Hi == 0). - Set(N)) - }, + F: opINI, }, { @@ -62,17 +42,7 @@ var inout = []*OPCode{ }, T: []int{4, 5, 3, 4, 5}, T2: []int{4, 5, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.Memory.Set(cpu.HL.U16(), cpu.ioIn(cpu.BC.Hi)) - cpu.BC.Hi-- - cpu.HL.SetU16(cpu.HL.U16() + 1) - cpu.flagUpdate(FlagOp{}. - Put(Z, cpu.BC.Hi == 0). - Set(N)) - if cpu.BC.Hi != 0 { - cpu.PC -= 2 - } - }, + F: opINIR, }, { @@ -82,14 +52,7 @@ var inout = []*OPCode{ {0xaa, 0x00, nil}, }, T: []int{4, 5, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.Memory.Set(cpu.HL.U16(), cpu.ioIn(cpu.BC.Hi)) - cpu.BC.Hi-- - cpu.HL.SetU16(cpu.HL.U16() - 1) - cpu.flagUpdate(FlagOp{}. - Put(Z, cpu.BC.Hi == 0). - Set(N)) - }, + F: opIND, }, { @@ -100,17 +63,7 @@ var inout = []*OPCode{ }, T: []int{4, 5, 3, 4, 5}, T2: []int{4, 5, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.Memory.Set(cpu.HL.U16(), cpu.ioIn(cpu.BC.Hi)) - cpu.BC.Hi-- - cpu.HL.SetU16(cpu.HL.U16() - 1) - cpu.flagUpdate(FlagOp{}. - Put(Z, cpu.BC.Hi == 0). - Set(N)) - if cpu.BC.Hi != 0 { - cpu.PC -= 2 - } - }, + F: opINDR, }, { @@ -120,9 +73,7 @@ var inout = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.ioOut(codes[1], cpu.AF.Hi) - }, + F: opOUTnPA, }, { @@ -132,10 +83,7 @@ var inout = []*OPCode{ {0x41, 0x38, vReg8_3}, }, T: []int{4, 4, 4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1] >> 3) - cpu.ioOut(cpu.BC.Lo, *r) - }, + F: opOUTCPr, }, { @@ -145,14 +93,7 @@ var inout = []*OPCode{ {0xa3, 0x00, nil}, }, T: []int{4, 5, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.ioOut(cpu.BC.Lo, cpu.Memory.Get(cpu.HL.U16())) - cpu.BC.Hi-- - cpu.HL.SetU16(cpu.HL.U16() + 1) - cpu.flagUpdate(FlagOp{}. - Put(Z, cpu.BC.Hi == 0). - Set(N)) - }, + F: opOUTI, }, { @@ -163,17 +104,7 @@ var inout = []*OPCode{ }, T: []int{4, 5, 3, 4, 5}, T2: []int{4, 5, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.ioOut(cpu.BC.Lo, cpu.Memory.Get(cpu.HL.U16())) - cpu.BC.Hi-- - cpu.HL.SetU16(cpu.HL.U16() + 1) - cpu.flagUpdate(FlagOp{}. - Put(Z, cpu.BC.Hi == 0). - Set(N)) - if cpu.BC.Hi != 0 { - cpu.PC -= 2 - } - }, + F: opOTIR, }, { @@ -183,14 +114,7 @@ var inout = []*OPCode{ {0xab, 0x00, nil}, }, T: []int{4, 5, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.ioOut(cpu.BC.Lo, cpu.Memory.Get(cpu.HL.U16())) - cpu.BC.Hi-- - cpu.HL.SetU16(cpu.HL.U16() - 1) - cpu.flagUpdate(FlagOp{}. - Put(Z, cpu.BC.Hi == 0). - Set(N)) - }, + F: opOUTD, }, { @@ -201,16 +125,116 @@ var inout = []*OPCode{ }, T: []int{4, 5, 3, 4, 5}, T2: []int{4, 5, 3, 4}, - F: func(cpu *CPU, codes []uint8) { - cpu.ioOut(cpu.BC.Lo, cpu.Memory.Get(cpu.HL.U16())) - cpu.BC.Hi-- - cpu.HL.SetU16(cpu.HL.U16() - 1) - cpu.flagUpdate(FlagOp{}. - Put(Z, cpu.BC.Hi == 0). - Set(N)) - if cpu.BC.Hi != 0 { - cpu.PC -= 2 - } - }, + F: opOTDR, }, } + +func opINAnP(cpu *CPU, codes []uint8) { + cpu.AF.Hi = cpu.ioIn(codes[1]) +} + +func opINrCP(cpu *CPU, codes []uint8) { + v := cpu.ioIn(cpu.BC.Lo) + // FIXME: support 0x06 to apply flags only. + r := cpu.regP(codes[1] >> 3) + *r = v + cpu.flagUpdate(FlagOp{}. + Put(S, v&0x80 != 0). + Put(Z, v == 0). + Reset(H). + Put(PV, bits.OnesCount8(v)%2 == 0). + Reset(N)) +} + +func opINI(cpu *CPU, codes []uint8) { + cpu.Memory.Set(cpu.HL.U16(), cpu.ioIn(cpu.BC.Hi)) + cpu.BC.Hi-- + cpu.HL.SetU16(cpu.HL.U16() + 1) + cpu.flagUpdate(FlagOp{}. + Put(Z, cpu.BC.Hi == 0). + Set(N)) +} + +func opINIR(cpu *CPU, codes []uint8) { + cpu.Memory.Set(cpu.HL.U16(), cpu.ioIn(cpu.BC.Hi)) + cpu.BC.Hi-- + cpu.HL.SetU16(cpu.HL.U16() + 1) + cpu.flagUpdate(FlagOp{}. + Put(Z, cpu.BC.Hi == 0). + Set(N)) + if cpu.BC.Hi != 0 { + cpu.PC -= 2 + } +} + +func opIND(cpu *CPU, codes []uint8) { + cpu.Memory.Set(cpu.HL.U16(), cpu.ioIn(cpu.BC.Hi)) + cpu.BC.Hi-- + cpu.HL.SetU16(cpu.HL.U16() - 1) + cpu.flagUpdate(FlagOp{}. + Put(Z, cpu.BC.Hi == 0). + Set(N)) +} + +func opINDR(cpu *CPU, codes []uint8) { + cpu.Memory.Set(cpu.HL.U16(), cpu.ioIn(cpu.BC.Hi)) + cpu.BC.Hi-- + cpu.HL.SetU16(cpu.HL.U16() - 1) + cpu.flagUpdate(FlagOp{}. + Put(Z, cpu.BC.Hi == 0). + Set(N)) + if cpu.BC.Hi != 0 { + cpu.PC -= 2 + } +} + +func opOUTnPA(cpu *CPU, codes []uint8) { + cpu.ioOut(codes[1], cpu.AF.Hi) +} + +func opOUTCPr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1] >> 3) + cpu.ioOut(cpu.BC.Lo, *r) +} + +func opOUTI(cpu *CPU, codes []uint8) { + cpu.ioOut(cpu.BC.Lo, cpu.Memory.Get(cpu.HL.U16())) + cpu.BC.Hi-- + cpu.HL.SetU16(cpu.HL.U16() + 1) + cpu.flagUpdate(FlagOp{}. + Put(Z, cpu.BC.Hi == 0). + Set(N)) +} + +func opOTIR(cpu *CPU, codes []uint8) { + cpu.ioOut(cpu.BC.Lo, cpu.Memory.Get(cpu.HL.U16())) + cpu.BC.Hi-- + cpu.HL.SetU16(cpu.HL.U16() + 1) + cpu.flagUpdate(FlagOp{}. + Put(Z, cpu.BC.Hi == 0). + Set(N)) + if cpu.BC.Hi != 0 { + cpu.PC -= 2 + } +} + +func opOUTD(cpu *CPU, codes []uint8) { + cpu.ioOut(cpu.BC.Lo, cpu.Memory.Get(cpu.HL.U16())) + cpu.BC.Hi-- + cpu.HL.SetU16(cpu.HL.U16() - 1) + cpu.flagUpdate(FlagOp{}. + Put(Z, cpu.BC.Hi == 0). + Set(N)) +} + +func opOTDR(cpu *CPU, codes []uint8) { + cpu.ioOut(cpu.BC.Lo, cpu.Memory.Get(cpu.HL.U16())) + cpu.BC.Hi-- + cpu.HL.SetU16(cpu.HL.U16() - 1) + cpu.flagUpdate(FlagOp{}. + Put(Z, cpu.BC.Hi == 0). + Set(N)) + if cpu.BC.Hi != 0 { + cpu.PC -= 2 + } +} diff --git a/op_jump.go b/op_jump.go index 3a97620..609f8e3 100644 --- a/op_jump.go +++ b/op_jump.go @@ -10,9 +10,7 @@ var jump = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.PC = toU16(codes[1], codes[2]) - }, + F: opJPnn, }, { @@ -24,11 +22,7 @@ var jump = []*OPCode{ }, T: []int{4, 3, 4, 3, 3}, T2: []int{4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - if cpu.flagCC(codes[0] >> 3) { - cpu.PC = toU16(codes[1], codes[2]) - } - }, + F: opJPccnn, }, { @@ -38,9 +32,7 @@ var jump = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 5}, - F: func(cpu *CPU, codes []uint8) { - cpu.PC = addrOff(cpu.PC, codes[1]) - }, + F: opJRe, }, { @@ -51,11 +43,7 @@ var jump = []*OPCode{ }, T: []int{4, 3, 5}, T2: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - if cpu.flag(C) { - cpu.PC = addrOff(cpu.PC, codes[1]) - } - }, + F: opJRCe, }, { @@ -66,11 +54,7 @@ var jump = []*OPCode{ }, T: []int{4, 3, 5}, T2: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - if !cpu.flag(C) { - cpu.PC = addrOff(cpu.PC, codes[1]) - } - }, + F: opJRNCe, }, { @@ -81,11 +65,7 @@ var jump = []*OPCode{ }, T: []int{4, 3, 5}, T2: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - if cpu.flag(Z) { - cpu.PC = addrOff(cpu.PC, codes[1]) - } - }, + F: opJRZe, }, { @@ -96,11 +76,7 @@ var jump = []*OPCode{ }, T: []int{4, 3, 5}, T2: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - if !cpu.flag(Z) { - cpu.PC = addrOff(cpu.PC, codes[1]) - } - }, + F: opJRNZe, }, { @@ -109,10 +85,7 @@ var jump = []*OPCode{ {0xe9, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.PC = p - }, + F: opJPHLP, }, { @@ -122,10 +95,7 @@ var jump = []*OPCode{ {0xe9, 0x00, nil}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.IX - cpu.PC = p - }, + F: opJPIXP, }, { @@ -135,10 +105,7 @@ var jump = []*OPCode{ {0xe9, 0x00, nil}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.IY - cpu.PC = p - }, + F: opJPIYP, }, { @@ -149,11 +116,66 @@ var jump = []*OPCode{ }, T: []int{5, 3, 5}, T2: []int{5, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.BC.Hi-- - if cpu.BC.Hi != 0 { - cpu.PC = addrOff(cpu.PC, codes[1]) - } - }, + F: opDJNZe, }, } + +func opJPnn(cpu *CPU, codes []uint8) { + cpu.PC = toU16(codes[1], codes[2]) +} + +func opJPccnn(cpu *CPU, codes []uint8) { + if cpu.flagCC(codes[0] >> 3) { + cpu.PC = toU16(codes[1], codes[2]) + } +} + +func opJRe(cpu *CPU, codes []uint8) { + cpu.PC = addrOff(cpu.PC, codes[1]) +} + +func opJRCe(cpu *CPU, codes []uint8) { + if cpu.flag(C) { + cpu.PC = addrOff(cpu.PC, codes[1]) + } +} + +func opJRNCe(cpu *CPU, codes []uint8) { + if !cpu.flag(C) { + cpu.PC = addrOff(cpu.PC, codes[1]) + } +} + +func opJRZe(cpu *CPU, codes []uint8) { + if cpu.flag(Z) { + cpu.PC = addrOff(cpu.PC, codes[1]) + } +} + +func opJRNZe(cpu *CPU, codes []uint8) { + if !cpu.flag(Z) { + cpu.PC = addrOff(cpu.PC, codes[1]) + } +} + +func opJPHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.PC = p +} + +func opJPIXP(cpu *CPU, codes []uint8) { + p := cpu.IX + cpu.PC = p +} + +func opJPIYP(cpu *CPU, codes []uint8) { + p := cpu.IY + cpu.PC = p +} + +func opDJNZe(cpu *CPU, codes []uint8) { + cpu.BC.Hi-- + if cpu.BC.Hi != 0 { + cpu.PC = addrOff(cpu.PC, codes[1]) + } +} diff --git a/op_load16.go b/op_load16.go index 89e8de2..b385cde 100644 --- a/op_load16.go +++ b/op_load16.go @@ -10,11 +10,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - dd := cpu.reg16dd(codes[0] >> 4) - nn := toU16(codes[1], codes[2]) - dd.SetU16(nn) - }, + F: opLDddnn, }, { @@ -26,10 +22,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - nn := toU16(codes[2], codes[3]) - cpu.IX = nn - }, + F: opLDIXnn, }, { @@ -41,10 +34,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - nn := toU16(codes[2], codes[3]) - cpu.IY = nn - }, + F: opLDIYnn, }, { @@ -55,10 +45,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - nn := toU16(codes[1], codes[2]) - cpu.HL.SetU16(cpu.readU16(nn)) - }, + F: opLDHLnnP, }, { @@ -70,11 +57,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - dd := cpu.reg16dd(codes[1] >> 4) - nn := toU16(codes[2], codes[3]) - dd.SetU16(cpu.readU16(nn)) - }, + F: opLDddnnP, }, { @@ -86,10 +69,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - nn := toU16(codes[2], codes[3]) - cpu.IX = cpu.readU16(nn) - }, + F: opLDIXnnP, }, { @@ -101,10 +81,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - nn := toU16(codes[2], codes[3]) - cpu.IY = cpu.readU16(nn) - }, + F: opLDIYnnP, }, { @@ -115,10 +92,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - nn := toU16(codes[1], codes[2]) - cpu.writeU16(nn, cpu.HL.U16()) - }, + F: opLDnnPHL, }, { @@ -130,11 +104,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - dd := cpu.reg16dd(codes[1] >> 4) - nn := toU16(codes[2], codes[3]) - cpu.writeU16(nn, dd.U16()) - }, + F: opLDnnPdd, }, { @@ -146,10 +116,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - nn := toU16(codes[2], codes[3]) - cpu.writeU16(nn, cpu.IX) - }, + F: opLDnnPIX, }, { @@ -161,10 +128,7 @@ var load16 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - nn := toU16(codes[2], codes[3]) - cpu.writeU16(nn, cpu.IY) - }, + F: opLDnnPIY, }, { @@ -173,9 +137,7 @@ var load16 = []*OPCode{ {0xf9, 0x00, nil}, }, T: []int{6}, - F: func(cpu *CPU, codes []uint8) { - cpu.SP = cpu.HL.U16() - }, + F: opLDSPHL, }, { @@ -185,9 +147,7 @@ var load16 = []*OPCode{ {0xf9, 0x00, nil}, }, T: []int{4, 6}, - F: func(cpu *CPU, codes []uint8) { - cpu.SP = cpu.IX - }, + F: opLDSPIX, }, { @@ -197,9 +157,7 @@ var load16 = []*OPCode{ {0xf9, 0x00, nil}, }, T: []int{4, 6}, - F: func(cpu *CPU, codes []uint8) { - cpu.SP = cpu.IY - }, + F: opLDSPIY, }, { @@ -208,11 +166,7 @@ var load16 = []*OPCode{ {0xc5, 0x30, nil}, }, T: []int{5, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - qq := cpu.reg16qq(codes[0] >> 4) - cpu.SP -= 2 - cpu.writeU16(cpu.SP, qq.U16()) - }, + F: opPUSHqq, }, { @@ -222,10 +176,7 @@ var load16 = []*OPCode{ {0xe5, 0x00, nil}, }, T: []int{4, 5, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.SP -= 2 - cpu.writeU16(cpu.SP, cpu.IX) - }, + F: opPUSHIX, }, { @@ -235,10 +186,7 @@ var load16 = []*OPCode{ {0xe5, 0x00, nil}, }, T: []int{4, 5, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.SP -= 2 - cpu.writeU16(cpu.SP, cpu.IY) - }, + F: opPUSHIY, }, { @@ -247,11 +195,7 @@ var load16 = []*OPCode{ {0xc1, 0x30, nil}, }, T: []int{4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - qq := cpu.reg16qq(codes[0] >> 4) - qq.SetU16(cpu.readU16(cpu.SP)) - cpu.SP += 2 - }, + F: opPOPqq, }, { @@ -261,10 +205,7 @@ var load16 = []*OPCode{ {0xe1, 0x00, nil}, }, T: []int{4, 4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.IX = cpu.readU16(cpu.SP) - cpu.SP += 2 - }, + F: opPOPIX, }, { @@ -274,9 +215,108 @@ var load16 = []*OPCode{ {0xe1, 0x00, nil}, }, T: []int{4, 4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - cpu.IY = cpu.readU16(cpu.SP) - cpu.SP += 2 - }, + F: opPOPIY, }, } + +func opLDddnn(cpu *CPU, codes []uint8) { + dd := cpu.reg16dd(codes[0] >> 4) + nn := toU16(codes[1], codes[2]) + dd.SetU16(nn) +} + +func opLDIXnn(cpu *CPU, codes []uint8) { + nn := toU16(codes[2], codes[3]) + cpu.IX = nn +} + +func opLDIYnn(cpu *CPU, codes []uint8) { + nn := toU16(codes[2], codes[3]) + cpu.IY = nn +} + +func opLDHLnnP(cpu *CPU, codes []uint8) { + nn := toU16(codes[1], codes[2]) + cpu.HL.SetU16(cpu.readU16(nn)) +} + +func opLDddnnP(cpu *CPU, codes []uint8) { + dd := cpu.reg16dd(codes[1] >> 4) + nn := toU16(codes[2], codes[3]) + dd.SetU16(cpu.readU16(nn)) +} + +func opLDIXnnP(cpu *CPU, codes []uint8) { + nn := toU16(codes[2], codes[3]) + cpu.IX = cpu.readU16(nn) +} + +func opLDIYnnP(cpu *CPU, codes []uint8) { + nn := toU16(codes[2], codes[3]) + cpu.IY = cpu.readU16(nn) +} + +func opLDnnPHL(cpu *CPU, codes []uint8) { + nn := toU16(codes[1], codes[2]) + cpu.writeU16(nn, cpu.HL.U16()) +} + +func opLDnnPdd(cpu *CPU, codes []uint8) { + dd := cpu.reg16dd(codes[1] >> 4) + nn := toU16(codes[2], codes[3]) + cpu.writeU16(nn, dd.U16()) +} + +func opLDnnPIX(cpu *CPU, codes []uint8) { + nn := toU16(codes[2], codes[3]) + cpu.writeU16(nn, cpu.IX) +} + +func opLDnnPIY(cpu *CPU, codes []uint8) { + nn := toU16(codes[2], codes[3]) + cpu.writeU16(nn, cpu.IY) +} + +func opLDSPHL(cpu *CPU, codes []uint8) { + cpu.SP = cpu.HL.U16() +} + +func opLDSPIX(cpu *CPU, codes []uint8) { + cpu.SP = cpu.IX +} + +func opLDSPIY(cpu *CPU, codes []uint8) { + cpu.SP = cpu.IY +} + +func opPUSHqq(cpu *CPU, codes []uint8) { + qq := cpu.reg16qq(codes[0] >> 4) + cpu.SP -= 2 + cpu.writeU16(cpu.SP, qq.U16()) +} + +func opPUSHIX(cpu *CPU, codes []uint8) { + cpu.SP -= 2 + cpu.writeU16(cpu.SP, cpu.IX) +} + +func opPUSHIY(cpu *CPU, codes []uint8) { + cpu.SP -= 2 + cpu.writeU16(cpu.SP, cpu.IY) +} + +func opPOPqq(cpu *CPU, codes []uint8) { + qq := cpu.reg16qq(codes[0] >> 4) + qq.SetU16(cpu.readU16(cpu.SP)) + cpu.SP += 2 +} + +func opPOPIX(cpu *CPU, codes []uint8) { + cpu.IX = cpu.readU16(cpu.SP) + cpu.SP += 2 +} + +func opPOPIY(cpu *CPU, codes []uint8) { + cpu.IY = cpu.readU16(cpu.SP) + cpu.SP += 2 +} diff --git a/op_load8.go b/op_load8.go index af18590..c45dca2 100644 --- a/op_load8.go +++ b/op_load8.go @@ -8,9 +8,7 @@ var load8 = []*OPCode{ {0x40, 0x3f, vReg88}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - *cpu.regP(codes[0] >> 3) = *cpu.regP(codes[0]) - }, + F: opLDr1r2, }, { @@ -20,10 +18,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[0] >> 3) - *r = codes[1] - }, + F: opLDrn, }, { @@ -32,10 +27,7 @@ var load8 = []*OPCode{ {0x46, 0x38, vReg8_3}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[0] >> 3) - *r = cpu.Memory.Get(cpu.HL.U16()) - }, + F: opLDrHLP, }, { @@ -46,11 +38,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1] >> 3) - p := addrOff(cpu.IX, codes[2]) - *r = cpu.Memory.Get(p) - }, + F: opLDrIXdP, }, { @@ -61,11 +49,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1] >> 3) - p := addrOff(cpu.IY, codes[2]) - *r = cpu.Memory.Get(p) - }, + F: opLDrIYdP, }, { @@ -74,10 +58,7 @@ var load8 = []*OPCode{ {0x70, 0x07, vReg8}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[0]) - cpu.Memory.Set(cpu.HL.U16(), *r) - }, + F: opLDHLPr, }, { @@ -88,11 +69,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - p := addrOff(cpu.IX, codes[2]) - cpu.Memory.Set(p, *r) - }, + F: opLDIXdPr, }, { @@ -103,11 +80,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - p := addrOff(cpu.IY, codes[2]) - cpu.Memory.Set(p, *r) - }, + F: opLDIYdPr, }, { @@ -117,10 +90,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.Memory.Set(p, codes[1]) - }, + F: opLDHLPn, }, { @@ -132,10 +102,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - cpu.Memory.Set(p, codes[3]) - }, + F: opLDIXdPn, }, { @@ -147,10 +114,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 4, 3, 5, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - cpu.Memory.Set(p, codes[3]) - }, + F: opLDIYdPn, }, { @@ -159,10 +123,7 @@ var load8 = []*OPCode{ {0x0a, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.BC.U16() - cpu.AF.Hi = cpu.Memory.Get(p) - }, + F: opLDABCP, }, { @@ -171,10 +132,7 @@ var load8 = []*OPCode{ {0x1a, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.DE.U16() - cpu.AF.Hi = cpu.Memory.Get(p) - }, + F: opLDADEP, }, { @@ -185,10 +143,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - p := toU16(codes[1], codes[2]) - cpu.AF.Hi = cpu.Memory.Get(p) - }, + F: opLDAnnP, }, { @@ -197,10 +152,7 @@ var load8 = []*OPCode{ {0x02, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.BC.U16() - cpu.Memory.Set(p, cpu.AF.Hi) - }, + F: opLDBCPA, }, { @@ -209,10 +161,7 @@ var load8 = []*OPCode{ {0x12, 0x00, nil}, }, T: []int{4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.DE.U16() - cpu.Memory.Set(p, cpu.AF.Hi) - }, + F: opLDDEPA, }, { @@ -223,10 +172,7 @@ var load8 = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3, 3, 3}, - F: func(cpu *CPU, codes []uint8) { - p := toU16(codes[1], codes[2]) - cpu.Memory.Set(p, cpu.AF.Hi) - }, + F: opLDnnPA, }, { @@ -236,27 +182,7 @@ var load8 = []*OPCode{ {0x57, 0x00, nil}, }, T: []int{4, 5}, - F: func(cpu *CPU, codes []uint8) { - d := cpu.IR.Hi - cpu.AF.Hi = d - // update F by d - // - S is set if the I Register is negative; otherwise, it is - // reset. - // - Z is set if the I Register is 0; otherwise, it is reset. - // - H is reset. - // - P/V contains contents of IFF2. - // - N is reset. - // - C is not affected. - // - If an interrupt occurs during execution of this instruction, - // the Parity flag contains a 0. - cpu.flagUpdate(FlagOp{}. - Put(S, d&0x80 != 0). - Put(Z, d == 0). - Reset(H). - Put(PV, cpu.IFF2). - Reset(N). - Keep(C)) - }, + F: opLDAI, }, { @@ -266,26 +192,7 @@ var load8 = []*OPCode{ {0x5f, 0x00, nil}, }, T: []int{4, 5}, - F: func(cpu *CPU, codes []uint8) { - d := cpu.IR.Lo - cpu.AF.Hi = d - // update F by d - // - S is set if, R-Register is negative; otherwise, it is reset. - // - Z is set if the R Register is 0; otherwise, it is reset. - // - H is reset. - // - P/V contains contents of IFF2. - // - N is reset. - // - C is not affected. - // - If an interrupt occurs during execution of this instruction, - // the parity flag contains a 0. - cpu.flagUpdate(FlagOp{}. - Put(S, d&0x80 != 0). - Put(Z, d == 0). - Reset(H). - Put(PV, cpu.IFF2). - Reset(N). - Keep(C)) - }, + F: opLDAR, }, { @@ -295,9 +202,7 @@ var load8 = []*OPCode{ {0x47, 0x00, nil}, }, T: []int{4, 5}, - F: func(cpu *CPU, codes []uint8) { - cpu.IR.Hi = cpu.AF.Hi - }, + F: opLDIA, }, { @@ -307,8 +212,145 @@ var load8 = []*OPCode{ {0x4f, 0x00, nil}, }, T: []int{4, 5}, - F: func(cpu *CPU, codes []uint8) { - cpu.IR.Lo = cpu.AF.Hi - }, + F: opLDRA, }, } + +func opLDr1r2(cpu *CPU, codes []uint8) { + *cpu.regP(codes[0] >> 3) = *cpu.regP(codes[0]) +} + +func opLDrn(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[0] >> 3) + *r = codes[1] +} + +func opLDrHLP(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[0] >> 3) + *r = cpu.Memory.Get(cpu.HL.U16()) +} + +func opLDrIXdP(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1] >> 3) + p := addrOff(cpu.IX, codes[2]) + *r = cpu.Memory.Get(p) +} + +func opLDrIYdP(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1] >> 3) + p := addrOff(cpu.IY, codes[2]) + *r = cpu.Memory.Get(p) +} + +func opLDHLPr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[0]) + cpu.Memory.Set(cpu.HL.U16(), *r) +} + +func opLDIXdPr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + p := addrOff(cpu.IX, codes[2]) + cpu.Memory.Set(p, *r) +} + +func opLDIYdPr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + p := addrOff(cpu.IY, codes[2]) + cpu.Memory.Set(p, *r) +} + +func opLDHLPn(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.Memory.Set(p, codes[1]) +} + +func opLDIXdPn(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + cpu.Memory.Set(p, codes[3]) +} + +func opLDIYdPn(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + cpu.Memory.Set(p, codes[3]) +} + +func opLDABCP(cpu *CPU, codes []uint8) { + p := cpu.BC.U16() + cpu.AF.Hi = cpu.Memory.Get(p) +} + +func opLDADEP(cpu *CPU, codes []uint8) { + p := cpu.DE.U16() + cpu.AF.Hi = cpu.Memory.Get(p) +} + +func opLDAnnP(cpu *CPU, codes []uint8) { + p := toU16(codes[1], codes[2]) + cpu.AF.Hi = cpu.Memory.Get(p) +} + +func opLDBCPA(cpu *CPU, codes []uint8) { + p := cpu.BC.U16() + cpu.Memory.Set(p, cpu.AF.Hi) +} + +func opLDDEPA(cpu *CPU, codes []uint8) { + p := cpu.DE.U16() + cpu.Memory.Set(p, cpu.AF.Hi) +} + +func opLDnnPA(cpu *CPU, codes []uint8) { + p := toU16(codes[1], codes[2]) + cpu.Memory.Set(p, cpu.AF.Hi) +} + +func opLDAI(cpu *CPU, codes []uint8) { + d := cpu.IR.Hi + cpu.AF.Hi = d + // update F by d + // - S is set if the I Register is negative; otherwise, it is + // reset. + // - Z is set if the I Register is 0; otherwise, it is reset. + // - H is reset. + // - P/V contains contents of IFF2. + // - N is reset. + // - C is not affected. + // - If an interrupt occurs during execution of this instruction, + // the Parity flag contains a 0. + cpu.flagUpdate(FlagOp{}. + Put(S, d&0x80 != 0). + Put(Z, d == 0). + Reset(H). + Put(PV, cpu.IFF2). + Reset(N). + Keep(C)) +} + +func opLDAR(cpu *CPU, codes []uint8) { + d := cpu.IR.Lo + cpu.AF.Hi = d + // update F by d + // - S is set if, R-Register is negative; otherwise, it is reset. + // - Z is set if the R Register is 0; otherwise, it is reset. + // - H is reset. + // - P/V contains contents of IFF2. + // - N is reset. + // - C is not affected. + // - If an interrupt occurs during execution of this instruction, + // the parity flag contains a 0. + cpu.flagUpdate(FlagOp{}. + Put(S, d&0x80 != 0). + Put(Z, d == 0). + Reset(H). + Put(PV, cpu.IFF2). + Reset(N). + Keep(C)) +} + +func opLDIA(cpu *CPU, codes []uint8) { + cpu.IR.Hi = cpu.AF.Hi +} + +func opLDRA(cpu *CPU, codes []uint8) { + cpu.IR.Lo = cpu.AF.Hi +} diff --git a/op_rotateshift.go b/op_rotateshift.go index 197cde3..70f309f 100644 --- a/op_rotateshift.go +++ b/op_rotateshift.go @@ -10,15 +10,7 @@ var rotateshift = []*OPCode{ {0x07, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - a2 := a<<1 | a>>7 - cpu.AF.Hi = a2 - cpu.flagUpdate(FlagOp{}. - Reset(H). - Reset(N). - Put(C, a&0x80 != 0)) - }, + F: opRLCA, }, { @@ -27,18 +19,7 @@ var rotateshift = []*OPCode{ {0x17, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - a2 := a << 1 - if cpu.flag(C) { - a2 |= 0x01 - } - cpu.AF.Hi = a2 - cpu.flagUpdate(FlagOp{}. - Reset(H). - Reset(N). - Put(C, a&0x80 != 0)) - }, + F: opRLA, }, { @@ -47,15 +28,7 @@ var rotateshift = []*OPCode{ {0x0f, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - a2 := a>>1 | a<<7 - cpu.AF.Hi = a2 - cpu.flagUpdate(FlagOp{}. - Reset(H). - Reset(N). - Put(C, a&0x01 != 0)) - }, + F: opRRCA, }, { @@ -64,18 +37,7 @@ var rotateshift = []*OPCode{ {0x1f, 0x00, nil}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - a2 := a >> 1 - if cpu.flag(C) { - a2 |= 0x80 - } - cpu.AF.Hi = a2 - cpu.flagUpdate(FlagOp{}. - Reset(H). - Reset(N). - Put(C, a&0x01 != 0)) - }, + F: opRRA, }, { @@ -85,10 +47,7 @@ var rotateshift = []*OPCode{ {0x00, 0x07, vReg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - *r = cpu.rlcU8(*r) - }, + F: opRLCr, }, { @@ -98,10 +57,7 @@ var rotateshift = []*OPCode{ {0x06, 0x00, nil}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.Memory.Set(p, cpu.rlcU8(cpu.Memory.Get(p))) - }, + F: opRLCHLP, }, { @@ -113,10 +69,7 @@ var rotateshift = []*OPCode{ {0x06, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - cpu.Memory.Set(p, cpu.rlcU8(cpu.Memory.Get(p))) - }, + F: opRLCIXdP, }, { @@ -128,10 +81,7 @@ var rotateshift = []*OPCode{ {0x06, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - cpu.Memory.Set(p, cpu.rlcU8(cpu.Memory.Get(p))) - }, + F: opRLCIYdP, }, { @@ -141,10 +91,7 @@ var rotateshift = []*OPCode{ {0x10, 0x07, vReg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - *r = cpu.rlU8(*r) - }, + F: opRLr, }, { @@ -154,10 +101,7 @@ var rotateshift = []*OPCode{ {0x16, 0x00, nil}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.Memory.Set(p, cpu.rlU8(cpu.Memory.Get(p))) - }, + F: opRLHLP, }, { @@ -169,10 +113,7 @@ var rotateshift = []*OPCode{ {0x16, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - cpu.Memory.Set(p, cpu.rlU8(cpu.Memory.Get(p))) - }, + F: opRLIXdP, }, { @@ -184,10 +125,7 @@ var rotateshift = []*OPCode{ {0x16, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - cpu.Memory.Set(p, cpu.rlU8(cpu.Memory.Get(p))) - }, + F: opRLIYdP, }, { @@ -197,10 +135,7 @@ var rotateshift = []*OPCode{ {0x08, 0x07, vReg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - *r = cpu.rrcU8(*r) - }, + F: opRRCr, }, { @@ -210,10 +145,7 @@ var rotateshift = []*OPCode{ {0x0e, 0x00, nil}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.Memory.Set(p, cpu.rrcU8(cpu.Memory.Get(p))) - }, + F: opRRCHLP, }, { @@ -225,10 +157,7 @@ var rotateshift = []*OPCode{ {0x0e, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - cpu.Memory.Set(p, cpu.rrcU8(cpu.Memory.Get(p))) - }, + F: opRRCIXdP, }, { @@ -240,10 +169,7 @@ var rotateshift = []*OPCode{ {0x0e, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - cpu.Memory.Set(p, cpu.rrcU8(cpu.Memory.Get(p))) - }, + F: opRRCIYdP, }, { @@ -253,10 +179,7 @@ var rotateshift = []*OPCode{ {0x18, 0x07, vReg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - *r = cpu.rrU8(*r) - }, + F: opRRr, }, { @@ -266,10 +189,7 @@ var rotateshift = []*OPCode{ {0x1e, 0x00, nil}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.Memory.Set(p, cpu.rrU8(cpu.Memory.Get(p))) - }, + F: opRRHLP, }, { @@ -281,10 +201,7 @@ var rotateshift = []*OPCode{ {0x1e, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - cpu.Memory.Set(p, cpu.rrU8(cpu.Memory.Get(p))) - }, + F: opRRIXdP, }, { @@ -296,10 +213,7 @@ var rotateshift = []*OPCode{ {0x1e, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - cpu.Memory.Set(p, cpu.rrU8(cpu.Memory.Get(p))) - }, + F: opRRIYdP, }, { @@ -309,10 +223,7 @@ var rotateshift = []*OPCode{ {0x20, 0x07, vReg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - *r = cpu.slaU8(*r) - }, + F: opSLAr, }, { @@ -322,10 +233,7 @@ var rotateshift = []*OPCode{ {0x26, 0x00, nil}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.Memory.Set(p, cpu.slaU8(cpu.Memory.Get(p))) - }, + F: opSLAHLP, }, { @@ -337,10 +245,7 @@ var rotateshift = []*OPCode{ {0x26, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - cpu.Memory.Set(p, cpu.slaU8(cpu.Memory.Get(p))) - }, + F: opSLAIXdP, }, { @@ -352,10 +257,7 @@ var rotateshift = []*OPCode{ {0x26, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - cpu.Memory.Set(p, cpu.slaU8(cpu.Memory.Get(p))) - }, + F: opSLAIYdP, }, { @@ -365,10 +267,7 @@ var rotateshift = []*OPCode{ {0x28, 0x07, vReg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - *r = cpu.sraU8(*r) - }, + F: opSRAr, }, { @@ -378,10 +277,7 @@ var rotateshift = []*OPCode{ {0x2e, 0x00, nil}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.Memory.Set(p, cpu.sraU8(cpu.Memory.Get(p))) - }, + F: opSRAHLP, }, { @@ -393,10 +289,7 @@ var rotateshift = []*OPCode{ {0x2e, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - cpu.Memory.Set(p, cpu.sraU8(cpu.Memory.Get(p))) - }, + F: opSRAIXdP, }, { @@ -408,10 +301,7 @@ var rotateshift = []*OPCode{ {0x2e, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - cpu.Memory.Set(p, cpu.sraU8(cpu.Memory.Get(p))) - }, + F: opSRAIYdP, }, { @@ -421,10 +311,7 @@ var rotateshift = []*OPCode{ {0x38, 0x07, vReg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - *r = cpu.srlU8(*r) - }, + F: opSRLr, }, { @@ -434,10 +321,7 @@ var rotateshift = []*OPCode{ {0x3e, 0x00, nil}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.Memory.Set(p, cpu.srlU8(cpu.Memory.Get(p))) - }, + F: opSRLHLP, }, { @@ -449,10 +333,7 @@ var rotateshift = []*OPCode{ {0x3e, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - cpu.Memory.Set(p, cpu.srlU8(cpu.Memory.Get(p))) - }, + F: opSRLIXdP, }, { @@ -464,10 +345,7 @@ var rotateshift = []*OPCode{ {0x3e, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - cpu.Memory.Set(p, cpu.srlU8(cpu.Memory.Get(p))) - }, + F: opSRLIYdP, }, { @@ -477,21 +355,7 @@ var rotateshift = []*OPCode{ {0x6f, 0x00, nil}, }, T: []int{4, 4, 3, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - a := cpu.AF.Hi - b := cpu.Memory.Get(p) - a2 := a&0xf0 | b>>4 - b2 := b<<4 | a&0x0f - cpu.Memory.Set(p, b2) - cpu.AF.Hi = a2 - cpu.flagUpdate(FlagOp{}. - Put(S, a2&0x80 != 0). - Put(Z, a2 == 0). - Reset(H). - Put(PV, bits.OnesCount8(a2)%2 == 0). - Reset(N)) - }, + F: opRLD, }, { @@ -501,20 +365,224 @@ var rotateshift = []*OPCode{ {0x67, 0x00, nil}, }, T: []int{4, 4, 3, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - a := cpu.AF.Hi - b := cpu.Memory.Get(p) - a2 := a&0xf0 | b&0x0f - b2 := a<<4 | b>>4 - cpu.Memory.Set(p, b2) - cpu.AF.Hi = a2 - cpu.flagUpdate(FlagOp{}. - Put(S, a2&0x80 != 0). - Put(Z, a2 == 0). - Reset(H). - Put(PV, bits.OnesCount8(a2)%2 == 0). - Reset(N)) - }, + F: opRRD, }, } + +func opRLCA(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + a2 := a<<1 | a>>7 + cpu.AF.Hi = a2 + cpu.flagUpdate(FlagOp{}. + Reset(H). + Reset(N). + Put(C, a&0x80 != 0)) +} + +func opRLA(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + a2 := a << 1 + if cpu.flag(C) { + a2 |= 0x01 + } + cpu.AF.Hi = a2 + cpu.flagUpdate(FlagOp{}. + Reset(H). + Reset(N). + Put(C, a&0x80 != 0)) +} + +func opRRCA(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + a2 := a>>1 | a<<7 + cpu.AF.Hi = a2 + cpu.flagUpdate(FlagOp{}. + Reset(H). + Reset(N). + Put(C, a&0x01 != 0)) +} + +func opRRA(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + a2 := a >> 1 + if cpu.flag(C) { + a2 |= 0x80 + } + cpu.AF.Hi = a2 + cpu.flagUpdate(FlagOp{}. + Reset(H). + Reset(N). + Put(C, a&0x01 != 0)) +} + +func opRLCr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + *r = cpu.rlcU8(*r) +} + +func opRLCHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.Memory.Set(p, cpu.rlcU8(cpu.Memory.Get(p))) +} + +func opRLCIXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + cpu.Memory.Set(p, cpu.rlcU8(cpu.Memory.Get(p))) +} + +func opRLCIYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + cpu.Memory.Set(p, cpu.rlcU8(cpu.Memory.Get(p))) +} + +func opRLr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + *r = cpu.rlU8(*r) +} + +func opRLHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.Memory.Set(p, cpu.rlU8(cpu.Memory.Get(p))) +} + +func opRLIXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + cpu.Memory.Set(p, cpu.rlU8(cpu.Memory.Get(p))) +} + +func opRLIYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + cpu.Memory.Set(p, cpu.rlU8(cpu.Memory.Get(p))) +} + +func opRRCr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + *r = cpu.rrcU8(*r) +} + +func opRRCHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.Memory.Set(p, cpu.rrcU8(cpu.Memory.Get(p))) +} + +func opRRCIXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + cpu.Memory.Set(p, cpu.rrcU8(cpu.Memory.Get(p))) +} + +func opRRCIYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + cpu.Memory.Set(p, cpu.rrcU8(cpu.Memory.Get(p))) +} + +func opRRr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + *r = cpu.rrU8(*r) +} + +func opRRHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.Memory.Set(p, cpu.rrU8(cpu.Memory.Get(p))) +} + +func opRRIXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + cpu.Memory.Set(p, cpu.rrU8(cpu.Memory.Get(p))) +} + +func opRRIYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + cpu.Memory.Set(p, cpu.rrU8(cpu.Memory.Get(p))) +} + +func opSLAr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + *r = cpu.slaU8(*r) +} + +func opSLAHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.Memory.Set(p, cpu.slaU8(cpu.Memory.Get(p))) +} + +func opSLAIXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + cpu.Memory.Set(p, cpu.slaU8(cpu.Memory.Get(p))) +} + +func opSLAIYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + cpu.Memory.Set(p, cpu.slaU8(cpu.Memory.Get(p))) +} + +func opSRAr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + *r = cpu.sraU8(*r) +} + +func opSRAHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.Memory.Set(p, cpu.sraU8(cpu.Memory.Get(p))) +} + +func opSRAIXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + cpu.Memory.Set(p, cpu.sraU8(cpu.Memory.Get(p))) +} + +func opSRAIYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + cpu.Memory.Set(p, cpu.sraU8(cpu.Memory.Get(p))) +} + +func opSRLr(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + *r = cpu.srlU8(*r) +} + +func opSRLHLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.Memory.Set(p, cpu.srlU8(cpu.Memory.Get(p))) +} + +func opSRLIXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + cpu.Memory.Set(p, cpu.srlU8(cpu.Memory.Get(p))) +} + +func opSRLIYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + cpu.Memory.Set(p, cpu.srlU8(cpu.Memory.Get(p))) +} + +func opRLD(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + a := cpu.AF.Hi + b := cpu.Memory.Get(p) + a2 := a&0xf0 | b>>4 + b2 := b<<4 | a&0x0f + cpu.Memory.Set(p, b2) + cpu.AF.Hi = a2 + cpu.flagUpdate(FlagOp{}. + Put(S, a2&0x80 != 0). + Put(Z, a2 == 0). + Reset(H). + Put(PV, bits.OnesCount8(a2)%2 == 0). + Reset(N)) +} + +func opRRD(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + a := cpu.AF.Hi + b := cpu.Memory.Get(p) + a2 := a&0xf0 | b&0x0f + b2 := a<<4 | b>>4 + cpu.Memory.Set(p, b2) + cpu.AF.Hi = a2 + cpu.flagUpdate(FlagOp{}. + Put(S, a2&0x80 != 0). + Put(Z, a2 == 0). + Reset(H). + Put(PV, bits.OnesCount8(a2)%2 == 0). + Reset(N)) +} diff --git a/op_undoc.go b/op_undoc.go index 1a3b000..8db0e58 100644 --- a/op_undoc.go +++ b/op_undoc.go @@ -94,10 +94,7 @@ var undoc = []*OPCode{ {0x24, 0x00, nil}, }, T: []int{4, 6}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := cpu.incU8(uint8(cpu.IX >> 8)) - cpu.IX = uint16(v)<<8 | cpu.IX&0xff - }, + F: opINCIXH, }, { @@ -107,10 +104,7 @@ var undoc = []*OPCode{ {0x25, 0x00, nil}, }, T: []int{4, 6}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := cpu.decU8(uint8(cpu.IX >> 8)) - cpu.IX = uint16(v)<<8 | cpu.IX&0xff - }, + F: opDECIXH, }, { @@ -120,10 +114,7 @@ var undoc = []*OPCode{ {0x2c, 0x00, nil}, }, T: []int{4, 6}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := cpu.incU8(uint8(cpu.IX)) - cpu.IX = uint16(v) | cpu.IX&0xff00 - }, + F: opINCIXL, }, { @@ -133,10 +124,7 @@ var undoc = []*OPCode{ {0x2d, 0x00, nil}, }, T: []int{4, 6}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := cpu.decU8(uint8(cpu.IX)) - cpu.IX = uint16(v) | cpu.IX&0xff00 - }, + F: opDECIXL, }, { @@ -146,10 +134,7 @@ var undoc = []*OPCode{ {0x24, 0x00, nil}, }, T: []int{4, 6}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := cpu.incU8(uint8(cpu.IY >> 8)) - cpu.IY = uint16(v)<<8 | cpu.IY&0xff - }, + F: opINCIYH, }, { @@ -159,10 +144,7 @@ var undoc = []*OPCode{ {0x25, 0x00, nil}, }, T: []int{4, 6}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := cpu.decU8(uint8(cpu.IY >> 8)) - cpu.IY = uint16(v)<<8 | cpu.IY&0xff - }, + F: opDECIYH, }, { @@ -172,10 +154,7 @@ var undoc = []*OPCode{ {0x2c, 0x00, nil}, }, T: []int{4, 6}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := cpu.incU8(uint8(cpu.IY)) - cpu.IY = uint16(v) | cpu.IY&0xff00 - }, + F: opINCIYL, }, { @@ -185,10 +164,7 @@ var undoc = []*OPCode{ {0x2d, 0x00, nil}, }, T: []int{4, 6}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := cpu.decU8(uint8(cpu.IY)) - cpu.IY = uint16(v) | cpu.IY&0xff00 - }, + F: opDECIYL, }, { @@ -199,10 +175,7 @@ var undoc = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := codes[2] - cpu.IX = uint16(v)<<8 | cpu.IX&0xff - }, + F: opLDIXHn, }, { @@ -213,10 +186,7 @@ var undoc = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := codes[2] - cpu.IX = uint16(v) | cpu.IX&0xff00 - }, + F: opLDIXLn, }, { @@ -227,10 +197,7 @@ var undoc = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := codes[2] - cpu.IY = uint16(v)<<8 | cpu.IY&0xff - }, + F: opLDIYHn, }, { @@ -241,10 +208,7 @@ var undoc = []*OPCode{ {0x00, 0xff, nil}, }, T: []int{4, 3}, // not verified - F: func(cpu *CPU, codes []uint8) { - v := codes[2] - cpu.IY = uint16(v) | cpu.IY&0xff00 - }, + F: opLDIYLn, }, { @@ -256,11 +220,7 @@ var undoc = []*OPCode{ {0x36, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, // not verified - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IX, codes[2]) - v := cpu.sl1U8(cpu.Memory.Get(p)) - cpu.Memory.Set(p, v) - }, + F: opSL1IXdP, }, { @@ -272,11 +232,7 @@ var undoc = []*OPCode{ {0x36, 0x00, nil}, }, T: []int{4, 4, 3, 5, 4, 3}, // not verified - F: func(cpu *CPU, codes []uint8) { - p := addrOff(cpu.IY, codes[2]) - v := cpu.sl1U8(cpu.Memory.Get(p)) - cpu.Memory.Set(p, v) - }, + F: opSL1IYdP, }, { @@ -286,10 +242,7 @@ var undoc = []*OPCode{ {0x30, 0x07, vReg8}, }, T: []int{4, 4}, - F: func(cpu *CPU, codes []uint8) { - r := cpu.regP(codes[1]) - *r = cpu.sl1U8(*r) - }, + F: opSL1r, }, { @@ -299,10 +252,7 @@ var undoc = []*OPCode{ {0x36, 0x00, nil}, }, T: []int{4, 4, 4, 3}, - F: func(cpu *CPU, codes []uint8) { - p := cpu.HL.U16() - cpu.Memory.Set(p, cpu.sl1U8(cpu.Memory.Get(p))) - }, + F: opSL1HLP, }, { @@ -312,10 +262,7 @@ var undoc = []*OPCode{ {0x40, 0x3f, vReg88}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - v := cpu.getRX(codes[1]) - cpu.setRX(codes[1]>>3, v) - }, + F: opLDrx1rx2, }, { @@ -325,10 +272,7 @@ var undoc = []*OPCode{ {0x40, 0x3f, vReg88}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - v := cpu.getRY(codes[1]) - cpu.setRY(codes[1]>>3, v) - }, + F: opLDry1ry2, }, { @@ -338,11 +282,7 @@ var undoc = []*OPCode{ {0x80, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.getRX(codes[1]) - cpu.AF.Hi = cpu.addU8(a, x) - }, + F: opADDArx, }, { @@ -352,11 +292,7 @@ var undoc = []*OPCode{ {0x80, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - y := cpu.getRY(codes[1]) - cpu.AF.Hi = cpu.addU8(a, y) - }, + F: opADDAry, }, { @@ -366,11 +302,7 @@ var undoc = []*OPCode{ {0x88, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.getRX(codes[1]) - cpu.AF.Hi = cpu.adcU8(a, x) - }, + F: opADCArx, }, { @@ -380,11 +312,7 @@ var undoc = []*OPCode{ {0x88, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - y := cpu.getRY(codes[1]) - cpu.AF.Hi = cpu.adcU8(a, y) - }, + F: opADCAry, }, { @@ -394,11 +322,7 @@ var undoc = []*OPCode{ {0x90, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.getRX(codes[1]) - cpu.AF.Hi = cpu.subU8(a, x) - }, + F: opSUBArx, }, { @@ -408,11 +332,7 @@ var undoc = []*OPCode{ {0x90, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - y := cpu.getRY(codes[1]) - cpu.AF.Hi = cpu.subU8(a, y) - }, + F: opSUBAry, }, { @@ -422,11 +342,7 @@ var undoc = []*OPCode{ {0x98, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.getRX(codes[1]) - cpu.AF.Hi = cpu.sbcU8(a, x) - }, + F: opSBCArx, }, { @@ -436,11 +352,7 @@ var undoc = []*OPCode{ {0x98, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - y := cpu.getRY(codes[1]) - cpu.AF.Hi = cpu.sbcU8(a, y) - }, + F: opSBCAry, }, { @@ -450,11 +362,7 @@ var undoc = []*OPCode{ {0xa0, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.getRX(codes[1]) - cpu.AF.Hi = cpu.andU8(a, x) - }, + F: opANDrx, }, { @@ -464,11 +372,7 @@ var undoc = []*OPCode{ {0xa0, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - y := cpu.getRY(codes[1]) - cpu.AF.Hi = cpu.andU8(a, y) - }, + F: opANDry, }, { @@ -478,11 +382,7 @@ var undoc = []*OPCode{ {0xa8, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.getRX(codes[1]) - cpu.AF.Hi = cpu.xorU8(a, x) - }, + F: opXORrx, }, { @@ -492,11 +392,7 @@ var undoc = []*OPCode{ {0xa8, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - y := cpu.getRY(codes[1]) - cpu.AF.Hi = cpu.xorU8(a, y) - }, + F: opXORry, }, { @@ -506,11 +402,7 @@ var undoc = []*OPCode{ {0xb0, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.getRX(codes[1]) - cpu.AF.Hi = cpu.orU8(a, x) - }, + F: opORrx, }, { @@ -520,11 +412,7 @@ var undoc = []*OPCode{ {0xb0, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - y := cpu.getRY(codes[1]) - cpu.AF.Hi = cpu.orU8(a, y) - }, + F: opORry, }, { @@ -534,11 +422,7 @@ var undoc = []*OPCode{ {0xb8, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - x := cpu.getRX(codes[1]) - cpu.subU8(a, x) - }, + F: opCPrx, }, { @@ -548,10 +432,194 @@ var undoc = []*OPCode{ {0xb8, 0x07, vReg8}, }, T: []int{4}, - F: func(cpu *CPU, codes []uint8) { - a := cpu.AF.Hi - y := cpu.getRY(codes[1]) - cpu.subU8(a, y) - }, + F: opCPry, }, } + +func opINCIXH(cpu *CPU, codes []uint8) { + v := cpu.incU8(uint8(cpu.IX >> 8)) + cpu.IX = uint16(v)<<8 | cpu.IX&0xff +} + +func opDECIXH(cpu *CPU, codes []uint8) { + v := cpu.decU8(uint8(cpu.IX >> 8)) + cpu.IX = uint16(v)<<8 | cpu.IX&0xff +} + +func opINCIXL(cpu *CPU, codes []uint8) { + v := cpu.incU8(uint8(cpu.IX)) + cpu.IX = uint16(v) | cpu.IX&0xff00 +} + +func opDECIXL(cpu *CPU, codes []uint8) { + v := cpu.decU8(uint8(cpu.IX)) + cpu.IX = uint16(v) | cpu.IX&0xff00 +} + +func opINCIYH(cpu *CPU, codes []uint8) { + v := cpu.incU8(uint8(cpu.IY >> 8)) + cpu.IY = uint16(v)<<8 | cpu.IY&0xff +} + +func opDECIYH(cpu *CPU, codes []uint8) { + v := cpu.decU8(uint8(cpu.IY >> 8)) + cpu.IY = uint16(v)<<8 | cpu.IY&0xff +} + +func opINCIYL(cpu *CPU, codes []uint8) { + v := cpu.incU8(uint8(cpu.IY)) + cpu.IY = uint16(v) | cpu.IY&0xff00 +} + +func opDECIYL(cpu *CPU, codes []uint8) { + v := cpu.decU8(uint8(cpu.IY)) + cpu.IY = uint16(v) | cpu.IY&0xff00 +} + +func opLDIXHn(cpu *CPU, codes []uint8) { + v := codes[2] + cpu.IX = uint16(v)<<8 | cpu.IX&0xff +} + +func opLDIXLn(cpu *CPU, codes []uint8) { + v := codes[2] + cpu.IX = uint16(v) | cpu.IX&0xff00 +} + +func opLDIYHn(cpu *CPU, codes []uint8) { + v := codes[2] + cpu.IY = uint16(v)<<8 | cpu.IY&0xff +} + +func opLDIYLn(cpu *CPU, codes []uint8) { + v := codes[2] + cpu.IY = uint16(v) | cpu.IY&0xff00 +} + +func opSL1IXdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IX, codes[2]) + v := cpu.sl1U8(cpu.Memory.Get(p)) + cpu.Memory.Set(p, v) +} + +func opSL1IYdP(cpu *CPU, codes []uint8) { + p := addrOff(cpu.IY, codes[2]) + v := cpu.sl1U8(cpu.Memory.Get(p)) + cpu.Memory.Set(p, v) +} + +func opSL1r(cpu *CPU, codes []uint8) { + r := cpu.regP(codes[1]) + *r = cpu.sl1U8(*r) +} + +func opSL1HLP(cpu *CPU, codes []uint8) { + p := cpu.HL.U16() + cpu.Memory.Set(p, cpu.sl1U8(cpu.Memory.Get(p))) +} + +func opLDrx1rx2(cpu *CPU, codes []uint8) { + v := cpu.getRX(codes[1]) + cpu.setRX(codes[1]>>3, v) +} + +func opLDry1ry2(cpu *CPU, codes []uint8) { + v := cpu.getRY(codes[1]) + cpu.setRY(codes[1]>>3, v) +} + +func opADDArx(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.getRX(codes[1]) + cpu.AF.Hi = cpu.addU8(a, x) +} + +func opADDAry(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + y := cpu.getRY(codes[1]) + cpu.AF.Hi = cpu.addU8(a, y) +} + +func opADCArx(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.getRX(codes[1]) + cpu.AF.Hi = cpu.adcU8(a, x) +} + +func opADCAry(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + y := cpu.getRY(codes[1]) + cpu.AF.Hi = cpu.adcU8(a, y) +} + +func opSUBArx(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.getRX(codes[1]) + cpu.AF.Hi = cpu.subU8(a, x) +} + +func opSUBAry(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + y := cpu.getRY(codes[1]) + cpu.AF.Hi = cpu.subU8(a, y) +} + +func opSBCArx(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.getRX(codes[1]) + cpu.AF.Hi = cpu.sbcU8(a, x) +} + +func opSBCAry(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + y := cpu.getRY(codes[1]) + cpu.AF.Hi = cpu.sbcU8(a, y) +} + +func opANDrx(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.getRX(codes[1]) + cpu.AF.Hi = cpu.andU8(a, x) +} + +func opANDry(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + y := cpu.getRY(codes[1]) + cpu.AF.Hi = cpu.andU8(a, y) +} + +func opXORrx(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.getRX(codes[1]) + cpu.AF.Hi = cpu.xorU8(a, x) +} + +func opXORry(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + y := cpu.getRY(codes[1]) + cpu.AF.Hi = cpu.xorU8(a, y) +} + +func opORrx(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.getRX(codes[1]) + cpu.AF.Hi = cpu.orU8(a, x) +} + +func opORry(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + y := cpu.getRY(codes[1]) + cpu.AF.Hi = cpu.orU8(a, y) +} + +func opCPrx(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + x := cpu.getRX(codes[1]) + cpu.subU8(a, x) +} + +func opCPry(cpu *CPU, codes []uint8) { + a := cpu.AF.Hi + y := cpu.getRY(codes[1]) + cpu.subU8(a, y) +} diff --git a/step.go b/step.go new file mode 100644 index 0000000..2730033 --- /dev/null +++ b/step.go @@ -0,0 +1,46 @@ +package z80 + +import "fmt" + +func (cpu *CPU) step(f fetcher, enableInt bool) error { + afterEI := false + if !cpu.HALT { + // increment refresh counter + rr := cpu.IR.Lo + cpu.IR.Lo = rr&0x80 | (rr+1)&0x7f + // decode and execute with big switch + cpu.decodeBuf[0] = 0 + cpu.decodeBuf[1] = 0 + err := decodeExec(cpu, f) + if err != nil { + return fmt.Errorf("decode failed at %s: %w", f.fetchLabel(), err) + } + switch cpu.decodeBuf[0] { + case 0x76: // HALT + cpu.HALT = true + case 0xfb: // EI + afterEI = true + case 0xed: // RETI or RETN + switch cpu.decodeBuf[1] { + case 0x4d: // RETI + if cpu.INT != nil { + cpu.INT.ReturnINT() + } + case 0x45: // RETN + cpu.InNMI = false + } + } + } + // try interruptions. + if enableInt { + oldPC := cpu.PC + ok, err := cpu.tryInterrupt(afterEI) + if err != nil { + return err + } + if ok && cpu.IMon != nil { + cpu.IMon.OnInterrupt(cpu.InNMI, oldPC, cpu.PC) + } + } + return nil +} diff --git a/switch.go b/switch.go new file mode 100644 index 0000000..7c033d6 --- /dev/null +++ b/switch.go @@ -0,0 +1,848 @@ +package z80 + +func decodeExec(cpu *CPU, f fetcher) error { + var b uint8 + buf := cpu.decodeBuf[:4] + b = f.fetch() + buf[0] = b + switch b { + case 0x00: + opNOP(cpu, buf[:1]) + return nil + case 0x01, 0x11, 0x21, 0x31: + buf[1] = f.fetch() + buf[2] = f.fetch() + opLDddnn(cpu, buf[:3]) + return nil + case 0x02: + opLDBCPA(cpu, buf[:1]) + return nil + case 0x03, 0x13, 0x23, 0x33: + opINCss(cpu, buf[:1]) + return nil + case 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x3c: + opINCr(cpu, buf[:1]) + return nil + case 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x3d: + opDECr(cpu, buf[:1]) + return nil + case 0x06, 0x0e, 0x16, 0x1e, 0x26, 0x2e, 0x3e: + buf[1] = f.fetch() + opLDrn(cpu, buf[:2]) + return nil + case 0x07: + opRLCA(cpu, buf[:1]) + return nil + case 0x08: + opEXAFAF(cpu, buf[:1]) + return nil + case 0x09, 0x19, 0x29, 0x39: + opADDHLss(cpu, buf[:1]) + return nil + case 0x0a: + opLDABCP(cpu, buf[:1]) + return nil + case 0x0b, 0x1b, 0x2b, 0x3b: + opDECss(cpu, buf[:1]) + return nil + case 0x0f: + opRRCA(cpu, buf[:1]) + return nil + case 0x10: + buf[1] = f.fetch() + opDJNZe(cpu, buf[:2]) + return nil + case 0x12: + opLDDEPA(cpu, buf[:1]) + return nil + case 0x17: + opRLA(cpu, buf[:1]) + return nil + case 0x18: + buf[1] = f.fetch() + opJRe(cpu, buf[:2]) + return nil + case 0x1a: + opLDADEP(cpu, buf[:1]) + return nil + case 0x1f: + opRRA(cpu, buf[:1]) + return nil + case 0x20: + buf[1] = f.fetch() + opJRNZe(cpu, buf[:2]) + return nil + case 0x22: + buf[1] = f.fetch() + buf[2] = f.fetch() + opLDnnPHL(cpu, buf[:3]) + return nil + case 0x27: + opDAA(cpu, buf[:1]) + return nil + case 0x28: + buf[1] = f.fetch() + opJRZe(cpu, buf[:2]) + return nil + case 0x2a: + buf[1] = f.fetch() + buf[2] = f.fetch() + opLDHLnnP(cpu, buf[:3]) + return nil + case 0x2f: + opCPL(cpu, buf[:1]) + return nil + case 0x30: + buf[1] = f.fetch() + opJRNCe(cpu, buf[:2]) + return nil + case 0x32: + buf[1] = f.fetch() + buf[2] = f.fetch() + opLDnnPA(cpu, buf[:3]) + return nil + case 0x34: + opINCHLP(cpu, buf[:1]) + return nil + case 0x35: + opDECHLP(cpu, buf[:1]) + return nil + case 0x36: + buf[1] = f.fetch() + opLDHLPn(cpu, buf[:2]) + return nil + case 0x37: + opSCF(cpu, buf[:1]) + return nil + case 0x38: + buf[1] = f.fetch() + opJRCe(cpu, buf[:2]) + return nil + case 0x3a: + buf[1] = f.fetch() + buf[2] = f.fetch() + opLDAnnP(cpu, buf[:3]) + return nil + case 0x3f: + opCCF(cpu, buf[:1]) + return nil + case 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6f, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7f: + opLDr1r2(cpu, buf[:1]) + return nil + case 0x46, 0x4e, 0x56, 0x5e, 0x66, 0x6e, 0x7e: + opLDrHLP(cpu, buf[:1]) + return nil + case 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x77: + opLDHLPr(cpu, buf[:1]) + return nil + case 0x76: + opHALT(cpu, buf[:1]) + return nil + case 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87: + opADDAr(cpu, buf[:1]) + return nil + case 0x86: + opADDAHLP(cpu, buf[:1]) + return nil + case 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8f: + opADCAr(cpu, buf[:1]) + return nil + case 0x8e: + opADCAHLP(cpu, buf[:1]) + return nil + case 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x97: + opSUBAr(cpu, buf[:1]) + return nil + case 0x96: + opSUBAHLP(cpu, buf[:1]) + return nil + case 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9f: + opSBCAr(cpu, buf[:1]) + return nil + case 0x9e: + opSBCAHLP(cpu, buf[:1]) + return nil + case 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa7: + opANDr(cpu, buf[:1]) + return nil + case 0xa6: + opANDHLP(cpu, buf[:1]) + return nil + case 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xaf: + opXORr(cpu, buf[:1]) + return nil + case 0xae: + opXORHLP(cpu, buf[:1]) + return nil + case 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb7: + opORr(cpu, buf[:1]) + return nil + case 0xb6: + opORHLP(cpu, buf[:1]) + return nil + case 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbf: + opCPr(cpu, buf[:1]) + return nil + case 0xbe: + opCPHLP(cpu, buf[:1]) + return nil + case 0xc0, 0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8: + opRETcc(cpu, buf[:1]) + return nil + case 0xc1, 0xd1, 0xe1, 0xf1: + opPOPqq(cpu, buf[:1]) + return nil + case 0xc2, 0xca, 0xd2, 0xda, 0xe2, 0xea, 0xf2, 0xfa: + buf[1] = f.fetch() + buf[2] = f.fetch() + opJPccnn(cpu, buf[:3]) + return nil + case 0xc3: + buf[1] = f.fetch() + buf[2] = f.fetch() + opJPnn(cpu, buf[:3]) + return nil + case 0xc4, 0xcc, 0xd4, 0xdc, 0xe4, 0xec, 0xf4, 0xfc: + buf[1] = f.fetch() + buf[2] = f.fetch() + opCALLccnn(cpu, buf[:3]) + return nil + case 0xc5, 0xd5, 0xe5, 0xf5: + opPUSHqq(cpu, buf[:1]) + return nil + case 0xc6: + buf[1] = f.fetch() + opADDAn(cpu, buf[:2]) + return nil + case 0xc7, 0xcf, 0xd7, 0xdf, 0xe7, 0xef, 0xf7, 0xff: + opRSTp(cpu, buf[:1]) + return nil + case 0xc9: + opRET(cpu, buf[:1]) + return nil + case 0xcd: + buf[1] = f.fetch() + buf[2] = f.fetch() + opCALLnn(cpu, buf[:3]) + return nil + case 0xce: + buf[1] = f.fetch() + opADCAn(cpu, buf[:2]) + return nil + case 0xd3: + buf[1] = f.fetch() + opOUTnPA(cpu, buf[:2]) + return nil + case 0xd6: + buf[1] = f.fetch() + opSUBAn(cpu, buf[:2]) + return nil + case 0xd9: + opEXX(cpu, buf[:1]) + return nil + case 0xdb: + buf[1] = f.fetch() + opINAnP(cpu, buf[:2]) + return nil + case 0xde: + buf[1] = f.fetch() + opSBCAn(cpu, buf[:2]) + return nil + case 0xe3: + opEXSPPHL(cpu, buf[:1]) + return nil + case 0xe6: + buf[1] = f.fetch() + opANDn(cpu, buf[:2]) + return nil + case 0xe9: + opJPHLP(cpu, buf[:1]) + return nil + case 0xeb: + opEXDEHL(cpu, buf[:1]) + return nil + case 0xee: + buf[1] = f.fetch() + opXORn(cpu, buf[:2]) + return nil + case 0xf3: + opDI(cpu, buf[:1]) + return nil + case 0xf6: + buf[1] = f.fetch() + opORn(cpu, buf[:2]) + return nil + case 0xf9: + opLDSPHL(cpu, buf[:1]) + return nil + case 0xfb: + opEI(cpu, buf[:1]) + return nil + case 0xfe: + buf[1] = f.fetch() + opCPn(cpu, buf[:2]) + return nil + case 0xcb: + b = f.fetch() + buf[1] = b + switch b { + case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07: + opRLCr(cpu, buf[:2]) + return nil + case 0x06: + opRLCHLP(cpu, buf[:2]) + return nil + case 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0f: + opRRCr(cpu, buf[:2]) + return nil + case 0x0e: + opRRCHLP(cpu, buf[:2]) + return nil + case 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x17: + opRLr(cpu, buf[:2]) + return nil + case 0x16: + opRLHLP(cpu, buf[:2]) + return nil + case 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f: + opRRr(cpu, buf[:2]) + return nil + case 0x1e: + opRRHLP(cpu, buf[:2]) + return nil + case 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27: + opSLAr(cpu, buf[:2]) + return nil + case 0x26: + opSLAHLP(cpu, buf[:2]) + return nil + case 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2f: + opSRAr(cpu, buf[:2]) + return nil + case 0x2e: + opSRAHLP(cpu, buf[:2]) + return nil + case 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x37: + opSL1r(cpu, buf[:2]) + return nil + case 0x36: + opSL1HLP(cpu, buf[:2]) + return nil + case 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3f: + opSRLr(cpu, buf[:2]) + return nil + case 0x3e: + opSRLHLP(cpu, buf[:2]) + return nil + case 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7f: + opBITbr(cpu, buf[:2]) + return nil + case 0x46, 0x4e, 0x56, 0x5e, 0x66, 0x6e, 0x76, 0x7e: + opBITbHLP(cpu, buf[:2]) + return nil + case 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbf: + opRESbr(cpu, buf[:2]) + return nil + case 0x86, 0x8e, 0x96, 0x9e, 0xa6, 0xae, 0xb6, 0xbe: + opRESbHLP(cpu, buf[:2]) + return nil + case 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xff: + opSETbr(cpu, buf[:2]) + return nil + case 0xc6, 0xce, 0xd6, 0xde, 0xe6, 0xee, 0xf6, 0xfe: + opSETbHLP(cpu, buf[:2]) + return nil + default: + return ErrInvalidCodes + } + case 0xdd: + b = f.fetch() + buf[1] = b + switch b { + case 0x09, 0x19, 0x29, 0x39: + opADDIXpp(cpu, buf[:2]) + return nil + case 0x21: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDIXnn(cpu, buf[:4]) + return nil + case 0x22: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDnnPIX(cpu, buf[:4]) + return nil + case 0x23: + opINCIX(cpu, buf[:2]) + return nil + case 0x24: + opINCIXH(cpu, buf[:2]) + return nil + case 0x25: + opDECIXH(cpu, buf[:2]) + return nil + case 0x26: + buf[2] = f.fetch() + opLDIXHn(cpu, buf[:3]) + return nil + case 0x2a: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDIXnnP(cpu, buf[:4]) + return nil + case 0x2b: + opDECIX(cpu, buf[:2]) + return nil + case 0x2c: + opINCIXL(cpu, buf[:2]) + return nil + case 0x2d: + opDECIXL(cpu, buf[:2]) + return nil + case 0x2e: + buf[2] = f.fetch() + opLDIXLn(cpu, buf[:3]) + return nil + case 0x34: + buf[2] = f.fetch() + opINCIXdP(cpu, buf[:3]) + return nil + case 0x35: + buf[2] = f.fetch() + opDECIXdP(cpu, buf[:3]) + return nil + case 0x36: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDIXdPn(cpu, buf[:4]) + return nil + case 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6f, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7f: + opLDrx1rx2(cpu, buf[:2]) + return nil + case 0x46, 0x4e, 0x56, 0x5e, 0x66, 0x6e, 0x7e: + buf[2] = f.fetch() + opLDrIXdP(cpu, buf[:3]) + return nil + case 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x77: + buf[2] = f.fetch() + opLDIXdPr(cpu, buf[:3]) + return nil + case 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87: + opADDArx(cpu, buf[:2]) + return nil + case 0x86: + buf[2] = f.fetch() + opADDAIXdP(cpu, buf[:3]) + return nil + case 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8f: + opADCArx(cpu, buf[:2]) + return nil + case 0x8e: + buf[2] = f.fetch() + opADCAIXdP(cpu, buf[:3]) + return nil + case 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x97: + opSUBArx(cpu, buf[:2]) + return nil + case 0x96: + buf[2] = f.fetch() + opSUBAIXdP(cpu, buf[:3]) + return nil + case 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9f: + opSBCArx(cpu, buf[:2]) + return nil + case 0x9e: + buf[2] = f.fetch() + opSBCAIXdP(cpu, buf[:3]) + return nil + case 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa7: + opANDrx(cpu, buf[:2]) + return nil + case 0xa6: + buf[2] = f.fetch() + opANDIXdP(cpu, buf[:3]) + return nil + case 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xaf: + opXORrx(cpu, buf[:2]) + return nil + case 0xae: + buf[2] = f.fetch() + opXORIXdP(cpu, buf[:3]) + return nil + case 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb7: + opORrx(cpu, buf[:2]) + return nil + case 0xb6: + buf[2] = f.fetch() + opORIXdP(cpu, buf[:3]) + return nil + case 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbf: + opCPrx(cpu, buf[:2]) + return nil + case 0xbe: + buf[2] = f.fetch() + opCPIXdP(cpu, buf[:3]) + return nil + case 0xe1: + opPOPIX(cpu, buf[:2]) + return nil + case 0xe3: + opEXSPPIX(cpu, buf[:2]) + return nil + case 0xe5: + opPUSHIX(cpu, buf[:2]) + return nil + case 0xe9: + opJPIXP(cpu, buf[:2]) + return nil + case 0xf9: + opLDSPIX(cpu, buf[:2]) + return nil + case 0xcb: + buf[2] = f.fetch() + b = f.fetch() + buf[3] = b + switch b { + case 0x06: + opRLCIXdP(cpu, buf[:4]) + return nil + case 0x0e: + opRRCIXdP(cpu, buf[:4]) + return nil + case 0x16: + opRLIXdP(cpu, buf[:4]) + return nil + case 0x1e: + opRRIXdP(cpu, buf[:4]) + return nil + case 0x26: + opSLAIXdP(cpu, buf[:4]) + return nil + case 0x2e: + opSRAIXdP(cpu, buf[:4]) + return nil + case 0x36: + opSL1IXdP(cpu, buf[:4]) + return nil + case 0x3e: + opSRLIXdP(cpu, buf[:4]) + return nil + case 0x46, 0x4e, 0x56, 0x5e, 0x66, 0x6e, 0x76, 0x7e: + opBITbIXdP(cpu, buf[:4]) + return nil + case 0x86, 0x8e, 0x96, 0x9e, 0xa6, 0xae, 0xb6, 0xbe: + opRESbIXdP(cpu, buf[:4]) + return nil + case 0xc6, 0xce, 0xd6, 0xde, 0xe6, 0xee, 0xf6, 0xfe: + opSETbIXdP(cpu, buf[:4]) + return nil + default: + return ErrInvalidCodes + } + default: + return ErrInvalidCodes + } + case 0xed: + b = f.fetch() + buf[1] = b + switch b { + case 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x78: + opINrCP(cpu, buf[:2]) + return nil + case 0x41, 0x49, 0x51, 0x59, 0x61, 0x69, 0x79: + opOUTCPr(cpu, buf[:2]) + return nil + case 0x42, 0x52, 0x62, 0x72: + opSBCHLss(cpu, buf[:2]) + return nil + case 0x43, 0x53, 0x63, 0x73: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDnnPdd(cpu, buf[:4]) + return nil + case 0x44: + opNEG(cpu, buf[:2]) + return nil + case 0x45: + opRETN(cpu, buf[:2]) + return nil + case 0x46: + opIM0(cpu, buf[:2]) + return nil + case 0x47: + opLDIA(cpu, buf[:2]) + return nil + case 0x4a, 0x5a, 0x6a, 0x7a: + opADCHLss(cpu, buf[:2]) + return nil + case 0x4b, 0x5b, 0x6b, 0x7b: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDddnnP(cpu, buf[:4]) + return nil + case 0x4d: + opRETI(cpu, buf[:2]) + return nil + case 0x4f: + opLDRA(cpu, buf[:2]) + return nil + case 0x56: + opIM1(cpu, buf[:2]) + return nil + case 0x57: + opLDAI(cpu, buf[:2]) + return nil + case 0x5e: + opIM2(cpu, buf[:2]) + return nil + case 0x5f: + opLDAR(cpu, buf[:2]) + return nil + case 0x67: + opRRD(cpu, buf[:2]) + return nil + case 0x6f: + opRLD(cpu, buf[:2]) + return nil + case 0xa0: + opLDI(cpu, buf[:2]) + return nil + case 0xa1: + opCPI(cpu, buf[:2]) + return nil + case 0xa2: + opINI(cpu, buf[:2]) + return nil + case 0xa3: + opOUTI(cpu, buf[:2]) + return nil + case 0xa8: + opLDD(cpu, buf[:2]) + return nil + case 0xa9: + opCPD(cpu, buf[:2]) + return nil + case 0xaa: + opIND(cpu, buf[:2]) + return nil + case 0xab: + opOUTD(cpu, buf[:2]) + return nil + case 0xb0: + opLDIR(cpu, buf[:2]) + return nil + case 0xb1: + opCPIR(cpu, buf[:2]) + return nil + case 0xb2: + opINIR(cpu, buf[:2]) + return nil + case 0xb3: + opOTIR(cpu, buf[:2]) + return nil + case 0xb8: + opLDDR(cpu, buf[:2]) + return nil + case 0xb9: + opCPDR(cpu, buf[:2]) + return nil + case 0xba: + opINDR(cpu, buf[:2]) + return nil + case 0xbb: + opOTDR(cpu, buf[:2]) + return nil + default: + return ErrInvalidCodes + } + case 0xfd: + b = f.fetch() + buf[1] = b + switch b { + case 0x09, 0x19, 0x29, 0x39: + opADDIYrr(cpu, buf[:2]) + return nil + case 0x21: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDIYnn(cpu, buf[:4]) + return nil + case 0x22: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDnnPIY(cpu, buf[:4]) + return nil + case 0x23: + opINCIY(cpu, buf[:2]) + return nil + case 0x24: + opINCIYH(cpu, buf[:2]) + return nil + case 0x25: + opDECIYH(cpu, buf[:2]) + return nil + case 0x26: + buf[2] = f.fetch() + opLDIYHn(cpu, buf[:3]) + return nil + case 0x2a: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDIYnnP(cpu, buf[:4]) + return nil + case 0x2b: + opDECIY(cpu, buf[:2]) + return nil + case 0x2c: + opINCIYL(cpu, buf[:2]) + return nil + case 0x2d: + opDECIYL(cpu, buf[:2]) + return nil + case 0x2e: + buf[2] = f.fetch() + opLDIYLn(cpu, buf[:3]) + return nil + case 0x34: + buf[2] = f.fetch() + opINCIYdP(cpu, buf[:3]) + return nil + case 0x35: + buf[2] = f.fetch() + opDECIYdP(cpu, buf[:3]) + return nil + case 0x36: + buf[2] = f.fetch() + buf[3] = f.fetch() + opLDIYdPn(cpu, buf[:4]) + return nil + case 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6f, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7f: + opLDry1ry2(cpu, buf[:2]) + return nil + case 0x46, 0x4e, 0x56, 0x5e, 0x66, 0x6e, 0x7e: + buf[2] = f.fetch() + opLDrIYdP(cpu, buf[:3]) + return nil + case 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x77: + buf[2] = f.fetch() + opLDIYdPr(cpu, buf[:3]) + return nil + case 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87: + opADDAry(cpu, buf[:2]) + return nil + case 0x86: + buf[2] = f.fetch() + opADDAIYdP(cpu, buf[:3]) + return nil + case 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8f: + opADCAry(cpu, buf[:2]) + return nil + case 0x8e: + buf[2] = f.fetch() + opADCAIYdP(cpu, buf[:3]) + return nil + case 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x97: + opSUBAry(cpu, buf[:2]) + return nil + case 0x96: + buf[2] = f.fetch() + opSUBAIYdP(cpu, buf[:3]) + return nil + case 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9f: + opSBCAry(cpu, buf[:2]) + return nil + case 0x9e: + buf[2] = f.fetch() + opSBCAIYdP(cpu, buf[:3]) + return nil + case 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa7: + opANDry(cpu, buf[:2]) + return nil + case 0xa6: + buf[2] = f.fetch() + opANDIYdP(cpu, buf[:3]) + return nil + case 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xaf: + opXORry(cpu, buf[:2]) + return nil + case 0xae: + buf[2] = f.fetch() + opXORIYdP(cpu, buf[:3]) + return nil + case 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb7: + opORry(cpu, buf[:2]) + return nil + case 0xb6: + buf[2] = f.fetch() + opORIYdP(cpu, buf[:3]) + return nil + case 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbf: + opCPry(cpu, buf[:2]) + return nil + case 0xbe: + buf[2] = f.fetch() + opCPIYdP(cpu, buf[:3]) + return nil + case 0xe1: + opPOPIY(cpu, buf[:2]) + return nil + case 0xe3: + opEXSPPIY(cpu, buf[:2]) + return nil + case 0xe5: + opPUSHIY(cpu, buf[:2]) + return nil + case 0xe9: + opJPIYP(cpu, buf[:2]) + return nil + case 0xf9: + opLDSPIY(cpu, buf[:2]) + return nil + case 0xcb: + buf[2] = f.fetch() + b = f.fetch() + buf[3] = b + switch b { + case 0x06: + opRLCIYdP(cpu, buf[:4]) + return nil + case 0x0e: + opRRCIYdP(cpu, buf[:4]) + return nil + case 0x16: + opRLIYdP(cpu, buf[:4]) + return nil + case 0x1e: + opRRIYdP(cpu, buf[:4]) + return nil + case 0x26: + opSLAIYdP(cpu, buf[:4]) + return nil + case 0x2e: + opSRAIYdP(cpu, buf[:4]) + return nil + case 0x36: + opSL1IYdP(cpu, buf[:4]) + return nil + case 0x3e: + opSRLIYdP(cpu, buf[:4]) + return nil + case 0x46, 0x4e, 0x56, 0x5e, 0x66, 0x6e, 0x76, 0x7e: + opBITbIYdP(cpu, buf[:4]) + return nil + case 0x86, 0x8e, 0x96, 0x9e, 0xa6, 0xae, 0xb6, 0xbe: + opRESbIYdP(cpu, buf[:4]) + return nil + case 0xc6, 0xce, 0xd6, 0xde, 0xe6, 0xee, 0xf6, 0xfe: + opSETbIYdP(cpu, buf[:4]) + return nil + default: + return ErrInvalidCodes + } + default: + return ErrInvalidCodes + } + default: + return ErrInvalidCodes + } +} diff --git a/switch.go.dummy b/switch.go.dummy new file mode 100644 index 0000000..20bd0d9 --- /dev/null +++ b/switch.go.dummy @@ -0,0 +1,5 @@ +package z80 + +func decodeExec(cpu *CPU, f fetcher) error { + return nil +} diff --git a/z80.go b/z80.go index 6a19940..4f4e0ca 100644 --- a/z80.go +++ b/z80.go @@ -7,7 +7,7 @@ import ( "context" "fmt" "log" - "sync" + "sync/atomic" ) // Register is 16 bits register. @@ -94,9 +94,7 @@ type CPU struct { Debug bool BreakPoints map[uint16]struct{} - onceInit sync.Once - decodeLayer *decodeLayer - decodeBuf []byte + decodeBuf [4]uint8 } func (cpu *CPU) failf(msg string, args ...interface{}) { @@ -122,10 +120,10 @@ func (cpu *CPU) writeU16(addr uint16, v uint16) { cpu.Memory.Set(addr+1, h) } -func (cpu *CPU) fetch() (uint8, error) { +func (cpu *CPU) fetch() uint8 { v := cpu.Memory.Get(cpu.PC) cpu.PC++ - return v, nil + return v } func (cpu *CPU) fetchLabel() string { @@ -286,11 +284,6 @@ func (cpu *CPU) flagCC(n uint8) bool { } } -type fetcher interface { - fetch() (uint8, error) - fetchLabel() string -} - func (cpu *CPU) exec(op *OPCode, args []uint8) { for i, c := range op.C { args[i] &= c.M @@ -298,21 +291,21 @@ func (cpu *CPU) exec(op *OPCode, args []uint8) { op.F(cpu, args) } -func (cpu *CPU) init() { - cpu.onceInit.Do(func() { - cpu.decodeLayer = defaultDecodeLayer() - cpu.decodeBuf = make([]byte, 8) - }) -} - // Run executes instructions till HALT or error. func (cpu *CPU) Run(ctx context.Context) error { - cpu.init() + var ctxErr error + var canceled int32 + ctx2, cancel := context.WithCancel(ctx) + defer cancel() + go func() { + <-ctx2.Done() + ctxErr = ctx.Err() + atomic.StoreInt32(&canceled, 1) + }() + for !cpu.HALT { - select { - case <-ctx.Done(): - return ctx.Err() - default: + if atomic.LoadInt32(&canceled) != 0 { + return ctxErr } err := cpu.step(cpu, true) if err != nil { @@ -329,69 +322,9 @@ func (cpu *CPU) Run(ctx context.Context) error { // Step executes an instruction. func (cpu *CPU) Step() error { - cpu.init() return cpu.step(cpu, true) } -func (cpu *CPU) step(f fetcher, enableInt bool) error { - afterEI := false - if !cpu.HALT { - // fetch an OPCode and increase refresh register. - op, buf, err := decode(cpu.decodeLayer, cpu.decodeBuf[:0], f) - if err != nil { - label := f.fetchLabel() - return fmt.Errorf("decode failed %X at %s: %w", buf, label, err) - } - rr := cpu.IR.Lo - cpu.IR.Lo = rr&0x80 | (rr+1)&0x7f - // execute an OPCode. - if cpu.Debug { - label := f.fetchLabel() - cpu.debugf("execute OPCode:%s with %X at %s", op.N, buf, label) - } - cpu.exec(op, buf) - switch op { - case opHALT: - cpu.HALT = true - case opEI: - afterEI = true - case opRETI: - if cpu.INT != nil { - cpu.INT.ReturnINT() - } - case opRETN: - cpu.InNMI = false - } - } - // try interruptions. - if enableInt { - oldPC := cpu.PC - ok, err := cpu.tryInterrupt(afterEI) - if err != nil { - return err - } - if ok && cpu.IMon != nil { - cpu.IMon.OnInterrupt(cpu.InNMI, oldPC, cpu.PC) - } - } - return nil -} - -type memSrc []uint8 - -func (m *memSrc) fetch() (uint8, error) { - if len(*m) == 0 { - return 0, ErrTooShortIM0 - } - var b uint8 - b, *m = (*m)[0], (*m)[1:] - return b, nil -} - -func (m *memSrc) fetchLabel() string { - return "IM0" -} - func (cpu *CPU) tryInterrupt(suppressINT bool) (bool, error) { // check non-maskable interrupt. if cpu.InNMI { @@ -423,8 +356,11 @@ func (cpu *CPU) tryInterrupt(suppressINT bool) (bool, error) { cpu.PC = 0x0038 return true, nil case 2: - if len(d) < 1 { - return false, fmt.Errorf("interruption data should be 1 bytes in IM 2") + if n := len(d); n != 1 { + cpu.failf("interruption data should be 1 byte in IM 2") + if n == 0 { + return false, nil + } } cpu.HALT = false cpu.SP -= 2 @@ -433,6 +369,10 @@ func (cpu *CPU) tryInterrupt(suppressINT bool) (bool, error) { return true, nil } // interrupt with IM 0 + if len(d) == 0 { + cpu.failf("interruption data should be longer 1 byte in IM 0") + return false, nil + } cpu.HALT = false ms := memSrc(d) err := cpu.step(&ms, false)