aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-07-22 00:31:02 -0700
committeriximeow <me@iximeow.net>2021-07-22 00:31:02 -0700
commit4371ed02ac30cb56ec4ddbf60c87e85c183d860b (patch)
treeb24673d757b41cd58966fc0e8ea472cd9b6e6fb0 /src
parenta3c2c7486ef6830751fd0a5e2a6cb91b432f28a5 (diff)
fix incorrect decodes with scas and 67-prefixes1.0.4
Diffstat (limited to 'src')
-rw-r--r--src/long_mode/mod.rs67
-rw-r--r--src/protected_mode/mod.rs56
-rw-r--r--src/real_mode/mod.rs25
3 files changed, 125 insertions, 23 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index e967f4b..72ec802 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -382,6 +382,18 @@ impl RegSpec {
RegSpec { bank: RegisterBank::D, num: 3 }
}
+ // TODO: make pub in the 1.1 version bump
+ #[inline]
+ const fn esi() -> RegSpec {
+ RegSpec { bank: RegisterBank::D, num: 6 }
+ }
+
+ // TODO: make pub in the 1.1 version bump
+ #[inline]
+ const fn edi() -> RegSpec {
+ RegSpec { bank: RegisterBank::D, num: 7 }
+ }
+
#[inline]
pub const fn ax() -> RegSpec {
RegSpec { bank: RegisterBank::W, num: 0 }
@@ -582,6 +594,8 @@ impl OperandSpec {
OperandSpec::DispU32 |
OperandSpec::DispU64 |
OperandSpec::Deref |
+ OperandSpec::Deref_esi |
+ OperandSpec::Deref_edi |
OperandSpec::Deref_rsi |
OperandSpec::Deref_rdi |
OperandSpec::RegDisp |
@@ -760,6 +774,12 @@ impl Operand {
OperandSpec::Deref => {
Operand::RegDeref(inst.regs[1])
}
+ OperandSpec::Deref_esi => {
+ Operand::RegDeref(RegSpec::esi())
+ }
+ OperandSpec::Deref_edi => {
+ Operand::RegDeref(RegSpec::edi())
+ }
OperandSpec::Deref_rsi => {
Operand::RegDeref(RegSpec::rsi())
}
@@ -2782,6 +2802,8 @@ enum OperandSpec {
DispU32,
DispU64,
Deref,
+ Deref_esi,
+ Deref_edi,
Deref_rsi,
Deref_rdi,
RegDisp,
@@ -4415,7 +4437,8 @@ impl Instruction {
/// prefixes.
pub fn segment_override_for_op(&self, op: u8) -> Option<Segment> {
match self.opcode {
- Opcode::STOS => {
+ Opcode::STOS |
+ Opcode::SCAS => {
if op == 0 {
Some(Segment::ES)
} else {
@@ -9122,21 +9145,34 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
// sure hope these aren't backwards huh
OperandCode::AL_Xb => {
instruction.regs[0] = RegSpec::al();
- instruction.regs[1] = RegSpec::rsi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::esi();
+ } else {
+ instruction.regs[1] = RegSpec::rsi();
+ }
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = OperandSpec::Deref;
instruction.mem_size = 1;
instruction.operand_count = 2;
}
OperandCode::Yb_Xb => {
- instruction.operands[0] = OperandSpec::Deref_rdi;
- instruction.operands[1] = OperandSpec::Deref_rsi;
+ if instruction.prefixes.address_size() {
+ instruction.operands[0] = OperandSpec::Deref_edi;
+ instruction.operands[1] = OperandSpec::Deref_esi;
+ } else {
+ instruction.operands[0] = OperandSpec::Deref_rdi;
+ instruction.operands[1] = OperandSpec::Deref_rsi;
+ }
instruction.mem_size = 1;
instruction.operand_count = 2;
}
OperandCode::Yb_AL => {
instruction.regs[0] = RegSpec::al();
- instruction.regs[1] = RegSpec::rsi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::edi();
+ } else {
+ instruction.regs[1] = RegSpec::rdi();
+ }
instruction.operands[0] = OperandSpec::Deref;
instruction.operands[1] = OperandSpec::RegRRR;
instruction.mem_size = 1;
@@ -9150,7 +9186,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
8 => RegSpec::rax(),
_ => { unreachable!(); }
};
- instruction.regs[1] = RegSpec::rsi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::esi();
+ } else {
+ instruction.regs[1] = RegSpec::rsi();
+ }
instruction.operands[1] = OperandSpec::Deref;
instruction.mem_size = opwidth;
}
@@ -9162,7 +9202,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
8 => RegSpec::rax(),
_ => { unreachable!(); }
};
- instruction.regs[1] = RegSpec::rdi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::edi();
+ } else {
+ instruction.regs[1] = RegSpec::rdi();
+ }
instruction.operands[0] = OperandSpec::Deref;
instruction.operands[1] = OperandSpec::RegRRR;
instruction.mem_size = opwidth;
@@ -9170,8 +9214,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
OperandCode::Yv_Xv => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes);
instruction.mem_size = opwidth;
- instruction.operands[0] = OperandSpec::Deref_rdi;
- instruction.operands[1] = OperandSpec::Deref_rsi;
+ if instruction.prefixes.address_size() {
+ instruction.operands[0] = OperandSpec::Deref_edi;
+ instruction.operands[1] = OperandSpec::Deref_esi;
+ } else {
+ instruction.operands[0] = OperandSpec::Deref_rdi;
+ instruction.operands[1] = OperandSpec::Deref_rsi;
+ }
}
OperandCode::ModRM_0x0f12 => {
instruction.regs[0].bank = RegisterBank::X;
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index 6e503a0..19fe881 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -525,6 +525,8 @@ impl OperandSpec {
OperandSpec::DispU16 |
OperandSpec::DispU32 |
OperandSpec::Deref |
+ OperandSpec::Deref_si |
+ OperandSpec::Deref_di |
OperandSpec::Deref_esi |
OperandSpec::Deref_edi |
OperandSpec::RegDisp |
@@ -704,6 +706,12 @@ impl Operand {
OperandSpec::Deref => {
Operand::RegDeref(inst.regs[1])
}
+ OperandSpec::Deref_si => {
+ Operand::RegDeref(RegSpec::si())
+ }
+ OperandSpec::Deref_di => {
+ Operand::RegDeref(RegSpec::di())
+ }
OperandSpec::Deref_esi => {
Operand::RegDeref(RegSpec::esi())
}
@@ -2720,6 +2728,8 @@ enum OperandSpec {
DispU16,
DispU32,
Deref,
+ Deref_si,
+ Deref_di,
Deref_esi,
Deref_edi,
RegDisp,
@@ -4357,7 +4367,8 @@ impl Instruction {
/// prefixes.
pub fn segment_override_for_op(&self, op: u8) -> Option<Segment> {
match self.opcode {
- Opcode::STOS => {
+ Opcode::STOS |
+ Opcode::SCAS => {
if op == 0 {
Some(Segment::ES)
} else {
@@ -5748,6 +5759,7 @@ fn read_M_16bit<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpea
let modbits = modrm >> 6;
let mmm = modrm & 7;
if modbits == 0b00 && mmm == 0b110 {
+ instr.disp = read_num(words, 2)? as u16 as u32;
return Ok(OperandSpec::DispU16);
}
match mmm {
@@ -8975,21 +8987,34 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
// sure hope these aren't backwards huh
OperandCode::AL_Xb => {
instruction.regs[0] = RegSpec::al();
- instruction.regs[1] = RegSpec::esi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::si();
+ } else {
+ instruction.regs[1] = RegSpec::esi();
+ }
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = OperandSpec::Deref;
instruction.mem_size = 1;
instruction.operand_count = 2;
}
OperandCode::Yb_Xb => {
- instruction.operands[0] = OperandSpec::Deref_edi;
- instruction.operands[1] = OperandSpec::Deref_esi;
+ if instruction.prefixes.address_size() {
+ instruction.operands[0] = OperandSpec::Deref_di;
+ instruction.operands[1] = OperandSpec::Deref_si;
+ } else {
+ instruction.operands[0] = OperandSpec::Deref_edi;
+ instruction.operands[1] = OperandSpec::Deref_esi;
+ }
instruction.mem_size = 1;
instruction.operand_count = 2;
}
OperandCode::Yb_AL => {
instruction.regs[0] = RegSpec::al();
- instruction.regs[1] = RegSpec::esi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::di();
+ } else {
+ instruction.regs[1] = RegSpec::edi();
+ }
instruction.operands[0] = OperandSpec::Deref;
instruction.operands[1] = OperandSpec::RegRRR;
instruction.mem_size = 1;
@@ -9003,7 +9028,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
instruction.mem_size = 4;
RegSpec::eax()
};
- instruction.regs[1] = RegSpec::esi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::si();
+ } else {
+ instruction.regs[1] = RegSpec::esi();
+ }
instruction.operands[1] = OperandSpec::Deref;
}
OperandCode::Yv_AX => {
@@ -9014,7 +9043,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
instruction.mem_size = 4;
RegSpec::eax()
};
- instruction.regs[1] = RegSpec::edi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::di();
+ } else {
+ instruction.regs[1] = RegSpec::edi();
+ }
instruction.operands[0] = OperandSpec::Deref;
instruction.operands[1] = OperandSpec::RegRRR;
}
@@ -9024,8 +9057,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
} else {
4
};
- instruction.operands[0] = OperandSpec::Deref_edi;
- instruction.operands[1] = OperandSpec::Deref_esi;
+ if instruction.prefixes.address_size() {
+ instruction.operands[0] = OperandSpec::Deref_di;
+ instruction.operands[1] = OperandSpec::Deref_si;
+ } else {
+ instruction.operands[0] = OperandSpec::Deref_edi;
+ instruction.operands[1] = OperandSpec::Deref_esi;
+ }
}
OperandCode::ModRM_0x0f12 => {
instruction.regs[0].bank = RegisterBank::X;
diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs
index 6913fb4..3c9c279 100644
--- a/src/real_mode/mod.rs
+++ b/src/real_mode/mod.rs
@@ -4367,7 +4367,8 @@ impl Instruction {
/// prefixes.
pub fn segment_override_for_op(&self, op: u8) -> Option<Segment> {
match self.opcode {
- Opcode::STOS => {
+ Opcode::STOS |
+ Opcode::SCAS => {
if op == 0 {
Some(Segment::ES)
} else {
@@ -5758,6 +5759,7 @@ fn read_M_16bit<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpea
let modbits = modrm >> 6;
let mmm = modrm & 7;
if modbits == 0b00 && mmm == 0b110 {
+ instr.disp = read_num(words, 2)? as u16 as u32;
return Ok(OperandSpec::DispU16);
}
match mmm {
@@ -8994,21 +8996,34 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
// sure hope these aren't backwards huh
OperandCode::AL_Xb => {
instruction.regs[0] = RegSpec::al();
- instruction.regs[1] = RegSpec::esi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::esi();
+ } else {
+ instruction.regs[1] = RegSpec::si();
+ }
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = OperandSpec::Deref;
instruction.mem_size = 1;
instruction.operand_count = 2;
}
OperandCode::Yb_Xb => {
- instruction.operands[0] = OperandSpec::Deref_edi;
- instruction.operands[1] = OperandSpec::Deref_esi;
+ if instruction.prefixes.address_size() {
+ instruction.operands[0] = OperandSpec::Deref_edi;
+ instruction.operands[1] = OperandSpec::Deref_esi;
+ } else {
+ instruction.operands[0] = OperandSpec::Deref_di;
+ instruction.operands[1] = OperandSpec::Deref_si;
+ }
instruction.mem_size = 1;
instruction.operand_count = 2;
}
OperandCode::Yb_AL => {
instruction.regs[0] = RegSpec::al();
- instruction.regs[1] = RegSpec::esi();
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::edi();
+ } else {
+ instruction.regs[1] = RegSpec::di();
+ }
instruction.operands[0] = OperandSpec::Deref;
instruction.operands[1] = OperandSpec::RegRRR;
instruction.mem_size = 1;