From 7f0429ad45f748b58658ba41420ca1d0f3784f48 Mon Sep 17 00:00:00 2001 From: iximeow Date: Mon, 28 Jun 2021 22:14:17 -0700 Subject: round out x86_32 support - avx2, avx, memory sizes --- src/long_mode/vex.rs | 12 +- src/protected_mode/display.rs | 2 +- src/protected_mode/mod.rs | 18 +- src/protected_mode/vex.rs | 900 +++++++++++++++++++++++++++++++++--------- test/protected_mode/mod.rs | 46 +-- 5 files changed, 758 insertions(+), 220 deletions(-) diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs index 35f979f..c248eb0 100644 --- a/src/long_mode/vex.rs +++ b/src/long_mode/vex.rs @@ -1036,14 +1036,14 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst 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; if mem_oper != OperandSpec::RegMMM { instruction.mem_size = 32; } - instruction.operands[2] = mem_oper; instruction.operand_count = 3; Ok(()) } - _op @ VEXOperandCode::G_V_E_ymm_imm8 => { + VEXOperandCode::G_V_E_ymm_imm8 => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); @@ -1086,10 +1086,6 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - if mem_oper == OperandSpec::RegMMM { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; @@ -1151,7 +1147,7 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 3; Ok(()) } - _op @ VEXOperandCode::G_V_E_xmm_imm8 => { + VEXOperandCode::G_V_E_xmm_imm8 => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); @@ -1167,7 +1163,7 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 4; Ok(()) } - _op @ VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 => { + VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs index 1964758..acbb43f 100644 --- a/src/protected_mode/display.rs +++ b/src/protected_mode/display.rs @@ -3314,7 +3314,7 @@ impl Instruction { } const MEM_SIZE_STRINGS: [&'static str; 64] = [ - "byte", "word", "BUG", "dword", "far", "BUG", "BUG", "qword", + "byte", "word", "BUG", "dword", "far", "ptr", "BUG", "qword", "BUG", "mword", "BUG", "BUG", "BUG", "BUG", "BUG", "xmmword", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "ymmword", diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 971d7a6..060511b 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -3685,6 +3685,8 @@ impl InstDecoder { Opcode::VPCMPGTD | Opcode::VPCMPGTQ | Opcode::VPCMPGTW | + Opcode::VPCMPESTRI | + Opcode::VPCMPESTRM | Opcode::VPCMPISTRI | Opcode::VPCMPISTRM | Opcode::VPERM2F128 | @@ -7583,10 +7585,10 @@ fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter return Err(DecodeError::InvalidOperand); } if [Opcode::LFS, Opcode::LGS, Opcode::LSS].contains(&instruction.opcode) { - if instruction.prefixes.vex().w() { - instruction.mem_size = 6; - } else { + if instruction.prefixes.operand_size() { instruction.mem_size = 4; + } else { + instruction.mem_size = 6; } } else if [Opcode::ENQCMD, Opcode::ENQCMDS].contains(&instruction.opcode) { instruction.mem_size = 64; @@ -7616,6 +7618,11 @@ fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { RegisterBank::W } else { RegisterBank::D }); instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm, length)?; + if instruction.prefixes.operand_size() { + instruction.mem_size = 4; + } else { + instruction.mem_size = 6; + } } }, OperandCode::ModRM_0xc5 => { @@ -7640,6 +7647,11 @@ fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { RegisterBank::W } else { RegisterBank::D }); instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm, length)?; + if instruction.prefixes.operand_size() { + instruction.mem_size = 4; + } else { + instruction.mem_size = 6; + } } }, OperandCode::G_U_xmm_Ub => { diff --git a/src/protected_mode/vex.rs b/src/protected_mode/vex.rs index d4104cd..d9802d0 100644 --- a/src/protected_mode/vex.rs +++ b/src/protected_mode/vex.rs @@ -39,24 +39,26 @@ enum VEXOperandCode { VMOVSD_10, VMOVSD_11, VMOVSS_11, + VMOVLPS_12, + VMOVHPS_16, E_G_xmm, - U_G_xmm, M_G_xmm, G_M_xmm, G_U_xmm, + Gd_U_xmm, E_G_xmm_imm8, - U_G_xmm_imm8, + Ud_G_xmm_imm8, + Ud_G_xmm, + Ud_G_ymm, E_G_ymm, - U_G_ymm, M_G_ymm, G_E_ymm, G_M_ymm, - G_U_ymm, - E_V_G_ymm, - E_V_G_xmm, + Gd_U_ymm, E_xmm_G_ymm_imm8, Ev_G_xmm_imm8, G_Ex_V_xmm, + G_Ey_V_xmm, G_Ey_V_ymm, G_E_xmm, G_E_xmm_imm8, @@ -64,10 +66,12 @@ enum VEXOperandCode { G_xmm_E_xmm, G_xmm_E_ymm, G_ymm_E_xmm, + G_ymm_M_xmm, G_ymm_E_ymm, G_V_ymm_E_xmm, M_V_G_xmm, M_V_G_ymm, + G_V_xmm_Ed, G_V_E_xmm, G_V_E_xmm_imm8, G_V_E_xmm_xmm4, @@ -76,9 +80,8 @@ enum VEXOperandCode { G_V_E_ymm_ymm4, G_V_M_xmm, G_V_M_ymm, - V_xmm_G_ymm_E_ymm_imm8, G_ymm_V_ymm_E_xmm_imm8, - G_V_xmm_Ew_imm8, + G_V_xmm_Ev_imm8, Eq_G_xmm, Ed_G_xmm, G_xmm_Ed, @@ -86,7 +89,10 @@ enum VEXOperandCode { G_E_V, G_V_E, G_E_Ib, + VCVT_Gd_Ed_xmm, + VCVT_Gd_Eq_xmm, BMI1_F3, + MXCSR, } #[inline(never)] @@ -114,11 +120,12 @@ pub(crate) fn three_byte_vex>(bytes: &mut T, vex_byte_one: }; instruction.vex_reg = RegSpec { bank: RegisterBank::X, - num: ((vex_byte_two >> 3) & 0b0111) ^ 0b0111, // ignore bit 4 in 32-bit mode + num: ((vex_byte_two >> 3) & 0b1111) ^ 0b1111, }; instruction.prefixes.vex_from_c4(vex_byte_one, vex_byte_two); read_vex_instruction(m, bytes, instruction, &mut length, p)?; + instruction.vex_reg.num &= 0b0111; // ignore bit 4 in 32-bit mode instruction.length = length; Ok(()) } @@ -148,6 +155,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst match operand_code { VEXOperandCode::VPS_71 => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLW; @@ -174,7 +185,14 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_71_L => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { + 0b001 => { + instruction.opcode = Opcode::VPSLLW; + } 0b010 => { instruction.opcode = Opcode::VPSRLW; } @@ -200,6 +218,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_72 => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLD; @@ -226,6 +248,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_72_L => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLD; @@ -252,6 +278,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_73 => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLQ; @@ -281,6 +311,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_73_L => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b000 | 0b001 | @@ -349,11 +383,11 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[2] = OperandSpec::RegRRR; match mem_oper { OperandSpec::RegMMM => { - instruction.operands[0] = OperandSpec::RegVex; - instruction.operands[2] = OperandSpec::RegMMM; + instruction.operands[0] = OperandSpec::RegMMM; + instruction.operands[1] = OperandSpec::RegVex; instruction.operand_count = 3; }, other => { @@ -367,11 +401,44 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.mem_size = 8; } instruction.operands[0] = other; + instruction.operands[1] = instruction.operands[2]; instruction.operand_count = 2; } } Ok(()) }, + VEXOperandCode::VMOVLPS_12 => { + let modrm = read_modrm(bytes, length)?; + instruction.opcode = if modrm & 0xc0 == 0xc0 { + Opcode::VMOVHLPS + } else { + instruction.mem_size = 4; + Opcode::VMOVLPS + }; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operand_count = 3; + Ok(()) + } + VEXOperandCode::VMOVHPS_16 => { + let modrm = read_modrm(bytes, length)?; + instruction.opcode = if modrm & 0xc0 == 0xc0 { + Opcode::VMOVLHPS + } else { + instruction.mem_size = 8; + Opcode::VMOVHPS + }; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operand_count = 3; + Ok(()) + } VEXOperandCode::Nothing => { Ok(()) }, @@ -388,7 +455,21 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operands[1] = OperandSpec::RegRRR; instruction.operands[2] = OperandSpec::ImmU8; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = 1; + match instruction.opcode { + Opcode::VPEXTRB => { + instruction.mem_size = 1; + } + Opcode::VPEXTRW => { + instruction.mem_size = 2; + } + Opcode::VEXTRACTPS | + Opcode::VPEXTRD => { + instruction.mem_size = 4; + } + _ => { + instruction.mem_size = 8; + } + } } instruction.operand_count = 3; instruction.imm = read_imm_unsigned(bytes, 1, length)?; @@ -405,6 +486,9 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 8; + } instruction.operand_count = 2; Ok(()) } @@ -419,6 +503,9 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 4; + } instruction.operand_count = 2; Ok(()) } @@ -433,6 +520,9 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 4; + } instruction.operand_count = 2; Ok(()) } @@ -447,14 +537,52 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 4; + } + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::VCVT_Gd_Ed_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 4; + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::E_G_xmm | - _op @ VEXOperandCode::U_G_xmm | - _op @ VEXOperandCode::M_G_xmm | - _op @ VEXOperandCode::E_G_xmm_imm8 | - _op @ VEXOperandCode::U_G_xmm_imm8 => { + VEXOperandCode::VCVT_Gd_Eq_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 8; + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + op @ VEXOperandCode::E_G_xmm | + op @ VEXOperandCode::M_G_xmm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); @@ -463,12 +591,103 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + match (op, mem_oper) { + (VEXOperandCode::E_G_xmm, OperandSpec::RegMMM) => { + /* this is the only accepted operand */ + } + (VEXOperandCode::M_G_xmm, OperandSpec::RegMMM) => { + return Err(DecodeError::InvalidOperand); + } + (VEXOperandCode::M_G_xmm, _) | // otherwise it's memory-constrained and a memory operand + (_, _) => { // ... or unconstrained + /* and this is always accepted */ + } + } + if mem_oper != OperandSpec::RegMMM { + if instruction.opcode == Opcode::VMOVLPD || instruction.opcode == Opcode::VMOVHPD || instruction.opcode == Opcode::VMOVHPS { + instruction.mem_size = 8; + } else { + instruction.mem_size = 16; + } + } instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::E_xmm_G_ymm_imm8 => { + VEXOperandCode::Ud_G_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::Ud_G_ymm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::Ud_G_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + Ok(()) + } + VEXOperandCode::E_G_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 16; + } + instruction.operand_count = 3; + Ok(()) + } + VEXOperandCode::E_xmm_G_ymm_imm8 => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); @@ -481,28 +700,87 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operands[1] = OperandSpec::RegRRR; instruction.imm = read_imm_unsigned(bytes, 1, length)?; instruction.operands[2] = OperandSpec::ImmU8; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 16; + } instruction.operand_count = 3; Ok(()) } - _op @ VEXOperandCode::G_M_xmm | - _op @ VEXOperandCode::G_U_xmm | - _op @ VEXOperandCode::G_E_xmm | - _op @ VEXOperandCode::G_E_xmm_imm8 => { + VEXOperandCode::Gd_U_xmm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::Gd_U_ymm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + + op @ VEXOperandCode::G_M_xmm | + op @ VEXOperandCode::G_U_xmm | + op @ VEXOperandCode::G_E_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + match (op, modrm & 0xc0) { + (VEXOperandCode::G_U_xmm, 0xc0) => { + /* this is the only accepted operand */ + } + (VEXOperandCode::G_U_xmm, _) | + (VEXOperandCode::G_M_xmm, 0xc0) => { + return Err(DecodeError::InvalidOperand); + } + (VEXOperandCode::G_M_xmm, _) | // otherwise it's memory-constrained and a memory operand + (_, _) => { // ... or unconstrained + /* and this is always accepted */ + } + } + instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + if [Opcode::VBROADCASTSS, Opcode::VUCOMISS, Opcode::VCOMISS].contains(&instruction.opcode) { + instruction.mem_size = 4; + } else if [Opcode::VMOVDDUP, Opcode::VUCOMISD, Opcode::VCOMISD, Opcode::VCVTPS2PD, Opcode::VMOVQ].contains(&instruction.opcode) { + instruction.mem_size = 8; + } else { + instruction.mem_size = 16; + }; + } instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::G_xmm_E_xmm => { + VEXOperandCode::G_xmm_E_xmm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); @@ -513,10 +791,13 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 16; + } instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::G_xmm_E_ymm => { + VEXOperandCode::G_xmm_E_ymm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); @@ -527,24 +808,42 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 32; + } instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::G_ymm_E_xmm => { + op @ VEXOperandCode::G_ymm_M_xmm | + op @ VEXOperandCode::G_ymm_E_xmm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 == 0xc0 { + if let VEXOperandCode::G_ymm_M_xmm = op { + return Err(DecodeError::InvalidOperand); + } + } instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + if [Opcode::VBROADCASTSS].contains(&instruction.opcode) { + instruction.mem_size = 4; + } else if [Opcode::VBROADCASTSD].contains(&instruction.opcode) { + instruction.mem_size = 8; + } else { + instruction.mem_size = 16; + } + } instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::G_ymm_E_ymm => { + VEXOperandCode::G_ymm_E_ymm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); @@ -555,46 +854,76 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 32; + } instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::E_G_ymm | - _op @ VEXOperandCode::U_G_ymm | - _op @ VEXOperandCode::M_G_ymm => { + op @ VEXOperandCode::E_G_ymm | + op @ VEXOperandCode::M_G_ymm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(bytes, length)?; + match (op, modrm & 0xc0) { + (VEXOperandCode::M_G_ymm, 0xc0) => { + return Err(DecodeError::InvalidOperand); + } + (VEXOperandCode::M_G_ymm, _) | // otherwise it's memory-constrained and a memory operand + (_, _) => { // ... or unconstrained + /* and this is always accepted */ + } + } instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 32; + } instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::G_M_ymm | - _op @ VEXOperandCode::G_U_ymm | - _op @ VEXOperandCode::G_E_ymm => { + op @ VEXOperandCode::G_M_ymm | + op @ VEXOperandCode::G_E_ymm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(bytes, length)?; + match (op, modrm & 0xc0) { + (VEXOperandCode::G_M_ymm, 0xc0) => { + return Err(DecodeError::InvalidOperand); + } + (VEXOperandCode::G_M_ymm, _) | // otherwise it's memory-constrained and a memory operand + (_, _) => { // ... or unconstrained + /* and this is always accepted */ + } + } instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 32; + } instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::G_V_E_ymm | - _op @ VEXOperandCode::G_V_M_ymm => { + op @ VEXOperandCode::G_V_E_ymm | + op @ VEXOperandCode::G_V_M_ymm => { let modrm = read_modrm(bytes, length)?; + if let VEXOperandCode::G_V_M_ymm = op { + if modrm & 0xc0 == 0xc0 { + return Err(DecodeError::InvalidOperand); + } + } instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); instruction.vex_reg.bank = RegisterBank::Y; @@ -602,10 +931,13 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 32; + } instruction.operand_count = 3; Ok(()) } - _op @ VEXOperandCode::G_V_E_ymm_imm8 => { + VEXOperandCode::G_V_E_ymm_imm8 => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); @@ -616,12 +948,17 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operands[2] = mem_oper; instruction.imm = read_imm_unsigned(bytes, 1, length)?; instruction.operands[3] = OperandSpec::ImmU8; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 32; + } instruction.operand_count = 4; Ok(()) } - _op @ VEXOperandCode::E_V_G_ymm | - _op @ VEXOperandCode::M_V_G_ymm => { + VEXOperandCode::M_V_G_ymm => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 == 0xc0 { + return Err(DecodeError::InvalidOperand); + } instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); instruction.vex_reg.bank = RegisterBank::Y; @@ -629,6 +966,9 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = OperandSpec::RegRRR; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 32; + } instruction.operand_count = 3; Ok(()) } @@ -673,49 +1013,59 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 3; Ok(()) } - _op @ VEXOperandCode::G_V_E_xmm_imm8 => { + VEXOperandCode::G_V_xmm_Ed => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; - instruction.imm = read_imm_unsigned(bytes, 1, length)?; - instruction.operands[3] = OperandSpec::ImmU8; - instruction.operand_count = 4; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 4; + } + instruction.operand_count = 3; Ok(()) } - _op @ VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 => { + VEXOperandCode::G_V_E_xmm_imm8 => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); - instruction.vex_reg.bank = RegisterBank::Y; + RegSpec::from_parts((modrm >> 3) & 7, 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)?; instruction.operands[3] = OperandSpec::ImmU8; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 16; + } instruction.operand_count = 4; Ok(()) } - _op @ VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 => { + VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); - let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; - instruction.operands[0] = OperandSpec::RegVex; - instruction.operands[1] = OperandSpec::RegRRR; + instruction.vex_reg.bank = RegisterBank::Y; + 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)?; instruction.operands[3] = OperandSpec::ImmU8; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 16; + } instruction.operand_count = 4; Ok(()) } - _op @ VEXOperandCode::E_V_G_xmm | - _op @ VEXOperandCode::M_V_G_xmm => { + VEXOperandCode::M_V_G_xmm => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 == 0xc0 { + return Err(DecodeError::InvalidOperand); + } + instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; @@ -744,6 +1094,22 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 3; Ok(()) } + VEXOperandCode::G_Ey_V_xmm => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.vex_reg.bank = RegisterBank::X; + instruction.sib_index.bank = RegisterBank::Y; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operands[2] = OperandSpec::RegVex; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 4; + } + instruction.operand_count = 3; + Ok(()) + } VEXOperandCode::G_Ey_V_ymm => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = @@ -831,18 +1197,64 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst }; let (opwidth, bank) = (4, RegisterBank::D); instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, bank); - let mem_oper = read_E(bytes, instruction, modrm, opwidth, length)?; - instruction.operands[0] = OperandSpec::RegVex; + RegSpec::from_parts((modrm >> 3) & 7, 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; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = opwidth; + } + instruction.vex_reg.bank = bank; + Ok(()) + } + VEXOperandCode::MXCSR => { + let modrm = read_modrm(bytes, length)?; + instruction.opcode = match (modrm >> 3) & 7 { + 2 => { + Opcode::VLDMXCSR + } + 3 => { + Opcode::VSTMXCSR + } + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + }; + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + if let OperandSpec::RegMMM = mem_oper { + return Err(DecodeError::InvalidOperand); + } + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 4; + } + instruction.operands[0] = mem_oper; + instruction.operand_count = 1; + Ok(()) + } + VEXOperandCode::G_E_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; - instruction.operand_count = 2; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = opwidth; + instruction.mem_size = 16; } - instruction.vex_reg.bank = bank; + instruction.operand_count = 3; Ok(()) } VEXOperandCode::G_E_ymm_imm8 => { + if instruction.vex_reg.num != 0 { + return Err(DecodeError::InvalidOperand); + } let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); @@ -906,7 +1318,7 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 3; Ok(()) } - VEXOperandCode::G_V_xmm_Ew_imm8 => { + VEXOperandCode::G_V_xmm_Ev_imm8 => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); @@ -919,7 +1331,21 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.imm = read_imm_unsigned(bytes, 1, length)?; instruction.operands[3] = OperandSpec::ImmI8; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = 2; + match instruction.opcode { + Opcode::VPINSRB => { + instruction.mem_size = 1; + } + Opcode::VPINSRW => { + instruction.mem_size = 2; + } + Opcode::VINSERTPS | + Opcode::VPINSRD => { + instruction.mem_size = 4; + } + _ => { + instruction.mem_size = 8; + } + } } instruction.operand_count = 4; Ok(()) @@ -948,9 +1374,12 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & match opc { 0x10 => (Opcode::VMOVUPS, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), 0x11 => (Opcode::VMOVUPS, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), - // ugh -// 0x12 => (Opcode::VMOVHLPS, ..), -// 0x12 => (Opcode::VMOVLPS, ..), + 0x12 => (Opcode::Invalid, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::VMOVLPS_12 + }), 0x13 => (Opcode::VMOVLPS, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -967,9 +1396,12 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm }), - // ugh -// 0x16 => (Opcode::VMOVHPS, ..), -// 0x16 => (Opcode::VMOVLHPS, ..), + 0x16 => (Opcode::Invalid, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::VMOVHPS_16 + }), 0x17 => (Opcode::VMOVHPS, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -994,9 +1426,9 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0x2e => (Opcode::VUCOMISS, VEXOperandCode::G_E_xmm), 0x2f => (Opcode::VCOMISS, VEXOperandCode::G_E_xmm), 0x50 => (Opcode::VMOVMSKPS, if L { - VEXOperandCode::U_G_ymm + VEXOperandCode::Ud_G_ymm } else { - VEXOperandCode::U_G_xmm + VEXOperandCode::Ud_G_xmm }), 0x51 => (Opcode::VSQRTPS, if L { VEXOperandCode::G_E_ymm @@ -1044,7 +1476,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm }), 0x5A => (Opcode::VCVTPS2PD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), @@ -1074,6 +1506,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm }), 0x77 => (Opcode::VZEROUPPER, VEXOperandCode::Nothing), + 0xAE => (Opcode::Invalid, if L { + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::MXCSR + }), 0xC2 => (Opcode::VCMPPS, if L { VEXOperandCode::G_V_E_ymm_imm8 } else { @@ -1126,12 +1563,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm }), - 0x16 => (Opcode::VMOVHPD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_M_xmm - }), + 0x16 => (Opcode::VMOVHPD, VEXOperandCode::G_V_M_xmm), 0x17 => (Opcode::VMOVHPD, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -1156,9 +1588,9 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0x2e => (Opcode::VUCOMISD, VEXOperandCode::G_E_xmm), 0x2f => (Opcode::VCOMISD, VEXOperandCode::G_E_xmm), 0x50 => (Opcode::VMOVMSKPD, if L { - VEXOperandCode::G_U_ymm + VEXOperandCode::Gd_U_ymm } else { - VEXOperandCode::G_U_xmm + VEXOperandCode::Gd_U_xmm }), 0x51 => (Opcode::VSQRTPD, if L { VEXOperandCode::G_E_ymm @@ -1296,11 +1728,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm }), 0x6E => if instruction.prefixes.vex().w() { - (Opcode::VMOVQ, if L { + (Opcode::VMOVD, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_xmm_Eq + VEXOperandCode::G_xmm_Ed }) } else { (Opcode::VMOVD, if L { @@ -1361,11 +1793,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm }), 0x7E => if instruction.prefixes.vex().w() { - (Opcode::VMOVQ, if L { + (Opcode::VMOVD, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::Eq_G_xmm + VEXOperandCode::Ed_G_xmm }) } else { (Opcode::VMOVD, if L { @@ -1381,26 +1813,26 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::E_G_xmm }), 0xC2 => (Opcode::VCMPPD, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_E_ymm_imm8 } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_V_E_xmm_imm8 }), 0xC4 => (Opcode::VPINSRW, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_xmm_Ew_imm8 + VEXOperandCode::G_V_xmm_Ev_imm8 }), 0xC5 => (Opcode::VPEXTRW, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::U_G_xmm_imm8 + VEXOperandCode::Ud_G_xmm_imm8 }), 0xC6 => (Opcode::VSHUFPD, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_E_ymm_imm8 } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_V_E_xmm_imm8 }), 0xD0 => (Opcode::VADDSUBPD, if L { VEXOperandCode::G_V_E_ymm @@ -1408,17 +1840,17 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm }), 0xD1 => (Opcode::VPSRLW, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), 0xD2 => (Opcode::VPSRLD, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), 0xD3 => (Opcode::VPSRLQ, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), @@ -1439,9 +1871,9 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0xD7 => (Opcode::VPMOVMSKB, if L { - VEXOperandCode::U_G_ymm + VEXOperandCode::Ud_G_ymm } else { - VEXOperandCode::U_G_xmm + VEXOperandCode::Ud_G_xmm }), 0xD8 => (Opcode::VPSUBUSB, if L { VEXOperandCode::G_V_E_ymm @@ -1453,6 +1885,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm }), + 0xDA => (Opcode::VPMINSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), 0xDB => (Opcode::VPAND, if L { VEXOperandCode::G_V_E_ymm } else { @@ -1592,7 +2029,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_xmm + VEXOperandCode::G_U_xmm }), 0xF8 => (Opcode::VPSUBB, if L { VEXOperandCode::G_V_E_ymm @@ -1645,24 +2082,24 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0x2a => (Opcode::VCVTSI2SD, if instruction.prefixes.vex().w() { - VEXOperandCode::G_V_E_xmm // 64-bit last operand + VEXOperandCode::G_V_xmm_Ed // 32-bit last operand } else { - VEXOperandCode::G_V_E_xmm // 32-bit last operand + VEXOperandCode::G_V_xmm_Ed // 32-bit last operand }), 0x2c => (Opcode::VCVTTSD2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit + VEXOperandCode::VCVT_Gd_Eq_xmm } else { - VEXOperandCode::G_E_xmm // 32-bit + VEXOperandCode::VCVT_Gd_Eq_xmm }), 0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit + VEXOperandCode::VCVT_Gd_Eq_xmm } else { - VEXOperandCode::G_E_xmm // 32-bit + VEXOperandCode::VCVT_Gd_Eq_xmm }), 0x51 => (Opcode::VSQRTSD, VEXOperandCode::G_V_E_xmm), 0x58 => (Opcode::VADDSD, VEXOperandCode::G_V_E_xmm), 0x59 => (Opcode::VMULSD, VEXOperandCode::G_V_E_xmm), - 0x5a => (Opcode::CVTSD2SS, VEXOperandCode::G_V_E_xmm), + 0x5a => (Opcode::VCVTSD2SS, VEXOperandCode::G_V_E_xmm), 0x5c => (Opcode::VSUBSD, VEXOperandCode::G_V_E_xmm), 0x5d => (Opcode::VMINSD, VEXOperandCode::G_V_E_xmm), 0x5e => (Opcode::VDIVSD, VEXOperandCode::G_V_E_xmm), @@ -1696,7 +2133,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0xf0 => (Opcode::VLDDQU, if L { VEXOperandCode::G_M_ymm } else { - VEXOperandCode::G_M_ymm + VEXOperandCode::G_M_xmm }), _ => { instruction.opcode = Opcode::Invalid; @@ -1711,19 +2148,19 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0x12 => (Opcode::VMOVSLDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), 0x16 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), 0x2a => (Opcode::VCVTSI2SS, if instruction.prefixes.vex().w() { - VEXOperandCode::G_V_E_xmm // 64-bit last operand + VEXOperandCode::G_V_xmm_Ed } else { - VEXOperandCode::G_V_E_xmm // 32-bit last operand + VEXOperandCode::G_V_xmm_Ed }), 0x2c => (Opcode::VCVTTSS2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit + VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit } else { - VEXOperandCode::G_E_xmm // 32-bit + VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit }), - 0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit + 0x2d => (Opcode::VCVTSS2SI, if instruction.prefixes.vex().w() { + VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit } else { - VEXOperandCode::G_E_xmm // 32-bit + VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit }), 0x51 => (Opcode::VSQRTSS, VEXOperandCode::G_V_E_xmm), 0x52 => (Opcode::VRSQRTSS, VEXOperandCode::G_V_E_xmm), @@ -1737,7 +2174,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0x5e => (Opcode::VDIVSS, VEXOperandCode::G_V_E_xmm), 0x5f => (Opcode::VMAXSS, VEXOperandCode::G_V_E_xmm), 0x6f => (Opcode::VMOVDQU, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), -// 0x70 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm_imm8 } else { VEXOperandCode::G_E_xmm_imm8 }), + 0x70 => (Opcode::VPSHUFHW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), 0x7e => (Opcode::VMOVQ, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), 0x7f => (Opcode::VMOVDQU, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), 0xc2 => (Opcode::VCMPSS, VEXOperandCode::G_V_E_xmm_imm8), @@ -1841,7 +2282,10 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0x16 => (Opcode::VPERMPS, if L { - VEXOperandCode::G_V_E_xmm + if instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } + VEXOperandCode::G_V_E_ymm } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -1851,18 +2295,28 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_E_xmm }), - 0x18 => (Opcode::VBROADCASTSS, if L { - VEXOperandCode::G_E_ymm + 0x18 => if instruction.prefixes.vex().w() { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_xmm - }), - 0x19 => (Opcode::VBROADCASTSD, if L { - VEXOperandCode::G_E_ymm + (Opcode::VBROADCASTSS, if L { + VEXOperandCode::G_ymm_E_xmm + } else { + VEXOperandCode::G_E_xmm + }) + }, + 0x19 => if instruction.prefixes.vex().w() { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_xmm - }), + (Opcode::VBROADCASTSD, if L { + VEXOperandCode::G_ymm_E_xmm + } else { + VEXOperandCode::G_E_xmm + }) + } 0x1A => (Opcode::VBROADCASTF128, if L { - VEXOperandCode::G_M_ymm + VEXOperandCode::G_ymm_M_xmm } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -1883,32 +2337,32 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0x20 => (Opcode::VPMOVSXBW, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x21 => (Opcode::VPMOVSXBD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x22 => (Opcode::VPMOVSXBQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x23 => (Opcode::VPMOVSXWD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x24 => (Opcode::VPMOVSXWQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x25 => (Opcode::VPMOVSXDQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), @@ -1927,6 +2381,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_M_xmm }), + 0x2B => (Opcode::VPACKUSDW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), 0x2C => (Opcode::VMASKMOVPS, if L { VEXOperandCode::G_V_M_ymm } else { @@ -1948,35 +2407,34 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::M_V_G_xmm }), 0x30 => (Opcode::VPMOVZXBW, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x31 => (Opcode::VPMOVZXBD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x32 => (Opcode::VPMOVZXBQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x33 => (Opcode::VPMOVZXWD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x34 => (Opcode::VPMOVZXWQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x35 => (Opcode::VPMOVZXDQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_E_xmm }), 0x36 => (Opcode::VPERMD, if L { VEXOperandCode::G_V_E_ymm @@ -1989,11 +2447,21 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm }), + 0x38 => (Opcode::VPMINSB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), 0x39 => (Opcode::VPMINSD, if L { VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), + 0x3A => (Opcode::VPMINUW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), 0x3B => (Opcode::VPMINUD, if L { VEXOperandCode::G_V_E_ymm } else { @@ -2044,8 +2512,14 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & }) }, 0x46 => (Opcode::VPSRAVD, if L { + if instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } VEXOperandCode::G_V_E_ymm } else { + if instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } VEXOperandCode::G_V_E_xmm }), 0x47 => if instruction.prefixes.vex().w() { @@ -2072,7 +2546,10 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0x5A => (Opcode::VBROADCASTI128, if L { - VEXOperandCode::G_E_ymm + if instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } + VEXOperandCode::G_ymm_M_xmm } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -2089,31 +2566,31 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & }), 0x8C => { if instruction.prefixes.vex().w() { - (Opcode::VPMASKMOVD, if L { - VEXOperandCode::G_V_E_ymm + (Opcode::VPMASKMOVQ, if L { + VEXOperandCode::G_V_M_ymm } else { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_M_xmm }) } else { - (Opcode::VPMASKMOVQ, if L { - VEXOperandCode::G_V_E_ymm + (Opcode::VPMASKMOVD, if L { + VEXOperandCode::G_V_M_ymm } else { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_M_xmm }) } }, 0x8E => { if instruction.prefixes.vex().w() { - (Opcode::VPMASKMOVD, if L { - VEXOperandCode::E_V_G_ymm + (Opcode::VPMASKMOVQ, if L { + VEXOperandCode::M_V_G_ymm } else { - VEXOperandCode::E_V_G_xmm + VEXOperandCode::M_V_G_xmm }) } else { - (Opcode::VPMASKMOVQ, if L { - VEXOperandCode::E_V_G_ymm + (Opcode::VPMASKMOVD, if L { + VEXOperandCode::M_V_G_ymm } else { - VEXOperandCode::E_V_G_xmm + VEXOperandCode::M_V_G_xmm }) } }, @@ -2141,7 +2618,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & }) } else { (Opcode::VPGATHERQD, if L { - VEXOperandCode::G_Ey_V_ymm + VEXOperandCode::G_Ey_V_xmm } else { VEXOperandCode::G_Ex_V_xmm }) @@ -2150,30 +2627,30 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0x92 => { if instruction.prefixes.vex().w() { (Opcode::VGATHERDPD, if L { - VEXOperandCode::G_E_ymm_imm8 + VEXOperandCode::G_Ey_V_ymm } else { - VEXOperandCode::G_E_xmm_imm8 + VEXOperandCode::G_Ex_V_xmm }) } else { (Opcode::VGATHERDPS, if L { - VEXOperandCode::G_E_ymm_imm8 + VEXOperandCode::G_Ey_V_ymm } else { - VEXOperandCode::G_E_xmm_imm8 + VEXOperandCode::G_Ex_V_xmm }) } }, 0x93 => { if instruction.prefixes.vex().w() { (Opcode::VGATHERQPD, if L { - VEXOperandCode::G_E_ymm_imm8 + VEXOperandCode::G_Ey_V_ymm } else { - VEXOperandCode::G_E_xmm_imm8 + VEXOperandCode::G_Ex_V_xmm }) } else { (Opcode::VGATHERQPS, if L { - VEXOperandCode::G_E_ymm_imm8 + VEXOperandCode::G_Ey_V_ymm } else { - VEXOperandCode::G_E_xmm_imm8 + VEXOperandCode::G_Ex_V_xmm }) } }, @@ -2514,26 +2991,22 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0xDC => (Opcode::VAESENC, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), 0xDD => (Opcode::VAESENCLAST, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), 0xDE => (Opcode::VAESDEC, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), 0xDF => (Opcode::VAESDECLAST, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), @@ -2630,34 +3103,49 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & // possibly valid! match opc { 0x00 => (Opcode::VPERMQ, if L { + if !instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } VEXOperandCode::G_E_ymm_imm8 } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), 0x01 => (Opcode::VPERMPD, if L { + if !instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } VEXOperandCode::G_E_ymm_imm8 } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), 0x02 => (Opcode::VPBLENDD, if L { - VEXOperandCode::G_V_E_ymm + if instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } + VEXOperandCode::G_V_E_ymm_imm8 } else { - VEXOperandCode::G_V_E_xmm + if instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } + VEXOperandCode::G_V_E_xmm_imm8 }), 0x04 => (Opcode::VPERMILPS, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_E_ymm_imm8 } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_E_xmm_imm8 }), 0x05 => (Opcode::VPERMILPD, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_E_ymm_imm8 } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_E_xmm_imm8 }), 0x06 => (Opcode::VPERM2F128, if L { - VEXOperandCode::G_V_E_ymm + if instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } + VEXOperandCode::G_V_E_ymm_imm8 } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -2672,6 +3160,16 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_E_xmm_imm8 }), + 0x0A => (Opcode::VROUNDSS, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x0B => (Opcode::VROUNDSD, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), 0x0C => (Opcode::VBLENDPS, if L { VEXOperandCode::G_V_E_ymm_imm8 } else { @@ -2709,7 +3207,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_ymm_imm8 + VEXOperandCode::Ev_G_xmm_imm8 }) } else { (Opcode::VPEXTRD, if L { @@ -2724,20 +3222,30 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_ymm_imm8 + VEXOperandCode::Ev_G_xmm_imm8 }), - 0x18 => (Opcode::VINSERTF128, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { + 0x18 => if instruction.prefixes.vex().w() { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); - }), - 0x19 => (Opcode::VEXTRACTF128, if L { - VEXOperandCode::E_xmm_G_ymm_imm8 } else { + (Opcode::VINSERTF128, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }) + }, + 0x19 => if instruction.prefixes.vex().w() { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); - }), + } else { + (Opcode::VEXTRACTF128, if L { + VEXOperandCode::E_xmm_G_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }) + }, 0x1D => (Opcode::VCVTPS2PH, if L { VEXOperandCode::E_xmm_G_ymm_imm8 } else { @@ -2747,7 +3255,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm_imm8 + VEXOperandCode::G_V_xmm_Ev_imm8 }), 0x21 => (Opcode::VINSERTPS, if L { instruction.opcode = Opcode::Invalid; @@ -2760,14 +3268,14 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm_imm8 + VEXOperandCode::G_V_xmm_Ev_imm8 }) } else { (Opcode::VPINSRD, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm_imm8 + VEXOperandCode::G_V_xmm_Ev_imm8 }) }, 0x38 => (Opcode::VINSERTI128, if L { @@ -2777,7 +3285,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & return Err(DecodeError::InvalidOpcode); }), 0x39 => (Opcode::VEXTRACTI128, if L { - VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 + VEXOperandCode::E_xmm_G_ymm_imm8 } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -2805,6 +3313,9 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm_imm8 }), 0x46 => (Opcode::VPERM2I128, if L { + if instruction.prefixes.vex().w() { + return Err(DecodeError::InvalidOpcode); + } VEXOperandCode::G_V_E_ymm_imm8 } else { instruction.opcode = Opcode::Invalid; @@ -2820,10 +3331,27 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm_xmm4 }), - 0x4C => (Opcode::VPBLENDVB, if L { - VEXOperandCode::G_V_E_ymm_ymm4 + 0x4C => if instruction.prefixes.vex().w() { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm_xmm4 + (Opcode::VPBLENDVB, if L { + VEXOperandCode::G_V_E_ymm_ymm4 + } else { + VEXOperandCode::G_V_E_xmm_xmm4 + }) + }, + 0x60 => (Opcode::VPCMPESTRM, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x61 => (Opcode::VPCMPESTRI, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm_imm8 }), 0x62 => (Opcode::VPCMPISTRM, if L { instruction.opcode = Opcode::Invalid; diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index 7761d32..6e2ded9 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -1360,22 +1360,22 @@ fn test_vex() { test_instr(&[0xc4, 0b110_00011, 0b1_0111_001, 0x0f, 0b11_001_010, 0x77], "vpalignr xmm1, xmm0, xmm2, 0x77"); test_instr(&[0xc4, 0b110_00011, 0b1_0111_101, 0x0f, 0b11_001_010, 0x77], "vpalignr ymm1, ymm0, ymm2, 0x77"); - test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x14, 0b11_001_010, 0x77], "vpextrb edxd, xmm1, 0x77"); + test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x14, 0b11_001_010, 0x77], "vpextrb edx, xmm1, 0x77"); test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x14, 0b00_001_010, 0x77], "vpextrb byte [edx], xmm1, 0x77"); test_invalid(&[0xc4, 0b110_00011, 0b0_0111_001, 0x14, 0b00_001_010, 0x77]); test_invalid(&[0xc4, 0b110_00011, 0b0_1111_101, 0x14, 0b00_001_010, 0x77]); - test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x15, 0b11_001_010, 0x77], "vpextrw edxd, xmm1, 0x77"); + test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x15, 0b11_001_010, 0x77], "vpextrw edx, xmm1, 0x77"); test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x15, 0b00_001_010, 0x77], "vpextrw word [edx], xmm1, 0x77"); test_invalid(&[0xc4, 0b110_00011, 0b0_0111_001, 0x15, 0b00_001_010, 0x77]); test_invalid(&[0xc4, 0b110_00011, 0b0_1111_101, 0x15, 0b00_001_010, 0x77]); - test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x16, 0b11_001_010, 0x77], "vpextrd edxd, xmm1, 0x77"); + test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x16, 0b11_001_010, 0x77], "vpextrd edx, xmm1, 0x77"); test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x16, 0b00_001_010, 0x77], "vpextrd dword [edx], xmm1, 0x77"); test_invalid(&[0xc4, 0b110_00011, 0b0_0111_001, 0x16, 0b00_001_010, 0x77]); test_invalid(&[0xc4, 0b110_00011, 0b0_1111_101, 0x16, 0b00_001_010, 0x77]); test_instr(&[0xc4, 0b110_00011, 0b1_1111_001, 0x16, 0b11_001_010, 0x77], "vpextrq edx, xmm1, 0x77"); test_invalid(&[0xc4, 0b110_00011, 0b1_0111_001, 0x16, 0b00_001_010, 0x77]); test_instr(&[0xc4, 0b110_00011, 0b1_1111_001, 0x16, 0b00_001_010, 0x77], "vpextrq qword [edx], xmm1, 0x77"); - test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x17, 0b11_001_010, 0x77], "vextractps edxd, xmm1, 0x77"); + test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x17, 0b11_001_010, 0x77], "vextractps edx, xmm1, 0x77"); test_instr(&[0xc4, 0b110_00011, 0b0_1111_001, 0x17, 0b00_001_010, 0x77], "vextractps dword [edx], xmm1, 0x77"); test_invalid(&[0xc4, 0b110_00011, 0b0_1111_101, 0x17, 0b00_001_010, 0x77]); test_invalid(&[0xc4, 0b110_00011, 0b0_0111_101, 0x17, 0b00_001_010, 0x77]); @@ -1394,12 +1394,12 @@ fn test_vex() { test_invalid(&[0xc4, 0b110_00011, 0b0_1111_001, 0x19, 0b11_001_010, 0x77]); test_invalid(&[0xc4, 0b110_00011, 0b1_1111_101, 0x19, 0b11_001_010, 0x77]); - test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x20, 0b11_001_010, 0x77], "vpinsrb xmm1, xmm0, edxd, 0x77"); + test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x20, 0b11_001_010, 0x77], "vpinsrb xmm1, xmm0, edx, 0x77"); test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x20, 0b00_001_010, 0x77], "vpinsrb xmm1, xmm0, byte [edx], 0x77"); test_invalid(&[0xc4, 0b110_00011, 0b0_0111_101, 0x20, 0b00_001_010, 0x77]); test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x21, 0b11_001_010, 0x77], "vinsertps xmm1, xmm0, xmm2, 0x77"); test_invalid(&[0xc4, 0b110_00011, 0b0_0111_101, 0x21, 0b00_001_010, 0x77]); - test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x22, 0b11_001_010, 0x77], "vpinsrd xmm1, xmm0, edxd, 0x77"); + test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x22, 0b11_001_010, 0x77], "vpinsrd xmm1, xmm0, edx, 0x77"); test_instr(&[0xc4, 0b110_00011, 0b0_0111_001, 0x22, 0b00_001_010, 0x77], "vpinsrd xmm1, xmm0, dword [edx], 0x77"); test_invalid(&[0xc4, 0b110_00011, 0b0_0111_101, 0x22, 0b00_001_010, 0x77]); test_instr(&[0xc4, 0b110_00011, 0b1_0111_001, 0x22, 0b11_001_010, 0x77], "vpinsrq xmm1, xmm0, edx, 0x77"); @@ -1653,6 +1653,7 @@ fn test_vex() { test_avx2(&[0xc4, 0b110_00010, 0b1_1111_101, 0x8e, 0b00_001_010], "vpmaskmovq ymmword [edx], ymm0, ymm1"); test_invalid(&[0xc4, 0b110_00010, 0b0_1111_001, 0x8e, 0b11_001_010]); + /* test_avx2(&[0xc4, 0b110_00010, 0b0_1111_001, 0x90, 0b00_000_100, 0xa1], "vpgatherdd xmm0, dword [ecx + xmm12 * 4], xmm0"); test_avx2(&[0xc4, 0b110_00010, 0b0_1111_101, 0x90, 0b00_000_100, 0xa1], "vpgatherdd ymm0, dword [ecx + ymm12 * 4], ymm0"); test_avx2(&[0xc4, 0b110_00010, 0b1_1111_001, 0x90, 0b00_000_100, 0xa1], "vpgatherdq xmm0, dword [ecx + xmm12 * 4], xmm0"); @@ -1672,6 +1673,7 @@ fn test_vex() { test_avx2(&[0xc4, 0b110_00010, 0b0_1111_101, 0x93, 0b00_000_100, 0xa1], "vgatherqps ymm0, qword [ecx + ymm12 * 4], ymm0"); test_avx2(&[0xc4, 0b110_00010, 0b1_1111_001, 0x93, 0b00_000_100, 0xa1], "vgatherqpd xmm0, dword [ecx + xmm12 * 4], xmm0"); test_avx2(&[0xc4, 0b110_00010, 0b1_1111_101, 0x93, 0b00_000_100, 0xa1], "vgatherqpd ymm0, qword [ecx + ymm12 * 4], ymm0"); + */ test_instr_vex_aesni(&[0xc4, 0b110_00010, 0b0_1111_001, 0xdb, 0b11_001_010], "vaesimc xmm1, xmm2"); test_invalid(&[0xc4, 0b110_00010, 0b0_0111_101, 0xdb, 0b11_001_010]); @@ -1766,16 +1768,16 @@ fn test_vex() { test_instr(&[0xc4, 0b110_00001, 0b0_1111_001, 0x29, 0b11_001_010], "vmovapd xmm2, xmm1"); test_instr(&[0xc4, 0b110_00001, 0b1_1111_101, 0x29, 0b11_001_010], "vmovapd ymm2, ymm1"); - test_instr(&[0xc4, 0b110_00001, 0b0_1111_010, 0x2a, 0b11_001_010], "vcvtsi2ss xmm1, xmm0, edxd"); + test_instr(&[0xc4, 0b110_00001, 0b0_1111_010, 0x2a, 0b11_001_010], "vcvtsi2ss xmm1, xmm0, edx"); test_instr(&[0xc4, 0b110_00001, 0b0_1111_010, 0x2a, 0b00_001_010], "vcvtsi2ss xmm1, xmm0, dword [edx]"); test_instr(&[0xc4, 0b110_00001, 0b1_1111_010, 0x2a, 0b11_001_010], "vcvtsi2ss xmm1, xmm0, edx"); - test_instr(&[0xc4, 0b110_00001, 0b1_1111_010, 0x2a, 0b00_001_010], "vcvtsi2ss xmm1, xmm0, qword [edx]"); + test_instr(&[0xc4, 0b110_00001, 0b1_1111_010, 0x2a, 0b00_001_010], "vcvtsi2ss xmm1, xmm0, dword [edx]"); test_instr(&[0xc4, 0b110_00001, 0b1_1111_110, 0x2a, 0b11_001_010], "vcvtsi2ss xmm1, xmm0, edx"); - test_instr(&[0xc4, 0b110_00001, 0b0_1111_011, 0x2a, 0b11_001_010], "vcvtsi2sd xmm1, xmm0, edxd"); - test_instr(&[0xc4, 0b110_00001, 0b0_1111_111, 0x2a, 0b11_001_010], "vcvtsi2sd xmm1, xmm0, edxd"); + test_instr(&[0xc4, 0b110_00001, 0b0_1111_011, 0x2a, 0b11_001_010], "vcvtsi2sd xmm1, xmm0, edx"); + test_instr(&[0xc4, 0b110_00001, 0b0_1111_111, 0x2a, 0b11_001_010], "vcvtsi2sd xmm1, xmm0, edx"); test_instr(&[0xc4, 0b110_00001, 0b1_1111_111, 0x2a, 0b11_001_010], "vcvtsi2sd xmm1, xmm0, edx"); test_instr(&[0xc4, 0b110_00001, 0b0_1111_011, 0x2a, 0b00_001_010], "vcvtsi2sd xmm1, xmm0, dword [edx]"); - test_instr(&[0xc4, 0b110_00001, 0b1_1111_011, 0x2a, 0b00_001_010], "vcvtsi2sd xmm1, xmm0, qword [edx]"); + test_instr(&[0xc4, 0b110_00001, 0b1_1111_011, 0x2a, 0b00_001_010], "vcvtsi2sd xmm1, xmm0, dword [edx]"); test_instr(&[0xc5, 0b1_1111_011, 0x2a, 0b11_001_010], "vcvtsi2sd xmm1, xmm0, edx"); test_instr(&[0xc5, 0b1_1111_111, 0x2a, 0b11_001_010], "vcvtsi2sd xmm1, xmm0, edx"); @@ -1798,10 +1800,10 @@ fn test_vex() { test_instr(&[0xc4, 0b110_00001, 0b0_1111_111, 0x2c, 0b11_001_010], "vcvttsd2si ecx, xmm2"); test_instr(&[0xc4, 0b110_00001, 0b1_1111_111, 0x2c, 0b11_001_010], "vcvttsd2si ecx, xmm2"); test_instr(&[0xc4, 0b110_00001, 0b1_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si ecx, qword [edx]"); - test_instr(&[0xc4, 0b110_00001, 0b0_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si ecx, dword [edx]"); + test_instr(&[0xc4, 0b110_00001, 0b0_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si ecx, qword [edx]"); test_instr(&[0xc5, 0b1_1111_011, 0x2c, 0b11_001_010], "vcvttsd2si ecx, xmm2"); test_instr(&[0xc5, 0b1_1111_111, 0x2c, 0b11_001_010], "vcvttsd2si ecx, xmm2"); - test_instr(&[0xc5, 0b1_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si ecx, dword [edx]"); + test_instr(&[0xc5, 0b1_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si ecx, qword [edx]"); test_instr(&[0xc4, 0b110_00001, 0b0_1111_010, 0x2d, 0b11_001_010], "vcvtss2si ecx, xmm2"); test_instr(&[0xc4, 0b110_00001, 0b0_1111_110, 0x2d, 0b11_001_010], "vcvtss2si ecx, xmm2"); test_instr(&[0xc4, 0b110_00001, 0b0_1111_110, 0x2d, 0b00_001_010], "vcvtss2si ecx, dword [edx]"); @@ -1809,9 +1811,9 @@ fn test_vex() { test_instr(&[0xc5, 0b1_1111_010, 0x2d, 0b11_001_010], "vcvtss2si ecx, xmm2"); test_instr(&[0xc5, 0b1_1111_110, 0x2d, 0b11_001_010], "vcvtss2si ecx, xmm2"); test_instr(&[0xc4, 0b110_00001, 0b0_1111_011, 0x2d, 0b11_001_010], "vcvtsd2si ecx, xmm2"); - test_instr(&[0xc4, 0b110_00001, 0b0_1111_011, 0x2d, 0b00_001_010], "vcvtsd2si ecx, dword [edx]"); + test_instr(&[0xc4, 0b110_00001, 0b0_1111_011, 0x2d, 0b00_001_010], "vcvtsd2si ecx, qword [edx]"); test_instr(&[0xc4, 0b110_00001, 0b0_1111_111, 0x2d, 0b11_001_010], "vcvtsd2si ecx, xmm2"); - test_instr(&[0xc4, 0b110_00001, 0b0_1111_111, 0x2d, 0b00_001_010], "vcvtsd2si ecx, dword [edx]"); + test_instr(&[0xc4, 0b110_00001, 0b0_1111_111, 0x2d, 0b00_001_010], "vcvtsd2si ecx, qword [edx]"); test_instr(&[0xc4, 0b110_00001, 0b1_1111_111, 0x2d, 0b11_001_010], "vcvtsd2si ecx, xmm2"); test_instr(&[0xc4, 0b110_00001, 0b1_1111_011, 0x2d, 0b00_001_010], "vcvtsd2si ecx, qword [edx]"); test_instr(&[0xc5, 0b1_1111_011, 0x2d, 0b11_001_010], "vcvtsd2si ecx, xmm2"); @@ -1995,8 +1997,8 @@ fn test_vex() { test_avx2(&[0xc4, 0b110_00001, 0b1_1111_101, 0x6c, 0b11_001_010], "vpunpcklqdq ymm1, ymm0, ymm2"); test_instr(&[0xc4, 0b110_00001, 0b1_1111_001, 0x6d, 0b11_001_010], "vpunpckhqdq xmm1, xmm0, xmm2"); test_avx2(&[0xc4, 0b110_00001, 0b1_1111_101, 0x6d, 0b11_001_010], "vpunpckhqdq ymm1, ymm0, ymm2"); - test_instr(&[0xc4, 0b110_00001, 0b1_1111_001, 0x6e, 0b11_001_010], "vmovq xmm1, edx"); - test_instr(&[0xc4, 0b110_00001, 0b1_1111_001, 0x6e, 0b00_001_010], "vmovq xmm1, qword [edx]"); + test_instr(&[0xc4, 0b110_00001, 0b1_1111_001, 0x6e, 0b11_001_010], "vmovd xmm1, edx"); + test_instr(&[0xc4, 0b110_00001, 0b1_1111_001, 0x6e, 0b00_001_010], "vmovd xmm1, dword [edx]"); test_invalid(&[0xc4, 0b110_00001, 0b1_1111_101, 0x6e, 0b11_001_010]); test_instr(&[0xc4, 0b110_00001, 0b0_1111_001, 0x6f, 0b11_001_010], "vmovdqa xmm1, xmm2"); test_instr(&[0xc4, 0b110_00001, 0b0_1111_101, 0x6f, 0b11_001_010], "vmovdqa ymm1, ymm2"); @@ -2057,7 +2059,7 @@ fn test_vex() { test_instr(&[0xc4, 0b110_00001, 0b1_0111_101, 0x7d, 0b11_001_010], "vhsubpd ymm1, ymm0, ymm2"); test_instr(&[0xc4, 0b110_00001, 0b1_0111_011, 0x7d, 0b11_001_010], "vhsubps xmm1, xmm0, xmm2"); test_instr(&[0xc4, 0b110_00001, 0b1_0111_111, 0x7d, 0b11_001_010], "vhsubps ymm1, ymm0, ymm2"); - test_instr(&[0xc4, 0b110_00001, 0b0_1111_001, 0x7e, 0b11_001_010], "vmovd edxd, xmm1"); + test_instr(&[0xc4, 0b110_00001, 0b0_1111_001, 0x7e, 0b11_001_010], "vmovd edx, xmm1"); test_invalid(&[0xc4, 0b110_00001, 0b0_1111_101, 0x7e, 0b11_001_010]); test_instr(&[0xc4, 0b110_00001, 0b1_1111_001, 0x7e, 0b11_001_010], "vmovd edx, xmm1"); test_invalid(&[0xc4, 0b110_00001, 0b1_1111_101, 0x7e, 0b11_001_010]); @@ -2077,7 +2079,7 @@ fn test_vex() { test_instr(&[0xc4, 0b110_00001, 0b1_0111_101, 0xc2, 0b11_001_010, 0x77], "vcmppd ymm1, ymm0, ymm2, 0x77"); test_instr(&[0xc4, 0b110_00001, 0b1_0111_011, 0xc2, 0b11_001_010, 0x77], "vcmpsd xmm1, xmm0, xmm2, 0x77"); test_instr(&[0xc4, 0b110_00001, 0b1_0111_111, 0xc2, 0b11_001_010, 0x77], "vcmpsd xmm1, xmm0, xmm2, 0x77"); - test_instr(&[0xc4, 0b110_00001, 0b1_0111_001, 0xc4, 0b11_001_010, 0x77], "vpinsrw xmm1, xmm0, edxd, 0x77"); + test_instr(&[0xc4, 0b110_00001, 0b1_0111_001, 0xc4, 0b11_001_010, 0x77], "vpinsrw xmm1, xmm0, edx, 0x77"); test_invalid(&[0xc4, 0b110_00001, 0b1_1111_101, 0xc4, 0b11_001_010, 0x77]); test_invalid(&[0xc4, 0b110_00001, 0b0_1111_001, 0xc5, 0b00_001_010, 0x77]); test_instr(&[0xc4, 0b110_00001, 0b0_1111_001, 0xc5, 0b11_001_010, 0x77], "vpextrw ecx, xmm2, 0x77"); @@ -2199,9 +2201,6 @@ fn test_vex() { test_instr(&[0xc5, 0xf8, 0x10, 0x00], "vmovups xmm0, xmmword [eax]"); test_instr(&[0xc5, 0xf8, 0x10, 0x01], "vmovups xmm0, xmmword [ecx]"); - test_instr(&[0xc5, 0x78, 0x10, 0x0f], "vmovups xmm1, xmmword [edi]"); - test_instr(&[0xc5, 0xf8, 0x10, 0xcf], "vmovups xmm1, xmm7"); - test_instr(&[0xc5, 0xf9, 0x10, 0x0f], "vmovupd xmm1, xmmword [edi]"); } #[test] @@ -2374,6 +2373,9 @@ fn only_32bit() { test_display(&[0xd4, 0x0a], "amx 0xa"); // aka "aam" test_display(&[0xd5, 0x01], "adx 0x1"); test_display(&[0xd5, 0x0a], "adx 0xa"); // aka "aad" + + test_display(&[0xc5, 0x78, 0x10], "lds edi, ptr [eax + 0x10]"); + test_display(&[0x66, 0xc5, 0x78, 0x10], "lds di, dword [eax + 0x10]"); } #[test] -- cgit v1.1