From cea64b9991890910dc912db1f39d307d7fa00764 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sun, 11 Jun 2017 11:51:53 +1000 Subject: [PATCH] Update to v102r23 release. byuu says: Changelog: - rewrote the 6502 CPU core from scratch. Now called MOS6502, supported BCD mode - Famicom core disables BCD mode via MOS6502::BCD = 0; - renamed r65816 folder to wdc65816 (still need to rename the actual class, though ...) Note: need to remove build rules for the now renamed r6502, r65816 objects from processor/GNUmakefile. So this'll seem like a small WIP, but it was a solid five hours to rewrite the entire 6502 core. The reason I wanted to do this was because the old 6502 core was pretty sloppy. My coding style improved a lot, and I really liked how the HuC6280 CPU core came out, so I wanted the 6502 core to be like that one. The core can now support BCD mode, so hopefully that will prove useful to hex\_usr and allow one core to run both the NES and his Atari 2600 cores at some point. Note that right now, the core doesn't support any illegal instructions. The old core supported a small number of them, but were mostly the no operation ones. The goal is support all of the illegal instructions at some point. It's very possible the rewrite introduced some regressions, so thorough testing of the NES core would be appreciated if anyone were up for it. --- higan/emulator/emulator.hpp | 4 +- higan/fc/GNUmakefile | 2 +- higan/fc/cpu/cpu.cpp | 14 +- higan/fc/cpu/cpu.hpp | 2 +- higan/fc/cpu/serialization.cpp | 2 +- higan/fc/cpu/timing.cpp | 10 +- higan/fc/fc.hpp | 2 +- higan/processor/GNUmakefile | 6 +- higan/processor/huc6280/huc6280.cpp | 2 + higan/processor/huc6280/huc6280.hpp | 1 + higan/processor/mos6502/disassembler.cpp | 234 +++++++++++ higan/processor/mos6502/instruction.cpp | 178 +++++++++ higan/processor/mos6502/instructions.cpp | 378 ++++++++++++++++++ higan/processor/mos6502/memory.cpp | 36 ++ higan/processor/mos6502/mos6502.cpp | 59 +++ higan/processor/mos6502/mos6502.hpp | 129 ++++++ higan/processor/mos6502/serialization.cpp | 15 + higan/processor/r6502/algorithms.cpp | 148 ------- higan/processor/r6502/disassembler.cpp | 193 --------- higan/processor/r6502/instructions.cpp | 332 --------------- higan/processor/r6502/memory.cpp | 36 -- higan/processor/r6502/r6502.cpp | 47 --- higan/processor/r6502/r6502.hpp | 115 ------ higan/processor/r6502/registers.hpp | 36 -- higan/processor/r6502/serialization.cpp | 15 - higan/processor/r6502/switch.cpp | 195 --------- .../{r65816 => wdc65816}/algorithms.cpp | 0 .../{r65816 => wdc65816}/disassembler.cpp | 0 .../{r65816 => wdc65816}/disassembler.hpp | 0 .../instructions-misc.cpp | 0 .../{r65816 => wdc65816}/instructions-pc.cpp | 0 .../instructions-read.cpp | 0 .../{r65816 => wdc65816}/instructions-rmw.cpp | 0 .../instructions-write.cpp | 0 .../processor/{r65816 => wdc65816}/memory.hpp | 0 .../{r65816 => wdc65816}/registers.hpp | 0 .../{r65816 => wdc65816}/serialization.cpp | 0 .../processor/{r65816 => wdc65816}/switch.cpp | 0 .../r65816.cpp => wdc65816/wdc65816.cpp} | 2 +- .../r65816.hpp => wdc65816/wdc65816.hpp} | 0 higan/sfc/GNUmakefile | 2 +- higan/sfc/sfc.hpp | 2 +- 42 files changed, 1060 insertions(+), 1137 deletions(-) create mode 100644 higan/processor/mos6502/disassembler.cpp create mode 100644 higan/processor/mos6502/instruction.cpp create mode 100644 higan/processor/mos6502/instructions.cpp create mode 100644 higan/processor/mos6502/memory.cpp create mode 100644 higan/processor/mos6502/mos6502.cpp create mode 100644 higan/processor/mos6502/mos6502.hpp create mode 100644 higan/processor/mos6502/serialization.cpp delete mode 100644 higan/processor/r6502/algorithms.cpp delete mode 100644 higan/processor/r6502/disassembler.cpp delete mode 100644 higan/processor/r6502/instructions.cpp delete mode 100644 higan/processor/r6502/memory.cpp delete mode 100644 higan/processor/r6502/r6502.cpp delete mode 100644 higan/processor/r6502/r6502.hpp delete mode 100644 higan/processor/r6502/registers.hpp delete mode 100644 higan/processor/r6502/serialization.cpp delete mode 100644 higan/processor/r6502/switch.cpp rename higan/processor/{r65816 => wdc65816}/algorithms.cpp (100%) rename higan/processor/{r65816 => wdc65816}/disassembler.cpp (100%) rename higan/processor/{r65816 => wdc65816}/disassembler.hpp (100%) rename higan/processor/{r65816 => wdc65816}/instructions-misc.cpp (100%) rename higan/processor/{r65816 => wdc65816}/instructions-pc.cpp (100%) rename higan/processor/{r65816 => wdc65816}/instructions-read.cpp (100%) rename higan/processor/{r65816 => wdc65816}/instructions-rmw.cpp (100%) rename higan/processor/{r65816 => wdc65816}/instructions-write.cpp (100%) rename higan/processor/{r65816 => wdc65816}/memory.hpp (100%) rename higan/processor/{r65816 => wdc65816}/registers.hpp (100%) rename higan/processor/{r65816 => wdc65816}/serialization.cpp (100%) rename higan/processor/{r65816 => wdc65816}/switch.cpp (100%) rename higan/processor/{r65816/r65816.cpp => wdc65816/wdc65816.cpp} (98%) rename higan/processor/{r65816/r65816.hpp => wdc65816/wdc65816.hpp} (100%) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 9f0b68c5..b79f64e2 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,13 +12,13 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "102.22"; + static const string Version = "102.23"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; //incremented only when serialization format changes - static const string SerializerVersion = "102.20"; + static const string SerializerVersion = "102.23"; namespace Constants { namespace Colorburst { diff --git a/higan/fc/GNUmakefile b/higan/fc/GNUmakefile index 9eed6a49..b95f9b62 100644 --- a/higan/fc/GNUmakefile +++ b/higan/fc/GNUmakefile @@ -1,4 +1,4 @@ -processors += r6502 +processors += mos6502 objects += fc-interface fc-system fc-controller objects += fc-memory fc-cartridge fc-cpu fc-apu fc-ppu diff --git a/higan/fc/cpu/cpu.cpp b/higan/fc/cpu/cpu.cpp index 780a7854..8072928c 100644 --- a/higan/fc/cpu/cpu.cpp +++ b/higan/fc/cpu/cpu.cpp @@ -12,7 +12,12 @@ auto CPU::Enter() -> void { } auto CPU::main() -> void { - if(io.interruptPending) return interrupt(); + if(io.interruptPending) { + uint16 vector = 0xfffe; + if(io.nmiPending) io.nmiPending = false, vector = 0xfffa; + return interrupt(vector); + } + instruction(); } @@ -25,7 +30,8 @@ auto CPU::step(uint clocks) -> void { } auto CPU::power() -> void { - R6502::power(); + MOS6502::BCD = 0; + MOS6502::power(); create(CPU::Enter, system.colorburst() * 6.0); for(auto addr : range(0x0800)) ram[addr] = 0xff; @@ -34,8 +40,8 @@ auto CPU::power() -> void { ram[0x000a] = 0xdf; ram[0x000f] = 0xbf; - regs.pc = bus.read(0xfffc) << 0; - regs.pc |= bus.read(0xfffd) << 8; + r.pc.byte(0) = bus.read(0xfffc); + r.pc.byte(1) = bus.read(0xfffd); memory::fill(&io, sizeof(IO)); io.rdyLine = 1; diff --git a/higan/fc/cpu/cpu.hpp b/higan/fc/cpu/cpu.hpp index 5382dc17..500c308e 100644 --- a/higan/fc/cpu/cpu.hpp +++ b/higan/fc/cpu/cpu.hpp @@ -1,4 +1,4 @@ -struct CPU : Processor::R6502, Thread { +struct CPU : Processor::MOS6502, Thread { static auto Enter() -> void; auto main() -> void; auto step(uint clocks) -> void; diff --git a/higan/fc/cpu/serialization.cpp b/higan/fc/cpu/serialization.cpp index fbd9e644..ef9ddb8b 100644 --- a/higan/fc/cpu/serialization.cpp +++ b/higan/fc/cpu/serialization.cpp @@ -1,5 +1,5 @@ auto CPU::serialize(serializer& s) -> void { - R6502::serialize(s); + MOS6502::serialize(s); Thread::serialize(s); s.array(ram); diff --git a/higan/fc/cpu/timing.cpp b/higan/fc/cpu/timing.cpp index 14a864f4..8b0261fa 100644 --- a/higan/fc/cpu/timing.cpp +++ b/higan/fc/cpu/timing.cpp @@ -6,22 +6,22 @@ auto CPU::read(uint16 addr) -> uint8 { } while(io.rdyLine == 0) { - regs.mdr = bus.read(io.rdyAddrValid ? io.rdyAddrValue : addr); + r.mdr = bus.read(io.rdyAddrValid ? io.rdyAddrValue : addr); step(12); } - regs.mdr = bus.read(addr); + r.mdr = bus.read(addr); step(12); - return regs.mdr; + return r.mdr; } auto CPU::write(uint16 addr, uint8 data) -> void { - bus.write(addr, regs.mdr = data); + bus.write(addr, r.mdr = data); step(12); } auto CPU::lastCycle() -> void { - io.interruptPending = ((io.irqLine | io.apuLine) & ~regs.p.i) | io.nmiPending; + io.interruptPending = ((io.irqLine | io.apuLine) & ~r.p.i) | io.nmiPending; } auto CPU::nmi(uint16& vector) -> void { diff --git a/higan/fc/fc.hpp b/higan/fc/fc.hpp index 115ccd41..30015fef 100644 --- a/higan/fc/fc.hpp +++ b/higan/fc/fc.hpp @@ -8,7 +8,7 @@ #include #include -#include +#include namespace Famicom { #define platform Emulator::platform diff --git a/higan/processor/GNUmakefile b/higan/processor/GNUmakefile index a6fafc01..34c39f6e 100644 --- a/higan/processor/GNUmakefile +++ b/higan/processor/GNUmakefile @@ -6,11 +6,11 @@ objects += $(if $(findstring hg51b,$(processors)),processor-hg51b) objects += $(if $(findstring huc6280,$(processors)),processor-huc6280) objects += $(if $(findstring lr35902,$(processors)),processor-lr35902) objects += $(if $(findstring m68k,$(processors)),processor-m68k) -objects += $(if $(findstring r6502,$(processors)),processor-r6502) -objects += $(if $(findstring r65816,$(processors)),processor-r65816) +objects += $(if $(findstring mos6502,$(processors)),processor-mos6502) objects += $(if $(findstring spc700,$(processors)),processor-spc700) objects += $(if $(findstring upd96050,$(processors)),processor-upd96050) objects += $(if $(findstring v30mz,$(processors)),processor-v30mz) +objects += $(if $(findstring wdc65816,$(processors)),processor-wdc65816) objects += $(if $(findstring z80,$(processors)),processor-z80) obj/processor-arm.o: processor/arm/arm.cpp $(call rwildcard,processor/arm) @@ -19,9 +19,11 @@ obj/processor-hg51b.o: processor/hg51b/hg51b.cpp $(call rwildcard,processor/h obj/processor-huc6280.o: processor/huc6280/huc6280.cpp $(call rwildcard,processor/huc6280) obj/processor-lr35902.o: processor/lr35902/lr35902.cpp $(call rwildcard,processor/lr35902) obj/processor-m68k.o: processor/m68k/m68k.cpp $(call rwildcard,processor/m68k) +obj/processor-mos6502.o: processor/mos6502/mos6502.cpp $(call rwildcard,processor/mos6502) obj/processor-r6502.o: processor/r6502/r6502.cpp $(call rwildcard,processor/r6502) obj/processor-r65816.o: processor/r65816/r65816.cpp $(call rwildcard,processor/r65816) obj/processor-spc700.o: processor/spc700/spc700.cpp $(call rwildcard,processor/spc700) obj/processor-upd96050.o: processor/upd96050/upd96050.cpp $(call rwildcard,processor/upd96050) obj/processor-v30mz.o: processor/v30mz/v30mz.cpp $(call rwildcard,processor/v30mz) +obj/processor-wdc65816.o: processor/wdc65816/wdc65816.cpp $(call rwildcard,processor/wdc65816) obj/processor-z80.o: processor/z80/z80.cpp $(call rwildcard,processor/z80) diff --git a/higan/processor/huc6280/huc6280.cpp b/higan/processor/huc6280/huc6280.cpp index c44828a9..7f17cd03 100644 --- a/higan/processor/huc6280/huc6280.cpp +++ b/higan/processor/huc6280/huc6280.cpp @@ -22,11 +22,13 @@ namespace Processor { #define EA r.ea #define L lastCycle(); #define ALU (this->*alu) + #include "memory.cpp" #include "instruction.cpp" #include "instructions.cpp" #include "disassembler.cpp" #include "serialization.cpp" + #undef A #undef X #undef Y diff --git a/higan/processor/huc6280/huc6280.hpp b/higan/processor/huc6280/huc6280.hpp index 965001c6..59c7b0a7 100644 --- a/higan/processor/huc6280/huc6280.hpp +++ b/higan/processor/huc6280/huc6280.hpp @@ -11,6 +11,7 @@ struct HuC6280 { virtual auto store(uint2 addr, uint8 data) -> void = 0; virtual auto lastCycle() -> void = 0; + //huc6280.cpp auto power() -> void; //memory.cpp diff --git a/higan/processor/mos6502/disassembler.cpp b/higan/processor/mos6502/disassembler.cpp new file mode 100644 index 00000000..597ddfd1 --- /dev/null +++ b/higan/processor/mos6502/disassembler.cpp @@ -0,0 +1,234 @@ +auto MOS6502::disassemble(uint16 pc) -> string { + string s{hex(pc, 4L), " "}; + + auto absolute = [&]() -> string { + return {"$", hex(readDebugger(pc + 2), 2L), hex(readDebugger(pc + 1), 2L)}; + }; + + auto absoluteX = [&]() -> string { + return {"$", hex(readDebugger(pc + 2), 2L), hex(readDebugger(pc + 1), 2L), ",x"}; + }; + + auto absoluteY = [&]() -> string { + return {"$", hex(readDebugger(pc + 2), 2L), hex(readDebugger(pc + 1), 2L), ",y"}; + }; + + auto branch = [&]() -> string { + return {"$", hex((pc + 2) + (int8)readDebugger(pc + 1), 4L)}; + }; + + auto immediate = [&]() -> string { + return {"#$", hex(readDebugger(pc + 1), 2L)}; + }; + + auto implied = [&]() -> string { + return {""}; + }; + + auto indirect = [&]() -> string { + return {"($", hex(readDebugger(pc + 2), 2L), hex(readDebugger(pc + 1), 2L), ")"}; + }; + + auto indirectX = [&]() -> string { + return {"($", hex(readDebugger(pc + 1), 2L), ",x)"}; + }; + + auto indirectY = [&]() -> string { + return {"($", hex(readDebugger(pc + 1), 2L), "),y"}; + }; + + auto zeroPage = [&]() -> string { + return {"$", hex(readDebugger(pc + 1), 2L)}; + }; + + auto zeroPageX = [&]() -> string { + return {"$", hex(readDebugger(pc + 1), 2L), ",x"}; + }; + + auto zeroPageY = [&]() -> string { + return {"$", hex(readDebugger(pc + 1), 2L), ",y"}; + }; + + #define op(id, prefix, mode) \ + case id: s.append(prefix, " ", mode()); \ + break; + + switch(auto opcode = readDebugger(pc)) { + op(0x00, "brk", immediate) + op(0x01, "ora", indirectX) + op(0x05, "ora", zeroPage) + op(0x06, "asl", zeroPage) + op(0x08, "php", implied) + op(0x09, "ora", immediate) + op(0x0a, "asl", implied) + op(0x0d, "ora", absolute) + op(0x0e, "asl", absolute) + op(0x10, "bpl", branch) + op(0x11, "ora", indirectY) + op(0x15, "ora", zeroPageX) + op(0x16, "asl", zeroPageX) + op(0x18, "clc", implied) + op(0x19, "ora", absoluteY) + op(0x1d, "ora", absoluteX) + op(0x1e, "asl", absoluteX) + op(0x20, "jsr", absolute) + op(0x21, "and", indirectX) + op(0x24, "bit", zeroPage) + op(0x25, "and", zeroPage) + op(0x26, "rol", zeroPage) + op(0x28, "plp", implied) + op(0x29, "and", immediate) + op(0x2a, "rol", implied) + op(0x2c, "bit", absolute) + op(0x2d, "and", absolute) + op(0x2e, "rol", absolute) + op(0x30, "bmi", branch) + op(0x31, "and", indirectY) + op(0x35, "and", zeroPageX) + op(0x36, "rol", zeroPageX) + op(0x38, "sec", implied) + op(0x39, "and", absoluteY) + op(0x3d, "and", absoluteX) + op(0x3e, "rol", absoluteX) + op(0x40, "rti", implied) + op(0x41, "eor", indirectX) + op(0x45, "eor", zeroPage) + op(0x46, "lsr", zeroPage) + op(0x48, "pha", implied) + op(0x49, "eor", immediate) + op(0x4a, "lsr", implied) + op(0x4c, "jmp", absolute) + op(0x4d, "eor", absolute) + op(0x4e, "lsr", absolute) + op(0x50, "bvc", branch) + op(0x51, "eor", indirectY) + op(0x55, "eor", zeroPageX) + op(0x56, "lsr", zeroPageX) + op(0x58, "cli", implied) + op(0x59, "eor", absoluteY) + op(0x5d, "eor", absoluteX) + op(0x5e, "lsr", absoluteX) + op(0x60, "rts", implied) + op(0x61, "adc", indirectX) + op(0x65, "adc", zeroPage) + op(0x66, "ror", zeroPage) + op(0x68, "pla", implied) + op(0x69, "adc", immediate) + op(0x6a, "ror", implied) + op(0x6c, "jmp", indirect) + op(0x6d, "adc", absolute) + op(0x6e, "ror", absolute) + op(0x70, "bvs", branch) + op(0x71, "adc", indirectY) + op(0x75, "adc", zeroPageX) + op(0x76, "ror", zeroPageX) + op(0x78, "sei", implied) + op(0x79, "adc", absoluteY) + op(0x7d, "adc", absoluteX) + op(0x7e, "ror", absoluteX) + op(0x81, "sta", indirectX) + op(0x84, "sty", zeroPage) + op(0x85, "sta", zeroPage) + op(0x86, "stx", zeroPage) + op(0x88, "dey", implied) + op(0x8a, "txa", implied) + op(0x8c, "sty", absolute) + op(0x8d, "sta", absolute) + op(0x8e, "stx", absolute) + op(0x90, "bcc", branch) + op(0x91, "sta", indirectY) + op(0x94, "sty", zeroPageX) + op(0x95, "sta", zeroPageX) + op(0x96, "stx", zeroPageY) + op(0x98, "tya", implied) + op(0x99, "sta", absoluteY) + op(0x9a, "txs", implied) + op(0x9d, "sta", absoluteX) + op(0xa0, "ldy", immediate) + op(0xa1, "lda", indirectX) + op(0xa2, "ldx", immediate) + op(0xa4, "ldy", zeroPage) + op(0xa5, "lda", zeroPage) + op(0xa6, "ldx", zeroPage) + op(0xa8, "tay", implied) + op(0xa9, "lda", immediate) + op(0xaa, "tax", implied) + op(0xac, "ldy", absolute) + op(0xad, "lda", absolute) + op(0xae, "ldx", absolute) + op(0xb0, "bcs", branch) + op(0xb1, "lda", indirectY) + op(0xb4, "ldy", zeroPageX) + op(0xb5, "lda", zeroPageX) + op(0xb6, "ldx", zeroPageY) + op(0xb8, "clv", implied) + op(0xb9, "lda", absoluteY) + op(0xba, "tsx", implied) + op(0xbc, "ldy", absoluteX) + op(0xbd, "lda", absoluteX) + op(0xbe, "ldx", absoluteY) + op(0xc0, "cpy", immediate) + op(0xc1, "cmp", indirectX) + op(0xc4, "cpy", zeroPage) + op(0xc5, "cmp", zeroPage) + op(0xc6, "dec", zeroPage) + op(0xc8, "iny", implied) + op(0xc9, "cmp", immediate) + op(0xca, "dex", implied) + op(0xcc, "cpy", absolute) + op(0xcd, "cmp", absolute) + op(0xce, "dec", absolute) + op(0xd0, "bne", branch) + op(0xd1, "cmp", indirectY) + op(0xd5, "cmp", zeroPageX) + op(0xd6, "dec", zeroPageX) + op(0xd8, "cld", implied) + op(0xd9, "cmp", absoluteY) + op(0xdd, "cmp", absoluteX) + op(0xde, "dec", absoluteX) + op(0xe0, "cpx", immediate) + op(0xe1, "sbc", indirectX) + op(0xe4, "cpx", zeroPage) + op(0xe5, "sbc", zeroPage) + op(0xe6, "inc", zeroPage) + op(0xe8, "inx", implied) + op(0xe9, "sbc", immediate) + op(0xea, "nop", implied) + op(0xec, "cpx", absolute) + op(0xed, "sbc", absolute) + op(0xee, "inc", absolute) + op(0xf0, "beq", branch) + op(0xf1, "sbc", indirectY) + op(0xf5, "sbc", zeroPageX) + op(0xf6, "inc", zeroPageX) + op(0xf8, "sed", implied) + op(0xf9, "sbc", absoluteY) + op(0xfd, "sbc", absoluteX) + op(0xfe, "inc", absoluteX) + + default: + s.append("$", hex(opcode, 2L)); + break; + } + + #undef op + + s.append(" "); + s.resize(20); + + s.append(" A:", hex(A, 2L)); + s.append(" X:", hex(X, 2L)); + s.append(" Y:", hex(Y, 2L)); + s.append(" S:", hex(S, 2L)); + s.append(" "); + s.append(N ? "N" : "n"); + s.append(V ? "V" : "v"); + s.append("-"); + s.append("-"); + s.append(D ? "D" : "d"); + s.append(I ? "I" : "i"); + s.append(Z ? "Z" : "z"); + s.append(C ? "C" : "c"); + + return s; +} diff --git a/higan/processor/mos6502/instruction.cpp b/higan/processor/mos6502/instruction.cpp new file mode 100644 index 00000000..707e2a34 --- /dev/null +++ b/higan/processor/mos6502/instruction.cpp @@ -0,0 +1,178 @@ +#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); +#define fp(name) &MOS6502::name + +auto MOS6502::interrupt(uint16 vector) -> void { + idle(); + idle(); + push(PCH); + push(PCL); + push(P); + PCL = read(vector++); +L PCH = read(vector++); + I = 1; + D = 0; +} + +auto MOS6502::instruction() -> void { + auto code = opcode(); + + switch(code) { + op(0x00, BRK) + op(0x01, IndirectXRead, fp(ORA), A) + op(0x05, ZeroPageRead, fp(ORA), A) + op(0x06, ZeroPageModify, fp(ASL)) + op(0x08, PHP) + op(0x09, Immediate, fp(ORA), A) + op(0x0a, Implied, fp(ASL), A) + op(0x0d, AbsoluteRead, fp(ORA), A) + op(0x0e, AbsoluteModify, fp(ASL)) + op(0x10, Branch, N == 0) + op(0x11, IndirectYRead, fp(ORA), A) + op(0x15, ZeroPageRead, fp(ORA), A, X) + op(0x16, ZeroPageModify, fp(ASL), X) + op(0x18, Clear, C) + op(0x19, AbsoluteRead, fp(ORA), A, Y) + op(0x1d, AbsoluteRead, fp(ORA), A, X) + op(0x1e, AbsoluteModify, fp(ASL), X) + op(0x20, JSRAbsolute) + op(0x21, IndirectXRead, fp(AND), A) + op(0x24, ZeroPageRead, fp(BIT), A) + op(0x25, ZeroPageRead, fp(AND), A) + op(0x26, ZeroPageModify, fp(ROL)) + op(0x28, PLP) + op(0x29, Immediate, fp(AND), A) + op(0x2a, Implied, fp(ROL), A) + op(0x2c, AbsoluteRead, fp(BIT), A) + op(0x2d, AbsoluteRead, fp(AND), A) + op(0x2e, AbsoluteModify, fp(ROL)) + op(0x30, Branch, N == 1) + op(0x31, IndirectYRead, fp(AND), A) + op(0x35, ZeroPageRead, fp(AND), A, X) + op(0x36, ZeroPageModify, fp(ROL), X) + op(0x38, Set, C) + op(0x39, AbsoluteRead, fp(AND), A, Y) + op(0x3d, AbsoluteRead, fp(AND), A, X) + op(0x3e, AbsoluteModify, fp(ROL), X) + op(0x40, RTI) + op(0x41, IndirectXRead, fp(EOR), A) + op(0x45, ZeroPageRead, fp(EOR), A) + op(0x46, ZeroPageModify, fp(LSR)) + op(0x48, Push, A) + op(0x49, Immediate, fp(EOR), A) + op(0x4a, Implied, fp(LSR), A) + op(0x4c, JMPAbsolute) + op(0x4d, AbsoluteRead, fp(EOR), A) + op(0x4e, AbsoluteModify, fp(LSR)) + op(0x50, Branch, V == 0) + op(0x51, IndirectYRead, fp(EOR), A) + op(0x55, ZeroPageRead, fp(EOR), A, X) + op(0x56, ZeroPageModify, fp(LSR), X) + op(0x58, Clear, I) + op(0x59, AbsoluteRead, fp(EOR), A, Y) + op(0x5d, AbsoluteRead, fp(EOR), A, X) + op(0x5e, AbsoluteModify, fp(LSR), X) + op(0x60, RTS) + op(0x61, IndirectXRead, fp(ADC), A) + op(0x65, ZeroPageRead, fp(ADC), A) + op(0x66, ZeroPageModify, fp(ROR)) + op(0x68, Pull, A) + op(0x69, Immediate, fp(ADC), A) + op(0x6a, Implied, fp(ROR), A) + op(0x6c, JMPIndirect) + op(0x6d, AbsoluteRead, fp(ADC), A) + op(0x6e, AbsoluteModify, fp(ROR)) + op(0x70, Branch, V == 1) + op(0x71, IndirectYRead, fp(ADC), A) + op(0x75, ZeroPageRead, fp(ADC), A, X) + op(0x76, ZeroPageModify, fp(ROR), X) + op(0x78, Set, I) + op(0x79, AbsoluteRead, fp(ADC), A, Y) + op(0x7d, AbsoluteRead, fp(ADC), A, X) + op(0x7e, AbsoluteModify, fp(ROR), X) + op(0x81, IndirectXWrite, A) + op(0x84, ZeroPageWrite, Y) + op(0x85, ZeroPageWrite, A) + op(0x86, ZeroPageWrite, X) + op(0x88, Implied, fp(DEC), Y) + op(0x8a, Transfer, X, A, 1) + op(0x8c, AbsoluteWrite, Y) + op(0x8d, AbsoluteWrite, A) + op(0x8e, AbsoluteWrite, X) + op(0x90, Branch, C == 0) + op(0x91, IndirectYWrite, A) + op(0x94, ZeroPageWrite, Y, X) + op(0x95, ZeroPageWrite, A, X) + op(0x96, ZeroPageWrite, X, Y) + op(0x98, Transfer, Y, A, 1) + op(0x99, AbsoluteWrite, A, Y) + op(0x9a, Transfer, X, S, 0) + op(0x9d, AbsoluteWrite, A, X) + op(0xa0, Immediate, fp(LD), Y) + op(0xa1, IndirectXRead, fp(LD), A) + op(0xa2, Immediate, fp(LD), X) + op(0xa4, ZeroPageRead, fp(LD), Y) + op(0xa5, ZeroPageRead, fp(LD), A) + op(0xa6, ZeroPageRead, fp(LD), X) + op(0xa8, Transfer, A, Y, 1) + op(0xa9, Immediate, fp(LD), A) + op(0xaa, Transfer, A, X, 1) + op(0xac, AbsoluteRead, fp(LD), Y) + op(0xad, AbsoluteRead, fp(LD), A) + op(0xae, AbsoluteRead, fp(LD), X) + op(0xb0, Branch, C == 1) + op(0xb1, IndirectYRead, fp(LD), A) + op(0xb4, ZeroPageRead, fp(LD), Y, X) + op(0xb5, ZeroPageRead, fp(LD), A, X) + op(0xb6, ZeroPageRead, fp(LD), X, Y) + op(0xb8, Clear, V) + op(0xb9, AbsoluteRead, fp(LD), A, Y) + op(0xba, Transfer, S, X, 1) + op(0xbc, AbsoluteRead, fp(LD), Y, X) + op(0xbd, AbsoluteRead, fp(LD), A, X) + op(0xbe, AbsoluteRead, fp(LD), X, Y) + op(0xc0, Immediate, fp(CPY), Y) + op(0xc1, IndirectXRead, fp(CMP), A) + op(0xc4, ZeroPageRead, fp(CPY), Y) + op(0xc5, ZeroPageRead, fp(CMP), A) + op(0xc6, ZeroPageModify, fp(DEC)) + op(0xc8, Implied, fp(INC), Y) + op(0xc9, Immediate, fp(CMP), A) + op(0xca, Implied, fp(DEC), X) + op(0xcc, AbsoluteRead, fp(CPY), Y) + op(0xcd, AbsoluteRead, fp(CMP), A) + op(0xce, AbsoluteModify, fp(DEC)) + op(0xd0, Branch, Z == 0) + op(0xd1, IndirectYRead, fp(CMP), A) + op(0xd5, ZeroPageRead, fp(CMP), A, X) + op(0xd6, ZeroPageModify, fp(DEC), X) + op(0xd8, Clear, D) + op(0xd9, AbsoluteRead, fp(CMP), A, Y) + op(0xdd, AbsoluteRead, fp(CMP), A, X) + op(0xde, AbsoluteModify, fp(DEC), X) + op(0xe0, Immediate, fp(CPX), X) + op(0xe1, IndirectXRead, fp(SBC), A) + op(0xe4, ZeroPageRead, fp(CPX), X) + op(0xe5, ZeroPageRead, fp(SBC), A) + op(0xe6, ZeroPageModify, fp(INC)) + op(0xe8, Implied, fp(INC), X) + op(0xe9, Immediate, fp(SBC), A) + op(0xea, NOP) + op(0xec, AbsoluteRead, fp(CPX), X) + op(0xed, AbsoluteRead, fp(SBC), A) + op(0xee, AbsoluteModify, fp(INC)) + op(0xf0, Branch, Z == 1) + op(0xf1, IndirectYRead, fp(SBC), A) + op(0xf5, ZeroPageRead, fp(SBC), A, X) + op(0xf6, ZeroPageModify, fp(INC), X) + op(0xf8, Set, D) + op(0xf9, AbsoluteRead, fp(SBC), A, Y) + op(0xfd, AbsoluteRead, fp(SBC), A, X) + op(0xfe, AbsoluteModify, fp(INC), X) + } + + //unimplemented instruction + return instructionNOP(); +} + +#undef op +#undef fp diff --git a/higan/processor/mos6502/instructions.cpp b/higan/processor/mos6502/instructions.cpp new file mode 100644 index 00000000..8e12c77d --- /dev/null +++ b/higan/processor/mos6502/instructions.cpp @@ -0,0 +1,378 @@ +auto MOS6502::ADC(uint8 i) -> uint8 { + int16 o; + if(!BCD || !D) { + o = A + i + C; + V = ~(A ^ i) & (A ^ o) & 0x80; + } else { + idle(); + o = (A & 0x0f) + (i & 0x0f) + (C << 0); + if(o > 0x09) o += 0x06; + C = o > 0x0f; + o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f); + if(o > 0x9f) o += 0x60; + } + C = o.bit(8); + Z = uint8(o) == 0; + N = o.bit(7); + return o; +} + +auto MOS6502::AND(uint8 i) -> uint8 { + uint8 o = A & i; + Z = o == 0; + N = o.bit(7); + return o; +} + +auto MOS6502::ASL(uint8 i) -> uint8 { + C = i.bit(7); + i <<= 1; + Z = i == 0; + N = i.bit(7); + return i; +} + +auto MOS6502::BIT(uint8 i) -> uint8 { + Z = (A & i) == 0; + V = i.bit(6); + N = i.bit(7); + return A; +} + +auto MOS6502::CMP(uint8 i) -> uint8 { + uint9 o = A - i; + C = !o.bit(8); + Z = uint8(o) == 0; + N = o.bit(7); + return A; +} + +auto MOS6502::CPX(uint8 i) -> uint8 { + uint9 o = X - i; + C = !o.bit(8); + Z = uint8(o) == 0; + N = o.bit(7); + return X; +} + +auto MOS6502::CPY(uint8 i) -> uint8 { + uint9 o = Y - i; + C = !o.bit(8); + Z = uint8(o) == 0; + N = o.bit(7); + return Y; +} + +auto MOS6502::DEC(uint8 i) -> uint8 { + i--; + Z = i == 0; + N = i.bit(7); + return i; +} + +auto MOS6502::EOR(uint8 i) -> uint8 { + uint8 o = A ^ i; + Z = o == 0; + N = o.bit(7); + return o; +} + +auto MOS6502::INC(uint8 i) -> uint8 { + i++; + Z = i == 0; + N = i.bit(7); + return i; +} + +auto MOS6502::LD(uint8 i) -> uint8 { + Z = i == 0; + N = i.bit(7); + return i; +} + +auto MOS6502::LSR(uint8 i) -> uint8 { + C = i.bit(0); + i >>= 1; + Z = i == 0; + N = i.bit(7); + return i; +} + +auto MOS6502::ORA(uint8 i) -> uint8 { + uint8 o = A | i; + Z = o == 0; + N = o.bit(7); + return o; +} + +auto MOS6502::ROL(uint8 i) -> uint8 { + bool c = C; + C = i.bit(7); + i = i << 1 | c; + Z = i == 0; + N = i.bit(7); + return i; +} + +auto MOS6502::ROR(uint8 i) -> uint8 { + bool c = C; + C = i.bit(0); + i = c << 7 | i >> 1; + Z = i == 0; + N = i.bit(7); + return i; +} + +auto MOS6502::SBC(uint8 i) -> uint8 { + i ^= 0xff; + int16 o; + if(!BCD || !D) { + o = A + i + C; + V = ~(A ^ i) & (A ^ o) & 0x80; + } else { + idle(); + o = (A & 0x0f) + (i & 0x0f) + (C << 0); + if(o <= 0x0f) o -= 0x06; + C = o > 0x0f; + o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f); + if(o <= 0xff) o -= 0x60; + } + C = o.bit(8); + Z = uint8(o) == 0; + N = o.bit(7); + return o; +} + +// + +auto MOS6502::instructionAbsoluteModify(fp alu) -> void { + uint16 absolute = operand(); + absolute |= operand() << 8; + auto data = read(absolute); + write(absolute, data); +L write(absolute, ALU(data)); +} + +auto MOS6502::instructionAbsoluteModify(fp alu, uint8 index) -> void { + uint16 absolute = operand(); + absolute |= operand() << 8; + idlePageAlways(absolute, absolute + index); + auto data = read(absolute + index); + write(absolute + index, data); +L write(absolute + index, ALU(data)); +} + +auto MOS6502::instructionAbsoluteRead(fp alu, uint8& data) -> void { + uint16 absolute = operand(); + absolute |= operand() << 8; +L data = ALU(read(absolute)); +} + +auto MOS6502::instructionAbsoluteRead(fp alu, uint8& data, uint8 index) -> void { + uint16 absolute = operand(); + absolute |= operand() << 8; + idlePageCrossed(absolute, absolute + index); +L data = ALU(read(absolute + index)); +} + +auto MOS6502::instructionAbsoluteWrite(uint8& data) -> void { + uint16 absolute = operand(); + absolute |= operand() << 8; +L write(absolute, data); +} + +auto MOS6502::instructionAbsoluteWrite(uint8& data, uint8 index) -> void { + uint16 absolute = operand(); + absolute |= operand() << 8; + idlePageAlways(absolute, absolute + index); +L write(absolute + index, data); +} + +auto MOS6502::instructionBranch(bool take) -> void { + if(!take) { + L operand(); + } else { + int8 displacement = operand(); + idlePageCrossed(PC, PC + displacement); + L idle(); + PC = PC + displacement; + } +} + +auto MOS6502::instructionClear(bool& flag) -> void { +L idle(); + flag = 0; +} + +auto MOS6502::instructionImmediate(fp alu, uint8& data) -> void { +L data = ALU(operand()); +} + +auto MOS6502::instructionImplied(fp alu, uint8& data) -> void { +L idle(); + data = ALU(data); +} + +auto MOS6502::instructionIndirectXRead(fp alu, uint8& data) -> void { + auto zeroPage = operand(); + load(zeroPage); + uint16 absolute = load(zeroPage + X + 0); + absolute |= load(zeroPage + X + 1) << 8; +L data = ALU(read(absolute)); +} + +auto MOS6502::instructionIndirectXWrite(uint8& data) -> void { + auto zeroPage = operand(); + load(zeroPage); + uint16 absolute = load(zeroPage + X + 0); + absolute |= load(zeroPage + X + 1) << 8; +L write(absolute, data); +} + +auto MOS6502::instructionIndirectYRead(fp alu, uint8& data) -> void { + auto zeroPage = operand(); + uint16 absolute = load(zeroPage + 0); + absolute |= load(zeroPage + 1) << 8; + idlePageCrossed(absolute, absolute + Y); +L data = ALU(read(absolute + Y)); +} + +auto MOS6502::instructionIndirectYWrite(uint8& data) -> void { + auto zeroPage = operand(); + uint16 absolute = load(zeroPage + 0); + absolute |= load(zeroPage + 1) << 8; + idlePageAlways(absolute, absolute + Y); +L write(absolute + Y, data); +} + +auto MOS6502::instructionPull(uint8& data) -> void { + idle(); + idle(); +L data = pull(); + Z = data == 0; + N = data.bit(7); +} + +auto MOS6502::instructionPush(uint8& data) -> void { + idle(); +L push(data); +} + +auto MOS6502::instructionSet(bool& flag) -> void { +L idle(); + flag = 1; +} + +auto MOS6502::instructionTransfer(uint8& source, uint8& target, bool flag) -> void { +L idle(); + target = source; + if(!flag) return; + Z = target == 0; + N = target.bit(7); +} + +auto MOS6502::instructionZeroPageModify(fp alu) -> void { + auto zeroPage = operand(); + auto data = load(zeroPage); + store(zeroPage, data); +L store(zeroPage, ALU(data)); +} + +auto MOS6502::instructionZeroPageModify(fp alu, uint8 index) -> void { + auto zeroPage = operand(); + load(zeroPage); + auto data = load(zeroPage + index); + store(zeroPage + index, data); +L store(zeroPage + index, ALU(data)); +} + +auto MOS6502::instructionZeroPageRead(fp alu, uint8& data) -> void { + auto zeroPage = operand(); +L data = ALU(load(zeroPage)); +} + +auto MOS6502::instructionZeroPageRead(fp alu, uint8& data, uint8 index) -> void { + auto zeroPage = operand(); + load(zeroPage); +L data = ALU(load(zeroPage + index)); +} + +auto MOS6502::instructionZeroPageWrite(uint8& data) -> void { + auto zeroPage = operand(); +L store(zeroPage, data); +} + +auto MOS6502::instructionZeroPageWrite(uint8& data, uint8 index) -> void { + auto zeroPage = operand(); + read(zeroPage); +L store(zeroPage + index, data); +} + +// + +auto MOS6502::instructionBRK() -> void { + operand(); + push(PCH); + push(PCL); + push(P | 0x30); + PCL = read(0xfffe); +L PCH = read(0xffff); + I = 1; + D = 0; +} + +auto MOS6502::instructionJMPAbsolute() -> void { + uint16 absolute = operand(); +L absolute |= operand() << 8; + PC = absolute; +} + +auto MOS6502::instructionJMPIndirect() -> void { + uint16 absolute = operand(); + absolute |= operand() << 8; + uint16 pc = read(absolute); +L pc |= read((absolute & 0xff00) | ((absolute & 0x00ff) + 1)) << 8; + PC = pc; +} + +auto MOS6502::instructionJSRAbsolute() -> void { + uint16 absolute = operand(); + absolute |= operand() << 8; + idle(); + PC--; + push(PCH); +L push(PCL); + PC = absolute; +} + +auto MOS6502::instructionNOP() -> void { + idle(); +} + +auto MOS6502::instructionPHP() -> void { + idle(); +L push(P | 0x30); +} + +auto MOS6502::instructionPLP() -> void { + idle(); + idle(); +L P = pull(); +} + +auto MOS6502::instructionRTI() -> void { + idle(); + idle(); + P = pull(); + PCL = pull(); +L PCH = pull(); +} + +auto MOS6502::instructionRTS() -> void { + idle(); + idle(); + PCL = pull(); + PCH = pull(); +L idle(); + PC++; +} diff --git a/higan/processor/mos6502/memory.cpp b/higan/processor/mos6502/memory.cpp new file mode 100644 index 00000000..d666b835 --- /dev/null +++ b/higan/processor/mos6502/memory.cpp @@ -0,0 +1,36 @@ +auto MOS6502::idle() -> void { + read(PC); +} + +auto MOS6502::idlePageCrossed(uint16 x, uint16 y) -> void { + if(x >> 8 == y >> 8) return; + read((x & 0xff00) | (y & 0x00ff)); +} + +auto MOS6502::idlePageAlways(uint16 x, uint16 y) -> void { + read((x & 0xff00) | (y & 0x00ff)); +} + +auto MOS6502::opcode() -> uint8 { + return read(PC++); +} + +auto MOS6502::operand() -> uint8 { + return read(PC++); +} + +auto MOS6502::load(uint8 addr) -> uint8 { + return read(addr); +} + +auto MOS6502::store(uint8 addr, uint8 data) -> void { + write(addr, data); +} + +auto MOS6502::push(uint8 data) -> void { + write(0x0100 | S--, data); +} + +auto MOS6502::pull() -> uint8 { + return read(0x0100 | ++S); +} diff --git a/higan/processor/mos6502/mos6502.cpp b/higan/processor/mos6502/mos6502.cpp new file mode 100644 index 00000000..1e5cd8f2 --- /dev/null +++ b/higan/processor/mos6502/mos6502.cpp @@ -0,0 +1,59 @@ +#include +#include "mos6502.hpp" + +namespace Processor { + +#define A r.a +#define X r.x +#define Y r.y +#define S r.s +#define P r.p +#define PC r.pc +#define PCH r.pc.byte(1) +#define PCL r.pc.byte(0) +#define ALU (this->*alu) +#define C r.p.c +#define Z r.p.z +#define I r.p.i +#define D r.p.d +#define V r.p.v +#define N r.p.n +#define L lastCycle(); + +#include "memory.cpp" +#include "instruction.cpp" +#include "instructions.cpp" +#include "disassembler.cpp" +#include "serialization.cpp" + +#undef A +#undef X +#undef Y +#undef S +#undef P +#undef PC +#undef PCH +#undef PCL +#undef ALU +#undef C +#undef Z +#undef I +#undef D +#undef V +#undef N +#undef L + +auto MOS6502::mdr() const -> uint8 { + return r.mdr; +} + +auto MOS6502::power() -> void { + r.a = 0x00; + r.x = 0x00; + r.y = 0x00; + r.s = 0xff; + r.p = 0x04; + r.mdr = 0x00; +} + +} diff --git a/higan/processor/mos6502/mos6502.hpp b/higan/processor/mos6502/mos6502.hpp new file mode 100644 index 00000000..e45d866e --- /dev/null +++ b/higan/processor/mos6502/mos6502.hpp @@ -0,0 +1,129 @@ +//MOS Technologies MOS6502 + +#pragma once + +namespace Processor { + +struct MOS6502 { + virtual auto read(uint16 addr) -> uint8 = 0; + virtual auto write(uint16 addr, uint8 data) -> void = 0; + virtual auto lastCycle() -> void = 0; + virtual auto nmi(uint16& vector) -> void = 0; + virtual auto readDebugger(uint16 addr) -> uint8 { return 0; } + + //mos6502.cpp + auto mdr() const -> uint8; + auto power() -> void; + + //memory.cpp + auto idle() -> void; + auto idlePageCrossed(uint16, uint16) -> void; + auto idlePageAlways(uint16, uint16) -> void; + auto opcode() -> uint8; + auto operand() -> uint8; + auto load(uint8 addr) -> uint8; + auto store(uint8 addr, uint8 data) -> void; + auto push(uint8 data) -> void; + auto pull() -> uint8; + + //instruction.cpp + auto interrupt(uint16 vector) -> void; + auto instruction() -> void; + + //instructions.cpp + using fp = auto (MOS6502::*)(uint8) -> uint8; + auto ADC(uint8) -> uint8; + auto AND(uint8) -> uint8; + auto ASL(uint8) -> uint8; + auto BIT(uint8) -> uint8; + auto CMP(uint8) -> uint8; + auto CPX(uint8) -> uint8; + auto CPY(uint8) -> uint8; + auto DEC(uint8) -> uint8; + auto EOR(uint8) -> uint8; + auto INC(uint8) -> uint8; + auto LD (uint8) -> uint8; + auto LSR(uint8) -> uint8; + auto ORA(uint8) -> uint8; + auto ROL(uint8) -> uint8; + auto ROR(uint8) -> uint8; + auto SBC(uint8) -> uint8; + + auto instructionAbsoluteModify(fp alu) -> void; + auto instructionAbsoluteModify(fp alu, uint8 index) -> void; + auto instructionAbsoluteRead(fp alu, uint8& data) -> void; + auto instructionAbsoluteRead(fp alu, uint8& data, uint8 index) -> void; + auto instructionAbsoluteWrite(uint8& data) -> void; + auto instructionAbsoluteWrite(uint8& data, uint8 index) -> void; + auto instructionBranch(bool take) -> void; + auto instructionClear(bool& flag) -> void; + auto instructionImmediate(fp alu, uint8& data) -> void; + auto instructionImplied(fp alu, uint8& data) -> void; + auto instructionIndirectXRead(fp alu, uint8& data) -> void; + auto instructionIndirectXWrite(uint8& data) -> void; + auto instructionIndirectYRead(fp alu, uint8& data) -> void; + auto instructionIndirectYWrite(uint8& data) -> void; + auto instructionPull(uint8& data) -> void; + auto instructionPush(uint8& data) -> void; + auto instructionSet(bool& flag) -> void; + auto instructionTransfer(uint8& source, uint8& target, bool flag) -> void; + auto instructionZeroPageModify(fp alu) -> void; + auto instructionZeroPageModify(fp alu, uint8 index) -> void; + auto instructionZeroPageRead(fp alu, uint8& data) -> void; + auto instructionZeroPageRead(fp alu, uint8& data, uint8 index) -> void; + auto instructionZeroPageWrite(uint8& data) -> void; + auto instructionZeroPageWrite(uint8& data, uint8 index) -> void; + + auto instructionBRK() -> void; + auto instructionJMPAbsolute() -> void; + auto instructionJMPIndirect() -> void; + auto instructionJSRAbsolute() -> void; + auto instructionNOP() -> void; + auto instructionPHP() -> void; + auto instructionPLP() -> void; + auto instructionRTI() -> void; + auto instructionRTS() -> void; + + //serialization.cpp + auto serialize(serializer&) -> void; + + //disassembler.cpp + auto disassemble(uint16 pc) -> string; + + struct Flags { + bool c; //carry + bool z; //zero + bool i; //interrupt disable + bool d; //decimal mode + bool v; //overflow + bool n; //negative + + inline operator uint() const { + return c << 0 | z << 1 | i << 2 | d << 3 | v << 6 | n << 7; + } + + inline auto& operator=(uint8 data) { + c = data.bit(0); + z = data.bit(1); + i = data.bit(2); + d = data.bit(3); + v = data.bit(6); + n = data.bit(7); + return *this; + } + }; + + struct Registers { + uint8 a; + uint8 x; + uint8 y; + uint8 s; + uint16 pc; + Flags p; + uint8 mdr; + } r; + + bool BCD = true; +}; + +} diff --git a/higan/processor/mos6502/serialization.cpp b/higan/processor/mos6502/serialization.cpp new file mode 100644 index 00000000..322e203d --- /dev/null +++ b/higan/processor/mos6502/serialization.cpp @@ -0,0 +1,15 @@ +auto MOS6502::serialize(serializer& s) -> void { + s.integer(r.a); + s.integer(r.x); + s.integer(r.y); + s.integer(r.s); + s.integer(r.pc); + s.integer(r.p.c); + s.integer(r.p.z); + s.integer(r.p.i); + s.integer(r.p.d); + s.integer(r.p.v); + s.integer(r.p.n); + s.integer(r.mdr); + s.integer(BCD); +} diff --git a/higan/processor/r6502/algorithms.cpp b/higan/processor/r6502/algorithms.cpp deleted file mode 100644 index 27c786e1..00000000 --- a/higan/processor/r6502/algorithms.cpp +++ /dev/null @@ -1,148 +0,0 @@ -auto R6502::fp_adc() { - int result = regs.a + rd + regs.p.c; - regs.p.v = ~(regs.a ^ rd) & (regs.a ^ result) & 0x80; - regs.p.c = (result > 0xff); - regs.p.n = (result & 0x80); - regs.p.z = ((uint8)result == 0); - regs.a = result; -} - -auto R6502::fp_and() { - regs.a &= rd; - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -auto R6502::fp_asl() { - regs.p.c = rd & 0x80; - rd <<= 1; - regs.p.n = (rd & 0x80); - regs.p.z = (rd == 0); -} - -auto R6502::fp_bit() { - regs.p.n = (rd & 0x80); - regs.p.v = (rd & 0x40); - regs.p.z = ((rd & regs.a) == 0); -} - -auto R6502::fp_cmp() { - int r = regs.a - rd; - regs.p.n = (r & 0x80); - regs.p.z = (uint8)(r == 0); - regs.p.c = (r >= 0); -} - -auto R6502::fp_cpx() { - int r = regs.x - rd; - regs.p.n = (r & 0x80); - regs.p.z = (uint8)(r == 0); - regs.p.c = (r >= 0); -} - -auto R6502::fp_cpy() { - int r = regs.y - rd; - regs.p.n = (r & 0x80); - regs.p.z = (uint8)(r == 0); - regs.p.c = (r >= 0); -} - -auto R6502::fp_dec() { - rd--; - regs.p.n = (rd & 0x80); - regs.p.z = (rd == 0); -} - -auto R6502::fp_eor() { - regs.a ^= rd; - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -auto R6502::fp_inc() { - rd++; - regs.p.n = (rd & 0x80); - regs.p.z = (rd == 0); -} - -auto R6502::fp_lda() { - regs.a = rd; - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -auto R6502::fp_ldx() { - regs.x = rd; - regs.p.n = (regs.x & 0x80); - regs.p.z = (regs.x == 0); -} - -auto R6502::fp_ldy() { - regs.y = rd; - regs.p.n = (regs.y & 0x80); - regs.p.z = (regs.y == 0); -} - -auto R6502::fp_lsr() { - regs.p.c = rd & 0x01; - rd >>= 1; - regs.p.n = (rd & 0x80); - regs.p.z = (rd == 0); -} - -auto R6502::fp_ora() { - regs.a |= rd; - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -auto R6502::fp_rla() { - uint carry = (uint)regs.p.c; - regs.p.c = regs.a & 0x80; - regs.a = (regs.a << 1) | carry; - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -auto R6502::fp_rol() { - uint carry = (uint)regs.p.c; - regs.p.c = rd & 0x80; - rd = (rd << 1) | carry; - regs.p.n = (rd & 0x80); - regs.p.z = (rd == 0); -} - -auto R6502::fp_ror() { - uint carry = (uint)regs.p.c << 7; - regs.p.c = rd & 0x01; - rd = carry | (rd >> 1); - regs.p.n = (rd & 0x80); - regs.p.z = (rd == 0); -} - -auto R6502::fp_rra() { - uint carry = (uint)regs.p.c << 7; - regs.p.c = regs.a & 0x01; - regs.a = carry | (regs.a >> 1); - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -auto R6502::fp_sbc() { - rd ^= 0xff; - return fp_adc(); -} - -auto R6502::fp_sla() { - regs.p.c = regs.a & 0x80; - regs.a <<= 1; - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} - -auto R6502::fp_sra() { - regs.p.c = regs.a & 0x01; - regs.a >>= 1; - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); -} diff --git a/higan/processor/r6502/disassembler.cpp b/higan/processor/r6502/disassembler.cpp deleted file mode 100644 index c9ee6b09..00000000 --- a/higan/processor/r6502/disassembler.cpp +++ /dev/null @@ -1,193 +0,0 @@ -auto R6502::disassemble() -> string { - string output = {hex(regs.pc, 4L), " "}; - - auto abs = [&]() -> string { return {"$", hex(readDebugger(regs.pc + 2), 2L), hex(readDebugger(regs.pc + 1), 2L)}; }; - auto abx = [&]() -> string { return {"$", hex(readDebugger(regs.pc + 2), 2L), hex(readDebugger(regs.pc + 1), 2L), ",x"}; }; - auto aby = [&]() -> string { return {"$", hex(readDebugger(regs.pc + 2), 2L), hex(readDebugger(regs.pc + 1), 2L), ",y"}; }; - auto iab = [&]() -> string { return {"($", hex(readDebugger(regs.pc + 2), 2L), hex(readDebugger(regs.pc + 1), 2L), ")"}; }; - auto imm = [&]() -> string { return {"#$", hex(readDebugger(regs.pc + 1), 2L)}; }; - auto imp = [&]() -> string { return {""}; }; - auto izx = [&]() -> string { return {"($", hex(readDebugger(regs.pc + 1), 2L), ",x)"}; }; - auto izy = [&]() -> string { return {"($", hex(readDebugger(regs.pc + 1), 2L), "),y"}; }; - auto rel = [&]() -> string { return {"$", hex((regs.pc + 2) + (int8)readDebugger(regs.pc + 1), 4L)}; }; - auto zpg = [&]() -> string { return {"$", hex(readDebugger(regs.pc + 1), 2L)}; }; - auto zpx = [&]() -> string { return {"$", hex(readDebugger(regs.pc + 1), 2L), ",x"}; }; - auto zpy = [&]() -> string { return {"$", hex(readDebugger(regs.pc + 1), 2L), ",y"}; }; - - #define op(byte, prefix, mode) \ - case byte: output.append(#prefix, " ", mode()); \ - break - - switch(auto opcode = readDebugger(regs.pc)) { - op(0x00, brk, imm); - op(0x01, ora, izx); - op(0x05, ora, zpg); - op(0x06, asl, zpg); - op(0x08, php, imp); - op(0x09, ora, imm); - op(0x0a, asl, imp); - op(0x0d, ora, abs); - op(0x0e, asl, abs); - op(0x10, bpl, rel); - op(0x11, ora, izy); - op(0x15, ora, zpx); - op(0x16, asl, zpx); - op(0x18, clc, imp); - op(0x19, ora, aby); - op(0x1d, ora, abx); - op(0x1e, asl, abx); - op(0x20, jsr, abs); - op(0x21, and, izx); - op(0x24, bit, zpg); - op(0x25, and, zpg); - op(0x26, rol, zpg); - op(0x28, plp, imp); - op(0x29, and, imm); - op(0x2a, rol, imp); - op(0x2c, bit, abs); - op(0x2d, and, abs); - op(0x2e, rol, abs); - op(0x30, bmi, rel); - op(0x31, and, izy); - op(0x35, and, zpx); - op(0x36, rol, zpx); - op(0x38, sec, imp); - op(0x39, and, aby); - op(0x3d, and, abx); - op(0x3e, rol, abx); - op(0x40, rti, imp); - op(0x41, eor, izx); - op(0x45, eor, zpg); - op(0x46, lsr, zpg); - op(0x48, pha, imp); - op(0x49, eor, imm); - op(0x4a, lsr, imp); - op(0x4c, jmp, abs); - op(0x4d, eor, abs); - op(0x4e, lsr, abs); - op(0x50, bvc, rel); - op(0x51, eor, izy); - op(0x55, eor, zpx); - op(0x56, lsr, zpx); - op(0x58, cli, imp); - op(0x59, eor, aby); - op(0x5a, phy, imp); - op(0x5d, eor, abx); - op(0x5e, lsr, abx); - op(0x60, rts, imp); - op(0x61, adc, izx); - op(0x65, adc, zpg); - op(0x66, ror, zpg); - op(0x68, pla, imp); - op(0x69, adc, imm); - op(0x6a, ror, imp); - op(0x6c, jmp, iab); - op(0x6d, adc, abs); - op(0x6e, ror, abs); - op(0x70, bvs, rel); - op(0x71, adc, izy); - op(0x75, adc, zpx); - op(0x76, ror, zpx); - op(0x78, sei, imp); - op(0x79, adc, aby); - op(0x7a, ply, imp); - op(0x7d, adc, abx); - op(0x7e, ror, abx); - op(0x81, sta, izx); - op(0x84, sty, zpg); - op(0x85, sta, zpg); - op(0x86, stx, zpg); - op(0x88, dey, imp); - op(0x8a, txa, imp); - op(0x8c, sty, abs); - op(0x8d, sta, abs); - op(0x8e, stx, abs); - op(0x90, bcc, rel); - op(0x91, sta, izy); - op(0x94, sty, zpx); - op(0x95, sta, zpx); - op(0x96, stx, zpy); - op(0x98, tya, imp); - op(0x99, sta, aby); - op(0x9a, txs, imp); - op(0x9d, sta, abx); - op(0xa0, ldy, imm); - op(0xa1, lda, izx); - op(0xa2, ldx, imm); - op(0xa4, ldy, zpg); - op(0xa5, lda, zpg); - op(0xa6, ldx, zpg); - op(0xa8, tay, imp); - op(0xa9, lda, imm); - op(0xaa, tax, imp); - op(0xac, ldy, abs); - op(0xad, lda, abs); - op(0xae, ldx, abs); - op(0xb0, bcs, rel); - op(0xb1, lda, izy); - op(0xb4, ldy, zpx); - op(0xb5, lda, zpx); - op(0xb6, ldx, zpy); - op(0xb8, clv, imp); - op(0xb9, lda, aby); - op(0xba, tsx, imp); - op(0xbc, ldy, abx); - op(0xbd, lda, abx); - op(0xbe, ldx, aby); - op(0xc0, cpy, imm); - op(0xc1, cmp, izx); - op(0xc4, cpy, zpg); - op(0xc5, cmp, zpg); - op(0xc6, dec, zpg); - op(0xc8, iny, imp); - op(0xc9, cmp, imm); - op(0xca, dex, imp); - op(0xcc, cpy, abs); - op(0xcd, cmp, abs); - op(0xce, dec, abs); - op(0xd0, bne, rel); - op(0xd1, cmp, izy); - op(0xd5, cmp, zpx); - op(0xd6, dec, zpx); - op(0xd8, cld, imp); - op(0xd9, cmp, aby); - op(0xda, phx, imp); - op(0xdd, cmp, abx); - op(0xde, dec, abx); - op(0xe0, cpx, imm); - op(0xe1, sbc, izx); - op(0xe4, cpx, zpg); - op(0xe5, sbc, zpg); - op(0xe6, inc, zpg); - op(0xe8, inx, imp); - op(0xe9, sbc, imm); - op(0xea, nop, imp); - op(0xec, cpx, abs); - op(0xed, sbc, abs); - op(0xee, inc, abs); - op(0xf0, beq, rel); - op(0xf1, sbc, izy); - op(0xf5, sbc, zpx); - op(0xf6, inc, zpx); - op(0xf8, sed, imp); - op(0xf9, sbc, aby); - op(0xfa, plx, imp); - op(0xfd, sbc, abx); - op(0xfe, inc, abx); - - default: output.append("$", hex(opcode, 2L)); break; - } - - #undef op - - output.append(" "); - output.resize(20); - - output.append( - "A:", hex(regs.a, 2L), " X:", hex(regs.x, 2L), " Y:", hex(regs.y, 2L), " S:", hex(regs.s, 2L), " ", - regs.p.n ? "N" : "n", regs.p.v ? "V" : "v", regs.p.d ? "D" : "d", - regs.p.i ? "I" : "i", regs.p.z ? "Z" : "z", regs.p.c ? "C" : "c" - ); - - return output; -} diff --git a/higan/processor/r6502/instructions.cpp b/higan/processor/r6502/instructions.cpp deleted file mode 100644 index 7c873526..00000000 --- a/higan/processor/r6502/instructions.cpp +++ /dev/null @@ -1,332 +0,0 @@ -auto R6502::op_branch(bool condition) { - if(!condition) { -L rd = readPC(); - } else { - rd = readPC(); - aa = regs.pc + (int8)rd; - ioPage(regs.pc, aa); -L io(); - regs.pc = aa; - } -} - -auto R6502::op_clear_flag(uint bit) { -L io(); - regs.p &= ~(1 << bit); -} - -auto R6502::op_decrement(uint8& r) { -L io(); - r--; - regs.p.n = (r & 0x80); - regs.p.z = (r == 0); -} - -auto R6502::op_increment(uint8& r) { -L io(); - r++; - regs.p.n = (r & 0x80); - regs.p.z = (r == 0); -} - -auto R6502::op_pull(uint8& r) { - io(); - io(); -L r = readSP(); - regs.p.n = (r & 0x80); - regs.p.z = (r == 0); -} - -auto R6502::op_push(uint8& r) { - io(); -L writeSP(r); -} - -auto R6502::op_read_absolute(fp op) { - abs.l = readPC(); - abs.h = readPC(); -L rd = read(abs.w); - call(op); -} - -auto R6502::op_read_absolute_x(fp op) { - abs.l = readPC(); - abs.h = readPC(); - ioPage(abs.w, abs.w + regs.x); -L rd = read(abs.w + regs.x); - call(op); -} - -auto R6502::op_read_absolute_y(fp op) { - abs.l = readPC(); - abs.h = readPC(); - ioPage(abs.w, abs.w + regs.y); -L rd = read(abs.w + regs.y); - call(op); -} - -auto R6502::op_read_immediate(fp op) { -L rd = readPC(); - call(op); -} - -auto R6502::op_read_indirect_zero_page_x(fp op) { - zp = readPC(); - readZP(zp); - abs.l = readZP(zp++ + regs.x); - abs.h = readZP(zp++ + regs.x); -L rd = read(abs.w); - call(op); -} - -auto R6502::op_read_indirect_zero_page_y(fp op) { - rd = readPC(); - abs.l = readZP(rd++); - abs.h = readZP(rd++); - ioPage(abs.w, abs.w + regs.y); -L rd = read(abs.w + regs.y); - call(op); -} - -auto R6502::op_read_zero_page(fp op) { - zp = readPC(); -L rd = readZP(zp); - call(op); -} - -auto R6502::op_read_zero_page_x(fp op) { - zp = readPC(); - readZP(zp); -L rd = readZP(zp + regs.x); - call(op); -} - -auto R6502::op_read_zero_page_y(fp op) { - zp = readPC(); - readZP(zp); -L rd = readZP(zp + regs.y); - call(op); -} - -auto R6502::op_rmw_absolute(fp op) { - abs.l = readPC(); - abs.h = readPC(); - rd = read(abs.w); - write(abs.w, rd); - call(op); -L write(abs.w, rd); -} - -auto R6502::op_rmw_absolute_x(fp op) { - abs.l = readPC(); - abs.h = readPC(); - ioPageAlways(abs.w, abs.w + regs.x); - rd = read(abs.w + regs.x); - write(abs.w + regs.x, rd); - call(op); -L write(abs.w + regs.x, rd); -} - -auto R6502::op_rmw_zero_page(fp op) { - zp = readPC(); - rd = readZP(zp); - writeZP(zp, rd); - call(op); -L writeZP(zp, rd); -} - -auto R6502::op_rmw_zero_page_x(fp op) { - zp = readPC(); - readZP(zp); - rd = readZP(zp + regs.x); - writeZP(zp + regs.x, rd); - call(op); -L writeZP(zp + regs.x, rd); -} - -auto R6502::op_set_flag(uint bit) { -L io(); - regs.p |= 1 << bit; -} - -auto R6502::op_shift(fp op) { -L io(); - call(op); -} - -auto R6502::op_store_absolute(uint8& r) { - abs.l = readPC(); - abs.h = readPC(); -L write(abs.w, r); -} - -auto R6502::op_store_absolute_x(uint8& r) { - abs.l = readPC(); - abs.h = readPC(); - ioPageAlways(abs.w, abs.w + regs.x); -L write(abs.w + regs.x, r); -} - -auto R6502::op_store_absolute_y(uint8& r) { - abs.l = readPC(); - abs.h = readPC(); - ioPageAlways(abs.w, abs.w + regs.y); -L write(abs.w + regs.y, r); -} - -auto R6502::op_store_indirect_zero_page_x(uint8& r) { - zp = readPC(); - readZP(zp); - abs.l = readZP(zp++ + regs.x); - abs.h = readZP(zp++ + regs.x); -L write(abs.w, r); -} - -auto R6502::op_store_indirect_zero_page_y(uint8& r) { - rd = readPC(); - abs.l = readZP(rd++); - abs.h = readZP(rd++); - ioPageAlways(abs.w, abs.w + regs.y); -L write(abs.w + regs.y, r); -} - -auto R6502::op_store_zero_page(uint8& r) { - zp = readPC(); -L writeZP(zp, r); -} - -auto R6502::op_store_zero_page_x(uint8& r) { - zp = readPC(); - readZP(zp); -L writeZP(zp + regs.x, r); -} - -auto R6502::op_store_zero_page_y(uint8& r) { - zp = readPC(); - readZP(zp); -L writeZP(zp + regs.y, r); -} - -auto R6502::op_transfer(uint8& s, uint8& d, bool flag) { -L io(); - d = s; - if(!flag) return; - regs.p.n = (d & 0x80); - regs.p.z = (d == 0); -} - -// - -auto R6502::op_brk() { - readPC(); - writeSP(regs.pc >> 8); - writeSP(regs.pc >> 0); - writeSP(regs.p | 0x30); - abs.l = read(0xfffe); - regs.p.i = 1; - regs.p.d = 0; -L abs.h = read(0xffff); - regs.pc = abs.w; -} - -auto R6502::op_jmp_absolute() { - abs.l = readPC(); -L abs.h = readPC(); - regs.pc = abs.w; -} - -auto R6502::op_jmp_indirect_absolute() { - abs.l = readPC(); - abs.h = readPC(); - iabs.l = read(abs.w); abs.l++; -L iabs.h = read(abs.w); abs.l++; - regs.pc = iabs.w; -} - -auto R6502::op_jsr_absolute() { - abs.l = readPC(); - abs.h = readPC(); - io(); - regs.pc--; - writeSP(regs.pc >> 8); -L writeSP(regs.pc >> 0); - regs.pc = abs.w; -} - -auto R6502::op_nop() { -L io(); -} - -auto R6502::op_php() { - io(); -L writeSP(regs.p | 0x30); -} - -auto R6502::op_plp() { - io(); - io(); -L regs.p = readSP(); -} - -auto R6502::op_rti() { - io(); - io(); - regs.p = readSP(); - abs.l = readSP(); -L abs.h = readSP(); - regs.pc = abs.w; -} - -auto R6502::op_rts() { - io(); - io(); - abs.l = readSP(); - abs.h = readSP(); -L io(); - regs.pc = ++abs.w; -} - -//illegal opcodes -//=============== - -auto R6502::op_arr_immediate() { -L rd = readPC(); - regs.a &= rd; - regs.a = (regs.p.c << 7) | (regs.a >> 1); - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); - regs.p.c = (regs.a & 0x40); - regs.p.v = regs.p.c ^ ((regs.a >> 5) & 1); -} - -auto R6502::op_nop_absolute() { - abs.l = readPC(); - abs.h = readPC(); -L io(); -} - -auto R6502::op_nop_absolute_x() { - abs.l = readPC(); - abs.h = readPC(); - ioPage(abs.w, abs.w + regs.x); -L io(); -} - -auto R6502::op_nop_immediate() { -L io(); -} - -auto R6502::op_nop_implied() { -L io(); -} - -auto R6502::op_nop_zero_page() { - zp = readPC(); -L readZP(zp); -} - -auto R6502::op_nop_zero_page_x() { - zp = readPC(); - readZP(zp); -L readZP(zp + regs.x); -} diff --git a/higan/processor/r6502/memory.cpp b/higan/processor/r6502/memory.cpp deleted file mode 100644 index 78141241..00000000 --- a/higan/processor/r6502/memory.cpp +++ /dev/null @@ -1,36 +0,0 @@ -auto R6502::io() -> uint8 { - return read(regs.pc); -} - -auto R6502::readPC() -> uint8 { - return read(regs.pc++); -} - -auto R6502::readSP() -> uint8 { - return read(0x0100 | ++regs.s); -} - -auto R6502::readZP(uint8 addr) -> uint8 { - return read(addr); -} - -// - -auto R6502::writeSP(uint8 data) -> void { - write(0x0100 | regs.s--, data); -} - -auto R6502::writeZP(uint8 addr, uint8 data) -> void { - write(addr, data); -} - -// - -auto R6502::ioPage(uint16 x, uint16 y) -> void { - if(x >> 8 == y >> 8) return; - read((x & 0xff00) | (y & 0x00ff)); -} - -auto R6502::ioPageAlways(uint16 x, uint16 y) -> void { - read((x & 0xff00) | (y & 0x00ff)); -} diff --git a/higan/processor/r6502/r6502.cpp b/higan/processor/r6502/r6502.cpp deleted file mode 100644 index 76144b9b..00000000 --- a/higan/processor/r6502/r6502.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include "r6502.hpp" - -namespace Processor { - -#define L lastCycle(); -#define call(op) (this->*op)() - -#include "memory.cpp" -#include "algorithms.cpp" -#include "instructions.cpp" -#include "switch.cpp" -#include "disassembler.cpp" -#include "serialization.cpp" - -auto R6502::mdr() const -> uint8 { - return regs.mdr; -} - -auto R6502::power() -> void { - regs.a = 0x00; - regs.x = 0x00; - regs.y = 0x00; - regs.s = 0xff; - regs.p = 0x04; - regs.mdr = 0x00; -} - -auto R6502::interrupt() -> void { - io(); - io(); - writeSP(regs.pc >> 8); - writeSP(regs.pc >> 0); - writeSP(regs.p | 0x20); - uint16 vector = 0xfffe; //IRQ - nmi(vector); - abs.l = read(vector++); - regs.p.i = 1; - regs.p.d = 0; -L abs.h = read(vector++); - regs.pc = abs.w; -} - -#undef L -#undef call - -} diff --git a/higan/processor/r6502/r6502.hpp b/higan/processor/r6502/r6502.hpp deleted file mode 100644 index 46b1516c..00000000 --- a/higan/processor/r6502/r6502.hpp +++ /dev/null @@ -1,115 +0,0 @@ -//Ricoh 6502 -//* Ricoh 2A03 -//* Ricoh 2A07 - -#pragma once - -namespace Processor { - -struct R6502 { - virtual auto read(uint16 addr) -> uint8 = 0; - virtual auto write(uint16 addr, uint8 data) -> void = 0; - virtual auto lastCycle() -> void = 0; - virtual auto nmi(uint16& vector) -> void = 0; - virtual auto readDebugger(uint16 addr) -> uint8 { return 0u; } - - auto mdr() const -> uint8; - auto power() -> void; - auto interrupt() -> void; - auto instruction() -> void; - - auto serialize(serializer&) -> void; - - //memory.cpp - auto io() -> uint8; - auto readPC() -> uint8; - auto readSP() -> uint8; - auto readZP(uint8 addr) -> uint8; - - auto writeSP(uint8 data) -> void; - auto writeZP(uint8 addr, uint8 data) -> void; - - auto ioPage(uint16 x, uint16 y) -> void; - auto ioPageAlways(uint16 x, uint16 y) -> void; - - //instructions.cpp - using fp = auto (R6502::*)() -> void; - auto fp_asl(); - auto fp_adc(); - auto fp_and(); - auto fp_bit(); - auto fp_cmp(); - auto fp_cpx(); - auto fp_cpy(); - auto fp_dec(); - auto fp_eor(); - auto fp_inc(); - auto fp_lda(); - auto fp_ldx(); - auto fp_ldy(); - auto fp_lsr(); - auto fp_ora(); - auto fp_rla(); - auto fp_rol(); - auto fp_ror(); - auto fp_rra(); - auto fp_sbc(); - auto fp_sla(); - auto fp_sra(); - - auto op_branch(bool condition); - auto op_clear_flag(uint bit); - auto op_decrement(uint8& r); - auto op_increment(uint8& r); - auto op_pull(uint8& r); - auto op_push(uint8& r); - auto op_read_absolute(fp); - auto op_read_absolute_x(fp); - auto op_read_absolute_y(fp); - auto op_read_immediate(fp); - auto op_read_indirect_zero_page_x(fp); - auto op_read_indirect_zero_page_y(fp); - auto op_read_zero_page(fp); - auto op_read_zero_page_x(fp); - auto op_read_zero_page_y(fp); - auto op_rmw_absolute(fp); - auto op_rmw_absolute_x(fp); - auto op_rmw_zero_page(fp); - auto op_rmw_zero_page_x(fp); - auto op_set_flag(uint bit); - auto op_shift(fp); - auto op_store_absolute(uint8& r); - auto op_store_absolute_x(uint8& r); - auto op_store_absolute_y(uint8& r); - auto op_store_indirect_zero_page_x(uint8& r); - auto op_store_indirect_zero_page_y(uint8& r); - auto op_store_zero_page(uint8& r); - auto op_store_zero_page_x(uint8& r); - auto op_store_zero_page_y(uint8& r); - auto op_transfer(uint8& s, uint8& d, bool flag); - - auto op_brk(); - auto op_jmp_absolute(); - auto op_jmp_indirect_absolute(); - auto op_jsr_absolute(); - auto op_nop(); - auto op_php(); - auto op_plp(); - auto op_rti(); - auto op_rts(); - - auto op_arr_immediate(); - auto op_nop_absolute(); - auto op_nop_absolute_x(); - auto op_nop_immediate(); - auto op_nop_implied(); - auto op_nop_zero_page(); - auto op_nop_zero_page_x(); - - //disassembler.cpp - auto disassemble() -> string; - - #include "registers.hpp" -}; - -} diff --git a/higan/processor/r6502/registers.hpp b/higan/processor/r6502/registers.hpp deleted file mode 100644 index 9389faad..00000000 --- a/higan/processor/r6502/registers.hpp +++ /dev/null @@ -1,36 +0,0 @@ -struct Flags { - union { - uint8_t data = 0; - BooleanBitField n; - BooleanBitField v; - BooleanBitField d; - BooleanBitField i; - BooleanBitField z; - BooleanBitField c; - }; - - inline operator uint() { return data; } - inline auto& operator =(uint value) { return data = value, *this; } - inline auto& operator&=(uint value) { return data &= value, *this; } - inline auto& operator|=(uint value) { return data |= value, *this; } - inline auto& operator^=(uint value) { return data ^= value, *this; } -}; - -struct Registers { - uint8 mdr; - uint16 pc; - uint8 a, x, y, s; - Flags p; -} regs; - -struct Register16 { - union { - uint16_t w; - NaturalBitField l; - NaturalBitField h; - }; -} abs, iabs; - -uint8 rd; -uint8 zp; -uint16 aa; diff --git a/higan/processor/r6502/serialization.cpp b/higan/processor/r6502/serialization.cpp deleted file mode 100644 index ab5452c6..00000000 --- a/higan/processor/r6502/serialization.cpp +++ /dev/null @@ -1,15 +0,0 @@ -auto R6502::serialize(serializer& s) -> void { - s.integer(regs.mdr); - s.integer(regs.pc); - s.integer(regs.a); - s.integer(regs.x); - s.integer(regs.y); - s.integer(regs.s); - s.integer(regs.p.data); - - s.integer(abs.w); - s.integer(iabs.w); - s.integer(rd); - s.integer(zp); - s.integer(aa); -} diff --git a/higan/processor/r6502/switch.cpp b/higan/processor/r6502/switch.cpp deleted file mode 100644 index 1dd9e74d..00000000 --- a/higan/processor/r6502/switch.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#define I //prefix highlights illegal instructions -#define op(id, name, ...) case id: return op_##name(__VA_ARGS__); -#define fp(name) &R6502::fp_##name - -auto R6502::instruction() -> void { - switch(readPC()) { - op(0x00, brk) - op(0x01, read_indirect_zero_page_x, fp(ora)) -I op(0x04, nop_zero_page) - op(0x05, read_zero_page, fp(ora)) - op(0x06, rmw_zero_page, fp(asl)) - op(0x08, php) - op(0x09, read_immediate, fp(ora)) - op(0x0a, shift, fp(sla)) -I op(0x0c, nop_absolute) - op(0x0d, read_absolute, fp(ora)) - op(0x0e, rmw_absolute, fp(asl)) - op(0x10, branch, regs.p.n == 0) - op(0x11, read_indirect_zero_page_y, fp(ora)) -I op(0x14, nop_zero_page_x) - op(0x15, read_zero_page_x, fp(ora)) - op(0x16, rmw_zero_page_x, fp(asl)) - op(0x18, clear_flag, regs.p.c.bit) - op(0x19, read_absolute_y, fp(ora)) -I op(0x1a, nop_implied) -I op(0x1c, nop_absolute_x) - op(0x1d, read_absolute_x, fp(ora)) - op(0x1e, rmw_absolute_x, fp(asl)) - op(0x20, jsr_absolute) - op(0x21, read_indirect_zero_page_x, fp(and)) - op(0x24, read_zero_page, fp(bit)) - op(0x25, read_zero_page, fp(and)) - op(0x26, rmw_zero_page, fp(rol)) - op(0x28, plp) - op(0x29, read_immediate, fp(and)) - op(0x2a, shift, fp(rla)) - op(0x2c, read_absolute, fp(bit)) - op(0x2d, read_absolute, fp(and)) - op(0x2e, rmw_absolute, fp(rol)) - op(0x30, branch, regs.p.n == 1) - op(0x31, read_indirect_zero_page_y, fp(and)) -I op(0x34, nop_zero_page_x) - op(0x35, read_zero_page_x, fp(and)) - op(0x36, rmw_zero_page_x, fp(rol)) - op(0x38, set_flag, regs.p.c.bit) - op(0x39, read_absolute_y, fp(and)) -I op(0x3a, nop_implied) -I op(0x3c, nop_absolute_x) - op(0x3d, read_absolute_x, fp(and)) - op(0x3e, rmw_absolute_x, fp(rol)) - op(0x40, rti) - op(0x41, read_indirect_zero_page_x, fp(eor)) -I op(0x44, nop_zero_page) - op(0x45, read_zero_page, fp(eor)) - op(0x46, rmw_zero_page, fp(lsr)) - op(0x48, push, regs.a) - op(0x49, read_immediate, fp(eor)) - op(0x4a, shift, fp(sra)) - op(0x4c, jmp_absolute) - op(0x4d, read_absolute, fp(eor)) - op(0x4e, rmw_absolute, fp(lsr)) - op(0x50, branch, regs.p.v == 0) - op(0x51, read_indirect_zero_page_y, fp(eor)) -I op(0x54, nop_zero_page_x) - op(0x55, read_zero_page_x, fp(eor)) - op(0x56, rmw_zero_page_x, fp(lsr)) - op(0x58, clear_flag, regs.p.i.bit) - op(0x59, read_absolute_y, fp(eor)) -I op(0x5a, nop_implied) -I op(0x5c, nop_absolute_x) - op(0x5d, read_absolute_x, fp(eor)) - op(0x5e, rmw_absolute_x, fp(lsr)) - op(0x60, rts) - op(0x61, read_indirect_zero_page_x, fp(adc)) -I op(0x64, nop_zero_page) - op(0x65, read_zero_page, fp(adc)) - op(0x66, rmw_zero_page, fp(ror)) - op(0x68, pull, regs.a) - op(0x69, read_immediate, fp(adc)) - op(0x6a, shift, fp(rra)) -I op(0x6b, arr_immediate) - op(0x6c, jmp_indirect_absolute) - op(0x6d, read_absolute, fp(adc)) - op(0x6e, rmw_absolute, fp(ror)) - op(0x70, branch, regs.p.v == 1) - op(0x71, read_indirect_zero_page_y, fp(adc)) -I op(0x74, nop_zero_page_x) - op(0x75, read_zero_page_x, fp(adc)) - op(0x76, rmw_zero_page_x, fp(ror)) - op(0x78, set_flag, regs.p.i.bit) - op(0x79, read_absolute_y, fp(adc)) -I op(0x7a, nop_implied) -I op(0x7c, nop_absolute_x) - op(0x7d, read_absolute_x, fp(adc)) - op(0x7e, rmw_absolute_x, fp(ror)) -I case 0x80: return op_nop_absolute(); - case 0x81: return op_store_indirect_zero_page_x(regs.a); -I case 0x82: return op_nop_immediate(); - case 0x84: return op_store_zero_page(regs.y); - case 0x85: return op_store_zero_page(regs.a); - case 0x86: return op_store_zero_page(regs.x); - case 0x88: return op_decrement(regs.y); -I case 0x89: return op_nop_immediate(); - case 0x8a: return op_transfer(regs.x, regs.a, 1); - case 0x8c: return op_store_absolute(regs.y); - case 0x8d: return op_store_absolute(regs.a); - case 0x8e: return op_store_absolute(regs.x); - case 0x90: return op_branch(regs.p.c == 0); - case 0x91: return op_store_indirect_zero_page_y(regs.a); - case 0x94: return op_store_zero_page_x(regs.y); - case 0x95: return op_store_zero_page_x(regs.a); - case 0x96: return op_store_zero_page_y(regs.x); - case 0x98: return op_transfer(regs.y, regs.a, 1); - case 0x99: return op_store_absolute_y(regs.a); - case 0x9a: return op_transfer(regs.x, regs.s, 0); - case 0x9d: return op_store_absolute_x(regs.a); - case 0xa0: return op_read_immediate(fp(ldy)); - case 0xa1: return op_read_indirect_zero_page_x(fp(lda)); - case 0xa2: return op_read_immediate(fp(ldx)); - case 0xa4: return op_read_zero_page(fp(ldy)); - case 0xa5: return op_read_zero_page(fp(lda)); - case 0xa6: return op_read_zero_page(fp(ldx)); - case 0xa8: return op_transfer(regs.a, regs.y, 1); - case 0xa9: return op_read_immediate(fp(lda)); - case 0xaa: return op_transfer(regs.a, regs.x, 1); - case 0xac: return op_read_absolute(fp(ldy)); - case 0xad: return op_read_absolute(fp(lda)); - case 0xae: return op_read_absolute(fp(ldx)); - case 0xb0: return op_branch(regs.p.c == 1); - case 0xb1: return op_read_indirect_zero_page_y(fp(lda)); - case 0xb4: return op_read_zero_page_x(fp(ldy)); - case 0xb5: return op_read_zero_page_x(fp(lda)); - case 0xb6: return op_read_zero_page_y(fp(ldx)); - case 0xb8: return op_clear_flag(regs.p.v.bit); - case 0xb9: return op_read_absolute_y(fp(lda)); - case 0xba: return op_transfer(regs.s, regs.x, 1); - case 0xbc: return op_read_absolute_x(fp(ldy)); - case 0xbd: return op_read_absolute_x(fp(lda)); - case 0xbe: return op_read_absolute_y(fp(ldx)); - case 0xc0: return op_read_immediate(fp(cpy)); - case 0xc1: return op_read_indirect_zero_page_x(fp(cmp)); -I case 0xc2: return op_nop_immediate(); - case 0xc4: return op_read_zero_page(fp(cpy)); - case 0xc5: return op_read_zero_page(fp(cmp)); - case 0xc6: return op_rmw_zero_page(fp(dec)); - case 0xc8: return op_increment(regs.y); - case 0xc9: return op_read_immediate(fp(cmp)); - case 0xca: return op_decrement(regs.x); - case 0xcc: return op_read_absolute(fp(cpy)); - case 0xcd: return op_read_absolute(fp(cmp)); - case 0xce: return op_rmw_absolute(fp(dec)); - case 0xd0: return op_branch(regs.p.z == 0); - case 0xd1: return op_read_indirect_zero_page_y(fp(cmp)); -I case 0xd4: return op_nop_zero_page_x(); - case 0xd5: return op_read_zero_page_x(fp(cmp)); - case 0xd6: return op_rmw_zero_page_x(fp(dec)); - case 0xd8: return op_clear_flag(regs.p.d.bit); - case 0xd9: return op_read_absolute_y(fp(cmp)); -I case 0xda: return op_nop_implied(); -I case 0xdc: return op_nop_absolute_x(); - case 0xdd: return op_read_absolute_x(fp(cmp)); - case 0xde: return op_rmw_absolute_x(fp(dec)); - case 0xe0: return op_read_immediate(fp(cpx)); - case 0xe1: return op_read_indirect_zero_page_x(fp(sbc)); -I case 0xe2: return op_nop_immediate(); - case 0xe4: return op_read_zero_page(fp(cpx)); - case 0xe5: return op_read_zero_page(fp(sbc)); - case 0xe6: return op_rmw_zero_page(fp(inc)); - case 0xe8: return op_increment(regs.x); - case 0xe9: return op_read_immediate(fp(sbc)); - case 0xea: return op_nop(); -I case 0xeb: return op_read_immediate(fp(sbc)); - case 0xec: return op_read_absolute(fp(cpx)); - case 0xed: return op_read_absolute(fp(sbc)); - case 0xee: return op_rmw_absolute(fp(inc)); - case 0xf0: return op_branch(regs.p.z == 1); - case 0xf1: return op_read_indirect_zero_page_y(fp(sbc)); -I case 0xf4: return op_nop_zero_page_x(); - case 0xf5: return op_read_zero_page_x(fp(sbc)); - case 0xf6: return op_rmw_zero_page_x(fp(inc)); - case 0xf8: return op_set_flag(regs.p.d.bit); - case 0xf9: return op_read_absolute_y(fp(sbc)); -I case 0xfa: return op_nop_implied(); -I case 0xfc: return op_nop_absolute_x(); - case 0xfd: return op_read_absolute_x(fp(sbc)); - case 0xfe: return op_rmw_absolute_x(fp(inc)); - } - - //unimplemented opcode - return op_nop(); -} - -#undef I -#undef op -#undef fp diff --git a/higan/processor/r65816/algorithms.cpp b/higan/processor/wdc65816/algorithms.cpp similarity index 100% rename from higan/processor/r65816/algorithms.cpp rename to higan/processor/wdc65816/algorithms.cpp diff --git a/higan/processor/r65816/disassembler.cpp b/higan/processor/wdc65816/disassembler.cpp similarity index 100% rename from higan/processor/r65816/disassembler.cpp rename to higan/processor/wdc65816/disassembler.cpp diff --git a/higan/processor/r65816/disassembler.hpp b/higan/processor/wdc65816/disassembler.hpp similarity index 100% rename from higan/processor/r65816/disassembler.hpp rename to higan/processor/wdc65816/disassembler.hpp diff --git a/higan/processor/r65816/instructions-misc.cpp b/higan/processor/wdc65816/instructions-misc.cpp similarity index 100% rename from higan/processor/r65816/instructions-misc.cpp rename to higan/processor/wdc65816/instructions-misc.cpp diff --git a/higan/processor/r65816/instructions-pc.cpp b/higan/processor/wdc65816/instructions-pc.cpp similarity index 100% rename from higan/processor/r65816/instructions-pc.cpp rename to higan/processor/wdc65816/instructions-pc.cpp diff --git a/higan/processor/r65816/instructions-read.cpp b/higan/processor/wdc65816/instructions-read.cpp similarity index 100% rename from higan/processor/r65816/instructions-read.cpp rename to higan/processor/wdc65816/instructions-read.cpp diff --git a/higan/processor/r65816/instructions-rmw.cpp b/higan/processor/wdc65816/instructions-rmw.cpp similarity index 100% rename from higan/processor/r65816/instructions-rmw.cpp rename to higan/processor/wdc65816/instructions-rmw.cpp diff --git a/higan/processor/r65816/instructions-write.cpp b/higan/processor/wdc65816/instructions-write.cpp similarity index 100% rename from higan/processor/r65816/instructions-write.cpp rename to higan/processor/wdc65816/instructions-write.cpp diff --git a/higan/processor/r65816/memory.hpp b/higan/processor/wdc65816/memory.hpp similarity index 100% rename from higan/processor/r65816/memory.hpp rename to higan/processor/wdc65816/memory.hpp diff --git a/higan/processor/r65816/registers.hpp b/higan/processor/wdc65816/registers.hpp similarity index 100% rename from higan/processor/r65816/registers.hpp rename to higan/processor/wdc65816/registers.hpp diff --git a/higan/processor/r65816/serialization.cpp b/higan/processor/wdc65816/serialization.cpp similarity index 100% rename from higan/processor/r65816/serialization.cpp rename to higan/processor/wdc65816/serialization.cpp diff --git a/higan/processor/r65816/switch.cpp b/higan/processor/wdc65816/switch.cpp similarity index 100% rename from higan/processor/r65816/switch.cpp rename to higan/processor/wdc65816/switch.cpp diff --git a/higan/processor/r65816/r65816.cpp b/higan/processor/wdc65816/wdc65816.cpp similarity index 98% rename from higan/processor/r65816/r65816.cpp rename to higan/processor/wdc65816/wdc65816.cpp index e261a1dd..8a7b6452 100644 --- a/higan/processor/r65816/r65816.cpp +++ b/higan/processor/wdc65816/wdc65816.cpp @@ -1,5 +1,5 @@ #include -#include "r65816.hpp" +#include "wdc65816.hpp" namespace Processor { diff --git a/higan/processor/r65816/r65816.hpp b/higan/processor/wdc65816/wdc65816.hpp similarity index 100% rename from higan/processor/r65816/r65816.hpp rename to higan/processor/wdc65816/wdc65816.hpp diff --git a/higan/sfc/GNUmakefile b/higan/sfc/GNUmakefile index 045a9cf6..8d25ddff 100644 --- a/higan/sfc/GNUmakefile +++ b/higan/sfc/GNUmakefile @@ -1,4 +1,4 @@ -processors += r65816 spc700 arm gsu hg51b upd96050 +processors += wdc65816 spc700 arm gsu hg51b upd96050 objects += sfc-interface sfc-system sfc-controller objects += sfc-cartridge sfc-memory diff --git a/higan/sfc/sfc.hpp b/higan/sfc/sfc.hpp index a3641d0b..86dd61b2 100644 --- a/higan/sfc/sfc.hpp +++ b/higan/sfc/sfc.hpp @@ -11,9 +11,9 @@ #include #include #include -#include #include #include +#include #if defined(SFC_SUPERGAMEBOY) #include