summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp16
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp32
-rw-r--r--llvm/lib/Target/Mips/MipsTargetStreamer.h6
-rw-r--r--llvm/test/MC/Mips/cpsetup.s19
4 files changed, 73 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index d6994c6b5dc..4470baf8bff 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -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();
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
index 4e865663fc0..994126e83b6 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
@@ -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();
diff --git a/llvm/lib/Target/Mips/MipsTargetStreamer.h b/llvm/lib/Target/Mips/MipsTargetStreamer.h
index 9e6136d673b..b3222f5d89e 100644
--- a/llvm/lib/Target/Mips/MipsTargetStreamer.h
+++ b/llvm/lib/Target/Mips/MipsTargetStreamer.h
@@ -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();
};
diff --git a/llvm/test/MC/Mips/cpsetup.s b/llvm/test/MC/Mips/cpsetup.s
index 6b20562b0c5..95d84d95d85 100644
--- a/llvm/test/MC/Mips/cpsetup.s
+++ b/llvm/test/MC/Mips/cpsetup.s
@@ -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
@@ -124,10 +140,13 @@ 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
OpenPOWER on IntegriCloud