Update to v101r17 release.

byuu says:

Changelog:

  - Z80: added most opcodes between 0x00 and 0x3f (two or three hard
    ones missing still)
  - Z80: redid register declaration *again* to handle AF', BC', DE',
    HL' (ugggggh, the fuck? Alternate registers??)
      - basically, using `#define <register name>` values to get around
        horrendously awful naming syntax
  - Z80: improved handling of displace() so that it won't ever trigger
    on (BC) or (DE)
This commit is contained in:
Tim Allen
2016-09-06 23:53:14 +10:00
parent 2fbbccf985
commit d6e9d94ec3
8 changed files with 448 additions and 205 deletions

View File

@@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "higan"; static const string Name = "higan";
static const string Version = "101.16"; static const string Version = "101.17";
static const string Author = "byuu"; static const string Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";

View File

@@ -23,12 +23,12 @@ auto Z80::disassemble(uint16 pc) -> string {
s.append(pad(disassemble__(pc, prefix, code), -18L, ' ')); s.append(pad(disassemble__(pc, prefix, code), -18L, ' '));
finish: finish:
s.append(" AF:", hex(r.af, 4L)); s.append(" AF:", hex(r.af.word, 4L));
s.append(" BC:", hex(r.bc, 4L)); s.append(" BC:", hex(r.bc.word, 4L));
s.append(" DE:", hex(r.de, 4L)); s.append(" DE:", hex(r.de.word, 4L));
s.append(" HL:", hex(r.hl, 4L)); s.append(" HL:", hex(r.hl.word, 4L));
s.append(" IX:", hex(r.ix, 4L)); s.append(" IX:", hex(r.ix.word, 4L));
s.append(" IY:", hex(r.iy, 4L)); s.append(" IY:", hex(r.iy.word, 4L));
s.append(" SP:", hex(r.sp, 4L)); s.append(" SP:", hex(r.sp, 4L));
return s; return s;
@@ -50,16 +50,27 @@ auto Z80::disassemble(uint16 pc) -> string {
#define E "e" #define E "e"
#define H prefix == 0xdd ? "ixh" : prefix == 0xfd ? "iyh" : "h" #define H prefix == 0xdd ? "ixh" : prefix == 0xfd ? "iyh" : "h"
#define L prefix == 0xdd ? "ixl" : prefix == 0xfd ? "iyl" : "l" #define L prefix == 0xdd ? "ixl" : prefix == 0xfd ? "iyl" : "l"
#define HD "h" #define _H "h"
#define LD "l" #define _L "l"
#define _HL "hl"
#define AF "af" #define AF "af"
#define BC "bc" #define BC "bc"
#define DE "de" #define DE "de"
#define HL prefix == 0xdd ? "ix" : prefix == 0xfd ? "iy" : "hl" #define HL prefix == 0xdd ? "ix" : prefix == 0xfd ? "iy" : "hl"
#define SP "sp"
#define AF_ "af'"
#define BC_ "bc'"
#define DE_ "de'"
#define HL_ "hl'"
#define SP "sp"
#define PC "pc"
#define IBC "(bc)"
#define IDE "(de)"
#define IHL string{"(", HL, displace(), ")"} #define IHL string{"(", HL, displace(), ")"}
#define ISP "(sp)"
auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string {
auto byte = [&] { auto byte = [&] {
@@ -88,23 +99,66 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string {
switch(code) { switch(code) {
op(0x00, "nop ") op(0x00, "nop ")
op(0x01, "ld ", BC, NN) op(0x01, "ld ", BC, NN)
op(0x02, "ld ", IBC, A)
op(0x03, "inc ", BC)
op(0x04, "inc ", B)
op(0x05, "dec ", B)
op(0x06, "ld ", B, N) op(0x06, "ld ", B, N)
op(0x07, "rlca")
op(0x08, "ex ", AF, AF_)
op(0x09, "add ", HL, BC)
op(0x0a, "ld ", A, IBC)
op(0x0b, "dec ", BC)
op(0x0c, "inc ", C)
op(0x0d, "dec ", C)
op(0x0e, "ld ", C, N) op(0x0e, "ld ", C, N)
op(0x0f, "rrca")
op(0x11, "ld ", DE, NN) op(0x11, "ld ", DE, NN)
op(0x12, "ld ", IDE, A)
op(0x13, "inc ", DE)
op(0x14, "inc ", D)
op(0x15, "dec ", D)
op(0x16, "ld ", E, N) op(0x16, "ld ", E, N)
op(0x17, "rla ")
op(0x18, "jr ", R) op(0x18, "jr ", R)
op(0x19, "add ", HL, DE)
op(0x1a, "ld ", A, IDE)
op(0x1b, "dec ", DE)
op(0x1c, "inc ", E)
op(0x1d, "dec ", E)
op(0x1e, "ld ", E, N) op(0x1e, "ld ", E, N)
op(0x1f, "rra ")
op(0x20, "jr ", "nz", R) op(0x20, "jr ", "nz", R)
op(0x21, "ld ", HL, NN) op(0x21, "ld ", HL, NN)
op(0x22, "ld ", INN, HL)
op(0x23, "inc ", HL)
op(0x24, "inc ", H)
op(0x25, "dec ", H)
op(0x26, "ld ", H, N) op(0x26, "ld ", H, N)
op(0x28, "jr ", "z", R) op(0x28, "jr ", "z", R)
op(0x29, "add ", HL, HL)
op(0x2a, "ld ", HL, INN)
op(0x2b, "dec ", HL)
op(0x2c, "inc ", L)
op(0x2d, "dec ", L)
op(0x2e, "ld ", L, N) op(0x2e, "ld ", L, N)
op(0x2f, "cpl ")
op(0x30, "jr ", "nc", R) op(0x30, "jr ", "nc", R)
op(0x31, "ld ", SP, NN) op(0x31, "ld ", SP, NN)
op(0x32, "ld ", INN, A) op(0x32, "ld ", INN, A)
op(0x33, "inc ", SP)
op(0x34, "inc ", IHL)
op(0x35, "dec ", IHL)
op(0x36, "ld ", IHL, N) op(0x36, "ld ", IHL, N)
op(0x37, "scf ")
op(0x38, "jr ", "c", R) op(0x38, "jr ", "c", R)
op(0x39, "add ", HL, SP)
op(0x3a, "ld ", A, INN)
op(0x3b, "dec ", SP)
op(0x3c, "inc ", A)
op(0x3d, "dec ", A)
op(0x3e, "ld ", A, N) op(0x3e, "ld ", A, N)
op(0x3f, "ccf ")
op(0x40, "ld ", B, B) op(0x40, "ld ", B, B)
op(0x41, "ld ", B, C) op(0x41, "ld ", B, C)
op(0x42, "ld ", B, D) op(0x42, "ld ", B, D)
@@ -143,7 +197,7 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string {
op(0x63, "ld ", H, E) op(0x63, "ld ", H, E)
op(0x64, "ld ", H, H) op(0x64, "ld ", H, H)
op(0x65, "ld ", H, L) op(0x65, "ld ", H, L)
op(0x66, "ld ", HD, IHL) op(0x66, "ld ", _H, IHL)
op(0x67, "ld ", H, A) op(0x67, "ld ", H, A)
op(0x68, "ld ", L, B) op(0x68, "ld ", L, B)
op(0x69, "ld ", L, C) op(0x69, "ld ", L, C)
@@ -151,14 +205,14 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string {
op(0x6b, "ld ", L, E) op(0x6b, "ld ", L, E)
op(0x6c, "ld ", L, H) op(0x6c, "ld ", L, H)
op(0x6d, "ld ", L, L) op(0x6d, "ld ", L, L)
op(0x6e, "ld ", LD, IHL) op(0x6e, "ld ", _L, IHL)
op(0x6f, "ld ", L, A) op(0x6f, "ld ", L, A)
op(0x70, "ld ", IHL, B) op(0x70, "ld ", IHL, B)
op(0x71, "ld ", IHL, C) op(0x71, "ld ", IHL, C)
op(0x72, "ld ", IHL, D) op(0x72, "ld ", IHL, D)
op(0x73, "ld ", IHL, E) op(0x73, "ld ", IHL, E)
op(0x74, "ld ", IHL, HD) op(0x74, "ld ", IHL, _H)
op(0x75, "ld ", IHL, LD) op(0x75, "ld ", IHL, _L)
op(0x76, "halt") op(0x76, "halt")
op(0x77, "ld ", IHL, A) op(0x77, "ld ", IHL, A)
op(0x78, "ld ", A, B) op(0x78, "ld ", A, B)
@@ -242,6 +296,7 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string {
op(0xdb, "in ", A, IN) op(0xdb, "in ", A, IN)
op(0xe2, "jp ", "po", NN) op(0xe2, "jp ", "po", NN)
op(0xea, "jp ", "pe", NN) op(0xea, "jp ", "pe", NN)
op(0xeb, "ex ", DE, _HL)
op(0xed, "ed: ") op(0xed, "ed: ")
op(0xf2, "jp ", "p", NN) op(0xf2, "jp ", "p", NN)
op(0xf3, "di ") op(0xf3, "di ")
@@ -290,13 +345,24 @@ auto Z80::disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string {
#undef E #undef E
#undef H #undef H
#undef L #undef L
#undef HD #undef _H
#undef LD #undef _L
#undef _HL
#undef AF #undef AF
#undef BC #undef BC
#undef DE #undef DE
#undef HL #undef HL
#undef SP
#undef AF_
#undef BC_
#undef DE_
#undef HL_
#undef SP
#undef PC
#undef IBC
#undef IDE
#undef IHL #undef IHL
#undef ISP

View File

@@ -13,64 +13,78 @@ auto Z80::instruction() -> void {
instructionsExecuted++; instructionsExecuted++;
auto code = opcode(); auto code = opcode();
if(code == 0xdd || code == 0xfd) { if(code == 0xdd) { r.hlp = &r.ix; return; }
r.prefix = code; if(code == 0xfd) { r.hlp = &r.iy; return; }
return;
}
instruction__(code); instruction__(code);
r.prefix = 0x00; r.hlp = &r.hl;
} }
#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);
#define A (uint8&)(r.a)
#define F (uint8&)(r.f)
#define B (uint8&)(r.b)
#define C (uint8&)(r.c)
#define D (uint8&)(r.d)
#define E (uint8&)(r.e)
#define H (uint8&)(r.prefix == 0xdd ? r.ixh : r.prefix == 0xfd ? r.iyh : r.h)
#define L (uint8&)(r.prefix == 0xdd ? r.ixl : r.prefix == 0xfd ? r.iyl : r.l)
#define HD (uint8&)(r.h)
#define LD (uint8&)(r.l)
#define AF (uint16&)(r.af)
#define BC (uint16&)(r.bc)
#define DE (uint16&)(r.de)
#define HL (uint16&)(r.prefix == 0xdd ? r.ix : r.prefix == 0xfd ? r.iy : r.hl)
#define SP (uint16&)(r.sp)
#define CF r.p.c
#define NF r.p.n
#define PF r.p.p
#define VF r.p.v
#define XF r.p.x
#define HF r.p.h
#define YF r.p.y
#define ZF r.p.z
#define SF r.p.s
auto Z80::instruction__(uint8 code) -> void { auto Z80::instruction__(uint8 code) -> void {
switch(code) { switch(code) {
op(0x00, NOP) op(0x00, NOP)
op(0x01, LD_rr_nn, BC) op(0x01, LD_rr_nn, BC)
op(0x02, LD_irr_a, BC)
op(0x03, INC_rr, BC)
op(0x04, INC_r, B)
op(0x05, DEC_r, B)
op(0x06, LD_r_n, B) op(0x06, LD_r_n, B)
op(0x07, RLCA)
op(0x08, EX_rr_rr, AF, AF_)
op(0x09, ADD_rr_rr, HL, BC)
op(0x0a, LD_a_irr, BC)
op(0x0b, DEC_rr, BC)
op(0x0c, INC_r, C)
op(0x0d, DEC_r, C)
op(0x0e, LD_r_n, C) op(0x0e, LD_r_n, C)
op(0x0f, RRCA)
op(0x11, LD_rr_nn, DE) op(0x11, LD_rr_nn, DE)
op(0x12, LD_irr_a, DE)
op(0x13, INC_rr, DE)
op(0x14, INC_r, D)
op(0x15, DEC_r, D)
op(0x16, LD_r_n, D) op(0x16, LD_r_n, D)
op(0x17, RLA)
op(0x18, JR_c_e, 1) op(0x18, JR_c_e, 1)
op(0x19, ADD_rr_rr, HL, DE)
op(0x1a, LD_a_irr, DE)
op(0x1b, DEC_rr, DE)
op(0x1c, INC_r, E)
op(0x1d, DEC_r, E)
op(0x1e, LD_r_n, E) op(0x1e, LD_r_n, E)
op(0x1f, RRA)
op(0x20, JR_c_e, ZF == 0) op(0x20, JR_c_e, ZF == 0)
op(0x21, LD_rr_nn, HL) op(0x21, LD_rr_nn, HL)
op(0x22, LD_inn_rr, HL)
op(0x23, INC_rr, HL)
op(0x24, INC_r, H)
op(0x25, DEC_r, H)
op(0x26, LD_r_n, H) op(0x26, LD_r_n, H)
op(0x28, JR_c_e, ZF == 1) op(0x28, JR_c_e, ZF == 1)
op(0x29, ADD_rr_rr, HL, HL)
op(0x2a, LD_rr_inn, HL)
op(0x2b, DEC_rr, HL)
op(0x2c, INC_r, L)
op(0x2d, DEC_r, L)
op(0x2e, LD_r_n, L) op(0x2e, LD_r_n, L)
op(0x2f, CPL)
op(0x30, JR_c_e, CF == 0) op(0x30, JR_c_e, CF == 0)
op(0x31, LD_rr_nn, SP) op(0x31, LD_rr_nn, SP)
op(0x32, LD_inn_a) op(0x32, LD_inn_a)
op(0x33, INC_rr, SP)
op(0x34, INC_irr, HL)
op(0x35, DEC_irr, HL)
op(0x36, LD_irr_n, HL) op(0x36, LD_irr_n, HL)
op(0x37, SCF)
op(0x38, JR_c_e, CF == 1) op(0x38, JR_c_e, CF == 1)
op(0x39, ADD_rr_rr, HL, SP)
op(0x3a, LD_a_inn)
op(0x3b, DEC_rr, SP)
op(0x3c, INC_r, A)
op(0x3d, DEC_r, A)
op(0x3e, LD_r_n, A) op(0x3e, LD_r_n, A)
op(0x3f, CCF)
op(0x40, LD_r_r, B, B) op(0x40, LD_r_r, B, B)
op(0x41, LD_r_r, B, C) op(0x41, LD_r_r, B, C)
op(0x42, LD_r_r, B, D) op(0x42, LD_r_r, B, D)
@@ -109,7 +123,7 @@ auto Z80::instruction__(uint8 code) -> void {
op(0x63, LD_r_r, H, E) op(0x63, LD_r_r, H, E)
op(0x64, LD_r_r, H, H) op(0x64, LD_r_r, H, H)
op(0x65, LD_r_r, H, L) op(0x65, LD_r_r, H, L)
op(0x66, LD_r_irr, HD, HL) op(0x66, LD_r_irr, _H, HL)
op(0x67, LD_r_r, H, A) op(0x67, LD_r_r, H, A)
op(0x68, LD_r_r, L, B) op(0x68, LD_r_r, L, B)
op(0x69, LD_r_r, L, C) op(0x69, LD_r_r, L, C)
@@ -117,14 +131,14 @@ auto Z80::instruction__(uint8 code) -> void {
op(0x6b, LD_r_r, L, E) op(0x6b, LD_r_r, L, E)
op(0x6c, LD_r_r, L, H) op(0x6c, LD_r_r, L, H)
op(0x6d, LD_r_r, L, L) op(0x6d, LD_r_r, L, L)
op(0x6e, LD_r_irr, LD, HL) op(0x6e, LD_r_irr, _L, HL)
op(0x6f, LD_r_r, L, A) op(0x6f, LD_r_r, L, A)
op(0x70, LD_irr_r, HL, B) op(0x70, LD_irr_r, HL, B)
op(0x71, LD_irr_r, HL, C) op(0x71, LD_irr_r, HL, C)
op(0x72, LD_irr_r, HL, D) op(0x72, LD_irr_r, HL, D)
op(0x73, LD_irr_r, HL, E) op(0x73, LD_irr_r, HL, E)
op(0x74, LD_irr_r, HL, HD) op(0x74, LD_irr_r, HL, _H)
op(0x75, LD_irr_r, HL, LD) op(0x75, LD_irr_r, HL, _L)
op(0x76, HALT) op(0x76, HALT)
op(0x77, LD_irr_r, HL, A) op(0x77, LD_irr_r, HL, A)
op(0x78, LD_r_r, A, B) op(0x78, LD_r_r, A, B)
@@ -208,6 +222,7 @@ auto Z80::instruction__(uint8 code) -> void {
op(0xdb, IN_a_in) op(0xdb, IN_a_in)
op(0xe2, JP_c_nn, PF == 0) op(0xe2, JP_c_nn, PF == 0)
op(0xea, JP_c_nn, PF == 1) op(0xea, JP_c_nn, PF == 1)
op(0xeb, EX_rr_rr, DE, _HL)
op(0xed, ED, opcode()) op(0xed, ED, opcode())
op(0xf2, JP_c_nn, SF == 0) op(0xf2, JP_c_nn, SF == 0)
op(0xf3, DI) op(0xf3, DI)
@@ -237,30 +252,3 @@ auto Z80::instructionED(uint8 code) -> void {
} }
#undef op #undef op
#undef A
#undef F
#undef B
#undef C
#undef D
#undef E
#undef H
#undef L
#undef HD
#undef LD
#undef AF
#undef BC
#undef DE
#undef HL
#undef SP
#undef CF
#undef NF
#undef PF
#undef VF
#undef XF
#undef HF
#undef YF
#undef ZF
#undef SF

View File

@@ -1,5 +1,5 @@
//legend: //legend:
// a = r.a // a = register A
// c = condition // c = condition
// e = relative operand // e = relative operand
// in = (operand) // in = (operand)
@@ -13,14 +13,14 @@
auto Z80::ADD(uint8 x, uint8 y, bool c) -> uint8 { auto Z80::ADD(uint8 x, uint8 y, bool c) -> uint8 {
uint9 z = x + y + c; uint9 z = x + y + c;
r.p.c = z.bit(8); CF = z.bit(8);
r.p.n = 0; NF = 0;
r.p.v = ~(x ^ y) & (x ^ z) & 0x80; VF = ~(x ^ y) & (x ^ z) & 0x80;
r.p.x = z.bit(3); XF = z.bit(3);
r.p.h = (x ^ y ^ z) & 0x10; HF = (x ^ y ^ z) & 0x10;
r.p.y = z.bit(5); YF = z.bit(5);
r.p.z = (uint8)z == 0; ZF = (uint8)z == 0;
r.p.s = z.bit(7); SF = z.bit(7);
return z; return z;
} }
@@ -28,14 +28,42 @@ auto Z80::ADD(uint8 x, uint8 y, bool c) -> uint8 {
auto Z80::AND(uint8 x, uint8 y) -> uint8 { auto Z80::AND(uint8 x, uint8 y) -> uint8 {
uint8 z = x & y; uint8 z = x & y;
r.p.c = 0; CF = 0;
r.p.n = 0; NF = 0;
r.p.v = z == 0; PF = parity(z);
r.p.x = z.bit(3); XF = z.bit(3);
r.p.h = 1; HF = 1;
r.p.y = z.bit(5); YF = z.bit(5);
r.p.z = z == 0; ZF = z == 0;
r.p.s = z.bit(7); SF = z.bit(7);
return z;
}
auto Z80::DEC(uint8 x) -> uint8 {
uint8 z = x - 1;
NF = 1;
VF = z == 0x7f;
XF = z.bit(3);
HF = z.bits(0,3) == 0x0f;
YF = z.bit(5);
ZF = z == 0;
SF = z.bit(7);
return z;
}
auto Z80::INC(uint8 x) -> uint8 {
uint8 z = x + 1;
NF = 0;
VF = z == 0x80;
XF = z.bit(3);
HF = z.bits(0,3) == 0x00;
YF = z.bit(5);
ZF = z == 0;
SF = z.bit(7);
return z; return z;
} }
@@ -43,14 +71,14 @@ auto Z80::AND(uint8 x, uint8 y) -> uint8 {
auto Z80::OR(uint8 x, uint8 y) -> uint8 { auto Z80::OR(uint8 x, uint8 y) -> uint8 {
uint8 z = x | y; uint8 z = x | y;
r.p.c = 0; CF = 0;
r.p.n = 0; NF = 0;
r.p.v = z == 0; PF = parity(z);
r.p.x = z.bit(3); XF = z.bit(3);
r.p.h = 0; HF = 0;
r.p.y = z.bit(5); YF = z.bit(5);
r.p.z = z == 0; ZF = z == 0;
r.p.s = z.bit(7); SF = z.bit(7);
return z; return z;
} }
@@ -58,14 +86,14 @@ auto Z80::OR(uint8 x, uint8 y) -> uint8 {
auto Z80::SUB(uint8 x, uint8 y, bool c) -> uint8 { auto Z80::SUB(uint8 x, uint8 y, bool c) -> uint8 {
uint9 z = x - y - c; uint9 z = x - y - c;
r.p.c = z.bit(8); CF = z.bit(8);
r.p.n = 1; NF = 1;
r.p.v = (x ^ y) & (x ^ z) & 0x80; VF = (x ^ y) & (x ^ z) & 0x80;
r.p.x = z.bit(3); XF = z.bit(3);
r.p.h = (x ^ y ^ z) & 0x10; HF = (x ^ y ^ z) & 0x10;
r.p.y = z.bit(5); YF = z.bit(5);
r.p.z = (uint8)z == 0; ZF = (uint8)z == 0;
r.p.s = z.bit(7); SF = z.bit(7);
return z; return z;
} }
@@ -73,14 +101,14 @@ auto Z80::SUB(uint8 x, uint8 y, bool c) -> uint8 {
auto Z80::XOR(uint8 x, uint8 y) -> uint8 { auto Z80::XOR(uint8 x, uint8 y) -> uint8 {
uint8 z = x ^ y; uint8 z = x ^ y;
r.p.c = 0; CF = 0;
r.p.n = 0; NF = 0;
r.p.p = parity(z); PF = parity(z);
r.p.x = z.bit(3); XF = z.bit(3);
r.p.h = 0; HF = 0;
r.p.y = z.bit(5); YF = z.bit(5);
r.p.z = z == 0; ZF = z == 0;
r.p.s = z.bit(7); SF = z.bit(7);
return z; return z;
} }
@@ -88,39 +116,77 @@ auto Z80::XOR(uint8 x, uint8 y) -> uint8 {
// //
auto Z80::instructionADC_a_irr(uint16& x) -> void { auto Z80::instructionADC_a_irr(uint16& x) -> void {
r.a = ADD(r.a, read(displace(x)), r.p.c); A = ADD(A, read(displace(x)), CF);
} }
auto Z80::instructionADC_a_r(uint8& x) -> void { auto Z80::instructionADC_a_r(uint8& x) -> void {
r.a = ADD(r.a, x, r.p.c); A = ADD(A, x, CF);
} }
auto Z80::instructionADD_a_irr(uint16& x) -> void { auto Z80::instructionADD_a_irr(uint16& x) -> void {
r.a = ADD(r.a, read(displace(x))); A = ADD(A, read(displace(x)));
} }
auto Z80::instructionADD_a_r(uint8& x) -> void { auto Z80::instructionADD_a_r(uint8& x) -> void {
r.a = ADD(r.a, x); A = ADD(A, x);
}
auto Z80::instructionADD_rr_rr(uint16& x, uint16& y) -> void {
wait(4);
x.byte(0) = ADD(x.byte(0), y.byte(0));
wait(3);
x.byte(1) = ADD(x.byte(1), y.byte(1), CF);
} }
auto Z80::instructionAND_a_irr(uint16& x) -> void { auto Z80::instructionAND_a_irr(uint16& x) -> void {
r.a = AND(r.a, read(displace(x))); A = AND(A, read(displace(x)));
} }
auto Z80::instructionAND_a_r(uint8& x) -> void { auto Z80::instructionAND_a_r(uint8& x) -> void {
r.a = AND(r.a, x); A = AND(A, x);
}
auto Z80::instructionCCF() -> void {
CF = !CF;
NF = 0;
HF = !CF;
} }
auto Z80::instructionCP_a_irr(uint16& x) -> void { auto Z80::instructionCP_a_irr(uint16& x) -> void {
SUB(r.a, read(displace(x))); SUB(A, read(displace(x)));
} }
auto Z80::instructionCP_a_n() -> void { auto Z80::instructionCP_a_n() -> void {
SUB(r.a, operand()); SUB(A, operand());
} }
auto Z80::instructionCP_a_r(uint8& x) -> void { auto Z80::instructionCP_a_r(uint8& x) -> void {
SUB(r.a, x); SUB(A, x);
}
auto Z80::instructionCPL() -> void {
A = ~A;
NF = 1;
XF = A.bit(3);
HF = 1;
YF = A.bit(5);
}
auto Z80::instructionDEC_irr(uint16& x) -> void {
auto addr = displace(x);
auto data = read(addr);
wait(1);
write(addr, DEC(data));
}
auto Z80::instructionDEC_r(uint8& x) -> void {
x = DEC(x);
}
auto Z80::instructionDEC_rr(uint16& x) -> void {
wait(2);
x--;
} }
auto Z80::instructionDI() -> void { auto Z80::instructionDI() -> void {
@@ -133,6 +199,12 @@ auto Z80::instructionEI() -> void {
r.iff2 = 1; r.iff2 = 1;
} }
auto Z80::instructionEX_rr_rr(uint16& x, uint16& y) -> void {
auto z = x;
x = y;
y = z;
}
auto Z80::instructionHALT() -> void { auto Z80::instructionHALT() -> void {
r.halt = 1; r.halt = 1;
} }
@@ -143,7 +215,23 @@ auto Z80::instructionIM_o(uint2 code) -> void {
} }
auto Z80::instructionIN_a_in() -> void { auto Z80::instructionIN_a_in() -> void {
r.a = in(operand()); A = in(operand());
}
auto Z80::instructionINC_irr(uint16& x) -> void {
auto addr = displace(x);
auto data = read(addr);
wait(1);
write(addr, INC(data));
}
auto Z80::instructionINC_r(uint8& x) -> void {
x = INC(x);
}
auto Z80::instructionINC_rr(uint16& x) -> void {
wait(2);
x++;
} }
auto Z80::instructionJP_c_nn(bool c) -> void { auto Z80::instructionJP_c_nn(bool c) -> void {
@@ -156,8 +244,26 @@ auto Z80::instructionJR_c_e(bool c) -> void {
if(c) wait(5), r.pc += (int8)e; if(c) wait(5), r.pc += (int8)e;
} }
auto Z80::instructionLD_a_inn() -> void {
A = read(operands());
}
auto Z80::instructionLD_a_irr(uint16& x) -> void {
A = read(displace(x));
}
auto Z80::instructionLD_inn_a() -> void { auto Z80::instructionLD_inn_a() -> void {
write(operands(), r.a); write(operands(), A);
}
auto Z80::instructionLD_inn_rr(uint16& x) -> void {
auto addr = operands();
write(addr + 0, x >> 0);
write(addr + 1, x >> 8);
}
auto Z80::instructionLD_irr_a(uint16& x) -> void {
write(displace(x), A);
} }
auto Z80::instructionLD_irr_n(uint16& x) -> void { auto Z80::instructionLD_irr_n(uint16& x) -> void {
@@ -181,6 +287,12 @@ auto Z80::instructionLD_r_r(uint8& x, uint8& y) -> void {
x = y; x = y;
} }
auto Z80::instructionLD_rr_inn(uint16& x) -> void {
auto addr = operands();
x.byte(0) = read(addr + 0);
x.byte(1) = read(addr + 1);
}
auto Z80::instructionLD_rr_nn(uint16& x) -> void { auto Z80::instructionLD_rr_nn(uint16& x) -> void {
x = operands(); x = operands();
} }
@@ -189,33 +301,83 @@ auto Z80::instructionNOP() -> void {
} }
auto Z80::instructionOR_a_irr(uint16& x) -> void { auto Z80::instructionOR_a_irr(uint16& x) -> void {
r.a = OR(r.a, read(displace(x))); A = OR(A, read(displace(x)));
} }
auto Z80::instructionOR_a_r(uint8& x) -> void { auto Z80::instructionOR_a_r(uint8& x) -> void {
r.a = OR(r.a, x); A = OR(A, x);
}
auto Z80::instructionRLA() -> void {
bool c = A.bit(7);
A = A << 1 | CF;
CF = c;
NF = 0;
XF = A.bit(3);
HF = 0;
YF = A.bit(5);
}
auto Z80::instructionRLCA() -> void {
bool c = A.bit(7);
A = A << 1 | c;
CF = c;
NF = 0;
XF = A.bit(3);
HF = 0;
YF = A.bit(5);
}
auto Z80::instructionRRA() -> void {
bool c = A.bit(0);
A = CF << 7 | A >> 1;
CF = c;
NF = 0;
XF = A.bit(3);
HF = 0;
YF = A.bit(5);
}
auto Z80::instructionRRCA() -> void {
bool c = A.bit(0);
A = c << 7 | A >> 1;
CF = c;
NF = 0;
XF = A.bit(3);
HF = 0;
YF = A.bit(5);
} }
auto Z80::instructionSBC_a_irr(uint16& x) -> void { auto Z80::instructionSBC_a_irr(uint16& x) -> void {
r.a = SUB(r.a, read(displace(x)), r.p.c); A = SUB(A, read(displace(x)), CF);
} }
auto Z80::instructionSBC_a_r(uint8& x) -> void { auto Z80::instructionSBC_a_r(uint8& x) -> void {
r.a = SUB(r.a, x, r.p.c); A = SUB(A, x, CF);
}
auto Z80::instructionSCF() -> void {
CF = 1;
NF = 0;
HF = 0;
} }
auto Z80::instructionSUB_a_irr(uint16& x) -> void { auto Z80::instructionSUB_a_irr(uint16& x) -> void {
r.a = SUB(r.a, read(displace(x))); A = SUB(A, read(displace(x)));
} }
auto Z80::instructionSUB_a_r(uint8& x) -> void { auto Z80::instructionSUB_a_r(uint8& x) -> void {
r.a = SUB(r.a, x); A = SUB(A, x);
} }
auto Z80::instructionXOR_a_irr(uint16& x) -> void { auto Z80::instructionXOR_a_irr(uint16& x) -> void {
r.a = XOR(r.a, read(displace(x))); A = XOR(A, read(displace(x)));
} }
auto Z80::instructionXOR_a_r(uint8& x) -> void { auto Z80::instructionXOR_a_r(uint8& x) -> void {
r.a = XOR(r.a, x); A = XOR(A, x);
} }

View File

@@ -18,7 +18,7 @@ auto Z80::operands() -> uint16 {
} }
auto Z80::displace(uint16& x) -> uint16 { auto Z80::displace(uint16& x) -> uint16 {
if(!r.prefix) return x; if(&x != &r.ix.word && &x != &r.iy.word) return x;
auto d = read(x); auto d = read(x);
wait(5); wait(5);
return x + (int8)d; return x + (int8)d;

View File

@@ -0,0 +1,51 @@
#define AF r.af.word
#define BC r.bc.word
#define DE r.de.word
#define HL r.hlp->word
#define A r.af.byte.hi
#define F r.af.byte.lo
#define B r.bc.byte.hi
#define C r.bc.byte.lo
#define D r.de.byte.hi
#define E r.de.byte.lo
#define H r.hlp->byte.hi
#define L r.hlp->byte.lo
#define _H r.hl.byte.hi
#define _L r.hl.byte.lo
#define _HL r.hl.word
#define AF_ r.af_.word
#define BC_ r.bc_.word
#define DE_ r.de_.word
#define HL_ r.hl_.word
#define A_ r.af_.byte.hi
#define F_ r.af_.byte.lo
#define B_ r.bc_.byte.hi
#define C_ r.bc_.byte.lo
#define D_ r.de_.byte.hi
#define E_ r.de_.byte.lo
#define H_ r.hl_.byte.hi
#define L_ r.hl_.byte.lo
#define SP r.sp
#define PC r.pc
#define IX r.ix.word
#define IY r.iy.word
#define IR r.ir.word
#define I r.ir.byte.hi
#define R r.ir.byte.lo
#define CF r.af.byte.lo.bit(0)
#define NF r.af.byte.lo.bit(1)
#define PF r.af.byte.lo.bit(2)
#define VF r.af.byte.lo.bit(2)
#define XF r.af.byte.lo.bit(3)
#define HF r.af.byte.lo.bit(4)
#define YF r.af.byte.lo.bit(5)
#define ZF r.af.byte.lo.bit(6)
#define SF r.af.byte.lo.bit(7)

View File

@@ -3,30 +3,18 @@
namespace Processor { namespace Processor {
#include "disassembler.cpp"
#include "registers.cpp"
#include "memory.cpp" #include "memory.cpp"
#include "instruction.cpp" #include "instruction.cpp"
#include "instructions.cpp" #include "instructions.cpp"
#include "disassembler.cpp"
auto Z80::power() -> void { auto Z80::power() -> void {
} }
auto Z80::reset() -> void { auto Z80::reset() -> void {
r.af = 0x0000; memory::fill(&r, sizeof(Registers));
r.bc = 0x0000; r.hlp = &r.hl;
r.de = 0x0000;
r.hl = 0x0000;
r.ir = 0x0000;
r.ix = 0x0000;
r.iy = 0x0000;
r.sp = 0x0000;
r.pc = 0x0000;
r.halt = 0;
r.iff1 = 0;
r.iff2 = 0;
r.im = 0;
instructionsExecuted = 0; instructionsExecuted = 0;
} }

View File

@@ -41,6 +41,8 @@ struct Z80 {
//instructions.cpp //instructions.cpp
auto ADD(uint8, uint8, bool = false) -> uint8; auto ADD(uint8, uint8, bool = false) -> uint8;
auto AND(uint8, uint8) -> uint8; auto AND(uint8, uint8) -> uint8;
auto DEC(uint8) -> uint8;
auto INC(uint8) -> uint8;
auto OR (uint8, uint8) -> uint8; auto OR (uint8, uint8) -> uint8;
auto SUB(uint8, uint8, bool = false) -> uint8; auto SUB(uint8, uint8, bool = false) -> uint8;
auto XOR(uint8, uint8) -> uint8; auto XOR(uint8, uint8) -> uint8;
@@ -49,30 +51,50 @@ struct Z80 {
auto instructionADC_a_r(uint8&) -> void; auto instructionADC_a_r(uint8&) -> void;
auto instructionADD_a_irr(uint16&) -> void; auto instructionADD_a_irr(uint16&) -> void;
auto instructionADD_a_r(uint8&) -> void; auto instructionADD_a_r(uint8&) -> void;
auto instructionADD_rr_rr(uint16&, uint16&) -> void;
auto instructionAND_a_irr(uint16&) -> void; auto instructionAND_a_irr(uint16&) -> void;
auto instructionAND_a_r(uint8&) -> void; auto instructionAND_a_r(uint8&) -> void;
auto instructionCCF() -> void;
auto instructionCP_a_irr(uint16& x) -> void; auto instructionCP_a_irr(uint16& x) -> void;
auto instructionCP_a_n() -> void; auto instructionCP_a_n() -> void;
auto instructionCP_a_r(uint8& x) -> void; auto instructionCP_a_r(uint8& x) -> void;
auto instructionCPL() -> void;
auto instructionDEC_irr(uint16&) -> void;
auto instructionDEC_r(uint8&) -> void;
auto instructionDEC_rr(uint16&) -> void;
auto instructionDI() -> void; auto instructionDI() -> void;
auto instructionEI() -> void; auto instructionEI() -> void;
auto instructionEX_rr_rr(uint16&, uint16&) -> void;
auto instructionHALT() -> void; auto instructionHALT() -> void;
auto instructionIM_o(uint2) -> void; auto instructionIM_o(uint2) -> void;
auto instructionIN_a_in() -> void; auto instructionIN_a_in() -> void;
auto instructionINC_irr(uint16&) -> void;
auto instructionINC_r(uint8&) -> void;
auto instructionINC_rr(uint16&) -> void;
auto instructionJP_c_nn(bool) -> void; auto instructionJP_c_nn(bool) -> void;
auto instructionJR_c_e(bool) -> void; auto instructionJR_c_e(bool) -> void;
auto instructionLD_a_inn() -> void;
auto instructionLD_a_irr(uint16& x) -> void;
auto instructionLD_inn_a() -> void; auto instructionLD_inn_a() -> void;
auto instructionLD_inn_rr(uint16&) -> void;
auto instructionLD_irr_a(uint16&) -> void;
auto instructionLD_irr_n(uint16&) -> void; auto instructionLD_irr_n(uint16&) -> void;
auto instructionLD_irr_r(uint16&, uint8&) -> void; auto instructionLD_irr_r(uint16&, uint8&) -> void;
auto instructionLD_r_n(uint8&) -> void; auto instructionLD_r_n(uint8&) -> void;
auto instructionLD_r_irr(uint8&, uint16&) -> void; auto instructionLD_r_irr(uint8&, uint16&) -> void;
auto instructionLD_r_r(uint8&, uint8&) -> void; auto instructionLD_r_r(uint8&, uint8&) -> void;
auto instructionLD_rr_inn(uint16&) -> void;
auto instructionLD_rr_nn(uint16&) -> void; auto instructionLD_rr_nn(uint16&) -> void;
auto instructionNOP() -> void; auto instructionNOP() -> void;
auto instructionOR_a_irr(uint16&) -> void; auto instructionOR_a_irr(uint16&) -> void;
auto instructionOR_a_r(uint8&) -> void; auto instructionOR_a_r(uint8&) -> void;
auto instructionRLA() -> void;
auto instructionRLCA() -> void;
auto instructionRRA() -> void;
auto instructionRRCA() -> void;
auto instructionSBC_a_irr(uint16&) -> void; auto instructionSBC_a_irr(uint16&) -> void;
auto instructionSBC_a_r(uint8&) -> void; auto instructionSBC_a_r(uint8&) -> void;
auto instructionSCF() -> void;
auto instructionSUB_a_irr(uint16&) -> void; auto instructionSUB_a_irr(uint16&) -> void;
auto instructionSUB_a_r(uint8&) -> void; auto instructionSUB_a_r(uint8&) -> void;
auto instructionXOR_a_irr(uint16&) -> void; auto instructionXOR_a_irr(uint16&) -> void;
@@ -85,62 +107,28 @@ struct Z80 {
auto disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string; auto disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string;
struct Registers { struct Registers {
union { union Pair {
uint16_t af; Pair() : word(0) {}
struct { uint8_t order_msb2(a, f); }; uint16 word;
union { struct Byte { uint8 order_msb2(hi, lo); } byte;
BooleanBitField<uint16_t, 0> c; //carry
BooleanBitField<uint16_t, 1> n; //add / subtract
BooleanBitField<uint16_t, 2> p; //parity
BooleanBitField<uint16_t, 2> v; //overflow
BooleanBitField<uint16_t, 3> x; //unused (copy of bit 3 of result)
BooleanBitField<uint16_t, 4> h; //half-carry
BooleanBitField<uint16_t, 5> y; //unused (copy of bit 5 of result)
BooleanBitField<uint16_t, 6> z; //zero
BooleanBitField<uint16_t, 7> s; //sign
} p;
}; };
union { Pair af, af_;
uint16_t bc; Pair bc, bc_;
struct { uint8_t order_msb2(b, c); }; Pair de, de_;
}; Pair hl, hl_;
Pair ix;
union { Pair iy;
uint16_t de; Pair ir;
struct { uint8_t order_msb2(d, e); }; uint16 sp;
}; uint16 pc;
union {
uint16_t hl;
struct { uint8_t order_msb2(h, l); };
};
union {
uint16_t ix;
struct { uint8_t order_msb2(ixh, ixl); };
};
union {
uint16_t iy;
struct { uint8_t order_msb2(iyh, iyl); };
};
union {
uint16_t ir;
struct { uint8_t order_msb2(i, r); };
};
uint16_t sp;
uint16_t pc;
boolean halt; //HALT instruction executed boolean halt; //HALT instruction executed
boolean iff1; //interrupt flip-flop 1 boolean iff1; //interrupt flip-flop 1
boolean iff2; //interrupt flip-flop 2 boolean iff2; //interrupt flip-flop 2
uint2 im; //interrupt mode (0-2) uint2 im; //interrupt mode (0-2)
uint8 prefix; Pair* hlp = nullptr;
uint8 flag;
} r; } r;
Bus* bus = nullptr; Bus* bus = nullptr;