1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-29 16:55:59 +00:00

Switch Decoder into a template.

This commit is contained in:
Thomas Harte 2022-02-21 12:21:57 -05:00
parent 9e9e160c43
commit 1934c7faa2
3 changed files with 23 additions and 23 deletions

View File

@ -14,10 +14,8 @@
using namespace InstructionSet::x86; using namespace InstructionSet::x86;
// Only 8086 is suppoted for now. template <Model model>
Decoder::Decoder(Model model) : model_(model) {} std::pair<int, InstructionSet::x86::Instruction> Decoder<model>::decode(const uint8_t *source, size_t length) {
std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *source, size_t length) {
const uint8_t *const end = source + length; const uint8_t *const end = source + length;
// MARK: - Prefixes (if present) and the opcode. // MARK: - Prefixes (if present) and the opcode.
@ -115,7 +113,7 @@ std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *
// The 286 onwards have a further set of instructions // The 286 onwards have a further set of instructions
// prefixed with $0f. // prefixed with $0f.
case 0x0f: case 0x0f:
if(model_ < Model::i80286) undefined(); if constexpr (model < Model::i80286) undefined();
phase_ = Phase::InstructionPageF; phase_ = Phase::InstructionPageF;
break; break;
@ -163,35 +161,35 @@ std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *
#undef RegisterBlock #undef RegisterBlock
case 0x60: case 0x60:
if(model_ < Model::i80186) undefined(); if constexpr (model < Model::i80186) undefined();
Complete(PUSHA, None, None, 2); Complete(PUSHA, None, None, 2);
break; break;
case 0x61: case 0x61:
if(model_ < Model::i80186) undefined(); if constexpr (model < Model::i80186) undefined();
Complete(POPA, None, None, 2); Complete(POPA, None, None, 2);
break; break;
case 0x62: case 0x62:
if(model_ < Model::i80186) undefined(); if constexpr (model < Model::i80186) undefined();
MemRegReg(BOUND, Reg_MemReg, 2); MemRegReg(BOUND, Reg_MemReg, 2);
break; break;
case 0x63: case 0x63:
if(model_ < Model::i80286) undefined(); if constexpr (model < Model::i80286) undefined();
MemRegReg(ARPL, MemReg_Reg, 2); MemRegReg(ARPL, MemReg_Reg, 2);
break; break;
case 0x6c: // INSB case 0x6c: // INSB
if(model_ < Model::i80186) undefined(); if constexpr (model < Model::i80186) undefined();
Complete(INS, None, None, 1); Complete(INS, None, None, 1);
break; break;
case 0x6d: // INSW case 0x6d: // INSW
if(model_ < Model::i80186) undefined(); if constexpr (model < Model::i80186) undefined();
Complete(INS, None, None, 2); Complete(INS, None, None, 2);
break; break;
case 0x6e: // OUTSB case 0x6e: // OUTSB
if(model_ < Model::i80186) undefined(); if constexpr (model < Model::i80186) undefined();
Complete(OUTS, None, None, 1); Complete(OUTS, None, None, 1);
break; break;
case 0x6f: // OUTSW case 0x6f: // OUTSW
if(model_ < Model::i80186) undefined(); if constexpr (model < Model::i80186) undefined();
Complete(OUTS, None, None, 2); Complete(OUTS, None, None, 2);
break; break;
@ -291,11 +289,11 @@ std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *
case 0xc7: MemRegReg(MOV, MemRegMOV, 2); break; case 0xc7: MemRegReg(MOV, MemRegMOV, 2); break;
case 0xc8: case 0xc8:
if(model_ < Model::i80186) undefined(); if constexpr (model < Model::i80186) undefined();
Displacement16Operand8(ENTER); Displacement16Operand8(ENTER);
break; break;
case 0xc9: case 0xc9:
if(model_ < Model::i80186) undefined(); if constexpr (model < Model::i80186) undefined();
Complete(LEAVE, None, None, 0); Complete(LEAVE, None, None, 0);
break; break;
@ -392,7 +390,7 @@ std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *
case 0x02: MemRegReg(LAR, Reg_MemReg, 2); break; case 0x02: MemRegReg(LAR, Reg_MemReg, 2); break;
case 0x03: MemRegReg(LSL, Reg_MemReg, 2); break; case 0x03: MemRegReg(LSL, Reg_MemReg, 2); break;
case 0x05: case 0x05:
if(model_ != Model::i80286) undefined(); if constexpr (model != Model::i80286) undefined();
Complete(LOADALL, None, None, 0); Complete(LOADALL, None, None, 0);
break; break;
case 0x06: Complete(CLTS, None, None, 1); break; case 0x06: Complete(CLTS, None, None, 1); break;
@ -711,3 +709,9 @@ std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *
// i.e. not done yet. // i.e. not done yet.
return std::make_pair(0, Instruction()); return std::make_pair(0, Instruction());
} }
// Ensure all possible decoders are built.
template class InstructionSet::x86::Decoder<InstructionSet::x86::Model::i8086>;
template class InstructionSet::x86::Decoder<InstructionSet::x86::Model::i80186>;
template class InstructionSet::x86::Decoder<InstructionSet::x86::Model::i80286>;
template class InstructionSet::x86::Decoder<InstructionSet::x86::Model::i80386>;

View File

@ -29,10 +29,8 @@ enum class Model {
This is an experimental implementation; it has not yet undergone significant testing. This is an experimental implementation; it has not yet undergone significant testing.
*/ */
class Decoder { template <Model> class Decoder {
public: public:
Decoder(Model model);
/*! /*!
@returns an @c Instruction plus a size; a positive size to indicate successful decoding; a @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 negative size specifies the [negatived] number of further bytes the caller should ideally
@ -43,8 +41,6 @@ class Decoder {
std::pair<int, Instruction> decode(const uint8_t *source, size_t length); std::pair<int, Instruction> decode(const uint8_t *source, size_t length);
private: private:
const Model model_;
enum class Phase { enum class Phase {
/// Captures all prefixes and continues until an instruction byte is encountered. /// Captures all prefixes and continues until an instruction byte is encountered.
Instruction, Instruction,

View File

@ -105,7 +105,7 @@ namespace {
- (void)decode:(const std::initializer_list<uint8_t> &)stream { - (void)decode:(const std::initializer_list<uint8_t> &)stream {
// Decode by offering up all data at once. // Decode by offering up all data at once.
InstructionSet::x86::Decoder decoder(InstructionSet::x86::Model::i8086); InstructionSet::x86::Decoder<InstructionSet::x86::Model::i8086> decoder;
instructions.clear(); instructions.clear();
const uint8_t *byte = stream.begin(); const uint8_t *byte = stream.begin();
while(byte != stream.end()) { while(byte != stream.end()) {
@ -117,7 +117,7 @@ namespace {
// Grab a byte-at-a-time decoding and check that it matches the previous. // 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<InstructionSet::x86::Model::i8086> decoder;
auto previous_instruction = instructions.begin(); auto previous_instruction = instructions.begin();
for(auto item: stream) { for(auto item: stream) {