mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-27 15:29:34 +00:00
Attempts decoding of the 80186 set.
This commit is contained in:
parent
ae21726287
commit
7ceb3369eb
@ -15,7 +15,7 @@
|
|||||||
using namespace InstructionSet::x86;
|
using namespace InstructionSet::x86;
|
||||||
|
|
||||||
// Only 8086 is suppoted for now.
|
// Only 8086 is suppoted for now.
|
||||||
Decoder::Decoder(Model) {}
|
Decoder::Decoder(Model model) : model_(model) {}
|
||||||
|
|
||||||
std::pair<int, InstructionSet::x86::Instruction> Decoder::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;
|
||||||
@ -74,6 +74,13 @@ std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *
|
|||||||
phase_ = Phase::DisplacementOrOperand; \
|
phase_ = Phase::DisplacementOrOperand; \
|
||||||
operand_size_ = 4; \
|
operand_size_ = 4; \
|
||||||
|
|
||||||
|
/// Handles ENTER — a fixed three-byte operation.
|
||||||
|
#define Displacement16Operand8(op) \
|
||||||
|
operation_ = Operation::op; \
|
||||||
|
phase_ = Phase::DisplacementOrOperand; \
|
||||||
|
displacement_size_ = 2; \
|
||||||
|
operand_size_ = 1; \
|
||||||
|
|
||||||
while(phase_ == Phase::Instruction && source != end) {
|
while(phase_ == Phase::Instruction && source != end) {
|
||||||
// Retain the instruction byte, in case additional decoding is deferred
|
// Retain the instruction byte, in case additional decoding is deferred
|
||||||
// to the ModRegRM byte.
|
// to the ModRegRM byte.
|
||||||
@ -81,13 +88,15 @@ std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *
|
|||||||
++source;
|
++source;
|
||||||
++consumed_;
|
++consumed_;
|
||||||
|
|
||||||
switch(instr_) {
|
#define undefined() { \
|
||||||
default: {
|
const auto result = std::make_pair(consumed_, Instruction()); \
|
||||||
const auto result = std::make_pair(consumed_, Instruction());
|
reset_parsing(); \
|
||||||
reset_parsing();
|
return result; \
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(instr_) {
|
||||||
|
default: undefined();
|
||||||
|
|
||||||
#define PartialBlock(start, operation) \
|
#define PartialBlock(start, operation) \
|
||||||
case start + 0x00: MemRegReg(operation, MemReg_Reg, 1); break; \
|
case start + 0x00: MemRegReg(operation, MemReg_Reg, 1); break; \
|
||||||
case start + 0x01: MemRegReg(operation, MemReg_Reg, 2); break; \
|
case start + 0x01: MemRegReg(operation, MemReg_Reg, 2); break; \
|
||||||
@ -146,7 +155,34 @@ std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *
|
|||||||
|
|
||||||
#undef RegisterBlock
|
#undef RegisterBlock
|
||||||
|
|
||||||
// 0x60–0x6f: not used.
|
case 0x60:
|
||||||
|
if(model_ < Model::i80186) undefined();
|
||||||
|
Complete(PUSHA, None, None, 2);
|
||||||
|
break;
|
||||||
|
case 0x61:
|
||||||
|
if(model_ < Model::i80186) undefined();
|
||||||
|
Complete(POPA, None, None, 2);
|
||||||
|
break;
|
||||||
|
case 0x62:
|
||||||
|
if(model_ < Model::i80186) undefined();
|
||||||
|
MemRegReg(BOUND, Reg_MemReg, 2);
|
||||||
|
break;
|
||||||
|
case 0x6c: // INSB
|
||||||
|
if(model_ < Model::i80186) undefined();
|
||||||
|
Complete(INS, None, None, 1);
|
||||||
|
break;
|
||||||
|
case 0x6d: // INSW
|
||||||
|
if(model_ < Model::i80186) undefined();
|
||||||
|
Complete(INS, None, None, 2);
|
||||||
|
break;
|
||||||
|
case 0x6e: // OUTSB
|
||||||
|
if(model_ < Model::i80186) undefined();
|
||||||
|
Complete(OUTS, None, None, 1);
|
||||||
|
break;
|
||||||
|
case 0x6f: // OUTSW
|
||||||
|
if(model_ < Model::i80186) undefined();
|
||||||
|
Complete(OUTS, None, None, 2);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x70: Jump(JO); break;
|
case 0x70: Jump(JO); break;
|
||||||
case 0x71: Jump(JNO); break;
|
case 0x71: Jump(JNO); break;
|
||||||
@ -243,6 +279,15 @@ std::pair<int, InstructionSet::x86::Instruction> Decoder::decode(const uint8_t *
|
|||||||
case 0xc6: MemRegReg(MOV, MemRegMOV, 1); break;
|
case 0xc6: MemRegReg(MOV, MemRegMOV, 1); break;
|
||||||
case 0xc7: MemRegReg(MOV, MemRegMOV, 2); break;
|
case 0xc7: MemRegReg(MOV, MemRegMOV, 2); break;
|
||||||
|
|
||||||
|
case 0xc8:
|
||||||
|
if(model_ < Model::i80186) undefined();
|
||||||
|
Displacement16Operand8(ENTER);
|
||||||
|
break;
|
||||||
|
case 0xc9:
|
||||||
|
if(model_ < Model::i80186) undefined();
|
||||||
|
Complete(LEAVE, None, None, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0xca: RegData(RETF, None, 2); break;
|
case 0xca: RegData(RETF, None, 2); break;
|
||||||
case 0xcb: Complete(RETF, None, None, 4); break;
|
case 0xcb: Complete(RETF, None, None, 4); break;
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@ namespace x86 {
|
|||||||
|
|
||||||
enum class Model {
|
enum class Model {
|
||||||
i8086,
|
i8086,
|
||||||
|
i80186,
|
||||||
|
i80286,
|
||||||
|
i80386,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -40,6 +43,8 @@ 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,
|
||||||
|
@ -208,21 +208,19 @@ enum class Operation: uint8_t {
|
|||||||
|
|
||||||
/// Create stack frame.
|
/// Create stack frame.
|
||||||
ENTER,
|
ENTER,
|
||||||
/// Procedure exit.
|
/// Procedure exit; copies BP to SP, then pops a new BP from the stack.
|
||||||
LEAVE,
|
LEAVE,
|
||||||
|
|
||||||
/// Inputs a byte from a port, incrementing or decrementing the destination.
|
/// Inputs from a port, incrementing or decrementing the destination.
|
||||||
INSB,
|
INS,
|
||||||
/// Inputs a word from a port, incrementing or decrementingthe destination.
|
/// Outputs to a port, incrementing or decrementing the destination.
|
||||||
INSW,
|
OUTS,
|
||||||
/// Outputs a byte to a port, incrementing or decrementing the destination.
|
|
||||||
OUTSB,
|
|
||||||
/// Outputs a word to a port, incrementing or decrementing the destination.
|
|
||||||
OUTSW,
|
|
||||||
|
|
||||||
/// Pushes all general purpose registers to the stack.
|
/// Pushes all general purpose registers to the stack, in the order:
|
||||||
|
/// AX, CX, DX, BX, [original] SP, BP, SI, DI.
|
||||||
PUSHA,
|
PUSHA,
|
||||||
/// Pops all general purpose registers from the stack.
|
/// Pops all general purpose registers from the stack, in the reverse of
|
||||||
|
/// the PUSHA order, i.e. DI, SI, BP, [final] SP, BX, DX, CX, AX.
|
||||||
POPA,
|
POPA,
|
||||||
|
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user