mirror of https://github.com/bsnes-emu/bsnes.git
Update to v102r24 release.
byuu says Changelog: - FC: fixed three MOS6502 regressions [hex\_usr] - GBA: return fetched instruction instead of 0 for unmapped MMIO (passes all of endrift's I/O tests) - MD: fix VDP control port read Vblank bit to test screen height instead of hard-code 240 (fixes Phantasy Star IV) - MD: swap USP,SSP when executing an exception (allows Super Street Fighter II to run; but no sprites visible yet) - MD: grant 68K access to Z80 bus on reset (fixes vdpdoc demo ROM from freezing immediately) - SFC: reads from $00-3f,80-bf:4000-43ff no longer update MDR [p4plus2] - SFC: massive, eight-hour cleanup of WDC65816 CPU core ... still not complete The big change this time around is the SFC CPU core. I've renamed everything from R65816 to WDC65816, and then went through and tried to clean up the code as much as possible. This core is so much larger than the 6502 core that I chose cleaning up the code to rewriting it. First off, I really don't care for the BitRange style functionality. It was an interesting experiment, but its fatal flaw are that the types are just bizarre, which makes them hard to pass around generically to other functions as arguments. So I went back to the list of bools for flags, and union/struct blocks for the registers. Next, I renamed all of the functions to be more descriptive: eg `op_read_idpx_w` becomes `instructionIndexedIndirectRead16`. `op_adc_b` becomes `algorithmADC8`. And so forth. I eliminated about ten instructions because they were functionally identical sans the index, so I just added a uint index=0 parameter to said functions. I added a few new ones (adjust→INC,DEC; pflag→REP,SEP) where it seemed appropriate. I cleaned up the disaster of the instruction switch table into something a whole lot more elegant without all the weird argument decoding nonsense (still need M vs X variants to avoid having to have 4-5 separate switch tables, but all the F/I flags are gone now); and made some things saner, like the flag clear/set and branch conditions, now that I have normal types for flags and registers once again. I renamed all of the memory access functions to be more descriptive to what they're doing: eg writeSP→push, readPC→fetch, writeDP→writeDirect, etc. Eliminated some of the special read/write modes that were only used in one single instruction. I started to clean up some of the actual instructions themselves, but haven't really accomplished much here. The big thing I want to do is get rid of the global state (aa, rd, iaddr, etc) and instead use local variables like I am doing with my other 65xx CPU cores now. But this will take some time ... the algorithm functions depend on rd to be set to work on them, rather than taking arguments. So I'll need to rework that. And then lastly, the disassembler is still a mess. I want to finish the CPU cleanups, and then post a new WIP, and then rewrite the disassembler after that. The reason being ... I want a WIP that can generate identical trace logs to older versions, in case the CPU cleanup causes any regressions. That way I can more easily spot the errors. Oh ... and a bit of good news. v102 was running at ~140fps on the SNES core. With the new support to suspend/resume WAI/STP, plus the internal CPU registers not updating the MDR, the framerate dropped to ~132fps. But with the CPU cleanups, performance went back to ~140fps. So, hooray. Of course, without those two other improvements, we'd have ended up at possibly ~146-148fps, but oh well.
This commit is contained in:
parent
cea64b9991
commit
6e8406291c
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "102.23";
|
||||
static const string Version = "102.24";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -12,12 +12,7 @@ auto CPU::Enter() -> void {
|
|||
}
|
||||
|
||||
auto CPU::main() -> void {
|
||||
if(io.interruptPending) {
|
||||
uint16 vector = 0xfffe;
|
||||
if(io.nmiPending) io.nmiPending = false, vector = 0xfffa;
|
||||
return interrupt(vector);
|
||||
}
|
||||
|
||||
if(io.interruptPending) return interrupt();
|
||||
instruction();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ auto APU::readIO(uint32 addr) -> uint8 {
|
|||
|
||||
//NR10
|
||||
case 0x0400'0060: return square1.read(0);
|
||||
case 0x0400'0061: return 0;
|
||||
case 0x0400'0061: return 0x00;
|
||||
|
||||
//NR11, NR12
|
||||
case 0x0400'0062: return square1.read(1);
|
||||
|
@ -13,6 +13,10 @@ auto APU::readIO(uint32 addr) -> uint8 {
|
|||
case 0x0400'0064: return square1.read(3);
|
||||
case 0x0400'0065: return square1.read(4);
|
||||
|
||||
//zero
|
||||
case 0x0400'0066: return 0x00;
|
||||
case 0x0400'0067: return 0x00;
|
||||
|
||||
//NR21, NR22
|
||||
case 0x0400'0068: return square2.read(1);
|
||||
case 0x0400'0069: return square2.read(2);
|
||||
|
@ -21,9 +25,13 @@ auto APU::readIO(uint32 addr) -> uint8 {
|
|||
case 0x0400'006c: return square2.read(3);
|
||||
case 0x0400'006d: return square2.read(4);
|
||||
|
||||
//zero
|
||||
case 0x0400'006e: return 0x00;
|
||||
case 0x0400'006f: return 0x00;
|
||||
|
||||
//NR30
|
||||
case 0x0400'0070: return wave.read(0);
|
||||
case 0x0400'0071: return 0;
|
||||
case 0x0400'0071: return 0x00;
|
||||
|
||||
//NR31, NR32
|
||||
case 0x0400'0072: return wave.read(1);
|
||||
|
@ -33,14 +41,26 @@ auto APU::readIO(uint32 addr) -> uint8 {
|
|||
case 0x0400'0074: return wave.read(3);
|
||||
case 0x0400'0075: return wave.read(4);
|
||||
|
||||
//zero
|
||||
case 0x0400'0076: return 0x00;
|
||||
case 0x0400'0077: return 0x00;
|
||||
|
||||
//NR41, NR42
|
||||
case 0x0400'0078: return noise.read(1);
|
||||
case 0x0400'0079: return noise.read(2);
|
||||
|
||||
//zero
|
||||
case 0x0400'007a: return 0x00;
|
||||
case 0x0400'007b: return 0x00;
|
||||
|
||||
//NR43, NR44
|
||||
case 0x0400'007c: return noise.read(3);
|
||||
case 0x0400'007d: return noise.read(4);
|
||||
|
||||
//zero
|
||||
case 0x0400'007e: return 0x00;
|
||||
case 0x0400'007f: return 0x00;
|
||||
|
||||
//NR50, NR51
|
||||
case 0x0400'0080: return sequencer.read(0);
|
||||
case 0x0400'0081: return sequencer.read(1);
|
||||
|
@ -63,7 +83,11 @@ auto APU::readIO(uint32 addr) -> uint8 {
|
|||
|
||||
//NR52
|
||||
case 0x0400'0084: return sequencer.read(2);
|
||||
case 0x0400'0085: return 0;
|
||||
case 0x0400'0085: return 0x00;
|
||||
|
||||
//zero
|
||||
case 0x0400'0086: return 0x00;
|
||||
case 0x0400'0087: return 0x00;
|
||||
|
||||
//SOUNDBIAS
|
||||
case 0x0400'0088: return (
|
||||
|
@ -74,6 +98,10 @@ auto APU::readIO(uint32 addr) -> uint8 {
|
|||
| regs.bias.amplitude << 6
|
||||
);
|
||||
|
||||
//zero
|
||||
case 0x0400'008a: return 0x00;
|
||||
case 0x0400'008b: return 0x00;
|
||||
|
||||
//WAVE_RAM0_L
|
||||
case 0x0400'0090: return wave.readram( 0);
|
||||
case 0x0400'0091: return wave.readram( 1);
|
||||
|
@ -108,7 +136,7 @@ auto APU::readIO(uint32 addr) -> uint8 {
|
|||
|
||||
}
|
||||
|
||||
return 0;
|
||||
return cpu.pipeline.fetch.instruction.byte(addr & 1);
|
||||
}
|
||||
|
||||
auto APU::writeIO(uint32 addr, uint8 data) -> void {
|
||||
|
|
|
@ -4,6 +4,10 @@ auto CPU::readIO(uint32 addr) -> uint8 {
|
|||
|
||||
switch(addr) {
|
||||
|
||||
//DMA0CNT_L, DMA1CNT_L, DMA2CNT_L, DMA3CNT_L
|
||||
case 0x0400'00b8: case 0x0400'00c4: case 0x0400'00d0: case 0x0400'00dc: return 0x00;
|
||||
case 0x0400'00b9: case 0x0400'00c5: case 0x0400'00d1: case 0x0400'00dd: return 0x00;
|
||||
|
||||
//DMA0CNT_H, DMA1CNT_H, DMA2CNT_H, DMA3CNT_H
|
||||
case 0x0400'00ba: case 0x0400'00c6: case 0x0400'00d2: case 0x0400'00de: return (
|
||||
dma().control.targetmode << 5
|
||||
|
@ -195,7 +199,7 @@ auto CPU::readIO(uint32 addr) -> uint8 {
|
|||
|
||||
}
|
||||
|
||||
return 0;
|
||||
return cpu.pipeline.fetch.instruction.byte(addr & 1);
|
||||
}
|
||||
|
||||
auto CPU::writeIO(uint32 addr, uint8 data) -> void {
|
||||
|
|
|
@ -41,8 +41,12 @@ auto IO::writeIO(uint mode, uint32 addr, uint32 word) -> void {
|
|||
}
|
||||
|
||||
struct UnmappedIO : IO {
|
||||
auto readIO(uint32 addr) -> uint8 override { return 0; }
|
||||
auto writeIO(uint32 addr, uint8 byte) -> void override {}
|
||||
auto readIO(uint32 addr) -> uint8 override {
|
||||
return cpu.pipeline.fetch.instruction.byte(addr & 1);
|
||||
}
|
||||
|
||||
auto writeIO(uint32 addr, uint8 byte) -> void override {
|
||||
}
|
||||
};
|
||||
|
||||
static UnmappedIO unmappedIO;
|
||||
|
|
|
@ -99,7 +99,7 @@ auto PPU::readIO(uint32 addr) -> uint8 {
|
|||
|
||||
}
|
||||
|
||||
return 0;
|
||||
return cpu.pipeline.fetch.instruction.byte(addr & 1);
|
||||
}
|
||||
|
||||
auto PPU::writeIO(uint32 addr, uint8 data) -> void {
|
||||
|
|
|
@ -115,8 +115,8 @@ auto VDP::readControlPort() -> uint16 {
|
|||
|
||||
uint16 result = 0b0011'0100'0000'0000;
|
||||
result |= 1 << 9; //FIFO empty
|
||||
result |= (state.y >= 240) << 3; //vertical blank
|
||||
result |= (state.y >= 240 || state.x >= 320) << 2; //horizontal blank
|
||||
result |= (state.y >= screenHeight()) << 3; //vertical blank
|
||||
result |= (state.y >= screenHeight() || state.x >= 320) << 2; //horizontal blank
|
||||
result |= io.command.bit(5) << 1; //DMA active
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -20,8 +20,6 @@ obj/processor-huc6280.o: processor/huc6280/huc6280.cpp $(call rwildcard,process
|
|||
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)
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Processor {
|
|||
//* ARMv4T (ARM7TDMI)
|
||||
|
||||
struct ARM {
|
||||
enum : uint { //mode flags for bus_read, bus_write:
|
||||
enum : uint { //mode flags for bus_read, bus_write:
|
||||
Nonsequential = 1, //N cycle
|
||||
Sequential = 2, //S cycle
|
||||
Prefetch = 4, //instruction fetch (eligible for prefetch)
|
||||
|
|
|
@ -45,6 +45,7 @@ auto M68K::exception(uint exception, uint vector, uint priority) -> void {
|
|||
auto pc = r.pc;
|
||||
auto sr = readSR();
|
||||
|
||||
if(!r.s) swap(r.a[7], r.sp);
|
||||
r.i = priority;
|
||||
r.s = 1;
|
||||
r.t = 0;
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);
|
||||
#define fp(name) &MOS6502::name
|
||||
|
||||
auto MOS6502::interrupt(uint16 vector) -> void {
|
||||
auto MOS6502::interrupt() -> void {
|
||||
idle();
|
||||
idle();
|
||||
push(PCH);
|
||||
push(PCL);
|
||||
push(P);
|
||||
uint16 vector = 0xfffe;
|
||||
nmi(vector);
|
||||
push(P | 0x20);
|
||||
I = 1;
|
||||
PCL = read(vector++);
|
||||
L PCH = read(vector++);
|
||||
I = 1;
|
||||
D = 0;
|
||||
}
|
||||
|
||||
auto MOS6502::instruction() -> void {
|
||||
|
|
|
@ -314,11 +314,12 @@ auto MOS6502::instructionBRK() -> void {
|
|||
operand();
|
||||
push(PCH);
|
||||
push(PCL);
|
||||
uint16 vector = 0xfffe;
|
||||
nmi(vector);
|
||||
push(P | 0x30);
|
||||
PCL = read(0xfffe);
|
||||
L PCH = read(0xffff);
|
||||
I = 1;
|
||||
D = 0;
|
||||
PCL = read(vector++);
|
||||
L PCH = read(vector++);
|
||||
}
|
||||
|
||||
auto MOS6502::instructionJMPAbsolute() -> void {
|
||||
|
@ -331,7 +332,8 @@ auto MOS6502::instructionJMPIndirect() -> void {
|
|||
uint16 absolute = operand();
|
||||
absolute |= operand() << 8;
|
||||
uint16 pc = read(absolute);
|
||||
L pc |= read((absolute & 0xff00) | ((absolute & 0x00ff) + 1)) << 8;
|
||||
absolute.byte(0)++; //MOS6502: $00ff wraps here to $0000; not $0100
|
||||
L pc |= read(absolute) << 8;
|
||||
PC = pc;
|
||||
}
|
||||
|
||||
|
@ -346,7 +348,7 @@ L push(PCL);
|
|||
}
|
||||
|
||||
auto MOS6502::instructionNOP() -> void {
|
||||
idle();
|
||||
L idle();
|
||||
}
|
||||
|
||||
auto MOS6502::instructionPHP() -> void {
|
||||
|
|
|
@ -27,7 +27,7 @@ struct MOS6502 {
|
|||
auto pull() -> uint8;
|
||||
|
||||
//instruction.cpp
|
||||
auto interrupt(uint16 vector) -> void;
|
||||
auto interrupt() -> void;
|
||||
auto instruction() -> void;
|
||||
|
||||
//instructions.cpp
|
||||
|
@ -90,6 +90,9 @@ struct MOS6502 {
|
|||
//disassembler.cpp
|
||||
auto disassemble(uint16 pc) -> string;
|
||||
|
||||
//set to false to disable BCD mode in ADC, SBC instructions
|
||||
bool BCD = true;
|
||||
|
||||
struct Flags {
|
||||
bool c; //carry
|
||||
bool z; //zero
|
||||
|
@ -122,8 +125,6 @@ struct MOS6502 {
|
|||
Flags p;
|
||||
uint8 mdr;
|
||||
} r;
|
||||
|
||||
bool BCD = true;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
auto MOS6502::serialize(serializer& s) -> void {
|
||||
s.integer(BCD);
|
||||
s.integer(r.a);
|
||||
s.integer(r.x);
|
||||
s.integer(r.y);
|
||||
|
@ -11,5 +12,4 @@ auto MOS6502::serialize(serializer& s) -> void {
|
|||
s.integer(r.p.v);
|
||||
s.integer(r.p.n);
|
||||
s.integer(r.mdr);
|
||||
s.integer(BCD);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
auto V30MZ::interrupt(uint8 vector) -> void {
|
||||
wait(32);
|
||||
|
||||
state.halt = false;
|
||||
state.poll = true;
|
||||
state.prefix = false;
|
||||
|
||||
//if an IRQ fires during a rep string instruction;
|
||||
//flush prefix queue and seek back to first prefix.
|
||||
//this allows the transfer to resume after the IRQ.
|
||||
if(prefixes) {
|
||||
r.ip -= prefixes.size();
|
||||
prefixes.reset();
|
||||
}
|
||||
|
||||
auto ip = read(Word, 0x0000, vector * 4 + 0);
|
||||
auto cs = read(Word, 0x0000, vector * 4 + 2);
|
||||
|
||||
push(r.f);
|
||||
push(r.cs);
|
||||
push(r.ip);
|
||||
|
||||
r.f.m = true;
|
||||
r.f.i = false;
|
||||
r.f.b = false;
|
||||
|
||||
r.ip = ip;
|
||||
r.cs = cs;
|
||||
}
|
||||
|
||||
auto V30MZ::instruction() -> void {
|
||||
switch(opcode = fetch()) {
|
||||
case 0x00: return opAddMemReg(Byte);
|
||||
case 0x01: return opAddMemReg(Word);
|
||||
case 0x02: return opAddRegMem(Byte);
|
||||
case 0x03: return opAddRegMem(Word);
|
||||
case 0x04: return opAddAccImm(Byte);
|
||||
case 0x05: return opAddAccImm(Word);
|
||||
case 0x06: return opPushReg(r.es);
|
||||
case 0x07: return opPopReg(r.es);
|
||||
case 0x08: return opOrMemReg(Byte);
|
||||
case 0x09: return opOrMemReg(Word);
|
||||
case 0x0a: return opOrRegMem(Byte);
|
||||
case 0x0b: return opOrRegMem(Word);
|
||||
case 0x0c: return opOrAccImm(Byte);
|
||||
case 0x0d: return opOrAccImm(Word);
|
||||
case 0x0e: return opPushReg(r.cs);
|
||||
case 0x0f: return; //pop cs
|
||||
case 0x10: return opAdcMemReg(Byte);
|
||||
case 0x11: return opAdcMemReg(Word);
|
||||
case 0x12: return opAdcRegMem(Byte);
|
||||
case 0x13: return opAdcRegMem(Word);
|
||||
case 0x14: return opAdcAccImm(Byte);
|
||||
case 0x15: return opAdcAccImm(Word);
|
||||
case 0x16: return opPushReg(r.ss);
|
||||
case 0x17: return opPopReg(r.ss);
|
||||
case 0x18: return opSbbMemReg(Byte);
|
||||
case 0x19: return opSbbMemReg(Word);
|
||||
case 0x1a: return opSbbRegMem(Byte);
|
||||
case 0x1b: return opSbbRegMem(Word);
|
||||
case 0x1c: return opSbbAccImm(Byte);
|
||||
case 0x1d: return opSbbAccImm(Word);
|
||||
case 0x1e: return opPushReg(r.ds);
|
||||
case 0x1f: return opPopReg(r.ds);
|
||||
case 0x20: return opAndMemReg(Byte);
|
||||
case 0x21: return opAndMemReg(Word);
|
||||
case 0x22: return opAndRegMem(Byte);
|
||||
case 0x23: return opAndRegMem(Word);
|
||||
case 0x24: return opAndAccImm(Byte);
|
||||
case 0x25: return opAndAccImm(Word);
|
||||
case 0x26: return opSegment(r.es);
|
||||
case 0x27: return opDecimalAdjust(0); //daa
|
||||
case 0x28: return opSubMemReg(Byte);
|
||||
case 0x29: return opSubMemReg(Word);
|
||||
case 0x2a: return opSubRegMem(Byte);
|
||||
case 0x2b: return opSubRegMem(Word);
|
||||
case 0x2c: return opSubAccImm(Byte);
|
||||
case 0x2d: return opSubAccImm(Word);
|
||||
case 0x2e: return opSegment(r.cs);
|
||||
case 0x2f: return opDecimalAdjust(1); //das
|
||||
case 0x30: return opXorMemReg(Byte);
|
||||
case 0x31: return opXorMemReg(Word);
|
||||
case 0x32: return opXorRegMem(Byte);
|
||||
case 0x33: return opXorRegMem(Word);
|
||||
case 0x34: return opXorAccImm(Byte);
|
||||
case 0x35: return opXorAccImm(Word);
|
||||
case 0x36: return opSegment(r.ss);
|
||||
case 0x37: return opAsciiAdjust(0); //aaa
|
||||
case 0x38: return opCmpMemReg(Byte);
|
||||
case 0x39: return opCmpMemReg(Word);
|
||||
case 0x3a: return opCmpRegMem(Byte);
|
||||
case 0x3b: return opCmpRegMem(Word);
|
||||
case 0x3c: return opCmpAccImm(Byte);
|
||||
case 0x3d: return opCmpAccImm(Word);
|
||||
case 0x3e: return opSegment(r.ds);
|
||||
case 0x3f: return opAsciiAdjust(1); //aas
|
||||
case 0x40: return opIncReg(r.ax);
|
||||
case 0x41: return opIncReg(r.cx);
|
||||
case 0x42: return opIncReg(r.dx);
|
||||
case 0x43: return opIncReg(r.bx);
|
||||
case 0x44: return opIncReg(r.sp);
|
||||
case 0x45: return opIncReg(r.bp);
|
||||
case 0x46: return opIncReg(r.si);
|
||||
case 0x47: return opIncReg(r.di);
|
||||
case 0x48: return opDecReg(r.ax);
|
||||
case 0x49: return opDecReg(r.cx);
|
||||
case 0x4a: return opDecReg(r.dx);
|
||||
case 0x4b: return opDecReg(r.bx);
|
||||
case 0x4c: return opDecReg(r.sp);
|
||||
case 0x4d: return opDecReg(r.bp);
|
||||
case 0x4e: return opDecReg(r.si);
|
||||
case 0x4f: return opDecReg(r.di);
|
||||
case 0x50: return opPushReg(r.ax);
|
||||
case 0x51: return opPushReg(r.cx);
|
||||
case 0x52: return opPushReg(r.dx);
|
||||
case 0x53: return opPushReg(r.bx);
|
||||
case 0x54: return opPushReg(r.sp);
|
||||
case 0x55: return opPushReg(r.bp);
|
||||
case 0x56: return opPushReg(r.si);
|
||||
case 0x57: return opPushReg(r.di);
|
||||
case 0x58: return opPopReg(r.ax);
|
||||
case 0x59: return opPopReg(r.cx);
|
||||
case 0x5a: return opPopReg(r.dx);
|
||||
case 0x5b: return opPopReg(r.bx);
|
||||
case 0x5c: return opPopReg(r.sp);
|
||||
case 0x5d: return opPopReg(r.bp);
|
||||
case 0x5e: return opPopReg(r.si);
|
||||
case 0x5f: return opPopReg(r.di);
|
||||
case 0x60: return opPushAll();
|
||||
case 0x61: return opPopAll();
|
||||
case 0x62: return opBound();
|
||||
case 0x63: return;
|
||||
case 0x64: return;
|
||||
case 0x65: return;
|
||||
case 0x66: return;
|
||||
case 0x67: return;
|
||||
case 0x68: return opPushImm(Word);
|
||||
case 0x69: return opMultiplySignedRegMemImm(Word);
|
||||
case 0x6a: return opPushImm(Byte);
|
||||
case 0x6b: return opMultiplySignedRegMemImm(Byte);
|
||||
case 0x6c: return opInString(Byte);
|
||||
case 0x6d: return opInString(Word);
|
||||
case 0x6e: return opOutString(Byte);
|
||||
case 0x6f: return opOutString(Word);
|
||||
case 0x70: return opJumpIf(r.f.v == 1);
|
||||
case 0x71: return opJumpIf(r.f.v == 0);
|
||||
case 0x72: return opJumpIf(r.f.c == 1);
|
||||
case 0x73: return opJumpIf(r.f.c == 0);
|
||||
case 0x74: return opJumpIf(r.f.z == 1);
|
||||
case 0x75: return opJumpIf(r.f.z == 0);
|
||||
case 0x76: return opJumpIf(r.f.z == 1 || r.f.c == 1);
|
||||
case 0x77: return opJumpIf(r.f.z != 1 && r.f.c != 1);
|
||||
case 0x78: return opJumpIf(r.f.s == 1);
|
||||
case 0x79: return opJumpIf(r.f.s == 0);
|
||||
case 0x7a: return opJumpIf(r.f.p == 1);
|
||||
case 0x7b: return opJumpIf(r.f.p == 0);
|
||||
case 0x7c: return opJumpIf(r.f.s != r.f.v && r.f.z == 0);
|
||||
case 0x7d: return opJumpIf(r.f.s == r.f.v || r.f.z == 1);
|
||||
case 0x7e: return opJumpIf(r.f.s != r.f.v || r.f.z == 1);
|
||||
case 0x7f: return opJumpIf(r.f.s == r.f.v && r.f.z == 0);
|
||||
case 0x80: return opGroup1MemImm(Byte, 0);
|
||||
case 0x81: return opGroup1MemImm(Word, 0);
|
||||
case 0x82: return opGroup1MemImm(Byte, 1);
|
||||
case 0x83: return opGroup1MemImm(Word, 1);
|
||||
case 0x84: return opTestMemReg(Byte);
|
||||
case 0x85: return opTestMemReg(Word);
|
||||
case 0x86: return opExchangeMemReg(Byte);
|
||||
case 0x87: return opExchangeMemReg(Word);
|
||||
case 0x88: return opMoveMemReg(Byte);
|
||||
case 0x89: return opMoveMemReg(Word);
|
||||
case 0x8a: return opMoveRegMem(Byte);
|
||||
case 0x8b: return opMoveRegMem(Word);
|
||||
case 0x8c: return opMoveMemSeg();
|
||||
case 0x8d: return opLoadEffectiveAddressRegMem();
|
||||
case 0x8e: return opMoveSegMem();
|
||||
case 0x8f: return opPopMem();
|
||||
case 0x90: return opNop();
|
||||
case 0x91: return opExchange(r.ax, r.cx);
|
||||
case 0x92: return opExchange(r.ax, r.dx);
|
||||
case 0x93: return opExchange(r.ax, r.bx);
|
||||
case 0x94: return opExchange(r.ax, r.sp);
|
||||
case 0x95: return opExchange(r.ax, r.bp);
|
||||
case 0x96: return opExchange(r.ax, r.si);
|
||||
case 0x97: return opExchange(r.ax, r.di);
|
||||
case 0x98: return opSignExtendByte();
|
||||
case 0x99: return opSignExtendWord();
|
||||
case 0x9a: return opCallFar();
|
||||
case 0x9b: return opWait();
|
||||
case 0x9c: return opPushFlags();
|
||||
case 0x9d: return opPopFlags();
|
||||
case 0x9e: return opStoreFlagsAcc();
|
||||
case 0x9f: return opLoadAccFlags();
|
||||
case 0xa0: return opMoveAccMem(Byte);
|
||||
case 0xa1: return opMoveAccMem(Word);
|
||||
case 0xa2: return opMoveMemAcc(Byte);
|
||||
case 0xa3: return opMoveMemAcc(Word);
|
||||
case 0xa4: return opMoveString(Byte);
|
||||
case 0xa5: return opMoveString(Word);
|
||||
case 0xa6: return opCompareString(Byte);
|
||||
case 0xa7: return opCompareString(Word);
|
||||
case 0xa8: return opTestAcc(Byte);
|
||||
case 0xa9: return opTestAcc(Word);
|
||||
case 0xaa: return opStoreString(Byte);
|
||||
case 0xab: return opStoreString(Word);
|
||||
case 0xac: return opLoadString(Byte);
|
||||
case 0xad: return opLoadString(Word);
|
||||
case 0xae: return opScanString(Byte);
|
||||
case 0xaf: return opScanString(Word);
|
||||
case 0xb0: return opMoveRegImm(r.al);
|
||||
case 0xb1: return opMoveRegImm(r.cl);
|
||||
case 0xb2: return opMoveRegImm(r.dl);
|
||||
case 0xb3: return opMoveRegImm(r.bl);
|
||||
case 0xb4: return opMoveRegImm(r.ah);
|
||||
case 0xb5: return opMoveRegImm(r.ch);
|
||||
case 0xb6: return opMoveRegImm(r.dh);
|
||||
case 0xb7: return opMoveRegImm(r.bh);
|
||||
case 0xb8: return opMoveRegImm(r.ax);
|
||||
case 0xb9: return opMoveRegImm(r.cx);
|
||||
case 0xba: return opMoveRegImm(r.dx);
|
||||
case 0xbb: return opMoveRegImm(r.bx);
|
||||
case 0xbc: return opMoveRegImm(r.sp);
|
||||
case 0xbd: return opMoveRegImm(r.bp);
|
||||
case 0xbe: return opMoveRegImm(r.si);
|
||||
case 0xbf: return opMoveRegImm(r.di);
|
||||
case 0xc0: return opGroup2MemImm(Byte);
|
||||
case 0xc1: return opGroup2MemImm(Word);
|
||||
case 0xc2: return opReturnImm();
|
||||
case 0xc3: return opReturn();
|
||||
case 0xc4: return opLoadSegmentMem(r.es);
|
||||
case 0xc5: return opLoadSegmentMem(r.ds);
|
||||
case 0xc6: return opMoveMemImm(Byte);
|
||||
case 0xc7: return opMoveMemImm(Word);
|
||||
case 0xc8: return opEnter();
|
||||
case 0xc9: return opLeave();
|
||||
case 0xca: return opReturnFarImm();
|
||||
case 0xcb: return opReturnFar();
|
||||
case 0xcc: return opInt3();
|
||||
case 0xcd: return opIntImm();
|
||||
case 0xce: return opInto();
|
||||
case 0xcf: return opReturnInt();
|
||||
case 0xd0: return opGroup2MemImm(Byte, (uint8)1);
|
||||
case 0xd1: return opGroup2MemImm(Word, (uint8)1);
|
||||
case 0xd2: return opGroup2MemImm(Byte, (uint8)r.cl);
|
||||
case 0xd3: return opGroup2MemImm(Word, (uint8)r.cl);
|
||||
case 0xd4: return opAdjustAfterMultiply();
|
||||
case 0xd5: return opAdjustAfterDivide();
|
||||
case 0xd6: return;
|
||||
case 0xd7: return opTranslate();
|
||||
case 0xd8: return; //fpo1
|
||||
case 0xd9: return; //fpo1
|
||||
case 0xda: return; //fpo1
|
||||
case 0xdb: return; //fpo1
|
||||
case 0xdc: return; //fpo1
|
||||
case 0xdd: return; //fpo1
|
||||
case 0xde: return; //fpo1
|
||||
case 0xdf: return; //fpo1
|
||||
case 0xe0: return opLoopWhile(0); //loopnz
|
||||
case 0xe1: return opLoopWhile(1); //loopz
|
||||
case 0xe2: return opLoop();
|
||||
case 0xe3: return opJumpIf(r.cx == 0);
|
||||
case 0xe4: return opIn(Byte);
|
||||
case 0xe5: return opIn(Word);
|
||||
case 0xe6: return opOut(Byte);
|
||||
case 0xe7: return opOut(Word);
|
||||
case 0xe8: return opCallNear();
|
||||
case 0xe9: return opJumpNear();
|
||||
case 0xea: return opJumpFar();
|
||||
case 0xeb: return opJumpShort();
|
||||
case 0xec: return opInDX(Byte);
|
||||
case 0xed: return opInDX(Word);
|
||||
case 0xee: return opOutDX(Byte);
|
||||
case 0xef: return opOutDX(Word);
|
||||
case 0xf0: return opLock();
|
||||
case 0xf1: return;
|
||||
case 0xf2: return opRepeat(0); //repnz
|
||||
case 0xf3: return opRepeat(1); //repz
|
||||
case 0xf4: return opHalt();
|
||||
case 0xf5: return opComplementCarry();
|
||||
case 0xf6: return opGroup3MemImm(Byte);
|
||||
case 0xf7: return opGroup3MemImm(Word);
|
||||
case 0xf8: return opClearFlag(r.f.c.bit);
|
||||
case 0xf9: return opSetFlag(r.f.c.bit);
|
||||
case 0xfa: return opClearFlag(r.f.i.bit);
|
||||
case 0xfb: return opSetFlag(r.f.i.bit);
|
||||
case 0xfc: return opClearFlag(r.f.d.bit);
|
||||
case 0xfd: return opSetFlag(r.f.d.bit);
|
||||
case 0xfe: return opGroup4MemImm(Byte);
|
||||
case 0xff: return opGroup4MemImm(Word);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ namespace Processor {
|
|||
#include "instructions-misc.cpp"
|
||||
#include "instructions-move.cpp"
|
||||
#include "instructions-string.cpp"
|
||||
#include "instruction.cpp"
|
||||
#include "serialization.cpp"
|
||||
#include "disassembler.cpp"
|
||||
|
||||
|
@ -53,295 +54,4 @@ auto V30MZ::exec() -> void {
|
|||
if(!state.prefix) prefixes.reset();
|
||||
}
|
||||
|
||||
auto V30MZ::interrupt(uint8 vector) -> void {
|
||||
wait(32);
|
||||
|
||||
state.halt = false;
|
||||
state.poll = true;
|
||||
state.prefix = false;
|
||||
|
||||
//if an IRQ fires during a rep string instruction;
|
||||
//flush prefix queue and seek back to first prefix.
|
||||
//this allows the transfer to resume after the IRQ.
|
||||
if(prefixes) {
|
||||
r.ip -= prefixes.size();
|
||||
prefixes.reset();
|
||||
}
|
||||
|
||||
auto ip = read(Word, 0x0000, vector * 4 + 0);
|
||||
auto cs = read(Word, 0x0000, vector * 4 + 2);
|
||||
|
||||
push(r.f);
|
||||
push(r.cs);
|
||||
push(r.ip);
|
||||
|
||||
r.f.m = true;
|
||||
r.f.i = false;
|
||||
r.f.b = false;
|
||||
|
||||
r.ip = ip;
|
||||
r.cs = cs;
|
||||
}
|
||||
|
||||
auto V30MZ::instruction() -> void {
|
||||
switch(opcode = fetch()) {
|
||||
case 0x00: return opAddMemReg(Byte);
|
||||
case 0x01: return opAddMemReg(Word);
|
||||
case 0x02: return opAddRegMem(Byte);
|
||||
case 0x03: return opAddRegMem(Word);
|
||||
case 0x04: return opAddAccImm(Byte);
|
||||
case 0x05: return opAddAccImm(Word);
|
||||
case 0x06: return opPushReg(r.es);
|
||||
case 0x07: return opPopReg(r.es);
|
||||
case 0x08: return opOrMemReg(Byte);
|
||||
case 0x09: return opOrMemReg(Word);
|
||||
case 0x0a: return opOrRegMem(Byte);
|
||||
case 0x0b: return opOrRegMem(Word);
|
||||
case 0x0c: return opOrAccImm(Byte);
|
||||
case 0x0d: return opOrAccImm(Word);
|
||||
case 0x0e: return opPushReg(r.cs);
|
||||
case 0x0f: return; //pop cs
|
||||
case 0x10: return opAdcMemReg(Byte);
|
||||
case 0x11: return opAdcMemReg(Word);
|
||||
case 0x12: return opAdcRegMem(Byte);
|
||||
case 0x13: return opAdcRegMem(Word);
|
||||
case 0x14: return opAdcAccImm(Byte);
|
||||
case 0x15: return opAdcAccImm(Word);
|
||||
case 0x16: return opPushReg(r.ss);
|
||||
case 0x17: return opPopReg(r.ss);
|
||||
case 0x18: return opSbbMemReg(Byte);
|
||||
case 0x19: return opSbbMemReg(Word);
|
||||
case 0x1a: return opSbbRegMem(Byte);
|
||||
case 0x1b: return opSbbRegMem(Word);
|
||||
case 0x1c: return opSbbAccImm(Byte);
|
||||
case 0x1d: return opSbbAccImm(Word);
|
||||
case 0x1e: return opPushReg(r.ds);
|
||||
case 0x1f: return opPopReg(r.ds);
|
||||
case 0x20: return opAndMemReg(Byte);
|
||||
case 0x21: return opAndMemReg(Word);
|
||||
case 0x22: return opAndRegMem(Byte);
|
||||
case 0x23: return opAndRegMem(Word);
|
||||
case 0x24: return opAndAccImm(Byte);
|
||||
case 0x25: return opAndAccImm(Word);
|
||||
case 0x26: return opSegment(r.es);
|
||||
case 0x27: return opDecimalAdjust(0); //daa
|
||||
case 0x28: return opSubMemReg(Byte);
|
||||
case 0x29: return opSubMemReg(Word);
|
||||
case 0x2a: return opSubRegMem(Byte);
|
||||
case 0x2b: return opSubRegMem(Word);
|
||||
case 0x2c: return opSubAccImm(Byte);
|
||||
case 0x2d: return opSubAccImm(Word);
|
||||
case 0x2e: return opSegment(r.cs);
|
||||
case 0x2f: return opDecimalAdjust(1); //das
|
||||
case 0x30: return opXorMemReg(Byte);
|
||||
case 0x31: return opXorMemReg(Word);
|
||||
case 0x32: return opXorRegMem(Byte);
|
||||
case 0x33: return opXorRegMem(Word);
|
||||
case 0x34: return opXorAccImm(Byte);
|
||||
case 0x35: return opXorAccImm(Word);
|
||||
case 0x36: return opSegment(r.ss);
|
||||
case 0x37: return opAsciiAdjust(0); //aaa
|
||||
case 0x38: return opCmpMemReg(Byte);
|
||||
case 0x39: return opCmpMemReg(Word);
|
||||
case 0x3a: return opCmpRegMem(Byte);
|
||||
case 0x3b: return opCmpRegMem(Word);
|
||||
case 0x3c: return opCmpAccImm(Byte);
|
||||
case 0x3d: return opCmpAccImm(Word);
|
||||
case 0x3e: return opSegment(r.ds);
|
||||
case 0x3f: return opAsciiAdjust(1); //aas
|
||||
case 0x40: return opIncReg(r.ax);
|
||||
case 0x41: return opIncReg(r.cx);
|
||||
case 0x42: return opIncReg(r.dx);
|
||||
case 0x43: return opIncReg(r.bx);
|
||||
case 0x44: return opIncReg(r.sp);
|
||||
case 0x45: return opIncReg(r.bp);
|
||||
case 0x46: return opIncReg(r.si);
|
||||
case 0x47: return opIncReg(r.di);
|
||||
case 0x48: return opDecReg(r.ax);
|
||||
case 0x49: return opDecReg(r.cx);
|
||||
case 0x4a: return opDecReg(r.dx);
|
||||
case 0x4b: return opDecReg(r.bx);
|
||||
case 0x4c: return opDecReg(r.sp);
|
||||
case 0x4d: return opDecReg(r.bp);
|
||||
case 0x4e: return opDecReg(r.si);
|
||||
case 0x4f: return opDecReg(r.di);
|
||||
case 0x50: return opPushReg(r.ax);
|
||||
case 0x51: return opPushReg(r.cx);
|
||||
case 0x52: return opPushReg(r.dx);
|
||||
case 0x53: return opPushReg(r.bx);
|
||||
case 0x54: return opPushReg(r.sp);
|
||||
case 0x55: return opPushReg(r.bp);
|
||||
case 0x56: return opPushReg(r.si);
|
||||
case 0x57: return opPushReg(r.di);
|
||||
case 0x58: return opPopReg(r.ax);
|
||||
case 0x59: return opPopReg(r.cx);
|
||||
case 0x5a: return opPopReg(r.dx);
|
||||
case 0x5b: return opPopReg(r.bx);
|
||||
case 0x5c: return opPopReg(r.sp);
|
||||
case 0x5d: return opPopReg(r.bp);
|
||||
case 0x5e: return opPopReg(r.si);
|
||||
case 0x5f: return opPopReg(r.di);
|
||||
case 0x60: return opPushAll();
|
||||
case 0x61: return opPopAll();
|
||||
case 0x62: return opBound();
|
||||
case 0x63: return;
|
||||
case 0x64: return;
|
||||
case 0x65: return;
|
||||
case 0x66: return;
|
||||
case 0x67: return;
|
||||
case 0x68: return opPushImm(Word);
|
||||
case 0x69: return opMultiplySignedRegMemImm(Word);
|
||||
case 0x6a: return opPushImm(Byte);
|
||||
case 0x6b: return opMultiplySignedRegMemImm(Byte);
|
||||
case 0x6c: return opInString(Byte);
|
||||
case 0x6d: return opInString(Word);
|
||||
case 0x6e: return opOutString(Byte);
|
||||
case 0x6f: return opOutString(Word);
|
||||
case 0x70: return opJumpIf(r.f.v == 1);
|
||||
case 0x71: return opJumpIf(r.f.v == 0);
|
||||
case 0x72: return opJumpIf(r.f.c == 1);
|
||||
case 0x73: return opJumpIf(r.f.c == 0);
|
||||
case 0x74: return opJumpIf(r.f.z == 1);
|
||||
case 0x75: return opJumpIf(r.f.z == 0);
|
||||
case 0x76: return opJumpIf(r.f.z == 1 || r.f.c == 1);
|
||||
case 0x77: return opJumpIf(r.f.z != 1 && r.f.c != 1);
|
||||
case 0x78: return opJumpIf(r.f.s == 1);
|
||||
case 0x79: return opJumpIf(r.f.s == 0);
|
||||
case 0x7a: return opJumpIf(r.f.p == 1);
|
||||
case 0x7b: return opJumpIf(r.f.p == 0);
|
||||
case 0x7c: return opJumpIf(r.f.s != r.f.v && r.f.z == 0);
|
||||
case 0x7d: return opJumpIf(r.f.s == r.f.v || r.f.z == 1);
|
||||
case 0x7e: return opJumpIf(r.f.s != r.f.v || r.f.z == 1);
|
||||
case 0x7f: return opJumpIf(r.f.s == r.f.v && r.f.z == 0);
|
||||
case 0x80: return opGroup1MemImm(Byte, 0);
|
||||
case 0x81: return opGroup1MemImm(Word, 0);
|
||||
case 0x82: return opGroup1MemImm(Byte, 1);
|
||||
case 0x83: return opGroup1MemImm(Word, 1);
|
||||
case 0x84: return opTestMemReg(Byte);
|
||||
case 0x85: return opTestMemReg(Word);
|
||||
case 0x86: return opExchangeMemReg(Byte);
|
||||
case 0x87: return opExchangeMemReg(Word);
|
||||
case 0x88: return opMoveMemReg(Byte);
|
||||
case 0x89: return opMoveMemReg(Word);
|
||||
case 0x8a: return opMoveRegMem(Byte);
|
||||
case 0x8b: return opMoveRegMem(Word);
|
||||
case 0x8c: return opMoveMemSeg();
|
||||
case 0x8d: return opLoadEffectiveAddressRegMem();
|
||||
case 0x8e: return opMoveSegMem();
|
||||
case 0x8f: return opPopMem();
|
||||
case 0x90: return opNop();
|
||||
case 0x91: return opExchange(r.ax, r.cx);
|
||||
case 0x92: return opExchange(r.ax, r.dx);
|
||||
case 0x93: return opExchange(r.ax, r.bx);
|
||||
case 0x94: return opExchange(r.ax, r.sp);
|
||||
case 0x95: return opExchange(r.ax, r.bp);
|
||||
case 0x96: return opExchange(r.ax, r.si);
|
||||
case 0x97: return opExchange(r.ax, r.di);
|
||||
case 0x98: return opSignExtendByte();
|
||||
case 0x99: return opSignExtendWord();
|
||||
case 0x9a: return opCallFar();
|
||||
case 0x9b: return opWait();
|
||||
case 0x9c: return opPushFlags();
|
||||
case 0x9d: return opPopFlags();
|
||||
case 0x9e: return opStoreFlagsAcc();
|
||||
case 0x9f: return opLoadAccFlags();
|
||||
case 0xa0: return opMoveAccMem(Byte);
|
||||
case 0xa1: return opMoveAccMem(Word);
|
||||
case 0xa2: return opMoveMemAcc(Byte);
|
||||
case 0xa3: return opMoveMemAcc(Word);
|
||||
case 0xa4: return opMoveString(Byte);
|
||||
case 0xa5: return opMoveString(Word);
|
||||
case 0xa6: return opCompareString(Byte);
|
||||
case 0xa7: return opCompareString(Word);
|
||||
case 0xa8: return opTestAcc(Byte);
|
||||
case 0xa9: return opTestAcc(Word);
|
||||
case 0xaa: return opStoreString(Byte);
|
||||
case 0xab: return opStoreString(Word);
|
||||
case 0xac: return opLoadString(Byte);
|
||||
case 0xad: return opLoadString(Word);
|
||||
case 0xae: return opScanString(Byte);
|
||||
case 0xaf: return opScanString(Word);
|
||||
case 0xb0: return opMoveRegImm(r.al);
|
||||
case 0xb1: return opMoveRegImm(r.cl);
|
||||
case 0xb2: return opMoveRegImm(r.dl);
|
||||
case 0xb3: return opMoveRegImm(r.bl);
|
||||
case 0xb4: return opMoveRegImm(r.ah);
|
||||
case 0xb5: return opMoveRegImm(r.ch);
|
||||
case 0xb6: return opMoveRegImm(r.dh);
|
||||
case 0xb7: return opMoveRegImm(r.bh);
|
||||
case 0xb8: return opMoveRegImm(r.ax);
|
||||
case 0xb9: return opMoveRegImm(r.cx);
|
||||
case 0xba: return opMoveRegImm(r.dx);
|
||||
case 0xbb: return opMoveRegImm(r.bx);
|
||||
case 0xbc: return opMoveRegImm(r.sp);
|
||||
case 0xbd: return opMoveRegImm(r.bp);
|
||||
case 0xbe: return opMoveRegImm(r.si);
|
||||
case 0xbf: return opMoveRegImm(r.di);
|
||||
case 0xc0: return opGroup2MemImm(Byte);
|
||||
case 0xc1: return opGroup2MemImm(Word);
|
||||
case 0xc2: return opReturnImm();
|
||||
case 0xc3: return opReturn();
|
||||
case 0xc4: return opLoadSegmentMem(r.es);
|
||||
case 0xc5: return opLoadSegmentMem(r.ds);
|
||||
case 0xc6: return opMoveMemImm(Byte);
|
||||
case 0xc7: return opMoveMemImm(Word);
|
||||
case 0xc8: return opEnter();
|
||||
case 0xc9: return opLeave();
|
||||
case 0xca: return opReturnFarImm();
|
||||
case 0xcb: return opReturnFar();
|
||||
case 0xcc: return opInt3();
|
||||
case 0xcd: return opIntImm();
|
||||
case 0xce: return opInto();
|
||||
case 0xcf: return opReturnInt();
|
||||
case 0xd0: return opGroup2MemImm(Byte, (uint8)1);
|
||||
case 0xd1: return opGroup2MemImm(Word, (uint8)1);
|
||||
case 0xd2: return opGroup2MemImm(Byte, (uint8)r.cl);
|
||||
case 0xd3: return opGroup2MemImm(Word, (uint8)r.cl);
|
||||
case 0xd4: return opAdjustAfterMultiply();
|
||||
case 0xd5: return opAdjustAfterDivide();
|
||||
case 0xd6: return;
|
||||
case 0xd7: return opTranslate();
|
||||
case 0xd8: return; //fpo1
|
||||
case 0xd9: return; //fpo1
|
||||
case 0xda: return; //fpo1
|
||||
case 0xdb: return; //fpo1
|
||||
case 0xdc: return; //fpo1
|
||||
case 0xdd: return; //fpo1
|
||||
case 0xde: return; //fpo1
|
||||
case 0xdf: return; //fpo1
|
||||
case 0xe0: return opLoopWhile(0); //loopnz
|
||||
case 0xe1: return opLoopWhile(1); //loopz
|
||||
case 0xe2: return opLoop();
|
||||
case 0xe3: return opJumpIf(r.cx == 0);
|
||||
case 0xe4: return opIn(Byte);
|
||||
case 0xe5: return opIn(Word);
|
||||
case 0xe6: return opOut(Byte);
|
||||
case 0xe7: return opOut(Word);
|
||||
case 0xe8: return opCallNear();
|
||||
case 0xe9: return opJumpNear();
|
||||
case 0xea: return opJumpFar();
|
||||
case 0xeb: return opJumpShort();
|
||||
case 0xec: return opInDX(Byte);
|
||||
case 0xed: return opInDX(Word);
|
||||
case 0xee: return opOutDX(Byte);
|
||||
case 0xef: return opOutDX(Word);
|
||||
case 0xf0: return opLock();
|
||||
case 0xf1: return;
|
||||
case 0xf2: return opRepeat(0); //repnz
|
||||
case 0xf3: return opRepeat(1); //repz
|
||||
case 0xf4: return opHalt();
|
||||
case 0xf5: return opComplementCarry();
|
||||
case 0xf6: return opGroup3MemImm(Byte);
|
||||
case 0xf7: return opGroup3MemImm(Word);
|
||||
case 0xf8: return opClearFlag(r.f.c.bit);
|
||||
case 0xf9: return opSetFlag(r.f.c.bit);
|
||||
case 0xfa: return opClearFlag(r.f.i.bit);
|
||||
case 0xfb: return opSetFlag(r.f.i.bit);
|
||||
case 0xfc: return opClearFlag(r.f.d.bit);
|
||||
case 0xfd: return opSetFlag(r.f.d.bit);
|
||||
case 0xfe: return opGroup4MemImm(Byte);
|
||||
case 0xff: return opGroup4MemImm(Word);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ struct V30MZ {
|
|||
auto warning(string text) -> void;
|
||||
auto power() -> void;
|
||||
auto exec() -> void;
|
||||
|
||||
//instruction.cpp
|
||||
auto interrupt(uint8 vector) -> void;
|
||||
auto instruction() -> void;
|
||||
|
||||
|
@ -61,29 +63,29 @@ struct V30MZ {
|
|||
|
||||
//algorithms.cpp
|
||||
auto parity(uint8) const -> bool;
|
||||
auto alAdc(Size, uint16, uint16) -> uint16;
|
||||
auto alAdd(Size, uint16, uint16) -> uint16;
|
||||
auto alAnd(Size, uint16, uint16) -> uint16;
|
||||
auto alDec(Size, uint16 ) -> uint16;
|
||||
auto alDiv(Size, uint32, uint32) -> uint32;
|
||||
auto alDivi(Size, int32, int32) -> uint32;
|
||||
auto alInc(Size, uint16 ) -> uint16;
|
||||
auto alMul(Size, uint16, uint16) -> uint32;
|
||||
auto alMuli(Size, int16, int16) -> uint32;
|
||||
auto alNeg(Size, uint16 ) -> uint16;
|
||||
auto alNot(Size, uint16 ) -> uint16;
|
||||
auto alOr (Size, uint16, uint16) -> uint16;
|
||||
auto alRcl(Size, uint16, uint5 ) -> uint16;
|
||||
auto alRcr(Size, uint16, uint5 ) -> uint16;
|
||||
auto alRol(Size, uint16, uint4 ) -> uint16;
|
||||
auto alRor(Size, uint16, uint4 ) -> uint16;
|
||||
auto alSal(Size, uint16, uint5 ) -> uint16;
|
||||
auto alSar(Size, uint16, uint5 ) -> uint16;
|
||||
auto alSbb(Size, uint16, uint16) -> uint16;
|
||||
auto alSub(Size, uint16, uint16) -> uint16;
|
||||
auto alShl(Size, uint16, uint5 ) -> uint16;
|
||||
auto alShr(Size, uint16, uint5 ) -> uint16;
|
||||
auto alXor(Size, uint16, uint16) -> uint16;
|
||||
auto alAdc (Size, uint16, uint16) -> uint16;
|
||||
auto alAdd (Size, uint16, uint16) -> uint16;
|
||||
auto alAnd (Size, uint16, uint16) -> uint16;
|
||||
auto alDec (Size, uint16 ) -> uint16;
|
||||
auto alDiv (Size, uint32, uint32) -> uint32;
|
||||
auto alDivi(Size, int32, int32) -> uint32;
|
||||
auto alInc (Size, uint16 ) -> uint16;
|
||||
auto alMul (Size, uint16, uint16) -> uint32;
|
||||
auto alMuli(Size, int16, int16) -> uint32;
|
||||
auto alNeg (Size, uint16 ) -> uint16;
|
||||
auto alNot (Size, uint16 ) -> uint16;
|
||||
auto alOr (Size, uint16, uint16) -> uint16;
|
||||
auto alRcl (Size, uint16, uint5) -> uint16;
|
||||
auto alRcr (Size, uint16, uint5) -> uint16;
|
||||
auto alRol (Size, uint16, uint4) -> uint16;
|
||||
auto alRor (Size, uint16, uint4) -> uint16;
|
||||
auto alSal (Size, uint16, uint5) -> uint16;
|
||||
auto alSar (Size, uint16, uint5) -> uint16;
|
||||
auto alSbb (Size, uint16, uint16) -> uint16;
|
||||
auto alSub (Size, uint16, uint16) -> uint16;
|
||||
auto alShl (Size, uint16, uint5) -> uint16;
|
||||
auto alShr (Size, uint16, uint5) -> uint16;
|
||||
auto alXor (Size, uint16, uint16) -> uint16;
|
||||
|
||||
//instructions-adjust.cpp
|
||||
auto opDecimalAdjust(bool);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
auto R65816::op_adc_b() {
|
||||
auto WDC65816::algorithmADC8() -> void {
|
||||
int result;
|
||||
|
||||
if(!r.p.d) {
|
||||
|
@ -19,7 +19,7 @@ auto R65816::op_adc_b() {
|
|||
r.a.l = result;
|
||||
}
|
||||
|
||||
auto R65816::op_adc_w() {
|
||||
auto WDC65816::algorithmADC16() -> void {
|
||||
int result;
|
||||
|
||||
if(!r.p.d) {
|
||||
|
@ -46,133 +46,217 @@ auto R65816::op_adc_w() {
|
|||
r.a.w = result;
|
||||
}
|
||||
|
||||
auto R65816::op_and_b() {
|
||||
auto WDC65816::algorithmAND8() -> void {
|
||||
r.a.l &= rd.l;
|
||||
r.p.n = r.a.l & 0x80;
|
||||
r.p.z = r.a.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_and_w() {
|
||||
auto WDC65816::algorithmAND16() -> void {
|
||||
r.a.w &= rd.w;
|
||||
r.p.n = r.a.w & 0x8000;
|
||||
r.p.z = r.a.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_bit_b() {
|
||||
auto WDC65816::algorithmASL8() -> void {
|
||||
r.p.c = rd.l & 0x80;
|
||||
rd.l <<= 1;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmASL16() -> void {
|
||||
r.p.c = rd.w & 0x8000;
|
||||
rd.w <<= 1;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmBIT8() -> void {
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.v = rd.l & 0x40;
|
||||
r.p.z = (rd.l & r.a.l) == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_bit_w() {
|
||||
auto WDC65816::algorithmBIT16() -> void {
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.v = rd.w & 0x4000;
|
||||
r.p.z = (rd.w & r.a.w) == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_cmp_b() {
|
||||
auto WDC65816::algorithmCMP8() -> void {
|
||||
int result = r.a.l - rd.l;
|
||||
r.p.n = result & 0x80;
|
||||
r.p.z = (uint8)result == 0;
|
||||
r.p.c = result >= 0;
|
||||
}
|
||||
|
||||
auto R65816::op_cmp_w() {
|
||||
auto WDC65816::algorithmCMP16() -> void {
|
||||
int result = r.a.w - rd.w;
|
||||
r.p.n = result & 0x8000;
|
||||
r.p.z = (uint16)result == 0;
|
||||
r.p.c = result >= 0;
|
||||
}
|
||||
|
||||
auto R65816::op_cpx_b() {
|
||||
auto WDC65816::algorithmCPX8() -> void {
|
||||
int result = r.x.l - rd.l;
|
||||
r.p.n = result & 0x80;
|
||||
r.p.z = (uint8)result == 0;
|
||||
r.p.c = result >= 0;
|
||||
}
|
||||
|
||||
auto R65816::op_cpx_w() {
|
||||
auto WDC65816::algorithmCPX16() -> void {
|
||||
int result = r.x.w - rd.w;
|
||||
r.p.n = result & 0x8000;
|
||||
r.p.z = (uint16)result == 0;
|
||||
r.p.c = result >= 0;
|
||||
}
|
||||
|
||||
auto R65816::op_cpy_b() {
|
||||
auto WDC65816::algorithmCPY8() -> void {
|
||||
int result = r.y.l - rd.l;
|
||||
r.p.n = result & 0x80;
|
||||
r.p.z = (uint8)result == 0;
|
||||
r.p.c = result >= 0;
|
||||
}
|
||||
|
||||
auto R65816::op_cpy_w() {
|
||||
auto WDC65816::algorithmCPY16() -> void {
|
||||
int result = r.y.w - rd.w;
|
||||
r.p.n = result & 0x8000;
|
||||
r.p.z = (uint16)result == 0;
|
||||
r.p.c = result >= 0;
|
||||
}
|
||||
|
||||
auto R65816::op_eor_b() {
|
||||
auto WDC65816::algorithmDEC8() -> void {
|
||||
rd.l--;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmDEC16() -> void {
|
||||
rd.w--;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmEOR8() -> void {
|
||||
r.a.l ^= rd.l;
|
||||
r.p.n = r.a.l & 0x80;
|
||||
r.p.z = r.a.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_eor_w() {
|
||||
auto WDC65816::algorithmEOR16() -> void {
|
||||
r.a.w ^= rd.w;
|
||||
r.p.n = r.a.w & 0x8000;
|
||||
r.p.z = r.a.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_lda_b() {
|
||||
auto WDC65816::algorithmINC8() -> void {
|
||||
rd.l++;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmINC16() -> void {
|
||||
rd.w++;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmLDA8() -> void {
|
||||
r.a.l = rd.l;
|
||||
r.p.n = r.a.l & 0x80;
|
||||
r.p.z = r.a.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_lda_w() {
|
||||
auto WDC65816::algorithmLDA16() -> void {
|
||||
r.a.w = rd.w;
|
||||
r.p.n = r.a.w & 0x8000;
|
||||
r.p.z = r.a.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_ldx_b() {
|
||||
auto WDC65816::algorithmLDX8() -> void {
|
||||
r.x.l = rd.l;
|
||||
r.p.n = r.x.l & 0x80;
|
||||
r.p.z = r.x.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_ldx_w() {
|
||||
auto WDC65816::algorithmLDX16() -> void {
|
||||
r.x.w = rd.w;
|
||||
r.p.n = r.x.w & 0x8000;
|
||||
r.p.z = r.x.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_ldy_b() {
|
||||
auto WDC65816::algorithmLDY8() -> void {
|
||||
r.y.l = rd.l;
|
||||
r.p.n = r.y.l & 0x80;
|
||||
r.p.z = r.y.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_ldy_w() {
|
||||
auto WDC65816::algorithmLDY16() -> void {
|
||||
r.y.w = rd.w;
|
||||
r.p.n = r.y.w & 0x8000;
|
||||
r.p.z = r.y.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_ora_b() {
|
||||
auto WDC65816::algorithmLSR8() -> void {
|
||||
r.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmLSR16() -> void {
|
||||
r.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmORA8() -> void {
|
||||
r.a.l |= rd.l;
|
||||
r.p.n = r.a.l & 0x80;
|
||||
r.p.z = r.a.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_ora_w() {
|
||||
auto WDC65816::algorithmORA16() -> void {
|
||||
r.a.w |= rd.w;
|
||||
r.p.n = r.a.w & 0x8000;
|
||||
r.p.z = r.a.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_sbc_b() {
|
||||
auto WDC65816::algorithmROL8() -> void {
|
||||
auto carry = (uint)r.p.c;
|
||||
r.p.c = rd.l & 0x80;
|
||||
rd.l = (rd.l << 1) | carry;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmROL16() -> void {
|
||||
auto carry = (uint)r.p.c;
|
||||
r.p.c = rd.w & 0x8000;
|
||||
rd.w = (rd.w << 1) | carry;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmROR8() -> void {
|
||||
auto carry = (uint)r.p.c << 7;
|
||||
r.p.c = rd.l & 1;
|
||||
rd.l = carry | (rd.l >> 1);
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmROR16() -> void {
|
||||
auto carry = (uint)r.p.c << 15;
|
||||
r.p.c = rd.w & 1;
|
||||
rd.w = carry | (rd.w >> 1);
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::algorithmSBC8() -> void {
|
||||
int result;
|
||||
rd.l ^= 0xff;
|
||||
|
||||
|
@ -194,7 +278,7 @@ auto R65816::op_sbc_b() {
|
|||
r.a.l = result;
|
||||
}
|
||||
|
||||
auto R65816::op_sbc_w() {
|
||||
auto WDC65816::algorithmSBC16() -> void {
|
||||
int result;
|
||||
rd.w ^= 0xffff;
|
||||
|
||||
|
@ -222,106 +306,22 @@ auto R65816::op_sbc_w() {
|
|||
r.a.w = result;
|
||||
}
|
||||
|
||||
auto R65816::op_inc_b() {
|
||||
rd.l++;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_inc_w() {
|
||||
rd.w++;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_dec_b() {
|
||||
rd.l--;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_dec_w() {
|
||||
rd.w--;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_asl_b() {
|
||||
r.p.c = rd.l & 0x80;
|
||||
rd.l <<= 1;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_asl_w() {
|
||||
r.p.c = rd.w & 0x8000;
|
||||
rd.w <<= 1;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_lsr_b() {
|
||||
r.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_lsr_w() {
|
||||
r.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_rol_b() {
|
||||
auto carry = (uint)r.p.c;
|
||||
r.p.c = rd.l & 0x80;
|
||||
rd.l = (rd.l << 1) | carry;
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_rol_w() {
|
||||
auto carry = (uint)r.p.c;
|
||||
r.p.c = rd.w & 0x8000;
|
||||
rd.w = (rd.w << 1) | carry;
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_ror_b() {
|
||||
auto carry = (uint)r.p.c << 7;
|
||||
r.p.c = rd.l & 1;
|
||||
rd.l = carry | (rd.l >> 1);
|
||||
r.p.n = rd.l & 0x80;
|
||||
r.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_ror_w() {
|
||||
auto carry = (uint)r.p.c << 15;
|
||||
r.p.c = rd.w & 1;
|
||||
rd.w = carry | (rd.w >> 1);
|
||||
r.p.n = rd.w & 0x8000;
|
||||
r.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
auto R65816::op_trb_b() {
|
||||
auto WDC65816::algorithmTRB8() -> void {
|
||||
r.p.z = (rd.l & r.a.l) == 0;
|
||||
rd.l &= ~r.a.l;
|
||||
}
|
||||
|
||||
auto R65816::op_trb_w() {
|
||||
auto WDC65816::algorithmTRB16() -> void {
|
||||
r.p.z = (rd.w & r.a.w) == 0;
|
||||
rd.w &= ~r.a.w;
|
||||
}
|
||||
|
||||
auto R65816::op_tsb_b() {
|
||||
auto WDC65816::algorithmTSB8() -> void {
|
||||
r.p.z = (rd.l & r.a.l) == 0;
|
||||
rd.l |= r.a.l;
|
||||
}
|
||||
|
||||
auto R65816::op_tsb_w() {
|
||||
auto WDC65816::algorithmTSB16() -> void {
|
||||
r.p.z = (rd.w & r.a.w) == 0;
|
||||
rd.w |= r.a.w;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,28 @@
|
|||
auto R65816::dreadb(uint24 addr) -> uint8 {
|
||||
enum : uint {
|
||||
OPTYPE_DP = 0, //dp
|
||||
OPTYPE_DPX, //dp,x
|
||||
OPTYPE_DPY, //dp,y
|
||||
OPTYPE_IDP, //(dp)
|
||||
OPTYPE_IDPX, //(dp,x)
|
||||
OPTYPE_IDPY, //(dp),y
|
||||
OPTYPE_ILDP, //[dp]
|
||||
OPTYPE_ILDPY, //[dp],y
|
||||
OPTYPE_ADDR, //addr
|
||||
OPTYPE_ADDRX, //addr,x
|
||||
OPTYPE_ADDRY, //addr,y
|
||||
OPTYPE_IADDRX, //(addr,x)
|
||||
OPTYPE_ILADDR, //[addr]
|
||||
OPTYPE_LONG, //long
|
||||
OPTYPE_LONGX, //long, x
|
||||
OPTYPE_SR, //sr,s
|
||||
OPTYPE_ISRY, //(sr,s),y
|
||||
OPTYPE_ADDR_PC, //pbr:addr
|
||||
OPTYPE_IADDR_PC, //pbr:(addr)
|
||||
OPTYPE_RELB, //relb
|
||||
OPTYPE_RELW, //relw
|
||||
};
|
||||
|
||||
auto WDC65816::dreadb(uint24 addr) -> uint8 {
|
||||
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
|
||||
//$00-3f|80-bf:2000-5fff
|
||||
//do not read MMIO registers within debugger
|
||||
|
@ -7,14 +31,14 @@ auto R65816::dreadb(uint24 addr) -> uint8 {
|
|||
return readDisassembler(addr);
|
||||
}
|
||||
|
||||
auto R65816::dreadw(uint24 addr) -> uint16 {
|
||||
auto WDC65816::dreadw(uint24 addr) -> uint16 {
|
||||
uint16 data;
|
||||
data.byte(0) = dreadb(addr++);
|
||||
data.byte(1) = dreadb(addr++);
|
||||
return data;
|
||||
}
|
||||
|
||||
auto R65816::dreadl(uint24 addr) -> uint24 {
|
||||
auto WDC65816::dreadl(uint24 addr) -> uint24 {
|
||||
uint24 data;
|
||||
data.byte(0) = dreadb(addr++);
|
||||
data.byte(1) = dreadb(addr++);
|
||||
|
@ -22,7 +46,7 @@ auto R65816::dreadl(uint24 addr) -> uint24 {
|
|||
return data;
|
||||
}
|
||||
|
||||
auto R65816::decode(uint8 mode, uint24 addr) -> uint24 {
|
||||
auto WDC65816::decode(uint8 mode, uint24 addr) -> uint24 {
|
||||
uint24 a = 0;
|
||||
|
||||
switch(mode) {
|
||||
|
@ -102,16 +126,16 @@ auto R65816::decode(uint8 mode, uint24 addr) -> uint24 {
|
|||
return a;
|
||||
}
|
||||
|
||||
auto R65816::disassemble() -> string {
|
||||
auto WDC65816::disassemble() -> string {
|
||||
return disassemble(r.pc.d, r.e, r.p.m, r.p.x);
|
||||
}
|
||||
|
||||
auto R65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string {
|
||||
auto WDC65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string {
|
||||
string s;
|
||||
|
||||
Reg24 pc;
|
||||
Long pc;
|
||||
pc.d = addr;
|
||||
s = {hex(pc, 6), " "};
|
||||
s = {hex(pc.d, 6), " "};
|
||||
|
||||
uint8 op = dreadb(pc.d); pc.w++;
|
||||
uint8 op0 = dreadb(pc.d); pc.w++;
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
enum : uint {
|
||||
OPTYPE_DP = 0, //dp
|
||||
OPTYPE_DPX, //dp,x
|
||||
OPTYPE_DPY, //dp,y
|
||||
OPTYPE_IDP, //(dp)
|
||||
OPTYPE_IDPX, //(dp,x)
|
||||
OPTYPE_IDPY, //(dp),y
|
||||
OPTYPE_ILDP, //[dp]
|
||||
OPTYPE_ILDPY, //[dp],y
|
||||
OPTYPE_ADDR, //addr
|
||||
OPTYPE_ADDRX, //addr,x
|
||||
OPTYPE_ADDRY, //addr,y
|
||||
OPTYPE_IADDRX, //(addr,x)
|
||||
OPTYPE_ILADDR, //[addr]
|
||||
OPTYPE_LONG, //long
|
||||
OPTYPE_LONGX, //long, x
|
||||
OPTYPE_SR, //sr,s
|
||||
OPTYPE_ISRY, //(sr,s),y
|
||||
OPTYPE_ADDR_PC, //pbr:addr
|
||||
OPTYPE_IADDR_PC, //pbr:(addr)
|
||||
OPTYPE_RELB, //relb
|
||||
OPTYPE_RELW, //relw
|
||||
};
|
||||
|
||||
auto disassemble() -> string;
|
||||
auto disassemble(uint24 addr, bool e, bool m, bool x) -> string;
|
||||
auto dreadb(uint24 addr) -> uint8;
|
||||
auto dreadw(uint24 addr) -> uint16;
|
||||
auto dreadl(uint24 addr) -> uint24;
|
||||
auto decode(uint8 mode, uint24 addr) -> uint24;
|
|
@ -0,0 +1,286 @@
|
|||
auto WDC65816::interrupt() -> void {
|
||||
read(PC);
|
||||
idle();
|
||||
N push(PCB);
|
||||
push(PCH);
|
||||
push(PCL);
|
||||
push(EF ? P & ~0x10 : P);
|
||||
IF = 1;
|
||||
DF = 0;
|
||||
PCL = read(r.vector + 0);
|
||||
PCH = read(r.vector + 1);
|
||||
PCB = 0x00;
|
||||
}
|
||||
|
||||
auto WDC65816::instruction() -> void {
|
||||
#define opA(id, name, ...) case id: return instruction##name(__VA_ARGS__);
|
||||
#define opM(id, name, ...) case id: return MF ? instruction##name##8(__VA_ARGS__) : instruction##name##16(__VA_ARGS__);
|
||||
#define opX(id, name, ...) case id: return XF ? instruction##name##8(__VA_ARGS__) : instruction##name##16(__VA_ARGS__);
|
||||
#define m(name) MF ? &WDC65816::algorithm##name##8 : &WDC65816::algorithm##name##16
|
||||
#define x(name) XF ? &WDC65816::algorithm##name##8 : &WDC65816::algorithm##name##16
|
||||
|
||||
switch(fetch()) {
|
||||
opA(0x00, Interrupt, EF ? 0xfffe : 0xffe6) //emulation mode lacks BRK vector; uses IRQ vector instead
|
||||
opM(0x01, IndexedIndirectRead, m(ORA))
|
||||
opA(0x02, Interrupt, EF ? 0xfff4 : 0xffe4)
|
||||
opM(0x03, StackRead, m(ORA))
|
||||
opM(0x04, DirectModify, m(TSB))
|
||||
opM(0x05, DirectRead, m(ORA))
|
||||
opM(0x06, DirectModify, m(ASL))
|
||||
opM(0x07, IndirectLongRead, m(ORA))
|
||||
opA(0x08, PHP)
|
||||
opM(0x09, ImmediateRead, m(ORA))
|
||||
opM(0x0a, ASLImplied)
|
||||
opA(0x0b, PHD)
|
||||
opM(0x0c, BankModify, m(TSB))
|
||||
opM(0x0d, BankRead, m(ORA))
|
||||
opM(0x0e, BankModify, m(ASL))
|
||||
opM(0x0f, LongRead, m(ORA))
|
||||
opA(0x10, Branch, NF == 0)
|
||||
opM(0x11, IndirectIndexedRead, m(ORA))
|
||||
opM(0x12, IndirectRead, m(ORA))
|
||||
opM(0x13, IndirectStackRead, m(ORA))
|
||||
opM(0x14, DirectModify, m(TRB))
|
||||
opM(0x15, DirectRead, m(ORA), X)
|
||||
opM(0x16, DirectIndexedModify, m(ASL))
|
||||
opM(0x17, IndirectLongRead, m(ORA), Y)
|
||||
opA(0x18, ClearFlag, CF)
|
||||
opM(0x19, BankRead, m(ORA), Y)
|
||||
opM(0x1a, INCImplied, A)
|
||||
opA(0x1b, TCS)
|
||||
opM(0x1c, BankModify, m(TRB))
|
||||
opM(0x1d, BankRead, m(ORA), X)
|
||||
opM(0x1e, BankIndexedModify, m(ASL))
|
||||
opM(0x1f, LongRead, m(ORA), X)
|
||||
opA(0x20, JSRShort)
|
||||
opM(0x21, IndexedIndirectRead, m(AND))
|
||||
opA(0x22, JSRLong)
|
||||
opM(0x23, StackRead, m(AND))
|
||||
opM(0x24, DirectRead, m(BIT))
|
||||
opM(0x25, DirectRead, m(AND))
|
||||
opM(0x26, DirectModify, m(ROL))
|
||||
opM(0x27, IndirectLongRead, m(AND))
|
||||
opA(0x28, PLP)
|
||||
opM(0x29, ImmediateRead, m(AND))
|
||||
opM(0x2a, ROLImplied)
|
||||
opA(0x2b, PLD)
|
||||
opM(0x2c, BankRead, m(BIT))
|
||||
opM(0x2d, BankRead, m(AND))
|
||||
opM(0x2e, BankModify, m(ROL))
|
||||
opM(0x2f, LongRead, m(AND))
|
||||
opA(0x30, Branch, NF == 1)
|
||||
opM(0x31, IndirectIndexedRead, m(AND))
|
||||
opM(0x32, IndirectRead, m(AND))
|
||||
opM(0x33, IndirectStackRead, m(AND))
|
||||
opM(0x34, DirectRead, m(BIT), X)
|
||||
opM(0x35, DirectRead, m(AND), X)
|
||||
opM(0x36, DirectIndexedModify, m(ROL))
|
||||
opM(0x37, IndirectLongRead, m(AND), Y)
|
||||
opA(0x38, SetFlag, CF)
|
||||
opM(0x39, BankRead, m(AND), Y)
|
||||
opM(0x3a, DECImplied, A)
|
||||
opA(0x3b, Transfer16, S, A)
|
||||
opM(0x3c, BankRead, m(BIT), X)
|
||||
opM(0x3d, BankRead, m(AND), X)
|
||||
opM(0x3e, BankIndexedModify, m(ROL))
|
||||
opM(0x3f, LongRead, m(AND), X)
|
||||
opA(0x40, RTI)
|
||||
opM(0x41, IndexedIndirectRead, m(EOR))
|
||||
opA(0x42, WDM)
|
||||
opM(0x43, StackRead, m(EOR))
|
||||
opX(0x44, BlockMove, -1)
|
||||
opM(0x45, DirectRead, m(EOR))
|
||||
opM(0x46, DirectModify, m(LSR))
|
||||
opM(0x47, IndirectLongRead, m(EOR))
|
||||
opM(0x48, Push, A)
|
||||
opM(0x49, ImmediateRead, m(EOR))
|
||||
opM(0x4a, LSRImplied)
|
||||
opA(0x4b, PHK)
|
||||
opA(0x4c, JMPShort)
|
||||
opM(0x4d, BankRead, m(EOR))
|
||||
opM(0x4e, BankModify, m(LSR))
|
||||
opM(0x4f, LongRead, m(EOR))
|
||||
opA(0x50, Branch, VF == 0)
|
||||
opM(0x51, IndirectIndexedRead, m(EOR))
|
||||
opM(0x52, IndirectRead, m(EOR))
|
||||
opM(0x53, IndirectStackRead, m(EOR))
|
||||
opX(0x54, BlockMove, +1)
|
||||
opM(0x55, DirectRead, m(EOR), X)
|
||||
opM(0x56, DirectIndexedModify, m(LSR))
|
||||
opM(0x57, IndirectLongRead, m(EOR), Y)
|
||||
opA(0x58, ClearFlag, IF)
|
||||
opM(0x59, BankRead, m(EOR), Y)
|
||||
opX(0x5a, Push, Y)
|
||||
opA(0x5b, Transfer16, A, D)
|
||||
opA(0x5c, JMPLong)
|
||||
opM(0x5d, BankRead, m(EOR), X)
|
||||
opM(0x5e, BankIndexedModify, m(LSR))
|
||||
opM(0x5f, LongRead, m(EOR), X)
|
||||
opA(0x60, RTS)
|
||||
opM(0x61, IndexedIndirectRead, m(ADC))
|
||||
opA(0x62, PER)
|
||||
opM(0x63, StackRead, m(ADC))
|
||||
opM(0x64, DirectWrite, Z)
|
||||
opM(0x65, DirectRead, m(ADC))
|
||||
opM(0x66, DirectModify, m(ROR))
|
||||
opM(0x67, IndirectLongRead, m(ADC))
|
||||
opM(0x68, Pull, A)
|
||||
opM(0x69, ImmediateRead, m(ADC))
|
||||
opM(0x6a, RORImplied)
|
||||
opA(0x6b, RTL)
|
||||
opA(0x6c, JMPIndirect)
|
||||
opM(0x6d, BankRead, m(ADC))
|
||||
opM(0x6e, BankModify, m(ROR))
|
||||
opM(0x6f, LongRead, m(ADC))
|
||||
opA(0x70, Branch, VF == 1)
|
||||
opM(0x71, IndirectIndexedRead, m(ADC))
|
||||
opM(0x72, IndirectRead, m(ADC))
|
||||
opM(0x73, IndirectStackRead, m(ADC))
|
||||
opM(0x74, DirectWrite, Z, X)
|
||||
opM(0x75, DirectRead, m(ADC), X)
|
||||
opM(0x76, DirectIndexedModify, m(ROR))
|
||||
opM(0x77, IndirectLongRead, m(ADC), Y)
|
||||
opA(0x78, SetFlag, IF)
|
||||
opM(0x79, BankRead, m(ADC), Y)
|
||||
opX(0x7a, Pull, Y)
|
||||
opA(0x7b, Transfer16, D, A)
|
||||
opA(0x7c, JMPIndexedIndirect)
|
||||
opM(0x7d, BankRead, m(ADC), X)
|
||||
opM(0x7e, BankIndexedModify, m(ROR))
|
||||
opM(0x7f, LongRead, m(ADC), X)
|
||||
opA(0x80, Branch)
|
||||
opM(0x81, IndexedIndirectWrite)
|
||||
opA(0x82, BRL)
|
||||
opM(0x83, StackWrite)
|
||||
opX(0x84, DirectWrite, Y)
|
||||
opM(0x85, DirectWrite, A)
|
||||
opX(0x86, DirectWrite, X)
|
||||
opM(0x87, IndirectLongWrite)
|
||||
opX(0x88, DECImplied, Y)
|
||||
opM(0x89, BITImmediate)
|
||||
opM(0x8a, Transfer, X, A)
|
||||
opA(0x8b, PHB)
|
||||
opX(0x8c, BankWrite, Y)
|
||||
opM(0x8d, BankWrite, A)
|
||||
opX(0x8e, BankWrite, X)
|
||||
opM(0x8f, LongWrite)
|
||||
opA(0x90, Branch, CF == 0)
|
||||
opM(0x91, IndirectIndexedWrite)
|
||||
opM(0x92, IndirectWrite)
|
||||
opM(0x93, IndirectStackWrite)
|
||||
opX(0x94, DirectWrite, Y, X)
|
||||
opM(0x95, DirectWrite, A, X)
|
||||
opX(0x96, DirectWrite, X, Y)
|
||||
opM(0x97, IndirectLongWrite, Y)
|
||||
opM(0x98, Transfer, Y, A)
|
||||
opM(0x99, BankWrite, A, Y)
|
||||
opA(0x9a, TXS)
|
||||
opX(0x9b, Transfer, X, Y)
|
||||
opM(0x9c, BankWrite, Z)
|
||||
opM(0x9d, BankWrite, A, X)
|
||||
opM(0x9e, BankWrite, Z, X)
|
||||
opM(0x9f, LongWrite, X)
|
||||
opX(0xa0, ImmediateRead, x(LDY))
|
||||
opM(0xa1, IndexedIndirectRead, m(LDA))
|
||||
opX(0xa2, ImmediateRead, x(LDX))
|
||||
opM(0xa3, StackRead, m(LDA))
|
||||
opX(0xa4, DirectRead, x(LDY))
|
||||
opM(0xa5, DirectRead, m(LDA))
|
||||
opX(0xa6, DirectRead, x(LDX))
|
||||
opM(0xa7, IndirectLongRead, m(LDA))
|
||||
opX(0xa8, Transfer, A, Y)
|
||||
opM(0xa9, ImmediateRead, m(LDA))
|
||||
opX(0xaa, Transfer, A, X)
|
||||
opA(0xab, PLB)
|
||||
opX(0xac, BankRead, x(LDY))
|
||||
opM(0xad, BankRead, m(LDA))
|
||||
opX(0xae, BankRead, x(LDX))
|
||||
opM(0xaf, LongRead, m(LDA))
|
||||
opA(0xb0, Branch, CF == 1)
|
||||
opM(0xb1, IndirectIndexedRead, m(LDA))
|
||||
opM(0xb2, IndirectRead, m(LDA))
|
||||
opM(0xb3, IndirectStackRead, m(LDA))
|
||||
opX(0xb4, DirectRead, x(LDY), X)
|
||||
opM(0xb5, DirectRead, m(LDA), X)
|
||||
opX(0xb6, DirectRead, x(LDX), Y)
|
||||
opM(0xb7, IndirectLongRead, m(LDA), Y)
|
||||
opA(0xb8, ClearFlag, VF)
|
||||
opM(0xb9, BankRead, m(LDA), Y)
|
||||
opX(0xba, TSX)
|
||||
opX(0xbb, Transfer, Y, X)
|
||||
opX(0xbc, BankRead, x(LDY), X)
|
||||
opM(0xbd, BankRead, m(LDA), X)
|
||||
opX(0xbe, BankRead, x(LDX), Y)
|
||||
opM(0xbf, LongRead, m(LDA), X)
|
||||
opX(0xc0, ImmediateRead, x(CPY))
|
||||
opM(0xc1, IndexedIndirectRead, m(CMP))
|
||||
opA(0xc2, REP)
|
||||
opM(0xc3, StackRead, m(CMP))
|
||||
opX(0xc4, DirectRead, x(CPY))
|
||||
opM(0xc5, DirectRead, m(CMP))
|
||||
opM(0xc6, DirectModify, m(DEC))
|
||||
opM(0xc7, IndirectLongRead, m(CMP))
|
||||
opX(0xc8, INCImplied, Y)
|
||||
opM(0xc9, ImmediateRead, m(CMP))
|
||||
opX(0xca, DECImplied, X)
|
||||
opA(0xcb, WAI)
|
||||
opX(0xcc, BankRead, x(CPY))
|
||||
opM(0xcd, BankRead, m(CMP))
|
||||
opM(0xce, BankModify, m(DEC))
|
||||
opM(0xcf, LongRead, m(CMP))
|
||||
opA(0xd0, Branch, ZF == 0)
|
||||
opM(0xd1, IndirectIndexedRead, m(CMP))
|
||||
opM(0xd2, IndirectRead, m(CMP))
|
||||
opM(0xd3, IndirectStackRead, m(CMP))
|
||||
opA(0xd4, PEI)
|
||||
opM(0xd5, DirectRead, m(CMP), X)
|
||||
opM(0xd6, DirectIndexedModify, m(DEC))
|
||||
opM(0xd7, IndirectLongRead, m(CMP), Y)
|
||||
opA(0xd8, ClearFlag, DF)
|
||||
opM(0xd9, BankRead, m(CMP), Y)
|
||||
opX(0xda, Push, X)
|
||||
opA(0xdb, STP)
|
||||
opA(0xdc, JMPIndirectLong)
|
||||
opM(0xdd, BankRead, m(CMP), X)
|
||||
opM(0xde, BankIndexedModify, m(DEC))
|
||||
opM(0xdf, LongRead, m(CMP), X)
|
||||
opX(0xe0, ImmediateRead, x(CPX))
|
||||
opM(0xe1, IndexedIndirectRead, m(SBC))
|
||||
opA(0xe2, SEP)
|
||||
opM(0xe3, StackRead, m(SBC))
|
||||
opX(0xe4, DirectRead, x(CPX))
|
||||
opM(0xe5, DirectRead, m(SBC))
|
||||
opM(0xe6, DirectModify, m(INC))
|
||||
opM(0xe7, IndirectLongRead, m(SBC))
|
||||
opX(0xe8, INCImplied, X)
|
||||
opM(0xe9, ImmediateRead, m(SBC))
|
||||
opA(0xea, NOP)
|
||||
opA(0xeb, XBA)
|
||||
opX(0xec, BankRead, x(CPX))
|
||||
opM(0xed, BankRead, m(SBC))
|
||||
opM(0xee, BankModify, m(INC))
|
||||
opM(0xef, LongRead, m(SBC))
|
||||
opA(0xf0, Branch, ZF == 1)
|
||||
opM(0xf1, IndirectIndexedRead, m(SBC))
|
||||
opM(0xf2, IndirectRead, m(SBC))
|
||||
opM(0xf3, IndirectStackRead, m(SBC))
|
||||
opA(0xf4, PEA)
|
||||
opM(0xf5, DirectRead, m(SBC), X)
|
||||
opM(0xf6, DirectIndexedModify, m(INC))
|
||||
opM(0xf7, IndirectLongRead, m(SBC), Y)
|
||||
opA(0xf8, SetFlag, DF)
|
||||
opM(0xf9, BankRead, m(SBC), Y)
|
||||
opX(0xfa, Pull, X)
|
||||
opA(0xfb, XCE)
|
||||
opA(0xfc, JSRIndexedIndirect)
|
||||
opM(0xfd, BankRead, m(SBC), X)
|
||||
opM(0xfe, BankIndexedModify, m(INC))
|
||||
opM(0xff, LongRead, m(SBC), X)
|
||||
}
|
||||
|
||||
#undef opA
|
||||
#undef opM
|
||||
#undef opX
|
||||
#undef m
|
||||
#undef x
|
||||
}
|
|
@ -1,12 +1,23 @@
|
|||
auto R65816::op_nop() {
|
||||
auto WDC65816::instructionBITImmediate8() -> void {
|
||||
L uint8 immediate = fetch();
|
||||
ZF = (immediate & AL) == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::instructionBITImmediate16() -> void {
|
||||
uint16 immediate = fetch();
|
||||
L immediate |= fetch() << 8;
|
||||
ZF = (immediate & AW) == 0;
|
||||
}
|
||||
|
||||
auto WDC65816::instructionNOP() -> void {
|
||||
L idleIRQ();
|
||||
}
|
||||
|
||||
auto R65816::op_wdm() {
|
||||
L readPC();
|
||||
auto WDC65816::instructionWDM() -> void {
|
||||
L fetch();
|
||||
}
|
||||
|
||||
auto R65816::op_xba() {
|
||||
auto WDC65816::instructionXBA() -> void {
|
||||
idle();
|
||||
L idle();
|
||||
r.a.w = r.a.w >> 8 | r.a.w << 8;
|
||||
|
@ -14,12 +25,12 @@ L idle();
|
|||
r.p.z = (r.a.l == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_move_b(int adjust) {
|
||||
dp = readPC();
|
||||
sp = readPC();
|
||||
auto WDC65816::instructionBlockMove8(int adjust) -> void {
|
||||
dp = fetch();
|
||||
sp = fetch();
|
||||
r.db = dp;
|
||||
rd.l = readLong(sp << 16 | r.x.w);
|
||||
writeLong(dp << 16 | r.y.w, rd.l);
|
||||
rd.l = read(sp << 16 | r.x.w);
|
||||
write(dp << 16 | r.y.w, rd.l);
|
||||
idle();
|
||||
r.x.l += adjust;
|
||||
r.y.l += adjust;
|
||||
|
@ -27,12 +38,12 @@ L idle();
|
|||
if(r.a.w--) r.pc.w -= 3;
|
||||
}
|
||||
|
||||
auto R65816::op_move_w(int adjust) {
|
||||
dp = readPC();
|
||||
sp = readPC();
|
||||
auto WDC65816::instructionBlockMove16(int adjust) -> void {
|
||||
dp = fetch();
|
||||
sp = fetch();
|
||||
r.db = dp;
|
||||
rd.l = readLong(sp << 16 | r.x.w);
|
||||
writeLong(dp << 16 | r.y.w, rd.l);
|
||||
rd.l = read(sp << 16 | r.x.w);
|
||||
write(dp << 16 | r.y.w, rd.l);
|
||||
idle();
|
||||
r.x.w += adjust;
|
||||
r.y.w += adjust;
|
||||
|
@ -40,27 +51,27 @@ L idle();
|
|||
if(r.a.w--) r.pc.w -= 3;
|
||||
}
|
||||
|
||||
auto R65816::op_interrupt(uint16 vector) {
|
||||
readPC();
|
||||
N writeSP(r.pc.b);
|
||||
writeSP(r.pc.h);
|
||||
writeSP(r.pc.l);
|
||||
writeSP(r.p);
|
||||
r.pc.l = readLong(vector + 0);
|
||||
r.p.i = 1;
|
||||
r.p.d = 0;
|
||||
L r.pc.h = readLong(vector + 1);
|
||||
r.pc.b = 0x00;
|
||||
auto WDC65816::instructionInterrupt(uint16 vector) -> void {
|
||||
fetch();
|
||||
N push(PCB);
|
||||
push(PCH);
|
||||
push(PCL);
|
||||
push(P);
|
||||
IF = 1;
|
||||
DF = 0;
|
||||
PCL = read(vector++);
|
||||
L PCH = read(vector++);
|
||||
PCB = 0x00;
|
||||
}
|
||||
|
||||
auto R65816::op_stp() -> void {
|
||||
auto WDC65816::instructionSTP() -> void {
|
||||
r.stp = true;
|
||||
while(r.stp && !synchronizing()) {
|
||||
L idle();
|
||||
}
|
||||
}
|
||||
|
||||
auto R65816::op_wai() -> void {
|
||||
auto WDC65816::instructionWAI() -> void {
|
||||
r.wai = true;
|
||||
while(r.wai && !synchronizing()) {
|
||||
L idle();
|
||||
|
@ -68,7 +79,7 @@ L idle();
|
|||
idle();
|
||||
}
|
||||
|
||||
auto R65816::op_xce() {
|
||||
auto WDC65816::instructionXCE() -> void {
|
||||
L idleIRQ();
|
||||
bool carry = r.p.c;
|
||||
r.p.c = r.e;
|
||||
|
@ -82,139 +93,144 @@ L idleIRQ();
|
|||
}
|
||||
}
|
||||
|
||||
auto R65816::op_set_flag(uint bit) {
|
||||
auto WDC65816::instructionSetFlag(bool& flag) -> void {
|
||||
L idleIRQ();
|
||||
r.p |= 1 << bit;
|
||||
flag = 1;
|
||||
}
|
||||
|
||||
auto R65816::op_clear_flag(uint bit) {
|
||||
auto WDC65816::instructionClearFlag(bool& flag) -> void {
|
||||
L idleIRQ();
|
||||
r.p &= ~(1 << bit);
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
auto R65816::op_pflag(bool mode) {
|
||||
rd.l = readPC();
|
||||
auto WDC65816::instructionREP() -> void {
|
||||
auto data = fetch();
|
||||
L idle();
|
||||
r.p = (mode ? r.p | rd.l : r.p & ~rd.l);
|
||||
E r.p.m = 1, r.p.x = 1;
|
||||
if(r.p.x) {
|
||||
r.x.h = 0x00;
|
||||
r.y.h = 0x00;
|
||||
}
|
||||
P = P & ~data;
|
||||
E XF = 1, MF = 1;
|
||||
if(XF) XH = 0x00, YH = 0x00;
|
||||
}
|
||||
|
||||
auto R65816::op_transfer_b(Reg16& from, Reg16& to) {
|
||||
auto WDC65816::instructionSEP() -> void {
|
||||
auto data = fetch();
|
||||
L idle();
|
||||
P = P | data;
|
||||
E XF = 1, MF = 1;
|
||||
if(XF) XH = 0x00, YH = 0x00;
|
||||
}
|
||||
|
||||
auto WDC65816::instructionTransfer8(uint16& from, uint16& to) -> void {
|
||||
L idleIRQ();
|
||||
to.l = from.l;
|
||||
r.p.n = (to.l & 0x80);
|
||||
r.p.z = (to.l == 0);
|
||||
LO(to) = LO(from);
|
||||
r.p.n = (LO(to) & 0x80);
|
||||
r.p.z = (LO(to) == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_transfer_w(Reg16& from, Reg16& to) {
|
||||
auto WDC65816::instructionTransfer16(uint16& from, uint16& to) -> void {
|
||||
L idleIRQ();
|
||||
to.w = from.w;
|
||||
r.p.n = (to.w & 0x8000);
|
||||
r.p.z = (to.w == 0);
|
||||
to = from;
|
||||
r.p.n = (to & 0x8000);
|
||||
r.p.z = (to == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_tcs() {
|
||||
auto WDC65816::instructionTCS() -> void {
|
||||
L idleIRQ();
|
||||
r.s.w = r.a.w;
|
||||
E r.s.h = 0x01;
|
||||
}
|
||||
|
||||
auto R65816::op_tsx_b() {
|
||||
auto WDC65816::instructionTSX8() -> void {
|
||||
L idleIRQ();
|
||||
r.x.l = r.s.l;
|
||||
r.p.n = (r.x.l & 0x80);
|
||||
r.p.z = (r.x.l == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_tsx_w() {
|
||||
auto WDC65816::instructionTSX16() -> void {
|
||||
L idleIRQ();
|
||||
r.x.w = r.s.w;
|
||||
r.p.n = (r.x.w & 0x8000);
|
||||
r.p.z = (r.x.w == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_txs() {
|
||||
auto WDC65816::instructionTXS() -> void {
|
||||
L idleIRQ();
|
||||
E r.s.l = r.x.l;
|
||||
N r.s.w = r.x.w;
|
||||
}
|
||||
|
||||
auto R65816::op_push_b(Reg16& reg) {
|
||||
auto WDC65816::instructionPush8(uint16& reg) -> void {
|
||||
idle();
|
||||
L writeSP(reg.l);
|
||||
L push(reg);
|
||||
}
|
||||
|
||||
auto R65816::op_push_w(Reg16& reg) {
|
||||
auto WDC65816::instructionPush16(uint16& reg) -> void {
|
||||
idle();
|
||||
writeSP(reg.h);
|
||||
L writeSP(reg.l);
|
||||
push(reg >> 8);
|
||||
L push(reg >> 0);
|
||||
}
|
||||
|
||||
auto R65816::op_phd() {
|
||||
auto WDC65816::instructionPHD() -> void {
|
||||
idle();
|
||||
writeSPn(r.d.h);
|
||||
L writeSPn(r.d.l);
|
||||
pushN(r.d.h);
|
||||
L pushN(r.d.l);
|
||||
E r.s.h = 0x01;
|
||||
}
|
||||
|
||||
auto R65816::op_phb() {
|
||||
auto WDC65816::instructionPHB() -> void {
|
||||
idle();
|
||||
L writeSP(r.db);
|
||||
L push(r.db);
|
||||
}
|
||||
|
||||
auto R65816::op_phk() {
|
||||
auto WDC65816::instructionPHK() -> void {
|
||||
idle();
|
||||
L writeSP(r.pc.b);
|
||||
L push(r.pc.b);
|
||||
}
|
||||
|
||||
auto R65816::op_php() {
|
||||
auto WDC65816::instructionPHP() -> void {
|
||||
idle();
|
||||
L writeSP(r.p);
|
||||
L push(r.p);
|
||||
}
|
||||
|
||||
auto R65816::op_pull_b(Reg16& reg) {
|
||||
auto WDC65816::instructionPull8(uint16& reg) -> void {
|
||||
idle();
|
||||
idle();
|
||||
L reg.l = readSP();
|
||||
r.p.n = (reg.l & 0x80);
|
||||
r.p.z = (reg.l == 0);
|
||||
L LO(reg) = pull();
|
||||
r.p.n = (LO(reg) & 0x80);
|
||||
r.p.z = (LO(reg) == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_pull_w(Reg16& reg) {
|
||||
auto WDC65816::instructionPull16(uint16& reg) -> void {
|
||||
idle();
|
||||
idle();
|
||||
reg.l = readSP();
|
||||
L reg.h = readSP();
|
||||
r.p.n = (reg.w & 0x8000);
|
||||
r.p.z = (reg.w == 0);
|
||||
LO(reg) = pull();
|
||||
L HI(reg) = pull();
|
||||
r.p.n = (reg & 0x8000);
|
||||
r.p.z = (reg == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_pld() {
|
||||
auto WDC65816::instructionPLD() -> void {
|
||||
idle();
|
||||
idle();
|
||||
r.d.l = readSPn();
|
||||
L r.d.h = readSPn();
|
||||
r.d.l = pullN();
|
||||
L r.d.h = pullN();
|
||||
r.p.n = (r.d.w & 0x8000);
|
||||
r.p.z = (r.d.w == 0);
|
||||
E r.s.h = 0x01;
|
||||
}
|
||||
|
||||
auto R65816::op_plb() {
|
||||
auto WDC65816::instructionPLB() -> void {
|
||||
idle();
|
||||
idle();
|
||||
L r.db = readSP();
|
||||
L r.db = pull();
|
||||
r.p.n = (r.db & 0x80);
|
||||
r.p.z = (r.db == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_plp() {
|
||||
auto WDC65816::instructionPLP() -> void {
|
||||
idle();
|
||||
idle();
|
||||
L r.p = readSP();
|
||||
L r.p = pull();
|
||||
E r.p.m = 1, r.p.x = 1;
|
||||
if(r.p.x) {
|
||||
r.x.h = 0x00;
|
||||
|
@ -222,30 +238,30 @@ E r.p.m = 1, r.p.x = 1;
|
|||
}
|
||||
}
|
||||
|
||||
auto R65816::op_pea() {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
writeSPn(aa.h);
|
||||
L writeSPn(aa.l);
|
||||
auto WDC65816::instructionPEA() -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
pushN(aa.h);
|
||||
L pushN(aa.l);
|
||||
E r.s.h = 0x01;
|
||||
}
|
||||
|
||||
auto R65816::op_pei() {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionPEI() -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDPn(dp + 0);
|
||||
aa.h = readDPn(dp + 1);
|
||||
writeSPn(aa.h);
|
||||
L writeSPn(aa.l);
|
||||
aa.l = readDirectN(dp + 0);
|
||||
aa.h = readDirectN(dp + 1);
|
||||
pushN(aa.h);
|
||||
L pushN(aa.l);
|
||||
E r.s.h = 0x01;
|
||||
}
|
||||
|
||||
auto R65816::op_per() {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
auto WDC65816::instructionPER() -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
idle();
|
||||
rd.w = r.pc.d + (int16)aa.w;
|
||||
writeSPn(rd.h);
|
||||
L writeSPn(rd.l);
|
||||
pushN(rd.h);
|
||||
L pushN(rd.l);
|
||||
E r.s.h = 0x01;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
auto WDC65816::instructionINCImplied8(uint16& reg) -> void {
|
||||
L idleIRQ();
|
||||
LO(reg)++;
|
||||
r.p.n = (LO(reg) & 0x80);
|
||||
r.p.z = (LO(reg) == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionINCImplied16(uint16& reg) -> void {
|
||||
L idleIRQ();
|
||||
reg++;
|
||||
r.p.n = (reg & 0x8000);
|
||||
r.p.z = (reg == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDECImplied8(uint16& reg) -> void {
|
||||
L idleIRQ();
|
||||
LO(reg)--;
|
||||
r.p.n = (LO(reg) & 0x80);
|
||||
r.p.z = (LO(reg) == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDECImplied16(uint16& reg) -> void {
|
||||
L idleIRQ();
|
||||
reg--;
|
||||
r.p.n = (reg & 0x8000);
|
||||
r.p.z = (reg == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionASLImplied8() -> void {
|
||||
L idleIRQ();
|
||||
r.p.c = (r.a.l & 0x80);
|
||||
r.a.l <<= 1;
|
||||
r.p.n = (r.a.l & 0x80);
|
||||
r.p.z = (r.a.l == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionASLImplied16() -> void {
|
||||
L idleIRQ();
|
||||
r.p.c = (r.a.w & 0x8000);
|
||||
r.a.w <<= 1;
|
||||
r.p.n = (r.a.w & 0x8000);
|
||||
r.p.z = (r.a.w == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionLSRImplied8() -> void {
|
||||
L idleIRQ();
|
||||
r.p.c = (r.a.l & 0x01);
|
||||
r.a.l >>= 1;
|
||||
r.p.n = (r.a.l & 0x80);
|
||||
r.p.z = (r.a.l == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionLSRImplied16() -> void {
|
||||
L idleIRQ();
|
||||
r.p.c = (r.a.w & 0x0001);
|
||||
r.a.w >>= 1;
|
||||
r.p.n = (r.a.w & 0x8000);
|
||||
r.p.z = (r.a.w == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionROLImplied8() -> void {
|
||||
L idleIRQ();
|
||||
bool carry = r.p.c;
|
||||
r.p.c = (r.a.l & 0x80);
|
||||
r.a.l = (r.a.l << 1) | carry;
|
||||
r.p.n = (r.a.l & 0x80);
|
||||
r.p.z = (r.a.l == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionROLImplied16() -> void {
|
||||
L idleIRQ();
|
||||
bool carry = r.p.c;
|
||||
r.p.c = (r.a.w & 0x8000);
|
||||
r.a.w = (r.a.w << 1) | carry;
|
||||
r.p.n = (r.a.w & 0x8000);
|
||||
r.p.z = (r.a.w == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionRORImplied8() -> void {
|
||||
L idleIRQ();
|
||||
bool carry = r.p.c;
|
||||
r.p.c = (r.a.l & 0x01);
|
||||
r.a.l = (carry << 7) | (r.a.l >> 1);
|
||||
r.p.n = (r.a.l & 0x80);
|
||||
r.p.z = (r.a.l == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionRORImplied16() -> void {
|
||||
L idleIRQ();
|
||||
bool carry = r.p.c;
|
||||
r.p.c = (r.a.w & 0x0001);
|
||||
r.a.w = (carry << 15) | (r.a.w >> 1);
|
||||
r.p.n = (r.a.w & 0x8000);
|
||||
r.p.z = (r.a.w == 0);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionBankModify8(fp op) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
rd.l = readBank(aa.w);
|
||||
idle();
|
||||
call(op);
|
||||
L writeBank(aa.w, rd.l);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionBankModify16(fp op) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
rd.l = readBank(aa.w + 0);
|
||||
rd.h = readBank(aa.w + 1);
|
||||
idle();
|
||||
call(op);
|
||||
writeBank(aa.w + 1, rd.h);
|
||||
L writeBank(aa.w + 0, rd.l);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionBankIndexedModify8(fp op) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
idle();
|
||||
rd.l = readBank(aa.w + r.x.w);
|
||||
idle();
|
||||
call(op);
|
||||
L writeBank(aa.w + r.x.w, rd.l);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionBankIndexedModify16(fp op) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
idle();
|
||||
rd.l = readBank(aa.w + r.x.w + 0);
|
||||
rd.h = readBank(aa.w + r.x.w + 1);
|
||||
idle();
|
||||
call(op);
|
||||
writeBank(aa.w + r.x.w + 1, rd.h);
|
||||
L writeBank(aa.w + r.x.w + 0, rd.l);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDirectModify8(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
rd.l = readDirect(dp);
|
||||
idle();
|
||||
call(op);
|
||||
L writeDirect(dp, rd.l);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDirectModify16(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
rd.l = readDirect(dp + 0);
|
||||
rd.h = readDirect(dp + 1);
|
||||
idle();
|
||||
call(op);
|
||||
writeDirect(dp + 1, rd.h);
|
||||
L writeDirect(dp + 0, rd.l);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDirectIndexedModify8(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
rd.l = readDirect(dp + r.x.w);
|
||||
idle();
|
||||
call(op);
|
||||
L writeDirect(dp + r.x.w, rd.l);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDirectIndexedModify16(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
rd.l = readDirect(dp + r.x.w + 0);
|
||||
rd.h = readDirect(dp + r.x.w + 1);
|
||||
idle();
|
||||
call(op);
|
||||
writeDirect(dp + r.x.w + 1, rd.h);
|
||||
L writeDirect(dp + r.x.w + 0, rd.l);
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
auto R65816::op_branch(bool flag, bool value) {
|
||||
if(flag != value) {
|
||||
L rd.l = readPC();
|
||||
auto WDC65816::instructionBranch(bool take) -> void {
|
||||
if(!take) {
|
||||
L rd.l = fetch();
|
||||
} else {
|
||||
rd.l = readPC();
|
||||
rd.l = fetch();
|
||||
aa.w = r.pc.d + (int8)rd.l;
|
||||
idle6(aa.w);
|
||||
L idle();
|
||||
|
@ -10,128 +10,120 @@ L idle();
|
|||
}
|
||||
}
|
||||
|
||||
auto R65816::op_bra() {
|
||||
rd.l = readPC();
|
||||
aa.w = r.pc.d + (int8)rd.l;
|
||||
idle6(aa.w);
|
||||
L idle();
|
||||
r.pc.w = aa.w;
|
||||
}
|
||||
|
||||
auto R65816::op_brl() {
|
||||
rd.l = readPC();
|
||||
rd.h = readPC();
|
||||
auto WDC65816::instructionBRL() -> void {
|
||||
rd.l = fetch();
|
||||
rd.h = fetch();
|
||||
L idle();
|
||||
r.pc.w = r.pc.d + (int16)rd.w;
|
||||
}
|
||||
|
||||
auto R65816::op_jmp_addr() {
|
||||
rd.l = readPC();
|
||||
L rd.h = readPC();
|
||||
auto WDC65816::instructionJMPShort() -> void {
|
||||
rd.l = fetch();
|
||||
L rd.h = fetch();
|
||||
r.pc.w = rd.w;
|
||||
}
|
||||
|
||||
auto R65816::op_jmp_long() {
|
||||
rd.l = readPC();
|
||||
rd.h = readPC();
|
||||
L rd.b = readPC();
|
||||
auto WDC65816::instructionJMPLong() -> void {
|
||||
rd.l = fetch();
|
||||
rd.h = fetch();
|
||||
L rd.b = fetch();
|
||||
r.pc.d = rd.d;
|
||||
}
|
||||
|
||||
auto R65816::op_jmp_iaddr() {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
rd.l = readAddr(aa.w + 0);
|
||||
L rd.h = readAddr(aa.w + 1);
|
||||
auto WDC65816::instructionJMPIndirect() -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
rd.l = read(uint16(aa.w + 0));
|
||||
L rd.h = read(uint16(aa.w + 1));
|
||||
r.pc.w = rd.w;
|
||||
}
|
||||
|
||||
auto R65816::op_jmp_iaddrx() {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
auto WDC65816::instructionJMPIndexedIndirect() -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
idle();
|
||||
rd.l = readPB(aa.w + r.x.w + 0);
|
||||
L rd.h = readPB(aa.w + r.x.w + 1);
|
||||
rd.l = read(PCB << 16 | uint16(aa.w + r.x.w + 0));
|
||||
L rd.h = read(PCB << 16 | uint16(aa.w + r.x.w + 1));
|
||||
r.pc.w = rd.w;
|
||||
}
|
||||
|
||||
auto R65816::op_jmp_iladdr() {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
rd.l = readAddr(aa.w + 0);
|
||||
rd.h = readAddr(aa.w + 1);
|
||||
L rd.b = readAddr(aa.w + 2);
|
||||
auto WDC65816::instructionJMPIndirectLong() -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
rd.l = read(uint16(aa.w + 0));
|
||||
rd.h = read(uint16(aa.w + 1));
|
||||
L rd.b = read(uint16(aa.w + 2));
|
||||
r.pc.d = rd.d;
|
||||
}
|
||||
|
||||
auto R65816::op_jsr_addr() {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
auto WDC65816::instructionJSRShort() -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
idle();
|
||||
r.pc.w--;
|
||||
writeSP(r.pc.h);
|
||||
L writeSP(r.pc.l);
|
||||
push(r.pc.h);
|
||||
L push(r.pc.l);
|
||||
r.pc.w = aa.w;
|
||||
}
|
||||
|
||||
auto R65816::op_jsr_long() {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
writeSPn(r.pc.b);
|
||||
auto WDC65816::instructionJSRLong() -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
pushN(r.pc.b);
|
||||
idle();
|
||||
aa.b = readPC();
|
||||
aa.b = fetch();
|
||||
r.pc.w--;
|
||||
writeSPn(r.pc.h);
|
||||
L writeSPn(r.pc.l);
|
||||
pushN(r.pc.h);
|
||||
L pushN(r.pc.l);
|
||||
r.pc.d = aa.d;
|
||||
E r.s.h = 0x01;
|
||||
}
|
||||
|
||||
auto R65816::op_jsr_iaddrx() {
|
||||
aa.l = readPC();
|
||||
writeSPn(r.pc.h);
|
||||
writeSPn(r.pc.l);
|
||||
aa.h = readPC();
|
||||
auto WDC65816::instructionJSRIndexedIndirect() -> void {
|
||||
aa.l = fetch();
|
||||
pushN(r.pc.h);
|
||||
pushN(r.pc.l);
|
||||
aa.h = fetch();
|
||||
idle();
|
||||
rd.l = readPB(aa.w + r.x.w + 0);
|
||||
L rd.h = readPB(aa.w + r.x.w + 1);
|
||||
rd.l = read(PCB << 16 | uint16(aa.w + r.x.w + 0));
|
||||
L rd.h = read(PCB << 16 | uint16(aa.w + r.x.w + 1));
|
||||
r.pc.w = rd.w;
|
||||
E r.s.h = 0x01;
|
||||
}
|
||||
|
||||
auto R65816::op_rti() {
|
||||
auto WDC65816::instructionRTI() -> void {
|
||||
idle();
|
||||
idle();
|
||||
r.p = readSP();
|
||||
r.p = pull();
|
||||
E r.p.m = 1, r.p.x = 1;
|
||||
if(r.p.x) {
|
||||
r.x.h = 0x00;
|
||||
r.y.h = 0x00;
|
||||
}
|
||||
r.pc.l = readSP();
|
||||
r.pc.l = pull();
|
||||
if(r.e) {
|
||||
L r.pc.h = readSP();
|
||||
L r.pc.h = pull();
|
||||
} else {
|
||||
r.pc.h = readSP();
|
||||
L r.pc.b = readSP();
|
||||
r.pc.h = pull();
|
||||
L r.pc.b = pull();
|
||||
}
|
||||
}
|
||||
|
||||
auto R65816::op_rts() {
|
||||
auto WDC65816::instructionRTS() -> void {
|
||||
idle();
|
||||
idle();
|
||||
rd.l = readSP();
|
||||
rd.h = readSP();
|
||||
rd.l = pull();
|
||||
rd.h = pull();
|
||||
L idle();
|
||||
r.pc.w = ++rd.w;
|
||||
}
|
||||
|
||||
auto R65816::op_rtl() {
|
||||
auto WDC65816::instructionRTL() -> void {
|
||||
idle();
|
||||
idle();
|
||||
rd.l = readSPn();
|
||||
rd.h = readSPn();
|
||||
L rd.b = readSPn();
|
||||
rd.l = pullN();
|
||||
rd.h = pullN();
|
||||
L rd.b = pullN();
|
||||
r.pc.b = rd.b;
|
||||
r.pc.w = ++rd.w;
|
||||
E r.s.h = 0x01;
|
||||
|
|
|
@ -1,275 +1,209 @@
|
|||
auto R65816::op_read_const_b(fp op) {
|
||||
L rd.l = readPC();
|
||||
auto WDC65816::instructionImmediateRead8(fp op) -> void {
|
||||
L rd.l = fetch();
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_const_w(fp op) {
|
||||
rd.l = readPC();
|
||||
L rd.h = readPC();
|
||||
auto WDC65816::instructionImmediateRead16(fp op) -> void {
|
||||
rd.l = fetch();
|
||||
L rd.h = fetch();
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_bit_const_b() {
|
||||
L rd.l = readPC();
|
||||
r.p.z = ((rd.l & r.a.l) == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_read_bit_const_w() {
|
||||
rd.l = readPC();
|
||||
L rd.h = readPC();
|
||||
r.p.z = ((rd.w & r.a.w) == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_read_addr_b(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
L rd.l = readDB(aa.w);
|
||||
auto WDC65816::instructionBankRead8(fp op) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
L rd.l = readBank(aa.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_addr_w(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
rd.l = readDB(aa.w + 0);
|
||||
L rd.h = readDB(aa.w + 1);
|
||||
auto WDC65816::instructionBankRead16(fp op) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
rd.l = readBank(aa.w + 0);
|
||||
L rd.h = readBank(aa.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_addrx_b(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
idle4(aa.w, aa.w + r.x.w);
|
||||
L rd.l = readDB(aa.w + r.x.w);
|
||||
auto WDC65816::instructionBankRead8(fp op, uint16 index) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
idle4(aa.w, aa.w + index);
|
||||
L rd.l = readBank(aa.w + index);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_addrx_w(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
idle4(aa.w, aa.w + r.x.w);
|
||||
rd.l = readDB(aa.w + r.x.w + 0);
|
||||
L rd.h = readDB(aa.w + r.x.w + 1);
|
||||
auto WDC65816::instructionBankRead16(fp op, uint16 index) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
idle4(aa.w, aa.w + index);
|
||||
rd.l = readBank(aa.w + index + 0);
|
||||
L rd.h = readBank(aa.w + index + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_addry_b(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
auto WDC65816::instructionLongRead8(fp op, uint16 index) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
aa.b = fetch();
|
||||
L rd.l = read(aa.d + index);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionLongRead16(fp op, uint16 index) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
aa.b = fetch();
|
||||
rd.l = read(aa.d + index + 0);
|
||||
L rd.h = read(aa.d + index + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDirectRead8(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
L rd.l = readDirect(dp);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDirectRead16(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
rd.l = readDirect(dp + 0);
|
||||
L rd.h = readDirect(dp + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDirectRead8(fp op, uint16 index) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
L rd.l = readDirect(dp + index);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionDirectRead16(fp op, uint16 index) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
rd.l = readDirect(dp + index + 0);
|
||||
L rd.h = readDirect(dp + index + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionIndirectRead8(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDirect(dp + 0);
|
||||
aa.h = readDirect(dp + 1);
|
||||
L rd.l = readBank(aa.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionIndirectRead16(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDirect(dp + 0);
|
||||
aa.h = readDirect(dp + 1);
|
||||
rd.l = readBank(aa.w + 0);
|
||||
L rd.h = readBank(aa.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionIndexedIndirectRead8(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
aa.l = readDirect(dp + r.x.w + 0);
|
||||
aa.h = readDirect(dp + r.x.w + 1);
|
||||
L rd.l = readBank(aa.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionIndexedIndirectRead16(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
aa.l = readDirect(dp + r.x.w + 0);
|
||||
aa.h = readDirect(dp + r.x.w + 1);
|
||||
rd.l = readBank(aa.w + 0);
|
||||
L rd.h = readBank(aa.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto WDC65816::instructionIndirectIndexedRead8(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDirect(dp + 0);
|
||||
aa.h = readDirect(dp + 1);
|
||||
idle4(aa.w, aa.w + r.y.w);
|
||||
L rd.l = readDB(aa.w + r.y.w);
|
||||
L rd.l = readBank(aa.w + r.y.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_addry_w(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
auto WDC65816::instructionIndirectIndexedRead16(fp op) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDirect(dp + 0);
|
||||
aa.h = readDirect(dp + 1);
|
||||
idle4(aa.w, aa.w + r.y.w);
|
||||
rd.l = readDB(aa.w + r.y.w + 0);
|
||||
L rd.h = readDB(aa.w + r.y.w + 1);
|
||||
rd.l = readBank(aa.w + r.y.w + 0);
|
||||
L rd.h = readBank(aa.w + r.y.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_long_b(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
aa.b = readPC();
|
||||
L rd.l = readLong(aa.d);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_long_w(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
aa.b = readPC();
|
||||
rd.l = readLong(aa.d + 0);
|
||||
L rd.h = readLong(aa.d + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_longx_b(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
aa.b = readPC();
|
||||
L rd.l = readLong(aa.d + r.x.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_longx_w(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
aa.b = readPC();
|
||||
rd.l = readLong(aa.d + r.x.w + 0);
|
||||
L rd.h = readLong(aa.d + r.x.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_dp_b(fp op) {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndirectLongRead8(fp op, uint16 index) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
L rd.l = readDP(dp);
|
||||
aa.l = readDirectN(dp + 0);
|
||||
aa.h = readDirectN(dp + 1);
|
||||
aa.b = readDirectN(dp + 2);
|
||||
L rd.l = read(aa.d + index);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_dp_w(fp op) {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndirectLongRead16(fp op, uint16 index) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
rd.l = readDP(dp + 0);
|
||||
L rd.h = readDP(dp + 1);
|
||||
aa.l = readDirectN(dp + 0);
|
||||
aa.h = readDirectN(dp + 1);
|
||||
aa.b = readDirectN(dp + 2);
|
||||
rd.l = read(aa.d + index + 0);
|
||||
L rd.h = read(aa.d + index + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_dpr_b(fp op, Reg16& reg) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
auto WDC65816::instructionStackRead8(fp op) -> void {
|
||||
sp = fetch();
|
||||
idle();
|
||||
L rd.l = readDP(dp + reg.w);
|
||||
L rd.l = readStack(sp);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_dpr_w(fp op, Reg16& reg) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
auto WDC65816::instructionStackRead16(fp op) -> void {
|
||||
sp = fetch();
|
||||
idle();
|
||||
rd.l = readDP(dp + reg.w + 0);
|
||||
L rd.h = readDP(dp + reg.w + 1);
|
||||
rd.l = readStack(sp + 0);
|
||||
L rd.h = readStack(sp + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_idp_b(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDP(dp + 0);
|
||||
aa.h = readDP(dp + 1);
|
||||
L rd.l = readDB(aa.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_idp_w(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDP(dp + 0);
|
||||
aa.h = readDP(dp + 1);
|
||||
rd.l = readDB(aa.w + 0);
|
||||
L rd.h = readDB(aa.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_idpx_b(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
auto WDC65816::instructionIndirectStackRead8(fp op) -> void {
|
||||
sp = fetch();
|
||||
idle();
|
||||
aa.l = readDP(dp + r.x.w + 0);
|
||||
aa.h = readDP(dp + r.x.w + 1);
|
||||
L rd.l = readDB(aa.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_idpx_w(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readStack(sp + 0);
|
||||
aa.h = readStack(sp + 1);
|
||||
idle();
|
||||
aa.l = readDP(dp + r.x.w + 0);
|
||||
aa.h = readDP(dp + r.x.w + 1);
|
||||
rd.l = readDB(aa.w + 0);
|
||||
L rd.h = readDB(aa.w + 1);
|
||||
L rd.l = readBank(aa.w + r.y.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_idpy_b(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDP(dp + 0);
|
||||
aa.h = readDP(dp + 1);
|
||||
idle4(aa.w, aa.w + r.y.w);
|
||||
L rd.l = readDB(aa.w + r.y.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_idpy_w(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDP(dp + 0);
|
||||
aa.h = readDP(dp + 1);
|
||||
idle4(aa.w, aa.w + r.y.w);
|
||||
rd.l = readDB(aa.w + r.y.w + 0);
|
||||
L rd.h = readDB(aa.w + r.y.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_ildp_b(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDPn(dp + 0);
|
||||
aa.h = readDPn(dp + 1);
|
||||
aa.b = readDPn(dp + 2);
|
||||
L rd.l = readLong(aa.d);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_ildp_w(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDPn(dp + 0);
|
||||
aa.h = readDPn(dp + 1);
|
||||
aa.b = readDPn(dp + 2);
|
||||
rd.l = readLong(aa.d + 0);
|
||||
L rd.h = readLong(aa.d + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_ildpy_b(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDPn(dp + 0);
|
||||
aa.h = readDPn(dp + 1);
|
||||
aa.b = readDPn(dp + 2);
|
||||
L rd.l = readLong(aa.d + r.y.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_ildpy_w(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDPn(dp + 0);
|
||||
aa.h = readDPn(dp + 1);
|
||||
aa.b = readDPn(dp + 2);
|
||||
rd.l = readLong(aa.d + r.y.w + 0);
|
||||
L rd.h = readLong(aa.d + r.y.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_sr_b(fp op) {
|
||||
sp = readPC();
|
||||
auto WDC65816::instructionIndirectStackRead16(fp op) -> void {
|
||||
sp = fetch();
|
||||
idle();
|
||||
L rd.l = readSP(sp);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_sr_w(fp op) {
|
||||
sp = readPC();
|
||||
idle();
|
||||
rd.l = readSP(sp + 0);
|
||||
L rd.h = readSP(sp + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_isry_b(fp op) {
|
||||
sp = readPC();
|
||||
idle();
|
||||
aa.l = readSP(sp + 0);
|
||||
aa.h = readSP(sp + 1);
|
||||
idle();
|
||||
L rd.l = readDB(aa.w + r.y.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
auto R65816::op_read_isry_w(fp op) {
|
||||
sp = readPC();
|
||||
idle();
|
||||
aa.l = readSP(sp + 0);
|
||||
aa.h = readSP(sp + 1);
|
||||
idle();
|
||||
rd.l = readDB(aa.w + r.y.w + 0);
|
||||
L rd.h = readDB(aa.w + r.y.w + 1);
|
||||
aa.l = readStack(sp + 0);
|
||||
aa.h = readStack(sp + 1);
|
||||
idle();
|
||||
rd.l = readBank(aa.w + r.y.w + 0);
|
||||
L rd.h = readBank(aa.w + r.y.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
auto R65816::op_adjust_imm_b(Reg16& reg, int adjust) {
|
||||
L idleIRQ();
|
||||
reg.l += adjust;
|
||||
r.p.n = (reg.l & 0x80);
|
||||
r.p.z = (reg.l == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_adjust_imm_w(Reg16& reg, int adjust) {
|
||||
L idleIRQ();
|
||||
reg.w += adjust;
|
||||
r.p.n = (reg.w & 0x8000);
|
||||
r.p.z = (reg.w == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_asl_imm_b() {
|
||||
L idleIRQ();
|
||||
r.p.c = (r.a.l & 0x80);
|
||||
r.a.l <<= 1;
|
||||
r.p.n = (r.a.l & 0x80);
|
||||
r.p.z = (r.a.l == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_asl_imm_w() {
|
||||
L idleIRQ();
|
||||
r.p.c = (r.a.w & 0x8000);
|
||||
r.a.w <<= 1;
|
||||
r.p.n = (r.a.w & 0x8000);
|
||||
r.p.z = (r.a.w == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_lsr_imm_b() {
|
||||
L idleIRQ();
|
||||
r.p.c = (r.a.l & 0x01);
|
||||
r.a.l >>= 1;
|
||||
r.p.n = (r.a.l & 0x80);
|
||||
r.p.z = (r.a.l == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_lsr_imm_w() {
|
||||
L idleIRQ();
|
||||
r.p.c = (r.a.w & 0x0001);
|
||||
r.a.w >>= 1;
|
||||
r.p.n = (r.a.w & 0x8000);
|
||||
r.p.z = (r.a.w == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_rol_imm_b() {
|
||||
L idleIRQ();
|
||||
bool carry = r.p.c;
|
||||
r.p.c = (r.a.l & 0x80);
|
||||
r.a.l = (r.a.l << 1) | carry;
|
||||
r.p.n = (r.a.l & 0x80);
|
||||
r.p.z = (r.a.l == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_rol_imm_w() {
|
||||
L idleIRQ();
|
||||
bool carry = r.p.c;
|
||||
r.p.c = (r.a.w & 0x8000);
|
||||
r.a.w = (r.a.w << 1) | carry;
|
||||
r.p.n = (r.a.w & 0x8000);
|
||||
r.p.z = (r.a.w == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_ror_imm_b() {
|
||||
L idleIRQ();
|
||||
bool carry = r.p.c;
|
||||
r.p.c = (r.a.l & 0x01);
|
||||
r.a.l = (carry << 7) | (r.a.l >> 1);
|
||||
r.p.n = (r.a.l & 0x80);
|
||||
r.p.z = (r.a.l == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_ror_imm_w() {
|
||||
L idleIRQ();
|
||||
bool carry = r.p.c;
|
||||
r.p.c = (r.a.w & 0x0001);
|
||||
r.a.w = (carry << 15) | (r.a.w >> 1);
|
||||
r.p.n = (r.a.w & 0x8000);
|
||||
r.p.z = (r.a.w == 0);
|
||||
}
|
||||
|
||||
auto R65816::op_adjust_addr_b(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
rd.l = readDB(aa.w);
|
||||
idle();
|
||||
call(op);
|
||||
L writeDB(aa.w, rd.l);
|
||||
}
|
||||
|
||||
auto R65816::op_adjust_addr_w(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
rd.l = readDB(aa.w + 0);
|
||||
rd.h = readDB(aa.w + 1);
|
||||
idle();
|
||||
call(op);
|
||||
writeDB(aa.w + 1, rd.h);
|
||||
L writeDB(aa.w + 0, rd.l);
|
||||
}
|
||||
|
||||
auto R65816::op_adjust_addrx_b(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
idle();
|
||||
rd.l = readDB(aa.w + r.x.w);
|
||||
idle();
|
||||
call(op);
|
||||
L writeDB(aa.w + r.x.w, rd.l);
|
||||
}
|
||||
|
||||
auto R65816::op_adjust_addrx_w(fp op) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
idle();
|
||||
rd.l = readDB(aa.w + r.x.w + 0);
|
||||
rd.h = readDB(aa.w + r.x.w + 1);
|
||||
idle();
|
||||
call(op);
|
||||
writeDB(aa.w + r.x.w + 1, rd.h);
|
||||
L writeDB(aa.w + r.x.w + 0, rd.l);
|
||||
}
|
||||
|
||||
auto R65816::op_adjust_dp_b(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
rd.l = readDP(dp);
|
||||
idle();
|
||||
call(op);
|
||||
L writeDP(dp, rd.l);
|
||||
}
|
||||
|
||||
auto R65816::op_adjust_dp_w(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
rd.l = readDP(dp + 0);
|
||||
rd.h = readDP(dp + 1);
|
||||
idle();
|
||||
call(op);
|
||||
writeDP(dp + 1, rd.h);
|
||||
L writeDP(dp + 0, rd.l);
|
||||
}
|
||||
|
||||
auto R65816::op_adjust_dpx_b(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
idle();
|
||||
rd.l = readDP(dp + r.x.w);
|
||||
idle();
|
||||
call(op);
|
||||
L writeDP(dp + r.x.w, rd.l);
|
||||
}
|
||||
|
||||
auto R65816::op_adjust_dpx_w(fp op) {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
idle();
|
||||
rd.l = readDP(dp + r.x.w + 0);
|
||||
rd.h = readDP(dp + r.x.w + 1);
|
||||
idle();
|
||||
call(op);
|
||||
writeDP(dp + r.x.w + 1, rd.h);
|
||||
L writeDP(dp + r.x.w + 0, rd.l);
|
||||
}
|
|
@ -1,195 +1,176 @@
|
|||
auto R65816::op_write_addr_b(Reg16& reg) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
L writeDB(aa.w, reg);
|
||||
auto WDC65816::instructionBankWrite8(uint16& reg) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
L writeBank(aa.w, reg);
|
||||
}
|
||||
|
||||
auto R65816::op_write_addr_w(Reg16& reg) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
writeDB(aa.w + 0, reg >> 0);
|
||||
L writeDB(aa.w + 1, reg >> 8);
|
||||
auto WDC65816::instructionBankWrite16(uint16& reg) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
writeBank(aa.w + 0, reg >> 0);
|
||||
L writeBank(aa.w + 1, reg >> 8);
|
||||
}
|
||||
|
||||
auto R65816::op_write_addrr_b(Reg16& reg, Reg16& idx) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
auto WDC65816::instructionBankWrite8(uint16& reg, uint16 index) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
idle();
|
||||
L writeDB(aa.w + idx, reg);
|
||||
L writeBank(aa.w + index, reg);
|
||||
}
|
||||
|
||||
auto R65816::op_write_addrr_w(Reg16& reg, Reg16& idx) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
auto WDC65816::instructionBankWrite16(uint16& reg, uint16 index) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
idle();
|
||||
writeDB(aa.w + idx + 0, reg >> 0);
|
||||
L writeDB(aa.w + idx + 1, reg >> 8);
|
||||
writeBank(aa.w + index + 0, reg >> 0);
|
||||
L writeBank(aa.w + index + 1, reg >> 8);
|
||||
}
|
||||
|
||||
auto R65816::op_write_longr_b(Reg16& idx) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
aa.b = readPC();
|
||||
L writeLong(aa.d + idx, r.a.l);
|
||||
auto WDC65816::instructionLongWrite8(uint16 index) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
aa.b = fetch();
|
||||
L write(aa.d + index, r.a.l);
|
||||
}
|
||||
|
||||
auto R65816::op_write_longr_w(Reg16& idx) {
|
||||
aa.l = readPC();
|
||||
aa.h = readPC();
|
||||
aa.b = readPC();
|
||||
writeLong(aa.d + idx + 0, r.a.l);
|
||||
L writeLong(aa.d + idx + 1, r.a.h);
|
||||
auto WDC65816::instructionLongWrite16(uint16 index) -> void {
|
||||
aa.l = fetch();
|
||||
aa.h = fetch();
|
||||
aa.b = fetch();
|
||||
write(aa.d + index + 0, r.a.l);
|
||||
L write(aa.d + index + 1, r.a.h);
|
||||
}
|
||||
|
||||
auto R65816::op_write_dp_b(Reg16& reg) {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionDirectWrite8(uint16& reg) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
L writeDP(dp, reg);
|
||||
L writeDirect(dp, reg);
|
||||
}
|
||||
|
||||
auto R65816::op_write_dp_w(Reg16& reg) {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionDirectWrite16(uint16& reg) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
writeDP(dp + 0, reg >> 0);
|
||||
L writeDP(dp + 1, reg >> 8);
|
||||
writeDirect(dp + 0, reg >> 0);
|
||||
L writeDirect(dp + 1, reg >> 8);
|
||||
}
|
||||
|
||||
auto R65816::op_write_dpr_b(Reg16& reg, Reg16& idx) {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionDirectWrite8(uint16& reg, uint16 index) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
L writeDP(dp + idx, reg);
|
||||
L writeDirect(dp + index, reg);
|
||||
}
|
||||
|
||||
auto R65816::op_write_dpr_w(Reg16& reg, Reg16& idx) {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionDirectWrite16(uint16& reg, uint16 index) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
writeDP(dp + idx + 0, reg >> 0);
|
||||
L writeDP(dp + idx + 1, reg >> 8);
|
||||
writeDirect(dp + index + 0, reg >> 0);
|
||||
L writeDirect(dp + index + 1, reg >> 8);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_idp_b() {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndirectWrite8() -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDP(dp + 0);
|
||||
aa.h = readDP(dp + 1);
|
||||
L writeDB(aa.w, r.a.l);
|
||||
aa.l = readDirect(dp + 0);
|
||||
aa.h = readDirect(dp + 1);
|
||||
L writeBank(aa.w, r.a.l);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_idp_w() {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndirectWrite16() -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDP(dp + 0);
|
||||
aa.h = readDP(dp + 1);
|
||||
writeDB(aa.w + 0, r.a.l);
|
||||
L writeDB(aa.w + 1, r.a.h);
|
||||
aa.l = readDirect(dp + 0);
|
||||
aa.h = readDirect(dp + 1);
|
||||
writeBank(aa.w + 0, r.a.l);
|
||||
L writeBank(aa.w + 1, r.a.h);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_ildp_b() {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDPn(dp + 0);
|
||||
aa.h = readDPn(dp + 1);
|
||||
aa.b = readDPn(dp + 2);
|
||||
L writeLong(aa.d, r.a.l);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_ildp_w() {
|
||||
dp = readPC();
|
||||
idle2();
|
||||
aa.l = readDPn(dp + 0);
|
||||
aa.h = readDPn(dp + 1);
|
||||
aa.b = readDPn(dp + 2);
|
||||
writeLong(aa.d + 0, r.a.l);
|
||||
L writeLong(aa.d + 1, r.a.h);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_idpx_b() {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndexedIndirectWrite8() -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
aa.l = readDP(dp + r.x.w + 0);
|
||||
aa.h = readDP(dp + r.x.w + 1);
|
||||
L writeDB(aa.w, r.a.l);
|
||||
aa.l = readDirect(dp + r.x.w + 0);
|
||||
aa.h = readDirect(dp + r.x.w + 1);
|
||||
L writeBank(aa.w, r.a.l);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_idpx_w() {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndexedIndirectWrite16() -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
idle();
|
||||
aa.l = readDP(dp + r.x.w + 0);
|
||||
aa.h = readDP(dp + r.x.w + 1);
|
||||
writeDB(aa.w + 0, r.a.l);
|
||||
L writeDB(aa.w + 1, r.a.h);
|
||||
aa.l = readDirect(dp + r.x.w + 0);
|
||||
aa.h = readDirect(dp + r.x.w + 1);
|
||||
writeBank(aa.w + 0, r.a.l);
|
||||
L writeBank(aa.w + 1, r.a.h);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_idpy_b() {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndirectIndexedWrite8() -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDP(dp + 0);
|
||||
aa.h = readDP(dp + 1);
|
||||
aa.l = readDirect(dp + 0);
|
||||
aa.h = readDirect(dp + 1);
|
||||
idle();
|
||||
L writeDB(aa.w + r.y.w, r.a.l);
|
||||
L writeBank(aa.w + r.y.w, r.a.l);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_idpy_w() {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndirectIndexedWrite16() -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDP(dp + 0);
|
||||
aa.h = readDP(dp + 1);
|
||||
aa.l = readDirect(dp + 0);
|
||||
aa.h = readDirect(dp + 1);
|
||||
idle();
|
||||
writeDB(aa.w + r.y.w + 0, r.a.l);
|
||||
L writeDB(aa.w + r.y.w + 1, r.a.h);
|
||||
writeBank(aa.w + r.y.w + 0, r.a.l);
|
||||
L writeBank(aa.w + r.y.w + 1, r.a.h);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_ildpy_b() {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndirectLongWrite8(uint16 index) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDPn(dp + 0);
|
||||
aa.h = readDPn(dp + 1);
|
||||
aa.b = readDPn(dp + 2);
|
||||
L writeLong(aa.d + r.y.w, r.a.l);
|
||||
aa.l = readDirectN(dp + 0);
|
||||
aa.h = readDirectN(dp + 1);
|
||||
aa.b = readDirectN(dp + 2);
|
||||
L write(aa.d + index, r.a.l);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_ildpy_w() {
|
||||
dp = readPC();
|
||||
auto WDC65816::instructionIndirectLongWrite16(uint16 index) -> void {
|
||||
dp = fetch();
|
||||
idle2();
|
||||
aa.l = readDPn(dp + 0);
|
||||
aa.h = readDPn(dp + 1);
|
||||
aa.b = readDPn(dp + 2);
|
||||
writeLong(aa.d + r.y.w + 0, r.a.l);
|
||||
L writeLong(aa.d + r.y.w + 1, r.a.h);
|
||||
aa.l = readDirectN(dp + 0);
|
||||
aa.h = readDirectN(dp + 1);
|
||||
aa.b = readDirectN(dp + 2);
|
||||
write(aa.d + index + 0, r.a.l);
|
||||
L write(aa.d + index + 1, r.a.h);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_sr_b() {
|
||||
sp = readPC();
|
||||
auto WDC65816::instructionStackWrite8() -> void {
|
||||
sp = fetch();
|
||||
idle();
|
||||
L writeSP(sp, r.a.l);
|
||||
L writeStack(sp, r.a.l);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_sr_w() {
|
||||
sp = readPC();
|
||||
auto WDC65816::instructionStackWrite16() -> void {
|
||||
sp = fetch();
|
||||
idle();
|
||||
writeSP(sp + 0, r.a.l);
|
||||
L writeSP(sp + 1, r.a.h);
|
||||
writeStack(sp + 0, r.a.l);
|
||||
L writeStack(sp + 1, r.a.h);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_isry_b() {
|
||||
sp = readPC();
|
||||
auto WDC65816::instructionIndirectStackWrite8() -> void {
|
||||
sp = fetch();
|
||||
idle();
|
||||
aa.l = readSP(sp + 0);
|
||||
aa.h = readSP(sp + 1);
|
||||
aa.l = readStack(sp + 0);
|
||||
aa.h = readStack(sp + 1);
|
||||
idle();
|
||||
L writeDB(aa.w + r.y.w, r.a.l);
|
||||
L writeBank(aa.w + r.y.w, r.a.l);
|
||||
}
|
||||
|
||||
auto R65816::op_sta_isry_w() {
|
||||
sp = readPC();
|
||||
auto WDC65816::instructionIndirectStackWrite16() -> void {
|
||||
sp = fetch();
|
||||
idle();
|
||||
aa.l = readSP(sp + 0);
|
||||
aa.h = readSP(sp + 1);
|
||||
aa.l = readStack(sp + 0);
|
||||
aa.h = readStack(sp + 1);
|
||||
idle();
|
||||
writeDB(aa.w + r.y.w + 0, r.a.l);
|
||||
L writeDB(aa.w + r.y.w + 1, r.a.h);
|
||||
writeBank(aa.w + r.y.w + 0, r.a.l);
|
||||
L writeBank(aa.w + r.y.w + 1, r.a.h);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
//immediate, 2-cycle opcodes with idle cycle will become bus read
|
||||
//when an IRQ is to be triggered immediately after opcode completion.
|
||||
//this affects the following opcodes:
|
||||
// clc, cld, cli, clv, sec, sed, sei,
|
||||
// tax, tay, txa, txy, tya, tyx,
|
||||
// tcd, tcs, tdc, tsc, tsx, txs,
|
||||
// inc, inx, iny, dec, dex, dey,
|
||||
// asl, lsr, rol, ror, nop, xce.
|
||||
auto WDC65816::idleIRQ() -> void {
|
||||
if(interruptPending()) {
|
||||
//modify I/O cycle to bus read cycle, do not increment PC
|
||||
read(PC);
|
||||
} else {
|
||||
idle();
|
||||
}
|
||||
}
|
||||
|
||||
auto WDC65816::idle2() -> void {
|
||||
if(DL != 0x00) {
|
||||
idle();
|
||||
}
|
||||
}
|
||||
|
||||
auto WDC65816::idle4(uint16 x, uint16 y) -> void {
|
||||
if(!XF || (x & 0xff00) != (y & 0xff00)) {
|
||||
idle();
|
||||
}
|
||||
}
|
||||
|
||||
auto WDC65816::idle6(uint16 addr) -> void {
|
||||
if(EF && (PC & 0xff00) != (addr & 0xff00)) {
|
||||
idle();
|
||||
}
|
||||
}
|
||||
|
||||
auto WDC65816::fetch() -> uint8 {
|
||||
return read(PCB << 16 | PCW++);
|
||||
}
|
||||
|
||||
auto WDC65816::pull() -> uint8 {
|
||||
EF ? SL++ : S++;
|
||||
return read(S);
|
||||
}
|
||||
|
||||
auto WDC65816::push(uint8 data) -> void {
|
||||
write(S, data);
|
||||
EF ? SL-- : S--;
|
||||
}
|
||||
|
||||
auto WDC65816::pullN() -> uint8 {
|
||||
return read(++S);
|
||||
}
|
||||
|
||||
auto WDC65816::pushN(uint8 data) -> void {
|
||||
write(S--, data);
|
||||
}
|
||||
|
||||
auto WDC65816::readDirect(uint addr) -> uint8 {
|
||||
if(EF && !DL) return read(D | uint8(addr));
|
||||
return read(uint16(D + addr));
|
||||
}
|
||||
|
||||
auto WDC65816::writeDirect(uint addr, uint8 data) -> void {
|
||||
if(EF && !DL) return write(D | uint8(addr), data);
|
||||
write(uint16(D + addr), data);
|
||||
}
|
||||
|
||||
auto WDC65816::readDirectN(uint addr) -> uint8 {
|
||||
return read(uint16(D + addr));
|
||||
}
|
||||
|
||||
auto WDC65816::readBank(uint addr) -> uint8 {
|
||||
return read((B << 16) + addr);
|
||||
}
|
||||
|
||||
auto WDC65816::writeBank(uint addr, uint8 data) -> void {
|
||||
write((B << 16) + addr, data);
|
||||
}
|
||||
|
||||
auto WDC65816::readStack(uint addr) -> uint8 {
|
||||
return read(uint16(S + addr));
|
||||
}
|
||||
|
||||
auto WDC65816::writeStack(uint addr, uint8 data) -> void {
|
||||
write(uint16(S + addr), data);
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
alwaysinline auto readPC() -> uint8 {
|
||||
return read(r.pc.b << 16 | uint16(r.pc.w++));
|
||||
}
|
||||
|
||||
alwaysinline auto readSP() -> uint8 {
|
||||
r.e ? r.s.l++ : r.s.w++;
|
||||
return read(r.s.w);
|
||||
}
|
||||
|
||||
alwaysinline auto readSPn() -> uint8 {
|
||||
return read(++r.s.w);
|
||||
}
|
||||
|
||||
alwaysinline auto readAddr(uint addr) -> uint8 {
|
||||
return read(uint16(addr));
|
||||
}
|
||||
|
||||
alwaysinline auto readLong(uint addr) -> uint8 {
|
||||
return read(uint24(addr));
|
||||
}
|
||||
|
||||
alwaysinline auto readDB(uint addr) -> uint8 {
|
||||
return read(uint24((r.db << 16) + addr)); //DB can cross page boundaries
|
||||
}
|
||||
|
||||
alwaysinline auto readPB(uint addr) -> uint8 {
|
||||
return read(r.pc.b << 16 | uint16(addr)); //PB cannot cross page boundaries
|
||||
}
|
||||
|
||||
alwaysinline auto readDP(uint addr) -> uint8 {
|
||||
if(r.e && r.d.l == 0x00) {
|
||||
return read(r.d | uint8(addr));
|
||||
} else {
|
||||
return read(uint16(r.d + addr));
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline auto readDPn(uint addr) -> uint8 {
|
||||
return read(uint16(r.d + addr));
|
||||
}
|
||||
|
||||
alwaysinline auto readSP(uint addr) -> uint8 {
|
||||
return read(uint16(r.s + addr));
|
||||
}
|
||||
|
||||
alwaysinline auto writeSP(uint8 data) -> void {
|
||||
write(r.s.w, data);
|
||||
r.e ? r.s.l-- : r.s.w--;
|
||||
}
|
||||
|
||||
alwaysinline auto writeSPn(uint8 data) -> void {
|
||||
write(r.s.w--, data);
|
||||
}
|
||||
|
||||
alwaysinline auto writeAddr(uint addr, uint8 data) -> void {
|
||||
write(uint16(addr), data);
|
||||
}
|
||||
|
||||
alwaysinline auto writeLong(uint addr, uint8 data) -> void {
|
||||
write(uint24(addr), data);
|
||||
}
|
||||
|
||||
alwaysinline auto writeDB(uint addr, uint8 data) -> void {
|
||||
write(uint24((r.db << 16) + addr), data);
|
||||
}
|
||||
|
||||
alwaysinline auto writePB(uint addr, uint8 data) -> void {
|
||||
write(r.pc.b << 16 | uint16(addr), data);
|
||||
}
|
||||
|
||||
alwaysinline auto writeDP(uint addr, uint8 data) -> void {
|
||||
if(r.e && r.d.l == 0x00) {
|
||||
write(r.d | uint8(addr), data);
|
||||
} else {
|
||||
write(uint16(r.d + addr), data);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline auto writeSP(uint addr, uint8 data) -> void {
|
||||
write(uint16(r.s + addr), data);
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
struct Flags {
|
||||
union {
|
||||
uint8_t b = 0;
|
||||
BooleanBitField<uint8_t, 7> n;
|
||||
BooleanBitField<uint8_t, 6> v;
|
||||
BooleanBitField<uint8_t, 5> m;
|
||||
BooleanBitField<uint8_t, 4> x;
|
||||
BooleanBitField<uint8_t, 3> d;
|
||||
BooleanBitField<uint8_t, 2> i;
|
||||
BooleanBitField<uint8_t, 1> z;
|
||||
BooleanBitField<uint8_t, 0> c;
|
||||
};
|
||||
|
||||
inline operator uint() const { return b; }
|
||||
inline auto operator =(uint value) -> uint { return b = value; }
|
||||
inline auto operator&=(uint value) -> uint { return b &= value; }
|
||||
inline auto operator|=(uint value) -> uint { return b |= value; }
|
||||
};
|
||||
|
||||
struct Reg16 {
|
||||
union {
|
||||
uint16_t w = 0;
|
||||
NaturalBitField<uint16_t, 0, 7> l;
|
||||
NaturalBitField<uint16_t, 8, 15> h;
|
||||
};
|
||||
|
||||
inline operator uint() const { return w; }
|
||||
inline auto operator =(uint value) -> uint { return w = value; }
|
||||
inline auto operator |=(uint value) -> uint { return w |= value; }
|
||||
inline auto operator ^=(uint value) -> uint { return w ^= value; }
|
||||
inline auto operator &=(uint value) -> uint { return w &= value; }
|
||||
inline auto operator<<=(uint value) -> uint { return w <<= value; }
|
||||
inline auto operator>>=(uint value) -> uint { return w >>= value; }
|
||||
inline auto operator +=(uint value) -> uint { return w += value; }
|
||||
inline auto operator -=(uint value) -> uint { return w -= value; }
|
||||
inline auto operator *=(uint value) -> uint { return w *= value; }
|
||||
inline auto operator /=(uint value) -> uint { return w /= value; }
|
||||
inline auto operator %=(uint value) -> uint { return w %= value; }
|
||||
};
|
||||
|
||||
struct Reg24 {
|
||||
union {
|
||||
uint32_t d = 0;
|
||||
NaturalBitField<uint32_t, 0, 7> l;
|
||||
NaturalBitField<uint32_t, 8, 15> h;
|
||||
NaturalBitField<uint32_t, 16, 23> b;
|
||||
NaturalBitField<uint32_t, 0, 15> w;
|
||||
};
|
||||
|
||||
inline operator uint() const { return d; }
|
||||
inline auto operator =(uint value) -> uint { return d = uint24( value); }
|
||||
inline auto operator |=(uint value) -> uint { return d = uint24(d | value); }
|
||||
inline auto operator ^=(uint value) -> uint { return d = uint24(d ^ value); }
|
||||
inline auto operator &=(uint value) -> uint { return d = uint24(d & value); }
|
||||
inline auto operator<<=(uint value) -> uint { return d = uint24(d << value); }
|
||||
inline auto operator>>=(uint value) -> uint { return d = uint24(d >> value); }
|
||||
inline auto operator +=(uint value) -> uint { return d = uint24(d + value); }
|
||||
inline auto operator -=(uint value) -> uint { return d = uint24(d - value); }
|
||||
inline auto operator *=(uint value) -> uint { return d = uint24(d * value); }
|
||||
inline auto operator /=(uint value) -> uint { return d = uint24(d / value); }
|
||||
inline auto operator %=(uint value) -> uint { return d = uint24(d % value); }
|
||||
};
|
||||
|
||||
struct Registers {
|
||||
Reg24 pc;
|
||||
Reg16 a;
|
||||
Reg16 x;
|
||||
Reg16 y;
|
||||
Reg16 z; //pseudo-register (zero register)
|
||||
Reg16 s;
|
||||
Reg16 d;
|
||||
Flags p;
|
||||
uint8 db = 0;
|
||||
bool e = false;
|
||||
|
||||
bool irq = false; //IRQ pin (0 = low, 1 = trigger)
|
||||
bool wai = false; //raised during wai, cleared after interrupt triggered
|
||||
bool stp = false; //raised during stp, never cleared
|
||||
uint8 mdr = 0; //memory data register
|
||||
uint16 vector = 0; //interrupt vector address
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
auto R65816::serialize(serializer& s) -> void {
|
||||
auto WDC65816::serialize(serializer& s) -> void {
|
||||
s.integer(r.pc.d);
|
||||
|
||||
s.integer(r.a.w);
|
||||
|
@ -8,7 +8,14 @@ auto R65816::serialize(serializer& s) -> void {
|
|||
s.integer(r.s.w);
|
||||
s.integer(r.d.w);
|
||||
|
||||
s.integer(r.p.b);
|
||||
s.integer(r.p.c);
|
||||
s.integer(r.p.z);
|
||||
s.integer(r.p.i);
|
||||
s.integer(r.p.d);
|
||||
s.integer(r.p.x);
|
||||
s.integer(r.p.m);
|
||||
s.integer(r.p.v);
|
||||
s.integer(r.p.n);
|
||||
|
||||
s.integer(r.db);
|
||||
s.integer(r.e);
|
||||
|
|
|
@ -1,288 +0,0 @@
|
|||
auto R65816::instruction() -> void {
|
||||
#define opA( n, o ) case n: return op_##o();
|
||||
#define opAI( n, o, i ) case n: return op_##o(i);
|
||||
#define opAII(n, o, i, j) case n: return op_##o(i, j);
|
||||
#define opM( n, o ) case n: return r.p.m ? op_##o##_b() : op_##o##_w();
|
||||
#define opMF( n, o, f ) case n: return r.p.m ? op_##o##_b(&R65816::op_##f##_b) : op_##o##_w(&R65816::op_##f##_w);
|
||||
#define opMFI(n, o, f, i) case n: return r.p.m ? op_##o##_b(&R65816::op_##f##_b, i) : op_##o##_w(&R65816::op_##f##_w, i);
|
||||
#define opMI( n, o, i ) case n: return r.p.m ? op_##o##_b(i) : op_##o##_w(i);
|
||||
#define opMII(n, o, i, j) case n: return r.p.m ? op_##o##_b(i, j) : op_##o##_w(i, j);
|
||||
#define opX( n, o) case n: return r.p.x ? op_##o##_b() : op_##o##_w();
|
||||
#define opXF( n, o, f ) case n: return r.p.x ? op_##o##_b(&R65816::op_##f##_b) : op_##o##_w(&R65816::op_##f##_w);
|
||||
#define opXFI(n, o, f, i) case n: return r.p.x ? op_##o##_b(&R65816::op_##f##_b, i) : op_##o##_w(&R65816::op_##f##_w, i);
|
||||
#define opXI( n, o, i ) case n: return r.p.x ? op_##o##_b(i) : op_##o##_w(i);
|
||||
#define opXII(n, o, i, j) case n: return r.p.x ? op_##o##_b(i, j) : op_##o##_w(i, j);
|
||||
|
||||
switch(readPC()) {
|
||||
opAI (0x00, interrupt, r.e ? 0xfffe : 0xffe6) //emulation mode lacks BRK vector; uses IRQ vector instead
|
||||
opMF (0x01, read_idpx, ora)
|
||||
opAI (0x02, interrupt, r.e ? 0xfff4 : 0xffe4)
|
||||
opMF (0x03, read_sr, ora)
|
||||
opMF (0x04, adjust_dp, tsb)
|
||||
opMF (0x05, read_dp, ora)
|
||||
opMF (0x06, adjust_dp, asl)
|
||||
opMF (0x07, read_ildp, ora)
|
||||
opA (0x08, php)
|
||||
opMF (0x09, read_const, ora)
|
||||
opM (0x0a, asl_imm)
|
||||
opA (0x0b, phd)
|
||||
opMF (0x0c, adjust_addr, tsb)
|
||||
opMF (0x0d, read_addr, ora)
|
||||
opMF (0x0e, adjust_addr, asl)
|
||||
opMF (0x0f, read_long, ora)
|
||||
opAII(0x10, branch, r.p.n, 0)
|
||||
opMF (0x11, read_idpy, ora)
|
||||
opMF (0x12, read_idp, ora)
|
||||
opMF (0x13, read_isry, ora)
|
||||
opMF (0x14, adjust_dp, trb)
|
||||
opMFI(0x15, read_dpr, ora, r.x)
|
||||
opMF (0x16, adjust_dpx, asl)
|
||||
opMF (0x17, read_ildpy, ora)
|
||||
opAI (0x18, clear_flag, r.p.c.bit)
|
||||
opMF (0x19, read_addry, ora)
|
||||
opMII(0x1a, adjust_imm, r.a, +1)
|
||||
opA (0x1b, tcs)
|
||||
opMF (0x1c, adjust_addr, trb)
|
||||
opMF (0x1d, read_addrx, ora)
|
||||
opMF (0x1e, adjust_addrx, asl)
|
||||
opMF (0x1f, read_longx, ora)
|
||||
opA (0x20, jsr_addr)
|
||||
opMF (0x21, read_idpx, and)
|
||||
opA (0x22, jsr_long)
|
||||
opMF (0x23, read_sr, and)
|
||||
opMF (0x24, read_dp, bit)
|
||||
opMF (0x25, read_dp, and)
|
||||
opMF (0x26, adjust_dp, rol)
|
||||
opMF (0x27, read_ildp, and)
|
||||
opA (0x28, plp)
|
||||
opMF (0x29, read_const, and)
|
||||
opM (0x2a, rol_imm)
|
||||
opA (0x2b, pld)
|
||||
opMF (0x2c, read_addr, bit)
|
||||
opMF (0x2d, read_addr, and)
|
||||
opMF (0x2e, adjust_addr, rol)
|
||||
opMF (0x2f, read_long, and)
|
||||
opAII(0x30, branch, r.p.n, 1)
|
||||
opMF (0x31, read_idpy, and)
|
||||
opMF (0x32, read_idp, and)
|
||||
opMF (0x33, read_isry, and)
|
||||
opMFI(0x34, read_dpr, bit, r.x)
|
||||
opMFI(0x35, read_dpr, and, r.x)
|
||||
opMF (0x36, adjust_dpx, rol)
|
||||
opMF (0x37, read_ildpy, and)
|
||||
opAI (0x38, set_flag, r.p.c.bit)
|
||||
opMF (0x39, read_addry, and)
|
||||
opMII(0x3a, adjust_imm, r.a, -1)
|
||||
opAII(0x3b, transfer_w, r.s, r.a)
|
||||
opMF (0x3c, read_addrx, bit)
|
||||
opMF (0x3d, read_addrx, and)
|
||||
opMF (0x3e, adjust_addrx, rol)
|
||||
opMF (0x3f, read_longx, and)
|
||||
opA (0x40, rti)
|
||||
opMF (0x41, read_idpx, eor)
|
||||
opA (0x42, wdm)
|
||||
opMF (0x43, read_sr, eor)
|
||||
opXI (0x44, move, -1)
|
||||
opMF (0x45, read_dp, eor)
|
||||
opMF (0x46, adjust_dp, lsr)
|
||||
opMF (0x47, read_ildp, eor)
|
||||
opMI (0x48, push, r.a)
|
||||
opMF (0x49, read_const, eor)
|
||||
opM (0x4a, lsr_imm)
|
||||
opA (0x4b, phk)
|
||||
opA (0x4c, jmp_addr)
|
||||
opMF (0x4d, read_addr, eor)
|
||||
opMF (0x4e, adjust_addr, lsr)
|
||||
opMF (0x4f, read_long, eor)
|
||||
opAII(0x50, branch, r.p.v, 0)
|
||||
opMF (0x51, read_idpy, eor)
|
||||
opMF (0x52, read_idp, eor)
|
||||
opMF (0x53, read_isry, eor)
|
||||
opXI (0x54, move, +1)
|
||||
opMFI(0x55, read_dpr, eor, r.x)
|
||||
opMF (0x56, adjust_dpx, lsr)
|
||||
opMF (0x57, read_ildpy, eor)
|
||||
opAI (0x58, clear_flag, r.p.i.bit)
|
||||
opMF (0x59, read_addry, eor)
|
||||
opXI (0x5a, push, r.y)
|
||||
opAII(0x5b, transfer_w, r.a, r.d)
|
||||
opA (0x5c, jmp_long)
|
||||
opMF (0x5d, read_addrx, eor)
|
||||
opMF (0x5e, adjust_addrx, lsr)
|
||||
opMF (0x5f, read_longx, eor)
|
||||
opA (0x60, rts)
|
||||
opMF (0x61, read_idpx, adc)
|
||||
opA (0x62, per)
|
||||
opMF (0x63, read_sr, adc)
|
||||
opMI (0x64, write_dp, r.z)
|
||||
opMF (0x65, read_dp, adc)
|
||||
opMF (0x66, adjust_dp, ror)
|
||||
opMF (0x67, read_ildp, adc)
|
||||
opMI (0x68, pull, r.a)
|
||||
opMF (0x69, read_const, adc)
|
||||
opM (0x6a, ror_imm)
|
||||
opA (0x6b, rtl)
|
||||
opA (0x6c, jmp_iaddr)
|
||||
opMF (0x6d, read_addr, adc)
|
||||
opMF (0x6e, adjust_addr, ror)
|
||||
opMF (0x6f, read_long, adc)
|
||||
opAII(0x70, branch, r.p.v, 1)
|
||||
opMF (0x71, read_idpy, adc)
|
||||
opMF (0x72, read_idp, adc)
|
||||
opMF (0x73, read_isry, adc)
|
||||
opMII(0x74, write_dpr, r.z, r.x)
|
||||
opMFI(0x75, read_dpr, adc, r.x)
|
||||
opMF (0x76, adjust_dpx, ror)
|
||||
opMF (0x77, read_ildpy, adc)
|
||||
opAI (0x78, set_flag, r.p.i.bit)
|
||||
opMF (0x79, read_addry, adc)
|
||||
opXI (0x7a, pull, r.y)
|
||||
opAII(0x7b, transfer_w, r.d, r.a)
|
||||
opA (0x7c, jmp_iaddrx)
|
||||
opMF (0x7d, read_addrx, adc)
|
||||
opMF (0x7e, adjust_addrx, ror)
|
||||
opMF (0x7f, read_longx, adc)
|
||||
opA (0x80, bra)
|
||||
opM (0x81, sta_idpx)
|
||||
opA (0x82, brl)
|
||||
opM (0x83, sta_sr)
|
||||
opXI (0x84, write_dp, r.y)
|
||||
opMI (0x85, write_dp, r.a)
|
||||
opXI (0x86, write_dp, r.x)
|
||||
opM (0x87, sta_ildp)
|
||||
opXII(0x88, adjust_imm, r.y, -1)
|
||||
opM (0x89, read_bit_const)
|
||||
opMII(0x8a, transfer, r.x, r.a)
|
||||
opA (0x8b, phb)
|
||||
opXI (0x8c, write_addr, r.y)
|
||||
opMI (0x8d, write_addr, r.a)
|
||||
opXI (0x8e, write_addr, r.x)
|
||||
opMI (0x8f, write_longr, r.z)
|
||||
opAII(0x90, branch, r.p.c, 0)
|
||||
opM (0x91, sta_idpy)
|
||||
opM (0x92, sta_idp)
|
||||
opM (0x93, sta_isry)
|
||||
opXII(0x94, write_dpr, r.y, r.x)
|
||||
opMII(0x95, write_dpr, r.a, r.x)
|
||||
opXII(0x96, write_dpr, r.x, r.y)
|
||||
opM (0x97, sta_ildpy)
|
||||
opMII(0x98, transfer, r.y, r.a)
|
||||
opMII(0x99, write_addrr, r.a, r.y)
|
||||
opA (0x9a, txs)
|
||||
opXII(0x9b, transfer, r.x, r.y)
|
||||
opMI (0x9c, write_addr, r.z)
|
||||
opMII(0x9d, write_addrr, r.a, r.x)
|
||||
opMII(0x9e, write_addrr, r.z, r.x)
|
||||
opMI (0x9f, write_longr, r.x)
|
||||
opXF (0xa0, read_const, ldy)
|
||||
opMF (0xa1, read_idpx, lda)
|
||||
opXF (0xa2, read_const, ldx)
|
||||
opMF (0xa3, read_sr, lda)
|
||||
opXF (0xa4, read_dp, ldy)
|
||||
opMF (0xa5, read_dp, lda)
|
||||
opXF (0xa6, read_dp, ldx)
|
||||
opMF (0xa7, read_ildp, lda)
|
||||
opXII(0xa8, transfer, r.a, r.y)
|
||||
opMF (0xa9, read_const, lda)
|
||||
opXII(0xaa, transfer, r.a, r.x)
|
||||
opA (0xab, plb)
|
||||
opXF (0xac, read_addr, ldy)
|
||||
opMF (0xad, read_addr, lda)
|
||||
opXF (0xae, read_addr, ldx)
|
||||
opMF (0xaf, read_long, lda)
|
||||
opAII(0xb0, branch, r.p.c, 1)
|
||||
opMF (0xb1, read_idpy, lda)
|
||||
opMF (0xb2, read_idp, lda)
|
||||
opMF (0xb3, read_isry, lda)
|
||||
opXFI(0xb4, read_dpr, ldy, r.x)
|
||||
opMFI(0xb5, read_dpr, lda, r.x)
|
||||
opXFI(0xb6, read_dpr, ldx, r.y)
|
||||
opMF (0xb7, read_ildpy, lda)
|
||||
opAI (0xb8, clear_flag, r.p.v.bit)
|
||||
opMF (0xb9, read_addry, lda)
|
||||
opX (0xba, tsx)
|
||||
opXII(0xbb, transfer, r.y, r.x)
|
||||
opXF (0xbc, read_addrx, ldy)
|
||||
opMF (0xbd, read_addrx, lda)
|
||||
opXF (0xbe, read_addry, ldx)
|
||||
opMF (0xbf, read_longx, lda)
|
||||
opXF (0xc0, read_const, cpy)
|
||||
opMF (0xc1, read_idpx, cmp)
|
||||
opAI (0xc2, pflag, 0)
|
||||
opMF (0xc3, read_sr, cmp)
|
||||
opXF (0xc4, read_dp, cpy)
|
||||
opMF (0xc5, read_dp, cmp)
|
||||
opMF (0xc6, adjust_dp, dec)
|
||||
opMF (0xc7, read_ildp, cmp)
|
||||
opXII(0xc8, adjust_imm, r.y, +1)
|
||||
opMF (0xc9, read_const, cmp)
|
||||
opXII(0xca, adjust_imm, r.x, -1)
|
||||
opA (0xcb, wai)
|
||||
opXF (0xcc, read_addr, cpy)
|
||||
opMF (0xcd, read_addr, cmp)
|
||||
opMF (0xce, adjust_addr, dec)
|
||||
opMF (0xcf, read_long, cmp)
|
||||
opAII(0xd0, branch, r.p.z, 0)
|
||||
opMF (0xd1, read_idpy, cmp)
|
||||
opMF (0xd2, read_idp, cmp)
|
||||
opMF (0xd3, read_isry, cmp)
|
||||
opA (0xd4, pei)
|
||||
opMFI(0xd5, read_dpr, cmp, r.x)
|
||||
opMF (0xd6, adjust_dpx, dec)
|
||||
opMF (0xd7, read_ildpy, cmp)
|
||||
opAI (0xd8, clear_flag, r.p.d.bit)
|
||||
opMF (0xd9, read_addry, cmp)
|
||||
opXI (0xda, push, r.x)
|
||||
opA (0xdb, stp)
|
||||
opA (0xdc, jmp_iladdr)
|
||||
opMF (0xdd, read_addrx, cmp)
|
||||
opMF (0xde, adjust_addrx, dec)
|
||||
opMF (0xdf, read_longx, cmp)
|
||||
opXF (0xe0, read_const, cpx)
|
||||
opMF (0xe1, read_idpx, sbc)
|
||||
opAI (0xe2, pflag, 1)
|
||||
opMF (0xe3, read_sr, sbc)
|
||||
opXF (0xe4, read_dp, cpx)
|
||||
opMF (0xe5, read_dp, sbc)
|
||||
opMF (0xe6, adjust_dp, inc)
|
||||
opMF (0xe7, read_ildp, sbc)
|
||||
opXII(0xe8, adjust_imm, r.x, +1)
|
||||
opMF (0xe9, read_const, sbc)
|
||||
opA (0xea, nop)
|
||||
opA (0xeb, xba)
|
||||
opXF (0xec, read_addr, cpx)
|
||||
opMF (0xed, read_addr, sbc)
|
||||
opMF (0xee, adjust_addr, inc)
|
||||
opMF (0xef, read_long, sbc)
|
||||
opAII(0xf0, branch, r.p.z, 1)
|
||||
opMF (0xf1, read_idpy, sbc)
|
||||
opMF (0xf2, read_idp, sbc)
|
||||
opMF (0xf3, read_isry, sbc)
|
||||
opA (0xf4, pea)
|
||||
opMFI(0xf5, read_dpr, sbc, r.x)
|
||||
opMF (0xf6, adjust_dpx, inc)
|
||||
opMF (0xf7, read_ildpy, sbc)
|
||||
opAI (0xf8, set_flag, r.p.d.bit)
|
||||
opMF (0xf9, read_addry, sbc)
|
||||
opXI (0xfa, pull, r.x)
|
||||
opA (0xfb, xce)
|
||||
opA (0xfc, jsr_iaddrx)
|
||||
opMF (0xfd, read_addrx, sbc)
|
||||
opMF (0xfe, adjust_addrx, inc)
|
||||
opMF (0xff, read_longx, sbc)
|
||||
}
|
||||
|
||||
#undef opA
|
||||
#undef opAI
|
||||
#undef opAII
|
||||
#undef opM
|
||||
#undef opMF
|
||||
#undef opMFI
|
||||
#undef opMI
|
||||
#undef opMII
|
||||
#undef opX
|
||||
#undef opXF
|
||||
#undef opXFI
|
||||
#undef opXI
|
||||
#undef opXII
|
||||
}
|
|
@ -3,74 +3,128 @@
|
|||
|
||||
namespace Processor {
|
||||
|
||||
#include "algorithms.cpp"
|
||||
#include "disassembler.cpp"
|
||||
#include "serialization.cpp"
|
||||
#define A r.a.w
|
||||
#define X r.x.w
|
||||
#define Y r.y.w
|
||||
#define Z r.z.w
|
||||
#define S r.s.w
|
||||
#define D r.d.w
|
||||
#define B r.db
|
||||
#define P r.p
|
||||
#define PC r.pc.d
|
||||
#define CF r.p.c
|
||||
#define ZF r.p.z
|
||||
#define IF r.p.i
|
||||
#define DF r.p.d
|
||||
#define XF r.p.x
|
||||
#define MF r.p.m
|
||||
#define VF r.p.v
|
||||
#define NF r.p.n
|
||||
#define EF r.e
|
||||
#define AW r.a.w
|
||||
#define AH r.a.h
|
||||
#define AL r.a.l
|
||||
#define XW r.x.w
|
||||
#define XH r.x.h
|
||||
#define XL r.x.l
|
||||
#define YW r.y.w
|
||||
#define YH r.y.h
|
||||
#define YL r.y.l
|
||||
#define ZW r.x.w
|
||||
#define ZH r.z.h
|
||||
#define ZL r.z.l
|
||||
#define SH r.s.h
|
||||
#define SL r.s.l
|
||||
#define DH r.d.h
|
||||
#define DL r.d.l
|
||||
#define PCB r.pc.b
|
||||
#define PCW r.pc.w
|
||||
#define PCH r.pc.h
|
||||
#define PCL r.pc.l
|
||||
|
||||
#define E if(r.e)
|
||||
#define N if(!r.e)
|
||||
#define L lastCycle();
|
||||
#define call(op) (this->*op)()
|
||||
|
||||
#define LO(n) n.byte(0)
|
||||
#define HI(n) n.byte(1)
|
||||
|
||||
#include "memory.cpp"
|
||||
#include "algorithms.cpp"
|
||||
|
||||
#include "instructions-read.cpp"
|
||||
#include "instructions-write.cpp"
|
||||
#include "instructions-rmw.cpp"
|
||||
#include "instructions-modify.cpp"
|
||||
#include "instructions-pc.cpp"
|
||||
#include "instructions-misc.cpp"
|
||||
#include "switch.cpp"
|
||||
#include "instruction.cpp"
|
||||
|
||||
auto R65816::interrupt() -> void {
|
||||
read(r.pc.d);
|
||||
idle();
|
||||
N writeSP(r.pc.b);
|
||||
writeSP(r.pc.h);
|
||||
writeSP(r.pc.l);
|
||||
writeSP(r.e ? (r.p & ~0x10) : r.p);
|
||||
r.pc.l = read(r.vector + 0);
|
||||
r.p.i = 1;
|
||||
r.p.d = 0;
|
||||
r.pc.h = read(r.vector + 1);
|
||||
r.pc.b = 0x00;
|
||||
auto WDC65816::power() -> void {
|
||||
PC = 0x000000;
|
||||
A = 0x0000;
|
||||
X = 0x0000;
|
||||
Y = 0x0000;
|
||||
S = 0x01ff;
|
||||
D = 0x0000;
|
||||
B = 0x00;
|
||||
P = 0x34;
|
||||
EF = 1;
|
||||
|
||||
r.mdr = 0x00;
|
||||
r.wai = false;
|
||||
r.stp = false;
|
||||
r.vector = 0xfffc; //reset vector address
|
||||
}
|
||||
|
||||
//immediate, 2-cycle opcodes with idle cycle will become bus read
|
||||
//when an IRQ is to be triggered immediately after opcode completion.
|
||||
//this affects the following opcodes:
|
||||
// clc, cld, cli, clv, sec, sed, sei,
|
||||
// tax, tay, txa, txy, tya, tyx,
|
||||
// tcd, tcs, tdc, tsc, tsx, txs,
|
||||
// inc, inx, iny, dec, dex, dey,
|
||||
// asl, lsr, rol, ror, nop, xce.
|
||||
auto R65816::idleIRQ() -> void {
|
||||
if(interruptPending()) {
|
||||
//modify I/O cycle to bus read cycle, do not increment PC
|
||||
read(r.pc.d);
|
||||
} else {
|
||||
idle();
|
||||
}
|
||||
}
|
||||
|
||||
auto R65816::idle2() -> void {
|
||||
if(r.d.l != 0x00) {
|
||||
idle();
|
||||
}
|
||||
}
|
||||
|
||||
auto R65816::idle4(uint16 x, uint16 y) -> void {
|
||||
if(!r.p.x || (x & 0xff00) != (y & 0xff00)) {
|
||||
idle();
|
||||
}
|
||||
}
|
||||
|
||||
auto R65816::idle6(uint16 addr) -> void {
|
||||
if(r.e && (r.pc.w & 0xff00) != (addr & 0xff00)) {
|
||||
idle();
|
||||
}
|
||||
}
|
||||
#undef A
|
||||
#undef X
|
||||
#undef Y
|
||||
#undef Z
|
||||
#undef S
|
||||
#undef D
|
||||
#undef B
|
||||
#undef P
|
||||
#undef PC
|
||||
#undef CF
|
||||
#undef ZF
|
||||
#undef IF
|
||||
#undef DF
|
||||
#undef XF
|
||||
#undef MF
|
||||
#undef VF
|
||||
#undef NF
|
||||
#undef EF
|
||||
#undef AW
|
||||
#undef AH
|
||||
#undef AL
|
||||
#undef XW
|
||||
#undef XH
|
||||
#undef XL
|
||||
#undef YW
|
||||
#undef YH
|
||||
#undef YL
|
||||
#undef ZW
|
||||
#undef ZH
|
||||
#undef ZL
|
||||
#undef SH
|
||||
#undef SL
|
||||
#undef DH
|
||||
#undef DL
|
||||
#undef PCB
|
||||
#undef PCW
|
||||
#undef PCH
|
||||
#undef PCL
|
||||
|
||||
#undef E
|
||||
#undef N
|
||||
#undef L
|
||||
#undef call
|
||||
|
||||
#undef LO
|
||||
#undef HI
|
||||
|
||||
//#include "disassembler.cpp"
|
||||
#include "serialization.cpp"
|
||||
|
||||
}
|
||||
|
|
|
@ -6,12 +6,8 @@
|
|||
|
||||
namespace Processor {
|
||||
|
||||
struct R65816 {
|
||||
#include "registers.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "disassembler.hpp"
|
||||
|
||||
using fp = auto (R65816::*)() -> void;
|
||||
struct WDC65816 {
|
||||
using fp = auto (WDC65816::*)() -> void;
|
||||
|
||||
virtual auto idle() -> void = 0;
|
||||
virtual auto read(uint24 addr) -> uint8 = 0;
|
||||
|
@ -23,193 +19,268 @@ struct R65816 {
|
|||
|
||||
virtual auto readDisassembler(uint24 addr) -> uint8 { return 0; }
|
||||
|
||||
//r65816.cpp
|
||||
alwaysinline auto idleIRQ() -> void;
|
||||
alwaysinline auto idle2() -> void;
|
||||
alwaysinline auto idle4(uint16 x, uint16 y) -> void;
|
||||
alwaysinline auto idle6(uint16 addr) -> void;
|
||||
//wdc65816.cpp
|
||||
auto power() -> void;
|
||||
|
||||
//memory.cpp
|
||||
inline auto idleIRQ() -> void;
|
||||
inline auto idle2() -> void;
|
||||
inline auto idle4(uint16 x, uint16 y) -> void;
|
||||
inline auto idle6(uint16 addr) -> void;
|
||||
inline auto fetch() -> uint8;
|
||||
inline auto pull() -> uint8;
|
||||
auto push(uint8 data) -> void;
|
||||
inline auto pullN() -> uint8;
|
||||
inline auto pushN(uint8 data) -> void;
|
||||
inline auto readDirect(uint addr) -> uint8;
|
||||
inline auto writeDirect(uint addr, uint8 data) -> void;
|
||||
inline auto readDirectN(uint addr) -> uint8;
|
||||
inline auto readBank(uint addr) -> uint8;
|
||||
inline auto writeBank(uint addr, uint8 data) -> void;
|
||||
inline auto readStack(uint addr) -> uint8;
|
||||
inline auto writeStack(uint addr, uint8 data) -> void;
|
||||
|
||||
//algorithms.cpp
|
||||
auto op_adc_b();
|
||||
auto op_adc_w();
|
||||
auto op_and_b();
|
||||
auto op_and_w();
|
||||
auto op_bit_b();
|
||||
auto op_bit_w();
|
||||
auto op_cmp_b();
|
||||
auto op_cmp_w();
|
||||
auto op_cpx_b();
|
||||
auto op_cpx_w();
|
||||
auto op_cpy_b();
|
||||
auto op_cpy_w();
|
||||
auto op_eor_b();
|
||||
auto op_eor_w();
|
||||
auto op_lda_b();
|
||||
auto op_lda_w();
|
||||
auto op_ldx_b();
|
||||
auto op_ldx_w();
|
||||
auto op_ldy_b();
|
||||
auto op_ldy_w();
|
||||
auto op_ora_b();
|
||||
auto op_ora_w();
|
||||
auto op_sbc_b();
|
||||
auto op_sbc_w();
|
||||
auto algorithmADC8() ->void;
|
||||
auto algorithmADC16() -> void;
|
||||
auto algorithmAND8() -> void;
|
||||
auto algorithmAND16() -> void;
|
||||
auto algorithmASL8() -> void;
|
||||
auto algorithmASL16() -> void;
|
||||
auto algorithmBIT8() -> void;
|
||||
auto algorithmBIT16() -> void;
|
||||
auto algorithmCMP8() -> void;
|
||||
auto algorithmCMP16() -> void;
|
||||
auto algorithmCPX8() -> void;
|
||||
auto algorithmCPX16() -> void;
|
||||
auto algorithmCPY8() -> void;
|
||||
auto algorithmCPY16() -> void;
|
||||
auto algorithmDEC8() -> void;
|
||||
auto algorithmDEC16() -> void;
|
||||
auto algorithmEOR8() -> void;
|
||||
auto algorithmEOR16() -> void;
|
||||
auto algorithmINC8() -> void;
|
||||
auto algorithmINC16() -> void;
|
||||
auto algorithmLDA8() -> void;
|
||||
auto algorithmLDA16() -> void;
|
||||
auto algorithmLDX8() -> void;
|
||||
auto algorithmLDX16() -> void;
|
||||
auto algorithmLDY8() -> void;
|
||||
auto algorithmLDY16() -> void;
|
||||
auto algorithmLSR8() -> void;
|
||||
auto algorithmLSR16() -> void;
|
||||
auto algorithmORA8() -> void;
|
||||
auto algorithmORA16() -> void;
|
||||
auto algorithmROL8() -> void;
|
||||
auto algorithmROL16() -> void;
|
||||
auto algorithmROR8() -> void;
|
||||
auto algorithmROR16() -> void;
|
||||
auto algorithmSBC8() -> void;
|
||||
auto algorithmSBC16() -> void;
|
||||
auto algorithmTRB8() -> void;
|
||||
auto algorithmTRB16() -> void;
|
||||
auto algorithmTSB8() -> void;
|
||||
auto algorithmTSB16() -> void;
|
||||
|
||||
auto op_inc_b();
|
||||
auto op_inc_w();
|
||||
auto op_dec_b();
|
||||
auto op_dec_w();
|
||||
auto op_asl_b();
|
||||
auto op_asl_w();
|
||||
auto op_lsr_b();
|
||||
auto op_lsr_w();
|
||||
auto op_rol_b();
|
||||
auto op_rol_w();
|
||||
auto op_ror_b();
|
||||
auto op_ror_w();
|
||||
auto op_trb_b();
|
||||
auto op_trb_w();
|
||||
auto op_tsb_b();
|
||||
auto op_tsb_w();
|
||||
//instructions-read.cpp
|
||||
auto instructionImmediateRead8(fp) -> void;
|
||||
auto instructionImmediateRead16(fp) -> void;
|
||||
auto instructionBankRead8(fp) -> void;
|
||||
auto instructionBankRead16(fp) -> void;
|
||||
auto instructionBankRead8(fp, uint16) -> void;
|
||||
auto instructionBankRead16(fp, uint16) -> void;
|
||||
auto instructionLongRead8(fp, uint16 = 0) -> void;
|
||||
auto instructionLongRead16(fp, uint16 = 0) -> void;
|
||||
auto instructionDirectRead8(fp) -> void;
|
||||
auto instructionDirectRead16(fp) -> void;
|
||||
auto instructionDirectRead8(fp, uint16) -> void;
|
||||
auto instructionDirectRead16(fp, uint16) -> void;
|
||||
auto instructionIndirectRead8(fp) -> void;
|
||||
auto instructionIndirectRead16(fp) -> void;
|
||||
auto instructionIndexedIndirectRead8(fp) -> void;
|
||||
auto instructionIndexedIndirectRead16(fp) -> void;
|
||||
auto instructionIndirectIndexedRead8(fp) -> void;
|
||||
auto instructionIndirectIndexedRead16(fp) -> void;
|
||||
auto instructionIndirectLongRead8(fp, uint16 = 0) -> void;
|
||||
auto instructionIndirectLongRead16(fp, uint16 = 0) -> void;
|
||||
auto instructionStackRead8(fp) -> void;
|
||||
auto instructionStackRead16(fp) -> void;
|
||||
auto instructionIndirectStackRead8(fp) -> void;
|
||||
auto instructionIndirectStackRead16(fp) -> void;
|
||||
|
||||
//opcode_read.cpp
|
||||
auto op_read_const_b(fp);
|
||||
auto op_read_const_w(fp);
|
||||
auto op_read_bit_const_b();
|
||||
auto op_read_bit_const_w();
|
||||
auto op_read_addr_b(fp);
|
||||
auto op_read_addr_w(fp);
|
||||
auto op_read_addrx_b(fp);
|
||||
auto op_read_addrx_w(fp);
|
||||
auto op_read_addry_b(fp);
|
||||
auto op_read_addry_w(fp);
|
||||
auto op_read_long_b(fp);
|
||||
auto op_read_long_w(fp);
|
||||
auto op_read_longx_b(fp);
|
||||
auto op_read_longx_w(fp);
|
||||
auto op_read_dp_b(fp);
|
||||
auto op_read_dp_w(fp);
|
||||
auto op_read_dpr_b(fp, Reg16&);
|
||||
auto op_read_dpr_w(fp, Reg16&);
|
||||
auto op_read_idp_b(fp);
|
||||
auto op_read_idp_w(fp);
|
||||
auto op_read_idpx_b(fp);
|
||||
auto op_read_idpx_w(fp);
|
||||
auto op_read_idpy_b(fp);
|
||||
auto op_read_idpy_w(fp);
|
||||
auto op_read_ildp_b(fp);
|
||||
auto op_read_ildp_w(fp);
|
||||
auto op_read_ildpy_b(fp);
|
||||
auto op_read_ildpy_w(fp);
|
||||
auto op_read_sr_b(fp);
|
||||
auto op_read_sr_w(fp);
|
||||
auto op_read_isry_b(fp);
|
||||
auto op_read_isry_w(fp);
|
||||
//instructions-write.cpp
|
||||
auto instructionBankWrite8(uint16&) -> void;
|
||||
auto instructionBankWrite16(uint16&) -> void;
|
||||
auto instructionBankWrite8(uint16&, uint16) -> void;
|
||||
auto instructionBankWrite16(uint16&, uint16) -> void;
|
||||
auto instructionLongWrite8(uint16 = 0) -> void;
|
||||
auto instructionLongWrite16(uint16 = 0) -> void;
|
||||
auto instructionDirectWrite8(uint16&) -> void;
|
||||
auto instructionDirectWrite16(uint16&) -> void;
|
||||
auto instructionDirectWrite8(uint16&, uint16) -> void;
|
||||
auto instructionDirectWrite16(uint16&, uint16) -> void;
|
||||
auto instructionIndirectWrite8() -> void;
|
||||
auto instructionIndirectWrite16() -> void;
|
||||
auto instructionIndexedIndirectWrite8() -> void;
|
||||
auto instructionIndexedIndirectWrite16() -> void;
|
||||
auto instructionIndirectIndexedWrite8() -> void;
|
||||
auto instructionIndirectIndexedWrite16() -> void;
|
||||
auto instructionIndirectLongWrite8(uint16 = 0) -> void;
|
||||
auto instructionIndirectLongWrite16(uint16 = 0) -> void;
|
||||
auto instructionStackWrite8() -> void;
|
||||
auto instructionStackWrite16() -> void;
|
||||
auto instructionIndirectStackWrite8() -> void;
|
||||
auto instructionIndirectStackWrite16() -> void;
|
||||
|
||||
//opcode_write.cpp
|
||||
auto op_write_addr_b(Reg16&);
|
||||
auto op_write_addr_w(Reg16&);
|
||||
auto op_write_addrr_b(Reg16&, Reg16&);
|
||||
auto op_write_addrr_w(Reg16&, Reg16&);
|
||||
auto op_write_longr_b(Reg16&);
|
||||
auto op_write_longr_w(Reg16&);
|
||||
auto op_write_dp_b(Reg16&);
|
||||
auto op_write_dp_w(Reg16&);
|
||||
auto op_write_dpr_b(Reg16&, Reg16&);
|
||||
auto op_write_dpr_w(Reg16&, Reg16&);
|
||||
auto op_sta_idp_b();
|
||||
auto op_sta_idp_w();
|
||||
auto op_sta_ildp_b();
|
||||
auto op_sta_ildp_w();
|
||||
auto op_sta_idpx_b();
|
||||
auto op_sta_idpx_w();
|
||||
auto op_sta_idpy_b();
|
||||
auto op_sta_idpy_w();
|
||||
auto op_sta_ildpy_b();
|
||||
auto op_sta_ildpy_w();
|
||||
auto op_sta_sr_b();
|
||||
auto op_sta_sr_w();
|
||||
auto op_sta_isry_b();
|
||||
auto op_sta_isry_w();
|
||||
//instructions-modify.cpp
|
||||
auto instructionINCImplied8(uint16&) -> void;
|
||||
auto instructionINCImplied16(uint16&) -> void;
|
||||
auto instructionDECImplied8(uint16&) -> void;
|
||||
auto instructionDECImplied16(uint16&) -> void;
|
||||
auto instructionASLImplied8() -> void;
|
||||
auto instructionASLImplied16() -> void;
|
||||
auto instructionLSRImplied8() -> void;
|
||||
auto instructionLSRImplied16() -> void;
|
||||
auto instructionROLImplied8() -> void;
|
||||
auto instructionROLImplied16() -> void;
|
||||
auto instructionRORImplied8() -> void;
|
||||
auto instructionRORImplied16() -> void;
|
||||
auto instructionBankModify8(fp op) -> void;
|
||||
auto instructionBankModify16(fp op) -> void;
|
||||
auto instructionBankIndexedModify8(fp op) -> void;
|
||||
auto instructionBankIndexedModify16(fp op) -> void;
|
||||
auto instructionDirectModify8(fp op) -> void;
|
||||
auto instructionDirectModify16(fp op) -> void;
|
||||
auto instructionDirectIndexedModify8(fp op) -> void;
|
||||
auto instructionDirectIndexedModify16(fp op) -> void;
|
||||
|
||||
//opcode_rmw.cpp
|
||||
auto op_adjust_imm_b(Reg16&, int);
|
||||
auto op_adjust_imm_w(Reg16&, int);
|
||||
auto op_asl_imm_b();
|
||||
auto op_asl_imm_w();
|
||||
auto op_lsr_imm_b();
|
||||
auto op_lsr_imm_w();
|
||||
auto op_rol_imm_b();
|
||||
auto op_rol_imm_w();
|
||||
auto op_ror_imm_b();
|
||||
auto op_ror_imm_w();
|
||||
auto op_adjust_addr_b(fp op);
|
||||
auto op_adjust_addr_w(fp op);
|
||||
auto op_adjust_addrx_b(fp op);
|
||||
auto op_adjust_addrx_w(fp op);
|
||||
auto op_adjust_dp_b(fp op);
|
||||
auto op_adjust_dp_w(fp op);
|
||||
auto op_adjust_dpx_b(fp op);
|
||||
auto op_adjust_dpx_w(fp op);
|
||||
//instructions-pc.cpp
|
||||
auto instructionBranch(bool take = 1) -> void;
|
||||
auto instructionBRL() -> void;
|
||||
auto instructionJMPShort() -> void;
|
||||
auto instructionJMPLong() -> void;
|
||||
auto instructionJMPIndirect() -> void;
|
||||
auto instructionJMPIndexedIndirect() -> void;
|
||||
auto instructionJMPIndirectLong() -> void;
|
||||
auto instructionJSRShort() -> void;
|
||||
auto instructionJSRLong() -> void;
|
||||
auto instructionJSRIndexedIndirect() -> void;
|
||||
auto instructionRTI() -> void;
|
||||
auto instructionRTS() -> void;
|
||||
auto instructionRTL() -> void;
|
||||
|
||||
//opcode_pc.cpp
|
||||
auto op_branch(bool flag, bool value);
|
||||
auto op_bra();
|
||||
auto op_brl();
|
||||
auto op_jmp_addr();
|
||||
auto op_jmp_long();
|
||||
auto op_jmp_iaddr();
|
||||
auto op_jmp_iaddrx();
|
||||
auto op_jmp_iladdr();
|
||||
auto op_jsr_addr();
|
||||
auto op_jsr_long();
|
||||
auto op_jsr_iaddrx();
|
||||
auto op_rti();
|
||||
auto op_rts();
|
||||
auto op_rtl();
|
||||
//instructions-misc.cpp
|
||||
auto instructionBITImmediate8() -> void;
|
||||
auto instructionBITImmediate16() -> void;
|
||||
auto instructionNOP() -> void;
|
||||
auto instructionWDM() -> void;
|
||||
auto instructionXBA() -> void;
|
||||
auto instructionBlockMove8(int adjust) -> void;
|
||||
auto instructionBlockMove16(int adjust) -> void;
|
||||
auto instructionInterrupt(uint16) -> void;
|
||||
auto instructionSTP() -> void;
|
||||
auto instructionWAI() -> void;
|
||||
auto instructionXCE() -> void;
|
||||
auto instructionSetFlag(bool& flag) -> void;
|
||||
auto instructionClearFlag(bool& flag) -> void;
|
||||
auto instructionREP() -> void;
|
||||
auto instructionSEP() -> void;
|
||||
auto instructionTransfer8(uint16&, uint16&) -> void;
|
||||
auto instructionTransfer16(uint16&, uint16&) -> void;
|
||||
auto instructionTCS() -> void;
|
||||
auto instructionTSX8() -> void;
|
||||
auto instructionTSX16() -> void;
|
||||
auto instructionTXS() -> void;
|
||||
auto instructionPush8(uint16&) -> void;
|
||||
auto instructionPush16(uint16&) -> void;
|
||||
auto instructionPHD() -> void;
|
||||
auto instructionPHB() -> void;
|
||||
auto instructionPHK() -> void;
|
||||
auto instructionPHP() -> void;
|
||||
auto instructionPull8(uint16&) -> void;
|
||||
auto instructionPull16(uint16&) -> void;
|
||||
auto instructionPLD() -> void;
|
||||
auto instructionPLB() -> void;
|
||||
auto instructionPLP() -> void;
|
||||
auto instructionPEA() -> void;
|
||||
auto instructionPEI() -> void;
|
||||
auto instructionPER() -> void;
|
||||
|
||||
//opcode_misc.cpp
|
||||
auto op_nop();
|
||||
auto op_wdm();
|
||||
auto op_xba();
|
||||
auto op_move_b(int adjust);
|
||||
auto op_move_w(int adjust);
|
||||
auto op_interrupt(uint16);
|
||||
auto op_stp() -> void;
|
||||
auto op_wai() -> void;
|
||||
auto op_xce();
|
||||
auto op_set_flag(uint bit);
|
||||
auto op_clear_flag(uint bit);
|
||||
auto op_pflag(bool);
|
||||
auto op_transfer_b(Reg16&, Reg16&);
|
||||
auto op_transfer_w(Reg16&, Reg16&);
|
||||
auto op_tcs();
|
||||
auto op_tsx_b();
|
||||
auto op_tsx_w();
|
||||
auto op_txs();
|
||||
auto op_push_b(Reg16&);
|
||||
auto op_push_w(Reg16&);
|
||||
auto op_phd();
|
||||
auto op_phb();
|
||||
auto op_phk();
|
||||
auto op_php();
|
||||
auto op_pull_b(Reg16&);
|
||||
auto op_pull_w(Reg16&);
|
||||
auto op_pld();
|
||||
auto op_plb();
|
||||
auto op_plp();
|
||||
auto op_pea();
|
||||
auto op_pei();
|
||||
auto op_per();
|
||||
|
||||
//switch.cpp
|
||||
//instruction.cpp
|
||||
auto instruction() -> void;
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
//disassembler.cpp
|
||||
auto disassemble() -> string;
|
||||
auto disassemble(uint24 addr, bool e, bool m, bool x) -> string;
|
||||
auto dreadb(uint24 addr) -> uint8;
|
||||
auto dreadw(uint24 addr) -> uint16;
|
||||
auto dreadl(uint24 addr) -> uint24;
|
||||
auto decode(uint8 mode, uint24 addr) -> uint24;
|
||||
|
||||
struct Flags {
|
||||
bool c; //carry
|
||||
bool z; //zero
|
||||
bool i; //interrupt disable
|
||||
bool d; //decimal mode
|
||||
bool x; //index register mode
|
||||
bool m; //accumulator mode
|
||||
bool v; //overflow
|
||||
bool n; //negative
|
||||
|
||||
inline operator uint() const {
|
||||
return c << 0 | z << 1 | i << 2 | d << 3 | x << 4 | m << 5 | 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);
|
||||
x = data.bit(4);
|
||||
m = data.bit(5);
|
||||
v = data.bit(6);
|
||||
n = data.bit(7);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
union Word {
|
||||
Word() : w(0) {}
|
||||
uint16 w;
|
||||
struct { uint8_t order_lsb2(l, h); };
|
||||
};
|
||||
|
||||
union Long {
|
||||
Long() : d(0) {}
|
||||
uint32 d;
|
||||
struct { uint16_t order_lsb2(w, wh); };
|
||||
struct { uint8_t order_lsb4(l, h, b, bh); };
|
||||
};
|
||||
|
||||
struct Registers {
|
||||
Long pc;
|
||||
Word a;
|
||||
Word x;
|
||||
Word y;
|
||||
Word z;
|
||||
Word s;
|
||||
Word d;
|
||||
Flags p;
|
||||
uint8 db = 0;
|
||||
bool e = false;
|
||||
|
||||
bool irq = false; //IRQ pin (0 = low, 1 = trigger)
|
||||
bool wai = false; //raised during wai, cleared after interrupt triggered
|
||||
bool stp = false; //raised during stp, never cleared
|
||||
uint8 mdr = 0; //memory data register
|
||||
uint16 vector = 0; //interrupt vector address
|
||||
};
|
||||
|
||||
Registers r;
|
||||
Reg24 aa, rd;
|
||||
Long aa, rd;
|
||||
uint8 sp, dp;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ auto Z80::power() -> void {
|
|||
memory::fill(&r, sizeof(Registers));
|
||||
r.hlp = &r.hl;
|
||||
bus->request(false);
|
||||
bus->grant(false);
|
||||
bus->grant(true);
|
||||
}
|
||||
|
||||
auto Z80::irq(bool maskable, uint16 pc, uint8 extbus) -> bool {
|
||||
|
|
|
@ -14,8 +14,8 @@ auto SA1::Enter() -> void {
|
|||
}
|
||||
|
||||
auto SA1::main() -> void {
|
||||
if(r.wai) return op_wai();
|
||||
if(r.stp) return op_stp();
|
||||
if(r.wai) return instructionWAI();
|
||||
if(r.stp) return instructionSTP();
|
||||
|
||||
if(mmio.sa1_rdyb || mmio.sa1_resb) {
|
||||
//SA-1 co-processor is asleep
|
||||
|
@ -37,14 +37,14 @@ auto SA1::main() -> void {
|
|||
auto SA1::interrupt() -> void {
|
||||
read(r.pc.d);
|
||||
idle();
|
||||
if(!r.e) writeSP(r.pc.b);
|
||||
writeSP(r.pc.h);
|
||||
writeSP(r.pc.l);
|
||||
writeSP(r.e ? (r.p & ~0x10) : r.p);
|
||||
r.pc.w = r.vector;
|
||||
r.pc.b = 0x00;
|
||||
if(!r.e) push(r.pc.b);
|
||||
push(r.pc.h);
|
||||
push(r.pc.l);
|
||||
push(r.e ? r.p & ~0x10 : r.p);
|
||||
r.p.i = 1;
|
||||
r.p.d = 0;
|
||||
r.pc.w = r.vector;
|
||||
r.pc.b = 0x00;
|
||||
}
|
||||
|
||||
auto SA1::lastCycle() -> void {
|
||||
|
@ -131,6 +131,7 @@ auto SA1::unload() -> void {
|
|||
}
|
||||
|
||||
auto SA1::power() -> void {
|
||||
WDC65816::power();
|
||||
create(SA1::Enter, system.colorburst() * 6.0);
|
||||
|
||||
cpubwram.dma = false;
|
||||
|
@ -138,20 +139,6 @@ auto SA1::power() -> void {
|
|||
iram.write(addr, 0x00);
|
||||
}
|
||||
|
||||
r.pc.d = 0x000000;
|
||||
r.a = 0x0000;
|
||||
r.x = 0x0000;
|
||||
r.y = 0x0000;
|
||||
r.s = 0x01ff;
|
||||
r.d = 0x0000;
|
||||
r.db = 0x00;
|
||||
r.p = 0x34;
|
||||
r.e = 1;
|
||||
r.mdr = 0x00;
|
||||
r.wai = false;
|
||||
r.stp = false;
|
||||
r.vector = 0x0000;
|
||||
|
||||
status.counter = 0;
|
||||
|
||||
status.interruptPending = false;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
struct SA1 : Processor::R65816, Thread {
|
||||
struct SA1 : Processor::WDC65816, Thread {
|
||||
//sa1.cpp
|
||||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
auto SA1::serialize(serializer& s) -> void {
|
||||
R65816::serialize(s);
|
||||
WDC65816::serialize(s);
|
||||
Thread::serialize(s);
|
||||
|
||||
s.array(iram.data(), iram.size());
|
||||
|
|
|
@ -24,8 +24,8 @@ auto CPU::Enter() -> void {
|
|||
}
|
||||
|
||||
auto CPU::main() -> void {
|
||||
if(r.wai) return op_wai();
|
||||
if(r.stp) return op_stp();
|
||||
if(r.wai) return instructionWAI();
|
||||
if(r.stp) return instructionSTP();
|
||||
|
||||
if(status.interruptPending) {
|
||||
status.interruptPending = false;
|
||||
|
@ -59,6 +59,7 @@ auto CPU::load(Markup::Node node) -> bool {
|
|||
}
|
||||
|
||||
auto CPU::power() -> void {
|
||||
WDC65816::power();
|
||||
create(Enter, system.colorburst() * 6.0);
|
||||
coprocessors.reset();
|
||||
PPUcounter::reset();
|
||||
|
@ -85,21 +86,6 @@ auto CPU::power() -> void {
|
|||
|
||||
for(auto& byte : wram) byte = random(0x55);
|
||||
|
||||
//CPU
|
||||
r.pc = 0x000000;
|
||||
r.a = 0x0000;
|
||||
r.x = 0x0000;
|
||||
r.y = 0x0000;
|
||||
r.s = 0x01ff;
|
||||
r.d = 0x0000;
|
||||
r.db = 0x00;
|
||||
r.p = 0x34;
|
||||
r.e = 1;
|
||||
r.mdr = 0x00;
|
||||
r.wai = false;
|
||||
r.stp = false;
|
||||
r.vector = 0xfffc; //reset vector address
|
||||
|
||||
//DMA
|
||||
for(auto& channel : this->channel) {
|
||||
channel.dmaEnabled = false;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
struct CPU : Processor::R65816, Thread, PPUcounter {
|
||||
struct CPU : Processor::WDC65816, Thread, PPUcounter {
|
||||
auto interruptPending() const -> bool override;
|
||||
auto pio() const -> uint8;
|
||||
auto joylatch() const -> bool;
|
||||
|
|
|
@ -17,10 +17,12 @@ auto CPU::read(uint24 addr) -> uint8 {
|
|||
status.clockCount = speed(addr);
|
||||
dmaEdge();
|
||||
step(status.clockCount - 4);
|
||||
r.mdr = bus.read(addr, r.mdr);
|
||||
auto data = bus.read(addr, r.mdr);
|
||||
step(4);
|
||||
aluEdge();
|
||||
return r.mdr;
|
||||
//$00-3f,80-bf:4000-43ff reads are internal to CPU, and do not update the MDR
|
||||
if((addr & 0x40fc00) != 0x4000) r.mdr = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
auto CPU::write(uint24 addr, uint8 data) -> void {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
auto CPU::serialize(serializer& s) -> void {
|
||||
R65816::serialize(s);
|
||||
WDC65816::serialize(s);
|
||||
Thread::serialize(s);
|
||||
PPUcounter::serialize(s);
|
||||
|
||||
|
|
Loading…
Reference in New Issue