From d951f4bbce1102ddab30e3a5f65ddac8ab221ac9 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sat, 26 Jun 2021 01:32:08 -0700 Subject: add long-mode avx512 support, except for compressed displacements --- src/shared/evex.in | 4874 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4874 insertions(+) create mode 100644 src/shared/evex.in (limited to 'src/shared/evex.in') diff --git a/src/shared/evex.in b/src/shared/evex.in new file mode 100644 index 0000000..e997cf0 --- /dev/null +++ b/src/shared/evex.in @@ -0,0 +1,4874 @@ +use super::OperandSpec; + +#[inline(never)] +pub(crate) fn read_evex>(bytes: &mut T, instruction: &mut Instruction, mut length: u8) -> Result<(), DecodeError> { + let evex_byte_one = bytes.next().ok_or(DecodeError::ExhaustedInput)?; + let evex_byte_two = bytes.next().ok_or(DecodeError::ExhaustedInput)?; + let evex_byte_three = bytes.next().ok_or(DecodeError::ExhaustedInput)?; + length += 3; + let p = evex_byte_two & 0x03; + let m = evex_byte_one & 0x03; + if m == 0 { + return Err(DecodeError::InvalidOpcode); + } + let m = m - 1; + // instead of enums for the lookup bits, these are used to select a TABLES entry in the first + // place + /* + let p = [ + EVEXOpcodePrefix::None, + EVEXOpcodePrefix::Prefix66, + EVEXOpcodePrefix::PrefixF3, + EVEXOpcodePrefix::PrefixF2, + ][p]; + let m = [ + Ok(EVEXOpcodeMap::Map0F), + Ok(EVEXOpcodeMap::Map0F38), + Ok(EVEXOpcodeMap::Map0F3A), + Err(DecodeError::InvalidOpcode), + ][m - 1]?; + */ + + let vp = ((evex_byte_three >> 3) & 1) << 4; + let vvvvv = ((evex_byte_two >> 3) & 0b1111) | vp; + + instruction.vex_reg = RegSpec { + bank: RegisterBank::X, + num: vvvvv ^ 0b11111 // `vvvvv` is provided in inverted form + }; + + instruction.prefixes.evex_from(evex_byte_one, evex_byte_two, evex_byte_three); + + let opc = bytes.next().ok_or(DecodeError::ExhaustedInput)?; + length += 1; + let table_idx = ((m << 2) | p) as usize; + let table = generated::TABLES[table_idx]; + if table as *const [_] == &generated::DUMMY[..] as *const [_] { + panic!("no table for m={}, p={}", m, p); + } + let mut index_lower = 0; + if instruction.prefixes.evex_unchecked().vex().l() { + index_lower |= 1; + } + if instruction.prefixes.evex_unchecked().lp() { + index_lower |= 2; + } + if let Ok(entry) = table.binary_search_by_key(&opc, |x| x.0) { + let (opcode, operand_code) = table[entry].1[index_lower]; + instruction.opcode = opcode; + read_evex_operands(bytes, instruction, operand_code, &mut length)?; + // TODO: apply rp and bp? + } else { + return Err(DecodeError::InvalidOpcode); + } + instruction.length = length; + Ok(()) +} + +fn deny_z(inst: &Instruction) -> Result<(), DecodeError> { + if inst.prefixes.evex_unchecked().merge() { + Err(DecodeError::InvalidOperand) + } else { + Ok(()) + } +} + +fn deny_vex_reg(inst: &Instruction) -> Result<(), DecodeError> { + if inst.vex_reg.num != 0 { + Err(DecodeError::InvalidOperand) + } else { + Ok(()) + } +} + +#[allow(non_snake_case)] +fn ensure_W(inst: &Instruction, w: u8) -> Result<(), DecodeError> { + if inst.prefixes.evex_unchecked().vex().w() ^ (w != 0) { + Err(DecodeError::InvalidOpcode) + } else { + Ok(()) + } +} + +fn deny_mask_reg(inst: &Instruction) -> Result<(), DecodeError> { + if inst.prefixes.evex_unchecked().mask_reg() != 0 { + Err(DecodeError::InvalidOperand) + } else { + Ok(()) + } +} + +fn check_mask_reg(inst: &Instruction) -> Result<(), DecodeError> { + // if an operand is to be zeroed on mask bits but mask register 0 is + // selected, this instruction is nonsense and will #UD + if inst.prefixes.evex_unchecked().merge() && inst.prefixes.evex_unchecked().mask_reg() == 0 { + Err(DecodeError::InvalidOperand) + } else { + Ok(()) + } +} + +fn apply_broadcast(inst: &mut Instruction, item_size: u8, reg_size: u8) { + if inst.prefixes.evex_unchecked().broadcast() { + inst.mem_size = item_size; + } else { + inst.mem_size = reg_size; + } +} + +fn set_rrr(inst: &mut Instruction, modrm: u8) { + inst.modrm_rrr.num = (modrm >> 3) & 7; + if inst.prefixes.evex_unchecked().vex().r() { + inst.modrm_rrr.num |= 8; + } + if inst.prefixes.evex_unchecked().rp() { + inst.modrm_rrr.num |= 16; + } +} + +fn set_reg_sizes(inst: &mut Instruction, size: RegisterBank) { + inst.modrm_rrr.bank = size; + inst.vex_reg.bank = size; + for i in 0..inst.operand_count { + if [OperandSpec::RegMMM, OperandSpec::RegMMM_maskmerge, OperandSpec::RegMMM_maskmerge_sae_noround].contains(&inst.operands[i as usize]) { + inst.modrm_mmm.bank = size; + } + } +} + +fn regs_size(inst: &Instruction) -> u8 { + if inst.prefixes.evex_unchecked().lp() { + 64 + } else if inst.prefixes.evex_unchecked().vex().l() { + 32 + } else { + 16 + } +} + +fn set_reg_sizes_from_ll(inst: &mut Instruction) -> Result<(), DecodeError> { + if inst.prefixes.evex_unchecked().lp() { + if inst.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOperand); + } + set_reg_sizes(inst, RegisterBank::Z); + } else if inst.prefixes.evex_unchecked().vex().l() { + set_reg_sizes(inst, RegisterBank::Y); + } else { + set_reg_sizes(inst, RegisterBank::X); + } + Ok(()) +} + +pub(crate) fn read_evex_operands>(bytes: &mut T, instruction: &mut Instruction, operand_code: generated::EVEXOperandCode, length: &mut u8) -> Result<(), DecodeError> { + match operand_code { + generated::EVEXOperandCode::Gm_V_E_LL_imm8_sae_bcast => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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 instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VRANGEPS { + instruction.opcode = Opcode::VRANGEPD; + } else if instruction.opcode == Opcode::VFIXUPIMMPS { + instruction.opcode = Opcode::VFIXUPIMMPD; + } + } + + if let OperandSpec::RegMMM = mem_oper { + if instruction.prefixes.evex_unchecked().broadcast() { + if [Opcode::VRANGEPS, Opcode::VRANGEPD, Opcode::VFIXUPIMMPS, Opcode::VFIXUPIMMPD].contains(&instruction.opcode) { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + set_reg_sizes(instruction, RegisterBank::Z); + } else { + set_reg_sizes_from_ll(instruction)?; + } + } else { + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_V_Ed_xmm => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + + instruction.operand_count = 3; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VRSQRT14SS { + instruction.opcode = Opcode::VRSQRT14SD; + } + } + + if let OperandSpec::RegMMM = mem_oper { + instruction.mem_size = 0; + } else { + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::Gm_V_Eq_xmm_sae_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + + instruction.operand_count = 3; + + if let OperandSpec::RegMMM = mem_oper { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + instruction.mem_size = 0; + } else { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } + instruction.mem_size = 8; + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::Gm_V_Ed_xmm_sae_bcast => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + + instruction.operand_count = 3; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VGETEXPSS { + instruction.opcode = Opcode::VGETEXPSD; + } + } + + if let OperandSpec::RegMMM = mem_oper { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } + } else { + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::Gm_V_Ed_LL_sae => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + + instruction.operand_count = 3; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VFMADD132SS { + instruction.opcode = Opcode::VFMADD132SD; + } else if instruction.opcode == Opcode::VFMSUB132SS { + instruction.opcode = Opcode::VFMSUB132SD; + } else if instruction.opcode == Opcode::VFNMADD132SS { + instruction.opcode = Opcode::VFNMADD132SD; + } else if instruction.opcode == Opcode::VFNMSUB132SS { + instruction.opcode = Opcode::VFNMSUB132SD; + } else if instruction.opcode == Opcode::VFMADD213SS { + instruction.opcode = Opcode::VFMADD213SD; + } else if instruction.opcode == Opcode::VFMSUB213SS { + instruction.opcode = Opcode::VFMSUB213SD; + } else if instruction.opcode == Opcode::VFNMADD213SS { + instruction.opcode = Opcode::VFNMADD213SD; + } else if instruction.opcode == Opcode::VFNMSUB213SS { + instruction.opcode = Opcode::VFNMSUB213SD; + } else if instruction.opcode == Opcode::VFMADD231SS { + instruction.opcode = Opcode::VFMADD231SD; + } else if instruction.opcode == Opcode::VFMSUB231SS { + instruction.opcode = Opcode::VFMSUB231SD; + } else if instruction.opcode == Opcode::VFNMADD231SS { + instruction.opcode = Opcode::VFNMADD231SD; + } else if instruction.opcode == Opcode::VFNMSUB231SS { + instruction.opcode = Opcode::VFNMSUB231SD; + } + } + + set_reg_sizes(instruction, RegisterBank::X); + + if let OperandSpec::RegMMM = mem_oper { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + } else { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } + } + } + generated::EVEXOperandCode::Gm_V_E_LL_sae_bcast => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + + instruction.operand_count = 3; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VSCALEFPS { + instruction.opcode = Opcode::VSCALEFPD; + } else if instruction.opcode == Opcode::VFNMADD132PS { + instruction.opcode = Opcode::VFNMADD132PD; + } else if instruction.opcode == Opcode::VFNMSUB132PS { + instruction.opcode = Opcode::VFNMSUB132PD; + } else if instruction.opcode == Opcode::VFMADDSUB132PS { + instruction.opcode = Opcode::VFMADDSUB132PD; + } else if instruction.opcode == Opcode::VFMSUBADD132PS { + instruction.opcode = Opcode::VFMSUBADD132PD; + } else if instruction.opcode == Opcode::VFMADD132PS { + instruction.opcode = Opcode::VFMADD132PD; + } else if instruction.opcode == Opcode::VFMSUB132PS { + instruction.opcode = Opcode::VFMSUB132PD; + } else if instruction.opcode == Opcode::VFMADDSUB213PS { + instruction.opcode = Opcode::VFMADDSUB213PD; + } else if instruction.opcode == Opcode::VFMSUBADD213PS { + instruction.opcode = Opcode::VFMSUBADD213PD; + } else if instruction.opcode == Opcode::VFMADD213PS { + instruction.opcode = Opcode::VFMADD213PD; + } else if instruction.opcode == Opcode::VFMSUB213PS { + instruction.opcode = Opcode::VFMSUB213PD; + } else if instruction.opcode == Opcode::VFNMADD213PS { + instruction.opcode = Opcode::VFNMADD213PD; + } else if instruction.opcode == Opcode::VFNMSUB213PS { + instruction.opcode = Opcode::VFNMSUB213PD; + } else if instruction.opcode == Opcode::VFMADDSUB231PS { + instruction.opcode = Opcode::VFMADDSUB231PD; + } else if instruction.opcode == Opcode::VFMSUBADD231PS { + instruction.opcode = Opcode::VFMSUBADD231PD; + } else if instruction.opcode == Opcode::VFMADD231PS { + instruction.opcode = Opcode::VFMADD231PD; + } else if instruction.opcode == Opcode::VFMSUB231PS { + instruction.opcode = Opcode::VFMSUB231PD; + } else if instruction.opcode == Opcode::VFNMADD231PS { + instruction.opcode = Opcode::VFNMADD231PD; + } else if instruction.opcode == Opcode::VFNMSUB231PS { + instruction.opcode = Opcode::VFNMSUB231PD; + } + } + + if let OperandSpec::RegMMM = mem_oper { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + set_reg_sizes_from_ll(instruction)?; + } + } else { + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_E_LL_imm8_sae => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = Opcode::VREDUCEPD; + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + if let OperandSpec::RegMMM = mem_oper { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.mem_size = 0; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + + set_reg_sizes(instruction, RegisterBank::Z); + } else { + set_reg_sizes_from_ll(instruction)?; + } + } else { + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_E_LL_imm8_sae_W0 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + if let OperandSpec::RegMMM = mem_oper { + if instruction.prefixes.evex_unchecked().broadcast() { + // this mode is only used for `vcvtps2ph` and `vrndscaleps`, neither use sae rounding + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + + set_reg_sizes(instruction, RegisterBank::Z); + } else { + set_reg_sizes_from_ll(instruction)?; + } + } else { + let sz = regs_size(instruction); + + apply_broadcast(instruction, 4, sz); + + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_E_LL_imm8_sae_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + if let OperandSpec::RegMMM = mem_oper { + if instruction.prefixes.evex_unchecked().broadcast() { + // this mode is only used for `vrndscalepd`, does not use sae rounding + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + + set_reg_sizes(instruction, RegisterBank::Z); + } else { + set_reg_sizes_from_ll(instruction)?; + } + } else { + let sz = regs_size(instruction); + + apply_broadcast(instruction, 8, sz); + + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Mq_G_xmm_W1 => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 1)?; + + instruction.mem_size = 8; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::G_V_Ed_xmm_imm8_W0 => { + deny_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.vex_reg.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + 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; + } + generated::EVEXOperandCode::G_V_xmm_Edq_sae => { + deny_mask_reg(instruction)?; + deny_z(instruction)?; + + let (sz, bank) = if instruction.prefixes.evex_unchecked().vex().w() { + (8, RegisterBank::Q) + } else { + (4, RegisterBank::D) + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.vex_reg.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = bank; + instruction.mem_size = 0; + } else { + instruction.mem_size = sz; + } + if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper == OperandSpec::RegMMM { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + return Err(DecodeError::InvalidOperand); + } + } else { + instruction.operands[0] = OperandSpec::RegRRR; + } + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::G_V_xmm_Edq_imm8 => { + deny_mask_reg(instruction)?; + + let (sz, bank) = if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = Opcode::VPINSRQ; + (8, RegisterBank::Q) + } else { + (4, RegisterBank::D) + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.vex_reg.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = bank; + instruction.mem_size = 0; + } else { + instruction.mem_size = sz; + } + 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; + } + generated::EVEXOperandCode::G_V_xmm_Ebd_imm8 => { + deny_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.vex_reg.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::D; + instruction.mem_size = 0; + } else { + instruction.mem_size = 1; + } + 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; + } + generated::EVEXOperandCode::G_V_Mq_xmm_W1 => { + deny_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + instruction.mem_size = 8; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + 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] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::Gm_V_E_LL_bcast_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + // specifically for vunpcklpd!!! probably need to reconsider. + apply_broadcast(instruction, 8, sz); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::M_G_LL_W0 => { + deny_vex_reg(instruction)?; + deny_mask_reg(instruction)?; + + instruction.mem_size = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::M_G_LL_W1 => { + deny_vex_reg(instruction)?; + deny_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + instruction.mem_size = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Em_G_LL_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + instruction.mem_size = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::G_Ed_xmm_sae_W0 => { + deny_vex_reg(instruction)?; + deny_mask_reg(instruction)?; + // vucomiss and vcomiss both are W=0 + ensure_W(instruction, 0)?; + + instruction.mem_size = 4; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + + // in specific support of vcomisd/vucomisd + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR; + } + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_Eq_xmm_sae_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + // vucomisd and vcomisd both are W=1 + ensure_W(instruction, 1)?; + + instruction.mem_size = 8; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + + // in specific support of vcomisd/vucomisd + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR; + } + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_E_LL_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + instruction.mem_size = regs_size(instruction); + + if instruction.opcode == Opcode::VMOVDDUP && instruction.mem_size == 16 { + instruction.mem_size = 8; + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::VCVTUDQ2PD => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VCVTUDQ2PD { + instruction.opcode = Opcode::VCVTUQQ2PD; + } else if instruction.opcode == Opcode::VCVTDQ2PD { + instruction.opcode = Opcode::VCVTQQ2PD; + } + } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOperand); + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + if !instruction.prefixes.evex_unchecked().vex().w() { + if instruction.modrm_rrr.bank == RegisterBank::Z { + instruction.modrm_mmm.bank = RegisterBank::Y; + } else if instruction.modrm_rrr.bank == RegisterBank::Y { + instruction.modrm_mmm.bank = RegisterBank::X; + } + } + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz / 2); + } + } + } + generated::EVEXOperandCode::Maskm_V_E_LL_imm8_sae_bcast_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + 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 { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + apply_broadcast(instruction, 8, sz); + set_reg_sizes_from_ll(instruction)?; + } + instruction.modrm_rrr.bank = RegisterBank::K; + if instruction.modrm_rrr.num > 7 { + return Err(DecodeError::InvalidOperand); + } + } + generated::EVEXOperandCode::Gm_E_LL_sae_bcast_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + apply_broadcast(instruction, 8, sz); + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_E_LL_sae_bcast_W1 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + apply_broadcast(instruction, 8, sz); + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_V_Ed_LL_bcast => { + check_mask_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VPERMPS { + instruction.opcode = Opcode::VPERMPD; + } else if instruction.opcode == Opcode::VBLENDMPS { + instruction.opcode = Opcode::VBLENDMPD; + } else if instruction.opcode == Opcode::VPERMI2PS { + instruction.opcode = Opcode::VPERMI2PD; + } else if instruction.opcode == Opcode::VPERMT2PS { + instruction.opcode = Opcode::VPERMT2PD + } + } + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } else { + instruction.mem_size = 0; + } + } else { + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + } + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_Ed_LL_bcast_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } else { + instruction.mem_size = 0; + } + } else { + apply_broadcast(instruction, 4, sz); + } + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = sz; + } + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = sz; + } + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_sae_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.mem_size = sz; + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_V_E_LL_sae_bcast_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + if instruction.opcode == Opcode::VMINPS || instruction.opcode == Opcode::VMAXPS { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + set_reg_sizes(instruction, RegisterBank::Z); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + apply_broadcast(instruction, 4, sz); + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_V_E_LL_sae_bcast_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + if instruction.opcode == Opcode::VMINPD || instruction.opcode == Opcode::VMAXPD { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + set_reg_sizes(instruction, RegisterBank::Z); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + apply_broadcast(instruction, 8, sz); + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::G_V_E_LL => { + deny_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_bcast => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + instruction.opcode = if instruction.opcode == Opcode::VPANDD { + Opcode::VPANDQ + } else if instruction.opcode == Opcode::VPANDND { + Opcode::VPANDNQ + } else if instruction.opcode == Opcode::VPORD { + Opcode::VPORQ + } else if instruction.opcode == Opcode::VPXORD { + Opcode::VPXORQ + } else if instruction.opcode == Opcode::VPRORVD { + Opcode::VPRORVQ + } else if instruction.opcode == Opcode::VPROLVD { + Opcode::VPROLVQ + } else if instruction.opcode == Opcode::VPERMD { + Opcode::VPERMQ + } else if instruction.opcode == Opcode::VPMINSD { + Opcode::VPMINSQ + } else if instruction.opcode == Opcode::VPMINUD { + Opcode::VPMINUQ + } else if instruction.opcode == Opcode::VPMAXSD { + Opcode::VPMAXSQ + } else if instruction.opcode == Opcode::VPMAXUD { + Opcode::VPMAXUQ + } else if instruction.opcode == Opcode::VPSRLVD { + Opcode::VPSRLVQ + } else if instruction.opcode == Opcode::VPSRAVD { + Opcode::VPSRAVQ + } else if instruction.opcode == Opcode::VPSLLVD { + Opcode::VPSLLVQ + } else if instruction.opcode == Opcode::VPMULLD { + Opcode::VPMULLQ + } else if instruction.opcode == Opcode::VPBLENDMD { + Opcode::VPBLENDMQ + } else if instruction.opcode == Opcode::VPSHLDVD { + Opcode::VPSHLDVQ + } else if instruction.opcode == Opcode::VPSHRDVD { + Opcode::VPSHRDVQ + } else if instruction.opcode == Opcode::VPERMI2D { + Opcode::VPERMI2Q + } else if instruction.opcode == Opcode::VPERMT2D { + Opcode::VPERMT2Q + } else { + instruction.opcode + }; + } else { + apply_broadcast(instruction, 4, sz); + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_E_LL_imm8_bcast_W0 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + apply_broadcast(instruction, 4, sz); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_E_LL_imm8_bcast_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + apply_broadcast(instruction, 8, sz); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_Ed_LL_imm8_sae_noround_bcast => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VGETMANTPS { + instruction.opcode = Opcode::VGETMANTPD; + } + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_Ed_LL_sae_noround_bcast_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + apply_broadcast(instruction, 4, sz); + + if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_V_Ed_xmm_sae_noround_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::Gm_V_Ed_xmm_sae => { + check_mask_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VSCALEFSS { + instruction.opcode = Opcode::VSCALEFSD; + } else if instruction.opcode == Opcode::VRCP14SS { + instruction.opcode = Opcode::VRCP14SD; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::Gm_V_Ed_xmm_sae_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if instruction.prefixes.evex_unchecked().broadcast() { + if instruction.opcode == Opcode::VMINSS || instruction.opcode == Opcode::VMAXSS { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::Eqm_G_xmm_imm8_sae_W0 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + // sae sets this to `vcvtps2ph ymm, zmm, imm8` + instruction.modrm_mmm.bank = RegisterBank::Y; + instruction.modrm_rrr.bank = RegisterBank::Z; + instruction.operands[0] = OperandSpec::RegMMM_maskmerge_sae_noround; + } else { + instruction.modrm_mmm.bank = RegisterBank::X; + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.operands[0] = OperandSpec::RegMMM_maskmerge; + } + } else { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOperand); + } else { + instruction.mem_size = 8; + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.operands[0] = mem_oper.masked(); + } + } + instruction.operands[1] = OperandSpec::RegRRR; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::Em_xmm_G_ymm_imm8_sae_W0 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + // sae sets this to `vcvtps2ph ymm, zmm, imm8` + instruction.modrm_mmm.bank = RegisterBank::Y; + instruction.modrm_rrr.bank = RegisterBank::Z; + instruction.operands[0] = OperandSpec::RegMMM_maskmerge_sae_noround; + } else { + instruction.modrm_mmm.bank = RegisterBank::X; + instruction.modrm_rrr.bank = RegisterBank::Y; + instruction.operands[0] = OperandSpec::RegMMM_maskmerge; + } + } else { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::Y; + instruction.operands[0] = mem_oper.masked(); + } + } + instruction.operands[1] = OperandSpec::RegRRR; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.mem_size = 16; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::Em_ymm_G_zmm_imm8_sae_W0 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::Z; + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegMMM_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegMMM_maskmerge; + } + } else { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOperand); + } else { + instruction.operands[0] = mem_oper.masked(); + } + } + instruction.mem_size = 32; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::Gm_V_zmm_E_xmm_imm8 => { + check_mask_reg(instruction)?; + + instruction.opcode = if instruction.prefixes.evex_unchecked().vex().w() { + Opcode::VINSERTI64X2 + } else { + Opcode::VINSERTI32X4 + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::Z; + instruction.vex_reg.bank = RegisterBank::Z; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 16; + } + instruction.operands[0] = OperandSpec::RegRRR.masked(); + 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; + } + generated::EVEXOperandCode::Gm_V_ymm_E_xmm_imm8 => { + check_mask_reg(instruction)?; + + instruction.opcode = if instruction.prefixes.evex_unchecked().vex().w() { + Opcode::VINSERTI64X2 + } else { + Opcode::VINSERTI32X4 + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::Y; + instruction.vex_reg.bank = RegisterBank::Y; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 16; + } + instruction.operands[0] = OperandSpec::RegRRR.masked(); + 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; + } + generated::EVEXOperandCode::Gm_V_zmm_E_ymm_imm8 => { + check_mask_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VINSERTF32X8 { + instruction.opcode = Opcode::VINSERTF64X4; + } else if instruction.opcode == Opcode::VINSERTI32X8 { + instruction.opcode = Opcode::VINSERTI64X4; + } + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::Z; + instruction.vex_reg.bank = RegisterBank::Z; + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.mem_size = 32; + instruction.operands[0] = OperandSpec::RegRRR.masked(); + 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; + } + generated::EVEXOperandCode::Em_ymm_G_zmm_imm8 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VEXTRACTF32X8 { + instruction.opcode = Opcode::VEXTRACTF64X4; + } else if instruction.opcode == Opcode::VEXTRACTI32X8 { + instruction.opcode = Opcode::VEXTRACTI64X4; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::Z; + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.mem_size = 32; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::Gm_zmm_Eq_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 8; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_ymm_Ed_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_xmm_Ew_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 2; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_zmm_E_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 16; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_ymm_Eq_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 8; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_xmm_Ed_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_zmm_E_ymm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 32; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_zmm_E_ymm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 32; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_ymm_E_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 16; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_ymm_E_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 16; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_xmm_Eq_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 8; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_xmm_Eq_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 8; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Em_ymm_G_zmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + instruction.mem_size = 32; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Em_xmm_G_zmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + instruction.mem_size = 16; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Em_xmm_G_ymm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + instruction.mem_size = 16; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Eqm_xmm_G_zmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + instruction.mem_size = 8; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Eqm_xmm_G_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.mem_size = 8; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Edm_xmm_G_ymm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + instruction.mem_size = 4; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Edm_xmm_G_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.mem_size = 4; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Ewm_xmm_G_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.mem_size = 2; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Eqm_xmm_G_ymm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + instruction.mem_size = 8; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_xmm_Ed_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_ymm_Ed_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_zmm_M_ymm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VBROADCASTF32X8 { + instruction.opcode = Opcode::VBROADCASTF64X4; + } else if instruction.opcode == Opcode::VBROADCASTI32X8 { + instruction.opcode = Opcode::VBROADCASTI64X4; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } else { + instruction.mem_size = 32; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_zmm_M_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VBROADCASTF32X4 { + instruction.opcode = Opcode::VBROADCASTF64X2; + } else if instruction.opcode == Opcode::VBROADCASTI32X4 { + instruction.opcode = Opcode::VBROADCASTI64X2; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } else { + instruction.mem_size = 16; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_ymm_M_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VBROADCASTF32X4 { + instruction.opcode = Opcode::VBROADCASTF64X2; + } else if instruction.opcode == Opcode::VBROADCASTI32X4 { + instruction.opcode = Opcode::VBROADCASTI64X2; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } else { + instruction.mem_size = 16; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_zmm_Ed_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = Opcode::VBROADCASTSD; + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 8; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::VBROADCASTF32X2_Gm_ymm_Ed_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = Opcode::VBROADCASTSD; + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 8; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_zmm_Ed_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Z; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Em_xmm_G_LL_imm8 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = if instruction.opcode == Opcode::VEXTRACTF32X4 { + Opcode::VEXTRACTF64X2 + } else if instruction.opcode == Opcode::VEXTRACTI32X4 { + Opcode::VEXTRACTI64X2 + } else { + instruction.opcode + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + if instruction.prefixes.evex_unchecked().lp() { + instruction.modrm_rrr.bank = RegisterBank::Z; + } else { + instruction.modrm_rrr.bank = RegisterBank::Y; + } + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.mem_size = 16; + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::Gm_V_LL_E_xmm_imm8 => { + check_mask_reg(instruction)?; + + instruction.opcode = if instruction.prefixes.evex_unchecked().vex().w() { + Opcode::VINSERTF64X2 + } else { + Opcode::VINSERTF32X4 + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + set_reg_sizes_from_ll(instruction)?; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.mem_size = 16; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + } + generated::EVEXOperandCode::Gm_V_LL_E_xmm_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + set_reg_sizes_from_ll(instruction)?; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.mem_size = 16; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::Gm_V_LL_E_xmm_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + set_reg_sizes_from_ll(instruction)?; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.mem_size = 16; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::Gm_V_LL_E_xmm => { + check_mask_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = if instruction.opcode == Opcode::VPSRAD { + Opcode::VPSRAQ + } else { + instruction.opcode + }; + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + set_reg_sizes_from_ll(instruction)?; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.mem_size = 16; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::VPEXTRW => { + deny_mask_reg(instruction)?; + deny_z(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::D; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + 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; + } + generated::EVEXOperandCode::VPINSRW => { + deny_mask_reg(instruction)?; + deny_z(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::D; + } else { + instruction.mem_size = 2; + } + + 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; + } + generated::EVEXOperandCode::VMOVQ_G_Ed_xmm => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 8; + } + + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::VMOVQ_Ed_G_xmm => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 8; + } + + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::VMOVQ_7e => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 8; + } + + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::VMOVD_7e => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = Opcode::VMOVQ; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::Q; + } else { + instruction.mem_size = 8; + } + } else { + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::D; + } else { + instruction.mem_size = 4; + } + } + + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR_maskmerge; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::VMOVD_6e => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::X; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = Opcode::VMOVQ; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::Q; + } else { + instruction.mem_size = 8; + } + } else { + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::D; + } else { + instruction.mem_size = 4; + } + } + + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Mask_V_E_LL_bcast => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VP2INTERSECTD { + instruction.opcode = Opcode::VP2INTERSECTQ; + } else if instruction.opcode == Opcode::VPTESTNMD { + instruction.opcode = Opcode::VPTESTNMQ; + } else if instruction.opcode == Opcode::VPTESTMD { + instruction.opcode = Opcode::VPTESTMQ; + } + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Mask_V_E_LL_bcast_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + apply_broadcast(instruction, 8, sz); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Mask_V_E_LL_bcast_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + apply_broadcast(instruction, 4, sz); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Em_G_LL => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VMOVDQA32 { + instruction.opcode = Opcode::VMOVDQA64; + } else if instruction.opcode == Opcode::VMOVDQU32 { + instruction.opcode = Opcode::VMOVDQU64; + } else if instruction.opcode == Opcode::VMOVDQU8 { + instruction.opcode = Opcode::VMOVDQU16; + } else if instruction.opcode == Opcode::VPCOMPRESSB { + instruction.opcode = Opcode::VPCOMPRESSW; + } else if instruction.opcode == Opcode::VPCOMPRESSD { + instruction.opcode = Opcode::VPCOMPRESSQ; + } else if instruction.opcode == Opcode::VCOMPRESSPS { + instruction.opcode = Opcode::VCOMPRESSPD; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Mask_U_LL => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VPMOVB2M { + instruction.opcode = Opcode::VPMOVW2M; + } else { + instruction.opcode = Opcode::VPMOVQ2M; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_rrr.bank = RegisterBank::K; + } else { + return Err(DecodeError::InvalidOperand); + } + } + generated::EVEXOperandCode::G_LL_Mask => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VPMOVM2B { + instruction.opcode = Opcode::VPMOVM2W; + } else { + instruction.opcode = Opcode::VPMOVM2Q; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_mmm.bank = RegisterBank::K; + } else { + return Err(DecodeError::InvalidOperand); + } + } + generated::EVEXOperandCode::G_LL_Mask_W1 => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_mmm.bank = RegisterBank::K; + } else { + return Err(DecodeError::InvalidOperand); + } + } + generated::EVEXOperandCode::G_LL_Mask_W0 => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_mmm.bank = RegisterBank::K; + } else { + return Err(DecodeError::InvalidOperand); + } + } + generated::EVEXOperandCode::G_E_LL_W0 => { + deny_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::E_G_LL_W0 => { + deny_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Em_G_LL_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = mem_oper.masked(); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Operands_72_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + let (r_sz, m_sz, m_data_sz) = match ( + instruction.prefixes.evex_unchecked().lp(), + instruction.prefixes.evex_unchecked().vex().l(), + ) { + (true, true) => { return Err(DecodeError::InvalidOpcode); }, + (true, false) => (RegisterBank::Y, RegisterBank::Z, 64), + (false, true) => (RegisterBank::X, RegisterBank::Y, 32), + (false, false) => (RegisterBank::X, RegisterBank::X, 16), + }; + instruction.modrm_rrr.bank = r_sz; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_mmm.bank = m_sz; + } else { + apply_broadcast(instruction, 4, m_data_sz); + } + } + generated::EVEXOperandCode::Gm_E_LL_bcast => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VPLZCNTD { + instruction.opcode = Opcode::VPLZCNTQ; + } else if instruction.opcode == Opcode::VRCP14PS { + instruction.opcode = Opcode::VRCP14PD; + } else if instruction.opcode == Opcode::VPOPCNTD { + instruction.opcode = Opcode::VPOPCNTQ; + } else if instruction.opcode == Opcode::VPCONFLICTD { + instruction.opcode = Opcode::VPCONFLICTQ; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } + instruction.mem_size = 0; + } else { + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_E_LL_bcast_W1 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } + instruction.mem_size = 0; + } else { + apply_broadcast(instruction, 8, sz); + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_E_LL_bcast_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } + instruction.mem_size = 0; + } else { + apply_broadcast(instruction, 4, sz); + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_LL_Ud => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VPBROADCASTD { + instruction.opcode = Opcode::VPBROADCASTQ; + } + } + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_mmm.bank = RegisterBank::Q; + } else { + instruction.modrm_mmm.bank = RegisterBank::D; + } + } else { + return Err(DecodeError::InvalidOperand); + } + } + generated::EVEXOperandCode::Gm_LL_Ud_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_mmm.bank = RegisterBank::D; + } else { + return Err(DecodeError::InvalidOperand); + } + } + generated::EVEXOperandCode::Gm_LL_Eq_xmm => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = Opcode::VPBROADCASTQ; + } else { + instruction.opcode = Opcode::VBROADCASTI32X2; + } + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 8; + } + } + generated::EVEXOperandCode::Gm_LL_Ed_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 4; + } + } + generated::EVEXOperandCode::Gm_LL_Ew_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 2; + } + } + generated::EVEXOperandCode::Gm_LL_Eb_xmm_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 1; + } + } + generated::EVEXOperandCode::Gm_E_LL_W0 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_E_LL_imm8 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VMOVDQA32 { + instruction.opcode = Opcode::VMOVDQA64; + } else if instruction.opcode == Opcode::VMOVDQU32 { + instruction.opcode = Opcode::VMOVDQU64; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gd_Ed_xmm_sae => { + deny_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + deny_z(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_rrr.bank = RegisterBank::Q; + } else { + instruction.modrm_rrr.bank = RegisterBank::D; + } + + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + + if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper == OperandSpec::RegMMM { + if instruction.opcode == Opcode::VCVTSS2USI || instruction.opcode == Opcode::VCVTSD2SI || instruction.opcode == Opcode::VCVTSD2USI { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } + } else { + return Err(DecodeError::InvalidOperand); + } + } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOperand); + } + } + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + if instruction.opcode == Opcode::VCVTTSD2SI || instruction.opcode == Opcode::VCVTSD2SI || instruction.opcode == Opcode::VCVTTSD2USI || instruction.opcode == Opcode::VCVTSD2USI { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } + } + instruction.operands[1] = mem_oper; + + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_E_LL_sae_bcast => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VGETEXPPS { + instruction.opcode = Opcode::VGETEXPPD; + } else if instruction.opcode == Opcode::VRSQRT14PS { + instruction.opcode = Opcode::VRSQRT14PD; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper != OperandSpec::RegMMM { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + apply_broadcast(instruction, if instruction.prefixes.evex_unchecked().vex().w() { + 8 + } else { + 4 + }, sz); + } else { + if instruction.opcode == Opcode::VSQRTPS || instruction.opcode == Opcode::VCVTPS2DQ { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } + set_reg_sizes(instruction, RegisterBank::Z); + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_E_LL => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VMOVDQA32 { + instruction.opcode = Opcode::VMOVDQA64; + } else if instruction.opcode == Opcode::VMOVDQU32 { + instruction.opcode = Opcode::VMOVDQU64; + } else if instruction.opcode == Opcode::VMOVDQU8 { + instruction.opcode = Opcode::VMOVDQU16; + } else if instruction.opcode == Opcode::VPOPCNTB { + instruction.opcode = Opcode::VPOPCNTW; + } else if instruction.opcode == Opcode::VPEXPANDB { + instruction.opcode = Opcode::VPEXPANDW; + } else if instruction.opcode == Opcode::VEXPANDPS { + instruction.opcode = Opcode::VEXPANDPD; + } else if instruction.opcode == Opcode::VPEXPANDD { + instruction.opcode = Opcode::VPEXPANDQ; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_Ed_LL_imm8_bcast => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VSHUFF32X4 { + instruction.opcode = Opcode::VSHUFF64X2; + } + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_bcast_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + apply_broadcast(instruction, 4, sz); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VPBLENDMB { + instruction.opcode = Opcode::VPBLENDMW; + } else if instruction.opcode == Opcode::VPERMI2B { + instruction.opcode = Opcode::VPERMI2W; + } else if instruction.opcode == Opcode::VPERMT2B { + instruction.opcode = Opcode::VPERMT2W; + } else if instruction.opcode == Opcode::VPERMB { + instruction.opcode = Opcode::VPERMW; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Mask_V_E_LL_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Mask_V_E_LL => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + instruction.mem_size = sz; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VPTESTNMB { + instruction.opcode = Opcode::VPTESTNMW; + } else if instruction.opcode == Opcode::VPTESTMB { + instruction.opcode = Opcode::VPTESTMW; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Maskm_V_Eq_xmm_imm8_sae_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + deny_z(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 8; + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOperand); + } + } + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + 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; + + set_reg_sizes(instruction, RegisterBank::X); + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Maskm_V_Ed_xmm_imm8_sae_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + deny_z(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOperand); + } + } + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + 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; + + set_reg_sizes(instruction, RegisterBank::X); + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Mask_V_E_LL_imm8 => { + check_mask_reg(instruction)?; + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOperand); + } + + let sz = regs_size(instruction); + instruction.mem_size = sz; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VPCMPUB { + instruction.opcode = Opcode::VPCMPUW; + } else if instruction.opcode == Opcode::VPCMPB { + instruction.opcode = Opcode::VPCMPW; + } + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + + set_reg_sizes_from_ll(instruction)?; + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Mask_Ed_xmm_imm8 => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + deny_z(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = if instruction.opcode == Opcode::VFPCLASSSS { + Opcode::VFPCLASSSD + } else { + instruction.opcode + }; + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + set_reg_sizes(instruction, RegisterBank::X); + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Mask_E_LL_imm8_bcast => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.prefixes.evex_unchecked().broadcast() { + apply_broadcast(instruction, 8, sz); + } else { + instruction.mem_size = sz; + } + instruction.opcode = if instruction.opcode == Opcode::VFPCLASSPS { + Opcode::VFPCLASSPD + } else { + instruction.opcode + }; + } else { + if instruction.prefixes.evex_unchecked().broadcast() { + apply_broadcast(instruction, 4, sz); + } else { + instruction.mem_size = sz; + } + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Mask_V_E_LL_imm8_sae_bcast_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.prefixes.evex_unchecked().broadcast() { + apply_broadcast(instruction, 8, sz); + } else { + instruction.mem_size = sz; + } + } else { + if instruction.prefixes.evex_unchecked().broadcast() { + apply_broadcast(instruction, 4, sz); + } else { + instruction.mem_size = sz; + } + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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 { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + set_reg_sizes_from_ll(instruction)?; + } + instruction.mem_size = 0; + } else { + set_reg_sizes_from_ll(instruction)?; + } + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Mask_V_E_LL_imm8_bcast => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.prefixes.evex_unchecked().broadcast() { + apply_broadcast(instruction, 8, sz); + } else { + instruction.mem_size = sz; + } + // this operand code is used in a few places, apply `w` as appropriate + instruction.opcode = if instruction.opcode == Opcode::VPCMPUD { + Opcode::VPCMPUQ + } else { + Opcode::VPCMPQ + }; + } else { + if instruction.prefixes.evex_unchecked().broadcast() { + apply_broadcast(instruction, 4, sz); + } else { + instruction.mem_size = sz; + } + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + + set_reg_sizes_from_ll(instruction)?; + if instruction.modrm_rrr.num >= 8 { + return Err(DecodeError::InvalidOperand); + } else { + instruction.modrm_rrr.bank = RegisterBank::K; + } + } + generated::EVEXOperandCode::Opcode_72_Gm_E_LL_imm8_bcast => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + let rrr = (modrm >> 3) & 7; + + let item_size = if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = [ + Ok(Opcode::VPRORQ), + Ok(Opcode::VPROLQ), + Err(DecodeError::InvalidOpcode), + Err(DecodeError::InvalidOpcode), + Ok(Opcode::VPSRAQ), + Err(DecodeError::InvalidOpcode), + Err(DecodeError::InvalidOpcode), + Err(DecodeError::InvalidOpcode), + ][rrr as usize]?; + 8 + } else { + instruction.opcode = [ + Ok(Opcode::VPRORD), + Ok(Opcode::VPROLD), + Ok(Opcode::VPSRLD), + Err(DecodeError::InvalidOpcode), + Ok(Opcode::VPSRAD), + Ok(Opcode::VPSLLD), + Err(DecodeError::InvalidOpcode), + Err(DecodeError::InvalidOpcode), + ][rrr as usize]?; + 4 + }; + + apply_broadcast(instruction, item_size, sz); + + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegVex_maskmerge; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_imm8_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + instruction.mem_size = sz; +/* + instruction.opcode = if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + if instruction.opcode == Opcode::VALIGND { + Opcode::VALIGNQ + } else if instruction.opcode == Opcode::VPTERNLOGD { + Opcode::VPTERNLOGQ + } else if instruction.opcode == Opcode::VSHUFI32X4 { + Opcode::VSHUFI64X2 + } else { + instruction.opcode + } + } else { + apply_broadcast(instruction, 4, sz); + instruction.opcode + }; +*/ + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_imm8_bcast => { + check_mask_reg(instruction)?; + + let sz = regs_size(instruction); + + instruction.opcode = if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + if instruction.opcode == Opcode::VALIGND { + Opcode::VALIGNQ + } else if instruction.opcode == Opcode::VPTERNLOGD { + Opcode::VPTERNLOGQ + } else if instruction.opcode == Opcode::VSHUFI32X4 { + Opcode::VSHUFI64X2 + } else if instruction.opcode == Opcode::VPSHLDD { + Opcode::VPSHLDQ + } else if instruction.opcode == Opcode::VPSHRDD { + Opcode::VPSHRDQ + } else { + instruction.opcode + } + } else { + apply_broadcast(instruction, 4, sz); + instruction.opcode + }; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_imm8_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOperand); + } else { + instruction.mem_size = sz; + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_imm8_bcast_W0 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let sz = regs_size(instruction); + + if instruction.opcode == Opcode::VSHUFPS { + apply_broadcast(instruction, 4, sz); + } else { + apply_broadcast(instruction, 8, sz); + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::G_V_E_LL_imm8 => { + check_mask_reg(instruction)?; + + instruction.mem_size = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + 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; + instruction.operand_count = 4; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_imm8 => { + check_mask_reg(instruction)?; + + instruction.mem_size = regs_size(instruction); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_V_E_LL_imm8_bcast_W1 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let sz = regs_size(instruction); + + apply_broadcast(instruction, 8, sz); + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + 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; + + set_reg_sizes_from_ll(instruction)?; + } + generated::EVEXOperandCode::Gm_ymm_E_zmm_sae_bcast_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_zmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + instruction.operands[1] = mem_oper; + if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper != OperandSpec::RegMMM { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + apply_broadcast(instruction, 8, 64); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.mem_size = 64; + } + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_xmm_E_ymm_sae_bcast_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.operands[1] = mem_oper; + if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper != OperandSpec::RegMMM { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + apply_broadcast(instruction, 8, 32); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + instruction.modrm_rrr.bank = RegisterBank::Y; + instruction.modrm_mmm.bank = RegisterBank::Z; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.mem_size = 32; + } + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_xmm_E_xmm_sae_bcast_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.operands[1] = mem_oper; + if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper != OperandSpec::RegMMM { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + apply_broadcast(instruction, 8, 16); + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + instruction.modrm_rrr.bank = RegisterBank::Y; + instruction.modrm_mmm.bank = RegisterBank::Z; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.mem_size = 16; + } + instruction.operand_count = 2; + } + generated::EVEXOperandCode::VCVTTPS2UQQ => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VCVTTPS2UQQ { + instruction.opcode = Opcode::VCVTTPD2UQQ; + } else if instruction.opcode == Opcode::VCVTPS2UQQ { + instruction.opcode = Opcode::VCVTPD2UQQ; + } else if instruction.opcode == Opcode::VCVTTPS2QQ { + instruction.opcode = Opcode::VCVTTPD2QQ; + } else if instruction.opcode == Opcode::VCVTPS2QQ { + instruction.opcode = Opcode::VCVTPD2QQ; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + instruction.mem_size = 0; + + let mut lp = 0; + if instruction.prefixes.evex_unchecked().lp() { lp |= 2; } + if instruction.prefixes.evex_unchecked().vex().l() { lp |= 1; } + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + if instruction.opcode == Opcode::VCVTPD2UQQ || instruction.opcode == Opcode::VCVTPS2UQQ || instruction.opcode == Opcode::VCVTPD2QQ || instruction.opcode == Opcode::VCVTPS2QQ { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } + instruction.modrm_rrr.bank = RegisterBank::Z; + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_mmm.bank = RegisterBank::Z; + } else { + instruction.modrm_mmm.bank = RegisterBank::Y; + } + } else { + let (r_sz, m_sz) = if instruction.prefixes.evex_unchecked().vex().w() { + [ + Ok((RegisterBank::X, RegisterBank::X)), + Ok((RegisterBank::Y, RegisterBank::Y)), + Ok((RegisterBank::Z, RegisterBank::Z)), + Err(DecodeError::InvalidOperand), + ][lp]? + } else { + [ + Ok((RegisterBank::X, RegisterBank::X)), + Ok((RegisterBank::Y, RegisterBank::X)), + Ok((RegisterBank::Z, RegisterBank::Y)), + Err(DecodeError::InvalidOperand), + ][lp]? + }; + instruction.modrm_rrr.bank = r_sz; + instruction.modrm_mmm.bank = m_sz; + } + } else { + let (r_sz, m_sz) = if instruction.prefixes.evex_unchecked().vex().w() { + [ + Ok((RegisterBank::X, 16)), + Ok((RegisterBank::Y, 32)), + Ok((RegisterBank::Z, 64)), + Err(DecodeError::InvalidOperand), + ][lp]? + } else { + [ + Ok((RegisterBank::X, 8)), + Ok((RegisterBank::Y, 16)), + Ok((RegisterBank::Z, 32)), + Err(DecodeError::InvalidOperand), + ][lp]? + }; + instruction.modrm_rrr.bank = r_sz; + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, m_sz); + } else { + apply_broadcast(instruction, 4, m_sz); + } + } + } + generated::EVEXOperandCode::VCVTPH2PS => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.opcode == Opcode::VCVTPS2PD { + if instruction.prefixes.evex_unchecked().vex().w() { + return Err(DecodeError::InvalidOpcode); + } + } else if instruction.opcode == Opcode::VCVTTPS2UQQ { + instruction.opcode = Opcode::VCVTTPD2UQQ; + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + instruction.mem_size = 0; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + instruction.modrm_rrr.bank = RegisterBank::Z; + if instruction.opcode == Opcode::VCVTTPD2UQQ { + instruction.modrm_mmm.bank = RegisterBank::Z; + } else { + instruction.modrm_mmm.bank = RegisterBank::Y; + } + } else { + let (r_sz, m_sz) = match ( + instruction.prefixes.evex_unchecked().vex().l(), + instruction.prefixes.evex_unchecked().lp() + ) { + (true, true) => { return Err(DecodeError::InvalidOperand); } + (false, true) => (RegisterBank::Z, RegisterBank::Y), + (true, false) => (RegisterBank::Y, RegisterBank::X), + (false, false) => (RegisterBank::X, RegisterBank::X), + }; + instruction.modrm_rrr.bank = r_sz; + instruction.modrm_mmm.bank = m_sz; + } + } else { + let (r_sz, m_sz) = match ( + instruction.prefixes.evex_unchecked().vex().l(), + instruction.prefixes.evex_unchecked().lp() + ) { + (true, true) => { return Err(DecodeError::InvalidOperand); } + (true, false) => (RegisterBank::Y, 16), + (false, true) => (RegisterBank::Z, 32), + (false, false) => (RegisterBank::X, 8), + }; + instruction.modrm_rrr.bank = r_sz; + if instruction.opcode == Opcode::VCVTPS2PD { + apply_broadcast(instruction, 4, m_sz); + } else { + apply_broadcast(instruction, 8, m_sz); + } + } + } + generated::EVEXOperandCode::VCVTDQ2PS => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VCVTDQ2PS { + instruction.opcode = Opcode::VCVTQQ2PS; + } else if instruction.opcode == Opcode::VCVTUDQ2PS { + instruction.opcode = Opcode::VCVTUQQ2PS; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + instruction.mem_size = 0; + + let mut lp = 0; + if instruction.prefixes.evex_unchecked().lp() { lp |= 2; } + if instruction.prefixes.evex_unchecked().vex().l() { lp |= 1; } + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_rrr.bank = RegisterBank::Y; + } else { + instruction.modrm_rrr.bank = RegisterBank::Z; + } + instruction.modrm_mmm.bank = RegisterBank::Z; + } else { + let (r_sz, m_sz) = if instruction.prefixes.evex_unchecked().vex().w() { + [ + Ok((RegisterBank::X, RegisterBank::X)), + Ok((RegisterBank::X, RegisterBank::Y)), + Ok((RegisterBank::Y, RegisterBank::Z)), + Err(DecodeError::InvalidOperand), + ][lp]? + } else { + [ + Ok((RegisterBank::X, RegisterBank::X)), + Ok((RegisterBank::Y, RegisterBank::Y)), + Ok((RegisterBank::Z, RegisterBank::Z)), + Err(DecodeError::InvalidOperand), + ][lp]? + }; + instruction.modrm_rrr.bank = r_sz; + instruction.modrm_mmm.bank = m_sz; + } + } else { + let (r_sz, m_sz, item_sz) = if instruction.prefixes.evex_unchecked().vex().w() { + [ + Ok((RegisterBank::X, 16, 8)), + Ok((RegisterBank::X, 32, 8)), + Ok((RegisterBank::Y, 64, 8)), + Err(DecodeError::InvalidOperand), + ][lp]? + } else { + [ + Ok((RegisterBank::X, 16, 4)), + Ok((RegisterBank::Y, 32, 4)), + Ok((RegisterBank::Z, 64, 4)), + Err(DecodeError::InvalidOperand), + ][lp]? + }; + instruction.modrm_rrr.bank = r_sz; + apply_broadcast(instruction, item_sz, m_sz); + } + } + generated::EVEXOperandCode::VCVTTPS2UDQ => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + instruction.mem_size = 0; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VCVTTPS2UDQ { + instruction.opcode = Opcode::VCVTTPD2UDQ; + } else if instruction.opcode == Opcode::VCVTPS2UDQ { + instruction.opcode = Opcode::VCVTPD2UDQ; + } + } + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + if instruction.opcode == Opcode::VCVTTPD2UDQ || instruction.opcode == Opcode::VCVTTPS2UDQ { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_rrr.bank = RegisterBank::Y; + } else { + instruction.modrm_rrr.bank = RegisterBank::Z; + } + instruction.modrm_mmm.bank = RegisterBank::Z; + } else { + let (r_sz, m_sz) = match ( + instruction.prefixes.evex_unchecked().vex().l(), + instruction.prefixes.evex_unchecked().lp() + ) { + (true, true) => { return Err(DecodeError::InvalidOperand); } + (false, true) => (if instruction.prefixes.evex_unchecked().vex().w() { RegisterBank::Y } else { RegisterBank::Z }, RegisterBank::Z), + (true, false) => (if instruction.prefixes.evex_unchecked().vex().w() { RegisterBank::X } else { RegisterBank::Y }, RegisterBank::Y), + (false, false) => (RegisterBank::X, RegisterBank::X), + }; + instruction.modrm_rrr.bank = r_sz; + instruction.modrm_mmm.bank = m_sz; + } + } else { + let (r_sz, m_sz) = match ( + instruction.prefixes.evex_unchecked().vex().l(), + instruction.prefixes.evex_unchecked().lp() + ) { + (true, true) => { return Err(DecodeError::InvalidOperand); } +// (true, false) => (RegisterBank::Y, 32), + (true, false) => (if instruction.prefixes.evex_unchecked().vex().w() { RegisterBank::X } else { RegisterBank::Y }, 32), + (false, true) => (if instruction.prefixes.evex_unchecked().vex().w() { RegisterBank::Y } else { RegisterBank::Z }, 64), + (false, false) => (RegisterBank::X, 16), + }; + instruction.modrm_rrr.bank = r_sz; + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, m_sz); + } else { + apply_broadcast(instruction, 4, m_sz); + } + } + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VCVTDQ2PS { + instruction.opcode = Opcode::VCVTQQ2PS; + } + } + } + generated::EVEXOperandCode::VCVTTPD2DQ => { + check_mask_reg(instruction)?; + deny_vex_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + instruction.mem_size = 0; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VCVTTPS2UDQ { + instruction.opcode = Opcode::VCVTTPD2UDQ; + } + } + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + if instruction.opcode == Opcode::VCVTDQ2PS || instruction.opcode == Opcode::VCVTPD2DQ { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } + if instruction.opcode == Opcode::VCVTDQ2PS && !instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_rrr.bank = RegisterBank::Z; + } else { + instruction.modrm_rrr.bank = RegisterBank::Y; + } + instruction.modrm_mmm.bank = RegisterBank::Z; + } else { + let (r_sz, m_sz) = match ( + instruction.prefixes.evex_unchecked().vex().l(), + instruction.prefixes.evex_unchecked().lp() + ) { + (true, true) => { return Err(DecodeError::InvalidOperand); } + (false, true) => (RegisterBank::Y, RegisterBank::Z), + (true, false) => (RegisterBank::X, RegisterBank::Y), + (false, false) => (RegisterBank::X, RegisterBank::X), + }; + instruction.modrm_rrr.bank = r_sz; + instruction.modrm_mmm.bank = m_sz; + } + } else { + let (r_sz, m_sz) = match ( + instruction.prefixes.evex_unchecked().vex().l(), + instruction.prefixes.evex_unchecked().lp() + ) { + (true, true) => { return Err(DecodeError::InvalidOperand); } + (true, false) => (RegisterBank::X, 32), + (false, true) => (RegisterBank::Y, 64), + (false, false) => (RegisterBank::X, 16), + }; + instruction.modrm_rrr.bank = r_sz; + apply_broadcast(instruction, 8, m_sz); + } + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VCVTDQ2PS { + instruction.opcode = Opcode::VCVTQQ2PS; + } + } + } + generated::EVEXOperandCode::Gm_ymm_U_zmm_sae_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_zmm(bytes, instruction, modrm, length)?; + instruction.modrm_rrr.bank = RegisterBank::Y; + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Gm_V_E_xmm_sae_W1 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + set_reg_sizes(instruction, RegisterBank::X); + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + if instruction.opcode == Opcode::VMINSD || instruction.opcode == Opcode::VMAXSD { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + } + } else { + instruction.mem_size = 8; + } + } + generated::EVEXOperandCode::Gm_V_E_xmm_sae => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VEXP2SS { + instruction.opcode = Opcode::VEXP2SD; + } else if instruction.opcode == Opcode::VRCP28SS { + instruction.opcode = Opcode::VRCP28SD; + } else if instruction.opcode == Opcode::VRSQRT28SS { + instruction.opcode = Opcode::VRSQRT28SD; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + set_reg_sizes(instruction, RegisterBank::X); + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } + } else { + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } + } + } + generated::EVEXOperandCode::Gm_E_zmm_sae_bcast => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VEXP2PS { + instruction.opcode = Opcode::VEXP2PD; + } else if instruction.opcode == Opcode::VRCP28PS { + instruction.opcode = Opcode::VRCP28PD; + } else if instruction.opcode == Opcode::VRSQRT28PS { + instruction.opcode = Opcode::VRSQRT28PD; + } + } + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_zmm(bytes, instruction, modrm, length)?; + + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + set_reg_sizes(instruction, RegisterBank::Z); + } else { + let sz = regs_size(instruction); + if sz < 64 { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + set_reg_sizes_from_ll(instruction)?; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + let sz = regs_size(instruction); + if sz < 64 { + return Err(DecodeError::InvalidOperand); + } + + if instruction.prefixes.evex_unchecked().vex().w() { + apply_broadcast(instruction, 8, sz); + } else { + apply_broadcast(instruction, 4, sz); + } + set_reg_sizes_from_ll(instruction)?; + } + } + generated::EVEXOperandCode::Gm_U_zmm_sae_W0 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + set_reg_sizes(instruction, RegisterBank::Z); + } + generated::EVEXOperandCode::Gm_U_zmm_imm8_sae_W0 => { + deny_vex_reg(instruction)?; + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + + set_reg_sizes(instruction, RegisterBank::Z); + } + generated::EVEXOperandCode::Edd_G_xmm_imm8 => { + deny_vex_reg(instruction)?; + deny_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = 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; + instruction.operand_count = 3; + + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.opcode = Opcode::VPEXTRQ; + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::Q; + } else { + instruction.mem_size = 8; + } + } else { + instruction.opcode = Opcode::VPEXTRD; + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::D; + } else { + instruction.mem_size = 4; + } + } + } + generated::EVEXOperandCode::VCVTUSI2SD => { + deny_mask_reg(instruction)?; + deny_z(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = 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; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_mmm.bank = RegisterBank::Q; + } else { + instruction.modrm_mmm.bank = RegisterBank::D; + } + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + if instruction.prefixes.evex_unchecked().lp() || !instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOpcode); + } + } + } + } else { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } + } + instruction.operand_count = 3; + } + generated::EVEXOperandCode::VEXTRACTPS => { + deny_vex_reg(instruction)?; + deny_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = 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; + instruction.operand_count = 3; + + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::D; + } else { + instruction.mem_size = 4; + } + } + generated::EVEXOperandCode::Ewd_G_xmm_imm8 => { + deny_vex_reg(instruction)?; + deny_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = 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; + instruction.operand_count = 3; + + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::D; + } else { + instruction.mem_size = 2; + } + } + generated::EVEXOperandCode::Ebd_G_xmm_imm8 => { + deny_vex_reg(instruction)?; + deny_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = 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; + instruction.operand_count = 3; + + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::D; + } else { + instruction.mem_size = 1; + } + } + generated::EVEXOperandCode::Gm_V_Ed_xmm_imm8_sae => { + check_mask_reg(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + + let item_size = if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VRANGESS { + instruction.opcode = Opcode::VRANGESD; + 8 + } else if instruction.opcode == Opcode::VFPCLASSSS { + instruction.opcode = Opcode::VFPCLASSSD; + 8 + } else if instruction.opcode == Opcode::VREDUCESS { + instruction.opcode = Opcode::VREDUCESD; + 8 + } else if instruction.opcode == Opcode::VFIXUPIMMSS { + instruction.opcode = Opcode::VFIXUPIMMSD; + 8 + } else if instruction.opcode == Opcode::VGETMANTSS { + instruction.opcode = Opcode::VGETMANTSD; + 8 + } else { + 4 + } + } else { + 4 + }; + + if let OperandSpec::RegMMM = mem_oper { + instruction.mem_size = 0; + } else{ + instruction.mem_size = item_size; + } + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + 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; + + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::Gm_V_E_xmm_imm8_sae => { + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if let OperandSpec::RegMMM = mem_oper { + /* no mem size */ + } else{ + instruction.mem_size = 8; + } + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + } + 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; + + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::Gm_V_zmm_M_xmm_W0 => { + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + instruction.modrm_rrr.bank = RegisterBank::Z; + instruction.vex_reg.bank = RegisterBank::Z; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if let OperandSpec::RegMMM = mem_oper { + return Err(DecodeError::InvalidOperand); + } else{ + instruction.mem_size = 16; + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + } + generated::EVEXOperandCode::Gm_V_M_xmm => { + check_mask_reg(instruction)?; + + instruction.mem_size = 16; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::VMOVSD_10 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + if mem_oper == OperandSpec::RegMMM { + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + instruction.mem_size = 0; + } else { + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + instruction.mem_size = 8; + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::VMOVSD_11 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 1)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper.masked(); + if mem_oper == OperandSpec::RegMMM { + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = OperandSpec::RegRRR; + instruction.operand_count = 3; + + instruction.mem_size = 0; + } else { + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + instruction.mem_size = 8; + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::VMOVSS_10 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR_maskmerge; + if mem_oper == OperandSpec::RegMMM { + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + instruction.mem_size = 0; + } else { + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + + instruction.mem_size = 4; + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::VMOVSS_11 => { + check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper.masked(); + if mem_oper == OperandSpec::RegMMM { + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = OperandSpec::RegRRR; + instruction.operand_count = 3; + + instruction.mem_size = 0; + } else { + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + instruction.mem_size = 4; + } + set_reg_sizes(instruction, RegisterBank::X); + } + generated::EVEXOperandCode::VCVTSI2SS => { + check_mask_reg(instruction)?; + deny_z(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if instruction.prefixes.evex_unchecked().broadcast() && mem_oper == OperandSpec::RegMMM { + if !instruction.prefixes.evex_unchecked().vex().w() && instruction.opcode == Opcode::VCVTSI2SD { + instruction.operands[0] = OperandSpec::RegRRR; + } else { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } + } else { + instruction.operands[0] = OperandSpec::RegRRR; + } + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + + set_reg_sizes(instruction, RegisterBank::X); + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_mmm.bank = RegisterBank::Q; + } else { + instruction.modrm_mmm.bank = RegisterBank::D; + } + } else { + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } + } + } + generated::EVEXOperandCode::VCVTTSS2SI => { + check_mask_reg(instruction)?; + deny_z(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; + } else { + instruction.operands[0] = OperandSpec::RegRRR; + } + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_rrr.bank = RegisterBank::Q; + } else { + instruction.modrm_rrr.bank = RegisterBank::D; + } + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::VCVTSS2SI => { + check_mask_reg(instruction)?; + deny_z(instruction)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if instruction.prefixes.evex_unchecked().broadcast() { + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; + } else { + instruction.operands[0] = OperandSpec::RegRRR; + } + if instruction.prefixes.evex_unchecked().vex().w() { + instruction.modrm_rrr.bank = RegisterBank::Q; + } else { + instruction.modrm_rrr.bank = RegisterBank::D; + } + + if mem_oper == OperandSpec::RegMMM { + instruction.mem_size = 0; + } else { + instruction.mem_size = 4; + } + + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + } + generated::EVEXOperandCode::Operands_12_W0 => { + deny_mask_reg(instruction)?; + deny_z(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + 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.operand_count = 3; + + set_reg_sizes(instruction, RegisterBank::X); + + if mem_oper == OperandSpec::RegMMM { + instruction.opcode = Opcode::VMOVHLPS; + + instruction.mem_size = 0; + } else { + instruction.opcode = Opcode::VMOVLPS; + + instruction.mem_size = 8; + } + } + generated::EVEXOperandCode::Operands_16_W0 => { + deny_mask_reg(instruction)?; + deny_z(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + 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.operand_count = 3; + + set_reg_sizes(instruction, RegisterBank::X); + + if mem_oper == OperandSpec::RegMMM { + instruction.opcode = Opcode::VMOVLHPS; + + instruction.mem_size = 0; + } else { + instruction.opcode = Opcode::VMOVHPS; + + instruction.mem_size = 8; + } + } + generated::EVEXOperandCode::Mq_G_W0 => { + deny_mask_reg(instruction)?; + deny_z(instruction)?; + ensure_W(instruction, 0)?; + + let modrm = read_modrm(bytes, length)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + set_reg_sizes(instruction, RegisterBank::X); + + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } else { + instruction.mem_size = 8; + } + } + generated::EVEXOperandCode::Nothing => {} + o => { + panic!("unhandled operand code {:?}. opcode={}", o, instruction.opcode); + } + } + Ok(()) +} -- cgit v1.1