[llvm-commits] [llvm] r135524 - in /llvm/trunk: include/llvm/Target/Target.td lib/Target/ARM/ARMInstrFormats.td utils/TableGen/FixedLenDecoderEmitter.cpp utils/TableGen/FixedLenDecoderEmitter.h

Owen Anderson resistor at mac.com
Tue Jul 19 14:06:00 PDT 2011


Author: resistor
Date: Tue Jul 19 16:06:00 2011
New Revision: 135524

URL: http://llvm.org/viewvc/llvm-project?rev=135524&view=rev
Log:
Enhance the FixedLengthDecoder to be able to generate plausible-looking decoders for ARM.

Modified:
    llvm/trunk/include/llvm/Target/Target.td
    llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
    llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp
    llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.h

Modified: llvm/trunk/include/llvm/Target/Target.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=135524&r1=135523&r2=135524&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/Target.td (original)
+++ llvm/trunk/include/llvm/Target/Target.td Tue Jul 19 16:06:00 2011
@@ -297,6 +297,10 @@
   // from the opcode.
   int Size = 0;
 
+  // DecoderNamespace - The "namespace" in which this instruction exists, on
+  // targets like ARM which multiple ISA namespaces exist.
+  string DecoderNamespace = "";
+
   // Code size, for instruction selection.
   // FIXME: What does this actually mean?
   int CodeSize = 0;

Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=135524&r1=135523&r2=135524&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Tue Jul 19 16:06:00 2011
@@ -262,13 +262,17 @@
 
 class InstARM<AddrMode am, int sz, IndexMode im,
               Format f, Domain d, string cstr, InstrItinClass itin>
-  : InstTemplate<am, sz, im, f, d, cstr, itin>, Encoding;
+  : InstTemplate<am, sz, im, f, d, cstr, itin>, Encoding {
+  let DecoderNamespace = "ARM";
+}
 
 // This Encoding-less class is used by Thumb1 to specify the encoding bits later
 // on by adding flavors to specific instructions.
 class InstThumb<AddrMode am, int sz, IndexMode im,
                 Format f, Domain d, string cstr, InstrItinClass itin>
-  : InstTemplate<am, sz, im, f, d, cstr, itin>;
+  : InstTemplate<am, sz, im, f, d, cstr, itin> {
+  let DecoderNamespace = "Thumb";
+}
 
 class PseudoInst<dag oops, dag iops, InstrItinClass itin, list<dag> pattern>
   : InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo,
@@ -1071,6 +1075,7 @@
   let AsmString = !strconcat(opc, "${p}", asm);
   let Pattern = pattern;
   list<Predicate> Predicates = [IsThumb2];
+  let DecoderNamespace = "Thumb2";
 }
 
 // Same as Thumb2I except it can optionally modify CPSR. Note it's modeled as an
@@ -1091,6 +1096,7 @@
   let AsmString = !strconcat(opc, "${s}${p}", asm);
   let Pattern = pattern;
   list<Predicate> Predicates = [IsThumb2];
+  let DecoderNamespace = "Thumb2";
 }
 
 // Special cases
@@ -1103,6 +1109,7 @@
   let AsmString = asm;
   let Pattern = pattern;
   list<Predicate> Predicates = [IsThumb2];
+  let DecoderNamespace = "Thumb2";
 }
 
 class ThumbXI<dag oops, dag iops, AddrMode am, int sz,
@@ -1114,6 +1121,7 @@
   let AsmString = asm;
   let Pattern = pattern;
   list<Predicate> Predicates = [IsThumb, IsThumb1Only];
+  let DecoderNamespace = "Thumb";
 }
 
 class T2I<dag oops, dag iops, InstrItinClass itin,
@@ -1183,6 +1191,7 @@
   let AsmString = !strconcat(opc, "${p}", asm);
   let Pattern = pattern;
   list<Predicate> Predicates = [IsThumb2];
+  let DecoderNamespace = "Thumb2";
   let Inst{31-27} = 0b11111;
   let Inst{26-25} = 0b00;
   let Inst{24}    = signed;

Modified: llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp?rev=135524&r1=135523&r2=135524&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp Tue Jul 19 16:06:00 2011
@@ -84,11 +84,8 @@
 // Forward declaration.
 class FilterChooser;
 
-// FIXME: Possibly auto-detected?
-#define BIT_WIDTH 32
-
 // Representation of the instruction to work on.
-typedef bit_value_t insn_t[BIT_WIDTH];
+typedef std::vector<bit_value_t> insn_t;
 
 /// Filter - Filter works with FilterChooser to produce the decoding tree for
 /// the ISA.
@@ -230,7 +227,7 @@
 
   // Array of bit values passed down from our parent.
   // Set to all BIT_UNFILTERED's for Parent == NULL.
-  bit_value_t FilterBitValues[BIT_WIDTH];
+  std::vector<bit_value_t> FilterBitValues;
 
   // Links to the FilterChooser above us in the decoding tree.
   FilterChooser *Parent;
@@ -238,21 +235,24 @@
   // Index of the best filter from Filters.
   int BestIndex;
 
+  // Width of instructions
+  unsigned BitWidth;
+
 public:
   FilterChooser(const FilterChooser &FC) :
     AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
-      Operands(FC.Operands), Filters(FC.Filters), Parent(FC.Parent),
-      BestIndex(FC.BestIndex) {
-    memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues));
-  }
+      Operands(FC.Operands), Filters(FC.Filters),
+      FilterBitValues(FC.FilterBitValues), Parent(FC.Parent),
+      BestIndex(FC.BestIndex), BitWidth(FC.BitWidth) { }
 
   FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
                 const std::vector<unsigned> &IDs,
-    std::map<unsigned, std::vector<OperandInfo> > &Ops) :
+    std::map<unsigned, std::vector<OperandInfo> > &Ops,
+                unsigned BW) :
       AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(),
-      Parent(NULL), BestIndex(-1) {
-    for (unsigned i = 0; i < BIT_WIDTH; ++i)
-      FilterBitValues[i] = BIT_UNFILTERED;
+      Parent(NULL), BestIndex(-1), BitWidth(BW) {
+    for (unsigned i = 0; i < BitWidth; ++i)
+      FilterBitValues.push_back(BIT_UNFILTERED);
 
     doFilter();
   }
@@ -260,13 +260,11 @@
   FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
                 const std::vector<unsigned> &IDs,
         std::map<unsigned, std::vector<OperandInfo> > &Ops,
-                bit_value_t (&ParentFilterBitValues)[BIT_WIDTH],
+                std::vector<bit_value_t> &ParentFilterBitValues,
                 FilterChooser &parent) :
       AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
-      Filters(), Parent(&parent), BestIndex(-1) {
-    for (unsigned i = 0; i < BIT_WIDTH; ++i)
-      FilterBitValues[i] = ParentFilterBitValues[i];
-
+      Filters(), FilterBitValues(ParentFilterBitValues),
+      Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth) {
     doFilter();
   }
 
@@ -274,15 +272,15 @@
   bool isTopLevel() { return Parent == NULL; }
 
   // Emit the top level typedef and decodeInstruction() function.
-  void emitTop(raw_ostream &o, unsigned Indentation);
+  void emitTop(raw_ostream &o, unsigned Indentation, std::string Namespace);
 
 protected:
   // Populates the insn given the uid.
   void insnWithID(insn_t &Insn, unsigned Opcode) const {
     BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");
 
-    for (unsigned i = 0; i < BIT_WIDTH; ++i)
-      Insn[i] = bitFromBits(Bits, i);
+    for (unsigned i = 0; i < BitWidth; ++i)
+      Insn.push_back(bitFromBits(Bits, i));
   }
 
   // Returns the record name.
@@ -300,7 +298,7 @@
 
   /// dumpFilterArray - dumpFilterArray prints out debugging info for the given
   /// filter array as a series of chars.
-  void dumpFilterArray(raw_ostream &o, bit_value_t (&filter)[BIT_WIDTH]);
+  void dumpFilterArray(raw_ostream &o, std::vector<bit_value_t> & filter);
 
   /// dumpStack - dumpStack traverses the filter chooser chain and calls
   /// dumpFilterArray on each filter chooser up to the top level one.
@@ -375,7 +373,7 @@
 Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
     bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits),
                   Mixed(mixed) {
-  assert(StartBit + NumBits - 1 < BIT_WIDTH);
+  assert(StartBit + NumBits - 1 < Owner->BitWidth);
 
   NumFiltered = 0;
   LastOpcFiltered = 0;
@@ -427,9 +425,8 @@
 void Filter::recurse() {
   std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;
 
-  bit_value_t BitValueArray[BIT_WIDTH];
   // Starts by inheriting our parent filter chooser's filter bit values.
-  memcpy(BitValueArray, Owner->FilterBitValues, sizeof(BitValueArray));
+  std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues);
 
   unsigned bitIndex;
 
@@ -493,8 +490,9 @@
 
   o << StartBit << "} ...\n";
 
-  o.indent(Indentation) << "switch (fieldFromInstruction(insn, "
-                        << StartBit << ", " << NumBits << ")) {\n";
+  o.indent(Indentation) << "switch (fieldFromInstruction" << Owner->BitWidth
+                        << "(insn, " << StartBit << ", "
+                        << NumBits << ")) {\n";
 
   std::map<unsigned, FilterChooser*>::iterator filterIterator;
 
@@ -559,60 +557,12 @@
 //////////////////////////////////
 
 // Emit the top level typedef and decodeInstruction() function.
-void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation) {
-  switch (BIT_WIDTH) {
-  case 8:
-    o.indent(Indentation) << "typedef uint8_t field_t;\n";
-    break;
-  case 16:
-    o.indent(Indentation) << "typedef uint16_t field_t;\n";
-    break;
-  case 32:
-    o.indent(Indentation) << "typedef uint32_t field_t;\n";
-    break;
-  case 64:
-    o.indent(Indentation) << "typedef uint64_t field_t;\n";
-    break;
-  default:
-    assert(0 && "Unexpected instruction size!");
-  }
-
-  o << '\n';
-
-  o.indent(Indentation) << "static field_t " <<
-    "fieldFromInstruction(field_t insn, unsigned startBit, unsigned numBits)\n";
-
-  o.indent(Indentation) << "{\n";
-
-  ++Indentation; ++Indentation;
-  o.indent(Indentation) << "assert(startBit + numBits <= " << BIT_WIDTH
-                        << " && \"Instruction field out of bounds!\");\n";
-  o << '\n';
-  o.indent(Indentation) << "field_t fieldMask;\n";
-  o << '\n';
-  o.indent(Indentation) << "if (numBits == " << BIT_WIDTH << ")\n";
-
-  ++Indentation; ++Indentation;
-  o.indent(Indentation) << "fieldMask = (field_t)-1;\n";
-  --Indentation; --Indentation;
-
-  o.indent(Indentation) << "else\n";
-
-  ++Indentation; ++Indentation;
-  o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
-  --Indentation; --Indentation;
-
-  o << '\n';
-  o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n";
-  --Indentation; --Indentation;
-
-  o.indent(Indentation) << "}\n";
-
-  o << '\n';
-
+void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation,
+                            std::string Namespace) {
   o.indent(Indentation) <<
-    "static bool decodeInstruction(MCInst &MI, field_t insn, "
-    "uint64_t Address, const void *Decoder) {\n";
+    "static bool decode" << Namespace << "Instruction" << BitWidth
+    << "(MCInst &MI, uint" << BitWidth << "_t insn, uint64_t Address, "
+    << "const void *Decoder) {\n";
   o.indent(Indentation) << "  unsigned tmp = 0;\n";
 
   ++Indentation; ++Indentation;
@@ -651,10 +601,10 @@
 /// dumpFilterArray - dumpFilterArray prints out debugging info for the given
 /// filter array as a series of chars.
 void FilterChooser::dumpFilterArray(raw_ostream &o,
-                                    bit_value_t (&filter)[BIT_WIDTH]) {
+                                    std::vector<bit_value_t> &filter) {
   unsigned bitIndex;
 
-  for (bitIndex = BIT_WIDTH; bitIndex > 0; bitIndex--) {
+  for (bitIndex = BitWidth; bitIndex > 0; bitIndex--) {
     switch (filter[bitIndex - 1]) {
     case BIT_UNFILTERED:
       o << ".";
@@ -727,7 +677,7 @@
   int State = 0;
   int Val = -1;
 
-  for (unsigned i = 0; i < BIT_WIDTH; ++i) {
+  for (unsigned i = 0; i < BitWidth; ++i) {
     Val = Value(Insn[i]);
     bool Filtered = PositionFiltered(i);
     switch (State) {
@@ -761,7 +711,7 @@
   }
   // If we are still in Island after the loop, do some housekeeping.
   if (State == 2) {
-    EndBits.push_back(BIT_WIDTH - 1);
+    EndBits.push_back(BitWidth - 1);
     FieldVals.push_back(FieldVal);
     ++Num;
   }
@@ -802,8 +752,8 @@
       }
 
       o.indent(Indentation)
-        << "  tmp = fieldFromInstruction(insn, " << I->FieldBase
-        << ", " << I->FieldLength << ");\n";
+        << "  tmp = fieldFromInstruction" << BitWidth
+        << "(insn, " << I->FieldBase << ", " << I->FieldLength << ");\n";
       if (I->Decoder != "") {
         o.indent(Indentation) << "  " << I->Decoder
                               << "(MI, tmp, Address, Decoder);\n";
@@ -836,7 +786,8 @@
 
   for (I = Size; I != 0; --I) {
     NumBits = EndBits[I-1] - StartBits[I-1] + 1;
-    o << "fieldFromInstruction(insn, " << StartBits[I-1] << ", " << NumBits
+    o << "fieldFromInstruction" << BitWidth << "(insn, "
+      << StartBits[I-1] << ", " << NumBits
       << ") == " << FieldVals[I-1];
     if (I > 1)
       o << " && ";
@@ -855,7 +806,8 @@
     }
 
     o.indent(Indentation)
-      << "  tmp = fieldFromInstruction(insn, " << I->FieldBase
+      << "  tmp = fieldFromInstruction" << BitWidth
+      << "(insn, " << I->FieldBase
       << ", " << I->FieldLength << ");\n";
     if (I->Decoder != "") {
       o.indent(Indentation) << "  " << I->Decoder
@@ -965,23 +917,23 @@
   // (MIXED) ------ . ----> (MIXED)
   // (FILTERED)---- . ----> (FILTERED)
 
-  bitAttr_t bitAttrs[BIT_WIDTH];
+  std::vector<bitAttr_t> bitAttrs;
 
   // FILTERED bit positions provide no entropy and are not worthy of pursuing.
   // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
-  for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex)
+  for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex)
     if (FilterBitValues[BitIndex] == BIT_TRUE ||
         FilterBitValues[BitIndex] == BIT_FALSE)
-      bitAttrs[BitIndex] = ATTR_FILTERED;
+      bitAttrs.push_back(ATTR_FILTERED);
     else
-      bitAttrs[BitIndex] = ATTR_NONE;
+      bitAttrs.push_back(ATTR_NONE);
 
   for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) {
     insn_t insn;
 
     insnWithID(insn, Opcodes[InsnIndex]);
 
-    for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex) {
+    for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
       switch (bitAttrs[BitIndex]) {
       case ATTR_NONE:
         if (insn[BitIndex] == BIT_UNSET)
@@ -1027,7 +979,7 @@
   bitAttr_t RA = ATTR_NONE;
   unsigned StartBit = 0;
 
-  for (BitIndex = 0; BitIndex < BIT_WIDTH; BitIndex++) {
+  for (BitIndex = 0; BitIndex < BitWidth; BitIndex++) {
     bitAttr_t bitAttr = bitAttrs[BitIndex];
 
     assert(bitAttr != ATTR_NONE && "Bit without attributes");
@@ -1216,8 +1168,9 @@
   return true;
 }
 
-bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
-                                                 unsigned Opc){
+static bool populateInstruction(const CodeGenInstruction &CGI,
+                                unsigned Opc,
+                      std::map<unsigned, std::vector<OperandInfo> >& Operands){
   const Record &Def = *CGI.TheDef;
   // If all the bit positions are not specified; do not decode this instruction.
   // We are bound to fail!  For proper disassembly, the well-known encoding bits
@@ -1351,16 +1304,43 @@
   return true;
 }
 
-void FixedLenDecoderEmitter::populateInstructions() {
-  for (unsigned i = 0, e = NumberedInstructions.size(); i < e; ++i) {
-    Record *R = NumberedInstructions[i]->TheDef;
-    if (R->getValueAsString("Namespace") == "TargetOpcode" ||
-        R->getValueAsBit("isPseudo"))
-      continue;
+static void emitHelper(llvm::raw_ostream &o, unsigned BitWidth) {
+  unsigned Indentation = 0;
+  std::string WidthStr = "uint" + utostr(BitWidth) + "_t";
 
-    if (populateInstruction(*NumberedInstructions[i], i))
-      Opcodes.push_back(i);
-  }
+  o << '\n';
+
+  o.indent(Indentation) << "static " << WidthStr <<
+    " fieldFromInstruction" << BitWidth <<
+    "(" << WidthStr <<" insn, unsigned startBit, unsigned numBits)\n";
+
+  o.indent(Indentation) << "{\n";
+
+  ++Indentation; ++Indentation;
+  o.indent(Indentation) << "assert(startBit + numBits <= " << BitWidth
+                        << " && \"Instruction field out of bounds!\");\n";
+  o << '\n';
+  o.indent(Indentation) << WidthStr << " fieldMask;\n";
+  o << '\n';
+  o.indent(Indentation) << "if (numBits == " << BitWidth << ")\n";
+
+  ++Indentation; ++Indentation;
+  o.indent(Indentation) << "fieldMask = (" << WidthStr << ")-1;\n";
+  --Indentation; --Indentation;
+
+  o.indent(Indentation) << "else\n";
+
+  ++Indentation; ++Indentation;
+  o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
+  --Indentation; --Indentation;
+
+  o << '\n';
+  o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n";
+  --Indentation; --Indentation;
+
+  o.indent(Indentation) << "}\n";
+
+  o << '\n';
 }
 
 // Emits disassembler code for instruction decoding.
@@ -1372,10 +1352,47 @@
   o << '\n';
   o << "namespace llvm {\n\n";
 
+  // Parameterize the decoders based on namespace and instruction width.
   NumberedInstructions = Target.getInstructionsByEnumValue();
-  populateInstructions();
-  FilterChooser FC(NumberedInstructions, Opcodes, Operands);
-  FC.emitTop(o, 0);
+  std::map<std::pair<std::string, unsigned>,
+           std::vector<unsigned> > OpcMap;
+  std::map<unsigned, std::vector<OperandInfo> > Operands;
+
+  for (unsigned i = 0; i < NumberedInstructions.size(); ++i) {
+    const CodeGenInstruction *Inst = NumberedInstructions[i];
+    Record *Def = Inst->TheDef;
+    unsigned Size = Def->getValueAsInt("Size");
+    if (Def->getValueAsString("Namespace") == "TargetOpcode" ||
+        Def->getValueAsBit("isPseudo") ||
+        Def->getValueAsBit("isAsmParserOnly") ||
+        Def->getValueAsBit("isCodeGenOnly"))
+      continue;
+
+    std::string DecoderNamespace = Def->getValueAsString("DecoderNamespace");
+
+    if (Size) {
+      if (populateInstruction(*Inst, i, Operands)) {
+        OpcMap[std::make_pair(DecoderNamespace, Size)].push_back(i);
+      }
+    }
+  }
+
+  std::set<unsigned> Sizes;
+  for (std::map<std::pair<std::string, unsigned>,
+                std::vector<unsigned> >::iterator
+       I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) {
+    // If we haven't visited this instruction width before, emit the
+    // helper method to extract fields.
+    if (!Sizes.count(I->first.second)) {
+      emitHelper(o, 8*I->first.second);
+      Sizes.insert(I->first.second);
+    }
+
+    // Emit the decoder for this namespace+width combination.
+    FilterChooser FC(NumberedInstructions, I->second, Operands,
+                     8*I->first.second);
+    FC.emitTop(o, 0, I->first.first);
+  }
 
   o << "\n} // End llvm namespace \n";
 }

Modified: llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.h?rev=135524&r1=135523&r2=135524&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.h (original)
+++ llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.h Tue Jul 19 16:06:00 2011
@@ -47,8 +47,6 @@
   std::vector<unsigned> Opcodes;
   std::map<unsigned, std::vector<OperandInfo> > Operands;
 
-  bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc);
-  void populateInstructions();
 };
 
 } // end llvm namespace





More information about the llvm-commits mailing list