From 4e61dc5e3ea882022e815814ed324fa7515923a6 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 9 Aug 2020 02:07:52 -0700 Subject: support four-reg operand forms, new tests --- src/long_mode/mod.rs | 7 +++++++ src/long_mode/vex.rs | 28 ++++++++++++++++++++++++++++ test/long_mode/mod.rs | 9 +++++++++ 3 files changed, 44 insertions(+) diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 5c431b4..3fcf4ab 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -368,6 +368,7 @@ impl OperandSpec { OperandSpec::RegRRR | OperandSpec::RegMMM | OperandSpec::RegVex | + OperandSpec::Reg4 | OperandSpec::EnterFrameSize | OperandSpec::Nothing => { false @@ -392,6 +393,9 @@ impl Operand { OperandSpec::RegVex => { Operand::Register(inst.vex_reg) } + OperandSpec::Reg4 => { + Operand::Register(RegSpec { num: inst.imm as u8, bank: inst.vex_reg.bank }) + } OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8), OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8), OperandSpec::ImmI16 => Operand::ImmediateI16(inst.imm as i16), @@ -1596,6 +1600,9 @@ enum OperandSpec { RegMMM, // the register selected by vex-vvvv bits RegVex, + // the register selected by a handful of avx2 vex-coded instructions, + // stuffed in imm4. + Reg4, ImmI8, ImmI16, ImmI32, diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs index 8563fc7..7c4e27d 100644 --- a/src/long_mode/vex.rs +++ b/src/long_mode/vex.rs @@ -798,6 +798,34 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 3; Ok(()) } + VEXOperandCode::G_V_E_ymm_ymm4 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), RegisterBank::Y); + instruction.vex_reg.bank = RegisterBank::Y; + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)? >> 4; + instruction.operands[3] = OperandSpec::Reg4; + instruction.operand_count = 4; + Ok(()) + } + VEXOperandCode::G_V_E_xmm_xmm4 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), RegisterBank::X); + instruction.vex_reg.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)? >> 4; + instruction.operands[3] = OperandSpec::Reg4; + instruction.operand_count = 4; + Ok(()) + } VEXOperandCode::G_V_E_xmm_xmm4 | VEXOperandCode::G_V_E_ymm_ymm4 | diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index bd5008c..c56c732 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -1394,6 +1394,15 @@ fn test_vex() { test_instr(&[0xc5, 0xfd, 0xee, 0xd9], "vpmaxsw ymm3, ymm0, ymm1"); test_instr(&[0xc4, 0xe3, 0x7d, 0x19, 0xd1, 0x01], "vextractf128 xmm1, ymm2, 0x1"); test_instr(&[0xc4, 0xc3, 0x75, 0x38, 0x7c, 0x12, 0x05, 0x01], "vinserti128 ymm7, ymm1, [r10 + rdx * 1 + 0x5], 0x1"); + test_instr(&[0xc4, 0xc3, 0x75, 0x42, 0x7c, 0x12, 0x05, 0x61], "vmpsadbw ymm7, ymm1, [r10 + rdx * 1 + 0x5], 0x61"); + test_instr(&[0xc4, 0xc3, 0x75, 0x46, 0x7c, 0x12, 0x05, 0x61], "vperm2i128 ymm7, ymm1, [r10 + rdx * 1 + 0x5], 0x61"); + test_instr(&[0xc4, 0xc3, 0x75, 0x4a, 0x7c, 0x12, 0x05, 0x61], "vblendvps ymm7, ymm1, [r10 + rdx * 1 + 0x5], ymm6"); + test_instr(&[0xc4, 0xc3, 0x71, 0x4a, 0x7c, 0x12, 0x05, 0x61], "vblendvps xmm7, xmm1, [r10 + rdx * 1 + 0x5], xmm6"); + test_instr(&[0xc4, 0xc3, 0x71, 0x4a, 0xcc, 0x61], "vblendvps xmm7, xmm1, xmm12, xmm6"); + test_instr(&[0xc4, 0xc3, 0x75, 0x4b, 0x7c, 0x12, 0x05, 0x61], "vblendvpd ymm7, ymm1, [r10 + rdx * 1 + 0x5], ymm6"); + test_instr(&[0xc4, 0xc3, 0x71, 0x4b, 0x7c, 0x12, 0x05, 0x61], "vblendvpd xmm7, xmm1, [r10 + rdx * 1 + 0x5], xmm6"); + test_instr(&[0xc4, 0xc3, 0x71, 0x4b, 0xcc, 0x61], "vblendvpd xmm7, xmm1, xmm12, xmm6"); + test_instr(&[0xc4, 0xc3, 0x71, 0x4c, 0x7c, 0x12, 0x05, 0x61], "vpblendvb xmm7, xmm1, [r10 + rdx * 1 + 0x5], xmm6"); } #[test] -- cgit v1.1