mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-05 04:37:41 +00:00
Ostensibly gets the instruction stream correct for test case 1.
Subject to operand and displacement currently being absent, and likely inconsistencies in field population, most of which are omitted from the Instruction anyway.
This commit is contained in:
parent
3b55d3f158
commit
9d7d45338f
@ -276,6 +276,9 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) {
|
||||
MapComplete(0xec, IN, DX, AL, 1); MapComplete(0xed, IN, DX, AX, 1);
|
||||
MapComplete(0xee, OUT, AL, DX, 1); MapComplete(0xef, OUT, AX, DX, 1);
|
||||
|
||||
MapMemRegReg(0xf6, Invalid, MemRegTEST_to_IDIV, 1);
|
||||
MapMemRegReg(0xf7, Invalid, MemRegTEST_to_IDIV, 2);
|
||||
|
||||
MapComplete(0xf9, STC, None, None, 1);
|
||||
MapComplete(0xfd, STD, None, None, 1);
|
||||
|
||||
@ -297,51 +300,49 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) {
|
||||
++source;
|
||||
++consumed_;
|
||||
|
||||
Source memreg;
|
||||
constexpr Source reg_table[3][8] = {
|
||||
{},
|
||||
{
|
||||
Source::AL, Source::CL, Source::DL, Source::BL,
|
||||
Source::AH, Source::CH, Source::DH, Source::BH,
|
||||
}, {
|
||||
Source::AX, Source::CX, Source::DX, Source::BX,
|
||||
Source::SP, Source::BP, Source::SI, Source::DI,
|
||||
}
|
||||
};
|
||||
switch(mod) {
|
||||
case 0: {
|
||||
constexpr Source rm_table[8] = {
|
||||
Source::IndBXPlusSI, Source::IndBXPlusDI,
|
||||
Source::IndBPPlusSI, Source::IndBPPlusDI,
|
||||
Source::IndSI, Source::IndDI,
|
||||
Source::DirectAddress, Source::IndBX,
|
||||
};
|
||||
memreg = rm_table[rm];
|
||||
} break;
|
||||
|
||||
default: {
|
||||
constexpr Source rm_table[8] = {
|
||||
Source::IndBXPlusSI, Source::IndBXPlusDI,
|
||||
Source::IndBPPlusSI, Source::IndBPPlusDI,
|
||||
Source::IndSI, Source::IndDI,
|
||||
Source::IndBP, Source::IndBX,
|
||||
};
|
||||
memreg = rm_table[rm];
|
||||
|
||||
displacement_size_ = 1 + (mod == 2);
|
||||
} break;
|
||||
|
||||
// Other operand is just a register.
|
||||
case 3:
|
||||
memreg = reg_table[operation_size_][rm];
|
||||
break;
|
||||
}
|
||||
|
||||
switch(modregrm_format_) {
|
||||
case ModRegRMFormat::Reg_MemReg:
|
||||
case ModRegRMFormat::MemReg_Reg: {
|
||||
Source memreg;
|
||||
|
||||
constexpr Source reg_table[3][8] = {
|
||||
{},
|
||||
{
|
||||
Source::AL, Source::CL, Source::DL, Source::BL,
|
||||
Source::AH, Source::CH, Source::DH, Source::BH,
|
||||
}, {
|
||||
Source::AX, Source::CX, Source::DX, Source::BX,
|
||||
Source::SP, Source::BP, Source::SI, Source::DI,
|
||||
}
|
||||
};
|
||||
|
||||
switch(mod) {
|
||||
case 0: {
|
||||
constexpr Source rm_table[8] = {
|
||||
Source::IndBXPlusSI, Source::IndBXPlusDI,
|
||||
Source::IndBPPlusSI, Source::IndBPPlusDI,
|
||||
Source::IndSI, Source::IndDI,
|
||||
Source::DirectAddress, Source::IndBX,
|
||||
};
|
||||
memreg = rm_table[rm];
|
||||
} break;
|
||||
|
||||
default: {
|
||||
constexpr Source rm_table[8] = {
|
||||
Source::IndBXPlusSI, Source::IndBXPlusDI,
|
||||
Source::IndBPPlusSI, Source::IndBPPlusDI,
|
||||
Source::IndSI, Source::IndDI,
|
||||
Source::IndBP, Source::IndBX,
|
||||
};
|
||||
memreg = rm_table[rm];
|
||||
|
||||
displacement_size_ = 1 + (mod == 2);
|
||||
} break;
|
||||
|
||||
// Other operand is just a register.
|
||||
case 3:
|
||||
memreg = reg_table[operation_size_][rm];
|
||||
break;
|
||||
}
|
||||
|
||||
if(modregrm_format_ == ModRegRMFormat::Reg_MemReg) {
|
||||
source_ = memreg;
|
||||
destination_ = reg_table[operation_size_][reg];
|
||||
@ -349,11 +350,30 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) {
|
||||
source_ = reg_table[operation_size_][reg];
|
||||
destination_ = memreg;
|
||||
}
|
||||
phase_ = Phase::AwaitingDisplacementOrOperand;
|
||||
} break;
|
||||
|
||||
case ModRegRMFormat::MemRegTEST_to_IDIV:
|
||||
source_ = destination_ = memreg;
|
||||
|
||||
switch(reg) {
|
||||
default:
|
||||
reset_parsing();
|
||||
return Instruction();
|
||||
|
||||
case 0: operation_ = Operation::TEST; break;
|
||||
case 2: operation_ = Operation::NOT; break;
|
||||
case 3: operation_ = Operation::NEG; break;
|
||||
case 4: operation_ = Operation::MUL; break;
|
||||
case 5: operation_ = Operation::IMUL; break;
|
||||
case 6: operation_ = Operation::DIV; break;
|
||||
case 7: operation_ = Operation::IDIV; break;
|
||||
}
|
||||
break;
|
||||
|
||||
default: assert(false);
|
||||
}
|
||||
|
||||
phase_ = Phase::AwaitingDisplacementOrOperand;
|
||||
}
|
||||
|
||||
// MARK: - Displacement and operand.
|
||||
|
@ -146,11 +146,16 @@ struct Decoder {
|
||||
/// During the ReadyToPost phase, format determines how transiently-recorded fields
|
||||
/// are packaged into an Instruction.
|
||||
enum class ModRegRMFormat: uint8_t {
|
||||
// Parse the ModRegRM for mode, register and register/memory flags
|
||||
// Parse the ModRegRM for mode, register and register/memory fields
|
||||
// and populate the source_ and destination_ fields appropriate.
|
||||
MemReg_Reg,
|
||||
Reg_MemReg,
|
||||
|
||||
// Parse for mode and register/memory fields, populating both
|
||||
// source_ and destination_ fields with the result. Use the 'register'
|
||||
// field to pick an operation from the TEST/NOT/NEG/MUL/IMUL/DIV/IDIV group.
|
||||
MemRegTEST_to_IDIV,
|
||||
|
||||
} modregrm_format_ = ModRegRMFormat::MemReg_Reg;
|
||||
|
||||
// Ephemeral decoding state.
|
||||
|
Loading…
x
Reference in New Issue
Block a user