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);
bool isEvaluated(const MCExpr *Expr);
bool parseSetFeature(uint64_t Feature);
+ bool parseDirectiveCPLoad(SMLoc Loc);
bool parseDirectiveCPSetup();
bool parseDirectiveNaN();
bool parseDirectiveSet();
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.
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;
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;
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)
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);
+}
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
void emitDirectiveSetMips64() override;
void emitDirectiveSetMips64R2() override;
void emitDirectiveSetDsp() override;
+
+ // PIC support
+ virtual void emitDirectiveCpload(unsigned RegNo);
};
// This part is for ELF object output
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
--- /dev/null
+# 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
--- /dev/null
+# 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