aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-08-09 02:07:52 -0700
committeriximeow <me@iximeow.net>2020-08-09 02:07:52 -0700
commit4e61dc5e3ea882022e815814ed324fa7515923a6 (patch)
tree7dd1d008fffcc1c23bf14822c4cd1eb56f4a8cf9
parentdcea0a9548a91bb3726bf64364a9e37fc0f7f204 (diff)
support four-reg operand forms, new tests
-rw-r--r--src/long_mode/mod.rs7
-rw-r--r--src/long_mode/vex.rs28
-rw-r--r--test/long_mode/mod.rs9
3 files changed, 44 insertions, 0 deletions
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<T: Iterator<Item=u8>>(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]