diff options
-rw-r--r-- | lib/Target/Mips/Mips64InstrInfo.td | 4 | ||||
-rw-r--r-- | lib/Target/Mips/MipsAsmPrinter.cpp | 6 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMCInstLower.cpp | 42 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMCInstLower.h | 2 | ||||
-rw-r--r-- | test/MC/Mips/mips64extins.ll | 29 |
5 files changed, 60 insertions, 23 deletions
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 366672518b..147be5db15 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -222,6 +222,10 @@ let Pattern = []<dag> in { def DEXTM : ExtBase<1, "dextm", CPU64Regs>; } def DINS : InsBase<7, "dins", CPU64Regs>; +let Pattern = []<dag> in { + def DINSU : InsBase<6, "dinsu", CPU64Regs>; + def DINSM : InsBase<5, "dinsm", CPU64Regs>; +} let isCodeGenOnly = 1, rs = 0, shamt = 0 in { def DSLL64_32 : FR<0x00, 0x3c, (outs CPU64Regs:$rd), (ins CPURegs:$rt), diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 13bd0cc219..e4db9915f0 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -86,11 +86,11 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { break; // Double extract instruction is chosen by pos and size operands case Mips::DEXT: - assert(Subtarget->hasMips64() && - "DEXT is a MIPS64 instruction"); + case Mips::DINS: + assert(Subtarget->hasMips64() && "DEXT/DINS are MIPS64 instructions"); { MCInst TmpInst0; - MCInstLowering.LowerDEXT(I, TmpInst0); + MCInstLowering.LowerDextDins(I, TmpInst0); OutStreamer.EmitInstruction(TmpInst0); return; } diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index d65e74d2c5..674bce30a5 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -11,7 +11,6 @@ // MCInst records. // //===----------------------------------------------------------------------===// - #include "MipsMCInstLower.h" #include "MipsAsmPrinter.h" #include "MipsInstrInfo.h" @@ -190,10 +189,17 @@ void MipsMCInstLower::LowerLargeShift(const MachineInstr *MI, } } -// Pick a DEXT instruction variant based on the pos and size operands -void MipsMCInstLower::LowerDEXT(const MachineInstr *MI, MCInst& Inst) { +// Pick a DEXT or DINS instruction variant based on the pos and size operands +void MipsMCInstLower::LowerDextDins(const MachineInstr *MI, MCInst& Inst) { + int Opcode = MI->getOpcode(); + + if (Opcode == Mips::DEXT) + assert(MI->getNumOperands() == 4 && + "Invalid no. of machine operands for DEXT!"); + else // Only DEXT and DINS are possible + assert(MI->getNumOperands() == 5 && + "Invalid no. of machine operands for DINS!"); - 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()); @@ -204,23 +210,21 @@ void MipsMCInstLower::LowerDEXT(const MachineInstr *MI, MCInst& Inst) { // 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 { + if (size <= 32) { + if ((pos < 32)) { // DEXT/DINS + Inst.addOperand(MCOperand::CreateImm(pos)); + Inst.addOperand(MCOperand::CreateImm(size)); + Inst.setOpcode(Opcode); + } else { // DEXTU/DINSU + Inst.addOperand(MCOperand::CreateImm(pos - 32)); + Inst.addOperand(MCOperand::CreateImm(size)); + Inst.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU); + } + } else { // DEXTM/DINSM + assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32"); Inst.addOperand(MCOperand::CreateImm(pos)); Inst.addOperand(MCOperand::CreateImm(size - 32)); Inst.setOpcode(Mips::DEXTM); + Inst.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM); } - return; } diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index b5d88de948..c1fe697a20 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -34,7 +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); + void LowerDextDins(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 index b15409e5ca..ebe8f86513 100644 --- a/test/MC/Mips/mips64extins.ll +++ b/test/MC/Mips/mips64extins.ll @@ -26,3 +26,32 @@ entry: ret i64 %and } +define i64 @dins(i64 %i, i64 %j) nounwind readnone { +entry: +; CHECK: dins ${{[0-9]+}}, ${{[0-9]+}}, 8, 10 + %shl2 = shl i64 %j, 8 + %and = and i64 %shl2, 261888 + %and3 = and i64 %i, -261889 + %or = or i64 %and3, %and + ret i64 %or +} + +define i64 @dinsm(i64 %i, i64 %j) nounwind readnone { +entry: +; CHECK: dinsm ${{[0-9]+}}, ${{[0-9]+}}, 10, 1 + %shl4 = shl i64 %j, 10 + %and = and i64 %shl4, 8796093021184 + %and5 = and i64 %i, -8796093021185 + %or = or i64 %and5, %and + ret i64 %or +} + +define i64 @dinsu(i64 %i, i64 %j) nounwind readnone { +entry: +; CHECK: dinsu ${{[0-9]+}}, ${{[0-9]+}}, 8, 13 + %shl4 = shl i64 %j, 40 + %and = and i64 %shl4, 9006099743113216 + %and5 = and i64 %i, -9006099743113217 + %or = or i64 %and5, %and + ret i64 %or +} |