aboutsummaryrefslogtreecommitdiff
path: root/src/long_mode/vex.rs
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-05-23 19:37:58 -0700
committeriximeow <me@iximeow.net>2020-05-23 19:37:58 -0700
commit9b965525afced37e99543e3a412218207a41e793 (patch)
treed82cb429eb2b7f230249769f935bc24d60a6158f /src/long_mode/vex.rs
parenta0fd5a24cb0aa0b697f680c451d928cefe8323b4 (diff)
add SHA, BMI1, and BMI2, complete XSAVE extension support
additionally: cmpcxchg{8,16}b, rdrand, rdseed, rdpid, {rd,wr}{fs,gs}base
Diffstat (limited to 'src/long_mode/vex.rs')
-rw-r--r--src/long_mode/vex.rs182
1 files changed, 179 insertions, 3 deletions
diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs
index fe50c4e..cf30622 100644
--- a/src/long_mode/vex.rs
+++ b/src/long_mode/vex.rs
@@ -83,6 +83,10 @@ enum VEXOperandCode {
Ed_G_xmm,
G_xmm_Ed,
G_xmm_Eq,
+ G_E_V,
+ G_V_E,
+ G_E_Ib,
+ BMI1_F3,
}
#[inline(never)]
@@ -694,6 +698,88 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst
instruction.operands[2] = OperandSpec::RegVex;
Ok(())
}
+ VEXOperandCode::G_V_E => {
+ let modrm = read_modrm(bytes, length)?;
+ let (opwidth, bank) = if instruction.prefixes.vex().w() {
+ (8, RegisterBank::Q)
+ } else {
+ (4, RegisterBank::D)
+ };
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), bank);
+ instruction.vex_reg.bank = bank;
+ let mem_oper = read_E(bytes, instruction, modrm, opwidth, length)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = OperandSpec::RegVex;
+ instruction.operands[2] = mem_oper;
+ instruction.operand_count = 3;
+ Ok(())
+ }
+ VEXOperandCode::G_E_V => {
+ let modrm = read_modrm(bytes, length)?;
+ let (opwidth, bank) = if instruction.prefixes.vex().w() {
+ (8, RegisterBank::Q)
+ } else {
+ (4, RegisterBank::D)
+ };
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), bank);
+ instruction.vex_reg.bank = bank;
+ let mem_oper = read_E(bytes, instruction, modrm, opwidth, length)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = mem_oper;
+ instruction.operands[2] = OperandSpec::RegVex;
+ instruction.operand_count = 3;
+ Ok(())
+ }
+ VEXOperandCode::G_E_Ib => {
+ let modrm = read_modrm(bytes, length)?;
+ let (opwidth, bank) = if instruction.prefixes.vex().w() {
+ (8, RegisterBank::Q)
+ } else {
+ (4, RegisterBank::D)
+ };
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), bank);
+ let mem_oper = read_E(bytes, instruction, modrm, opwidth, length)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = mem_oper;
+ instruction.imm = read_imm_unsigned(bytes, 1, length)?;
+ instruction.operands[2] = OperandSpec::ImmI8;
+ instruction.operand_count = 3;
+ Ok(())
+ }
+ VEXOperandCode::BMI1_F3 => {
+ let modrm = read_modrm(bytes, length)?;
+ instruction.opcode = match (modrm >> 3) & 7 {
+ 1 => {
+ Opcode::BLSR
+ }
+ 2 => {
+ Opcode::BLSMSK
+ }
+ 3 => {
+ Opcode::BLSI
+ }
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ }
+ };
+ let (opwidth, bank) = if instruction.prefixes.vex().w() {
+ (8, RegisterBank::Q)
+ } else {
+ (4, RegisterBank::D)
+ };
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), bank);
+ let mem_oper = read_E(bytes, instruction, modrm, opwidth, length)?;
+ instruction.operands[0] = OperandSpec::RegVex;
+ instruction.operands[1] = mem_oper;
+ instruction.operand_count = 2;
+ instruction.vex_reg.bank = bank;
+ Ok(())
+ }
VEXOperandCode::G_E_ymm_imm8 |
VEXOperandCode::G_V_E_xmm_xmm4 |
@@ -2270,15 +2356,92 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &
} else {
VEXOperandCode::G_V_E_xmm
}),
+ 0xF7 => (Opcode::SHLX, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_V
+ }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ }
+ }
+ } else if let VEXOpcodePrefix::PrefixF2 = p {
+ match opc {
+ 0xF5 => (Opcode::PDEP, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_V_E
+ }),
+ 0xF6 => (Opcode::MULX, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_V_E
+ }),
+ 0xF7 => (Opcode::SHRX, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_V
+ }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ }
+ }
+ } else if let VEXOpcodePrefix::PrefixF3 = p {
+ match opc {
+ 0xF5 => (Opcode::PEXT, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_V_E
+ }),
+ 0xF7 => (Opcode::SARX, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_V
+ }),
_ => {
instruction.opcode = Opcode::Invalid;
return Err(DecodeError::InvalidOpcode);
}
}
} else {
- // the only VEX* 0f38 instructions have an implied 66 prefix.
- instruction.opcode = Opcode::Invalid;
- return Err(DecodeError::InvalidOpcode);
+ match opc {
+ 0xF2 => (Opcode::ANDN, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_V_E
+ }),
+ 0xF3 => (Opcode::Invalid, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::BMI1_F3
+ }),
+ 0xF5 => (Opcode::BZHI, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_V
+ }),
+ 0xF7 => (Opcode::BEXTR, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_V
+ }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ }
+ }
}
}
VEXOpcodeMap::Map0F3A => {
@@ -2504,6 +2667,19 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &
return Err(DecodeError::InvalidOpcode);
}
}
+ } else if let VEXOpcodePrefix::PrefixF2 = p {
+ match opc {
+ 0xF0 => (Opcode::RORX, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_Ib
+ }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ }
+ }
} else {
// the only VEX* 0f3a instructions have an implied 66 prefix.
instruction.opcode = Opcode::Invalid;