aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-07-04 15:03:50 -0700
committeriximeow <me@iximeow.net>2021-07-04 15:03:50 -0700
commit6f91a743a8e6bf720abdb0748bc6755f280b59de (patch)
treedd8cac68e96ec0c6c6143238a062cee0990611a5
parent723cbb61c1a8a7aa03fa4e2fc9081c5eb16f53e8 (diff)
support vpscatter{dd,dq,qd,qq}
-rw-r--r--src/shared/evex.in50
-rw-r--r--src/shared/generated_evex.in5
-rw-r--r--test/long_mode/mod.rs8
3 files changed, 62 insertions, 1 deletions
diff --git a/src/shared/evex.in b/src/shared/evex.in
index 6446b52..8a1e4eb 100644
--- a/src/shared/evex.in
+++ b/src/shared/evex.in
@@ -5013,6 +5013,56 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
instruction.mem_size = 8;
}
}
+ generated::EVEXOperandCode::Mvector_Mask_G_LL => {
+ check_mask_reg(instruction)?;
+ deny_z(instruction)?;
+
+ // we can't just `deny_vex_reg` because vp is used as bit 5 for the index register
+ if instruction.regs[3].num & 0b1111 != 0 {
+ return Err(DecodeError::InvalidOperand);
+ }
+
+ let modrm = read_modrm(words)?;
+ set_rrr(instruction, modrm);
+ let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;
+ instruction.regs[2].num |= instruction.regs[3].num & 0b10000;
+ instruction.operands[0] = mem_oper;
+ instruction.operands[1] = OperandSpec::RegVex;
+ instruction.regs[3].bank = RegisterBank::K;
+ instruction.regs[3].num = instruction.prefixes.evex_unchecked().mask_reg();
+ instruction.operands[2] = OperandSpec::RegRRR;
+ instruction.operand_count = 2;
+
+ if mem_oper == OperandSpec::RegMMM {
+ return Err(DecodeError::InvalidOperand);
+ }
+
+ if instruction.prefixes.evex_unchecked().lp() {
+ if instruction.prefixes.evex_unchecked().vex().l() {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.regs[0].bank = RegisterBank::Z;
+ instruction.regs[2].bank = RegisterBank::Z;
+ } else if instruction.prefixes.evex_unchecked().vex().l() {
+ instruction.regs[0].bank = RegisterBank::Y;
+ instruction.regs[2].bank = RegisterBank::Y;
+ } else {
+ instruction.regs[0].bank = RegisterBank::X;
+ instruction.regs[2].bank = RegisterBank::X;
+ }
+
+ if instruction.prefixes.evex_unchecked().vex().w() {
+ if instruction.opcode == Opcode::VPSCATTERDD {
+ instruction.opcode = Opcode::VPSCATTERDQ;
+ } else if instruction.opcode == Opcode::VPSCATTERQD {
+ instruction.opcode = Opcode::VPSCATTERQQ;
+ }
+ instruction.mem_size = 8;
+ } else {
+ instruction.mem_size = 4;
+ }
+ instruction.operand_count = 3;
+ }
generated::EVEXOperandCode::Nothing => {}
}
Ok(())
diff --git a/src/shared/generated_evex.in b/src/shared/generated_evex.in
index 7f2d192..0acdcab 100644
--- a/src/shared/generated_evex.in
+++ b/src/shared/generated_evex.in
@@ -502,6 +502,7 @@ const EVEX_OPCODES: [super::Opcode; 496] = [
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub(crate) enum EVEXOperandCode {
+ Mvector_Mask_G_LL,
Gm_U_zmm_imm8_sae_W0,
Gm_V_E_LL_sae_W1,
Gm_U_zmm_sae_W0,
@@ -839,7 +840,7 @@ const EVEX_66_0f: [(u8, [(super::Opcode, EVEXOperandCode); 4]); 100] = [
(0xfe, [(super::Opcode::VPADDD, EVEXOperandCode::Gm_V_E_LL_bcast_W0), (super::Opcode::VPADDD, EVEXOperandCode::Gm_V_E_LL_bcast_W0), (super::Opcode::VPADDD, EVEXOperandCode::Gm_V_E_LL_bcast_W0), (super::Opcode::Invalid, EVEXOperandCode::Nothing)]),
];
-const EVEX_66_0f38: [(u8, [(super::Opcode, EVEXOperandCode); 4]); 141] = [
+const EVEX_66_0f38: [(u8, [(super::Opcode, EVEXOperandCode); 4]); 143] = [
(0x00, [(super::Opcode::VPSHUFB, EVEXOperandCode::Gm_V_E_LL), (super::Opcode::VPSHUFB, EVEXOperandCode::Gm_V_E_LL), (super::Opcode::VPSHUFB, EVEXOperandCode::Gm_V_E_LL), (super::Opcode::Invalid, EVEXOperandCode::Nothing)]),
(0x04, [(super::Opcode::VPMADDUBSW, EVEXOperandCode::Gm_V_E_LL), (super::Opcode::VPMADDUBSW, EVEXOperandCode::Gm_V_E_LL), (super::Opcode::VPMADDUBSW, EVEXOperandCode::Gm_V_E_LL), (super::Opcode::Invalid, EVEXOperandCode::Nothing)]),
(0x0b, [(super::Opcode::VPMULHRSW, EVEXOperandCode::Gm_V_E_LL), (super::Opcode::VPMULHRSW, EVEXOperandCode::Gm_V_E_LL), (super::Opcode::VPMULHRSW, EVEXOperandCode::Gm_V_E_LL), (super::Opcode::Invalid, EVEXOperandCode::Nothing)]),
@@ -948,6 +949,8 @@ const EVEX_66_0f38: [(u8, [(super::Opcode, EVEXOperandCode); 4]); 141] = [
(0x9d, [(super::Opcode::VFNMADD132SS, EVEXOperandCode::Gm_V_Ed_LL_sae), (super::Opcode::VFNMADD132SS, EVEXOperandCode::Gm_V_Ed_LL_sae), (super::Opcode::VFNMADD132SS, EVEXOperandCode::Gm_V_Ed_LL_sae), (super::Opcode::VFNMADD132SS, EVEXOperandCode::Gm_V_Ed_LL_sae)]),
(0x9e, [(super::Opcode::VFNMSUB132PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFNMSUB132PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFNMSUB132PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFNMSUB132PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast)]),
(0x9f, [(super::Opcode::VFNMSUB132SS, EVEXOperandCode::Gm_V_Ed_LL_sae), (super::Opcode::VFNMSUB132SS, EVEXOperandCode::Gm_V_Ed_LL_sae), (super::Opcode::VFNMSUB132SS, EVEXOperandCode::Gm_V_Ed_LL_sae), (super::Opcode::VFNMSUB132SS, EVEXOperandCode::Gm_V_Ed_LL_sae)]),
+ (0xa0, [(super::Opcode::VPSCATTERDD, EVEXOperandCode::Mvector_Mask_G_LL), (super::Opcode::VPSCATTERDD, EVEXOperandCode::Mvector_Mask_G_LL), (super::Opcode::VPSCATTERDD, EVEXOperandCode::Mvector_Mask_G_LL), (super::Opcode::Invalid, EVEXOperandCode::Nothing)]),
+ (0xa1, [(super::Opcode::VPSCATTERQD, EVEXOperandCode::Mvector_Mask_G_LL), (super::Opcode::VPSCATTERQD, EVEXOperandCode::Mvector_Mask_G_LL), (super::Opcode::VPSCATTERQD, EVEXOperandCode::Mvector_Mask_G_LL), (super::Opcode::Invalid, EVEXOperandCode::Nothing)]),
(0xa6, [(super::Opcode::VFMADDSUB213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFMADDSUB213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFMADDSUB213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFMADDSUB213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast)]),
(0xa7, [(super::Opcode::VFMSUBADD213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFMSUBADD213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFMSUBADD213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFMSUBADD213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast)]),
(0xa8, [(super::Opcode::VFMADD213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFMADD213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFMADD213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast), (super::Opcode::VFMADD213PS, EVEXOperandCode::Gm_V_E_LL_sae_bcast)]),
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 4868f39..ae79761 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1427,6 +1427,14 @@ fn evex() {
test_display(&[0x62, 0xf2, 0x7d, 0x48, 0x2a, 0x44, 0x40, 0x01], "vmovntdqa zmm0, zmmword [rax + rax * 2 + 0x40]");
test_display(&[0x62, 0xf2, 0x7d, 0x08, 0x2a, 0x44, 0x40, 0x01], "vmovntdqa xmm0, xmmword [rax + rax * 2 + 0x10]");
test_invalid(&[0x62, 0xf2, 0x7d, 0x1d, 0x66, 0x50, 0x01, 0x11]);
+ test_display(&[0x62, 0x12, 0x7d, 0x06, 0xa0, 0x04, 0x2f], "vpscatterdd dword [r15 + xmm29 * 1], k6, xmm8");
+ test_display(&[0x62, 0x12, 0x7d, 0x06, 0xa0, 0x14, 0x0f], "vpscatterdd dword [r15 + xmm25 * 1], k6, xmm10");
+ test_display(&[0x62, 0x12, 0x7d, 0x26, 0xa0, 0x14, 0x0f], "vpscatterdd dword [r15 + ymm25 * 1], k6, ymm10");
+ test_display(&[0x62, 0x12, 0x7d, 0x46, 0xa0, 0x14, 0x0f], "vpscatterdd dword [r15 + zmm25 * 1], k6, zmm10");
+
+ test_display(&[0x62, 0x12, 0xfd, 0x46, 0xa0, 0x14, 0x0f], "vpscatterdq qword [r15 + zmm25 * 1], k6, zmm10");
+ test_display(&[0x62, 0x12, 0x7d, 0x46, 0xa1, 0x14, 0x0f], "vpscatterqd dword [r15 + zmm25 * 1], k6, zmm10");
+ test_display(&[0x62, 0x12, 0xfd, 0x46, 0xa1, 0x14, 0x0f], "vpscatterqq qword [r15 + zmm25 * 1], k6, zmm10");
}
#[test]