1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Allow for non-sign-extended offsets/displacements.

This commit is contained in:
Thomas Harte 2023-09-24 15:00:16 -04:00
parent d36f785428
commit d2b9c435e5
2 changed files with 22 additions and 10 deletions

View File

@ -238,7 +238,7 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
RequiresMin(i80286);
MemRegReg(IMUL_3, Reg_MemReg, data_size_);
operand_size_ = DataSize::Byte;
sign_extend_ = true;
sign_extend_operand_ = true;
break;
case 0x6c: // INSB
RequiresMin(i80186);
@ -795,7 +795,7 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
source_ = Source::Immediate;
destination_ = memreg;
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.
sign_extend_operand_ = true; // Will be effective only if modregrm_format_ == ModRegRMFormat::MemRegADD_to_CMP_SignExtend.
switch(reg) {
default: operation_ = Operation::ADD; break;
@ -905,16 +905,25 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
// TODO: whether the displacement is signed appears to depend on the opcode.
// Find an appropriate table.
switch(displacement_size_) {
case DataSize::None: displacement_ = 0; break;
case DataSize::Byte: displacement_ = int8_t(inward_data_); break;
case DataSize::Word: displacement_ = int16_t(inward_data_); break;
case DataSize::DWord: displacement_ = int32_t(inward_data_); break;
if(!sign_extend_displacement_) {
switch(displacement_size_) {
case DataSize::None: displacement_ = 0; break;
case DataSize::Byte: displacement_ = decltype(operand_)(uint8_t(inward_data_)); break;
case DataSize::Word: displacement_ = decltype(operand_)(uint16_t(inward_data_)); break;
case DataSize::DWord: displacement_ = decltype(operand_)(uint32_t(inward_data_)); break;
}
} else {
switch(displacement_size_) {
case DataSize::None: displacement_ = 0; break;
case DataSize::Byte: displacement_ = int8_t(inward_data_); break;
case DataSize::Word: displacement_ = int16_t(inward_data_); break;
case DataSize::DWord: displacement_ = int32_t(inward_data_); break;
}
}
inward_data_ >>= bit_size(displacement_size_);
// Use inequality of sizes as a test for necessary sign extension.
if(operand_size_ == data_size_ || !sign_extend_) {
if(operand_size_ == data_size_ || !sign_extend_operand_) {
operand_ = decltype(operand_)(inward_data_);
} else {
switch(operand_size_) {

View File

@ -193,8 +193,10 @@ template <Model model> class Decoder {
DataSize operand_size_ = DataSize::None; // i.e. size of in-stream operand, if any.
DataSize operation_size_ = DataSize::None; // i.e. size of data manipulated by the operation.
bool sign_extend_ = false; // If set then sign extend the operand up to the operation size;
bool sign_extend_operand_ = false; // If set then sign extend the operand up to the operation size;
// otherwise it'll be zero-padded.
bool sign_extend_displacement_ = false; // Much as above; 'displacement' is used internally for both
// displacements and offsets, so signage will vary.
// Prefix capture fields.
Repetition repetition_ = Repetition::None;
@ -222,7 +224,8 @@ template <Model model> class Decoder {
sib_ = ScaleIndexBase();
next_inward_data_shift_ = 0;
inward_data_ = 0;
sign_extend_ = false;
sign_extend_operand_ = false;
sign_extend_displacement_ = false;
}
};