From 714313b4828cec98b086b54b356407540aa775c4 Mon Sep 17 00:00:00 2001 From: Jack Carter Date: Tue, 28 Aug 2012 20:07:41 +0000 Subject: The instruction DEXT may be transformed into DEXTU 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@162782 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/Mips64InstrInfo.td | 10 +++++++--- lib/Target/Mips/MipsAsmPrinter.cpp | 11 +++++++++++ lib/Target/Mips/MipsMCInstLower.cpp | 35 +++++++++++++++++++++++++++++++++++ lib/Target/Mips/MipsMCInstLower.h | 1 + test/MC/Mips/mips64extins.ll | 28 ++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 test/MC/Mips/mips64extins.ll diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 20fc178..3666725 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -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 = [] 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; def DEXT : ExtBase<3, "dext", CPU64Regs>; +let Pattern = [] 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 { diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 3b1509d..13bd0cc 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -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); diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index d4c5e6d..d65e74d 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -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; +} diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index 0abb996..b5d88de 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -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 index 0000000..b15409e --- /dev/null +++ b/test/MC/Mips/mips64extins.ll @@ -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 +} + -- cgit v1.1