[llvm] a22e8c9 - [X86][MC][NFC] Refine code in X86MCCodeEmitter.cpp about opcode prefix

Shengchen Kan via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 9 19:11:29 PST 2023


Author: Shengchen Kan
Date: 2023-02-10T11:11:21+08:00
New Revision: a22e8c9dadea290b4b2d675f60b27428e420b16f

URL: https://github.com/llvm/llvm-project/commit/a22e8c9dadea290b4b2d675f60b27428e420b16f
DIFF: https://github.com/llvm/llvm-project/commit/a22e8c9dadea290b4b2d675f60b27428e420b16f.diff

LOG: [X86][MC][NFC] Refine code in X86MCCodeEmitter.cpp about opcode prefix

1. Make code clearer by separating the logic of setting bits from the
   logic of how a prefix is encoded
2. Extract common code into functions to avoid code duplication
3. Return a enum rather a boolean to ehance scalability and uniform
   the behavior of functions

Reviewed By: pengfei, craig.topper

Differential Revision: https://reviews.llvm.org/D143471

Added: 
    

Modified: 
    llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 2b819641ee5fc..84b11af0a3565 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -37,6 +37,210 @@ using namespace llvm;
 
 namespace {
 
+enum PrefixKind { None, REX, XOP, VEX2, VEX3, EVEX };
+
+static void emitByte(uint8_t C, raw_ostream &OS) { OS << static_cast<char>(C); }
+
+class X86OpcodePrefixHelper {
+  // REX (1 byte)
+  // +-----+ +------+
+  // | 40H | | WRXB |
+  // +-----+ +------+
+
+  // XOP (3-byte)
+  // +-----+ +--------------+ +-------------------+
+  // | 8Fh | | RXB | m-mmmm | | W | vvvv | L | pp |
+  // +-----+ +--------------+ +-------------------+
+
+  // VEX2 (2 bytes)
+  // +-----+ +-------------------+
+  // | C5h | | R | vvvv | L | pp |
+  // +-----+ +-------------------+
+
+  // VEX3 (3 bytes)
+  // +-----+ +--------------+ +-------------------+
+  // | C4h | | RXB | m-mmmm | | W | vvvv | L | pp |
+  // +-----+ +--------------+ +-------------------+
+
+  // VEX_R: opcode externsion equivalent to REX.R in
+  // 1's complement (inverted) form
+  //
+  //  1: Same as REX_R=0 (must be 1 in 32-bit mode)
+  //  0: Same as REX_R=1 (64 bit mode only)
+
+  // VEX_X: equivalent to REX.X, only used when a
+  // register is used for index in SIB Byte.
+  //
+  //  1: Same as REX.X=0 (must be 1 in 32-bit mode)
+  //  0: Same as REX.X=1 (64-bit mode only)
+
+  // VEX_B:
+  //  1: Same as REX_B=0 (ignored in 32-bit mode)
+  //  0: Same as REX_B=1 (64 bit mode only)
+
+  // VEX_W: opcode specific (use like REX.W, or used for
+  // opcode extension, or ignored, depending on the opcode byte)
+
+  // VEX_5M (VEX m-mmmmm field):
+  //
+  //  0b00000: Reserved for future use
+  //  0b00001: implied 0F leading opcode
+  //  0b00010: implied 0F 38 leading opcode bytes
+  //  0b00011: implied 0F 3A leading opcode bytes
+  //  0b00100: Reserved for future use
+  //  0b00101: VEX MAP5
+  //  0b00110: VEX MAP6
+  //  0b00111-0b11111: Reserved for future use
+  //  0b01000: XOP map select - 08h instructions with imm byte
+  //  0b01001: XOP map select - 09h instructions with no imm byte
+  //  0b01010: XOP map select - 0Ah instructions with imm dword
+
+  // VEX_4V (VEX vvvv field): a register specifier
+  // (in 1's complement form) or 1111 if unused.
+
+  // VEX_PP: opcode extension providing equivalent
+  // functionality of a SIMD prefix
+  //  0b00: None
+  //  0b01: 66
+  //  0b10: F3
+  //  0b11: F2
+
+  // EVEX (4 bytes)
+  // +-----+ +--------------+ +-------------------+ +------------------------+
+  // | 62h | | RXBR' | 00mm | | W | vvvv | 1 | pp | | z | L'L | b | v' | aaa |
+  // +-----+ +--------------+ +-------------------+ +------------------------+
+
+  // EVEX_L2/VEX_L (Vector Length):
+  // L2 L
+  //  0 0: scalar or 128-bit vector
+  //  0 1: 256-bit vector
+  //  1 0: 512-bit vector
+
+private:
+  unsigned W : 1;
+  unsigned R : 1;
+  unsigned X : 1;
+  unsigned B : 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;
+  unsigned EVEX_V2 : 1;
+  unsigned EVEX_aaa : 3;
+  PrefixKind Kind = None;
+  const MCRegisterInfo &MRI;
+
+  unsigned getRegEncoding(const MCInst &MI, unsigned OpNum) const {
+    return MRI.getEncodingValue(MI.getOperand(OpNum).getReg());
+  }
+
+  void setR(unsigned Encoding) { R = Encoding >> 3 & 1; }
+  void setR2(unsigned Encoding) { EVEX_R2 = Encoding >> 4 & 1; }
+  void set4V(unsigned Encoding) { VEX_4V = Encoding & 0xf; }
+  void setV2(unsigned Encoding) { EVEX_V2 = Encoding >> 4 & 1; }
+
+public:
+  void setW(bool V) { W = V; }
+  void setR(const MCInst &MI, unsigned OpNum) {
+    setR(getRegEncoding(MI, OpNum));
+  }
+  void setX(const MCInst &MI, unsigned OpNum, unsigned Shift = 3) {
+    X = getRegEncoding(MI, OpNum) >> Shift & 1;
+  }
+  void setB(const MCInst &MI, unsigned OpNum) {
+    B = getRegEncoding(MI, OpNum) >> 3 & 1;
+  }
+  void set4V(const MCInst &MI, unsigned OpNum) {
+    set4V(getRegEncoding(MI, OpNum));
+  }
+  void setL(bool V) { VEX_L = V; }
+  void setPP(unsigned V) { VEX_PP = V; }
+  void set5M(unsigned V) { VEX_5M = V; }
+  void setR2(const MCInst &MI, unsigned OpNum) {
+    setR2(getRegEncoding(MI, OpNum));
+  }
+  void setRR2(const MCInst &MI, unsigned OpNum) {
+    unsigned Encoding = getRegEncoding(MI, OpNum);
+    setR(Encoding);
+    setR2(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 set4VV2(const MCInst &MI, unsigned OpNum) {
+    unsigned Encoding = getRegEncoding(MI, OpNum);
+    set4V(Encoding);
+    setV2(Encoding);
+  }
+  void setAAA(const MCInst &MI, unsigned OpNum) {
+    EVEX_aaa = getRegEncoding(MI, OpNum);
+  }
+
+  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) {}
+
+  void setLowerBound(PrefixKind K) { Kind = K; }
+
+  PrefixKind determineOptimalKind() {
+    switch (Kind) {
+    case None:
+      Kind = (W | R | X | B) ? REX : None;
+      break;
+    case REX:
+    case XOP:
+    case VEX3:
+    case EVEX:
+      break;
+    case VEX2:
+      Kind = (W | X | B | (VEX_5M != 1)) ? VEX3 : VEX2;
+      break;
+    }
+    return Kind;
+  }
+
+  void emit(raw_ostream &OS) const {
+    uint8_t FirstPayload =
+        ((~R) & 0x1) << 7 | ((~X) & 0x1) << 6 | ((~B) & 0x1) << 5;
+    uint8_t LastPayload = ((~VEX_4V) & 0xf) << 3 | VEX_L << 2 | VEX_PP;
+    switch (Kind) {
+    case None:
+      return;
+    case REX:
+      emitByte(0x40 | W << 3 | R << 2 | X << 1 | B, OS);
+      return;
+    case VEX2:
+      emitByte(0xC5, OS);
+      emitByte(~R << 7 | LastPayload, OS);
+      return;
+    case VEX3:
+    case XOP:
+      emitByte(Kind == VEX3 ? 0xC4 : 0x8F, OS);
+      emitByte(FirstPayload | VEX_5M, OS);
+      emitByte(W << 7 | LastPayload, OS);
+      return;
+    case EVEX:
+      assert(VEX_5M & 0x7 &&
+             "More than 3 significant bits in VEX.m-mmmm fields for EVEX!");
+      emitByte(0x62, OS);
+      emitByte(FirstPayload | ((~EVEX_R2) & 0x1) << 4 | VEX_5M, OS);
+      emitByte(W << 7 | ((~VEX_4V) & 0xf) << 3 | 1 << 2 | VEX_PP, OS);
+      emitByte(EVEX_z << 7 | EVEX_L2 << 6 | VEX_L << 5 | EVEX_b << 4 |
+                   ((~EVEX_V2) & 0x1) << 3 | EVEX_aaa,
+               OS);
+      return;
+    }
+  }
+};
+
 class X86MCCodeEmitter : public MCCodeEmitter {
   const MCInstrInfo &MCII;
   MCContext &Ctx;
@@ -60,12 +264,6 @@ class X86MCCodeEmitter : public MCCodeEmitter {
 
   unsigned getX86RegEncoding(const MCInst &MI, unsigned OpNum) const;
 
-  /// \param MI a single low-level machine instruction.
-  /// \param OpNum the operand #.
-  /// \returns true if the OpNumth operand of MI  require a bit to be set in
-  /// REX prefix.
-  bool isREXExtendedReg(const MCInst &MI, unsigned OpNum) const;
-
   void emitImmediate(const MCOperand &Disp, SMLoc Loc, unsigned ImmSize,
                      MCFixupKind FixupKind, uint64_t StartByte, raw_ostream &OS,
                      SmallVectorImpl<MCFixup> &Fixups, int ImmOffset = 0) const;
@@ -77,25 +275,26 @@ class X86MCCodeEmitter : public MCCodeEmitter {
                    raw_ostream &OS) const;
 
   void emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField,
-                        uint64_t TSFlags, bool HasREX, uint64_t StartByte,
+                        uint64_t TSFlags, PrefixKind Kind, uint64_t StartByte,
                         raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
                         const MCSubtargetInfo &STI,
                         bool ForceSIB = false) const;
 
-  bool emitPrefixImpl(unsigned &CurOp, const MCInst &MI,
-                      const MCSubtargetInfo &STI, raw_ostream &OS) const;
+  PrefixKind emitPrefixImpl(unsigned &CurOp, const MCInst &MI,
+                            const MCSubtargetInfo &STI, raw_ostream &OS) const;
 
-  void emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
-                           raw_ostream &OS) const;
+  PrefixKind emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
+                                 raw_ostream &OS) const;
 
   void emitSegmentOverridePrefix(unsigned SegOperand, const MCInst &MI,
                                  raw_ostream &OS) const;
 
-  bool emitOpcodePrefix(int MemOperand, const MCInst &MI,
-                        const MCSubtargetInfo &STI, raw_ostream &OS) const;
+  PrefixKind emitOpcodePrefix(int MemOperand, const MCInst &MI,
+                              const MCSubtargetInfo &STI,
+                              raw_ostream &OS) const;
 
-  bool emitREXPrefix(int MemOperand, const MCInst &MI,
-                     const MCSubtargetInfo &STI, raw_ostream &OS) const;
+  PrefixKind emitREXPrefix(int MemOperand, const MCInst &MI,
+                           const MCSubtargetInfo &STI, raw_ostream &OS) const;
 };
 
 } // end anonymous namespace
@@ -105,8 +304,6 @@ static uint8_t modRMByte(unsigned Mod, unsigned RegOpcode, unsigned RM) {
   return RM | (RegOpcode << 3) | (Mod << 6);
 }
 
-static void emitByte(uint8_t C, raw_ostream &OS) { OS << static_cast<char>(C); }
-
 static void emitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) {
   // Output the constant in little endian byte order.
   for (unsigned i = 0; i != Size; ++i) {
@@ -218,15 +415,6 @@ unsigned X86MCCodeEmitter::getX86RegEncoding(const MCInst &MI,
   return Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(OpNum).getReg());
 }
 
-/// \param MI a single low-level machine instruction.
-/// \param OpNum the operand #.
-/// \returns true if the OpNumth operand of MI  require a bit to be set in
-/// REX prefix.
-bool X86MCCodeEmitter::isREXExtendedReg(const MCInst &MI,
-                                        unsigned OpNum) const {
-  return (getX86RegEncoding(MI, OpNum) >> 3) & 1;
-}
-
 void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc,
                                      unsigned Size, MCFixupKind FixupKind,
                                      uint64_t StartByte, raw_ostream &OS,
@@ -319,7 +507,7 @@ void X86MCCodeEmitter::emitSIBByte(unsigned SS, unsigned Index, unsigned Base,
 
 void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
                                         unsigned RegOpcodeField,
-                                        uint64_t TSFlags, bool HasREX,
+                                        uint64_t TSFlags, PrefixKind Kind,
                                         uint64_t StartByte, raw_ostream &OS,
                                         SmallVectorImpl<MCFixup> &Fixups,
                                         const MCSubtargetInfo &STI,
@@ -355,7 +543,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
         // 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(HasREX);
+        assert(Kind == REX);
         return X86::reloc_riprel_4byte_movq_load;
       case X86::ADC32rm:
       case X86::ADD32rm:
@@ -379,8 +567,8 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
       case X86::SBB64rm:
       case X86::SUB64rm:
       case X86::XOR64rm:
-        return HasREX ? X86::reloc_riprel_4byte_relax_rex
-                      : X86::reloc_riprel_4byte_relax;
+        return Kind == REX ? X86::reloc_riprel_4byte_relax_rex
+                           : X86::reloc_riprel_4byte_relax;
       }
     }();
 
@@ -592,10 +780,11 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
 
 /// Emit all instruction prefixes.
 ///
-/// \returns true if REX prefix is used, otherwise returns false.
-bool X86MCCodeEmitter::emitPrefixImpl(unsigned &CurOp, const MCInst &MI,
-                                      const MCSubtargetInfo &STI,
-                                      raw_ostream &OS) const {
+/// \returns one of the REX, XOP, VEX2, VEX3, EVEX if any of them is used,
+/// otherwise returns None.
+PrefixKind X86MCCodeEmitter::emitPrefixImpl(unsigned &CurOp, const MCInst &MI,
+                                            const MCSubtargetInfo &STI,
+                                            raw_ostream &OS) const {
   uint64_t TSFlags = MCII.get(MI.getOpcode()).TSFlags;
   // Determine where the memory operand starts, if present.
   int MemoryOperand = X86II::getMemoryOperandNo(TSFlags);
@@ -648,154 +837,102 @@ bool X86MCCodeEmitter::emitPrefixImpl(unsigned &CurOp, const MCInst &MI,
 
   // REX prefix is optional, but if used must be immediately before the opcode
   // Encoding type for this instruction.
-  uint64_t Encoding = TSFlags & X86II::EncodingMask;
-  bool HasREX = false;
-  if (Encoding)
-    emitVEXOpcodePrefix(MemoryOperand, MI, OS);
-  else
-    HasREX = emitOpcodePrefix(MemoryOperand, MI, STI, OS);
-
-  return HasREX;
+  return (TSFlags & X86II::EncodingMask)
+             ? emitVEXOpcodePrefix(MemoryOperand, MI, OS)
+             : emitOpcodePrefix(MemoryOperand, MI, STI, OS);
 }
 
-/// AVX instructions are encoded using a opcode prefix called VEX.
-void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
-                                           raw_ostream &OS) const {
+// AVX instructions are encoded using an encoding scheme that combines
+// prefix bytes, opcode extension field, operand encoding fields, and vector
+// length encoding capability into a new prefix, referred to as VEX.
+
+// The majority of the AVX-512 family of instructions (operating on
+// 512/256/128-bit vector register operands) are encoded using a new prefix
+// (called EVEX).
+
+// XOP is a revised subset of what was originally intended as SSE5. It was
+// changed to be similar but not overlapping with AVX.
+
+/// Emit XOP, VEX2, VEX3 or EVEX prefix.
+/// \returns the used prefix.
+PrefixKind X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand,
+                                                 const MCInst &MI,
+                                                 raw_ostream &OS) const {
   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
   uint64_t TSFlags = Desc.TSFlags;
 
   assert(!(TSFlags & X86II::LOCK) && "Can't have LOCK VEX.");
 
-  uint64_t Encoding = TSFlags & X86II::EncodingMask;
+  X86OpcodePrefixHelper Prefix(*Ctx.getRegisterInfo());
+  switch (TSFlags & X86II::EncodingMask) {
+  default:
+    break;
+  case X86II::XOP:
+    Prefix.setLowerBound(XOP);
+    break;
+  case X86II::VEX:
+    // VEX can be 2 byte or 3 byte, not determined yet if not explicit
+    Prefix.setLowerBound(MI.getFlags() & X86::IP_USE_VEX3 ? VEX3 : VEX2);
+    break;
+  case X86II::EVEX:
+    Prefix.setLowerBound(EVEX);
+    break;
+  }
+
+  Prefix.setW(TSFlags & X86II::VEX_W);
+
   bool HasEVEX_K = TSFlags & X86II::EVEX_K;
   bool HasVEX_4V = TSFlags & X86II::VEX_4V;
   bool HasEVEX_RC = TSFlags & X86II::EVEX_RC;
 
-  // VEX_R: opcode externsion equivalent to REX.R in
-  // 1's complement (inverted) form
-  //
-  //  1: Same as REX_R=0 (must be 1 in 32-bit mode)
-  //  0: Same as REX_R=1 (64 bit mode only)
-  //
-  uint8_t VEX_R = 0x1;
-  uint8_t EVEX_R2 = 0x1;
-
-  // VEX_X: equivalent to REX.X, only used when a
-  // register is used for index in SIB Byte.
-  //
-  //  1: Same as REX.X=0 (must be 1 in 32-bit mode)
-  //  0: Same as REX.X=1 (64-bit mode only)
-  uint8_t VEX_X = 0x1;
-
-  // VEX_B:
-  //
-  //  1: Same as REX_B=0 (ignored in 32-bit mode)
-  //  0: Same as REX_B=1 (64 bit mode only)
-  //
-  uint8_t VEX_B = 0x1;
-
-  // VEX_W: opcode specific (use like REX.W, or used for
-  // opcode extension, or ignored, depending on the opcode byte)
-  uint8_t VEX_W = (TSFlags & X86II::VEX_W) ? 1 : 0;
-
-  // VEX_5M (VEX m-mmmmm field):
-  //
-  //  0b00000: Reserved for future use
-  //  0b00001: implied 0F leading opcode
-  //  0b00010: implied 0F 38 leading opcode bytes
-  //  0b00011: implied 0F 3A leading opcode bytes
-  //  0b00100: Reserved for future use
-  //  0b00101: VEX MAP5
-  //  0b00110: VEX MAP6
-  //  0b00111-0b11111: Reserved for future use
-  //  0b01000: XOP map select - 08h instructions with imm byte
-  //  0b01001: XOP map select - 09h instructions with no imm byte
-  //  0b01010: XOP map select - 0Ah instructions with imm dword
-  uint8_t VEX_5M;
   switch (TSFlags & X86II::OpMapMask) {
   default:
     llvm_unreachable("Invalid prefix!");
   case X86II::TB:
-    VEX_5M = 0x1;
-    break; // 0F
+    Prefix.set5M(0x1); // 0F
+    break;
   case X86II::T8:
-    VEX_5M = 0x2;
-    break; // 0F 38
+    Prefix.set5M(0x2); // 0F 38
+    break;
   case X86II::TA:
-    VEX_5M = 0x3;
-    break; // 0F 3A
+    Prefix.set5M(0x3); // 0F 3A
+    break;
   case X86II::XOP8:
-    VEX_5M = 0x8;
+    Prefix.set5M(0x8);
     break;
   case X86II::XOP9:
-    VEX_5M = 0x9;
+    Prefix.set5M(0x9);
     break;
   case X86II::XOPA:
-    VEX_5M = 0xA;
+    Prefix.set5M(0xA);
     break;
   case X86II::T_MAP5:
-    VEX_5M = 0x5;
+    Prefix.set5M(0x5);
     break;
   case X86II::T_MAP6:
-    VEX_5M = 0x6;
+    Prefix.set5M(0x6);
     break;
   }
 
-  // VEX_4V (VEX vvvv field): a register specifier
-  // (in 1's complement form) or 1111 if unused.
-  uint8_t VEX_4V = 0xf;
-  uint8_t EVEX_V2 = 0x1;
-
-  // EVEX_L2/VEX_L (Vector Length):
-  //
-  // L2 L
-  //  0 0: scalar or 128-bit vector
-  //  0 1: 256-bit vector
-  //  1 0: 512-bit vector
-  //
-  uint8_t VEX_L = (TSFlags & X86II::VEX_L) ? 1 : 0;
-  uint8_t EVEX_L2 = (TSFlags & X86II::EVEX_L2) ? 1 : 0;
-
-  // VEX_PP: opcode extension providing equivalent
-  // functionality of a SIMD prefix
-  //
-  //  0b00: None
-  //  0b01: 66
-  //  0b10: F3
-  //  0b11: F2
-  //
-  uint8_t VEX_PP = 0;
+  Prefix.setL(TSFlags & X86II::VEX_L);
+  Prefix.setL2(TSFlags & X86II::EVEX_L2);
   switch (TSFlags & X86II::OpPrefixMask) {
   case X86II::PD:
-    VEX_PP = 0x1;
-    break; // 66
+    Prefix.setPP(0x1); // 66
+    break;
   case X86II::XS:
-    VEX_PP = 0x2;
-    break; // F3
+    Prefix.setPP(0x2); // F3
+    break;
   case X86II::XD:
-    VEX_PP = 0x3;
-    break; // F2
+    Prefix.setPP(0x3); // F2
+    break;
   }
 
-  // EVEX_U
-  uint8_t EVEX_U = 1; // Always '1' so far
-
-  // EVEX_z
-  uint8_t EVEX_z = (HasEVEX_K && (TSFlags & X86II::EVEX_Z)) ? 1 : 0;
-
-  // EVEX_b
-  uint8_t EVEX_b = (TSFlags & X86II::EVEX_B) ? 1 : 0;
-
-  // EVEX_rc
-  uint8_t EVEX_rc = 0;
-
-  // EVEX_aaa
-  uint8_t EVEX_aaa = 0;
+  Prefix.setZ(HasEVEX_K && (TSFlags & X86II::EVEX_Z));
+  Prefix.setEVEX_b(TSFlags & X86II::EVEX_B);
 
   bool EncodeRC = false;
-
-  // Classify VEX_B, VEX_4V, VEX_R, VEX_X
-  unsigned NumOps = Desc.getNumOperands();
+  uint8_t EVEX_rc = 0;
   unsigned CurOp = X86II::getOperandBias(Desc);
 
   switch (TSFlags & X86II::FormMask) {
@@ -803,19 +940,11 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     llvm_unreachable("Unexpected form in emitVEXOpcodePrefix!");
   case X86II::MRMDestMem4VOp3CC: {
     //  MemAddr, src1(ModR/M), src2(VEX_4V)
-    unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg);
-    VEX_B = ~(BaseRegEnc >> 3) & 1;
-    unsigned IndexRegEnc =
-        getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg);
-    VEX_X = ~(IndexRegEnc >> 3) & 1;
-
+    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
     CurOp += X86::AddrNumOperands;
-
-    unsigned RegEnc = getX86RegEncoding(MI, ++CurOp);
-    VEX_R = ~(RegEnc >> 3) & 1;
-
-    unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_4V = ~VRegEnc & 0xf;
+    Prefix.setR(MI, ++CurOp);
+    Prefix.set4V(MI, CurOp++);
     break;
   }
   case X86II::MRM_C0:
@@ -829,28 +958,20 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     //  MemAddr, src1(VEX_4V), src2(ModR/M)
     //  MemAddr, src1(ModR/M), imm8
     //
-    unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg);
-    VEX_B = ~(BaseRegEnc >> 3) & 1;
-    unsigned IndexRegEnc =
-        getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg);
-    VEX_X = ~(IndexRegEnc >> 3) & 1;
+    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
     if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV.
-      EVEX_V2 = ~(IndexRegEnc >> 4) & 1;
+      Prefix.setV2(MI, MemOperand + X86::AddrIndexReg);
 
     CurOp += X86::AddrNumOperands;
 
     if (HasEVEX_K)
-      EVEX_aaa = getX86RegEncoding(MI, CurOp++);
+      Prefix.setAAA(MI, CurOp++);
 
-    if (HasVEX_4V) {
-      unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
-      VEX_4V = ~VRegEnc & 0xf;
-      EVEX_V2 = ~(VRegEnc >> 4) & 1;
-    }
+    if (HasVEX_4V)
+      Prefix.set4VV2(MI, CurOp++);
 
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_R = ~(RegEnc >> 3) & 1;
-    EVEX_R2 = ~(RegEnc >> 4) & 1;
+    Prefix.setRR2(MI, CurOp++);
     break;
   }
   case X86II::MRMSrcMemFSIB:
@@ -863,57 +984,36 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     //
     //  FMA4:
     //  dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4])
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_R = ~(RegEnc >> 3) & 1;
-    EVEX_R2 = ~(RegEnc >> 4) & 1;
+    Prefix.setRR2(MI, CurOp++);
 
     if (HasEVEX_K)
-      EVEX_aaa = getX86RegEncoding(MI, CurOp++);
+      Prefix.setAAA(MI, CurOp++);
 
-    if (HasVEX_4V) {
-      unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
-      VEX_4V = ~VRegEnc & 0xf;
-      EVEX_V2 = ~(VRegEnc >> 4) & 1;
-    }
+    if (HasVEX_4V)
+      Prefix.set4VV2(MI, CurOp++);
 
-    unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg);
-    VEX_B = ~(BaseRegEnc >> 3) & 1;
-    unsigned IndexRegEnc =
-        getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg);
-    VEX_X = ~(IndexRegEnc >> 3) & 1;
+    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
     if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV.
-      EVEX_V2 = ~(IndexRegEnc >> 4) & 1;
+      Prefix.setV2(MI, MemOperand + X86::AddrIndexReg);
 
     break;
   }
   case X86II::MRMSrcMem4VOp3: {
     // Instruction format for 4VOp3:
     //   src1(ModR/M), MemAddr, src3(VEX_4V)
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_R = ~(RegEnc >> 3) & 1;
-
-    unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg);
-    VEX_B = ~(BaseRegEnc >> 3) & 1;
-    unsigned IndexRegEnc =
-        getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg);
-    VEX_X = ~(IndexRegEnc >> 3) & 1;
-
-    VEX_4V = ~getX86RegEncoding(MI, CurOp + X86::AddrNumOperands) & 0xf;
+    Prefix.setR(MI, CurOp++);
+    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
+    Prefix.set4V(MI, CurOp + X86::AddrNumOperands);
     break;
   }
   case X86II::MRMSrcMemOp4: {
     //  dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_R = ~(RegEnc >> 3) & 1;
-
-    unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_4V = ~VRegEnc & 0xf;
-
-    unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg);
-    VEX_B = ~(BaseRegEnc >> 3) & 1;
-    unsigned IndexRegEnc =
-        getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg);
-    VEX_X = ~(IndexRegEnc >> 3) & 1;
+    Prefix.setR(MI, CurOp++);
+    Prefix.set4V(MI, CurOp++);
+    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
     break;
   }
   case X86II::MRM0m:
@@ -927,22 +1027,16 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     // MRM[0-9]m instructions forms:
     //  MemAddr
     //  src1(VEX_4V), MemAddr
-    if (HasVEX_4V) {
-      unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
-      VEX_4V = ~VRegEnc & 0xf;
-      EVEX_V2 = ~(VRegEnc >> 4) & 1;
-    }
+    if (HasVEX_4V)
+      Prefix.set4VV2(MI, CurOp++);
 
     if (HasEVEX_K)
-      EVEX_aaa = getX86RegEncoding(MI, CurOp++);
+      Prefix.setAAA(MI, CurOp++);
 
-    unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg);
-    VEX_B = ~(BaseRegEnc >> 3) & 1;
-    unsigned IndexRegEnc =
-        getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg);
-    VEX_X = ~(IndexRegEnc >> 3) & 1;
+    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
     if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV.
-      EVEX_V2 = ~(IndexRegEnc >> 4) & 1;
+      Prefix.setV2(MI, MemOperand + X86::AddrIndexReg);
 
     break;
   }
@@ -954,25 +1048,21 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     //
     //  FMA4:
     //  dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_R = ~(RegEnc >> 3) & 1;
-    EVEX_R2 = ~(RegEnc >> 4) & 1;
+    Prefix.setRR2(MI, CurOp++);
 
     if (HasEVEX_K)
-      EVEX_aaa = getX86RegEncoding(MI, CurOp++);
+      Prefix.setAAA(MI, CurOp++);
 
-    if (HasVEX_4V) {
-      unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
-      VEX_4V = ~VRegEnc & 0xf;
-      EVEX_V2 = ~(VRegEnc >> 4) & 1;
-    }
+    if (HasVEX_4V)
+      Prefix.set4VV2(MI, CurOp++);
 
-    RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_B = ~(RegEnc >> 3) & 1;
-    VEX_X = ~(RegEnc >> 4) & 1;
+    Prefix.setB(MI, CurOp);
+    Prefix.setX(MI, CurOp, 4);
+    ++CurOp;
 
-    if (EVEX_b) {
+    if (TSFlags & X86II::EVEX_B) {
       if (HasEVEX_RC) {
+        unsigned NumOps = Desc.getNumOperands();
         unsigned RcOperand = NumOps - 1;
         assert(RcOperand >= CurOp);
         EVEX_rc = MI.getOperand(RcOperand).getImm();
@@ -985,29 +1075,21 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
   case X86II::MRMSrcReg4VOp3: {
     // Instruction format for 4VOp3:
     //   src1(ModR/M), src2(ModR/M), src3(VEX_4V)
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_R = ~(RegEnc >> 3) & 1;
-
-    RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_B = ~(RegEnc >> 3) & 1;
-
-    VEX_4V = ~getX86RegEncoding(MI, CurOp++) & 0xf;
+    Prefix.setR(MI, CurOp++);
+    Prefix.setB(MI, CurOp++);
+    Prefix.set4V(MI, CurOp++);
     break;
   }
   case X86II::MRMSrcRegOp4: {
     //  dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_R = ~(RegEnc >> 3) & 1;
-
-    unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_4V = ~VRegEnc & 0xf;
-
+    Prefix.setR(MI, CurOp++);
+    Prefix.set4V(MI, CurOp++);
     // Skip second register source (encoded in Imm[7:4])
     ++CurOp;
 
-    RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_B = ~(RegEnc >> 3) & 1;
-    VEX_X = ~(RegEnc >> 4) & 1;
+    Prefix.setB(MI, CurOp);
+    Prefix.setX(MI, CurOp, 4);
+    ++CurOp;
     break;
   }
   case X86II::MRMDestReg: {
@@ -1015,23 +1097,18 @@ void 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)
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_B = ~(RegEnc >> 3) & 1;
-    VEX_X = ~(RegEnc >> 4) & 1;
+    Prefix.setB(MI, CurOp);
+    Prefix.setX(MI, CurOp, 4);
+    ++CurOp;
 
     if (HasEVEX_K)
-      EVEX_aaa = getX86RegEncoding(MI, CurOp++);
+      Prefix.setAAA(MI, CurOp++);
 
-    if (HasVEX_4V) {
-      unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
-      VEX_4V = ~VRegEnc & 0xf;
-      EVEX_V2 = ~(VRegEnc >> 4) & 1;
-    }
+    if (HasVEX_4V)
+      Prefix.set4VV2(MI, CurOp++);
 
-    RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_R = ~(RegEnc >> 3) & 1;
-    EVEX_R2 = ~(RegEnc >> 4) & 1;
-    if (EVEX_b)
+    Prefix.setRR2(MI, CurOp++);
+    if (TSFlags & X86II::EVEX_B)
       EncodeRC = true;
     break;
   }
@@ -1039,9 +1116,7 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
     // MRMr0 instructions forms:
     //  11:rrr:000
     //  dst(ModR/M)
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_R = ~(RegEnc >> 3) & 1;
-    EVEX_R2 = ~(RegEnc >> 4) & 1;
+    Prefix.setRR2(MI, CurOp++);
     break;
   }
   case X86II::MRM0r:
@@ -1054,75 +1129,25 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
   case X86II::MRM7r: {
     // MRM0r-MRM7r instructions forms:
     //  dst(VEX_4V), src(ModR/M), imm8
-    if (HasVEX_4V) {
-      unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
-      VEX_4V = ~VRegEnc & 0xf;
-      EVEX_V2 = ~(VRegEnc >> 4) & 1;
-    }
+    if (HasVEX_4V)
+      Prefix.set4VV2(MI, CurOp++);
+
     if (HasEVEX_K)
-      EVEX_aaa = getX86RegEncoding(MI, CurOp++);
+      Prefix.setAAA(MI, CurOp++);
 
-    unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
-    VEX_B = ~(RegEnc >> 3) & 1;
-    VEX_X = ~(RegEnc >> 4) & 1;
+    Prefix.setB(MI, CurOp);
+    Prefix.setX(MI, CurOp, 4);
+    ++CurOp;
     break;
   }
   }
-
-  if (Encoding == X86II::VEX || Encoding == X86II::XOP) {
-    // VEX opcode prefix can have 2 or 3 bytes
-    //
-    //  3 bytes:
-    //    +-----+ +--------------+ +-------------------+
-    //    | C4h | | RXB | m-mmmm | | W | vvvv | L | pp |
-    //    +-----+ +--------------+ +-------------------+
-    //  2 bytes:
-    //    +-----+ +-------------------+
-    //    | C5h | | R | vvvv | L | pp |
-    //    +-----+ +-------------------+
-    //
-    //  XOP uses a similar prefix:
-    //    +-----+ +--------------+ +-------------------+
-    //    | 8Fh | | RXB | m-mmmm | | W | vvvv | L | pp |
-    //    +-----+ +--------------+ +-------------------+
-    uint8_t LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3);
-
-    // Can we use the 2 byte VEX prefix?
-    if (!(MI.getFlags() & X86::IP_USE_VEX3) && Encoding == X86II::VEX &&
-        VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) {
-      emitByte(0xC5, OS);
-      emitByte(LastByte | (VEX_R << 7), OS);
-      return;
-    }
-
-    // 3 byte VEX prefix
-    emitByte(Encoding == X86II::XOP ? 0x8F : 0xC4, OS);
-    emitByte(VEX_R << 7 | VEX_X << 6 | VEX_B << 5 | VEX_5M, OS);
-    emitByte(LastByte | (VEX_W << 7), OS);
-  } else {
-    assert(Encoding == X86II::EVEX && "unknown encoding!");
-    // EVEX opcode prefix can have 4 bytes
-    //
-    // +-----+ +--------------+ +-------------------+ +------------------------+
-    // | 62h | | RXBR' | 0mmm | | W | vvvv | U | pp | | z | L'L | b | v' | aaa |
-    // +-----+ +--------------+ +-------------------+ +------------------------+
-    assert((VEX_5M & 0x7) == VEX_5M &&
-           "More than 3 significant bits in VEX.m-mmmm fields for EVEX!");
-
-    emitByte(0x62, OS);
-    emitByte((VEX_R << 7) | (VEX_X << 6) | (VEX_B << 5) | (EVEX_R2 << 4) |
-                 VEX_5M,
-             OS);
-    emitByte((VEX_W << 7) | (VEX_4V << 3) | (EVEX_U << 2) | VEX_PP, OS);
-    if (EncodeRC)
-      emitByte((EVEX_z << 7) | (EVEX_rc << 5) | (EVEX_b << 4) | (EVEX_V2 << 3) |
-                   EVEX_aaa,
-               OS);
-    else
-      emitByte((EVEX_z << 7) | (EVEX_L2 << 6) | (VEX_L << 5) | (EVEX_b << 4) |
-                   (EVEX_V2 << 3) | EVEX_aaa,
-               OS);
+  if (EncodeRC) {
+    Prefix.setL(EVEX_rc & 0x1);
+    Prefix.setL2(EVEX_rc & 0x2);
   }
+  PrefixKind Kind = Prefix.determineOptimalKind();
+  Prefix.emit(OS);
+  return Kind;
 }
 
 /// Emit REX prefix which specifies
@@ -1130,120 +1155,109 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
 ///   2) non-default operand size, and
 ///   3) use of X86-64 extended registers.
 ///
-/// \returns true if REX prefix is used, otherwise returns false.
-bool X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
-                                     const MCSubtargetInfo &STI,
-                                     raw_ostream &OS) const {
-  uint8_t REX = [&, MemOperand]() {
-    uint8_t REX = 0;
-    bool UsesHighByteReg = false;
-
-    const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
-    uint64_t TSFlags = Desc.TSFlags;
-
-    if (TSFlags & X86II::REX_W)
-      REX |= 1 << 3; // set REX.W
-
-    if (MI.getNumOperands() == 0)
-      return REX;
-
-    unsigned NumOps = MI.getNumOperands();
-    unsigned CurOp = X86II::getOperandBias(Desc);
-
-    // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix.
-    for (unsigned i = CurOp; i != NumOps; ++i) {
-      const MCOperand &MO = MI.getOperand(i);
-      if (MO.isReg()) {
-        unsigned Reg = MO.getReg();
-        if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH ||
-            Reg == X86::DH)
-          UsesHighByteReg = true;
-        if (X86II::isX86_64NonExtLowByteReg(Reg))
-          // FIXME: The caller of determineREXPrefix slaps this prefix onto
-          // anything that returns non-zero.
-          REX |= 0x40; // REX fixed encoding prefix
-      } else if (MO.isExpr() && STI.getTargetTriple().isX32()) {
-        // GOTTPOFF and TLSDESC relocations require a REX prefix to allow
-        // linker optimizations: even if the instructions we see may not require
-        // any prefix, they may be replaced by instructions that do. This is
-        // handled as a special case here so that it also works for hand-written
-        // assembly without the user needing to write REX, as with GNU as.
-        const auto *Ref = dyn_cast<MCSymbolRefExpr>(MO.getExpr());
-        if (Ref && (Ref->getKind() == MCSymbolRefExpr::VK_GOTTPOFF ||
-                    Ref->getKind() == MCSymbolRefExpr::VK_TLSDESC)) {
-          REX |= 0x40; // REX fixed encoding prefix
-        }
+/// \returns the used prefix (REX or None).
+PrefixKind X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
+                                           const MCSubtargetInfo &STI,
+                                           raw_ostream &OS) const {
+  if (!STI.hasFeature(X86::Is64Bit))
+    return None;
+  X86OpcodePrefixHelper Prefix(*Ctx.getRegisterInfo());
+  bool UsesHighByteReg = false;
+  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
+  uint64_t TSFlags = Desc.TSFlags;
+  Prefix.setW(TSFlags & X86II::REX_W);
+  unsigned NumOps = MI.getNumOperands();
+  if (!NumOps) {
+    PrefixKind Kind = Prefix.determineOptimalKind();
+    Prefix.emit(OS);
+    return Kind;
+  }
+  unsigned CurOp = X86II::getOperandBias(Desc);
+  for (unsigned i = CurOp; i != NumOps; ++i) {
+    const MCOperand &MO = MI.getOperand(i);
+    if (MO.isReg()) {
+      unsigned Reg = MO.getReg();
+      if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH)
+        UsesHighByteReg = true;
+      // If it accesses SPL, BPL, SIL, or DIL, then it requires a REX prefix.
+      if (X86II::isX86_64NonExtLowByteReg(Reg))
+        Prefix.setLowerBound(REX);
+    } else if (MO.isExpr() && STI.getTargetTriple().isX32()) {
+      // GOTTPOFF and TLSDESC relocations require a REX prefix to allow
+      // linker optimizations: even if the instructions we see may not require
+      // any prefix, they may be replaced by instructions that do. This is
+      // handled as a special case here so that it also works for hand-written
+      // assembly without the user needing to write REX, as with GNU as.
+      const auto *Ref = dyn_cast<MCSymbolRefExpr>(MO.getExpr());
+      if (Ref && (Ref->getKind() == MCSymbolRefExpr::VK_GOTTPOFF ||
+                  Ref->getKind() == MCSymbolRefExpr::VK_TLSDESC)) {
+        Prefix.setLowerBound(REX);
       }
     }
-
-    switch (TSFlags & X86II::FormMask) {
-    case X86II::AddRegFrm:
-      REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B
-      break;
-    case X86II::MRMSrcReg:
-    case X86II::MRMSrcRegCC:
-      REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R
-      REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B
-      break;
-    case X86II::MRMSrcMem:
-    case X86II::MRMSrcMemCC:
-      REX |= isREXExtendedReg(MI, CurOp++) << 2;                        // REX.R
-      REX |= isREXExtendedReg(MI, MemOperand + X86::AddrBaseReg) << 0;  // REX.B
-      REX |= isREXExtendedReg(MI, MemOperand + X86::AddrIndexReg) << 1; // REX.X
-      CurOp += X86::AddrNumOperands;
-      break;
-    case X86II::MRMDestReg:
-      REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B
-      REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R
-      break;
-    case X86II::MRMDestMem:
-      REX |= isREXExtendedReg(MI, MemOperand + X86::AddrBaseReg) << 0;  // REX.B
-      REX |= isREXExtendedReg(MI, MemOperand + X86::AddrIndexReg) << 1; // REX.X
-      CurOp += X86::AddrNumOperands;
-      REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R
-      break;
-    case X86II::MRMXmCC:
-    case X86II::MRMXm:
-    case X86II::MRM0m:
-    case X86II::MRM1m:
-    case X86II::MRM2m:
-    case X86II::MRM3m:
-    case X86II::MRM4m:
-    case X86II::MRM5m:
-    case X86II::MRM6m:
-    case X86II::MRM7m:
-      REX |= isREXExtendedReg(MI, MemOperand + X86::AddrBaseReg) << 0;  // REX.B
-      REX |= isREXExtendedReg(MI, MemOperand + X86::AddrIndexReg) << 1; // REX.X
-      break;
-    case X86II::MRMXrCC:
-    case X86II::MRMXr:
-    case X86II::MRM0r:
-    case X86II::MRM1r:
-    case X86II::MRM2r:
-    case X86II::MRM3r:
-    case X86II::MRM4r:
-    case X86II::MRM5r:
-    case X86II::MRM6r:
-    case X86II::MRM7r:
-      REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B
-      break;
-    case X86II::MRMr0:
-      REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R
-      break;
-    case X86II::MRMDestMemFSIB:
-      llvm_unreachable("FSIB format never need REX prefix!");
-    }
-    if (REX && UsesHighByteReg)
-      report_fatal_error(
-          "Cannot encode high byte register in REX-prefixed instruction");
-    return REX;
-  }();
-
-  if (!REX)
-    return false;
-
-  emitByte(0x40 | REX, OS);
-  return true;
+  }
+  switch (TSFlags & X86II::FormMask) {
+  case X86II::AddRegFrm:
+    Prefix.setB(MI, CurOp++);
+    break;
+  case X86II::MRMSrcReg:
+  case X86II::MRMSrcRegCC:
+    Prefix.setR(MI, CurOp++);
+    Prefix.setB(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);
+    CurOp += X86::AddrNumOperands;
+    break;
+  case X86II::MRMDestReg:
+    Prefix.setB(MI, CurOp++);
+    Prefix.setR(MI, CurOp++);
+    break;
+  case X86II::MRMDestMem:
+    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
+    CurOp += X86::AddrNumOperands;
+    Prefix.setR(MI, CurOp++);
+    break;
+  case X86II::MRMXmCC:
+  case X86II::MRMXm:
+  case X86II::MRM0m:
+  case X86II::MRM1m:
+  case X86II::MRM2m:
+  case X86II::MRM3m:
+  case X86II::MRM4m:
+  case X86II::MRM5m:
+  case X86II::MRM6m:
+  case X86II::MRM7m:
+    Prefix.setB(MI, MemOperand + X86::AddrBaseReg);
+    Prefix.setX(MI, MemOperand + X86::AddrIndexReg);
+    break;
+  case X86II::MRMXrCC:
+  case X86II::MRMXr:
+  case X86II::MRM0r:
+  case X86II::MRM1r:
+  case X86II::MRM2r:
+  case X86II::MRM3r:
+  case X86II::MRM4r:
+  case X86II::MRM5r:
+  case X86II::MRM6r:
+  case X86II::MRM7r:
+    Prefix.setB(MI, CurOp++);
+    break;
+  case X86II::MRMr0:
+    Prefix.setR(MI, CurOp++);
+    break;
+  case X86II::MRMDestMemFSIB:
+    llvm_unreachable("FSIB format never need REX prefix!");
+  }
+  PrefixKind Kind = Prefix.determineOptimalKind();
+  if (Kind && UsesHighByteReg)
+    report_fatal_error(
+        "Cannot encode high byte register in REX-prefixed instruction");
+  Prefix.emit(OS);
+  return Kind;
 }
 
 /// Emit segment override opcode prefix as needed.
@@ -1260,8 +1274,8 @@ void X86MCCodeEmitter::emitSegmentOverridePrefix(unsigned SegOperand,
 /// \param MemOperand the operand # of the start of a memory operand if present.
 /// If not present, it is -1.
 ///
-/// \returns true if REX prefix is used, otherwise returns false.
-bool X86MCCodeEmitter::emitOpcodePrefix(int MemOperand, const MCInst &MI,
+/// \returns the used prefix (REX or None).
+PrefixKind X86MCCodeEmitter::emitOpcodePrefix(int MemOperand, const MCInst &MI,
                                         const MCSubtargetInfo &STI,
                                         raw_ostream &OS) const {
   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
@@ -1295,9 +1309,7 @@ bool X86MCCodeEmitter::emitOpcodePrefix(int MemOperand, const MCInst &MI,
   // Handle REX prefix.
   assert((STI.hasFeature(X86::Is64Bit) || !(TSFlags & X86II::REX_W)) &&
          "REX.W requires 64bit mode.");
-  bool HasREX = STI.hasFeature(X86::Is64Bit)
-                    ? emitREXPrefix(MemOperand, MI, STI, OS)
-                    : false;
+  PrefixKind Kind = emitREXPrefix(MemOperand, MI, STI, OS);
 
   // 0x0F escape code must be emitted just before the opcode.
   switch (TSFlags & X86II::OpMapMask) {
@@ -1318,7 +1330,7 @@ bool X86MCCodeEmitter::emitOpcodePrefix(int MemOperand, const MCInst &MI,
     break;
   }
 
-  return HasREX;
+  return Kind;
 }
 
 void X86MCCodeEmitter::emitPrefix(const MCInst &MI, raw_ostream &OS,
@@ -1352,7 +1364,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
 
   uint64_t StartByte = OS.tell();
 
-  bool HasREX = emitPrefixImpl(CurOp, MI, STI, OS);
+  PrefixKind Kind = emitPrefixImpl(CurOp, MI, STI, OS);
 
   // It uses the VEX.VVVV field?
   bool HasVEX_4V = TSFlags & X86II::VEX_4V;
@@ -1451,7 +1463,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     emitByte(BaseOpcode + CC, OS);
     unsigned SrcRegNum = CurOp + X86::AddrNumOperands;
     emitMemModRMByte(MI, CurOp + 1, getX86RegNum(MI.getOperand(0)), TSFlags,
-                    HasREX, StartByte, OS, Fixups, STI, false);
+                     Kind, StartByte, OS, Fixups, STI, false);
     CurOp = SrcRegNum + 3; // skip reg, VEX_V4 and CC
     break;
   }
@@ -1468,7 +1480,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
 
     bool ForceSIB = (Form == X86II::MRMDestMemFSIB);
     emitMemModRMByte(MI, CurOp, getX86RegNum(MI.getOperand(SrcRegNum)), TSFlags,
-                     HasREX, StartByte, OS, Fixups, STI, ForceSIB);
+                     Kind, StartByte, OS, Fixups, STI, ForceSIB);
     CurOp = SrcRegNum + 1;
     break;
   }
@@ -1543,7 +1555,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
 
     bool ForceSIB = (Form == X86II::MRMSrcMemFSIB);
     emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)),
-                     TSFlags, HasREX, StartByte, OS, Fixups, STI, ForceSIB);
+                     TSFlags, Kind, StartByte, OS, Fixups, STI, ForceSIB);
     CurOp = FirstMemOp + X86::AddrNumOperands;
     if (HasVEX_I8Reg)
       I8RegNum = getX86RegEncoding(MI, CurOp++);
@@ -1555,7 +1567,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     emitByte(BaseOpcode, OS);
 
     emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)),
-                     TSFlags, HasREX, StartByte, OS, Fixups, STI);
+                     TSFlags, Kind, StartByte, OS, Fixups, STI);
     CurOp = FirstMemOp + X86::AddrNumOperands;
     ++CurOp; // Encoded in VEX.VVVV.
     break;
@@ -1572,7 +1584,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     emitByte(BaseOpcode, OS);
 
     emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)),
-                     TSFlags, HasREX, StartByte, OS, Fixups, STI);
+                     TSFlags, Kind, StartByte, OS, Fixups, STI);
     CurOp = FirstMemOp + X86::AddrNumOperands;
     break;
   }
@@ -1585,7 +1597,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     emitByte(BaseOpcode + CC, OS);
 
     emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(RegOp)),
-                     TSFlags, HasREX, StartByte, OS, Fixups, STI);
+                     TSFlags, Kind, StartByte, OS, Fixups, STI);
     break;
   }
 
@@ -1627,7 +1639,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     unsigned CC = MI.getOperand(CurOp++).getImm();
     emitByte(BaseOpcode + CC, OS);
 
-    emitMemModRMByte(MI, FirstMemOp, 0, TSFlags, HasREX, StartByte, OS, Fixups,
+    emitMemModRMByte(MI, FirstMemOp, 0, TSFlags, Kind, StartByte, OS, Fixups,
                      STI);
     break;
   }
@@ -1648,7 +1660,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     emitByte(BaseOpcode, OS);
     emitMemModRMByte(MI, CurOp,
                      (Form == X86II::MRMXm) ? 0 : Form - X86II::MRM0m, TSFlags,
-                     HasREX, StartByte, OS, Fixups, STI);
+                     Kind, StartByte, OS, Fixups, STI);
     CurOp += X86::AddrNumOperands;
     break;
 


        


More information about the llvm-commits mailing list