brintos

brintos / llvm-project-archived public Read only

0
0
Text · 47.3 KiB · 01f18ac Raw
1396 lines · cpp
1//===-- MipsTargetStreamer.cpp - Mips Target Streamer Methods -------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file provides Mips specific target streamer methods.10//11//===----------------------------------------------------------------------===//12 13#include "MipsTargetStreamer.h"14#include "MCTargetDesc/MipsABIInfo.h"15#include "MCTargetDesc/MipsMCAsmInfo.h"16#include "MipsBaseInfo.h"17#include "MipsELFStreamer.h"18#include "MipsInstPrinter.h"19#include "MipsMCTargetDesc.h"20#include "llvm/BinaryFormat/ELF.h"21#include "llvm/MC/MCAsmInfo.h"22#include "llvm/MC/MCAssembler.h"23#include "llvm/MC/MCContext.h"24#include "llvm/MC/MCELFObjectWriter.h"25#include "llvm/MC/MCObjectFileInfo.h"26#include "llvm/MC/MCSectionELF.h"27#include "llvm/MC/MCSubtargetInfo.h"28#include "llvm/MC/MCSymbolELF.h"29#include "llvm/Support/CommandLine.h"30#include "llvm/Support/ErrorHandling.h"31#include "llvm/Support/FormattedStream.h"32 33using namespace llvm;34 35namespace {36static cl::opt<bool> RoundSectionSizes(37    "mips-round-section-sizes", cl::init(false),38    cl::desc("Round section sizes up to the section alignment"), cl::Hidden);39} // end anonymous namespace40 41static bool isMicroMips(const MCSubtargetInfo *STI) {42  return STI->hasFeature(Mips::FeatureMicroMips);43}44 45static bool isMips32r6(const MCSubtargetInfo *STI) {46  return STI->hasFeature(Mips::FeatureMips32r6);47}48 49MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)50    : MCTargetStreamer(S), GPReg(Mips::GP), ModuleDirectiveAllowed(true) {51  GPRInfoSet = FPRInfoSet = FrameInfoSet = false;52}53 54void MipsTargetStreamer::emitGPRel32Value(const MCExpr *) {}55void MipsTargetStreamer::emitGPRel64Value(const MCExpr *) {}56void MipsTargetStreamer::emitDTPRel32Value(const MCExpr *) {}57void MipsTargetStreamer::emitDTPRel64Value(const MCExpr *) {}58void MipsTargetStreamer::emitTPRel32Value(const MCExpr *) {}59void MipsTargetStreamer::emitTPRel64Value(const MCExpr *) {}60void MipsTargetStreamer::emitDirectiveSetMicroMips() {}61void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {}62void MipsTargetStreamer::setUsesMicroMips() {}63void MipsTargetStreamer::emitDirectiveSetMips16() {}64void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); }65void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); }66void MipsTargetStreamer::emitDirectiveSetNoReorder() {}67void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); }68void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); }69void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); }70void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); }71void MipsTargetStreamer::emitDirectiveSetMt() {}72void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); }73void MipsTargetStreamer::emitDirectiveSetCRC() {}74void MipsTargetStreamer::emitDirectiveSetNoCRC() {}75void MipsTargetStreamer::emitDirectiveSetVirt() {}76void MipsTargetStreamer::emitDirectiveSetNoVirt() {}77void MipsTargetStreamer::emitDirectiveSetGINV() {}78void MipsTargetStreamer::emitDirectiveSetNoGINV() {}79void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); }80void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {81  forbidModuleDirective();82}83void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); }84void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {}85void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {}86void MipsTargetStreamer::emitDirectiveAbiCalls() {}87void MipsTargetStreamer::emitDirectiveNaN2008() {}88void MipsTargetStreamer::emitDirectiveNaNLegacy() {}89void MipsTargetStreamer::emitDirectiveOptionPic0() {}90void MipsTargetStreamer::emitDirectiveOptionPic2() {}91void MipsTargetStreamer::emitDirectiveInsn() { forbidModuleDirective(); }92void MipsTargetStreamer::emitFrame(MCRegister StackReg, unsigned StackSize,93                                   MCRegister ReturnReg) {}94void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {}95void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) {96}97void MipsTargetStreamer::emitDirectiveSetArch(StringRef Arch) {98  forbidModuleDirective();99}100void MipsTargetStreamer::emitDirectiveSetMips0() { forbidModuleDirective(); }101void MipsTargetStreamer::emitDirectiveSetMips1() { forbidModuleDirective(); }102void MipsTargetStreamer::emitDirectiveSetMips2() { forbidModuleDirective(); }103void MipsTargetStreamer::emitDirectiveSetMips3() { forbidModuleDirective(); }104void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); }105void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); }106void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); }107void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); }108void MipsTargetStreamer::emitDirectiveSetMips32R3() { forbidModuleDirective(); }109void MipsTargetStreamer::emitDirectiveSetMips32R5() { forbidModuleDirective(); }110void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); }111void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); }112void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); }113void MipsTargetStreamer::emitDirectiveSetMips64R3() { forbidModuleDirective(); }114void MipsTargetStreamer::emitDirectiveSetMips64R5() { forbidModuleDirective(); }115void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); }116void MipsTargetStreamer::emitDirectiveSetPop() { forbidModuleDirective(); }117void MipsTargetStreamer::emitDirectiveSetPush() { forbidModuleDirective(); }118void MipsTargetStreamer::emitDirectiveSetSoftFloat() {119  forbidModuleDirective();120}121void MipsTargetStreamer::emitDirectiveSetHardFloat() {122  forbidModuleDirective();123}124void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }125void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); }126void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }127void MipsTargetStreamer::emitDirectiveSetMips3D() { forbidModuleDirective(); }128void MipsTargetStreamer::emitDirectiveSetNoMips3D() { forbidModuleDirective(); }129void MipsTargetStreamer::emitDirectiveCpAdd(MCRegister Reg) {}130void MipsTargetStreamer::emitDirectiveCpLoad(MCRegister Reg) {}131void MipsTargetStreamer::emitDirectiveCpLocal(MCRegister Reg) {132  // .cplocal $reg133  // This directive forces to use the alternate register for context pointer.134  // For example135  //   .cplocal $4136  //   jal foo137  // expands to138  //   ld    $25, %call16(foo)($4)139  //   jalr  $25140 141  if (!getABI().IsN32() && !getABI().IsN64())142    return;143 144  GPReg = Reg;145 146  forbidModuleDirective();147}148bool MipsTargetStreamer::emitDirectiveCpRestore(149    int Offset, function_ref<MCRegister()> GetATReg, SMLoc IDLoc,150    const MCSubtargetInfo *STI) {151  forbidModuleDirective();152  return true;153}154void MipsTargetStreamer::emitDirectiveCpsetup(MCRegister Reg, int RegOrOffset,155                                              const MCSymbol &Sym, bool IsReg) {156}157void MipsTargetStreamer::emitDirectiveCpreturn(unsigned SaveLocation,158                                               bool SaveLocationIsRegister) {}159 160void MipsTargetStreamer::emitDirectiveModuleFP() {}161 162void MipsTargetStreamer::emitDirectiveModuleOddSPReg() {163  if (!ABIFlagsSection.OddSPReg && !ABIFlagsSection.Is32BitABI)164    report_fatal_error("+nooddspreg is only valid for O32");165}166void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {}167void MipsTargetStreamer::emitDirectiveModuleHardFloat() {}168void MipsTargetStreamer::emitDirectiveModuleMT() {}169void MipsTargetStreamer::emitDirectiveModuleCRC() {}170void MipsTargetStreamer::emitDirectiveModuleNoCRC() {}171void MipsTargetStreamer::emitDirectiveModuleVirt() {}172void MipsTargetStreamer::emitDirectiveModuleNoVirt() {}173void MipsTargetStreamer::emitDirectiveModuleGINV() {}174void MipsTargetStreamer::emitDirectiveModuleNoGINV() {}175void MipsTargetStreamer::emitDirectiveSetFp(176    MipsABIFlagsSection::FpABIKind Value) {177  forbidModuleDirective();178}179void MipsTargetStreamer::emitDirectiveSetOddSPReg() { forbidModuleDirective(); }180void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() {181  forbidModuleDirective();182}183 184void MipsTargetStreamer::emitR(unsigned Opcode, MCRegister Reg0, SMLoc IDLoc,185                               const MCSubtargetInfo *STI) {186  MCInst TmpInst;187  TmpInst.setOpcode(Opcode);188  TmpInst.addOperand(MCOperand::createReg(Reg0));189  TmpInst.setLoc(IDLoc);190  getStreamer().emitInstruction(TmpInst, *STI);191}192 193void MipsTargetStreamer::emitRX(unsigned Opcode, MCRegister Reg0, MCOperand Op1,194                                SMLoc IDLoc, const MCSubtargetInfo *STI) {195  MCInst TmpInst;196  TmpInst.setOpcode(Opcode);197  TmpInst.addOperand(MCOperand::createReg(Reg0));198  TmpInst.addOperand(Op1);199  TmpInst.setLoc(IDLoc);200  getStreamer().emitInstruction(TmpInst, *STI);201}202 203void MipsTargetStreamer::emitRI(unsigned Opcode, MCRegister Reg0, int32_t Imm,204                                SMLoc IDLoc, const MCSubtargetInfo *STI) {205  emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI);206}207 208void MipsTargetStreamer::emitRR(unsigned Opcode, MCRegister Reg0,209                                MCRegister Reg1, SMLoc IDLoc,210                                const MCSubtargetInfo *STI) {211  emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI);212}213 214void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2,215                                SMLoc IDLoc, const MCSubtargetInfo *STI) {216  MCInst TmpInst;217  TmpInst.setOpcode(Opcode);218  TmpInst.addOperand(MCOperand::createImm(Imm1));219  TmpInst.addOperand(MCOperand::createImm(Imm2));220  TmpInst.setLoc(IDLoc);221  getStreamer().emitInstruction(TmpInst, *STI);222}223 224void MipsTargetStreamer::emitRRX(unsigned Opcode, MCRegister Reg0,225                                 MCRegister Reg1, MCOperand Op2, SMLoc IDLoc,226                                 const MCSubtargetInfo *STI) {227  MCInst TmpInst;228  TmpInst.setOpcode(Opcode);229  TmpInst.addOperand(MCOperand::createReg(Reg0));230  TmpInst.addOperand(MCOperand::createReg(Reg1));231  TmpInst.addOperand(Op2);232  TmpInst.setLoc(IDLoc);233  getStreamer().emitInstruction(TmpInst, *STI);234}235 236void MipsTargetStreamer::emitRRR(unsigned Opcode, MCRegister Reg0,237                                 MCRegister Reg1, MCRegister Reg2, SMLoc IDLoc,238                                 const MCSubtargetInfo *STI) {239  emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI);240}241 242void MipsTargetStreamer::emitRRRX(unsigned Opcode, MCRegister Reg0,243                                  MCRegister Reg1, MCRegister Reg2,244                                  MCOperand Op3, SMLoc IDLoc,245                                  const MCSubtargetInfo *STI) {246  MCInst TmpInst;247  TmpInst.setOpcode(Opcode);248  TmpInst.addOperand(MCOperand::createReg(Reg0));249  TmpInst.addOperand(MCOperand::createReg(Reg1));250  TmpInst.addOperand(MCOperand::createReg(Reg2));251  TmpInst.addOperand(Op3);252  TmpInst.setLoc(IDLoc);253  getStreamer().emitInstruction(TmpInst, *STI);254}255 256void MipsTargetStreamer::emitRRI(unsigned Opcode, MCRegister Reg0,257                                 MCRegister Reg1, int16_t Imm, SMLoc IDLoc,258                                 const MCSubtargetInfo *STI) {259  emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI);260}261 262void MipsTargetStreamer::emitRRIII(unsigned Opcode, MCRegister Reg0,263                                   MCRegister Reg1, int16_t Imm0, int16_t Imm1,264                                   int16_t Imm2, SMLoc IDLoc,265                                   const MCSubtargetInfo *STI) {266  MCInst TmpInst;267  TmpInst.setOpcode(Opcode);268  TmpInst.addOperand(MCOperand::createReg(Reg0));269  TmpInst.addOperand(MCOperand::createReg(Reg1));270  TmpInst.addOperand(MCOperand::createImm(Imm0));271  TmpInst.addOperand(MCOperand::createImm(Imm1));272  TmpInst.addOperand(MCOperand::createImm(Imm2));273  TmpInst.setLoc(IDLoc);274  getStreamer().emitInstruction(TmpInst, *STI);275}276 277void MipsTargetStreamer::emitAddu(MCRegister DstReg, MCRegister SrcReg,278                                  MCRegister TrgReg, bool Is64Bit,279                                  const MCSubtargetInfo *STI) {280  emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),281          STI);282}283 284void MipsTargetStreamer::emitDSLL(MCRegister DstReg, MCRegister SrcReg,285                                  int16_t ShiftAmount, SMLoc IDLoc,286                                  const MCSubtargetInfo *STI) {287  if (ShiftAmount >= 32) {288    emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI);289    return;290  }291 292  emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI);293}294 295void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,296                                            const MCSubtargetInfo *STI) {297  // The default case of `nop` is `sll $zero, $zero, 0`.298  unsigned Opc = Mips::SLL;299  if (isMicroMips(STI) && hasShortDelaySlot) {300    Opc = isMips32r6(STI) ? Mips::MOVE16_MMR6 : Mips::MOVE16_MM;301    emitRR(Opc, Mips::ZERO, Mips::ZERO, IDLoc, STI);302    return;303  }304 305  if (isMicroMips(STI))306    Opc = isMips32r6(STI) ? Mips::SLL_MMR6 : Mips::SLL_MM;307 308  emitRRI(Opc, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);309}310 311void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {312  if (isMicroMips(STI))313    emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI);314  else315    emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);316}317 318/// Emit the $gp restore operation for .cprestore.319void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,320                                       const MCSubtargetInfo *STI) {321  emitLoadWithImmOffset(Mips::LW, GPReg, Mips::SP, Offset, GPReg, IDLoc, STI);322}323 324/// Emit a store instruction with an immediate offset.325void MipsTargetStreamer::emitStoreWithImmOffset(326    unsigned Opcode, MCRegister SrcReg, MCRegister BaseReg, int64_t Offset,327    function_ref<MCRegister()> GetATReg, SMLoc IDLoc,328    const MCSubtargetInfo *STI) {329  if (isInt<16>(Offset)) {330    emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI);331    return;332  }333 334  // sw $8, offset($8) => lui $at, %hi(offset)335  //                      add $at, $at, $8336  //                      sw $8, %lo(offset)($at)337 338  MCRegister ATReg = GetATReg();339  if (!ATReg)340    return;341 342  unsigned LoOffset = Offset & 0x0000ffff;343  unsigned HiOffset = (Offset & 0xffff0000) >> 16;344 345  // If msb of LoOffset is 1(negative number) we must increment HiOffset346  // to account for the sign-extension of the low part.347  if (LoOffset & 0x8000)348    HiOffset++;349 350  // Generate the base address in ATReg.351  emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI);352  if (BaseReg != Mips::ZERO)353    emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);354  // Emit the store with the adjusted base and offset.355  emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI);356}357 358/// Emit a load instruction with an immediate offset. DstReg and TmpReg are359/// permitted to be the same register iff DstReg is distinct from BaseReg and360/// DstReg is a GPR. It is the callers responsibility to identify such cases361/// and pass the appropriate register in TmpReg.362void MipsTargetStreamer::emitLoadWithImmOffset(363    unsigned Opcode, MCRegister DstReg, MCRegister BaseReg, int64_t Offset,364    MCRegister TmpReg, SMLoc IDLoc, const MCSubtargetInfo *STI) {365  if (isInt<16>(Offset)) {366    emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI);367    return;368  }369 370  // 1) lw $8, offset($9) => lui $8, %hi(offset)371  //                         add $8, $8, $9372  //                         lw $8, %lo(offset)($9)373  // 2) lw $8, offset($8) => lui $at, %hi(offset)374  //                         add $at, $at, $8375  //                         lw $8, %lo(offset)($at)376 377  unsigned LoOffset = Offset & 0x0000ffff;378  unsigned HiOffset = (Offset & 0xffff0000) >> 16;379 380  // If msb of LoOffset is 1(negative number) we must increment HiOffset381  // to account for the sign-extension of the low part.382  if (LoOffset & 0x8000)383    HiOffset++;384 385  // Generate the base address in TmpReg.386  emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI);387  if (BaseReg != Mips::ZERO)388    emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);389  // Emit the load with the adjusted base and offset.390  emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI);391}392 393MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,394                                             formatted_raw_ostream &OS)395    : MipsTargetStreamer(S), OS(OS) {}396 397void MipsTargetAsmStreamer::emitDTPRel32Value(const MCExpr *Value) {398  auto *MAI = getStreamer().getContext().getAsmInfo();399  OS << "\t.dtprelword\t";400  MAI->printExpr(OS, *Value);401  OS << '\n';402}403 404void MipsTargetAsmStreamer::emitDTPRel64Value(const MCExpr *Value) {405  auto *MAI = getStreamer().getContext().getAsmInfo();406  OS << "\t.dtpreldword\t";407  MAI->printExpr(OS, *Value);408  OS << '\n';409}410 411void MipsTargetAsmStreamer::emitTPRel32Value(const MCExpr *Value) {412  auto *MAI = getStreamer().getContext().getAsmInfo();413  OS << "\t.tprelword\t";414  MAI->printExpr(OS, *Value);415  OS << '\n';416}417 418void MipsTargetAsmStreamer::emitTPRel64Value(const MCExpr *Value) {419  auto *MAI = getStreamer().getContext().getAsmInfo();420  OS << "\t.tpreldword\t";421  MAI->printExpr(OS, *Value);422  OS << '\n';423}424 425void MipsTargetAsmStreamer::emitGPRel32Value(const MCExpr *Value) {426  auto *MAI = getStreamer().getContext().getAsmInfo();427  OS << "\t.gpword\t";428  MAI->printExpr(OS, *Value);429  OS << '\n';430}431 432void MipsTargetAsmStreamer::emitGPRel64Value(const MCExpr *Value) {433  auto *MAI = getStreamer().getContext().getAsmInfo();434  OS << "\t.gpdword\t";435  MAI->printExpr(OS, *Value);436  OS << '\n';437}438 439void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() {440  OS << "\t.set\tmicromips\n";441  forbidModuleDirective();442}443 444void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() {445  OS << "\t.set\tnomicromips\n";446  forbidModuleDirective();447}448 449void MipsTargetAsmStreamer::emitDirectiveSetMips16() {450  OS << "\t.set\tmips16\n";451  forbidModuleDirective();452}453 454void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() {455  OS << "\t.set\tnomips16\n";456  MipsTargetStreamer::emitDirectiveSetNoMips16();457}458 459void MipsTargetAsmStreamer::emitDirectiveSetReorder() {460  OS << "\t.set\treorder\n";461  MipsTargetStreamer::emitDirectiveSetReorder();462}463 464void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() {465  OS << "\t.set\tnoreorder\n";466  forbidModuleDirective();467}468 469void MipsTargetAsmStreamer::emitDirectiveSetMacro() {470  OS << "\t.set\tmacro\n";471  MipsTargetStreamer::emitDirectiveSetMacro();472}473 474void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() {475  OS << "\t.set\tnomacro\n";476  MipsTargetStreamer::emitDirectiveSetNoMacro();477}478 479void MipsTargetAsmStreamer::emitDirectiveSetMsa() {480  OS << "\t.set\tmsa\n";481  MipsTargetStreamer::emitDirectiveSetMsa();482}483 484void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() {485  OS << "\t.set\tnomsa\n";486  MipsTargetStreamer::emitDirectiveSetNoMsa();487}488 489void MipsTargetAsmStreamer::emitDirectiveSetMt() {490  OS << "\t.set\tmt\n";491  MipsTargetStreamer::emitDirectiveSetMt();492}493 494void MipsTargetAsmStreamer::emitDirectiveSetNoMt() {495  OS << "\t.set\tnomt\n";496  MipsTargetStreamer::emitDirectiveSetNoMt();497}498 499void MipsTargetAsmStreamer::emitDirectiveSetCRC() {500  OS << "\t.set\tcrc\n";501  MipsTargetStreamer::emitDirectiveSetCRC();502}503 504void MipsTargetAsmStreamer::emitDirectiveSetNoCRC() {505  OS << "\t.set\tnocrc\n";506  MipsTargetStreamer::emitDirectiveSetNoCRC();507}508 509void MipsTargetAsmStreamer::emitDirectiveSetVirt() {510  OS << "\t.set\tvirt\n";511  MipsTargetStreamer::emitDirectiveSetVirt();512}513 514void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() {515  OS << "\t.set\tnovirt\n";516  MipsTargetStreamer::emitDirectiveSetNoVirt();517}518 519void MipsTargetAsmStreamer::emitDirectiveSetGINV() {520  OS << "\t.set\tginv\n";521  MipsTargetStreamer::emitDirectiveSetGINV();522}523 524void MipsTargetAsmStreamer::emitDirectiveSetNoGINV() {525  OS << "\t.set\tnoginv\n";526  MipsTargetStreamer::emitDirectiveSetNoGINV();527}528 529void MipsTargetAsmStreamer::emitDirectiveSetAt() {530  OS << "\t.set\tat\n";531  MipsTargetStreamer::emitDirectiveSetAt();532}533 534void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {535  OS << "\t.set\tat=$" << Twine(RegNo) << "\n";536  MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo);537}538 539void MipsTargetAsmStreamer::emitDirectiveSetNoAt() {540  OS << "\t.set\tnoat\n";541  MipsTargetStreamer::emitDirectiveSetNoAt();542}543 544void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) {545  OS << "\t.end\t" << Name << '\n';546}547 548void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {549  OS << "\t.ent\t" << Symbol.getName() << '\n';550}551 552void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; }553 554void MipsTargetAsmStreamer::emitDirectiveNaN2008() { OS << "\t.nan\t2008\n"; }555 556void MipsTargetAsmStreamer::emitDirectiveNaNLegacy() {557  OS << "\t.nan\tlegacy\n";558}559 560void MipsTargetAsmStreamer::emitDirectiveOptionPic0() {561  OS << "\t.option\tpic0\n";562}563 564void MipsTargetAsmStreamer::emitDirectiveOptionPic2() {565  OS << "\t.option\tpic2\n";566}567 568void MipsTargetAsmStreamer::emitDirectiveInsn() {569  MipsTargetStreamer::emitDirectiveInsn();570  OS << "\t.insn\n";571}572 573void MipsTargetAsmStreamer::emitFrame(MCRegister StackReg, unsigned StackSize,574                                      MCRegister ReturnReg) {575  OS << "\t.frame\t$"576     << StringRef(MipsInstPrinter::getRegisterName(StackReg)).lower() << ","577     << StackSize << ",$"578     << StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n';579}580 581void MipsTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) {582  OS << "\t.set arch=" << Arch << "\n";583  MipsTargetStreamer::emitDirectiveSetArch(Arch);584}585 586void MipsTargetAsmStreamer::emitDirectiveSetMips0() {587  OS << "\t.set\tmips0\n";588  MipsTargetStreamer::emitDirectiveSetMips0();589}590 591void MipsTargetAsmStreamer::emitDirectiveSetMips1() {592  OS << "\t.set\tmips1\n";593  MipsTargetStreamer::emitDirectiveSetMips1();594}595 596void MipsTargetAsmStreamer::emitDirectiveSetMips2() {597  OS << "\t.set\tmips2\n";598  MipsTargetStreamer::emitDirectiveSetMips2();599}600 601void MipsTargetAsmStreamer::emitDirectiveSetMips3() {602  OS << "\t.set\tmips3\n";603  MipsTargetStreamer::emitDirectiveSetMips3();604}605 606void MipsTargetAsmStreamer::emitDirectiveSetMips4() {607  OS << "\t.set\tmips4\n";608  MipsTargetStreamer::emitDirectiveSetMips4();609}610 611void MipsTargetAsmStreamer::emitDirectiveSetMips5() {612  OS << "\t.set\tmips5\n";613  MipsTargetStreamer::emitDirectiveSetMips5();614}615 616void MipsTargetAsmStreamer::emitDirectiveSetMips32() {617  OS << "\t.set\tmips32\n";618  MipsTargetStreamer::emitDirectiveSetMips32();619}620 621void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() {622  OS << "\t.set\tmips32r2\n";623  MipsTargetStreamer::emitDirectiveSetMips32R2();624}625 626void MipsTargetAsmStreamer::emitDirectiveSetMips32R3() {627  OS << "\t.set\tmips32r3\n";628  MipsTargetStreamer::emitDirectiveSetMips32R3();629}630 631void MipsTargetAsmStreamer::emitDirectiveSetMips32R5() {632  OS << "\t.set\tmips32r5\n";633  MipsTargetStreamer::emitDirectiveSetMips32R5();634}635 636void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() {637  OS << "\t.set\tmips32r6\n";638  MipsTargetStreamer::emitDirectiveSetMips32R6();639}640 641void MipsTargetAsmStreamer::emitDirectiveSetMips64() {642  OS << "\t.set\tmips64\n";643  MipsTargetStreamer::emitDirectiveSetMips64();644}645 646void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() {647  OS << "\t.set\tmips64r2\n";648  MipsTargetStreamer::emitDirectiveSetMips64R2();649}650 651void MipsTargetAsmStreamer::emitDirectiveSetMips64R3() {652  OS << "\t.set\tmips64r3\n";653  MipsTargetStreamer::emitDirectiveSetMips64R3();654}655 656void MipsTargetAsmStreamer::emitDirectiveSetMips64R5() {657  OS << "\t.set\tmips64r5\n";658  MipsTargetStreamer::emitDirectiveSetMips64R5();659}660 661void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() {662  OS << "\t.set\tmips64r6\n";663  MipsTargetStreamer::emitDirectiveSetMips64R6();664}665 666void MipsTargetAsmStreamer::emitDirectiveSetDsp() {667  OS << "\t.set\tdsp\n";668  MipsTargetStreamer::emitDirectiveSetDsp();669}670 671void MipsTargetAsmStreamer::emitDirectiveSetDspr2() {672  OS << "\t.set\tdspr2\n";673  MipsTargetStreamer::emitDirectiveSetDspr2();674}675 676void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() {677  OS << "\t.set\tnodsp\n";678  MipsTargetStreamer::emitDirectiveSetNoDsp();679}680 681void MipsTargetAsmStreamer::emitDirectiveSetMips3D() {682  OS << "\t.set\tmips3d\n";683  MipsTargetStreamer::emitDirectiveSetMips3D();684}685 686void MipsTargetAsmStreamer::emitDirectiveSetNoMips3D() {687  OS << "\t.set\tnomips3d\n";688  MipsTargetStreamer::emitDirectiveSetNoMips3D();689}690 691void MipsTargetAsmStreamer::emitDirectiveSetPop() {692  OS << "\t.set\tpop\n";693  MipsTargetStreamer::emitDirectiveSetPop();694}695 696void MipsTargetAsmStreamer::emitDirectiveSetPush() {697 OS << "\t.set\tpush\n";698 MipsTargetStreamer::emitDirectiveSetPush();699}700 701void MipsTargetAsmStreamer::emitDirectiveSetSoftFloat() {702  OS << "\t.set\tsoftfloat\n";703  MipsTargetStreamer::emitDirectiveSetSoftFloat();704}705 706void MipsTargetAsmStreamer::emitDirectiveSetHardFloat() {707  OS << "\t.set\thardfloat\n";708  MipsTargetStreamer::emitDirectiveSetHardFloat();709}710 711// Print a 32 bit hex number with all numbers.712static void printHex32(unsigned Value, raw_ostream &OS) {713  OS << "0x";714  for (int i = 7; i >= 0; i--)715    OS.write_hex((Value & (0xF << (i * 4))) >> (i * 4));716}717 718void MipsTargetAsmStreamer::emitMask(unsigned CPUBitmask,719                                     int CPUTopSavedRegOff) {720  OS << "\t.mask \t";721  printHex32(CPUBitmask, OS);722  OS << ',' << CPUTopSavedRegOff << '\n';723}724 725void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask,726                                      int FPUTopSavedRegOff) {727  OS << "\t.fmask\t";728  printHex32(FPUBitmask, OS);729  OS << "," << FPUTopSavedRegOff << '\n';730}731 732void MipsTargetAsmStreamer::emitDirectiveCpAdd(MCRegister Reg) {733  OS << "\t.cpadd\t$"734     << StringRef(MipsInstPrinter::getRegisterName(Reg)).lower() << "\n";735  forbidModuleDirective();736}737 738void MipsTargetAsmStreamer::emitDirectiveCpLoad(MCRegister Reg) {739  OS << "\t.cpload\t$"740     << StringRef(MipsInstPrinter::getRegisterName(Reg)).lower() << "\n";741  forbidModuleDirective();742}743 744void MipsTargetAsmStreamer::emitDirectiveCpLocal(MCRegister Reg) {745  OS << "\t.cplocal\t$"746     << StringRef(MipsInstPrinter::getRegisterName(Reg)).lower() << "\n";747  MipsTargetStreamer::emitDirectiveCpLocal(Reg);748}749 750bool MipsTargetAsmStreamer::emitDirectiveCpRestore(751    int Offset, function_ref<MCRegister()> GetATReg, SMLoc IDLoc,752    const MCSubtargetInfo *STI) {753  MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);754  OS << "\t.cprestore\t" << Offset << "\n";755  return true;756}757 758void MipsTargetAsmStreamer::emitDirectiveCpsetup(MCRegister Reg,759                                                 int RegOrOffset,760                                                 const MCSymbol &Sym,761                                                 bool IsReg) {762  OS << "\t.cpsetup\t$"763     << StringRef(MipsInstPrinter::getRegisterName(Reg)).lower() << ", ";764 765  if (IsReg)766    OS << "$"767       << StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower();768  else769    OS << RegOrOffset;770 771  OS << ", ";772 773  OS << Sym.getName();774  forbidModuleDirective();775}776 777void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation,778                                                  bool SaveLocationIsRegister) {779  OS << "\t.cpreturn";780  forbidModuleDirective();781}782 783void MipsTargetAsmStreamer::emitDirectiveModuleFP() {784  MipsABIFlagsSection::FpABIKind FpABI = ABIFlagsSection.getFpABI();785  if (FpABI == MipsABIFlagsSection::FpABIKind::SOFT)786    OS << "\t.module\tsoftfloat\n";787  else788    OS << "\t.module\tfp=" << ABIFlagsSection.getFpABIString(FpABI) << "\n";789}790 791void MipsTargetAsmStreamer::emitDirectiveSetFp(792    MipsABIFlagsSection::FpABIKind Value) {793  MipsTargetStreamer::emitDirectiveSetFp(Value);794 795  OS << "\t.set\tfp=";796  OS << ABIFlagsSection.getFpABIString(Value) << "\n";797}798 799void MipsTargetAsmStreamer::emitDirectiveModuleOddSPReg() {800  MipsTargetStreamer::emitDirectiveModuleOddSPReg();801 802  OS << "\t.module\t" << (ABIFlagsSection.OddSPReg ? "" : "no") << "oddspreg\n";803}804 805void MipsTargetAsmStreamer::emitDirectiveSetOddSPReg() {806  MipsTargetStreamer::emitDirectiveSetOddSPReg();807  OS << "\t.set\toddspreg\n";808}809 810void MipsTargetAsmStreamer::emitDirectiveSetNoOddSPReg() {811  MipsTargetStreamer::emitDirectiveSetNoOddSPReg();812  OS << "\t.set\tnooddspreg\n";813}814 815void MipsTargetAsmStreamer::emitDirectiveModuleSoftFloat() {816  OS << "\t.module\tsoftfloat\n";817}818 819void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() {820  OS << "\t.module\thardfloat\n";821}822 823void MipsTargetAsmStreamer::emitDirectiveModuleMT() {824  OS << "\t.module\tmt\n";825}826 827void MipsTargetAsmStreamer::emitDirectiveModuleCRC() {828  OS << "\t.module\tcrc\n";829}830 831void MipsTargetAsmStreamer::emitDirectiveModuleNoCRC() {832  OS << "\t.module\tnocrc\n";833}834 835void MipsTargetAsmStreamer::emitDirectiveModuleVirt() {836  OS << "\t.module\tvirt\n";837}838 839void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() {840  OS << "\t.module\tnovirt\n";841}842 843void MipsTargetAsmStreamer::emitDirectiveModuleGINV() {844  OS << "\t.module\tginv\n";845}846 847void MipsTargetAsmStreamer::emitDirectiveModuleNoGINV() {848  OS << "\t.module\tnoginv\n";849}850 851// This part is for ELF object output.852MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,853                                             const MCSubtargetInfo &STI)854    : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) {855  MCAssembler &MCA = getStreamer().getAssembler();856  ELFObjectWriter &W = getStreamer().getWriter();857 858  // It's possible that MCObjectFileInfo isn't fully initialized at this point859  // due to an initialization order problem where CodeGenTargetMachineImpl860  // creates the target streamer before TargetLoweringObjectFile calls861  // InitializeMCObjectFileInfo. There doesn't seem to be a single place that862  // covers all cases so this statement covers most cases and direct object863  // emission must call setPic() once MCObjectFileInfo has been initialized. The864  // cases we don't handle here are covered by MipsAsmPrinter.865  Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent();866 867  const FeatureBitset &Features = STI.getFeatureBits();868 869  // Set the header flags that we can in the constructor.870  // FIXME: This is a fairly terrible hack. We set the rest871  // of these in the destructor. The problem here is two-fold:872  //873  // a: Some of the eflags can be set/reset by directives.874  // b: There aren't any usage paths that initialize the ABI875  //    pointer until after we initialize either an assembler876  //    or the target machine.877  // We can fix this by making the target streamer construct878  // the ABI, but this is fraught with wide ranging dependency879  // issues as well.880  unsigned EFlags = W.getELFHeaderEFlags();881 882  // FIXME: Fix a dependency issue by instantiating the ABI object to some883  // default based off the triple. The triple doesn't describe the target884  // fully, but any external user of the API that uses the MCTargetStreamer885  // would otherwise crash on assertion failure.886 887  ABI = MipsABIInfo(888      STI.getTargetTriple().getArch() == Triple::ArchType::mipsel ||889              STI.getTargetTriple().getArch() == Triple::ArchType::mips890          ? MipsABIInfo::O32()891          : MipsABIInfo::N64());892 893  // Architecture894  if (Features[Mips::FeatureMips64r6])895    EFlags |= ELF::EF_MIPS_ARCH_64R6;896  else if (Features[Mips::FeatureMips64r2] ||897           Features[Mips::FeatureMips64r3] ||898           Features[Mips::FeatureMips64r5])899    EFlags |= ELF::EF_MIPS_ARCH_64R2;900  else if (Features[Mips::FeatureMips64])901    EFlags |= ELF::EF_MIPS_ARCH_64;902  else if (Features[Mips::FeatureMips5])903    EFlags |= ELF::EF_MIPS_ARCH_5;904  else if (Features[Mips::FeatureMips4])905    EFlags |= ELF::EF_MIPS_ARCH_4;906  else if (Features[Mips::FeatureMips3])907    EFlags |= ELF::EF_MIPS_ARCH_3;908  else if (Features[Mips::FeatureMips32r6])909    EFlags |= ELF::EF_MIPS_ARCH_32R6;910  else if (Features[Mips::FeatureMips32r2] ||911           Features[Mips::FeatureMips32r3] ||912           Features[Mips::FeatureMips32r5])913    EFlags |= ELF::EF_MIPS_ARCH_32R2;914  else if (Features[Mips::FeatureMips32])915    EFlags |= ELF::EF_MIPS_ARCH_32;916  else if (Features[Mips::FeatureMips2])917    EFlags |= ELF::EF_MIPS_ARCH_2;918  else919    EFlags |= ELF::EF_MIPS_ARCH_1;920 921  // Machine922  if (Features[Mips::FeatureCnMips])923    EFlags |= ELF::EF_MIPS_MACH_OCTEON;924 925  // Other options.926  if (Features[Mips::FeatureNaN2008])927    EFlags |= ELF::EF_MIPS_NAN2008;928 929  W.setELFHeaderEFlags(EFlags);930}931 932void MipsTargetELFStreamer::emitLabel(MCSymbol *S) {933  auto *Symbol = static_cast<MCSymbolELF *>(S);934  getStreamer().getAssembler().registerSymbol(*Symbol);935  uint8_t Type = Symbol->getType();936  if (Type != ELF::STT_FUNC)937    return;938 939  if (isMicroMipsEnabled())940    Symbol->setOther(ELF::STO_MIPS_MICROMIPS);941}942 943void MipsTargetELFStreamer::finish() {944  MCAssembler &MCA = getStreamer().getAssembler();945  ELFObjectWriter &W = getStreamer().getWriter();946  const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo();947  MCELFStreamer &S = getStreamer();948 949  // .bss, .text and .data are always at least 16-byte aligned.950  MCSection &TextSection = *OFI.getTextSection();951  S.switchSection(&TextSection);952  MCSection &DataSection = *OFI.getDataSection();953  S.switchSection(&DataSection);954  MCSection &BSSSection = *OFI.getBSSSection();955  S.switchSection(&BSSSection);956 957  TextSection.ensureMinAlignment(Align(16));958  DataSection.ensureMinAlignment(Align(16));959  BSSSection.ensureMinAlignment(Align(16));960 961  if (RoundSectionSizes) {962    // Make sections sizes a multiple of the alignment. This is useful for963    // verifying the output of IAS against the output of other assemblers but964    // it's not necessary to produce a correct object and increases section965    // size.966    for (MCSection &Sec : MCA) {967      MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);968 969      Align Alignment = Section.getAlign();970      S.switchSection(&Section);971      if (getContext().getAsmInfo()->useCodeAlign(Section))972        S.emitCodeAlignment(Alignment, &STI, Alignment.value());973      else974        S.emitValueToAlignment(Alignment, 0, 1, Alignment.value());975    }976  }977 978  const FeatureBitset &Features = STI.getFeatureBits();979 980  // Update e_header flags. See the FIXME and comment above in981  // the constructor for a full rundown on this.982  unsigned EFlags = W.getELFHeaderEFlags();983 984  // ABI985  // N64 does not require any ABI bits.986  if (getABI().IsO32())987    EFlags |= ELF::EF_MIPS_ABI_O32;988  else if (getABI().IsN32())989    EFlags |= ELF::EF_MIPS_ABI2;990 991  if (Features[Mips::FeatureGP64Bit]) {992    if (getABI().IsO32())993      EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */994  } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64])995    EFlags |= ELF::EF_MIPS_32BITMODE;996 997  // -mplt is not implemented but we should act as if it was998  // given.999  if (!Features[Mips::FeatureNoABICalls])1000    EFlags |= ELF::EF_MIPS_CPIC;1001 1002  if (Pic)1003    EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;1004 1005  W.setELFHeaderEFlags(EFlags);1006 1007  // Emit all the option records.1008  // At the moment we are only emitting .Mips.options (ODK_REGINFO) and1009  // .reginfo.1010  MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);1011  MEF.EmitMipsOptionRecords();1012 1013  emitMipsAbiFlags();1014}1015 1016void MipsTargetELFStreamer::emitAssignment(MCSymbol *S, const MCExpr *Value) {1017  auto *Symbol = static_cast<MCSymbolELF *>(S);1018  // If on rhs is micromips symbol then mark Symbol as microMips.1019  if (Value->getKind() != MCExpr::SymbolRef)1020    return;1021  auto &RhsSym = static_cast<const MCSymbolELF &>(1022      static_cast<const MCSymbolRefExpr *>(Value)->getSymbol());1023 1024  if (!(RhsSym.getOther() & ELF::STO_MIPS_MICROMIPS))1025    return;1026 1027  Symbol->setOther(ELF::STO_MIPS_MICROMIPS);1028}1029 1030MCELFStreamer &MipsTargetELFStreamer::getStreamer() {1031  return static_cast<MCELFStreamer &>(Streamer);1032}1033 1034void MipsTargetELFStreamer::emitGPRel32Value(const MCExpr *Value) {1035  auto &S = getStreamer();1036  S.ensureHeadroom(4);1037  S.addFixup(Value, Mips::fixup_Mips_GPREL32);1038  S.appendContents(4, 0);1039}1040 1041void MipsTargetELFStreamer::emitGPRel64Value(const MCExpr *Value) {1042  auto &S = getStreamer();1043  S.ensureHeadroom(8);1044  // fixup_Mips_GPREL32 desginates R_MIPS_GPREL32+R_MIPS_64 on MIPS64.1045  S.addFixup(Value, Mips::fixup_Mips_GPREL32);1046  S.appendContents(8, 0);1047}1048 1049void MipsTargetELFStreamer::emitDTPRel32Value(const MCExpr *Value) {1050  auto &S = getStreamer();1051  S.ensureHeadroom(4);1052  S.addFixup(Value, Mips::fixup_Mips_DTPREL32);1053  S.appendContents(4, 0);1054}1055 1056void MipsTargetELFStreamer::emitDTPRel64Value(const MCExpr *Value) {1057  auto &S = getStreamer();1058  S.ensureHeadroom(8);1059  S.addFixup(Value, Mips::fixup_Mips_DTPREL64);1060  S.appendContents(8, 0);1061}1062 1063void MipsTargetELFStreamer::emitTPRel32Value(const MCExpr *Value) {1064  auto &S = getStreamer();1065  S.ensureHeadroom(4);1066  S.addFixup(Value, Mips::fixup_Mips_TPREL32);1067  S.appendContents(4, 0);1068}1069 1070void MipsTargetELFStreamer::emitTPRel64Value(const MCExpr *Value) {1071  auto &S = getStreamer();1072  S.ensureHeadroom(8);1073  S.addFixup(Value, Mips::fixup_Mips_TPREL64);1074  S.appendContents(8, 0);1075}1076 1077void MipsTargetELFStreamer::emitDirectiveSetMicroMips() {1078  MicroMipsEnabled = true;1079  forbidModuleDirective();1080}1081 1082void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() {1083  MicroMipsEnabled = false;1084  forbidModuleDirective();1085}1086 1087void MipsTargetELFStreamer::setUsesMicroMips() {1088  ELFObjectWriter &W = getStreamer().getWriter();1089  unsigned Flags = W.getELFHeaderEFlags();1090  Flags |= ELF::EF_MIPS_MICROMIPS;1091  W.setELFHeaderEFlags(Flags);1092}1093 1094void MipsTargetELFStreamer::emitDirectiveSetMips16() {1095  ELFObjectWriter &W = getStreamer().getWriter();1096  unsigned Flags = W.getELFHeaderEFlags();1097  Flags |= ELF::EF_MIPS_ARCH_ASE_M16;1098  W.setELFHeaderEFlags(Flags);1099  forbidModuleDirective();1100}1101 1102void MipsTargetELFStreamer::emitDirectiveSetNoReorder() {1103  ELFObjectWriter &W = getStreamer().getWriter();1104  unsigned Flags = W.getELFHeaderEFlags();1105  Flags |= ELF::EF_MIPS_NOREORDER;1106  W.setELFHeaderEFlags(Flags);1107  forbidModuleDirective();1108}1109 1110void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {1111  MCAssembler &MCA = getStreamer().getAssembler();1112  MCContext &Context = MCA.getContext();1113  MCStreamer &OS = getStreamer();1114 1115  OS.pushSection();1116  MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0);1117  OS.switchSection(Sec);1118  Sec->setAlignment(Align(4));1119 1120  MCSymbol *Sym = Context.getOrCreateSymbol(Name);1121  const auto *ExprRef = MCSymbolRefExpr::create(Sym, Context);1122  OS.emitValueImpl(ExprRef, 4);1123 1124  OS.emitIntValue(GPRInfoSet ? GPRBitMask : 0, 4); // reg_mask1125  OS.emitIntValue(GPRInfoSet ? GPROffset : 0, 4);  // reg_offset1126 1127  OS.emitIntValue(FPRInfoSet ? FPRBitMask : 0, 4); // fpreg_mask1128  OS.emitIntValue(FPRInfoSet ? FPROffset : 0, 4);  // fpreg_offset1129 1130  OS.emitIntValue(FrameInfoSet ? FrameOffset : 0, 4); // frame_offset1131  OS.emitIntValue(FrameInfoSet ? FrameReg : 0, 4);    // frame_reg1132  OS.emitIntValue(FrameInfoSet ? ReturnReg : 0, 4);   // return_reg1133 1134  // The .end directive marks the end of a procedure. Invalidate1135  // the information gathered up until this point.1136  GPRInfoSet = FPRInfoSet = FrameInfoSet = false;1137 1138  OS.popSection();1139 1140  // .end also implicitly sets the size.1141  MCSymbol *CurPCSym = Context.createTempSymbol();1142  OS.emitLabel(CurPCSym);1143  const MCExpr *Size = MCBinaryExpr::createSub(1144      MCSymbolRefExpr::create(CurPCSym, Context), ExprRef, Context);1145 1146  // The ELFObjectWriter can determine the absolute size as it has access to1147  // the layout information of the assembly file, so a size expression rather1148  // than an absolute value is ok here.1149  static_cast<MCSymbolELF *>(Sym)->setSize(Size);1150}1151 1152void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {1153  GPRInfoSet = FPRInfoSet = FrameInfoSet = false;1154 1155  // .ent also acts like an implicit '.type symbol, STT_FUNC'1156  static_cast<const MCSymbolELF &>(Symbol).setType(ELF::STT_FUNC);1157}1158 1159void MipsTargetELFStreamer::emitDirectiveAbiCalls() {1160  ELFObjectWriter &W = getStreamer().getWriter();1161  unsigned Flags = W.getELFHeaderEFlags();1162  Flags |= ELF::EF_MIPS_CPIC | ELF::EF_MIPS_PIC;1163  W.setELFHeaderEFlags(Flags);1164}1165 1166void MipsTargetELFStreamer::emitDirectiveNaN2008() {1167  ELFObjectWriter &W = getStreamer().getWriter();1168  unsigned Flags = W.getELFHeaderEFlags();1169  Flags |= ELF::EF_MIPS_NAN2008;1170  W.setELFHeaderEFlags(Flags);1171}1172 1173void MipsTargetELFStreamer::emitDirectiveNaNLegacy() {1174  ELFObjectWriter &W = getStreamer().getWriter();1175  unsigned Flags = W.getELFHeaderEFlags();1176  Flags &= ~ELF::EF_MIPS_NAN2008;1177  W.setELFHeaderEFlags(Flags);1178}1179 1180void MipsTargetELFStreamer::emitDirectiveOptionPic0() {1181  ELFObjectWriter &W = getStreamer().getWriter();1182  unsigned Flags = W.getELFHeaderEFlags();1183  // This option overrides other PIC options like -KPIC.1184  Pic = false;1185  Flags &= ~ELF::EF_MIPS_PIC;1186  W.setELFHeaderEFlags(Flags);1187}1188 1189void MipsTargetELFStreamer::emitDirectiveOptionPic2() {1190  ELFObjectWriter &W = getStreamer().getWriter();1191  unsigned Flags = W.getELFHeaderEFlags();1192  Pic = true;1193  // NOTE: We are following the GAS behaviour here which means the directive1194  // 'pic2' also sets the CPIC bit in the ELF header. This is different from1195  // what is stated in the SYSV ABI which consider the bits EF_MIPS_PIC and1196  // EF_MIPS_CPIC to be mutually exclusive.1197  Flags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;1198  W.setELFHeaderEFlags(Flags);1199}1200 1201void MipsTargetELFStreamer::emitDirectiveInsn() {1202  MipsTargetStreamer::emitDirectiveInsn();1203  MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);1204  MEF.createPendingLabelRelocs();1205}1206 1207void MipsTargetELFStreamer::emitFrame(MCRegister StackReg, unsigned StackSize,1208                                      MCRegister ReturnReg_) {1209  MCContext &Context = getStreamer().getAssembler().getContext();1210  const MCRegisterInfo *RegInfo = Context.getRegisterInfo();1211 1212  FrameInfoSet = true;1213  FrameReg = RegInfo->getEncodingValue(StackReg);1214  FrameOffset = StackSize;1215  ReturnReg = RegInfo->getEncodingValue(ReturnReg_);1216}1217 1218void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask,1219                                     int CPUTopSavedRegOff) {1220  GPRInfoSet = true;1221  GPRBitMask = CPUBitmask;1222  GPROffset = CPUTopSavedRegOff;1223}1224 1225void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask,1226                                      int FPUTopSavedRegOff) {1227  FPRInfoSet = true;1228  FPRBitMask = FPUBitmask;1229  FPROffset = FPUTopSavedRegOff;1230}1231 1232void MipsTargetELFStreamer::emitDirectiveCpAdd(MCRegister Reg) {1233  // .cpadd $reg1234  // This directive inserts code to add $gp to the argument's register1235  // when support for position independent code is enabled.1236  if (!Pic)1237    return;1238 1239  emitAddu(Reg, Reg, GPReg, getABI().IsN64(), &STI);1240  forbidModuleDirective();1241}1242 1243void MipsTargetELFStreamer::emitDirectiveCpLoad(MCRegister Reg) {1244  // .cpload $reg1245  // This directive expands to:1246  // lui   $gp, %hi(_gp_disp)1247  // addui $gp, $gp, %lo(_gp_disp)1248  // addu  $gp, $gp, $reg1249  // when support for position independent code is enabled.1250  if (!Pic || (getABI().IsN32() || getABI().IsN64()))1251    return;1252 1253  // There's a GNU extension controlled by -mno-shared that allows1254  // locally-binding symbols to be accessed using absolute addresses.1255  // This is currently not supported. When supported -mno-shared makes1256  // .cpload expand to:1257  //   lui     $gp, %hi(__gnu_local_gp)1258  //   addiu   $gp, $gp, %lo(__gnu_local_gp)1259 1260  StringRef SymName("_gp_disp");1261  MCAssembler &MCA = getStreamer().getAssembler();1262  MCSymbol *GP_Disp = MCA.getContext().getOrCreateSymbol(SymName);1263  MCA.registerSymbol(*GP_Disp);1264 1265  MCInst TmpInst;1266  TmpInst.setOpcode(Mips::LUi);1267  TmpInst.addOperand(MCOperand::createReg(GPReg));1268  auto *HiSym = MCSpecifierExpr::create(GP_Disp, Mips::S_HI, MCA.getContext());1269  TmpInst.addOperand(MCOperand::createExpr(HiSym));1270  getStreamer().emitInstruction(TmpInst, STI);1271 1272  TmpInst.clear();1273 1274  TmpInst.setOpcode(Mips::ADDiu);1275  TmpInst.addOperand(MCOperand::createReg(GPReg));1276  TmpInst.addOperand(MCOperand::createReg(GPReg));1277  auto *LoSym = MCSpecifierExpr::create(GP_Disp, Mips::S_LO, MCA.getContext());1278  TmpInst.addOperand(MCOperand::createExpr(LoSym));1279  getStreamer().emitInstruction(TmpInst, STI);1280 1281  TmpInst.clear();1282 1283  TmpInst.setOpcode(Mips::ADDu);1284  TmpInst.addOperand(MCOperand::createReg(GPReg));1285  TmpInst.addOperand(MCOperand::createReg(GPReg));1286  TmpInst.addOperand(MCOperand::createReg(Reg));1287  getStreamer().emitInstruction(TmpInst, STI);1288 1289  forbidModuleDirective();1290}1291 1292void MipsTargetELFStreamer::emitDirectiveCpLocal(MCRegister Reg) {1293  if (Pic)1294    MipsTargetStreamer::emitDirectiveCpLocal(Reg);1295}1296 1297bool MipsTargetELFStreamer::emitDirectiveCpRestore(1298    int Offset, function_ref<MCRegister()> GetATReg, SMLoc IDLoc,1299    const MCSubtargetInfo *STI) {1300  MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);1301  // .cprestore offset1302  // When PIC mode is enabled and the O32 ABI is used, this directive expands1303  // to:1304  //    sw $gp, offset($sp)1305  // and adds a corresponding LW after every JAL.1306 1307  // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it1308  // is used in non-PIC mode.1309  if (!Pic || (getABI().IsN32() || getABI().IsN64()))1310    return true;1311 1312  // Store the $gp on the stack.1313  emitStoreWithImmOffset(Mips::SW, GPReg, Mips::SP, Offset, GetATReg, IDLoc,1314                         STI);1315  return true;1316}1317 1318void MipsTargetELFStreamer::emitDirectiveCpsetup(MCRegister Reg,1319                                                 int RegOrOffset,1320                                                 const MCSymbol &Sym,1321                                                 bool IsReg) {1322  // Only N32 and N64 emit anything for .cpsetup iff PIC is set.1323  if (!Pic || !(getABI().IsN32() || getABI().IsN64()))1324    return;1325 1326  forbidModuleDirective();1327 1328  MCAssembler &MCA = getStreamer().getAssembler();1329  MCInst Inst;1330 1331  // Either store the old $gp in a register or on the stack1332  if (IsReg) {1333    // move $save, $gpreg1334    emitRRR(Mips::OR64, RegOrOffset, GPReg, Mips::ZERO, SMLoc(), &STI);1335  } else {1336    // sd $gpreg, offset($sp)1337    emitRRI(Mips::SD, GPReg, Mips::SP, RegOrOffset, SMLoc(), &STI);1338  }1339 1340  auto *HiExpr =1341      Mips::createGpOff(MCSymbolRefExpr::create(&Sym, MCA.getContext()),1342                        Mips::S_HI, MCA.getContext());1343  auto *LoExpr =1344      Mips::createGpOff(MCSymbolRefExpr::create(&Sym, MCA.getContext()),1345                        Mips::S_LO, MCA.getContext());1346 1347  // lui $gp, %hi(%neg(%gp_rel(funcSym)))1348  emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI);1349 1350  // addiu  $gp, $gp, %lo(%neg(%gp_rel(funcSym)))1351  emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(),1352          &STI);1353 1354  // (d)addu  $gp, $gp, $funcreg1355  if (getABI().IsN32())1356    emitRRR(Mips::ADDu, GPReg, GPReg, Reg, SMLoc(), &STI);1357  else1358    emitRRR(Mips::DADDu, GPReg, GPReg, Reg, SMLoc(), &STI);1359}1360 1361void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,1362                                                  bool SaveLocationIsRegister) {1363  // Only N32 and N64 emit anything for .cpreturn iff PIC is set.1364  if (!Pic || !(getABI().IsN32() || getABI().IsN64()))1365    return;1366 1367  MCInst Inst;1368  // Either restore the old $gp from a register or on the stack1369  if (SaveLocationIsRegister) {1370    Inst.setOpcode(Mips::OR);1371    Inst.addOperand(MCOperand::createReg(GPReg));1372    Inst.addOperand(MCOperand::createReg(SaveLocation));1373    Inst.addOperand(MCOperand::createReg(Mips::ZERO));1374  } else {1375    Inst.setOpcode(Mips::LD);1376    Inst.addOperand(MCOperand::createReg(GPReg));1377    Inst.addOperand(MCOperand::createReg(Mips::SP));1378    Inst.addOperand(MCOperand::createImm(SaveLocation));1379  }1380  getStreamer().emitInstruction(Inst, STI);1381 1382  forbidModuleDirective();1383}1384 1385void MipsTargetELFStreamer::emitMipsAbiFlags() {1386  MCAssembler &MCA = getStreamer().getAssembler();1387  MCContext &Context = MCA.getContext();1388  MCStreamer &OS = getStreamer();1389  MCSectionELF *Sec = Context.getELFSection(1390      ".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24);1391  OS.switchSection(Sec);1392  Sec->setAlignment(Align(8));1393 1394  OS << ABIFlagsSection;1395}1396