Path: blob/main/contrib/llvm-project/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
35294 views
//===-- MipsTargetStreamer.cpp - Mips Target Streamer Methods -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file provides Mips specific target streamer methods.9//10//===----------------------------------------------------------------------===//1112#include "MipsTargetStreamer.h"13#include "MCTargetDesc/MipsABIInfo.h"14#include "MipsELFStreamer.h"15#include "MipsInstPrinter.h"16#include "MipsMCExpr.h"17#include "MipsMCTargetDesc.h"18#include "llvm/BinaryFormat/ELF.h"19#include "llvm/MC/MCAssembler.h"20#include "llvm/MC/MCContext.h"21#include "llvm/MC/MCObjectFileInfo.h"22#include "llvm/MC/MCSectionELF.h"23#include "llvm/MC/MCSubtargetInfo.h"24#include "llvm/MC/MCSymbolELF.h"25#include "llvm/Support/Casting.h"26#include "llvm/Support/CommandLine.h"27#include "llvm/Support/ErrorHandling.h"28#include "llvm/Support/FormattedStream.h"2930using namespace llvm;3132namespace {33static cl::opt<bool> RoundSectionSizes(34"mips-round-section-sizes", cl::init(false),35cl::desc("Round section sizes up to the section alignment"), cl::Hidden);36} // end anonymous namespace3738static bool isMicroMips(const MCSubtargetInfo *STI) {39return STI->hasFeature(Mips::FeatureMicroMips);40}4142static bool isMips32r6(const MCSubtargetInfo *STI) {43return STI->hasFeature(Mips::FeatureMips32r6);44}4546MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)47: MCTargetStreamer(S), GPReg(Mips::GP), ModuleDirectiveAllowed(true) {48GPRInfoSet = FPRInfoSet = FrameInfoSet = false;49}50void MipsTargetStreamer::emitDirectiveSetMicroMips() {}51void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {}52void MipsTargetStreamer::setUsesMicroMips() {}53void MipsTargetStreamer::emitDirectiveSetMips16() {}54void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); }55void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); }56void MipsTargetStreamer::emitDirectiveSetNoReorder() {}57void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); }58void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); }59void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); }60void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); }61void MipsTargetStreamer::emitDirectiveSetMt() {}62void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); }63void MipsTargetStreamer::emitDirectiveSetCRC() {}64void MipsTargetStreamer::emitDirectiveSetNoCRC() {}65void MipsTargetStreamer::emitDirectiveSetVirt() {}66void MipsTargetStreamer::emitDirectiveSetNoVirt() {}67void MipsTargetStreamer::emitDirectiveSetGINV() {}68void MipsTargetStreamer::emitDirectiveSetNoGINV() {}69void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); }70void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {71forbidModuleDirective();72}73void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); }74void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {}75void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {}76void MipsTargetStreamer::emitDirectiveAbiCalls() {}77void MipsTargetStreamer::emitDirectiveNaN2008() {}78void MipsTargetStreamer::emitDirectiveNaNLegacy() {}79void MipsTargetStreamer::emitDirectiveOptionPic0() {}80void MipsTargetStreamer::emitDirectiveOptionPic2() {}81void MipsTargetStreamer::emitDirectiveInsn() { forbidModuleDirective(); }82void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize,83unsigned ReturnReg) {}84void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {}85void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) {86}87void MipsTargetStreamer::emitDirectiveSetArch(StringRef Arch) {88forbidModuleDirective();89}90void MipsTargetStreamer::emitDirectiveSetMips0() { forbidModuleDirective(); }91void MipsTargetStreamer::emitDirectiveSetMips1() { forbidModuleDirective(); }92void MipsTargetStreamer::emitDirectiveSetMips2() { forbidModuleDirective(); }93void MipsTargetStreamer::emitDirectiveSetMips3() { forbidModuleDirective(); }94void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); }95void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); }96void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); }97void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); }98void MipsTargetStreamer::emitDirectiveSetMips32R3() { forbidModuleDirective(); }99void MipsTargetStreamer::emitDirectiveSetMips32R5() { forbidModuleDirective(); }100void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); }101void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); }102void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); }103void MipsTargetStreamer::emitDirectiveSetMips64R3() { forbidModuleDirective(); }104void MipsTargetStreamer::emitDirectiveSetMips64R5() { forbidModuleDirective(); }105void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); }106void MipsTargetStreamer::emitDirectiveSetPop() { forbidModuleDirective(); }107void MipsTargetStreamer::emitDirectiveSetPush() { forbidModuleDirective(); }108void MipsTargetStreamer::emitDirectiveSetSoftFloat() {109forbidModuleDirective();110}111void MipsTargetStreamer::emitDirectiveSetHardFloat() {112forbidModuleDirective();113}114void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }115void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); }116void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }117void MipsTargetStreamer::emitDirectiveSetMips3D() { forbidModuleDirective(); }118void MipsTargetStreamer::emitDirectiveSetNoMips3D() { forbidModuleDirective(); }119void MipsTargetStreamer::emitDirectiveCpAdd(unsigned RegNo) {}120void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}121void MipsTargetStreamer::emitDirectiveCpLocal(unsigned RegNo) {122// .cplocal $reg123// This directive forces to use the alternate register for context pointer.124// For example125// .cplocal $4126// jal foo127// expands to128// ld $25, %call16(foo)($4)129// jalr $25130131if (!getABI().IsN32() && !getABI().IsN64())132return;133134GPReg = RegNo;135136forbidModuleDirective();137}138bool MipsTargetStreamer::emitDirectiveCpRestore(139int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,140const MCSubtargetInfo *STI) {141forbidModuleDirective();142return true;143}144void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,145const MCSymbol &Sym, bool IsReg) {146}147void MipsTargetStreamer::emitDirectiveCpreturn(unsigned SaveLocation,148bool SaveLocationIsRegister) {}149150void MipsTargetStreamer::emitDirectiveModuleFP() {}151152void MipsTargetStreamer::emitDirectiveModuleOddSPReg() {153if (!ABIFlagsSection.OddSPReg && !ABIFlagsSection.Is32BitABI)154report_fatal_error("+nooddspreg is only valid for O32");155}156void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {}157void MipsTargetStreamer::emitDirectiveModuleHardFloat() {}158void MipsTargetStreamer::emitDirectiveModuleMT() {}159void MipsTargetStreamer::emitDirectiveModuleCRC() {}160void MipsTargetStreamer::emitDirectiveModuleNoCRC() {}161void MipsTargetStreamer::emitDirectiveModuleVirt() {}162void MipsTargetStreamer::emitDirectiveModuleNoVirt() {}163void MipsTargetStreamer::emitDirectiveModuleGINV() {}164void MipsTargetStreamer::emitDirectiveModuleNoGINV() {}165void MipsTargetStreamer::emitDirectiveSetFp(166MipsABIFlagsSection::FpABIKind Value) {167forbidModuleDirective();168}169void MipsTargetStreamer::emitDirectiveSetOddSPReg() { forbidModuleDirective(); }170void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() {171forbidModuleDirective();172}173174void MipsTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,175const MCSubtargetInfo *STI) {176MCInst TmpInst;177TmpInst.setOpcode(Opcode);178TmpInst.addOperand(MCOperand::createReg(Reg0));179TmpInst.setLoc(IDLoc);180getStreamer().emitInstruction(TmpInst, *STI);181}182183void MipsTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1,184SMLoc IDLoc, const MCSubtargetInfo *STI) {185MCInst TmpInst;186TmpInst.setOpcode(Opcode);187TmpInst.addOperand(MCOperand::createReg(Reg0));188TmpInst.addOperand(Op1);189TmpInst.setLoc(IDLoc);190getStreamer().emitInstruction(TmpInst, *STI);191}192193void MipsTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm,194SMLoc IDLoc, const MCSubtargetInfo *STI) {195emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI);196}197198void MipsTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,199SMLoc IDLoc, const MCSubtargetInfo *STI) {200emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI);201}202203void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2,204SMLoc IDLoc, const MCSubtargetInfo *STI) {205MCInst TmpInst;206TmpInst.setOpcode(Opcode);207TmpInst.addOperand(MCOperand::createImm(Imm1));208TmpInst.addOperand(MCOperand::createImm(Imm2));209TmpInst.setLoc(IDLoc);210getStreamer().emitInstruction(TmpInst, *STI);211}212213void MipsTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,214MCOperand Op2, SMLoc IDLoc,215const MCSubtargetInfo *STI) {216MCInst TmpInst;217TmpInst.setOpcode(Opcode);218TmpInst.addOperand(MCOperand::createReg(Reg0));219TmpInst.addOperand(MCOperand::createReg(Reg1));220TmpInst.addOperand(Op2);221TmpInst.setLoc(IDLoc);222getStreamer().emitInstruction(TmpInst, *STI);223}224225void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,226unsigned Reg2, SMLoc IDLoc,227const MCSubtargetInfo *STI) {228emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI);229}230231void MipsTargetStreamer::emitRRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,232unsigned Reg2, MCOperand Op3, SMLoc IDLoc,233const MCSubtargetInfo *STI) {234MCInst TmpInst;235TmpInst.setOpcode(Opcode);236TmpInst.addOperand(MCOperand::createReg(Reg0));237TmpInst.addOperand(MCOperand::createReg(Reg1));238TmpInst.addOperand(MCOperand::createReg(Reg2));239TmpInst.addOperand(Op3);240TmpInst.setLoc(IDLoc);241getStreamer().emitInstruction(TmpInst, *STI);242}243244void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,245int16_t Imm, SMLoc IDLoc,246const MCSubtargetInfo *STI) {247emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI);248}249250void MipsTargetStreamer::emitRRIII(unsigned Opcode, unsigned Reg0,251unsigned Reg1, int16_t Imm0, int16_t Imm1,252int16_t Imm2, SMLoc IDLoc,253const MCSubtargetInfo *STI) {254MCInst TmpInst;255TmpInst.setOpcode(Opcode);256TmpInst.addOperand(MCOperand::createReg(Reg0));257TmpInst.addOperand(MCOperand::createReg(Reg1));258TmpInst.addOperand(MCOperand::createImm(Imm0));259TmpInst.addOperand(MCOperand::createImm(Imm1));260TmpInst.addOperand(MCOperand::createImm(Imm2));261TmpInst.setLoc(IDLoc);262getStreamer().emitInstruction(TmpInst, *STI);263}264265void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg,266unsigned TrgReg, bool Is64Bit,267const MCSubtargetInfo *STI) {268emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),269STI);270}271272void MipsTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg,273int16_t ShiftAmount, SMLoc IDLoc,274const MCSubtargetInfo *STI) {275if (ShiftAmount >= 32) {276emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI);277return;278}279280emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI);281}282283void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,284const MCSubtargetInfo *STI) {285// The default case of `nop` is `sll $zero, $zero, 0`.286unsigned Opc = Mips::SLL;287if (isMicroMips(STI) && hasShortDelaySlot) {288Opc = isMips32r6(STI) ? Mips::MOVE16_MMR6 : Mips::MOVE16_MM;289emitRR(Opc, Mips::ZERO, Mips::ZERO, IDLoc, STI);290return;291}292293if (isMicroMips(STI))294Opc = isMips32r6(STI) ? Mips::SLL_MMR6 : Mips::SLL_MM;295296emitRRI(Opc, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);297}298299void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {300if (isMicroMips(STI))301emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI);302else303emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);304}305306/// Emit the $gp restore operation for .cprestore.307void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,308const MCSubtargetInfo *STI) {309emitLoadWithImmOffset(Mips::LW, GPReg, Mips::SP, Offset, GPReg, IDLoc, STI);310}311312/// Emit a store instruction with an immediate offset.313void MipsTargetStreamer::emitStoreWithImmOffset(314unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset,315function_ref<unsigned()> GetATReg, SMLoc IDLoc,316const MCSubtargetInfo *STI) {317if (isInt<16>(Offset)) {318emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI);319return;320}321322// sw $8, offset($8) => lui $at, %hi(offset)323// add $at, $at, $8324// sw $8, %lo(offset)($at)325326unsigned ATReg = GetATReg();327if (!ATReg)328return;329330unsigned LoOffset = Offset & 0x0000ffff;331unsigned HiOffset = (Offset & 0xffff0000) >> 16;332333// If msb of LoOffset is 1(negative number) we must increment HiOffset334// to account for the sign-extension of the low part.335if (LoOffset & 0x8000)336HiOffset++;337338// Generate the base address in ATReg.339emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI);340if (BaseReg != Mips::ZERO)341emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);342// Emit the store with the adjusted base and offset.343emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI);344}345346/// Emit a load instruction with an immediate offset. DstReg and TmpReg are347/// permitted to be the same register iff DstReg is distinct from BaseReg and348/// DstReg is a GPR. It is the callers responsibility to identify such cases349/// and pass the appropriate register in TmpReg.350void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg,351unsigned BaseReg, int64_t Offset,352unsigned TmpReg, SMLoc IDLoc,353const MCSubtargetInfo *STI) {354if (isInt<16>(Offset)) {355emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI);356return;357}358359// 1) lw $8, offset($9) => lui $8, %hi(offset)360// add $8, $8, $9361// lw $8, %lo(offset)($9)362// 2) lw $8, offset($8) => lui $at, %hi(offset)363// add $at, $at, $8364// lw $8, %lo(offset)($at)365366unsigned LoOffset = Offset & 0x0000ffff;367unsigned HiOffset = (Offset & 0xffff0000) >> 16;368369// If msb of LoOffset is 1(negative number) we must increment HiOffset370// to account for the sign-extension of the low part.371if (LoOffset & 0x8000)372HiOffset++;373374// Generate the base address in TmpReg.375emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI);376if (BaseReg != Mips::ZERO)377emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);378// Emit the load with the adjusted base and offset.379emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI);380}381382MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,383formatted_raw_ostream &OS)384: MipsTargetStreamer(S), OS(OS) {}385386void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() {387OS << "\t.set\tmicromips\n";388forbidModuleDirective();389}390391void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() {392OS << "\t.set\tnomicromips\n";393forbidModuleDirective();394}395396void MipsTargetAsmStreamer::emitDirectiveSetMips16() {397OS << "\t.set\tmips16\n";398forbidModuleDirective();399}400401void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() {402OS << "\t.set\tnomips16\n";403MipsTargetStreamer::emitDirectiveSetNoMips16();404}405406void MipsTargetAsmStreamer::emitDirectiveSetReorder() {407OS << "\t.set\treorder\n";408MipsTargetStreamer::emitDirectiveSetReorder();409}410411void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() {412OS << "\t.set\tnoreorder\n";413forbidModuleDirective();414}415416void MipsTargetAsmStreamer::emitDirectiveSetMacro() {417OS << "\t.set\tmacro\n";418MipsTargetStreamer::emitDirectiveSetMacro();419}420421void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() {422OS << "\t.set\tnomacro\n";423MipsTargetStreamer::emitDirectiveSetNoMacro();424}425426void MipsTargetAsmStreamer::emitDirectiveSetMsa() {427OS << "\t.set\tmsa\n";428MipsTargetStreamer::emitDirectiveSetMsa();429}430431void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() {432OS << "\t.set\tnomsa\n";433MipsTargetStreamer::emitDirectiveSetNoMsa();434}435436void MipsTargetAsmStreamer::emitDirectiveSetMt() {437OS << "\t.set\tmt\n";438MipsTargetStreamer::emitDirectiveSetMt();439}440441void MipsTargetAsmStreamer::emitDirectiveSetNoMt() {442OS << "\t.set\tnomt\n";443MipsTargetStreamer::emitDirectiveSetNoMt();444}445446void MipsTargetAsmStreamer::emitDirectiveSetCRC() {447OS << "\t.set\tcrc\n";448MipsTargetStreamer::emitDirectiveSetCRC();449}450451void MipsTargetAsmStreamer::emitDirectiveSetNoCRC() {452OS << "\t.set\tnocrc\n";453MipsTargetStreamer::emitDirectiveSetNoCRC();454}455456void MipsTargetAsmStreamer::emitDirectiveSetVirt() {457OS << "\t.set\tvirt\n";458MipsTargetStreamer::emitDirectiveSetVirt();459}460461void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() {462OS << "\t.set\tnovirt\n";463MipsTargetStreamer::emitDirectiveSetNoVirt();464}465466void MipsTargetAsmStreamer::emitDirectiveSetGINV() {467OS << "\t.set\tginv\n";468MipsTargetStreamer::emitDirectiveSetGINV();469}470471void MipsTargetAsmStreamer::emitDirectiveSetNoGINV() {472OS << "\t.set\tnoginv\n";473MipsTargetStreamer::emitDirectiveSetNoGINV();474}475476void MipsTargetAsmStreamer::emitDirectiveSetAt() {477OS << "\t.set\tat\n";478MipsTargetStreamer::emitDirectiveSetAt();479}480481void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {482OS << "\t.set\tat=$" << Twine(RegNo) << "\n";483MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo);484}485486void MipsTargetAsmStreamer::emitDirectiveSetNoAt() {487OS << "\t.set\tnoat\n";488MipsTargetStreamer::emitDirectiveSetNoAt();489}490491void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) {492OS << "\t.end\t" << Name << '\n';493}494495void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {496OS << "\t.ent\t" << Symbol.getName() << '\n';497}498499void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; }500501void MipsTargetAsmStreamer::emitDirectiveNaN2008() { OS << "\t.nan\t2008\n"; }502503void MipsTargetAsmStreamer::emitDirectiveNaNLegacy() {504OS << "\t.nan\tlegacy\n";505}506507void MipsTargetAsmStreamer::emitDirectiveOptionPic0() {508OS << "\t.option\tpic0\n";509}510511void MipsTargetAsmStreamer::emitDirectiveOptionPic2() {512OS << "\t.option\tpic2\n";513}514515void MipsTargetAsmStreamer::emitDirectiveInsn() {516MipsTargetStreamer::emitDirectiveInsn();517OS << "\t.insn\n";518}519520void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize,521unsigned ReturnReg) {522OS << "\t.frame\t$"523<< StringRef(MipsInstPrinter::getRegisterName(StackReg)).lower() << ","524<< StackSize << ",$"525<< StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n';526}527528void MipsTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) {529OS << "\t.set arch=" << Arch << "\n";530MipsTargetStreamer::emitDirectiveSetArch(Arch);531}532533void MipsTargetAsmStreamer::emitDirectiveSetMips0() {534OS << "\t.set\tmips0\n";535MipsTargetStreamer::emitDirectiveSetMips0();536}537538void MipsTargetAsmStreamer::emitDirectiveSetMips1() {539OS << "\t.set\tmips1\n";540MipsTargetStreamer::emitDirectiveSetMips1();541}542543void MipsTargetAsmStreamer::emitDirectiveSetMips2() {544OS << "\t.set\tmips2\n";545MipsTargetStreamer::emitDirectiveSetMips2();546}547548void MipsTargetAsmStreamer::emitDirectiveSetMips3() {549OS << "\t.set\tmips3\n";550MipsTargetStreamer::emitDirectiveSetMips3();551}552553void MipsTargetAsmStreamer::emitDirectiveSetMips4() {554OS << "\t.set\tmips4\n";555MipsTargetStreamer::emitDirectiveSetMips4();556}557558void MipsTargetAsmStreamer::emitDirectiveSetMips5() {559OS << "\t.set\tmips5\n";560MipsTargetStreamer::emitDirectiveSetMips5();561}562563void MipsTargetAsmStreamer::emitDirectiveSetMips32() {564OS << "\t.set\tmips32\n";565MipsTargetStreamer::emitDirectiveSetMips32();566}567568void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() {569OS << "\t.set\tmips32r2\n";570MipsTargetStreamer::emitDirectiveSetMips32R2();571}572573void MipsTargetAsmStreamer::emitDirectiveSetMips32R3() {574OS << "\t.set\tmips32r3\n";575MipsTargetStreamer::emitDirectiveSetMips32R3();576}577578void MipsTargetAsmStreamer::emitDirectiveSetMips32R5() {579OS << "\t.set\tmips32r5\n";580MipsTargetStreamer::emitDirectiveSetMips32R5();581}582583void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() {584OS << "\t.set\tmips32r6\n";585MipsTargetStreamer::emitDirectiveSetMips32R6();586}587588void MipsTargetAsmStreamer::emitDirectiveSetMips64() {589OS << "\t.set\tmips64\n";590MipsTargetStreamer::emitDirectiveSetMips64();591}592593void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() {594OS << "\t.set\tmips64r2\n";595MipsTargetStreamer::emitDirectiveSetMips64R2();596}597598void MipsTargetAsmStreamer::emitDirectiveSetMips64R3() {599OS << "\t.set\tmips64r3\n";600MipsTargetStreamer::emitDirectiveSetMips64R3();601}602603void MipsTargetAsmStreamer::emitDirectiveSetMips64R5() {604OS << "\t.set\tmips64r5\n";605MipsTargetStreamer::emitDirectiveSetMips64R5();606}607608void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() {609OS << "\t.set\tmips64r6\n";610MipsTargetStreamer::emitDirectiveSetMips64R6();611}612613void MipsTargetAsmStreamer::emitDirectiveSetDsp() {614OS << "\t.set\tdsp\n";615MipsTargetStreamer::emitDirectiveSetDsp();616}617618void MipsTargetAsmStreamer::emitDirectiveSetDspr2() {619OS << "\t.set\tdspr2\n";620MipsTargetStreamer::emitDirectiveSetDspr2();621}622623void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() {624OS << "\t.set\tnodsp\n";625MipsTargetStreamer::emitDirectiveSetNoDsp();626}627628void MipsTargetAsmStreamer::emitDirectiveSetMips3D() {629OS << "\t.set\tmips3d\n";630MipsTargetStreamer::emitDirectiveSetMips3D();631}632633void MipsTargetAsmStreamer::emitDirectiveSetNoMips3D() {634OS << "\t.set\tnomips3d\n";635MipsTargetStreamer::emitDirectiveSetNoMips3D();636}637638void MipsTargetAsmStreamer::emitDirectiveSetPop() {639OS << "\t.set\tpop\n";640MipsTargetStreamer::emitDirectiveSetPop();641}642643void MipsTargetAsmStreamer::emitDirectiveSetPush() {644OS << "\t.set\tpush\n";645MipsTargetStreamer::emitDirectiveSetPush();646}647648void MipsTargetAsmStreamer::emitDirectiveSetSoftFloat() {649OS << "\t.set\tsoftfloat\n";650MipsTargetStreamer::emitDirectiveSetSoftFloat();651}652653void MipsTargetAsmStreamer::emitDirectiveSetHardFloat() {654OS << "\t.set\thardfloat\n";655MipsTargetStreamer::emitDirectiveSetHardFloat();656}657658// Print a 32 bit hex number with all numbers.659static void printHex32(unsigned Value, raw_ostream &OS) {660OS << "0x";661for (int i = 7; i >= 0; i--)662OS.write_hex((Value & (0xF << (i * 4))) >> (i * 4));663}664665void MipsTargetAsmStreamer::emitMask(unsigned CPUBitmask,666int CPUTopSavedRegOff) {667OS << "\t.mask \t";668printHex32(CPUBitmask, OS);669OS << ',' << CPUTopSavedRegOff << '\n';670}671672void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask,673int FPUTopSavedRegOff) {674OS << "\t.fmask\t";675printHex32(FPUBitmask, OS);676OS << "," << FPUTopSavedRegOff << '\n';677}678679void MipsTargetAsmStreamer::emitDirectiveCpAdd(unsigned RegNo) {680OS << "\t.cpadd\t$"681<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";682forbidModuleDirective();683}684685void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) {686OS << "\t.cpload\t$"687<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";688forbidModuleDirective();689}690691void MipsTargetAsmStreamer::emitDirectiveCpLocal(unsigned RegNo) {692OS << "\t.cplocal\t$"693<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";694MipsTargetStreamer::emitDirectiveCpLocal(RegNo);695}696697bool MipsTargetAsmStreamer::emitDirectiveCpRestore(698int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,699const MCSubtargetInfo *STI) {700MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);701OS << "\t.cprestore\t" << Offset << "\n";702return true;703}704705void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,706int RegOrOffset,707const MCSymbol &Sym,708bool IsReg) {709OS << "\t.cpsetup\t$"710<< StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << ", ";711712if (IsReg)713OS << "$"714<< StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower();715else716OS << RegOrOffset;717718OS << ", ";719720OS << Sym.getName();721forbidModuleDirective();722}723724void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation,725bool SaveLocationIsRegister) {726OS << "\t.cpreturn";727forbidModuleDirective();728}729730void MipsTargetAsmStreamer::emitDirectiveModuleFP() {731MipsABIFlagsSection::FpABIKind FpABI = ABIFlagsSection.getFpABI();732if (FpABI == MipsABIFlagsSection::FpABIKind::SOFT)733OS << "\t.module\tsoftfloat\n";734else735OS << "\t.module\tfp=" << ABIFlagsSection.getFpABIString(FpABI) << "\n";736}737738void MipsTargetAsmStreamer::emitDirectiveSetFp(739MipsABIFlagsSection::FpABIKind Value) {740MipsTargetStreamer::emitDirectiveSetFp(Value);741742OS << "\t.set\tfp=";743OS << ABIFlagsSection.getFpABIString(Value) << "\n";744}745746void MipsTargetAsmStreamer::emitDirectiveModuleOddSPReg() {747MipsTargetStreamer::emitDirectiveModuleOddSPReg();748749OS << "\t.module\t" << (ABIFlagsSection.OddSPReg ? "" : "no") << "oddspreg\n";750}751752void MipsTargetAsmStreamer::emitDirectiveSetOddSPReg() {753MipsTargetStreamer::emitDirectiveSetOddSPReg();754OS << "\t.set\toddspreg\n";755}756757void MipsTargetAsmStreamer::emitDirectiveSetNoOddSPReg() {758MipsTargetStreamer::emitDirectiveSetNoOddSPReg();759OS << "\t.set\tnooddspreg\n";760}761762void MipsTargetAsmStreamer::emitDirectiveModuleSoftFloat() {763OS << "\t.module\tsoftfloat\n";764}765766void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() {767OS << "\t.module\thardfloat\n";768}769770void MipsTargetAsmStreamer::emitDirectiveModuleMT() {771OS << "\t.module\tmt\n";772}773774void MipsTargetAsmStreamer::emitDirectiveModuleCRC() {775OS << "\t.module\tcrc\n";776}777778void MipsTargetAsmStreamer::emitDirectiveModuleNoCRC() {779OS << "\t.module\tnocrc\n";780}781782void MipsTargetAsmStreamer::emitDirectiveModuleVirt() {783OS << "\t.module\tvirt\n";784}785786void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() {787OS << "\t.module\tnovirt\n";788}789790void MipsTargetAsmStreamer::emitDirectiveModuleGINV() {791OS << "\t.module\tginv\n";792}793794void MipsTargetAsmStreamer::emitDirectiveModuleNoGINV() {795OS << "\t.module\tnoginv\n";796}797798// This part is for ELF object output.799MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,800const MCSubtargetInfo &STI)801: MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) {802MCAssembler &MCA = getStreamer().getAssembler();803ELFObjectWriter &W = getStreamer().getWriter();804805// It's possible that MCObjectFileInfo isn't fully initialized at this point806// due to an initialization order problem where LLVMTargetMachine creates the807// target streamer before TargetLoweringObjectFile calls808// InitializeMCObjectFileInfo. There doesn't seem to be a single place that809// covers all cases so this statement covers most cases and direct object810// emission must call setPic() once MCObjectFileInfo has been initialized. The811// cases we don't handle here are covered by MipsAsmPrinter.812Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent();813814const FeatureBitset &Features = STI.getFeatureBits();815816// Set the header flags that we can in the constructor.817// FIXME: This is a fairly terrible hack. We set the rest818// of these in the destructor. The problem here is two-fold:819//820// a: Some of the eflags can be set/reset by directives.821// b: There aren't any usage paths that initialize the ABI822// pointer until after we initialize either an assembler823// or the target machine.824// We can fix this by making the target streamer construct825// the ABI, but this is fraught with wide ranging dependency826// issues as well.827unsigned EFlags = W.getELFHeaderEFlags();828829// FIXME: Fix a dependency issue by instantiating the ABI object to some830// default based off the triple. The triple doesn't describe the target831// fully, but any external user of the API that uses the MCTargetStreamer832// would otherwise crash on assertion failure.833834ABI = MipsABIInfo(835STI.getTargetTriple().getArch() == Triple::ArchType::mipsel ||836STI.getTargetTriple().getArch() == Triple::ArchType::mips837? MipsABIInfo::O32()838: MipsABIInfo::N64());839840// Architecture841if (Features[Mips::FeatureMips64r6])842EFlags |= ELF::EF_MIPS_ARCH_64R6;843else if (Features[Mips::FeatureMips64r2] ||844Features[Mips::FeatureMips64r3] ||845Features[Mips::FeatureMips64r5])846EFlags |= ELF::EF_MIPS_ARCH_64R2;847else if (Features[Mips::FeatureMips64])848EFlags |= ELF::EF_MIPS_ARCH_64;849else if (Features[Mips::FeatureMips5])850EFlags |= ELF::EF_MIPS_ARCH_5;851else if (Features[Mips::FeatureMips4])852EFlags |= ELF::EF_MIPS_ARCH_4;853else if (Features[Mips::FeatureMips3])854EFlags |= ELF::EF_MIPS_ARCH_3;855else if (Features[Mips::FeatureMips32r6])856EFlags |= ELF::EF_MIPS_ARCH_32R6;857else if (Features[Mips::FeatureMips32r2] ||858Features[Mips::FeatureMips32r3] ||859Features[Mips::FeatureMips32r5])860EFlags |= ELF::EF_MIPS_ARCH_32R2;861else if (Features[Mips::FeatureMips32])862EFlags |= ELF::EF_MIPS_ARCH_32;863else if (Features[Mips::FeatureMips2])864EFlags |= ELF::EF_MIPS_ARCH_2;865else866EFlags |= ELF::EF_MIPS_ARCH_1;867868// Machine869if (Features[Mips::FeatureCnMips])870EFlags |= ELF::EF_MIPS_MACH_OCTEON;871872// Other options.873if (Features[Mips::FeatureNaN2008])874EFlags |= ELF::EF_MIPS_NAN2008;875876W.setELFHeaderEFlags(EFlags);877}878879void MipsTargetELFStreamer::emitLabel(MCSymbol *S) {880auto *Symbol = cast<MCSymbolELF>(S);881getStreamer().getAssembler().registerSymbol(*Symbol);882uint8_t Type = Symbol->getType();883if (Type != ELF::STT_FUNC)884return;885886if (isMicroMipsEnabled())887Symbol->setOther(ELF::STO_MIPS_MICROMIPS);888}889890void MipsTargetELFStreamer::finish() {891MCAssembler &MCA = getStreamer().getAssembler();892ELFObjectWriter &W = getStreamer().getWriter();893const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo();894MCELFStreamer &S = getStreamer();895896// .bss, .text and .data are always at least 16-byte aligned.897MCSection &TextSection = *OFI.getTextSection();898S.switchSection(&TextSection);899MCSection &DataSection = *OFI.getDataSection();900S.switchSection(&DataSection);901MCSection &BSSSection = *OFI.getBSSSection();902S.switchSection(&BSSSection);903904TextSection.ensureMinAlignment(Align(16));905DataSection.ensureMinAlignment(Align(16));906BSSSection.ensureMinAlignment(Align(16));907908if (RoundSectionSizes) {909// Make sections sizes a multiple of the alignment. This is useful for910// verifying the output of IAS against the output of other assemblers but911// it's not necessary to produce a correct object and increases section912// size.913for (MCSection &Sec : MCA) {914MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);915916Align Alignment = Section.getAlign();917S.switchSection(&Section);918if (Section.useCodeAlign())919S.emitCodeAlignment(Alignment, &STI, Alignment.value());920else921S.emitValueToAlignment(Alignment, 0, 1, Alignment.value());922}923}924925const FeatureBitset &Features = STI.getFeatureBits();926927// Update e_header flags. See the FIXME and comment above in928// the constructor for a full rundown on this.929unsigned EFlags = W.getELFHeaderEFlags();930931// ABI932// N64 does not require any ABI bits.933if (getABI().IsO32())934EFlags |= ELF::EF_MIPS_ABI_O32;935else if (getABI().IsN32())936EFlags |= ELF::EF_MIPS_ABI2;937938if (Features[Mips::FeatureGP64Bit]) {939if (getABI().IsO32())940EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */941} else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64])942EFlags |= ELF::EF_MIPS_32BITMODE;943944// -mplt is not implemented but we should act as if it was945// given.946if (!Features[Mips::FeatureNoABICalls])947EFlags |= ELF::EF_MIPS_CPIC;948949if (Pic)950EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;951952W.setELFHeaderEFlags(EFlags);953954// Emit all the option records.955// At the moment we are only emitting .Mips.options (ODK_REGINFO) and956// .reginfo.957MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);958MEF.EmitMipsOptionRecords();959960emitMipsAbiFlags();961}962963void MipsTargetELFStreamer::emitAssignment(MCSymbol *S, const MCExpr *Value) {964auto *Symbol = cast<MCSymbolELF>(S);965// If on rhs is micromips symbol then mark Symbol as microMips.966if (Value->getKind() != MCExpr::SymbolRef)967return;968const auto &RhsSym = cast<MCSymbolELF>(969static_cast<const MCSymbolRefExpr *>(Value)->getSymbol());970971if (!(RhsSym.getOther() & ELF::STO_MIPS_MICROMIPS))972return;973974Symbol->setOther(ELF::STO_MIPS_MICROMIPS);975}976977MCELFStreamer &MipsTargetELFStreamer::getStreamer() {978return static_cast<MCELFStreamer &>(Streamer);979}980981void MipsTargetELFStreamer::emitDirectiveSetMicroMips() {982MicroMipsEnabled = true;983forbidModuleDirective();984}985986void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() {987MicroMipsEnabled = false;988forbidModuleDirective();989}990991void MipsTargetELFStreamer::setUsesMicroMips() {992ELFObjectWriter &W = getStreamer().getWriter();993unsigned Flags = W.getELFHeaderEFlags();994Flags |= ELF::EF_MIPS_MICROMIPS;995W.setELFHeaderEFlags(Flags);996}997998void MipsTargetELFStreamer::emitDirectiveSetMips16() {999ELFObjectWriter &W = getStreamer().getWriter();1000unsigned Flags = W.getELFHeaderEFlags();1001Flags |= ELF::EF_MIPS_ARCH_ASE_M16;1002W.setELFHeaderEFlags(Flags);1003forbidModuleDirective();1004}10051006void MipsTargetELFStreamer::emitDirectiveSetNoReorder() {1007ELFObjectWriter &W = getStreamer().getWriter();1008unsigned Flags = W.getELFHeaderEFlags();1009Flags |= ELF::EF_MIPS_NOREORDER;1010W.setELFHeaderEFlags(Flags);1011forbidModuleDirective();1012}10131014void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {1015MCAssembler &MCA = getStreamer().getAssembler();1016MCContext &Context = MCA.getContext();1017MCStreamer &OS = getStreamer();10181019OS.pushSection();1020MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0);1021OS.switchSection(Sec);1022Sec->setAlignment(Align(4));10231024MCSymbol *Sym = Context.getOrCreateSymbol(Name);1025const MCSymbolRefExpr *ExprRef =1026MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Context);10271028OS.emitValueImpl(ExprRef, 4);10291030OS.emitIntValue(GPRInfoSet ? GPRBitMask : 0, 4); // reg_mask1031OS.emitIntValue(GPRInfoSet ? GPROffset : 0, 4); // reg_offset10321033OS.emitIntValue(FPRInfoSet ? FPRBitMask : 0, 4); // fpreg_mask1034OS.emitIntValue(FPRInfoSet ? FPROffset : 0, 4); // fpreg_offset10351036OS.emitIntValue(FrameInfoSet ? FrameOffset : 0, 4); // frame_offset1037OS.emitIntValue(FrameInfoSet ? FrameReg : 0, 4); // frame_reg1038OS.emitIntValue(FrameInfoSet ? ReturnReg : 0, 4); // return_reg10391040// The .end directive marks the end of a procedure. Invalidate1041// the information gathered up until this point.1042GPRInfoSet = FPRInfoSet = FrameInfoSet = false;10431044OS.popSection();10451046// .end also implicitly sets the size.1047MCSymbol *CurPCSym = Context.createTempSymbol();1048OS.emitLabel(CurPCSym);1049const MCExpr *Size = MCBinaryExpr::createSub(1050MCSymbolRefExpr::create(CurPCSym, MCSymbolRefExpr::VK_None, Context),1051ExprRef, Context);10521053// The ELFObjectWriter can determine the absolute size as it has access to1054// the layout information of the assembly file, so a size expression rather1055// than an absolute value is ok here.1056static_cast<MCSymbolELF *>(Sym)->setSize(Size);1057}10581059void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {1060GPRInfoSet = FPRInfoSet = FrameInfoSet = false;10611062// .ent also acts like an implicit '.type symbol, STT_FUNC'1063static_cast<const MCSymbolELF &>(Symbol).setType(ELF::STT_FUNC);1064}10651066void MipsTargetELFStreamer::emitDirectiveAbiCalls() {1067ELFObjectWriter &W = getStreamer().getWriter();1068unsigned Flags = W.getELFHeaderEFlags();1069Flags |= ELF::EF_MIPS_CPIC | ELF::EF_MIPS_PIC;1070W.setELFHeaderEFlags(Flags);1071}10721073void MipsTargetELFStreamer::emitDirectiveNaN2008() {1074ELFObjectWriter &W = getStreamer().getWriter();1075unsigned Flags = W.getELFHeaderEFlags();1076Flags |= ELF::EF_MIPS_NAN2008;1077W.setELFHeaderEFlags(Flags);1078}10791080void MipsTargetELFStreamer::emitDirectiveNaNLegacy() {1081ELFObjectWriter &W = getStreamer().getWriter();1082unsigned Flags = W.getELFHeaderEFlags();1083Flags &= ~ELF::EF_MIPS_NAN2008;1084W.setELFHeaderEFlags(Flags);1085}10861087void MipsTargetELFStreamer::emitDirectiveOptionPic0() {1088ELFObjectWriter &W = getStreamer().getWriter();1089unsigned Flags = W.getELFHeaderEFlags();1090// This option overrides other PIC options like -KPIC.1091Pic = false;1092Flags &= ~ELF::EF_MIPS_PIC;1093W.setELFHeaderEFlags(Flags);1094}10951096void MipsTargetELFStreamer::emitDirectiveOptionPic2() {1097ELFObjectWriter &W = getStreamer().getWriter();1098unsigned Flags = W.getELFHeaderEFlags();1099Pic = true;1100// NOTE: We are following the GAS behaviour here which means the directive1101// 'pic2' also sets the CPIC bit in the ELF header. This is different from1102// what is stated in the SYSV ABI which consider the bits EF_MIPS_PIC and1103// EF_MIPS_CPIC to be mutually exclusive.1104Flags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;1105W.setELFHeaderEFlags(Flags);1106}11071108void MipsTargetELFStreamer::emitDirectiveInsn() {1109MipsTargetStreamer::emitDirectiveInsn();1110MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);1111MEF.createPendingLabelRelocs();1112}11131114void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize,1115unsigned ReturnReg_) {1116MCContext &Context = getStreamer().getAssembler().getContext();1117const MCRegisterInfo *RegInfo = Context.getRegisterInfo();11181119FrameInfoSet = true;1120FrameReg = RegInfo->getEncodingValue(StackReg);1121FrameOffset = StackSize;1122ReturnReg = RegInfo->getEncodingValue(ReturnReg_);1123}11241125void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask,1126int CPUTopSavedRegOff) {1127GPRInfoSet = true;1128GPRBitMask = CPUBitmask;1129GPROffset = CPUTopSavedRegOff;1130}11311132void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask,1133int FPUTopSavedRegOff) {1134FPRInfoSet = true;1135FPRBitMask = FPUBitmask;1136FPROffset = FPUTopSavedRegOff;1137}11381139void MipsTargetELFStreamer::emitDirectiveCpAdd(unsigned RegNo) {1140// .cpadd $reg1141// This directive inserts code to add $gp to the argument's register1142// when support for position independent code is enabled.1143if (!Pic)1144return;11451146emitAddu(RegNo, RegNo, GPReg, getABI().IsN64(), &STI);1147forbidModuleDirective();1148}11491150void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {1151// .cpload $reg1152// This directive expands to:1153// lui $gp, %hi(_gp_disp)1154// addui $gp, $gp, %lo(_gp_disp)1155// addu $gp, $gp, $reg1156// when support for position independent code is enabled.1157if (!Pic || (getABI().IsN32() || getABI().IsN64()))1158return;11591160// There's a GNU extension controlled by -mno-shared that allows1161// locally-binding symbols to be accessed using absolute addresses.1162// This is currently not supported. When supported -mno-shared makes1163// .cpload expand to:1164// lui $gp, %hi(__gnu_local_gp)1165// addiu $gp, $gp, %lo(__gnu_local_gp)11661167StringRef SymName("_gp_disp");1168MCAssembler &MCA = getStreamer().getAssembler();1169MCSymbol *GP_Disp = MCA.getContext().getOrCreateSymbol(SymName);1170MCA.registerSymbol(*GP_Disp);11711172MCInst TmpInst;1173TmpInst.setOpcode(Mips::LUi);1174TmpInst.addOperand(MCOperand::createReg(GPReg));1175const MCExpr *HiSym = MipsMCExpr::create(1176MipsMCExpr::MEK_HI,1177MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,1178MCA.getContext()),1179MCA.getContext());1180TmpInst.addOperand(MCOperand::createExpr(HiSym));1181getStreamer().emitInstruction(TmpInst, STI);11821183TmpInst.clear();11841185TmpInst.setOpcode(Mips::ADDiu);1186TmpInst.addOperand(MCOperand::createReg(GPReg));1187TmpInst.addOperand(MCOperand::createReg(GPReg));1188const MCExpr *LoSym = MipsMCExpr::create(1189MipsMCExpr::MEK_LO,1190MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,1191MCA.getContext()),1192MCA.getContext());1193TmpInst.addOperand(MCOperand::createExpr(LoSym));1194getStreamer().emitInstruction(TmpInst, STI);11951196TmpInst.clear();11971198TmpInst.setOpcode(Mips::ADDu);1199TmpInst.addOperand(MCOperand::createReg(GPReg));1200TmpInst.addOperand(MCOperand::createReg(GPReg));1201TmpInst.addOperand(MCOperand::createReg(RegNo));1202getStreamer().emitInstruction(TmpInst, STI);12031204forbidModuleDirective();1205}12061207void MipsTargetELFStreamer::emitDirectiveCpLocal(unsigned RegNo) {1208if (Pic)1209MipsTargetStreamer::emitDirectiveCpLocal(RegNo);1210}12111212bool MipsTargetELFStreamer::emitDirectiveCpRestore(1213int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,1214const MCSubtargetInfo *STI) {1215MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);1216// .cprestore offset1217// When PIC mode is enabled and the O32 ABI is used, this directive expands1218// to:1219// sw $gp, offset($sp)1220// and adds a corresponding LW after every JAL.12211222// Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it1223// is used in non-PIC mode.1224if (!Pic || (getABI().IsN32() || getABI().IsN64()))1225return true;12261227// Store the $gp on the stack.1228emitStoreWithImmOffset(Mips::SW, GPReg, Mips::SP, Offset, GetATReg, IDLoc,1229STI);1230return true;1231}12321233void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,1234int RegOrOffset,1235const MCSymbol &Sym,1236bool IsReg) {1237// Only N32 and N64 emit anything for .cpsetup iff PIC is set.1238if (!Pic || !(getABI().IsN32() || getABI().IsN64()))1239return;12401241forbidModuleDirective();12421243MCAssembler &MCA = getStreamer().getAssembler();1244MCInst Inst;12451246// Either store the old $gp in a register or on the stack1247if (IsReg) {1248// move $save, $gpreg1249emitRRR(Mips::OR64, RegOrOffset, GPReg, Mips::ZERO, SMLoc(), &STI);1250} else {1251// sd $gpreg, offset($sp)1252emitRRI(Mips::SD, GPReg, Mips::SP, RegOrOffset, SMLoc(), &STI);1253}12541255const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff(1256MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()),1257MCA.getContext());1258const MipsMCExpr *LoExpr = MipsMCExpr::createGpOff(1259MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(&Sym, MCA.getContext()),1260MCA.getContext());12611262// lui $gp, %hi(%neg(%gp_rel(funcSym)))1263emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI);12641265// addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))1266emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(),1267&STI);12681269// (d)addu $gp, $gp, $funcreg1270if (getABI().IsN32())1271emitRRR(Mips::ADDu, GPReg, GPReg, RegNo, SMLoc(), &STI);1272else1273emitRRR(Mips::DADDu, GPReg, GPReg, RegNo, SMLoc(), &STI);1274}12751276void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,1277bool SaveLocationIsRegister) {1278// Only N32 and N64 emit anything for .cpreturn iff PIC is set.1279if (!Pic || !(getABI().IsN32() || getABI().IsN64()))1280return;12811282MCInst Inst;1283// Either restore the old $gp from a register or on the stack1284if (SaveLocationIsRegister) {1285Inst.setOpcode(Mips::OR);1286Inst.addOperand(MCOperand::createReg(GPReg));1287Inst.addOperand(MCOperand::createReg(SaveLocation));1288Inst.addOperand(MCOperand::createReg(Mips::ZERO));1289} else {1290Inst.setOpcode(Mips::LD);1291Inst.addOperand(MCOperand::createReg(GPReg));1292Inst.addOperand(MCOperand::createReg(Mips::SP));1293Inst.addOperand(MCOperand::createImm(SaveLocation));1294}1295getStreamer().emitInstruction(Inst, STI);12961297forbidModuleDirective();1298}12991300void MipsTargetELFStreamer::emitMipsAbiFlags() {1301MCAssembler &MCA = getStreamer().getAssembler();1302MCContext &Context = MCA.getContext();1303MCStreamer &OS = getStreamer();1304MCSectionELF *Sec = Context.getELFSection(1305".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24);1306OS.switchSection(Sec);1307Sec->setAlignment(Align(8));13081309OS << ABIFlagsSection;1310}131113121313