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:
parent
8a0902a83b
commit
1afcbba218
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user