diff options
| -rw-r--r-- | CHANGELOG | 1 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 13 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 13 | ||||
| -rw-r--r-- | src/real_mode/mod.rs | 13 | ||||
| -rw-r--r-- | test/long_mode/operand.rs | 8 | ||||
| -rw-r--r-- | test/protected_mode/operand.rs | 8 | ||||
| -rw-r--r-- | test/real_mode/operand.rs | 8 |
7 files changed, 61 insertions, 3 deletions
@@ -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 5e8dafa..264e2d3 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -4028,6 +4028,7 @@ enum OperandCase { G_Ev_xmm_Ib, G_E_mm_Ib, MOVDIR64B, + MASKMOVDQU, ModRM_0x0f00, ModRM_0x0f01, ModRM_0x0f0d, @@ -4384,6 +4385,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 { @@ -6924,6 +6926,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 = 16; + }, OperandCase::Gv_Ev_Ib => { instruction.imm = read_imm_signed(words, 1)? as u64; @@ -7145,6 +7155,7 @@ fn read_operands< instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; instruction.regs[0].num &= 0b111; + instruction.mem_size = 8; instruction.operand_count = 2; }, OperandCase::E_G_q => { @@ -10720,7 +10731,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/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index eeb2942..0cb6674 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -3943,6 +3943,7 @@ enum OperandCase { G_E_mm_Ib, AbsFar, MOVDIR64B, + MASKMOVDQU, ModRM_0x0f00, ModRM_0x0f01, ModRM_0x0f0d, @@ -4287,6 +4288,7 @@ enum OperandCode { AbsFar = OperandCodeBuilder::new().operand_case(OperandCase::AbsFar).bits(), ModRM_0xc4 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc4).bits(), ModRM_0xc5 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc5).bits(), + MASKMOVDQU = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::MASKMOVDQU).bits(), } fn base_opcode_map(v: u8) -> Opcode { @@ -6804,6 +6806,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 = 16; + } OperandCase::Gv_Ev_Ib => { instruction.imm = read_imm_signed(words, 1)? as u32; @@ -7023,6 +7033,7 @@ fn read_operands< instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; instruction.regs[0].num &= 0b111; + instruction.mem_size = 8; instruction.operand_count = 2; }, OperandCase::E_G_q => { @@ -10555,7 +10566,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/src/real_mode/mod.rs b/src/real_mode/mod.rs index cab3fb1..930d450 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -3973,6 +3973,7 @@ enum OperandCase { G_E_mm_Ib, AbsFar, MOVDIR64B, + MASKMOVDQU, ModRM_0x0f00, ModRM_0x0f01, ModRM_0x0f0d, @@ -4317,6 +4318,7 @@ enum OperandCode { AbsFar = OperandCodeBuilder::new().operand_case(OperandCase::AbsFar).bits(), ModRM_0xc4 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc4).bits(), ModRM_0xc5 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc5).bits(), + MASKMOVDQU = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::MASKMOVDQU).bits(), } fn base_opcode_map(v: u8) -> Opcode { @@ -6843,6 +6845,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 = 16; + }, OperandCase::Gv_Ev_Ib => { instruction.imm = read_imm_signed(words, 1)? as u32; @@ -7062,6 +7072,7 @@ fn read_operands< instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; instruction.regs[0].num &= 0b111; + instruction.mem_size = 8; instruction.operand_count = 2; }, OperandCase::E_G_q => { @@ -10597,7 +10608,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..379cc7b 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(), "qword"); + + // "maskmovdqu xmm0, xmm1" + assert_eq!(mem_size_of(&[0x66, 0x4f, 0x0f, 0xf7, 0xc1]).size_name(), "xmmword"); + assert_eq!(mem_size_of(&[0x67, 0x66, 0x0f, 0xf7, 0xc1]).size_name(), "xmmword"); } #[test] diff --git a/test/protected_mode/operand.rs b/test/protected_mode/operand.rs index 70dcadb..cfda896 100644 --- a/test/protected_mode/operand.rs +++ b/test/protected_mode/operand.rs @@ -25,6 +25,14 @@ fn memory_widths() { assert_eq!(mem_size_of(&[0x32, 0x00]).size_name(), "byte"); assert_eq!(mem_size_of(&[0x66, 0x33, 0x00]).size_name(), "word"); assert_eq!(mem_size_of(&[0x33, 0x00]).size_name(), "dword"); + + // "maskmovq mm0, mm1" + assert_eq!(mem_size_of(&[0x0f, 0xf7, 0xc1]).size_name(), "qword"); + assert_eq!(mem_size_of(&[0x67, 0x0f, 0xf7, 0xc1]).size_name(), "qword"); + + // "maskmovdqu xmm0, xmm1" + assert_eq!(mem_size_of(&[0x66, 0x0f, 0xf7, 0xc1]).size_name(), "xmmword"); + assert_eq!(mem_size_of(&[0x67, 0x66, 0x0f, 0xf7, 0xc1]).size_name(), "xmmword"); } #[test] diff --git a/test/real_mode/operand.rs b/test/real_mode/operand.rs index cdf5113..68eea48 100644 --- a/test/real_mode/operand.rs +++ b/test/real_mode/operand.rs @@ -36,4 +36,12 @@ fn test_implied_memory_width() { assert_eq!(mem_size_of(&[0x0f, 0xa8]), Some(2)); // pop gs assert_eq!(mem_size_of(&[0x0f, 0xa9]), Some(2)); + + // "maskmovq mm0, mm1" + assert_eq!(mem_size_of(&[0x0f, 0xf7, 0xc1]), Some(8)); + assert_eq!(mem_size_of(&[0x67, 0x0f, 0xf7, 0xc1]), Some(8)); + + // "maskmovdqu xmm0, xmm1" + assert_eq!(mem_size_of(&[0x66, 0x0f, 0xf7, 0xc1]), Some(16)); + assert_eq!(mem_size_of(&[0x67, 0x66, 0x0f, 0xf7, 0xc1]), Some(16)); } |
