Support little-endian encodings in the FixedLenDecoderEmitter
authorHal Finkel <hfinkel@anl.gov>
Tue, 17 Dec 2013 22:37:50 +0000 (22:37 +0000)
committerHal Finkel <hfinkel@anl.gov>
Tue, 17 Dec 2013 22:37:50 +0000 (22:37 +0000)
The convention used to specify the PowerPC ISA is that bits are numbered in
reverse order (0 is the index of the high bit). To support this "little endian"
encoding convention, CodeEmitterGen will reverse the bit numberings prior to
generating the encoding tables. In order to generate a disassembler,
FixedLenDecoderEmitter needs to do the same.

This moves the bit reversal logic out of CodeEmitterGen and into CodeGenTarget
(where it can be used by both CodeEmitterGen and FixedLenDecoderEmitter). This
is prep work for disassembly support in the PPC backend (which is the only
in-tree user of this little-endian encoding support).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197532 91177308-0d34-0410-b5e6-96231b3b80d8

utils/TableGen/CodeEmitterGen.cpp
utils/TableGen/CodeGenTarget.cpp
utils/TableGen/CodeGenTarget.h
utils/TableGen/FixedLenDecoderEmitter.cpp

index c94d384901f0c21d02081448c1df5c9f3fe30a23..b7dea1046ba66d379021e9d04d2510d5c9ff517c 100644 (file)
@@ -43,7 +43,6 @@ public:
 private:
   void emitMachineOpEmitter(raw_ostream &o, const std::string &Namespace);
   void emitGetValueBit(raw_ostream &o, const std::string &Namespace);
-  void reverseBits(std::vector<Record*> &Insts);
   int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
   std::string getInstructionCase(Record *R, CodeGenTarget &Target);
   void AddCodeToMergeInOperand(Record *R, BitsInit *BI,
@@ -53,40 +52,6 @@ private:
 
 };
 
-void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
-  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
-       I != E; ++I) {
-    Record *R = *I;
-    if (R->getValueAsString("Namespace") == "TargetOpcode" ||
-        R->getValueAsBit("isPseudo"))
-      continue;
-
-    BitsInit *BI = R->getValueAsBitsInit("Inst");
-
-    unsigned numBits = BI->getNumBits();
-    SmallVector<Init *, 16> NewBits(numBits);
-    for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
-      unsigned bitSwapIdx = numBits - bit - 1;
-      Init *OrigBit = BI->getBit(bit);
-      Init *BitSwap = BI->getBit(bitSwapIdx);
-      NewBits[bit]        = BitSwap;
-      NewBits[bitSwapIdx] = OrigBit;
-    }
-    if (numBits % 2) {
-      unsigned middle = (numBits + 1) / 2;
-      NewBits[middle] = BI->getBit(middle);
-    }
-
-    BitsInit *NewBI = BitsInit::get(NewBits);
-
-    // Update the bits in reversed order so that emitInstrOpBits will get the
-    // correct endianness.
-    R->getValue("Inst")->setValue(NewBI);
-  }
-}
-
 // If the VarBitInit at position 'bit' matches the specified variable then
 // return the variable bit position.  Otherwise return -1.
 int CodeEmitterGen::getVariableBit(const std::string &VarName,
@@ -238,8 +203,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
   std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
 
   // For little-endian instruction bit encodings, reverse the bit order
-  if (Target.isLittleEndianEncoding()) reverseBits(Insts);
-
+  Target.reverseBitsForLittleEndianEncoding();
 
   const std::vector<const CodeGenInstruction*> &NumberedInstructions =
     Target.getInstructionsByEnumValue();
index dd170595582490d3b812054d98336d38e841b441..4b8efff600c03107f155b769870c1f7e2c89cde0 100644 (file)
@@ -357,6 +357,46 @@ bool CodeGenTarget::isLittleEndianEncoding() const {
   return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
 }
 
+/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
+/// encodings, reverse the bit order of all instructions.
+void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
+  if (!isLittleEndianEncoding())
+    return;
+
+  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
+       I != E; ++I) {
+    Record *R = *I;
+    if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+        R->getValueAsBit("isPseudo"))
+      continue;
+
+    BitsInit *BI = R->getValueAsBitsInit("Inst");
+
+    unsigned numBits = BI->getNumBits();
+    SmallVector<Init *, 16> NewBits(numBits);
+    for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
+      unsigned bitSwapIdx = numBits - bit - 1;
+      Init *OrigBit = BI->getBit(bit);
+      Init *BitSwap = BI->getBit(bitSwapIdx);
+      NewBits[bit]        = BitSwap;
+      NewBits[bitSwapIdx] = OrigBit;
+    }
+    if (numBits % 2) {
+      unsigned middle = (numBits + 1) / 2;
+      NewBits[middle] = BI->getBit(middle);
+    }
+
+    BitsInit *NewBI = BitsInit::get(NewBits);
+
+    // Update the bits in reversed order so that emitInstrOpBits will get the
+    // correct endianness.
+    R->getValue("Inst")->setValue(NewBI);
+  }
+}
+
 /// guessInstructionProperties - Return true if it's OK to guess instruction
 /// properties instead of raising an error.
 ///
index 627144302932b605342cae4f1543ff4487cdec4c..d6458f41cf23bf8d35974cbd34c9e05952a520e1 100644 (file)
@@ -177,6 +177,10 @@ public:
   ///
   bool isLittleEndianEncoding() const;
 
+  /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
+  /// encodings, reverse the bit order of all instructions.
+  void reverseBitsForLittleEndianEncoding();
+
   /// guessInstructionProperties - should we just guess unset instruction
   /// properties?
   bool guessInstructionProperties() const;
index 87d18cdb9d46bb31ed600740f315278898c6aab0..d2d3f3dd07644034df6b92c57a684ca954fae306 100644 (file)
@@ -2012,6 +2012,8 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
 
   emitFieldFromInstruction(OS);
 
+  Target.reverseBitsForLittleEndianEncoding();
+
   // Parameterize the decoders based on namespace and instruction width.
   NumberedInstructions = &Target.getInstructionsByEnumValue();
   std::map<std::pair<std::string, unsigned>,