aboutsummaryrefslogtreecommitdiff
path: root/src/shared/evex.in
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-06-26 01:32:08 -0700
committeriximeow <me@iximeow.net>2021-06-26 01:39:04 -0700
commitd951f4bbce1102ddab30e3a5f65ddac8ab221ac9 (patch)
tree0de4ae9d1c3368e8d355ed3de3974ac22fbc18d1 /src/shared/evex.in
parenta801fefb208c83a8d32f2be4d88b1f384e3017dc (diff)
add long-mode avx512 support, except for compressed displacements
Diffstat (limited to 'src/shared/evex.in')
-rw-r--r--src/shared/evex.in4874
1 files changed, 4874 insertions, 0 deletions
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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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(())
+}