diff options
-rw-r--r-- | lib/Target/Mips/Mips64InstrInfo.td | 5 | ||||
-rw-r--r-- | lib/Target/Mips/MipsAsmPrinter.cpp | 22 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMCInstLower.cpp | 29 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMCInstLower.h | 2 | ||||
-rw-r--r-- | test/MC/Mips/mips64shift.ll | 45 |
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 +} + |