From 8c670d2105822671aaeb6b19122aa2856cb618f7 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 23 Oct 2022 11:46:47 -0400 Subject: [PATCH] Add decodes for TRAPcc and PACK, discovering it's three operand (sort of). --- InstructionSets/M68k/Decoder.cpp | 47 ++++++++++++++++++++++++---- InstructionSets/M68k/Instruction.hpp | 37 ++++++++++++++++++---- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/InstructionSets/M68k/Decoder.cpp b/InstructionSets/M68k/Decoder.cpp index aa20d8adc..0e1a431c8 100644 --- a/InstructionSets/M68k/Decoder.cpp +++ b/InstructionSets/M68k/Decoder.cpp @@ -340,17 +340,22 @@ template uint32_t Predecoder::invalid_operands() { case OpT(Operation::BFCHG): case OpT(Operation::BFCLR): case OpT(Operation::BFSET): case OpT(Operation::BFINS): return ~TwoOperandMask< - Imm, + Ext, Dn | Ind | d16An | d8AnXn | XXXw | XXXl >::value; case OpT(Operation::BFTST): case OpT(Operation::BFFFO): case OpT(Operation::BFEXTU): case OpT(Operation::BFEXTS): return ~TwoOperandMask< - Imm, + Ext, Dn | Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn >::value; + case OpT(Operation::PACK): + return ~OneOperandMask< + Imm + >::value; + case CMPIb: case CMPIl: case CMPIw: if constexpr (model == Model::M68000) { return ~TwoOperandMask< @@ -527,6 +532,7 @@ template Preinstruction Predecoder::validated op1_mode, op1_reg, op2_mode, op2_reg, requires_supervisor(operation), + requires_extension_word(operation), operand_size(operation), condition); } @@ -540,6 +546,7 @@ template Preinstruction Predecoder::validated op1_mode, op1_reg, op2_mode, op2_reg, requires_supervisor(operation), + requires_extension_word(operation), operand_size(operation), condition); } @@ -940,7 +947,7 @@ template Preinstruction Predecoder::decode(ui case OpT(Operation::BFEXTU): case OpT(Operation::BFEXTS): case OpT(Operation::BFCLR): case OpT(Operation::BFSET): case OpT(Operation::BFINS): return validated( - AddressingMode::ImmediateData, 0, + AddressingMode::ExtensionWord, 0, combined_mode(ea_mode, ea_register), ea_register); // @@ -973,6 +980,18 @@ template Preinstruction Predecoder::decode(ui return validated(addressing_mode, ea_register); } + // + // MARK: PACK + // + // b0–b2: a register number; + // b3: address/data register selection — if address registers, then this is predec; + // b9–b11: an additional register number. + // This instruction is also followed by a 16-bit adjustment extension. + // + case OpT(Operation::PACK): + // TODO; need to square the wheel on a prima-facie three operands. + return Preinstruction(); + // // MARK: DIVl // @@ -1291,12 +1310,23 @@ Preinstruction Predecoder::decode5(uint16_t instruction) { default: break; } + switch(instruction & 0x0ff) { + // 4-173 (p276) + case 0x0f8: case 0x0f9: Decode(Op::Scc); + + // 4-189 (p294) + case 0x0fa: case 0x0fb: case 0x0fc: + DecodeReq(model >= Model::M68020, Op::TRAPcc); + + default: break; + } + switch(instruction & 0x0f8) { // 4-173 (p276) case 0x0c0: case 0x0d0: case 0x0d8: case 0x0e0: case 0x0e8: - case 0x0f0: case 0x0f8: Decode(Op::Scc); + case 0x0f0: Decode(Op::Scc); // 4-91 (p195) case 0x0c8: Decode(Op::DBcc); @@ -1352,8 +1382,13 @@ template Preinstruction Predecoder::decode8(uint16_t instruction) { using Op = Operation; - // 4-171 (p275) - if((instruction & 0x1f0) == 0x100) Decode(Op::SBCD); + + switch(instruction & 0x1f0) { + case 0x100: Decode(Op::SBCD); // 4-171 (p275) + case 0x1f0: DecodeReq(model >= Model::M68020, Op::PACK); // 4-157 (p261) + + default: break; + } switch(instruction & 0x1c0) { case 0x0c0: Decode(Op::DIVUw); // 4-97 (p201) diff --git a/InstructionSets/M68k/Instruction.hpp b/InstructionSets/M68k/Instruction.hpp index a0a08abb5..e4448b714 100644 --- a/InstructionSets/M68k/Instruction.hpp +++ b/InstructionSets/M68k/Instruction.hpp @@ -168,6 +168,16 @@ constexpr bool requires_supervisor(Operation op) { } } +inline constexpr bool requires_extension_word(Operation op) { + switch(op) { + case Operation::PACK: + return true; + + default: + return false; + } +} + enum class DataSize { Byte = 0, Word = 1, @@ -356,13 +366,16 @@ class Preinstruction { } bool requires_supervisor() const { - return flags_ & 0x80; + return flags_ & Flags::IsSupervisor; + } + bool requires_extension_word() const { + return flags_ & Flags::RequiresExtensionWord; } DataSize operand_size() const { - return DataSize(flags_ & 0x03); + return DataSize((flags_ & Flags::SizeMask) >> Flags::SizeShift); } Condition condition() const { - return Condition((flags_ >> 2) & 0x0f); + return Condition((flags_ & Flags::ConditionMask) >> Flags::ConditionShift); } private: @@ -377,18 +390,30 @@ class Preinstruction { AddressingMode op1_mode, int op1_reg, AddressingMode op2_mode, int op2_reg, bool is_supervisor, + bool requires_extension_word, DataSize size, Condition condition) : operation(operation) { operands_[0] = uint8_t((uint8_t(op1_mode) << 3) | op1_reg); operands_[1] = uint8_t((uint8_t(op2_mode) << 3) | op2_reg); flags_ = uint8_t( - (is_supervisor ? 0x80 : 0x00) | - (int(condition) << 2) | - int(size) + (is_supervisor ? Flags::IsSupervisor : 0x00) | + (requires_extension_word ? Flags::RequiresExtensionWord : 0x00) | + (int(condition) << Flags::ConditionShift) | + (int(size) << Flags::SizeShift) ); } + struct Flags { + static constexpr uint8_t IsSupervisor = 0b1000'0000; + static constexpr uint8_t RequiresExtensionWord = 0b0100'0000; + static constexpr uint8_t ConditionMask = 0b0011'1100; + static constexpr uint8_t SizeMask = 0b0000'0011; + + static constexpr int ConditionShift = 2; + static constexpr int SizeShift = 0; + }; + Preinstruction() {} /// Produces a string description of this instruction; if @c opcode