diff options
| -rw-r--r-- | src/long_mode/vex.rs | 125 | ||||
| -rw-r--r-- | test/long_mode/mod.rs | 140 | 
2 files changed, 228 insertions, 37 deletions
diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs index 401c61f..d7e2257 100644 --- a/src/long_mode/vex.rs +++ b/src/long_mode/vex.rs @@ -74,6 +74,7 @@ enum VEXOperandCode {      G_xmm_E_xmm,      G_xmm_E_ymm,      G_ymm_E_xmm, +    G_ymm_M_xmm,      G_ymm_E_ymm,      G_V_ymm_E_xmm,      M_V_G_xmm, @@ -913,12 +914,18 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operand_count = 2;              Ok(())          } -        _op @ VEXOperandCode::G_ymm_E_xmm => { +        op @ VEXOperandCode::G_ymm_M_xmm | +        op @ VEXOperandCode::G_ymm_E_xmm => {              if instruction.vex_reg.num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(bytes, length)?; +            if modrm & 0xc0 == 0xc0 { +                if let VEXOperandCode::G_ymm_M_xmm = op { +                    return Err(DecodeError::InvalidOperand); +                } +            }              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; @@ -1001,9 +1008,14 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operand_count = 2;              Ok(())          } -        _op @ VEXOperandCode::G_V_E_ymm | -        _op @ VEXOperandCode::G_V_M_ymm => { +        op @ VEXOperandCode::G_V_E_ymm | +        op @ VEXOperandCode::G_V_M_ymm => {              let modrm = read_modrm(bytes, length)?; +            if let VEXOperandCode::G_V_M_ymm = op { +                if modrm & 0xc0 == 0xc0 { +                    return Err(DecodeError::InvalidOperand); +                } +            }              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              instruction.vex_reg.bank = RegisterBank::Y; @@ -1028,9 +1040,14 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operand_count = 4;              Ok(())          } -        _op @ VEXOperandCode::E_V_G_ymm | -        _op @ VEXOperandCode::M_V_G_ymm => { +        op @ VEXOperandCode::E_V_G_ymm | +        op @ VEXOperandCode::M_V_G_ymm => {              let modrm = read_modrm(bytes, length)?; +            if let VEXOperandCode::M_V_G_ymm = op { +                if modrm & 0xc0 == 0xc0 { +                    return Err(DecodeError::InvalidOperand); +                } +            }              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              instruction.vex_reg.bank = RegisterBank::Y; @@ -1043,6 +1060,9 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst          }          VEXOperandCode::G_V_M_xmm => {              let modrm = read_modrm(bytes, length)?; +            if modrm & 0xc0 == 0xc0 { +                return Err(DecodeError::InvalidOperand); +            }              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; @@ -1129,9 +1149,14 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operand_count = 4;              Ok(())          } -        _op @ VEXOperandCode::E_V_G_xmm | -        _op @ VEXOperandCode::M_V_G_xmm => { +        op @ VEXOperandCode::E_V_G_xmm | +        op @ VEXOperandCode::M_V_G_xmm => {              let modrm = read_modrm(bytes, length)?; +            if let VEXOperandCode::M_V_G_xmm = op { +                if modrm & 0xc0 == 0xc0 { +                    return Err(DecodeError::InvalidOperand); +                } +            }              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; @@ -2288,7 +2313,10 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          VEXOperandCode::G_E_xmm                      }),                      0x16 => (Opcode::VPERMPS, if L { -                        VEXOperandCode::G_V_E_xmm +                        if instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        } +                        VEXOperandCode::G_V_E_ymm                      } else {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOpcode); @@ -2303,7 +2331,7 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          return Err(DecodeError::InvalidOpcode);                      } else {                          (Opcode::VBROADCASTSS, if L { -                            VEXOperandCode::G_E_ymm +                            VEXOperandCode::G_ymm_E_xmm                          } else {                              VEXOperandCode::G_E_xmm                          }) @@ -2313,13 +2341,13 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          return Err(DecodeError::InvalidOpcode);                      } else {                          (Opcode::VBROADCASTSD, if L { -                            VEXOperandCode::G_E_ymm +                            VEXOperandCode::G_ymm_E_xmm                          } else {                              VEXOperandCode::G_E_xmm                          })                      }                      0x1A => (Opcode::VBROADCASTF128, if L { -                        VEXOperandCode::G_M_ymm +                        VEXOperandCode::G_ymm_M_xmm                      } else {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOpcode); @@ -2515,8 +2543,14 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          })                      },                      0x46 => (Opcode::VPSRAVD, if L { +                        if instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        }                          VEXOperandCode::G_V_E_ymm                      } else { +                        if instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        }                          VEXOperandCode::G_V_E_xmm                      }),                      0x47 => if instruction.prefixes.vex().w() { @@ -2543,7 +2577,10 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          VEXOperandCode::G_E_xmm                      }),                      0x5A => (Opcode::VBROADCASTI128, if L { -                        VEXOperandCode::G_E_ymm +                        if instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        } +                        VEXOperandCode::G_ymm_M_xmm                      } else {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOpcode); @@ -2560,31 +2597,31 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                      }),                      0x8C => {                          if instruction.prefixes.vex().w() { -                            (Opcode::VPMASKMOVD, if L { -                                VEXOperandCode::G_V_E_ymm +                            (Opcode::VPMASKMOVQ, if L { +                                VEXOperandCode::G_V_M_ymm                              } else { -                                VEXOperandCode::G_V_E_ymm +                                VEXOperandCode::G_V_M_xmm                              })                          } else { -                            (Opcode::VPMASKMOVQ, if L { -                                VEXOperandCode::G_V_E_ymm +                            (Opcode::VPMASKMOVD, if L { +                                VEXOperandCode::G_V_M_ymm                              } else { -                                VEXOperandCode::G_V_E_ymm +                                VEXOperandCode::G_V_M_xmm                              })                          }                      },                      0x8E => {                          if instruction.prefixes.vex().w() { -                            (Opcode::VPMASKMOVD, if L { -                                VEXOperandCode::E_V_G_ymm +                            (Opcode::VPMASKMOVQ, if L { +                                VEXOperandCode::M_V_G_ymm                              } else { -                                VEXOperandCode::E_V_G_xmm +                                VEXOperandCode::M_V_G_xmm                              })                          } else { -                            (Opcode::VPMASKMOVQ, if L { -                                VEXOperandCode::E_V_G_ymm +                            (Opcode::VPMASKMOVD, if L { +                                VEXOperandCode::M_V_G_ymm                              } else { -                                VEXOperandCode::E_V_G_xmm +                                VEXOperandCode::M_V_G_xmm                              })                          }                      }, @@ -2621,30 +2658,30 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                      0x92 => {                          if instruction.prefixes.vex().w() {                              (Opcode::VGATHERDPD, if L { -                                VEXOperandCode::G_E_ymm_imm8 +                                VEXOperandCode::G_Ey_V_ymm                              } else { -                                VEXOperandCode::G_E_xmm_imm8 +                                VEXOperandCode::G_Ex_V_xmm                              })                          } else {                              (Opcode::VGATHERDPS, if L { -                                VEXOperandCode::G_E_ymm_imm8 +                                VEXOperandCode::G_Ey_V_ymm                              } else { -                                VEXOperandCode::G_E_xmm_imm8 +                                VEXOperandCode::G_Ex_V_xmm                              })                          }                      },                      0x93 => {                          if instruction.prefixes.vex().w() {                              (Opcode::VGATHERQPD, if L { -                                VEXOperandCode::G_E_ymm_imm8 +                                VEXOperandCode::G_Ey_V_ymm                              } else { -                                VEXOperandCode::G_E_xmm_imm8 +                                VEXOperandCode::G_Ex_V_xmm                              })                          } else {                              (Opcode::VGATHERQPS, if L { -                                VEXOperandCode::G_E_ymm_imm8 +                                VEXOperandCode::G_Ey_V_ymm                              } else { -                                VEXOperandCode::G_E_xmm_imm8 +                                VEXOperandCode::G_Ex_V_xmm                              })                          }                      }, @@ -3097,21 +3134,33 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                  // possibly valid!                  match opc {                      0x00 => (Opcode::VPERMQ, if L { +                        if !instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        }                          VEXOperandCode::G_E_ymm_imm8                      } else {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOpcode);                      }),                      0x01 => (Opcode::VPERMPD, if L { +                        if !instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        }                          VEXOperandCode::G_E_ymm_imm8                      } else {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOpcode);                      }),                      0x02 => (Opcode::VPBLENDD, if L { -                        VEXOperandCode::G_V_E_ymm +                        if instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        } +                        VEXOperandCode::G_V_E_ymm_imm8                      } else { -                        VEXOperandCode::G_V_E_xmm +                        if instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        } +                        VEXOperandCode::G_V_E_xmm_imm8                      }),                      0x04 => (Opcode::VPERMILPS, if L {                          VEXOperandCode::G_E_ymm_imm8 @@ -3124,6 +3173,9 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          VEXOperandCode::G_E_xmm_imm8                      }),                      0x06 => (Opcode::VPERM2F128, if L { +                        if instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        }                          VEXOperandCode::G_V_E_ymm_imm8                      } else {                          instruction.opcode = Opcode::Invalid; @@ -3264,7 +3316,7 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          return Err(DecodeError::InvalidOpcode);                      }),                      0x39 => (Opcode::VEXTRACTI128, if L { -                        VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 +                        VEXOperandCode::E_xmm_G_ymm_imm8                      } else {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOpcode); @@ -3292,6 +3344,9 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          VEXOperandCode::G_V_E_xmm_imm8                      }),                      0x46 => (Opcode::VPERM2I128, if L { +                        if instruction.prefixes.vex().w() { +                            return Err(DecodeError::InvalidOpcode); +                        }                          VEXOperandCode::G_V_E_ymm_imm8                      } else {                          instruction.opcode = Opcode::Invalid; diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index c6b895c..3c2861d 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -1430,12 +1430,29 @@ fn test_vex() {      }      // prefix 03 +    test_invalid(&[0xc4, 0b000_00011, 0b1_1111_001, 0x00, 0b11_001_010, 0x77]); +    test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x00, 0b11_001_010, 0x77]); +    test_avx2(&[0xc4, 0b000_00011, 0b1_1111_101, 0x00, 0b11_001_010, 0x77], "vpermq ymm9, ymm10, 0x77"); +    test_invalid(&[0xc4, 0b000_00011, 0b1_1111_001, 0x01, 0b11_001_010, 0x77]); +    test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x01, 0b11_001_010, 0x77]); +    test_avx2(&[0xc4, 0b000_00011, 0b1_1111_101, 0x01, 0b11_001_010, 0x77], "vpermpd ymm9, ymm10, 0x77"); +    test_invalid(&[0xc4, 0b000_00011, 0b1_1111_001, 0x02, 0b11_001_010, 0x77]); +    test_invalid(&[0xc4, 0b000_00011, 0b1_1111_101, 0x02, 0b11_001_010, 0x77]); +    test_avx2(&[0xc4, 0b000_00011, 0b0_1111_001, 0x02, 0b11_001_010, 0x77], "vpblendd xmm9, xmm0, xmm10, 0x77"); +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00011, 0b0_1111_001, 0x02, 0b00_001_010, 0x77], "vpblendd xmm9, xmm0, [r10], 0x77"); +    test_avx2(&[0xc4, 0b000_00011, 0b0_1111_101, 0x02, 0b11_001_010, 0x77], "vpblendd ymm9, ymm0, ymm10, 0x77"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00011, 0b0_1111_101, 0x02, 0b00_001_010, 0x77], "vpblendd ymm9, ymm0, [r10], 0x77"); +      test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x04, 0b11_001_010, 0x77], "vpermilps xmm9, xmm10, 0x77");      test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x04, 0b11_001_010, 0x77], "vpermilps ymm9, ymm10, 0x77");      test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x05, 0b11_001_010, 0x77], "vpermilpd xmm9, xmm10, 0x77");      test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x05, 0b11_001_010, 0x77], "vpermilpd ymm9, ymm10, 0x77");      test_invalid(&[0xc4, 0b000_00011, 0b0_1111_001, 0x06, 0b11_001_010, 0x77]);      test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x06, 0b11_001_010, 0x77], "vperm2f128 ymm9, ymm0, ymm10, 0x77"); +    // TODO: ymmword ptr +    test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x06, 0b00_001_010, 0x77], "vperm2f128 ymm9, ymm0, [r10], 0x77");      test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x0c, 0b11_001_010, 0x77], "vblendps xmm9, xmm8, xmm10, 0x77");      test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0c, 0b11_001_010, 0x77], "vblendps ymm9, ymm8, ymm10, 0x77"); @@ -1487,6 +1504,13 @@ fn test_vex() {      test_invalid(&[0xc4, 0b000_00011, 0b0_1111_001, 0x19, 0b11_001_010, 0x77]);      test_invalid(&[0xc4, 0b000_00011, 0b1_1111_101, 0x19, 0b11_001_010, 0x77]); +    test_invalid(&[0xc4, 0b000_00011, 0b1_0111_001, 0x18, 0b11_001_010, 0x77]); +    test_avx2(&[0xc4, 0b000_00011, 0b0_0111_101, 0x38, 0b11_001_010, 0x77], "vinserti128 ymm9, ymm8, xmm10, 0x77"); +    test_invalid(&[0xc4, 0b000_00011, 0b1_0111_101, 0x18, 0b11_001_010, 0x77]); +    test_avx2(&[0xc4, 0b000_00011, 0b0_1111_101, 0x39, 0b11_001_010, 0x77], "vextracti128 xmm10, ymm9, 0x77"); +    test_invalid(&[0xc4, 0b000_00011, 0b0_1111_001, 0x19, 0b11_001_010, 0x77]); +    test_invalid(&[0xc4, 0b000_00011, 0b1_1111_101, 0x19, 0b11_001_010, 0x77]); +      test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x20, 0b11_001_010, 0x77], "vpinsrb xmm9, xmm8, r10d, 0x77");      // TODO: byte ptr      test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x20, 0b00_001_010, 0x77], "vpinsrb xmm9, xmm8, [r10], 0x77"); @@ -1508,6 +1532,13 @@ fn test_vex() {      test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x41, 0b11_001_010, 0x77]);      test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x42, 0b11_001_010, 0x77], "vmpsadbw xmm9, xmm8, xmm10, 0x77");      test_avx2(&[0xc4, 0b000_00011, 0b0_0111_101, 0x42, 0b11_001_010, 0x77], "vmpsadbw ymm9, ymm8, ymm10, 0x77"); + +    test_avx2(&[0xc4, 0b000_00011, 0b0_1111_101, 0x46, 0b11_001_010, 0x77], "vperm2i128 ymm9, ymm0, ymm10, 0x77"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00011, 0b0_1111_101, 0x46, 0b00_001_010, 0x77], "vperm2i128 ymm9, ymm0, [r10], 0x77"); +    test_invalid(&[0xc4, 0b000_00011, 0b0_1111_001, 0x46, 0b11_001_010, 0x77]); +    test_invalid(&[0xc4, 0b000_00011, 0b1_1111_101, 0x46, 0b11_001_010, 0x77]); +      test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x4c, 0b11_001_010, 0x77], "vpblendvb xmm9, xmm8, xmm10, xmm7");      test_avx2(&[0xc4, 0b000_00011, 0b0_0111_101, 0x4c, 0b11_001_010, 0x77], "vpblendvb ymm9, ymm8, ymm10, ymm7");      test_invalid(&[0xc4, 0b000_00011, 0b1_0111_001, 0x4c, 0b11_001_010, 0x77]); @@ -1570,6 +1601,12 @@ fn test_vex() {      test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x0f, 0b11_001_010], "vtestpd xmm9, xmm10");      test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x0f, 0b11_001_010], "vtestpd ymm9, ymm10"); +    test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x16, 0b11_001_010], "vpermps ymm9, ymm0, ymm10"); +    // TODO: ymmword ptr +    test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x16, 0b00_001_010], "vpermps ymm9, ymm0, [r10]"); +    test_invalid(&[0xc4, 0b000_00010, 0b0_1111_001, 0x16, 0b00_011_010]); +    test_invalid(&[0xc4, 0b000_00010, 0b1_1111_101, 0x16, 0b00_011_010]); +      test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x17, 0b11_001_010], "vptest xmm9, xmm10");      test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x17, 0b11_001_010], "vptest ymm9, ymm10");      test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x17, 0b11_001_010]); @@ -1589,12 +1626,18 @@ fn test_vex() {      test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x1a, 0b00_001_010], "vbroadcastf128 ymm9, [r10]");      test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x1a, 0b00_001_010]);      test_invalid(&[0xc4, 0b000_00010, 0b1_0111_001, 0x1a, 0b00_001_010]); -    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x18, 0b11_001_010], "vbroadcastss xmm9, xmm10"); +    // TODO: xmmword ptr +    test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x5a, 0b00_001_010], "vbroadcasti128 ymm9, [r10]"); +    test_invalid(&[0xc4, 0b000_00010, 0b0_1111_101, 0x5a, 0b11_001_010]); +    test_invalid(&[0xc4, 0b000_00010, 0b0_1111_001, 0x5a, 0b00_001_010]); +    test_invalid(&[0xc4, 0b000_00010, 0b1_1111_101, 0x5a, 0b00_001_010]); +    test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x18, 0b11_001_010], "vbroadcastss xmm9, xmm10"); +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x18, 0b11_001_010], "vbroadcastss ymm9, xmm10");      // TODO: dword ptr      test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x18, 0b00_001_010], "vbroadcastss ymm9, [r10]");      test_invalid(&[0xc4, 0b000_00010, 0b1_0111_001, 0x18, 0b11_001_010]);      test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x18, 0b11_001_010]); -    test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x19, 0b11_001_010], "vbroadcastsd ymm9, ymm10"); +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x19, 0b11_001_010], "vbroadcastsd ymm9, xmm10");      // TODO: qword ptr      test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x19, 0b00_001_010], "vbroadcastsd ymm9, [r10]");      test_invalid(&[0xc4, 0b000_00010, 0b1_1111_101, 0x19, 0b11_001_010]); @@ -1675,6 +1718,8 @@ fn test_vex() {      test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x35, 0b11_001_010]);      test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x35, 0b11_001_010]); +    test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x36, 0b11_001_010]); +    test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x36, 0b11_001_010], "vpermd ymm9, ymm8, ymm10");      test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x37, 0b11_001_010], "vpcmpgtq xmm9, xmm8, xmm10");      test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x37, 0b11_001_010], "vpcmpgtq ymm9, ymm8, ymm10");      test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x38, 0b11_001_010], "vpminsb xmm9, xmm8, xmm10"); @@ -1703,6 +1748,97 @@ fn test_vex() {  //    test_instr(&[0xc4, 0b000_00010, 0b1_0111_001, 0x42, 0b11_001_010], "vphminposuw xmm");  //    test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x41, 0b11_001_010]); +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x45, 0b00_001_010], "vpsrlvd xmm9, xmm0, [r10]"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x45, 0b00_001_010], "vpsrlvd ymm9, ymm0, [r10]"); +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x45, 0b11_001_010], "vpsrlvd xmm9, xmm0, xmm10"); +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x45, 0b11_001_010], "vpsrlvd ymm9, ymm0, ymm10"); +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x45, 0b00_001_010], "vpsrlvq xmm9, xmm0, [r10]"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x45, 0b00_001_010], "vpsrlvq ymm9, ymm0, [r10]"); +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x45, 0b11_001_010], "vpsrlvq xmm9, xmm0, xmm10"); +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x45, 0b11_001_010], "vpsrlvq ymm9, ymm0, ymm10"); + +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x46, 0b00_001_010], "vpsravd xmm9, xmm0, [r10]"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x46, 0b00_001_010], "vpsravd ymm9, ymm0, [r10]"); +    test_invalid(&[0xc4, 0b000_00010, 0b1_1111_001, 0x46, 0b00_001_010]); +    test_invalid(&[0xc4, 0b000_00010, 0b1_1111_101, 0x46, 0b00_001_010]); + +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x47, 0b00_001_010], "vpsllvd xmm9, xmm0, [r10]"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x47, 0b00_001_010], "vpsllvd ymm9, ymm0, [r10]"); +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x47, 0b11_001_010], "vpsllvd xmm9, xmm0, xmm10"); +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x47, 0b11_001_010], "vpsllvd ymm9, ymm0, ymm10"); +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x47, 0b00_001_010], "vpsllvq xmm9, xmm0, [r10]"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x47, 0b00_001_010], "vpsllvq ymm9, ymm0, [r10]"); +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x47, 0b11_001_010], "vpsllvq xmm9, xmm0, xmm10"); +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x47, 0b11_001_010], "vpsllvq ymm9, ymm0, ymm10"); + +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x8c, 0b00_001_010], "vpmaskmovd xmm9, xmm0, [r10]"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x8c, 0b00_001_010], "vpmaskmovd ymm9, ymm0, [r10]"); +    test_invalid(&[0xc4, 0b000_00010, 0b0_1111_001, 0x8c, 0b11_001_010]); +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x8c, 0b00_001_010], "vpmaskmovq xmm9, xmm0, [r10]"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x8c, 0b00_001_010], "vpmaskmovq ymm9, ymm0, [r10]"); +    test_invalid(&[0xc4, 0b000_00010, 0b0_1111_001, 0x8c, 0b11_001_010]); + +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x8e, 0b00_001_010], "vpmaskmovd [r10], xmm0, xmm9"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x8e, 0b00_001_010], "vpmaskmovd [r10], ymm0, ymm9"); +    test_invalid(&[0xc4, 0b000_00010, 0b0_1111_001, 0x8e, 0b11_001_010]); +    // TODO: xmmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x8e, 0b00_001_010], "vpmaskmovq [r10], xmm0, xmm9"); +    // TODO: ymmword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x8e, 0b00_001_010], "vpmaskmovq [r10], ymm0, ymm9"); +    test_invalid(&[0xc4, 0b000_00010, 0b0_1111_001, 0x8e, 0b11_001_010]); + +    // TODO: dword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x90, 0b00_000_100, 0xa1], "vpgatherdd xmm8, [r9 + xmm12 * 4], xmm0"); +    // TODO: qword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x90, 0b00_000_100, 0xa1], "vpgatherdd ymm8, [r9 + ymm12 * 4], ymm0"); +    // TODO: dword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x90, 0b00_000_100, 0xa1], "vpgatherdq xmm8, [r9 + xmm12 * 4], xmm0"); +    // TODO: qword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x90, 0b00_000_100, 0xa1], "vpgatherdq ymm8, [r9 + ymm12 * 4], ymm0"); + +    // TODO: dword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x91, 0b00_000_100, 0xa1], "vpgatherqd xmm8, [r9 + xmm12 * 4], xmm0"); +    // TODO: qword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x91, 0b00_000_100, 0xa1], "vpgatherqd ymm8, [r9 + ymm12 * 4], ymm0"); +    // TODO: dword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x91, 0b00_000_100, 0xa1], "vpgatherqq xmm8, [r9 + xmm12 * 4], xmm0"); +    // TODO: qword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x91, 0b00_000_100, 0xa1], "vpgatherqq ymm8, [r9 + ymm12 * 4], ymm0"); + +    // TODO: dword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x92, 0b00_000_100, 0xa1], "vgatherdps xmm8, [r9 + xmm12 * 4], xmm0"); +    // TODO: qword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x92, 0b00_000_100, 0xa1], "vgatherdps ymm8, [r9 + ymm12 * 4], ymm0"); +    // TODO: dword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x92, 0b00_000_100, 0xa1], "vgatherdpd xmm8, [r9 + xmm12 * 4], xmm0"); +    // TODO: qword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x92, 0b00_000_100, 0xa1], "vgatherdpd ymm8, [r9 + ymm12 * 4], ymm0"); + +    // TODO: dword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x93, 0b00_000_100, 0xa1], "vgatherqps xmm8, [r9 + xmm12 * 4], xmm0"); +    // TODO: qword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x93, 0b00_000_100, 0xa1], "vgatherqps ymm8, [r9 + ymm12 * 4], ymm0"); +    // TODO: dword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_001, 0x93, 0b00_000_100, 0xa1], "vgatherqpd xmm8, [r9 + xmm12 * 4], xmm0"); +    // TODO: qword ptr +    test_avx2(&[0xc4, 0b000_00010, 0b1_1111_101, 0x93, 0b00_000_100, 0xa1], "vgatherqpd ymm8, [r9 + ymm12 * 4], ymm0"); +      test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b0_1111_001, 0xdb, 0b11_001_010], "vaesimc xmm9, xmm10");      test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0xdb, 0b11_001_010]);      test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0xdb, 0b11_001_010]);  | 
