mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-19 23:29:05 +00:00
Switch Decoder
into a template.
This commit is contained in:
parent
9e9e160c43
commit
1934c7faa2
@ -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>;
|
||||||
|
@ -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,
|
||||||
|
@ -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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user