1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Clarify sign extension availability.

This commit is contained in:
Thomas Harte 2022-03-05 16:44:26 -05:00
parent 8a0902a83b
commit 1afcbba218
2 changed files with 57 additions and 44 deletions

View File

@ -220,16 +220,10 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
case 0x7e: Jump(JLE, DataSize::Byte); break;
case 0x7f: Jump(JNLE, DataSize::Byte); break;
case 0x80: MemRegReg(Invalid, MemRegADD_to_CMP, DataSize::Byte); break;
case 0x81: MemRegReg(Invalid, MemRegADD_to_CMP, data_size_); break;
case 0x82:
MemRegReg(Invalid, MemRegADC_to_CMP, DataSize::Byte);
sign_extend_ = true;
break;
case 0x83:
MemRegReg(Invalid, MemRegADC_to_CMP, data_size_);
sign_extend_ = true;
break;
case 0x80: MemRegReg(Invalid, MemRegADD_to_CMP, DataSize::Byte); break;
case 0x81: MemRegReg(Invalid, MemRegADD_to_CMP, data_size_); break;
case 0x82: MemRegReg(Invalid, MemRegADD_to_CMP_SignExtend, DataSize::Byte); break;
case 0x83: MemRegReg(Invalid, MemRegADD_to_CMP_SignExtend, data_size_); break;
case 0x84: MemRegReg(TEST, MemReg_Reg, DataSize::Byte); break;
case 0x85: MemRegReg(TEST, MemReg_Reg, data_size_); break;
@ -582,8 +576,11 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
break;
case ModRegRMFormat::MemRegADD_to_CMP:
case ModRegRMFormat::MemRegADD_to_CMP_SignExtend:
source_ = Source::Immediate;
destination_ = memreg;
operand_size_ = operation_size_;
operand_size_ = (modregrm_format_ == ModRegRMFormat::MemRegADD_to_CMP_SignExtend) ? DataSize::Byte : operation_size_;
sign_extend_ = true; // Will be effective only if modregrm_format_ == ModRegRMFormat::MemRegADD_to_CMP_SignExtend.
switch(reg) {
default: operation_ = Operation::ADD; break;
@ -597,23 +594,6 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
}
break;
case ModRegRMFormat::MemRegADC_to_CMP:
destination_ = memreg;
source_ = Source::Immediate;
operand_size_ = DataSize::Byte; // ... and always a byte; it'll be sign extended if
// the operation requires it.
switch(reg) {
default: undefined();
case 0: operation_ = Operation::ADD; break;
case 2: operation_ = Operation::ADC; break;
case 3: operation_ = Operation::SBB; break;
case 5: operation_ = Operation::SUB; break;
case 7: operation_ = Operation::CMP; break;
}
break;
case ModRegRMFormat::MemRegSLDT_to_VERW:
destination_ = source_ = memreg;

View File

@ -69,11 +69,6 @@ template <Model model> class Decoder {
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,
// Parse for mode and register/memory fields, populating both
// source_ and destination_ fields with the result. Use the 'register'
// field to check for the POP operation.
@ -85,9 +80,13 @@ template <Model model> class Decoder {
MemRegMOV,
// Parse for mode and register/memory fields, populating the
// destination_ field with the result. Use the 'register' field
// to pick an operation from the ROL/ROR/RCL/RCR/SAL/SHR/SAR group.
MemRegROL_to_SAR,
// source_ field with the result. Fills destination_ with a segment
// register based on the reg field.
SegReg,
//
// 'Group 1'
//
// Parse for mode and register/memory fields, populating the
// destination_ field with the result. Use the 'register' field
@ -95,37 +94,71 @@ template <Model model> class Decoder {
// waits for an operand equal to the operation size.
MemRegADD_to_CMP,
// Acts exactly as MemRegADD_to_CMP but the operand is fixed in size
// at a single byte, which is sign extended to the operation size.
MemRegADD_to_CMP_SignExtend,
//
// 'Group 2'
//
// 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,
// destination_ field with the result. Use the 'register' field
// to pick an operation from the ROL/ROR/RCL/RCR/SAL/SHR/SAR group.
MemRegROL_to_SAR,
//
// 'Group 3'
//
// 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,
//
// 'Group 4'
//
// Parse for mode and register/memory fields, populating the
// source_ and destination_ fields with the result. Uses the
// 'register' field to pick INC or DEC.
MemRegINC_DEC,
//
// 'Group 5'
//
// Parse for mode and register/memory fields, populating the
// source_ and destination_ fields with the result. Uses the
// 'register' field to pick from INC/DEC/CALL/JMP/PUSH, altering
// the source to ::Immediate and setting an operand size if necessary.
MemRegINC_to_PUSH,
// Parse for mode and register/memory fields, populating the
// source_ and destination_ fields with the result. Uses the
// 'register' field to pick from ADD/ADC/SBB/SUB/CMP, altering
// the source to ::Immediate and setting an appropriate operand size.
MemRegADC_to_CMP,
//
// 'Group 6'
//
// Parse for mode and register/memory field, populating both source_
// and destination_ fields with the result. Uses the 'register' field
// to pick from SLDT/STR/LLDT/LTR/VERR/VERW.
MemRegSLDT_to_VERW,
//
// 'Group 7'
//
// Parse for mode and register/memory field, populating both source_
// and destination_ fields with the result. Uses the 'register' field
// to pick from SGDT/LGDT/SMSW/LMSW.
MemRegSGDT_to_LMSW,
//
// 'Group 8'
//
// TODO.
MemRegBT_to_BTC,
} modregrm_format_ = ModRegRMFormat::MemReg_Reg;
// Ephemeral decoding state.