summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Carter <jcarter@mips.com>2012-08-31 18:06:48 +0000
committerJack Carter <jcarter@mips.com>2012-08-31 18:06:48 +0000
commit3185f9a2ea80afec30064b7cd095f82c31dc154e (patch)
tree00e44379ea6fc446b71b0e8fcba494ef4996add7
parente4fb6eae9997e80bfedb251ca3251cbed884d4ff (diff)
downloadllvm-3185f9a2ea80afec30064b7cd095f82c31dc154e.tar.gz
llvm-3185f9a2ea80afec30064b7cd095f82c31dc154e.tar.bz2
llvm-3185f9a2ea80afec30064b7cd095f82c31dc154e.tar.xz
The instruction DINS may be transformed into DINSU or DEXTM depending
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
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td4
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp6
-rw-r--r--lib/Target/Mips/MipsMCInstLower.cpp42
-rw-r--r--lib/Target/Mips/MipsMCInstLower.h2
-rw-r--r--test/MC/Mips/mips64extins.ll29
5 files changed, 60 insertions, 23 deletions
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td
index 366672518b..147be5db15 100644
--- a/lib/Target/Mips/Mips64InstrInfo.td
+++ b/lib/Target/Mips/Mips64InstrInfo.td
@@ -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),
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 13bd0cc219..e4db9915f0 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -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;
}
diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp
index d65e74d2c5..674bce30a5 100644
--- a/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/lib/Target/Mips/MipsMCInstLower.cpp
@@ -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;
}
diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h
index b5d88de948..c1fe697a20 100644
--- a/lib/Target/Mips/MipsMCInstLower.h
+++ b/lib/Target/Mips/MipsMCInstLower.h
@@ -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,
diff --git a/test/MC/Mips/mips64extins.ll b/test/MC/Mips/mips64extins.ll
index b15409e5ca..ebe8f86513 100644
--- a/test/MC/Mips/mips64extins.ll
+++ b/test/MC/Mips/mips64extins.ll
@@ -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
+}