aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td5
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp22
-rw-r--r--lib/Target/Mips/MipsMCInstLower.cpp29
-rw-r--r--lib/Target/Mips/MipsMCInstLower.h2
-rw-r--r--test/MC/Mips/mips64shift.ll45
5 files changed, 102 insertions, 1 deletions
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td
index 7a9d41b..cceee24 100644
--- a/lib/Target/Mips/Mips64InstrInfo.td
+++ b/lib/Target/Mips/Mips64InstrInfo.td
@@ -109,6 +109,11 @@ def DSRA : shift_rotate_imm64<0x3b, 0x00, "dsra", sra>;
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>;
+}
}
// Rotate Instructions
let Predicates = [HasMips64r2, HasStandardEncoding],
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 4dac591..914a204 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -13,9 +13,10 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "mips-asm-printer"
-#include "MipsAsmPrinter.h"
#include "Mips.h"
+#include "MipsAsmPrinter.h"
#include "MipsInstrInfo.h"
+#include "MipsMCInstLower.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "llvm/ADT/SmallString.h"
@@ -57,6 +58,25 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
return;
}
+ // Direct object specific instruction lowering
+ if (!OutStreamer.hasRawTextSupport())
+ switch (MI->getOpcode()) {
+ case Mips::DSLL:
+ case Mips::DSRL:
+ case Mips::DSRA:
+ assert(MI->getNumOperands() == 3 &&
+ "Invalid no. of machine operands for shift!");
+ assert(MI->getOperand(2).isImm());
+ int64_t Shift = MI->getOperand(2).getImm();
+ if (Shift > 31) {
+ MCInst TmpInst0;
+ MCInstLowering.LowerLargeShift(MI, TmpInst0, Shift - 32);
+ OutStreamer.EmitInstruction(TmpInst0);
+ return;
+ }
+ break;
+ }
+
MachineBasicBlock::const_instr_iterator I = MI;
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp
index b6042af..c49d530 100644
--- a/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/lib/Target/Mips/MipsMCInstLower.cpp
@@ -158,3 +158,32 @@ void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
OutMI.addOperand(MCOp);
}
}
+
+// If the D<shift> instruction has a shift amount that is greater
+// than 31 (checked in calling routine), lower it to a D<shift>32 instruction
+void MipsMCInstLower::LowerLargeShift(const MachineInstr *MI,
+ MCInst& Inst,
+ int64_t Shift) {
+ // rt
+ Inst.addOperand(LowerOperand(MI->getOperand(0)));
+ // rd
+ Inst.addOperand(LowerOperand(MI->getOperand(1)));
+ // saminus32
+ Inst.addOperand(MCOperand::CreateImm(Shift));
+
+ switch (MI->getOpcode()) {
+ default:
+ // Calling function is not synchronized
+ llvm_unreachable("Unexpected shift instruction");
+ break;
+ case Mips::DSLL:
+ Inst.setOpcode(Mips::DSLL32);
+ break;
+ case Mips::DSRL:
+ Inst.setOpcode(Mips::DSRL32);
+ break;
+ case Mips::DSRA:
+ Inst.setOpcode(Mips::DSRA32);
+ break;
+ }
+}
diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h
index 314420a..0abb996 100644
--- a/lib/Target/Mips/MipsMCInstLower.h
+++ b/lib/Target/Mips/MipsMCInstLower.h
@@ -33,6 +33,8 @@ public:
MipsMCInstLower(MipsAsmPrinter &asmprinter);
void Initialize(Mangler *mang, MCContext *C);
void Lower(const MachineInstr *MI, MCInst &OutMI) const;
+ void LowerLargeShift(const MachineInstr *MI, MCInst &Inst, int64_t Shift);
+
private:
MCOperand LowerSymbolOperand(const MachineOperand &MO,
MachineOperandType MOTy, unsigned Offset) const;
diff --git a/test/MC/Mips/mips64shift.ll b/test/MC/Mips/mips64shift.ll
new file mode 100644
index 0000000..7817b96
--- /dev/null
+++ b/test/MC/Mips/mips64shift.ll
@@ -0,0 +1,45 @@
+; RUN: llc -march=mips64el -filetype=obj -mcpu=mips64r2 %s -o - | llvm-objdump -disassemble -triple mips64el - | FileCheck %s
+
+
+define i64 @f3(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsll ${{[0-9]+}}, ${{[0-9]+}}, 10
+ %shl = shl i64 %a0, 10
+ ret i64 %shl
+}
+
+define i64 @f4(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsra ${{[0-9]+}}, ${{[0-9]+}}, 10
+ %shr = ashr i64 %a0, 10
+ ret i64 %shr
+}
+
+define i64 @f5(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsrl ${{[0-9]+}}, ${{[0-9]+}}, 10
+ %shr = lshr i64 %a0, 10
+ ret i64 %shr
+}
+
+define i64 @f6(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsll32 ${{[0-9]+}}, ${{[0-9]+}}, 8
+ %shl = shl i64 %a0, 40
+ ret i64 %shl
+}
+
+define i64 @f7(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsra32 ${{[0-9]+}}, ${{[0-9]+}}, 8
+ %shr = ashr i64 %a0, 40
+ ret i64 %shr
+}
+
+define i64 @f8(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsrl32 ${{[0-9]+}}, ${{[0-9]+}}, 8
+ %shr = lshr i64 %a0, 40
+ ret i64 %shr
+}
+