mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
[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:
parent
737de9db8e
commit
00bdeb4c54
@ -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;
|
||||
|
@ -144,6 +144,11 @@ void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask,
|
||||
OS << "," << FPUTopSavedRegOff << '\n';
|
||||
}
|
||||
|
||||
void MipsTargetAsmStreamer::emitDirectiveCpload(unsigned RegNo) {
|
||||
OS << "\t.cpload\t$"
|
||||
<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
|
||||
}
|
||||
|
||||
// This part is for ELF object output.
|
||||
MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
|
||||
const MCSubtargetInfo &STI)
|
||||
@ -402,3 +407,52 @@ void MipsTargetELFStreamer::emitDirectiveSetMips64R2() {
|
||||
void MipsTargetELFStreamer::emitDirectiveSetDsp() {
|
||||
// No action required for ELF output.
|
||||
}
|
||||
|
||||
void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) {
|
||||
// .cpload $reg
|
||||
// This directive expands to:
|
||||
// lui $gp, %hi(_gp_disp)
|
||||
// addui $gp, $gp, %lo(_gp_disp)
|
||||
// addu $gp, $gp, $reg
|
||||
// when support for position independent code is enabled.
|
||||
if (!Pic || (isN32() || isN64()))
|
||||
return;
|
||||
|
||||
// There's a GNU extension controlled by -mno-shared that allows
|
||||
// locally-binding symbols to be accessed using absolute addresses.
|
||||
// This is currently not supported. When supported -mno-shared makes
|
||||
// .cpload expand to:
|
||||
// lui $gp, %hi(__gnu_local_gp)
|
||||
// addiu $gp, $gp, %lo(__gnu_local_gp)
|
||||
|
||||
StringRef SymName("_gp_disp");
|
||||
MCAssembler &MCA = getStreamer().getAssembler();
|
||||
MCSymbol *GP_Disp = MCA.getContext().GetOrCreateSymbol(SymName);
|
||||
MCA.getOrCreateSymbolData(*GP_Disp);
|
||||
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(Mips::LUi);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::Create(
|
||||
"_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext());
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(HiSym));
|
||||
getStreamer().EmitInstruction(TmpInst, STI);
|
||||
|
||||
TmpInst.clear();
|
||||
|
||||
TmpInst.setOpcode(Mips::ADDiu);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::Create(
|
||||
"_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext());
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(LoSym));
|
||||
getStreamer().EmitInstruction(TmpInst, STI);
|
||||
|
||||
TmpInst.clear();
|
||||
|
||||
TmpInst.setOpcode(Mips::ADDu);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(RegNo));
|
||||
getStreamer().EmitInstruction(TmpInst, STI);
|
||||
}
|
||||
|
@ -47,6 +47,9 @@ public:
|
||||
virtual void emitDirectiveSetMips64() = 0;
|
||||
virtual void emitDirectiveSetMips64R2() = 0;
|
||||
virtual void emitDirectiveSetDsp() = 0;
|
||||
|
||||
// PIC support
|
||||
virtual void emitDirectiveCpload(unsigned RegNo) = 0;
|
||||
};
|
||||
|
||||
// This part is for ascii assembly output
|
||||
@ -83,6 +86,9 @@ public:
|
||||
void emitDirectiveSetMips64() override;
|
||||
void emitDirectiveSetMips64R2() override;
|
||||
void emitDirectiveSetDsp() override;
|
||||
|
||||
// PIC support
|
||||
virtual void emitDirectiveCpload(unsigned RegNo);
|
||||
};
|
||||
|
||||
// This part is for ELF object output
|
||||
@ -128,6 +134,14 @@ public:
|
||||
void emitDirectiveSetMips64() override;
|
||||
void emitDirectiveSetMips64R2() override;
|
||||
void emitDirectiveSetDsp() override;
|
||||
|
||||
// PIC support
|
||||
virtual void emitDirectiveCpload(unsigned RegNo);
|
||||
|
||||
protected:
|
||||
bool isO32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
|
||||
bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
|
||||
bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
15
test/MC/Mips/cpload-bad.s
Normal file
15
test/MC/Mips/cpload-bad.s
Normal file
@ -0,0 +1,15 @@
|
||||
# RUN: not llvm-mc %s -arch=mips -mcpu=mips32r2 2>%t1
|
||||
# RUN: FileCheck %s < %t1 -check-prefix=ASM
|
||||
|
||||
.text
|
||||
.option pic2
|
||||
.set reorder
|
||||
.cpload $25
|
||||
# ASM: :[[@LINE-1]]:9: warning: .cpload in reorder section
|
||||
.set noreorder
|
||||
.cpload $32
|
||||
# ASM: :[[@LINE-1]]:17: error: invalid register
|
||||
.cpload $foo
|
||||
# ASM: :[[@LINE-1]]:17: error: expected register containing function address
|
||||
.cpload bar
|
||||
# ASM: :[[@LINE-1]]:17: error: expected register containing function address
|
33
test/MC/Mips/cpload.s
Normal file
33
test/MC/Mips/cpload.s
Normal file
@ -0,0 +1,33 @@
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 | FileCheck %s -check-prefix=ASM
|
||||
#
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -filetype=obj -o -| \
|
||||
# RUN: llvm-objdump -d -r -arch=mips - | \
|
||||
# RUN: FileCheck %s -check-prefix=OBJ
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64r2 -filetype=obj -o -| \
|
||||
# RUN: llvm-objdump -d -r -arch=mips - | \
|
||||
# RUN: FileCheck %s -check-prefix=OBJ64
|
||||
|
||||
# ASM: .text
|
||||
# ASM: .option pic2
|
||||
# ASM: .set noreorder
|
||||
# ASM: .cpload $25
|
||||
# ASM: .set reorder
|
||||
|
||||
# OBJ: .text
|
||||
# OBJ: lui $gp, 0
|
||||
# OBJ: R_MIPS_HI16 _gp_disp
|
||||
# OBJ: addiu $gp, $gp, 0
|
||||
# OBJ: R_MIPS_LO16 _gp_disp
|
||||
# OBJ: addu $gp, $gp, $25
|
||||
|
||||
# OBJ64: .text
|
||||
# OBJ64-NOT: lui $gp, 0
|
||||
# OBJ64-NOT: addiu $gp, $gp, 0
|
||||
# OBJ64-NOT: addu $gp, $gp, $25
|
||||
|
||||
.text
|
||||
.option pic2
|
||||
.set noreorder
|
||||
.cpload $25
|
||||
.set reorder
|
Loading…
Reference in New Issue
Block a user