The instruction DEXT may be transformed into DEXTU or DEXTM depending
authorJack Carter <jcarter@mips.com>
Tue, 28 Aug 2012 20:07:41 +0000 (20:07 +0000)
committerJack Carter <jcarter@mips.com>
Tue, 28 Aug 2012 20:07:41 +0000 (20:07 +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@162782 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 [new file with mode: 0644]

index 20fc17807757d77e9ba01421cffc816d935c9fc1..366672518b9d7365bf5f233135ca4c4d59e9f44f 100644 (file)
@@ -110,9 +110,9 @@ def DSLLV    : shift_rotate_reg<0x14, 0x00, "dsllv", shl, CPU64Regs>;
 def DSRLV    : shift_rotate_reg<0x16, 0x00, "dsrlv", srl, CPU64Regs>;
 def DSRAV    : shift_rotate_reg<0x17, 0x00, "dsrav", sra, CPU64Regs>;
 let Pattern = []<dag> in {
-def DSLL32   : shift_rotate_imm64<0x3c, 0x00, "dsll32", shl>;
-def DSRL32   : shift_rotate_imm64<0x3e, 0x00, "dsrl32", srl>;
-def DSRA32   : shift_rotate_imm64<0x3f, 0x00, "dsra32", sra>;
+  def DSLL32   : shift_rotate_imm64<0x3c, 0x00, "dsll32", shl>;
+  def DSRL32   : shift_rotate_imm64<0x3e, 0x00, "dsrl32", srl>;
+  def DSRA32   : shift_rotate_imm64<0x3f, 0x00, "dsra32", sra>;
 }
 }
 // Rotate Instructions
@@ -217,6 +217,10 @@ let DecoderNamespace = "Mips64" in {
 def RDHWR64 : ReadHardware<CPU64Regs, HWRegs64>;
 
 def DEXT : ExtBase<3, "dext", CPU64Regs>;
+let Pattern = []<dag> in {
+  def DEXTU : ExtBase<2, "dextu", CPU64Regs>;
+  def DEXTM : ExtBase<1, "dextm", CPU64Regs>;
+}
 def DINS : InsBase<7, "dins", CPU64Regs>;
 
 let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
index 3b1509d46bb350c4466810db3bb87354916d5b5e..13bd0cc219a548995a68f9fc158a1085c6c3a6d6 100644 (file)
@@ -83,6 +83,17 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
           return;
         }
       }
+      break;
+      // Double extract instruction is chosen by pos and size operands
+      case Mips::DEXT:
+        assert(Subtarget->hasMips64() &&
+                    "DEXT is a MIPS64 instruction");
+        {
+          MCInst TmpInst0;
+          MCInstLowering.LowerDEXT(I, TmpInst0);
+          OutStreamer.EmitInstruction(TmpInst0);
+          return;
+        }
       }
 
     MCInstLowering.Lower(I++, TmpInst0);
index d4c5e6dd74cf07bf669303004e40dec4424d2ef1..d65e74d2c5366dbc6ba8811b32b53c4dfc9c0473 100644 (file)
@@ -189,3 +189,38 @@ void MipsMCInstLower::LowerLargeShift(const MachineInstr *MI,
     break;
   }
 }
+
+// Pick a DEXT instruction variant based on the pos and size operands
+void MipsMCInstLower::LowerDEXT(const MachineInstr *MI,  MCInst& Inst) {
+
+  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());
+  int64_t size = MI->getOperand(3).getImm();
+
+  // rt
+  Inst.addOperand(LowerOperand(MI->getOperand(0)));
+  // 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 {
+    Inst.addOperand(MCOperand::CreateImm(pos));
+    Inst.addOperand(MCOperand::CreateImm(size - 32));
+    Inst.setOpcode(Mips::DEXTM);
+  }
+  return;
+}
index 0abb996a6877532ce1caecdcb9db95067d1b1d98..b5d88de9489ebf5db4aa5742a7dcd3fecd8b2315 100644 (file)
@@ -34,6 +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);
 
 private:
   MCOperand LowerSymbolOperand(const MachineOperand &MO,
diff --git a/test/MC/Mips/mips64extins.ll b/test/MC/Mips/mips64extins.ll
new file mode 100644 (file)
index 0000000..b15409e
--- /dev/null
@@ -0,0 +1,28 @@
+; RUN: llc -march=mips64el -filetype=obj -mcpu=mips64r2 -mattr=n64 %s -o - \
+; RUN: | llvm-objdump -disassemble -triple mips64el -mattr +mips64r2 - \
+; RUN: | FileCheck %s
+
+define i64 @dext(i64 %i) nounwind readnone {
+entry:
+; CHECK: dext ${{[0-9]+}}, ${{[0-9]+}}, 5, 10
+  %shr = lshr i64 %i, 5
+  %and = and i64 %shr, 1023
+  ret i64 %and
+}
+
+define i64 @dextu(i64 %i) nounwind readnone {
+entry:
+; CHECK: dextu ${{[0-9]+}}, ${{[0-9]+}}, 2, 6
+  %shr = lshr i64 %i, 34
+  %and = and i64 %shr, 63
+  ret i64 %and
+}
+
+define i64 @dextm(i64 %i) nounwind readnone {
+entry:
+; CHECK: dextm ${{[0-9]+}}, ${{[0-9]+}}, 5, 2
+  %shr = lshr i64 %i, 5
+  %and = and i64 %shr, 17179869183
+  ret i64 %and
+}
+