Skip to content

Commit 525bc4f

Browse files
author
Matheus Almeida
committedApr 30, 2014
[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 llvm-svn: 207637
1 parent c0284d1 commit 525bc4f

File tree

5 files changed

+148
-0
lines changed

5 files changed

+148
-0
lines changed
 

‎llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class MipsAsmParser : public MCTargetAsmParser {
137137
SmallVectorImpl<MCInst> &Instructions, bool isLoad,
138138
bool isImmOpnd);
139139
bool reportParseError(StringRef ErrorMsg);
140+
bool reportParseError(SMLoc Loc, StringRef ErrorMsg);
140141

141142
bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
142143
bool parseRelocOperand(const MCExpr *&Res);
@@ -145,6 +146,7 @@ class MipsAsmParser : public MCTargetAsmParser {
145146

146147
bool isEvaluated(const MCExpr *Expr);
147148
bool parseSetFeature(uint64_t Feature);
149+
bool parseDirectiveCPLoad(SMLoc Loc);
148150
bool parseDirectiveCPSetup();
149151
bool parseDirectiveNaN();
150152
bool parseDirectiveSet();
@@ -2083,6 +2085,10 @@ bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
20832085
return Error(Loc, ErrorMsg);
20842086
}
20852087

2088+
bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2089+
return Error(Loc, ErrorMsg);
2090+
}
2091+
20862092
bool MipsAsmParser::parseSetNoAtDirective() {
20872093
// Line should look like: ".set noat".
20882094
// set at reg to 0.
@@ -2301,6 +2307,30 @@ bool MipsAsmParser::eatComma(StringRef ErrorStr) {
23012307
return true;
23022308
}
23032309

2310+
bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2311+
if (Options.isReorder())
2312+
Warning(Loc, ".cpload in reorder section");
2313+
2314+
// FIXME: Warn if cpload is used in Mips16 mode.
2315+
2316+
SmallVector<MCParsedAsmOperand *, 1> Reg;
2317+
OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2318+
if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2319+
reportParseError("expected register containing function address");
2320+
return false;
2321+
}
2322+
2323+
MipsOperand *RegOpnd = static_cast<MipsOperand *>(Reg[0]);
2324+
if (!RegOpnd->isGPRAsmReg()) {
2325+
reportParseError(RegOpnd->getStartLoc(), "invalid register");
2326+
return false;
2327+
}
2328+
2329+
getTargetStreamer().emitDirectiveCpload(RegOpnd->getGPR32Reg());
2330+
delete RegOpnd;
2331+
return false;
2332+
}
2333+
23042334
bool MipsAsmParser::parseDirectiveCPSetup() {
23052335
unsigned FuncReg;
23062336
unsigned Save;
@@ -2550,6 +2580,8 @@ bool MipsAsmParser::parseDirectiveOption() {
25502580
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
25512581
StringRef IDVal = DirectiveID.getString();
25522582

2583+
if (IDVal == ".cpload")
2584+
return parseDirectiveCPLoad(DirectiveID.getLoc());
25532585
if (IDVal == ".dword") {
25542586
parseDataDirective(8, DirectiveID.getLoc());
25552587
return false;

‎llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp

+54
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask,
144144
OS << "," << FPUTopSavedRegOff << '\n';
145145
}
146146

147+
void MipsTargetAsmStreamer::emitDirectiveCpload(unsigned RegNo) {
148+
OS << "\t.cpload\t$"
149+
<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
150+
}
151+
147152
// This part is for ELF object output.
148153
MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
149154
const MCSubtargetInfo &STI)
@@ -402,3 +407,52 @@ void MipsTargetELFStreamer::emitDirectiveSetMips64R2() {
402407
void MipsTargetELFStreamer::emitDirectiveSetDsp() {
403408
// No action required for ELF output.
404409
}
410+
411+
void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) {
412+
// .cpload $reg
413+
// This directive expands to:
414+
// lui $gp, %hi(_gp_disp)
415+
// addui $gp, $gp, %lo(_gp_disp)
416+
// addu $gp, $gp, $reg
417+
// when support for position independent code is enabled.
418+
if (!Pic || (isN32() || isN64()))
419+
return;
420+
421+
// There's a GNU extension controlled by -mno-shared that allows
422+
// locally-binding symbols to be accessed using absolute addresses.
423+
// This is currently not supported. When supported -mno-shared makes
424+
// .cpload expand to:
425+
// lui $gp, %hi(__gnu_local_gp)
426+
// addiu $gp, $gp, %lo(__gnu_local_gp)
427+
428+
StringRef SymName("_gp_disp");
429+
MCAssembler &MCA = getStreamer().getAssembler();
430+
MCSymbol *GP_Disp = MCA.getContext().GetOrCreateSymbol(SymName);
431+
MCA.getOrCreateSymbolData(*GP_Disp);
432+
433+
MCInst TmpInst;
434+
TmpInst.setOpcode(Mips::LUi);
435+
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
436+
const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::Create(
437+
"_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext());
438+
TmpInst.addOperand(MCOperand::CreateExpr(HiSym));
439+
getStreamer().EmitInstruction(TmpInst, STI);
440+
441+
TmpInst.clear();
442+
443+
TmpInst.setOpcode(Mips::ADDiu);
444+
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
445+
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
446+
const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::Create(
447+
"_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext());
448+
TmpInst.addOperand(MCOperand::CreateExpr(LoSym));
449+
getStreamer().EmitInstruction(TmpInst, STI);
450+
451+
TmpInst.clear();
452+
453+
TmpInst.setOpcode(Mips::ADDu);
454+
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
455+
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
456+
TmpInst.addOperand(MCOperand::CreateReg(RegNo));
457+
getStreamer().EmitInstruction(TmpInst, STI);
458+
}

‎llvm/lib/Target/Mips/MipsTargetStreamer.h

+14
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ class MipsTargetStreamer : public MCTargetStreamer {
4747
virtual void emitDirectiveSetMips64() = 0;
4848
virtual void emitDirectiveSetMips64R2() = 0;
4949
virtual void emitDirectiveSetDsp() = 0;
50+
51+
// PIC support
52+
virtual void emitDirectiveCpload(unsigned RegNo) = 0;
5053
};
5154

5255
// This part is for ascii assembly output
@@ -83,6 +86,9 @@ class MipsTargetAsmStreamer : public MipsTargetStreamer {
8386
void emitDirectiveSetMips64() override;
8487
void emitDirectiveSetMips64R2() override;
8588
void emitDirectiveSetDsp() override;
89+
90+
// PIC support
91+
virtual void emitDirectiveCpload(unsigned RegNo);
8692
};
8793

8894
// This part is for ELF object output
@@ -128,6 +134,14 @@ class MipsTargetELFStreamer : public MipsTargetStreamer {
128134
void emitDirectiveSetMips64() override;
129135
void emitDirectiveSetMips64R2() override;
130136
void emitDirectiveSetDsp() override;
137+
138+
// PIC support
139+
virtual void emitDirectiveCpload(unsigned RegNo);
140+
141+
protected:
142+
bool isO32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
143+
bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
144+
bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
131145
};
132146
}
133147
#endif

‎llvm/test/MC/Mips/cpload-bad.s

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# RUN: not llvm-mc %s -arch=mips -mcpu=mips32r2 2>%t1
2+
# RUN: FileCheck %s < %t1 -check-prefix=ASM
3+
4+
.text
5+
.option pic2
6+
.set reorder
7+
.cpload $25
8+
# ASM: :[[@LINE-1]]:9: warning: .cpload in reorder section
9+
.set noreorder
10+
.cpload $32
11+
# ASM: :[[@LINE-1]]:17: error: invalid register
12+
.cpload $foo
13+
# ASM: :[[@LINE-1]]:17: error: expected register containing function address
14+
.cpload bar
15+
# ASM: :[[@LINE-1]]:17: error: expected register containing function address

‎llvm/test/MC/Mips/cpload.s

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 | FileCheck %s -check-prefix=ASM
2+
#
3+
# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -filetype=obj -o -| \
4+
# RUN: llvm-objdump -d -r -arch=mips - | \
5+
# RUN: FileCheck %s -check-prefix=OBJ
6+
7+
# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64r2 -filetype=obj -o -| \
8+
# RUN: llvm-objdump -d -r -arch=mips - | \
9+
# RUN: FileCheck %s -check-prefix=OBJ64
10+
11+
# ASM: .text
12+
# ASM: .option pic2
13+
# ASM: .set noreorder
14+
# ASM: .cpload $25
15+
# ASM: .set reorder
16+
17+
# OBJ: .text
18+
# OBJ: lui $gp, 0
19+
# OBJ: R_MIPS_HI16 _gp_disp
20+
# OBJ: addiu $gp, $gp, 0
21+
# OBJ: R_MIPS_LO16 _gp_disp
22+
# OBJ: addu $gp, $gp, $25
23+
24+
# OBJ64: .text
25+
# OBJ64-NOT: lui $gp, 0
26+
# OBJ64-NOT: addiu $gp, $gp, 0
27+
# OBJ64-NOT: addu $gp, $gp, $25
28+
29+
.text
30+
.option pic2
31+
.set noreorder
32+
.cpload $25
33+
.set reorder

0 commit comments

Comments
 (0)
Please sign in to comment.