From e4c63b7b683d7a64eeb6f44dc3222a1f7a55e25f Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Thu, 27 Mar 2014 13:52:53 +0000 Subject: [PATCH] [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 llvm-svn: 204924 --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 133 ++++++++++++++++++++ test/MC/Mips/cpsetup.s | 36 ++++++ 2 files changed, 169 insertions(+) create mode 100644 test/MC/Mips/cpsetup.s diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 36c4e2aa9ed..602bf04dac3 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -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; } diff --git a/test/MC/Mips/cpsetup.s b/test/MC/Mips/cpsetup.s new file mode 100644 index 00000000000..dbdcaab4ae3 --- /dev/null +++ b/test/MC/Mips/cpsetup.s @@ -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