Update to v102r26 release.

byuu says:

Changelog:

  - md/ym2612: initialize DAC sample to center volume [Cydrak]
  - processor/arm: add accumulate mode extra cycle to mlal [Jonas
    Quinn]
  - processor/huc6280: split off algorithms, improve naming of functions
  - processor/mos6502: split off algorithms
  - processor/spc700: major revamp of entire core (~50% completed)
  - processor/wdc65816: fixed several bugs introduced by rewrite

For the SPC700, this turns out to be very old code as well, with global
object state variables, those annoying `{Boolean,Natural}BitField` types,
`under_case` naming conventions, heavily abbreviated function names, etc.
I'm working to get the code to be in the same design as the MOS6502,
HuC6280, WDC65816 cores, since they're all extremely similar in terms of
architectural design (the SPC700 is more of an off-label
reimplementation of a 6502 core, but still.)

The main thing left is that about 90% of the actual instructions still
need to be adapted to not use the internal state (`aa`, `rd`, `dp`,
`sp`, `bit` variables.) I wanted to finish this today, but ran out of
time before work.

I wouldn't suggest too much testing just yet. We should wait until the
SPC700 core is finished for that. However, if some does want to and
spots regressions, please let me know.
This commit is contained in:
Tim Allen 2017-06-16 10:06:17 +10:00
parent b73d918776
commit 50411a17d1
29 changed files with 1643 additions and 1544 deletions

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "higan"; static const string Name = "higan";
static const string Version = "102.25"; static const string Version = "102.26";
static const string Author = "byuu"; static const string Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";

View File

@ -32,7 +32,7 @@ private:
struct DAC { struct DAC {
uint1 enable = 0; uint1 enable = 0;
uint8 sample = 0; uint8 sample = 0x80;
} dac; } dac;
struct Envelope { struct Envelope {

View File

@ -108,6 +108,7 @@ auto ARM::arm_op_multiply_long() {
idle(); idle();
idle(); idle();
if(accumulate) idle();
//this instruction uses an 8-bit Booth algorithm for multiplication //this instruction uses an 8-bit Booth algorithm for multiplication
//this supports short-circuiting, so that smaller numbers multiply faster //this supports short-circuiting, so that smaller numbers multiply faster

View File

@ -0,0 +1,184 @@
auto HuC6280::algorithmADC(uint8 i) -> uint8 {
int16 o;
if(!D) {
o = A + i + C;
V = ~(A ^ i) & (A ^ o) & 0x80;
} else {
io();
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
if(o > 0x09) o += 0x06;
C = o > 0x0f;
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
if(o > 0x9f) o += 0x60;
}
C = o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return o;
}
auto HuC6280::algorithmAND(uint8 i) -> uint8 {
uint8 o = A & i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto HuC6280::algorithmASL(uint8 i) -> uint8 {
C = i.bit(7);
i <<= 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::algorithmBIT(uint8 i) -> uint8 {
Z = (A & i) == 0;
V = i.bit(6);
N = i.bit(7);
return A;
}
auto HuC6280::algorithmCMP(uint8 i) -> uint8 {
uint9 o = A - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return A;
}
auto HuC6280::algorithmCPX(uint8 i) -> uint8 {
uint9 o = X - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return X;
}
auto HuC6280::algorithmCPY(uint8 i) -> uint8 {
uint9 o = Y - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return Y;
}
auto HuC6280::algorithmDEC(uint8 i) -> uint8 {
i--;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::algorithmEOR(uint8 i) -> uint8 {
uint8 o = A ^ i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto HuC6280::algorithmINC(uint8 i) -> uint8 {
i++;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::algorithmLD(uint8 i) -> uint8 {
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::algorithmLSR(uint8 i) -> uint8 {
C = i.bit(0);
i >>= 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::algorithmORA(uint8 i) -> uint8 {
uint8 o = A | i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto HuC6280::algorithmROL(uint8 i) -> uint8 {
bool c = C;
C = i.bit(7);
i = i << 1 | c;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::algorithmROR(uint8 i) -> uint8 {
bool c = C;
C = i.bit(0);
i = c << 7 | i >> 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::algorithmSBC(uint8 i) -> uint8 {
i ^= 0xff;
int16 o;
if(!D) {
o = A + i + C;
V = ~(A ^ i) & (A ^ o) & 0x80;
} else {
io();
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
if(o <= 0x0f) o -= 0x06;
C = o > 0x0f;
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
if(o <= 0xff) o -= 0x60;
}
C = o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return o;
}
auto HuC6280::algorithmTRB(uint8 i) -> uint8 {
Z = (A & i) == 0;
V = i.bit(6);
N = i.bit(7);
return ~A & i;
}
auto HuC6280::algorithmTSB(uint8 i) -> uint8 {
Z = (A & i) == 0;
V = i.bit(6);
N = i.bit(7);
return A | i;
}
//
auto HuC6280::algorithmTAI(uint16& source, uint16& target, bool alternate) -> void {
!alternate ? source++ : source--;
target++;
}
auto HuC6280::algorithmTDD(uint16& source, uint16& target, bool) -> void {
source--;
target--;
}
auto HuC6280::algorithmTIA(uint16& source, uint16& target, bool alternate) -> void {
source++;
!alternate ? target++ : target--;
}
auto HuC6280::algorithmTII(uint16& source, uint16& target, bool) -> void {
source++;
target++;
}
auto HuC6280::algorithmTIN(uint16& source, uint16& target, bool) -> void {
source++;
}

View File

@ -24,6 +24,7 @@ namespace Processor {
#define ALU (this->*alu) #define ALU (this->*alu)
#include "memory.cpp" #include "memory.cpp"
#include "algorithms.cpp"
#include "instruction.cpp" #include "instruction.cpp"
#include "instructions.cpp" #include "instructions.cpp"
#include "disassembler.cpp" #include "disassembler.cpp"

View File

@ -27,82 +27,83 @@ struct HuC6280 {
auto push(uint8) -> void; auto push(uint8) -> void;
auto pull() -> uint8; auto pull() -> uint8;
//instructions.cpp
using fp = auto (HuC6280::*)(uint8) -> uint8;
auto algorithmADC(uint8) -> uint8;
auto algorithmAND(uint8) -> uint8;
auto algorithmASL(uint8) -> uint8;
auto algorithmBIT(uint8) -> uint8;
auto algorithmCMP(uint8) -> uint8;
auto algorithmCPX(uint8) -> uint8;
auto algorithmCPY(uint8) -> uint8;
auto algorithmDEC(uint8) -> uint8;
auto algorithmEOR(uint8) -> uint8;
auto algorithmINC(uint8) -> uint8;
auto algorithmLD (uint8) -> uint8;
auto algorithmLSR(uint8) -> uint8;
auto algorithmORA(uint8) -> uint8;
auto algorithmROL(uint8) -> uint8;
auto algorithmROR(uint8) -> uint8;
auto algorithmSBC(uint8) -> uint8;
auto algorithmTRB(uint8) -> uint8;
auto algorithmTSB(uint8) -> uint8;
using bp = auto (HuC6280::*)(uint16&, uint16&, bool) -> void;
auto algorithmTAI(uint16&, uint16&, bool) -> void;
auto algorithmTDD(uint16&, uint16&, bool) -> void;
auto algorithmTIA(uint16&, uint16&, bool) -> void;
auto algorithmTII(uint16&, uint16&, bool) -> void;
auto algorithmTIN(uint16&, uint16&, bool) -> void;
//instruction.cpp //instruction.cpp
auto interrupt(uint16 vector) -> void; auto interrupt(uint16 vector) -> void;
auto instruction() -> void; auto instruction() -> void;
//instructions.cpp //instructions.cpp
using fp = auto (HuC6280::*)(uint8) -> uint8; auto instructionAbsoluteModify(fp, uint8 = 0) -> void;
auto ADC(uint8) -> uint8; auto instructionAbsoluteRead(fp, uint8&, uint8 = 0) -> void;
auto AND(uint8) -> uint8; auto instructionAbsoluteWrite(uint8, uint8 = 0) -> void;
auto ASL(uint8) -> uint8; auto instructionBlockMove(bp) -> void;
auto BIT(uint8) -> uint8; auto instructionBranch(bool) -> void;
auto CMP(uint8) -> uint8; auto instructionClear(uint8&) -> void;
auto CPX(uint8) -> uint8; auto instructionClear(bool&) -> void;
auto CPY(uint8) -> uint8; auto instructionImmediate(fp, uint8&) -> void;
auto DEC(uint8) -> uint8; auto instructionImplied(fp, uint8&) -> void;
auto EOR(uint8) -> uint8; auto instructionIndirectRead(fp, uint8&, uint8 = 0) -> void;
auto INC(uint8) -> uint8; auto instructionIndirectWrite(uint8, uint8 = 0) -> void;
auto LD (uint8) -> uint8; auto instructionIndirectYRead(fp, uint8&) -> void;
auto LSR(uint8) -> uint8; auto instructionIndirectYWrite(uint8) -> void;
auto ORA(uint8) -> uint8; auto instructionMemory(fp) -> void;
auto ROL(uint8) -> uint8; auto instructionPull(uint8&) -> void;
auto ROR(uint8) -> uint8; auto instructionPush(uint8) -> void;
auto SBC(uint8) -> uint8; auto instructionSet(bool&) -> void;
auto TRB(uint8) -> uint8; auto instructionSwap(uint8&, uint8&) -> void;
auto TSB(uint8) -> uint8; auto instructionTransfer(uint8&, uint8&) -> void;
auto instructionZeroPageModify(fp, uint8 = 0) -> void;
auto instructionZeroPageRead(fp, uint8&, uint8 = 0) -> void;
auto instructionZeroPageWrite(uint8, uint8 = 0) -> void;
using bp = auto (HuC6280::*)(uint16&, uint16&, bool) -> void; auto instructionBBR(uint3) -> void;
auto TAI(uint16&, uint16&, bool) -> void; auto instructionBBS(uint3) -> void;
auto TDD(uint16&, uint16&, bool) -> void; auto instructionBRK() -> void;
auto TIA(uint16&, uint16&, bool) -> void; auto instructionBSR() -> void;
auto TII(uint16&, uint16&, bool) -> void; auto instructionCSL() -> void;
auto TIN(uint16&, uint16&, bool) -> void; auto instructionCSH() -> void;
auto instructionJMPAbsolute() -> void;
auto instruction_absoluteLoad(fp, uint8&, uint8 = 0) -> void; auto instructionJMPIndirect(uint8 = 0) -> void;
auto instruction_absoluteModify(fp, uint8 = 0) -> void; auto instructionJSR() -> void;
auto instruction_absoluteStore(uint8, uint8 = 0) -> void; auto instructionNOP() -> void;
auto instruction_blockmove(bp) -> void; auto instructionPLP() -> void;
auto instruction_branch(bool) -> void; auto instructionRMB(uint3) -> void;
auto instruction_clear(uint8&) -> void; auto instructionRTI() -> void;
auto instruction_clear(bool&) -> void; auto instructionRTS() -> void;
auto instruction_immediate(fp, uint8&) -> void; auto instructionSMB(uint3) -> void;
auto instruction_implied(fp, uint8&) -> void; auto instructionST(uint2) -> void;
auto instruction_indirectLoad(fp, uint8&, uint8 = 0) -> void; auto instructionTAM() -> void;
auto instruction_indirectStore(uint8, uint8 = 0) -> void; auto instructionTMA() -> void;
auto instruction_indirectYLoad(fp, uint8&) -> void; auto instructionTSTAbsolute(uint8 = 0) -> void;
auto instruction_indirectYStore(uint8) -> void; auto instructionTSTZeroPage(uint8 = 0) -> void;
auto instruction_memory(fp) -> void; auto instructionTXS() -> void;
auto instruction_pull(uint8&) -> void;
auto instruction_push(uint8) -> void;
auto instruction_set(bool&) -> void;
auto instruction_swap(uint8&, uint8&) -> void;
auto instruction_transfer(uint8&, uint8&) -> void;
auto instruction_zeropageLoad(fp, uint8&, uint8 = 0) -> void;
auto instruction_zeropageModify(fp, uint8 = 0) -> void;
auto instruction_zeropageStore(uint8, uint8 = 0) -> void;
auto instruction_BBR(uint3) -> void;
auto instruction_BBS(uint3) -> void;
auto instruction_BRK() -> void;
auto instruction_BSR() -> void;
auto instruction_CSL() -> void;
auto instruction_CSH() -> void;
auto instruction_JMP_absolute() -> void;
auto instruction_JMP_indirect(uint8 = 0) -> void;
auto instruction_JSR() -> void;
auto instruction_NOP() -> void;
auto instruction_PLP() -> void;
auto instruction_RMB(uint3) -> void;
auto instruction_RTI() -> void;
auto instruction_RTS() -> void;
auto instruction_SMB(uint3) -> void;
auto instruction_ST(uint2) -> void;
auto instruction_TAM() -> void;
auto instruction_TMA() -> void;
auto instruction_TST_absolute(uint8 = 0) -> void;
auto instruction_TST_zeropage(uint8 = 0) -> void;
auto instruction_TXS() -> void;
//disassembler.cpp //disassembler.cpp
auto disassemble(uint16 pc) -> string; auto disassemble(uint16 pc) -> string;

View File

@ -1,5 +1,5 @@
#define op(id, name, ...) case id: instruction_##name(__VA_ARGS__); return; #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);
#define fp(name) &HuC6280::name #define fp(name) &HuC6280::algorithm##name
auto HuC6280::interrupt(uint16 vector) -> void { auto HuC6280::interrupt(uint16 vector) -> void {
io(); io();
@ -19,270 +19,270 @@ auto HuC6280::instruction() -> void {
if(T) { if(T) {
T = 0; T = 0;
switch(code) { switch(code) {
op(0x09, memory, fp(ORA)) op(0x09, Memory, fp(ORA))
op(0x29, memory, fp(AND)) op(0x29, Memory, fp(AND))
op(0x49, memory, fp(EOR)) op(0x49, Memory, fp(EOR))
op(0x69, memory, fp(ADC)) op(0x69, Memory, fp(ADC))
} }
} }
#define U #define U
switch(code) { switch(code) {
op(0x00, BRK) op(0x00, BRK)
op(0x01, indirectLoad, fp(ORA), A, X) op(0x01, IndirectRead, fp(ORA), A, X)
op(0x02, swap, X, Y) op(0x02, Swap, X, Y)
op(0x03, ST, 0) op(0x03, ST, 0)
op(0x04, zeropageModify, fp(TSB)) op(0x04, ZeroPageModify, fp(TSB))
op(0x05, zeropageLoad, fp(ORA), A) op(0x05, ZeroPageRead, fp(ORA), A)
op(0x06, zeropageModify, fp(ASL)) op(0x06, ZeroPageModify, fp(ASL))
op(0x07, RMB, 0) op(0x07, RMB, 0)
op(0x08, push, P) op(0x08, Push, P)
op(0x09, immediate, fp(ORA), A) op(0x09, Immediate, fp(ORA), A)
op(0x0a, implied, fp(ASL), A) op(0x0a, Implied, fp(ASL), A)
U op(0x0b, NOP) U op(0x0b, NOP)
op(0x0c, absoluteModify, fp(TSB)) op(0x0c, AbsoluteModify, fp(TSB))
op(0x0d, absoluteLoad, fp(ORA), A) op(0x0d, AbsoluteRead, fp(ORA), A)
op(0x0e, absoluteModify, fp(ASL)) op(0x0e, AbsoluteModify, fp(ASL))
op(0x0f, BBR, 0) op(0x0f, BBR, 0)
op(0x10, branch, N == 0) op(0x10, Branch, N == 0)
op(0x11, indirectYLoad, fp(ORA), A) op(0x11, IndirectYRead, fp(ORA), A)
op(0x12, indirectLoad, fp(ORA), A) op(0x12, IndirectRead, fp(ORA), A)
op(0x13, ST, 1) op(0x13, ST, 1)
op(0x14, zeropageModify, fp(TRB)) op(0x14, ZeroPageModify, fp(TRB))
op(0x15, zeropageLoad, fp(ORA), A, X) op(0x15, ZeroPageRead, fp(ORA), A, X)
op(0x16, zeropageModify, fp(ASL), X) op(0x16, ZeroPageModify, fp(ASL), X)
op(0x17, RMB, 1) op(0x17, RMB, 1)
op(0x18, clear, C) op(0x18, Clear, C)
op(0x19, absoluteLoad, fp(ORA), A, Y) op(0x19, AbsoluteRead, fp(ORA), A, Y)
op(0x1a, implied, fp(INC), A) op(0x1a, Implied, fp(INC), A)
U op(0x1b, NOP) U op(0x1b, NOP)
op(0x1c, absoluteModify, fp(TRB)) op(0x1c, AbsoluteModify, fp(TRB))
op(0x1d, absoluteLoad, fp(ORA), A, X) op(0x1d, AbsoluteRead, fp(ORA), A, X)
op(0x1e, absoluteModify, fp(ASL), X) op(0x1e, AbsoluteModify, fp(ASL), X)
op(0x1f, BBR, 1) op(0x1f, BBR, 1)
op(0x20, JSR) op(0x20, JSR)
op(0x21, indirectLoad, fp(AND), A, X) op(0x21, IndirectRead, fp(AND), A, X)
op(0x22, swap, A, X) op(0x22, Swap, A, X)
op(0x23, ST, 2) op(0x23, ST, 2)
op(0x24, zeropageLoad, fp(BIT), A) op(0x24, ZeroPageRead, fp(BIT), A)
op(0x25, zeropageLoad, fp(AND), A) op(0x25, ZeroPageRead, fp(AND), A)
op(0x26, zeropageModify, fp(ROL)) op(0x26, ZeroPageModify, fp(ROL))
op(0x27, RMB, 2) op(0x27, RMB, 2)
op(0x28, PLP) op(0x28, PLP)
op(0x29, immediate, fp(AND), A) op(0x29, Immediate, fp(AND), A)
op(0x2a, implied, fp(ROL), A) op(0x2a, Implied, fp(ROL), A)
U op(0x2b, NOP) U op(0x2b, NOP)
op(0x2c, absoluteLoad, fp(BIT), A) op(0x2c, AbsoluteRead, fp(BIT), A)
op(0x2d, absoluteLoad, fp(AND), A) op(0x2d, AbsoluteRead, fp(AND), A)
op(0x2e, absoluteModify, fp(ROL)) op(0x2e, AbsoluteModify, fp(ROL))
op(0x2f, BBR, 2) op(0x2f, BBR, 2)
op(0x30, branch, N == 1) op(0x30, Branch, N == 1)
op(0x31, indirectYLoad, fp(AND), A) op(0x31, IndirectYRead, fp(AND), A)
op(0x32, indirectLoad, fp(AND), A) op(0x32, IndirectRead, fp(AND), A)
U op(0x33, NOP) U op(0x33, NOP)
op(0x34, zeropageLoad, fp(BIT), A, X) op(0x34, ZeroPageRead, fp(BIT), A, X)
op(0x35, zeropageLoad, fp(AND), A, X) op(0x35, ZeroPageRead, fp(AND), A, X)
op(0x36, zeropageModify, fp(ROL), X) op(0x36, ZeroPageModify, fp(ROL), X)
op(0x37, RMB, 3) op(0x37, RMB, 3)
op(0x38, set, C) op(0x38, Set, C)
op(0x39, absoluteLoad, fp(AND), A, Y) op(0x39, AbsoluteRead, fp(AND), A, Y)
op(0x3a, implied, fp(DEC), A) op(0x3a, Implied, fp(DEC), A)
U op(0x3b, NOP) U op(0x3b, NOP)
op(0x3c, absoluteLoad, fp(BIT), A, X) op(0x3c, AbsoluteRead, fp(BIT), A, X)
op(0x3d, absoluteLoad, fp(AND), A, X) op(0x3d, AbsoluteRead, fp(AND), A, X)
op(0x3e, absoluteModify, fp(ROL), X) op(0x3e, AbsoluteModify, fp(ROL), X)
op(0x3f, BBR, 3) op(0x3f, BBR, 3)
op(0x40, RTI) op(0x40, RTI)
op(0x41, indirectLoad, fp(EOR), A, X) op(0x41, IndirectRead, fp(EOR), A, X)
op(0x42, swap, A, Y) op(0x42, Swap, A, Y)
op(0x43, TMA) op(0x43, TMA)
op(0x44, BSR) op(0x44, BSR)
op(0x45, zeropageLoad, fp(EOR), A) op(0x45, ZeroPageRead, fp(EOR), A)
op(0x46, zeropageModify, fp(LSR)) op(0x46, ZeroPageModify, fp(LSR))
op(0x47, RMB, 4) op(0x47, RMB, 4)
op(0x48, push, A) op(0x48, Push, A)
op(0x49, immediate, fp(EOR), A) op(0x49, Immediate, fp(EOR), A)
op(0x4a, implied, fp(LSR), A) op(0x4a, Implied, fp(LSR), A)
U op(0x4b, NOP) U op(0x4b, NOP)
op(0x4c, JMP_absolute) op(0x4c, JMPAbsolute)
op(0x4d, absoluteLoad, fp(EOR), A) op(0x4d, AbsoluteRead, fp(EOR), A)
op(0x4e, absoluteModify, fp(LSR)) op(0x4e, AbsoluteModify, fp(LSR))
op(0x4f, BBR, 4) op(0x4f, BBR, 4)
op(0x50, branch, V == 0) op(0x50, Branch, V == 0)
op(0x51, indirectYLoad, fp(EOR), A) op(0x51, IndirectYRead, fp(EOR), A)
op(0x52, indirectLoad, fp(EOR), A) op(0x52, IndirectRead, fp(EOR), A)
op(0x53, TAM) op(0x53, TAM)
op(0x54, CSL) op(0x54, CSL)
op(0x55, zeropageLoad, fp(EOR), A, X) op(0x55, ZeroPageRead, fp(EOR), A, X)
op(0x56, zeropageModify, fp(LSR), X) op(0x56, ZeroPageModify, fp(LSR), X)
op(0x57, RMB, 5) op(0x57, RMB, 5)
op(0x58, clear, I) op(0x58, Clear, I)
op(0x59, absoluteLoad, fp(EOR), A, Y) op(0x59, AbsoluteRead, fp(EOR), A, Y)
op(0x5a, push, Y) op(0x5a, Push, Y)
U op(0x5b, NOP) U op(0x5b, NOP)
U op(0x5c, NOP) U op(0x5c, NOP)
op(0x5d, absoluteLoad, fp(EOR), A, X) op(0x5d, AbsoluteRead, fp(EOR), A, X)
op(0x5e, absoluteModify, fp(LSR), X) op(0x5e, AbsoluteModify, fp(LSR), X)
op(0x5f, BBR, 5) op(0x5f, BBR, 5)
op(0x60, RTS) op(0x60, RTS)
op(0x61, indirectLoad, fp(ADC), A, X) op(0x61, IndirectRead, fp(ADC), A, X)
op(0x62, clear, A) op(0x62, Clear, A)
U op(0x63, NOP) U op(0x63, NOP)
op(0x64, zeropageStore, 0) op(0x64, ZeroPageWrite, 0)
op(0x65, zeropageLoad, fp(ADC), A) op(0x65, ZeroPageRead, fp(ADC), A)
op(0x66, zeropageModify, fp(ROR)) op(0x66, ZeroPageModify, fp(ROR))
op(0x67, RMB, 6) op(0x67, RMB, 6)
op(0x68, pull, A) op(0x68, Pull, A)
op(0x69, immediate, fp(ADC), A) op(0x69, Immediate, fp(ADC), A)
op(0x6a, implied, fp(ROR), A) op(0x6a, Implied, fp(ROR), A)
U op(0x6b, NOP) U op(0x6b, NOP)
op(0x6c, JMP_indirect) op(0x6c, JMPIndirect)
op(0x6d, absoluteLoad, fp(ADC), A) op(0x6d, AbsoluteRead, fp(ADC), A)
op(0x6e, absoluteModify, fp(ROR)) op(0x6e, AbsoluteModify, fp(ROR))
op(0x6f, BBR, 6) op(0x6f, BBR, 6)
op(0x70, branch, V == 1) op(0x70, Branch, V == 1)
op(0x71, indirectYLoad, fp(ADC), A) op(0x71, IndirectYRead, fp(ADC), A)
op(0x72, indirectLoad, fp(ADC), A) op(0x72, IndirectRead, fp(ADC), A)
op(0x73, blockmove, fp(TII)) op(0x73, BlockMove, fp(TII))
op(0x74, zeropageStore, 0, X) op(0x74, ZeroPageWrite, 0, X)
op(0x75, zeropageLoad, fp(ADC), A, X) op(0x75, ZeroPageRead, fp(ADC), A, X)
op(0x76, zeropageModify, fp(ROR), X) op(0x76, ZeroPageModify, fp(ROR), X)
op(0x77, RMB, 7) op(0x77, RMB, 7)
op(0x78, set, I) op(0x78, Set, I)
op(0x79, absoluteLoad, fp(ADC), A, Y) op(0x79, AbsoluteRead, fp(ADC), A, Y)
op(0x7a, pull, Y) op(0x7a, Pull, Y)
U op(0x7b, NOP) U op(0x7b, NOP)
op(0x7c, JMP_indirect, X) op(0x7c, JMPIndirect, X)
op(0x7d, absoluteLoad, fp(ADC), A, X) op(0x7d, AbsoluteRead, fp(ADC), A, X)
op(0x7e, absoluteModify, fp(ROR), X) op(0x7e, AbsoluteModify, fp(ROR), X)
op(0x7f, BBR, 7) op(0x7f, BBR, 7)
op(0x80, branch, 1) op(0x80, Branch, 1)
op(0x81, indirectStore, A, X) op(0x81, IndirectWrite, A, X)
op(0x82, clear, X) op(0x82, Clear, X)
op(0x83, TST_zeropage) op(0x83, TSTZeroPage)
op(0x84, zeropageStore, Y) op(0x84, ZeroPageWrite, Y)
op(0x85, zeropageStore, A) op(0x85, ZeroPageWrite, A)
op(0x86, zeropageStore, X) op(0x86, ZeroPageWrite, X)
op(0x87, SMB, 0) op(0x87, SMB, 0)
op(0x88, implied, fp(DEC), Y) op(0x88, Implied, fp(DEC), Y)
op(0x89, immediate, fp(BIT), A) op(0x89, Immediate, fp(BIT), A)
op(0x8a, transfer, X, A) op(0x8a, Transfer, X, A)
U op(0x8b, NOP) U op(0x8b, NOP)
op(0x8c, absoluteStore, Y) op(0x8c, AbsoluteWrite, Y)
op(0x8d, absoluteStore, A) op(0x8d, AbsoluteWrite, A)
op(0x8e, absoluteStore, X) op(0x8e, AbsoluteWrite, X)
op(0x8f, BBS, 0) op(0x8f, BBS, 0)
op(0x90, branch, C == 0) op(0x90, Branch, C == 0)
op(0x91, indirectYStore, A) op(0x91, IndirectYWrite, A)
op(0x92, indirectStore, A) op(0x92, IndirectWrite, A)
op(0x93, TST_absolute) op(0x93, TSTAbsolute)
op(0x94, zeropageStore, Y, X) op(0x94, ZeroPageWrite, Y, X)
op(0x95, zeropageStore, A, X) op(0x95, ZeroPageWrite, A, X)
op(0x96, zeropageStore, X, Y) op(0x96, ZeroPageWrite, X, Y)
op(0x97, SMB, 1) op(0x97, SMB, 1)
op(0x98, transfer, Y, A) op(0x98, Transfer, Y, A)
op(0x99, absoluteStore, A, Y) op(0x99, AbsoluteWrite, A, Y)
op(0x9a, TXS) op(0x9a, TXS)
U op(0x9b, NOP) U op(0x9b, NOP)
op(0x9c, absoluteStore, 0) op(0x9c, AbsoluteWrite, 0)
op(0x9d, absoluteStore, A, X) op(0x9d, AbsoluteWrite, A, X)
op(0x9e, absoluteStore, 0, X) op(0x9e, AbsoluteWrite, 0, X)
op(0x9f, BBS, 1) op(0x9f, BBS, 1)
op(0xa0, immediate, fp(LD), Y) op(0xa0, Immediate, fp(LD), Y)
op(0xa1, indirectLoad, fp(LD), A, X) op(0xa1, IndirectRead, fp(LD), A, X)
op(0xa2, immediate, fp(LD), X) op(0xa2, Immediate, fp(LD), X)
op(0xa3, TST_zeropage, X) op(0xa3, TSTZeroPage, X)
op(0xa4, zeropageLoad, fp(LD), Y) op(0xa4, ZeroPageRead, fp(LD), Y)
op(0xa5, zeropageLoad, fp(LD), A) op(0xa5, ZeroPageRead, fp(LD), A)
op(0xa6, zeropageLoad, fp(LD), X) op(0xa6, ZeroPageRead, fp(LD), X)
op(0xa7, SMB, 2) op(0xa7, SMB, 2)
op(0xa8, transfer, A, Y) op(0xa8, Transfer, A, Y)
op(0xa9, immediate, fp(LD), A) op(0xa9, Immediate, fp(LD), A)
op(0xaa, transfer, A, X) op(0xaa, Transfer, A, X)
U op(0xab, NOP) U op(0xab, NOP)
op(0xac, absoluteLoad, fp(LD), Y) op(0xac, AbsoluteRead, fp(LD), Y)
op(0xad, absoluteLoad, fp(LD), A) op(0xad, AbsoluteRead, fp(LD), A)
op(0xae, absoluteLoad, fp(LD), X) op(0xae, AbsoluteRead, fp(LD), X)
op(0xaf, BBS, 2) op(0xaf, BBS, 2)
op(0xb0, branch, C == 1) op(0xb0, Branch, C == 1)
op(0xb1, indirectYLoad, fp(LD), A) op(0xb1, IndirectYRead, fp(LD), A)
op(0xb2, indirectLoad, fp(LD), A) op(0xb2, IndirectRead, fp(LD), A)
op(0xb3, TST_absolute, X) op(0xb3, TSTAbsolute, X)
op(0xb4, zeropageLoad, fp(LD), Y, X) op(0xb4, ZeroPageRead, fp(LD), Y, X)
op(0xb5, zeropageLoad, fp(LD), A, X) op(0xb5, ZeroPageRead, fp(LD), A, X)
op(0xb6, zeropageLoad, fp(LD), X, Y) op(0xb6, ZeroPageRead, fp(LD), X, Y)
op(0xb7, SMB, 3) op(0xb7, SMB, 3)
op(0xb8, clear, V) op(0xb8, Clear, V)
op(0xb9, absoluteLoad, fp(LD), A, Y) op(0xb9, AbsoluteRead, fp(LD), A, Y)
op(0xba, transfer, S, X) op(0xba, Transfer, S, X)
U op(0xbb, NOP) U op(0xbb, NOP)
op(0xbc, absoluteLoad, fp(LD), Y, X) op(0xbc, AbsoluteRead, fp(LD), Y, X)
op(0xbd, absoluteLoad, fp(LD), A, X) op(0xbd, AbsoluteRead, fp(LD), A, X)
op(0xbe, absoluteLoad, fp(LD), X, Y) op(0xbe, AbsoluteRead, fp(LD), X, Y)
op(0xbf, BBS, 3) op(0xbf, BBS, 3)
op(0xc0, immediate, fp(CPY), Y) op(0xc0, Immediate, fp(CPY), Y)
op(0xc1, indirectLoad, fp(CMP), A, X) op(0xc1, IndirectRead, fp(CMP), A, X)
op(0xc2, clear, Y) op(0xc2, Clear, Y)
op(0xc3, blockmove, fp(TDD)) op(0xc3, BlockMove, fp(TDD))
op(0xc4, zeropageLoad, fp(CPY), Y) op(0xc4, ZeroPageRead, fp(CPY), Y)
op(0xc5, zeropageLoad, fp(CMP), A) op(0xc5, ZeroPageRead, fp(CMP), A)
op(0xc6, zeropageModify, fp(DEC)) op(0xc6, ZeroPageModify, fp(DEC))
op(0xc7, SMB, 4) op(0xc7, SMB, 4)
op(0xc8, implied, fp(INC), Y) op(0xc8, Implied, fp(INC), Y)
op(0xc9, immediate, fp(CMP), A) op(0xc9, Immediate, fp(CMP), A)
op(0xca, implied, fp(DEC), X) op(0xca, Implied, fp(DEC), X)
U op(0xcb, NOP) U op(0xcb, NOP)
op(0xcc, absoluteLoad, fp(CPY), Y) op(0xcc, AbsoluteRead, fp(CPY), Y)
op(0xcd, absoluteLoad, fp(CMP), A) op(0xcd, AbsoluteRead, fp(CMP), A)
op(0xce, absoluteModify, fp(DEC)) op(0xce, AbsoluteModify, fp(DEC))
op(0xcf, BBS, 4) op(0xcf, BBS, 4)
op(0xd0, branch, Z == 0) op(0xd0, Branch, Z == 0)
op(0xd1, indirectYLoad, fp(CMP), A) op(0xd1, IndirectYRead, fp(CMP), A)
op(0xd2, indirectLoad, fp(CMP), A) op(0xd2, IndirectRead, fp(CMP), A)
op(0xd3, blockmove, fp(TIN)) op(0xd3, BlockMove, fp(TIN))
op(0xd4, CSH) op(0xd4, CSH)
op(0xd5, zeropageLoad, fp(CMP), A, X) op(0xd5, ZeroPageRead, fp(CMP), A, X)
op(0xd6, zeropageModify, fp(DEC), X) op(0xd6, ZeroPageModify, fp(DEC), X)
op(0xd7, SMB, 5) op(0xd7, SMB, 5)
op(0xd8, clear, D) op(0xd8, Clear, D)
op(0xd9, absoluteLoad, fp(CMP), A, Y) op(0xd9, AbsoluteRead, fp(CMP), A, Y)
op(0xda, push, X) op(0xda, Push, X)
U op(0xdb, NOP) U op(0xdb, NOP)
U op(0xdc, NOP) U op(0xdc, NOP)
op(0xdd, absoluteLoad, fp(CMP), A, X) op(0xdd, AbsoluteRead, fp(CMP), A, X)
op(0xde, absoluteModify, fp(DEC), X) op(0xde, AbsoluteModify, fp(DEC), X)
op(0xdf, BBS, 5) op(0xdf, BBS, 5)
op(0xe0, immediate, fp(CPX), X) op(0xe0, Immediate, fp(CPX), X)
op(0xe1, indirectLoad, fp(SBC), A, X) op(0xe1, IndirectRead, fp(SBC), A, X)
U op(0xe2, NOP) U op(0xe2, NOP)
op(0xe3, blockmove, fp(TIA)) op(0xe3, BlockMove, fp(TIA))
op(0xe4, zeropageLoad, fp(CPX), X) op(0xe4, ZeroPageRead, fp(CPX), X)
op(0xe5, zeropageLoad, fp(SBC), A) op(0xe5, ZeroPageRead, fp(SBC), A)
op(0xe6, zeropageModify, fp(INC)) op(0xe6, ZeroPageModify, fp(INC))
op(0xe7, SMB, 6) op(0xe7, SMB, 6)
op(0xe8, implied, fp(INC), X) op(0xe8, Implied, fp(INC), X)
op(0xe9, immediate, fp(SBC), A) op(0xe9, Immediate, fp(SBC), A)
op(0xea, NOP) op(0xea, NOP)
U op(0xeb, NOP) U op(0xeb, NOP)
op(0xec, absoluteLoad, fp(CPX), X) op(0xec, AbsoluteRead, fp(CPX), X)
op(0xed, absoluteLoad, fp(SBC), A) op(0xed, AbsoluteRead, fp(SBC), A)
op(0xee, absoluteModify, fp(INC)) op(0xee, AbsoluteModify, fp(INC))
op(0xef, BBS, 6) op(0xef, BBS, 6)
op(0xf0, branch, Z == 1) op(0xf0, Branch, Z == 1)
op(0xf1, indirectYLoad, fp(SBC), A) op(0xf1, IndirectYRead, fp(SBC), A)
op(0xf2, indirectLoad, fp(SBC), A) op(0xf2, IndirectRead, fp(SBC), A)
op(0xf3, blockmove, fp(TAI)) op(0xf3, BlockMove, fp(TAI))
op(0xf4, set, T) op(0xf4, Set, T)
op(0xf5, zeropageLoad, fp(SBC), A, X) op(0xf5, ZeroPageRead, fp(SBC), A, X)
op(0xf6, zeropageModify, fp(INC), X) op(0xf6, ZeroPageModify, fp(INC), X)
op(0xf7, SMB, 7) op(0xf7, SMB, 7)
op(0xf8, set, D) op(0xf8, Set, D)
op(0xf9, absoluteLoad, fp(SBC), A, Y) op(0xf9, AbsoluteRead, fp(SBC), A, Y)
op(0xfa, pull, X) op(0xfa, Pull, X)
U op(0xfb, NOP) U op(0xfb, NOP)
U op(0xfc, NOP) U op(0xfc, NOP)
op(0xfd, absoluteLoad, fp(SBC), A, X) op(0xfd, AbsoluteRead, fp(SBC), A, X)
op(0xfe, absoluteModify, fp(INC), X) op(0xfe, AbsoluteModify, fp(INC), X)
op(0xff, BBS, 7) op(0xff, BBS, 7)
} }
#undef U #undef U

View File

@ -1,198 +1,4 @@
auto HuC6280::ADC(uint8 i) -> uint8 { auto HuC6280::instructionAbsoluteModify(fp alu, uint8 index) -> void {
int16 o;
if(!D) {
o = A + i + C;
V = ~(A ^ i) & (A ^ o) & 0x80;
} else {
io();
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
if(o > 0x09) o += 0x06;
C = o > 0x0f;
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
if(o > 0x9f) o += 0x60;
}
C = o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return o;
}
auto HuC6280::AND(uint8 i) -> uint8 {
uint8 o = A & i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto HuC6280::ASL(uint8 i) -> uint8 {
C = i.bit(7);
i <<= 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::BIT(uint8 i) -> uint8 {
Z = (A & i) == 0;
V = i.bit(6);
N = i.bit(7);
return A;
}
auto HuC6280::CMP(uint8 i) -> uint8 {
uint9 o = A - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return A;
}
auto HuC6280::CPX(uint8 i) -> uint8 {
uint9 o = X - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return X;
}
auto HuC6280::CPY(uint8 i) -> uint8 {
uint9 o = Y - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return Y;
}
auto HuC6280::DEC(uint8 i) -> uint8 {
i--;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::EOR(uint8 i) -> uint8 {
uint8 o = A ^ i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto HuC6280::INC(uint8 i) -> uint8 {
i++;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::LD(uint8 i) -> uint8 {
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::LSR(uint8 i) -> uint8 {
C = i.bit(0);
i >>= 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::ORA(uint8 i) -> uint8 {
uint8 o = A | i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto HuC6280::ROL(uint8 i) -> uint8 {
bool c = C;
C = i.bit(7);
i = i << 1 | c;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::ROR(uint8 i) -> uint8 {
bool c = C;
C = i.bit(0);
i = c << 7 | i >> 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto HuC6280::SBC(uint8 i) -> uint8 {
i ^= 0xff;
int16 o;
if(!D) {
o = A + i + C;
V = ~(A ^ i) & (A ^ o) & 0x80;
} else {
io();
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
if(o <= 0x0f) o -= 0x06;
C = o > 0x0f;
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
if(o <= 0xff) o -= 0x60;
}
C = o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return o;
}
auto HuC6280::TRB(uint8 i) -> uint8 {
Z = (A & i) == 0;
V = i.bit(6);
N = i.bit(7);
return ~A & i;
}
auto HuC6280::TSB(uint8 i) -> uint8 {
Z = (A & i) == 0;
V = i.bit(6);
N = i.bit(7);
return A | i;
}
//
auto HuC6280::TAI(uint16& source, uint16& target, bool alternate) -> void {
!alternate ? source++ : source--;
target++;
}
auto HuC6280::TDD(uint16& source, uint16& target, bool) -> void {
source--;
target--;
}
auto HuC6280::TIA(uint16& source, uint16& target, bool alternate) -> void {
source++;
!alternate ? target++ : target--;
}
auto HuC6280::TII(uint16& source, uint16& target, bool) -> void {
source++;
target++;
}
auto HuC6280::TIN(uint16& source, uint16& target, bool) -> void {
source++;
}
//
auto HuC6280::instruction_absoluteLoad(fp alu, uint8& data, uint8 index) -> void {
uint16 absolute = operand();
absolute |= operand() << 8;
io();
L data = ALU(load16(absolute + index));
}
auto HuC6280::instruction_absoluteModify(fp alu, uint8 index) -> void {
uint16 absolute = operand(); uint16 absolute = operand();
absolute |= operand() << 8; absolute |= operand() << 8;
io(); io();
@ -201,14 +7,21 @@ auto HuC6280::instruction_absoluteModify(fp alu, uint8 index) -> void {
L store16(absolute + index, data); L store16(absolute + index, data);
} }
auto HuC6280::instruction_absoluteStore(uint8 data, uint8 index) -> void { auto HuC6280::instructionAbsoluteRead(fp alu, uint8& data, uint8 index) -> void {
uint16 absolute = operand();
absolute |= operand() << 8;
io();
L data = ALU(load16(absolute + index));
}
auto HuC6280::instructionAbsoluteWrite(uint8 data, uint8 index) -> void {
uint16 absolute = operand(); uint16 absolute = operand();
absolute |= operand() << 8; absolute |= operand() << 8;
io(); io();
L store16(absolute + index, data); L store16(absolute + index, data);
} }
auto HuC6280::instruction_blockmove(bp alu) -> void { auto HuC6280::instructionBlockMove(bp alu) -> void {
uint16 source = operand(); uint16 source = operand();
source |= operand() << 8; source |= operand() << 8;
uint16 target = operand(); uint16 target = operand();
@ -238,7 +51,7 @@ auto HuC6280::instruction_blockmove(bp alu) -> void {
L Y = pull(); L Y = pull();
} }
auto HuC6280::instruction_branch(bool take) -> void { auto HuC6280::instructionBranch(bool take) -> void {
if(!take) { if(!take) {
L operand(); L operand();
} else { } else {
@ -249,26 +62,26 @@ auto HuC6280::instruction_branch(bool take) -> void {
} }
} }
auto HuC6280::instruction_clear(uint8& data) -> void { auto HuC6280::instructionClear(uint8& data) -> void {
L io(); L io();
data = 0; data = 0;
} }
auto HuC6280::instruction_clear(bool& flag) -> void { auto HuC6280::instructionClear(bool& flag) -> void {
L io(); L io();
flag = 0; flag = 0;
} }
auto HuC6280::instruction_immediate(fp alu, uint8& data) -> void { auto HuC6280::instructionImmediate(fp alu, uint8& data) -> void {
L data = ALU(operand()); L data = ALU(operand());
} }
auto HuC6280::instruction_implied(fp alu, uint8& data) -> void { auto HuC6280::instructionImplied(fp alu, uint8& data) -> void {
L io(); L io();
data = ALU(data); data = ALU(data);
} }
auto HuC6280::instruction_indirectLoad(fp alu, uint8& data, uint8 index) -> void { auto HuC6280::instructionIndirectRead(fp alu, uint8& data, uint8 index) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
uint16 absolute = load8(zeropage + index + 0); uint16 absolute = load8(zeropage + index + 0);
@ -277,7 +90,7 @@ auto HuC6280::instruction_indirectLoad(fp alu, uint8& data, uint8 index) -> void
L data = ALU(load16(absolute)); L data = ALU(load16(absolute));
} }
auto HuC6280::instruction_indirectStore(uint8 data, uint8 index) -> void { auto HuC6280::instructionIndirectWrite(uint8 data, uint8 index) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
uint16 absolute = load8(zeropage + index + 0); uint16 absolute = load8(zeropage + index + 0);
@ -285,7 +98,7 @@ auto HuC6280::instruction_indirectStore(uint8 data, uint8 index) -> void {
L store16(absolute, data); L store16(absolute, data);
} }
auto HuC6280::instruction_indirectYLoad(fp alu, uint8& data) -> void { auto HuC6280::instructionIndirectYRead(fp alu, uint8& data) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
uint16 absolute = load8(zeropage + 0); uint16 absolute = load8(zeropage + 0);
@ -294,7 +107,7 @@ auto HuC6280::instruction_indirectYLoad(fp alu, uint8& data) -> void {
L data = ALU(load16(absolute + Y)); L data = ALU(load16(absolute + Y));
} }
auto HuC6280::instruction_indirectYStore(uint8 data) -> void { auto HuC6280::instructionIndirectYWrite(uint8 data) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
uint16 absolute = load8(zeropage + 0); uint16 absolute = load8(zeropage + 0);
@ -302,14 +115,14 @@ auto HuC6280::instruction_indirectYStore(uint8 data) -> void {
L store16(absolute + Y, data); L store16(absolute + Y, data);
} }
auto HuC6280::instruction_memory(fp alu) -> void { auto HuC6280::instructionMemory(fp alu) -> void {
auto a = A; auto a = A;
A = ALU(load8(X)); A = ALU(load8(X));
L store8(X, A); L store8(X, A);
A = a; A = a;
} }
auto HuC6280::instruction_pull(uint8& data) -> void { auto HuC6280::instructionPull(uint8& data) -> void {
io(); io();
io(); io();
L data = pull(); L data = pull();
@ -317,36 +130,30 @@ L data = pull();
N = data.bit(7); N = data.bit(7);
} }
auto HuC6280::instruction_push(uint8 data) -> void { auto HuC6280::instructionPush(uint8 data) -> void {
io(); io();
L push(data); L push(data);
} }
auto HuC6280::instruction_set(bool& flag) -> void { auto HuC6280::instructionSet(bool& flag) -> void {
L io(); L io();
flag = 1; flag = 1;
} }
auto HuC6280::instruction_swap(uint8& lhs, uint8& rhs) -> void { auto HuC6280::instructionSwap(uint8& lhs, uint8& rhs) -> void {
io(); io();
L io(); L io();
swap(lhs, rhs); swap(lhs, rhs);
} }
auto HuC6280::instruction_transfer(uint8& source, uint8& target) -> void { auto HuC6280::instructionTransfer(uint8& source, uint8& target) -> void {
L io(); L io();
target = source; target = source;
Z = target == 0; Z = target == 0;
N = target.bit(7); N = target.bit(7);
} }
auto HuC6280::instruction_zeropageLoad(fp alu, uint8& data, uint8 index) -> void { auto HuC6280::instructionZeroPageModify(fp alu, uint8 index) -> void {
auto zeropage = operand();
io();
L data = ALU(load8(zeropage + index));
}
auto HuC6280::instruction_zeropageModify(fp alu, uint8 index) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
io(); io();
@ -354,7 +161,13 @@ auto HuC6280::instruction_zeropageModify(fp alu, uint8 index) -> void {
L store8(zeropage + index, data); L store8(zeropage + index, data);
} }
auto HuC6280::instruction_zeropageStore(uint8 data, uint8 index) -> void { auto HuC6280::instructionZeroPageRead(fp alu, uint8& data, uint8 index) -> void {
auto zeropage = operand();
io();
L data = ALU(load8(zeropage + index));
}
auto HuC6280::instructionZeroPageWrite(uint8 data, uint8 index) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
L store8(zeropage + index, data); L store8(zeropage + index, data);
@ -362,7 +175,7 @@ L store8(zeropage + index, data);
// //
auto HuC6280::instruction_BBR(uint3 index) -> void { auto HuC6280::instructionBBR(uint3 index) -> void {
auto zeropage = operand(); auto zeropage = operand();
auto displacement = operand(); auto displacement = operand();
io(); io();
@ -373,7 +186,7 @@ L auto data = load8(zeropage);
} }
} }
auto HuC6280::instruction_BBS(uint3 index) -> void { auto HuC6280::instructionBBS(uint3 index) -> void {
auto zeropage = operand(); auto zeropage = operand();
auto displacement = operand(); auto displacement = operand();
io(); io();
@ -384,7 +197,7 @@ L auto data = load8(zeropage);
} }
} }
auto HuC6280::instruction_BRK() -> void { auto HuC6280::instructionBRK() -> void {
operand(); operand();
io(); io();
push(PC >> 8); push(PC >> 8);
@ -397,7 +210,7 @@ auto HuC6280::instruction_BRK() -> void {
L PC.byte(1) = load16(0xfff7); L PC.byte(1) = load16(0xfff7);
} }
auto HuC6280::instruction_BSR() -> void { auto HuC6280::instructionBSR() -> void {
auto displacement = operand(); auto displacement = operand();
io(); io();
io(); io();
@ -408,24 +221,24 @@ L push((PC - 1) >> 0);
PC += (int8)displacement; PC += (int8)displacement;
} }
auto HuC6280::instruction_CSL() -> void { auto HuC6280::instructionCSL() -> void {
L io(); L io();
r.cs = 4; r.cs = 4;
} }
auto HuC6280::instruction_CSH() -> void { auto HuC6280::instructionCSH() -> void {
L io(); L io();
r.cs = 1; r.cs = 1;
} }
auto HuC6280::instruction_JMP_absolute() -> void { auto HuC6280::instructionJMPAbsolute() -> void {
uint16 address = operand(); uint16 address = operand();
address |= operand() << 8; address |= operand() << 8;
L io(); L io();
PC = address; PC = address;
} }
auto HuC6280::instruction_JMP_indirect(uint8 index) -> void { auto HuC6280::instructionJMPIndirect(uint8 index) -> void {
uint16 address = operand(); uint16 address = operand();
address |= operand() << 8; address |= operand() << 8;
io(); io();
@ -434,7 +247,7 @@ auto HuC6280::instruction_JMP_indirect(uint8 index) -> void {
L PC.byte(1) = load16(address + index + 1); L PC.byte(1) = load16(address + index + 1);
} }
auto HuC6280::instruction_JSR() -> void { auto HuC6280::instructionJSR() -> void {
uint16 address = operand(); uint16 address = operand();
address |= operand() << 8; address |= operand() << 8;
io(); io();
@ -444,17 +257,17 @@ L push((PC - 1) >> 0);
PC = address; PC = address;
} }
auto HuC6280::instruction_NOP() -> void { auto HuC6280::instructionNOP() -> void {
L io(); L io();
} }
auto HuC6280::instruction_PLP() -> void { auto HuC6280::instructionPLP() -> void {
io(); io();
io(); io();
L P = pull(); L P = pull();
} }
auto HuC6280::instruction_RMB(uint3 index) -> void { auto HuC6280::instructionRMB(uint3 index) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
io(); io();
@ -464,7 +277,7 @@ auto HuC6280::instruction_RMB(uint3 index) -> void {
L store8(zeropage, data); L store8(zeropage, data);
} }
auto HuC6280::instruction_RTI() -> void { auto HuC6280::instructionRTI() -> void {
io(); io();
io(); io();
io(); io();
@ -473,7 +286,7 @@ auto HuC6280::instruction_RTI() -> void {
L PC.byte(1) = pull(); L PC.byte(1) = pull();
} }
auto HuC6280::instruction_RTS() -> void { auto HuC6280::instructionRTS() -> void {
io(); io();
io(); io();
io(); io();
@ -483,7 +296,7 @@ L io();
PC++; PC++;
} }
auto HuC6280::instruction_SMB(uint3 index) -> void { auto HuC6280::instructionSMB(uint3 index) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
io(); io();
@ -493,14 +306,14 @@ auto HuC6280::instruction_SMB(uint3 index) -> void {
L store8(zeropage, data); L store8(zeropage, data);
} }
auto HuC6280::instruction_ST(uint2 index) -> void { auto HuC6280::instructionST(uint2 index) -> void {
auto data = operand(); auto data = operand();
io(); io();
io(); io();
L store(index, data); L store(index, data);
} }
auto HuC6280::instruction_TAM() -> void { auto HuC6280::instructionTAM() -> void {
auto mask = operand(); auto mask = operand();
io(); io();
io(); io();
@ -510,7 +323,7 @@ L io();
} }
} }
auto HuC6280::instruction_TMA() -> void { auto HuC6280::instructionTMA() -> void {
auto mask = operand(); auto mask = operand();
io(); io();
L io(); L io();
@ -519,7 +332,7 @@ L io();
} }
} }
auto HuC6280::instruction_TST_absolute(uint8 index) -> void { auto HuC6280::instructionTSTAbsolute(uint8 index) -> void {
auto mask = operand(); auto mask = operand();
uint16 absolute = operand(); uint16 absolute = operand();
absolute |= operand() << 8; absolute |= operand() << 8;
@ -532,7 +345,7 @@ L uint8 data = load16(absolute + index);
N = data.bit(7); N = data.bit(7);
} }
auto HuC6280::instruction_TST_zeropage(uint8 index) -> void { auto HuC6280::instructionTSTZeroPage(uint8 index) -> void {
auto mask = operand(); auto mask = operand();
auto zeropage = operand(); auto zeropage = operand();
io(); io();
@ -544,7 +357,7 @@ L uint8 data = load8(zeropage + index);
N = data.bit(7); N = data.bit(7);
} }
auto HuC6280::instruction_TXS() -> void { auto HuC6280::instructionTXS() -> void {
L io(); L io();
S = X; S = X;
} }

View File

@ -0,0 +1,144 @@
auto MOS6502::algorithmADC(uint8 i) -> uint8 {
int16 o;
if(!BCD || !D) {
o = A + i + C;
V = ~(A ^ i) & (A ^ o) & 0x80;
} else {
idle();
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
if(o > 0x09) o += 0x06;
C = o > 0x0f;
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
if(o > 0x9f) o += 0x60;
}
C = o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return o;
}
auto MOS6502::algorithmAND(uint8 i) -> uint8 {
uint8 o = A & i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto MOS6502::algorithmASL(uint8 i) -> uint8 {
C = i.bit(7);
i <<= 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::algorithmBIT(uint8 i) -> uint8 {
Z = (A & i) == 0;
V = i.bit(6);
N = i.bit(7);
return A;
}
auto MOS6502::algorithmCMP(uint8 i) -> uint8 {
uint9 o = A - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return A;
}
auto MOS6502::algorithmCPX(uint8 i) -> uint8 {
uint9 o = X - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return X;
}
auto MOS6502::algorithmCPY(uint8 i) -> uint8 {
uint9 o = Y - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return Y;
}
auto MOS6502::algorithmDEC(uint8 i) -> uint8 {
i--;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::algorithmEOR(uint8 i) -> uint8 {
uint8 o = A ^ i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto MOS6502::algorithmINC(uint8 i) -> uint8 {
i++;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::algorithmLD(uint8 i) -> uint8 {
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::algorithmLSR(uint8 i) -> uint8 {
C = i.bit(0);
i >>= 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::algorithmORA(uint8 i) -> uint8 {
uint8 o = A | i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto MOS6502::algorithmROL(uint8 i) -> uint8 {
bool c = C;
C = i.bit(7);
i = i << 1 | c;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::algorithmROR(uint8 i) -> uint8 {
bool c = C;
C = i.bit(0);
i = c << 7 | i >> 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::algorithmSBC(uint8 i) -> uint8 {
i = ~i;
int16 o;
if(!BCD || !D) {
o = A + i + C;
V = ~(A ^ i) & (A ^ o) & 0x80;
} else {
idle();
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
if(o <= 0x0f) o -= 0x06;
C = o > 0x0f;
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
if(o <= 0xff) o -= 0x60;
}
C = o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return o;
}

View File

@ -1,5 +1,5 @@
#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);
#define fp(name) &MOS6502::name #define fp(name) &MOS6502::algorithm##name
auto MOS6502::interrupt() -> void { auto MOS6502::interrupt() -> void {
idle(); idle();

View File

@ -1,150 +1,3 @@
auto MOS6502::ADC(uint8 i) -> uint8 {
int16 o;
if(!BCD || !D) {
o = A + i + C;
V = ~(A ^ i) & (A ^ o) & 0x80;
} else {
idle();
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
if(o > 0x09) o += 0x06;
C = o > 0x0f;
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
if(o > 0x9f) o += 0x60;
}
C = o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return o;
}
auto MOS6502::AND(uint8 i) -> uint8 {
uint8 o = A & i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto MOS6502::ASL(uint8 i) -> uint8 {
C = i.bit(7);
i <<= 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::BIT(uint8 i) -> uint8 {
Z = (A & i) == 0;
V = i.bit(6);
N = i.bit(7);
return A;
}
auto MOS6502::CMP(uint8 i) -> uint8 {
uint9 o = A - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return A;
}
auto MOS6502::CPX(uint8 i) -> uint8 {
uint9 o = X - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return X;
}
auto MOS6502::CPY(uint8 i) -> uint8 {
uint9 o = Y - i;
C = !o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return Y;
}
auto MOS6502::DEC(uint8 i) -> uint8 {
i--;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::EOR(uint8 i) -> uint8 {
uint8 o = A ^ i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto MOS6502::INC(uint8 i) -> uint8 {
i++;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::LD(uint8 i) -> uint8 {
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::LSR(uint8 i) -> uint8 {
C = i.bit(0);
i >>= 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::ORA(uint8 i) -> uint8 {
uint8 o = A | i;
Z = o == 0;
N = o.bit(7);
return o;
}
auto MOS6502::ROL(uint8 i) -> uint8 {
bool c = C;
C = i.bit(7);
i = i << 1 | c;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::ROR(uint8 i) -> uint8 {
bool c = C;
C = i.bit(0);
i = c << 7 | i >> 1;
Z = i == 0;
N = i.bit(7);
return i;
}
auto MOS6502::SBC(uint8 i) -> uint8 {
i ^= 0xff;
int16 o;
if(!BCD || !D) {
o = A + i + C;
V = ~(A ^ i) & (A ^ o) & 0x80;
} else {
idle();
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
if(o <= 0x0f) o -= 0x06;
C = o > 0x0f;
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
if(o <= 0xff) o -= 0x60;
}
C = o.bit(8);
Z = uint8(o) == 0;
N = o.bit(7);
return o;
}
//
auto MOS6502::instructionAbsoluteModify(fp alu) -> void { auto MOS6502::instructionAbsoluteModify(fp alu) -> void {
uint16 absolute = operand(); uint16 absolute = operand();
absolute |= operand() << 8; absolute |= operand() << 8;

View File

@ -21,6 +21,7 @@ namespace Processor {
#define L lastCycle(); #define L lastCycle();
#include "memory.cpp" #include "memory.cpp"
#include "algorithms.cpp"
#include "instruction.cpp" #include "instruction.cpp"
#include "instructions.cpp" #include "instructions.cpp"
#include "disassembler.cpp" #include "disassembler.cpp"

View File

@ -26,29 +26,30 @@ struct MOS6502 {
auto push(uint8 data) -> void; auto push(uint8 data) -> void;
auto pull() -> uint8; auto pull() -> uint8;
//algorithms.cpp
using fp = auto (MOS6502::*)(uint8) -> uint8;
auto algorithmADC(uint8) -> uint8;
auto algorithmAND(uint8) -> uint8;
auto algorithmASL(uint8) -> uint8;
auto algorithmBIT(uint8) -> uint8;
auto algorithmCMP(uint8) -> uint8;
auto algorithmCPX(uint8) -> uint8;
auto algorithmCPY(uint8) -> uint8;
auto algorithmDEC(uint8) -> uint8;
auto algorithmEOR(uint8) -> uint8;
auto algorithmINC(uint8) -> uint8;
auto algorithmLD (uint8) -> uint8;
auto algorithmLSR(uint8) -> uint8;
auto algorithmORA(uint8) -> uint8;
auto algorithmROL(uint8) -> uint8;
auto algorithmROR(uint8) -> uint8;
auto algorithmSBC(uint8) -> uint8;
//instruction.cpp //instruction.cpp
auto interrupt() -> void; auto interrupt() -> void;
auto instruction() -> void; auto instruction() -> void;
//instructions.cpp //instructions.cpp
using fp = auto (MOS6502::*)(uint8) -> uint8;
auto ADC(uint8) -> uint8;
auto AND(uint8) -> uint8;
auto ASL(uint8) -> uint8;
auto BIT(uint8) -> uint8;
auto CMP(uint8) -> uint8;
auto CPX(uint8) -> uint8;
auto CPY(uint8) -> uint8;
auto DEC(uint8) -> uint8;
auto EOR(uint8) -> uint8;
auto INC(uint8) -> uint8;
auto LD (uint8) -> uint8;
auto LSR(uint8) -> uint8;
auto ORA(uint8) -> uint8;
auto ROL(uint8) -> uint8;
auto ROR(uint8) -> uint8;
auto SBC(uint8) -> uint8;
auto instructionAbsoluteModify(fp alu) -> void; auto instructionAbsoluteModify(fp alu) -> void;
auto instructionAbsoluteModify(fp alu, uint8 index) -> void; auto instructionAbsoluteModify(fp alu, uint8 index) -> void;
auto instructionAbsoluteRead(fp alu, uint8& data) -> void; auto instructionAbsoluteRead(fp alu, uint8& data) -> void;

View File

@ -1,134 +1,134 @@
auto SPC700::op_adc(uint8 x, uint8 y) -> uint8 { auto SPC700::algorithmADC(uint8 x, uint8 y) -> uint8 {
int r = x + y + regs.p.c; int z = x + y + CF;
regs.p.n = r & 0x80; CF = z > 0xff;
regs.p.v = ~(x ^ y) & (x ^ r) & 0x80; ZF = (uint8)z == 0;
regs.p.h = (x ^ y ^ r) & 0x10; HF = (x ^ y ^ z) & 0x10;
regs.p.z = (uint8)r == 0; VF = ~(x ^ y) & (x ^ z) & 0x80;
regs.p.c = r > 0xff; NF = z & 0x80;
return r; return z;
} }
auto SPC700::op_and(uint8 x, uint8 y) -> uint8 { auto SPC700::algorithmAND(uint8 x, uint8 y) -> uint8 {
x &= y; x &= y;
regs.p.n = x & 0x80; ZF = x == 0;
regs.p.z = x == 0; NF = x & 0x80;
return x; return x;
} }
auto SPC700::op_asl(uint8 x) -> uint8 { auto SPC700::algorithmASL(uint8 x) -> uint8 {
regs.p.c = x & 0x80; CF = x & 0x80;
x <<= 1; x <<= 1;
regs.p.n = x & 0x80; ZF = x == 0;
regs.p.z = x == 0; NF = x & 0x80;
return x; return x;
} }
auto SPC700::op_cmp(uint8 x, uint8 y) -> uint8 { auto SPC700::algorithmCMP(uint8 x, uint8 y) -> uint8 {
int r = x - y; int z = x - y;
regs.p.n = r & 0x80; CF = z >= 0;
regs.p.z = (uint8)r == 0; ZF = (uint8)z == 0;
regs.p.c = r >= 0; NF = z & 0x80;
return x; return x;
} }
auto SPC700::op_dec(uint8 x) -> uint8 { auto SPC700::algorithmDEC(uint8 x) -> uint8 {
x--; x--;
regs.p.n = x & 0x80; ZF = x == 0;
regs.p.z = x == 0; NF = x & 0x80;
return x; return x;
} }
auto SPC700::op_eor(uint8 x, uint8 y) -> uint8 { auto SPC700::algorithmEOR(uint8 x, uint8 y) -> uint8 {
x ^= y; x ^= y;
regs.p.n = x & 0x80; ZF = x == 0;
regs.p.z = x == 0; NF = x & 0x80;
return x; return x;
} }
auto SPC700::op_inc(uint8 x) -> uint8 { auto SPC700::algorithmINC(uint8 x) -> uint8 {
x++; x++;
regs.p.n = x & 0x80; ZF = x == 0;
regs.p.z = x == 0; NF = x & 0x80;
return x; return x;
} }
auto SPC700::op_ld(uint8 x, uint8 y) -> uint8 { auto SPC700::algorithmLD(uint8 x, uint8 y) -> uint8 {
regs.p.n = y & 0x80; ZF = y == 0;
regs.p.z = y == 0; NF = y & 0x80;
return y; return y;
} }
auto SPC700::op_lsr(uint8 x) -> uint8 { auto SPC700::algorithmLSR(uint8 x) -> uint8 {
regs.p.c = x & 0x01; CF = x & 0x01;
x >>= 1; x >>= 1;
regs.p.n = x & 0x80; ZF = x == 0;
regs.p.z = x == 0; NF = x & 0x80;
return x; return x;
} }
auto SPC700::op_or(uint8 x, uint8 y) -> uint8 { auto SPC700::algorithmOR(uint8 x, uint8 y) -> uint8 {
x |= y; x |= y;
regs.p.n = x & 0x80; ZF = x == 0;
regs.p.z = x == 0; NF = x & 0x80;
return x; return x;
} }
auto SPC700::op_rol(uint8 x) -> uint8 { auto SPC700::algorithmROL(uint8 x) -> uint8 {
uint carry = regs.p.c << 0; bool carry = CF;
regs.p.c = x & 0x80; CF = x & 0x80;
x = (x << 1) | carry; x = x << 1 | carry;
regs.p.n = x & 0x80; ZF = x == 0;
regs.p.z = x == 0; NF = x & 0x80;
return x; return x;
} }
auto SPC700::op_ror(uint8 x) -> uint8 { auto SPC700::algorithmROR(uint8 x) -> uint8 {
uint carry = regs.p.c << 7; bool carry = CF;
regs.p.c = x & 0x01; CF = x & 0x01;
x = carry | (x >> 1); x = carry << 7 | x >> 1;
regs.p.n = x & 0x80; ZF = x == 0;
regs.p.z = x == 0; NF = x & 0x80;
return x; return x;
} }
auto SPC700::op_sbc(uint8 x, uint8 y) -> uint8 { auto SPC700::algorithmSBC(uint8 x, uint8 y) -> uint8 {
return op_adc(x, ~y); return algorithmADC(x, ~y);
} }
auto SPC700::op_st(uint8 x, uint8 y) -> uint8 { auto SPC700::algorithmST(uint8 x, uint8 y) -> uint8 {
return y; return y;
} }
// //
auto SPC700::op_adw(uint16 x, uint16 y) -> uint16 { auto SPC700::algorithmADW(uint16 x, uint16 y) -> uint16 {
uint16 r; uint16 z;
regs.p.c = 0; CF = 0;
r = op_adc(x, y); z = algorithmADC(x, y);
r |= op_adc(x >> 8, y >> 8) << 8; z |= algorithmADC(x >> 8, y >> 8) << 8;
regs.p.z = r == 0; ZF = z == 0;
return r; return z;
} }
auto SPC700::op_cpw(uint16 x, uint16 y) -> uint16 { auto SPC700::algorithmCPW(uint16 x, uint16 y) -> uint16 {
int r = x - y; int z = x - y;
regs.p.n = r & 0x8000; CF = z >= 0;
regs.p.z = (uint16)r == 0; ZF = (uint16)z == 0;
regs.p.c = r >= 0; NF = z & 0x8000;
return x; return x;
} }
auto SPC700::op_ldw(uint16 x, uint16 y) -> uint16 { auto SPC700::algorithmLDW(uint16 x, uint16 y) -> uint16 {
regs.p.n = y & 0x8000; ZF = y == 0;
regs.p.z = y == 0; NF = y & 0x8000;
return y; return y;
} }
auto SPC700::op_sbw(uint16 x, uint16 y) -> uint16 { auto SPC700::algorithmSBW(uint16 x, uint16 y) -> uint16 {
uint16 r; uint16 z;
regs.p.c = 1; CF = 1;
r = op_sbc(x, y); z = algorithmSBC(x, y);
r |= op_sbc(x >> 8, y >> 8) << 8; z |= algorithmSBC(x >> 8, y >> 8) << 8;
regs.p.z = r == 0; ZF = z == 0;
return r; return z;
} }

View File

@ -10,7 +10,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
auto a = [&] { return hex((read(addr + 1) << 0) + (read(addr + 2) << 8), 4L); }; auto a = [&] { return hex((read(addr + 1) << 0) + (read(addr + 2) << 8), 4L); };
auto b = [&](uint n) { return hex(read(addr + 1 + n), 2L); }; auto b = [&](uint n) { return hex(read(addr + 1 + n), 2L); };
auto r = [&](uint r, uint n = 0) { return hex(addr + r + (int8)read(addr + 1 + n), 4L); }; auto rel = [&](uint r, uint n = 0) { return hex(addr + r + (int8)read(addr + 1 + n), 4L); };
auto dp = [&](uint n) { return hex((p << 8) + read(addr + 1 + n), 3L); }; auto dp = [&](uint n) { return hex((p << 8) + read(addr + 1 + n), 3L); };
auto ab = [&] { auto ab = [&] {
uint n = (read(addr + 1) << 0) + (read(addr + 2) << 8); uint n = (read(addr + 1) << 0) + (read(addr + 2) << 8);
@ -22,7 +22,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x00: return { "nop" }; case 0x00: return { "nop" };
case 0x01: return { "jst $ffde" }; case 0x01: return { "jst $ffde" };
case 0x02: return { "set $", dp(0), ":0" }; case 0x02: return { "set $", dp(0), ":0" };
case 0x03: return { "bbs $", dp(0), ":0=$", r(+3, 1) }; case 0x03: return { "bbs $", dp(0), ":0=$", rel(+3, 1) };
case 0x04: return { "ora $", dp(0) }; case 0x04: return { "ora $", dp(0) };
case 0x05: return { "ora $", a() }; case 0x05: return { "ora $", a() };
case 0x06: return { "ora (x)" }; case 0x06: return { "ora (x)" };
@ -35,10 +35,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x0d: return { "php" }; case 0x0d: return { "php" };
case 0x0e: return { "tsb $", a() }; case 0x0e: return { "tsb $", a() };
case 0x0f: return { "brk" }; case 0x0f: return { "brk" };
case 0x10: return { "bpl $", r(+2) }; case 0x10: return { "bpl $", rel(+2) };
case 0x11: return { "jst $ffdc" }; case 0x11: return { "jst $ffdc" };
case 0x12: return { "clr $", dp(0), ":0" }; case 0x12: return { "clr $", dp(0), ":0" };
case 0x13: return { "bbc $", dp(0), ":0=$", r(+3, 1) }; case 0x13: return { "bbc $", dp(0), ":0=$", rel(+3, 1) };
case 0x14: return { "ora $", dp(0), ",x" }; case 0x14: return { "ora $", dp(0), ",x" };
case 0x15: return { "ora $", a(), ",x" }; case 0x15: return { "ora $", a(), ",x" };
case 0x16: return { "ora $", a(), ",y" }; case 0x16: return { "ora $", a(), ",y" };
@ -54,7 +54,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x20: return { "clp" }; case 0x20: return { "clp" };
case 0x21: return { "jst $ffda" }; case 0x21: return { "jst $ffda" };
case 0x22: return { "set $", dp(0), ":1" }; case 0x22: return { "set $", dp(0), ":1" };
case 0x23: return { "bbs $", dp(0), ":1=$", r(+3, 1) }; case 0x23: return { "bbs $", dp(0), ":1=$", rel(+3, 1) };
case 0x24: return { "and $", dp(0) }; case 0x24: return { "and $", dp(0) };
case 0x25: return { "and $", a() }; case 0x25: return { "and $", a() };
case 0x26: return { "and (x)" }; case 0x26: return { "and (x)" };
@ -64,13 +64,13 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x2b: return { "rol $", dp(0) }; case 0x2b: return { "rol $", dp(0) };
case 0x2c: return { "rol $", a() }; case 0x2c: return { "rol $", a() };
case 0x2d: return { "pha" }; case 0x2d: return { "pha" };
case 0x2e: return { "bne $", dp(0), "=$", r(+3, 1) }; case 0x2e: return { "bne $", dp(0), "=$", rel(+3, 1) };
case 0x28: return { "and #$", b(0) }; case 0x28: return { "and #$", b(0) };
case 0x2f: return { "bra $", r(+2) }; case 0x2f: return { "bra $", rel(+2) };
case 0x30: return { "bmi $", r(+2) }; case 0x30: return { "bmi $", rel(+2) };
case 0x31: return { "jst $ffd8" }; case 0x31: return { "jst $ffd8" };
case 0x32: return { "clr $", dp(0), ":1" }; case 0x32: return { "clr $", dp(0), ":1" };
case 0x33: return { "bbc $", dp(0), ":1=$", r(+3, 1) }; case 0x33: return { "bbc $", dp(0), ":1=$", rel(+3, 1) };
case 0x34: return { "and $", dp(0), ",x" }; case 0x34: return { "and $", dp(0), ",x" };
case 0x35: return { "and $", a(), ",x" }; case 0x35: return { "and $", a(), ",x" };
case 0x36: return { "and $", a(), ",y" }; case 0x36: return { "and $", a(), ",y" };
@ -86,7 +86,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x40: return { "sep" }; case 0x40: return { "sep" };
case 0x41: return { "jst $ffd6" }; case 0x41: return { "jst $ffd6" };
case 0x42: return { "set $", dp(0), ":2" }; case 0x42: return { "set $", dp(0), ":2" };
case 0x43: return { "bbs $", dp(0), ":2=$", r(+3, 1) }; case 0x43: return { "bbs $", dp(0), ":2=$", rel(+3, 1) };
case 0x44: return { "eor $", dp(0) }; case 0x44: return { "eor $", dp(0) };
case 0x45: return { "eor $", a() }; case 0x45: return { "eor $", a() };
case 0x46: return { "eor (x)" }; case 0x46: return { "eor (x)" };
@ -99,10 +99,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x4d: return { "phx" }; case 0x4d: return { "phx" };
case 0x4e: return { "trb $", a() }; case 0x4e: return { "trb $", a() };
case 0x4f: return { "jsp $ff", b(0) }; case 0x4f: return { "jsp $ff", b(0) };
case 0x50: return { "bvc $", r(+2) }; case 0x50: return { "bvc $", rel(+2) };
case 0x51: return { "jst $ffd4" }; case 0x51: return { "jst $ffd4" };
case 0x52: return { "clr $", dp(0), ":2" }; case 0x52: return { "clr $", dp(0), ":2" };
case 0x53: return { "bbc $", dp(0), ":2=$", r(+3, 1) }; case 0x53: return { "bbc $", dp(0), ":2=$", rel(+3, 1) };
case 0x54: return { "eor $", dp(0), ",x" }; case 0x54: return { "eor $", dp(0), ",x" };
case 0x55: return { "eor $", a(), ",x" }; case 0x55: return { "eor $", a(), ",x" };
case 0x56: return { "eor $", a(), ",y" }; case 0x56: return { "eor $", a(), ",y" };
@ -118,7 +118,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x60: return { "clc" }; case 0x60: return { "clc" };
case 0x61: return { "jst $ffd2" }; case 0x61: return { "jst $ffd2" };
case 0x62: return { "set $", dp(0), ":3" }; case 0x62: return { "set $", dp(0), ":3" };
case 0x63: return { "bbs $", dp(0), ":3=$", r(+3, 1) }; case 0x63: return { "bbs $", dp(0), ":3=$", rel(+3, 1) };
case 0x64: return { "cmp $", dp(0) }; case 0x64: return { "cmp $", dp(0) };
case 0x65: return { "cmp $", a() }; case 0x65: return { "cmp $", a() };
case 0x66: return { "cmp (x)" }; case 0x66: return { "cmp (x)" };
@ -129,12 +129,12 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x6b: return { "ror $", dp(0) }; case 0x6b: return { "ror $", dp(0) };
case 0x6c: return { "ror $", a() }; case 0x6c: return { "ror $", a() };
case 0x6d: return { "phy" }; case 0x6d: return { "phy" };
case 0x6e: return { "bne --$", dp(0), "=$", r(+3, 1) }; case 0x6e: return { "bne --$", dp(0), "=$", rel(+3, 1) };
case 0x6f: return { "rts" }; case 0x6f: return { "rts" };
case 0x70: return { "bvs $", r(+2) }; case 0x70: return { "bvs $", rel(+2) };
case 0x71: return { "jst $ffd0" }; case 0x71: return { "jst $ffd0" };
case 0x72: return { "clr $", dp(0), ":3" }; case 0x72: return { "clr $", dp(0), ":3" };
case 0x73: return { "bbc $", dp(0), ":3=$", r(+3, 1) }; case 0x73: return { "bbc $", dp(0), ":3=$", rel(+3, 1) };
case 0x74: return { "cmp $", dp(0), ",x" }; case 0x74: return { "cmp $", dp(0), ",x" };
case 0x75: return { "cmp $", a(), ",x" }; case 0x75: return { "cmp $", a(), ",x" };
case 0x76: return { "cmp $", a(), ",y" }; case 0x76: return { "cmp $", a(), ",y" };
@ -150,7 +150,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x80: return { "sec" }; case 0x80: return { "sec" };
case 0x81: return { "jst $ffce" }; case 0x81: return { "jst $ffce" };
case 0x82: return { "set $", dp(0), ":4" }; case 0x82: return { "set $", dp(0), ":4" };
case 0x83: return { "bbs $", dp(0), ":4=$", r(+3, 1) }; case 0x83: return { "bbs $", dp(0), ":4=$", rel(+3, 1) };
case 0x84: return { "adc $", dp(0) }; case 0x84: return { "adc $", dp(0) };
case 0x85: return { "adc $", a() }; case 0x85: return { "adc $", a() };
case 0x86: return { "adc (x)" }; case 0x86: return { "adc (x)" };
@ -163,10 +163,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0x8d: return { "ldy #$", b(0) }; case 0x8d: return { "ldy #$", b(0) };
case 0x8e: return { "plp" }; case 0x8e: return { "plp" };
case 0x8f: return { "str $", dp(1), "=#$", b(0) }; case 0x8f: return { "str $", dp(1), "=#$", b(0) };
case 0x90: return { "bcc $", r(+2) }; case 0x90: return { "bcc $", rel(+2) };
case 0x91: return { "jst $ffcc" }; case 0x91: return { "jst $ffcc" };
case 0x92: return { "clr $", dp(0), ":4" }; case 0x92: return { "clr $", dp(0), ":4" };
case 0x93: return { "bbc $", dp(0), ":4=$", r(+3, 1) }; case 0x93: return { "bbc $", dp(0), ":4=$", rel(+3, 1) };
case 0x94: return { "adc $", dp(0), ",x" }; case 0x94: return { "adc $", dp(0), ",x" };
case 0x95: return { "adc $", a(), ",x" }; case 0x95: return { "adc $", a(), ",x" };
case 0x96: return { "adc $", a(), ",y" }; case 0x96: return { "adc $", a(), ",y" };
@ -182,7 +182,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0xa0: return { "sei" }; case 0xa0: return { "sei" };
case 0xa1: return { "jst $ffca" }; case 0xa1: return { "jst $ffca" };
case 0xa2: return { "set $", dp(0), ":5" }; case 0xa2: return { "set $", dp(0), ":5" };
case 0xa3: return { "bbs $", dp(0), ":5=$", r(+3, 1) }; case 0xa3: return { "bbs $", dp(0), ":5=$", rel(+3, 1) };
case 0xa4: return { "sbc $", dp(0) }; case 0xa4: return { "sbc $", dp(0) };
case 0xa5: return { "sbc $", a() }; case 0xa5: return { "sbc $", a() };
case 0xa6: return { "sbc (x)" }; case 0xa6: return { "sbc (x)" };
@ -195,10 +195,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0xad: return { "cpy #$", b(0) }; case 0xad: return { "cpy #$", b(0) };
case 0xae: return { "pla" }; case 0xae: return { "pla" };
case 0xaf: return { "sta (x++)" }; case 0xaf: return { "sta (x++)" };
case 0xb0: return { "bcs $", r(+2) }; case 0xb0: return { "bcs $", rel(+2) };
case 0xb1: return { "jst $ffc8" }; case 0xb1: return { "jst $ffc8" };
case 0xb2: return { "clr $", dp(0), ":5" }; case 0xb2: return { "clr $", dp(0), ":5" };
case 0xb3: return { "bbc $", dp(0), ":5=$", r(+3, 1) }; case 0xb3: return { "bbc $", dp(0), ":5=$", rel(+3, 1) };
case 0xb4: return { "sbc $", dp(0), ",x" }; case 0xb4: return { "sbc $", dp(0), ",x" };
case 0xb5: return { "sbc $", a(), ",x" }; case 0xb5: return { "sbc $", a(), ",x" };
case 0xb6: return { "sbc $", a(), ",y" }; case 0xb6: return { "sbc $", a(), ",y" };
@ -214,7 +214,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0xc0: return { "cli" }; case 0xc0: return { "cli" };
case 0xc1: return { "jst $ffc6" }; case 0xc1: return { "jst $ffc6" };
case 0xc2: return { "set $", dp(0), ":6" }; case 0xc2: return { "set $", dp(0), ":6" };
case 0xc3: return { "bbs $", dp(0), ":6=$", r(+3, 1) }; case 0xc3: return { "bbs $", dp(0), ":6=$", rel(+3, 1) };
case 0xc4: return { "sta $", dp(0) }; case 0xc4: return { "sta $", dp(0) };
case 0xc5: return { "sta $", a() }; case 0xc5: return { "sta $", a() };
case 0xc6: return { "sta (x)" }; case 0xc6: return { "sta (x)" };
@ -227,10 +227,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0xcd: return { "ldx #$", b(0) }; case 0xcd: return { "ldx #$", b(0) };
case 0xce: return { "plx" }; case 0xce: return { "plx" };
case 0xcf: return { "mul" }; case 0xcf: return { "mul" };
case 0xd0: return { "bne $", r(+2) }; case 0xd0: return { "bne $", rel(+2) };
case 0xd1: return { "jst $ffc4" }; case 0xd1: return { "jst $ffc4" };
case 0xd2: return { "clr $", dp(0), ":6" }; case 0xd2: return { "clr $", dp(0), ":6" };
case 0xd3: return { "bbc $", dp(0), ":6=$", r(+3, 1) }; case 0xd3: return { "bbc $", dp(0), ":6=$", rel(+3, 1) };
case 0xd4: return { "sta $", dp(0), ",x" }; case 0xd4: return { "sta $", dp(0), ",x" };
case 0xd5: return { "sta $", a(), ",x" }; case 0xd5: return { "sta $", a(), ",x" };
case 0xd6: return { "sta $", a(), ",y" }; case 0xd6: return { "sta $", a(), ",y" };
@ -241,12 +241,12 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0xdb: return { "sty $", dp(0), ",x" }; case 0xdb: return { "sty $", dp(0), ",x" };
case 0xdc: return { "dey" }; case 0xdc: return { "dey" };
case 0xdd: return { "tya" }; case 0xdd: return { "tya" };
case 0xde: return { "bne $", dp(0), ",x=$", r(+3, 1) }; case 0xde: return { "bne $", dp(0), ",x=$", rel(+3, 1) };
case 0xdf: return { "daa" }; case 0xdf: return { "daa" };
case 0xe0: return { "clv" }; case 0xe0: return { "clv" };
case 0xe1: return { "jst $ffc2" }; case 0xe1: return { "jst $ffc2" };
case 0xe2: return { "set $", dp(0), ":7" }; case 0xe2: return { "set $", dp(0), ":7" };
case 0xe3: return { "bbs $", dp(0), ":7=$", r(+3, 1) }; case 0xe3: return { "bbs $", dp(0), ":7=$", rel(+3, 1) };
case 0xe4: return { "lda $", dp(0) }; case 0xe4: return { "lda $", dp(0) };
case 0xe5: return { "lda $", a() }; case 0xe5: return { "lda $", a() };
case 0xe6: return { "lda (x)" }; case 0xe6: return { "lda (x)" };
@ -259,10 +259,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0xed: return { "cmc" }; case 0xed: return { "cmc" };
case 0xee: return { "ply" }; case 0xee: return { "ply" };
case 0xef: return { "wai" }; case 0xef: return { "wai" };
case 0xf0: return { "beq $", r(+2) }; case 0xf0: return { "beq $", rel(+2) };
case 0xf1: return { "jst $ffc0" }; case 0xf1: return { "jst $ffc0" };
case 0xf2: return { "clr $", dp(0), ":7" }; case 0xf2: return { "clr $", dp(0), ":7" };
case 0xf3: return { "bbc $", dp(0), ":7=$", r(+3, 1) }; case 0xf3: return { "bbc $", dp(0), ":7=$", rel(+3, 1) };
case 0xf4: return { "lda $", dp(0), ",x" }; case 0xf4: return { "lda $", dp(0), ",x" };
case 0xf5: return { "lda $", a(), ",x" }; case 0xf5: return { "lda $", a(), ",x" };
case 0xf6: return { "lda $", a(), ",y" }; case 0xf6: return { "lda $", a(), ",y" };
@ -273,7 +273,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
case 0xfb: return { "ldy $", dp(0), ",x" }; case 0xfb: return { "ldy $", dp(0), ",x" };
case 0xfc: return { "iny" }; case 0xfc: return { "iny" };
case 0xfd: return { "tay" }; case 0xfd: return { "tay" };
case 0xfe: return { "bne --y=$", r(+2) }; case 0xfe: return { "bne --y=$", rel(+2) };
case 0xff: return { "stp" }; case 0xff: return { "stp" };
} }
throw; throw;
@ -285,20 +285,20 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string {
while(length++ < 30) output.append(" "); while(length++ < 30) output.append(" ");
output.append( output.append(
"YA:", hex(regs.ya, 4L), "YA:", hex(YA, 4L),
" A:", hex(regs.a, 2L), " A:", hex(A, 2L),
" X:", hex(regs.x, 2L), " X:", hex(X, 2L),
" Y:", hex(regs.y, 2L), " Y:", hex(Y, 2L),
" S:", hex(regs.s, 2L), " S:", hex(S, 2L),
" ", " ",
regs.p.n ? "N" : "n", NF ? "N" : "n",
regs.p.v ? "V" : "v", VF ? "V" : "v",
regs.p.p ? "P" : "p", PF ? "P" : "p",
regs.p.b ? "B" : "b", BF ? "B" : "b",
regs.p.h ? "H" : "h", HF ? "H" : "h",
regs.p.i ? "I" : "i", IF ? "I" : "i",
regs.p.z ? "Z" : "z", ZF ? "Z" : "z",
regs.p.c ? "C" : "c" CF ? "C" : "c"
); );
return output; return output;

View File

@ -0,0 +1,266 @@
#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);
#define fp(name) &SPC700::algorithm##name
auto SPC700::instruction() -> void {
switch(opcode = fetch()) {
op(0x00, NOP)
op(0x01, JST, 0)
op(0x02, SET, 0)
op(0x03, BBS, 0)
op(0x04, DirectPageRead, fp(OR), A)
op(0x05, AbsoluteRead, fp(OR), A)
op(0x06, IndirectXRead, fp(OR))
op(0x07, IndirectPageXRead, fp(OR))
op(0x08, ImmediateRead, fp(OR), A)
op(0x09, DirectPageWriteDirectPage, fp(OR))
op(0x0a, AbsoluteModifyBit)
op(0x0b, DirectPageModify, fp(ASL))
op(0x0c, AbsoluteModify, fp(ASL))
op(0x0d, Push, P)
op(0x0e, TSBAbsolute)
op(0x0f, BRK)
op(0x10, Branch, NF == 0)
op(0x11, JST, 1)
op(0x12, CLR, 0)
op(0x13, BBC, 0)
op(0x14, DirectPageIndexedRead, fp(OR), A, X)
op(0x15, AbsoluteIndexedRead, fp(OR), X)
op(0x16, AbsoluteIndexedRead, fp(OR), Y)
op(0x17, IndirectPageYRead, fp(OR))
op(0x18, DirectPageWriteImmediate, fp(OR))
op(0x19, IndirectXWriteIndirectY, fp(OR))
op(0x1a, DirectPageModifyWord, -1)
op(0x1b, DirectPageXModify, fp(ASL))
op(0x1c, ImpliedModify, fp(ASL), A)
op(0x1d, ImpliedModify, fp(DEC), X)
op(0x1e, AbsoluteRead, fp(CMP), X)
op(0x1f, JMPIndirectAbsoluteX)
op(0x20, FlagClear, PF)
op(0x21, JST, 2)
op(0x22, SET, 1)
op(0x23, BBS, 1)
op(0x24, DirectPageRead, fp(AND), A)
op(0x25, AbsoluteRead, fp(AND), A)
op(0x26, IndirectXRead, fp(AND))
op(0x27, IndirectPageXRead, fp(AND))
op(0x28, ImmediateRead, fp(AND), A)
op(0x29, DirectPageWriteDirectPage, fp(AND))
op(0x2a, AbsoluteModifyBit)
op(0x2b, DirectPageModify, fp(ROL))
op(0x2c, AbsoluteModify, fp(ROL))
op(0x2d, Push, A)
op(0x2e, BNEDirectPage)
op(0x2f, Branch, true)
op(0x30, Branch, NF == 1)
op(0x31, JST, 3)
op(0x32, CLR, 1)
op(0x33, BBC, 1)
op(0x34, DirectPageIndexedRead, fp(AND), A, X)
op(0x35, AbsoluteIndexedRead, fp(AND), X)
op(0x36, AbsoluteIndexedRead, fp(AND), Y)
op(0x37, IndirectPageYRead, fp(AND))
op(0x38, DirectPageWriteImmediate, fp(AND))
op(0x39, IndirectXWriteIndirectY, fp(AND))
op(0x3a, DirectPageModifyWord, +1)
op(0x3b, DirectPageXModify, fp(ROL))
op(0x3c, ImpliedModify, fp(ROL), A)
op(0x3d, ImpliedModify, fp(INC), X)
op(0x3e, DirectPageRead, fp(CMP), X)
op(0x3f, JSRAbsolute)
op(0x40, FlagSet, PF)
op(0x41, JST, 4)
op(0x42, SET, 2)
op(0x43, BBS, 2)
op(0x44, DirectPageRead, fp(EOR), A)
op(0x45, AbsoluteRead, fp(EOR), A)
op(0x46, IndirectXRead, fp(EOR))
op(0x47, IndirectPageXRead, fp(EOR))
op(0x48, ImmediateRead, fp(EOR), A)
op(0x49, DirectPageWriteDirectPage, fp(EOR))
op(0x4a, AbsoluteModifyBit)
op(0x4b, DirectPageModify, fp(LSR))
op(0x4c, AbsoluteModify, fp(LSR))
op(0x4d, Push, X)
op(0x4e, TRBAbsolute)
op(0x4f, JSPDirectPage)
op(0x50, Branch, VF == 0)
op(0x51, JST, 5)
op(0x52, CLR, 2)
op(0x53, BBC, 2)
op(0x54, DirectPageIndexedRead, fp(EOR), A, X)
op(0x55, AbsoluteIndexedRead, fp(EOR), X)
op(0x56, AbsoluteIndexedRead, fp(EOR), Y)
op(0x57, IndirectPageYRead, fp(EOR))
op(0x58, DirectPageWriteImmediate, fp(EOR))
op(0x59, IndirectXWriteIndirectY, fp(EOR))
op(0x5a, DirectPageReadWord, fp(CPW))
op(0x5b, DirectPageXModify, fp(LSR))
op(0x5c, ImpliedModify, fp(LSR), A)
op(0x5d, Transfer, A, X)
op(0x5e, AbsoluteRead, fp(CMP), Y)
op(0x5f, JMPAbsolute)
op(0x60, FlagClear, CF)
op(0x61, JST, 6)
op(0x62, SET, 3)
op(0x63, BBS, 3)
op(0x64, DirectPageRead, fp(CMP), A)
op(0x65, AbsoluteRead, fp(CMP), A)
op(0x66, IndirectXRead, fp(CMP))
op(0x67, IndirectPageXRead, fp(CMP))
op(0x68, ImmediateRead, fp(CMP), A)
op(0x69, DirectPageWriteDirectPage, fp(CMP))
op(0x6a, AbsoluteModifyBit)
op(0x6b, DirectPageModify, fp(ROR))
op(0x6c, AbsoluteModify, fp(ROR))
op(0x6d, Push, Y)
op(0x6e, BNEDirectPageDecrement)
op(0x6f, RTS)
op(0x70, Branch, VF == 1)
op(0x71, JST, 7)
op(0x72, CLR, 3)
op(0x73, BBC, 3)
op(0x74, DirectPageIndexedRead, fp(CMP), A, X)
op(0x75, AbsoluteIndexedRead, fp(CMP), X)
op(0x76, AbsoluteIndexedRead, fp(CMP), Y)
op(0x77, IndirectPageYRead, fp(CMP))
op(0x78, DirectPageWriteImmediate, fp(CMP))
op(0x79, IndirectXWriteIndirectY, fp(CMP))
op(0x7a, DirectPageReadWord, fp(ADW))
op(0x7b, DirectPageXModify, fp(ROR))
op(0x7c, ImpliedModify, fp(ROR), A)
op(0x7d, Transfer, X, A)
op(0x7e, DirectPageRead, fp(CMP), Y)
op(0x7f, RTI)
op(0x80, FlagSet, CF)
op(0x81, JST, 8)
op(0x82, SET, 4)
op(0x83, BBS, 4)
op(0x84, DirectPageRead, fp(ADC), A)
op(0x85, AbsoluteRead, fp(ADC), A)
op(0x86, IndirectXRead, fp(ADC))
op(0x87, IndirectPageXRead, fp(ADC))
op(0x88, ImmediateRead, fp(ADC), A)
op(0x89, DirectPageWriteDirectPage, fp(ADC))
op(0x8a, AbsoluteModifyBit)
op(0x8b, DirectPageModify, fp(DEC))
op(0x8c, AbsoluteModify, fp(DEC))
op(0x8d, ImmediateRead, fp(LD), Y)
op(0x8e, PLP)
op(0x8f, DirectPageWriteImmediate, fp(ST))
op(0x90, Branch, CF == 0)
op(0x91, JST, 9)
op(0x92, CLR, 4)
op(0x93, BBC, 4)
op(0x94, DirectPageIndexedRead, fp(ADC), A, X)
op(0x95, AbsoluteIndexedRead, fp(ADC), X)
op(0x96, AbsoluteIndexedRead, fp(ADC), Y)
op(0x97, IndirectPageYRead, fp(ADC))
op(0x98, DirectPageWriteImmediate, fp(ADC))
op(0x99, IndirectXWriteIndirectY, fp(ADC))
op(0x9a, DirectPageReadWord, fp(SBW))
op(0x9b, DirectPageXModify, fp(DEC))
op(0x9c, ImpliedModify, fp(DEC), A)
op(0x9d, Transfer, S, X)
op(0x9e, DIV)
op(0x9f, XCN)
op(0xa0, FlagSet, IF)
op(0xa1, JST, 10)
op(0xa2, SET, 5)
op(0xa3, BBS, 5)
op(0xa4, DirectPageRead, fp(SBC), A)
op(0xa5, AbsoluteRead, fp(SBC), A)
op(0xa6, IndirectXRead, fp(SBC))
op(0xa7, IndirectPageXRead, fp(SBC))
op(0xa8, ImmediateRead, fp(SBC), A)
op(0xa9, DirectPageWriteDirectPage, fp(SBC))
op(0xaa, AbsoluteModifyBit)
op(0xab, DirectPageModify, fp(INC))
op(0xac, AbsoluteModify, fp(INC))
op(0xad, ImmediateRead, fp(CMP), Y)
op(0xae, Pull, A)
op(0xaf, STAIndirectXIncrement)
op(0xb0, Branch, CF == 1)
op(0xb1, JST, 11)
op(0xb2, CLR, 5)
op(0xb3, BBC, 5)
op(0xb4, DirectPageIndexedRead, fp(SBC), A, X)
op(0xb5, AbsoluteIndexedRead, fp(SBC), X)
op(0xb6, AbsoluteIndexedRead, fp(SBC), Y)
op(0xb7, IndirectPageYRead, fp(SBC))
op(0xb8, DirectPageWriteImmediate, fp(SBC))
op(0xb9, IndirectXWriteIndirectY, fp(SBC))
op(0xba, DirectPageReadWord, fp(LDW))
op(0xbb, DirectPageXModify, fp(INC))
op(0xbc, ImpliedModify, fp(INC), A)
op(0xbd, Transfer, X, S)
op(0xbe, DAS)
op(0xbf, LDAIndirectXIncrement)
op(0xc0, FlagClear, IF)
op(0xc1, JST, 12)
op(0xc2, SET, 6)
op(0xc3, BBS, 6)
op(0xc4, DirectPageWrite, A)
op(0xc5, AbsoluteWrite, A)
op(0xc6, STAIndirectX)
op(0xc7, STAIndirectPageX)
op(0xc8, ImmediateRead, fp(CMP), X)
op(0xc9, AbsoluteWrite, X)
op(0xca, AbsoluteModifyBit)
op(0xcb, DirectPageWrite, Y)
op(0xcc, AbsoluteWrite, Y)
op(0xcd, ImmediateRead, fp(LD), X)
op(0xce, Pull, X)
op(0xcf, MUL)
op(0xd0, Branch, ZF == 0)
op(0xd1, JST, 13)
op(0xd2, CLR, 6)
op(0xd3, BBC, 6)
op(0xd4, DirectPageIndexedWrite, A, X)
op(0xd5, AbsoluteIndexedWrite, X)
op(0xd6, AbsoluteIndexedWrite, Y)
op(0xd7, STAIndirectPageY)
op(0xd8, DirectPageWrite, X)
op(0xd9, DirectPageIndexedWrite, X, Y)
op(0xda, STWDirectPage)
op(0xdb, DirectPageIndexedWrite, Y, X)
op(0xdc, ImpliedModify, fp(DEC), Y)
op(0xdd, Transfer, Y, A)
op(0xde, BNEDirectPageX)
op(0xdf, DAA)
op(0xe0, CLV)
op(0xe1, JST, 14)
op(0xe2, SET, 7)
op(0xe3, BBS, 7)
op(0xe4, DirectPageRead, fp(LD), A)
op(0xe5, AbsoluteRead, fp(LD), A)
op(0xe6, IndirectXRead, fp(LD))
op(0xe7, IndirectPageXRead, fp(LD))
op(0xe8, ImmediateRead, fp(LD), A)
op(0xe9, AbsoluteRead, fp(LD), X)
op(0xea, AbsoluteModifyBit)
op(0xeb, DirectPageRead, fp(LD), Y)
op(0xec, AbsoluteRead, fp(LD), Y)
op(0xed, CMC)
op(0xee, Pull, Y)
op(0xef, WAI)
op(0xf0, Branch, ZF == 1)
op(0xf1, JST, 15)
op(0xf2, CLR, 7)
op(0xf3, BBC, 7)
op(0xf4, DirectPageIndexedRead, fp(LD), A, X)
op(0xf5, AbsoluteIndexedRead, fp(LD), X)
op(0xf6, AbsoluteIndexedRead, fp(LD), Y)
op(0xf7, IndirectPageYRead, fp(LD))
op(0xf8, DirectPageRead, fp(LD), X)
op(0xf9, DirectPageIndexedRead, fp(LD), X, Y)
op(0xfa, DirectPageWriteDirectPage, fp(ST))
op(0xfb, DirectPageIndexedRead, fp(LD), Y, X)
op(0xfc, ImpliedModify, fp(INC), Y)
op(0xfd, Transfer, A, Y)
op(0xfe, BNEYDecrement)
op(0xff, STP)
}
}
#undef op
#undef fp

View File

@ -1,142 +1,128 @@
#define call (this->*op) #define alu (this->*op)
auto SPC700::op_adjust(fps op, reg r) { auto SPC700::instructionImpliedModify(fps op, uint8& target) -> void {
idle(); idle();
r = call(r); target = alu(target);
} }
auto SPC700::op_adjust_addr(fps op) { auto SPC700::instructionAbsoluteModify(fps op) -> void {
dp.l = readPC(); uint16 absolute = fetch();
dp.h = readPC(); absolute |= fetch() << 8;
rd = read(dp); uint8 data = read(absolute);
rd = call(rd); write(absolute, alu(data));
write(dp, rd);
} }
auto SPC700::op_adjust_dp(fps op) { auto SPC700::instructionDirectPageModify(fps op) -> void {
dp = readPC(); uint8 direct = fetch();
rd = readDP(dp); uint8 data = load(direct);
rd = call(rd); store(direct, alu(data));
writeDP(dp, rd);
} }
auto SPC700::op_adjust_dpw(int n) { auto SPC700::instructionDirectPageModifyWord(int adjust) -> void {
dp = readPC(); uint8 direct = fetch();
rd.w = readDP(dp) + n; uint16 data = load(direct) + adjust;
writeDP(dp++, rd.l); store(direct++, data >> 0);
rd.h += readDP(dp); data += load(direct) << 8;
writeDP(dp++, rd.h); store(direct++, data >> 8);
regs.p.n = rd & 0x8000; ZF = data == 0;
regs.p.z = rd == 0; NF = data & 0x8000;
} }
auto SPC700::op_adjust_dpx(fps op) { auto SPC700::instructionDirectPageXModify(fps op) -> void {
dp = readPC(); uint8 direct = fetch();
idle(); idle();
rd = readDP(dp + regs.x); uint8 data = load(direct + X);
rd = call(rd); store(direct + X, alu(data));
writeDP(dp + regs.x, rd);
} }
auto SPC700::op_branch(bool condition) { auto SPC700::instructionBranch(bool take) -> void {
rd = readPC(); uint8 data = fetch();
if(!condition) return; if(!take) return;
idle(); idle();
idle(); idle();
regs.pc += (int8)rd; PC += (int8)data;
} }
auto SPC700::op_branch_bit() { auto SPC700::instructionPull(uint8& data) -> void {
dp = readPC();
sp = readDP(dp);
rd = readPC();
idle();
if((bool)(sp & (1 << (opcode >> 5))) == (bool)(opcode & 0x10)) return;
idle(); idle();
idle(); idle();
regs.pc += (int8)rd; data = pull();
} }
auto SPC700::op_pull(reg r) { auto SPC700::instructionPush(uint8 data) -> void {
idle(); idle();
idle(); idle();
r = readSP(); push(data);
} }
auto SPC700::op_push(uint8 r) { auto SPC700::instructionAbsoluteRead(fpb op, uint8& target) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
uint8 data = read(absolute);
target = alu(target, data);
}
auto SPC700::instructionAbsoluteIndexedRead(fpb op, uint8& index) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
idle(); idle();
uint8 data = read(absolute + index);
A = alu(A, data);
}
auto SPC700::instructionImmediateRead(fpb op, uint8& target) -> void {
uint8 data = fetch();
target = alu(target, data);
}
auto SPC700::instructionDirectPageRead(fpb op, uint8& target) -> void {
uint8 direct = fetch();
uint8 data = load(direct);
target = alu(target, data);
}
auto SPC700::instructionDirectPageIndexedRead(fpb op, uint8& data, uint8& index) -> void {
dp = fetch();
idle(); idle();
writeSP(r); rd = load(dp + index);
data = alu(data, rd);
} }
auto SPC700::op_read_addr(fpb op, reg r) { auto SPC700::instructionDirectPageReadWord(fpw op) -> void {
dp.l = readPC(); dp = fetch();
dp.h = readPC(); rd.l = load(dp++);
rd = read(dp); if(op != &SPC700::algorithmCPW) idle();
r = call(r, rd); rd.h = load(dp++);
YA = alu(YA, rd);
} }
auto SPC700::op_read_addri(fpb op, reg r) { auto SPC700::instructionIndirectPageXRead(fpb op) -> void {
dp.l = readPC(); dp = fetch() + X;
dp.h = readPC();
idle(); idle();
rd = read(dp + r); sp.l = load(dp++);
regs.a = call(regs.a, rd); sp.h = load(dp++);
}
auto SPC700::op_read_const(fpb op, reg r) {
rd = readPC();
r = call(r, rd);
}
auto SPC700::op_read_dp(fpb op, reg r) {
dp = readPC();
rd = readDP(dp);
r = call(r, rd);
}
auto SPC700::op_read_dpi(fpb op, reg r, reg i) {
dp = readPC();
idle();
rd = readDP(dp + i);
r = call(r, rd);
}
auto SPC700::op_read_dpw(fpw op) {
dp = readPC();
rd.l = readDP(dp++);
if(op != &SPC700::op_cpw) idle();
rd.h = readDP(dp++);
regs.ya = call(regs.ya, rd);
}
auto SPC700::op_read_idpx(fpb op) {
dp = readPC() + regs.x;
idle();
sp.l = readDP(dp++);
sp.h = readDP(dp++);
rd = read(sp); rd = read(sp);
regs.a = call(regs.a, rd); A = alu(A, rd);
} }
auto SPC700::op_read_idpy(fpb op) { auto SPC700::instructionIndirectPageYRead(fpb op) -> void {
dp = readPC(); dp = fetch();
idle(); idle();
sp.l = readDP(dp++); sp.l = load(dp++);
sp.h = readDP(dp++); sp.h = load(dp++);
rd = read(sp + regs.y); rd = read(sp + Y);
regs.a = call(regs.a, rd); A = alu(A, rd);
} }
auto SPC700::op_read_ix(fpb op) { auto SPC700::instructionIndirectXRead(fpb op) -> void {
idle(); idle();
rd = readDP(regs.x); rd = load(X);
regs.a = call(regs.a, rd); A = alu(A, rd);
} }
auto SPC700::op_set_addr_bit() { auto SPC700::instructionAbsoluteModifyBit() -> void {
dp.l = readPC(); dp.l = fetch();
dp.h = readPC(); dp.h = fetch();
bit = dp >> 13; bit = dp >> 13;
dp &= 0x1fff; dp &= 0x1fff;
rd = read(dp); rd = read(dp);
@ -144,22 +130,22 @@ auto SPC700::op_set_addr_bit() {
case 0: //orc addr:bit case 0: //orc addr:bit
case 1: //orc !addr:bit case 1: //orc !addr:bit
idle(); idle();
regs.p.c |= (rd & (1 << bit)) ^ (bool)(opcode & 0x20); CF |= (rd & (1 << bit)) ^ (bool)(opcode & 0x20);
break; break;
case 2: //and addr:bit case 2: //and addr:bit
case 3: //and !addr:bit case 3: //and !addr:bit
regs.p.c &= (rd & (1 << bit)) ^ (bool)(opcode & 0x20); CF &= (rd & (1 << bit)) ^ (bool)(opcode & 0x20);
break; break;
case 4: //eor addr:bit case 4: //eor addr:bit
idle(); idle();
regs.p.c ^= (bool)(rd & (1 << bit)); CF ^= (bool)(rd & (1 << bit));
break; break;
case 5: //ldc addr:bit case 5: //ldc addr:bit
regs.p.c = (rd & (1 << bit)); CF = (rd & (1 << bit));
break; break;
case 6: //stc addr:bit case 6: //stc addr:bit
idle(); idle();
rd = (rd & ~(1 << bit)) | (regs.p.c << bit); rd = (rd & ~(1 << bit)) | (CF << bit);
write(dp, rd); write(dp, rd);
break; break;
case 7: //not addr:bit case 7: //not addr:bit
@ -169,190 +155,209 @@ auto SPC700::op_set_addr_bit() {
} }
} }
auto SPC700::op_set_bit() { auto SPC700::instructionFlagClear(bool& flag) -> void {
dp = readPC();
rd = readDP(dp) & ~(1 << (opcode >> 5));
writeDP(dp, rd | (!(opcode & 0x10) << (opcode >> 5)));
}
auto SPC700::op_set_flag(uint bit, bool value) {
idle(); idle();
if(bit == regs.p.i.bit) idle(); if(&flag == &IF) idle();
regs.p = value ? (regs.p | (1 << bit)) : (regs.p & ~(1 << bit)); flag = 0;
} }
auto SPC700::op_test_addr(bool set) { auto SPC700::instructionFlagSet(bool& flag) -> void {
dp.l = readPC(); idle();
dp.h = readPC(); if(&flag == &IF) idle();
rd = read(dp); flag = 1;
regs.p.n = (regs.a - rd) & 0x80;
regs.p.z = (regs.a - rd) == 0;
read(dp);
write(dp, set ? rd | regs.a : rd & ~regs.a);
} }
auto SPC700::op_transfer(reg from, reg to) { auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void {
idle(); idle();
to = from; to = from;
if(&to == &regs.s) return; if(&to == &S) return;
regs.p.n = (to & 0x80); ZF = to == 0;
regs.p.z = (to == 0); NF = to & 0x80;
} }
auto SPC700::op_write_addr(reg r) { auto SPC700::instructionAbsoluteWrite(uint8& data) -> void {
dp.l = readPC(); dp.l = fetch();
dp.h = readPC(); dp.h = fetch();
read(dp); read(dp);
write(dp, r); write(dp, data);
} }
auto SPC700::op_write_addri(reg i) { auto SPC700::instructionAbsoluteIndexedWrite(uint8& index) -> void {
dp.l = readPC(); dp.l = fetch();
dp.h = readPC(); dp.h = fetch();
idle(); idle();
dp += i; dp += index;
read(dp); read(dp);
write(dp, regs.a); write(dp, A);
} }
auto SPC700::op_write_dp(reg r) { auto SPC700::instructionDirectPageWrite(uint8& data) -> void {
dp = readPC(); dp = fetch();
readDP(dp); load(dp);
writeDP(dp, r); store(dp, data);
} }
auto SPC700::op_write_dpi(reg r, reg i) { auto SPC700::instructionDirectPageIndexedWrite(uint8& data, uint8& index) -> void {
dp = readPC() + i; dp = fetch() + index;
idle(); idle();
readDP(dp); load(dp);
writeDP(dp, r); store(dp, data);
} }
auto SPC700::op_write_dp_const(fpb op) { auto SPC700::instructionDirectPageWriteImmediate(fpb op) -> void {
rd = readPC(); rd = fetch();
dp = readPC(); dp = fetch();
wr = readDP(dp); wr = load(dp);
wr = call(wr, rd); wr = alu(wr, rd);
op != &SPC700::op_cmp ? writeDP(dp, wr) : idle(); op != &SPC700::algorithmCMP ? store(dp, wr) : idle();
} }
auto SPC700::op_write_dp_dp(fpb op) { auto SPC700::instructionDirectPageWriteDirectPage(fpb op) -> void {
sp = readPC(); sp = fetch();
rd = readDP(sp); rd = load(sp);
dp = readPC(); dp = fetch();
if(op != &SPC700::op_st) wr = readDP(dp); if(op != &SPC700::algorithmST) wr = load(dp);
wr = call(wr, rd); wr = alu(wr, rd);
op != &SPC700::op_cmp ? writeDP(dp, wr) : idle(); op != &SPC700::algorithmCMP ? store(dp, wr) : idle();
} }
auto SPC700::op_write_ix_iy(fpb op) { auto SPC700::instructionIndirectXWriteIndirectY(fpb op) -> void {
idle(); idle();
rd = readDP(regs.y); rd = load(Y);
wr = readDP(regs.x); wr = load(X);
wr = call(wr, rd); wr = alu(wr, rd);
op != &SPC700::op_cmp ? writeDP(regs.x, wr) : idle(); op != &SPC700::algorithmCMP ? store(X, wr) : idle();
} }
// //
auto SPC700::op_bne_dp() { auto SPC700::instructionBBC(uint3 bit) -> void {
dp = readPC(); dp = fetch();
sp = readDP(dp); uint8 data = load(dp);
rd = readPC(); rd = fetch();
idle(); idle();
if(regs.a == sp) return; if(data.bit(bit) == 1) return;
idle(); idle();
idle(); idle();
regs.pc += (int8)rd; PC += (int8)rd;
} }
auto SPC700::op_bne_dpdec() { auto SPC700::instructionBBS(uint3 bit) -> void {
dp = readPC(); dp = fetch();
wr = readDP(dp); uint8 data = load(dp);
writeDP(dp, --wr); rd = fetch();
rd = readPC(); idle();
if(data.bit(bit) == 0) return;
idle();
idle();
PC += (int8)rd;
}
auto SPC700::instructionBNEDirectPage() -> void {
dp = fetch();
sp = load(dp);
rd = fetch();
idle();
if(A == sp) return;
idle();
idle();
PC += (int8)rd;
}
auto SPC700::instructionBNEDirectPageDecrement() -> void {
dp = fetch();
wr = load(dp);
store(dp, --wr);
rd = fetch();
if(wr == 0) return; if(wr == 0) return;
idle(); idle();
idle(); idle();
regs.pc += (int8)rd; PC += (int8)rd;
} }
auto SPC700::op_bne_dpx() { auto SPC700::instructionBNEDirectPageX() -> void {
dp = readPC(); dp = fetch();
idle(); idle();
sp = readDP(dp + regs.x); sp = load(dp + X);
rd = readPC(); rd = fetch();
idle(); idle();
if(regs.a == sp) return; if(A == sp) return;
idle(); idle();
idle(); idle();
regs.pc += (int8)rd; PC += (int8)rd;
} }
auto SPC700::op_bne_ydec() { auto SPC700::instructionBNEYDecrement() -> void {
rd = readPC(); rd = fetch();
idle(); idle();
idle(); idle();
if(--regs.y == 0) return; if(--Y == 0) return;
idle(); idle();
idle(); idle();
regs.pc += (int8)rd; PC += (int8)rd;
} }
auto SPC700::op_brk() { auto SPC700::instructionBRK() -> void {
rd.l = read(0xffde); rd.l = read(0xffde);
rd.h = read(0xffdf); rd.h = read(0xffdf);
idle(); idle();
idle(); idle();
writeSP(regs.pc.h); push(PC >> 8);
writeSP(regs.pc.l); push(PC >> 0);
writeSP(regs.p); push(P);
regs.pc = rd; PC = rd;
regs.p.b = 1; IF = 0;
regs.p.i = 0; BF = 1;
} }
auto SPC700::op_clv() { auto SPC700::instructionCLR(uint3 bit) -> void {
idle(); uint8 direct = fetch();
regs.p.v = 0; uint8 data = load(direct);
regs.p.h = 0; data.bit(bit) = 0;
store(direct, data);
} }
auto SPC700::op_cmc() { auto SPC700::instructionCLV() -> void {
idle(); idle();
idle(); HF = 0;
regs.p.c = !regs.p.c; VF = 0;
} }
auto SPC700::op_daa() { auto SPC700::instructionCMC() -> void {
idle(); idle();
idle(); idle();
if(regs.p.c || (regs.a) > 0x99) { CF = !CF;
regs.a += 0x60; }
regs.p.c = 1;
auto SPC700::instructionDAA() -> void {
idle();
idle();
if(CF || A > 0x99) {
A += 0x60;
CF = 1;
} }
if(regs.p.h || (regs.a & 15) > 0x09) { if(HF || (A & 15) > 0x09) {
regs.a += 0x06; A += 0x06;
} }
regs.p.n = (regs.a & 0x80); ZF = A == 0;
regs.p.z = (regs.a == 0); NF = A & 0x80;
} }
auto SPC700::op_das() { auto SPC700::instructionDAS() -> void {
idle(); idle();
idle(); idle();
if(!regs.p.c || (regs.a) > 0x99) { if(!CF || A > 0x99) {
regs.a -= 0x60; A -= 0x60;
regs.p.c = 0; CF = 0;
} }
if(!regs.p.h || (regs.a & 15) > 0x09) { if(!HF || (A & 15) > 0x09) {
regs.a -= 0x06; A -= 0x06;
} }
regs.p.n = (regs.a & 0x80); ZF = A == 0;
regs.p.z = (regs.a == 0); NF = A & 0x80;
} }
auto SPC700::op_div_ya_x() { auto SPC700::instructionDIV() -> void {
idle(); idle();
idle(); idle();
idle(); idle();
@ -364,82 +369,82 @@ auto SPC700::op_div_ya_x() {
idle(); idle();
idle(); idle();
idle(); idle();
ya = regs.ya; uint16 ya = YA;
//overflow set if quotient >= 256 //overflow set if quotient >= 256
regs.p.v = (regs.y >= regs.x); HF = (Y & 15) >= (X & 15);
regs.p.h = ((regs.y & 15) >= (regs.x & 15)); VF = Y >= X;
if(regs.y < (regs.x << 1)) { if(Y < (X << 1)) {
//if quotient is <= 511 (will fit into 9-bit result) //if quotient is <= 511 (will fit into 9-bit result)
regs.a = ya / regs.x; A = ya / X;
regs.y = ya % regs.x; Y = ya % X;
} else { } else {
//otherwise, the quotient won't fit into regs.p.v + regs.a //otherwise, the quotient won't fit into VF + A
//this emulates the odd behavior of the S-SMP in this case //this emulates the odd behavior of the S-SMP in this case
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); A = 255 - (ya - (X << 9)) / (256 - X);
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); Y = X + (ya - (X << 9)) % (256 - X);
} }
//result is set based on a (quotient) only //result is set based on a (quotient) only
regs.p.n = (regs.a & 0x80); ZF = A == 0;
regs.p.z = (regs.a == 0); NF = A & 0x80;
} }
auto SPC700::op_jmp_addr() { auto SPC700::instructionJMPAbsolute() -> void {
rd.l = readPC(); rd.l = fetch();
rd.h = readPC(); rd.h = fetch();
regs.pc = rd; PC = rd;
} }
auto SPC700::op_jmp_iaddrx() { auto SPC700::instructionJMPIndirectAbsoluteX() -> void {
dp.l = readPC(); dp.l = fetch();
dp.h = readPC(); dp.h = fetch();
idle(); idle();
dp += regs.x; dp += X;
rd.l = read(dp++); rd.l = read(dp++);
rd.h = read(dp++); rd.h = read(dp++);
regs.pc = rd; PC = rd;
} }
auto SPC700::op_jsp_dp() { auto SPC700::instructionJSPDirectPage() -> void {
rd = readPC(); rd = fetch();
idle(); idle();
idle(); idle();
writeSP(regs.pc.h); push(PC >> 8);
writeSP(regs.pc.l); push(PC >> 0);
regs.pc = 0xff00 | rd; PC = 0xff00 | rd;
} }
auto SPC700::op_jsr_addr() { auto SPC700::instructionJSRAbsolute() -> void {
rd.l = readPC(); rd.l = fetch();
rd.h = readPC(); rd.h = fetch();
idle(); idle();
idle(); idle();
idle(); idle();
writeSP(regs.pc.h); push(PC >> 8);
writeSP(regs.pc.l); push(PC >> 0);
regs.pc = rd; PC = rd;
} }
auto SPC700::op_jst() { auto SPC700::instructionJST(uint4 vector) -> void {
dp = 0xffde - ((opcode >> 4) << 1); dp = 0xffde - (vector << 1);
rd.l = read(dp++); rd.l = read(dp++);
rd.h = read(dp++); rd.h = read(dp++);
idle(); idle();
idle(); idle();
idle(); idle();
writeSP(regs.pc.h); push(PC >> 8);
writeSP(regs.pc.l); push(PC >> 0);
regs.pc = rd; PC = rd;
} }
auto SPC700::op_lda_ixinc() { auto SPC700::instructionLDAIndirectXIncrement() -> void {
idle(); idle();
regs.a = readDP(regs.x++); A = load(X++);
idle(); idle();
regs.p.n = regs.a & 0x80; ZF = A == 0;
regs.p.z = regs.a == 0; NF = A & 0x80;
} }
auto SPC700::op_mul_ya() { auto SPC700::instructionMUL() -> void {
idle(); idle();
idle(); idle();
idle(); idle();
@ -448,94 +453,128 @@ auto SPC700::op_mul_ya() {
idle(); idle();
idle(); idle();
idle(); idle();
ya = regs.y * regs.a; uint16 ya = Y * A;
regs.a = ya; A = ya >> 0;
regs.y = ya >> 8; Y = ya >> 8;
//result is set based on y (high-byte) only //result is set based on y (high-byte) only
regs.p.n = (regs.y & 0x80); ZF = Y == 0;
regs.p.z = (regs.y == 0); NF = Y & 0x80;
} }
auto SPC700::op_nop() { auto SPC700::instructionNOP() -> void {
idle(); idle();
} }
auto SPC700::op_plp() { auto SPC700::instructionPLP() -> void {
idle(); idle();
idle(); idle();
regs.p = readSP(); P = pull();
} }
auto SPC700::op_rti() { auto SPC700::instructionRTI() -> void {
regs.p = readSP(); P = pull();
rd.l = readSP(); rd.l = pull();
rd.h = readSP(); rd.h = pull();
idle(); idle();
idle(); idle();
regs.pc = rd; PC = rd;
} }
auto SPC700::op_rts() { auto SPC700::instructionRTS() -> void {
rd.l = readSP(); rd.l = pull();
rd.h = readSP(); rd.h = pull();
idle(); idle();
idle(); idle();
regs.pc = rd; PC = rd;
} }
auto SPC700::op_sta_idpx() { auto SPC700::instructionSET(uint3 bit) -> void {
sp = readPC() + regs.x; uint8 direct = fetch();
uint8 data = load(direct);
data.bit(bit) = 1;
store(direct, data);
}
auto SPC700::instructionSTAIndirectPageX() -> void {
sp = fetch() + X;
idle(); idle();
dp.l = readDP(sp++); dp.l = load(sp++);
dp.h = readDP(sp++); dp.h = load(sp++);
read(dp); read(dp);
write(dp, regs.a); write(dp, A);
} }
auto SPC700::op_sta_idpy() { auto SPC700::instructionSTAIndirectPageY() -> void {
sp = readPC(); sp = fetch();
dp.l = readDP(sp++); dp.l = load(sp++);
dp.h = readDP(sp++); dp.h = load(sp++);
idle(); idle();
dp += regs.y; dp += Y;
read(dp); read(dp);
write(dp, regs.a); write(dp, A);
} }
auto SPC700::op_sta_ix() { auto SPC700::instructionSTAIndirectX() -> void {
idle(); idle();
readDP(regs.x); load(X);
writeDP(regs.x, regs.a); store(X, A);
} }
auto SPC700::op_sta_ixinc() { auto SPC700::instructionSTAIndirectXIncrement() -> void {
idle(); idle();
idle(); idle();
writeDP(regs.x++, regs.a); store(X++, A);
} }
auto SPC700::op_stw_dp() { auto SPC700::instructionSTP() -> void {
dp = readPC();
readDP(dp);
writeDP(dp++, regs.a);
writeDP(dp++, regs.y);
}
auto SPC700::op_wait() {
while(true) { while(true) {
idle(); idle();
idle(); idle();
} }
} }
auto SPC700::op_xcn() { auto SPC700::instructionSTWDirectPage() -> void {
idle(); dp = fetch();
idle(); load(dp);
idle(); store(dp++, A);
idle(); store(dp++, Y);
regs.a = (regs.a >> 4) | (regs.a << 4);
regs.p.n = regs.a & 0x80;
regs.p.z = regs.a == 0;
} }
#undef call auto SPC700::instructionTRBAbsolute() -> void {
dp.l = fetch();
dp.h = fetch();
rd = read(dp);
ZF = (A - rd) == 0;
NF = (A - rd) & 0x80;
read(dp);
write(dp, rd & ~A);
}
auto SPC700::instructionTSBAbsolute() -> void {
dp.l = fetch();
dp.h = fetch();
rd = read(dp);
ZF = (A - rd) == 0;
NF = (A - rd) & 0x80;
read(dp);
write(dp, rd | A);
}
auto SPC700::instructionWAI() -> void {
while(true) {
idle();
idle();
}
}
auto SPC700::instructionXCN() -> void {
idle();
idle();
idle();
idle();
A = A >> 4 | A << 4;
ZF = A == 0;
NF = A & 0x80;
}
#undef alu

View File

@ -0,0 +1,19 @@
auto SPC700::fetch() -> uint8 {
return read(PC++);
}
auto SPC700::pull() -> uint8 {
return read(0x0100 | ++S);
}
auto SPC700::push(uint8 data) -> void {
return write(0x0100 | S--, data);
}
auto SPC700::load(uint8 addr) -> uint8 {
return read(PF << 8 | addr);
}
auto SPC700::store(uint8 addr, uint8 data) -> void {
return write(PF << 8 | addr, data);
}

View File

@ -1,19 +0,0 @@
alwaysinline auto readPC() -> uint8 {
return read(regs.pc++);
}
alwaysinline auto readSP() -> uint8 {
return read(0x0100 | ++regs.s);
}
alwaysinline auto writeSP(uint8 data) -> void {
return write(0x0100 | regs.s--, data);
}
alwaysinline auto readDP(uint8 addr) -> uint8 {
return read(regs.p.p << 8 | addr);
}
alwaysinline auto writeDP(uint8 addr, uint8 data) -> void {
return write(regs.p.p << 8 | addr, data);
}

View File

@ -1,53 +0,0 @@
struct Flags {
union {
uint8_t data = 0;
BooleanBitField<uint8_t, 7> n;
BooleanBitField<uint8_t, 6> v;
BooleanBitField<uint8_t, 5> p;
BooleanBitField<uint8_t, 4> b;
BooleanBitField<uint8_t, 3> h;
BooleanBitField<uint8_t, 2> i;
BooleanBitField<uint8_t, 1> z;
BooleanBitField<uint8_t, 0> c;
};
inline operator uint() const { return data; }
inline auto& operator =(uint value) { return data = value, *this; }
inline auto& operator&=(uint value) { return data &= value, *this; }
inline auto& operator|=(uint value) { return data |= value, *this; }
inline auto& operator^=(uint value) { return data ^= value, *this; }
};
struct Register {
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=(const Register& value) { w = value.w; }
inline auto operator++(int) { uint value = w++; return value; }
inline auto operator--(int) { uint value = w--; return value; }
inline auto& operator++() { return ++w, *this; }
inline auto& operator--() { return --w, *this; }
inline auto& operator =(uint value) { return w = value, *this; }
inline auto& operator&=(uint value) { return w &= value, *this; }
inline auto& operator|=(uint value) { return w |= value, *this; }
inline auto& operator^=(uint value) { return w ^= value, *this; }
inline auto& operator+=(uint value) { return w += value, *this; }
inline auto& operator-=(uint value) { return w -= value, *this; }
};
struct Registers {
Register pc;
union {
uint16_t ya;
struct { uint8_t order_lsb2(a, y); };
};
uint8_t x, s;
Flags p;
};

View File

@ -1,10 +1,16 @@
auto SPC700::serialize(serializer& s) -> void { auto SPC700::serialize(serializer& s) -> void {
s.integer(regs.pc.w); s.integer(r.pc.w);
s.integer(regs.a); s.integer(r.ya.w);
s.integer(regs.x); s.integer(r.x);
s.integer(regs.y); s.integer(r.s);
s.integer(regs.s); s.integer(r.p.c);
s.integer(regs.p.data); s.integer(r.p.z);
s.integer(r.p.i);
s.integer(r.p.h);
s.integer(r.p.b);
s.integer(r.p.p);
s.integer(r.p.v);
s.integer(r.p.n);
s.integer(opcode); s.integer(opcode);
s.integer(dp.w); s.integer(dp.w);
@ -12,5 +18,4 @@ auto SPC700::serialize(serializer& s) -> void {
s.integer(rd.w); s.integer(rd.w);
s.integer(wr.w); s.integer(wr.w);
s.integer(bit.w); s.integer(bit.w);
s.integer(ya.w);
} }

View File

@ -3,276 +3,53 @@
namespace Processor { namespace Processor {
#define PC r.pc.w
#define YA r.ya.w
#define A r.ya.byte.l
#define X r.x
#define Y r.ya.byte.h
#define S r.s
#define P r.p
#define CF r.p.c
#define ZF r.p.z
#define IF r.p.i
#define HF r.p.h
#define BF r.p.b
#define PF r.p.p
#define VF r.p.v
#define NF r.p.n
#include "memory.cpp"
#include "algorithms.cpp" #include "algorithms.cpp"
#include "instructions.cpp" #include "instructions.cpp"
#include "disassembler.cpp" #include "instruction.cpp"
#include "serialization.cpp" #include "serialization.cpp"
#include "disassembler.cpp"
#define op(id, name, ...) case id: return op_##name(__VA_ARGS__); #undef PC
#define fp(name) &SPC700::op_##name #undef YA
#undef A
#undef X
#undef Y
#undef S
#undef P
auto SPC700::instruction() -> void { #undef CF
switch(opcode = readPC()) { #undef ZF
op(0x00, nop) #undef IF
op(0x01, jst) #undef HF
op(0x02, set_bit) #undef BF
op(0x03, branch_bit) #undef PF
op(0x04, read_dp, fp(or), regs.a) #undef VF
op(0x05, read_addr, fp(or), regs.a) #undef NF
op(0x06, read_ix, fp(or))
op(0x07, read_idpx, fp(or)) auto SPC700::power() -> void {
op(0x08, read_const, fp(or), regs.a) r.pc.w = 0x0000;
op(0x09, write_dp_dp, fp(or)) r.ya.w = 0x0000;
op(0x0a, set_addr_bit) r.x = 0x00;
op(0x0b, adjust_dp, fp(asl)) r.s = 0xef;
op(0x0c, adjust_addr, fp(asl)) r.p = 0x02;
op(0x0d, push, regs.p)
op(0x0e, test_addr, 1)
op(0x0f, brk)
op(0x10, branch, regs.p.n == 0)
op(0x11, jst)
op(0x12, set_bit)
op(0x13, branch_bit)
op(0x14, read_dpi, fp(or), regs.a, regs.x)
op(0x15, read_addri, fp(or), regs.x)
op(0x16, read_addri, fp(or), regs.y)
op(0x17, read_idpy, fp(or))
op(0x18, write_dp_const, fp(or))
op(0x19, write_ix_iy, fp(or))
op(0x1a, adjust_dpw, -1)
op(0x1b, adjust_dpx, fp(asl))
op(0x1c, adjust, fp(asl), regs.a)
op(0x1d, adjust, fp(dec), regs.x)
op(0x1e, read_addr, fp(cmp), regs.x)
op(0x1f, jmp_iaddrx)
op(0x20, set_flag, regs.p.p.bit, 0)
op(0x21, jst)
op(0x22, set_bit)
op(0x23, branch_bit)
op(0x24, read_dp, fp(and), regs.a)
op(0x25, read_addr, fp(and), regs.a)
op(0x26, read_ix, fp(and))
op(0x27, read_idpx, fp(and))
op(0x28, read_const, fp(and), regs.a)
op(0x29, write_dp_dp, fp(and))
op(0x2a, set_addr_bit)
op(0x2b, adjust_dp, fp(rol))
op(0x2c, adjust_addr, fp(rol))
op(0x2d, push, regs.a)
op(0x2e, bne_dp)
op(0x2f, branch, true)
op(0x30, branch, regs.p.n == 1)
op(0x31, jst)
op(0x32, set_bit)
op(0x33, branch_bit)
op(0x34, read_dpi, fp(and), regs.a, regs.x)
op(0x35, read_addri, fp(and), regs.x)
op(0x36, read_addri, fp(and), regs.y)
op(0x37, read_idpy, fp(and))
op(0x38, write_dp_const, fp(and))
op(0x39, write_ix_iy, fp(and))
op(0x3a, adjust_dpw, +1)
op(0x3b, adjust_dpx, fp(rol))
op(0x3c, adjust, fp(rol), regs.a)
op(0x3d, adjust, fp(inc), regs.x)
op(0x3e, read_dp, fp(cmp), regs.x)
op(0x3f, jsr_addr)
op(0x40, set_flag, regs.p.p.bit, 1)
op(0x41, jst)
op(0x42, set_bit)
op(0x43, branch_bit)
op(0x44, read_dp, fp(eor), regs.a)
op(0x45, read_addr, fp(eor), regs.a)
op(0x46, read_ix, fp(eor))
op(0x47, read_idpx, fp(eor))
op(0x48, read_const, fp(eor), regs.a)
op(0x49, write_dp_dp, fp(eor))
op(0x4a, set_addr_bit)
op(0x4b, adjust_dp, fp(lsr))
op(0x4c, adjust_addr, fp(lsr))
op(0x4d, push, regs.x)
op(0x4e, test_addr, 0)
op(0x4f, jsp_dp)
op(0x50, branch, regs.p.v == 0)
op(0x51, jst)
op(0x52, set_bit)
op(0x53, branch_bit)
op(0x54, read_dpi, fp(eor), regs.a, regs.x)
op(0x55, read_addri, fp(eor), regs.x)
op(0x56, read_addri, fp(eor), regs.y)
op(0x57, read_idpy, fp(eor))
op(0x58, write_dp_const, fp(eor))
op(0x59, write_ix_iy, fp(eor))
op(0x5a, read_dpw, fp(cpw))
op(0x5b, adjust_dpx, fp(lsr))
op(0x5c, adjust, fp(lsr), regs.a)
op(0x5d, transfer, regs.a, regs.x)
op(0x5e, read_addr, fp(cmp), regs.y)
op(0x5f, jmp_addr)
op(0x60, set_flag, regs.p.c.bit, 0)
op(0x61, jst)
op(0x62, set_bit)
op(0x63, branch_bit)
op(0x64, read_dp, fp(cmp), regs.a)
op(0x65, read_addr, fp(cmp), regs.a)
op(0x66, read_ix, fp(cmp))
op(0x67, read_idpx, fp(cmp))
op(0x68, read_const, fp(cmp), regs.a)
op(0x69, write_dp_dp, fp(cmp))
op(0x6a, set_addr_bit)
op(0x6b, adjust_dp, fp(ror))
op(0x6c, adjust_addr, fp(ror))
op(0x6d, push, regs.y)
op(0x6e, bne_dpdec)
op(0x6f, rts)
op(0x70, branch, regs.p.v == 1)
op(0x71, jst)
op(0x72, set_bit)
op(0x73, branch_bit)
op(0x74, read_dpi, fp(cmp), regs.a, regs.x)
op(0x75, read_addri, fp(cmp), regs.x)
op(0x76, read_addri, fp(cmp), regs.y)
op(0x77, read_idpy, fp(cmp))
op(0x78, write_dp_const, fp(cmp))
op(0x79, write_ix_iy, fp(cmp))
op(0x7a, read_dpw, fp(adw))
op(0x7b, adjust_dpx, fp(ror))
op(0x7c, adjust, fp(ror), regs.a)
op(0x7d, transfer, regs.x, regs.a)
op(0x7e, read_dp, fp(cmp), regs.y)
op(0x7f, rti)
op(0x80, set_flag, regs.p.c.bit, 1)
op(0x81, jst)
op(0x82, set_bit)
op(0x83, branch_bit)
op(0x84, read_dp, fp(adc), regs.a)
op(0x85, read_addr, fp(adc), regs.a)
op(0x86, read_ix, fp(adc))
op(0x87, read_idpx, fp(adc))
op(0x88, read_const, fp(adc), regs.a)
op(0x89, write_dp_dp, fp(adc))
op(0x8a, set_addr_bit)
op(0x8b, adjust_dp, fp(dec))
op(0x8c, adjust_addr, fp(dec))
op(0x8d, read_const, fp(ld), regs.y)
op(0x8e, plp)
op(0x8f, write_dp_const, fp(st))
op(0x90, branch, regs.p.c == 0)
op(0x91, jst)
op(0x92, set_bit)
op(0x93, branch_bit)
op(0x94, read_dpi, fp(adc), regs.a, regs.x)
op(0x95, read_addri, fp(adc), regs.x)
op(0x96, read_addri, fp(adc), regs.y)
op(0x97, read_idpy, fp(adc))
op(0x98, write_dp_const, fp(adc))
op(0x99, write_ix_iy, fp(adc))
op(0x9a, read_dpw, fp(sbw))
op(0x9b, adjust_dpx, fp(dec))
op(0x9c, adjust, fp(dec), regs.a)
op(0x9d, transfer, regs.s, regs.x)
op(0x9e, div_ya_x)
op(0x9f, xcn)
op(0xa0, set_flag, regs.p.i.bit, 1)
op(0xa1, jst)
op(0xa2, set_bit)
op(0xa3, branch_bit)
op(0xa4, read_dp, fp(sbc), regs.a)
op(0xa5, read_addr, fp(sbc), regs.a)
op(0xa6, read_ix, fp(sbc))
op(0xa7, read_idpx, fp(sbc))
op(0xa8, read_const, fp(sbc), regs.a)
op(0xa9, write_dp_dp, fp(sbc))
op(0xaa, set_addr_bit)
op(0xab, adjust_dp, fp(inc))
op(0xac, adjust_addr, fp(inc))
op(0xad, read_const, fp(cmp), regs.y)
op(0xae, pull, regs.a)
op(0xaf, sta_ixinc)
op(0xb0, branch, regs.p.c == 1)
op(0xb1, jst)
op(0xb2, set_bit)
op(0xb3, branch_bit)
op(0xb4, read_dpi, fp(sbc), regs.a, regs.x)
op(0xb5, read_addri, fp(sbc), regs.x)
op(0xb6, read_addri, fp(sbc), regs.y)
op(0xb7, read_idpy, fp(sbc))
op(0xb8, write_dp_const, fp(sbc))
op(0xb9, write_ix_iy, fp(sbc))
op(0xba, read_dpw, fp(ldw))
op(0xbb, adjust_dpx, fp(inc))
op(0xbc, adjust, fp(inc), regs.a)
op(0xbd, transfer, regs.x, regs.s)
op(0xbe, das)
op(0xbf, lda_ixinc)
op(0xc0, set_flag, regs.p.i.bit, 0)
op(0xc1, jst)
op(0xc2, set_bit)
op(0xc3, branch_bit)
op(0xc4, write_dp, regs.a)
op(0xc5, write_addr, regs.a)
op(0xc6, sta_ix)
op(0xc7, sta_idpx)
op(0xc8, read_const, fp(cmp), regs.x)
op(0xc9, write_addr, regs.x)
op(0xca, set_addr_bit)
op(0xcb, write_dp, regs.y)
op(0xcc, write_addr, regs.y)
op(0xcd, read_const, fp(ld), regs.x)
op(0xce, pull, regs.x)
op(0xcf, mul_ya)
op(0xd0, branch, regs.p.z == 0)
op(0xd1, jst)
op(0xd2, set_bit)
op(0xd3, branch_bit)
op(0xd4, write_dpi, regs.a, regs.x)
op(0xd5, write_addri, regs.x)
op(0xd6, write_addri, regs.y)
op(0xd7, sta_idpy)
op(0xd8, write_dp, regs.x)
op(0xd9, write_dpi, regs.x, regs.y)
op(0xda, stw_dp)
op(0xdb, write_dpi, regs.y, regs.x)
op(0xdc, adjust, fp(dec), regs.y)
op(0xdd, transfer, regs.y, regs.a)
op(0xde, bne_dpx)
op(0xdf, daa)
op(0xe0, clv)
op(0xe1, jst)
op(0xe2, set_bit)
op(0xe3, branch_bit)
op(0xe4, read_dp, fp(ld), regs.a)
op(0xe5, read_addr, fp(ld), regs.a)
op(0xe6, read_ix, fp(ld))
op(0xe7, read_idpx, fp(ld))
op(0xe8, read_const, fp(ld), regs.a)
op(0xe9, read_addr, fp(ld), regs.x)
op(0xea, set_addr_bit)
op(0xeb, read_dp, fp(ld), regs.y)
op(0xec, read_addr, fp(ld), regs.y)
op(0xed, cmc)
op(0xee, pull, regs.y)
op(0xef, wait)
op(0xf0, branch, regs.p.z == 1)
op(0xf1, jst)
op(0xf2, set_bit)
op(0xf3, branch_bit)
op(0xf4, read_dpi, fp(ld), regs.a, regs.x)
op(0xf5, read_addri, fp(ld), regs.x)
op(0xf6, read_addri, fp(ld), regs.y)
op(0xf7, read_idpy, fp(ld))
op(0xf8, read_dp, fp(ld), regs.x)
op(0xf9, read_dpi, fp(ld), regs.x, regs.y)
op(0xfa, write_dp_dp, fp(st))
op(0xfb, read_dpi, fp(ld), regs.y, regs.x)
op(0xfc, adjust, fp(inc), regs.y)
op(0xfd, transfer, regs.a, regs.y)
op(0xfe, bne_ydec)
op(0xff, wait)
}
} }
#undef op
#undef fp
} }

View File

@ -8,103 +8,178 @@ struct SPC700 {
virtual auto write(uint16 addr, uint8 data) -> void = 0; virtual auto write(uint16 addr, uint8 data) -> void = 0;
virtual auto readDisassembler(uint16 addr) -> uint8 = 0; virtual auto readDisassembler(uint16 addr) -> uint8 = 0;
//spc700.cpp
auto power() -> void;
//instruction.cpp
auto instruction() -> void; auto instruction() -> void;
auto serialize(serializer&) -> void; //memory.cpp
auto fetch() -> uint8;
auto pull() -> uint8;
auto push(uint8 data) -> void;
auto load(uint8 addr) -> uint8;
auto store(uint8 addr, uint8 data) -> void;
auto disassemble(uint16 addr, bool p) -> string; //algorithms.cpp
auto algorithmADC(uint8, uint8) -> uint8;
auto algorithmAND(uint8, uint8) -> uint8;
auto algorithmASL(uint8) -> uint8;
auto algorithmCMP(uint8, uint8) -> uint8;
auto algorithmDEC(uint8) -> uint8;
auto algorithmEOR(uint8, uint8) -> uint8;
auto algorithmINC(uint8) -> uint8;
auto algorithmLD (uint8, uint8) -> uint8;
auto algorithmLSR(uint8) -> uint8;
auto algorithmOR (uint8, uint8) -> uint8;
auto algorithmROL(uint8) -> uint8;
auto algorithmROR(uint8) -> uint8;
auto algorithmSBC(uint8, uint8) -> uint8;
auto algorithmST (uint8, uint8) -> uint8;
auto algorithmADW(uint16, uint16) -> uint16;
auto algorithmCPW(uint16, uint16) -> uint16;
auto algorithmLDW(uint16, uint16) -> uint16;
auto algorithmSBW(uint16, uint16) -> uint16;
#include "registers.hpp" //instructions.cpp
#include "memory.hpp"
Registers regs;
Register dp, sp, rd, wr, bit, ya;
uint8 opcode;
protected:
using fps = auto (SPC700::*)(uint8) -> uint8; using fps = auto (SPC700::*)(uint8) -> uint8;
using fpb = auto (SPC700::*)(uint8, uint8) -> uint8; using fpb = auto (SPC700::*)(uint8, uint8) -> uint8;
using fpw = auto (SPC700::*)(uint16, uint16) -> uint16; using fpw = auto (SPC700::*)(uint16, uint16) -> uint16;
using reg = uint8_t&;
auto op_adc(uint8, uint8) -> uint8; auto instructionImpliedModify(fps, uint8&) -> void;
auto op_and(uint8, uint8) -> uint8; auto instructionAbsoluteModify(fps) -> void;
auto op_asl(uint8) -> uint8; auto instructionDirectPageModify(fps) -> void;
auto op_cmp(uint8, uint8) -> uint8; auto instructionDirectPageModifyWord(int) -> void;
auto op_dec(uint8) -> uint8; auto instructionDirectPageXModify(fps) -> void;
auto op_eor(uint8, uint8) -> uint8; auto instructionBranch(bool) -> void;
auto op_inc(uint8) -> uint8; auto instructionPull(uint8&) -> void;
auto op_ld (uint8, uint8) -> uint8; auto instructionPush(uint8) -> void;
auto op_lsr(uint8) -> uint8; auto instructionAbsoluteRead(fpb, uint8&) -> void;
auto op_or (uint8, uint8) -> uint8; auto instructionAbsoluteIndexedRead(fpb, uint8&) -> void;
auto op_rol(uint8) -> uint8; auto instructionImmediateRead(fpb, uint8&) -> void;
auto op_ror(uint8) -> uint8; auto instructionDirectPageRead(fpb, uint8&) -> void;
auto op_sbc(uint8, uint8) -> uint8; auto instructionDirectPageIndexedRead(fpb, uint8&, uint8&) -> void;
auto op_st (uint8, uint8) -> uint8; auto instructionDirectPageReadWord(fpw) -> void;
auto op_adw(uint16, uint16) -> uint16; auto instructionIndirectPageXRead(fpb) -> void;
auto op_cpw(uint16, uint16) -> uint16; auto instructionIndirectPageYRead(fpb) -> void;
auto op_ldw(uint16, uint16) -> uint16; auto instructionIndirectXRead(fpb) -> void;
auto op_sbw(uint16, uint16) -> uint16; auto instructionAbsoluteModifyBit() -> void;
auto instructionFlagClear(bool&) -> void;
auto instructionFlagSet(bool&) -> void;
auto instructionTransfer(uint8&, uint8&) -> void;
auto instructionAbsoluteWrite(uint8&) -> void;
auto instructionAbsoluteIndexedWrite(uint8&) -> void;
auto instructionDirectPageWrite(uint8&) -> void;
auto instructionDirectPageIndexedWrite(uint8&, uint8&) -> void;
auto instructionDirectPageWriteImmediate(fpb) -> void;
auto instructionDirectPageWriteDirectPage(fpb) -> void;
auto instructionIndirectXWriteIndirectY(fpb) -> void;
auto op_adjust(fps, reg); auto instructionBBC(uint3) -> void;
auto op_adjust_addr(fps); auto instructionBBS(uint3) -> void;
auto op_adjust_dp(fps); auto instructionBNEDirectPage() -> void;
auto op_adjust_dpw(int); auto instructionBNEDirectPageDecrement() -> void;
auto op_adjust_dpx(fps); auto instructionBNEDirectPageX() -> void;
auto op_branch(bool); auto instructionBNEYDecrement() -> void;
auto op_branch_bit(); auto instructionBRK() -> void;
auto op_pull(reg); auto instructionCLR(uint3) -> void;
auto op_push(uint8); auto instructionCLV() -> void;
auto op_read_addr(fpb, reg); auto instructionCMC() -> void;
auto op_read_addri(fpb, reg); auto instructionDAA() -> void;
auto op_read_const(fpb, reg); auto instructionDAS() -> void;
auto op_read_dp(fpb, reg); auto instructionDIV() -> void;
auto op_read_dpi(fpb, reg, reg); auto instructionJMPAbsolute() -> void;
auto op_read_dpw(fpw); auto instructionJMPIndirectAbsoluteX() -> void;
auto op_read_idpx(fpb); auto instructionJSPDirectPage() -> void;
auto op_read_idpy(fpb); auto instructionJSRAbsolute() -> void;
auto op_read_ix(fpb); auto instructionJST(uint4) -> void;
auto op_set_addr_bit(); auto instructionLDAIndirectXIncrement() -> void;
auto op_set_bit(); auto instructionMUL() -> void;
auto op_set_flag(uint, bool); auto instructionNOP() -> void;
auto op_test_addr(bool); auto instructionPLP() -> void;
auto op_transfer(reg, reg); auto instructionRTI() -> void;
auto op_write_addr(reg); auto instructionRTS() -> void;
auto op_write_addri(reg); auto instructionSET(uint3) -> void;
auto op_write_dp(reg); auto instructionSTAIndirectPageX() -> void;
auto op_write_dpi(reg, reg); auto instructionSTAIndirectPageY() -> void;
auto op_write_dp_const(fpb); auto instructionSTAIndirectX() -> void;
auto op_write_dp_dp(fpb); auto instructionSTAIndirectXIncrement() -> void;
auto op_write_ix_iy(fpb); auto instructionSTP() -> void;
auto instructionSTWDirectPage() -> void;
auto instructionTRBAbsolute() -> void;
auto instructionTSBAbsolute() -> void;
auto instructionWAI() -> void;
auto instructionXCN() -> void;
auto op_bne_dp(); //serialization.cpp
auto op_bne_dpdec(); auto serialize(serializer&) -> void;
auto op_bne_dpx();
auto op_bne_ydec(); //disassembler.cpp
auto op_brk(); auto disassemble(uint16 addr, bool p) -> string;
auto op_clv();
auto op_cmc(); struct Flags {
auto op_daa(); bool c; //carry
auto op_das(); bool z; //zero
auto op_div_ya_x(); bool i; //interrupt disable
auto op_jmp_addr(); bool h; //half-carry
auto op_jmp_iaddrx(); bool b; //break
auto op_jsp_dp(); bool p; //page
auto op_jsr_addr(); bool v; //overflow
auto op_jst(); bool n; //negative
auto op_lda_ixinc();
auto op_mul_ya(); inline operator uint() const {
auto op_nop(); return c << 0 | z << 1 | i << 2 | h << 3 | b << 4 | p << 5 | v << 6 | n << 7;
auto op_plp(); }
auto op_rti();
auto op_rts(); inline auto& operator=(uint8 data) {
auto op_sta_idpx(); c = data.bit(0);
auto op_sta_idpy(); z = data.bit(1);
auto op_sta_ix(); i = data.bit(2);
auto op_sta_ixinc(); h = data.bit(3);
auto op_stw_dp(); b = data.bit(4);
auto op_wait(); p = data.bit(5);
auto op_xcn(); v = data.bit(6);
n = data.bit(7);
return *this;
}
};
struct Registers {
union Pair {
Pair() : w(0) {}
uint16 w;
struct Byte { uint8 order_lsb2(l, h); } byte;
} pc, ya;
uint8 x, s;
Flags p;
} r;
struct Register {
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=(const Register& value) { w = value.w; }
inline auto operator++(int) { uint value = w++; return value; }
inline auto operator--(int) { uint value = w--; return value; }
inline auto& operator++() { return ++w, *this; }
inline auto& operator--() { return --w, *this; }
inline auto& operator =(uint value) { return w = value, *this; }
inline auto& operator&=(uint value) { return w &= value, *this; }
inline auto& operator|=(uint value) { return w |= value, *this; }
inline auto& operator^=(uint value) { return w ^= value, *this; }
inline auto& operator+=(uint value) { return w += value, *this; }
inline auto& operator-=(uint value) { return w -= value, *this; }
};
Register dp, sp, rd, wr, bit;
uint8 opcode;
}; };
} }

View File

@ -38,7 +38,7 @@ auto WDC65816::algorithmADC16(uint16 data) -> uint16 {
} }
VF = ~(A ^ data) & (A ^ result) & 0x8000; VF = ~(A ^ data) & (A ^ result) & 0x8000;
if(D && result > 0x9fff) result += 0x6000; if(DF && result > 0x9fff) result += 0x6000;
CF = result > 0xffff; CF = result > 0xffff;
ZF = (uint16)result == 0; ZF = (uint16)result == 0;
NF = result & 0x8000; NF = result & 0x8000;
@ -48,7 +48,7 @@ auto WDC65816::algorithmADC16(uint16 data) -> uint16 {
auto WDC65816::algorithmAND8(uint8 data) -> uint8 { auto WDC65816::algorithmAND8(uint8 data) -> uint8 {
lo(A) &= data; lo(A) &= data;
ZF = A == 0; ZF = lo(A) == 0;
NF = A & 0x80; NF = A & 0x80;
return data; return data;
} }
@ -148,13 +148,13 @@ auto WDC65816::algorithmDEC8(uint8 data) -> uint8 {
auto WDC65816::algorithmDEC16(uint16 data) -> uint16 { auto WDC65816::algorithmDEC16(uint16 data) -> uint16 {
data--; data--;
ZF = data == 0; ZF = data == 0;
NF = data & 0x80; NF = data & 0x8000;
return data; return data;
} }
auto WDC65816::algorithmEOR8(uint8 data) -> uint8 { auto WDC65816::algorithmEOR8(uint8 data) -> uint8 {
lo(A) ^= data; lo(A) ^= data;
ZF = A == 0; ZF = lo(A) == 0;
NF = A & 0x80; NF = A & 0x80;
return lo(A); return lo(A);
} }

View File

@ -171,7 +171,7 @@ L push(lo(data));
auto WDC65816::instructionPHD() -> void { auto WDC65816::instructionPHD() -> void {
idle(); idle();
pushN(hi(D)); pushN(hi(D));
L pushN(hi(D)); L pushN(lo(D));
E hi(S) = 0x01; E hi(S) = 0x01;
} }

View File

@ -112,7 +112,7 @@ auto WDC65816::instructionRTS() -> void {
uint16 data = pull(); uint16 data = pull();
hi(data) = pull(); hi(data) = pull();
L idle(); L idle();
PC = data; aa(PC) = data;
aa(PC)++; aa(PC)++;
} }

View File

@ -50,11 +50,6 @@ auto CPU::main() -> void {
} }
} }
#if 1
static uint counter = 0;
if(++counter < 40) print(disassemble(), "\n");
#endif
instruction(); instruction();
} }

View File

@ -74,7 +74,7 @@ auto SMP::readBus(uint16 addr) -> uint8 {
auto SMP::writeBus(uint16 addr, uint8 data) -> void { auto SMP::writeBus(uint16 addr, uint8 data) -> void {
switch(addr) { switch(addr) {
case 0xf0: //TEST case 0xf0: //TEST
if(regs.p.p) break; //writes only valid when P flag is clear if(r.p.p) break; //writes only valid when P flag is clear
io.clockSpeed = (data >> 6) & 3; io.clockSpeed = (data >> 6) & 3;
io.timerSpeed = (data >> 4) & 3; io.timerSpeed = (data >> 4) & 3;

View File

@ -27,15 +27,11 @@ auto SMP::load(Markup::Node node) -> bool {
} }
auto SMP::power() -> void { auto SMP::power() -> void {
SPC700::power();
create(Enter, 32040.0 * 768.0); create(Enter, 32040.0 * 768.0);
regs.pc.l = iplrom[62]; r.pc.byte.l = iplrom[62];
regs.pc.h = iplrom[63]; r.pc.byte.h = iplrom[63];
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;
regs.s = 0xef;
regs.p = 0x02;
for(auto& byte : apuram) byte = random(0x00); for(auto& byte : apuram) byte = random(0x00);
apuram[0x00f4] = 0x00; apuram[0x00f4] = 0x00;