mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
2fbbccf985
commit
d6e9d94ec3
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
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 License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -23,12 +23,12 @@ auto Z80::disassemble(uint16 pc) -> string {
|
|||
s.append(pad(disassemble__(pc, prefix, code), -18L, ' '));
|
||||
|
||||
finish:
|
||||
s.append(" AF:", hex(r.af, 4L));
|
||||
s.append(" BC:", hex(r.bc, 4L));
|
||||
s.append(" DE:", hex(r.de, 4L));
|
||||
s.append(" HL:", hex(r.hl, 4L));
|
||||
s.append(" IX:", hex(r.ix, 4L));
|
||||
s.append(" IY:", hex(r.iy, 4L));
|
||||
s.append(" AF:", hex(r.af.word, 4L));
|
||||
s.append(" BC:", hex(r.bc.word, 4L));
|
||||
s.append(" DE:", hex(r.de.word, 4L));
|
||||
s.append(" HL:", hex(r.hl.word, 4L));
|
||||
s.append(" IX:", hex(r.ix.word, 4L));
|
||||
s.append(" IY:", hex(r.iy.word, 4L));
|
||||
s.append(" SP:", hex(r.sp, 4L));
|
||||
|
||||
return s;
|
||||
|
@ -50,16 +50,27 @@ auto Z80::disassemble(uint16 pc) -> string {
|
|||
#define E "e"
|
||||
#define H prefix == 0xdd ? "ixh" : prefix == 0xfd ? "iyh" : "h"
|
||||
#define L prefix == 0xdd ? "ixl" : prefix == 0xfd ? "iyl" : "l"
|
||||
#define HD "h"
|
||||
#define LD "l"
|
||||
#define _H "h"
|
||||
#define _L "l"
|
||||
#define _HL "hl"
|
||||
|
||||
#define AF "af"
|
||||
#define BC "bc"
|
||||
#define DE "de"
|
||||
#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 ISP "(sp)"
|
||||
|
||||
auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string {
|
||||
auto byte = [&] {
|
||||
|
@ -88,23 +99,66 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string {
|
|||
switch(code) {
|
||||
op(0x00, "nop ")
|
||||
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(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(0x0f, "rrca")
|
||||
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(0x17, "rla ")
|
||||
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(0x1f, "rra ")
|
||||
op(0x20, "jr ", "nz", R)
|
||||
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(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(0x2f, "cpl ")
|
||||
op(0x30, "jr ", "nc", R)
|
||||
op(0x31, "ld ", SP, NN)
|
||||
op(0x32, "ld ", INN, A)
|
||||
op(0x33, "inc ", SP)
|
||||
op(0x34, "inc ", IHL)
|
||||
op(0x35, "dec ", IHL)
|
||||
op(0x36, "ld ", IHL, N)
|
||||
op(0x37, "scf ")
|
||||
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(0x3f, "ccf ")
|
||||
op(0x40, "ld ", B, B)
|
||||
op(0x41, "ld ", B, C)
|
||||
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(0x64, "ld ", H, H)
|
||||
op(0x65, "ld ", H, L)
|
||||
op(0x66, "ld ", HD, IHL)
|
||||
op(0x66, "ld ", _H, IHL)
|
||||
op(0x67, "ld ", H, A)
|
||||
op(0x68, "ld ", L, B)
|
||||
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(0x6c, "ld ", L, H)
|
||||
op(0x6d, "ld ", L, L)
|
||||
op(0x6e, "ld ", LD, IHL)
|
||||
op(0x6e, "ld ", _L, IHL)
|
||||
op(0x6f, "ld ", L, A)
|
||||
op(0x70, "ld ", IHL, B)
|
||||
op(0x71, "ld ", IHL, C)
|
||||
op(0x72, "ld ", IHL, D)
|
||||
op(0x73, "ld ", IHL, E)
|
||||
op(0x74, "ld ", IHL, HD)
|
||||
op(0x75, "ld ", IHL, LD)
|
||||
op(0x74, "ld ", IHL, _H)
|
||||
op(0x75, "ld ", IHL, _L)
|
||||
op(0x76, "halt")
|
||||
op(0x77, "ld ", IHL, A)
|
||||
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(0xe2, "jp ", "po", NN)
|
||||
op(0xea, "jp ", "pe", NN)
|
||||
op(0xeb, "ex ", DE, _HL)
|
||||
op(0xed, "ed: ")
|
||||
op(0xf2, "jp ", "p", NN)
|
||||
op(0xf3, "di ")
|
||||
|
@ -290,13 +345,24 @@ auto Z80::disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string {
|
|||
#undef E
|
||||
#undef H
|
||||
#undef L
|
||||
#undef HD
|
||||
#undef LD
|
||||
#undef _H
|
||||
#undef _L
|
||||
#undef _HL
|
||||
|
||||
#undef AF
|
||||
#undef BC
|
||||
#undef DE
|
||||
#undef HL
|
||||
#undef SP
|
||||
|
||||
#undef AF_
|
||||
#undef BC_
|
||||
#undef DE_
|
||||
#undef HL_
|
||||
|
||||
#undef SP
|
||||
#undef PC
|
||||
|
||||
#undef IBC
|
||||
#undef IDE
|
||||
#undef IHL
|
||||
#undef ISP
|
||||
|
|
|
@ -13,64 +13,78 @@ auto Z80::instruction() -> void {
|
|||
instructionsExecuted++;
|
||||
|
||||
auto code = opcode();
|
||||
if(code == 0xdd || code == 0xfd) {
|
||||
r.prefix = code;
|
||||
return;
|
||||
}
|
||||
if(code == 0xdd) { r.hlp = &r.ix; return; }
|
||||
if(code == 0xfd) { r.hlp = &r.iy; return; }
|
||||
instruction__(code);
|
||||
r.prefix = 0x00;
|
||||
r.hlp = &r.hl;
|
||||
}
|
||||
|
||||
#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 {
|
||||
switch(code) {
|
||||
op(0x00, NOP)
|
||||
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(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(0x0f, RRCA)
|
||||
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(0x17, RLA)
|
||||
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(0x1f, RRA)
|
||||
op(0x20, JR_c_e, ZF == 0)
|
||||
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(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(0x2f, CPL)
|
||||
op(0x30, JR_c_e, CF == 0)
|
||||
op(0x31, LD_rr_nn, SP)
|
||||
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(0x37, SCF)
|
||||
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(0x3f, CCF)
|
||||
op(0x40, LD_r_r, B, B)
|
||||
op(0x41, LD_r_r, B, C)
|
||||
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(0x64, LD_r_r, H, H)
|
||||
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(0x68, LD_r_r, L, B)
|
||||
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(0x6c, LD_r_r, L, H)
|
||||
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(0x70, LD_irr_r, HL, B)
|
||||
op(0x71, LD_irr_r, HL, C)
|
||||
op(0x72, LD_irr_r, HL, D)
|
||||
op(0x73, LD_irr_r, HL, E)
|
||||
op(0x74, LD_irr_r, HL, HD)
|
||||
op(0x75, LD_irr_r, HL, LD)
|
||||
op(0x74, LD_irr_r, HL, _H)
|
||||
op(0x75, LD_irr_r, HL, _L)
|
||||
op(0x76, HALT)
|
||||
op(0x77, LD_irr_r, HL, A)
|
||||
op(0x78, LD_r_r, A, B)
|
||||
|
@ -208,6 +222,7 @@ auto Z80::instruction__(uint8 code) -> void {
|
|||
op(0xdb, IN_a_in)
|
||||
op(0xe2, JP_c_nn, PF == 0)
|
||||
op(0xea, JP_c_nn, PF == 1)
|
||||
op(0xeb, EX_rr_rr, DE, _HL)
|
||||
op(0xed, ED, opcode())
|
||||
op(0xf2, JP_c_nn, SF == 0)
|
||||
op(0xf3, DI)
|
||||
|
@ -237,30 +252,3 @@ auto Z80::instructionED(uint8 code) -> void {
|
|||
}
|
||||
|
||||
#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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//legend:
|
||||
// a = r.a
|
||||
// a = register A
|
||||
// c = condition
|
||||
// e = relative operand
|
||||
// in = (operand)
|
||||
|
@ -13,14 +13,14 @@
|
|||
auto Z80::ADD(uint8 x, uint8 y, bool c) -> uint8 {
|
||||
uint9 z = x + y + c;
|
||||
|
||||
r.p.c = z.bit(8);
|
||||
r.p.n = 0;
|
||||
r.p.v = ~(x ^ y) & (x ^ z) & 0x80;
|
||||
r.p.x = z.bit(3);
|
||||
r.p.h = (x ^ y ^ z) & 0x10;
|
||||
r.p.y = z.bit(5);
|
||||
r.p.z = (uint8)z == 0;
|
||||
r.p.s = z.bit(7);
|
||||
CF = z.bit(8);
|
||||
NF = 0;
|
||||
VF = ~(x ^ y) & (x ^ z) & 0x80;
|
||||
XF = z.bit(3);
|
||||
HF = (x ^ y ^ z) & 0x10;
|
||||
YF = z.bit(5);
|
||||
ZF = (uint8)z == 0;
|
||||
SF = z.bit(7);
|
||||
|
||||
return z;
|
||||
}
|
||||
|
@ -28,14 +28,42 @@ auto Z80::ADD(uint8 x, uint8 y, bool c) -> uint8 {
|
|||
auto Z80::AND(uint8 x, uint8 y) -> uint8 {
|
||||
uint8 z = x & y;
|
||||
|
||||
r.p.c = 0;
|
||||
r.p.n = 0;
|
||||
r.p.v = z == 0;
|
||||
r.p.x = z.bit(3);
|
||||
r.p.h = 1;
|
||||
r.p.y = z.bit(5);
|
||||
r.p.z = z == 0;
|
||||
r.p.s = z.bit(7);
|
||||
CF = 0;
|
||||
NF = 0;
|
||||
PF = parity(z);
|
||||
XF = z.bit(3);
|
||||
HF = 1;
|
||||
YF = z.bit(5);
|
||||
ZF = z == 0;
|
||||
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;
|
||||
}
|
||||
|
@ -43,14 +71,14 @@ auto Z80::AND(uint8 x, uint8 y) -> uint8 {
|
|||
auto Z80::OR(uint8 x, uint8 y) -> uint8 {
|
||||
uint8 z = x | y;
|
||||
|
||||
r.p.c = 0;
|
||||
r.p.n = 0;
|
||||
r.p.v = z == 0;
|
||||
r.p.x = z.bit(3);
|
||||
r.p.h = 0;
|
||||
r.p.y = z.bit(5);
|
||||
r.p.z = z == 0;
|
||||
r.p.s = z.bit(7);
|
||||
CF = 0;
|
||||
NF = 0;
|
||||
PF = parity(z);
|
||||
XF = z.bit(3);
|
||||
HF = 0;
|
||||
YF = z.bit(5);
|
||||
ZF = z == 0;
|
||||
SF = z.bit(7);
|
||||
|
||||
return z;
|
||||
}
|
||||
|
@ -58,14 +86,14 @@ auto Z80::OR(uint8 x, uint8 y) -> uint8 {
|
|||
auto Z80::SUB(uint8 x, uint8 y, bool c) -> uint8 {
|
||||
uint9 z = x - y - c;
|
||||
|
||||
r.p.c = z.bit(8);
|
||||
r.p.n = 1;
|
||||
r.p.v = (x ^ y) & (x ^ z) & 0x80;
|
||||
r.p.x = z.bit(3);
|
||||
r.p.h = (x ^ y ^ z) & 0x10;
|
||||
r.p.y = z.bit(5);
|
||||
r.p.z = (uint8)z == 0;
|
||||
r.p.s = z.bit(7);
|
||||
CF = z.bit(8);
|
||||
NF = 1;
|
||||
VF = (x ^ y) & (x ^ z) & 0x80;
|
||||
XF = z.bit(3);
|
||||
HF = (x ^ y ^ z) & 0x10;
|
||||
YF = z.bit(5);
|
||||
ZF = (uint8)z == 0;
|
||||
SF = z.bit(7);
|
||||
|
||||
return z;
|
||||
}
|
||||
|
@ -73,14 +101,14 @@ auto Z80::SUB(uint8 x, uint8 y, bool c) -> uint8 {
|
|||
auto Z80::XOR(uint8 x, uint8 y) -> uint8 {
|
||||
uint8 z = x ^ y;
|
||||
|
||||
r.p.c = 0;
|
||||
r.p.n = 0;
|
||||
r.p.p = parity(z);
|
||||
r.p.x = z.bit(3);
|
||||
r.p.h = 0;
|
||||
r.p.y = z.bit(5);
|
||||
r.p.z = z == 0;
|
||||
r.p.s = z.bit(7);
|
||||
CF = 0;
|
||||
NF = 0;
|
||||
PF = parity(z);
|
||||
XF = z.bit(3);
|
||||
HF = 0;
|
||||
YF = z.bit(5);
|
||||
ZF = z == 0;
|
||||
SF = z.bit(7);
|
||||
|
||||
return z;
|
||||
}
|
||||
|
@ -88,39 +116,77 @@ auto Z80::XOR(uint8 x, uint8 y) -> uint8 {
|
|||
//
|
||||
|
||||
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 {
|
||||
r.a = ADD(r.a, x, r.p.c);
|
||||
A = ADD(A, x, CF);
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
r.a = AND(r.a, read(displace(x)));
|
||||
A = AND(A, read(displace(x)));
|
||||
}
|
||||
|
||||
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 {
|
||||
SUB(r.a, read(displace(x)));
|
||||
SUB(A, read(displace(x)));
|
||||
}
|
||||
|
||||
auto Z80::instructionCP_a_n() -> void {
|
||||
SUB(r.a, operand());
|
||||
SUB(A, operand());
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -133,6 +199,12 @@ auto Z80::instructionEI() -> void {
|
|||
r.iff2 = 1;
|
||||
}
|
||||
|
||||
auto Z80::instructionEX_rr_rr(uint16& x, uint16& y) -> void {
|
||||
auto z = x;
|
||||
x = y;
|
||||
y = z;
|
||||
}
|
||||
|
||||
auto Z80::instructionHALT() -> void {
|
||||
r.halt = 1;
|
||||
}
|
||||
|
@ -143,7 +215,23 @@ auto Z80::instructionIM_o(uint2 code) -> 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 {
|
||||
|
@ -156,8 +244,26 @@ auto Z80::instructionJR_c_e(bool c) -> void {
|
|||
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 {
|
||||
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 {
|
||||
|
@ -181,6 +287,12 @@ auto Z80::instructionLD_r_r(uint8& x, uint8& y) -> void {
|
|||
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 {
|
||||
x = operands();
|
||||
}
|
||||
|
@ -189,33 +301,83 @@ auto Z80::instructionNOP() -> 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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
r.a = SUB(r.a, read(displace(x)));
|
||||
A = SUB(A, read(displace(x)));
|
||||
}
|
||||
|
||||
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 {
|
||||
r.a = XOR(r.a, read(displace(x)));
|
||||
A = XOR(A, read(displace(x)));
|
||||
}
|
||||
|
||||
auto Z80::instructionXOR_a_r(uint8& x) -> void {
|
||||
r.a = XOR(r.a, x);
|
||||
A = XOR(A, x);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ auto Z80::operands() -> 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);
|
||||
wait(5);
|
||||
return x + (int8)d;
|
||||
|
|
|
@ -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)
|
|
@ -3,30 +3,18 @@
|
|||
|
||||
namespace Processor {
|
||||
|
||||
#include "disassembler.cpp"
|
||||
#include "registers.cpp"
|
||||
#include "memory.cpp"
|
||||
#include "instruction.cpp"
|
||||
#include "instructions.cpp"
|
||||
#include "disassembler.cpp"
|
||||
|
||||
auto Z80::power() -> void {
|
||||
}
|
||||
|
||||
auto Z80::reset() -> void {
|
||||
r.af = 0x0000;
|
||||
r.bc = 0x0000;
|
||||
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;
|
||||
|
||||
memory::fill(&r, sizeof(Registers));
|
||||
r.hlp = &r.hl;
|
||||
instructionsExecuted = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ struct Z80 {
|
|||
//instructions.cpp
|
||||
auto ADD(uint8, uint8, bool = false) -> uint8;
|
||||
auto AND(uint8, uint8) -> uint8;
|
||||
auto DEC(uint8) -> uint8;
|
||||
auto INC(uint8) -> uint8;
|
||||
auto OR (uint8, uint8) -> uint8;
|
||||
auto SUB(uint8, uint8, bool = false) -> uint8;
|
||||
auto XOR(uint8, uint8) -> uint8;
|
||||
|
@ -49,30 +51,50 @@ struct Z80 {
|
|||
auto instructionADC_a_r(uint8&) -> void;
|
||||
auto instructionADD_a_irr(uint16&) -> void;
|
||||
auto instructionADD_a_r(uint8&) -> void;
|
||||
auto instructionADD_rr_rr(uint16&, uint16&) -> void;
|
||||
auto instructionAND_a_irr(uint16&) -> void;
|
||||
auto instructionAND_a_r(uint8&) -> void;
|
||||
auto instructionCCF() -> void;
|
||||
auto instructionCP_a_irr(uint16& x) -> void;
|
||||
auto instructionCP_a_n() -> 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 instructionEI() -> void;
|
||||
auto instructionEX_rr_rr(uint16&, uint16&) -> void;
|
||||
auto instructionHALT() -> void;
|
||||
auto instructionIM_o(uint2) -> 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 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_rr(uint16&) -> void;
|
||||
auto instructionLD_irr_a(uint16&) -> void;
|
||||
auto instructionLD_irr_n(uint16&) -> void;
|
||||
auto instructionLD_irr_r(uint16&, uint8&) -> void;
|
||||
auto instructionLD_r_n(uint8&) -> void;
|
||||
auto instructionLD_r_irr(uint8&, uint16&) -> void;
|
||||
auto instructionLD_r_r(uint8&, uint8&) -> void;
|
||||
auto instructionLD_rr_inn(uint16&) -> void;
|
||||
auto instructionLD_rr_nn(uint16&) -> void;
|
||||
auto instructionNOP() -> void;
|
||||
auto instructionOR_a_irr(uint16&) -> 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_r(uint8&) -> void;
|
||||
auto instructionSCF() -> void;
|
||||
auto instructionSUB_a_irr(uint16&) -> void;
|
||||
auto instructionSUB_a_r(uint8&) -> void;
|
||||
auto instructionXOR_a_irr(uint16&) -> void;
|
||||
|
@ -85,62 +107,28 @@ struct Z80 {
|
|||
auto disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string;
|
||||
|
||||
struct Registers {
|
||||
union {
|
||||
uint16_t af;
|
||||
struct { uint8_t order_msb2(a, f); };
|
||||
union {
|
||||
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 {
|
||||
Pair() : word(0) {}
|
||||
uint16 word;
|
||||
struct Byte { uint8 order_msb2(hi, lo); } byte;
|
||||
};
|
||||
|
||||
union {
|
||||
uint16_t bc;
|
||||
struct { uint8_t order_msb2(b, c); };
|
||||
};
|
||||
|
||||
union {
|
||||
uint16_t de;
|
||||
struct { uint8_t order_msb2(d, e); };
|
||||
};
|
||||
|
||||
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;
|
||||
Pair af, af_;
|
||||
Pair bc, bc_;
|
||||
Pair de, de_;
|
||||
Pair hl, hl_;
|
||||
Pair ix;
|
||||
Pair iy;
|
||||
Pair ir;
|
||||
uint16 sp;
|
||||
uint16 pc;
|
||||
|
||||
boolean halt; //HALT instruction executed
|
||||
boolean iff1; //interrupt flip-flop 1
|
||||
boolean iff2; //interrupt flip-flop 2
|
||||
uint2 im; //interrupt mode (0-2)
|
||||
|
||||
uint8 prefix;
|
||||
uint8 flag;
|
||||
Pair* hlp = nullptr;
|
||||
} r;
|
||||
|
||||
Bus* bus = nullptr;
|
||||
|
|
Loading…
Reference in New Issue