[mips] Manually replace JAL pseudo-instructions with their JALR equivalent, instead...
authorToma Tabacu <toma.tabacu@imgtec.com>
Fri, 30 Jan 2015 11:18:50 +0000 (11:18 +0000)
committerToma Tabacu <toma.tabacu@imgtec.com>
Fri, 30 Jan 2015 11:18:50 +0000 (11:18 +0000)
Summary:
This is needed by the .cprestore assembler directive.

This directive needs to be able to insert an LW instruction after every JALR replacement of a JAL pseudo-instruction
(and never after a JALR which has NOT been a result of a pseudo-instruction replacement).

The problem with using InstAlias for these is that after it replaces the pseudo-instruction, we can't find out if the resulting JALR instruction
was generated by an InstAlias or not, so we don't know whether or not to insert our LW instruction.

By replacing it manually, we know when the pseudo-instruction replacement happens and we can insert the LW instruction correctly.

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: emaste, llvm-commits

Differential Revision: http://reviews.llvm.org/D5601

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227568 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/MipsInstrInfo.td
test/MC/Mips/micromips-jump-instructions.s

index af9a731e60664164c4c72b98e6747fa502ab16ab..09ed44fa8a47ea148f7bb0eefecd97f182f1e231 100644 (file)
@@ -165,6 +165,9 @@ class MipsAsmParser : public MCTargetAsmParser {
   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);
 
@@ -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<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;
index 2266569978c3877a6653ef1efdef4b0bea6e5b16..ae2223a58559cc9fb02e026045b8486a3e358c3a 100644 (file)
@@ -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<string instr_asm, Operand Od, RegisterOperand RO> :
                      !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 76f85abafe79dfb0da6c7cc7747b2fd156c3e081..945d87d293472b4cd611555228ef5373d8804bdc 100644 (file)
 # 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
@@ -48,3 +56,5 @@
      j $7
      jals 1328
      jalrs $ra, $6
+     jal $25
+     jal $4, $25