1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-11 08:30:55 +00:00

Fix $8e data size, add $8c.

This commit is contained in:
Thomas Harte 2022-03-05 17:00:48 -05:00
parent 1afcbba218
commit eb180656bb
2 changed files with 33 additions and 15 deletions

View File

@ -233,9 +233,12 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
case 0x89: MemRegReg(MOV, MemReg_Reg, data_size_); break; case 0x89: MemRegReg(MOV, MemReg_Reg, data_size_); break;
case 0x8a: MemRegReg(MOV, Reg_MemReg, DataSize::Byte); break; case 0x8a: MemRegReg(MOV, Reg_MemReg, DataSize::Byte); break;
case 0x8b: MemRegReg(MOV, Reg_MemReg, data_size_); break; case 0x8b: MemRegReg(MOV, Reg_MemReg, data_size_); break;
// 0x8c: not used. case 0x8c:
RequiresMin(i80286); // TODO: or is this 80386?
MemRegReg(MOV, MemReg_Seg, DataSize::Word);
break;
case 0x8d: MemRegReg(LEA, Reg_MemReg, data_size_); break; case 0x8d: MemRegReg(LEA, Reg_MemReg, data_size_); break;
case 0x8e: MemRegReg(MOV, SegReg, data_size_); break; case 0x8e: MemRegReg(MOV, Seg_MemReg, DataSize::Word); break;
case 0x8f: MemRegReg(POP, MemRegPOP, data_size_); break; case 0x8f: MemRegReg(POP, MemRegPOP, data_size_); break;
case 0x90: Complete(NOP, None, None, DataSize::None); break; // Or XCHG AX, AX? case 0x90: Complete(NOP, None, None, DataSize::None); break; // Or XCHG AX, AX?
@ -430,10 +433,15 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
++consumed_; ++consumed_;
Source memreg; Source memreg;
// TODO: can I just eliminate these lookup tables given the deliberate ordering within Source?
constexpr Source reg_table[8] = { constexpr Source reg_table[8] = {
Source::eAX, Source::eCX, Source::eDX, Source::eBX, Source::eAX, Source::eCX, Source::eDX, Source::eBX,
Source::eSPorAH, Source::eBPorCH, Source::eSIorDH, Source::eDIorBH, Source::eSPorAH, Source::eBPorCH, Source::eSIorDH, Source::eDIorBH,
}; };
constexpr Source seg_table[6] = {
Source::ES, Source::CS, Source::SS, Source::DS, Source::FS, Source::GS
};
switch(mod) { switch(mod) {
default: { default: {
const DataSize sizes[] = {DataSize::Byte, data_size_}; const DataSize sizes[] = {DataSize::Byte, data_size_};
@ -495,20 +503,29 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
} }
break; break;
case ModRegRMFormat::SegReg: { case ModRegRMFormat::Seg_MemReg:
source_ = memreg; case ModRegRMFormat::MemReg_Seg:
// The 16-bit chips have four segment registers;
constexpr Source seg_table[4] = { // the 80386 onwards has six.
Source::ES, Source::CS, if(!is_32bit(model) && reg > 3) {
Source::SS, Source::DS, undefined();
}; } else if(reg > 5) {
if(reg & 4) {
undefined(); undefined();
} }
destination_ = seg_table[reg]; if(modregrm_format_ == ModRegRMFormat::Seg_MemReg) {
} break; source_ = memreg;
destination_ = seg_table[reg];
// 80286 and later disallow MOV to CS.
if(model >= Model::i80286 && destination_ == Source::CS) {
undefined();
}
} else {
source_ = seg_table[reg];
destination_ = memreg;
}
break;
case ModRegRMFormat::MemRegROL_to_SAR: case ModRegRMFormat::MemRegROL_to_SAR:
destination_ = memreg; destination_ = memreg;

View File

@ -65,7 +65,7 @@ template <Model model> class Decoder {
/// are packaged into an Instruction. /// are packaged into an Instruction.
enum class ModRegRMFormat: uint8_t { enum class ModRegRMFormat: uint8_t {
// Parse the ModRegRM for mode, register and register/memory fields // Parse the ModRegRM for mode, register and register/memory fields
// and populate the source_ and destination_ fields appropriate. // and populate the source_ and destination_ fields appropriately.
MemReg_Reg, MemReg_Reg,
Reg_MemReg, Reg_MemReg,
@ -82,7 +82,8 @@ template <Model model> class Decoder {
// Parse for mode and register/memory fields, populating the // Parse for mode and register/memory fields, populating the
// source_ field with the result. Fills destination_ with a segment // source_ field with the result. Fills destination_ with a segment
// register based on the reg field. // register based on the reg field.
SegReg, Seg_MemReg,
MemReg_Seg,
// //
// 'Group 1' // 'Group 1'