Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -2561,6 +2561,24 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { StringRef IDVal = DirectiveID.getString(); + if (IDVal == ".cpload") { + if (Parser.getTok().isNot(AsmToken::Dollar)) + return reportParseError("unexpected token after .cpload"); + + Parser.Lex(); + + unsigned RegNo = tryParseRegister(isMips64()); + + if (RegNo == (unsigned)-1) + return reportParseError("invalid register number"); + + Parser.Lex(); + + getTargetStreamer().emitDirectiveCpload(RegNo); + + return false; + } + if (IDVal == ".ent") { // Ignore this directive for now. Parser.Lex(); Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -129,6 +129,11 @@ 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) @@ -335,3 +340,46 @@ void MipsTargetELFStreamer::emitDirectiveSetDsp() { // No action required for ELF output. } + +void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) { + //.cpload $reg + // This directive expands to + // lui gp,_gp_disp + // addui gp,gp,_gp_disp + // addu gp,gp,reg + // when support for position independant code is enabled. + if (!Pic || !(STI.getFeatureBits() & Mips::FeatureO32)) + return; + + MCAssembler &MCA = getStreamer().getAssembler(); + MCInst LUi, ADDiu; + StringRef GP_DispName("_gp_disp"); + MCSymbol *GP_Disp = MCA.getContext().GetOrCreateSymbol(GP_DispName); + MCSymbolData &GP_DispData = MCA.getOrCreateSymbolData(*GP_Disp); + const MCSymbolRefExpr *HiSymExpr, *LoSymExpr; + + (void)GP_DispData; //Silence unused variable. + + LUi.setOpcode(Mips::LUi); + LUi.addOperand(MCOperand::CreateReg(Mips::GP)); + HiSymExpr = MCSymbolRefExpr::Create("_gp_disp", + MCSymbolRefExpr::VK_Mips_ABS_HI, + getStreamer().getAssembler().getContext()); + LUi.addOperand(MCOperand::CreateExpr(HiSymExpr)); + getStreamer().EmitInstruction(LUi, STI); + + ADDiu.setOpcode(Mips::ADDiu); + ADDiu.addOperand(MCOperand::CreateReg(Mips::GP)); + ADDiu.addOperand(MCOperand::CreateReg(Mips::GP)); + LoSymExpr = MCSymbolRefExpr::Create("_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, + getStreamer().getAssembler().getContext()); + ADDiu.addOperand(MCOperand::CreateExpr(LoSymExpr)); + getStreamer().EmitInstruction(ADDiu, STI); + + MCInst ADDu; + ADDu.setOpcode(Mips::ADDu); + ADDu.addOperand(MCOperand::CreateReg(Mips::GP)); + ADDu.addOperand(MCOperand::CreateReg(Mips::GP)); + ADDu.addOperand(MCOperand::CreateReg(RegNo)); + getStreamer().EmitInstruction(ADDu, STI); +} Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -43,6 +43,9 @@ virtual void emitDirectiveSetMips32R2() = 0; virtual void emitDirectiveSetDsp() = 0; + + //PIC support + virtual void emitDirectiveCpload(unsigned RegNo) = 0; }; // This part is for ascii assembly output @@ -75,6 +78,9 @@ virtual void emitDirectiveSetMips32R2(); virtual void emitDirectiveSetDsp(); + + //PIC support + virtual void emitDirectiveCpload(unsigned RegNo); }; // This part is for ELF object output @@ -115,6 +121,9 @@ virtual void emitDirectiveSetMips32R2(); virtual void emitDirectiveSetDsp(); + + //PIC support + virtual void emitDirectiveCpload(unsigned RegNo); }; } #endif Index: test/MC/Mips/mips-pic-support.s =================================================================== --- /dev/null +++ test/MC/Mips/mips-pic-support.s @@ -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