From 4c3f58150c3ac9b98755b19d25fd936c0bce5948 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sun, 4 Sep 2016 23:51:27 +1000 Subject: [PATCH] Update to v101r15 release. byuu says: Changelog: - added (poorly-named) castable template - Z80 debugger rewritten to make declaring instructions much simpler - Z80 has more instructions implemented; supports displacement on (IX), (IY) now - added `Processor::M68K::Bus` to mirror `Processor::Z80::Bus` - it does add a pointer indirection; so I'm not sure if I want to do this for all of my emulator cores ... --- higan/emulator/emulator.hpp | 2 +- higan/md/apu/apu.cpp | 3 +- higan/md/bus/bus.cpp | 14 +-- higan/md/bus/bus.hpp | 15 +-- higan/md/cpu/cpu.cpp | 10 +- higan/md/cpu/cpu.hpp | 5 - higan/md/vdp/dma.cpp | 2 +- higan/ms/cpu/cpu.cpp | 5 +- higan/processor/m68k/disassembler.cpp | 4 +- higan/processor/m68k/m68k.hpp | 17 +-- higan/processor/m68k/memory.cpp | 32 +++--- higan/processor/z80/disassembler.cpp | 151 +++++++++++++++++--------- higan/processor/z80/instruction.cpp | 22 ++++ higan/processor/z80/instructions.cpp | 34 +++++- higan/processor/z80/memory.cpp | 7 ++ higan/processor/z80/z80.cpp | 5 +- higan/processor/z80/z80.hpp | 53 +++++---- nall/utility.hpp | 9 ++ 18 files changed, 249 insertions(+), 141 deletions(-) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 810d6561..7df5326c 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "101.14"; + static const string Version = "101.15"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/md/apu/apu.cpp b/higan/md/apu/apu.cpp index eab2a48d..2839fd87 100644 --- a/higan/md/apu/apu.cpp +++ b/higan/md/apu/apu.cpp @@ -18,7 +18,8 @@ auto APU::step(uint clocks) -> void { } auto APU::power() -> void { - Z80::power(&busAPU); + Z80::bus = &busAPU; + Z80::power(); } auto APU::reset() -> void { diff --git a/higan/md/bus/bus.cpp b/higan/md/bus/bus.cpp index 2014be31..c69c180a 100644 --- a/higan/md/bus/bus.cpp +++ b/higan/md/bus/bus.cpp @@ -2,10 +2,10 @@ namespace MegaDrive { -Bus bus; +BusCPU busCPU; BusAPU busAPU; -auto Bus::readByte(uint24 addr) -> uint16 { +auto BusCPU::readByte(uint24 addr) -> uint16 { if(addr < 0x400000) return cartridge.read(addr & ~1).byte(!addr.bit(0)); if(addr < 0xa00000) return 0x0000; if(addr < 0xa10000) return 0x0000; @@ -15,7 +15,7 @@ auto Bus::readByte(uint24 addr) -> uint16 { return ram[addr & 0xffff]; } -auto Bus::readWord(uint24 addr) -> uint16 { +auto BusCPU::readWord(uint24 addr) -> uint16 { if(addr < 0x400000) return cartridge.read(addr); if(addr < 0xa00000) return 0x0000; if(addr < 0xa10000) return 0x0000; @@ -26,7 +26,7 @@ auto Bus::readWord(uint24 addr) -> uint16 { return data | ram[addr + 1 & 0xffff] << 0; } -auto Bus::writeByte(uint24 addr, uint16 data) -> void { +auto BusCPU::writeByte(uint24 addr, uint16 data) -> void { if(addr < 0x400000) return cartridge.write(addr & ~1, data << 8 | data << 0); if(addr < 0xa00000) return; if(addr < 0xa10000) return; @@ -36,7 +36,7 @@ auto Bus::writeByte(uint24 addr, uint16 data) -> void { ram[addr & 0xffff] = data; } -auto Bus::writeWord(uint24 addr, uint16 data) -> void { +auto BusCPU::writeWord(uint24 addr, uint16 data) -> void { if(addr < 0x400000) return cartridge.write(addr, data); if(addr < 0xa00000) return; if(addr < 0xa10000) return; @@ -49,7 +49,7 @@ auto Bus::writeWord(uint24 addr, uint16 data) -> void { // -auto Bus::readIO(uint24 addr) -> uint16 { +auto BusCPU::readIO(uint24 addr) -> uint16 { switch(addr & ~1) { case 0xa10002: return peripherals.controllerPort1->readData(); case 0xa10004: return peripherals.controllerPort2->readData(); @@ -63,7 +63,7 @@ auto Bus::readIO(uint24 addr) -> uint16 { return 0x0000; } -auto Bus::writeIO(uint24 addr, uint16 data) -> void { +auto BusCPU::writeIO(uint24 addr, uint16 data) -> void { switch(addr & ~1) { case 0xa10002: return peripherals.controllerPort1->writeData(data); case 0xa10004: return peripherals.controllerPort2->writeData(data); diff --git a/higan/md/bus/bus.hpp b/higan/md/bus/bus.hpp index 074e2039..57f470ef 100644 --- a/higan/md/bus/bus.hpp +++ b/higan/md/bus/bus.hpp @@ -1,11 +1,8 @@ -struct APU_Bus : Processor::Z80::Bus { -}; - -struct Bus { - auto readByte(uint24 addr) -> uint16; - auto readWord(uint24 addr) -> uint16; - auto writeByte(uint24 addr, uint16 data) -> void; - auto writeWord(uint24 addr, uint16 data) -> void; +struct BusCPU : Processor::M68K::Bus { + auto readByte(uint24 addr) -> uint16 override; + auto readWord(uint24 addr) -> uint16 override; + auto writeByte(uint24 addr, uint16 data) -> void override; + auto writeWord(uint24 addr, uint16 data) -> void override; auto readIO(uint24 addr) -> uint16; auto writeIO(uint24 addr, uint16 data) -> void; @@ -21,5 +18,5 @@ struct BusAPU : Processor::Z80::Bus { auto out(uint8 addr, uint8 data) -> void override; }; -extern Bus bus; +extern BusCPU busCPU; extern BusAPU busAPU; diff --git a/higan/md/cpu/cpu.cpp b/higan/md/cpu/cpu.cpp index 55551f5a..4dd9d0d5 100644 --- a/higan/md/cpu/cpu.cpp +++ b/higan/md/cpu/cpu.cpp @@ -10,8 +10,8 @@ auto CPU::Enter() -> void { } auto CPU::boot() -> void { - r.a[7] = readWord(0) << 16 | readWord(2) << 0; - r.pc = readWord(4) << 16 | readWord(6) << 0; + r.a[7] = bus->readWord(0) << 16 | bus->readWord(2) << 0; + r.pc = bus->readWord(4) << 16 | bus->readWord(6) << 0; } auto CPU::main() -> void { @@ -71,6 +71,7 @@ auto CPU::lower(Interrupt interrupt) -> void { } auto CPU::power() -> void { + M68K::bus = &busCPU; M68K::power(); } @@ -81,9 +82,4 @@ auto CPU::reset() -> void { memory::fill(&state, sizeof(State)); } -auto CPU::readByte(uint24 addr) -> uint16 { return bus.readByte(addr); } -auto CPU::readWord(uint24 addr) -> uint16 { return bus.readWord(addr); } -auto CPU::writeByte(uint24 addr, uint16 data) -> void { return bus.writeByte(addr, data); } -auto CPU::writeWord(uint24 addr, uint16 data) -> void { return bus.writeWord(addr, data); } - } diff --git a/higan/md/cpu/cpu.hpp b/higan/md/cpu/cpu.hpp index 781c2f92..1ed82998 100644 --- a/higan/md/cpu/cpu.hpp +++ b/higan/md/cpu/cpu.hpp @@ -20,11 +20,6 @@ struct CPU : Processor::M68K, Thread { auto power() -> void; auto reset() -> void; - auto readByte(uint24 addr) -> uint16 override; - auto readWord(uint24 addr) -> uint16 override; - auto writeByte(uint24 addr, uint16 data) -> void override; - auto writeWord(uint24 addr, uint16 data) -> void override; - vector peripherals; private: diff --git a/higan/md/vdp/dma.cpp b/higan/md/vdp/dma.cpp index 0c385250..67f544be 100644 --- a/higan/md/vdp/dma.cpp +++ b/higan/md/vdp/dma.cpp @@ -10,7 +10,7 @@ auto VDP::dmaRun() -> void { auto VDP::dmaLoad() -> void { cpu.wait |= Wait::VDP_DMA; - auto data = cpu.readWord(io.dmaMode.bit(0) << 23 | io.dmaSource << 1); + auto data = busCPU.readWord(io.dmaMode.bit(0) << 23 | io.dmaSource << 1); writeDataPort(data); io.dmaSource.bits(0,15)++; diff --git a/higan/ms/cpu/cpu.cpp b/higan/ms/cpu/cpu.cpp index 18bdfab6..80b3652f 100644 --- a/higan/ms/cpu/cpu.cpp +++ b/higan/ms/cpu/cpu.cpp @@ -19,11 +19,12 @@ auto CPU::step(uint clocks) -> void { } auto CPU::power() -> void { - Processor::Z80::power(&MasterSystem::bus); + Z80::bus = &MasterSystem::bus; + Z80::power(); } auto CPU::reset() -> void { - Processor::Z80::reset(); + Z80::reset(); create(CPU::Enter, system.colorburst()); } diff --git a/higan/processor/m68k/disassembler.cpp b/higan/processor/m68k/disassembler.cpp index 8db277a7..02b96918 100644 --- a/higan/processor/m68k/disassembler.cpp +++ b/higan/processor/m68k/disassembler.cpp @@ -1,9 +1,9 @@ template<> auto M68K::_read(uint32 addr) -> uint32 { - return readByte(addr); + return bus->readByte(addr); } template<> auto M68K::_read(uint32 addr) -> uint32 { - return readWord(addr); + return bus->readWord(addr); } template<> auto M68K::_read(uint32 addr) -> uint32 { diff --git a/higan/processor/m68k/m68k.hpp b/higan/processor/m68k/m68k.hpp index 85ab051a..8d0843ba 100644 --- a/higan/processor/m68k/m68k.hpp +++ b/higan/processor/m68k/m68k.hpp @@ -5,6 +5,15 @@ namespace Processor { struct M68K { + struct Bus { + virtual auto readByte(uint24 addr) -> uint16 = 0; + virtual auto readWord(uint24 addr) -> uint16 = 0; + virtual auto writeByte(uint24 addr, uint16 data) -> void = 0; + virtual auto writeWord(uint24 addr, uint16 data) -> void = 0; + }; + + virtual auto step(uint clocks) -> void = 0; + enum : bool { User, Supervisor }; enum : uint { Byte, Word, Long }; enum : bool { Reverse = 1, Extend = 1, Hold = 1 }; @@ -48,13 +57,6 @@ struct M68K { };}; M68K(); - - virtual auto step(uint clocks) -> void = 0; - virtual auto readByte(uint24 addr) -> uint16 = 0; - virtual auto readWord(uint24 addr) -> uint16 = 0; - virtual auto writeByte(uint24 addr, uint16 data) -> void = 0; - virtual auto writeWord(uint24 addr, uint16 data) -> void = 0; - auto power() -> void; auto reset() -> void; auto supervisor() -> bool; @@ -274,6 +276,7 @@ struct M68K { uint instructionsExecuted = 0; function instructionTable[65536]; + Bus* bus = nullptr; private: //disassembler.cpp diff --git a/higan/processor/m68k/memory.cpp b/higan/processor/m68k/memory.cpp index 343dea96..3a33315f 100644 --- a/higan/processor/m68k/memory.cpp +++ b/higan/processor/m68k/memory.cpp @@ -1,78 +1,78 @@ template<> auto M68K::read(uint32 addr) -> uint32 { step(4); - return readByte(addr); + return bus->readByte(addr); } template<> auto M68K::read(uint32 addr) -> uint32 { step(4); - return readWord(addr); + return bus->readWord(addr); } template<> auto M68K::read(uint32 addr) -> uint32 { step(4); - uint32 data = readWord(addr + 0) << 16; + uint32 data = bus->readWord(addr + 0) << 16; step(4); - return data | readWord(addr + 2) << 0; + return data | bus->readWord(addr + 2) << 0; } // template<> auto M68K::write(uint32 addr, uint32 data) -> void { step(4); - return writeByte(addr, data); + return bus->writeByte(addr, data); } template<> auto M68K::write(uint32 addr, uint32 data) -> void { step(4); - return writeWord(addr, data); + return bus->writeWord(addr, data); } template<> auto M68K::write(uint32 addr, uint32 data) -> void { step(4); - writeWord(addr + 0, data >> 16); + bus->writeWord(addr + 0, data >> 16); step(4); - writeWord(addr + 2, data >> 0); + bus->writeWord(addr + 2, data >> 0); } template<> auto M68K::write(uint32 addr, uint32 data) -> void { step(4); - return writeByte(addr, data); + return bus->writeByte(addr, data); } template<> auto M68K::write(uint32 addr, uint32 data) -> void { step(4); - return writeWord(addr, data); + return bus->writeWord(addr, data); } template<> auto M68K::write(uint32 addr, uint32 data) -> void { step(4); - writeWord(addr + 2, data >> 0); + bus->writeWord(addr + 2, data >> 0); step(4); - writeWord(addr + 0, data >> 16); + bus->writeWord(addr + 0, data >> 16); } // template<> auto M68K::readPC() -> uint32 { step(4); - auto data = readWord(r.pc); + auto data = bus->readWord(r.pc); r.pc += 2; return (uint8)data; } template<> auto M68K::readPC() -> uint32 { step(4); - auto data = readWord(r.pc); + auto data = bus->readWord(r.pc); r.pc += 2; return data; } template<> auto M68K::readPC() -> uint32 { step(4); - auto hi = readWord(r.pc); + auto hi = bus->readWord(r.pc); r.pc += 2; step(4); - auto lo = readWord(r.pc); + auto lo = bus->readWord(r.pc); r.pc += 2; return hi << 16 | lo << 0; } diff --git a/higan/processor/z80/disassembler.cpp b/higan/processor/z80/disassembler.cpp index e2e8b562..9885c6af 100644 --- a/higan/processor/z80/disassembler.cpp +++ b/higan/processor/z80/disassembler.cpp @@ -24,59 +24,100 @@ auto Z80::disassemble(uint16 pc) -> string { 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 R hex(pc + 1 + (int8)x, 4L) +#define op(id, name, ...) case id: return {name, " ", string_vector{__VA_ARGS__}.merge(",")}; + +#define N string{"$", hex(byte(), 2L)} +#define IN string{"(", N, ")"} +#define NN string{"$", hex(word(), 4L)} +#define INN string{"(", NN, ")"} +#define E string{"$", hex(branch(), 4L)} + +#define H string{prefix == 0xdd ? "ixh" : prefix == 0xfd ? "iyh" : "h"} +#define L string{prefix == 0xdd ? "ixl" : prefix == 0xfd ? "iyl" : "l"} +#define HL string{prefix == 0xdd ? "ix" : prefix == 0xfd ? "iy" : "hl"} +#define IHL string{"(", HL, displace(), ")"} 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); + auto byte = [&] { + return bus->read(pc++); + }; + + auto word = [&] { + uint16 data = byte() << 0; + return data | byte() << 8; + }; + + auto branch = [&] { + auto d = byte(); + return pc + (int8)d; + }; + + auto displace = [&] { + if(!prefix) return string{}; + auto d = (int8)byte(); + return d >= 0 ? string{"+$", hex(d, 2L)} : string{"-$", hex(-d, 2L)}; + }; + + if(code == 0xcb) return code = byte(), disassembleCB(pc, prefix, code); + if(code == 0xed) return code = byte(), disassembleED(pc, prefix, code); 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}; + op(0x00, "nop ") + op(0x01, "ld ", "bc", NN) + op(0x06, "ld ", "b", N) + op(0x0e, "ld ", "c", N) + op(0x11, "ld ", "de", NN) + op(0x16, "ld ", "d", N) + op(0x18, "jr ", E) + op(0x1e, "ld ", "e", N) + op(0x20, "jr ", "nz", E) + op(0x21, "ld ", HL, NN) + op(0x26, "ld ", H, N) + op(0x28, "jr ", "z", E) + op(0x2e, "ld ", L, N) + op(0x30, "jr ", "nc", E) + op(0x31, "ld ", "sp", NN) + op(0x32, "ld ", INN, "a") + op(0x36, "ld ", IHL, N) + op(0x38, "jr ", "c", E) + op(0x3e, "ld ", "a", N) + op(0x70, "ld ", IHL, "b") + op(0x71, "ld ", IHL, "c") + op(0x72, "ld ", IHL, "d") + op(0x73, "ld ", IHL, "e") + op(0x74, "ld ", IHL, "h") + op(0x75, "ld ", IHL, "l") + op(0x77, "ld ", IHL, "a") + op(0xb8, "cp ", "b") + op(0xb9, "cp ", "c") + op(0xba, "cp ", "d") + op(0xbb, "cp ", "e") + op(0xbc, "cp ", H) + op(0xbd, "cp ", L) + op(0xbe, "cp ", IHL) + op(0xbf, "cp ", "a") + op(0xc2, "jp ", "nz", NN) + op(0xc3, "jp ", NN) + op(0xca, "jp ", "z", NN) + op(0xcb, "cb: ") + op(0xd2, "jp ", "nc", NN) + op(0xda, "jp ", "c", NN) + op(0xdb, "in ", "a", IN) + op(0xe2, "jp ", "po", NN) + op(0xea, "jp ", "pe", NN) + op(0xed, "ed: ") + op(0xf2, "jp ", "p", NN) + op(0xf3, "di ") + op(0xfa, "jp ", "m", NN) + op(0xfb, "ei ") + op(0xfe, "cp ", N) } return {"???: ", hex(code, 2L)}; } 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); + auto read = [&] { return bus->read(pc++); }; switch(code) { } @@ -85,24 +126,26 @@ auto Z80::disassembleCB(uint16 pc, uint8 prefix, uint8 code) -> string { } 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); + auto read = [&] { return bus->read(pc++); }; switch(code) { - case 0x46: return {"im 0"}; - case 0x56: return {"im 1"}; - case 0x5e: return {"im 2"}; + op(0x46, "im ", "0") + op(0x56, "im ", "1") + op(0x5e, "im ", "2") } return {"???: ed ", hex(code, 2L)}; } +#undef op + +#undef N +#undef IN +#undef NN +#undef INN +#undef E + #undef H #undef L #undef HL -#undef W -#undef X -#undef Y -#undef Z -#undef R +#undef IHL diff --git a/higan/processor/z80/instruction.cpp b/higan/processor/z80/instruction.cpp index 02a897ec..116aa61f 100644 --- a/higan/processor/z80/instruction.cpp +++ b/higan/processor/z80/instruction.cpp @@ -36,6 +36,7 @@ auto Z80::instruction() -> void { #define BC r.bc #define DE r.de #define HL r.prefix == 0xdd ? r.ix : r.prefix == 0xfd ? r.iy : r.hl +#define SP r.sp #define CF r.p.c #define NF r.p.n @@ -50,19 +51,39 @@ auto Z80::instruction() -> void { auto Z80::instruction__(uint8 code) -> void { switch(code) { op(0x00, NOP) + op(0x01, LD_rr_nn, BC) op(0x06, LD_r_n, B) op(0x0e, LD_r_n, C) + op(0x11, LD_rr_nn, DE) 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(0x21, LD_rr_nn, HL) 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(0x31, LD_rr_nn, SP) + op(0x32, LD_inn_a) op(0x36, LD_irr_n, HL) op(0x38, JR_c_e, CF == 1) op(0x3e, LD_r_n, 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, r.h) + op(0x75, LD_irr_r, HL, r.l) + op(0x77, LD_irr_r, HL, A) + op(0xb8, CP_r, B) + op(0xb9, CP_r, C) + op(0xba, CP_r, D) + op(0xbb, CP_r, E) + op(0xbc, CP_r, H) + op(0xbd, CP_r, L) + op(0xbe, CP_irr, HL) + op(0xbf, CP_r, A) op(0xc2, JP_c_nn, ZF == 0) op(0xc3, JP_c_nn, 1) op(0xca, JP_c_nn, ZF == 1) @@ -115,6 +136,7 @@ auto Z80::instructionED(uint8 code) -> void { #undef BC #undef DE #undef HL +#undef SP #undef CF #undef NF diff --git a/higan/processor/z80/instructions.cpp b/higan/processor/z80/instructions.cpp index 69733b1d..18001080 100644 --- a/higan/processor/z80/instructions.cpp +++ b/higan/processor/z80/instructions.cpp @@ -2,6 +2,7 @@ // a = r.a // e = relative operand // in = (operand) +// inn = (operand-word) // irr = (register-word) // o = opcode bits // n = operand @@ -21,10 +22,19 @@ auto Z80::CP(uint8 x) -> void { r.p.s = y.bit(7); } +auto Z80::instructionCP_irr(uint16& x) -> void { + auto addr = displace(x); + CP(read(addr)); +} + auto Z80::instructionCP_n() -> void { CP(operand()); } +auto Z80::instructionCP_r(uint8& x) -> void { + CP(x); +} + auto Z80::instructionDI() -> void { r.iff1 = 0; r.iff2 = 0; @@ -57,13 +67,31 @@ auto Z80::instructionJR_c_e(bool c) -> void { r.pc += (int8)e; } -auto Z80::instructionLD_irr_n(uint16_t& x) -> void { - write(x, operand()); +auto Z80::instructionLD_inn_a() -> void { + auto lo = operand(); + auto hi = operand(); + write(hi << 8 | lo << 0, r.a); } -auto Z80::instructionLD_r_n(uint8_t& x) -> void { +auto Z80::instructionLD_irr_n(uint16& x) -> void { + auto addr = displace(x); + write(addr, operand()); +} + +auto Z80::instructionLD_irr_r(uint16& x, uint8& y) -> void { + auto addr = displace(x); + write(addr, y); +} + +auto Z80::instructionLD_r_n(uint8& x) -> void { x = operand(); } +auto Z80::instructionLD_rr_nn(uint16& x) -> void { + auto lo = operand(); + auto hi = operand(); + x = hi << 8 | lo << 0; +} + auto Z80::instructionNOP() -> void { } diff --git a/higan/processor/z80/memory.cpp b/higan/processor/z80/memory.cpp index 3d949ad2..443fe649 100644 --- a/higan/processor/z80/memory.cpp +++ b/higan/processor/z80/memory.cpp @@ -12,6 +12,13 @@ auto Z80::operand() -> uint8 { return bus->read(r.pc++); } +auto Z80::displace(uint16& x) -> uint16 { + if(!r.prefix) return x; + auto d = read(x); + wait(5); + return x + (int8)d; +} + auto Z80::read(uint16 addr) -> uint8 { step(3); return bus->read(addr); diff --git a/higan/processor/z80/z80.cpp b/higan/processor/z80/z80.cpp index d4d67509..f6e1b0c0 100644 --- a/higan/processor/z80/z80.cpp +++ b/higan/processor/z80/z80.cpp @@ -8,8 +8,7 @@ namespace Processor { #include "instructions.cpp" #include "disassembler.cpp" -auto Z80::power(Z80::Bus* bus) -> void { - this->bus = bus; +auto Z80::power() -> void { } auto Z80::reset() -> void { @@ -30,7 +29,7 @@ auto Z80::reset() -> void { instructionsExecuted = 0; } -auto Z80::parity(uint8_t value) const -> bool { +auto Z80::parity(uint8 value) const -> bool { value ^= value >> 4; value ^= value >> 2; value ^= value >> 1; diff --git a/higan/processor/z80/z80.hpp b/higan/processor/z80/z80.hpp index 5e6808b5..f59eba4f 100644 --- a/higan/processor/z80/z80.hpp +++ b/higan/processor/z80/z80.hpp @@ -15,15 +15,16 @@ struct Z80 { virtual auto step(uint clocks) -> void = 0; //z80.cpp - auto power(Z80::Bus*) -> void; + auto power() -> void; auto reset() -> void; - auto parity(uint8_t) const -> bool; + auto parity(uint8) const -> bool; //memory.cpp auto wait(uint clocks = 1) -> void; auto opcode() -> uint8; auto operand() -> uint8; + auto displace(uint16&) -> uint16; auto read(uint16 addr) -> uint8; auto write(uint16 addr, uint8 data) -> void; auto in(uint8 addr) -> uint8; @@ -38,15 +39,20 @@ struct Z80 { //instructions.cpp auto CP(uint8) -> void; + auto instructionCP_irr(uint16& x) -> void; auto instructionCP_n() -> void; + auto instructionCP_r(uint8& x) -> void; auto instructionDI() -> void; auto instructionEI() -> void; auto instructionIM_o(uint2) -> void; auto instructionIN_a_in() -> void; auto instructionJP_c_nn(bool) -> void; auto instructionJR_c_e(bool) -> void; - auto instructionLD_irr_n(uint16_t&) -> void; - auto instructionLD_r_n(uint8_t&) -> void; + auto instructionLD_inn_a() -> void; + auto instructionLD_irr_n(uint16&) -> void; + auto instructionLD_irr_r(uint16&, uint8&) -> void; + auto instructionLD_r_n(uint8&) -> void; + auto instructionLD_rr_nn(uint16&) -> void; auto instructionNOP() -> void; //disassembler.cpp @@ -57,8 +63,8 @@ struct Z80 { struct Registers { union { - uint16_t af; - struct { uint8_t order_msb2(a, f); }; + castable af; + struct { castable order_msb2(a, f); }; union { BooleanBitField c; //carry BooleanBitField n; //add / subtract @@ -73,48 +79,49 @@ struct Z80 { }; union { - uint16_t bc; - struct { uint8_t order_msb2(b, c); }; + castable bc; + struct { castable order_msb2(b, c); }; }; union { - uint16_t de; - struct { uint8_t order_msb2(d, e); }; + castable de; + struct { castable order_msb2(d, e); }; }; union { - uint16_t hl; - struct { uint8_t order_msb2(h, l); }; + castable hl; + struct { castable order_msb2(h, l); }; }; union { - uint16_t ix; - struct { uint8_t order_msb2(ixh, ixl); }; + castable ix; + struct { castable order_msb2(ixh, ixl); }; }; union { - uint16_t iy; - struct { uint8_t order_msb2(iyh, iyl); }; + castable iy; + struct { castable order_msb2(iyh, iyl); }; }; union { - uint16_t ir; - struct { uint8_t order_msb2(i, r); }; + castable ir; + struct { castable order_msb2(i, r); }; }; - uint16_t sp; - uint16_t pc; + uint16 sp; + uint16 pc; boolean iff1; //interrupt flip-flop 1 boolean iff2; //interrupt flip-flop 2 uint2 im; //interrupt mode (0-2) - uint8_t prefix; - uint8_t flag; + uint8 prefix; + uint8 flag; } r; -private: Bus* bus = nullptr; + +private: uint64 instructionsExecuted = 0; }; diff --git a/nall/utility.hpp b/nall/utility.hpp index 23abcc82..f1ab1a7a 100644 --- a/nall/utility.hpp +++ b/nall/utility.hpp @@ -9,6 +9,15 @@ template struct base_from_member { T value; }; +template struct castable { + operator To&() { return (To&)value; } + operator const To&() const { return (const To&)value; } + operator With&() { return value; } + operator const With&() const { return value; } + auto& operator=(const With& value) { return this->value = value; } + With value; +}; + template inline auto allocate(uint size, const T& value) -> T* { T* array = new T[size]; for(uint i = 0; i < size; i++) array[i] = value;