diff options
author | iximeow <me@iximeow.net> | 2020-05-23 19:37:58 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2020-05-23 19:37:58 -0700 |
commit | 9b965525afced37e99543e3a412218207a41e793 (patch) | |
tree | d82cb429eb2b7f230249769f935bc24d60a6158f /src/long_mode/vex.rs | |
parent | a0fd5a24cb0aa0b697f680c451d928cefe8323b4 (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.rs | 182 |
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; |