aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG1
-rw-r--r--src/long_mode/mod.rs13
-rw-r--r--test/long_mode/operand.rs8
3 files changed, 21 insertions, 1 deletions
diff --git a/CHANGELOG b/CHANGELOG
index c513e0a..9ae9fd9 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -19,6 +19,7 @@
zero-extend, whereas writing to "ax" does not imply any zero-extension. mov reg-to-seg
is unchanged and uses a 16-bit form for source GPR.
* reject 0f0d prefetch/nop with a register operand, which was incorrectly decoded before.
+* maskmovq and maskmovdqu now have their implicit memory access size reported correctly.
## 2.0.0
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 6433464..5d7180e 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -4036,6 +4036,7 @@ pub enum OperandCase {
G_Ev_xmm_Ib,
G_E_mm_Ib,
MOVDIR64B,
+ MASKMOVDQU,
ModRM_0x0f00,
ModRM_0x0f01,
ModRM_0x0f0d,
@@ -4392,6 +4393,7 @@ enum OperandCode {
PMOVX_E_G_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_E_G_xmm).bits(),
G_Ev_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_Ev_xmm_Ib).bits(),
G_E_mm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_mm_Ib).bits(),
+ MASKMOVDQU = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::MASKMOVDQU).bits(),
}
fn base_opcode_map(v: u8) -> Opcode {
@@ -6932,6 +6934,14 @@ fn read_operands<
instruction.regs[0].bank = RegisterBank::X;
instruction.regs[1].bank = RegisterBank::X;
},
+ OperandCase::MASKMOVDQU => {
+ if mem_oper != OperandSpec::RegMMM {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.regs[0].bank = RegisterBank::X;
+ instruction.regs[1].bank = RegisterBank::X;
+ instruction.mem_size = if instruction.prefixes.address_size() { 4 } else { 8 };
+ },
OperandCase::Gv_Ev_Ib => {
instruction.imm =
read_imm_signed(words, 1)? as u64;
@@ -7151,6 +7161,7 @@ fn read_operands<
instruction.regs[1].bank = RegisterBank::MM;
instruction.regs[1].num &= 0b111;
instruction.regs[0].num &= 0b111;
+ instruction.mem_size = if !instruction.prefixes.address_size() { 8 } else { 4 };
instruction.operand_count = 2;
},
OperandCase::E_G_q => {
@@ -10728,7 +10739,7 @@ const OPERAND_SIZE_0F_CODES: [OpcodeRecord; 256] = [
OpcodeRecord::new(Interpretation::Instruction(Opcode::PMULUDQ), OperandCode::G_E_xmm),
OpcodeRecord::new(Interpretation::Instruction(Opcode::PMADDWD), OperandCode::G_E_xmm),
OpcodeRecord::new(Interpretation::Instruction(Opcode::PSADBW), OperandCode::G_E_xmm),
- OpcodeRecord::new(Interpretation::Instruction(Opcode::MASKMOVDQU), OperandCode::G_U_xmm),
+ OpcodeRecord::new(Interpretation::Instruction(Opcode::MASKMOVDQU), OperandCode::MASKMOVDQU),
OpcodeRecord::new(Interpretation::Instruction(Opcode::PSUBB), OperandCode::G_E_xmm),
OpcodeRecord::new(Interpretation::Instruction(Opcode::PSUBW), OperandCode::G_E_xmm),
OpcodeRecord::new(Interpretation::Instruction(Opcode::PSUBD), OperandCode::G_E_xmm),
diff --git a/test/long_mode/operand.rs b/test/long_mode/operand.rs
index 9f594b5..fe64fb6 100644
--- a/test/long_mode/operand.rs
+++ b/test/long_mode/operand.rs
@@ -29,6 +29,14 @@ fn memory_widths() {
assert_eq!(mem_size_of(&[0x48, 0x33, 0x00]).size_name(), "qword");
assert_eq!(mem_size_of(&[0x6a, 0x00]).size_name(), "qword");
assert_eq!(mem_size_of(&[0x68, 0x00, 0x00, 0x00, 0x00]).size_name(), "qword");
+
+ // "maskmovq mm0, mm1"
+ assert_eq!(mem_size_of(&[0x4f, 0x0f, 0xf7, 0xc1]).size_name(), "qword");
+ assert_eq!(mem_size_of(&[0x67, 0x0f, 0xf7, 0xc1]).size_name(), "dword");
+
+ // "maskmovdqu xmm0, xmm1"
+ assert_eq!(mem_size_of(&[0x66, 0x4f, 0x0f, 0xf7, 0xc1]).size_name(), "qword");
+ assert_eq!(mem_size_of(&[0x67, 0x66, 0x0f, 0xf7, 0xc1]).size_name(), "dword");
}
#[test]