forked from OSchip/llvm-project
[mips] Move expansion of .cpsetup to target streamer.
Summary: There are two functional changes: 1) The directive is not expanded for the ASM->ASM code path. 2) If PIC is not set, there's no expansion for the ASM->OBJ code path (same behaviour as GAS). Reviewers: dsanders Reviewed By: dsanders Differential Revision: http://reviews.llvm.org/D3482 llvm-svn: 207741
This commit is contained in:
parent
88fbbcaa30
commit
d92a3fa212
|
@ -2361,58 +2361,8 @@ bool MipsAsmParser::parseDirectiveCPSetup() {
|
|||
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);
|
||||
getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -149,6 +149,24 @@ void MipsTargetAsmStreamer::emitDirectiveCpload(unsigned RegNo) {
|
|||
<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
|
||||
}
|
||||
|
||||
void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
|
||||
int RegOrOffset,
|
||||
const MCSymbol &Sym,
|
||||
bool IsReg) {
|
||||
OS << "\t.cpsetup\t$"
|
||||
<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << ", ";
|
||||
|
||||
if (IsReg)
|
||||
OS << "$"
|
||||
<< StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower();
|
||||
else
|
||||
OS << RegOrOffset;
|
||||
|
||||
OS << ", ";
|
||||
|
||||
OS << Sym.getName() << "\n";
|
||||
}
|
||||
|
||||
// This part is for ELF object output.
|
||||
MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
|
||||
const MCSubtargetInfo &STI)
|
||||
|
@ -456,3 +474,58 @@ void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) {
|
|||
TmpInst.addOperand(MCOperand::CreateReg(RegNo));
|
||||
getStreamer().EmitInstruction(TmpInst, STI);
|
||||
}
|
||||
|
||||
void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
|
||||
int RegOrOffset,
|
||||
const MCSymbol &Sym,
|
||||
bool IsReg) {
|
||||
// Only N32 and N64 emit anything for .cpsetup iff PIC is set.
|
||||
if (!Pic || !(isN32() || isN64()))
|
||||
return;
|
||||
|
||||
MCAssembler &MCA = getStreamer().getAssembler();
|
||||
MCInst Inst;
|
||||
|
||||
// Either store the old $gp in a register or on the stack
|
||||
if (IsReg) {
|
||||
// move $save, $gpreg
|
||||
Inst.setOpcode(Mips::DADDu);
|
||||
Inst.addOperand(MCOperand::CreateReg(RegOrOffset));
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
|
||||
} else {
|
||||
// sd $gpreg, offset($sp)
|
||||
Inst.setOpcode(Mips::SD);
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::SP));
|
||||
Inst.addOperand(MCOperand::CreateImm(RegOrOffset));
|
||||
}
|
||||
getStreamer().EmitInstruction(Inst, STI);
|
||||
Inst.clear();
|
||||
|
||||
const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
|
||||
Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext());
|
||||
const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
|
||||
Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext());
|
||||
// lui $gp, %hi(%neg(%gp_rel(funcSym)))
|
||||
Inst.setOpcode(Mips::LUi);
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
Inst.addOperand(MCOperand::CreateExpr(HiExpr));
|
||||
getStreamer().EmitInstruction(Inst, STI);
|
||||
Inst.clear();
|
||||
|
||||
// addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
|
||||
Inst.setOpcode(Mips::ADDiu);
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
Inst.addOperand(MCOperand::CreateExpr(LoExpr));
|
||||
getStreamer().EmitInstruction(Inst, STI);
|
||||
Inst.clear();
|
||||
|
||||
// daddu $gp, $gp, $funcreg
|
||||
Inst.setOpcode(Mips::DADDu);
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::GP));
|
||||
Inst.addOperand(MCOperand::CreateReg(RegNo));
|
||||
getStreamer().EmitInstruction(Inst, STI);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ public:
|
|||
|
||||
// PIC support
|
||||
virtual void emitDirectiveCpload(unsigned RegNo) = 0;
|
||||
virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
|
||||
const MCSymbol &Sym, bool IsReg) = 0;
|
||||
};
|
||||
|
||||
// This part is for ascii assembly output
|
||||
|
@ -89,6 +91,8 @@ public:
|
|||
|
||||
// PIC support
|
||||
virtual void emitDirectiveCpload(unsigned RegNo);
|
||||
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
|
||||
const MCSymbol &Sym, bool IsReg) override;
|
||||
};
|
||||
|
||||
// This part is for ELF object output
|
||||
|
@ -137,6 +141,8 @@ public:
|
|||
|
||||
// PIC support
|
||||
virtual void emitDirectiveCpload(unsigned RegNo);
|
||||
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
|
||||
const MCSymbol &Sym, bool IsReg) override;
|
||||
|
||||
protected:
|
||||
bool isO32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
|
||||
|
|
|
@ -1,36 +1,78 @@
|
|||
# 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
|
||||
# RUN: llvm-mc -triple mips64-unknown-unknown -mattr=-n64,+o32 -filetype=obj -o - %s | \
|
||||
# RUN: llvm-objdump -d -r -arch=mips64 - | \
|
||||
# RUN: FileCheck -check-prefix=O32 %s
|
||||
|
||||
# TODO: !PIC -> no output
|
||||
# RUN: llvm-mc -triple mips64-unknown-unknown -mattr=-n64,+o32 %s | \
|
||||
# RUN: FileCheck -check-prefix=ASM %s
|
||||
|
||||
# RUN: llvm-mc -triple mips64-unknown-unknown -mattr=-n64,+n32 -filetype=obj -o - %s | \
|
||||
# RUN: llvm-objdump -d -r -arch=mips64 - | \
|
||||
# RUN: FileCheck -check-prefix=NXX -check-prefix=N32 %s
|
||||
|
||||
# RUN: llvm-mc -triple mips64-unknown-unknown -mattr=-n64,+n32 %s | \
|
||||
# RUN: FileCheck -check-prefix=ASM %s
|
||||
|
||||
# RUN: llvm-mc -triple mips64-unknown-unknown %s -filetype=obj -o - | \
|
||||
# RUN: llvm-objdump -d -r -arch=mips64 - | \
|
||||
# RUN: FileCheck -check-prefix=NXX -check-prefix=N64 %s
|
||||
|
||||
# RUN: llvm-mc -triple mips64-unknown-unknown %s | \
|
||||
# RUN: FileCheck -check-prefix=ASM %s
|
||||
|
||||
.text
|
||||
.option pic2
|
||||
t1:
|
||||
.cpsetup $25, 8, __cerror
|
||||
|
||||
# ANY-LABEL: t1:
|
||||
|
||||
# O32-NOT: __cerror
|
||||
|
||||
# FIXME: Direct object emission for N32 is still under development.
|
||||
# N32 doesn't allow 3 operations to be specified in the same relocation
|
||||
# record like N64 does.
|
||||
|
||||
# NXX: sd $gp, 8($sp)
|
||||
# NXX: lui $gp, %hi(%neg(%gp_rel(__cerror)))
|
||||
# NXX: addiu $gp, $gp, %lo(%neg(%gp_rel(__cerror)))
|
||||
# NXX: lui $gp, 0
|
||||
# NXX: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 __cerror
|
||||
# NXX: addiu $gp, $gp, 0
|
||||
# NXX: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 __cerror
|
||||
# N32: addu $gp, $gp, $25
|
||||
# N64: daddu $gp, $gp, $25
|
||||
|
||||
# ASM: .cpsetup $25, 8, __cerror
|
||||
|
||||
t2:
|
||||
# ANY-LABEL: t2:
|
||||
|
||||
.cpsetup $25, $2, __cerror
|
||||
|
||||
# O32-NOT: __cerror
|
||||
|
||||
# FIXME: Direct object emission for N32 is still under development.
|
||||
# N32 doesn't allow 3 operations to be specified in the same relocation
|
||||
# record like N64 does.
|
||||
|
||||
# NXX: move $2, $gp
|
||||
# NXX: lui $gp, %hi(%neg(%gp_rel(__cerror)))
|
||||
# NXX: addiu $gp, $gp, %lo(%neg(%gp_rel(__cerror)))
|
||||
# NXX: lui $gp, 0
|
||||
# NXX: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 __cerror
|
||||
# NXX: addiu $gp, $gp, 0
|
||||
# NXX: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 __cerror
|
||||
# N32: addu $gp, $gp, $25
|
||||
# N64: daddu $gp, $gp, $25
|
||||
|
||||
# ASM: .cpsetup $25, $2, __cerror
|
||||
|
||||
t3:
|
||||
.option pic0
|
||||
nop
|
||||
.cpsetup $25, 8, __cerror
|
||||
nop
|
||||
|
||||
# Testing that .cpsetup expands to nothing in this case
|
||||
# by checking that the next instruction after the first
|
||||
# nop is also a 'nop'.
|
||||
# NXX: nop
|
||||
# NXX-NEXT: nop
|
||||
|
||||
# ASM: nop
|
||||
# ASM: .cpsetup $25, 8, __cerror
|
||||
# ASM: nop
|
||||
|
|
Loading…
Reference in New Issue