forked from OSchip/llvm-project
[mips] Add assembler support for the .cprestore directive.
Summary: This assembler directive is used in O32 PIC to restore the current function's $gp after executing JAL's. The $gp is first stored on the stack at a user-specified offset. It has the following format: ".cprestore 8" (where 8 is the offset). This fixes llvm.org/PR20967. Patch by Toma Tabacu. Reviewers: seanbruno, tomatabacu Subscribers: brooks, seanbruno, emaste, llvm-commits Differential Revision: http://reviews.llvm.org/D6267 llvm-svn: 247897
This commit is contained in:
parent
30618f978e
commit
e2982adc0b
|
@ -116,6 +116,8 @@ class MipsAsmParser : public MCTargetAsmParser {
|
|||
// directive.
|
||||
bool IsLittleEndian;
|
||||
bool IsPicEnabled;
|
||||
bool IsCpRestoreSet;
|
||||
int CpRestoreOffset;
|
||||
|
||||
// Print a warning along with its fix-it message at the given range.
|
||||
void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
|
||||
|
@ -219,6 +221,9 @@ class MipsAsmParser : public MCTargetAsmParser {
|
|||
void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
|
||||
bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
|
||||
|
||||
void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions);
|
||||
|
||||
bool reportParseError(Twine ErrorMsg);
|
||||
bool reportParseError(SMLoc Loc, Twine ErrorMsg);
|
||||
|
||||
|
@ -231,7 +236,9 @@ class MipsAsmParser : public MCTargetAsmParser {
|
|||
bool parseSetMips0Directive();
|
||||
bool parseSetArchDirective();
|
||||
bool parseSetFeature(uint64_t Feature);
|
||||
bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
|
||||
bool parseDirectiveCpLoad(SMLoc Loc);
|
||||
bool parseDirectiveCpRestore(SMLoc Loc);
|
||||
bool parseDirectiveCPSetup();
|
||||
bool parseDirectiveNaN();
|
||||
bool parseDirectiveSet();
|
||||
|
@ -402,6 +409,9 @@ public:
|
|||
IsPicEnabled =
|
||||
(getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
|
||||
|
||||
IsCpRestoreSet = false;
|
||||
CpRestoreOffset = -1;
|
||||
|
||||
Triple TheTriple(sti.getTargetTriple());
|
||||
if ((TheTriple.getArch() == Triple::mips) ||
|
||||
(TheTriple.getArch() == Triple::mips64))
|
||||
|
@ -1355,6 +1365,7 @@ static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
|
|||
bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions) {
|
||||
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
|
||||
bool ExpandedJalSym = false;
|
||||
|
||||
Inst.setLoc(IDLoc);
|
||||
|
||||
|
@ -1581,7 +1592,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
|
|||
}
|
||||
|
||||
MCInst JalrInst;
|
||||
JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
|
||||
if (IsCpRestoreSet && inMicroMipsMode())
|
||||
JalrInst.setOpcode(Mips::JALRS_MM);
|
||||
else
|
||||
JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
|
||||
JalrInst.addOperand(MCOperand::createReg(Mips::RA));
|
||||
JalrInst.addOperand(MCOperand::createReg(Mips::T9));
|
||||
|
||||
|
@ -1590,6 +1604,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
|
|||
// and is not necessary for correctness.
|
||||
|
||||
Inst = JalrInst;
|
||||
ExpandedJalSym = true;
|
||||
}
|
||||
|
||||
if (MCID.mayLoad() || MCID.mayStore()) {
|
||||
|
@ -1800,6 +1815,28 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
|
|||
if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
|
||||
createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
|
||||
|
||||
if ((Inst.getOpcode() == Mips::JalOneReg ||
|
||||
Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
|
||||
isPicAndNotNxxAbi()) {
|
||||
if (IsCpRestoreSet) {
|
||||
// We need a NOP between the JALR and the LW:
|
||||
// If .set reorder has been used, we've already emitted a NOP.
|
||||
// If .set noreorder has been used, we need to emit a NOP at this point.
|
||||
if (!AssemblerOptions.back()->isReorder())
|
||||
createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
|
||||
|
||||
// Load the $gp from the stack.
|
||||
SmallVector<MCInst, 3> LoadInsts;
|
||||
createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
|
||||
IDLoc, LoadInsts);
|
||||
|
||||
for (const MCInst &Inst : LoadInsts)
|
||||
Instructions.push_back(Inst);
|
||||
|
||||
} else
|
||||
Warning(IDLoc, "no .cprestore used in PIC mode");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2004,7 +2041,10 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
|
|||
|
||||
if (Opcode == Mips::JalOneReg) {
|
||||
// jal $rs => jalr $rs
|
||||
if (inMicroMipsMode()) {
|
||||
if (IsCpRestoreSet && inMicroMipsMode()) {
|
||||
JalrInst.setOpcode(Mips::JALRS16_MM);
|
||||
JalrInst.addOperand(FirstRegOp);
|
||||
} else if (inMicroMipsMode()) {
|
||||
JalrInst.setOpcode(Mips::JALR16_MM);
|
||||
JalrInst.addOperand(FirstRegOp);
|
||||
} else {
|
||||
|
@ -2014,7 +2054,10 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
|
|||
}
|
||||
} else if (Opcode == Mips::JalTwoReg) {
|
||||
// jal $rd, $rs => jalr $rd, $rs
|
||||
JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
|
||||
if (IsCpRestoreSet && inMicroMipsMode())
|
||||
JalrInst.setOpcode(Mips::JALRS_MM);
|
||||
else
|
||||
JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
|
||||
JalrInst.addOperand(FirstRegOp);
|
||||
const MCOperand SecondRegOp = Inst.getOperand(1);
|
||||
JalrInst.addOperand(SecondRegOp);
|
||||
|
@ -2022,16 +2065,8 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
|
|||
Instructions.push_back(JalrInst);
|
||||
|
||||
// If .set reorder is active, emit a NOP after it.
|
||||
if (AssemblerOptions.back()->isReorder()) {
|
||||
// This is a 32-bit NOP because these 2 pseudo-instructions
|
||||
// do not have a short delay slot.
|
||||
MCInst NopInst;
|
||||
NopInst.setOpcode(Mips::SLL);
|
||||
NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
|
||||
NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
|
||||
NopInst.addOperand(MCOperand::createImm(0));
|
||||
Instructions.push_back(NopInst);
|
||||
}
|
||||
if (AssemblerOptions.back()->isReorder())
|
||||
createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -3109,6 +3144,22 @@ void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
|
|||
Instructions);
|
||||
}
|
||||
|
||||
void MipsAsmParser::createCpRestoreMemOp(
|
||||
bool IsLoad, int StackOffset, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions) {
|
||||
MCInst MemInst;
|
||||
MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
|
||||
MemInst.addOperand(MCOperand::createReg(Mips::GP));
|
||||
MemInst.addOperand(MCOperand::createReg(Mips::SP));
|
||||
MemInst.addOperand(MCOperand::createImm(StackOffset));
|
||||
|
||||
// If the offset can not fit into 16 bits, we need to expand.
|
||||
if (!isInt<16>(StackOffset))
|
||||
expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
|
||||
else
|
||||
Instructions.push_back(MemInst);
|
||||
}
|
||||
|
||||
unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
|
||||
// As described by the Mips32r2 spec, the registers Rd and Rs for
|
||||
// jalr.hb must be different.
|
||||
|
@ -4758,6 +4809,14 @@ bool MipsAsmParser::eatComma(StringRef ErrorStr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
|
||||
// In this class, it is only used for .cprestore.
|
||||
// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
|
||||
// MipsTargetELFStreamer and MipsAsmParser.
|
||||
bool MipsAsmParser::isPicAndNotNxxAbi() {
|
||||
return inPicMode() && !(isABI_N32() || isABI_N64());
|
||||
}
|
||||
|
||||
bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
|
||||
if (AssemblerOptions.back()->isReorder())
|
||||
Warning(Loc, ".cpload should be inside a noreorder section");
|
||||
|
@ -4790,6 +4849,54 @@ bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
|
||||
MCAsmParser &Parser = getParser();
|
||||
|
||||
// Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
|
||||
// is used in non-PIC mode.
|
||||
|
||||
if (inMips16Mode()) {
|
||||
reportParseError(".cprestore is not supported in Mips16 mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the stack offset value.
|
||||
const MCExpr *StackOffset;
|
||||
int64_t StackOffsetVal;
|
||||
if (Parser.parseExpression(StackOffset)) {
|
||||
reportParseError("expected stack offset value");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
|
||||
reportParseError("stack offset is not an absolute expression");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (StackOffsetVal < 0) {
|
||||
Warning(Loc, ".cprestore with negative stack offset has no effect");
|
||||
IsCpRestoreSet = false;
|
||||
} else {
|
||||
IsCpRestoreSet = true;
|
||||
CpRestoreOffset = StackOffsetVal;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Store the $gp on the stack.
|
||||
SmallVector<MCInst, 3> StoreInsts;
|
||||
createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
|
||||
StoreInsts);
|
||||
|
||||
getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
|
||||
Parser.Lex(); // Consume the EndOfStatement.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsAsmParser::parseDirectiveCPSetup() {
|
||||
MCAsmParser &Parser = getParser();
|
||||
unsigned FuncReg;
|
||||
|
@ -5322,6 +5429,8 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
|||
|
||||
if (IDVal == ".cpload")
|
||||
return parseDirectiveCpLoad(DirectiveID.getLoc());
|
||||
if (IDVal == ".cprestore")
|
||||
return parseDirectiveCpRestore(DirectiveID.getLoc());
|
||||
if (IDVal == ".dword") {
|
||||
parseDataDirective(8, DirectiveID.getLoc());
|
||||
return false;
|
||||
|
@ -5372,6 +5481,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
|||
|
||||
getTargetStreamer().emitDirectiveEnt(*Sym);
|
||||
CurrentFn = Sym;
|
||||
IsCpRestoreSet = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5400,6 +5510,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
|||
|
||||
getTargetStreamer().emitDirectiveEnd(SymbolName);
|
||||
CurrentFn = nullptr;
|
||||
IsCpRestoreSet = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5471,6 +5582,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
|||
|
||||
getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
|
||||
ReturnRegOpnd.getGPR32Reg());
|
||||
IsCpRestoreSet = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,10 @@ void MipsTargetStreamer::emitDirectiveSetHardFloat() {
|
|||
void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }
|
||||
void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
|
||||
void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
|
||||
void MipsTargetStreamer::emitDirectiveCpRestore(
|
||||
SmallVector<MCInst, 3> &StoreInsts, int Offset) {
|
||||
forbidModuleDirective();
|
||||
}
|
||||
void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
|
||||
const MCSymbol &Sym, bool IsReg) {
|
||||
}
|
||||
|
@ -358,6 +362,12 @@ void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) {
|
|||
forbidModuleDirective();
|
||||
}
|
||||
|
||||
void MipsTargetAsmStreamer::emitDirectiveCpRestore(
|
||||
SmallVector<MCInst, 3> &StoreInsts, int Offset) {
|
||||
MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset);
|
||||
OS << "\t.cprestore\t" << Offset << "\n";
|
||||
}
|
||||
|
||||
void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
|
||||
int RegOrOffset,
|
||||
const MCSymbol &Sym,
|
||||
|
@ -752,6 +762,24 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
|
|||
forbidModuleDirective();
|
||||
}
|
||||
|
||||
void MipsTargetELFStreamer::emitDirectiveCpRestore(
|
||||
SmallVector<MCInst, 3> &StoreInsts, int Offset) {
|
||||
MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset);
|
||||
// .cprestore offset
|
||||
// When PIC mode is enabled and the O32 ABI is used, this directive expands
|
||||
// to:
|
||||
// sw $gp, offset($sp)
|
||||
// and adds a corresponding LW after every JAL.
|
||||
|
||||
// Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
|
||||
// is used in non-PIC mode.
|
||||
if (!Pic || (getABI().IsN32() || getABI().IsN64()))
|
||||
return;
|
||||
|
||||
for (const MCInst &Inst : StoreInsts)
|
||||
getStreamer().EmitInstruction(Inst, STI);
|
||||
}
|
||||
|
||||
void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
|
||||
int RegOrOffset,
|
||||
const MCSymbol &Sym,
|
||||
|
|
|
@ -78,6 +78,8 @@ public:
|
|||
|
||||
// PIC support
|
||||
virtual void emitDirectiveCpLoad(unsigned RegNo);
|
||||
virtual void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts,
|
||||
int Offset);
|
||||
virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
|
||||
const MCSymbol &Sym, bool IsReg);
|
||||
|
||||
|
@ -189,6 +191,8 @@ public:
|
|||
|
||||
// PIC support
|
||||
void emitDirectiveCpLoad(unsigned RegNo) override;
|
||||
void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts,
|
||||
int Offset) override;
|
||||
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
|
||||
const MCSymbol &Sym, bool IsReg) override;
|
||||
|
||||
|
@ -238,6 +242,8 @@ public:
|
|||
|
||||
// PIC support
|
||||
void emitDirectiveCpLoad(unsigned RegNo) override;
|
||||
void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts,
|
||||
int Offset) override;
|
||||
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
|
||||
const MCSymbol &Sym, bool IsReg) override;
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# RUN: not llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic 2>%t1
|
||||
# RUN: FileCheck %s < %t1
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
.cpload $25
|
||||
|
||||
.set mips16
|
||||
.cprestore 8
|
||||
# CHECK: :[[@LINE-1]]:14: error: .cprestore is not supported in Mips16 mode
|
||||
.set nomips16
|
||||
|
||||
.cprestore
|
||||
# CHECK: :[[@LINE-1]]:13: error: expected stack offset value
|
||||
|
||||
.cprestore foo
|
||||
# CHECK: :[[@LINE-1]]:17: error: stack offset is not an absolute expression
|
||||
|
||||
.cprestore -8
|
||||
# CHECK: :[[@LINE-1]]:3: warning: .cprestore with negative stack offset has no effect
|
||||
|
||||
.cprestore 8, 35, bar
|
||||
# CHECK: :[[@LINE-1]]:15: error: unexpected token, expected end of statement
|
|
@ -0,0 +1,97 @@
|
|||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic -show-encoding | \
|
||||
# RUN: FileCheck %s
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic -filetype=obj -o -| \
|
||||
# RUN: llvm-objdump -d -r -arch=mips - | \
|
||||
# RUN: FileCheck %s -check-prefix=CHECK-FOR-STORE
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -mattr=+micromips -relocation-model=pic -show-encoding | \
|
||||
# RUN: FileCheck %s -check-prefix=MICROMIPS
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=static -show-encoding | \
|
||||
# RUN: FileCheck %s -check-prefix=NO-PIC
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips64 -target-abi n32 -relocation-model=pic -show-encoding | \
|
||||
# RUN: FileCheck %s -check-prefix=BAD-ABI -check-prefix=BAD-ABI-N32
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64 -target-abi n64 -relocation-model=pic -show-encoding | \
|
||||
# RUN: FileCheck %s -check-prefix=BAD-ABI -check-prefix=BAD-ABI-N64
|
||||
|
||||
.text
|
||||
.ent foo
|
||||
foo:
|
||||
.frame $sp, 0, $ra
|
||||
.set noreorder
|
||||
|
||||
.cpload $25
|
||||
.cprestore 8
|
||||
|
||||
jal $25
|
||||
jal $4, $25
|
||||
jal foo
|
||||
|
||||
.end foo
|
||||
|
||||
# CHECK-FOR-STORE: sw $gp, 8($sp)
|
||||
|
||||
# CHECK: .cprestore 8
|
||||
# CHECK: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# CHECK: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09]
|
||||
# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# CHECK: lw $25, %got(foo)($gp) # encoding: [0x8f,0x99,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: foo@GOT, kind: fixup_Mips_GOT_Local
|
||||
# CHECK: addiu $25, $25, %lo(foo) # encoding: [0x27,0x39,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
|
||||
# CHECK: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
# CHECK: .end foo
|
||||
|
||||
# MICROMIPS: .cprestore 8
|
||||
# MICROMIPS: jalrs16 $25 # encoding: [0x45,0xf9]
|
||||
# MICROMIPS: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08]
|
||||
|
||||
# MICROMIPS: jalrs $4, $25 # encoding: [0x00,0x99,0x4f,0x3c]
|
||||
# MICROMIPS: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08]
|
||||
|
||||
# MICROMIPS: lw $25, %got(foo)($gp) # encoding: [0xff,0x3c,A,A]
|
||||
# MICROMIPS: # fixup A - offset: 0, value: foo@GOT, kind: fixup_MICROMIPS_GOT16
|
||||
# MICROMIPS: addiu $25, $25, %lo(foo) # encoding: [0x33,0x39,A,A]
|
||||
# MICROMIPS: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16
|
||||
# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c]
|
||||
# MICROMIPS: nop # encoding: [0x0c,0x00]
|
||||
# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08]
|
||||
# MICROMIPS: .end foo
|
||||
|
||||
# NO-PIC: .cprestore 8
|
||||
# NO-PIC: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# NO-PIC: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09]
|
||||
# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# NO-PIC: jal foo # encoding: [0b000011AA,A,A,A]
|
||||
# NO-PIC: # fixup A - offset: 0, value: foo, kind: fixup_Mips_26
|
||||
# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
# NO-PIC: .end foo
|
||||
|
||||
# BAD-ABI: .cprestore 8
|
||||
# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# BAD-ABI: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09]
|
||||
# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# BAD-ABI-N32: lw $25, %got_disp(foo)($gp) # encoding: [0x8f,0x99,A,A]
|
||||
# BAD-ABI-N64: ld $25, %got_disp(foo)($gp) # encoding: [0xdf,0x99,A,A]
|
||||
# BAD-ABI: # fixup A - offset: 0, value: foo@GOT_DISP, kind: fixup_Mips_GOT_DISP
|
||||
# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
# BAD-ABI: .end foo
|
|
@ -0,0 +1,98 @@
|
|||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic -show-encoding | \
|
||||
# RUN: FileCheck %s
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic -filetype=obj -o -| \
|
||||
# RUN: llvm-objdump -d -r -arch=mips - | \
|
||||
# RUN: FileCheck %s -check-prefix=CHECK-FOR-STORE
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -mattr=+micromips -relocation-model=pic -show-encoding | \
|
||||
# RUN: FileCheck %s -check-prefix=MICROMIPS
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=static -show-encoding | \
|
||||
# RUN: FileCheck %s -check-prefix=NO-PIC
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips -mcpu=mips64 -target-abi n32 -relocation-model=pic -show-encoding | \
|
||||
# RUN: FileCheck %s -check-prefix=BAD-ABI -check-prefix=BAD-ABI-N32
|
||||
|
||||
# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64 -target-abi n64 -relocation-model=pic -show-encoding | \
|
||||
# RUN: FileCheck %s -check-prefix=BAD-ABI -check-prefix=BAD-ABI-N64
|
||||
|
||||
.text
|
||||
.ent foo
|
||||
foo:
|
||||
.frame $sp, 0, $ra
|
||||
.set noreorder
|
||||
.cpload $25
|
||||
.set reorder
|
||||
|
||||
.cprestore 8
|
||||
|
||||
jal $25
|
||||
jal $4, $25
|
||||
jal foo
|
||||
|
||||
.end foo
|
||||
|
||||
# CHECK-FOR-STORE: sw $gp, 8($sp)
|
||||
|
||||
# CHECK: .cprestore 8
|
||||
# CHECK: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# CHECK: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09]
|
||||
# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# CHECK: lw $25, %got(foo)($gp) # encoding: [0x8f,0x99,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: foo@GOT, kind: fixup_Mips_GOT_Local
|
||||
# CHECK: addiu $25, $25, %lo(foo) # encoding: [0x27,0x39,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
|
||||
# CHECK: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
# CHECK: .end foo
|
||||
|
||||
# MICROMIPS: .cprestore 8
|
||||
# MICROMIPS: jalrs16 $25 # encoding: [0x45,0xf9]
|
||||
# MICROMIPS: nop # encoding: [0x0c,0x00]
|
||||
# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08]
|
||||
|
||||
# MICROMIPS: jalrs $4, $25 # encoding: [0x00,0x99,0x4f,0x3c]
|
||||
# MICROMIPS: nop # encoding: [0x0c,0x00]
|
||||
# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08]
|
||||
|
||||
# MICROMIPS: lw $25, %got(foo)($gp) # encoding: [0xff,0x3c,A,A]
|
||||
# MICROMIPS: # fixup A - offset: 0, value: foo@GOT, kind: fixup_MICROMIPS_GOT16
|
||||
# MICROMIPS: addiu $25, $25, %lo(foo) # encoding: [0x33,0x39,A,A]
|
||||
# MICROMIPS: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16
|
||||
# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c]
|
||||
# MICROMIPS: nop # encoding: [0x0c,0x00]
|
||||
# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08]
|
||||
# MICROMIPS: .end foo
|
||||
|
||||
# NO-PIC: .cprestore 8
|
||||
# NO-PIC: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# NO-PIC: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09]
|
||||
# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# NO-PIC: jal foo # encoding: [0b000011AA,A,A,A]
|
||||
# NO-PIC: # fixup A - offset: 0, value: foo, kind: fixup_Mips_26
|
||||
# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
# NO-PIC: .end foo
|
||||
|
||||
# BAD-ABI: .cprestore 8
|
||||
# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# BAD-ABI: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09]
|
||||
# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
|
||||
# BAD-ABI-N32: lw $25, %got_disp(foo)($gp) # encoding: [0x8f,0x99,A,A]
|
||||
# BAD-ABI-N64: ld $25, %got_disp(foo)($gp) # encoding: [0xdf,0x99,A,A]
|
||||
# BAD-ABI: # fixup A - offset: 0, value: foo@GOT_DISP, kind: fixup_Mips_GOT_DISP
|
||||
# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
|
||||
# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08]
|
||||
# BAD-ABI: .end foo
|
|
@ -0,0 +1,10 @@
|
|||
# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic 2>%t1
|
||||
# RUN: FileCheck %s < %t1
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
.cpload $25
|
||||
.set reorder
|
||||
|
||||
jal $25
|
||||
# CHECK: :[[@LINE-1]]:3: warning: no .cprestore used in PIC mode
|
Loading…
Reference in New Issue