The instruction DINS may be transformed into DINSU or DEXTM depending
authorJack Carter <jcarter@mips.com>
Fri, 31 Aug 2012 18:06:48 +0000 (18:06 +0000)
committerJack Carter <jcarter@mips.com>
Fri, 31 Aug 2012 18:06:48 +0000 (18:06 +0000)
on the size of the extraction and its position in the 64 bit word.

This patch allows support of the dext transformations with mips64 direct
object output.

0 <= msb < 32 0 <= lsb < 32 0 <= pos < 32 1 <= size <= 32
DINS
The field is entirely contained in the right-most word of the doubleword

32 <= msb < 64 0 <= lsb < 32 0 <= pos < 32 2 <= size <= 64
DINSM
The field straddles the words of the doubleword

32 <= msb < 64 32 <= lsb < 64 32 <= pos < 64 1 <= size <= 32
DINSU
The field is entirely contained in the left-most word of the doubleword

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

lib/Target/Mips/Mips64InstrInfo.td
lib/Target/Mips/MipsAsmPrinter.cpp
lib/Target/Mips/MipsMCInstLower.cpp
lib/Target/Mips/MipsMCInstLower.h
test/MC/Mips/mips64extins.ll

index 366672518b9d7365bf5f233135ca4c4d59e9f44f..147be5db15310caf0766079e00388e7fad4d31b2 100644 (file)
@@ -222,6 +222,10 @@ let Pattern = []<dag> in {
   def DEXTM : ExtBase<1, "dextm", CPU64Regs>;
 }
 def DINS : InsBase<7, "dins", CPU64Regs>;
+let Pattern = []<dag> in {
+  def DINSU : InsBase<6, "dinsu", CPU64Regs>;
+  def DINSM : InsBase<5, "dinsm", CPU64Regs>;
+}
 
 let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
   def DSLL64_32 : FR<0x00, 0x3c, (outs CPU64Regs:$rd), (ins CPURegs:$rt),
index 13bd0cc219a548995a68f9fc158a1085c6c3a6d6..e4db9915f0a9f2de20e535009f44e08d8d7c9996 100644 (file)
@@ -86,11 +86,11 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
       break;
       // Double extract instruction is chosen by pos and size operands
       case Mips::DEXT:
-        assert(Subtarget->hasMips64() &&
-                    "DEXT is a MIPS64 instruction");
+      case Mips::DINS:
+        assert(Subtarget->hasMips64() && "DEXT/DINS are MIPS64 instructions");
         {
           MCInst TmpInst0;
-          MCInstLowering.LowerDEXT(I, TmpInst0);
+          MCInstLowering.LowerDextDins(I, TmpInst0);
           OutStreamer.EmitInstruction(TmpInst0);
           return;
         }
index d65e74d2c5366dbc6ba8811b32b53c4dfc9c0473..674bce30a5bd3fbe5b56bd4ea1161e2e442db779 100644 (file)
@@ -11,7 +11,6 @@
 // MCInst records.
 //
 //===----------------------------------------------------------------------===//
-
 #include "MipsMCInstLower.h"
 #include "MipsAsmPrinter.h"
 #include "MipsInstrInfo.h"
@@ -190,10 +189,17 @@ void MipsMCInstLower::LowerLargeShift(const MachineInstr *MI,
   }
 }
 
-// Pick a DEXT instruction variant based on the pos and size operands
-void MipsMCInstLower::LowerDEXT(const MachineInstr *MI,  MCInst& Inst) {
+// Pick a DEXT or DINS instruction variant based on the pos and size operands
+void MipsMCInstLower::LowerDextDins(const MachineInstr *MI,  MCInst& Inst) {
+  int Opcode = MI->getOpcode();
+
+  if (Opcode == Mips::DEXT)
+    assert(MI->getNumOperands() == 4 &&
+           "Invalid no. of machine operands for DEXT!");
+  else // Only DEXT and DINS are possible
+    assert(MI->getNumOperands() == 5 &&
+           "Invalid no. of machine operands for DINS!");
 
-  assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands for DEXT!");
   assert(MI->getOperand(2).isImm());
   int64_t pos = MI->getOperand(2).getImm();
   assert(MI->getOperand(3).isImm());
@@ -204,23 +210,21 @@ void MipsMCInstLower::LowerDEXT(const MachineInstr *MI,  MCInst& Inst) {
   // rs
   Inst.addOperand(LowerOperand(MI->getOperand(1)));
 
-  // DEXT
-  if ((pos < 32) && (size <= 32)) {
-    Inst.addOperand(MCOperand::CreateImm(pos));
-    Inst.addOperand(MCOperand::CreateImm(size));
-    Inst.setOpcode(Mips::DEXT);
-  }
-  // DEXTU
-  else if ((pos < 64) && (size <= 32)) {
-    Inst.addOperand(MCOperand::CreateImm(pos - 32));
-    Inst.addOperand(MCOperand::CreateImm(size));
-    Inst.setOpcode(Mips::DEXTU);
-  }
-  // DEXTM
-  else {
+  if (size <= 32) {
+    if ((pos < 32)) { // DEXT/DINS
+      Inst.addOperand(MCOperand::CreateImm(pos));
+      Inst.addOperand(MCOperand::CreateImm(size));
+      Inst.setOpcode(Opcode);
+    } else { // DEXTU/DINSU
+      Inst.addOperand(MCOperand::CreateImm(pos - 32));
+      Inst.addOperand(MCOperand::CreateImm(size));
+      Inst.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU);
+    }
+  } else { // DEXTM/DINSM
+    assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32");
     Inst.addOperand(MCOperand::CreateImm(pos));
     Inst.addOperand(MCOperand::CreateImm(size - 32));
     Inst.setOpcode(Mips::DEXTM);
+    Inst.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM);
   }
-  return;
 }
index b5d88de9489ebf5db4aa5742a7dcd3fecd8b2315..c1fe697a20a568fdd7e0ac57c91d2e081fb44786 100644 (file)
@@ -34,7 +34,7 @@ public:
   void Initialize(Mangler *mang, MCContext *C);
   void Lower(const MachineInstr *MI, MCInst &OutMI) const;
   void LowerLargeShift(const MachineInstr *MI, MCInst &Inst, int64_t Shift);
-  void LowerDEXT(const MachineInstr *MI, MCInst &Inst);
+  void LowerDextDins(const MachineInstr *MI, MCInst &Inst);
 
 private:
   MCOperand LowerSymbolOperand(const MachineOperand &MO,
index b15409e5ca70bbdef4bdffd8b367cae14dd6c9ee..ebe8f86513fd92860f5987b7fb16355c7e850a31 100644 (file)
@@ -26,3 +26,32 @@ entry:
   ret i64 %and
 }
 
+define i64 @dins(i64 %i, i64 %j) nounwind readnone {
+entry:
+; CHECK: dins ${{[0-9]+}}, ${{[0-9]+}}, 8, 10
+  %shl2 = shl i64 %j, 8
+  %and = and i64 %shl2, 261888
+  %and3 = and i64 %i, -261889
+  %or = or i64 %and3, %and
+  ret i64 %or
+}
+
+define i64 @dinsm(i64 %i, i64 %j) nounwind readnone {
+entry:
+; CHECK: dinsm ${{[0-9]+}}, ${{[0-9]+}}, 10, 1
+  %shl4 = shl i64 %j, 10
+  %and = and i64 %shl4, 8796093021184
+  %and5 = and i64 %i, -8796093021185
+  %or = or i64 %and5, %and
+  ret i64 %or
+}
+
+define i64 @dinsu(i64 %i, i64 %j) nounwind readnone {
+entry:
+; CHECK: dinsu ${{[0-9]+}}, ${{[0-9]+}}, 8, 13
+  %shl4 = shl i64 %j, 40
+  %and = and i64 %shl4, 9006099743113216
+  %and5 = and i64 %i, -9006099743113217
+  %or = or i64 %and5, %and
+  ret i64 %or
+}