diff options
Diffstat (limited to 'src/shared/evex.in')
| -rw-r--r-- | src/shared/evex.in | 344 |
1 files changed, 267 insertions, 77 deletions
diff --git a/src/shared/evex.in b/src/shared/evex.in index 0aa7d95..07c82e5 100644 --- a/src/shared/evex.in +++ b/src/shared/evex.in @@ -1,6 +1,7 @@ use super::OperandSpec; use super::FieldDescription; use super::InnerDescription; +use super::Prefixes; use yaxpeax_arch::annotation::DescriptionSink; @@ -312,6 +313,23 @@ fn check_mask_reg(inst: &Instruction) -> Result<(), DecodeError> { } #[inline(always)] +fn check_allowed_zero_merge(prefixes: &Prefixes, oper: OperandSpec) -> Result<(), DecodeError> { + if prefixes.evex_unchecked().merge() { + // if evex.z is set + + if oper.is_memory() { + // quoth APM, + // > 3.2.4 Exceptions Caused by Illegal EVEX encodings + // > .. + // > EVEX.z == 1 ... Instructions that do not specify {z} ... #UD + return Err(DecodeError::InvalidOperand); + } + } + + Ok(()) +} + +#[inline(always)] fn apply_broadcast(inst: &mut Instruction, item_size: u8, reg_size: u8) { if inst.prefixes.evex_unchecked().broadcast() { inst.mem_size = item_size; @@ -436,6 +454,8 @@ pub(crate) fn read_evex_operands< if instruction.prefixes.evex_unchecked().vex().w() { if instruction.opcode == Opcode::VRSQRT14SS { instruction.opcode = Opcode::VRSQRT14SD; + } else if instruction.opcode == Opcode::VRCP14SS { + instruction.opcode = Opcode::VRCP14SD; } } @@ -471,6 +491,10 @@ pub(crate) fn read_evex_operands< } else { if instruction.prefixes.evex_unchecked().broadcast() { return Err(DecodeError::InvalidOpcode); + } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOpcode); + } } instruction.mem_size = 8; } @@ -488,12 +512,6 @@ pub(crate) fn read_evex_operands< 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; @@ -554,7 +572,10 @@ pub(crate) fn read_evex_operands< instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; } } else { - if instruction.prefixes.evex_unchecked().broadcast() { + deny_broadcast(instruction)?; + + if instruction.prefixes.evex_unchecked().lp() && + instruction.prefixes.evex_unchecked().vex().l() { return Err(DecodeError::InvalidOpcode); } @@ -763,6 +784,8 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::G_V_Ed_xmm_imm8_W0 => { deny_mask_reg(instruction)?; ensure_W(instruction, 0)?; + deny_z(instruction)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -809,6 +832,9 @@ pub(crate) fn read_evex_operands< return Err(DecodeError::InvalidOperand); } } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOpcode); + } instruction.operands[0] = OperandSpec::RegRRR; } instruction.operands[1] = OperandSpec::RegVex; @@ -817,6 +843,8 @@ pub(crate) fn read_evex_operands< } generated::EVEXOperandCode::G_V_xmm_Edq_imm8 => { deny_mask_reg(instruction)?; + deny_z(instruction)?; + deny_broadcast(instruction)?; let (sz, bank) = if instruction.prefixes.evex_unchecked().vex().w() { if isa_has_qwords() { @@ -847,6 +875,8 @@ pub(crate) fn read_evex_operands< } generated::EVEXOperandCode::G_V_xmm_Ebd_imm8 => { deny_mask_reg(instruction)?; + deny_z(instruction)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -900,25 +930,10 @@ pub(crate) fn read_evex_operands< 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(words)?; - set_rrr(instruction, modrm); - let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y, sink)?; if mem_oper == OperandSpec::RegMMM { - return Err(DecodeError::InvalidOperand); + deny_broadcast(instruction)?; } - instruction.operands[0] = mem_oper; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.operand_count = 2; + instruction.operand_count = 3; set_reg_sizes_from_ll(instruction)?; } @@ -926,6 +941,8 @@ pub(crate) fn read_evex_operands< deny_vex_reg(instruction)?; deny_mask_reg(instruction)?; ensure_W(instruction, 1)?; + deny_z(instruction)?; + deny_broadcast(instruction)?; instruction.mem_size = regs_size(instruction); @@ -945,12 +962,14 @@ pub(crate) fn read_evex_operands< deny_vex_reg(instruction)?; check_mask_reg(instruction)?; ensure_W(instruction, 1)?; + deny_broadcast(instruction)?; instruction.mem_size = regs_size(instruction); let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.operands[0] = mem_oper.masked(); instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; @@ -960,6 +979,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::G_Ed_xmm_sae_W0 => { deny_vex_reg(instruction)?; deny_mask_reg(instruction)?; + deny_z(instruction)?; // vucomiss and vcomiss both are W=0 ensure_W(instruction, 0)?; @@ -968,12 +988,18 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if mem_oper.is_memory() { + deny_broadcast(instruction)?; + } instruction.regs[0].bank = RegisterBank::X; // in specific support of vcomisd/vucomisd 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::InvalidOpcode); + } instruction.operands[0] = OperandSpec::RegRRR; } instruction.operands[1] = mem_oper; @@ -981,7 +1007,8 @@ pub(crate) fn read_evex_operands< } generated::EVEXOperandCode::Gm_Eq_xmm_sae_W1 => { deny_vex_reg(instruction)?; - check_mask_reg(instruction)?; + deny_mask_reg(instruction)?; + deny_z(instruction)?; // vucomisd and vcomisd both are W=1 ensure_W(instruction, 1)?; @@ -990,12 +1017,18 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if mem_oper.is_memory() { + deny_broadcast(instruction)?; + } instruction.regs[0].bank = RegisterBank::X; // in specific support of vcomisd/vucomisd 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::InvalidOpcode); + } instruction.operands[0] = OperandSpec::RegRRR; } instruction.operands[1] = mem_oper; @@ -1005,6 +1038,7 @@ pub(crate) fn read_evex_operands< deny_vex_reg(instruction)?; check_mask_reg(instruction)?; ensure_W(instruction, 1)?; + deny_broadcast(instruction)?; instruction.mem_size = regs_size(instruction); @@ -1073,6 +1107,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Maskm_V_E_LL_imm8_sae_bcast_W1 => { check_mask_reg(instruction)?; ensure_W(instruction, 1)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -1126,7 +1161,7 @@ pub(crate) fn read_evex_operands< } } else { instruction.operands[0] = OperandSpec::RegRRR_maskmerge; - apply_broadcast(instruction, 8, sz); + apply_broadcast(instruction, 4, sz); set_reg_sizes_from_ll(instruction)?; } } @@ -1365,9 +1400,8 @@ pub(crate) fn read_evex_operands< } generated::EVEXOperandCode::G_V_E_LL => { deny_mask_reg(instruction)?; - if [Opcode::VAESDECLAST, Opcode::VAESDEC, Opcode::VAESENC, Opcode::VAESENCLAST].contains(&instruction.opcode) { - deny_z(instruction)?; - } + deny_z(instruction)?; + deny_broadcast(instruction)?; let sz = regs_size(instruction); @@ -1444,6 +1478,9 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y, sink)?; + if instruction.prefixes.evex_unchecked().broadcast() && !mem_oper.is_memory() { + return Err(DecodeError::InvalidOpcode); + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; @@ -1463,6 +1500,9 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y, sink)?; + if mem_oper == OperandSpec::RegMMM { + deny_broadcast(instruction)?; + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; instruction.operands[1] = mem_oper; instruction.imm = read_imm_unsigned(words, 1)?; @@ -1483,6 +1523,9 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y, sink)?; + if mem_oper == OperandSpec::RegMMM { + deny_broadcast(instruction)?; + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; instruction.operands[1] = mem_oper; instruction.imm = read_imm_unsigned(words, 1)?; @@ -1571,6 +1614,9 @@ pub(crate) fn read_evex_operands< set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper.is_memory() { + return Err(DecodeError::InvalidOperand); + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; } else { if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { @@ -1595,8 +1641,6 @@ pub(crate) fn read_evex_operands< 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; } } @@ -1604,6 +1648,9 @@ pub(crate) fn read_evex_operands< set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper.is_memory() { + return Err(DecodeError::InvalidOpcode); + }; instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; } else { if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { @@ -1626,6 +1673,44 @@ pub(crate) fn read_evex_operands< } set_reg_sizes(instruction, RegisterBank::X); } + generated::EVEXOperandCode::Gm_V_Ed_xmm_sae_noround => { + check_mask_reg(instruction)?; + + if instruction.prefixes.evex_unchecked().vex().w() { + if instruction.opcode == Opcode::VGETEXPSS { + instruction.opcode = Opcode::VGETEXPSD; + } + } + + let modrm = read_modrm(words)?; + set_rrr(instruction, modrm); + let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if instruction.prefixes.evex_unchecked().broadcast() { + if mem_oper.is_memory() { + return Err(DecodeError::InvalidOpcode); + }; + 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 { + 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)?; @@ -1665,6 +1750,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; if mem_oper == OperandSpec::RegMMM { if instruction.prefixes.evex_unchecked().broadcast() { // sae sets this to `vcvtps2ph ymm, zmm, imm8` @@ -1698,6 +1784,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; if mem_oper == OperandSpec::RegMMM { if instruction.prefixes.evex_unchecked().broadcast() { // sae sets this to `vcvtps2ph ymm, zmm, imm8` @@ -1732,6 +1819,7 @@ pub(crate) fn read_evex_operands< set_rrr(instruction, modrm); instruction.regs[0].bank = RegisterBank::Z; let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; if mem_oper == OperandSpec::RegMMM { if instruction.prefixes.evex_unchecked().broadcast() { instruction.operands[0] = OperandSpec::RegMMM_maskmerge_sae_noround; @@ -1739,6 +1827,9 @@ pub(crate) fn read_evex_operands< instruction.operands[0] = OperandSpec::RegMMM_maskmerge; } } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOpcode); + } if instruction.prefixes.evex_unchecked().broadcast() { return Err(DecodeError::InvalidOperand); } else { @@ -1847,6 +1938,7 @@ pub(crate) fn read_evex_operands< set_rrr(instruction, modrm); instruction.regs[0].bank = RegisterBank::Z; let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.mem_size = 32; instruction.operands[0] = mem_oper.masked(); instruction.operands[1] = OperandSpec::RegRRR; @@ -1966,6 +2058,7 @@ pub(crate) fn read_evex_operands< check_mask_reg(instruction)?; deny_vex_reg(instruction)?; deny_broadcast(instruction)?; + ensure_W(instruction, 0)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -2001,8 +2094,8 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Gm_ymm_E_xmm_W0 => { check_mask_reg(instruction)?; deny_vex_reg(instruction)?; - ensure_W(instruction, 0)?; deny_broadcast(instruction)?; + ensure_W(instruction, 0)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -2039,6 +2132,7 @@ pub(crate) fn read_evex_operands< check_mask_reg(instruction)?; deny_vex_reg(instruction)?; deny_broadcast(instruction)?; + ensure_W(instruction, 0)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -2080,6 +2174,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.regs[0].bank = RegisterBank::Z; instruction.mem_size = 32; instruction.operands[0] = mem_oper.masked(); @@ -2095,6 +2190,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.regs[0].bank = RegisterBank::Z; instruction.mem_size = 16; instruction.operands[0] = mem_oper.masked(); @@ -2110,6 +2206,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.regs[0].bank = RegisterBank::Y; instruction.mem_size = 16; instruction.operands[0] = mem_oper.masked(); @@ -2125,6 +2222,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.regs[0].bank = RegisterBank::Z; instruction.mem_size = 8; instruction.operands[0] = mem_oper.masked(); @@ -2140,6 +2238,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.regs[0].bank = RegisterBank::X; instruction.mem_size = 8; instruction.operands[0] = mem_oper.masked(); @@ -2155,6 +2254,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.regs[0].bank = RegisterBank::Y; instruction.mem_size = 4; instruction.operands[0] = mem_oper.masked(); @@ -2170,6 +2270,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.regs[0].bank = RegisterBank::X; instruction.mem_size = 4; instruction.operands[0] = mem_oper.masked(); @@ -2185,6 +2286,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.regs[0].bank = RegisterBank::X; instruction.mem_size = 2; instruction.operands[0] = mem_oper.masked(); @@ -2200,6 +2302,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.regs[0].bank = RegisterBank::Y; instruction.mem_size = 8; instruction.operands[0] = mem_oper.masked(); @@ -2408,6 +2511,7 @@ pub(crate) fn read_evex_operands< instruction.regs[0].bank = RegisterBank::Y; } let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.mem_size = 16; instruction.operands[0] = mem_oper.masked(); instruction.operands[1] = OperandSpec::RegRRR; @@ -2534,32 +2638,12 @@ pub(crate) fn read_evex_operands< 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)?; - deny_broadcast(instruction)?; - - let modrm = read_modrm(words)?; - set_rrr(instruction, modrm); - instruction.regs[0].bank = RegisterBank::X; - let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; - - 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)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -2581,6 +2665,7 @@ pub(crate) fn read_evex_operands< deny_vex_reg(instruction)?; ensure_W(instruction, 1)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -2599,6 +2684,7 @@ pub(crate) fn read_evex_operands< deny_mask_reg(instruction)?; deny_vex_reg(instruction)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -2630,6 +2716,7 @@ pub(crate) fn read_evex_operands< deny_mask_reg(instruction)?; deny_vex_reg(instruction)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -2659,6 +2746,11 @@ pub(crate) fn read_evex_operands< } generated::EVEXOperandCode::Mask_V_E_LL_bcast => { check_mask_reg(instruction)?; + deny_z(instruction)?; + + if instruction.opcode == Opcode::VP2INTERSECTD { + deny_mask_reg(instruction)?; + } let sz = regs_size(instruction); @@ -2680,6 +2772,7 @@ pub(crate) fn read_evex_operands< let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; if mem_oper == OperandSpec::RegMMM { instruction.mem_size = 0; + deny_broadcast(instruction)?; } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; instruction.operands[1] = OperandSpec::RegVex; @@ -2696,6 +2789,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Mask_V_E_LL_bcast_W1 => { check_mask_reg(instruction)?; ensure_W(instruction, 1)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -2704,7 +2798,9 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; if mem_oper == OperandSpec::RegMMM { + deny_broadcast(instruction)?; instruction.mem_size = 0; } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; @@ -2722,6 +2818,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Mask_V_E_LL_bcast_W0 => { check_mask_reg(instruction)?; ensure_W(instruction, 0)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -2731,6 +2828,7 @@ pub(crate) fn read_evex_operands< set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; if mem_oper == OperandSpec::RegMMM { + deny_broadcast(instruction)?; instruction.mem_size = 0; } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; @@ -2773,6 +2871,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; if mem_oper == OperandSpec::RegMMM { instruction.mem_size = 0; } @@ -2786,6 +2885,7 @@ pub(crate) fn read_evex_operands< deny_mask_reg(instruction)?; deny_vex_reg(instruction)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -2821,6 +2921,7 @@ pub(crate) fn read_evex_operands< deny_mask_reg(instruction)?; deny_vex_reg(instruction)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -2856,6 +2957,7 @@ pub(crate) fn read_evex_operands< deny_vex_reg(instruction)?; ensure_W(instruction, 1)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -2883,6 +2985,7 @@ pub(crate) fn read_evex_operands< deny_vex_reg(instruction)?; ensure_W(instruction, 0)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -2905,10 +3008,11 @@ pub(crate) fn read_evex_operands< return Err(DecodeError::InvalidOperand); } } - generated::EVEXOperandCode::G_E_LL_W0 => { + generated::EVEXOperandCode::G_M_LL_W0 => { deny_mask_reg(instruction)?; ensure_W(instruction, 0)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -2918,7 +3022,7 @@ pub(crate) fn read_evex_operands< set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; if mem_oper == OperandSpec::RegMMM { - instruction.mem_size = 0; + return Err(DecodeError::InvalidOperand); } instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; @@ -2926,20 +3030,20 @@ pub(crate) fn read_evex_operands< set_reg_sizes_from_ll(instruction)?; } - generated::EVEXOperandCode::E_G_LL_W0 => { + generated::EVEXOperandCode::M_G_LL_W0 => { + deny_vex_reg(instruction)?; deny_mask_reg(instruction)?; ensure_W(instruction, 0)?; deny_broadcast(instruction)?; + deny_z(instruction)?; - let sz = regs_size(instruction); - - instruction.mem_size = sz; + instruction.mem_size = regs_size(instruction); let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; if mem_oper == OperandSpec::RegMMM { - instruction.mem_size = 0; + return Err(DecodeError::InvalidOperand); } instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; @@ -2959,6 +3063,7 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; if mem_oper == OperandSpec::RegMMM { instruction.mem_size = 0; } @@ -2990,6 +3095,7 @@ pub(crate) fn read_evex_operands< }; instruction.regs[0].bank = r_sz; if mem_oper == OperandSpec::RegMMM { + deny_broadcast(instruction)?; instruction.mem_size = 0; instruction.regs[1].bank = m_sz; } else { @@ -3007,6 +3113,8 @@ pub(crate) fn read_evex_operands< instruction.opcode = Opcode::VPLZCNTQ; } else if instruction.opcode == Opcode::VRCP14PS { instruction.opcode = Opcode::VRCP14PD; + } else if instruction.opcode == Opcode::VRSQRT14PS { + instruction.opcode = Opcode::VRSQRT14PD; } else if instruction.opcode == Opcode::VPOPCNTD { instruction.opcode = Opcode::VPOPCNTQ; } else if instruction.opcode == Opcode::VPCONFLICTD { @@ -3086,6 +3194,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Gm_LL_Ud => { check_mask_reg(instruction)?; deny_vex_reg(instruction)?; + deny_broadcast(instruction)?; if instruction.prefixes.evex_unchecked().vex().w() && isa_has_qwords() { if instruction.opcode == Opcode::VPBROADCASTD { @@ -3120,6 +3229,7 @@ pub(crate) fn read_evex_operands< check_mask_reg(instruction)?; deny_vex_reg(instruction)?; ensure_W(instruction, 0)?; + deny_broadcast(instruction)?; let sz = regs_size(instruction); @@ -3355,8 +3465,6 @@ pub(crate) fn read_evex_operands< 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; } } @@ -3380,11 +3488,7 @@ pub(crate) fn read_evex_operands< 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; - } + instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; set_reg_sizes(instruction, RegisterBank::Z); } } else { @@ -3520,6 +3624,7 @@ pub(crate) fn read_evex_operands< check_mask_reg(instruction)?; ensure_W(instruction, 0)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -3546,6 +3651,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Mask_V_E_LL => { check_mask_reg(instruction)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -3594,6 +3700,10 @@ pub(crate) fn read_evex_operands< 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::InvalidOpcode); + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; } instruction.operands[1] = OperandSpec::RegVex; @@ -3626,6 +3736,10 @@ pub(crate) fn read_evex_operands< 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::InvalidOpcode); + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; } instruction.operands[1] = OperandSpec::RegVex; @@ -3644,6 +3758,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Mask_V_E_LL_imm8 => { check_mask_reg(instruction)?; deny_broadcast(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); instruction.mem_size = sz; @@ -3718,6 +3833,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Mask_E_LL_imm8_bcast => { check_mask_reg(instruction)?; deny_vex_reg(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -3763,6 +3879,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Mask_V_E_LL_imm8_sae_bcast_W0 => { check_mask_reg(instruction)?; ensure_W(instruction, 0)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -3809,6 +3926,7 @@ pub(crate) fn read_evex_operands< } generated::EVEXOperandCode::Mask_V_E_LL_imm8_bcast => { check_mask_reg(instruction)?; + deny_z(instruction)?; let sz = regs_size(instruction); @@ -3890,6 +4008,9 @@ pub(crate) fn read_evex_operands< apply_broadcast(instruction, item_size, sz); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if mem_oper == OperandSpec::RegMMM { + deny_broadcast(instruction)?; + } instruction.operands[0] = OperandSpec::RegVex_maskmerge; instruction.operands[1] = mem_oper; instruction.imm = read_imm_unsigned(words, 1)?; @@ -3978,17 +4099,14 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Gm_V_E_LL_imm8_W0 => { check_mask_reg(instruction)?; ensure_W(instruction, 0)?; + deny_broadcast(instruction)?; let sz = regs_size(instruction); let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; - if mem_oper == OperandSpec::RegMMM { - deny_broadcast(instruction)?; - } else { - instruction.mem_size = sz; - } + instruction.mem_size = sz; instruction.operands[0] = OperandSpec::RegRRR_maskmerge; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; @@ -4013,6 +4131,9 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if mem_oper == OperandSpec::RegMMM { + deny_broadcast(instruction)?; + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; @@ -4023,7 +4144,9 @@ pub(crate) fn read_evex_operands< set_reg_sizes_from_ll(instruction)?; } generated::EVEXOperandCode::G_V_E_LL_imm8 => { - check_mask_reg(instruction)?; + deny_mask_reg(instruction)?; + deny_z(instruction)?; + deny_broadcast(instruction)?; instruction.mem_size = regs_size(instruction); @@ -4041,6 +4164,7 @@ pub(crate) fn read_evex_operands< } generated::EVEXOperandCode::Gm_V_E_LL_imm8 => { check_mask_reg(instruction)?; + deny_broadcast(instruction)?; instruction.mem_size = regs_size(instruction); @@ -4067,6 +4191,9 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if mem_oper == OperandSpec::RegMMM { + deny_broadcast(instruction)?; + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; @@ -4235,6 +4362,7 @@ pub(crate) fn read_evex_operands< } generated::EVEXOperandCode::VCVTPH2PS => { check_mask_reg(instruction)?; + ensure_W(instruction, 0)?; deny_vex_reg(instruction)?; if instruction.opcode == Opcode::VCVTPS2PD { @@ -4248,6 +4376,9 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if instruction.opcode == Opcode::VCVTPH2PS && mem_oper.is_memory() { + deny_broadcast(instruction)?; + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; instruction.operands[1] = mem_oper; instruction.operand_count = 2; @@ -4439,6 +4570,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::VCVTTPD2DQ => { check_mask_reg(instruction)?; deny_vex_reg(instruction)?; + ensure_W(instruction, 1)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -4527,6 +4659,15 @@ pub(crate) fn read_evex_operands< let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if !instruction.prefixes.evex_unchecked().broadcast() { + if instruction.prefixes.evex_unchecked().lp() { + if instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOperand); + } + } + } else if mem_oper.is_memory() { + return Err(DecodeError::InvalidOperand); + } instruction.operands[0] = OperandSpec::RegRRR_maskmerge; instruction.operands[1] = OperandSpec::RegVex; @@ -4673,6 +4814,8 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Edd_G_xmm_imm8 => { deny_vex_reg(instruction)?; deny_mask_reg(instruction)?; + deny_z(instruction)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -4734,6 +4877,9 @@ pub(crate) fn read_evex_operands< } } } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOpcode); + } if instruction.prefixes.evex_unchecked().broadcast() { return Err(DecodeError::InvalidOpcode); } @@ -4748,6 +4894,8 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::VEXTRACTPS => { deny_vex_reg(instruction)?; deny_mask_reg(instruction)?; + deny_z(instruction)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -4768,6 +4916,8 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Ewd_G_xmm_imm8 => { deny_vex_reg(instruction)?; deny_mask_reg(instruction)?; + deny_z(instruction)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -4788,6 +4938,8 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Ebd_G_xmm_imm8 => { deny_vex_reg(instruction)?; deny_mask_reg(instruction)?; + deny_z(instruction)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -4840,6 +4992,10 @@ pub(crate) fn read_evex_operands< if let OperandSpec::RegMMM = mem_oper { instruction.mem_size = 0; } else{ + deny_broadcast(instruction)?; + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOpcode); + } instruction.mem_size = item_size; } if instruction.prefixes.evex_unchecked().broadcast() { @@ -4857,13 +5013,18 @@ pub(crate) fn read_evex_operands< } generated::EVEXOperandCode::Gm_V_E_xmm_imm8_sae_W1 => { ensure_W(instruction, 1)?; + check_mask_reg(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; if let OperandSpec::RegMMM = mem_oper { /* no mem size */ - } else{ + } else { + deny_broadcast(instruction)?; + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOpcode); + } instruction.mem_size = 8; } if instruction.prefixes.evex_unchecked().broadcast() { @@ -4918,6 +5079,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::VMOVSD_10 => { check_mask_reg(instruction)?; ensure_W(instruction, 1)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); @@ -4940,10 +5102,12 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::VMOVSD_11 => { check_mask_reg(instruction)?; ensure_W(instruction, 1)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.operands[0] = mem_oper.masked(); if mem_oper == OperandSpec::RegMMM { instruction.operands[1] = OperandSpec::RegVex; @@ -4962,12 +5126,16 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::VMOVSS_10 => { check_mask_reg(instruction)?; ensure_W(instruction, 0)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; instruction.operands[0] = OperandSpec::RegRRR_maskmerge; if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.evex_unchecked().broadcast() { + return Err(DecodeError::InvalidOpcode); + } instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; instruction.operand_count = 3; @@ -4984,10 +5152,12 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::VMOVSS_11 => { check_mask_reg(instruction)?; ensure_W(instruction, 0)?; + deny_broadcast(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + check_allowed_zero_merge(&instruction.prefixes, mem_oper)?; instruction.operands[0] = mem_oper.masked(); if mem_oper == OperandSpec::RegMMM { instruction.operands[1] = OperandSpec::RegVex; @@ -5004,12 +5174,15 @@ pub(crate) fn read_evex_operands< set_reg_sizes(instruction, RegisterBank::X); } generated::EVEXOperandCode::VCVTSI2SS => { - check_mask_reg(instruction)?; + deny_mask_reg(instruction)?; deny_z(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if mem_oper.is_memory() { + deny_broadcast(instruction)?; + } if instruction.prefixes.evex_unchecked().broadcast() && mem_oper == OperandSpec::RegMMM { if (!instruction.prefixes.evex_unchecked().vex().w() || !isa_has_qwords()) && instruction.opcode == Opcode::VCVTSI2SD { instruction.operands[0] = OperandSpec::RegRRR; @@ -5017,6 +5190,9 @@ pub(crate) fn read_evex_operands< instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; } } else { + if instruction.prefixes.evex_unchecked().lp() && instruction.prefixes.evex_unchecked().vex().l() { + return Err(DecodeError::InvalidOpcode); + } instruction.operands[0] = OperandSpec::RegRRR; } instruction.operands[1] = OperandSpec::RegVex; @@ -5049,15 +5225,21 @@ pub(crate) fn read_evex_operands< } } generated::EVEXOperandCode::VCVTTSS2SI => { - check_mask_reg(instruction)?; + deny_mask_reg(instruction)?; deny_z(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if mem_oper.is_memory() { + deny_broadcast(instruction)?; + } 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::InvalidOpcode); + } instruction.operands[0] = OperandSpec::RegRRR; } if instruction.prefixes.evex_unchecked().vex().w() { @@ -5076,15 +5258,21 @@ pub(crate) fn read_evex_operands< instruction.operand_count = 2; } generated::EVEXOperandCode::VCVTSS2SI => { - check_mask_reg(instruction)?; + deny_mask_reg(instruction)?; deny_z(instruction)?; let modrm = read_modrm(words)?; set_rrr(instruction, modrm); let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X, sink)?; + if mem_oper.is_memory() { + deny_broadcast(instruction)?; + } 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); + } instruction.operands[0] = OperandSpec::RegRRR; } if instruction.prefixes.evex_unchecked().vex().w() { @@ -5105,6 +5293,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Operands_12_W0 => { deny_mask_reg(instruction)?; deny_z(instruction)?; + deny_broadcast(instruction)?; ensure_W(instruction, 0)?; let modrm = read_modrm(words)?; @@ -5130,6 +5319,7 @@ pub(crate) fn read_evex_operands< generated::EVEXOperandCode::Operands_16_W0 => { deny_mask_reg(instruction)?; deny_z(instruction)?; + deny_broadcast(instruction)?; ensure_W(instruction, 0)?; let modrm = read_modrm(words)?; |
