diff --git a/InstructionSets/CachingExecutor.hpp b/InstructionSets/CachingExecutor.hpp index c6a3f4cd4..63a7b4ff1 100644 --- a/InstructionSets/CachingExecutor.hpp +++ b/InstructionSets/CachingExecutor.hpp @@ -38,7 +38,18 @@ template struct MinIntTypeValue { }; +/*! + A caching executor makes use of an instruction set-specific executor to cache 'performers' (i.e. function pointers) + that result from decoding. + In other words, it's almost a JIT compiler, but producing threaded code (in the Forth sense) and then incurring whatever + costs sit behind using the C ABI for calling. Since there'll always be exactly one parameter, being the specific executor, + hopefully the calling costs are acceptable. + + Intended usage is for specific executors to subclass from this and declare it a friend. + + TODO: determine promises re: interruption, amongst other things. +*/ template < /// Indicates the Executor for this platform. typename Executor, @@ -53,11 +64,13 @@ template < protected: using Performer = void (*)(Executor *); + using PerformerIndex = typename MinIntTypeValue::type; + std::array performers_; typename MinIntTypeValue::type program_counter_; private: - typename MinIntTypeValue::type actions_[100]; + PerformerIndex actions_[100]; }; } diff --git a/InstructionSets/M50740/Decoder.cpp b/InstructionSets/M50740/Decoder.cpp index eda9aeeb5..8eda39630 100644 --- a/InstructionSets/M50740/Decoder.cpp +++ b/InstructionSets/M50740/Decoder.cpp @@ -13,6 +13,224 @@ namespace InstructionSet { namespace M50740 { +Instruction Decoder::instrucion_for_opcode(uint8_t opcode) { + switch(opcode) { + default: return Instruction(opcode); + +#define Map(opcode, operation, addressing_mode) case opcode: return Instruction(Operation::operation, AddressingMode::addressing_mode, opcode); + + /* 0x00 – 0x0f */ + Map(0x00, BRK, Implied); Map(0x01, ORA, XIndirect); + Map(0x02, JSR, ZeroPageIndirect); Map(0x03, BBS, Bit0AccumulatorRelative); + + Map(0x05, ORA, ZeroPage); + Map(0x06, ASL, ZeroPage); Map(0x07, BBS, Bit0ZeroPageRelative); + + Map(0x08, PHP, Implied); Map(0x09, ORA, Immediate); + Map(0x0a, ASL, Accumulator); Map(0x0b, SEB, Bit0Accumulator); + + Map(0x0d, ORA, Absolute); + Map(0x0e, ASL, Absolute); Map(0x0f, SEB, Bit0ZeroPage); + + /* 0x10 – 0x1f */ + Map(0x10, BPL, Relative); Map(0x11, ORA, IndirectY); + Map(0x12, CLT, Implied); Map(0x13, BBC, Bit0AccumulatorRelative); + + Map(0x15, ORA, ZeroPageX); + Map(0x16, ASL, ZeroPageX); Map(0x17, BBC, Bit0ZeroPageRelative); + + Map(0x18, CLC, Implied); Map(0x19, ORA, AbsoluteY); + Map(0x1a, DEC, Accumulator); Map(0x1b, CLB, Bit0Accumulator); + + Map(0x1d, ORA, AbsoluteX); + Map(0x1e, ASL, AbsoluteX); Map(0x1f, CLB, Bit0ZeroPage); + + /* 0x20 – 0x2f */ + Map(0x20, JSR, Absolute); Map(0x21, AND, XIndirect); + Map(0x22, JSR, SpecialPage); Map(0x23, BBS, Bit1AccumulatorRelative); + + Map(0x24, BIT, ZeroPage); Map(0x25, AND, ZeroPage); + Map(0x26, ROL, ZeroPage); Map(0x27, BBS, Bit1ZeroPageRelative); + + Map(0x28, PLP, Implied); Map(0x29, AND, Immediate); + Map(0x2a, ROL, Accumulator); Map(0x2b, SEB, Bit1Accumulator); + + Map(0x2c, BIT, Absolute); Map(0x2d, AND, Absolute); + Map(0x2e, ROL, Absolute); Map(0x2f, SEB, Bit1ZeroPage); + + /* 0x30 – 0x3f */ + Map(0x30, BMI, Relative); Map(0x31, AND, IndirectY); + Map(0x32, SET, Implied); Map(0x33, BBC, Bit1AccumulatorRelative); + + Map(0x35, AND, ZeroPageX); + Map(0x36, ROL, ZeroPageX); Map(0x37, BBC, Bit1ZeroPageRelative); + + Map(0x38, SEC, Implied); Map(0x39, AND, AbsoluteY); + Map(0x3a, INC, Accumulator); Map(0x3b, CLB, Bit1Accumulator); + + Map(0x3c, LDM, ImmediateZeroPage); Map(0x3d, AND, AbsoluteX); + Map(0x3e, ROL, AbsoluteX); Map(0x3f, CLB, Bit1ZeroPage); + + /* 0x40 – 0x4f */ + Map(0x40, RTI, Implied); Map(0x41, EOR, XIndirect); + Map(0x42, STP, Implied); Map(0x43, BBS, Bit2AccumulatorRelative); + + Map(0x44, COM, ZeroPage); Map(0x45, EOR, ZeroPage); + Map(0x46, LSR, ZeroPage); Map(0x47, BBS, Bit2ZeroPageRelative); + + Map(0x48, PHA, Implied); Map(0x49, EOR, Immediate); + Map(0x4a, LSR, Accumulator); Map(0x4b, SEB, Bit2Accumulator); + + Map(0x4c, JMP, Absolute); Map(0x4d, EOR, Absolute); + Map(0x4e, LSR, Absolute); Map(0x4f, SEB, Bit2ZeroPage); + + /* 0x50 – 0x5f */ + Map(0x50, BVC, Relative); Map(0x51, EOR, IndirectY); + Map(0x53, BBC, Bit2AccumulatorRelative); + + Map(0x55, EOR, ZeroPageX); + Map(0x56, LSR, ZeroPageX); Map(0x57, BBC, Bit2ZeroPageRelative); + + Map(0x58, CLI, Implied); Map(0x59, EOR, AbsoluteY); + Map(0x5b, CLB, Bit2Accumulator); + + Map(0x5d, EOR, AbsoluteX); + Map(0x5e, LSR, AbsoluteX); Map(0x5f, CLB, Bit2ZeroPage); + + /* 0x60 – 0x6f */ + Map(0x60, RTS, Implied); Map(0x61, ADC, XIndirect); + Map(0x63, BBS, Bit3AccumulatorRelative); + + Map(0x64, TST, ZeroPage); Map(0x65, ADC, ZeroPage); + Map(0x66, ROR, ZeroPage); Map(0x67, BBS, Bit3ZeroPageRelative); + + Map(0x68, PLA, Implied); Map(0x69, ADC, Immediate); + Map(0x6a, ROR, Accumulator); Map(0x6b, SEB, Bit3Accumulator); + + Map(0x6c, JMP, AbsoluteIndirect); Map(0x6d, ADC, Absolute); + Map(0x6e, ROR, Absolute); Map(0x6f, SEB, Bit3ZeroPage); + + /* 0x70 – 0x7f */ + Map(0x70, BVS, Relative); Map(0x71, ADC, IndirectY); + Map(0x73, BBC, Bit3AccumulatorRelative); + + Map(0x75, ADC, ZeroPageX); + Map(0x76, ROR, ZeroPageX); Map(0x77, BBC, Bit3ZeroPageRelative); + + Map(0x78, SEI, Implied); Map(0x79, ADC, AbsoluteY); + Map(0x7b, CLB, Bit3Accumulator); + + Map(0x7d, ADC, AbsoluteX); + Map(0x7e, ROR, AbsoluteX); Map(0x7f, CLB, Bit3ZeroPage); + + /* 0x80 – 0x8f */ + Map(0x80, BRA, Relative); Map(0x81, STA, XIndirect); + Map(0x82, RRF, ZeroPage); Map(0x83, BBS, Bit4AccumulatorRelative); + + Map(0x84, STY, ZeroPage); Map(0x85, STA, ZeroPage); + Map(0x86, STX, ZeroPage); Map(0x87, BBS, Bit4ZeroPageRelative); + + Map(0x88, DEY, Implied); + Map(0x8a, TXA, Implied); Map(0x8b, SEB, Bit4Accumulator); + + Map(0x8c, STY, Absolute); Map(0x8d, STA, Absolute); + Map(0x8e, STX, Absolute); Map(0x8f, SEB, Bit4ZeroPage); + + /* 0x90 – 0x9f */ + Map(0x90, BCC, Relative); Map(0x91, STA, IndirectY); + Map(0x93, BBC, Bit4AccumulatorRelative); + + Map(0x94, STY, ZeroPageX); Map(0x95, STA, ZeroPageX); + Map(0x96, STX, ZeroPageX); Map(0x97, BBC, Bit4ZeroPageRelative); + + Map(0x98, TYA, Implied); Map(0x99, STA, AbsoluteY); + Map(0x9a, TXS, AbsoluteY); Map(0x9b, CLB, Bit4Accumulator); + + Map(0x9d, ADC, AbsoluteX); + Map(0x9f, CLB, Bit4ZeroPage); + + /* 0xa0 – 0xaf */ + Map(0xa0, LDY, Immediate); Map(0xa1, LDA, XIndirect); + Map(0xa2, LDX, Immediate); Map(0xa3, BBS, Bit5AccumulatorRelative); + + Map(0xa4, LDY, ZeroPage); Map(0xa5, LDA, ZeroPage); + Map(0xa6, LDX, ZeroPage); Map(0xa7, BBS, Bit5ZeroPageRelative); + + Map(0xa8, TAY, Implied); Map(0xa9, LDA, Immediate); + Map(0xaa, TAX, Implied); Map(0xab, SEB, Bit5Accumulator); + + Map(0xac, LDY, Absolute); Map(0xad, LDA, Absolute); + Map(0xae, LDX, Absolute); Map(0xaf, SEB, Bit5ZeroPage); + + /* 0xb0 – 0xbf */ + Map(0xb0, BCS, Relative); Map(0xb1, STA, IndirectY); + Map(0xb2, JMP, ZeroPageIndirect); Map(0xb3, BBC, Bit5AccumulatorRelative); + + Map(0xb4, LDY, ZeroPageX); Map(0xb5, LDA, ZeroPageX); + Map(0xb6, LDX, ZeroPageY); Map(0xb7, BBC, Bit5ZeroPageRelative); + + Map(0xb8, CLV, Implied); Map(0xb9, LDA, AbsoluteY); + Map(0xba, TSX, AbsoluteY); Map(0xbb, CLB, Bit5Accumulator); + + Map(0xbc, LDY, AbsoluteX); Map(0xbd, LDA, AbsoluteX); + Map(0xbe, LDX, AbsoluteY); Map(0xbf, CLB, Bit5ZeroPage); + + /* 0xc0 – 0xcf */ + Map(0xc0, CPY, Immediate); Map(0xc1, CMP, XIndirect); + Map(0xc2, SLW, Implied); Map(0xc3, BBS, Bit6AccumulatorRelative); + + Map(0xc4, CPY, ZeroPage); Map(0xc5, CMP, ZeroPage); + Map(0xc6, DEC, ZeroPage); Map(0xc7, BBS, Bit6ZeroPageRelative); + + Map(0xc8, INY, Implied); Map(0xc9, CMP, Immediate); + Map(0xca, DEX, Implied); Map(0xcb, SEB, Bit6Accumulator); + + Map(0xcc, CPY, Absolute); Map(0xcd, CMP, Absolute); + Map(0xce, DEC, Absolute); Map(0xcf, SEB, Bit6ZeroPage); + + /* 0xd0 – 0xdf */ + Map(0xd0, BNE, Relative); Map(0xd1, CMP, IndirectY); + Map(0xd3, BBC, Bit6AccumulatorRelative); + + Map(0xd5, CMP, ZeroPageX); + Map(0xd6, DEC, ZeroPageX); Map(0xd7, BBC, Bit6ZeroPageRelative); + + Map(0xd8, CLD, Implied); Map(0xd9, CMP, AbsoluteY); + Map(0xdb, CLB, Bit6Accumulator); + + Map(0xdd, CMP, AbsoluteX); + Map(0xde, DEC, AbsoluteX); Map(0xdf, CLB, Bit6ZeroPage); + + /* 0xe0 – 0xef */ + Map(0xe0, CPX, Immediate); Map(0xe1, SBC, XIndirect); + Map(0xe2, FST, Implied); Map(0xe3, BBS, Bit7AccumulatorRelative); + + Map(0xe4, CPX, ZeroPage); Map(0xe5, SBC, ZeroPage); + Map(0xe6, INC, ZeroPage); Map(0xe7, BBS, Bit7ZeroPageRelative); + + Map(0xe8, INX, Implied); Map(0xe9, SBC, Immediate); + Map(0xea, NOP, Implied); Map(0xeb, SEB, Bit7Accumulator); + + Map(0xec, CPX, Absolute); Map(0xed, SBC, Absolute); + Map(0xee, INC, Absolute); Map(0xef, SEB, Bit7ZeroPage); + + /* 0xf0 – 0xff */ + Map(0xf0, BEQ, Relative); Map(0xf1, SBC, IndirectY); + Map(0xf3, BBC, Bit7AccumulatorRelative); + + Map(0xf5, SBC, ZeroPageX); + Map(0xf6, INC, ZeroPageX); Map(0xf7, BBC, Bit7ZeroPageRelative); + + Map(0xf8, SED, Implied); Map(0xf9, SBC, AbsoluteY); + Map(0xfb, CLB, Bit7Accumulator); + + Map(0xfd, SBC, AbsoluteX); + Map(0xfe, INC, AbsoluteX); Map(0xff, CLB, Bit7ZeroPage); + +#undef Map + } +} + std::pair Decoder::decode(const uint8_t *source, size_t length) { const uint8_t *const end = source + length; @@ -21,224 +239,14 @@ std::pair Decoder::decode(const uint8_ ++source; ++consumed_; - switch(instruction) { - default: - consumed_ = 0; - return std::make_pair(1, Instruction()); - -#define Map(opcode, operation, addressing_mode) case opcode: instr_ = Instruction(Operation::operation, AddressingMode::addressing_mode); break - - /* 0x00 – 0x0f */ - Map(0x00, BRK, Implied); Map(0x01, ORA, XIndirect); - Map(0x02, JSR, ZeroPageIndirect); Map(0x03, BBS, Bit0AccumulatorRelative); - - Map(0x05, ORA, ZeroPage); - Map(0x06, ASL, ZeroPage); Map(0x07, BBS, Bit0ZeroPageRelative); - - Map(0x08, PHP, Implied); Map(0x09, ORA, Immediate); - Map(0x0a, ASL, Accumulator); Map(0x0b, SEB, Bit0Accumulator); - - Map(0x0d, ORA, Absolute); - Map(0x0e, ASL, Absolute); Map(0x0f, SEB, Bit0ZeroPage); - - /* 0x10 – 0x1f */ - Map(0x10, BPL, Relative); Map(0x11, ORA, IndirectY); - Map(0x12, CLT, Implied); Map(0x13, BBC, Bit0AccumulatorRelative); - - Map(0x15, ORA, ZeroPageX); - Map(0x16, ASL, ZeroPageX); Map(0x17, BBC, Bit0ZeroPageRelative); - - Map(0x18, CLC, Implied); Map(0x19, ORA, AbsoluteY); - Map(0x1a, DEC, Accumulator); Map(0x1b, CLB, Bit0Accumulator); - - Map(0x1d, ORA, AbsoluteX); - Map(0x1e, ASL, AbsoluteX); Map(0x1f, CLB, Bit0ZeroPage); - - /* 0x20 – 0x2f */ - Map(0x20, JSR, Absolute); Map(0x21, AND, XIndirect); - Map(0x22, JSR, SpecialPage); Map(0x23, BBS, Bit1AccumulatorRelative); - - Map(0x24, BIT, ZeroPage); Map(0x25, AND, ZeroPage); - Map(0x26, ROL, ZeroPage); Map(0x27, BBS, Bit1ZeroPageRelative); - - Map(0x28, PLP, Implied); Map(0x29, AND, Immediate); - Map(0x2a, ROL, Accumulator); Map(0x2b, SEB, Bit1Accumulator); - - Map(0x2c, BIT, Absolute); Map(0x2d, AND, Absolute); - Map(0x2e, ROL, Absolute); Map(0x2f, SEB, Bit1ZeroPage); - - /* 0x30 – 0x3f */ - Map(0x30, BMI, Relative); Map(0x31, AND, IndirectY); - Map(0x32, SET, Implied); Map(0x33, BBC, Bit1AccumulatorRelative); - - Map(0x35, AND, ZeroPageX); - Map(0x36, ROL, ZeroPageX); Map(0x37, BBC, Bit1ZeroPageRelative); - - Map(0x38, SEC, Implied); Map(0x39, AND, AbsoluteY); - Map(0x3a, INC, Accumulator); Map(0x3b, CLB, Bit1Accumulator); - - Map(0x3c, LDM, ImmediateZeroPage); Map(0x3d, AND, AbsoluteX); - Map(0x3e, ROL, AbsoluteX); Map(0x3f, CLB, Bit1ZeroPage); - - /* 0x40 – 0x4f */ - Map(0x40, RTI, Implied); Map(0x41, EOR, XIndirect); - Map(0x42, STP, Implied); Map(0x43, BBS, Bit2AccumulatorRelative); - - Map(0x44, COM, ZeroPage); Map(0x45, EOR, ZeroPage); - Map(0x46, LSR, ZeroPage); Map(0x47, BBS, Bit2ZeroPageRelative); - - Map(0x48, PHA, Implied); Map(0x49, EOR, Immediate); - Map(0x4a, LSR, Accumulator); Map(0x4b, SEB, Bit2Accumulator); - - Map(0x4c, JMP, Absolute); Map(0x4d, EOR, Absolute); - Map(0x4e, LSR, Absolute); Map(0x4f, SEB, Bit2ZeroPage); - - /* 0x50 – 0x5f */ - Map(0x50, BVC, Relative); Map(0x51, EOR, IndirectY); - Map(0x53, BBC, Bit2AccumulatorRelative); - - Map(0x55, EOR, ZeroPageX); - Map(0x56, LSR, ZeroPageX); Map(0x57, BBC, Bit2ZeroPageRelative); - - Map(0x58, CLI, Implied); Map(0x59, EOR, AbsoluteY); - Map(0x5b, CLB, Bit2Accumulator); - - Map(0x5d, EOR, AbsoluteX); - Map(0x5e, LSR, AbsoluteX); Map(0x5f, CLB, Bit2ZeroPage); - - /* 0x60 – 0x6f */ - Map(0x60, RTS, Implied); Map(0x61, ADC, XIndirect); - Map(0x63, BBS, Bit3AccumulatorRelative); - - Map(0x64, TST, ZeroPage); Map(0x65, ADC, ZeroPage); - Map(0x66, ROR, ZeroPage); Map(0x67, BBS, Bit3ZeroPageRelative); - - Map(0x68, PLA, Implied); Map(0x69, ADC, Immediate); - Map(0x6a, ROR, Accumulator); Map(0x6b, SEB, Bit3Accumulator); - - Map(0x6c, JMP, AbsoluteIndirect); Map(0x6d, ADC, Absolute); - Map(0x6e, ROR, Absolute); Map(0x6f, SEB, Bit3ZeroPage); - - /* 0x70 – 0x7f */ - Map(0x70, BVS, Relative); Map(0x71, ADC, IndirectY); - Map(0x73, BBC, Bit3AccumulatorRelative); - - Map(0x75, ADC, ZeroPageX); - Map(0x76, ROR, ZeroPageX); Map(0x77, BBC, Bit3ZeroPageRelative); - - Map(0x78, SEI, Implied); Map(0x79, ADC, AbsoluteY); - Map(0x7b, CLB, Bit3Accumulator); - - Map(0x7d, ADC, AbsoluteX); - Map(0x7e, ROR, AbsoluteX); Map(0x7f, CLB, Bit3ZeroPage); - - /* 0x80 – 0x8f */ - Map(0x80, BRA, Relative); Map(0x81, STA, XIndirect); - Map(0x82, RRF, ZeroPage); Map(0x83, BBS, Bit4AccumulatorRelative); - - Map(0x84, STY, ZeroPage); Map(0x85, STA, ZeroPage); - Map(0x86, STX, ZeroPage); Map(0x87, BBS, Bit4ZeroPageRelative); - - Map(0x88, DEY, Implied); - Map(0x8a, TXA, Implied); Map(0x8b, SEB, Bit4Accumulator); - - Map(0x8c, STY, Absolute); Map(0x8d, STA, Absolute); - Map(0x8e, STX, Absolute); Map(0x8f, SEB, Bit4ZeroPage); - - /* 0x90 – 0x9f */ - Map(0x90, BCC, Relative); Map(0x91, STA, IndirectY); - Map(0x93, BBC, Bit4AccumulatorRelative); - - Map(0x94, STY, ZeroPageX); Map(0x95, STA, ZeroPageX); - Map(0x96, STX, ZeroPageX); Map(0x97, BBC, Bit4ZeroPageRelative); - - Map(0x98, TYA, Implied); Map(0x99, STA, AbsoluteY); - Map(0x9a, TXS, AbsoluteY); Map(0x9b, CLB, Bit4Accumulator); - - Map(0x9d, ADC, AbsoluteX); - Map(0x9f, CLB, Bit4ZeroPage); - - /* 0xa0 – 0xaf */ - Map(0xa0, LDY, Immediate); Map(0xa1, LDA, XIndirect); - Map(0xa2, LDX, Immediate); Map(0xa3, BBS, Bit5AccumulatorRelative); - - Map(0xa4, LDY, ZeroPage); Map(0xa5, LDA, ZeroPage); - Map(0xa6, LDX, ZeroPage); Map(0xa7, BBS, Bit5ZeroPageRelative); - - Map(0xa8, TAY, Implied); Map(0xa9, LDA, Immediate); - Map(0xaa, TAX, Implied); Map(0xab, SEB, Bit5Accumulator); - - Map(0xac, LDY, Absolute); Map(0xad, LDA, Absolute); - Map(0xae, LDX, Absolute); Map(0xaf, SEB, Bit5ZeroPage); - - /* 0xb0 – 0xbf */ - Map(0xb0, BCS, Relative); Map(0xb1, STA, IndirectY); - Map(0xb2, JMP, ZeroPageIndirect); Map(0xb3, BBC, Bit5AccumulatorRelative); - - Map(0xb4, LDY, ZeroPageX); Map(0xb5, LDA, ZeroPageX); - Map(0xb6, LDX, ZeroPageY); Map(0xb7, BBC, Bit5ZeroPageRelative); - - Map(0xb8, CLV, Implied); Map(0xb9, LDA, AbsoluteY); - Map(0xba, TSX, AbsoluteY); Map(0xbb, CLB, Bit5Accumulator); - - Map(0xbc, LDY, AbsoluteX); Map(0xbd, LDA, AbsoluteX); - Map(0xbe, LDX, AbsoluteY); Map(0xbf, CLB, Bit5ZeroPage); - - /* 0xc0 – 0xcf */ - Map(0xc0, CPY, Immediate); Map(0xc1, CMP, XIndirect); - Map(0xc2, SLW, Implied); Map(0xc3, BBS, Bit6AccumulatorRelative); - - Map(0xc4, CPY, ZeroPage); Map(0xc5, CMP, ZeroPage); - Map(0xc6, DEC, ZeroPage); Map(0xc7, BBS, Bit6ZeroPageRelative); - - Map(0xc8, INY, Implied); Map(0xc9, CMP, Immediate); - Map(0xca, DEX, Implied); Map(0xcb, SEB, Bit6Accumulator); - - Map(0xcc, CPY, Absolute); Map(0xcd, CMP, Absolute); - Map(0xce, DEC, Absolute); Map(0xcf, SEB, Bit6ZeroPage); - - /* 0xd0 – 0xdf */ - Map(0xd0, BNE, Relative); Map(0xd1, CMP, IndirectY); - Map(0xd3, BBC, Bit6AccumulatorRelative); - - Map(0xd5, CMP, ZeroPageX); - Map(0xd6, DEC, ZeroPageX); Map(0xd7, BBC, Bit6ZeroPageRelative); - - Map(0xd8, CLD, Implied); Map(0xd9, CMP, AbsoluteY); - Map(0xdb, CLB, Bit6Accumulator); - - Map(0xdd, CMP, AbsoluteX); - Map(0xde, DEC, AbsoluteX); Map(0xdf, CLB, Bit6ZeroPage); - - /* 0xe0 – 0xef */ - Map(0xe0, CPX, Immediate); Map(0xe1, SBC, XIndirect); - Map(0xe2, FST, Implied); Map(0xe3, BBS, Bit7AccumulatorRelative); - - Map(0xe4, CPX, ZeroPage); Map(0xe5, SBC, ZeroPage); - Map(0xe6, INC, ZeroPage); Map(0xe7, BBS, Bit7ZeroPageRelative); - - Map(0xe8, INX, Implied); Map(0xe9, SBC, Immediate); - Map(0xea, NOP, Implied); Map(0xeb, SEB, Bit7Accumulator); - - Map(0xec, CPX, Absolute); Map(0xed, SBC, Absolute); - Map(0xee, INC, Absolute); Map(0xef, SEB, Bit7ZeroPage); - - /* 0xf0 – 0xff */ - Map(0xf0, BEQ, Relative); Map(0xf1, SBC, IndirectY); - Map(0xf3, BBC, Bit7AccumulatorRelative); - - Map(0xf5, SBC, ZeroPageX); - Map(0xf6, INC, ZeroPageX); Map(0xf7, BBC, Bit7ZeroPageRelative); - - Map(0xf8, SED, Implied); Map(0xf9, SBC, AbsoluteY); - Map(0xfb, CLB, Bit7Accumulator); - - Map(0xfd, SBC, AbsoluteX); - Map(0xfe, INC, AbsoluteX); Map(0xff, CLB, Bit7ZeroPage); - -#undef Map + // Determine the instruction in hand, and finish now if its undefined. + instr_ = instrucion_for_opcode(instruction); + if(instr_.operation == Operation::Invalid) { + consumed_ = 0; + return std::make_pair(1, instr_); } + // Obtain an operand size and roll onto the correct phase. operand_size_ = size(instr_.addressing_mode); phase_ = operand_size_ ? Phase::AwaitingOperand : Phase::ReadyToPost; operand_bytes_ = 0; @@ -266,6 +274,7 @@ std::pair Decoder::decode(const uint8_ return result; } + // Decoding didn't complete, without it being clear how many more bytes are required. return std::make_pair(0, Instruction()); } diff --git a/InstructionSets/M50740/Decoder.hpp b/InstructionSets/M50740/Decoder.hpp index cc10961b9..4f3f3d5b2 100644 --- a/InstructionSets/M50740/Decoder.hpp +++ b/InstructionSets/M50740/Decoder.hpp @@ -20,6 +20,7 @@ namespace M50740 { class Decoder { public: std::pair decode(const uint8_t *source, size_t length); + Instruction instrucion_for_opcode(uint8_t opcode); private: enum class Phase { diff --git a/InstructionSets/M50740/Executor.cpp b/InstructionSets/M50740/Executor.cpp index 52d4d612a..3c637bb62 100644 --- a/InstructionSets/M50740/Executor.cpp +++ b/InstructionSets/M50740/Executor.cpp @@ -10,12 +10,18 @@ using namespace InstructionSet::M50740; +Executor::Executor() { + // Cut down the list of all generated performers to those the processor actually uses, and install that + // for future referencing by action_for. + Decoder decoder; + for(size_t c = 0; c < 256; c++) { + const auto instruction = decoder.instrucion_for_opcode(uint8_t(c)); + performers_[c] = performer_lookup_.performer(instruction.operation, instruction.addressing_mode); + } +} + template void Executor::perform(uint8_t *operand [[maybe_unused]]) { } template void Executor::perform(Executor *) { } - -Action Executor::action_for(Instruction instruction) { - return Action(performer_lookup_.performer(instruction.operation, instruction.addressing_mode)); -} diff --git a/InstructionSets/M50740/Executor.hpp b/InstructionSets/M50740/Executor.hpp index 3ed004322..f547d6608 100644 --- a/InstructionSets/M50740/Executor.hpp +++ b/InstructionSets/M50740/Executor.hpp @@ -31,20 +31,23 @@ struct Action { class Executor: public CachingExecutor { public: + Executor(); private: + // MARK: - CachingExecutor-facing interface. + friend CachingExecutor; - Action action_for(Instruction); /*! - Performs @c operation using @c operand as the value fetched from memory, if any. + Maps instructions to performers; called by the CachingExecutor and for this instruction set, extremely trivial. */ - template static void perform(uint8_t *operand); + inline PerformerIndex action_for(Instruction instruction) { + // This is a super-simple processor, so the opcode can be used directly to index the performers. + return instruction.opcode; + } - /*! - Performs @c operation in @c addressing_mode. - */ - template static void perform(Executor *); + private: + // MARK: - Internal framework for generator performers. /*! Provides dynamic lookup of @c perform(Executor*). @@ -77,8 +80,20 @@ class Executor: public CachingExecutor { } } }; - inline static PerformerLookup performer_lookup_; + + /*! + Performs @c operation using @c operand as the value fetched from memory, if any. + */ + template static void perform(uint8_t *operand); + + /*! + Performs @c operation in @c addressing_mode. + */ + template static void perform(Executor *); + + private: + // MARK: - Instruction set state. uint8_t memory_[0x2000]; }; diff --git a/InstructionSets/M50740/Instruction.hpp b/InstructionSets/M50740/Instruction.hpp index 4b5eaaa52..a0c30629f 100644 --- a/InstructionSets/M50740/Instruction.hpp +++ b/InstructionSets/M50740/Instruction.hpp @@ -116,9 +116,10 @@ constexpr AccessType access_type(Operation operation) { struct Instruction { Operation operation = Operation::Invalid; AddressingMode addressing_mode = AddressingMode::Implied; + uint8_t opcode = 0; - Instruction(Operation operation, AddressingMode addressing_mode) : operation(operation), addressing_mode(addressing_mode) {} - Instruction(Operation operation) : operation(operation) {} + Instruction(Operation operation, AddressingMode addressing_mode, uint8_t opcode) : operation(operation), addressing_mode(addressing_mode), opcode(opcode) {} + Instruction(uint8_t opcode) : opcode(opcode) {} Instruction() {} }; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 4f2dc667e..03897e825 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -4405,8 +4405,8 @@ 4BEDA40925B2844B000C2DBD /* M50740 */ = { isa = PBXGroup; children = ( - 4BEDA42F25B3C700000C2DBD /* Executor.cpp */, 4BEDA40B25B2844B000C2DBD /* Decoder.cpp */, + 4BEDA42F25B3C700000C2DBD /* Executor.cpp */, 4BEDA40A25B2844B000C2DBD /* Decoder.hpp */, 4BEDA42E25B3C613000C2DBD /* Executor.hpp */, 4BEDA41725B2845D000C2DBD /* Instruction.hpp */,