Update to v101r14 release.

byuu says:
Changelog:

  - rewrote the Z80 core to properly handle 0xDD (IX0 and 0xFD (IY)
    prefixes
  - added Processor::Z80::Bus as a new type of abstraction
  - all of the instructions implemented have their proper T-cycle counts
    now
  - added nall/certificates for my public keys

The goal of `Processor::Z80::Bus` is to simulate the opcode fetches being
2-read + 2-wait states; operand+regular reads/writes being 3-read. For
now, this puts the cycle counts inside the CPU core. At the moment, I
can't think of any CPU core where this wouldn't be appropriate. But it's
certainly possible that such a case exists. So this may not be the
perfect solution.

The reason for having it be a subclass of Processor::Z80 instead of
virtual functions for the MasterSystem::CPU core to define is due to
naming conflicts. I wanted the core to say `in(addr)` and have it take
the four clocks. But I also wanted a version of the function that didn't
consume time when called. One way to do that would be for the core to
call `Z80::in(addr)`, which then calls the regular `in(addr)` that goes to
`MasterSystem::CPU::in(addr)`. But I don't want to put the `Z80::`
prefix on all of the opcodes. Very easy to forget it, and then end up not
consuming any time. Another is to use uglier names in the
`MasterSystem::CPU` core, like `read_`, `write_`, `in_`, `out_`, etc. But,
yuck.

So ... yeah, this is an experiment. We'll see how it goes.
This commit is contained in:
Tim Allen 2016-09-03 21:26:04 +10:00
parent 7c96826eb0
commit d91f3999cc
16 changed files with 372 additions and 279 deletions

View File

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

View File

@ -17,30 +17,12 @@ auto APU::step(uint clocks) -> void {
synchronize(cpu);
}
auto APU::wait() -> void {
step(1);
}
auto APU::read(uint16 addr) -> uint8 {
step(1);
return 0x00;
}
auto APU::write(uint16 addr, uint8 data) -> void {
step(1);
}
auto APU::in(uint8 addr) -> uint8 {
return 0x00;
}
auto APU::out(uint8 addr, uint8 data) -> void {
}
auto APU::power() -> void {
Z80::power(&busAPU);
}
auto APU::reset() -> void {
Z80::reset();
create(APU::Enter, system.colorburst());
}

View File

@ -5,12 +5,6 @@ struct APU : Processor::Z80, Thread {
auto main() -> void;
auto step(uint clocks) -> void;
auto wait() -> void override;
auto read(uint16 addr) -> uint8 override;
auto write(uint16 addr, uint8 data) -> void override;
auto in(uint8 addr) -> uint8 override;
auto out(uint8 addr, uint8 data) -> void override;
auto power() -> void;
auto reset() -> void;
};

View File

@ -3,6 +3,7 @@
namespace MegaDrive {
Bus bus;
BusAPU busAPU;
auto Bus::readByte(uint24 addr) -> uint16 {
if(addr < 0x400000) return cartridge.read(addr & ~1).byte(!addr.bit(0));
@ -74,4 +75,20 @@ auto Bus::writeIO(uint24 addr, uint16 data) -> void {
}
}
//
auto BusAPU::read(uint16 addr) -> uint8 {
return 0x00;
}
auto BusAPU::write(uint16 addr, uint8 data) -> void {
}
auto BusAPU::in(uint8 addr) -> uint8 {
return 0x00;
}
auto BusAPU::out(uint8 addr, uint8 data) -> void {
}
}

View File

@ -1,3 +1,6 @@
struct APU_Bus : Processor::Z80::Bus {
};
struct Bus {
auto readByte(uint24 addr) -> uint16;
auto readWord(uint24 addr) -> uint16;
@ -11,4 +14,12 @@ private:
uint8 ram[64 * 1024];
};
struct BusAPU : Processor::Z80::Bus {
auto read(uint16 addr) -> uint8 override;
auto write(uint16 addr, uint8 data) -> void override;
auto in(uint8 addr) -> uint8 override;
auto out(uint8 addr, uint8 data) -> void override;
};
extern Bus bus;
extern BusAPU busAPU;

View File

@ -1,9 +1,9 @@
struct Bus {
auto read(uint16 addr) -> uint8;
auto write(uint16 addr, uint8 data) -> void;
struct Bus : Processor::Z80::Bus {
auto read(uint16 addr) -> uint8 override;
auto write(uint16 addr, uint8 data) -> void override;
auto in(uint8 addr) -> uint8;
auto out(uint8 addr, uint8 data) -> void;
auto in(uint8 addr) -> uint8 override;
auto out(uint8 addr, uint8 data) -> void override;
private:
uint8 ram[0x2000];

View File

@ -18,34 +18,12 @@ auto CPU::step(uint clocks) -> void {
synchronize(psg);
}
auto CPU::wait() -> void {
step(1);
}
auto CPU::read(uint16 addr) -> uint8 {
step(1);
return bus.read(addr);
}
auto CPU::write(uint16 addr, uint8 data) -> void {
step(1);
return bus.write(addr, data);
}
auto CPU::in(uint8 addr) -> uint8 {
step(1);
return bus.in(addr);
}
auto CPU::out(uint8 addr, uint8 data) -> void {
step(1);
return bus.out(addr, data);
}
auto CPU::power() -> void {
Processor::Z80::power(&MasterSystem::bus);
}
auto CPU::reset() -> void {
Processor::Z80::reset();
create(CPU::Enter, system.colorburst());
}

View File

@ -5,12 +5,6 @@ struct CPU : Processor::Z80, Thread {
auto main() -> void;
auto step(uint clocks) -> void;
auto wait() -> void override;
auto read(uint16 addr) -> uint8 override;
auto write(uint16 addr, uint8 data) -> void override;
auto in(uint8 addr) -> uint8 override;
auto out(uint8 addr, uint8 data) -> void override;
auto power() -> void;
auto reset() -> void;
};

View File

@ -1,120 +1,108 @@
auto Z80::disassemble(uint16 pc) -> string {
string output{hex(pc, 4L), " "};
string s;
s.append(hex(pc, 4L), " ");
output.append(pad(disassembleOpcode(pc), -18, ' '));
uint8 prefix = 0x00;
while(true) {
auto code = bus->read(pc++);
if(code == 0xdd || code == 0xfd) {
prefix = code;
continue;
}
s.append(pad(disassemble__(pc, prefix, code), -18L, ' '));
break;
}
output.append(
" AF:", hex(r.af, 4L),
" BC:", hex(r.bc, 4L),
" DE:", hex(r.de, 4L),
" HL:", hex(r.hl, 4L),
" IX:", hex(r.ix, 4L),
" IY:", hex(r.iy, 4L),
" SP:", hex(r.sp, 4L)
);
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(" SP:", hex(r.sp, 4L));
return output;
return s;
}
#define H (prefix == 0xdd ? "ixh" : prefix == 0xfd ? "iyh" : "h")
#define L (prefix == 0xdd ? "ixl" : prefix == 0xfd ? "iyl" : "l")
#define HL (prefix == 0xdd ? "ix" : prefix == 0xfd ? "iy" : "hl")
#define W hex(y << 8 | x << 0, 4L)
#define X hex(x, 2L)
#define Y hex(y, 2L)
#define Z hex(z, 2L)
#define W hex(y << 8 | x << 0, 4L)
#define R hex(pc + 2 + (int8)x, 4L)
#define R hex(pc + 1 + (int8)x, 4L)
auto Z80::disassembleOpcode(uint16 pc) -> string {
auto o = read(pc + 0);
auto x = read(pc + 1);
auto y = read(pc + 2);
auto z = read(pc + 3);
auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string {
auto x = bus->read(pc + 0);
auto y = bus->read(pc + 1);
auto z = bus->read(pc + 2);
switch(o) {
case 0x00: return {"nop "};
case 0x18: return {"jr $", R};
case 0x20: return {"jr nz,$", R};
case 0x28: return {"jr z,$", R};
case 0x30: return {"jr nc,$", R};
case 0x38: return {"jr c,$", R};
case 0xb8: return {"cp b"};
case 0xb9: return {"cp c"};
case 0xba: return {"cp d"};
case 0xbb: return {"cp e"};
case 0xbc: return {"cp h"};
case 0xbd: return {"cp l"};
case 0xbe: return {"cp (hl)"};
case 0xbf: return {"cp a"};
case 0xc2: return {"jp nz,$", W};
case 0xc3: return {"jp $", W};
case 0xca: return {"jp z,$", W};
case 0xd2: return {"jp nc,$", W};
case 0xda: return {"jp c,$", W};
case 0xdb: return {"in a,($", X, ")"};
case 0xdd: return disassembleOpcodeDD(pc + 1);
case 0xe2: return {"jp po,$", W};
case 0xe9: return {"jp hl"};
case 0xea: return {"jp pe,$", W};
case 0xed: return disassembleOpcodeED(pc + 1);
case 0xf2: return {"jp p,$", W};
case 0xf3: return {"di "};
case 0xfa: return {"jp m,$", W};
case 0xfd: return disassembleOpcodeFD(pc + 1);
case 0xfe: return {"cp $", X};
switch(code) {
case 0x00: return {"nop "};
case 0x06: return {"ld b,$", X};
case 0x0e: return {"ld c,$", X};
case 0x16: return {"ld d,$", X};
case 0x18: return {"jr $", R};
case 0x1e: return {"ld e,$", X};
case 0x20: return {"jr nz,$", R};
case 0x26: return {"ld ", H, ",$", X};
case 0x28: return {"jr z,$", R};
case 0x2e: return {"ld ", L, ",$", X};
case 0x30: return {"jr nc,$", R};
case 0x36: return {"ld (", HL, "),$", X};
case 0x38: return {"jr c,$", R};
case 0x3e: return {"ld a,$", X};
case 0xc2: return {"jp nz,$", W};
case 0xc3: return {"jp $", W};
case 0xca: return {"jp z,$", W};
case 0xcb: return disassembleCB(++pc, prefix, x);
case 0xd2: return {"jp nc,$", W};
case 0xda: return {"jp c,$", W};
case 0xdb: return {"in a,($", X, ")"};
case 0xe2: return {"jp po,$", W};
case 0xea: return {"jp pe,$", W};
case 0xed: return disassembleED(++pc, prefix, x);
case 0xf2: return {"jp p,$", W};
case 0xf3: return {"di "};
case 0xfa: return {"jp m,$", W};
case 0xfb: return {"ei "};
case 0xfe: return {"cp $", X};
}
return {"??? (", hex(o, 2L), " ", X, " ", Y, " ", Z, ")"};
return {"???: ", hex(code, 2L)};
}
auto Z80::disassembleOpcodeDD(uint16 pc) -> string {
auto o = read(pc + 0);
auto x = read(pc + 1);
auto y = read(pc + 2);
auto z = read(pc + 3);
auto Z80::disassembleCB(uint16 pc, uint8 prefix, uint8 code) -> string {
auto x = bus->read(pc + 0);
auto y = bus->read(pc + 1);
auto z = bus->read(pc + 2);
switch(o) {
case 0xe9: return {"jp ix"};
switch(code) {
}
return {"??? (dd ", hex(o, 2L), " ", X, " ", Y, ")"};
return {"???: cb ", hex(code, 2L)};
}
auto Z80::disassembleOpcodeED(uint16 pc) -> string {
auto o = read(pc + 0);
auto x = read(pc + 1);
auto y = read(pc + 2);
auto z = read(pc + 3);
auto Z80::disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string {
auto x = bus->read(pc + 0);
auto y = bus->read(pc + 1);
auto z = bus->read(pc + 2);
switch(o) {
case 0x40: return {"in b,(c)"};
switch(code) {
case 0x46: return {"im 0"};
case 0x48: return {"in c,(c)"};
case 0x50: return {"in d,(c)"};
case 0x56: return {"im 1"};
case 0x58: return {"in e,(c)"};
case 0x5e: return {"im 2"};
case 0x60: return {"in h,(c)"};
case 0x68: return {"in l,(c)"};
case 0x70: return {"in (c)"};
case 0x78: return {"in a,(c)"};
}
return {"??? (ed ", hex(o, 2L), " ", X, " ", Y, ")"};
}
auto Z80::disassembleOpcodeFD(uint16 pc) -> string {
auto o = read(pc + 0);
auto x = read(pc + 1);
auto y = read(pc + 2);
auto z = read(pc + 3);
switch(o) {
case 0xe9: return {"jp iy"};
}
return {"??? (fd ", hex(o, 2L), " ", X, " ", Y, ")"};
return {"???: ed ", hex(code, 2L)};
}
#undef H
#undef L
#undef HL
#undef W
#undef X
#undef Y
#undef Z
#undef W
#undef R

View File

@ -1,11 +1,9 @@
auto Z80::trap(uint8_t prefix, uint8_t opcode) -> void {
print("[Z80] unimplemented instruction: ", prefix ? pad(hex(prefix, 2L), ' ', -3) : "", hex(opcode, 2L), "\n");
auto Z80::trap(uint8 prefix, uint8 code) -> void {
print("[Z80] unimplemented instruction: ", prefix ? pad(hex(prefix, 2L), -3L, ' ') : "", hex(code, 2L), "\n");
print("[Z80] instructions executed: ", --instructionsExecuted, "\n");
while(true) wait();
}
#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);
auto Z80::instruction() -> void {
#if 1
if(instructionsExecuted < 20)
@ -14,76 +12,116 @@ auto Z80::instruction() -> void {
instructionsExecuted++;
r.r = (r.r & 0x80) | (r.r + 1 & 0x7f);
auto code = opcode();
if(code == 0xdd || code == 0xfd) {
r.prefix = code;
return;
}
instruction__(code);
r.prefix = 0x00;
}
auto opcode = read(r.pc++);
switch(opcode) {
#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);
#define A r.a
#define F r.f
#define B r.b
#define C r.c
#define D r.d
#define E r.e
#define H r.prefix == 0xdd ? r.ixh : r.prefix == 0xfd ? r.iyh : r.h
#define L r.prefix == 0xdd ? r.ixl : r.prefix == 0xfd ? r.iyl : r.l
#define AF r.af
#define BC r.bc
#define DE r.de
#define HL r.prefix == 0xdd ? r.ix : r.prefix == 0xfd ? r.iy : r.hl
#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(0x18, JR_c, true)
op(0x20, JR_c, r.p.z == 0)
op(0x28, JR_c, r.p.z == 1)
op(0x30, JR_c, r.p.c == 0)
op(0x38, JR_c, r.p.c == 1)
op(0xb8, CP_r, r.b)
op(0xb9, CP_r, r.c)
op(0xba, CP_r, r.d)
op(0xbb, CP_r, r.e)
op(0xbc, CP_r, r.h)
op(0xbd, CP_r, r.l)
op(0xbe, CP_ihl)
op(0xbf, CP_r, r.a)
op(0xc2, JP_c_nn, r.p.z == 0)
op(0xc3, JP_c_nn, true)
op(0xca, JP_c_nn, r.p.z == 1)
op(0xd2, JP_c_nn, r.p.c == 0)
op(0xda, JP_c_nn, r.p.c == 1)
op(0x06, LD_r_n, B)
op(0x0e, LD_r_n, C)
op(0x16, LD_r_n, D)
op(0x18, JR_c_e, 1)
op(0x1e, LD_r_n, E)
op(0x20, JR_c_e, ZF == 0)
op(0x26, LD_r_n, H)
op(0x28, JR_c_e, ZF == 1)
op(0x2e, LD_r_n, L)
op(0x30, JR_c_e, CF == 0)
op(0x36, LD_irr_n, HL)
op(0x38, JR_c_e, CF == 1)
op(0x3e, LD_r_n, A)
op(0xc2, JP_c_nn, ZF == 0)
op(0xc3, JP_c_nn, 1)
op(0xca, JP_c_nn, ZF == 1)
op(0xcb, CB, opcode())
op(0xd2, JP_c_nn, CF == 0)
op(0xda, JP_c_nn, CF == 1)
op(0xdb, IN_a_in)
op(0xdd, DD)
op(0xe2, JP_c_nn, r.p.p == 0)
op(0xe9, JP_rr, r.hl)
op(0xea, JP_c_nn, r.p.p == 1)
op(0xed, ED)
op(0xf2, JP_c_nn, r.p.s == 0)
op(0xe2, JP_c_nn, PF == 0)
op(0xea, JP_c_nn, PF == 1)
op(0xed, ED, opcode())
op(0xf2, JP_c_nn, SF == 0)
op(0xf3, DI)
op(0xfa, JP_c_nn, r.p.s == 1)
op(0xfd, FD)
op(0xfa, JP_c_nn, SF == 1)
op(0xfb, EI)
op(0xfe, CP_n)
}
trap(0x00, opcode);
trap(0x00, code);
}
auto Z80::instructionDD() -> void {
auto opcode = read(r.pc++);
switch(opcode) {
op(0xe9, JP_rr, r.ix)
auto Z80::instructionCB(uint8 code) -> void {
switch(code) {
}
trap(0xdd, opcode);
trap(0xcb, code);
}
auto Z80::instructionED() -> void {
auto opcode = read(r.pc++);
switch(opcode) {
op(0x40, IN_r_ic, r.b)
op(0x46, IM, 0)
op(0x48, IN_r_ic, r.c)
op(0x50, IN_r_ic, r.d)
op(0x56, IM, 1)
op(0x58, IN_r_ic, r.e)
op(0x5e, IM, 2)
op(0x60, IN_r_ic, r.h)
op(0x68, IN_r_ic, r.l)
op(0x70, IN_r_ic, r.flag)
op(0x78, IN_r_ic, r.a)
auto Z80::instructionED(uint8 code) -> void {
switch(code) {
op(0x46, IM_o, 0)
op(0x56, IM_o, 1)
op(0x5e, IM_o, 2)
}
trap(0xed, opcode);
}
auto Z80::instructionFD() -> void {
auto opcode = read(r.pc++);
switch(opcode) {
op(0xe9, JP_rr, r.iy)
}
trap(0xfd, opcode);
trap(0xed, code);
}
#undef op
#undef A
#undef F
#undef B
#undef C
#undef D
#undef E
#undef H
#undef L
#undef AF
#undef BC
#undef DE
#undef HL
#undef CF
#undef NF
#undef PF
#undef VF
#undef XF
#undef HF
#undef YF
#undef ZF
#undef SF

View File

@ -1,60 +1,68 @@
auto Z80::CP(uint8 x) -> void {
uint16 y = r.a - x;
//legend:
// a = r.a
// e = relative operand
// in = (operand)
// irr = (register-word)
// o = opcode bits
// n = operand
// nn = operand-word
// r = register
r.p.c = y > 0xff;
auto Z80::CP(uint8 x) -> void {
uint9 y = r.a - x;
r.p.c = y.bit(8);
r.p.n = 1;
r.p.v = (r.a ^ x) & (r.a ^ y) & 0x80;
r.p.x = y.bit(3);
r.p.h = (r.a ^ y ^ x) & 0x10;
r.p.z = y == 0;
r.p.s = y & 0x80;
}
auto Z80::instructionCP_ihl() -> void {
CP(read(r.hl));
r.p.y = y.bit(5);
r.p.z = (uint8)y == 0;
r.p.s = y.bit(7);
}
auto Z80::instructionCP_n() -> void {
CP(read(r.pc++));
}
auto Z80::instructionCP_r(uint8_t& x) -> void {
CP(x);
CP(operand());
}
auto Z80::instructionDI() -> void {
r.di = 1;
r.iff1 = 0;
r.iff2 = 0;
}
auto Z80::instructionIM(uint mode) -> void {
r.im = mode;
auto Z80::instructionEI() -> void {
r.iff1 = 1;
r.iff2 = 1;
}
auto Z80::instructionIM_o(uint2 code) -> void {
wait(4);
r.im = code;
}
auto Z80::instructionIN_a_in() -> void {
r.a = in(read(r.pc++));
}
auto Z80::instructionIN_r_ic(uint8_t& x) -> void {
x = in(read(r.c));
r.p.n = 0;
r.p.p = parity(x);
r.p.h = 0;
r.p.z = x == 0;
r.p.s = x & 0x80;
r.a = in(operand());
}
auto Z80::instructionJP_c_nn(bool c) -> void {
auto lo = read(r.pc++);
auto hi = read(r.pc++);
auto lo = operand();
auto hi = operand();
if(c) r.pc = hi << 8 | lo << 0;
}
auto Z80::instructionJP_rr(uint16_t& x) -> void {
r.pc = x;
auto Z80::instructionJR_c_e(bool c) -> void {
auto e = operand();
if(!c) return;
wait(5);
r.pc += (int8)e;
}
auto Z80::instructionJR_c(bool c) -> void {
auto d = read(r.pc++);
if(c) r.pc += (int8)d;
auto Z80::instructionLD_irr_n(uint16_t& x) -> void {
write(x, operand());
}
auto Z80::instructionLD_r_n(uint8_t& x) -> void {
x = operand();
}
auto Z80::instructionNOP() -> void {

View File

@ -0,0 +1,33 @@
auto Z80::wait(uint clocks) -> void {
step(clocks);
}
auto Z80::opcode() -> uint8 {
step(4);
return bus->read(r.pc++);
}
auto Z80::operand() -> uint8 {
step(3);
return bus->read(r.pc++);
}
auto Z80::read(uint16 addr) -> uint8 {
step(3);
return bus->read(addr);
}
auto Z80::write(uint16 addr, uint8 data) -> void {
step(3);
return bus->write(addr, data);
}
auto Z80::in(uint8 addr) -> uint8 {
step(4);
return bus->in(addr);
}
auto Z80::out(uint8 addr, uint8 data) -> void {
step(4);
return bus->out(addr, data);
}

View File

@ -3,11 +3,13 @@
namespace Processor {
#include "memory.cpp"
#include "instruction.cpp"
#include "instructions.cpp"
#include "disassembler.cpp"
auto Z80::power() -> void {
auto Z80::power(Z80::Bus* bus) -> void {
this->bus = bus;
}
auto Z80::reset() -> void {
@ -15,16 +17,17 @@ auto Z80::reset() -> void {
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.i = 0x00;
r.r = 0x00;
r.di = false;
r.ei = false;
r.iff1 = 0;
r.iff2 = 0;
r.im = 0;
instructionsExecuted = 0;
}
auto Z80::parity(uint8_t value) const -> bool {

View File

@ -5,45 +5,55 @@
namespace Processor {
struct Z80 {
virtual auto wait() -> void = 0;
virtual auto read(uint16 addr) -> uint8 = 0;
virtual auto write(uint16 addr, uint8 data) -> void = 0;
virtual auto in(uint8 addr) -> uint8 = 0;
virtual auto out(uint8 addr, uint8 data) -> void = 0;
struct Bus {
virtual auto read(uint16 addr) -> uint8 = 0;
virtual auto write(uint16 addr, uint8 data) -> void = 0;
virtual auto in(uint8 addr) -> uint8 = 0;
virtual auto out(uint8 addr, uint8 data) -> void = 0;
};
virtual auto step(uint clocks) -> void = 0;
//z80.cpp
auto power() -> void;
auto power(Z80::Bus*) -> void;
auto reset() -> void;
auto parity(uint8_t) const -> bool;
//memory.cpp
auto wait(uint clocks = 1) -> void;
auto opcode() -> uint8;
auto operand() -> uint8;
auto read(uint16 addr) -> uint8;
auto write(uint16 addr, uint8 data) -> void;
auto in(uint8 addr) -> uint8;
auto out(uint8 addr, uint8 data) -> void;
//instruction.cpp
auto trap(uint8_t prefix, uint8_t opcode) -> void;
auto trap(uint8 prefix, uint8 code) -> void;
auto instruction() -> void;
auto instructionDD() -> void;
auto instructionED() -> void;
auto instructionFD() -> void;
auto instruction__(uint8 code) -> void;
auto instructionCB(uint8 code) -> void;
auto instructionED(uint8 code) -> void;
//instructions.cpp
auto CP(uint8 x) -> void;
auto instructionCP_ihl() -> void;
auto CP(uint8) -> void;
auto instructionCP_n() -> void;
auto instructionCP_r(uint8_t&) -> void;
auto instructionDI() -> void;
auto instructionIM(uint) -> void;
auto instructionEI() -> void;
auto instructionIM_o(uint2) -> void;
auto instructionIN_a_in() -> void;
auto instructionIN_r_ic(uint8_t&) -> void;
auto instructionJP_c_nn(bool) -> void;
auto instructionJP_rr(uint16_t&) -> void;
auto instructionJR_c(bool) -> void;
auto instructionJR_c_e(bool) -> void;
auto instructionLD_irr_n(uint16_t&) -> void;
auto instructionLD_r_n(uint8_t&) -> void;
auto instructionNOP() -> void;
//disassembler.cpp
auto disassemble(uint16 pc) -> string;
auto disassembleOpcode(uint16 pc) -> string;
auto disassembleOpcodeDD(uint16 pc) -> string;
auto disassembleOpcodeED(uint16 pc) -> string;
auto disassembleOpcodeFD(uint16 pc) -> string;
auto disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string;
auto disassembleCB(uint16 pc, uint8 prefix, uint8 code) -> string;
auto disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string;
struct Registers {
union {
@ -77,22 +87,34 @@ struct Z80 {
struct { uint8_t order_msb2(h, l); };
};
uint16_t ix;
uint16_t iy;
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;
uint8_t i;
uint8_t r;
boolean di; //disable interrupt
boolean ei; //enable interrupt
uint2 im; //interrupt mode (0-2)
boolean iff1; //interrupt flip-flop 1
boolean iff2; //interrupt flip-flop 2
uint2 im; //interrupt mode (0-2)
uint8_t prefix;
uint8_t flag;
} r;
private:
Bus* bus = nullptr;
uint64 instructionsExecuted = 0;
};

View File

@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIByDCCAU6gAwIBAgIJAI83xahWv0iSMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwODMxMDQ1MjEzWhgPMjA5MTA4MTMw
NDUyMTNaMB4xDTALBgNVBAMMBGJ5dXUxDTALBgNVBAoMBGJ5dXUwdjAQBgcqhkjO
PQIBBgUrgQQAIgNiAAT5ArnlLKmJZrkmDwBNroM+djFS1CM/KLVXGZQUmkjyDJSB
/JeC/aT3v4g236kzcHu4+FBDPT1MhPUmtFC+mGjnWjtQsGHuTknGYXpjOEK77PXy
LL2m9gXB0eKE0SkMIdijVjBUMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE
FErJPHQ5yHMo18r8c0LI4XmrKjnRMB8GA1UdIwQYMBaAFErJPHQ5yHMo18r8c0LI
4XmrKjnRMAoGCCqGSM49BAMDA2gAMGUCMQDAcBz38wdb5lJmcMf8Y1eqPZxXkgCt
OZklW1cXZnoB2w3yjdImujHVyEfhK684HCkCMEjsxEUPRf8tB0UKO836qKmAKFHW
OYBX8Sx6jlzonkb1miqjxiNQdTmGdkWk1IsP8Q==
-----END CERTIFICATE-----

View File

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB6zCCAXCgAwIBAgIJAPQ6cLpDt9l8MAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwODMxMDQ1MzQyWhgPMjA5MTA4MTMw
NDUzNDJaMCIxETAPBgNVBAMMCGJ5dXUub3JnMQ0wCwYDVQQKDARieXV1MHYwEAYH
KoZIzj0CAQYFK4EEACIDYgAEuYjwx8y8nO9yAR7Hb8AB8lB1SSXk1lBm9ofcEzkN
SLOvrC+ESHR1C+w9krlbJlSq2wPA482DIW3aLukfNIdwhuTciVFBZfk0bgRgVqXq
Ha+iyL64/naqzWGxk5m/HDkFo3QwcjAMBgNVHRMBAf8EAjAAMCIGA1UdEQEB/wQY
MBaCCGJ5dXUub3JnggoqLmJ5dXUub3JnMB0GA1UdDgQWBBSJd/vrUirTNFcxur/9
hN+Q55H+AzAfBgNVHSMEGDAWgBRKyTx0OchzKNfK/HNCyOF5qyo50TAKBggqhkjO
PQQDAwNpADBmAjEAh5Jc3nepWmrRJDLaGzy7ews23uEcrz3PfBbtJrTC3qw5b2Ig
fqZ6h5/nG7BXAeq9AjEAnxwn221GihthlL6nzSS5SRyjmR6crGfqWcQwSQTp8b+8
DqXqRKiYVHoiedKJslCF
-----END CERTIFICATE-----