aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-07-04 12:20:13 -0700
committeriximeow <me@iximeow.net>2021-07-04 12:36:03 -0700
commit48559b18574b44e2de879a5c641ab602ec22f0d8 (patch)
tree0195cd249c1ce2429b12a14d063447fe96e3283e
parent404cb6e81988ed84a75c89d67bf324409e22a390 (diff)
fix several incorrect tests and docs in 64- and 32-bit modes
-rw-r--r--src/lib.rs34
-rw-r--r--src/long_mode/mod.rs2
-rw-r--r--src/long_mode/vex.rs10
-rw-r--r--src/protected_mode/display.rs12
-rw-r--r--src/protected_mode/mod.rs55
-rw-r--r--src/protected_mode/vex.rs28
-rw-r--r--test/long_mode/mod.rs14
-rw-r--r--test/protected_mode/mod.rs41
8 files changed, 118 insertions, 78 deletions
diff --git a/src/lib.rs b/src/lib.rs
index cb879fd..057c125 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -84,8 +84,8 @@ mod real_mode;
pub use real_mode::Arch as x86_16;
const MEM_SIZE_STRINGS: [&'static str; 64] = [
- "byte", "word", "BUG", "dword", "far", "ptr", "BUG", "qword",
- "far", "mword", "BUG", "BUG", "BUG", "BUG", "BUG", "xmmword",
+ "byte", "word", "BUG", "dword", "ptr", "far", "BUG", "qword",
+ "BUG", "mword", "BUG", "BUG", "BUG", "BUG", "BUG", "xmmword",
"BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG",
"BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "ymmword",
"BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG",
@@ -98,6 +98,11 @@ pub struct MemoryAccessSize {
size: u8,
}
impl MemoryAccessSize {
+ /// return the number of bytes referenced by this memory access.
+ ///
+ /// if the number of bytes cannot be confidently known by the instruction in isolation (as is
+ /// the case for `xsave`/`xrstor`-style "operate on all processor state" instructions), this
+ /// function will return `None`.
pub fn bytes_size(&self) -> Option<u8> {
if self.size == 63 {
None
@@ -106,6 +111,31 @@ impl MemoryAccessSize {
}
}
+ /// a human-friendly label for the number of bytes this memory access references.
+ ///
+ /// there are some differences from size names that may be expected elsewhere; `yaxpeax-x86`
+ /// prefers to use consistent names for a width even if the way those bytes are used varies.
+ ///
+ /// the sizes `yaxpeax-x86` knows are as follows:
+ /// | size (bytes) | name |
+ /// |--------------|------------|
+ /// | 1 | `byte` |
+ /// | 2 | `word` |
+ /// | 4 | `dword` |
+ /// | 6 | `far` |
+ /// | 8 | `qword` |
+ /// | 10 | `mword` |
+ /// | 16 | `xmmword` |
+ /// | 32 | `ymmword` |
+ /// | 64 | `zmmword` |
+ /// | variable | `ptr` |
+ ///
+ /// "mword" refers to an mmx-sized access - 80 bits, or 10 bytes. `mword` is also used for
+ /// 64-bit far calls, because they reference a contiguous ten bytes; two bytes of segment
+ /// selector and eight bytes of address.
+ ///
+ /// "variable" accesses access a number of bytes dependent on the physical processor and its
+ /// operating mode. this is particularly relevant for `xsave`/`xrstor`-style instructions.
pub fn size_name(&self) -> &'static str {
MEM_SIZE_STRINGS[self.size as usize - 1]
}
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 600a81a..79f3fee 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -7673,7 +7673,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe
if opcode == Opcode::CALL || opcode == Opcode::JMP || opcode == Opcode::PUSH || opcode == Opcode::POP {
instruction.mem_size = 8;
} else if opcode == Opcode::CALLF || opcode == Opcode::JMPF {
- instruction.mem_size = 9;
+ instruction.mem_size = 10;
}
}
instruction.opcode = opcode;
diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs
index 67c4965..5695b17 100644
--- a/src/long_mode/vex.rs
+++ b/src/long_mode/vex.rs
@@ -411,7 +411,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
instruction.opcode = if modrm & 0xc0 == 0xc0 {
Opcode::VMOVHLPS
} else {
- instruction.mem_size = 4;
+ instruction.mem_size = 8;
Opcode::VMOVLPS
};
instruction.regs[0] =
@@ -1925,7 +1925,7 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
} else {
VEXOperandCode::G_V_E_xmm
}),
- 0xDA => (Opcode::VPMINSW, if L {
+ 0xDA => (Opcode::VPMINUB, if L {
VEXOperandCode::G_V_E_ymm
} else {
VEXOperandCode::G_V_E_xmm
@@ -3201,12 +3201,12 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
VEXOperandCode::G_E_xmm_imm8
}),
0x0A => (Opcode::VROUNDSS, if L {
- VEXOperandCode::G_V_E_ymm_imm8
+ VEXOperandCode::G_V_E_xmm_imm8
} else {
VEXOperandCode::G_V_E_xmm_imm8
}),
0x0B => (Opcode::VROUNDSD, if L {
- VEXOperandCode::G_V_E_ymm_imm8
+ VEXOperandCode::G_V_E_xmm_imm8
} else {
VEXOperandCode::G_V_E_xmm_imm8
}),
@@ -3269,7 +3269,7 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
return Err(DecodeError::InvalidOpcode);
} else {
(Opcode::VINSERTF128, if L {
- VEXOperandCode::G_V_E_ymm_imm8
+ VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8
} else {
instruction.opcode = Opcode::Invalid;
return Err(DecodeError::InvalidOpcode);
diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs
index baca1a2..c5892c2 100644
--- a/src/protected_mode/display.rs
+++ b/src/protected_mode/display.rs
@@ -1328,7 +1328,7 @@ const MNEMONICS: &[&'static str] = &[
"loopnz",
"loopz",
"loop",
- "jrcxz",
+ "jecxz",
"pusha",
"popa",
"bound",
@@ -1337,8 +1337,8 @@ const MNEMONICS: &[&'static str] = &[
"aaa",
"das",
"daa",
- "amx",
- "adx",
+ "aam",
+ "aad",
"movdir64b",
"movdiri",
"aesdec128kl",
@@ -2332,8 +2332,8 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::AAS |
Opcode::DAS |
Opcode::DAA |
- Opcode::ADX |
- Opcode::AMX |
+ Opcode::AAD |
+ Opcode::AAM |
Opcode::KADDB |
Opcode::KANDB |
Opcode::KANDNB |
@@ -2403,7 +2403,7 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::LOOPNZ |
Opcode::LOOPZ |
Opcode::LOOP |
- Opcode::JRCXZ |
+ Opcode::JECXZ |
Opcode::CALL |
Opcode::CALLF |
Opcode::JMP |
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index 3678bf8..a6ad2ee 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -888,7 +888,7 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[
"eflags",
];
-/// high-level register classes in an x86 machine, such as "8-byte general purpose", "xmm", "x87",
+/// high-level register classes in an x86 machine, such as "4-byte general purpose", "xmm", "x87",
/// and so on. constants in this module are useful for inspecting the register class of a decoded
/// instruction. as an example:
/// ```
@@ -2078,7 +2078,7 @@ pub enum Opcode {
LOOPNZ,
LOOPZ,
LOOP,
- JRCXZ,
+ JECXZ,
PUSHA,
POPA,
@@ -2088,8 +2088,8 @@ pub enum Opcode {
AAA,
DAS,
DAA,
- AMX,
- ADX,
+ AAM,
+ AAD,
// started shipping in Tremont, 2020 sept 23
MOVDIR64B,
@@ -5471,8 +5471,8 @@ const OPCODES: [OpcodeRecord; 256] = [
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd1_Ev_1),
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd2_Eb_CL),
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd3_Ev_CL),
- OpcodeRecord(Interpretation::Instruction(Opcode::AMX), OperandCode::Ib),
- OpcodeRecord(Interpretation::Instruction(Opcode::ADX), OperandCode::Ib),
+ OpcodeRecord(Interpretation::Instruction(Opcode::AAM), OperandCode::Ib),
+ OpcodeRecord(Interpretation::Instruction(Opcode::AAD), OperandCode::Ib),
OpcodeRecord(Interpretation::Instruction(Opcode::SALC), OperandCode::Nothing),
// XLAT
OpcodeRecord(Interpretation::Instruction(Opcode::XLAT), OperandCode::Nothing),
@@ -5496,7 +5496,7 @@ const OPCODES: [OpcodeRecord; 256] = [
OpcodeRecord(Interpretation::Instruction(Opcode::LOOPNZ), OperandCode::Ibs),
OpcodeRecord(Interpretation::Instruction(Opcode::LOOPZ), OperandCode::Ibs),
OpcodeRecord(Interpretation::Instruction(Opcode::LOOP), OperandCode::Ibs),
- OpcodeRecord(Interpretation::Instruction(Opcode::JRCXZ), OperandCode::Ibs),
+ OpcodeRecord(Interpretation::Instruction(Opcode::JECXZ), OperandCode::Ibs),
OpcodeRecord(Interpretation::Instruction(Opcode::IN), OperandCode::AL_Ib),
OpcodeRecord(Interpretation::Instruction(Opcode::IN), OperandCode::AX_Ib),
OpcodeRecord(Interpretation::Instruction(Opcode::OUT), OperandCode::Ib_AL),
@@ -5721,19 +5721,35 @@ fn read_M_16bit<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpea
}
},
0b01 => {
- instr.disp = read_num(words, 1)?;
+ instr.disp = read_num(words, 1)? as i8 as i32 as u32;
if mmm > 3 {
- Ok(OperandSpec::RegDisp)
+ if instr.disp != 0 {
+ Ok(OperandSpec::RegDisp)
+ } else {
+ Ok(OperandSpec::Deref)
+ }
} else {
- Ok(OperandSpec::RegIndexBaseDisp)
+ if instr.disp != 0 {
+ Ok(OperandSpec::RegIndexBaseDisp)
+ } else {
+ Ok(OperandSpec::RegIndexBase)
+ }
}
},
0b10 => {
- instr.disp = read_num(words, 2)?;
+ instr.disp = read_num(words, 2)? as i16 as i32 as u32;
if mmm > 3 {
- Ok(OperandSpec::RegDisp)
+ if instr.disp != 0 {
+ Ok(OperandSpec::RegDisp)
+ } else {
+ Ok(OperandSpec::Deref)
+ }
} else {
- Ok(OperandSpec::RegIndexBaseDisp)
+ if instr.disp != 0 {
+ Ok(OperandSpec::RegIndexBaseDisp)
+ } else {
+ Ok(OperandSpec::RegIndexBase)
+ }
}
},
_ => {
@@ -7528,7 +7544,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe
if opcode == Opcode::CALL || opcode == Opcode::JMP || opcode == Opcode::PUSH || opcode == Opcode::POP {
instruction.mem_size = 4;
} else if opcode == Opcode::CALLF || opcode == Opcode::JMPF {
- instruction.mem_size = 5;
+ instruction.mem_size = 6;
}
}
instruction.opcode = opcode;
@@ -7782,6 +7798,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
instruction.regs[0] = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 };
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = read_E_xmm(words, instruction, modrm)?;
+ if instruction.opcode == Opcode::CVTTSD2SI || instruction.opcode == Opcode::CVTSD2SI {
+ instruction.regs[0].bank = RegisterBank::D;
+ }
if instruction.operands[1] != OperandSpec::RegMMM {
if [Opcode::PMOVSXBQ, Opcode::PMOVZXBQ].contains(&instruction.opcode) {
instruction.mem_size = 2;
@@ -8462,7 +8481,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
}
7 => {
instruction.opcode = Opcode::RDPID;
- instruction.operands[0] = read_E(words, instruction, modrm, opwidth)?;
+ instruction.operands[0] = read_E(words, instruction, modrm, 4)?;
if instruction.operands[0] != OperandSpec::RegMMM {
return Err(DecodeError::InvalidOperand);
}
@@ -9668,7 +9687,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
}
6 => {
instruction.opcode = Opcode::UMONITOR;
- instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::D);
+ if instruction.prefixes.address_size() {
+ instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::W);
+ } else {
+ instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::D);
+ };
instruction.operands[0] = OperandSpec::RegMMM;
instruction.operand_count = 1;
}
diff --git a/src/protected_mode/vex.rs b/src/protected_mode/vex.rs
index 053d1aa..3550f77 100644
--- a/src/protected_mode/vex.rs
+++ b/src/protected_mode/vex.rs
@@ -412,7 +412,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
instruction.opcode = if modrm & 0xc0 == 0xc0 {
Opcode::VMOVHLPS
} else {
- instruction.mem_size = 4;
+ instruction.mem_size = 8;
Opcode::VMOVLPS
};
instruction.regs[0] =
@@ -1854,7 +1854,7 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
} else {
VEXOperandCode::G_V_E_xmm
}),
- 0xDA => (Opcode::VPMINSW, if L {
+ 0xDA => (Opcode::VPMINUB, if L {
VEXOperandCode::G_V_E_ymm
} else {
VEXOperandCode::G_V_E_xmm
@@ -3130,12 +3130,12 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
VEXOperandCode::G_E_xmm_imm8
}),
0x0A => (Opcode::VROUNDSS, if L {
- VEXOperandCode::G_V_E_ymm_imm8
+ VEXOperandCode::G_V_E_xmm_imm8
} else {
VEXOperandCode::G_V_E_xmm_imm8
}),
0x0B => (Opcode::VROUNDSD, if L {
- VEXOperandCode::G_V_E_ymm_imm8
+ VEXOperandCode::G_V_E_xmm_imm8
} else {
VEXOperandCode::G_V_E_xmm_imm8
}),
@@ -3171,14 +3171,7 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
} else {
VEXOperandCode::Ev_G_xmm_imm8
}),
- 0x16 => if instruction.prefixes.vex_unchecked().w() {
- (Opcode::VPEXTRQ, if L {
- instruction.opcode = Opcode::Invalid;
- return Err(DecodeError::InvalidOpcode);
- } else {
- VEXOperandCode::Ev_G_xmm_imm8
- })
- } else {
+ 0x16 => {
(Opcode::VPEXTRD, if L {
instruction.opcode = Opcode::Invalid;
return Err(DecodeError::InvalidOpcode);
@@ -3198,7 +3191,7 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
return Err(DecodeError::InvalidOpcode);
} else {
(Opcode::VINSERTF128, if L {
- VEXOperandCode::G_V_E_ymm_imm8
+ VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8
} else {
instruction.opcode = Opcode::Invalid;
return Err(DecodeError::InvalidOpcode);
@@ -3232,14 +3225,7 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
} else {
VEXOperandCode::G_V_E_xmm_imm8
}),
- 0x22 => if instruction.prefixes.vex_unchecked().w() {
- (Opcode::VPINSRQ, if L {
- instruction.opcode = Opcode::Invalid;
- return Err(DecodeError::InvalidOpcode);
- } else {
- VEXOperandCode::G_V_xmm_Ev_imm8
- })
- } else {
+ 0x22 => {
(Opcode::VPINSRD, if L {
instruction.opcode = Opcode::Invalid;
return Err(DecodeError::InvalidOpcode);
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index d33a4ec..6c2cdc9 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1218,7 +1218,7 @@ fn test_control_flow() {
test_display(&[0x66, 0xff, 0xe0], "jmp rax");
test_display(&[0x67, 0xff, 0xe0], "jmp rax");
test_invalid(&[0xff, 0xd8]);
- test_display(&[0xff, 0x18], "callf far [rax]");
+ test_display(&[0xff, 0x18], "callf mword [rax]");
test_display(&[0xe0, 0x12], "loopnz 0x12");
test_display(&[0xe1, 0x12], "loopz 0x12");
test_display(&[0xe2, 0x12], "loop 0x12");
@@ -1489,9 +1489,9 @@ fn test_vex() {
test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x09, 0b11_001_010, 0x77]);
test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x09, 0b11_001_010, 0x77]);
test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x0a, 0b11_001_010, 0x77], "vroundss xmm9, xmm8, xmm10, 0x77");
- test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0a, 0b11_001_010, 0x77], "vroundss ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0a, 0b11_001_010, 0x77], "vroundss xmm9, xmm8, xmm10, 0x77");
test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x0b, 0b11_001_010, 0x77], "vroundsd xmm9, xmm8, xmm10, 0x77");
- test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0b, 0b11_001_010, 0x77], "vroundsd ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0b, 0b11_001_010, 0x77], "vroundsd xmm9, xmm8, xmm10, 0x77");
test_instr(&[0xc4, 0b000_00011, 0b1_0111_001, 0x0f, 0b11_001_010, 0x77], "vpalignr xmm9, xmm8, xmm10, 0x77");
test_instr(&[0xc4, 0b000_00011, 0b1_0111_101, 0x0f, 0b11_001_010, 0x77], "vpalignr ymm9, ymm8, ymm10, 0x77");
@@ -1517,7 +1517,7 @@ fn test_vex() {
test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x17, 0b00_001_010, 0x77]);
test_invalid(&[0xc4, 0b000_00011, 0b1_0111_001, 0x18, 0b11_001_010, 0x77]);
- test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x18, 0b11_001_010, 0x77], "vinsertf128 ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x18, 0b11_001_010, 0x77], "vinsertf128 ymm9, ymm8, xmm10, 0x77");
test_invalid(&[0xc4, 0b000_00011, 0b1_0111_101, 0x18, 0b11_001_010, 0x77]);
test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x19, 0b11_001_010, 0x77], "vextractf128 xmm10, ymm9, 0x77");
test_invalid(&[0xc4, 0b000_00011, 0b0_1111_001, 0x19, 0b11_001_010, 0x77]);
@@ -1853,7 +1853,7 @@ fn test_vex() {
test_invalid(&[0xc4, 0b000_00001, 0b0_0111_011, 0x12, 0b00_001_010]);
test_invalid(&[0xc4, 0b000_00001, 0b0_0111_111, 0x12, 0b00_001_010]);
test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x12, 0b11_001_010], "vmovhlps xmm9, xmm8, xmm10");
- test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x12, 0b00_001_010], "vmovlps xmm9, xmm8, dword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x12, 0b00_001_010], "vmovlps xmm9, xmm8, qword [r10]");
test_invalid(&[0xc4, 0b000_00001, 0b1_0111_100, 0x12, 0b11_001_010]);
test_invalid(&[0xc4, 0b000_00001, 0b1_0111_111, 0x12, 0b11_001_010]);
test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x12, 0b00_001_010], "vmovsldup xmm9, xmmword [r10]");
@@ -2269,8 +2269,8 @@ fn test_vex() {
test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xd9, 0b11_001_010], "vpsubusw xmm9, xmm8, xmm10");
test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd9, 0b11_001_010], "vpsubusw ymm9, ymm8, ymm10");
- test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xda, 0b11_001_010], "vpminsw xmm9, xmm8, xmm10");
- test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xda, 0b11_001_010], "vpminsw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xda, 0b11_001_010], "vpminub xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xda, 0b11_001_010], "vpminub ymm9, ymm8, ymm10");
test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xdb, 0b11_001_010], "vpand xmm9, xmm8, xmm10");
test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xdb, 0b11_001_010], "vpand ymm9, ymm8, ymm10");
test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xdc, 0b11_001_010], "vpaddusb xmm9, xmm8, xmm10");
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index 76876e3..dd52cfe 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -247,12 +247,12 @@ fn test_sse2() {
test_instr(&[0x66, 0x0f, 0x2b, 0x0f], "movntpd xmmword [edi], xmm1");
test_instr(&[0x66, 0x0f, 0x2c, 0xcf], "cvttpd2pi mm1, xmm7");
test_instr(&[0x66, 0x0f, 0x2c, 0x0f], "cvttpd2pi mm1, xmmword [edi]");
- test_instr(&[0xf2, 0x0f, 0x2c, 0xcf], "cvttsd2si xmm1, xmm7");
- test_instr(&[0xf2, 0x0f, 0x2c, 0x0f], "cvttsd2si xmm1, qword [edi]");
+ test_instr(&[0xf2, 0x0f, 0x2c, 0xcf], "cvttsd2si ecx, xmm7");
+ test_instr(&[0xf2, 0x0f, 0x2c, 0x0f], "cvttsd2si ecx, qword [edi]");
test_instr(&[0x66, 0x0f, 0x2d, 0xcf], "cvtpd2pi mm1, xmm7");
test_instr(&[0x66, 0x0f, 0x2d, 0x0f], "cvtpd2pi mm1, xmmword [edi]");
- test_instr(&[0xf2, 0x0f, 0x2d, 0xcf], "cvtsd2si xmm1, xmm7");
- test_instr(&[0xf2, 0x0f, 0x2d, 0x0f], "cvtsd2si xmm1, qword [edi]");
+ test_instr(&[0xf2, 0x0f, 0x2d, 0xcf], "cvtsd2si ecx, xmm7");
+ test_instr(&[0xf2, 0x0f, 0x2d, 0x0f], "cvtsd2si ecx, qword [edi]");
test_instr(&[0x66, 0x0f, 0x2e, 0xcf], "ucomisd xmm1, xmm7");
test_instr(&[0x66, 0x0f, 0x2e, 0x0f], "ucomisd xmm1, qword [edi]");
test_instr(&[0x66, 0x0f, 0x2f, 0xcf], "comisd xmm1, xmm7");
@@ -1108,7 +1108,7 @@ fn test_control_flow() {
test_display(&[0xe0, 0x12], "loopnz 0x12");
test_display(&[0xe1, 0x12], "loopz 0x12");
test_display(&[0xe2, 0x12], "loop 0x12");
- test_display(&[0xe3, 0x12], "jrcxz 0x12");
+ test_display(&[0xe3, 0x12], "jecxz 0x12");
test_display(&[0xc3], "ret");
}
@@ -1291,6 +1291,7 @@ fn test_misc() {
test_display(&[0x66, 0x0f, 0xae, 0x37], "clwb zmmword [edi]");
test_display(&[0x66, 0x0f, 0xae, 0xf7], "tpause edi");
test_display(&[0xf3, 0x0f, 0xae, 0xf1], "umonitor ecx");
+ test_display(&[0x67, 0xf3, 0x0f, 0xae, 0xf1], "umonitor cx");
test_display(&[0xf2, 0x0f, 0xae, 0xf1], "umwait ecx");
test_display(&[0x66, 0x0f, 0x38, 0x80, 0x2f], "invept ebp, xmmword [edi]");
test_invalid(&[0x0f, 0x38, 0x80, 0x2f]);
@@ -1371,9 +1372,9 @@ fn test_vex() {
test_invalid(&[0xc4, 0b110_00011, 0b0_0111_001, 0x09, 0b11_001_010, 0x77]);
test_invalid(&[0xc4, 0b110_00011, 0b0_0111_101, 0x09, 0b11_001_010, 0x77]);
test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x0a, 0b11_001_010, 0x77], "vroundss xmm1, xmm0, xmm2, 0x77");
- test_instr(&[0xc4, 0b110_00011, 0b0_0111_101, 0x0a, 0b11_001_010, 0x77], "vroundss ymm1, ymm0, ymm2, 0x77");
+ test_instr(&[0xc4, 0b110_00011, 0b0_0111_101, 0x0a, 0b11_001_010, 0x77], "vroundss xmm1, xmm0, xmm2, 0x77");
test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x0b, 0b11_001_010, 0x77], "vroundsd xmm1, xmm0, xmm2, 0x77");
- test_instr(&[0xc4, 0b110_00011, 0b0_0111_101, 0x0b, 0b11_001_010, 0x77], "vroundsd ymm1, ymm0, ymm2, 0x77");
+ test_instr(&[0xc4, 0b110_00011, 0b0_0111_101, 0x0b, 0b11_001_010, 0x77], "vroundsd xmm1, xmm0, xmm2, 0x77");
test_instr(&[0xc4, 0b110_00011, 0b1_0111_001, 0x0f, 0b11_001_010, 0x77], "vpalignr xmm1, xmm0, xmm2, 0x77");
test_instr(&[0xc4, 0b110_00011, 0b1_0111_101, 0x0f, 0b11_001_010, 0x77], "vpalignr ymm1, ymm0, ymm2, 0x77");
@@ -1390,16 +1391,16 @@ fn test_vex() {
test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x16, 0b00_001_010, 0x77], "vpextrd dword [edx], xmm1, 0x77");
test_invalid(&[0xc4, 0b110_00011, 0b0_0111_001, 0x16, 0b00_001_010, 0x77]);
test_invalid(&[0xc4, 0b110_00011, 0b0_1111_101, 0x16, 0b00_001_010, 0x77]);
- test_instr(&[0xc4, 0b110_00011, 0b1_1111_001, 0x16, 0b11_001_010, 0x77], "vpextrq edx, xmm1, 0x77");
+ test_instr(&[0xc4, 0b110_00011, 0b1_1111_001, 0x16, 0b11_001_010, 0x77], "vpextrd edx, xmm1, 0x77");
test_invalid(&[0xc4, 0b110_00011, 0b1_0111_001, 0x16, 0b00_001_010, 0x77]);
- test_instr(&[0xc4, 0b110_00011, 0b1_1111_001, 0x16, 0b00_001_010, 0x77], "vpextrq qword [edx], xmm1, 0x77");
+ test_instr(&[0xc4, 0b110_00011, 0b1_1111_001, 0x16, 0b00_001_010, 0x77], "vpextrd dword [edx], xmm1, 0x77");
test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x17, 0b11_001_010, 0x77], "vextractps edx, xmm1, 0x77");
test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x17, 0b00_001_010, 0x77], "vextractps dword [edx], xmm1, 0x77");
test_invalid(&[0xc4, 0b110_00011, 0b0_1111_101, 0x17, 0b00_001_010, 0x77]);
test_invalid(&[0xc4, 0b110_00011, 0b0_0111_101, 0x17, 0b00_001_010, 0x77]);
test_invalid(&[0xc4, 0b110_00011, 0b1_0111_001, 0x18, 0b11_001_010, 0x77]);
- test_instr(&[0xc4, 0b110_00011, 0b0_0111_101, 0x18, 0b11_001_010, 0x77], "vinsertf128 ymm1, ymm0, ymm2, 0x77");
+ test_instr(&[0xc4, 0b110_00011, 0b0_0111_101, 0x18, 0b11_001_010, 0x77], "vinsertf128 ymm1, ymm0, xmm2, 0x77");
test_invalid(&[0xc4, 0b110_00011, 0b1_0111_101, 0x18, 0b11_001_010, 0x77]);
test_instr(&[0xc4, 0b110_00011, 0b0_1111_101, 0x19, 0b11_001_010, 0x77], "vextractf128 xmm2, ymm1, 0x77");
test_invalid(&[0xc4, 0b110_00011, 0b0_1111_001, 0x19, 0b11_001_010, 0x77]);
@@ -1420,8 +1421,8 @@ fn test_vex() {
test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x22, 0b11_001_010, 0x77], "vpinsrd xmm1, xmm0, edx, 0x77");
test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x22, 0b00_001_010, 0x77], "vpinsrd xmm1, xmm0, dword [edx], 0x77");
test_invalid(&[0xc4, 0b110_00011, 0b0_0111_101, 0x22, 0b00_001_010, 0x77]);
- test_instr(&[0xc4, 0b110_00011, 0b1_0111_001, 0x22, 0b11_001_010, 0x77], "vpinsrq xmm1, xmm0, edx, 0x77");
- test_instr(&[0xc4, 0b110_00011, 0b1_0111_001, 0x22, 0b00_001_010, 0x77], "vpinsrq xmm1, xmm0, qword [edx], 0x77");
+ test_instr(&[0xc4, 0b110_00011, 0b1_0111_001, 0x22, 0b11_001_010, 0x77], "vpinsrd xmm1, xmm0, edx, 0x77");
+ test_instr(&[0xc4, 0b110_00011, 0b1_0111_001, 0x22, 0b00_001_010, 0x77], "vpinsrd xmm1, xmm0, dword [edx], 0x77");
test_invalid(&[0xc4, 0b110_00011, 0b1_0111_101, 0x22, 0b00_001_010, 0x77]);
test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x40, 0b11_001_010, 0x77], "vdpps xmm1, xmm0, xmm2, 0x77");
@@ -1737,7 +1738,7 @@ fn test_vex() {
test_invalid(&[0xc4, 0b110_00001, 0b0_0111_011, 0x12, 0b00_001_010]);
test_invalid(&[0xc4, 0b110_00001, 0b0_0111_111, 0x12, 0b00_001_010]);
test_instr(&[0xc4, 0b110_00001, 0b1_0111_000, 0x12, 0b11_001_010], "vmovhlps xmm1, xmm0, xmm2");
- test_instr(&[0xc4, 0b110_00001, 0b1_0111_000, 0x12, 0b00_001_010], "vmovlps xmm1, xmm0, dword [edx]");
+ test_instr(&[0xc4, 0b110_00001, 0b1_0111_000, 0x12, 0b00_001_010], "vmovlps xmm1, xmm0, qword [edx]");
test_invalid(&[0xc4, 0b110_00001, 0b1_0111_100, 0x12, 0b11_001_010]);
test_invalid(&[0xc4, 0b110_00001, 0b1_0111_111, 0x12, 0b11_001_010]);
test_instr(&[0xc4, 0b110_00001, 0b1_1111_010, 0x12, 0b00_001_010], "vmovsldup xmm1, xmmword [edx]");
@@ -2131,8 +2132,8 @@ fn test_vex() {
test_avx2(&[0xc4, 0b110_00001, 0b1_0111_101, 0xd8, 0b11_001_010], "vpsubusb ymm1, ymm0, ymm2");
test_instr(&[0xc4, 0b110_00001, 0b1_0111_001, 0xd9, 0b11_001_010], "vpsubusw xmm1, xmm0, xmm2");
test_avx2(&[0xc4, 0b110_00001, 0b1_0111_101, 0xd9, 0b11_001_010], "vpsubusw ymm1, ymm0, ymm2");
- test_instr(&[0xc4, 0b110_00001, 0b0_0111_001, 0xda, 0b11_001_010], "vpminsw xmm1, xmm0, xmm2");
- test_avx2(&[0xc4, 0b110_00001, 0b0_0111_101, 0xda, 0b11_001_010], "vpminsw ymm1, ymm0, ymm2");
+ test_instr(&[0xc4, 0b110_00001, 0b0_0111_001, 0xda, 0b11_001_010], "vpminub xmm1, xmm0, xmm2");
+ test_avx2(&[0xc4, 0b110_00001, 0b0_0111_101, 0xda, 0b11_001_010], "vpminub ymm1, ymm0, ymm2");
test_instr(&[0xc4, 0b110_00001, 0b1_0111_001, 0xdb, 0b11_001_010], "vpand xmm1, xmm0, xmm2");
test_avx2(&[0xc4, 0b110_00001, 0b1_0111_101, 0xdb, 0b11_001_010], "vpand ymm1, ymm0, ymm2");
test_instr(&[0xc4, 0b110_00001, 0b1_0111_001, 0xdc, 0b11_001_010], "vpaddusb xmm1, xmm0, xmm2");
@@ -2387,12 +2388,12 @@ fn only_32bit() {
test_display(&[0x2f], "das");
test_display(&[0x37], "aaa");
test_display(&[0x3f], "aas");
- test_display(&[0xd4, 0x01], "amx 0x1");
- test_display(&[0xd4, 0x0a], "amx 0xa"); // aka "aam"
- test_display(&[0xd5, 0x01], "adx 0x1");
- test_display(&[0xd5, 0x0a], "adx 0xa"); // aka "aad"
+ test_display(&[0xd4, 0x01], "aam 0x1");
+ test_display(&[0xd4, 0x0a], "aam 0xa");
+ test_display(&[0xd5, 0x01], "aad 0x1");
+ test_display(&[0xd5, 0x0a], "aad 0xa");
- test_display(&[0xc5, 0x78, 0x10], "lds edi, ptr [eax + 0x10]");
+ test_display(&[0xc5, 0x78, 0x10], "lds edi, far [eax + 0x10]");
test_display(&[0x66, 0xc5, 0x78, 0x10], "lds di, dword [eax + 0x10]");
}