[mips][ias] Implement .cpreturn directive.
authorDaniel Sanders <daniel.sanders@imgtec.com>
Tue, 22 Sep 2015 10:50:09 +0000 (10:50 +0000)
committerDaniel Sanders <daniel.sanders@imgtec.com>
Tue, 22 Sep 2015 10:50:09 +0000 (10:50 +0000)
Summary:
Based on a patch by David Chisnall. I've modified the original patch as follows:
* Moved the expansion to the TargetStreamers so that the directive isn't
  expanded when emitting assembly.
* Fixed an operand order bug.
* Changed the move instructions from DADDu to OR to match recent changes to GAS.

Reviewers: vkalintiris

Subscribers: llvm-commits, emaste, seanbruno, theraven

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

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

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
lib/Target/Mips/MipsTargetStreamer.h
test/MC/Mips/cpsetup.s

index d6994c6b5dc41f4eb85db72419ceb53e3fdf33ef..4470baf8bff33d5e8ef18eeb412bdda18ef4f931 100644 (file)
@@ -118,6 +118,9 @@ class MipsAsmParser : public MCTargetAsmParser {
   bool IsPicEnabled;
   bool IsCpRestoreSet;
   int CpRestoreOffset;
+  unsigned CpSaveLocation;
+  /// If true, then CpSaveLocation is a register, otherwise it's an offset.
+  bool     CpSaveLocationIsRegister;
 
   // Print a warning along with its fix-it message at the given range.
   void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
@@ -240,6 +243,7 @@ class MipsAsmParser : public MCTargetAsmParser {
   bool parseDirectiveCpLoad(SMLoc Loc);
   bool parseDirectiveCpRestore(SMLoc Loc);
   bool parseDirectiveCPSetup();
+  bool parseDirectiveCPReturn();
   bool parseDirectiveNaN();
   bool parseDirectiveSet();
   bool parseDirectiveOption();
@@ -4964,11 +4968,20 @@ bool MipsAsmParser::parseDirectiveCPSetup() {
   }
   const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
 
+  CpSaveLocation = Save;
+  CpSaveLocationIsRegister = SaveIsReg;
+
   getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
                                            SaveIsReg);
   return false;
 }
 
+bool MipsAsmParser::parseDirectiveCPReturn() {
+  getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
+                                            CpSaveLocationIsRegister);
+  return false;
+}
+
 bool MipsAsmParser::parseDirectiveNaN() {
   MCAsmParser &Parser = getParser();
   if (getLexer().isNot(AsmToken::EndOfStatement)) {
@@ -5686,6 +5699,9 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
   if (IDVal == ".cpsetup")
     return parseDirectiveCPSetup();
 
+  if (IDVal == ".cpreturn")
+    return parseDirectiveCPReturn();
+
   if (IDVal == ".module")
     return parseDirectiveModule();
 
index 4e865663fc0a15aff712f0d5edbd948d818ebb18..994126e83b6e425ff518ea03e5771657189efc54 100644 (file)
@@ -96,6 +96,8 @@ void MipsTargetStreamer::emitDirectiveCpRestore(
 void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
                                               const MCSymbol &Sym, bool IsReg) {
 }
+void MipsTargetStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
+                                               bool SaveLocationIsRegister) {}
 
 void MipsTargetStreamer::emitDirectiveModuleFP() {}
 
@@ -387,6 +389,12 @@ void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
   forbidModuleDirective();
 }
 
+void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
+                                                  bool SaveLocationIsRegister) {
+  OS << "\t.cpreturn";
+  forbidModuleDirective();
+}
+
 void MipsTargetAsmStreamer::emitDirectiveModuleFP() {
   OS << "\t.module\tfp=";
   OS << ABIFlagsSection.getFpABIString(ABIFlagsSection.getFpABI()) << "\n";
@@ -838,6 +846,30 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
   forbidModuleDirective();
 }
 
+void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
+                                                  bool SaveLocationIsRegister) {
+  // Only N32 and N64 emit anything for .cpreturn iff PIC is set.
+  if (!Pic || !(getABI().IsN32() || getABI().IsN64()))
+    return;
+
+  MCInst Inst;
+  // Either restore the old $gp from a register or on the stack
+  if (SaveLocationIsRegister) {
+    Inst.setOpcode(Mips::OR);
+    Inst.addOperand(MCOperand::createReg(Mips::GP));
+    Inst.addOperand(MCOperand::createReg(SaveLocation));
+    Inst.addOperand(MCOperand::createReg(Mips::ZERO));
+  } else {
+    Inst.setOpcode(Mips::LD);
+    Inst.addOperand(MCOperand::createReg(Mips::GP));
+    Inst.addOperand(MCOperand::createReg(Mips::SP));
+    Inst.addOperand(MCOperand::createImm(SaveLocation));
+  }
+  getStreamer().EmitInstruction(Inst, STI);
+
+  forbidModuleDirective();
+}
+
 void MipsTargetELFStreamer::emitMipsAbiFlags() {
   MCAssembler &MCA = getStreamer().getAssembler();
   MCContext &Context = MCA.getContext();
index 9e6136d673b1dd93de86df457f3a4c276acd0027..b3222f5d89ef00d998b79463d8b34d31de44758f 100644 (file)
@@ -82,6 +82,8 @@ public:
                                       int Offset);
   virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
                                     const MCSymbol &Sym, bool IsReg);
+  virtual void emitDirectiveCpreturn(unsigned SaveLocation,
+                                     bool SaveLocationIsRegister);
 
   // FP abiflags directives
   virtual void emitDirectiveModuleFP();
@@ -195,6 +197,8 @@ public:
                               int Offset) override;
   void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
                             const MCSymbol &Sym, bool IsReg) override;
+  void emitDirectiveCpreturn(unsigned SaveLocation,
+                             bool SaveLocationIsRegister) override;
 
   // FP abiflags directives
   void emitDirectiveModuleFP() override;
@@ -246,6 +250,8 @@ public:
                               int Offset) override;
   void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
                             const MCSymbol &Sym, bool IsReg) override;
+  void emitDirectiveCpreturn(unsigned SaveLocation,
+                             bool SaveLocationIsRegister) override;
 
   void emitMipsAbiFlags();
 };
index 6b20562b0c5bf84b70e560cd1bec4f55bfc8cefa..95d84d95d851bce3f5069bd27743d8fd050a10fb 100644 (file)
@@ -24,6 +24,8 @@
 t1:
         .cpsetup $25, 8, __cerror
         nop
+        .cpreturn
+        nop
 
 # ALL-LABEL: t1:
 
@@ -45,9 +47,16 @@ t1:
 
 # ALL-NEXT: nop
 
+# ASM-NEXT: .cpreturn
+# NXX-NEXT: ld $gp, 8($sp)
+
+# ALL-NEXT: nop
+
 t2:
         .cpsetup $25, $2, __cerror
         nop
+        .cpreturn
+        nop
 
 # ALL-LABEL: t2:
 
@@ -69,6 +78,11 @@ t2:
 
 # ALL-NEXT: nop
 
+# ASM-NEXT: .cpreturn
+# NXX-NEXT: move $gp, $2
+
+# ALL-NEXT: nop
+
 # .cpsetup with local labels (PR22518):
 
 # The '1:' label isn't emitted in all cases but we still want a label to match
@@ -115,6 +129,8 @@ t4:
         nop
         .cpsetup $25, 8, __cerror
         nop
+        .cpreturn
+        nop
 
 # Testing that .cpsetup expands to nothing in this case
 # by checking that the next instruction after the first
@@ -122,12 +138,15 @@ t4:
 
 # ALL-LABEL: t4:
 
+# NXX-NEXT: nop
 # NXX-NEXT: nop
 # NXX-NEXT: nop
 
 # ASM-NEXT: nop
 # ASM-NEXT: .cpsetup $25, 8, __cerror
 # ASM-NEXT: nop
+# ASM-NEXT: .cpreturn
+# ASM-NEXT: nop
 
 # Test that we accept constant expressions.
         .option pic2