diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 1b7e9a53..1256f98d 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { 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 License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/md/ym2612/ym2612.hpp b/higan/md/ym2612/ym2612.hpp index 7b2e9a70..dc0695dd 100644 --- a/higan/md/ym2612/ym2612.hpp +++ b/higan/md/ym2612/ym2612.hpp @@ -32,7 +32,7 @@ private: struct DAC { uint1 enable = 0; - uint8 sample = 0; + uint8 sample = 0x80; } dac; struct Envelope { diff --git a/higan/processor/arm/instructions-arm.cpp b/higan/processor/arm/instructions-arm.cpp index d4af7bfc..7697a1d6 100644 --- a/higan/processor/arm/instructions-arm.cpp +++ b/higan/processor/arm/instructions-arm.cpp @@ -108,6 +108,7 @@ auto ARM::arm_op_multiply_long() { idle(); idle(); + if(accumulate) idle(); //this instruction uses an 8-bit Booth algorithm for multiplication //this supports short-circuiting, so that smaller numbers multiply faster diff --git a/higan/processor/huc6280/algorithms.cpp b/higan/processor/huc6280/algorithms.cpp new file mode 100644 index 00000000..7ca334e0 --- /dev/null +++ b/higan/processor/huc6280/algorithms.cpp @@ -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++; +} diff --git a/higan/processor/huc6280/huc6280.cpp b/higan/processor/huc6280/huc6280.cpp index 7f17cd03..a1631a89 100644 --- a/higan/processor/huc6280/huc6280.cpp +++ b/higan/processor/huc6280/huc6280.cpp @@ -24,6 +24,7 @@ namespace Processor { #define ALU (this->*alu) #include "memory.cpp" +#include "algorithms.cpp" #include "instruction.cpp" #include "instructions.cpp" #include "disassembler.cpp" diff --git a/higan/processor/huc6280/huc6280.hpp b/higan/processor/huc6280/huc6280.hpp index 59c7b0a7..fb125485 100644 --- a/higan/processor/huc6280/huc6280.hpp +++ b/higan/processor/huc6280/huc6280.hpp @@ -27,82 +27,83 @@ struct HuC6280 { auto push(uint8) -> void; 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 auto interrupt(uint16 vector) -> void; auto instruction() -> void; //instructions.cpp - using fp = auto (HuC6280::*)(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 TRB(uint8) -> uint8; - auto TSB(uint8) -> uint8; + auto instructionAbsoluteModify(fp, uint8 = 0) -> void; + auto instructionAbsoluteRead(fp, uint8&, uint8 = 0) -> void; + auto instructionAbsoluteWrite(uint8, uint8 = 0) -> void; + auto instructionBlockMove(bp) -> void; + auto instructionBranch(bool) -> void; + auto instructionClear(uint8&) -> void; + auto instructionClear(bool&) -> void; + auto instructionImmediate(fp, uint8&) -> void; + auto instructionImplied(fp, uint8&) -> void; + auto instructionIndirectRead(fp, uint8&, uint8 = 0) -> void; + auto instructionIndirectWrite(uint8, uint8 = 0) -> void; + auto instructionIndirectYRead(fp, uint8&) -> void; + auto instructionIndirectYWrite(uint8) -> void; + auto instructionMemory(fp) -> void; + auto instructionPull(uint8&) -> void; + auto instructionPush(uint8) -> void; + auto instructionSet(bool&) -> void; + auto instructionSwap(uint8&, uint8&) -> void; + 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 TAI(uint16&, uint16&, bool) -> void; - auto TDD(uint16&, uint16&, bool) -> void; - auto TIA(uint16&, uint16&, bool) -> void; - auto TII(uint16&, uint16&, bool) -> void; - auto TIN(uint16&, uint16&, bool) -> void; - - auto instruction_absoluteLoad(fp, uint8&, uint8 = 0) -> void; - auto instruction_absoluteModify(fp, uint8 = 0) -> void; - auto instruction_absoluteStore(uint8, uint8 = 0) -> void; - auto instruction_blockmove(bp) -> void; - auto instruction_branch(bool) -> void; - auto instruction_clear(uint8&) -> void; - auto instruction_clear(bool&) -> void; - auto instruction_immediate(fp, uint8&) -> void; - auto instruction_implied(fp, uint8&) -> void; - auto instruction_indirectLoad(fp, uint8&, uint8 = 0) -> void; - auto instruction_indirectStore(uint8, uint8 = 0) -> void; - auto instruction_indirectYLoad(fp, uint8&) -> void; - auto instruction_indirectYStore(uint8) -> void; - auto instruction_memory(fp) -> 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; + auto instructionBBR(uint3) -> void; + auto instructionBBS(uint3) -> void; + auto instructionBRK() -> void; + auto instructionBSR() -> void; + auto instructionCSL() -> void; + auto instructionCSH() -> void; + auto instructionJMPAbsolute() -> void; + auto instructionJMPIndirect(uint8 = 0) -> void; + auto instructionJSR() -> void; + auto instructionNOP() -> void; + auto instructionPLP() -> void; + auto instructionRMB(uint3) -> void; + auto instructionRTI() -> void; + auto instructionRTS() -> void; + auto instructionSMB(uint3) -> void; + auto instructionST(uint2) -> void; + auto instructionTAM() -> void; + auto instructionTMA() -> void; + auto instructionTSTAbsolute(uint8 = 0) -> void; + auto instructionTSTZeroPage(uint8 = 0) -> void; + auto instructionTXS() -> void; //disassembler.cpp auto disassemble(uint16 pc) -> string; diff --git a/higan/processor/huc6280/instruction.cpp b/higan/processor/huc6280/instruction.cpp index 44848ab9..69f6f78b 100644 --- a/higan/processor/huc6280/instruction.cpp +++ b/higan/processor/huc6280/instruction.cpp @@ -1,5 +1,5 @@ -#define op(id, name, ...) case id: instruction_##name(__VA_ARGS__); return; -#define fp(name) &HuC6280::name +#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); +#define fp(name) &HuC6280::algorithm##name auto HuC6280::interrupt(uint16 vector) -> void { io(); @@ -19,270 +19,270 @@ auto HuC6280::instruction() -> void { if(T) { T = 0; switch(code) { - op(0x09, memory, fp(ORA)) - op(0x29, memory, fp(AND)) - op(0x49, memory, fp(EOR)) - op(0x69, memory, fp(ADC)) + op(0x09, Memory, fp(ORA)) + op(0x29, Memory, fp(AND)) + op(0x49, Memory, fp(EOR)) + op(0x69, Memory, fp(ADC)) } } #define U switch(code) { op(0x00, BRK) - op(0x01, indirectLoad, fp(ORA), A, X) - op(0x02, swap, X, Y) + op(0x01, IndirectRead, fp(ORA), A, X) + op(0x02, Swap, X, Y) op(0x03, ST, 0) - op(0x04, zeropageModify, fp(TSB)) - op(0x05, zeropageLoad, fp(ORA), A) - op(0x06, zeropageModify, fp(ASL)) + op(0x04, ZeroPageModify, fp(TSB)) + op(0x05, ZeroPageRead, fp(ORA), A) + op(0x06, ZeroPageModify, fp(ASL)) op(0x07, RMB, 0) - op(0x08, push, P) - op(0x09, immediate, fp(ORA), A) - op(0x0a, implied, fp(ASL), A) + op(0x08, Push, P) + op(0x09, Immediate, fp(ORA), A) + op(0x0a, Implied, fp(ASL), A) U op(0x0b, NOP) - op(0x0c, absoluteModify, fp(TSB)) - op(0x0d, absoluteLoad, fp(ORA), A) - op(0x0e, absoluteModify, fp(ASL)) + op(0x0c, AbsoluteModify, fp(TSB)) + op(0x0d, AbsoluteRead, fp(ORA), A) + op(0x0e, AbsoluteModify, fp(ASL)) op(0x0f, BBR, 0) - op(0x10, branch, N == 0) - op(0x11, indirectYLoad, fp(ORA), A) - op(0x12, indirectLoad, fp(ORA), A) + op(0x10, Branch, N == 0) + op(0x11, IndirectYRead, fp(ORA), A) + op(0x12, IndirectRead, fp(ORA), A) op(0x13, ST, 1) - op(0x14, zeropageModify, fp(TRB)) - op(0x15, zeropageLoad, fp(ORA), A, X) - op(0x16, zeropageModify, fp(ASL), X) + op(0x14, ZeroPageModify, fp(TRB)) + op(0x15, ZeroPageRead, fp(ORA), A, X) + op(0x16, ZeroPageModify, fp(ASL), X) op(0x17, RMB, 1) - op(0x18, clear, C) - op(0x19, absoluteLoad, fp(ORA), A, Y) - op(0x1a, implied, fp(INC), A) + op(0x18, Clear, C) + op(0x19, AbsoluteRead, fp(ORA), A, Y) + op(0x1a, Implied, fp(INC), A) U op(0x1b, NOP) - op(0x1c, absoluteModify, fp(TRB)) - op(0x1d, absoluteLoad, fp(ORA), A, X) - op(0x1e, absoluteModify, fp(ASL), X) + op(0x1c, AbsoluteModify, fp(TRB)) + op(0x1d, AbsoluteRead, fp(ORA), A, X) + op(0x1e, AbsoluteModify, fp(ASL), X) op(0x1f, BBR, 1) op(0x20, JSR) - op(0x21, indirectLoad, fp(AND), A, X) - op(0x22, swap, A, X) + op(0x21, IndirectRead, fp(AND), A, X) + op(0x22, Swap, A, X) op(0x23, ST, 2) - op(0x24, zeropageLoad, fp(BIT), A) - op(0x25, zeropageLoad, fp(AND), A) - op(0x26, zeropageModify, fp(ROL)) + op(0x24, ZeroPageRead, fp(BIT), A) + op(0x25, ZeroPageRead, fp(AND), A) + op(0x26, ZeroPageModify, fp(ROL)) op(0x27, RMB, 2) op(0x28, PLP) - op(0x29, immediate, fp(AND), A) - op(0x2a, implied, fp(ROL), A) + op(0x29, Immediate, fp(AND), A) + op(0x2a, Implied, fp(ROL), A) U op(0x2b, NOP) - op(0x2c, absoluteLoad, fp(BIT), A) - op(0x2d, absoluteLoad, fp(AND), A) - op(0x2e, absoluteModify, fp(ROL)) + op(0x2c, AbsoluteRead, fp(BIT), A) + op(0x2d, AbsoluteRead, fp(AND), A) + op(0x2e, AbsoluteModify, fp(ROL)) op(0x2f, BBR, 2) - op(0x30, branch, N == 1) - op(0x31, indirectYLoad, fp(AND), A) - op(0x32, indirectLoad, fp(AND), A) + op(0x30, Branch, N == 1) + op(0x31, IndirectYRead, fp(AND), A) + op(0x32, IndirectRead, fp(AND), A) U op(0x33, NOP) - op(0x34, zeropageLoad, fp(BIT), A, X) - op(0x35, zeropageLoad, fp(AND), A, X) - op(0x36, zeropageModify, fp(ROL), X) + op(0x34, ZeroPageRead, fp(BIT), A, X) + op(0x35, ZeroPageRead, fp(AND), A, X) + op(0x36, ZeroPageModify, fp(ROL), X) op(0x37, RMB, 3) - op(0x38, set, C) - op(0x39, absoluteLoad, fp(AND), A, Y) - op(0x3a, implied, fp(DEC), A) + op(0x38, Set, C) + op(0x39, AbsoluteRead, fp(AND), A, Y) + op(0x3a, Implied, fp(DEC), A) U op(0x3b, NOP) - op(0x3c, absoluteLoad, fp(BIT), A, X) - op(0x3d, absoluteLoad, fp(AND), A, X) - op(0x3e, absoluteModify, fp(ROL), X) + op(0x3c, AbsoluteRead, fp(BIT), A, X) + op(0x3d, AbsoluteRead, fp(AND), A, X) + op(0x3e, AbsoluteModify, fp(ROL), X) op(0x3f, BBR, 3) op(0x40, RTI) - op(0x41, indirectLoad, fp(EOR), A, X) - op(0x42, swap, A, Y) + op(0x41, IndirectRead, fp(EOR), A, X) + op(0x42, Swap, A, Y) op(0x43, TMA) op(0x44, BSR) - op(0x45, zeropageLoad, fp(EOR), A) - op(0x46, zeropageModify, fp(LSR)) + op(0x45, ZeroPageRead, fp(EOR), A) + op(0x46, ZeroPageModify, fp(LSR)) op(0x47, RMB, 4) - op(0x48, push, A) - op(0x49, immediate, fp(EOR), A) - op(0x4a, implied, fp(LSR), A) + op(0x48, Push, A) + op(0x49, Immediate, fp(EOR), A) + op(0x4a, Implied, fp(LSR), A) U op(0x4b, NOP) - op(0x4c, JMP_absolute) - op(0x4d, absoluteLoad, fp(EOR), A) - op(0x4e, absoluteModify, fp(LSR)) + op(0x4c, JMPAbsolute) + op(0x4d, AbsoluteRead, fp(EOR), A) + op(0x4e, AbsoluteModify, fp(LSR)) op(0x4f, BBR, 4) - op(0x50, branch, V == 0) - op(0x51, indirectYLoad, fp(EOR), A) - op(0x52, indirectLoad, fp(EOR), A) + op(0x50, Branch, V == 0) + op(0x51, IndirectYRead, fp(EOR), A) + op(0x52, IndirectRead, fp(EOR), A) op(0x53, TAM) op(0x54, CSL) - op(0x55, zeropageLoad, fp(EOR), A, X) - op(0x56, zeropageModify, fp(LSR), X) + op(0x55, ZeroPageRead, fp(EOR), A, X) + op(0x56, ZeroPageModify, fp(LSR), X) op(0x57, RMB, 5) - op(0x58, clear, I) - op(0x59, absoluteLoad, fp(EOR), A, Y) - op(0x5a, push, Y) + op(0x58, Clear, I) + op(0x59, AbsoluteRead, fp(EOR), A, Y) + op(0x5a, Push, Y) U op(0x5b, NOP) U op(0x5c, NOP) - op(0x5d, absoluteLoad, fp(EOR), A, X) - op(0x5e, absoluteModify, fp(LSR), X) + op(0x5d, AbsoluteRead, fp(EOR), A, X) + op(0x5e, AbsoluteModify, fp(LSR), X) op(0x5f, BBR, 5) op(0x60, RTS) - op(0x61, indirectLoad, fp(ADC), A, X) - op(0x62, clear, A) + op(0x61, IndirectRead, fp(ADC), A, X) + op(0x62, Clear, A) U op(0x63, NOP) - op(0x64, zeropageStore, 0) - op(0x65, zeropageLoad, fp(ADC), A) - op(0x66, zeropageModify, fp(ROR)) + op(0x64, ZeroPageWrite, 0) + op(0x65, ZeroPageRead, fp(ADC), A) + op(0x66, ZeroPageModify, fp(ROR)) op(0x67, RMB, 6) - op(0x68, pull, A) - op(0x69, immediate, fp(ADC), A) - op(0x6a, implied, fp(ROR), A) + op(0x68, Pull, A) + op(0x69, Immediate, fp(ADC), A) + op(0x6a, Implied, fp(ROR), A) U op(0x6b, NOP) - op(0x6c, JMP_indirect) - op(0x6d, absoluteLoad, fp(ADC), A) - op(0x6e, absoluteModify, fp(ROR)) + op(0x6c, JMPIndirect) + op(0x6d, AbsoluteRead, fp(ADC), A) + op(0x6e, AbsoluteModify, fp(ROR)) op(0x6f, BBR, 6) - op(0x70, branch, V == 1) - op(0x71, indirectYLoad, fp(ADC), A) - op(0x72, indirectLoad, fp(ADC), A) - op(0x73, blockmove, fp(TII)) - op(0x74, zeropageStore, 0, X) - op(0x75, zeropageLoad, fp(ADC), A, X) - op(0x76, zeropageModify, fp(ROR), X) + op(0x70, Branch, V == 1) + op(0x71, IndirectYRead, fp(ADC), A) + op(0x72, IndirectRead, fp(ADC), A) + op(0x73, BlockMove, fp(TII)) + op(0x74, ZeroPageWrite, 0, X) + op(0x75, ZeroPageRead, fp(ADC), A, X) + op(0x76, ZeroPageModify, fp(ROR), X) op(0x77, RMB, 7) - op(0x78, set, I) - op(0x79, absoluteLoad, fp(ADC), A, Y) - op(0x7a, pull, Y) + op(0x78, Set, I) + op(0x79, AbsoluteRead, fp(ADC), A, Y) + op(0x7a, Pull, Y) U op(0x7b, NOP) - op(0x7c, JMP_indirect, X) - op(0x7d, absoluteLoad, fp(ADC), A, X) - op(0x7e, absoluteModify, fp(ROR), X) + op(0x7c, JMPIndirect, X) + op(0x7d, AbsoluteRead, fp(ADC), A, X) + op(0x7e, AbsoluteModify, fp(ROR), X) op(0x7f, BBR, 7) - op(0x80, branch, 1) - op(0x81, indirectStore, A, X) - op(0x82, clear, X) - op(0x83, TST_zeropage) - op(0x84, zeropageStore, Y) - op(0x85, zeropageStore, A) - op(0x86, zeropageStore, X) + op(0x80, Branch, 1) + op(0x81, IndirectWrite, A, X) + op(0x82, Clear, X) + op(0x83, TSTZeroPage) + op(0x84, ZeroPageWrite, Y) + op(0x85, ZeroPageWrite, A) + op(0x86, ZeroPageWrite, X) op(0x87, SMB, 0) - op(0x88, implied, fp(DEC), Y) - op(0x89, immediate, fp(BIT), A) - op(0x8a, transfer, X, A) + op(0x88, Implied, fp(DEC), Y) + op(0x89, Immediate, fp(BIT), A) + op(0x8a, Transfer, X, A) U op(0x8b, NOP) - op(0x8c, absoluteStore, Y) - op(0x8d, absoluteStore, A) - op(0x8e, absoluteStore, X) + op(0x8c, AbsoluteWrite, Y) + op(0x8d, AbsoluteWrite, A) + op(0x8e, AbsoluteWrite, X) op(0x8f, BBS, 0) - op(0x90, branch, C == 0) - op(0x91, indirectYStore, A) - op(0x92, indirectStore, A) - op(0x93, TST_absolute) - op(0x94, zeropageStore, Y, X) - op(0x95, zeropageStore, A, X) - op(0x96, zeropageStore, X, Y) + op(0x90, Branch, C == 0) + op(0x91, IndirectYWrite, A) + op(0x92, IndirectWrite, A) + op(0x93, TSTAbsolute) + op(0x94, ZeroPageWrite, Y, X) + op(0x95, ZeroPageWrite, A, X) + op(0x96, ZeroPageWrite, X, Y) op(0x97, SMB, 1) - op(0x98, transfer, Y, A) - op(0x99, absoluteStore, A, Y) + op(0x98, Transfer, Y, A) + op(0x99, AbsoluteWrite, A, Y) op(0x9a, TXS) U op(0x9b, NOP) - op(0x9c, absoluteStore, 0) - op(0x9d, absoluteStore, A, X) - op(0x9e, absoluteStore, 0, X) + op(0x9c, AbsoluteWrite, 0) + op(0x9d, AbsoluteWrite, A, X) + op(0x9e, AbsoluteWrite, 0, X) op(0x9f, BBS, 1) - op(0xa0, immediate, fp(LD), Y) - op(0xa1, indirectLoad, fp(LD), A, X) - op(0xa2, immediate, fp(LD), X) - op(0xa3, TST_zeropage, X) - op(0xa4, zeropageLoad, fp(LD), Y) - op(0xa5, zeropageLoad, fp(LD), A) - op(0xa6, zeropageLoad, fp(LD), X) + op(0xa0, Immediate, fp(LD), Y) + op(0xa1, IndirectRead, fp(LD), A, X) + op(0xa2, Immediate, fp(LD), X) + op(0xa3, TSTZeroPage, X) + op(0xa4, ZeroPageRead, fp(LD), Y) + op(0xa5, ZeroPageRead, fp(LD), A) + op(0xa6, ZeroPageRead, fp(LD), X) op(0xa7, SMB, 2) - op(0xa8, transfer, A, Y) - op(0xa9, immediate, fp(LD), A) - op(0xaa, transfer, A, X) + op(0xa8, Transfer, A, Y) + op(0xa9, Immediate, fp(LD), A) + op(0xaa, Transfer, A, X) U op(0xab, NOP) - op(0xac, absoluteLoad, fp(LD), Y) - op(0xad, absoluteLoad, fp(LD), A) - op(0xae, absoluteLoad, fp(LD), X) + op(0xac, AbsoluteRead, fp(LD), Y) + op(0xad, AbsoluteRead, fp(LD), A) + op(0xae, AbsoluteRead, fp(LD), X) op(0xaf, BBS, 2) - op(0xb0, branch, C == 1) - op(0xb1, indirectYLoad, fp(LD), A) - op(0xb2, indirectLoad, fp(LD), A) - op(0xb3, TST_absolute, X) - op(0xb4, zeropageLoad, fp(LD), Y, X) - op(0xb5, zeropageLoad, fp(LD), A, X) - op(0xb6, zeropageLoad, fp(LD), X, Y) + op(0xb0, Branch, C == 1) + op(0xb1, IndirectYRead, fp(LD), A) + op(0xb2, IndirectRead, fp(LD), A) + op(0xb3, TSTAbsolute, X) + op(0xb4, ZeroPageRead, fp(LD), Y, X) + op(0xb5, ZeroPageRead, fp(LD), A, X) + op(0xb6, ZeroPageRead, fp(LD), X, Y) op(0xb7, SMB, 3) - op(0xb8, clear, V) - op(0xb9, absoluteLoad, fp(LD), A, Y) - op(0xba, transfer, S, X) + op(0xb8, Clear, V) + op(0xb9, AbsoluteRead, fp(LD), A, Y) + op(0xba, Transfer, S, X) U op(0xbb, NOP) - op(0xbc, absoluteLoad, fp(LD), Y, X) - op(0xbd, absoluteLoad, fp(LD), A, X) - op(0xbe, absoluteLoad, fp(LD), X, Y) + op(0xbc, AbsoluteRead, fp(LD), Y, X) + op(0xbd, AbsoluteRead, fp(LD), A, X) + op(0xbe, AbsoluteRead, fp(LD), X, Y) op(0xbf, BBS, 3) - op(0xc0, immediate, fp(CPY), Y) - op(0xc1, indirectLoad, fp(CMP), A, X) - op(0xc2, clear, Y) - op(0xc3, blockmove, fp(TDD)) - op(0xc4, zeropageLoad, fp(CPY), Y) - op(0xc5, zeropageLoad, fp(CMP), A) - op(0xc6, zeropageModify, fp(DEC)) + op(0xc0, Immediate, fp(CPY), Y) + op(0xc1, IndirectRead, fp(CMP), A, X) + op(0xc2, Clear, Y) + op(0xc3, BlockMove, fp(TDD)) + op(0xc4, ZeroPageRead, fp(CPY), Y) + op(0xc5, ZeroPageRead, fp(CMP), A) + op(0xc6, ZeroPageModify, fp(DEC)) op(0xc7, SMB, 4) - op(0xc8, implied, fp(INC), Y) - op(0xc9, immediate, fp(CMP), A) - op(0xca, implied, fp(DEC), X) + op(0xc8, Implied, fp(INC), Y) + op(0xc9, Immediate, fp(CMP), A) + op(0xca, Implied, fp(DEC), X) U op(0xcb, NOP) - op(0xcc, absoluteLoad, fp(CPY), Y) - op(0xcd, absoluteLoad, fp(CMP), A) - op(0xce, absoluteModify, fp(DEC)) + op(0xcc, AbsoluteRead, fp(CPY), Y) + op(0xcd, AbsoluteRead, fp(CMP), A) + op(0xce, AbsoluteModify, fp(DEC)) op(0xcf, BBS, 4) - op(0xd0, branch, Z == 0) - op(0xd1, indirectYLoad, fp(CMP), A) - op(0xd2, indirectLoad, fp(CMP), A) - op(0xd3, blockmove, fp(TIN)) + op(0xd0, Branch, Z == 0) + op(0xd1, IndirectYRead, fp(CMP), A) + op(0xd2, IndirectRead, fp(CMP), A) + op(0xd3, BlockMove, fp(TIN)) op(0xd4, CSH) - op(0xd5, zeropageLoad, fp(CMP), A, X) - op(0xd6, zeropageModify, fp(DEC), X) + op(0xd5, ZeroPageRead, fp(CMP), A, X) + op(0xd6, ZeroPageModify, fp(DEC), X) op(0xd7, SMB, 5) - op(0xd8, clear, D) - op(0xd9, absoluteLoad, fp(CMP), A, Y) - op(0xda, push, X) + op(0xd8, Clear, D) + op(0xd9, AbsoluteRead, fp(CMP), A, Y) + op(0xda, Push, X) U op(0xdb, NOP) U op(0xdc, NOP) - op(0xdd, absoluteLoad, fp(CMP), A, X) - op(0xde, absoluteModify, fp(DEC), X) + op(0xdd, AbsoluteRead, fp(CMP), A, X) + op(0xde, AbsoluteModify, fp(DEC), X) op(0xdf, BBS, 5) - op(0xe0, immediate, fp(CPX), X) - op(0xe1, indirectLoad, fp(SBC), A, X) + op(0xe0, Immediate, fp(CPX), X) + op(0xe1, IndirectRead, fp(SBC), A, X) U op(0xe2, NOP) - op(0xe3, blockmove, fp(TIA)) - op(0xe4, zeropageLoad, fp(CPX), X) - op(0xe5, zeropageLoad, fp(SBC), A) - op(0xe6, zeropageModify, fp(INC)) + op(0xe3, BlockMove, fp(TIA)) + op(0xe4, ZeroPageRead, fp(CPX), X) + op(0xe5, ZeroPageRead, fp(SBC), A) + op(0xe6, ZeroPageModify, fp(INC)) op(0xe7, SMB, 6) - op(0xe8, implied, fp(INC), X) - op(0xe9, immediate, fp(SBC), A) + op(0xe8, Implied, fp(INC), X) + op(0xe9, Immediate, fp(SBC), A) op(0xea, NOP) U op(0xeb, NOP) - op(0xec, absoluteLoad, fp(CPX), X) - op(0xed, absoluteLoad, fp(SBC), A) - op(0xee, absoluteModify, fp(INC)) + op(0xec, AbsoluteRead, fp(CPX), X) + op(0xed, AbsoluteRead, fp(SBC), A) + op(0xee, AbsoluteModify, fp(INC)) op(0xef, BBS, 6) - op(0xf0, branch, Z == 1) - op(0xf1, indirectYLoad, fp(SBC), A) - op(0xf2, indirectLoad, fp(SBC), A) - op(0xf3, blockmove, fp(TAI)) - op(0xf4, set, T) - op(0xf5, zeropageLoad, fp(SBC), A, X) - op(0xf6, zeropageModify, fp(INC), X) + op(0xf0, Branch, Z == 1) + op(0xf1, IndirectYRead, fp(SBC), A) + op(0xf2, IndirectRead, fp(SBC), A) + op(0xf3, BlockMove, fp(TAI)) + op(0xf4, Set, T) + op(0xf5, ZeroPageRead, fp(SBC), A, X) + op(0xf6, ZeroPageModify, fp(INC), X) op(0xf7, SMB, 7) - op(0xf8, set, D) - op(0xf9, absoluteLoad, fp(SBC), A, Y) - op(0xfa, pull, X) + op(0xf8, Set, D) + op(0xf9, AbsoluteRead, fp(SBC), A, Y) + op(0xfa, Pull, X) U op(0xfb, NOP) U op(0xfc, NOP) - op(0xfd, absoluteLoad, fp(SBC), A, X) - op(0xfe, absoluteModify, fp(INC), X) + op(0xfd, AbsoluteRead, fp(SBC), A, X) + op(0xfe, AbsoluteModify, fp(INC), X) op(0xff, BBS, 7) } #undef U diff --git a/higan/processor/huc6280/instructions.cpp b/higan/processor/huc6280/instructions.cpp index 289dbc49..21a34bdf 100644 --- a/higan/processor/huc6280/instructions.cpp +++ b/higan/processor/huc6280/instructions.cpp @@ -1,198 +1,4 @@ -auto HuC6280::ADC(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::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 { +auto HuC6280::instructionAbsoluteModify(fp alu, uint8 index) -> void { uint16 absolute = operand(); absolute |= operand() << 8; io(); @@ -201,14 +7,21 @@ auto HuC6280::instruction_absoluteModify(fp alu, uint8 index) -> void { 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(); absolute |= operand() << 8; io(); L store16(absolute + index, data); } -auto HuC6280::instruction_blockmove(bp alu) -> void { +auto HuC6280::instructionBlockMove(bp alu) -> void { uint16 source = operand(); source |= operand() << 8; uint16 target = operand(); @@ -238,7 +51,7 @@ auto HuC6280::instruction_blockmove(bp alu) -> void { L Y = pull(); } -auto HuC6280::instruction_branch(bool take) -> void { +auto HuC6280::instructionBranch(bool take) -> void { if(!take) { L operand(); } 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(); data = 0; } -auto HuC6280::instruction_clear(bool& flag) -> void { +auto HuC6280::instructionClear(bool& flag) -> void { L io(); flag = 0; } -auto HuC6280::instruction_immediate(fp alu, uint8& data) -> void { +auto HuC6280::instructionImmediate(fp alu, uint8& data) -> void { L data = ALU(operand()); } -auto HuC6280::instruction_implied(fp alu, uint8& data) -> void { +auto HuC6280::instructionImplied(fp alu, uint8& data) -> void { L io(); 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(); io(); 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)); } -auto HuC6280::instruction_indirectStore(uint8 data, uint8 index) -> void { +auto HuC6280::instructionIndirectWrite(uint8 data, uint8 index) -> void { auto zeropage = operand(); io(); uint16 absolute = load8(zeropage + index + 0); @@ -285,7 +98,7 @@ auto HuC6280::instruction_indirectStore(uint8 data, uint8 index) -> void { L store16(absolute, data); } -auto HuC6280::instruction_indirectYLoad(fp alu, uint8& data) -> void { +auto HuC6280::instructionIndirectYRead(fp alu, uint8& data) -> void { auto zeropage = operand(); io(); uint16 absolute = load8(zeropage + 0); @@ -294,7 +107,7 @@ auto HuC6280::instruction_indirectYLoad(fp alu, uint8& data) -> void { L data = ALU(load16(absolute + Y)); } -auto HuC6280::instruction_indirectYStore(uint8 data) -> void { +auto HuC6280::instructionIndirectYWrite(uint8 data) -> void { auto zeropage = operand(); io(); uint16 absolute = load8(zeropage + 0); @@ -302,14 +115,14 @@ auto HuC6280::instruction_indirectYStore(uint8 data) -> void { L store16(absolute + Y, data); } -auto HuC6280::instruction_memory(fp alu) -> void { +auto HuC6280::instructionMemory(fp alu) -> void { auto a = A; A = ALU(load8(X)); L store8(X, A); A = a; } -auto HuC6280::instruction_pull(uint8& data) -> void { +auto HuC6280::instructionPull(uint8& data) -> void { io(); io(); L data = pull(); @@ -317,36 +130,30 @@ L data = pull(); N = data.bit(7); } -auto HuC6280::instruction_push(uint8 data) -> void { +auto HuC6280::instructionPush(uint8 data) -> void { io(); L push(data); } -auto HuC6280::instruction_set(bool& flag) -> void { +auto HuC6280::instructionSet(bool& flag) -> void { L io(); flag = 1; } -auto HuC6280::instruction_swap(uint8& lhs, uint8& rhs) -> void { +auto HuC6280::instructionSwap(uint8& lhs, uint8& rhs) -> void { io(); L io(); swap(lhs, rhs); } -auto HuC6280::instruction_transfer(uint8& source, uint8& target) -> void { +auto HuC6280::instructionTransfer(uint8& source, uint8& target) -> void { L io(); target = source; Z = target == 0; N = target.bit(7); } -auto HuC6280::instruction_zeropageLoad(fp alu, uint8& data, uint8 index) -> void { - auto zeropage = operand(); - io(); -L data = ALU(load8(zeropage + index)); -} - -auto HuC6280::instruction_zeropageModify(fp alu, uint8 index) -> void { +auto HuC6280::instructionZeroPageModify(fp alu, uint8 index) -> void { auto zeropage = operand(); io(); io(); @@ -354,7 +161,13 @@ auto HuC6280::instruction_zeropageModify(fp alu, uint8 index) -> void { 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(); io(); 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 displacement = operand(); 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 displacement = operand(); io(); @@ -384,7 +197,7 @@ L auto data = load8(zeropage); } } -auto HuC6280::instruction_BRK() -> void { +auto HuC6280::instructionBRK() -> void { operand(); io(); push(PC >> 8); @@ -397,7 +210,7 @@ auto HuC6280::instruction_BRK() -> void { L PC.byte(1) = load16(0xfff7); } -auto HuC6280::instruction_BSR() -> void { +auto HuC6280::instructionBSR() -> void { auto displacement = operand(); io(); io(); @@ -408,24 +221,24 @@ L push((PC - 1) >> 0); PC += (int8)displacement; } -auto HuC6280::instruction_CSL() -> void { +auto HuC6280::instructionCSL() -> void { L io(); r.cs = 4; } -auto HuC6280::instruction_CSH() -> void { +auto HuC6280::instructionCSH() -> void { L io(); r.cs = 1; } -auto HuC6280::instruction_JMP_absolute() -> void { +auto HuC6280::instructionJMPAbsolute() -> void { uint16 address = operand(); address |= operand() << 8; L io(); PC = address; } -auto HuC6280::instruction_JMP_indirect(uint8 index) -> void { +auto HuC6280::instructionJMPIndirect(uint8 index) -> void { uint16 address = operand(); address |= operand() << 8; io(); @@ -434,7 +247,7 @@ auto HuC6280::instruction_JMP_indirect(uint8 index) -> void { L PC.byte(1) = load16(address + index + 1); } -auto HuC6280::instruction_JSR() -> void { +auto HuC6280::instructionJSR() -> void { uint16 address = operand(); address |= operand() << 8; io(); @@ -444,17 +257,17 @@ L push((PC - 1) >> 0); PC = address; } -auto HuC6280::instruction_NOP() -> void { +auto HuC6280::instructionNOP() -> void { L io(); } -auto HuC6280::instruction_PLP() -> void { +auto HuC6280::instructionPLP() -> void { io(); io(); L P = pull(); } -auto HuC6280::instruction_RMB(uint3 index) -> void { +auto HuC6280::instructionRMB(uint3 index) -> void { auto zeropage = operand(); io(); io(); @@ -464,7 +277,7 @@ auto HuC6280::instruction_RMB(uint3 index) -> void { L store8(zeropage, data); } -auto HuC6280::instruction_RTI() -> void { +auto HuC6280::instructionRTI() -> void { io(); io(); io(); @@ -473,7 +286,7 @@ auto HuC6280::instruction_RTI() -> void { L PC.byte(1) = pull(); } -auto HuC6280::instruction_RTS() -> void { +auto HuC6280::instructionRTS() -> void { io(); io(); io(); @@ -483,7 +296,7 @@ L io(); PC++; } -auto HuC6280::instruction_SMB(uint3 index) -> void { +auto HuC6280::instructionSMB(uint3 index) -> void { auto zeropage = operand(); io(); io(); @@ -493,14 +306,14 @@ auto HuC6280::instruction_SMB(uint3 index) -> void { L store8(zeropage, data); } -auto HuC6280::instruction_ST(uint2 index) -> void { +auto HuC6280::instructionST(uint2 index) -> void { auto data = operand(); io(); io(); L store(index, data); } -auto HuC6280::instruction_TAM() -> void { +auto HuC6280::instructionTAM() -> void { auto mask = operand(); io(); io(); @@ -510,7 +323,7 @@ L io(); } } -auto HuC6280::instruction_TMA() -> void { +auto HuC6280::instructionTMA() -> void { auto mask = operand(); 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(); uint16 absolute = operand(); absolute |= operand() << 8; @@ -532,7 +345,7 @@ L uint8 data = load16(absolute + index); N = data.bit(7); } -auto HuC6280::instruction_TST_zeropage(uint8 index) -> void { +auto HuC6280::instructionTSTZeroPage(uint8 index) -> void { auto mask = operand(); auto zeropage = operand(); io(); @@ -544,7 +357,7 @@ L uint8 data = load8(zeropage + index); N = data.bit(7); } -auto HuC6280::instruction_TXS() -> void { +auto HuC6280::instructionTXS() -> void { L io(); S = X; } diff --git a/higan/processor/mos6502/algorithms.cpp b/higan/processor/mos6502/algorithms.cpp new file mode 100644 index 00000000..1aef48a1 --- /dev/null +++ b/higan/processor/mos6502/algorithms.cpp @@ -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; +} diff --git a/higan/processor/mos6502/instruction.cpp b/higan/processor/mos6502/instruction.cpp index 3b46a6a6..1f0e867b 100644 --- a/higan/processor/mos6502/instruction.cpp +++ b/higan/processor/mos6502/instruction.cpp @@ -1,5 +1,5 @@ #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 { idle(); diff --git a/higan/processor/mos6502/instructions.cpp b/higan/processor/mos6502/instructions.cpp index e8e2e3d9..428ee66b 100644 --- a/higan/processor/mos6502/instructions.cpp +++ b/higan/processor/mos6502/instructions.cpp @@ -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 { uint16 absolute = operand(); absolute |= operand() << 8; diff --git a/higan/processor/mos6502/mos6502.cpp b/higan/processor/mos6502/mos6502.cpp index 1e5cd8f2..33f581cc 100644 --- a/higan/processor/mos6502/mos6502.cpp +++ b/higan/processor/mos6502/mos6502.cpp @@ -21,6 +21,7 @@ namespace Processor { #define L lastCycle(); #include "memory.cpp" +#include "algorithms.cpp" #include "instruction.cpp" #include "instructions.cpp" #include "disassembler.cpp" diff --git a/higan/processor/mos6502/mos6502.hpp b/higan/processor/mos6502/mos6502.hpp index 4e7b5f4e..6ec933c4 100644 --- a/higan/processor/mos6502/mos6502.hpp +++ b/higan/processor/mos6502/mos6502.hpp @@ -26,29 +26,30 @@ struct MOS6502 { auto push(uint8 data) -> void; 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 auto interrupt() -> void; auto instruction() -> void; //instructions.cpp - using fp = auto (MOS6502::*)(uint8) -> uint8; - auto ADC(uint8) -> uint8; - auto AND(uint8) -> uint8; - auto ASL(uint8) -> uint8; - auto BIT(uint8) -> uint8; - auto CMP(uint8) -> uint8; - auto CPX(uint8) -> uint8; - auto CPY(uint8) -> uint8; - auto DEC(uint8) -> uint8; - auto EOR(uint8) -> uint8; - auto INC(uint8) -> uint8; - auto LD (uint8) -> uint8; - auto LSR(uint8) -> uint8; - auto ORA(uint8) -> uint8; - auto ROL(uint8) -> uint8; - auto ROR(uint8) -> uint8; - auto SBC(uint8) -> uint8; - auto instructionAbsoluteModify(fp alu) -> void; auto instructionAbsoluteModify(fp alu, uint8 index) -> void; auto instructionAbsoluteRead(fp alu, uint8& data) -> void; diff --git a/higan/processor/spc700/algorithms.cpp b/higan/processor/spc700/algorithms.cpp index 8b1486c3..10caa61c 100644 --- a/higan/processor/spc700/algorithms.cpp +++ b/higan/processor/spc700/algorithms.cpp @@ -1,134 +1,134 @@ -auto SPC700::op_adc(uint8 x, uint8 y) -> uint8 { - int r = x + y + regs.p.c; - regs.p.n = r & 0x80; - regs.p.v = ~(x ^ y) & (x ^ r) & 0x80; - regs.p.h = (x ^ y ^ r) & 0x10; - regs.p.z = (uint8)r == 0; - regs.p.c = r > 0xff; - return r; +auto SPC700::algorithmADC(uint8 x, uint8 y) -> uint8 { + int z = x + y + CF; + CF = z > 0xff; + ZF = (uint8)z == 0; + HF = (x ^ y ^ z) & 0x10; + VF = ~(x ^ y) & (x ^ z) & 0x80; + NF = z & 0x80; + return z; } -auto SPC700::op_and(uint8 x, uint8 y) -> uint8 { +auto SPC700::algorithmAND(uint8 x, uint8 y) -> uint8 { x &= y; - regs.p.n = x & 0x80; - regs.p.z = x == 0; + ZF = x == 0; + NF = x & 0x80; return x; } -auto SPC700::op_asl(uint8 x) -> uint8 { - regs.p.c = x & 0x80; +auto SPC700::algorithmASL(uint8 x) -> uint8 { + CF = x & 0x80; x <<= 1; - regs.p.n = x & 0x80; - regs.p.z = x == 0; + ZF = x == 0; + NF = x & 0x80; return x; } -auto SPC700::op_cmp(uint8 x, uint8 y) -> uint8 { - int r = x - y; - regs.p.n = r & 0x80; - regs.p.z = (uint8)r == 0; - regs.p.c = r >= 0; +auto SPC700::algorithmCMP(uint8 x, uint8 y) -> uint8 { + int z = x - y; + CF = z >= 0; + ZF = (uint8)z == 0; + NF = z & 0x80; return x; } -auto SPC700::op_dec(uint8 x) -> uint8 { +auto SPC700::algorithmDEC(uint8 x) -> uint8 { x--; - regs.p.n = x & 0x80; - regs.p.z = x == 0; + ZF = x == 0; + NF = x & 0x80; return x; } -auto SPC700::op_eor(uint8 x, uint8 y) -> uint8 { +auto SPC700::algorithmEOR(uint8 x, uint8 y) -> uint8 { x ^= y; - regs.p.n = x & 0x80; - regs.p.z = x == 0; + ZF = x == 0; + NF = x & 0x80; return x; } -auto SPC700::op_inc(uint8 x) -> uint8 { +auto SPC700::algorithmINC(uint8 x) -> uint8 { x++; - regs.p.n = x & 0x80; - regs.p.z = x == 0; + ZF = x == 0; + NF = x & 0x80; return x; } -auto SPC700::op_ld(uint8 x, uint8 y) -> uint8 { - regs.p.n = y & 0x80; - regs.p.z = y == 0; +auto SPC700::algorithmLD(uint8 x, uint8 y) -> uint8 { + ZF = y == 0; + NF = y & 0x80; return y; } -auto SPC700::op_lsr(uint8 x) -> uint8 { - regs.p.c = x & 0x01; +auto SPC700::algorithmLSR(uint8 x) -> uint8 { + CF = x & 0x01; x >>= 1; - regs.p.n = x & 0x80; - regs.p.z = x == 0; + ZF = x == 0; + NF = x & 0x80; return x; } -auto SPC700::op_or(uint8 x, uint8 y) -> uint8 { +auto SPC700::algorithmOR(uint8 x, uint8 y) -> uint8 { x |= y; - regs.p.n = x & 0x80; - regs.p.z = x == 0; + ZF = x == 0; + NF = x & 0x80; return x; } -auto SPC700::op_rol(uint8 x) -> uint8 { - uint carry = regs.p.c << 0; - regs.p.c = x & 0x80; - x = (x << 1) | carry; - regs.p.n = x & 0x80; - regs.p.z = x == 0; +auto SPC700::algorithmROL(uint8 x) -> uint8 { + bool carry = CF; + CF = x & 0x80; + x = x << 1 | carry; + ZF = x == 0; + NF = x & 0x80; return x; } -auto SPC700::op_ror(uint8 x) -> uint8 { - uint carry = regs.p.c << 7; - regs.p.c = x & 0x01; - x = carry | (x >> 1); - regs.p.n = x & 0x80; - regs.p.z = x == 0; +auto SPC700::algorithmROR(uint8 x) -> uint8 { + bool carry = CF; + CF = x & 0x01; + x = carry << 7 | x >> 1; + ZF = x == 0; + NF = x & 0x80; return x; } -auto SPC700::op_sbc(uint8 x, uint8 y) -> uint8 { - return op_adc(x, ~y); +auto SPC700::algorithmSBC(uint8 x, uint8 y) -> uint8 { + return algorithmADC(x, ~y); } -auto SPC700::op_st(uint8 x, uint8 y) -> uint8 { +auto SPC700::algorithmST(uint8 x, uint8 y) -> uint8 { return y; } // -auto SPC700::op_adw(uint16 x, uint16 y) -> uint16 { - uint16 r; - regs.p.c = 0; - r = op_adc(x, y); - r |= op_adc(x >> 8, y >> 8) << 8; - regs.p.z = r == 0; - return r; +auto SPC700::algorithmADW(uint16 x, uint16 y) -> uint16 { + uint16 z; + CF = 0; + z = algorithmADC(x, y); + z |= algorithmADC(x >> 8, y >> 8) << 8; + ZF = z == 0; + return z; } -auto SPC700::op_cpw(uint16 x, uint16 y) -> uint16 { - int r = x - y; - regs.p.n = r & 0x8000; - regs.p.z = (uint16)r == 0; - regs.p.c = r >= 0; +auto SPC700::algorithmCPW(uint16 x, uint16 y) -> uint16 { + int z = x - y; + CF = z >= 0; + ZF = (uint16)z == 0; + NF = z & 0x8000; return x; } -auto SPC700::op_ldw(uint16 x, uint16 y) -> uint16 { - regs.p.n = y & 0x8000; - regs.p.z = y == 0; +auto SPC700::algorithmLDW(uint16 x, uint16 y) -> uint16 { + ZF = y == 0; + NF = y & 0x8000; return y; } -auto SPC700::op_sbw(uint16 x, uint16 y) -> uint16 { - uint16 r; - regs.p.c = 1; - r = op_sbc(x, y); - r |= op_sbc(x >> 8, y >> 8) << 8; - regs.p.z = r == 0; - return r; +auto SPC700::algorithmSBW(uint16 x, uint16 y) -> uint16 { + uint16 z; + CF = 1; + z = algorithmSBC(x, y); + z |= algorithmSBC(x >> 8, y >> 8) << 8; + ZF = z == 0; + return z; } diff --git a/higan/processor/spc700/disassembler.cpp b/higan/processor/spc700/disassembler.cpp index 96cef88c..e5405fe3 100644 --- a/higan/processor/spc700/disassembler.cpp +++ b/higan/processor/spc700/disassembler.cpp @@ -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 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 ab = [&] { 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 0x01: return { "jst $ffde" }; 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 0x05: return { "ora $", a() }; case 0x06: return { "ora (x)" }; @@ -35,10 +35,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0x0d: return { "php" }; case 0x0e: return { "tsb $", a() }; case 0x0f: return { "brk" }; - case 0x10: return { "bpl $", r(+2) }; + case 0x10: return { "bpl $", rel(+2) }; case 0x11: return { "jst $ffdc" }; 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 0x15: return { "ora $", a(), ",x" }; case 0x16: return { "ora $", a(), ",y" }; @@ -54,7 +54,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0x20: return { "clp" }; case 0x21: return { "jst $ffda" }; 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 0x25: return { "and $", a() }; case 0x26: return { "and (x)" }; @@ -64,13 +64,13 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0x2b: return { "rol $", dp(0) }; case 0x2c: return { "rol $", a() }; 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 0x2f: return { "bra $", r(+2) }; - case 0x30: return { "bmi $", r(+2) }; + case 0x2f: return { "bra $", rel(+2) }; + case 0x30: return { "bmi $", rel(+2) }; case 0x31: return { "jst $ffd8" }; 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 0x35: return { "and $", a(), ",x" }; case 0x36: return { "and $", a(), ",y" }; @@ -86,7 +86,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0x40: return { "sep" }; case 0x41: return { "jst $ffd6" }; 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 0x45: return { "eor $", a() }; case 0x46: return { "eor (x)" }; @@ -99,10 +99,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0x4d: return { "phx" }; case 0x4e: return { "trb $", a() }; 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 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 0x55: return { "eor $", a(), ",x" }; case 0x56: return { "eor $", a(), ",y" }; @@ -118,7 +118,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0x60: return { "clc" }; case 0x61: return { "jst $ffd2" }; 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 0x65: return { "cmp $", a() }; case 0x66: return { "cmp (x)" }; @@ -129,12 +129,12 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0x6b: return { "ror $", dp(0) }; case 0x6c: return { "ror $", a() }; 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 0x70: return { "bvs $", r(+2) }; + case 0x70: return { "bvs $", rel(+2) }; case 0x71: return { "jst $ffd0" }; 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 0x75: return { "cmp $", a(), ",x" }; case 0x76: return { "cmp $", a(), ",y" }; @@ -150,7 +150,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0x80: return { "sec" }; case 0x81: return { "jst $ffce" }; 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 0x85: return { "adc $", a() }; case 0x86: return { "adc (x)" }; @@ -163,10 +163,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0x8d: return { "ldy #$", b(0) }; case 0x8e: return { "plp" }; 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 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 0x95: return { "adc $", a(), ",x" }; case 0x96: return { "adc $", a(), ",y" }; @@ -182,7 +182,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0xa0: return { "sei" }; case 0xa1: return { "jst $ffca" }; 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 0xa5: return { "sbc $", a() }; case 0xa6: return { "sbc (x)" }; @@ -195,10 +195,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0xad: return { "cpy #$", b(0) }; case 0xae: return { "pla" }; case 0xaf: return { "sta (x++)" }; - case 0xb0: return { "bcs $", r(+2) }; + case 0xb0: return { "bcs $", rel(+2) }; case 0xb1: return { "jst $ffc8" }; 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 0xb5: return { "sbc $", a(), ",x" }; case 0xb6: return { "sbc $", a(), ",y" }; @@ -214,7 +214,7 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0xc0: return { "cli" }; case 0xc1: return { "jst $ffc6" }; 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 0xc5: return { "sta $", a() }; case 0xc6: return { "sta (x)" }; @@ -227,10 +227,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0xcd: return { "ldx #$", b(0) }; case 0xce: return { "plx" }; case 0xcf: return { "mul" }; - case 0xd0: return { "bne $", r(+2) }; + case 0xd0: return { "bne $", rel(+2) }; case 0xd1: return { "jst $ffc4" }; 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 0xd5: return { "sta $", a(), ",x" }; 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 0xdc: return { "dey" }; 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 0xe0: return { "clv" }; case 0xe1: return { "jst $ffc2" }; 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 0xe5: return { "lda $", a() }; case 0xe6: return { "lda (x)" }; @@ -259,10 +259,10 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { case 0xed: return { "cmc" }; case 0xee: return { "ply" }; case 0xef: return { "wai" }; - case 0xf0: return { "beq $", r(+2) }; + case 0xf0: return { "beq $", rel(+2) }; case 0xf1: return { "jst $ffc0" }; 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 0xf5: return { "lda $", a(), ",x" }; 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 0xfc: return { "iny" }; case 0xfd: return { "tay" }; - case 0xfe: return { "bne --y=$", r(+2) }; + case 0xfe: return { "bne --y=$", rel(+2) }; case 0xff: return { "stp" }; } throw; @@ -285,20 +285,20 @@ auto SPC700::disassemble(uint16 addr, bool p) -> string { while(length++ < 30) output.append(" "); output.append( - "YA:", hex(regs.ya, 4L), - " A:", hex(regs.a, 2L), - " X:", hex(regs.x, 2L), - " Y:", hex(regs.y, 2L), - " S:", hex(regs.s, 2L), + "YA:", hex(YA, 4L), + " A:", hex(A, 2L), + " X:", hex(X, 2L), + " Y:", hex(Y, 2L), + " S:", hex(S, 2L), " ", - regs.p.n ? "N" : "n", - regs.p.v ? "V" : "v", - regs.p.p ? "P" : "p", - regs.p.b ? "B" : "b", - regs.p.h ? "H" : "h", - regs.p.i ? "I" : "i", - regs.p.z ? "Z" : "z", - regs.p.c ? "C" : "c" + NF ? "N" : "n", + VF ? "V" : "v", + PF ? "P" : "p", + BF ? "B" : "b", + HF ? "H" : "h", + IF ? "I" : "i", + ZF ? "Z" : "z", + CF ? "C" : "c" ); return output; diff --git a/higan/processor/spc700/instruction.cpp b/higan/processor/spc700/instruction.cpp new file mode 100644 index 00000000..eabb1ea7 --- /dev/null +++ b/higan/processor/spc700/instruction.cpp @@ -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 diff --git a/higan/processor/spc700/instructions.cpp b/higan/processor/spc700/instructions.cpp index f66f5c6f..a30eb725 100644 --- a/higan/processor/spc700/instructions.cpp +++ b/higan/processor/spc700/instructions.cpp @@ -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(); - r = call(r); + target = alu(target); } -auto SPC700::op_adjust_addr(fps op) { - dp.l = readPC(); - dp.h = readPC(); - rd = read(dp); - rd = call(rd); - write(dp, rd); +auto SPC700::instructionAbsoluteModify(fps op) -> void { + uint16 absolute = fetch(); + absolute |= fetch() << 8; + uint8 data = read(absolute); + write(absolute, alu(data)); } -auto SPC700::op_adjust_dp(fps op) { - dp = readPC(); - rd = readDP(dp); - rd = call(rd); - writeDP(dp, rd); +auto SPC700::instructionDirectPageModify(fps op) -> void { + uint8 direct = fetch(); + uint8 data = load(direct); + store(direct, alu(data)); } -auto SPC700::op_adjust_dpw(int n) { - dp = readPC(); - rd.w = readDP(dp) + n; - writeDP(dp++, rd.l); - rd.h += readDP(dp); - writeDP(dp++, rd.h); - regs.p.n = rd & 0x8000; - regs.p.z = rd == 0; +auto SPC700::instructionDirectPageModifyWord(int adjust) -> void { + uint8 direct = fetch(); + uint16 data = load(direct) + adjust; + store(direct++, data >> 0); + data += load(direct) << 8; + store(direct++, data >> 8); + ZF = data == 0; + NF = data & 0x8000; } -auto SPC700::op_adjust_dpx(fps op) { - dp = readPC(); +auto SPC700::instructionDirectPageXModify(fps op) -> void { + uint8 direct = fetch(); idle(); - rd = readDP(dp + regs.x); - rd = call(rd); - writeDP(dp + regs.x, rd); + uint8 data = load(direct + X); + store(direct + X, alu(data)); } -auto SPC700::op_branch(bool condition) { - rd = readPC(); - if(!condition) return; +auto SPC700::instructionBranch(bool take) -> void { + uint8 data = fetch(); + if(!take) return; idle(); idle(); - regs.pc += (int8)rd; + PC += (int8)data; } -auto SPC700::op_branch_bit() { - dp = readPC(); - sp = readDP(dp); - rd = readPC(); - idle(); - if((bool)(sp & (1 << (opcode >> 5))) == (bool)(opcode & 0x10)) return; +auto SPC700::instructionPull(uint8& data) -> void { idle(); idle(); - regs.pc += (int8)rd; + data = pull(); } -auto SPC700::op_pull(reg r) { +auto SPC700::instructionPush(uint8 data) -> void { 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(); + 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(); - writeSP(r); + rd = load(dp + index); + data = alu(data, rd); } -auto SPC700::op_read_addr(fpb op, reg r) { - dp.l = readPC(); - dp.h = readPC(); - rd = read(dp); - r = call(r, rd); +auto SPC700::instructionDirectPageReadWord(fpw op) -> void { + dp = fetch(); + rd.l = load(dp++); + if(op != &SPC700::algorithmCPW) idle(); + rd.h = load(dp++); + YA = alu(YA, rd); } -auto SPC700::op_read_addri(fpb op, reg r) { - dp.l = readPC(); - dp.h = readPC(); +auto SPC700::instructionIndirectPageXRead(fpb op) -> void { + dp = fetch() + X; idle(); - rd = read(dp + r); - regs.a = call(regs.a, rd); -} - -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++); + sp.l = load(dp++); + sp.h = load(dp++); rd = read(sp); - regs.a = call(regs.a, rd); + A = alu(A, rd); } -auto SPC700::op_read_idpy(fpb op) { - dp = readPC(); +auto SPC700::instructionIndirectPageYRead(fpb op) -> void { + dp = fetch(); idle(); - sp.l = readDP(dp++); - sp.h = readDP(dp++); - rd = read(sp + regs.y); - regs.a = call(regs.a, rd); + sp.l = load(dp++); + sp.h = load(dp++); + rd = read(sp + Y); + A = alu(A, rd); } -auto SPC700::op_read_ix(fpb op) { +auto SPC700::instructionIndirectXRead(fpb op) -> void { idle(); - rd = readDP(regs.x); - regs.a = call(regs.a, rd); + rd = load(X); + A = alu(A, rd); } -auto SPC700::op_set_addr_bit() { - dp.l = readPC(); - dp.h = readPC(); +auto SPC700::instructionAbsoluteModifyBit() -> void { + dp.l = fetch(); + dp.h = fetch(); bit = dp >> 13; dp &= 0x1fff; rd = read(dp); @@ -144,22 +130,22 @@ auto SPC700::op_set_addr_bit() { case 0: //orc addr:bit case 1: //orc !addr:bit idle(); - regs.p.c |= (rd & (1 << bit)) ^ (bool)(opcode & 0x20); + CF |= (rd & (1 << bit)) ^ (bool)(opcode & 0x20); break; case 2: //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; case 4: //eor addr:bit idle(); - regs.p.c ^= (bool)(rd & (1 << bit)); + CF ^= (bool)(rd & (1 << bit)); break; case 5: //ldc addr:bit - regs.p.c = (rd & (1 << bit)); + CF = (rd & (1 << bit)); break; case 6: //stc addr:bit idle(); - rd = (rd & ~(1 << bit)) | (regs.p.c << bit); + rd = (rd & ~(1 << bit)) | (CF << bit); write(dp, rd); break; case 7: //not addr:bit @@ -169,190 +155,209 @@ auto SPC700::op_set_addr_bit() { } } -auto SPC700::op_set_bit() { - dp = readPC(); - rd = readDP(dp) & ~(1 << (opcode >> 5)); - writeDP(dp, rd | (!(opcode & 0x10) << (opcode >> 5))); -} - -auto SPC700::op_set_flag(uint bit, bool value) { +auto SPC700::instructionFlagClear(bool& flag) -> void { idle(); - if(bit == regs.p.i.bit) idle(); - regs.p = value ? (regs.p | (1 << bit)) : (regs.p & ~(1 << bit)); + if(&flag == &IF) idle(); + flag = 0; } -auto SPC700::op_test_addr(bool set) { - dp.l = readPC(); - dp.h = readPC(); - rd = read(dp); - 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::instructionFlagSet(bool& flag) -> void { + idle(); + if(&flag == &IF) idle(); + flag = 1; } -auto SPC700::op_transfer(reg from, reg to) { +auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void { idle(); to = from; - if(&to == ®s.s) return; - regs.p.n = (to & 0x80); - regs.p.z = (to == 0); + if(&to == &S) return; + ZF = to == 0; + NF = to & 0x80; } -auto SPC700::op_write_addr(reg r) { - dp.l = readPC(); - dp.h = readPC(); +auto SPC700::instructionAbsoluteWrite(uint8& data) -> void { + dp.l = fetch(); + dp.h = fetch(); read(dp); - write(dp, r); + write(dp, data); } -auto SPC700::op_write_addri(reg i) { - dp.l = readPC(); - dp.h = readPC(); +auto SPC700::instructionAbsoluteIndexedWrite(uint8& index) -> void { + dp.l = fetch(); + dp.h = fetch(); idle(); - dp += i; + dp += index; read(dp); - write(dp, regs.a); + write(dp, A); } -auto SPC700::op_write_dp(reg r) { - dp = readPC(); - readDP(dp); - writeDP(dp, r); +auto SPC700::instructionDirectPageWrite(uint8& data) -> void { + dp = fetch(); + load(dp); + store(dp, data); } -auto SPC700::op_write_dpi(reg r, reg i) { - dp = readPC() + i; +auto SPC700::instructionDirectPageIndexedWrite(uint8& data, uint8& index) -> void { + dp = fetch() + index; idle(); - readDP(dp); - writeDP(dp, r); + load(dp); + store(dp, data); } -auto SPC700::op_write_dp_const(fpb op) { - rd = readPC(); - dp = readPC(); - wr = readDP(dp); - wr = call(wr, rd); - op != &SPC700::op_cmp ? writeDP(dp, wr) : idle(); +auto SPC700::instructionDirectPageWriteImmediate(fpb op) -> void { + rd = fetch(); + dp = fetch(); + wr = load(dp); + wr = alu(wr, rd); + op != &SPC700::algorithmCMP ? store(dp, wr) : idle(); } -auto SPC700::op_write_dp_dp(fpb op) { - sp = readPC(); - rd = readDP(sp); - dp = readPC(); - if(op != &SPC700::op_st) wr = readDP(dp); - wr = call(wr, rd); - op != &SPC700::op_cmp ? writeDP(dp, wr) : idle(); +auto SPC700::instructionDirectPageWriteDirectPage(fpb op) -> void { + sp = fetch(); + rd = load(sp); + dp = fetch(); + if(op != &SPC700::algorithmST) wr = load(dp); + wr = alu(wr, rd); + op != &SPC700::algorithmCMP ? store(dp, wr) : idle(); } -auto SPC700::op_write_ix_iy(fpb op) { +auto SPC700::instructionIndirectXWriteIndirectY(fpb op) -> void { idle(); - rd = readDP(regs.y); - wr = readDP(regs.x); - wr = call(wr, rd); - op != &SPC700::op_cmp ? writeDP(regs.x, wr) : idle(); + rd = load(Y); + wr = load(X); + wr = alu(wr, rd); + op != &SPC700::algorithmCMP ? store(X, wr) : idle(); } // -auto SPC700::op_bne_dp() { - dp = readPC(); - sp = readDP(dp); - rd = readPC(); +auto SPC700::instructionBBC(uint3 bit) -> void { + dp = fetch(); + uint8 data = load(dp); + rd = fetch(); idle(); - if(regs.a == sp) return; + if(data.bit(bit) == 1) return; idle(); idle(); - regs.pc += (int8)rd; + PC += (int8)rd; } -auto SPC700::op_bne_dpdec() { - dp = readPC(); - wr = readDP(dp); - writeDP(dp, --wr); - rd = readPC(); +auto SPC700::instructionBBS(uint3 bit) -> void { + dp = fetch(); + uint8 data = load(dp); + rd = fetch(); + 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; idle(); idle(); - regs.pc += (int8)rd; + PC += (int8)rd; } -auto SPC700::op_bne_dpx() { - dp = readPC(); +auto SPC700::instructionBNEDirectPageX() -> void { + dp = fetch(); idle(); - sp = readDP(dp + regs.x); - rd = readPC(); + sp = load(dp + X); + rd = fetch(); idle(); - if(regs.a == sp) return; + if(A == sp) return; idle(); idle(); - regs.pc += (int8)rd; + PC += (int8)rd; } -auto SPC700::op_bne_ydec() { - rd = readPC(); +auto SPC700::instructionBNEYDecrement() -> void { + rd = fetch(); idle(); idle(); - if(--regs.y == 0) return; + if(--Y == 0) return; idle(); idle(); - regs.pc += (int8)rd; + PC += (int8)rd; } -auto SPC700::op_brk() { +auto SPC700::instructionBRK() -> void { rd.l = read(0xffde); rd.h = read(0xffdf); idle(); idle(); - writeSP(regs.pc.h); - writeSP(regs.pc.l); - writeSP(regs.p); - regs.pc = rd; - regs.p.b = 1; - regs.p.i = 0; + push(PC >> 8); + push(PC >> 0); + push(P); + PC = rd; + IF = 0; + BF = 1; } -auto SPC700::op_clv() { - idle(); - regs.p.v = 0; - regs.p.h = 0; +auto SPC700::instructionCLR(uint3 bit) -> void { + uint8 direct = fetch(); + uint8 data = load(direct); + data.bit(bit) = 0; + store(direct, data); } -auto SPC700::op_cmc() { +auto SPC700::instructionCLV() -> void { idle(); - idle(); - regs.p.c = !regs.p.c; + HF = 0; + VF = 0; } -auto SPC700::op_daa() { +auto SPC700::instructionCMC() -> void { idle(); idle(); - if(regs.p.c || (regs.a) > 0x99) { - regs.a += 0x60; - regs.p.c = 1; + CF = !CF; +} + +auto SPC700::instructionDAA() -> void { + idle(); + idle(); + if(CF || A > 0x99) { + A += 0x60; + CF = 1; } - if(regs.p.h || (regs.a & 15) > 0x09) { - regs.a += 0x06; + if(HF || (A & 15) > 0x09) { + A += 0x06; } - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); + ZF = A == 0; + NF = A & 0x80; } -auto SPC700::op_das() { +auto SPC700::instructionDAS() -> void { idle(); idle(); - if(!regs.p.c || (regs.a) > 0x99) { - regs.a -= 0x60; - regs.p.c = 0; + if(!CF || A > 0x99) { + A -= 0x60; + CF = 0; } - if(!regs.p.h || (regs.a & 15) > 0x09) { - regs.a -= 0x06; + if(!HF || (A & 15) > 0x09) { + A -= 0x06; } - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); + ZF = A == 0; + NF = A & 0x80; } -auto SPC700::op_div_ya_x() { +auto SPC700::instructionDIV() -> void { idle(); idle(); idle(); @@ -364,82 +369,82 @@ auto SPC700::op_div_ya_x() { idle(); idle(); idle(); - ya = regs.ya; + uint16 ya = YA; //overflow set if quotient >= 256 - regs.p.v = (regs.y >= regs.x); - regs.p.h = ((regs.y & 15) >= (regs.x & 15)); - if(regs.y < (regs.x << 1)) { + HF = (Y & 15) >= (X & 15); + VF = Y >= X; + if(Y < (X << 1)) { //if quotient is <= 511 (will fit into 9-bit result) - regs.a = ya / regs.x; - regs.y = ya % regs.x; + A = ya / X; + Y = ya % X; } 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 - regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); - regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + A = 255 - (ya - (X << 9)) / (256 - X); + Y = X + (ya - (X << 9)) % (256 - X); } //result is set based on a (quotient) only - regs.p.n = (regs.a & 0x80); - regs.p.z = (regs.a == 0); + ZF = A == 0; + NF = A & 0x80; } -auto SPC700::op_jmp_addr() { - rd.l = readPC(); - rd.h = readPC(); - regs.pc = rd; +auto SPC700::instructionJMPAbsolute() -> void { + rd.l = fetch(); + rd.h = fetch(); + PC = rd; } -auto SPC700::op_jmp_iaddrx() { - dp.l = readPC(); - dp.h = readPC(); +auto SPC700::instructionJMPIndirectAbsoluteX() -> void { + dp.l = fetch(); + dp.h = fetch(); idle(); - dp += regs.x; + dp += X; rd.l = read(dp++); rd.h = read(dp++); - regs.pc = rd; + PC = rd; } -auto SPC700::op_jsp_dp() { - rd = readPC(); +auto SPC700::instructionJSPDirectPage() -> void { + rd = fetch(); idle(); idle(); - writeSP(regs.pc.h); - writeSP(regs.pc.l); - regs.pc = 0xff00 | rd; + push(PC >> 8); + push(PC >> 0); + PC = 0xff00 | rd; } -auto SPC700::op_jsr_addr() { - rd.l = readPC(); - rd.h = readPC(); +auto SPC700::instructionJSRAbsolute() -> void { + rd.l = fetch(); + rd.h = fetch(); idle(); idle(); idle(); - writeSP(regs.pc.h); - writeSP(regs.pc.l); - regs.pc = rd; + push(PC >> 8); + push(PC >> 0); + PC = rd; } -auto SPC700::op_jst() { - dp = 0xffde - ((opcode >> 4) << 1); +auto SPC700::instructionJST(uint4 vector) -> void { + dp = 0xffde - (vector << 1); rd.l = read(dp++); rd.h = read(dp++); idle(); idle(); idle(); - writeSP(regs.pc.h); - writeSP(regs.pc.l); - regs.pc = rd; + push(PC >> 8); + push(PC >> 0); + PC = rd; } -auto SPC700::op_lda_ixinc() { +auto SPC700::instructionLDAIndirectXIncrement() -> void { idle(); - regs.a = readDP(regs.x++); + A = load(X++); idle(); - regs.p.n = regs.a & 0x80; - regs.p.z = regs.a == 0; + ZF = A == 0; + NF = A & 0x80; } -auto SPC700::op_mul_ya() { +auto SPC700::instructionMUL() -> void { idle(); idle(); idle(); @@ -448,94 +453,128 @@ auto SPC700::op_mul_ya() { idle(); idle(); idle(); - ya = regs.y * regs.a; - regs.a = ya; - regs.y = ya >> 8; + uint16 ya = Y * A; + A = ya >> 0; + Y = ya >> 8; //result is set based on y (high-byte) only - regs.p.n = (regs.y & 0x80); - regs.p.z = (regs.y == 0); + ZF = Y == 0; + NF = Y & 0x80; } -auto SPC700::op_nop() { +auto SPC700::instructionNOP() -> void { idle(); } -auto SPC700::op_plp() { +auto SPC700::instructionPLP() -> void { idle(); idle(); - regs.p = readSP(); + P = pull(); } -auto SPC700::op_rti() { - regs.p = readSP(); - rd.l = readSP(); - rd.h = readSP(); +auto SPC700::instructionRTI() -> void { + P = pull(); + rd.l = pull(); + rd.h = pull(); idle(); idle(); - regs.pc = rd; + PC = rd; } -auto SPC700::op_rts() { - rd.l = readSP(); - rd.h = readSP(); +auto SPC700::instructionRTS() -> void { + rd.l = pull(); + rd.h = pull(); idle(); idle(); - regs.pc = rd; + PC = rd; } -auto SPC700::op_sta_idpx() { - sp = readPC() + regs.x; +auto SPC700::instructionSET(uint3 bit) -> void { + uint8 direct = fetch(); + uint8 data = load(direct); + data.bit(bit) = 1; + store(direct, data); +} + +auto SPC700::instructionSTAIndirectPageX() -> void { + sp = fetch() + X; idle(); - dp.l = readDP(sp++); - dp.h = readDP(sp++); + dp.l = load(sp++); + dp.h = load(sp++); read(dp); - write(dp, regs.a); + write(dp, A); } -auto SPC700::op_sta_idpy() { - sp = readPC(); - dp.l = readDP(sp++); - dp.h = readDP(sp++); +auto SPC700::instructionSTAIndirectPageY() -> void { + sp = fetch(); + dp.l = load(sp++); + dp.h = load(sp++); idle(); - dp += regs.y; + dp += Y; read(dp); - write(dp, regs.a); + write(dp, A); } -auto SPC700::op_sta_ix() { +auto SPC700::instructionSTAIndirectX() -> void { idle(); - readDP(regs.x); - writeDP(regs.x, regs.a); + load(X); + store(X, A); } -auto SPC700::op_sta_ixinc() { +auto SPC700::instructionSTAIndirectXIncrement() -> void { idle(); idle(); - writeDP(regs.x++, regs.a); + store(X++, A); } -auto SPC700::op_stw_dp() { - dp = readPC(); - readDP(dp); - writeDP(dp++, regs.a); - writeDP(dp++, regs.y); -} - -auto SPC700::op_wait() { +auto SPC700::instructionSTP() -> void { while(true) { idle(); idle(); } } -auto SPC700::op_xcn() { - idle(); - idle(); - idle(); - idle(); - regs.a = (regs.a >> 4) | (regs.a << 4); - regs.p.n = regs.a & 0x80; - regs.p.z = regs.a == 0; +auto SPC700::instructionSTWDirectPage() -> void { + dp = fetch(); + load(dp); + store(dp++, A); + store(dp++, Y); } -#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 diff --git a/higan/processor/spc700/memory.cpp b/higan/processor/spc700/memory.cpp new file mode 100644 index 00000000..91541f4e --- /dev/null +++ b/higan/processor/spc700/memory.cpp @@ -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); +} diff --git a/higan/processor/spc700/memory.hpp b/higan/processor/spc700/memory.hpp deleted file mode 100644 index 94c28b94..00000000 --- a/higan/processor/spc700/memory.hpp +++ /dev/null @@ -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); -} diff --git a/higan/processor/spc700/registers.hpp b/higan/processor/spc700/registers.hpp deleted file mode 100644 index 622cd43c..00000000 --- a/higan/processor/spc700/registers.hpp +++ /dev/null @@ -1,53 +0,0 @@ -struct Flags { - union { - uint8_t data = 0; - BooleanBitField n; - BooleanBitField v; - BooleanBitField p; - BooleanBitField b; - BooleanBitField h; - BooleanBitField i; - BooleanBitField z; - BooleanBitField 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 l; - NaturalBitField 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; -}; diff --git a/higan/processor/spc700/serialization.cpp b/higan/processor/spc700/serialization.cpp index ad195768..0e90b928 100644 --- a/higan/processor/spc700/serialization.cpp +++ b/higan/processor/spc700/serialization.cpp @@ -1,10 +1,16 @@ auto SPC700::serialize(serializer& s) -> void { - s.integer(regs.pc.w); - s.integer(regs.a); - s.integer(regs.x); - s.integer(regs.y); - s.integer(regs.s); - s.integer(regs.p.data); + s.integer(r.pc.w); + s.integer(r.ya.w); + s.integer(r.x); + s.integer(r.s); + s.integer(r.p.c); + 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(dp.w); @@ -12,5 +18,4 @@ auto SPC700::serialize(serializer& s) -> void { s.integer(rd.w); s.integer(wr.w); s.integer(bit.w); - s.integer(ya.w); } diff --git a/higan/processor/spc700/spc700.cpp b/higan/processor/spc700/spc700.cpp index 80455fc0..93f14fca 100644 --- a/higan/processor/spc700/spc700.cpp +++ b/higan/processor/spc700/spc700.cpp @@ -3,276 +3,53 @@ 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 "instructions.cpp" -#include "disassembler.cpp" +#include "instruction.cpp" #include "serialization.cpp" +#include "disassembler.cpp" -#define op(id, name, ...) case id: return op_##name(__VA_ARGS__); -#define fp(name) &SPC700::op_##name +#undef PC +#undef YA +#undef A +#undef X +#undef Y +#undef S +#undef P -auto SPC700::instruction() -> void { - switch(opcode = readPC()) { - op(0x00, nop) - op(0x01, jst) - op(0x02, set_bit) - op(0x03, branch_bit) - op(0x04, read_dp, fp(or), regs.a) - op(0x05, read_addr, fp(or), regs.a) - op(0x06, read_ix, fp(or)) - op(0x07, read_idpx, fp(or)) - op(0x08, read_const, fp(or), regs.a) - op(0x09, write_dp_dp, fp(or)) - op(0x0a, set_addr_bit) - op(0x0b, adjust_dp, fp(asl)) - op(0x0c, adjust_addr, fp(asl)) - 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 CF +#undef ZF +#undef IF +#undef HF +#undef BF +#undef PF +#undef VF +#undef NF + +auto SPC700::power() -> void { + r.pc.w = 0x0000; + r.ya.w = 0x0000; + r.x = 0x00; + r.s = 0xef; + r.p = 0x02; } -#undef op -#undef fp - } diff --git a/higan/processor/spc700/spc700.hpp b/higan/processor/spc700/spc700.hpp index 7e885623..c930abe1 100644 --- a/higan/processor/spc700/spc700.hpp +++ b/higan/processor/spc700/spc700.hpp @@ -8,103 +8,178 @@ struct SPC700 { virtual auto write(uint16 addr, uint8 data) -> void = 0; virtual auto readDisassembler(uint16 addr) -> uint8 = 0; + //spc700.cpp + auto power() -> void; + + //instruction.cpp 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" - #include "memory.hpp" - - Registers regs; - Register dp, sp, rd, wr, bit, ya; - uint8 opcode; - -protected: + //instructions.cpp using fps = auto (SPC700::*)(uint8) -> uint8; using fpb = auto (SPC700::*)(uint8, uint8) -> uint8; using fpw = auto (SPC700::*)(uint16, uint16) -> uint16; - using reg = uint8_t&; - auto op_adc(uint8, uint8) -> uint8; - auto op_and(uint8, uint8) -> uint8; - auto op_asl(uint8) -> uint8; - auto op_cmp(uint8, uint8) -> uint8; - auto op_dec(uint8) -> uint8; - auto op_eor(uint8, uint8) -> uint8; - auto op_inc(uint8) -> uint8; - auto op_ld (uint8, uint8) -> uint8; - auto op_lsr(uint8) -> uint8; - auto op_or (uint8, uint8) -> uint8; - auto op_rol(uint8) -> uint8; - auto op_ror(uint8) -> uint8; - auto op_sbc(uint8, uint8) -> uint8; - auto op_st (uint8, uint8) -> uint8; - auto op_adw(uint16, uint16) -> uint16; - auto op_cpw(uint16, uint16) -> uint16; - auto op_ldw(uint16, uint16) -> uint16; - auto op_sbw(uint16, uint16) -> uint16; + auto instructionImpliedModify(fps, uint8&) -> void; + auto instructionAbsoluteModify(fps) -> void; + auto instructionDirectPageModify(fps) -> void; + auto instructionDirectPageModifyWord(int) -> void; + auto instructionDirectPageXModify(fps) -> void; + auto instructionBranch(bool) -> void; + auto instructionPull(uint8&) -> void; + auto instructionPush(uint8) -> void; + auto instructionAbsoluteRead(fpb, uint8&) -> void; + auto instructionAbsoluteIndexedRead(fpb, uint8&) -> void; + auto instructionImmediateRead(fpb, uint8&) -> void; + auto instructionDirectPageRead(fpb, uint8&) -> void; + auto instructionDirectPageIndexedRead(fpb, uint8&, uint8&) -> void; + auto instructionDirectPageReadWord(fpw) -> void; + auto instructionIndirectPageXRead(fpb) -> void; + auto instructionIndirectPageYRead(fpb) -> void; + auto instructionIndirectXRead(fpb) -> void; + 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 op_adjust_addr(fps); - auto op_adjust_dp(fps); - auto op_adjust_dpw(int); - auto op_adjust_dpx(fps); - auto op_branch(bool); - auto op_branch_bit(); - auto op_pull(reg); - auto op_push(uint8); - auto op_read_addr(fpb, reg); - auto op_read_addri(fpb, reg); - auto op_read_const(fpb, reg); - auto op_read_dp(fpb, reg); - auto op_read_dpi(fpb, reg, reg); - auto op_read_dpw(fpw); - auto op_read_idpx(fpb); - auto op_read_idpy(fpb); - auto op_read_ix(fpb); - auto op_set_addr_bit(); - auto op_set_bit(); - auto op_set_flag(uint, bool); - auto op_test_addr(bool); - auto op_transfer(reg, reg); - auto op_write_addr(reg); - auto op_write_addri(reg); - auto op_write_dp(reg); - auto op_write_dpi(reg, reg); - auto op_write_dp_const(fpb); - auto op_write_dp_dp(fpb); - auto op_write_ix_iy(fpb); + auto instructionBBC(uint3) -> void; + auto instructionBBS(uint3) -> void; + auto instructionBNEDirectPage() -> void; + auto instructionBNEDirectPageDecrement() -> void; + auto instructionBNEDirectPageX() -> void; + auto instructionBNEYDecrement() -> void; + auto instructionBRK() -> void; + auto instructionCLR(uint3) -> void; + auto instructionCLV() -> void; + auto instructionCMC() -> void; + auto instructionDAA() -> void; + auto instructionDAS() -> void; + auto instructionDIV() -> void; + auto instructionJMPAbsolute() -> void; + auto instructionJMPIndirectAbsoluteX() -> void; + auto instructionJSPDirectPage() -> void; + auto instructionJSRAbsolute() -> void; + auto instructionJST(uint4) -> void; + auto instructionLDAIndirectXIncrement() -> void; + auto instructionMUL() -> void; + auto instructionNOP() -> void; + auto instructionPLP() -> void; + auto instructionRTI() -> void; + auto instructionRTS() -> void; + auto instructionSET(uint3) -> void; + auto instructionSTAIndirectPageX() -> void; + auto instructionSTAIndirectPageY() -> void; + auto instructionSTAIndirectX() -> void; + auto instructionSTAIndirectXIncrement() -> void; + auto instructionSTP() -> void; + auto instructionSTWDirectPage() -> void; + auto instructionTRBAbsolute() -> void; + auto instructionTSBAbsolute() -> void; + auto instructionWAI() -> void; + auto instructionXCN() -> void; - auto op_bne_dp(); - auto op_bne_dpdec(); - auto op_bne_dpx(); - auto op_bne_ydec(); - auto op_brk(); - auto op_clv(); - auto op_cmc(); - auto op_daa(); - auto op_das(); - auto op_div_ya_x(); - auto op_jmp_addr(); - auto op_jmp_iaddrx(); - auto op_jsp_dp(); - auto op_jsr_addr(); - auto op_jst(); - auto op_lda_ixinc(); - auto op_mul_ya(); - auto op_nop(); - auto op_plp(); - auto op_rti(); - auto op_rts(); - auto op_sta_idpx(); - auto op_sta_idpy(); - auto op_sta_ix(); - auto op_sta_ixinc(); - auto op_stw_dp(); - auto op_wait(); - auto op_xcn(); + //serialization.cpp + auto serialize(serializer&) -> void; + + //disassembler.cpp + auto disassemble(uint16 addr, bool p) -> string; + + struct Flags { + bool c; //carry + bool z; //zero + bool i; //interrupt disable + bool h; //half-carry + bool b; //break + bool p; //page + bool v; //overflow + bool n; //negative + + inline operator uint() const { + return c << 0 | z << 1 | i << 2 | h << 3 | b << 4 | p << 5 | v << 6 | n << 7; + } + + inline auto& operator=(uint8 data) { + c = data.bit(0); + z = data.bit(1); + i = data.bit(2); + h = data.bit(3); + b = data.bit(4); + p = data.bit(5); + 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 l; + NaturalBitField 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; }; } diff --git a/higan/processor/wdc65816/algorithms.cpp b/higan/processor/wdc65816/algorithms.cpp index df41d35a..aecffdf7 100644 --- a/higan/processor/wdc65816/algorithms.cpp +++ b/higan/processor/wdc65816/algorithms.cpp @@ -38,7 +38,7 @@ auto WDC65816::algorithmADC16(uint16 data) -> uint16 { } VF = ~(A ^ data) & (A ^ result) & 0x8000; - if(D && result > 0x9fff) result += 0x6000; + if(DF && result > 0x9fff) result += 0x6000; CF = result > 0xffff; ZF = (uint16)result == 0; NF = result & 0x8000; @@ -48,7 +48,7 @@ auto WDC65816::algorithmADC16(uint16 data) -> uint16 { auto WDC65816::algorithmAND8(uint8 data) -> uint8 { lo(A) &= data; - ZF = A == 0; + ZF = lo(A) == 0; NF = A & 0x80; return data; } @@ -148,13 +148,13 @@ auto WDC65816::algorithmDEC8(uint8 data) -> uint8 { auto WDC65816::algorithmDEC16(uint16 data) -> uint16 { data--; ZF = data == 0; - NF = data & 0x80; + NF = data & 0x8000; return data; } auto WDC65816::algorithmEOR8(uint8 data) -> uint8 { lo(A) ^= data; - ZF = A == 0; + ZF = lo(A) == 0; NF = A & 0x80; return lo(A); } diff --git a/higan/processor/wdc65816/instructions-misc.cpp b/higan/processor/wdc65816/instructions-misc.cpp index 7a20111c..b366dac1 100644 --- a/higan/processor/wdc65816/instructions-misc.cpp +++ b/higan/processor/wdc65816/instructions-misc.cpp @@ -171,7 +171,7 @@ L push(lo(data)); auto WDC65816::instructionPHD() -> void { idle(); pushN(hi(D)); -L pushN(hi(D)); +L pushN(lo(D)); E hi(S) = 0x01; } diff --git a/higan/processor/wdc65816/instructions-pc.cpp b/higan/processor/wdc65816/instructions-pc.cpp index 506f12d2..b09c84b3 100644 --- a/higan/processor/wdc65816/instructions-pc.cpp +++ b/higan/processor/wdc65816/instructions-pc.cpp @@ -112,7 +112,7 @@ auto WDC65816::instructionRTS() -> void { uint16 data = pull(); hi(data) = pull(); L idle(); - PC = data; + aa(PC) = data; aa(PC)++; } diff --git a/higan/sfc/cpu/cpu.cpp b/higan/sfc/cpu/cpu.cpp index c34da70d..f1cdbe91 100644 --- a/higan/sfc/cpu/cpu.cpp +++ b/higan/sfc/cpu/cpu.cpp @@ -50,11 +50,6 @@ auto CPU::main() -> void { } } - #if 1 - static uint counter = 0; - if(++counter < 40) print(disassemble(), "\n"); - #endif - instruction(); } diff --git a/higan/sfc/smp/memory.cpp b/higan/sfc/smp/memory.cpp index fb56f578..a8fbe83c 100644 --- a/higan/sfc/smp/memory.cpp +++ b/higan/sfc/smp/memory.cpp @@ -74,7 +74,7 @@ auto SMP::readBus(uint16 addr) -> uint8 { auto SMP::writeBus(uint16 addr, uint8 data) -> void { switch(addr) { 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.timerSpeed = (data >> 4) & 3; diff --git a/higan/sfc/smp/smp.cpp b/higan/sfc/smp/smp.cpp index ccdc8478..9ea8c1ac 100644 --- a/higan/sfc/smp/smp.cpp +++ b/higan/sfc/smp/smp.cpp @@ -27,15 +27,11 @@ auto SMP::load(Markup::Node node) -> bool { } auto SMP::power() -> void { + SPC700::power(); create(Enter, 32040.0 * 768.0); - regs.pc.l = iplrom[62]; - regs.pc.h = iplrom[63]; - regs.a = 0x00; - regs.x = 0x00; - regs.y = 0x00; - regs.s = 0xef; - regs.p = 0x02; + r.pc.byte.l = iplrom[62]; + r.pc.byte.h = iplrom[63]; for(auto& byte : apuram) byte = random(0x00); apuram[0x00f4] = 0x00;