diff --git a/InstructionSets/M68k/Decoder.cpp b/InstructionSets/M68k/Decoder.cpp index 414b9768d..49b190846 100644 --- a/InstructionSets/M68k/Decoder.cpp +++ b/InstructionSets/M68k/Decoder.cpp @@ -479,7 +479,8 @@ template uint32_t Predecoder::invalid_operands() { template template Preinstruction Predecoder::validated( AddressingMode op1_mode, int op1_reg, - AddressingMode op2_mode, int op2_reg + AddressingMode op2_mode, int op2_reg, + Condition condition ) { constexpr auto operation = Predecoder::operation(op); @@ -489,7 +490,8 @@ template Preinstruction Predecoder::validated op1_mode, op1_reg, op2_mode, op2_reg, requires_supervisor(operation), - size(operation)); + size(operation), + condition); } const auto invalid = invalid_operands(); @@ -501,7 +503,8 @@ template Preinstruction Predecoder::validated op1_mode, op1_reg, op2_mode, op2_reg, requires_supervisor(operation), - size(operation)); + size(operation), + condition); } /// Decodes the fields within an instruction and constructs a `Preinstruction`, given that the operation has already been @@ -601,18 +604,29 @@ template Preinstruction Predecoder::decode(ui combined_mode(ea_mode, ea_register), ea_register); // - // MARK: STOP, ANDItoCCR, ANDItoSR, EORItoCCR, EORItoSR, ORItoCCR, ORItoSR, Bccl, Bccw, BSRl, BSRw + // MARK: STOP, ANDItoCCR, ANDItoSR, EORItoCCR, EORItoSR, ORItoCCR, ORItoSR, BSRl, BSRw // - // Operand is an immedate; destination/source (if any) is implied by the operation. + // Operand is an immedate; destination/source (if any) is implied by the operation, + // e.g. ORItoSR has a destination of SR. // case OpT(Operation::STOP): - case OpT(Operation::Bccl): case OpT(Operation::Bccw): case OpT(Operation::BSRl): case OpT(Operation::BSRw): case OpT(Operation::ORItoSR): case OpT(Operation::ORItoCCR): case OpT(Operation::ANDItoSR): case OpT(Operation::ANDItoCCR): case OpT(Operation::EORItoSR): case OpT(Operation::EORItoCCR): return validated(AddressingMode::ImmediateData); + // + // MARK: Bccl, Bccw + // + // Operand is an immedate; b8–b11 are a condition code. + // + case OpT(Operation::Bccl): case OpT(Operation::Bccw): + return validated( + AddressingMode::ImmediateData, 0, + AddressingMode::None, 0, + Condition((instruction >> 8) & 0xf)); + // // MARK: CHK // @@ -724,9 +738,20 @@ template Preinstruction Predecoder::decode(ui case OpT(Operation::PEA): case OpT(Operation::TAS): case OpT(Operation::TSTb): case OpT(Operation::TSTw): case OpT(Operation::TSTl): - case OpT(Operation::Scc): return validated(combined_mode(ea_mode, ea_register), ea_register); + // + // MARK: Scc + // + // b0–b2 and b3–b5: effective address; + // b8–b11: a condition. + // + case OpT(Operation::Scc): + return validated( + combined_mode(ea_mode, ea_register), ea_register, + AddressingMode::None, 0, + Condition((instruction >> 8) & 0xf)); + // // MARK: UNLINK, MOVEtoUSP, MOVEfromUSP // @@ -739,13 +764,15 @@ template Preinstruction Predecoder::decode(ui // // MARK: DBcc // - // b0–b2: a data register. + // b0–b2: a data register; + // b8–b11: a condition. // Followed by an immediate value. // case OpT(Operation::DBcc): return validated( AddressingMode::DataRegisterDirect, ea_register, - AddressingMode::ImmediateData, 0); + AddressingMode::ImmediateData, 0, + Condition((instruction >> 8) & 0xf)); // // MARK: SWAP, EXTbtow, EXTwtol diff --git a/InstructionSets/M68k/Decoder.hpp b/InstructionSets/M68k/Decoder.hpp index 14903755d..59bae5cce 100644 --- a/InstructionSets/M68k/Decoder.hpp +++ b/InstructionSets/M68k/Decoder.hpp @@ -56,7 +56,8 @@ template class Predecoder { template Preinstruction decode(uint16_t instruction); template Preinstruction validated( AddressingMode op1_mode = AddressingMode::None, int op1_reg = 0, - AddressingMode op2_mode = AddressingMode::None, int op2_reg = 0 + AddressingMode op2_mode = AddressingMode::None, int op2_reg = 0, + Condition condition = Condition::True ); template uint32_t invalid_operands(); diff --git a/InstructionSets/M68k/Instruction.hpp b/InstructionSets/M68k/Instruction.hpp index 3ae2e7006..252fb5e77 100644 --- a/InstructionSets/M68k/Instruction.hpp +++ b/InstructionSets/M68k/Instruction.hpp @@ -252,6 +252,17 @@ constexpr uint32_t quick(Operation op, uint16_t instruction) { } } +enum class Condition { + True = 0x00, False = 0x01, + High = 0x02, LowOrSame = 0x03, + CarryClear = 0x04, CarrySet = 0x05, + NotEqual = 0x06, Equal = 0x07, + OverflowClear = 0x08, OverflowSet = 0x09, + Positive = 0x0a, Negative = 0x0b, + GreaterThanOrEqual = 0x0c, LessThan = 0x0d, + GreaterThan = 0x0e, LessThanOrEqual = 0x0f, +}; + /// Indicates the addressing mode applicable to an operand. /// /// Implementation notes: @@ -363,7 +374,10 @@ class Preinstruction { return flags_ & 0x80; } DataSize size() { - return DataSize(flags_ & 0x7f); + return DataSize(flags_ & 0x03); + } + Condition condition() { + return Condition((flags_ >> 2) & 0x0f); } private: @@ -376,11 +390,16 @@ class Preinstruction { AddressingMode op1_mode, int op1_reg, AddressingMode op2_mode, int op2_reg, bool is_supervisor, - DataSize size) : operation(operation) + DataSize size, + Condition condition) : operation(operation) { operands_[0] = uint8_t(op1_mode) | uint8_t(op1_reg << 5); operands_[1] = uint8_t(op2_mode) | uint8_t(op2_reg << 5); - flags_ = (is_supervisor ? 0x80 : 0x00) | uint8_t(size); + flags_ = uint8_t( + (is_supervisor ? 0x80 : 0x00) | + (int(condition) << 2) | + int(size) + ); } Preinstruction() {}