[X86] AVX512: Add disassembler support for compressed displacement
authorAdam Nemet <anemet@apple.com>
Thu, 17 Jul 2014 17:04:56 +0000 (17:04 +0000)
committerAdam Nemet <anemet@apple.com>
Thu, 17 Jul 2014 17:04:56 +0000 (17:04 +0000)
There are two parts here.  First is to modify tablegen to adjust the encoding
type ENCODING_RM with the scaling factor.

The second is to use the new encoding types to compute the correct
displacement in the decoder.

Fixes <rdar://problem/17608489>

llvm-svn: 213281

llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h
llvm/test/MC/Disassembler/X86/avx-512.txt
llvm/utils/TableGen/X86RecognizableInstr.cpp
llvm/utils/TableGen/X86RecognizableInstr.h

index c366725..521bd21 100644 (file)
@@ -717,7 +717,7 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,
     return false;
   case ENCODING_WRITEMASK:
     return translateMaskRegister(mcInst, insn.writemask);
-  case ENCODING_RM:
+  CASE_ENCODING_RM:
     return translateRM(mcInst, operand, insn, Dis);
   case ENCODING_CB:
   case ENCODING_CW:
index 55587d4..ab3d1f7 100644 (file)
@@ -1488,7 +1488,7 @@ static int fixupReg(struct InternalInstruction *insn,
     if (!valid)
       return -1;
     break;
-  case ENCODING_RM:
+  CASE_ENCODING_RM:
     if (insn->eaBase >= insn->eaRegBase) {
       insn->eaBase = (EABase)fixupRMValue(insn,
                                           (OperandType)op->type,
@@ -1681,11 +1681,14 @@ static int readOperands(struct InternalInstruction* insn) {
     case ENCODING_DI:
       break;
     case ENCODING_REG:
-    case ENCODING_RM:
+    CASE_ENCODING_RM:
       if (readModRM(insn))
         return -1;
       if (fixupReg(insn, &Op))
         return -1;
+      // Apply the AVX512 compressed displacement scaling factor.
+      if (Op.encoding != ENCODING_REG && insn->eaDisplacement == EA_DISP_8)
+        insn->displacement *= 1 << (Op.encoding - ENCODING_RM);
       break;
     case ENCODING_CB:
     case ENCODING_CW:
index f59e0b6..4baaf1e 100644 (file)
@@ -325,11 +325,26 @@ enum ModRMDecisionType {
 };
 #undef ENUM_ENTRY
 
+#define CASE_ENCODING_RM     \
+    case ENCODING_RM:        \
+    case ENCODING_RM_CD2:    \
+    case ENCODING_RM_CD4:    \
+    case ENCODING_RM_CD8:    \
+    case ENCODING_RM_CD16:   \
+    case ENCODING_RM_CD32:   \
+    case ENCODING_RM_CD64
+
 // Physical encodings of instruction operands.
 #define ENCODINGS                                                              \
   ENUM_ENTRY(ENCODING_NONE,   "")                                              \
   ENUM_ENTRY(ENCODING_REG,    "Register operand in ModR/M byte.")              \
   ENUM_ENTRY(ENCODING_RM,     "R/M operand in ModR/M byte.")                   \
+  ENUM_ENTRY(ENCODING_RM_CD2, "R/M operand with CDisp scaling of 2")           \
+  ENUM_ENTRY(ENCODING_RM_CD4, "R/M operand with CDisp scaling of 4")           \
+  ENUM_ENTRY(ENCODING_RM_CD8, "R/M operand with CDisp scaling of 8")           \
+  ENUM_ENTRY(ENCODING_RM_CD16,"R/M operand with CDisp scaling of 16")          \
+  ENUM_ENTRY(ENCODING_RM_CD32,"R/M operand with CDisp scaling of 32")          \
+  ENUM_ENTRY(ENCODING_RM_CD64,"R/M operand with CDisp scaling of 64")          \
   ENUM_ENTRY(ENCODING_VVVV,   "Register operand in VEX.vvvv byte.")            \
   ENUM_ENTRY(ENCODING_WRITEMASK, "Register operand in EVEX.aaa byte.")         \
   ENUM_ENTRY(ENCODING_CB,     "1-byte code offset (possible new CS value)")    \
index b1a8aaf..f78db55 100644 (file)
 
 # CHECK: kmovw   %k5, %k1
 0xc5 0xf8 0x90 0xcd
+
+#####################################################
+#             COMPRESSED DISPLACEMENT               #
+#####################################################
+
+# TupleType = FVM
+# CHECK: vmovdqu32 %zmm0, -448(%rcx)
+0x62 0xf1 0x7e 0x48 0x7f 0x41 0xf9
+
+# TupleType = T1S, 64-bit eltsize
+# CHECK: vaddsd 256(%rdx), %xmm0, %xmm16
+0x62 0xe1 0xff 0x08 0x58 0x42 0x20
+
+# TupleType = T1S, 32-bit eltsize
+# CHECK: vaddss 256(%rdx), %xmm0, %xmm16
+0x62 0xe1 0x7e 0x08 0x58 0x42 0x40
+
+# TupleType = FV
+# CHECK: vaddpd 256(%rdx), %zmm0, %zmm16
+0x62 0xe1 0xfd 0x48 0x58 0x42 0x04
+
+# TupleType = FV, broadcast, 64-bit eltsize
+# CHECK: vaddpd 256(%rdx){1to8}, %zmm0, %zmm16
+0x62 0xe1 0xfd 0x58 0x58 0x42 0x20
+
+# TupleType = FV, broadcast, 32-bit eltsize
+# CHECK: vaddps 256(%rdx){1to16}, %zmm0, %zmm16
+0x62 0xe1 0x7c 0x58 0x58 0x42 0x40
+
+# TupleType = T4
+# CHECK: vbroadcasti32x4 256(%rdx), %zmm16
+0x62 0xe2 0x7d 0x48 0x5a 0x42 0x10
+
+# Cases where we can't use cdisp8
+# CHECK: vaddss 255(%rdx), %xmm0, %xmm16
+0x62 0xe1 0x7e 0x08 0x58 0x82 0xff 0x00 0x00 0x00
+
+# CHECK: vaddss 1024(%rdx), %xmm0, %xmm16
+0x62 0xe1 0x7e 0x08 0x58 0x82 0x00 0x04 0x00 0x00
index ead419e..4137a57 100644 (file)
@@ -205,6 +205,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
   HasEVEX_B        = Rec->getValueAsBit("hasEVEX_B");
   IsCodeGenOnly    = Rec->getValueAsBit("isCodeGenOnly");
   ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
+  CD8_Scale        = byteFromRec(Rec, "CD8_Scale");
 
   Name      = Rec->getName();
   AsmString = Rec->getValueAsString("AsmString");
@@ -441,6 +442,16 @@ InstructionContext RecognizableInstr::insnContext() const {
   return insnContext;
 }
 
+void RecognizableInstr::adjustOperandEncoding(OperandEncoding &encoding) {
+  // The scaling factor for AVX512 compressed displacement encoding is an
+  // instruction attribute.  Adjust the ModRM encoding type to include the
+  // scale for compressed displacement.
+  if (encoding != ENCODING_RM || CD8_Scale == 0)
+    return;
+  encoding = (OperandEncoding)(encoding + Log2_32(CD8_Scale));
+  assert(encoding <= ENCODING_RM_CD64 && "Invalid CDisp scaling");
+}
+
 void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
                                       unsigned &physicalOperandIndex,
                                       unsigned &numPhysicalOperands,
@@ -464,8 +475,10 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
 
   const std::string &typeName = (*Operands)[operandIndex].Rec->getName();
 
-  Spec->operands[operandIndex].encoding = encodingFromString(typeName,
-                                                              OpSize);
+  OperandEncoding encoding = encodingFromString(typeName, OpSize);
+  // Adjust the encoding type for an operand based on the instruction.
+  adjustOperandEncoding(encoding);
+  Spec->operands[operandIndex].encoding = encoding;
   Spec->operands[operandIndex].type = typeFromString(typeName,
                                                      HasREX_WPrefix, OpSize);
 
index 77286bc..4bc52eb 100644 (file)
@@ -78,6 +78,8 @@ private:
   bool IsCodeGenOnly;
   /// The ForceDisassemble field from the record
   bool ForceDisassemble;
+  // The CD8_Scale field from the record
+  uint8_t CD8_Scale;
   // Whether the instruction has the predicate "In64BitMode"
   bool Is64Bit;
   // Whether the instruction has the predicate "In32BitMode"
@@ -153,6 +155,9 @@ private:
   static OperandEncoding writemaskRegisterEncodingFromString(const std::string &s,
                                                              uint8_t OpSize);
 
+  /// \brief Adjust the encoding type for an operand based on the instruction.
+  void adjustOperandEncoding(OperandEncoding &encoding);
+
   /// handleOperand - Converts a single operand from the LLVM table format to
   ///   the emitted table format, handling any duplicate operands it encounters
   ///   and then one non-duplicate.