mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
[mips] Implement .cplocal directive
This directive forces to use the alternate register for context pointer. For example, this code: .cplocal $4 jal foo expands to: ld $25, %call16(foo)($4) jalr $25 Differential Revision: https://reviews.llvm.org/D64743 llvm-svn: 366300
This commit is contained in:
parent
94c2670118
commit
f709c58051
@ -146,6 +146,7 @@ class MipsAsmParser : public MCTargetAsmParser {
|
||||
bool IsPicEnabled;
|
||||
bool IsCpRestoreSet;
|
||||
int CpRestoreOffset;
|
||||
unsigned GPReg;
|
||||
unsigned CpSaveLocation;
|
||||
/// If true, then CpSaveLocation is a register, otherwise it's an offset.
|
||||
bool CpSaveLocationIsRegister;
|
||||
@ -334,6 +335,7 @@ class MipsAsmParser : public MCTargetAsmParser {
|
||||
bool parseSetFeature(uint64_t Feature);
|
||||
bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
|
||||
bool parseDirectiveCpLoad(SMLoc Loc);
|
||||
bool parseDirectiveCpLocal(SMLoc Loc);
|
||||
bool parseDirectiveCpRestore(SMLoc Loc);
|
||||
bool parseDirectiveCPSetup();
|
||||
bool parseDirectiveCPReturn();
|
||||
@ -527,6 +529,7 @@ public:
|
||||
|
||||
IsCpRestoreSet = false;
|
||||
CpRestoreOffset = -1;
|
||||
GPReg = ABI.GetGlobalPtr();
|
||||
|
||||
const Triple &TheTriple = sti.getTargetTriple();
|
||||
IsLittleEndian = TheTriple.isLittleEndian();
|
||||
@ -2040,7 +2043,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
const MCExpr *Lo16RelocExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
|
||||
|
||||
TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
|
||||
TOut.emitRRX(Mips::LW, Mips::T9, GPReg,
|
||||
MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
|
||||
TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
|
||||
MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
|
||||
@ -2054,7 +2057,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
|
||||
|
||||
TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
|
||||
Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
|
||||
GPReg, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
|
||||
STI);
|
||||
}
|
||||
} else {
|
||||
@ -2065,7 +2068,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
const MCExpr *Call16RelocExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
|
||||
|
||||
TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
|
||||
TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, GPReg,
|
||||
MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
|
||||
}
|
||||
|
||||
@ -2893,8 +2896,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
||||
ELF::STB_LOCAL))) {
|
||||
const MCExpr *CallExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
|
||||
TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
|
||||
MCOperand::createExpr(CallExpr), IDLoc, STI);
|
||||
TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr),
|
||||
IDLoc, STI);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2933,8 +2936,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
||||
TmpReg = ATReg;
|
||||
}
|
||||
|
||||
TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
|
||||
MCOperand::createExpr(GotExpr), IDLoc, STI);
|
||||
TOut.emitRRX(Mips::LW, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc,
|
||||
STI);
|
||||
|
||||
if (LoExpr)
|
||||
TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
|
||||
@ -2969,8 +2972,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
||||
ELF::STB_LOCAL))) {
|
||||
const MCExpr *CallExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
|
||||
TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
|
||||
MCOperand::createExpr(CallExpr), IDLoc, STI);
|
||||
TOut.emitRRX(Mips::LD, DstReg, GPReg, MCOperand::createExpr(CallExpr),
|
||||
IDLoc, STI);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3012,8 +3015,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
||||
TmpReg = ATReg;
|
||||
}
|
||||
|
||||
TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
|
||||
MCOperand::createExpr(GotExpr), IDLoc, STI);
|
||||
TOut.emitRRX(Mips::LD, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc,
|
||||
STI);
|
||||
|
||||
if (LoExpr)
|
||||
TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
|
||||
@ -3243,10 +3246,10 @@ bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
|
||||
|
||||
if(isABI_O32() || isABI_N32()) {
|
||||
TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
|
||||
TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr),
|
||||
IDLoc, STI);
|
||||
} else { //isABI_N64()
|
||||
TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
|
||||
TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr),
|
||||
IDLoc, STI);
|
||||
}
|
||||
} else { //!IsPicEnabled
|
||||
@ -7241,6 +7244,40 @@ bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) {
|
||||
if (!isABI_N32() && !isABI_N64()) {
|
||||
reportParseError(".cplocal is allowed only in N32 or N64 mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
|
||||
OperandMatchResultTy ResTy = parseAnyRegister(Reg);
|
||||
if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
|
||||
reportParseError("expected register containing global pointer");
|
||||
return false;
|
||||
}
|
||||
|
||||
MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
|
||||
if (!RegOpnd.isGPRAsmReg()) {
|
||||
reportParseError(RegOpnd.getStartLoc(), "invalid register");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is not the end of the statement, report an error.
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
||||
reportParseError("unexpected token, expected end of statement");
|
||||
return false;
|
||||
}
|
||||
getParser().Lex(); // Consume the EndOfStatement.
|
||||
|
||||
unsigned NewReg = RegOpnd.getGPR32Reg();
|
||||
if (IsPicEnabled)
|
||||
GPReg = NewReg;
|
||||
|
||||
getTargetStreamer().emitDirectiveCpLocal(NewReg);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
|
||||
MCAsmParser &Parser = getParser();
|
||||
|
||||
@ -8091,6 +8128,10 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
parseDirectiveCpRestore(DirectiveID.getLoc());
|
||||
return false;
|
||||
}
|
||||
if (IDVal == ".cplocal") {
|
||||
parseDirectiveCpLocal(DirectiveID.getLoc());
|
||||
return false;
|
||||
}
|
||||
if (IDVal == ".ent") {
|
||||
StringRef SymbolName;
|
||||
|
||||
|
@ -35,7 +35,7 @@ static cl::opt<bool> RoundSectionSizes(
|
||||
} // end anonymous namespace
|
||||
|
||||
MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)
|
||||
: MCTargetStreamer(S), ModuleDirectiveAllowed(true) {
|
||||
: MCTargetStreamer(S), GPReg(Mips::GP), ModuleDirectiveAllowed(true) {
|
||||
GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
|
||||
}
|
||||
void MipsTargetStreamer::emitDirectiveSetMicroMips() {}
|
||||
@ -106,6 +106,23 @@ void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }
|
||||
void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); }
|
||||
void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
|
||||
void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
|
||||
void MipsTargetStreamer::emitDirectiveCpLocal(unsigned RegNo) {
|
||||
// .cplocal $reg
|
||||
// This directive forces to use the alternate register for context pointer.
|
||||
// For example
|
||||
// .cplocal $4
|
||||
// jal foo
|
||||
// expands to
|
||||
// ld $25, %call16(foo)($4)
|
||||
// jalr $25
|
||||
|
||||
if (!getABI().IsN32() && !getABI().IsN64())
|
||||
return;
|
||||
|
||||
GPReg = RegNo;
|
||||
|
||||
forbidModuleDirective();
|
||||
}
|
||||
bool MipsTargetStreamer::emitDirectiveCpRestore(
|
||||
int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
|
||||
const MCSubtargetInfo *STI) {
|
||||
@ -257,8 +274,7 @@ void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {
|
||||
/// Emit the $gp restore operation for .cprestore.
|
||||
void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,
|
||||
const MCSubtargetInfo *STI) {
|
||||
emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc,
|
||||
STI);
|
||||
emitLoadWithImmOffset(Mips::LW, GPReg, Mips::SP, Offset, GPReg, IDLoc, STI);
|
||||
}
|
||||
|
||||
/// Emit a store instruction with an immediate offset.
|
||||
@ -665,6 +681,12 @@ void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) {
|
||||
forbidModuleDirective();
|
||||
}
|
||||
|
||||
void MipsTargetAsmStreamer::emitDirectiveCpLocal(unsigned RegNo) {
|
||||
OS << "\t.cplocal\t$"
|
||||
<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
|
||||
MipsTargetStreamer::emitDirectiveCpLocal(RegNo);
|
||||
}
|
||||
|
||||
bool MipsTargetAsmStreamer::emitDirectiveCpRestore(
|
||||
int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
|
||||
const MCSubtargetInfo *STI) {
|
||||
@ -1135,7 +1157,7 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
|
||||
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(Mips::LUi);
|
||||
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
|
||||
TmpInst.addOperand(MCOperand::createReg(GPReg));
|
||||
const MCExpr *HiSym = MipsMCExpr::create(
|
||||
MipsMCExpr::MEK_HI,
|
||||
MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
|
||||
@ -1147,8 +1169,8 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
|
||||
TmpInst.clear();
|
||||
|
||||
TmpInst.setOpcode(Mips::ADDiu);
|
||||
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
|
||||
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
|
||||
TmpInst.addOperand(MCOperand::createReg(GPReg));
|
||||
TmpInst.addOperand(MCOperand::createReg(GPReg));
|
||||
const MCExpr *LoSym = MipsMCExpr::create(
|
||||
MipsMCExpr::MEK_LO,
|
||||
MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
|
||||
@ -1160,14 +1182,19 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
|
||||
TmpInst.clear();
|
||||
|
||||
TmpInst.setOpcode(Mips::ADDu);
|
||||
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
|
||||
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
|
||||
TmpInst.addOperand(MCOperand::createReg(GPReg));
|
||||
TmpInst.addOperand(MCOperand::createReg(GPReg));
|
||||
TmpInst.addOperand(MCOperand::createReg(RegNo));
|
||||
getStreamer().EmitInstruction(TmpInst, STI);
|
||||
|
||||
forbidModuleDirective();
|
||||
}
|
||||
|
||||
void MipsTargetELFStreamer::emitDirectiveCpLocal(unsigned RegNo) {
|
||||
if (Pic)
|
||||
MipsTargetStreamer::emitDirectiveCpLocal(RegNo);
|
||||
}
|
||||
|
||||
bool MipsTargetELFStreamer::emitDirectiveCpRestore(
|
||||
int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
|
||||
const MCSubtargetInfo *STI) {
|
||||
@ -1184,7 +1211,7 @@ bool MipsTargetELFStreamer::emitDirectiveCpRestore(
|
||||
return true;
|
||||
|
||||
// Store the $gp on the stack.
|
||||
emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc,
|
||||
emitStoreWithImmOffset(Mips::SW, GPReg, Mips::SP, Offset, GetATReg, IDLoc,
|
||||
STI);
|
||||
return true;
|
||||
}
|
||||
@ -1205,10 +1232,10 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
|
||||
// Either store the old $gp in a register or on the stack
|
||||
if (IsReg) {
|
||||
// move $save, $gpreg
|
||||
emitRRR(Mips::OR64, RegOrOffset, Mips::GP, Mips::ZERO, SMLoc(), &STI);
|
||||
emitRRR(Mips::OR64, RegOrOffset, GPReg, Mips::ZERO, SMLoc(), &STI);
|
||||
} else {
|
||||
// sd $gpreg, offset($sp)
|
||||
emitRRI(Mips::SD, Mips::GP, Mips::SP, RegOrOffset, SMLoc(), &STI);
|
||||
emitRRI(Mips::SD, GPReg, Mips::SP, RegOrOffset, SMLoc(), &STI);
|
||||
}
|
||||
|
||||
if (getABI().IsN32()) {
|
||||
@ -1221,11 +1248,11 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
|
||||
MCA.getContext());
|
||||
|
||||
// lui $gp, %hi(__gnu_local_gp)
|
||||
emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
|
||||
emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
|
||||
|
||||
// addiu $gp, $gp, %lo(__gnu_local_gp)
|
||||
emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
|
||||
SMLoc(), &STI);
|
||||
emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(),
|
||||
&STI);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1238,14 +1265,14 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
|
||||
MCA.getContext());
|
||||
|
||||
// lui $gp, %hi(%neg(%gp_rel(funcSym)))
|
||||
emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
|
||||
emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
|
||||
|
||||
// addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
|
||||
emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
|
||||
SMLoc(), &STI);
|
||||
emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(),
|
||||
&STI);
|
||||
|
||||
// daddu $gp, $gp, $funcreg
|
||||
emitRRR(Mips::DADDu, Mips::GP, Mips::GP, RegNo, SMLoc(), &STI);
|
||||
emitRRR(Mips::DADDu, GPReg, GPReg, RegNo, SMLoc(), &STI);
|
||||
}
|
||||
|
||||
void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
|
||||
@ -1258,12 +1285,12 @@ void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
|
||||
// Either restore the old $gp from a register or on the stack
|
||||
if (SaveLocationIsRegister) {
|
||||
Inst.setOpcode(Mips::OR);
|
||||
Inst.addOperand(MCOperand::createReg(Mips::GP));
|
||||
Inst.addOperand(MCOperand::createReg(GPReg));
|
||||
Inst.addOperand(MCOperand::createReg(SaveLocation));
|
||||
Inst.addOperand(MCOperand::createReg(Mips::ZERO));
|
||||
} else {
|
||||
Inst.setOpcode(Mips::LD);
|
||||
Inst.addOperand(MCOperand::createReg(Mips::GP));
|
||||
Inst.addOperand(MCOperand::createReg(GPReg));
|
||||
Inst.addOperand(MCOperand::createReg(Mips::SP));
|
||||
Inst.addOperand(MCOperand::createImm(SaveLocation));
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ public:
|
||||
|
||||
// PIC support
|
||||
virtual void emitDirectiveCpLoad(unsigned RegNo);
|
||||
virtual void emitDirectiveCpLocal(unsigned RegNo);
|
||||
virtual bool emitDirectiveCpRestore(int Offset,
|
||||
function_ref<unsigned()> GetATReg,
|
||||
SMLoc IDLoc, const MCSubtargetInfo *STI);
|
||||
@ -199,6 +200,7 @@ protected:
|
||||
bool FrameInfoSet;
|
||||
int FrameOffset;
|
||||
unsigned FrameReg;
|
||||
unsigned GPReg;
|
||||
unsigned ReturnReg;
|
||||
|
||||
private:
|
||||
@ -274,6 +276,7 @@ public:
|
||||
|
||||
// PIC support
|
||||
void emitDirectiveCpLoad(unsigned RegNo) override;
|
||||
void emitDirectiveCpLocal(unsigned RegNo) override;
|
||||
|
||||
/// Emit a .cprestore directive. If the offset is out of range then it will
|
||||
/// be synthesized using the assembler temporary.
|
||||
@ -345,6 +348,7 @@ public:
|
||||
|
||||
// PIC support
|
||||
void emitDirectiveCpLoad(unsigned RegNo) override;
|
||||
void emitDirectiveCpLocal(unsigned RegNo) override;
|
||||
bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg,
|
||||
SMLoc IDLoc, const MCSubtargetInfo *STI) override;
|
||||
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
|
||||
|
20
test/MC/Mips/cplocal-bad.s
Normal file
20
test/MC/Mips/cplocal-bad.s
Normal file
@ -0,0 +1,20 @@
|
||||
# RUN: not llvm-mc -triple=mips-unknown-linux-gnu %s 2>&1 \
|
||||
# RUN: | FileCheck -check-prefix=O32 %s
|
||||
# RUN: not llvm-mc -triple=mips64-unknown-linux-gnuabin32 %s 2>&1 \
|
||||
# RUN: | FileCheck -check-prefix=NABI %s
|
||||
# RUN: not llvm-mc -triple=mips64-unknown-linux-gnu %s 2>&1 \
|
||||
# RUN: | FileCheck -check-prefix=NABI %s
|
||||
|
||||
.text
|
||||
.cplocal $32
|
||||
# O32: :[[@LINE-1]]:{{[0-9]+}}: error: .cplocal is allowed only in N32 or N64 mode
|
||||
# NABI: :[[@LINE-2]]:{{[0-9]+}}: error: invalid register
|
||||
.cplocal $foo
|
||||
# O32: :[[@LINE-1]]:{{[0-9]+}}: error: .cplocal is allowed only in N32 or N64 mode
|
||||
# NABI: :[[@LINE-2]]:{{[0-9]+}}: error: expected register containing global pointer
|
||||
.cplocal bar
|
||||
# O32: :[[@LINE-1]]:{{[0-9]+}}: error: .cplocal is allowed only in N32 or N64 mode
|
||||
# NABI: :[[@LINE-2]]:{{[0-9]+}}: error: expected register containing global pointer
|
||||
.cplocal $25 foobar
|
||||
# O32: :[[@LINE-1]]:{{[0-9]+}}: error: .cplocal is allowed only in N32 or N64 mode
|
||||
# NABI: :[[@LINE-2]]:{{[0-9]+}}: error: unexpected token, expected end of statement
|
45
test/MC/Mips/cplocal.s
Normal file
45
test/MC/Mips/cplocal.s
Normal file
@ -0,0 +1,45 @@
|
||||
# RUN: llvm-mc -triple=mips64-unknown-linux-gnuabin32 -position-independent %s \
|
||||
# RUN: | FileCheck -check-prefix=ASM-PIC32 %s
|
||||
# RUN: llvm-mc -triple=mips64-unknown-linux-gnu -position-independent %s \
|
||||
# RUN: | FileCheck -check-prefix=ASM-PIC64 %s
|
||||
# RUN: llvm-mc -triple=mips64-unknown-linux-gnuabin32 %s \
|
||||
# RUN: | FileCheck -check-prefix=ASM-NPIC %s
|
||||
# RUN: llvm-mc -triple=mips64-unknown-linux-gnu %s \
|
||||
# RUN: | FileCheck -check-prefix=ASM-NPIC %s
|
||||
|
||||
# RUN: llvm-mc -triple=mips64-unknown-linux-gnuabin32 \
|
||||
# RUN: -position-independent -filetype=obj -o - %s \
|
||||
# RUN: | llvm-objdump -d -r - | FileCheck -check-prefix=OBJ32 %s
|
||||
# RUN: llvm-mc -triple=mips64-unknown-linux-gnu \
|
||||
# RUN: -position-independent -filetype=obj -o - %s \
|
||||
# RUN: | llvm-objdump -d -r - | FileCheck -check-prefix=OBJ64 %s
|
||||
|
||||
# ASM-PIC32: .text
|
||||
# ASM-PIC32: .cplocal $4
|
||||
# ASM-PIC32: lw $25, %call16(foo)($4)
|
||||
# ASM-PIC32: jalr $25
|
||||
|
||||
# ASM-PIC64: .text
|
||||
# ASM-PIC64: .cplocal $4
|
||||
# ASM-PIC64: ld $25, %call16(foo)($4)
|
||||
# ASM-PIC64: jalr $25
|
||||
|
||||
# ASM-NPIC: .text
|
||||
# ASM-NPIC: .cplocal $4
|
||||
# ASM-NPIC: jal foo
|
||||
|
||||
# OBJ32: lw $25, 0($4)
|
||||
# OBJ32: R_MIPS_CALL16 foo
|
||||
# OBJ32: jalr $25
|
||||
# OBJ32: R_MIPS_JALR foo
|
||||
|
||||
# OBJ64: ld $25, 0($4)
|
||||
# OBJ64: R_MIPS_CALL16/R_MIPS_NONE/R_MIPS_NONE foo
|
||||
# OBJ64: jalr $25
|
||||
# OBJ64: R_MIPS_JALR/R_MIPS_NONE/R_MIPS_NONE foo
|
||||
|
||||
.text
|
||||
.cplocal $4
|
||||
jal foo
|
||||
foo:
|
||||
nop
|
Loading…
Reference in New Issue
Block a user