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