[mips] Add support for .cpsetup

Summary:
Patch by Robert N. M. Watson
His work was sponsored by: DARPA, AFRL

Small corrections by myself.

CC: theraven, matheusalmeida

Differential Revision: http://llvm-reviews.chandlerc.com/D3199

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204924 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Daniel Sanders 2014-03-27 13:52:53 +00:00
parent 38899fc4da
commit 743cf74530
2 changed files with 169 additions and 0 deletions

View File

@ -196,6 +196,7 @@ class MipsAsmParser : public MCTargetAsmParser {
bool isEvaluated(const MCExpr *Expr);
bool parseSetFeature(uint64_t Feature);
bool parseDirectiveCPSetup();
bool parseDirectiveSet();
bool parseDirectiveOption();
@ -229,6 +230,10 @@ class MipsAsmParser : public MCTargetAsmParser {
return STI.getFeatureBits() & Mips::FeatureMicroMips;
}
bool parseRegister(unsigned &RegNum);
bool eatComma(StringRef ErrorStr);
int matchRegisterName(StringRef Symbol, bool is64BitReg);
int matchCPURegisterName(StringRef Symbol);
@ -249,6 +254,8 @@ class MipsAsmParser : public MCTargetAsmParser {
unsigned getReg(int RC, int RegNo);
unsigned getGPR(int RegNo);
int getATReg();
// Warn if RegNo is the current assembler temporary.
@ -1202,6 +1209,12 @@ unsigned MipsAsmParser::getReg(int RC, int RegNo) {
return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
}
unsigned MipsAsmParser::getGPR(int RegNo) {
return getReg((isMips64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
RegNo);
}
int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
if (RegNum >
getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs())
@ -2501,6 +2514,123 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
return false;
}
bool MipsAsmParser::parseRegister(unsigned &RegNum) {
if (!getLexer().is(AsmToken::Dollar))
return false;
Parser.Lex();
const AsmToken &Reg = Parser.getTok();
if (Reg.is(AsmToken::Identifier)) {
RegNum = matchCPURegisterName(Reg.getIdentifier());
} else if (Reg.is(AsmToken::Integer)) {
RegNum = Reg.getIntVal();
} else {
return false;
}
Parser.Lex();
return true;
}
bool MipsAsmParser::eatComma(StringRef ErrorStr) {
if (getLexer().isNot(AsmToken::Comma)) {
SMLoc Loc = getLexer().getLoc();
Parser.eatToEndOfStatement();
return Error(Loc, ErrorStr);
}
Parser.Lex(); // Eat the comma.
return true;
}
bool MipsAsmParser::parseDirectiveCPSetup() {
unsigned FuncReg;
unsigned Save;
bool SaveIsReg = true;
if (!parseRegister(FuncReg))
return reportParseError("expected register containing function address");
FuncReg = getGPR(FuncReg);
if (!eatComma("expected comma parsing directive"))
return true;
if (!parseRegister(Save)) {
const AsmToken &Tok = Parser.getTok();
if (Tok.is(AsmToken::Integer)) {
Save = Tok.getIntVal();
SaveIsReg = false;
Parser.Lex();
} else
return reportParseError("expected save register or stack offset");
} else
Save = getGPR(Save);
if (!eatComma("expected comma parsing directive"))
return true;
StringRef Name;
if (Parser.parseIdentifier(Name))
reportParseError("expected identifier");
MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
unsigned GPReg = getGPR(matchCPURegisterName("gp"));
// FIXME: The code below this point should be in the TargetStreamers.
// Only N32 and N64 emit anything for .cpsetup
// FIXME: We should only emit something for PIC mode too.
if (!isN32() && !isN64())
return false;
MCStreamer &TS = getStreamer();
MCInst Inst;
// Either store the old $gp in a register or on the stack
if (SaveIsReg) {
// move $save, $gpreg
Inst.setOpcode(Mips::DADDu);
Inst.addOperand(MCOperand::CreateReg(Save));
Inst.addOperand(MCOperand::CreateReg(GPReg));
Inst.addOperand(MCOperand::CreateReg(getGPR(0)));
} else {
// sd $gpreg, offset($sp)
Inst.setOpcode(Mips::SD);
Inst.addOperand(MCOperand::CreateReg(GPReg));
Inst.addOperand(MCOperand::CreateReg(getGPR(matchCPURegisterName("sp"))));
Inst.addOperand(MCOperand::CreateImm(Save));
}
TS.EmitInstruction(Inst, STI);
Inst.clear();
const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI,
getContext());
const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO,
getContext());
// lui $gp, %hi(%neg(%gp_rel(funcSym)))
Inst.setOpcode(Mips::LUi);
Inst.addOperand(MCOperand::CreateReg(GPReg));
Inst.addOperand(MCOperand::CreateExpr(HiExpr));
TS.EmitInstruction(Inst, STI);
Inst.clear();
// addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
Inst.setOpcode(Mips::ADDiu);
Inst.addOperand(MCOperand::CreateReg(GPReg));
Inst.addOperand(MCOperand::CreateReg(GPReg));
Inst.addOperand(MCOperand::CreateExpr(LoExpr));
TS.EmitInstruction(Inst, STI);
Inst.clear();
// daddu $gp, $gp, $funcreg
Inst.setOpcode(Mips::DADDu);
Inst.addOperand(MCOperand::CreateReg(GPReg));
Inst.addOperand(MCOperand::CreateReg(GPReg));
Inst.addOperand(MCOperand::CreateReg(FuncReg));
TS.EmitInstruction(Inst, STI);
return false;
}
bool MipsAsmParser::parseDirectiveSet() {
// Get the next token.
@ -2692,6 +2822,9 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
}
if (IDVal == ".cpsetup")
return parseDirectiveCPSetup();
return true;
}

36
test/MC/Mips/cpsetup.s Normal file
View File

@ -0,0 +1,36 @@
# RUN: llvm-mc -triple mips64-unknown-unknown -mattr=-n64,+o32 %s | \
# RUN: FileCheck -check-prefix=ANY -check-prefix=O32 %s
# RUN: llvm-mc -triple mips64-unknown-unknown -mattr=-n64,+n32 %s | \
# RUN: FileCheck -check-prefix=ANY -check-prefix=NXX -check-prefix=N32 %s
# RUN: llvm-mc -triple mips64-unknown-unknown %s | \
# RUN: FileCheck -check-prefix=ANY -check-prefix=NXX -check-prefix=N64 %s
# TODO: !PIC -> no output
.text
.option pic2
t1:
.cpsetup $25, 8, __cerror
# ANY-LABEL: t1:
# O32-NOT: __cerror
# NXX: sd $gp, 8($sp)
# NXX: lui $gp, %hi(%neg(%gp_rel(__cerror)))
# NXX: addiu $gp, $gp, %lo(%neg(%gp_rel(__cerror)))
# N32: addu $gp, $gp, $25
# N64: daddu $gp, $gp, $25
t2:
# ANY-LABEL: t2:
.cpsetup $25, $2, __cerror
# O32-NOT: __cerror
# NXX: move $2, $gp
# NXX: lui $gp, %hi(%neg(%gp_rel(__cerror)))
# NXX: addiu $gp, $gp, %lo(%neg(%gp_rel(__cerror)))
# N32: addu $gp, $gp, $25
# N64: daddu $gp, $gp, $25