Add RORX code generation support
[oota-llvm.git] / lib / Target / Mips / MipsAsmPrinter.cpp
index 3c50bae071af96ba8ac1b7fa56d470360cad007c..e780134033f7b5dafeb892161d98d5440c9fa49f 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "mips-asm-printer"
-#include "MipsAsmPrinter.h"
 #include "Mips.h"
+#include "MipsAsmPrinter.h"
+#include "MipsDirectObjLower.h"
 #include "MipsInstrInfo.h"
+#include "MipsMCInstLower.h"
 #include "InstPrinter/MipsInstPrinter.h"
 #include "MCTargetDesc/MipsBaseInfo.h"
 #include "llvm/ADT/SmallString.h"
@@ -63,8 +65,25 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
   do {
     MCInst TmpInst0;
     MCInstLowering.Lower(I++, TmpInst0);
+
+    // Direct object specific instruction lowering
+    if (!OutStreamer.hasRawTextSupport()){
+      switch (TmpInst0.getOpcode()) {
+      // If shift amount is >= 32 it the inst needs to be lowered further
+      case Mips::DSLL:
+      case Mips::DSRL:
+      case Mips::DSRA:
+        Mips::LowerLargeShift(TmpInst0);
+        break;
+        // Double extract instruction is chosen by pos and size operands
+      case Mips::DEXT:
+      case Mips::DINS:
+        Mips::LowerDextDins(TmpInst0);
+      }
+    }
+
     OutStreamer.EmitInstruction(TmpInst0);
-  } while ((I != E) && I->isInsideBundle());
+  } while ((I != E) && I->isInsideBundle()); // Delay slot check
 }
 
 //===----------------------------------------------------------------------===//
@@ -194,7 +213,7 @@ const char *MipsAsmPrinter::getCurrentABIString() const {
   case MipsSubtarget::N32:  return "abiN32";
   case MipsSubtarget::N64:  return "abi64";
   case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64
-  default: llvm_unreachable("Unknown Mips ABI");;
+  default: llvm_unreachable("Unknown Mips ABI");
   }
 }
 
@@ -335,6 +354,7 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
     }
     case 'D': // Second part of a double word register operand
     case 'L': // Low order register of a double word register operand
+    case 'M': // High order register of a double word register operand
     {
       if (OpNum == 0)
         return true;
@@ -353,17 +373,20 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
         }
         return true;
       }
-      unsigned RegOp;
-      if (Subtarget->isGP64bit())
-        RegOp = OpNum;
-      else {
+
+      unsigned RegOp = OpNum;
+      if (!Subtarget->isGP64bit()){
         // Endianess reverses which register holds the high or low value
+        // between M and L.
         switch(ExtraCode[0]) {
-        case 'D':
-          RegOp = (Subtarget->isLittle()) ? OpNum : OpNum+1;
+        case 'M':
+          RegOp = (Subtarget->isLittle()) ? OpNum + 1 : OpNum;
           break;
         case 'L':
-          RegOp = (Subtarget->isLittle()) ? OpNum+1 : OpNum;
+          RegOp = (Subtarget->isLittle()) ? OpNum : OpNum + 1;
+          break;
+        case 'D': // Always the second part
+          RegOp = OpNum + 1;
         }
         if (RegOp >= MI->getNumOperands())
           return true;