diff --git a/InstructionSets/M68k/Instruction.hpp b/InstructionSets/M68k/Instruction.hpp index ce211dbec..314729f8d 100644 --- a/InstructionSets/M68k/Instruction.hpp +++ b/InstructionSets/M68k/Instruction.hpp @@ -104,9 +104,9 @@ enum class Operation: uint8_t { Max = RESET }; -template -constexpr bool requires_supervisor(Operation r_op = Operation::Undefined) { - switch(t_op != Operation::Undefined ? t_op : r_op) { +template +constexpr bool requires_supervisor(Operation op) { + switch(op) { case Operation::MOVEfromSR: if constexpr (model == Model::M68000) { return false; diff --git a/InstructionSets/M68k/Status.hpp b/InstructionSets/M68k/Status.hpp index d43a6dbd4..7fe42b5f1 100644 --- a/InstructionSets/M68k/Status.hpp +++ b/InstructionSets/M68k/Status.hpp @@ -95,6 +95,23 @@ struct Status { return is_supervisor; } + /// Adjusts the status for exception processing — sets supervisor mode, disables trace, + /// and if @c new_interrupt_level is greater than or equal to 0 sets that as the new + /// interrupt level. + /// + /// @returns The status prior to those changes. + uint16_t begin_exception(int new_interrupt_level = -1) { + const uint16_t initial_status = status(); + + if(new_interrupt_level >= 0) { + interrupt_level = new_interrupt_level; + } + is_supervisor = true; + trace_flag = 0; + + return initial_status; + } + /// Evaluates @c condition. bool evaluate_condition(Condition condition) { switch(condition) { diff --git a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp index f99d9f7b8..5e67d9417 100644 --- a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp +++ b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp @@ -91,12 +91,16 @@ enum ExecutionState: int { CalcAddressRegisterIndirectWithPostincrement, // - CalcAddressRegisterIndirectWithPredecrement, // - CalcAddressRegisterIndirectWithDisplacement, // np - CalcAddressRegisterIndirectWithIndex8bitDisplacement, // n np n + CalcAddressRegisterIndirectWithIndex8bitDisplacement, // np n CalcProgramCounterIndirectWithDisplacement, // np - CalcProgramCounterIndirectWithIndex8bitDisplacement, // n np n + CalcProgramCounterIndirectWithIndex8bitDisplacement, // np n CalcAbsoluteShort, // np CalcAbsoluteLong, // np np + CalcEffectiveAddressIdleFor8bitDisplacement, // As per CalcEffectiveAddress unless one of the + // 8-bit displacement modes is in use, in which case + // an extra idle bus state is prefixed. + // Various forms of perform; each of these will // perform the current instruction, then do the // indicated bus cycle. @@ -355,9 +359,7 @@ void Processor()) { \ - if(!status_.is_supervisor) { \ - RaiseException(InstructionSet::M68k::Exception::PrivilegeViolation); \ - } \ +#define CheckSupervisor(x) \ + if constexpr (InstructionSet::M68k::requires_supervisor(InstructionSet::M68k::Operation::x)) { \ + if(!status_.is_supervisor) { \ + RaiseException(InstructionSet::M68k::Exception::PrivilegeViolation); \ + } \ } #define CASE(x) \ @@ -638,11 +631,13 @@ void Processor() == \ - InstructionSet::M68k::operand_flags() && \ - InstructionSet::M68k::operand_size() == \ - InstructionSet::M68k::operand_size() \ - ); \ + InstructionSet::M68k::operand_flags() == \ + InstructionSet::M68k::operand_flags() && \ + InstructionSet::M68k::operand_size() == \ + InstructionSet::M68k::operand_size() && \ + InstructionSet::M68k::requires_supervisor(InstructionSet::M68k::Operation::x) == \ + InstructionSet::M68k::requires_supervisor(InstructionSet::M68k::Operation::y) \ + ); \ [[fallthrough]]; #define SpecialCASE(x) case InstructionSet::M68k::Operation::x: CheckSupervisor(x); MoveToStateSpecific(x) @@ -934,11 +929,11 @@ void Processor