[llvm] [X86][MC] Support encoding of EGPR for APX (PR #71909)

Shengchen Kan via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 10 19:13:34 PST 2023


https://github.com/KanRobert updated https://github.com/llvm/llvm-project/pull/71909

>From a18b5333eefa053b9061864cfa15f58370641101 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Fri, 10 Nov 2023 17:12:20 +0800
Subject: [PATCH 1/5] [X86][MC] Support encoding of EGPR for APX

---
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp |  10 +
 .../lib/Target/X86/MCTargetDesc/X86BaseInfo.h |   8 +
 .../X86/MCTargetDesc/X86MCCodeEmitter.cpp     | 223 ++++++++----
 llvm/test/MC/X86/apx/evex-format-att.s        |  67 ++++
 llvm/test/MC/X86/apx/evex-format-intel.s      |  67 ++++
 llvm/test/MC/X86/apx/rex2-bit-att.s           | 240 ++++++++++++
 llvm/test/MC/X86/apx/rex2-bit-intel.s         | 237 ++++++++++++
 llvm/test/MC/X86/apx/rex2-format-att.s        | 343 ++++++++++++++++++
 llvm/test/MC/X86/apx/rex2-format-intel.s      | 343 ++++++++++++++++++
 9 files changed, 1470 insertions(+), 68 deletions(-)
 create mode 100644 llvm/test/MC/X86/apx/evex-format-att.s
 create mode 100644 llvm/test/MC/X86/apx/evex-format-intel.s
 create mode 100644 llvm/test/MC/X86/apx/rex2-bit-att.s
 create mode 100644 llvm/test/MC/X86/apx/rex2-bit-intel.s
 create mode 100644 llvm/test/MC/X86/apx/rex2-format-att.s
 create mode 100644 llvm/test/MC/X86/apx/rex2-format-intel.s

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index a367fa1ff74396b..73b03723c263323 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -106,6 +106,9 @@ class X86AsmParser : public MCTargetAsmParser {
 
   DispEncoding ForcedDispEncoding = DispEncoding_Default;
 
+  // Does this instruction use apx extended register?
+  bool UseApxExtendedReg = false;
+
 private:
   SMLoc consumeToken() {
     MCAsmParser &Parser = getParser();
@@ -1410,6 +1413,9 @@ bool X86AsmParser::MatchRegisterByName(MCRegister &RegNo, StringRef RegName,
     }
   }
 
+ if (X86II::isApxExtendedReg(RegNo))
+    UseApxExtendedReg = true;
+
   // If this is "db[0-15]", match it as an alias
   // for dr[0-15].
   if (RegNo == 0 && RegName.startswith("db")) {
@@ -3084,6 +3090,7 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
   // Reset the forced VEX encoding.
   ForcedVEXEncoding = VEXEncoding_Default;
   ForcedDispEncoding = DispEncoding_Default;
+  UseApxExtendedReg = false;
 
   // Parse pseudo prefixes.
   while (true) {
@@ -3954,6 +3961,9 @@ unsigned X86AsmParser::checkTargetMatchPredicate(MCInst &Inst) {
   unsigned Opc = Inst.getOpcode();
   const MCInstrDesc &MCID = MII.get(Opc);
 
+  if (UseApxExtendedReg && !X86II::canUseApxExtendedReg(MCID))
+    return Match_Unsupported;
+
   if (ForcedVEXEncoding == VEXEncoding_EVEX &&
       (MCID.TSFlags & X86II::EncodingMask) != X86II::EVEX)
     return Match_Unsupported;
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index 3ccc73398064b76..865987260b42a43 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -1208,6 +1208,11 @@ namespace X86II {
     return RegNo >= X86::ZMM0 && RegNo <= X86::ZMM31;
   }
 
+  /// \returns true if \p RegNo is an apx extended register.
+  inline bool isApxExtendedReg(unsigned RegNo) {
+    return RegNo >= X86::R16 && RegNo <= X86::R31WH;
+  }
+
   /// \returns true if the MachineOperand is a x86-64 extended (r8 or
   /// higher) register,  e.g. r8, xmm8, xmm13, etc.
   inline bool isX86_64ExtendedReg(unsigned RegNo) {
@@ -1218,6 +1223,9 @@ namespace X86II {
         (RegNo >= X86::ZMM8 && RegNo <= X86::ZMM31))
       return true;
 
+   if (isApxExtendedReg(RegNo))
+      return true;
+
     switch (RegNo) {
     default: break;
     case X86::R8:    case X86::R9:    case X86::R10:   case X86::R11:
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index b85404be3063dae..7e471f57c9c144f 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -36,7 +36,7 @@ using namespace llvm;
 
 namespace {
 
-enum PrefixKind { None, REX, XOP, VEX2, VEX3, EVEX };
+enum PrefixKind { None, REX, REX2, XOP, VEX2, VEX3, EVEX };
 
 static void emitByte(uint8_t C, SmallVectorImpl<char> &CB) { CB.push_back(C); }
 
@@ -46,6 +46,11 @@ class X86OpcodePrefixHelper {
   // | 40H | | WRXB |
   // +-----+ +------+
 
+  // REX2 (2 byte)
+  // +-----+ +-------------------+
+  // | D5H | | M | R'X'B' | WRXB |
+  // +-----+ +-------------------+
+
   // XOP (3-byte)
   // +-----+ +--------------+ +-------------------+
   // | 8Fh | | RXB | m-mmmm | | W | vvvv | L | pp |
@@ -106,9 +111,9 @@ class X86OpcodePrefixHelper {
   //  0b11: F2
 
   // EVEX (4 bytes)
-  // +-----+ +--------------+ +-------------------+ +------------------------+
-  // | 62h | | RXBR' | 0mmm | | W | vvvv | 1 | pp | | z | L'L | b | v' | aaa |
-  // +-----+ +--------------+ +-------------------+ +------------------------+
+  // +-----+ +---------------+ +--------------------+ +------------------------+
+  // | 62h | | RXBR' | B'mmm | | W | vvvv | X' | pp | | z | L'L | b | v' | aaa |
+  // +-----+ +---------------+ +--------------------+ +------------------------+
 
   // EVEX_L2/VEX_L (Vector Length):
   // L2 L
@@ -121,11 +126,14 @@ class X86OpcodePrefixHelper {
   unsigned R : 1;
   unsigned X : 1;
   unsigned B : 1;
+  unsigned M : 1;
+  unsigned R2 : 1;
+  unsigned X2 : 1;
+  unsigned B2 : 1;
   unsigned VEX_4V : 4;
   unsigned VEX_L : 1;
   unsigned VEX_PP : 2;
   unsigned VEX_5M : 5;
-  unsigned EVEX_R2 : 1;
   unsigned EVEX_z : 1;
   unsigned EVEX_L2 : 1;
   unsigned EVEX_b : 1;
@@ -139,7 +147,20 @@ class X86OpcodePrefixHelper {
   }
 
   void setR(unsigned Encoding) { R = Encoding >> 3 & 1; }
-  void setR2(unsigned Encoding) { EVEX_R2 = Encoding >> 4 & 1; }
+  void setR2(unsigned Encoding) {
+    R2 = Encoding >> 4 & 1;
+    assert((!R2 || (Kind <= REX2 || Kind == EVEX)) && "invalid setting");
+  }
+  void setX(unsigned Encoding) { X = Encoding >> 3 & 1; }
+  void setX2(unsigned Encoding) {
+    assert((Kind <= REX2 || Kind == EVEX) && "invalid setting");
+    X2 = Encoding >> 4 & 1;
+  }
+  void setB(unsigned Encoding) { B = Encoding >> 3 & 1; }
+  void setB2(unsigned Encoding) {
+    assert((Kind <= REX2 || Kind == EVEX) && "invalid setting");
+    B2 = Encoding >> 4 & 1;
+  }
   void set4V(unsigned Encoding) { VEX_4V = Encoding & 0xf; }
   void setV2(unsigned Encoding) { EVEX_V2 = Encoding >> 4 & 1; }
 
@@ -149,7 +170,12 @@ class X86OpcodePrefixHelper {
     setR(getRegEncoding(MI, OpNum));
   }
   void setX(const MCInst &MI, unsigned OpNum, unsigned Shift = 3) {
-    X = getRegEncoding(MI, OpNum) >> Shift & 1;
+    unsigned Reg = MI.getOperand(OpNum).getReg();
+    // X is used to extend vector register only when shift is not 3
+    if (Shift != 3 && X86II::isApxExtendedReg(Reg))
+      return;
+    unsigned Encoding = MRI.getEncodingValue(Reg);
+    X = Encoding >> Shift & 1;
   }
   void setB(const MCInst &MI, unsigned OpNum) {
     B = getRegEncoding(MI, OpNum) >> 3 & 1;
@@ -168,11 +194,34 @@ class X86OpcodePrefixHelper {
     setR(Encoding);
     setR2(Encoding);
   }
+  void setM(bool V) { M = V; }
+  void setXX2(const MCInst &MI, unsigned OpNum) {
+    unsigned Reg = MI.getOperand(OpNum).getReg();
+    unsigned Encoding = MRI.getEncodingValue(Reg);
+    setX(Encoding);
+    // Index can be a vector register while X2 is used to extend GPR only
+    if (Kind <= REX2 || X86II::isApxExtendedReg(Reg))
+      setX2(Encoding);
+  }
+  void setBB2(const MCInst &MI, unsigned OpNum) {
+    unsigned Reg = MI.getOperand(OpNum).getReg();
+    unsigned Encoding = MRI.getEncodingValue(Reg);
+    setB(Encoding);
+    // Base can be a vector register while B2 is used to extend GPR only
+    if (Kind <= REX2 || X86II::isApxExtendedReg(Reg))
+      setB2(Encoding);
+  }
   void setZ(bool V) { EVEX_z = V; }
   void setL2(bool V) { EVEX_L2 = V; }
   void setEVEX_b(bool V) { EVEX_b = V; }
-  void setV2(const MCInst &MI, unsigned OpNum) {
-    setV2(getRegEncoding(MI, OpNum));
+  void setV2(const MCInst &MI, unsigned OpNum, bool HasVEX_4V) {
+    // Only needed with VSIB which don't use VVVV.
+    if (HasVEX_4V)
+      return;
+    unsigned Reg = MI.getOperand(OpNum).getReg();
+    if (X86II::isApxExtendedReg(Reg))
+      return;
+    setV2(MRI.getEncodingValue(Reg));
   }
   void set4VV2(const MCInst &MI, unsigned OpNum) {
     unsigned Encoding = getRegEncoding(MI, OpNum);
@@ -184,18 +233,23 @@ class X86OpcodePrefixHelper {
   }
 
   X86OpcodePrefixHelper(const MCRegisterInfo &MRI)
-      : W(0), R(0), X(0), B(0), VEX_4V(0), VEX_L(0), VEX_PP(0), VEX_5M(0),
-        EVEX_R2(0), EVEX_z(0), EVEX_L2(0), EVEX_b(0), EVEX_V2(0), EVEX_aaa(0),
-        MRI(MRI) {}
+      : W(0), R(0), X(0), B(0), M(0), R2(0), X2(0), B2(0), VEX_4V(0), VEX_L(0),
+        VEX_PP(0), VEX_5M(0), EVEX_z(0), EVEX_L2(0), EVEX_b(0), EVEX_V2(0),
+        EVEX_aaa(0), MRI(MRI) {}
 
   void setLowerBound(PrefixKind K) { Kind = K; }
 
   PrefixKind determineOptimalKind() {
     switch (Kind) {
     case None:
-      Kind = (W | R | X | B) ? REX : None;
+      // Not M bit here by intention b/c
+      // 1. No guarantee that REX2 is supported by arch w/o explict EGPR
+      // 2. REX2 is longer than 0FH
+      Kind = (R2 | X2 | B2) ? REX2 : (W | R | X | B) ? REX : None;
       break;
     case REX:
+      Kind = (R2 | X2 | B2) ? REX2 : REX;
+    case REX2:
     case XOP:
     case VEX3:
     case EVEX:
@@ -217,6 +271,12 @@ class X86OpcodePrefixHelper {
     case REX:
       emitByte(0x40 | W << 3 | R << 2 | X << 1 | B, CB);
       return;
+    case REX2:
+      emitByte(0xD5, CB);
+      emitByte(M << 7 | R2 << 6 | X2 << 5 | B2 << 4 | W << 3 | R << 2 | X << 1 |
+                   B,
+               CB);
+      return;
     case VEX2:
       emitByte(0xC5, CB);
       emitByte(((~R) & 1) << 7 | LastPayload, CB);
@@ -230,8 +290,9 @@ class X86OpcodePrefixHelper {
     case EVEX:
       assert(VEX_5M && !(VEX_5M & 0x8) && "invalid mmm fields for EVEX!");
       emitByte(0x62, CB);
-      emitByte(FirstPayload | ((~EVEX_R2) & 0x1) << 4 | VEX_5M, CB);
-      emitByte(W << 7 | ((~VEX_4V) & 0xf) << 3 | 1 << 2 | VEX_PP, CB);
+      emitByte(FirstPayload | ((~R2) & 0x1) << 4 | B2 << 3 | VEX_5M, CB);
+      emitByte(W << 7 | ((~VEX_4V) & 0xf) << 3 | ((~X2) & 0x1) << 2 | VEX_PP,
+               CB);
       emitByte(EVEX_z << 7 | EVEX_L2 << 6 | VEX_L << 5 | EVEX_b << 4 |
                    ((~EVEX_V2) & 0x1) << 3 | EVEX_aaa,
                CB);
@@ -548,7 +609,7 @@ void X86MCCodeEmitter::emitMemModRMByte(
         // movq loads is a subset of reloc_riprel_4byte_relax_rex. It is a
         // special case because COFF and Mach-O don't support ELF's more
         // flexible R_X86_64_REX_GOTPCRELX relaxation.
-        assert(Kind == REX);
+        assert(Kind == REX || Kind == REX2);
         return X86::reloc_riprel_4byte_movq_load;
       case X86::ADC32rm:
       case X86::ADD32rm:
@@ -572,8 +633,11 @@ void X86MCCodeEmitter::emitMemModRMByte(
       case X86::SBB64rm:
       case X86::SUB64rm:
       case X86::XOR64rm:
-        return Kind == REX ? X86::reloc_riprel_4byte_relax_rex
-                           : X86::reloc_riprel_4byte_relax;
+        // We haven't support relocation for REX2 prefix, so temporarily use REX relocation
+        // TODO: Support new relocation for REX2.
+        return (Kind == REX || Kind == REX2) ? X86::reloc_riprel_4byte_relax_rex
+                                             : X86::reloc_riprel_4byte_relax;
+
       }
     }();
 
@@ -683,10 +747,11 @@ void X86MCCodeEmitter::emitMemModRMByte(
       return;
     }
 
-    // If the base is not EBP/ESP/R12/R13 and there is no displacement, use
-    // simple indirect register encoding, this handles addresses like [EAX].
-    // The encoding for [EBP] or[R13] with no displacement means [disp32] so we
-    // handle it by emitting a displacement of 0 later.
+    // If the base is not EBP/ESP/R12/R13/R20/R21/R28/R29 and there is no
+    // displacement, use simple indirect register encoding, this handles
+    // addresses like [EAX]. The encoding for [EBP], [R13], [R20], [R21], [R28]
+    // or [R29] with no displacement means [disp32] so we handle it by emitting
+    // a displacement of 0 later.
     if (BaseRegNo != N86::EBP) {
       if (Disp.isImm() && Disp.getImm() == 0 && AllowNoDisp) {
         emitByte(modRMByte(0, RegOpcodeField, BaseRegNo), CB);
@@ -708,8 +773,8 @@ void X86MCCodeEmitter::emitMemModRMByte(
 
     // Otherwise, if the displacement fits in a byte, encode as [REG+disp8].
     // Including a compressed disp8 for EVEX instructions that support it.
-    // This also handles the 0 displacement for [EBP] or [R13]. We can't use
-    // disp8 if the {disp32} pseudo prefix is present.
+    // This also handles the 0 displacement for [EBP], [R13], [R21] or [R29]. We
+    // can't use disp8 if the {disp32} pseudo prefix is present.
     if (Disp.isImm() && AllowDisp8) {
       int ImmOffset = 0;
       if (isDispOrCDisp8(TSFlags, Disp.getImm(), ImmOffset)) {
@@ -721,8 +786,8 @@ void X86MCCodeEmitter::emitMemModRMByte(
     }
 
     // Otherwise, emit the most general non-SIB encoding: [REG+disp32].
-    // Displacement may be 0 for [EBP] or [R13] case if {disp32} pseudo prefix
-    // prevented using disp8 above.
+    // Displacement may be 0 for [EBP], [R13], [R21], [R29] case if {disp32}
+    // pseudo prefix prevented using disp8 above.
     emitByte(modRMByte(2, RegOpcodeField, BaseRegNo), CB);
     unsigned Opcode = MI.getOpcode();
     unsigned FixupKind = Opcode == X86::MOV32rm ? X86::reloc_signed_4byte_relax
@@ -746,10 +811,10 @@ void X86MCCodeEmitter::emitMemModRMByte(
     emitByte(modRMByte(0, RegOpcodeField, 4), CB);
     ForceDisp32 = true;
   } else if (Disp.isImm() && Disp.getImm() == 0 && AllowNoDisp &&
-             // Base reg can't be EBP/RBP/R13 as that would end up with '5' as
-             // the base field, but that is the magic [*] nomenclature that
-             // indicates no base when mod=0. For these cases we'll emit a 0
-             // displacement instead.
+             // Base reg can't be EBP/RBP/R13/R21/R29 as that would end up with
+             // '5' as the base field, but that is the magic [*] nomenclature
+             // that indicates no base when mod=0. For these cases we'll emit a
+             // 0 displacement instead.
              BaseRegNo != N86::EBP) {
     // Emit no displacement ModR/M byte
     emitByte(modRMByte(0, RegOpcodeField, 4), CB);
@@ -869,6 +934,20 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
 
   assert(!(TSFlags & X86II::LOCK) && "Can't have LOCK VEX.");
 
+#ifndef NDEBUG
+  unsigned NumOps = MI.getNumOperands();
+  for (unsigned I = NumOps ? X86II::getOperandBias(Desc) : 0; I != NumOps;
+       ++I) {
+    const MCOperand &MO = MI.getOperand(I);
+    if (!MO.isReg())
+      continue;
+    unsigned Reg = MO.getReg();
+    if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH)
+      report_fatal_error(
+          "Cannot encode high byte register in VEX/EVEX-prefixed instruction");
+  }
+#endif
+
   X86OpcodePrefixHelper Prefix(*Ctx.getRegisterInfo());
   switch (TSFlags & X86II::EncodingMask) {
   default:
@@ -952,9 +1031,9 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     llvm_unreachable("Unexpected form in emitVEXOpcodePrefix!");
   case X86II::MRMDestMem4VOp3CC: {
     //  src1(ModR/M), MemAddr, src2(VEX_4V)
-    Prefix.setR(MI, CurOp++);
-    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
-    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setRR2(MI, CurOp++);
+    Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
     CurOp += X86::AddrNumOperands;
     Prefix.set4V(MI, CurOp++);
     break;
@@ -969,10 +1048,9 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     //  MemAddr, src1(VEX_4V), src2(ModR/M)
     //  MemAddr, src1(ModR/M), imm8
     //
-    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
-    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
-    if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV.
-      Prefix.setV2(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setV2(MI, MemOperand + X86::AddrIndexReg, HasVEX_4V);
 
     CurOp += X86::AddrNumOperands;
 
@@ -1003,10 +1081,9 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     if (HasVEX_4V)
       Prefix.set4VV2(MI, CurOp++);
 
-    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
-    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
-    if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV.
-      Prefix.setV2(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setV2(MI, MemOperand + X86::AddrIndexReg, HasVEX_4V);
 
     break;
   }
@@ -1014,8 +1091,8 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     // Instruction format for 4VOp3:
     //   src1(ModR/M), MemAddr, src3(VEX_4V)
     Prefix.setR(MI, CurOp++);
-    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
-    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
     Prefix.set4V(MI, CurOp + X86::AddrNumOperands);
     break;
   }
@@ -1023,8 +1100,8 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     //  dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
     Prefix.setR(MI, CurOp++);
     Prefix.set4V(MI, CurOp++);
-    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
-    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
     break;
   }
   case X86II::MRM0m:
@@ -1044,10 +1121,9 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     if (HasEVEX_K)
       Prefix.setAAA(MI, CurOp++);
 
-    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
-    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
-    if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV.
-      Prefix.setV2(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setV2(MI, MemOperand + X86::AddrIndexReg, HasVEX_4V);
 
     break;
   }
@@ -1067,7 +1143,7 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     if (HasVEX_4V)
       Prefix.set4VV2(MI, CurOp++);
 
-    Prefix.setB(MI, CurOp);
+    Prefix.setBB2(MI, CurOp);
     Prefix.setX(MI, CurOp, 4);
     ++CurOp;
 
@@ -1086,6 +1162,12 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
   case X86II::MRMSrcReg4VOp3: {
     // Instruction format for 4VOp3:
     //   src1(ModR/M), src2(ModR/M), src3(VEX_4V)
+    if ((TSFlags & X86II::EncodingMask) == X86II::EVEX) {
+      Prefix.setRR2(MI, CurOp++);
+      Prefix.setBB2(MI, CurOp++);
+      Prefix.set4V(MI, CurOp++);
+      break;
+    }
     Prefix.setR(MI, CurOp++);
     Prefix.setB(MI, CurOp++);
     Prefix.set4V(MI, CurOp++);
@@ -1093,12 +1175,12 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
   }
   case X86II::MRMSrcRegOp4: {
     //  dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
-    Prefix.setR(MI, CurOp++);
+    Prefix.setRR2(MI, CurOp++);
     Prefix.set4V(MI, CurOp++);
     // Skip second register source (encoded in Imm[7:4])
     ++CurOp;
 
-    Prefix.setB(MI, CurOp);
+    Prefix.setBB2(MI, CurOp);
     Prefix.setX(MI, CurOp, 4);
     ++CurOp;
     break;
@@ -1108,7 +1190,7 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     //  dst(ModR/M), src(ModR/M)
     //  dst(ModR/M), src(ModR/M), imm8
     //  dst(ModR/M), src1(VEX_4V), src2(ModR/M)
-    Prefix.setB(MI, CurOp);
+    Prefix.setBB2(MI, CurOp);
     Prefix.setX(MI, CurOp, 4);
     ++CurOp;
 
@@ -1146,7 +1228,7 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     if (HasEVEX_K)
       Prefix.setAAA(MI, CurOp++);
 
-    Prefix.setB(MI, CurOp);
+    Prefix.setBB2(MI, CurOp);
     Prefix.setX(MI, CurOp, 4);
     ++CurOp;
     break;
@@ -1218,29 +1300,29 @@ PrefixKind X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
   case X86II::RawFrmDstSrc:
     break;
   case X86II::AddRegFrm:
-    Prefix.setB(MI, CurOp++);
+    Prefix.setBB2(MI, CurOp++);
     break;
   case X86II::MRMSrcReg:
   case X86II::MRMSrcRegCC:
-    Prefix.setR(MI, CurOp++);
-    Prefix.setB(MI, CurOp++);
+    Prefix.setRR2(MI, CurOp++);
+    Prefix.setBB2(MI, CurOp++);
     break;
   case X86II::MRMSrcMem:
   case X86II::MRMSrcMemCC:
-    Prefix.setR(MI, CurOp++);
-    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
-    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setRR2(MI, CurOp++);
+    Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
     CurOp += X86::AddrNumOperands;
     break;
   case X86II::MRMDestReg:
-    Prefix.setB(MI, CurOp++);
-    Prefix.setR(MI, CurOp++);
+    Prefix.setBB2(MI, CurOp++);
+    Prefix.setRR2(MI, CurOp++);
     break;
   case X86II::MRMDestMem:
-    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
-    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
     CurOp += X86::AddrNumOperands;
-    Prefix.setR(MI, CurOp++);
+    Prefix.setRR2(MI, CurOp++);
     break;
   case X86II::MRMXmCC:
   case X86II::MRMXm:
@@ -1252,8 +1334,8 @@ PrefixKind X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
   case X86II::MRM5m:
   case X86II::MRM6m:
   case X86II::MRM7m:
-    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
-    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
     break;
   case X86II::MRMXrCC:
   case X86II::MRMXr:
@@ -1265,9 +1347,10 @@ PrefixKind X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
   case X86II::MRM5r:
   case X86II::MRM6r:
   case X86II::MRM7r:
-    Prefix.setB(MI, CurOp++);
+    Prefix.setBB2(MI, CurOp++);
     break;
   }
+  Prefix.setM((TSFlags & X86II::OpMapMask) == X86II::TB);
   PrefixKind Kind = Prefix.determineOptimalKind();
   if (Kind && UsesHighByteReg)
     report_fatal_error(
@@ -1329,6 +1412,10 @@ PrefixKind X86MCCodeEmitter::emitOpcodePrefix(int MemOperand, const MCInst &MI,
   // 0x0F escape code must be emitted just before the opcode.
   switch (TSFlags & X86II::OpMapMask) {
   case X86II::TB:        // Two-byte opcode map
+    // Encoded by M bit in REX2
+    if (Kind == REX2)
+      break;
+    LLVM_FALLTHROUGH;
   case X86II::T8:        // 0F 38
   case X86II::TA:        // 0F 3A
   case X86II::ThreeDNow: // 0F 0F, second 0F emitted by caller.
diff --git a/llvm/test/MC/X86/apx/evex-format-att.s b/llvm/test/MC/X86/apx/evex-format-att.s
new file mode 100644
index 000000000000000..aedd09e7e698df2
--- /dev/null
+++ b/llvm/test/MC/X86/apx/evex-format-att.s
@@ -0,0 +1,67 @@
+## NOTE: This file needs to be updated after promoted instruction is supported
+# RUN: llvm-mc -triple x86_64 -show-encoding %s | FileCheck %s
+
+## MRMDestMem
+
+# CHECK: vextractf32x4	$1, %zmm0, (%r16,%r17)
+# CHECK: encoding: [0x62,0xfb,0x79,0x48,0x19,0x04,0x08,0x01]
+         vextractf32x4	$1, %zmm0, (%r16,%r17)
+
+## MRMSrcMem
+
+# CHECK: vbroadcasti32x4	(%r16,%r17), %zmm0
+# CHECK: encoding: [0x62,0xfa,0x79,0x48,0x5a,0x04,0x08]
+         vbroadcasti32x4	(%r16,%r17), %zmm0
+
+## MRM0m
+
+# CHECK: vprorq	$0, (%r16,%r17), %zmm0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x72,0x04,0x08,0x00]
+         vprorq	$0, (%r16,%r17), %zmm0
+
+## MRM1m
+
+# CHECK: vprolq	$0, (%r16,%r17), %zmm0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x72,0x0c,0x08,0x00]
+         vprolq	$0, (%r16,%r17), %zmm0
+## MRM2m
+
+# CHECK: vpsrlq	$0, (%r16,%r17), %zmm0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x73,0x14,0x08,0x00]
+         vpsrlq	$0, (%r16,%r17), %zmm0
+
+## MRM3m
+
+# CHECK: vpsrldq	$0, (%r16,%r17), %zmm0
+# CHECK: encoding: [0x62,0xf9,0x79,0x48,0x73,0x1c,0x08,0x00]
+         vpsrldq	$0, (%r16,%r17), %zmm0
+
+## MRM4m
+
+# CHECK: vpsraq	$0, (%r16,%r17), %zmm0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x72,0x24,0x08,0x00]
+         vpsraq	$0, (%r16,%r17), %zmm0
+
+## MRM5m
+
+# CHECK: vscatterpf0dps	(%r16,%zmm0) {%k1}
+# CHECK: encoding: [0x62,0xfa,0x7d,0x49,0xc6,0x2c,0x00]
+         vscatterpf0dps	(%r16,%zmm0) {%k1}
+
+## MRM6m
+
+# CHECK: vpsllq	$0, (%r16,%r17), %zmm0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x73,0x34,0x08,0x00]
+         vpsllq	$0, (%r16,%r17), %zmm0
+
+## MRM7m
+
+# CHECK: vpslldq	$0, (%r16,%r17), %zmm0
+# CHECK: encoding: [0x62,0xf9,0x79,0x48,0x73,0x3c,0x08,0x00]
+         vpslldq	$0, (%r16,%r17), %zmm0
+
+## MRMDestReg
+
+# CHECK: vextractps	$1, %xmm16, %r16d
+# CHECK: encoding: [0x62,0xeb,0x7d,0x08,0x17,0xc0,0x01]
+         vextractps	$1, %xmm16, %r16d
diff --git a/llvm/test/MC/X86/apx/evex-format-intel.s b/llvm/test/MC/X86/apx/evex-format-intel.s
new file mode 100644
index 000000000000000..aa11a879f4b4c60
--- /dev/null
+++ b/llvm/test/MC/X86/apx/evex-format-intel.s
@@ -0,0 +1,67 @@
+## NOTE: This file needs to be updated after promoted instruction is supported
+# RUN: llvm-mc -triple x86_64 -show-encoding -x86-asm-syntax=intel -output-asm-variant=1 %s | FileCheck %s
+
+## MRMDestMem
+
+# CHECK: vextractf32x4	xmmword ptr [r16 + r17], zmm0, 1
+# CHECK: encoding: [0x62,0xfb,0x79,0x48,0x19,0x04,0x08,0x01]
+         vextractf32x4	xmmword ptr [r16 + r17], zmm0, 1
+
+## MRMSrcMem
+
+# CHECK: vbroadcasti32x4	zmm0, xmmword ptr [r16 + r17]
+# CHECK: encoding: [0x62,0xfa,0x79,0x48,0x5a,0x04,0x08]
+         vbroadcasti32x4	zmm0, xmmword ptr [r16 + r17]
+
+## MRM0m
+
+# CHECK: vprorq	zmm0, zmmword ptr [r16 + r17], 0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x72,0x04,0x08,0x00]
+         vprorq	zmm0, zmmword ptr [r16 + r17], 0
+
+## MRM1m
+
+# CHECK: vprolq	zmm0, zmmword ptr [r16 + r17], 0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x72,0x0c,0x08,0x00]
+         vprolq	zmm0, zmmword ptr [r16 + r17], 0
+
+## MRM2m
+
+# CHECK: vpsrlq	zmm0, zmmword ptr [r16 + r17], 0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x73,0x14,0x08,0x00]
+         vpsrlq	zmm0, zmmword ptr [r16 + r17], 0
+
+## MRM3m
+
+# CHECK: vpsrldq	zmm0, zmmword ptr [r16 + r17], 0
+# CHECK: encoding: [0x62,0xf9,0x79,0x48,0x73,0x1c,0x08,0x00]
+         vpsrldq	zmm0, zmmword ptr [r16 + r17], 0
+## MRM4m
+
+# CHECK: vpsraq	zmm0, zmmword ptr [r16 + r17], 0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x72,0x24,0x08,0x00]
+         vpsraq	zmm0, zmmword ptr [r16 + r17], 0
+
+## MRM5m
+## AsmParser is buggy for this KNC instruction
+# C;HECK: vscatterpf0dps	{k1}, zmmword ptr [r16 + zmm0]
+# C;HECK: encoding: [0x62,0xfa,0x7d,0x49,0xc6,0x2c,0x00]
+#         vscatterpf0dps	{k1}, zmmword ptr [r16 + zmm0]
+
+## MRM6m
+
+# CHECK: vpsllq	zmm0, zmmword ptr [r16 + r17], 0
+# CHECK: encoding: [0x62,0xf9,0xf9,0x48,0x73,0x34,0x08,0x00]
+         vpsllq	zmm0, zmmword ptr [r16 + r17], 0
+
+## MRM7m
+
+# CHECK: vpslldq	zmm0, zmmword ptr [r16 + r17], 0
+# CHECK: encoding: [0x62,0xf9,0x79,0x48,0x73,0x3c,0x08,0x00]
+         vpslldq	zmm0, zmmword ptr [r16 + r17], 0
+
+## MRMDestReg
+
+# CHECK: vextractps	r16d, xmm16, 1
+# CHECK: encoding: [0x62,0xeb,0x7d,0x08,0x17,0xc0,0x01]
+         vextractps	r16d, xmm16, 1
diff --git a/llvm/test/MC/X86/apx/rex2-bit-att.s b/llvm/test/MC/X86/apx/rex2-bit-att.s
new file mode 100644
index 000000000000000..8ae99699eb50ee3
--- /dev/null
+++ b/llvm/test/MC/X86/apx/rex2-bit-att.s
@@ -0,0 +1,240 @@
+# RUN: llvm-mc -triple x86_64 -show-encoding %s | FileCheck %s
+# RUN: not llvm-mc -triple i386 -show-encoding %s 2>&1 | FileCheck %s --check-prefix=ERROR
+
+# ERROR-COUNT-56: error:
+# ERROR-NOT: error:
+## R bit
+
+# CHECK: leal	(%rax), %r16d
+# CHECK: encoding: [0xd5,0x40,0x8d,0x00]
+         leal	(%rax), %r16d
+
+# CHECK: leal	(%rax), %r17d
+# CHECK: encoding: [0xd5,0x40,0x8d,0x08]
+         leal	(%rax), %r17d
+
+# CHECK: leal	(%rax), %r18d
+# CHECK: encoding: [0xd5,0x40,0x8d,0x10]
+         leal	(%rax), %r18d
+
+# CHECK: leal	(%rax), %r19d
+# CHECK: encoding: [0xd5,0x40,0x8d,0x18]
+         leal	(%rax), %r19d
+
+# CHECK: leal	(%rax), %r20d
+# CHECK: encoding: [0xd5,0x40,0x8d,0x20]
+         leal	(%rax), %r20d
+
+# CHECK: leal	(%rax), %r21d
+# CHECK: encoding: [0xd5,0x40,0x8d,0x28]
+         leal	(%rax), %r21d
+
+# CHECK: leal	(%rax), %r22d
+# CHECK: encoding: [0xd5,0x40,0x8d,0x30]
+         leal	(%rax), %r22d
+
+# CHECK: leal	(%rax), %r23d
+# CHECK: encoding: [0xd5,0x40,0x8d,0x38]
+         leal	(%rax), %r23d
+
+# CHECK: leal	(%rax), %r24d
+# CHECK: encoding: [0xd5,0x44,0x8d,0x00]
+         leal	(%rax), %r24d
+
+# CHECK: leal	(%rax), %r25d
+# CHECK: encoding: [0xd5,0x44,0x8d,0x08]
+         leal	(%rax), %r25d
+
+# CHECK: leal	(%rax), %r26d
+# CHECK: encoding: [0xd5,0x44,0x8d,0x10]
+         leal	(%rax), %r26d
+
+# CHECK: leal	(%rax), %r27d
+# CHECK: encoding: [0xd5,0x44,0x8d,0x18]
+         leal	(%rax), %r27d
+
+# CHECK: leal	(%rax), %r28d
+# CHECK: encoding: [0xd5,0x44,0x8d,0x20]
+         leal	(%rax), %r28d
+
+# CHECK: leal	(%rax), %r29d
+# CHECK: encoding: [0xd5,0x44,0x8d,0x28]
+         leal	(%rax), %r29d
+
+# CHECK: leal	(%rax), %r30d
+# CHECK: encoding: [0xd5,0x44,0x8d,0x30]
+         leal	(%rax), %r30d
+
+# CHECK: leal	(%rax), %r31d
+# CHECK: encoding: [0xd5,0x44,0x8d,0x38]
+         leal	(%rax), %r31d
+
+## X bit
+
+# CHECK: leal	(,%r16), %eax
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x05,0x00,0x00,0x00,0x00]
+         leal	(,%r16), %eax
+
+# CHECK: leal	(,%r17), %eax
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x0d,0x00,0x00,0x00,0x00]
+         leal	(,%r17), %eax
+
+# CHECK: leal	(,%r18), %eax
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x15,0x00,0x00,0x00,0x00]
+         leal	(,%r18), %eax
+
+# CHECK: leal	(,%r19), %eax
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x1d,0x00,0x00,0x00,0x00]
+         leal	(,%r19), %eax
+
+# CHECK: leal	(,%r20), %eax
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x25,0x00,0x00,0x00,0x00]
+         leal	(,%r20), %eax
+
+# CHECK: leal	(,%r21), %eax
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x2d,0x00,0x00,0x00,0x00]
+         leal	(,%r21), %eax
+
+# CHECK: leal	(,%r22), %eax
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x35,0x00,0x00,0x00,0x00]
+         leal	(,%r22), %eax
+
+# CHECK: leal	(,%r23), %eax
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x3d,0x00,0x00,0x00,0x00]
+         leal	(,%r23), %eax
+
+# CHECK: leal	(,%r24), %eax
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x05,0x00,0x00,0x00,0x00]
+         leal	(,%r24), %eax
+
+# CHECK: leal	(,%r25), %eax
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x0d,0x00,0x00,0x00,0x00]
+         leal	(,%r25), %eax
+
+# CHECK: leal	(,%r26), %eax
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x15,0x00,0x00,0x00,0x00]
+         leal	(,%r26), %eax
+
+# CHECK: leal	(,%r27), %eax
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x1d,0x00,0x00,0x00,0x00]
+         leal	(,%r27), %eax
+
+# CHECK: leal	(,%r28), %eax
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x25,0x00,0x00,0x00,0x00]
+         leal	(,%r28), %eax
+
+# CHECK: leal	(,%r29), %eax
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x2d,0x00,0x00,0x00,0x00]
+         leal	(,%r29), %eax
+
+# CHECK: leal	(,%r30), %eax
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x35,0x00,0x00,0x00,0x00]
+         leal	(,%r30), %eax
+
+# CHECK: leal	(,%r31), %eax
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x3d,0x00,0x00,0x00,0x00]
+         leal	(,%r31), %eax
+
+## B bit
+
+# CHECK: leal	(%r16), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x00]
+         leal	(%r16), %eax
+
+# CHECK: leal	(%r17), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x01]
+         leal	(%r17), %eax
+
+# CHECK: leal	(%r18), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x02]
+         leal	(%r18), %eax
+
+# CHECK: leal	(%r19), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x03]
+         leal	(%r19), %eax
+
+# CHECK: leal	(%r20), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x04,0x24]
+         leal	(%r20), %eax
+
+# CHECK: leal	(%r21), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x45,0x00]
+         leal	(%r21), %eax
+
+# CHECK: leal	(%r22), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x06]
+         leal	(%r22), %eax
+
+# CHECK: leal	(%r23), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x07]
+         leal	(%r23), %eax
+
+# CHECK: leal	(%r24), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x00]
+         leal	(%r24), %eax
+
+# CHECK: leal	(%r25), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x01]
+         leal	(%r25), %eax
+
+# CHECK: leal	(%r26), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x02]
+         leal	(%r26), %eax
+
+# CHECK: leal	(%r27), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x03]
+         leal	(%r27), %eax
+
+# CHECK: leal	(%r28), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x04,0x24]
+         leal	(%r28), %eax
+
+# CHECK: leal	(%r29), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x45,0x00]
+         leal	(%r29), %eax
+
+# CHECK: leal	(%r30), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x06]
+         leal	(%r30), %eax
+
+# CHECK: leal	(%r31), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x07]
+         leal	(%r31), %eax
+
+## SIB
+
+# CHECK: leal	1(%r20), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x44,0x24,0x01]
+         leal	1(%r20), %eax
+
+# CHECK: leal	1(%r28), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x44,0x24,0x01]
+         leal	1(%r28), %eax
+
+# CHECK: leal	129(%r20), %eax
+# CHECK: encoding: [0xd5,0x10,0x8d,0x84,0x24,0x81,0x00,0x00,0x00]
+         leal	129(%r20), %eax
+
+# CHECK: leal	129(%r28), %eax
+# CHECK: encoding: [0xd5,0x11,0x8d,0x84,0x24,0x81,0x00,0x00,0x00]
+         leal	129(%r28), %eax
+
+## W bit
+
+# CHECK: leaq	(%rax), %r16
+# CHECK: encoding: [0xd5,0x48,0x8d,0x00]
+         leaq	(%rax), %r16
+
+# CHECK: leaq	(%r16), %rax
+# CHECK: encoding: [0xd5,0x18,0x8d,0x00]
+         leaq	(%r16), %rax
+
+# CHECK: leaq	(,%r16), %rax
+# CHECK: encoding: [0xd5,0x28,0x8d,0x04,0x05,0x00,0x00,0x00,0x00]
+         leaq	(,%r16), %rax
+
+## M bit
+
+# CHECK: imull	%eax, %r16d
+# CHECK: encoding: [0xd5,0xc0,0xaf,0xc0]
+         imull	%eax, %r16d
diff --git a/llvm/test/MC/X86/apx/rex2-bit-intel.s b/llvm/test/MC/X86/apx/rex2-bit-intel.s
new file mode 100644
index 000000000000000..492c599a3662d0c
--- /dev/null
+++ b/llvm/test/MC/X86/apx/rex2-bit-intel.s
@@ -0,0 +1,237 @@
+# RUN: llvm-mc -triple x86_64 -show-encoding -x86-asm-syntax=intel -output-asm-variant=1 %s | FileCheck %s
+
+## R bit
+
+# CHECK: lea	r16d, [rax]
+# CHECK: encoding: [0xd5,0x40,0x8d,0x00]
+         lea	r16d, [rax]
+
+# CHECK: lea	r17d, [rax]
+# CHECK: encoding: [0xd5,0x40,0x8d,0x08]
+         lea	r17d, [rax]
+
+# CHECK: lea	r18d, [rax]
+# CHECK: encoding: [0xd5,0x40,0x8d,0x10]
+         lea	r18d, [rax]
+
+# CHECK: lea	r19d, [rax]
+# CHECK: encoding: [0xd5,0x40,0x8d,0x18]
+         lea	r19d, [rax]
+
+# CHECK: lea	r20d, [rax]
+# CHECK: encoding: [0xd5,0x40,0x8d,0x20]
+         lea	r20d, [rax]
+
+# CHECK: lea	r21d, [rax]
+# CHECK: encoding: [0xd5,0x40,0x8d,0x28]
+         lea	r21d, [rax]
+
+# CHECK: lea	r22d, [rax]
+# CHECK: encoding: [0xd5,0x40,0x8d,0x30]
+         lea	r22d, [rax]
+
+# CHECK: lea	r23d, [rax]
+# CHECK: encoding: [0xd5,0x40,0x8d,0x38]
+         lea	r23d, [rax]
+
+# CHECK: lea	r24d, [rax]
+# CHECK: encoding: [0xd5,0x44,0x8d,0x00]
+         lea	r24d, [rax]
+
+# CHECK: lea	r25d, [rax]
+# CHECK: encoding: [0xd5,0x44,0x8d,0x08]
+         lea	r25d, [rax]
+
+# CHECK: lea	r26d, [rax]
+# CHECK: encoding: [0xd5,0x44,0x8d,0x10]
+         lea	r26d, [rax]
+
+# CHECK: lea	r27d, [rax]
+# CHECK: encoding: [0xd5,0x44,0x8d,0x18]
+         lea	r27d, [rax]
+
+# CHECK: lea	r28d, [rax]
+# CHECK: encoding: [0xd5,0x44,0x8d,0x20]
+         lea	r28d, [rax]
+
+# CHECK: lea	r29d, [rax]
+# CHECK: encoding: [0xd5,0x44,0x8d,0x28]
+         lea	r29d, [rax]
+
+# CHECK: lea	r30d, [rax]
+# CHECK: encoding: [0xd5,0x44,0x8d,0x30]
+         lea	r30d, [rax]
+
+# CHECK: lea	r31d, [rax]
+# CHECK: encoding: [0xd5,0x44,0x8d,0x38]
+         lea	r31d, [rax]
+
+## X bit
+
+# CHECK: lea	eax, [1*r16]
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x05,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r16]
+
+# CHECK: lea	eax, [1*r17]
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x0d,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r17]
+
+# CHECK: lea	eax, [1*r18]
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x15,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r18]
+
+# CHECK: lea	eax, [1*r19]
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x1d,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r19]
+
+# CHECK: lea	eax, [1*r20]
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x25,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r20]
+
+# CHECK: lea	eax, [1*r21]
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x2d,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r21]
+
+# CHECK: lea	eax, [1*r22]
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x35,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r22]
+
+# CHECK: lea	eax, [1*r23]
+# CHECK: encoding: [0xd5,0x20,0x8d,0x04,0x3d,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r23]
+
+# CHECK: lea	eax, [1*r24]
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x05,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r24]
+
+# CHECK: lea	eax, [1*r25]
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x0d,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r25]
+
+# CHECK: lea	eax, [1*r26]
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x15,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r26]
+
+# CHECK: lea	eax, [1*r27]
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x1d,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r27]
+
+# CHECK: lea	eax, [1*r28]
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x25,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r28]
+
+# CHECK: lea	eax, [1*r29]
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x2d,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r29]
+
+# CHECK: lea	eax, [1*r30]
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x35,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r30]
+
+# CHECK: lea	eax, [1*r31]
+# CHECK: encoding: [0xd5,0x22,0x8d,0x04,0x3d,0x00,0x00,0x00,0x00]
+         lea	eax, [1*r31]
+
+## B bit
+
+# CHECK: lea	eax, [r16]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x00]
+         lea	eax, [r16]
+
+# CHECK: lea	eax, [r17]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x01]
+         lea	eax, [r17]
+
+# CHECK: lea	eax, [r18]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x02]
+         lea	eax, [r18]
+
+# CHECK: lea	eax, [r19]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x03]
+         lea	eax, [r19]
+
+# CHECK: lea	eax, [r20]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x04,0x24]
+         lea	eax, [r20]
+
+# CHECK: lea	eax, [r21]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x45,0x00]
+         lea	eax, [r21]
+
+# CHECK: lea	eax, [r22]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x06]
+         lea	eax, [r22]
+
+# CHECK: lea	eax, [r23]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x07]
+         lea	eax, [r23]
+
+# CHECK: lea	eax, [r24]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x00]
+         lea	eax, [r24]
+
+# CHECK: lea	eax, [r25]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x01]
+         lea	eax, [r25]
+
+# CHECK: lea	eax, [r26]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x02]
+         lea	eax, [r26]
+
+# CHECK: lea	eax, [r27]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x03]
+         lea	eax, [r27]
+
+# CHECK: lea	eax, [r28]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x04,0x24]
+         lea	eax, [r28]
+
+# CHECK: lea	eax, [r29]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x45,0x00]
+         lea	eax, [r29]
+
+# CHECK: lea	eax, [r30]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x06]
+         lea	eax, [r30]
+
+# CHECK: lea	eax, [r31]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x07]
+         lea	eax, [r31]
+
+## SIB
+
+# CHECK: lea	eax, [r20 + 1]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x44,0x24,0x01]
+         lea	eax, [r20 + 1]
+
+# CHECK: lea	eax, [r28 + 1]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x44,0x24,0x01]
+         lea	eax, [r28 + 1]
+
+# CHECK: lea	eax, [r20 + 129]
+# CHECK: encoding: [0xd5,0x10,0x8d,0x84,0x24,0x81,0x00,0x00,0x00]
+         lea	eax, [r20 + 129]
+
+# CHECK: lea	eax, [r28 + 129]
+# CHECK: encoding: [0xd5,0x11,0x8d,0x84,0x24,0x81,0x00,0x00,0x00]
+         lea	eax, [r28 + 129]
+
+## W bit
+
+# CHECK: lea	r16, [rax]
+# CHECK: encoding: [0xd5,0x48,0x8d,0x00]
+         lea	r16, [rax]
+
+# CHECK: lea	rax, [r16]
+# CHECK: encoding: [0xd5,0x18,0x8d,0x00]
+         lea	rax, [r16]
+
+# CHECK: lea	rax, [1*r16]
+# CHECK: encoding: [0xd5,0x28,0x8d,0x04,0x05,0x00,0x00,0x00,0x00]
+         lea	rax, [1*r16]
+
+## M bit
+
+# CHECK: imul	r16d, eax
+# CHECK: encoding: [0xd5,0xc0,0xaf,0xc0]
+         imul	r16d, eax
diff --git a/llvm/test/MC/X86/apx/rex2-format-att.s b/llvm/test/MC/X86/apx/rex2-format-att.s
new file mode 100644
index 000000000000000..3dacd2a82876a4a
--- /dev/null
+++ b/llvm/test/MC/X86/apx/rex2-format-att.s
@@ -0,0 +1,343 @@
+# RUN: llvm-mc -triple x86_64 -show-encoding %s | FileCheck %s
+
+## AddRegFrm
+
+# CHECK: movl	$1, %r16d
+# CHECK: encoding: [0xd5,0x10,0xb8,0x01,0x00,0x00,0x00]
+         movl	$1, %r16d
+
+## MRMSrcReg
+
+# CHECK: movslq	%r16d, %rax
+# CHECK: encoding: [0xd5,0x18,0x63,0xc0]
+         movslq	%r16d, %rax
+
+# CHECK: movslq	%eax, %r16
+# CHECK: encoding: [0xd5,0x48,0x63,0xc0]
+         movslq	%eax, %r16
+
+# CHECK: movslq	%r16d, %r17
+# CHECK: encoding: [0xd5,0x58,0x63,0xc8]
+         movslq	%r16d, %r17
+
+## MRMSrcRegCC
+
+# CHECK: cmovll	%r16d, %eax
+# CHECK: encoding: [0xd5,0x90,0x4c,0xc0]
+         cmovll	%r16d, %eax
+
+# CHECK: cmovll	%eax, %r16d
+# CHECK: encoding: [0xd5,0xc0,0x4c,0xc0]
+         cmovll	%eax, %r16d
+
+# CHECK: cmovll	%r16d, %r17d
+# CHECK: encoding: [0xd5,0xd0,0x4c,0xc8]
+         cmovll	%r16d, %r17d
+
+## MRMSrcMem
+
+# CHECK: imull	(%r16,%rax), %ebx
+# CHECK: encoding: [0xd5,0x90,0xaf,0x1c,0x00]
+         imull	(%r16,%rax), %ebx
+
+# CHECK: imull	(%rax,%r16), %ebx
+# CHECK: encoding: [0xd5,0xa0,0xaf,0x1c,0x00]
+         imull	(%rax,%r16), %ebx
+
+# CHECK: imull	(%rax,%rbx), %r16d
+# CHECK: encoding: [0xd5,0xc0,0xaf,0x04,0x18]
+         imull	(%rax,%rbx), %r16d
+
+# CHECK: imull	(%r16,%r17), %eax
+# CHECK: encoding: [0xd5,0xb0,0xaf,0x04,0x08]
+         imull	(%r16,%r17), %eax
+
+# CHECK: imull	(%rax,%r16), %r17d
+# CHECK: encoding: [0xd5,0xe0,0xaf,0x0c,0x00]
+         imull	(%rax,%r16), %r17d
+
+# CHECK: imull	(%r16,%rax), %r17d
+# CHECK: encoding: [0xd5,0xd0,0xaf,0x0c,0x00]
+         imull	(%r16,%rax), %r17d
+
+# CHECK: imull	(%r16,%r17), %r18d
+# CHECK: encoding: [0xd5,0xf0,0xaf,0x14,0x08]
+         imull	(%r16,%r17), %r18d
+
+## MRMSrcMemCC
+
+# CHECK: cmovll	(%r16,%rax), %ebx
+# CHECK: encoding: [0xd5,0x90,0x4c,0x1c,0x00]
+         cmovll	(%r16,%rax), %ebx
+
+# CHECK: cmovll	(%rax,%r16), %ebx
+# CHECK: encoding: [0xd5,0xa0,0x4c,0x1c,0x00]
+         cmovll	(%rax,%r16), %ebx
+
+# CHECK: cmovll	(%rax,%rbx), %r16d
+# CHECK: encoding: [0xd5,0xc0,0x4c,0x04,0x18]
+         cmovll	(%rax,%rbx), %r16d
+
+# CHECK: cmovll	(%r16,%r17), %eax
+# CHECK: encoding: [0xd5,0xb0,0x4c,0x04,0x08]
+         cmovll	(%r16,%r17), %eax
+
+# CHECK: cmovll	(%rax,%r16), %r17d
+# CHECK: encoding: [0xd5,0xe0,0x4c,0x0c,0x00]
+         cmovll	(%rax,%r16), %r17d
+
+# CHECK: cmovll	(%r16,%rax), %r17d
+# CHECK: encoding: [0xd5,0xd0,0x4c,0x0c,0x00]
+         cmovll	(%r16,%rax), %r17d
+
+# CHECK: cmovll	(%r16,%r17), %r18d
+# CHECK: encoding: [0xd5,0xf0,0x4c,0x14,0x08]
+         cmovll	(%r16,%r17), %r18d
+
+## MRMDestReg
+
+# CHECK: movl	%eax, %r16d
+# CHECK: encoding: [0xd5,0x10,0x89,0xc0]
+         movl	%eax, %r16d
+
+# CHECK: movl	%r16d, %eax
+# CHECK: encoding: [0xd5,0x40,0x89,0xc0]
+         movl	%r16d, %eax
+
+# CHECK: movl	%r16d, %r17d
+# CHECK: encoding: [0xd5,0x50,0x89,0xc1]
+         movl	%r16d, %r17d
+
+## MRMDestMem
+
+# CHECK: movl	%ebx, (%r16,%rax)
+# CHECK: encoding: [0xd5,0x10,0x89,0x1c,0x00]
+         movl	%ebx, (%r16,%rax)
+
+# CHECK: movl	%ebx, (%rax,%r16)
+# CHECK: encoding: [0xd5,0x20,0x89,0x1c,0x00]
+         movl	%ebx, (%rax,%r16)
+
+# CHECK: movl	%r16d, (%rax,%rbx)
+# CHECK: encoding: [0xd5,0x40,0x89,0x04,0x18]
+         movl	%r16d, (%rax,%rbx)
+
+# CHECK: movl	%eax, (%r16,%r17)
+# CHECK: encoding: [0xd5,0x30,0x89,0x04,0x08]
+         movl	%eax, (%r16,%r17)
+
+# CHECK: movl	%r17d, (%rax,%r16)
+# CHECK: encoding: [0xd5,0x60,0x89,0x0c,0x00]
+         movl	%r17d, (%rax,%r16)
+
+# CHECK: movl	%r17d, (%r16,%rax)
+# CHECK: encoding: [0xd5,0x50,0x89,0x0c,0x00]
+         movl	%r17d, (%r16,%rax)
+
+# CHECK: movl	%r18d, (%r16,%r17)
+# CHECK: encoding: [0xd5,0x70,0x89,0x14,0x08]
+         movl	%r18d, (%r16,%r17)
+
+# CHECK: movb    %bpl, (%r16,%r14)
+# CHECK: encoding: [0xd5,0x12,0x88,0x2c,0x30]
+         movb    %bpl, (%r16,%r14)
+
+## MRMXmCC
+
+# CHECK: sete	(%rax,%r16)
+# CHECK: encoding: [0xd5,0xa0,0x94,0x04,0x00]
+         sete	(%rax,%r16)
+
+# CHECK: sete	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x90,0x94,0x04,0x00]
+         sete	(%r16,%rax)
+
+# CHECK: sete	(%r16,%r17)
+# CHECK: encoding: [0xd5,0xb0,0x94,0x04,0x08]
+         sete	(%r16,%r17)
+
+## MRMXm
+
+# CHECK: nopl	(%rax,%r16)
+# CHECK: encoding: [0xd5,0xa0,0x1f,0x04,0x00]
+         nopl	(%rax,%r16)
+
+# CHECK: nopl	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x90,0x1f,0x04,0x00]
+         nopl	(%r16,%rax)
+
+# CHECK: nopl	(%r16,%r17)
+# CHECK: encoding: [0xd5,0xb0,0x1f,0x04,0x08]
+         nopl	(%r16,%r17)
+
+## MRM0m
+
+# CHECK: incl	(%rax,%r16)
+# CHECK: encoding: [0xd5,0x20,0xff,0x04,0x00]
+         incl	(%rax,%r16)
+
+# CHECK: incl	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x10,0xff,0x04,0x00]
+         incl	(%r16,%rax)
+
+# CHECK: incl	(%r16,%r17)
+# CHECK: encoding: [0xd5,0x30,0xff,0x04,0x08]
+         incl	(%r16,%r17)
+
+## MRM1m
+
+# CHECK: decl	(%rax,%r16)
+# CHECK: encoding: [0xd5,0x20,0xff,0x0c,0x00]
+         decl	(%rax,%r16)
+
+# CHECK: decl	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x10,0xff,0x0c,0x00]
+         decl	(%r16,%rax)
+
+# CHECK: decl	(%r16,%r17)
+# CHECK: encoding: [0xd5,0x30,0xff,0x0c,0x08]
+         decl	(%r16,%r17)
+
+## MRM2m
+
+# CHECK: notl	(%rax,%r16)
+# CHECK: encoding: [0xd5,0x20,0xf7,0x14,0x00]
+         notl	(%rax,%r16)
+
+# CHECK: notl	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x10,0xf7,0x14,0x00]
+         notl	(%r16,%rax)
+
+# CHECK: notl	(%r16,%r17)
+# CHECK: encoding: [0xd5,0x30,0xf7,0x14,0x08]
+         notl	(%r16,%r17)
+
+## MRM3m
+
+# CHECK: negl	(%rax,%r16)
+# CHECK: encoding: [0xd5,0x20,0xf7,0x1c,0x00]
+         negl	(%rax,%r16)
+
+# CHECK: negl	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x10,0xf7,0x1c,0x00]
+         negl	(%r16,%rax)
+
+# CHECK: negl	(%r16,%r17)
+# CHECK: encoding: [0xd5,0x30,0xf7,0x1c,0x08]
+         negl	(%r16,%r17)
+
+## MRM4m
+
+# CHECK: mull	(%rax,%r16)
+# CHECK: encoding: [0xd5,0x20,0xf7,0x24,0x00]
+         mull	(%rax,%r16)
+
+# CHECK: mull	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x10,0xf7,0x24,0x00]
+         mull	(%r16,%rax)
+
+# CHECK: mull	(%r16,%r17)
+# CHECK: encoding: [0xd5,0x30,0xf7,0x24,0x08]
+         mull	(%r16,%r17)
+
+## MRM5m
+
+# CHECK: imull	(%rax,%r16)
+# CHECK: encoding: [0xd5,0x20,0xf7,0x2c,0x00]
+         imull	(%rax,%r16)
+
+# CHECK: imull	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x10,0xf7,0x2c,0x00]
+         imull	(%r16,%rax)
+
+# CHECK: imull	(%r16,%r17)
+# CHECK: encoding: [0xd5,0x30,0xf7,0x2c,0x08]
+         imull	(%r16,%r17)
+
+## MRM6m
+
+# CHECK: divl	(%rax,%r16)
+# CHECK: encoding: [0xd5,0x20,0xf7,0x34,0x00]
+         divl	(%rax,%r16)
+
+# CHECK: divl	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x10,0xf7,0x34,0x00]
+         divl	(%r16,%rax)
+
+# CHECK: divl	(%r16,%r17)
+# CHECK: encoding: [0xd5,0x30,0xf7,0x34,0x08]
+         divl	(%r16,%r17)
+
+## MRM7m
+
+# CHECK: idivl	(%rax,%r16)
+# CHECK: encoding: [0xd5,0x20,0xf7,0x3c,0x00]
+         idivl	(%rax,%r16)
+
+# CHECK: idivl	(%r16,%rax)
+# CHECK: encoding: [0xd5,0x10,0xf7,0x3c,0x00]
+         idivl	(%r16,%rax)
+
+# CHECK: idivl	(%r16,%r17)
+# CHECK: encoding: [0xd5,0x30,0xf7,0x3c,0x08]
+         idivl	(%r16,%r17)
+
+## MRMXrCC
+
+# CHECK: sete	%r16b
+# CHECK: encoding: [0xd5,0x90,0x94,0xc0]
+         sete	%r16b
+
+## MRMXr
+
+# CHECK: nopl	%r16d
+# CHECK: encoding: [0xd5,0x90,0x1f,0xc0]
+         nopl	%r16d
+
+## MRM0r
+
+# CHECK: incl	%r16d
+# CHECK: encoding: [0xd5,0x10,0xff,0xc0]
+         incl	%r16d
+
+## MRM1r
+
+# CHECK: decl	%r16d
+# CHECK: encoding: [0xd5,0x10,0xff,0xc8]
+         decl	%r16d
+
+## MRM2r
+
+# CHECK: notl	%r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xd0]
+         notl	%r16d
+
+## MRM3r
+
+# CHECK: negl	%r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xd8]
+         negl	%r16d
+
+## MRM4r
+
+# CHECK: mull	%r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xe0]
+         mull	%r16d
+
+## MRM5r
+
+# CHECK: imull	%r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xe8]
+         imull	%r16d
+
+## MRM6r
+
+# CHECK: divl	%r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xf0]
+         divl	%r16d
+
+## MRM7r
+
+# CHECK: idivl	%r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xf8]
+         idivl	%r16d
diff --git a/llvm/test/MC/X86/apx/rex2-format-intel.s b/llvm/test/MC/X86/apx/rex2-format-intel.s
new file mode 100644
index 000000000000000..935bd86537af145
--- /dev/null
+++ b/llvm/test/MC/X86/apx/rex2-format-intel.s
@@ -0,0 +1,343 @@
+# RUN: llvm-mc -triple x86_64 -show-encoding -x86-asm-syntax=intel -output-asm-variant=1 %s | FileCheck %s
+
+## AddRegFrm
+
+# CHECK: mov	r16d, 1
+# CHECK: encoding: [0xd5,0x10,0xb8,0x01,0x00,0x00,0x00]
+         mov	r16d, 1
+
+## MRMSrcReg
+
+# CHECK: movsxd	rax, r16d
+# CHECK: encoding: [0xd5,0x18,0x63,0xc0]
+         movsxd	rax, r16d
+
+# CHECK: movsxd	r16, eax
+# CHECK: encoding: [0xd5,0x48,0x63,0xc0]
+         movsxd	r16, eax
+
+# CHECK: movsxd	r17, r16d
+# CHECK: encoding: [0xd5,0x58,0x63,0xc8]
+         movsxd	r17, r16d
+
+## MRMSrcRegCC
+
+# CHECK: cmovl	eax, r16d
+# CHECK: encoding: [0xd5,0x90,0x4c,0xc0]
+         cmovl	eax, r16d
+
+# CHECK: cmovl	r16d, eax
+# CHECK: encoding: [0xd5,0xc0,0x4c,0xc0]
+         cmovl	r16d, eax
+
+# CHECK: cmovl	r17d, r16d
+# CHECK: encoding: [0xd5,0xd0,0x4c,0xc8]
+         cmovl	r17d, r16d
+
+## MRMSrcMem
+
+# CHECK: imul	ebx, dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x90,0xaf,0x1c,0x00]
+         imul	ebx, dword ptr [r16 + rax]
+
+# CHECK: imul	ebx, dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0xa0,0xaf,0x1c,0x00]
+         imul	ebx, dword ptr [rax + r16]
+
+# CHECK: imul	r16d, dword ptr [rax + rbx]
+# CHECK: encoding: [0xd5,0xc0,0xaf,0x04,0x18]
+         imul	r16d, dword ptr [rax + rbx]
+
+# CHECK: imul	eax, dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0xb0,0xaf,0x04,0x08]
+         imul	eax, dword ptr [r16 + r17]
+
+# CHECK: imul	r17d, dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0xe0,0xaf,0x0c,0x00]
+         imul	r17d, dword ptr [rax + r16]
+
+# CHECK: imul	r17d, dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0xd0,0xaf,0x0c,0x00]
+         imul	r17d, dword ptr [r16 + rax]
+
+# CHECK: imul	r18d, dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0xf0,0xaf,0x14,0x08]
+         imul	r18d, dword ptr [r16 + r17]
+
+## MRMSrcMemCC
+
+# CHECK: cmovl	ebx, dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x90,0x4c,0x1c,0x00]
+         cmovl	ebx, dword ptr [r16 + rax]
+
+# CHECK: cmovl	ebx, dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0xa0,0x4c,0x1c,0x00]
+         cmovl	ebx, dword ptr [rax + r16]
+
+# CHECK: cmovl	r16d, dword ptr [rax + rbx]
+# CHECK: encoding: [0xd5,0xc0,0x4c,0x04,0x18]
+         cmovl	r16d, dword ptr [rax + rbx]
+
+# CHECK: cmovl	eax, dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0xb0,0x4c,0x04,0x08]
+         cmovl	eax, dword ptr [r16 + r17]
+
+# CHECK: cmovl	r17d, dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0xe0,0x4c,0x0c,0x00]
+         cmovl	r17d, dword ptr [rax + r16]
+
+# CHECK: cmovl	r17d, dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0xd0,0x4c,0x0c,0x00]
+         cmovl	r17d, dword ptr [r16 + rax]
+
+# CHECK: cmovl	r18d, dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0xf0,0x4c,0x14,0x08]
+         cmovl	r18d, dword ptr [r16 + r17]
+
+## MRMDestReg
+
+# CHECK: mov	r16d, eax
+# CHECK: encoding: [0xd5,0x10,0x89,0xc0]
+         mov	r16d, eax
+
+# CHECK: mov	eax, r16d
+# CHECK: encoding: [0xd5,0x40,0x89,0xc0]
+         mov	eax, r16d
+
+# CHECK: mov	r17d, r16d
+# CHECK: encoding: [0xd5,0x50,0x89,0xc1]
+         mov	r17d, r16d
+
+## MRMDestMem
+
+# CHECK: mov	dword ptr [r16 + rax], ebx
+# CHECK: encoding: [0xd5,0x10,0x89,0x1c,0x00]
+         mov	dword ptr [r16 + rax], ebx
+
+# CHECK: mov	dword ptr [rax + r16], ebx
+# CHECK: encoding: [0xd5,0x20,0x89,0x1c,0x00]
+         mov	dword ptr [rax + r16], ebx
+
+# CHECK: mov	dword ptr [rax + rbx], r16d
+# CHECK: encoding: [0xd5,0x40,0x89,0x04,0x18]
+         mov	dword ptr [rax + rbx], r16d
+
+# CHECK: mov	dword ptr [r16 + r17], eax
+# CHECK: encoding: [0xd5,0x30,0x89,0x04,0x08]
+         mov	dword ptr [r16 + r17], eax
+
+# CHECK: mov	dword ptr [rax + r16], r17d
+# CHECK: encoding: [0xd5,0x60,0x89,0x0c,0x00]
+         mov	dword ptr [rax + r16], r17d
+
+# CHECK: mov	dword ptr [r16 + rax], r17d
+# CHECK: encoding: [0xd5,0x50,0x89,0x0c,0x00]
+         mov	dword ptr [r16 + rax], r17d
+
+# CHECK: mov	dword ptr [r16 + r17], r18d
+# CHECK: encoding: [0xd5,0x70,0x89,0x14,0x08]
+         mov	dword ptr [r16 + r17], r18d
+
+# CHECK: mov    byte ptr [r16 + r14], bpl
+# CHECK: encoding: [0xd5,0x12,0x88,0x2c,0x30]
+         mov    byte ptr [r16 + r14], bpl
+
+## MRMXmCC
+
+# CHECK: sete	byte ptr [rax + r16]
+# CHECK: encoding: [0xd5,0xa0,0x94,0x04,0x00]
+         sete	byte ptr [rax + r16]
+
+# CHECK: sete	byte ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x90,0x94,0x04,0x00]
+         sete	byte ptr [r16 + rax]
+
+# CHECK: sete	byte ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0xb0,0x94,0x04,0x08]
+         sete	byte ptr [r16 + r17]
+
+## MRMXm
+
+# CHECK: nop	dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0xa0,0x1f,0x04,0x00]
+         nop	dword ptr [rax + r16]
+
+# CHECK: nop	dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x90,0x1f,0x04,0x00]
+         nop	dword ptr [r16 + rax]
+
+# CHECK: nop	dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0xb0,0x1f,0x04,0x08]
+         nop	dword ptr [r16 + r17]
+
+## MRM0m
+
+# CHECK: inc	dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0x20,0xff,0x04,0x00]
+         inc	dword ptr [rax + r16]
+
+# CHECK: inc	dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x10,0xff,0x04,0x00]
+         inc	dword ptr [r16 + rax]
+
+# CHECK: inc	dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0x30,0xff,0x04,0x08]
+         inc	dword ptr [r16 + r17]
+
+## MRM1m
+
+# CHECK: dec	dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0x20,0xff,0x0c,0x00]
+         dec	dword ptr [rax + r16]
+
+# CHECK: dec	dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x10,0xff,0x0c,0x00]
+         dec	dword ptr [r16 + rax]
+
+# CHECK: dec	dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0x30,0xff,0x0c,0x08]
+         dec	dword ptr [r16 + r17]
+
+## MRM2m
+
+# CHECK: not	dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0x20,0xf7,0x14,0x00]
+         not	dword ptr [rax + r16]
+
+# CHECK: not	dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x10,0xf7,0x14,0x00]
+         not	dword ptr [r16 + rax]
+
+# CHECK: not	dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0x30,0xf7,0x14,0x08]
+         not	dword ptr [r16 + r17]
+
+## MRM3m
+
+# CHECK: neg	dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0x20,0xf7,0x1c,0x00]
+         neg	dword ptr [rax + r16]
+
+# CHECK: neg	dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x10,0xf7,0x1c,0x00]
+         neg	dword ptr [r16 + rax]
+
+# CHECK: neg	dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0x30,0xf7,0x1c,0x08]
+         neg	dword ptr [r16 + r17]
+
+## MRM4m
+
+# CHECK: mul	dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0x20,0xf7,0x24,0x00]
+         mul	dword ptr [rax + r16]
+
+# CHECK: mul	dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x10,0xf7,0x24,0x00]
+         mul	dword ptr [r16 + rax]
+
+# CHECK: mul	dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0x30,0xf7,0x24,0x08]
+         mul	dword ptr [r16 + r17]
+
+## MRM5m
+
+# CHECK: imul	dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0x20,0xf7,0x2c,0x00]
+         imul	dword ptr [rax + r16]
+
+# CHECK: imul	dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x10,0xf7,0x2c,0x00]
+         imul	dword ptr [r16 + rax]
+
+# CHECK: imul	dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0x30,0xf7,0x2c,0x08]
+         imul	dword ptr [r16 + r17]
+
+## MRM6m
+
+# CHECK: div	dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0x20,0xf7,0x34,0x00]
+         div	dword ptr [rax + r16]
+
+# CHECK: div	dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x10,0xf7,0x34,0x00]
+         div	dword ptr [r16 + rax]
+
+# CHECK: div	dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0x30,0xf7,0x34,0x08]
+         div	dword ptr [r16 + r17]
+
+## MRM7m
+
+# CHECK: idiv	dword ptr [rax + r16]
+# CHECK: encoding: [0xd5,0x20,0xf7,0x3c,0x00]
+         idiv	dword ptr [rax + r16]
+
+# CHECK: idiv	dword ptr [r16 + rax]
+# CHECK: encoding: [0xd5,0x10,0xf7,0x3c,0x00]
+         idiv	dword ptr [r16 + rax]
+
+# CHECK: idiv	dword ptr [r16 + r17]
+# CHECK: encoding: [0xd5,0x30,0xf7,0x3c,0x08]
+         idiv	dword ptr [r16 + r17]
+
+## MRMXrCC
+
+# CHECK: sete	r16b
+# CHECK: encoding: [0xd5,0x90,0x94,0xc0]
+         sete	r16b
+
+## MRMXr
+
+# CHECK: nop	r16d
+# CHECK: encoding: [0xd5,0x90,0x1f,0xc0]
+         nop	r16d
+
+## MRM0r
+
+# CHECK: inc	r16d
+# CHECK: encoding: [0xd5,0x10,0xff,0xc0]
+         inc	r16d
+
+## MRM1r
+
+# CHECK: dec	r16d
+# CHECK: encoding: [0xd5,0x10,0xff,0xc8]
+         dec	r16d
+
+## MRM2r
+
+# CHECK: not	r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xd0]
+         not	r16d
+
+## MRM3r
+
+# CHECK: neg	r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xd8]
+         neg	r16d
+
+## MRM4r
+
+# CHECK: mul	r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xe0]
+         mul	r16d
+
+## MRM5r
+
+# CHECK: imul	r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xe8]
+         imul	r16d
+
+## MRM6r
+
+# CHECK: div	r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xf0]
+         div	r16d
+
+## MRM7r
+
+# CHECK: idiv	r16d
+# CHECK: encoding: [0xd5,0x10,0xf7,0xf8]
+         idiv	r16d

>From fd413782a0d30c5587e9cbeeff9e0d9e4ff14e77 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Fri, 10 Nov 2023 17:24:21 +0800
Subject: [PATCH 2/5] format code

---
 llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp        | 2 +-
 llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h        | 2 +-
 llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 3 ++-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 73b03723c263323..19b4ea474f5284b 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -1413,7 +1413,7 @@ bool X86AsmParser::MatchRegisterByName(MCRegister &RegNo, StringRef RegName,
     }
   }
 
- if (X86II::isApxExtendedReg(RegNo))
+  if (X86II::isApxExtendedReg(RegNo))
     UseApxExtendedReg = true;
 
   // If this is "db[0-15]", match it as an alias
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index 865987260b42a43..88420215bcc1b78 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -1223,7 +1223,7 @@ namespace X86II {
         (RegNo >= X86::ZMM8 && RegNo <= X86::ZMM31))
       return true;
 
-   if (isApxExtendedReg(RegNo))
+    if (isApxExtendedReg(RegNo))
       return true;
 
     switch (RegNo) {
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 7e471f57c9c144f..02badbf74b2fe31 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -633,7 +633,8 @@ void X86MCCodeEmitter::emitMemModRMByte(
       case X86::SBB64rm:
       case X86::SUB64rm:
       case X86::XOR64rm:
-        // We haven't support relocation for REX2 prefix, so temporarily use REX relocation
+        // We haven't support relocation for REX2 prefix, so temporarily use REX
+        // relocation.
         // TODO: Support new relocation for REX2.
         return (Kind == REX || Kind == REX2) ? X86::reloc_riprel_4byte_relax_rex
                                              : X86::reloc_riprel_4byte_relax;

>From 37c127ede63cc36f6fa606b26a5398acf4fb39cb Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Fri, 10 Nov 2023 18:10:03 +0800
Subject: [PATCH 3/5] Format code - remove empty line

---
 llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 02badbf74b2fe31..e56c833b88bbfd8 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -638,7 +638,6 @@ void X86MCCodeEmitter::emitMemModRMByte(
         // TODO: Support new relocation for REX2.
         return (Kind == REX || Kind == REX2) ? X86::reloc_riprel_4byte_relax_rex
                                              : X86::reloc_riprel_4byte_relax;
-
       }
     }();
 

>From cc84e0000e70e566478cfa212927050c03ab55ea Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Sat, 11 Nov 2023 10:14:15 +0800
Subject: [PATCH 4/5] Address review comments: assertion, std fallthrough,
 comments

---
 llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h        | 1 +
 llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index 88420215bcc1b78..4c57009e3bc08bf 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -1210,6 +1210,7 @@ namespace X86II {
 
   /// \returns true if \p RegNo is an apx extended register.
   inline bool isApxExtendedReg(unsigned RegNo) {
+    assert(X86::R31WH - X86::R16 == 95 && "EGPRs are not continuous");
     return RegNo >= X86::R16 && RegNo <= X86::R31WH;
   }
 
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index e56c833b88bbfd8..031998ef431bd93 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -46,7 +46,7 @@ class X86OpcodePrefixHelper {
   // | 40H | | WRXB |
   // +-----+ +------+
 
-  // REX2 (2 byte)
+  // REX2 (2 bytes)
   // +-----+ +-------------------+
   // | D5H | | M | R'X'B' | WRXB |
   // +-----+ +-------------------+
@@ -1415,7 +1415,7 @@ PrefixKind X86MCCodeEmitter::emitOpcodePrefix(int MemOperand, const MCInst &MI,
     // Encoded by M bit in REX2
     if (Kind == REX2)
       break;
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case X86II::T8:        // 0F 38
   case X86II::TA:        // 0F 3A
   case X86II::ThreeDNow: // 0F 0F, second 0F emitted by caller.

>From 2f5c8345aee84ba4d3d1cf11d88c6104c83c2bb9 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Sat, 11 Nov 2023 11:10:11 +0800
Subject: [PATCH 5/5] Revert the change for MRMSrcRegOp4 b/c all its operands
 are vector registers

---
 llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 031998ef431bd93..6f372ba46d5ab0e 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -1175,12 +1175,12 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
   }
   case X86II::MRMSrcRegOp4: {
     //  dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
-    Prefix.setRR2(MI, CurOp++);
+    Prefix.setR(MI, CurOp++);
     Prefix.set4V(MI, CurOp++);
     // Skip second register source (encoded in Imm[7:4])
     ++CurOp;
 
-    Prefix.setBB2(MI, CurOp);
+    Prefix.setB(MI, CurOp);
     Prefix.setX(MI, CurOp, 4);
     ++CurOp;
     break;



More information about the llvm-commits mailing list