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