From 002a8c061fad4cb1fb61c9e9fb9ee188cad17e32 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 13 May 2022 13:55:37 -0400 Subject: [PATCH] Trim the public interface of `Executor`. --- InstructionSets/M68k/Executor.hpp | 130 ++++--- .../Implementation/ExecutorImplementation.hpp | 359 +++++++++--------- 2 files changed, 253 insertions(+), 236 deletions(-) diff --git a/InstructionSets/M68k/Executor.hpp b/InstructionSets/M68k/Executor.hpp index 3519f2ba1..d0663ddef 100644 --- a/InstructionSets/M68k/Executor.hpp +++ b/InstructionSets/M68k/Executor.hpp @@ -59,7 +59,7 @@ struct BusHandler { /// Ties together the decoder, sequencer and performer to provide an executor for 680x0 instruction streams. /// As is standard for these executors, no bus- or cache-level fidelity to any real 680x0 is attempted. This is /// simply an executor of 680x0 code. -template class Executor: public NullFlowController { +template class Executor { public: Executor(BusHandler &); @@ -77,36 +77,8 @@ template class Executor: public NullFlowContr /// Sets the current input interrupt level. void set_interrupt_level(int); - // Flow control; Cf. Perform.hpp. - template void raise_exception(int); - - void did_update_status(); - - template void complete_bcc(bool matched_condition, IntT offset); - void complete_dbcc(bool matched_condition, bool overflowed, int16_t offset); - void bsr(uint32_t offset); - void jmp(uint32_t); - void jsr(uint32_t offset); - void rtr(); - void rts(); - void rte(); - void stop(); - void reset(); - - void link(Preinstruction instruction, uint32_t offset); - void unlink(uint32_t &address); - void pea(uint32_t address); - - void move_to_usp(uint32_t address); - void move_from_usp(uint32_t &address); - - template void movep(Preinstruction instruction, uint32_t source, uint32_t dest); - template void movem_toM(Preinstruction instruction, uint32_t source, uint32_t dest); - template void movem_toR(Preinstruction instruction, uint32_t source, uint32_t dest); - - void tas(Preinstruction instruction, uint32_t address); - - // TODO: ownership of this shouldn't be here. + // TODO: this will likely be shared in some capacity with the bus-accurate versions of the 680x0; + // therefore it will almost certainly be factored out in future. struct Registers { uint32_t data[8], address[7]; uint32_t user_stack_pointer; @@ -118,44 +90,80 @@ template class Executor: public NullFlowContr void set_state(const Registers &); private: - void run(int &); + /// Reset the processor, back to a state as if just externally reset. + void reset(); - BusHandler &bus_handler_; - Predecoder decoder_; + class State: public NullFlowController { + public: + State(BusHandler &handler) : bus_handler_(handler) {} - void reset_processor(); - struct EffectiveAddress { - CPU::SlicedInt32 value; - bool requires_fetch; - }; - EffectiveAddress calculate_effective_address(Preinstruction instruction, uint16_t opcode, int index); + void run(int &); - void read(DataSize size, uint32_t address, CPU::SlicedInt32 &value); - void write(DataSize size, uint32_t address, CPU::SlicedInt32 value); - template IntT read(uint32_t address, bool is_from_pc = false); - template void write(uint32_t address, IntT value); + void read(DataSize size, uint32_t address, CPU::SlicedInt32 &value); + void write(DataSize size, uint32_t address, CPU::SlicedInt32 value); + template IntT read(uint32_t address, bool is_from_pc = false); + template void write(uint32_t address, IntT value); - template IntT read_pc(); + template IntT read_pc(); - uint32_t index_8bitdisplacement(); + // Processor state. + Status status; + CPU::SlicedInt32 program_counter; + CPU::SlicedInt32 registers[16]; // D0–D7 followed by A0–A7. + CPU::SlicedInt32 stack_pointers[2]; + uint32_t instruction_address; + uint16_t instruction_opcode; + int active_stack_pointer = 0; - // Processor state. - Status status_; - CPU::SlicedInt32 program_counter_; - CPU::SlicedInt32 registers_[16]; // D0–D8, followed by A0–A8. - CPU::SlicedInt32 stack_pointers_[2]; - uint32_t instruction_address_; - uint16_t instruction_opcode_; - int active_stack_pointer_ = 0; + // Bus state. + int interrupt_input = 0; - // Bus state. - int interrupt_input_ = 0; + // A lookup table to ensure that A7 is adjusted by 2 rather than 1 in + // postincrement and predecrement mode. + static constexpr uint32_t byte_increments[] = { + 1, 1, 1, 1, 1, 1, 1, 2 + }; - // A lookup table to ensure that A7 is adjusted by 2 rather than 1 in - // postincrement and predecrement mode. - static constexpr uint32_t byte_increments[] = { - 1, 1, 1, 1, 1, 1, 1, 2 - }; + // Flow control; Cf. Perform.hpp. + template void raise_exception(int); + + void did_update_status(); + + template void complete_bcc(bool matched_condition, IntT offset); + void complete_dbcc(bool matched_condition, bool overflowed, int16_t offset); + void bsr(uint32_t offset); + void jmp(uint32_t); + void jsr(uint32_t offset); + void rtr(); + void rts(); + void rte(); + void stop(); + void reset(); + + void link(Preinstruction instruction, uint32_t offset); + void unlink(uint32_t &address); + void pea(uint32_t address); + + void move_to_usp(uint32_t address); + void move_from_usp(uint32_t &address); + + template void movep(Preinstruction instruction, uint32_t source, uint32_t dest); + template void movem_toM(Preinstruction instruction, uint32_t source, uint32_t dest); + template void movem_toR(Preinstruction instruction, uint32_t source, uint32_t dest); + + void tas(Preinstruction instruction, uint32_t address); + + private: + BusHandler &bus_handler_; + Predecoder decoder_; + + struct EffectiveAddress { + CPU::SlicedInt32 value; + bool requires_fetch; + }; + EffectiveAddress calculate_effective_address(Preinstruction instruction, uint16_t opcode, int index); + uint32_t index_8bitdisplacement(); + } state_; }; } diff --git a/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp b/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp index dddaf45e8..95dfd907b 100644 --- a/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp +++ b/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp @@ -17,33 +17,127 @@ namespace InstructionSet { namespace M68k { -#define An(x) registers_[8 + x] -#define Dn(x) registers_[x] +#define An(x) state_.registers[8 + x] +#define Dn(x) state_.registers[x] #define sp An(7) #define AccessException(code, address, vector) \ uint64_t(((vector) << 8) | uint64_t(code) | ((address) << 16)) +// MARK: - Executor itself. + template -Executor::Executor(BusHandler &handler) : bus_handler_(handler) { - reset_processor(); +Executor::Executor(BusHandler &handler) : state_(handler) { + reset(); } template -void Executor::reset_processor() { +void Executor::reset() { // Establish: supervisor state, all interrupts blocked. - status_.set_status(0b0010'0011'1000'0000); - did_update_status(); + state_.status.set_status(0b0010'0011'1000'0000); + state_.did_update_status(); // Seed stack pointer and program counter. - sp.l = read(0) & 0xffff'fffe; - program_counter_.l = read(4); + sp.l = state_.template read(0) & 0xffff'fffe; + state_.program_counter.l = state_.template read(4); } +template +void Executor::signal_bus_error(FunctionCode code, uint32_t address) { + throw AccessException(code, address, Exception::AccessFault); +} + +template +void Executor::set_interrupt_level(int level) { + state_.interrupt_input_ = level; +} + +template +void Executor::run_for_instructions(int count) { + while(count > 0) { + try { + state_.run(count); + } catch (uint64_t exception) { + // Unpack the exception; this is the converse of the AccessException macro. + const int vector_address = (exception >> 6) & 0xfc; + const uint16_t code = uint16_t(exception & 0xff); + const uint32_t faulting_address = uint32_t(exception >> 16); + + // Grab the status to store, then switch into supervisor mode. + const uint16_t status = state_.status.status(); + state_.status.is_supervisor = true; + state_.status.trace_flag = 0; + state_.did_update_status(); + + // Push status and the program counter at instruction start. + state_.template write(sp.l - 14, code); + state_.template write(sp.l - 12, faulting_address); + state_.template write(sp.l - 8, state_.instruction_opcode); + state_.template write(sp.l - 6, status); + state_.template write(sp.l - 4, state_.instruction_address); + sp.l -= 14; + + // Fetch the new program counter; reset on a double fault. + try { + state_.program_counter.l = state_.template read(vector_address); + } catch (uint64_t) { + // TODO: I think this is incorrect, but need to verify consistency + // across different 680x0s. + reset(); + } + } + } +} + +template +typename Executor::Registers Executor::get_state() { + Registers result; + + for(int c = 0; c < 8; c++) { + result.data[c] = Dn(c).l; + } + for(int c = 0; c < 7; c++) { + result.address[c] = An(c).l; + } + result.status = state_.status.status(); + result.program_counter = state_.program_counter.l; + + state_.stack_pointers[state_.active_stack_pointer] = sp; + result.user_stack_pointer = state_.stack_pointers[0].l; + result.supervisor_stack_pointer = state_.stack_pointers[1].l; + + return result; +} + +template +void Executor::set_state(const Registers &state) { + for(int c = 0; c < 8; c++) { + Dn(c).l = state.data[c]; + } + for(int c = 0; c < 7; c++) { + An(c).l = state.address[c]; + } + state_.status.set_status(state.status); + state_.did_update_status(); + state_.program_counter.l = state.program_counter; + + state_.stack_pointers[0].l = state.user_stack_pointer; + state_.stack_pointers[1].l = state.supervisor_stack_pointer; + sp = state_.stack_pointers[state_.active_stack_pointer]; +} + +#undef Dn +#undef An + +// MARK: - State. + +#define An(x) registers[8 + x] +#define Dn(x) registers[x] + template template -IntT Executor::read(uint32_t address, bool is_from_pc) { - const auto code = FunctionCode((active_stack_pointer_ << 2) | 1 << int(is_from_pc)); +IntT Executor::State::read(uint32_t address, bool is_from_pc) { + const auto code = FunctionCode((active_stack_pointer << 2) | 1 << int(is_from_pc)); if(model == Model::M68000 && sizeof(IntT) > 1 && address & 1) { throw AccessException(code, address, Exception::AddressError | (int(is_from_pc) << 3) | (1 << 4)); } @@ -53,8 +147,8 @@ IntT Executor::read(uint32_t address, bool is_from_pc) { template template -void Executor::write(uint32_t address, IntT value) { - const auto code = FunctionCode((active_stack_pointer_ << 2) | 1); +void Executor::State::write(uint32_t address, IntT value) { + const auto code = FunctionCode((active_stack_pointer << 2) | 1); if(model == Model::M68000 && sizeof(IntT) > 1 && address & 1) { throw AccessException(code, address, Exception::AddressError); } @@ -63,7 +157,7 @@ void Executor::write(uint32_t address, IntT value) { } template -void Executor::read(DataSize size, uint32_t address, CPU::SlicedInt32 &value) { +void Executor::State::read(DataSize size, uint32_t address, CPU::SlicedInt32 &value) { switch(size) { case DataSize::Byte: value.b = read(address); break; case DataSize::Word: value.w = read(address); break; @@ -72,7 +166,7 @@ void Executor::read(DataSize size, uint32_t address, CPU::Sli } template -void Executor::write(DataSize size, uint32_t address, CPU::SlicedInt32 value) { +void Executor::State::write(DataSize size, uint32_t address, CPU::SlicedInt32 value) { switch(size) { case DataSize::Byte: write(address, value.b); break; case DataSize::Word: write(address, value.w); break; @@ -81,32 +175,33 @@ void Executor::write(DataSize size, uint32_t address, CPU::Sl } template -template IntT Executor::read_pc() { - const IntT result = read(program_counter_.l, true); +template IntT Executor::State::read_pc() { + const IntT result = read(program_counter.l, true); if constexpr (sizeof(IntT) == 4) { - program_counter_.l += 4; + program_counter.l += 4; } else { - program_counter_.l += 2; + program_counter.l += 2; } return result; } template -uint32_t Executor::index_8bitdisplacement() { +uint32_t Executor::State::index_8bitdisplacement() { // TODO: if not a 68000, check bit 8 for whether this should be a full extension word; // also include the scale field even if not. const auto extension = read_pc(); const auto offset = int8_t(extension); const int register_index = (extension >> 12) & 7; - const uint32_t displacement = registers_[register_index + ((extension >> 12) & 0x08)].l; + const uint32_t displacement = registers[register_index + ((extension >> 12) & 0x08)].l; const uint32_t sized_displacement = (extension & 0x800) ? displacement : int16_t(displacement); return offset + sized_displacement; } template -typename Executor::EffectiveAddress Executor::calculate_effective_address(Preinstruction instruction, uint16_t opcode, int index) { +typename Executor::State::EffectiveAddress +Executor::State::calculate_effective_address(Preinstruction instruction, uint16_t opcode, int index) { EffectiveAddress ea; switch(instruction.mode(index)) { @@ -120,7 +215,7 @@ typename Executor::EffectiveAddress Executor::EffectiveAddress Executor()); + ea.value.l = program_counter.l + int16_t(read_pc()); ea.requires_fetch = true; break; case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - ea.value.l = program_counter_.l + index_8bitdisplacement(); + ea.value.l = program_counter.l + index_8bitdisplacement(); ea.requires_fetch = true; break; @@ -214,77 +309,30 @@ typename Executor::EffectiveAddress Executor -void Executor::signal_bus_error(FunctionCode code, uint32_t address) { - throw AccessException(code, address, Exception::AccessFault); -} - -template -void Executor::set_interrupt_level(int level) { - interrupt_input_ = level; -} - -template -void Executor::run_for_instructions(int count) { - while(count > 0) { - try { - run(count); - } catch (uint64_t exception) { - // Unpack the exception; this is the converse of the AccessException macro. - const int vector_address = (exception >> 6) & 0xfc; - const uint16_t code = uint16_t(exception & 0xff); - const uint32_t faulting_address = uint32_t(exception >> 16); - - // Grab the status to store, then switch into supervisor mode. - const uint16_t status = status_.status(); - status_.is_supervisor = true; - status_.trace_flag = 0; - did_update_status(); - - // Push status and the program counter at instruction start. - write(sp.l - 14, code); - write(sp.l - 12, faulting_address); - write(sp.l - 8, instruction_opcode_); - write(sp.l - 6, status); - write(sp.l - 4, instruction_address_); - sp.l -= 14; - - // Fetch the new program counter; reset on a double fault. - try { - program_counter_.l = read(vector_address); - } catch (uint64_t) { - // TODO: I think this is incorrect, but need to verify consistency - // across different 680x0s. - reset_processor(); - } - } - } -} - -template -void Executor::run(int &count) { +void Executor::State::run(int &count) { while(count--) { // Check for a new interrupt. - if(interrupt_input_ > status_.interrupt_level) { - const int vector = bus_handler_.acknowlege_interrupt(interrupt_input_); + if(interrupt_input > status.interrupt_level) { + const int vector = bus_handler_.acknowlege_interrupt(interrupt_input); if(vector >= 0) { raise_exception(vector); } else { - raise_exception(Exception::InterruptAutovectorBase - 1 + interrupt_input_); + raise_exception(Exception::InterruptAutovectorBase - 1 + interrupt_input); } - status_.interrupt_level = interrupt_input_; + status.interrupt_level = interrupt_input; } // Read the next instruction. - instruction_address_ = program_counter_.l; - instruction_opcode_ = read_pc(); - const Preinstruction instruction = decoder_.decode(instruction_opcode_); + instruction_address = program_counter.l; + instruction_opcode = read_pc(); + const Preinstruction instruction = decoder_.decode(instruction_opcode); - if(instruction.requires_supervisor() && !status_.is_supervisor) { + if(instruction.requires_supervisor() && !status.is_supervisor) { raise_exception(Exception::PrivilegeViolation); continue; } if(instruction.operation == Operation::Undefined) { - switch(instruction_opcode_ & 0xf000) { + switch(instruction_opcode & 0xf000) { default: raise_exception(Exception::IllegalInstruction); continue; @@ -299,7 +347,7 @@ void Executor::run(int &count) { // Capture the trace bit, indicating whether to trace // after this instruction. - const auto should_trace = status_.trace_flag; + const auto should_trace = status.trace_flag; // Temporary storage. CPU::SlicedInt32 operand_[2]; @@ -309,8 +357,8 @@ void Executor::run(int &count) { // operands by default both: (i) because they might be values, // rather than addresses; and (ii) then they'll be there for use // by LEA and PEA. - effective_address_[0] = calculate_effective_address(instruction, instruction_opcode_, 0); - effective_address_[1] = calculate_effective_address(instruction, instruction_opcode_, 1); + effective_address_[0] = calculate_effective_address(instruction, instruction_opcode, 0); + effective_address_[1] = calculate_effective_address(instruction, instruction_opcode, 1); operand_[0] = effective_address_[0].value; operand_[1] = effective_address_[1].value; @@ -327,11 +375,11 @@ void Executor::run(int &count) { #undef fetch_operand - perform(instruction, operand_[0], operand_[1], status_, *this); + perform(instruction, operand_[0], operand_[1], status, *this); #define store_operand(n) \ if(!effective_address_[n].requires_fetch) { \ - registers_[instruction.lreg(n)] = operand_[n]; \ + registers[instruction.lreg(n)] = operand_[n]; \ } else { \ write(instruction.operand_size(), effective_address_[n].value.l, operand_[n]); \ } @@ -348,119 +396,80 @@ void Executor::run(int &count) { } } -// MARK: - State - -template -typename Executor::Registers Executor::get_state() { - Registers result; - - for(int c = 0; c < 8; c++) { - result.data[c] = Dn(c).l; - } - for(int c = 0; c < 7; c++) { - result.address[c] = An(c).l; - } - result.status = status_.status(); - result.program_counter = program_counter_.l; - - stack_pointers_[active_stack_pointer_] = sp; - result.user_stack_pointer = stack_pointers_[0].l; - result.supervisor_stack_pointer = stack_pointers_[1].l; - - return result; -} - -template -void Executor::set_state(const Registers &state) { - for(int c = 0; c < 8; c++) { - Dn(c).l = state.data[c]; - } - for(int c = 0; c < 7; c++) { - An(c).l = state.address[c]; - } - status_.set_status(state.status); - did_update_status(); - program_counter_.l = state.program_counter; - - stack_pointers_[0].l = state.user_stack_pointer; - stack_pointers_[1].l = state.supervisor_stack_pointer; - sp = stack_pointers_[active_stack_pointer_]; -} - // MARK: - Flow Control. template template -void Executor::raise_exception(int index) { +void Executor::State::raise_exception(int index) { const uint32_t address = index << 2; // Grab the status to store, then switch into supervisor mode // and disable tracing. - const uint16_t status = status_.status(); - status_.is_supervisor = true; - status_.trace_flag = 0; + const uint16_t previous_status = status.status(); + status.is_supervisor = true; + status.trace_flag = 0; did_update_status(); // Push status and the program counter at instruction start. - write(sp.l - 4, use_current_instruction_pc ? instruction_address_ : program_counter_.l); - write(sp.l - 6, status); + write(sp.l - 4, use_current_instruction_pc ? instruction_address : program_counter.l); + write(sp.l - 6, previous_status); sp.l -= 6; // Fetch the new program counter. - program_counter_.l = read(address); + program_counter.l = read(address); } template -void Executor::did_update_status() { +void Executor::State::did_update_status() { // Shuffle the stack pointers. - stack_pointers_[active_stack_pointer_] = sp; - sp = stack_pointers_[int(status_.is_supervisor)]; - active_stack_pointer_ = int(status_.is_supervisor); + stack_pointers[active_stack_pointer] = sp; + sp = stack_pointers[int(status.is_supervisor)]; + active_stack_pointer = int(status.is_supervisor); } template -void Executor::stop() {} +void Executor::State::stop() {} template -void Executor::reset() { +void Executor::State::reset() { bus_handler_.reset(); } template -void Executor::jmp(uint32_t address) { - program_counter_.l = address; +void Executor::State::jmp(uint32_t address) { + program_counter.l = address; } template -template void Executor::complete_bcc(bool branch, IntT offset) { +template void Executor::State::complete_bcc(bool branch, IntT offset) { if(branch) { - program_counter_.l = instruction_address_ + offset + 2; + program_counter.l = instruction_address + offset + 2; } } template -void Executor::complete_dbcc(bool matched_condition, bool overflowed, int16_t offset) { +void Executor::State::complete_dbcc(bool matched_condition, bool overflowed, int16_t offset) { if(!matched_condition && !overflowed) { - program_counter_.l = instruction_address_ + offset + 2; + program_counter.l = instruction_address + offset + 2; } } template -void Executor::bsr(uint32_t offset) { +void Executor::State::bsr(uint32_t offset) { sp.l -= 4; - write(sp.l, program_counter_.l); - program_counter_.l = instruction_address_ + offset; + write(sp.l, program_counter.l); + program_counter.l = instruction_address + offset; } template -void Executor::jsr(uint32_t address) { +void Executor::State::jsr(uint32_t address) { sp.l -= 4; - write(sp.l, program_counter_.l); - program_counter_.l = address; + write(sp.l, program_counter.l); + program_counter.l = address; } template -void Executor::link(Preinstruction instruction, uint32_t offset) { +void Executor::State::link(Preinstruction instruction, uint32_t offset) { const auto reg = 8 + instruction.reg<0>(); sp.l -= 4; @@ -470,40 +479,40 @@ void Executor::link(Preinstruction instruction, uint32_t offs } template -void Executor::unlink(uint32_t &address) { +void Executor::State::unlink(uint32_t &address) { sp.l = address; address = read(sp.l); sp.l += 4; } template -void Executor::pea(uint32_t address) { +void Executor::State::pea(uint32_t address) { sp.l -= 4; write(sp.l, address); } template -void Executor::rtr() { - status_.set_ccr(read(sp.l)); +void Executor::State::rtr() { + status.set_ccr(read(sp.l)); sp.l += 2; rts(); } template -void Executor::rte() { - status_.set_status(read(sp.l)); +void Executor::State::rte() { + status.set_status(read(sp.l)); sp.l += 2; rts(); } template -void Executor::rts() { - program_counter_.l = read(sp.l); +void Executor::State::rts() { + program_counter.l = read(sp.l); sp.l += 4; } template -void Executor::tas(Preinstruction instruction, uint32_t address) { +void Executor::State::tas(Preinstruction instruction, uint32_t address) { uint8_t value; if(instruction.mode<0>() != AddressingMode::DataRegisterDirect) { value = read(address); @@ -513,24 +522,24 @@ void Executor::tas(Preinstruction instruction, uint32_t addre Dn(instruction.reg<0>()).b = uint8_t(address | 0x80); } - status_.overflow_flag = status_.carry_flag = 0; - status_.zero_result = value; - status_.negative_flag = value & 0x80; + status.overflow_flag = status.carry_flag = 0; + status.zero_result = value; + status.negative_flag = value & 0x80; } template -void Executor::move_to_usp(uint32_t address) { - stack_pointers_[0].l = address; +void Executor::State::move_to_usp(uint32_t address) { + stack_pointers[0].l = address; } template -void Executor::move_from_usp(uint32_t &address) { - address = stack_pointers_[0].l; +void Executor::State::move_from_usp(uint32_t &address) { + address = stack_pointers[0].l; } template template -void Executor::movep(Preinstruction instruction, uint32_t source, uint32_t dest) { +void Executor::State::movep(Preinstruction instruction, uint32_t source, uint32_t dest) { if(instruction.mode<0>() == AddressingMode::DataRegisterDirect) { // Move register to memory. const uint32_t reg = source; @@ -572,7 +581,7 @@ void Executor::movep(Preinstruction instruction, uint32_t sou template template -void Executor::movem_toM(Preinstruction instruction, uint32_t source, uint32_t dest) { +void Executor::State::movem_toM(Preinstruction instruction, uint32_t source, uint32_t dest) { // Move registers to memory. This is the only permitted use of the predecrement mode, // which reverses output order. @@ -596,7 +605,7 @@ void Executor::movem_toM(Preinstruction instruction, uint32_t while(source) { if(source & 1) { address -= sizeof(IntT); - write(address, IntT(registers_[index].l)); + write(address, IntT(registers[index].l)); } --index; source >>= 1; @@ -609,7 +618,7 @@ void Executor::movem_toM(Preinstruction instruction, uint32_t int index = 0; while(source) { if(source & 1) { - write(dest, IntT(registers_[index].l)); + write(dest, IntT(registers[index].l)); dest += sizeof(IntT); } ++index; @@ -619,7 +628,7 @@ void Executor::movem_toM(Preinstruction instruction, uint32_t template template -void Executor::movem_toR(Preinstruction instruction, uint32_t source, uint32_t dest) { +void Executor::State::movem_toR(Preinstruction instruction, uint32_t source, uint32_t dest) { // Move memory to registers. // // A 68000 convention has been broken here; the instruction form is: @@ -631,9 +640,9 @@ void Executor::movem_toR(Preinstruction instruction, uint32_t while(source) { if(source & 1) { if constexpr (sizeof(IntT) == 2) { - registers_[index].l = int16_t(read(dest)); + registers[index].l = int16_t(read(dest)); } else { - registers_[index].l = read(dest); + registers[index].l = read(dest); } dest += sizeof(IntT); }