diff --git a/Processors/68000Mk2/68000Mk2.hpp b/Processors/68000Mk2/68000Mk2.hpp index ccbe18378..847876ed5 100644 --- a/Processors/68000Mk2/68000Mk2.hpp +++ b/Processors/68000Mk2/68000Mk2.hpp @@ -372,6 +372,7 @@ template +#include namespace CPU { namespace MC68000Mk2 { @@ -145,6 +146,8 @@ void Processor(instruction_.operation); + // TODO: check for privilege and unrecognised instructions. - operand_ = 0; + // Obtain operand flags and pick a perform pattern. + setup_operation(); + + next_operand_ = 0; [[fallthrough]]; // Check the operand flags to determine whether the operand at index // operand_ needs to be fetched, and do so. case State::FetchOperand: + switch(instruction_.mode(next_operand_)) { + case Mode::None: + state_ = perform_state_; + continue; + + case Mode::AddressRegisterDirect: + case Mode::DataRegisterDirect: + operand_[next_operand_] = registers_[instruction_.lreg(next_operand_)]; + ++next_operand_; + state_ = next_operand_ == 2 ? perform_state_ : state_; + continue; + + default: + assert(false); + } [[fallthrough]]; default: + printf("Unhandled or unterminated state: %d\n", state_); assert(false); }} @@ -214,6 +234,25 @@ void Processor +void Processor::setup_operation() { + +#define BIND(x, p) \ + case InstructionSet::M68k::Operation::x: \ + operand_flags_ = InstructionSet::M68k::operand_flags(); \ + perform_state_ = State::p; \ + break; + + switch(instruction_.operation) { + BIND(NBCD, Perform_np); + + default: + assert(false); + } + +#undef BIND +} + template CPU::MC68000Mk2::State Processor::get_state() { return CPU::MC68000Mk2::State(); diff --git a/Processors/68000Mk2/Implementation/68000Mk2Storage.hpp b/Processors/68000Mk2/Implementation/68000Mk2Storage.hpp index 9fb92bb41..78583eec2 100644 --- a/Processors/68000Mk2/Implementation/68000Mk2Storage.hpp +++ b/Processors/68000Mk2/Implementation/68000Mk2Storage.hpp @@ -16,34 +16,76 @@ namespace CPU { namespace MC68000Mk2 { struct ProcessorBase { + /// States for the state machine which are named by + /// me for their purpose rather than automatically by file position. + /// These are negative to avoid ambiguity with the other group. enum State: int { Reset = -1, Decode = -2, WaitForDTACK = -3, FetchOperand = -4, + + // Various different effective address calculations. + + CalculateAnDn = -5, + + // Various forms of perform; each of these will + // perform the current instruction, then do the + // indicated bus cycle. + + Perform_np = -6, }; int state_ = State::Reset; + /// Counts time left on the clock before the current batch of processing + /// is complete; may be less than zero. HalfCycles time_remaining_; - int post_dtack_state_ = 0; + + /// Current supervisor state, for direct provision to the bus handler. int is_supervisor_ = 1; + // A decoder for instructions, plus all collected information about the + // current instruction. InstructionSet::M68k::Predecoder decoder_; InstructionSet::M68k::Preinstruction instruction_; uint16_t opcode_; uint8_t operand_flags_; + uint32_t instruction_address_; + // Register state. InstructionSet::M68k::Status status_; SlicedInt32 program_counter_; SlicedInt32 registers_[16]; // D0–D7 followed by A0–A7. SlicedInt32 stack_pointers_[2]; + /// Current state of the DTACK input. bool dtack_ = false; + /// Current state of the VPA input. bool vpa_ = false; + /// Current state of the BERR input. bool berr_ = false; + /// Contains the prefetch queue; the most-recently fetched thing is the + /// low portion of this word, and the thing fetched before that has + /// proceeded to the high portion. SlicedInt32 prefetch_; - int operand_ = 0; + + // Temporary storage for the current instruction's operands + // and the corresponding effective addresses. + CPU::SlicedInt32 operand_[2]; + uint32_t effective_address_[2]; + + /// If currently in the wait-for-DTACK state, this indicates where to go + /// upon receipt of DTACK or VPA. BERR will automatically segue + /// into the proper exception. + int post_dtack_state_ = 0; + + /// The perform state for this operation. + int perform_state_ = 0; + + /// When fetching or storing operands, this is the next one to fetch + /// or store. + int next_operand_ = 0; }; }