bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
+ bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
+
bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
case Mips::B_MM_Pseudo:
case Mips::LWM_MM:
case Mips::SWM_MM:
+ case Mips::JalOneReg:
+ case Mips::JalTwoReg:
return true;
default:
return false;
case Mips::SWM_MM:
case Mips::LWM_MM:
return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
+ case Mips::JalOneReg:
+ case Mips::JalTwoReg:
+ return expandJalWithRegs(Inst, IDLoc, Instructions);
}
}
}
}
+bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &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<MCInst> &Instructions) {
MCInst tmpInst;
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>;
!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
//===----------------------------------------------------------------------===//
# 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
#------------------------------------------------------------------------------
# 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
j $7
jals 1328
jalrs $ra, $6
+ jal $25
+ jal $4, $25