mirror of https://github.com/bsnes-emu/bsnes.git
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.
This commit is contained in:
parent
8af3e4a6e2
commit
cea64b9991
|
@ -12,13 +12,13 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
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 Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
||||||
//incremented only when serialization format changes
|
//incremented only when serialization format changes
|
||||||
static const string SerializerVersion = "102.20";
|
static const string SerializerVersion = "102.23";
|
||||||
|
|
||||||
namespace Constants {
|
namespace Constants {
|
||||||
namespace Colorburst {
|
namespace Colorburst {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
processors += r6502
|
processors += mos6502
|
||||||
|
|
||||||
objects += fc-interface fc-system fc-controller
|
objects += fc-interface fc-system fc-controller
|
||||||
objects += fc-memory fc-cartridge fc-cpu fc-apu fc-ppu
|
objects += fc-memory fc-cartridge fc-cpu fc-apu fc-ppu
|
||||||
|
|
|
@ -12,7 +12,12 @@ auto CPU::Enter() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::main() -> 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();
|
instruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +30,8 @@ auto CPU::step(uint clocks) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::power() -> void {
|
auto CPU::power() -> void {
|
||||||
R6502::power();
|
MOS6502::BCD = 0;
|
||||||
|
MOS6502::power();
|
||||||
create(CPU::Enter, system.colorburst() * 6.0);
|
create(CPU::Enter, system.colorburst() * 6.0);
|
||||||
|
|
||||||
for(auto addr : range(0x0800)) ram[addr] = 0xff;
|
for(auto addr : range(0x0800)) ram[addr] = 0xff;
|
||||||
|
@ -34,8 +40,8 @@ auto CPU::power() -> void {
|
||||||
ram[0x000a] = 0xdf;
|
ram[0x000a] = 0xdf;
|
||||||
ram[0x000f] = 0xbf;
|
ram[0x000f] = 0xbf;
|
||||||
|
|
||||||
regs.pc = bus.read(0xfffc) << 0;
|
r.pc.byte(0) = bus.read(0xfffc);
|
||||||
regs.pc |= bus.read(0xfffd) << 8;
|
r.pc.byte(1) = bus.read(0xfffd);
|
||||||
|
|
||||||
memory::fill(&io, sizeof(IO));
|
memory::fill(&io, sizeof(IO));
|
||||||
io.rdyLine = 1;
|
io.rdyLine = 1;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
struct CPU : Processor::R6502, Thread {
|
struct CPU : Processor::MOS6502, Thread {
|
||||||
static auto Enter() -> void;
|
static auto Enter() -> void;
|
||||||
auto main() -> void;
|
auto main() -> void;
|
||||||
auto step(uint clocks) -> void;
|
auto step(uint clocks) -> void;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
auto CPU::serialize(serializer& s) -> void {
|
auto CPU::serialize(serializer& s) -> void {
|
||||||
R6502::serialize(s);
|
MOS6502::serialize(s);
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
|
|
||||||
s.array(ram);
|
s.array(ram);
|
||||||
|
|
|
@ -6,22 +6,22 @@ auto CPU::read(uint16 addr) -> uint8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
while(io.rdyLine == 0) {
|
while(io.rdyLine == 0) {
|
||||||
regs.mdr = bus.read(io.rdyAddrValid ? io.rdyAddrValue : addr);
|
r.mdr = bus.read(io.rdyAddrValid ? io.rdyAddrValue : addr);
|
||||||
step(12);
|
step(12);
|
||||||
}
|
}
|
||||||
|
|
||||||
regs.mdr = bus.read(addr);
|
r.mdr = bus.read(addr);
|
||||||
step(12);
|
step(12);
|
||||||
return regs.mdr;
|
return r.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::write(uint16 addr, uint8 data) -> void {
|
auto CPU::write(uint16 addr, uint8 data) -> void {
|
||||||
bus.write(addr, regs.mdr = data);
|
bus.write(addr, r.mdr = data);
|
||||||
step(12);
|
step(12);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::lastCycle() -> void {
|
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 {
|
auto CPU::nmi(uint16& vector) -> void {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <emulator/scheduler.hpp>
|
#include <emulator/scheduler.hpp>
|
||||||
#include <emulator/cheat.hpp>
|
#include <emulator/cheat.hpp>
|
||||||
|
|
||||||
#include <processor/r6502/r6502.hpp>
|
#include <processor/mos6502/mos6502.hpp>
|
||||||
|
|
||||||
namespace Famicom {
|
namespace Famicom {
|
||||||
#define platform Emulator::platform
|
#define platform Emulator::platform
|
||||||
|
|
|
@ -6,11 +6,11 @@ objects += $(if $(findstring hg51b,$(processors)),processor-hg51b)
|
||||||
objects += $(if $(findstring huc6280,$(processors)),processor-huc6280)
|
objects += $(if $(findstring huc6280,$(processors)),processor-huc6280)
|
||||||
objects += $(if $(findstring lr35902,$(processors)),processor-lr35902)
|
objects += $(if $(findstring lr35902,$(processors)),processor-lr35902)
|
||||||
objects += $(if $(findstring m68k,$(processors)),processor-m68k)
|
objects += $(if $(findstring m68k,$(processors)),processor-m68k)
|
||||||
objects += $(if $(findstring r6502,$(processors)),processor-r6502)
|
objects += $(if $(findstring mos6502,$(processors)),processor-mos6502)
|
||||||
objects += $(if $(findstring r65816,$(processors)),processor-r65816)
|
|
||||||
objects += $(if $(findstring spc700,$(processors)),processor-spc700)
|
objects += $(if $(findstring spc700,$(processors)),processor-spc700)
|
||||||
objects += $(if $(findstring upd96050,$(processors)),processor-upd96050)
|
objects += $(if $(findstring upd96050,$(processors)),processor-upd96050)
|
||||||
objects += $(if $(findstring v30mz,$(processors)),processor-v30mz)
|
objects += $(if $(findstring v30mz,$(processors)),processor-v30mz)
|
||||||
|
objects += $(if $(findstring wdc65816,$(processors)),processor-wdc65816)
|
||||||
objects += $(if $(findstring z80,$(processors)),processor-z80)
|
objects += $(if $(findstring z80,$(processors)),processor-z80)
|
||||||
|
|
||||||
obj/processor-arm.o: processor/arm/arm.cpp $(call rwildcard,processor/arm)
|
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-huc6280.o: processor/huc6280/huc6280.cpp $(call rwildcard,processor/huc6280)
|
||||||
obj/processor-lr35902.o: processor/lr35902/lr35902.cpp $(call rwildcard,processor/lr35902)
|
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-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-r6502.o: processor/r6502/r6502.cpp $(call rwildcard,processor/r6502)
|
||||||
obj/processor-r65816.o: processor/r65816/r65816.cpp $(call rwildcard,processor/r65816)
|
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-spc700.o: processor/spc700/spc700.cpp $(call rwildcard,processor/spc700)
|
||||||
obj/processor-upd96050.o: processor/upd96050/upd96050.cpp $(call rwildcard,processor/upd96050)
|
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-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)
|
obj/processor-z80.o: processor/z80/z80.cpp $(call rwildcard,processor/z80)
|
||||||
|
|
|
@ -22,11 +22,13 @@ namespace Processor {
|
||||||
#define EA r.ea
|
#define EA r.ea
|
||||||
#define L lastCycle();
|
#define L lastCycle();
|
||||||
#define ALU (this->*alu)
|
#define ALU (this->*alu)
|
||||||
|
|
||||||
#include "memory.cpp"
|
#include "memory.cpp"
|
||||||
#include "instruction.cpp"
|
#include "instruction.cpp"
|
||||||
#include "instructions.cpp"
|
#include "instructions.cpp"
|
||||||
#include "disassembler.cpp"
|
#include "disassembler.cpp"
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
|
|
||||||
#undef A
|
#undef A
|
||||||
#undef X
|
#undef X
|
||||||
#undef Y
|
#undef Y
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct HuC6280 {
|
||||||
virtual auto store(uint2 addr, uint8 data) -> void = 0;
|
virtual auto store(uint2 addr, uint8 data) -> void = 0;
|
||||||
virtual auto lastCycle() -> void = 0;
|
virtual auto lastCycle() -> void = 0;
|
||||||
|
|
||||||
|
//huc6280.cpp
|
||||||
auto power() -> void;
|
auto power() -> void;
|
||||||
|
|
||||||
//memory.cpp
|
//memory.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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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++;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include <processor/processor.hpp>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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));
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
#include <processor/processor.hpp>
|
|
||||||
#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
|
|
||||||
|
|
||||||
}
|
|
|
@ -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"
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
struct Flags {
|
|
||||||
union {
|
|
||||||
uint8_t data = 0;
|
|
||||||
BooleanBitField<uint8_t, 7> n;
|
|
||||||
BooleanBitField<uint8_t, 6> v;
|
|
||||||
BooleanBitField<uint8_t, 3> d;
|
|
||||||
BooleanBitField<uint8_t, 2> i;
|
|
||||||
BooleanBitField<uint8_t, 1> z;
|
|
||||||
BooleanBitField<uint8_t, 0> 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<uint16_t, 0, 7> l;
|
|
||||||
NaturalBitField<uint16_t, 8, 15> h;
|
|
||||||
};
|
|
||||||
} abs, iabs;
|
|
||||||
|
|
||||||
uint8 rd;
|
|
||||||
uint8 zp;
|
|
||||||
uint16 aa;
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <processor/processor.hpp>
|
#include <processor/processor.hpp>
|
||||||
#include "r65816.hpp"
|
#include "wdc65816.hpp"
|
||||||
|
|
||||||
namespace Processor {
|
namespace Processor {
|
||||||
|
|
|
@ -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-interface sfc-system sfc-controller
|
||||||
objects += sfc-cartridge sfc-memory
|
objects += sfc-cartridge sfc-memory
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
#include <processor/arm/arm.hpp>
|
#include <processor/arm/arm.hpp>
|
||||||
#include <processor/gsu/gsu.hpp>
|
#include <processor/gsu/gsu.hpp>
|
||||||
#include <processor/hg51b/hg51b.hpp>
|
#include <processor/hg51b/hg51b.hpp>
|
||||||
#include <processor/r65816/r65816.hpp>
|
|
||||||
#include <processor/spc700/spc700.hpp>
|
#include <processor/spc700/spc700.hpp>
|
||||||
#include <processor/upd96050/upd96050.hpp>
|
#include <processor/upd96050/upd96050.hpp>
|
||||||
|
#include <processor/wdc65816/wdc65816.hpp>
|
||||||
|
|
||||||
#if defined(SFC_SUPERGAMEBOY)
|
#if defined(SFC_SUPERGAMEBOY)
|
||||||
#include <gb/gb.hpp>
|
#include <gb/gb.hpp>
|
||||||
|
|
Loading…
Reference in New Issue