[mips] Add support for .cpload.

Summary:
This directive is used for setting up $gp in the beginning of a function.
It expands to three instructions if PIC is enabled:
lui   $gp, %hi(_gp_disp)
addui $gp, $gp, %lo(_gp_disp)
addu  $gp, $gp, $reg

_gp_disp is a special symbol that the linker sets to the distance between
the lui instruction and the context pointer (_gp).

Reviewers: dsanders

Reviewed By: dsanders

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207637 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Matheus Almeida
2014-04-30 11:28:42 +00:00
parent 737de9db8e
commit 00bdeb4c54
5 changed files with 148 additions and 0 deletions

View File

@@ -137,6 +137,7 @@ class MipsAsmParser : public MCTargetAsmParser {
SmallVectorImpl<MCInst> &Instructions, bool isLoad,
bool isImmOpnd);
bool reportParseError(StringRef ErrorMsg);
bool reportParseError(SMLoc Loc, StringRef ErrorMsg);
bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
bool parseRelocOperand(const MCExpr *&Res);
@@ -145,6 +146,7 @@ class MipsAsmParser : public MCTargetAsmParser {
bool isEvaluated(const MCExpr *Expr);
bool parseSetFeature(uint64_t Feature);
bool parseDirectiveCPLoad(SMLoc Loc);
bool parseDirectiveCPSetup();
bool parseDirectiveNaN();
bool parseDirectiveSet();
@@ -2083,6 +2085,10 @@ bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
return Error(Loc, ErrorMsg);
}
bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
return Error(Loc, ErrorMsg);
}
bool MipsAsmParser::parseSetNoAtDirective() {
// Line should look like: ".set noat".
// set at reg to 0.
@@ -2301,6 +2307,30 @@ bool MipsAsmParser::eatComma(StringRef ErrorStr) {
return true;
}
bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
if (Options.isReorder())
Warning(Loc, ".cpload in reorder section");
// FIXME: Warn if cpload is used in Mips16 mode.
SmallVector<MCParsedAsmOperand *, 1> Reg;
OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
reportParseError("expected register containing function address");
return false;
}
MipsOperand *RegOpnd = static_cast<MipsOperand *>(Reg[0]);
if (!RegOpnd->isGPRAsmReg()) {
reportParseError(RegOpnd->getStartLoc(), "invalid register");
return false;
}
getTargetStreamer().emitDirectiveCpload(RegOpnd->getGPR32Reg());
delete RegOpnd;
return false;
}
bool MipsAsmParser::parseDirectiveCPSetup() {
unsigned FuncReg;
unsigned Save;
@@ -2550,6 +2580,8 @@ bool MipsAsmParser::parseDirectiveOption() {
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getString();
if (IDVal == ".cpload")
return parseDirectiveCPLoad(DirectiveID.getLoc());
if (IDVal == ".dword") {
parseDataDirective(8, DirectiveID.getLoc());
return false;