Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -160,6 +160,9 @@ bool expandInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); + bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions); + bool expandLoadImm(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); @@ -1247,6 +1250,8 @@ case Mips::LoadAddr32Imm: case Mips::LoadAddr32Reg: case Mips::LoadImm64Reg: + case Mips::JalOneReg: + case Mips::JalTwoReg: return true; default: return false; @@ -1271,6 +1276,9 @@ return expandLoadAddressImm(Inst, IDLoc, Instructions); case Mips::LoadAddr32Reg: return expandLoadAddressReg(Inst, IDLoc, Instructions); + case Mips::JalOneReg: + case Mips::JalTwoReg: + return expandJalWithRegs(Inst, IDLoc, Instructions); } } @@ -1305,6 +1313,52 @@ } } +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 + if (inMicroMipsMode()) + JalrInst.setOpcode(Mips::JALR_MM); + else + JalrInst.setOpcode(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; Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1530,8 +1530,6 @@ 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>; @@ -1620,6 +1618,11 @@ !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 //===----------------------------------------------------------------------===// Index: test/MC/Mips/micromips-jump-instructions.s =================================================================== --- test/MC/Mips/micromips-jump-instructions.s +++ test/MC/Mips/micromips-jump-instructions.s @@ -23,6 +23,10 @@ # CHECK-EL: move $zero, $zero # encoding: [0x00,0x0c] # CHECK-EL: jalrs $ra, $6 # encoding: [0xe6,0x03,0x3c,0x4f] # CHECK-EL: move $zero, $zero # 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: move $zero, $zero # encoding: [0x0c,0x00] # CHECK-EB: jalrs $ra, $6 # encoding: [0x03,0xe6,0x4f,0x3c] # CHECK-EB: move $zero, $zero # 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