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
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>;
+ 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
def RDHWR64 : ReadHardware<CPU64Regs, HWRegs64>;
def DEXT : ExtBase<3, "dext", CPU64Regs>;
+let Pattern = []<dag> 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 {
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);
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;
+}
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,
--- /dev/null
+; 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
+}
+