summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Carter <jcarter@mips.com>2012-07-16 15:14:51 +0000
committerJack Carter <jcarter@mips.com>2012-07-16 15:14:51 +0000
commite035f65b16956cdb7ba29e741b7e3c04a8ce4d24 (patch)
treeea58432ec6155317779d6adabcc181ccebb68180
parent694fbf17777f96e65e782667826dbccbe7524c32 (diff)
downloadllvm-e035f65b16956cdb7ba29e741b7e3c04a8ce4d24.tar.gz
llvm-e035f65b16956cdb7ba29e741b7e3c04a8ce4d24.tar.bz2
llvm-e035f65b16956cdb7ba29e741b7e3c04a8ce4d24.tar.xz
Doubleword Shift Left Logical Plus 32
Mips shift instructions DSLL, DSRL and DSRA are transformed into DSLL32, DSRL32 and DSRA32 respectively if the shift amount is between 32 and 63 Here is a description of DSLL: Purpose: Doubleword Shift Left Logical Plus 32 To execute a left-shift of a doubleword by a fixed amount--32 to 63 bits Description: GPR[rd] <- GPR[rt] << (sa+32) The 64-bit doubleword contents of GPR rt are shifted left, inserting zeros into the emptied bits; the result is placed in GPR rd. The bit-shift amount in the range 0 to 31 is specified by sa. This patch implements the direct object output of these instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160277 91177308-0d34-0410-b5e6-96231b3b80d8
-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 7a9d41bae8..cceee24a74 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 4dac59105d..914a204fe2 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 b6042af619..c49d5308a5 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 314420a170..0abb996a68 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 0000000000..7817b96fa5
--- /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
+}
+