diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index af9a731e606..09ed44fa8a4 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -165,6 +165,9 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); + bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions); + bool expandLoadImm(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); @@ -1538,6 +1541,8 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) { case Mips::B_MM_Pseudo: case Mips::LWM_MM: case Mips::SWM_MM: + case Mips::JalOneReg: + case Mips::JalTwoReg: return true; default: return false; @@ -1565,6 +1570,9 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, case Mips::SWM_MM: case Mips::LWM_MM: return expandLoadStoreMultiple(Inst, IDLoc, Instructions); + case Mips::JalOneReg: + case Mips::JalTwoReg: + return expandJalWithRegs(Inst, IDLoc, Instructions); } } @@ -1599,6 +1607,48 @@ void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc, } } +bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions) { + // Create a JALR instruction which is going to replace the pseudo-JAL. + MCInst JalrInst; + JalrInst.setLoc(IDLoc); + const MCOperand FirstRegOp = Inst.getOperand(0); + const unsigned Opcode = Inst.getOpcode(); + + if (Opcode == Mips::JalOneReg) { + // jal $rs => jalr $rs + if (inMicroMipsMode()) { + JalrInst.setOpcode(Mips::JALR16_MM); + JalrInst.addOperand(FirstRegOp); + } else { + JalrInst.setOpcode(Mips::JALR); + JalrInst.addOperand(MCOperand::CreateReg(Mips::RA)); + JalrInst.addOperand(FirstRegOp); + } + } else if (Opcode == Mips::JalTwoReg) { + // jal $rd, $rs => jalr $rd, $rs + JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); + JalrInst.addOperand(FirstRegOp); + const MCOperand SecondRegOp = Inst.getOperand(1); + JalrInst.addOperand(SecondRegOp); + } + Instructions.push_back(JalrInst); + + // If .set reorder is active, emit a NOP after it. + if (AssemblerOptions.back()->isReorder()) { + // This is a 32-bit NOP because these 2 pseudo-instructions + // do not have a short delay slot. + MCInst NopInst; + NopInst.setOpcode(Mips::SLL); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateImm(0)); + Instructions.push_back(NopInst); + } + + return false; +} + bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions) { MCInst tmpInst; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 2266569978c..ae2223a5855 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -1556,8 +1556,6 @@ def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>; let Predicates = [NotInMicroMips] in { def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; } -def : MipsInstAlias<"jal $rs", (JALR RA, GPR32Opnd:$rs), 0>; -def : MipsInstAlias<"jal $rd,$rs", (JALR GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, ISA_MIPS32; def : MipsInstAlias<"not $rt, $rs", (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; @@ -1648,6 +1646,11 @@ class LoadAddressImm : !strconcat(instr_asm, "\t$rt, $imm32")> ; def LoadAddr32Imm : LoadAddressImm<"la", uimm5, GPR32Opnd>; +def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), + "jal\t$rd, $rs"> ; +def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs), + "jal\t$rs"> ; + //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// diff --git a/test/MC/Mips/micromips-jump-instructions.s b/test/MC/Mips/micromips-jump-instructions.s index 76f85abafe7..945d87d2934 100644 --- a/test/MC/Mips/micromips-jump-instructions.s +++ b/test/MC/Mips/micromips-jump-instructions.s @@ -23,6 +23,10 @@ # CHECK-EL: nop # encoding: [0x00,0x0c] # CHECK-EL: jalrs $ra, $6 # encoding: [0xe6,0x03,0x3c,0x4f] # CHECK-EL: nop # encoding: [0x00,0x0c] +# CHECK-EL: jalr $25 # encoding: [0xd9,0x45] +# CHECK-EL: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK-EL: jalr $4, $25 # encoding: [0x99,0x00,0x3c,0x0f] +# CHECK-EL: nop # encoding: [0x00,0x00,0x00,0x00] #------------------------------------------------------------------------------ # Big endian #------------------------------------------------------------------------------ @@ -40,6 +44,10 @@ # CHECK-EB: nop # encoding: [0x0c,0x00] # CHECK-EB: jalrs $ra, $6 # encoding: [0x03,0xe6,0x4f,0x3c] # CHECK-EB: nop # encoding: [0x0c,0x00] +# CHECK-EB: jalr $25 # encoding: [0x45,0xd9] +# CHECK-EB: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK-EB: jalr $4, $25 # encoding: [0x00,0x99,0x0f,0x3c] +# CHECK-EB: nop # encoding: [0x00,0x00,0x00,0x00] j 1328 jal 1328 @@ -48,3 +56,5 @@ j $7 jals 1328 jalrs $ra, $6 + jal $25 + jal $4, $25