1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-30 22:56:03 +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 0x8a: MemRegReg(MOV, Reg_MemReg, DataSize::Byte); 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 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 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_;
Source memreg;
// TODO: can I just eliminate these lookup tables given the deliberate ordering within Source?
constexpr Source reg_table[8] = {
Source::eAX, Source::eCX, Source::eDX, Source::eBX,
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) {
default: {
const DataSize sizes[] = {DataSize::Byte, data_size_};
@ -495,20 +503,29 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
}
break;
case ModRegRMFormat::SegReg: {
source_ = memreg;
constexpr Source seg_table[4] = {
Source::ES, Source::CS,
Source::SS, Source::DS,
};
if(reg & 4) {
case ModRegRMFormat::Seg_MemReg:
case ModRegRMFormat::MemReg_Seg:
// The 16-bit chips have four segment registers;
// the 80386 onwards has six.
if(!is_32bit(model) && reg > 3) {
undefined();
} else if(reg > 5) {
undefined();
}
destination_ = seg_table[reg];
} break;
if(modregrm_format_ == ModRegRMFormat::Seg_MemReg) {
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:
destination_ = memreg;

View File

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