diff --git a/InstructionSets/x86/Decoder.cpp b/InstructionSets/x86/Decoder.cpp index 45dd5ef71..d4c910903 100644 --- a/InstructionSets/x86/Decoder.cpp +++ b/InstructionSets/x86/Decoder.cpp @@ -14,10 +14,8 @@ using namespace InstructionSet::x86; -// Only 8086 is suppoted for now. -Decoder::Decoder(Model model) : model_(model) {} - -std::pair Decoder::decode(const uint8_t *source, size_t length) { +template +std::pair Decoder::decode(const uint8_t *source, size_t length) { const uint8_t *const end = source + length; // MARK: - Prefixes (if present) and the opcode. @@ -115,7 +113,7 @@ std::pair Decoder::decode(const uint8_t * // The 286 onwards have a further set of instructions // prefixed with $0f. case 0x0f: - if(model_ < Model::i80286) undefined(); + if constexpr (model < Model::i80286) undefined(); phase_ = Phase::InstructionPageF; break; @@ -163,35 +161,35 @@ std::pair Decoder::decode(const uint8_t * #undef RegisterBlock case 0x60: - if(model_ < Model::i80186) undefined(); + if constexpr (model < Model::i80186) undefined(); Complete(PUSHA, None, None, 2); break; case 0x61: - if(model_ < Model::i80186) undefined(); + if constexpr (model < Model::i80186) undefined(); Complete(POPA, None, None, 2); break; case 0x62: - if(model_ < Model::i80186) undefined(); + if constexpr (model < Model::i80186) undefined(); MemRegReg(BOUND, Reg_MemReg, 2); break; case 0x63: - if(model_ < Model::i80286) undefined(); + if constexpr (model < Model::i80286) undefined(); MemRegReg(ARPL, MemReg_Reg, 2); break; case 0x6c: // INSB - if(model_ < Model::i80186) undefined(); + if constexpr (model < Model::i80186) undefined(); Complete(INS, None, None, 1); break; case 0x6d: // INSW - if(model_ < Model::i80186) undefined(); + if constexpr (model < Model::i80186) undefined(); Complete(INS, None, None, 2); break; case 0x6e: // OUTSB - if(model_ < Model::i80186) undefined(); + if constexpr (model < Model::i80186) undefined(); Complete(OUTS, None, None, 1); break; case 0x6f: // OUTSW - if(model_ < Model::i80186) undefined(); + if constexpr (model < Model::i80186) undefined(); Complete(OUTS, None, None, 2); break; @@ -291,11 +289,11 @@ std::pair Decoder::decode(const uint8_t * case 0xc7: MemRegReg(MOV, MemRegMOV, 2); break; case 0xc8: - if(model_ < Model::i80186) undefined(); + if constexpr (model < Model::i80186) undefined(); Displacement16Operand8(ENTER); break; case 0xc9: - if(model_ < Model::i80186) undefined(); + if constexpr (model < Model::i80186) undefined(); Complete(LEAVE, None, None, 0); break; @@ -392,7 +390,7 @@ std::pair Decoder::decode(const uint8_t * case 0x02: MemRegReg(LAR, Reg_MemReg, 2); break; case 0x03: MemRegReg(LSL, Reg_MemReg, 2); break; case 0x05: - if(model_ != Model::i80286) undefined(); + if constexpr (model != Model::i80286) undefined(); Complete(LOADALL, None, None, 0); break; case 0x06: Complete(CLTS, None, None, 1); break; @@ -711,3 +709,9 @@ std::pair Decoder::decode(const uint8_t * // i.e. not done yet. return std::make_pair(0, Instruction()); } + +// Ensure all possible decoders are built. +template class InstructionSet::x86::Decoder; +template class InstructionSet::x86::Decoder; +template class InstructionSet::x86::Decoder; +template class InstructionSet::x86::Decoder; diff --git a/InstructionSets/x86/Decoder.hpp b/InstructionSets/x86/Decoder.hpp index e2c68a907..4213c4fd5 100644 --- a/InstructionSets/x86/Decoder.hpp +++ b/InstructionSets/x86/Decoder.hpp @@ -29,10 +29,8 @@ enum class Model { This is an experimental implementation; it has not yet undergone significant testing. */ -class Decoder { +template class Decoder { public: - Decoder(Model model); - /*! @returns an @c Instruction plus a size; a positive size to indicate successful decoding; a negative size specifies the [negatived] number of further bytes the caller should ideally @@ -43,8 +41,6 @@ class Decoder { std::pair decode(const uint8_t *source, size_t length); private: - const Model model_; - enum class Phase { /// Captures all prefixes and continues until an instruction byte is encountered. Instruction, diff --git a/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm b/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm index 51617d7b4..9c2fd60d2 100644 --- a/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm +++ b/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm @@ -105,7 +105,7 @@ namespace { - (void)decode:(const std::initializer_list &)stream { // Decode by offering up all data at once. - InstructionSet::x86::Decoder decoder(InstructionSet::x86::Model::i8086); + InstructionSet::x86::Decoder decoder; instructions.clear(); const uint8_t *byte = stream.begin(); while(byte != stream.end()) { @@ -117,7 +117,7 @@ namespace { // Grab a byte-at-a-time decoding and check that it matches the previous. { - InstructionSet::x86::Decoder decoder(InstructionSet::x86::Model::i8086); + InstructionSet::x86::Decoder decoder; auto previous_instruction = instructions.begin(); for(auto item: stream) {