From bef12f3d65afa5fef643fd2c4b5c8aee5d71d4f1 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 18 May 2022 15:35:38 -0400 Subject: [PATCH] Move `ExecutionState` into Implementation.hpp; use `goto` to avoid some double switches. Re: the latter, yuck. Yuck yuck yuck. But it does mean I can stop going back and forth on how to structure conditionality on effective address generation segueing into fetches without doubling up on tests. --- .../Implementation/68000Mk2Implementation.hpp | 83 ++++++++++++------- .../Implementation/68000Mk2Storage.hpp | 59 ++++++------- 2 files changed, 79 insertions(+), 63 deletions(-) diff --git a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp index cc7a9f863..d6c6eba57 100644 --- a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp +++ b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp @@ -15,6 +15,28 @@ namespace CPU { namespace MC68000Mk2 { +/// 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 ExecutionState: int { + Reset = std::numeric_limits::min(), + Decode, + WaitForDTACK, + FetchOperand, + StoreOperand, + + // Various forms of perform; each of these will + // perform the current instruction, then do the + // indicated bus cycle. + + Perform_np, + Perform_np_n, + + // MOVE has unique bus usage, so has a specialised state. + + MOVEWrite, +}; + // MARK: - The state machine. template @@ -34,21 +56,23 @@ void Processor. // // TODO: add MOVE special case, somewhere. - case State::FetchOperand: + BeginState(FetchOperand): // Check that this operand is meant to be fetched. if(!(operand_flags_ & (1 << next_operand_))) { state_ = perform_state_; @@ -214,8 +238,11 @@ void Processor> 3; \ - MoveToState(operand_flags_ & 0x0c ? State::StoreOperand : State::Decode) + if(operand_flags_ & 0x0c) MoveToState(StoreOperand) else MoveToState(Decode) - case State::Perform_np: + BeginState(Perform_np): InstructionSet::M68k::perform( instruction_, operand_[0], operand_[1], status_, *static_cast(this)); Prefetch(); // np + MoveToWritePhase(); - MoveToWritePhase(); - break; - - case State::Perform_np_n: + BeginState(Perform_np_n): InstructionSet::M68k::perform( instruction_, operand_[0], operand_[1], status_, *static_cast(this)); Prefetch(); // np IdleBus(1); // n - - MoveToWritePhase(); - break; + MoveToWritePhase(); #undef MoveToWritePhase + + // Various states TODO. + default: printf("Unhandled state: %d\n", state_); assert(false); @@ -296,11 +321,11 @@ void Processor + namespace CPU { namespace MC68000Mk2 { struct ProcessorBase: public InstructionSet::M68k::NullFlowController { - /// 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, - StoreOperand = -5, - - // 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, - Perform_np_n = -7, - - // MOVE has unique bus usage, so has a specialised state. - - MOVEWrite = -8, - }; - int state_ = State::Reset; + int state_ = std::numeric_limits::min(); /// Counts time left on the clock before the current batch of processing /// is complete; may be less than zero. @@ -137,14 +114,6 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController { // some of these may persist across multiple calls to run_for. Microcycle idle{0}; - // Read a data word. - Microcycle read_word_data_announce { - Microcycle::Read | Microcycle::NewAddress | Microcycle::IsData - }; - Microcycle read_word_data { - Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsData - }; - // Read a program word. All accesses via the program counter are word sized. Microcycle read_program_announce { Microcycle::Read | Microcycle::NewAddress | Microcycle::IsProgram @@ -153,6 +122,28 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController { Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsProgram }; + // Read a data word or byte. + Microcycle read_word_data_announce { + Microcycle::Read | Microcycle::NewAddress | Microcycle::IsData + }; + Microcycle read_word_data { + Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsData + }; + Microcycle read_byte_data { + Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectByte | Microcycle::IsData + }; + + // Write a data word or byte. + Microcycle write_word_data_announce { + Microcycle::NewAddress | Microcycle::IsData + }; + Microcycle write_word_data { + Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsData + }; + Microcycle write_byte_data { + Microcycle::SameAddress | Microcycle::SelectByte | Microcycle::IsData + }; + // Holding spot when awaiting DTACK/etc. Microcycle awaiting_dtack; };