186ac5c1bSJack Carter //===-- MipsTargetStreamer.cpp - Mips Target Streamer Methods -------------===//
286ac5c1bSJack Carter //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
686ac5c1bSJack Carter //
786ac5c1bSJack Carter //===----------------------------------------------------------------------===//
886ac5c1bSJack Carter //
986ac5c1bSJack Carter // This file provides Mips specific target streamer methods.
1086ac5c1bSJack Carter //
1186ac5c1bSJack Carter //===----------------------------------------------------------------------===//
1286ac5c1bSJack Carter
13b550cb17SMehdi Amini #include "MipsTargetStreamer.h"
146bda14b3SChandler Carruth #include "MCTargetDesc/MipsABIInfo.h"
1568c3747eSDaniel Sanders #include "MipsELFStreamer.h"
16ef736a1cSserge-sans-paille #include "MipsInstPrinter.h"
17fe98b2f5SDaniel Sanders #include "MipsMCExpr.h"
18442f7848SChandler Carruth #include "MipsMCTargetDesc.h"
19972e71abSRafael Espindola #include "MipsTargetObjectFile.h"
20264b5d9eSZachary Turner #include "llvm/BinaryFormat/ELF.h"
21ef736a1cSserge-sans-paille #include "llvm/MC/MCAssembler.h"
22972e71abSRafael Espindola #include "llvm/MC/MCContext.h"
23972e71abSRafael Espindola #include "llvm/MC/MCSectionELF.h"
24cb1953f6SRafael Espindola #include "llvm/MC/MCSubtargetInfo.h"
2595fb9b93SRafael Espindola #include "llvm/MC/MCSymbolELF.h"
26ef736a1cSserge-sans-paille #include "llvm/Support/Casting.h"
27c07f06aeSDaniel Sanders #include "llvm/Support/CommandLine.h"
2886ac5c1bSJack Carter #include "llvm/Support/ErrorHandling.h"
2986ac5c1bSJack Carter #include "llvm/Support/FormattedStream.h"
3086ac5c1bSJack Carter
3186ac5c1bSJack Carter using namespace llvm;
3286ac5c1bSJack Carter
33c07f06aeSDaniel Sanders namespace {
34c07f06aeSDaniel Sanders static cl::opt<bool> RoundSectionSizes(
35c07f06aeSDaniel Sanders "mips-round-section-sizes", cl::init(false),
36c07f06aeSDaniel Sanders cl::desc("Round section sizes up to the section alignment"), cl::Hidden);
37c07f06aeSDaniel Sanders } // end anonymous namespace
38c07f06aeSDaniel Sanders
isMicroMips(const MCSubtargetInfo * STI)39e5fa049eSSimon Atanasyan static bool isMicroMips(const MCSubtargetInfo *STI) {
40e5fa049eSSimon Atanasyan return STI->getFeatureBits()[Mips::FeatureMicroMips];
41e5fa049eSSimon Atanasyan }
42e5fa049eSSimon Atanasyan
isMips32r6(const MCSubtargetInfo * STI)43ba1c70c6SSimon Dardis static bool isMips32r6(const MCSubtargetInfo *STI) {
44ba1c70c6SSimon Dardis return STI->getFeatureBits()[Mips::FeatureMips32r6];
45ba1c70c6SSimon Dardis }
46ba1c70c6SSimon Dardis
MipsTargetStreamer(MCStreamer & S)47fb8a2a95SVladimir Medic MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)
48a884afb6SSimon Atanasyan : MCTargetStreamer(S), GPReg(Mips::GP), ModuleDirectiveAllowed(true) {
49d97a634fSDaniel Sanders GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
50d97a634fSDaniel Sanders }
emitDirectiveSetMicroMips()5160890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveSetMicroMips() {}
emitDirectiveSetNoMicroMips()5260890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {}
setUsesMicroMips()53cda908a0SDaniel Sanders void MipsTargetStreamer::setUsesMicroMips() {}
emitDirectiveSetMips16()5460890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveSetMips16() {}
emitDirectiveSetNoMips16()55cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); }
emitDirectiveSetReorder()56cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); }
emitDirectiveSetNoReorder()5760890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveSetNoReorder() {}
emitDirectiveSetMacro()58cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); }
emitDirectiveSetNoMacro()59cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); }
emitDirectiveSetMsa()60cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); }
emitDirectiveSetNoMsa()61cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); }
emitDirectiveSetMt()62805f1e03SSimon Dardis void MipsTargetStreamer::emitDirectiveSetMt() {}
emitDirectiveSetNoMt()63805f1e03SSimon Dardis void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); }
emitDirectiveSetCRC()643408caf6SPetar Jovanovic void MipsTargetStreamer::emitDirectiveSetCRC() {}
emitDirectiveSetNoCRC()653408caf6SPetar Jovanovic void MipsTargetStreamer::emitDirectiveSetNoCRC() {}
emitDirectiveSetVirt()66d4349f3bSPetar Jovanovic void MipsTargetStreamer::emitDirectiveSetVirt() {}
emitDirectiveSetNoVirt()67d4349f3bSPetar Jovanovic void MipsTargetStreamer::emitDirectiveSetNoVirt() {}
emitDirectiveSetGINV()68daf51693SPetar Jovanovic void MipsTargetStreamer::emitDirectiveSetGINV() {}
emitDirectiveSetNoGINV()69daf51693SPetar Jovanovic void MipsTargetStreamer::emitDirectiveSetNoGINV() {}
emitDirectiveSetAt()70cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); }
emitDirectiveSetAtWithArg(unsigned RegNo)7116a74499SToma Tabacu void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
7216a74499SToma Tabacu forbidModuleDirective();
7316a74499SToma Tabacu }
emitDirectiveSetNoAt()74cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); }
emitDirectiveEnd(StringRef Name)7560890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {}
emitDirectiveEnt(const MCSymbol & Symbol)7660890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {}
emitDirectiveAbiCalls()7760890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveAbiCalls() {}
emitDirectiveNaN2008()7860890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveNaN2008() {}
emitDirectiveNaNLegacy()7960890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveNaNLegacy() {}
emitDirectiveOptionPic0()8060890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveOptionPic0() {}
emitDirectiveOptionPic2()8160890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveOptionPic2() {}
emitDirectiveInsn()829ca5096fSToma Tabacu void MipsTargetStreamer::emitDirectiveInsn() { forbidModuleDirective(); }
emitFrame(unsigned StackReg,unsigned StackSize,unsigned ReturnReg)8360890b89SRafael Espindola void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
8460890b89SRafael Espindola unsigned ReturnReg) {}
emitMask(unsigned CPUBitmask,int CPUTopSavedRegOff)8560890b89SRafael Espindola void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {}
emitFMask(unsigned FPUBitmask,int FPUTopSavedRegOff)8660890b89SRafael Espindola void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) {
8760890b89SRafael Espindola }
emitDirectiveSetArch(StringRef Arch)8885618b31SToma Tabacu void MipsTargetStreamer::emitDirectiveSetArch(StringRef Arch) {
8985618b31SToma Tabacu forbidModuleDirective();
9085618b31SToma Tabacu }
emitDirectiveSetMips0()914e0cf8e2SToma Tabacu void MipsTargetStreamer::emitDirectiveSetMips0() { forbidModuleDirective(); }
emitDirectiveSetMips1()92cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips1() { forbidModuleDirective(); }
emitDirectiveSetMips2()93cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips2() { forbidModuleDirective(); }
emitDirectiveSetMips3()94cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips3() { forbidModuleDirective(); }
emitDirectiveSetMips4()95cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); }
emitDirectiveSetMips5()96cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); }
emitDirectiveSetMips32()97cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); }
emitDirectiveSetMips32R2()98cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); }
emitDirectiveSetMips32R3()991779314eSDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips32R3() { forbidModuleDirective(); }
emitDirectiveSetMips32R5()1001779314eSDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips32R5() { forbidModuleDirective(); }
emitDirectiveSetMips32R6()101cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); }
emitDirectiveSetMips64()102cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); }
emitDirectiveSetMips64R2()103cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); }
emitDirectiveSetMips64R3()1041779314eSDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips64R3() { forbidModuleDirective(); }
emitDirectiveSetMips64R5()1051779314eSDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips64R5() { forbidModuleDirective(); }
emitDirectiveSetMips64R6()106cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); }
emitDirectiveSetPop()1074e0cf8e2SToma Tabacu void MipsTargetStreamer::emitDirectiveSetPop() { forbidModuleDirective(); }
emitDirectiveSetPush()1084e0cf8e2SToma Tabacu void MipsTargetStreamer::emitDirectiveSetPush() { forbidModuleDirective(); }
emitDirectiveSetSoftFloat()1092969650eSToma Tabacu void MipsTargetStreamer::emitDirectiveSetSoftFloat() {
1102969650eSToma Tabacu forbidModuleDirective();
1112969650eSToma Tabacu }
emitDirectiveSetHardFloat()1122969650eSToma Tabacu void MipsTargetStreamer::emitDirectiveSetHardFloat() {
1132969650eSToma Tabacu forbidModuleDirective();
1142969650eSToma Tabacu }
emitDirectiveSetDsp()115cdb45fa3SDaniel Sanders void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }
emitDirectiveSetDspr2()11665f10246SPetar Jovanovic void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); }
emitDirectiveSetNoDsp()117351b2feeSToma Tabacu void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
emitDirectiveSetMips3D()11873b1da16SSimon Atanasyan void MipsTargetStreamer::emitDirectiveSetMips3D() { forbidModuleDirective(); }
emitDirectiveSetNoMips3D()11973b1da16SSimon Atanasyan void MipsTargetStreamer::emitDirectiveSetNoMips3D() { forbidModuleDirective(); }
emitDirectiveCpAdd(unsigned RegNo)1202dc4eb08SSimon Atanasyan void MipsTargetStreamer::emitDirectiveCpAdd(unsigned RegNo) {}
emitDirectiveCpLoad(unsigned RegNo)121c4c202a9SToma Tabacu void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
emitDirectiveCpLocal(unsigned RegNo)122a884afb6SSimon Atanasyan void MipsTargetStreamer::emitDirectiveCpLocal(unsigned RegNo) {
123a884afb6SSimon Atanasyan // .cplocal $reg
124a884afb6SSimon Atanasyan // This directive forces to use the alternate register for context pointer.
125a884afb6SSimon Atanasyan // For example
126a884afb6SSimon Atanasyan // .cplocal $4
127a884afb6SSimon Atanasyan // jal foo
128a884afb6SSimon Atanasyan // expands to
129a884afb6SSimon Atanasyan // ld $25, %call16(foo)($4)
130a884afb6SSimon Atanasyan // jalr $25
131a884afb6SSimon Atanasyan
132a884afb6SSimon Atanasyan if (!getABI().IsN32() && !getABI().IsN64())
133a884afb6SSimon Atanasyan return;
134a884afb6SSimon Atanasyan
135a884afb6SSimon Atanasyan GPReg = RegNo;
136a884afb6SSimon Atanasyan
137a884afb6SSimon Atanasyan forbidModuleDirective();
138a884afb6SSimon Atanasyan }
emitDirectiveCpRestore(int Offset,function_ref<unsigned ()> GetATReg,SMLoc IDLoc,const MCSubtargetInfo * STI)139df8510d4SDaniel Sanders bool MipsTargetStreamer::emitDirectiveCpRestore(
140d3f4c05aSBenjamin Kramer int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
1417225cd52SDaniel Sanders const MCSubtargetInfo *STI) {
142e2982adcSDaniel Sanders forbidModuleDirective();
143df8510d4SDaniel Sanders return true;
144e2982adcSDaniel Sanders }
emitDirectiveCpsetup(unsigned RegNo,int RegOrOffset,const MCSymbol & Sym,bool IsReg)14560890b89SRafael Espindola void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
14660890b89SRafael Espindola const MCSymbol &Sym, bool IsReg) {
14760890b89SRafael Espindola }
emitDirectiveCpreturn(unsigned SaveLocation,bool SaveLocationIsRegister)148f173dda0SDaniel Sanders void MipsTargetStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
149f173dda0SDaniel Sanders bool SaveLocationIsRegister) {}
150bfcbfd56SToma Tabacu
emitDirectiveModuleFP()151a64e5405SToma Tabacu void MipsTargetStreamer::emitDirectiveModuleFP() {}
152bfcbfd56SToma Tabacu
emitDirectiveModuleOddSPReg()1533c499589SToma Tabacu void MipsTargetStreamer::emitDirectiveModuleOddSPReg() {
1543c499589SToma Tabacu if (!ABIFlagsSection.OddSPReg && !ABIFlagsSection.Is32BitABI)
1557e527423SDaniel Sanders report_fatal_error("+nooddspreg is only valid for O32");
1567e527423SDaniel Sanders }
emitDirectiveModuleSoftFloat()1570f093130SToma Tabacu void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {}
emitDirectiveModuleHardFloat()1580f093130SToma Tabacu void MipsTargetStreamer::emitDirectiveModuleHardFloat() {}
emitDirectiveModuleMT()159805f1e03SSimon Dardis void MipsTargetStreamer::emitDirectiveModuleMT() {}
emitDirectiveModuleCRC()1603408caf6SPetar Jovanovic void MipsTargetStreamer::emitDirectiveModuleCRC() {}
emitDirectiveModuleNoCRC()1613408caf6SPetar Jovanovic void MipsTargetStreamer::emitDirectiveModuleNoCRC() {}
emitDirectiveModuleVirt()162d4349f3bSPetar Jovanovic void MipsTargetStreamer::emitDirectiveModuleVirt() {}
emitDirectiveModuleNoVirt()163d4349f3bSPetar Jovanovic void MipsTargetStreamer::emitDirectiveModuleNoVirt() {}
emitDirectiveModuleGINV()164daf51693SPetar Jovanovic void MipsTargetStreamer::emitDirectiveModuleGINV() {}
emitDirectiveModuleNoGINV()165daf51693SPetar Jovanovic void MipsTargetStreamer::emitDirectiveModuleNoGINV() {}
emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value)1664e0cf8e2SToma Tabacu void MipsTargetStreamer::emitDirectiveSetFp(
1674e0cf8e2SToma Tabacu MipsABIFlagsSection::FpABIKind Value) {
1684e0cf8e2SToma Tabacu forbidModuleDirective();
1694e0cf8e2SToma Tabacu }
emitDirectiveSetOddSPReg()17032c72aa0SToma Tabacu void MipsTargetStreamer::emitDirectiveSetOddSPReg() { forbidModuleDirective(); }
emitDirectiveSetNoOddSPReg()17132c72aa0SToma Tabacu void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() {
17232c72aa0SToma Tabacu forbidModuleDirective();
17332c72aa0SToma Tabacu }
17424ea09efSRafael Espindola
emitR(unsigned Opcode,unsigned Reg0,SMLoc IDLoc,const MCSubtargetInfo * STI)175a736b37aSDaniel Sanders void MipsTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
176a736b37aSDaniel Sanders const MCSubtargetInfo *STI) {
177a736b37aSDaniel Sanders MCInst TmpInst;
178a736b37aSDaniel Sanders TmpInst.setOpcode(Opcode);
179a736b37aSDaniel Sanders TmpInst.addOperand(MCOperand::createReg(Reg0));
180a736b37aSDaniel Sanders TmpInst.setLoc(IDLoc);
181bcd24b2dSFangrui Song getStreamer().emitInstruction(TmpInst, *STI);
182a736b37aSDaniel Sanders }
183a736b37aSDaniel Sanders
emitRX(unsigned Opcode,unsigned Reg0,MCOperand Op1,SMLoc IDLoc,const MCSubtargetInfo * STI)184a736b37aSDaniel Sanders void MipsTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1,
185a736b37aSDaniel Sanders SMLoc IDLoc, const MCSubtargetInfo *STI) {
186a736b37aSDaniel Sanders MCInst TmpInst;
187a736b37aSDaniel Sanders TmpInst.setOpcode(Opcode);
188a736b37aSDaniel Sanders TmpInst.addOperand(MCOperand::createReg(Reg0));
189a736b37aSDaniel Sanders TmpInst.addOperand(Op1);
190a736b37aSDaniel Sanders TmpInst.setLoc(IDLoc);
191bcd24b2dSFangrui Song getStreamer().emitInstruction(TmpInst, *STI);
192a736b37aSDaniel Sanders }
193a736b37aSDaniel Sanders
emitRI(unsigned Opcode,unsigned Reg0,int32_t Imm,SMLoc IDLoc,const MCSubtargetInfo * STI)194a736b37aSDaniel Sanders void MipsTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm,
195a736b37aSDaniel Sanders SMLoc IDLoc, const MCSubtargetInfo *STI) {
196a736b37aSDaniel Sanders emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI);
197a736b37aSDaniel Sanders }
198a736b37aSDaniel Sanders
emitRR(unsigned Opcode,unsigned Reg0,unsigned Reg1,SMLoc IDLoc,const MCSubtargetInfo * STI)199a736b37aSDaniel Sanders void MipsTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
200a736b37aSDaniel Sanders SMLoc IDLoc, const MCSubtargetInfo *STI) {
201a736b37aSDaniel Sanders emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI);
202a736b37aSDaniel Sanders }
203a736b37aSDaniel Sanders
emitII(unsigned Opcode,int16_t Imm1,int16_t Imm2,SMLoc IDLoc,const MCSubtargetInfo * STI)204a736b37aSDaniel Sanders void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2,
205a736b37aSDaniel Sanders SMLoc IDLoc, const MCSubtargetInfo *STI) {
206a736b37aSDaniel Sanders MCInst TmpInst;
207a736b37aSDaniel Sanders TmpInst.setOpcode(Opcode);
208a736b37aSDaniel Sanders TmpInst.addOperand(MCOperand::createImm(Imm1));
209a736b37aSDaniel Sanders TmpInst.addOperand(MCOperand::createImm(Imm2));
210a736b37aSDaniel Sanders TmpInst.setLoc(IDLoc);
211bcd24b2dSFangrui Song getStreamer().emitInstruction(TmpInst, *STI);
212a736b37aSDaniel Sanders }
213a736b37aSDaniel Sanders
emitRRX(unsigned Opcode,unsigned Reg0,unsigned Reg1,MCOperand Op2,SMLoc IDLoc,const MCSubtargetInfo * STI)214a736b37aSDaniel Sanders void MipsTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,
215a736b37aSDaniel Sanders MCOperand Op2, SMLoc IDLoc,
216a736b37aSDaniel Sanders const MCSubtargetInfo *STI) {
217a736b37aSDaniel Sanders MCInst TmpInst;
218a736b37aSDaniel Sanders TmpInst.setOpcode(Opcode);
219a736b37aSDaniel Sanders TmpInst.addOperand(MCOperand::createReg(Reg0));
220a736b37aSDaniel Sanders TmpInst.addOperand(MCOperand::createReg(Reg1));
221a736b37aSDaniel Sanders TmpInst.addOperand(Op2);
222a736b37aSDaniel Sanders TmpInst.setLoc(IDLoc);
223bcd24b2dSFangrui Song getStreamer().emitInstruction(TmpInst, *STI);
224a736b37aSDaniel Sanders }
225a736b37aSDaniel Sanders
emitRRR(unsigned Opcode,unsigned Reg0,unsigned Reg1,unsigned Reg2,SMLoc IDLoc,const MCSubtargetInfo * STI)226a736b37aSDaniel Sanders void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
227a736b37aSDaniel Sanders unsigned Reg2, SMLoc IDLoc,
228a736b37aSDaniel Sanders const MCSubtargetInfo *STI) {
229a736b37aSDaniel Sanders emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI);
230a736b37aSDaniel Sanders }
231a736b37aSDaniel Sanders
emitRRRX(unsigned Opcode,unsigned Reg0,unsigned Reg1,unsigned Reg2,MCOperand Op3,SMLoc IDLoc,const MCSubtargetInfo * STI)2329f2e076fSSimon Atanasyan void MipsTargetStreamer::emitRRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,
2339f2e076fSSimon Atanasyan unsigned Reg2, MCOperand Op3, SMLoc IDLoc,
2349f2e076fSSimon Atanasyan const MCSubtargetInfo *STI) {
2359f2e076fSSimon Atanasyan MCInst TmpInst;
2369f2e076fSSimon Atanasyan TmpInst.setOpcode(Opcode);
2379f2e076fSSimon Atanasyan TmpInst.addOperand(MCOperand::createReg(Reg0));
2389f2e076fSSimon Atanasyan TmpInst.addOperand(MCOperand::createReg(Reg1));
2399f2e076fSSimon Atanasyan TmpInst.addOperand(MCOperand::createReg(Reg2));
2409f2e076fSSimon Atanasyan TmpInst.addOperand(Op3);
2419f2e076fSSimon Atanasyan TmpInst.setLoc(IDLoc);
242bcd24b2dSFangrui Song getStreamer().emitInstruction(TmpInst, *STI);
2439f2e076fSSimon Atanasyan }
2449f2e076fSSimon Atanasyan
emitRRI(unsigned Opcode,unsigned Reg0,unsigned Reg1,int16_t Imm,SMLoc IDLoc,const MCSubtargetInfo * STI)245a736b37aSDaniel Sanders void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,
246a736b37aSDaniel Sanders int16_t Imm, SMLoc IDLoc,
247a736b37aSDaniel Sanders const MCSubtargetInfo *STI) {
248a736b37aSDaniel Sanders emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI);
249a736b37aSDaniel Sanders }
250a736b37aSDaniel Sanders
emitRRIII(unsigned Opcode,unsigned Reg0,unsigned Reg1,int16_t Imm0,int16_t Imm1,int16_t Imm2,SMLoc IDLoc,const MCSubtargetInfo * STI)251de5ed0c5SSimon Dardis void MipsTargetStreamer::emitRRIII(unsigned Opcode, unsigned Reg0,
252de5ed0c5SSimon Dardis unsigned Reg1, int16_t Imm0, int16_t Imm1,
253de5ed0c5SSimon Dardis int16_t Imm2, SMLoc IDLoc,
254de5ed0c5SSimon Dardis const MCSubtargetInfo *STI) {
255de5ed0c5SSimon Dardis MCInst TmpInst;
256de5ed0c5SSimon Dardis TmpInst.setOpcode(Opcode);
257de5ed0c5SSimon Dardis TmpInst.addOperand(MCOperand::createReg(Reg0));
258de5ed0c5SSimon Dardis TmpInst.addOperand(MCOperand::createReg(Reg1));
259de5ed0c5SSimon Dardis TmpInst.addOperand(MCOperand::createImm(Imm0));
260de5ed0c5SSimon Dardis TmpInst.addOperand(MCOperand::createImm(Imm1));
261de5ed0c5SSimon Dardis TmpInst.addOperand(MCOperand::createImm(Imm2));
262de5ed0c5SSimon Dardis TmpInst.setLoc(IDLoc);
263bcd24b2dSFangrui Song getStreamer().emitInstruction(TmpInst, *STI);
264de5ed0c5SSimon Dardis }
265de5ed0c5SSimon Dardis
emitAddu(unsigned DstReg,unsigned SrcReg,unsigned TrgReg,bool Is64Bit,const MCSubtargetInfo * STI)266a736b37aSDaniel Sanders void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg,
267a736b37aSDaniel Sanders unsigned TrgReg, bool Is64Bit,
268a736b37aSDaniel Sanders const MCSubtargetInfo *STI) {
269a736b37aSDaniel Sanders emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
270a736b37aSDaniel Sanders STI);
271a736b37aSDaniel Sanders }
272a736b37aSDaniel Sanders
emitDSLL(unsigned DstReg,unsigned SrcReg,int16_t ShiftAmount,SMLoc IDLoc,const MCSubtargetInfo * STI)273a736b37aSDaniel Sanders void MipsTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg,
274a736b37aSDaniel Sanders int16_t ShiftAmount, SMLoc IDLoc,
275a736b37aSDaniel Sanders const MCSubtargetInfo *STI) {
276a736b37aSDaniel Sanders if (ShiftAmount >= 32) {
277a736b37aSDaniel Sanders emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI);
278a736b37aSDaniel Sanders return;
279a736b37aSDaniel Sanders }
280a736b37aSDaniel Sanders
281a736b37aSDaniel Sanders emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI);
282a736b37aSDaniel Sanders }
283a736b37aSDaniel Sanders
emitEmptyDelaySlot(bool hasShortDelaySlot,SMLoc IDLoc,const MCSubtargetInfo * STI)284a736b37aSDaniel Sanders void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
285a736b37aSDaniel Sanders const MCSubtargetInfo *STI) {
286ba1c70c6SSimon Dardis // The default case of `nop` is `sll $zero, $zero, 0`.
287ba1c70c6SSimon Dardis unsigned Opc = Mips::SLL;
288ba1c70c6SSimon Dardis if (isMicroMips(STI) && hasShortDelaySlot) {
289ba1c70c6SSimon Dardis Opc = isMips32r6(STI) ? Mips::MOVE16_MMR6 : Mips::MOVE16_MM;
290ba1c70c6SSimon Dardis emitRR(Opc, Mips::ZERO, Mips::ZERO, IDLoc, STI);
291ba1c70c6SSimon Dardis return;
292ba1c70c6SSimon Dardis }
293ba1c70c6SSimon Dardis
294ba1c70c6SSimon Dardis if (isMicroMips(STI))
295ba1c70c6SSimon Dardis Opc = isMips32r6(STI) ? Mips::SLL_MMR6 : Mips::SLL_MM;
296ba1c70c6SSimon Dardis
297ba1c70c6SSimon Dardis emitRRI(Opc, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
298a736b37aSDaniel Sanders }
299a736b37aSDaniel Sanders
emitNop(SMLoc IDLoc,const MCSubtargetInfo * STI)300a736b37aSDaniel Sanders void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {
3018a7c0e7cSSimon Atanasyan if (isMicroMips(STI))
3028abf6804SAleksandar Beserminji emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI);
3038abf6804SAleksandar Beserminji else
304a736b37aSDaniel Sanders emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
305a736b37aSDaniel Sanders }
306a736b37aSDaniel Sanders
3077225cd52SDaniel Sanders /// Emit the $gp restore operation for .cprestore.
emitGPRestore(int Offset,SMLoc IDLoc,const MCSubtargetInfo * STI)3087225cd52SDaniel Sanders void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,
3097225cd52SDaniel Sanders const MCSubtargetInfo *STI) {
310a884afb6SSimon Atanasyan emitLoadWithImmOffset(Mips::LW, GPReg, Mips::SP, Offset, GPReg, IDLoc, STI);
3117225cd52SDaniel Sanders }
3127225cd52SDaniel Sanders
3137225cd52SDaniel Sanders /// Emit a store instruction with an immediate offset.
emitStoreWithImmOffset(unsigned Opcode,unsigned SrcReg,unsigned BaseReg,int64_t Offset,function_ref<unsigned ()> GetATReg,SMLoc IDLoc,const MCSubtargetInfo * STI)314fba875f9SDaniel Sanders void MipsTargetStreamer::emitStoreWithImmOffset(
315fba875f9SDaniel Sanders unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset,
316d3f4c05aSBenjamin Kramer function_ref<unsigned()> GetATReg, SMLoc IDLoc,
317241c6798SDaniel Sanders const MCSubtargetInfo *STI) {
3187225cd52SDaniel Sanders if (isInt<16>(Offset)) {
3197225cd52SDaniel Sanders emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI);
3207225cd52SDaniel Sanders return;
3217225cd52SDaniel Sanders }
3227225cd52SDaniel Sanders
323fba875f9SDaniel Sanders // sw $8, offset($8) => lui $at, %hi(offset)
324fba875f9SDaniel Sanders // add $at, $at, $8
325fba875f9SDaniel Sanders // sw $8, %lo(offset)($at)
326fba875f9SDaniel Sanders
327241c6798SDaniel Sanders unsigned ATReg = GetATReg();
328241c6798SDaniel Sanders if (!ATReg)
329241c6798SDaniel Sanders return;
330241c6798SDaniel Sanders
331fba875f9SDaniel Sanders unsigned LoOffset = Offset & 0x0000ffff;
332fba875f9SDaniel Sanders unsigned HiOffset = (Offset & 0xffff0000) >> 16;
333fba875f9SDaniel Sanders
334fba875f9SDaniel Sanders // If msb of LoOffset is 1(negative number) we must increment HiOffset
335fba875f9SDaniel Sanders // to account for the sign-extension of the low part.
336fba875f9SDaniel Sanders if (LoOffset & 0x8000)
337fba875f9SDaniel Sanders HiOffset++;
338fba875f9SDaniel Sanders
339fba875f9SDaniel Sanders // Generate the base address in ATReg.
340fba875f9SDaniel Sanders emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI);
341fba875f9SDaniel Sanders if (BaseReg != Mips::ZERO)
342fba875f9SDaniel Sanders emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
343fba875f9SDaniel Sanders // Emit the store with the adjusted base and offset.
344fba875f9SDaniel Sanders emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI);
345fba875f9SDaniel Sanders }
346fba875f9SDaniel Sanders
3477225cd52SDaniel Sanders /// Emit a load instruction with an immediate offset. DstReg and TmpReg are
3487225cd52SDaniel Sanders /// permitted to be the same register iff DstReg is distinct from BaseReg and
3497225cd52SDaniel Sanders /// DstReg is a GPR. It is the callers responsibility to identify such cases
3507225cd52SDaniel Sanders /// and pass the appropriate register in TmpReg.
emitLoadWithImmOffset(unsigned Opcode,unsigned DstReg,unsigned BaseReg,int64_t Offset,unsigned TmpReg,SMLoc IDLoc,const MCSubtargetInfo * STI)351fba875f9SDaniel Sanders void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg,
352fba875f9SDaniel Sanders unsigned BaseReg, int64_t Offset,
353fba875f9SDaniel Sanders unsigned TmpReg, SMLoc IDLoc,
354fba875f9SDaniel Sanders const MCSubtargetInfo *STI) {
3557225cd52SDaniel Sanders if (isInt<16>(Offset)) {
3567225cd52SDaniel Sanders emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI);
3577225cd52SDaniel Sanders return;
3587225cd52SDaniel Sanders }
3597225cd52SDaniel Sanders
360fba875f9SDaniel Sanders // 1) lw $8, offset($9) => lui $8, %hi(offset)
361fba875f9SDaniel Sanders // add $8, $8, $9
362fba875f9SDaniel Sanders // lw $8, %lo(offset)($9)
363fba875f9SDaniel Sanders // 2) lw $8, offset($8) => lui $at, %hi(offset)
364fba875f9SDaniel Sanders // add $at, $at, $8
365fba875f9SDaniel Sanders // lw $8, %lo(offset)($at)
366fba875f9SDaniel Sanders
367fba875f9SDaniel Sanders unsigned LoOffset = Offset & 0x0000ffff;
368fba875f9SDaniel Sanders unsigned HiOffset = (Offset & 0xffff0000) >> 16;
369fba875f9SDaniel Sanders
370fba875f9SDaniel Sanders // If msb of LoOffset is 1(negative number) we must increment HiOffset
371fba875f9SDaniel Sanders // to account for the sign-extension of the low part.
372fba875f9SDaniel Sanders if (LoOffset & 0x8000)
373fba875f9SDaniel Sanders HiOffset++;
374fba875f9SDaniel Sanders
375fba875f9SDaniel Sanders // Generate the base address in TmpReg.
376fba875f9SDaniel Sanders emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI);
377fba875f9SDaniel Sanders if (BaseReg != Mips::ZERO)
378fba875f9SDaniel Sanders emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
379fba875f9SDaniel Sanders // Emit the load with the adjusted base and offset.
380fba875f9SDaniel Sanders emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI);
381fba875f9SDaniel Sanders }
382fba875f9SDaniel Sanders
MipsTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream & OS)38324ea09efSRafael Espindola MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,
38424ea09efSRafael Espindola formatted_raw_ostream &OS)
38524ea09efSRafael Espindola : MipsTargetStreamer(S), OS(OS) {}
3866ef6cc5cSJack Carter
emitDirectiveSetMicroMips()3876d5f7ce3SRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() {
3886d5f7ce3SRafael Espindola OS << "\t.set\tmicromips\n";
389cdb45fa3SDaniel Sanders forbidModuleDirective();
3906ef6cc5cSJack Carter }
3916d5f7ce3SRafael Espindola
emitDirectiveSetNoMicroMips()3926d5f7ce3SRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() {
3936d5f7ce3SRafael Espindola OS << "\t.set\tnomicromips\n";
394cdb45fa3SDaniel Sanders forbidModuleDirective();
3956d5f7ce3SRafael Espindola }
3966d5f7ce3SRafael Espindola
emitDirectiveSetMips16()3976633d57aSRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetMips16() {
3986633d57aSRafael Espindola OS << "\t.set\tmips16\n";
399cdb45fa3SDaniel Sanders forbidModuleDirective();
4006633d57aSRafael Espindola }
4016633d57aSRafael Espindola
emitDirectiveSetNoMips16()4026633d57aSRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() {
4036633d57aSRafael Espindola OS << "\t.set\tnomips16\n";
40488f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetNoMips16();
4056633d57aSRafael Espindola }
4066633d57aSRafael Espindola
emitDirectiveSetReorder()407eb0a8af6SRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetReorder() {
408eb0a8af6SRafael Espindola OS << "\t.set\treorder\n";
40988f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetReorder();
410eb0a8af6SRafael Espindola }
411eb0a8af6SRafael Espindola
emitDirectiveSetNoReorder()412eb0a8af6SRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() {
413eb0a8af6SRafael Espindola OS << "\t.set\tnoreorder\n";
414cdb45fa3SDaniel Sanders forbidModuleDirective();
415eb0a8af6SRafael Espindola }
416eb0a8af6SRafael Espindola
emitDirectiveSetMacro()417eb0a8af6SRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetMacro() {
418eb0a8af6SRafael Espindola OS << "\t.set\tmacro\n";
41988f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMacro();
420eb0a8af6SRafael Espindola }
421eb0a8af6SRafael Espindola
emitDirectiveSetNoMacro()422eb0a8af6SRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() {
423eb0a8af6SRafael Espindola OS << "\t.set\tnomacro\n";
42488f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetNoMacro();
425eb0a8af6SRafael Espindola }
426eb0a8af6SRafael Espindola
emitDirectiveSetMsa()42744934431SDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMsa() {
42844934431SDaniel Sanders OS << "\t.set\tmsa\n";
42944934431SDaniel Sanders MipsTargetStreamer::emitDirectiveSetMsa();
43044934431SDaniel Sanders }
43144934431SDaniel Sanders
emitDirectiveSetNoMsa()43244934431SDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() {
43344934431SDaniel Sanders OS << "\t.set\tnomsa\n";
43444934431SDaniel Sanders MipsTargetStreamer::emitDirectiveSetNoMsa();
43544934431SDaniel Sanders }
43644934431SDaniel Sanders
emitDirectiveSetMt()437805f1e03SSimon Dardis void MipsTargetAsmStreamer::emitDirectiveSetMt() {
438805f1e03SSimon Dardis OS << "\t.set\tmt\n";
439805f1e03SSimon Dardis MipsTargetStreamer::emitDirectiveSetMt();
440805f1e03SSimon Dardis }
441805f1e03SSimon Dardis
emitDirectiveSetNoMt()442805f1e03SSimon Dardis void MipsTargetAsmStreamer::emitDirectiveSetNoMt() {
443805f1e03SSimon Dardis OS << "\t.set\tnomt\n";
444805f1e03SSimon Dardis MipsTargetStreamer::emitDirectiveSetNoMt();
445805f1e03SSimon Dardis }
446805f1e03SSimon Dardis
emitDirectiveSetCRC()4473408caf6SPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveSetCRC() {
4483408caf6SPetar Jovanovic OS << "\t.set\tcrc\n";
4493408caf6SPetar Jovanovic MipsTargetStreamer::emitDirectiveSetCRC();
4503408caf6SPetar Jovanovic }
4513408caf6SPetar Jovanovic
emitDirectiveSetNoCRC()4523408caf6SPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveSetNoCRC() {
4533408caf6SPetar Jovanovic OS << "\t.set\tnocrc\n";
4543408caf6SPetar Jovanovic MipsTargetStreamer::emitDirectiveSetNoCRC();
4553408caf6SPetar Jovanovic }
4563408caf6SPetar Jovanovic
emitDirectiveSetVirt()457d4349f3bSPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveSetVirt() {
458d4349f3bSPetar Jovanovic OS << "\t.set\tvirt\n";
459d4349f3bSPetar Jovanovic MipsTargetStreamer::emitDirectiveSetVirt();
460d4349f3bSPetar Jovanovic }
461d4349f3bSPetar Jovanovic
emitDirectiveSetNoVirt()462d4349f3bSPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() {
463d4349f3bSPetar Jovanovic OS << "\t.set\tnovirt\n";
464d4349f3bSPetar Jovanovic MipsTargetStreamer::emitDirectiveSetNoVirt();
465d4349f3bSPetar Jovanovic }
466d4349f3bSPetar Jovanovic
emitDirectiveSetGINV()467daf51693SPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveSetGINV() {
468daf51693SPetar Jovanovic OS << "\t.set\tginv\n";
469daf51693SPetar Jovanovic MipsTargetStreamer::emitDirectiveSetGINV();
470daf51693SPetar Jovanovic }
471daf51693SPetar Jovanovic
emitDirectiveSetNoGINV()472daf51693SPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveSetNoGINV() {
473daf51693SPetar Jovanovic OS << "\t.set\tnoginv\n";
474daf51693SPetar Jovanovic MipsTargetStreamer::emitDirectiveSetNoGINV();
475daf51693SPetar Jovanovic }
476daf51693SPetar Jovanovic
emitDirectiveSetAt()477eb0a8af6SRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetAt() {
478eb0a8af6SRafael Espindola OS << "\t.set\tat\n";
47988f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetAt();
480eb0a8af6SRafael Espindola }
481eb0a8af6SRafael Espindola
emitDirectiveSetAtWithArg(unsigned RegNo)48216a74499SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
48316a74499SToma Tabacu OS << "\t.set\tat=$" << Twine(RegNo) << "\n";
48416a74499SToma Tabacu MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo);
48516a74499SToma Tabacu }
48616a74499SToma Tabacu
emitDirectiveSetNoAt()487eb0a8af6SRafael Espindola void MipsTargetAsmStreamer::emitDirectiveSetNoAt() {
488eb0a8af6SRafael Espindola OS << "\t.set\tnoat\n";
48988f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetNoAt();
490eb0a8af6SRafael Espindola }
491eb0a8af6SRafael Espindola
emitDirectiveEnd(StringRef Name)492eb0a8af6SRafael Espindola void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) {
493eb0a8af6SRafael Espindola OS << "\t.end\t" << Name << '\n';
494eb0a8af6SRafael Espindola }
495eb0a8af6SRafael Espindola
emitDirectiveEnt(const MCSymbol & Symbol)4966633d57aSRafael Espindola void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {
4976633d57aSRafael Espindola OS << "\t.ent\t" << Symbol.getName() << '\n';
4986633d57aSRafael Espindola }
4996633d57aSRafael Espindola
emitDirectiveAbiCalls()5000cd3c19fSJack Carter void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; }
5010051f2dcSMatheus Almeida
emitDirectiveNaN2008()5020051f2dcSMatheus Almeida void MipsTargetAsmStreamer::emitDirectiveNaN2008() { OS << "\t.nan\t2008\n"; }
5030051f2dcSMatheus Almeida
emitDirectiveNaNLegacy()5040051f2dcSMatheus Almeida void MipsTargetAsmStreamer::emitDirectiveNaNLegacy() {
5050051f2dcSMatheus Almeida OS << "\t.nan\tlegacy\n";
5060051f2dcSMatheus Almeida }
5070051f2dcSMatheus Almeida
emitDirectiveOptionPic0()5080cd3c19fSJack Carter void MipsTargetAsmStreamer::emitDirectiveOptionPic0() {
5090cd3c19fSJack Carter OS << "\t.option\tpic0\n";
5100cd3c19fSJack Carter }
5110cd3c19fSJack Carter
emitDirectiveOptionPic2()512f79b2814SMatheus Almeida void MipsTargetAsmStreamer::emitDirectiveOptionPic2() {
513f79b2814SMatheus Almeida OS << "\t.option\tpic2\n";
514f79b2814SMatheus Almeida }
515f79b2814SMatheus Almeida
emitDirectiveInsn()5169ca5096fSToma Tabacu void MipsTargetAsmStreamer::emitDirectiveInsn() {
5179ca5096fSToma Tabacu MipsTargetStreamer::emitDirectiveInsn();
5189ca5096fSToma Tabacu OS << "\t.insn\n";
5199ca5096fSToma Tabacu }
5209ca5096fSToma Tabacu
emitFrame(unsigned StackReg,unsigned StackSize,unsigned ReturnReg)521054234faSRafael Espindola void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
522054234faSRafael Espindola unsigned ReturnReg) {
523054234faSRafael Espindola OS << "\t.frame\t$"
524054234faSRafael Espindola << StringRef(MipsInstPrinter::getRegisterName(StackReg)).lower() << ","
525054234faSRafael Espindola << StackSize << ",$"
52625fa291fSRafael Espindola << StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n';
52725fa291fSRafael Espindola }
52825fa291fSRafael Espindola
emitDirectiveSetArch(StringRef Arch)52985618b31SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) {
53085618b31SToma Tabacu OS << "\t.set arch=" << Arch << "\n";
53185618b31SToma Tabacu MipsTargetStreamer::emitDirectiveSetArch(Arch);
53285618b31SToma Tabacu }
53385618b31SToma Tabacu
emitDirectiveSetMips0()5344e0cf8e2SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetMips0() {
5354e0cf8e2SToma Tabacu OS << "\t.set\tmips0\n";
5364e0cf8e2SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips0();
5374e0cf8e2SToma Tabacu }
5382664779bSToma Tabacu
emitDirectiveSetMips1()539f0df221dSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips1() {
540f0df221dSDaniel Sanders OS << "\t.set\tmips1\n";
54188f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips1();
542f0df221dSDaniel Sanders }
543f0df221dSDaniel Sanders
emitDirectiveSetMips2()544f0df221dSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips2() {
545f0df221dSDaniel Sanders OS << "\t.set\tmips2\n";
54688f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips2();
547f0df221dSDaniel Sanders }
548f0df221dSDaniel Sanders
emitDirectiveSetMips3()549f0df221dSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips3() {
550f0df221dSDaniel Sanders OS << "\t.set\tmips3\n";
55188f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips3();
552f0df221dSDaniel Sanders }
553f0df221dSDaniel Sanders
emitDirectiveSetMips4()554f0df221dSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips4() {
555f0df221dSDaniel Sanders OS << "\t.set\tmips4\n";
55688f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips4();
557f0df221dSDaniel Sanders }
558f0df221dSDaniel Sanders
emitDirectiveSetMips5()559f0df221dSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips5() {
560f0df221dSDaniel Sanders OS << "\t.set\tmips5\n";
56188f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips5();
562f0df221dSDaniel Sanders }
563f0df221dSDaniel Sanders
emitDirectiveSetMips32()564f0df221dSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips32() {
565f0df221dSDaniel Sanders OS << "\t.set\tmips32\n";
56688f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips32();
567f0df221dSDaniel Sanders }
568f0df221dSDaniel Sanders
emitDirectiveSetMips32R2()569615b26e1SVladimir Medic void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() {
570615b26e1SVladimir Medic OS << "\t.set\tmips32r2\n";
57188f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips32R2();
572615b26e1SVladimir Medic }
573615b26e1SVladimir Medic
emitDirectiveSetMips32R3()5741779314eSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips32R3() {
5751779314eSDaniel Sanders OS << "\t.set\tmips32r3\n";
5761779314eSDaniel Sanders MipsTargetStreamer::emitDirectiveSetMips32R3();
5771779314eSDaniel Sanders }
5781779314eSDaniel Sanders
emitDirectiveSetMips32R5()5791779314eSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips32R5() {
5801779314eSDaniel Sanders OS << "\t.set\tmips32r5\n";
5811779314eSDaniel Sanders MipsTargetStreamer::emitDirectiveSetMips32R5();
5821779314eSDaniel Sanders }
5831779314eSDaniel Sanders
emitDirectiveSetMips32R6()584f0df221dSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() {
585f0df221dSDaniel Sanders OS << "\t.set\tmips32r6\n";
58688f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips32R6();
587f0df221dSDaniel Sanders }
588f0df221dSDaniel Sanders
emitDirectiveSetMips64()5893b9c63d2SMatheus Almeida void MipsTargetAsmStreamer::emitDirectiveSetMips64() {
5903b9c63d2SMatheus Almeida OS << "\t.set\tmips64\n";
59188f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips64();
5923b9c63d2SMatheus Almeida }
5933b9c63d2SMatheus Almeida
emitDirectiveSetMips64R2()594a2cd009cSMatheus Almeida void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() {
595a2cd009cSMatheus Almeida OS << "\t.set\tmips64r2\n";
59688f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips64R2();
597a2cd009cSMatheus Almeida }
598a2cd009cSMatheus Almeida
emitDirectiveSetMips64R3()5991779314eSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips64R3() {
6001779314eSDaniel Sanders OS << "\t.set\tmips64r3\n";
6011779314eSDaniel Sanders MipsTargetStreamer::emitDirectiveSetMips64R3();
6021779314eSDaniel Sanders }
6031779314eSDaniel Sanders
emitDirectiveSetMips64R5()6041779314eSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips64R5() {
6051779314eSDaniel Sanders OS << "\t.set\tmips64r5\n";
6061779314eSDaniel Sanders MipsTargetStreamer::emitDirectiveSetMips64R5();
6071779314eSDaniel Sanders }
6081779314eSDaniel Sanders
emitDirectiveSetMips64R6()609f0df221dSDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() {
610f0df221dSDaniel Sanders OS << "\t.set\tmips64r6\n";
61188f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetMips64R6();
612f0df221dSDaniel Sanders }
613f0df221dSDaniel Sanders
emitDirectiveSetDsp()61427c398e3SVladimir Medic void MipsTargetAsmStreamer::emitDirectiveSetDsp() {
61527c398e3SVladimir Medic OS << "\t.set\tdsp\n";
61688f05ce3SToma Tabacu MipsTargetStreamer::emitDirectiveSetDsp();
61727c398e3SVladimir Medic }
6189db22db9SToma Tabacu
emitDirectiveSetDspr2()61965f10246SPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveSetDspr2() {
62065f10246SPetar Jovanovic OS << "\t.set\tdspr2\n";
62165f10246SPetar Jovanovic MipsTargetStreamer::emitDirectiveSetDspr2();
62265f10246SPetar Jovanovic }
62365f10246SPetar Jovanovic
emitDirectiveSetNoDsp()624351b2feeSToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() {
625351b2feeSToma Tabacu OS << "\t.set\tnodsp\n";
626351b2feeSToma Tabacu MipsTargetStreamer::emitDirectiveSetNoDsp();
627351b2feeSToma Tabacu }
628351b2feeSToma Tabacu
emitDirectiveSetMips3D()62973b1da16SSimon Atanasyan void MipsTargetAsmStreamer::emitDirectiveSetMips3D() {
63073b1da16SSimon Atanasyan OS << "\t.set\tmips3d\n";
63173b1da16SSimon Atanasyan MipsTargetStreamer::emitDirectiveSetMips3D();
63273b1da16SSimon Atanasyan }
63373b1da16SSimon Atanasyan
emitDirectiveSetNoMips3D()63473b1da16SSimon Atanasyan void MipsTargetAsmStreamer::emitDirectiveSetNoMips3D() {
63573b1da16SSimon Atanasyan OS << "\t.set\tnomips3d\n";
63673b1da16SSimon Atanasyan MipsTargetStreamer::emitDirectiveSetNoMips3D();
63773b1da16SSimon Atanasyan }
63873b1da16SSimon Atanasyan
emitDirectiveSetPop()6394e0cf8e2SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetPop() {
6404e0cf8e2SToma Tabacu OS << "\t.set\tpop\n";
6414e0cf8e2SToma Tabacu MipsTargetStreamer::emitDirectiveSetPop();
6424e0cf8e2SToma Tabacu }
6439db22db9SToma Tabacu
emitDirectiveSetPush()6444e0cf8e2SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetPush() {
6454e0cf8e2SToma Tabacu OS << "\t.set\tpush\n";
6464e0cf8e2SToma Tabacu MipsTargetStreamer::emitDirectiveSetPush();
6474e0cf8e2SToma Tabacu }
6489db22db9SToma Tabacu
emitDirectiveSetSoftFloat()6492969650eSToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetSoftFloat() {
6502969650eSToma Tabacu OS << "\t.set\tsoftfloat\n";
6512969650eSToma Tabacu MipsTargetStreamer::emitDirectiveSetSoftFloat();
6522969650eSToma Tabacu }
6532969650eSToma Tabacu
emitDirectiveSetHardFloat()6542969650eSToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetHardFloat() {
6552969650eSToma Tabacu OS << "\t.set\thardfloat\n";
6562969650eSToma Tabacu MipsTargetStreamer::emitDirectiveSetHardFloat();
6572969650eSToma Tabacu }
6582969650eSToma Tabacu
65925fa291fSRafael Espindola // Print a 32 bit hex number with all numbers.
printHex32(unsigned Value,raw_ostream & OS)66025fa291fSRafael Espindola static void printHex32(unsigned Value, raw_ostream &OS) {
66125fa291fSRafael Espindola OS << "0x";
66225fa291fSRafael Espindola for (int i = 7; i >= 0; i--)
66325fa291fSRafael Espindola OS.write_hex((Value & (0xF << (i * 4))) >> (i * 4));
66425fa291fSRafael Espindola }
66525fa291fSRafael Espindola
emitMask(unsigned CPUBitmask,int CPUTopSavedRegOff)66625fa291fSRafael Espindola void MipsTargetAsmStreamer::emitMask(unsigned CPUBitmask,
66725fa291fSRafael Espindola int CPUTopSavedRegOff) {
66825fa291fSRafael Espindola OS << "\t.mask \t";
66925fa291fSRafael Espindola printHex32(CPUBitmask, OS);
67025fa291fSRafael Espindola OS << ',' << CPUTopSavedRegOff << '\n';
67125fa291fSRafael Espindola }
67225fa291fSRafael Espindola
emitFMask(unsigned FPUBitmask,int FPUTopSavedRegOff)67325fa291fSRafael Espindola void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask,
67425fa291fSRafael Espindola int FPUTopSavedRegOff) {
67525fa291fSRafael Espindola OS << "\t.fmask\t";
67625fa291fSRafael Espindola printHex32(FPUBitmask, OS);
67725fa291fSRafael Espindola OS << "," << FPUTopSavedRegOff << '\n';
678054234faSRafael Espindola }
679054234faSRafael Espindola
emitDirectiveCpAdd(unsigned RegNo)6802dc4eb08SSimon Atanasyan void MipsTargetAsmStreamer::emitDirectiveCpAdd(unsigned RegNo) {
6812dc4eb08SSimon Atanasyan OS << "\t.cpadd\t$"
6822dc4eb08SSimon Atanasyan << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
6832dc4eb08SSimon Atanasyan forbidModuleDirective();
6842dc4eb08SSimon Atanasyan }
6852dc4eb08SSimon Atanasyan
emitDirectiveCpLoad(unsigned RegNo)686c4c202a9SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) {
687525bc4f7SMatheus Almeida OS << "\t.cpload\t$"
688525bc4f7SMatheus Almeida << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
689cdb45fa3SDaniel Sanders forbidModuleDirective();
690525bc4f7SMatheus Almeida }
691525bc4f7SMatheus Almeida
emitDirectiveCpLocal(unsigned RegNo)692a884afb6SSimon Atanasyan void MipsTargetAsmStreamer::emitDirectiveCpLocal(unsigned RegNo) {
693a884afb6SSimon Atanasyan OS << "\t.cplocal\t$"
694a884afb6SSimon Atanasyan << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
695a884afb6SSimon Atanasyan MipsTargetStreamer::emitDirectiveCpLocal(RegNo);
696a884afb6SSimon Atanasyan }
697a884afb6SSimon Atanasyan
emitDirectiveCpRestore(int Offset,function_ref<unsigned ()> GetATReg,SMLoc IDLoc,const MCSubtargetInfo * STI)698df8510d4SDaniel Sanders bool MipsTargetAsmStreamer::emitDirectiveCpRestore(
699d3f4c05aSBenjamin Kramer int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
7007225cd52SDaniel Sanders const MCSubtargetInfo *STI) {
701df8510d4SDaniel Sanders MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);
702e2982adcSDaniel Sanders OS << "\t.cprestore\t" << Offset << "\n";
703df8510d4SDaniel Sanders return true;
704e2982adcSDaniel Sanders }
705e2982adcSDaniel Sanders
emitDirectiveCpsetup(unsigned RegNo,int RegOrOffset,const MCSymbol & Sym,bool IsReg)706d92a3fa2SMatheus Almeida void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
707d92a3fa2SMatheus Almeida int RegOrOffset,
708d92a3fa2SMatheus Almeida const MCSymbol &Sym,
709d92a3fa2SMatheus Almeida bool IsReg) {
710d92a3fa2SMatheus Almeida OS << "\t.cpsetup\t$"
711d92a3fa2SMatheus Almeida << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << ", ";
712d92a3fa2SMatheus Almeida
713d92a3fa2SMatheus Almeida if (IsReg)
714d92a3fa2SMatheus Almeida OS << "$"
715d92a3fa2SMatheus Almeida << StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower();
716d92a3fa2SMatheus Almeida else
717d92a3fa2SMatheus Almeida OS << RegOrOffset;
718d92a3fa2SMatheus Almeida
719d92a3fa2SMatheus Almeida OS << ", ";
720d92a3fa2SMatheus Almeida
7215d796288SDaniel Sanders OS << Sym.getName();
722cdb45fa3SDaniel Sanders forbidModuleDirective();
723fb8a2a95SVladimir Medic }
724fb8a2a95SVladimir Medic
emitDirectiveCpreturn(unsigned SaveLocation,bool SaveLocationIsRegister)725f173dda0SDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
726f173dda0SDaniel Sanders bool SaveLocationIsRegister) {
727f173dda0SDaniel Sanders OS << "\t.cpreturn";
728f173dda0SDaniel Sanders forbidModuleDirective();
729f173dda0SDaniel Sanders }
730f173dda0SDaniel Sanders
emitDirectiveModuleFP()731a64e5405SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveModuleFP() {
7328cb49702SSimon Atanasyan MipsABIFlagsSection::FpABIKind FpABI = ABIFlagsSection.getFpABI();
7338cb49702SSimon Atanasyan if (FpABI == MipsABIFlagsSection::FpABIKind::SOFT)
7348cb49702SSimon Atanasyan OS << "\t.module\tsoftfloat\n";
7358cb49702SSimon Atanasyan else
7368cb49702SSimon Atanasyan OS << "\t.module\tfp=" << ABIFlagsSection.getFpABIString(FpABI) << "\n";
737fb8a2a95SVladimir Medic }
738fb8a2a95SVladimir Medic
emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value)7397e527423SDaniel Sanders void MipsTargetAsmStreamer::emitDirectiveSetFp(
7407e527423SDaniel Sanders MipsABIFlagsSection::FpABIKind Value) {
7414e0cf8e2SToma Tabacu MipsTargetStreamer::emitDirectiveSetFp(Value);
7424e0cf8e2SToma Tabacu
743fb8a2a95SVladimir Medic OS << "\t.set\tfp=";
7447e527423SDaniel Sanders OS << ABIFlagsSection.getFpABIString(Value) << "\n";
745fb8a2a95SVladimir Medic }
746fb8a2a95SVladimir Medic
emitDirectiveModuleOddSPReg()7473c499589SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveModuleOddSPReg() {
7483c499589SToma Tabacu MipsTargetStreamer::emitDirectiveModuleOddSPReg();
7497e527423SDaniel Sanders
7503c499589SToma Tabacu OS << "\t.module\t" << (ABIFlagsSection.OddSPReg ? "" : "no") << "oddspreg\n";
7517e527423SDaniel Sanders }
7527e527423SDaniel Sanders
emitDirectiveSetOddSPReg()75332c72aa0SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetOddSPReg() {
75432c72aa0SToma Tabacu MipsTargetStreamer::emitDirectiveSetOddSPReg();
75532c72aa0SToma Tabacu OS << "\t.set\toddspreg\n";
75632c72aa0SToma Tabacu }
75732c72aa0SToma Tabacu
emitDirectiveSetNoOddSPReg()75832c72aa0SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveSetNoOddSPReg() {
75932c72aa0SToma Tabacu MipsTargetStreamer::emitDirectiveSetNoOddSPReg();
76032c72aa0SToma Tabacu OS << "\t.set\tnooddspreg\n";
76132c72aa0SToma Tabacu }
76232c72aa0SToma Tabacu
emitDirectiveModuleSoftFloat()7630f093130SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveModuleSoftFloat() {
7640f093130SToma Tabacu OS << "\t.module\tsoftfloat\n";
7650f093130SToma Tabacu }
7660f093130SToma Tabacu
emitDirectiveModuleHardFloat()7670f093130SToma Tabacu void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() {
7680f093130SToma Tabacu OS << "\t.module\thardfloat\n";
7690f093130SToma Tabacu }
7700f093130SToma Tabacu
emitDirectiveModuleMT()771805f1e03SSimon Dardis void MipsTargetAsmStreamer::emitDirectiveModuleMT() {
772805f1e03SSimon Dardis OS << "\t.module\tmt\n";
773805f1e03SSimon Dardis }
774805f1e03SSimon Dardis
emitDirectiveModuleCRC()7753408caf6SPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveModuleCRC() {
7763408caf6SPetar Jovanovic OS << "\t.module\tcrc\n";
7773408caf6SPetar Jovanovic }
7783408caf6SPetar Jovanovic
emitDirectiveModuleNoCRC()7793408caf6SPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveModuleNoCRC() {
7803408caf6SPetar Jovanovic OS << "\t.module\tnocrc\n";
7813408caf6SPetar Jovanovic }
7823408caf6SPetar Jovanovic
emitDirectiveModuleVirt()783d4349f3bSPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveModuleVirt() {
784d4349f3bSPetar Jovanovic OS << "\t.module\tvirt\n";
785d4349f3bSPetar Jovanovic }
786d4349f3bSPetar Jovanovic
emitDirectiveModuleNoVirt()787d4349f3bSPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() {
788d4349f3bSPetar Jovanovic OS << "\t.module\tnovirt\n";
789d4349f3bSPetar Jovanovic }
790d4349f3bSPetar Jovanovic
emitDirectiveModuleGINV()791daf51693SPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveModuleGINV() {
792daf51693SPetar Jovanovic OS << "\t.module\tginv\n";
793daf51693SPetar Jovanovic }
794daf51693SPetar Jovanovic
emitDirectiveModuleNoGINV()795daf51693SPetar Jovanovic void MipsTargetAsmStreamer::emitDirectiveModuleNoGINV() {
796daf51693SPetar Jovanovic OS << "\t.module\tnoginv\n";
797daf51693SPetar Jovanovic }
798daf51693SPetar Jovanovic
7990cd3c19fSJack Carter // This part is for ELF object output.
MipsTargetELFStreamer(MCStreamer & S,const MCSubtargetInfo & STI)800cb1953f6SRafael Espindola MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
801cb1953f6SRafael Espindola const MCSubtargetInfo &STI)
802972e71abSRafael Espindola : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) {
803cb1953f6SRafael Espindola MCAssembler &MCA = getStreamer().getAssembler();
8048de3d3caSDaniel Sanders
8058de3d3caSDaniel Sanders // It's possible that MCObjectFileInfo isn't fully initialized at this point
806bb8507e6SMatthias Braun // due to an initialization order problem where LLVMTargetMachine creates the
8078de3d3caSDaniel Sanders // target streamer before TargetLoweringObjectFile calls
8088de3d3caSDaniel Sanders // InitializeMCObjectFileInfo. There doesn't seem to be a single place that
8098de3d3caSDaniel Sanders // covers all cases so this statement covers most cases and direct object
8108de3d3caSDaniel Sanders // emission must call setPic() once MCObjectFileInfo has been initialized. The
8118de3d3caSDaniel Sanders // cases we don't handle here are covered by MipsAsmPrinter.
812699281ccSRafael Espindola Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent();
813cb1953f6SRafael Espindola
814db0712f9SMichael Kuperstein const FeatureBitset &Features = STI.getFeatureBits();
815a5762816SEric Christopher
816a5762816SEric Christopher // Set the header flags that we can in the constructor.
817a5762816SEric Christopher // FIXME: This is a fairly terrible hack. We set the rest
818a5762816SEric Christopher // of these in the destructor. The problem here is two-fold:
819a5762816SEric Christopher //
820a5762816SEric Christopher // a: Some of the eflags can be set/reset by directives.
821a5762816SEric Christopher // b: There aren't any usage paths that initialize the ABI
822a5762816SEric Christopher // pointer until after we initialize either an assembler
823a5762816SEric Christopher // or the target machine.
824a5762816SEric Christopher // We can fix this by making the target streamer construct
825a5762816SEric Christopher // the ABI, but this is fraught with wide ranging dependency
826a5762816SEric Christopher // issues as well.
827a5762816SEric Christopher unsigned EFlags = MCA.getELFHeaderEFlags();
828cb1953f6SRafael Espindola
8296433d5afSSimon Dardis // FIXME: Fix a dependency issue by instantiating the ABI object to some
8306433d5afSSimon Dardis // default based off the triple. The triple doesn't describe the target
8316433d5afSSimon Dardis // fully, but any external user of the API that uses the MCTargetStreamer
8326433d5afSSimon Dardis // would otherwise crash on assertion failure.
8336433d5afSSimon Dardis
8346433d5afSSimon Dardis ABI = MipsABIInfo(
8356433d5afSSimon Dardis STI.getTargetTriple().getArch() == Triple::ArchType::mipsel ||
8366433d5afSSimon Dardis STI.getTargetTriple().getArch() == Triple::ArchType::mips
8376433d5afSSimon Dardis ? MipsABIInfo::O32()
8386433d5afSSimon Dardis : MipsABIInfo::N64());
8396433d5afSSimon Dardis
840cb1953f6SRafael Espindola // Architecture
841db0712f9SMichael Kuperstein if (Features[Mips::FeatureMips64r6])
842950f48d3SDaniel Sanders EFlags |= ELF::EF_MIPS_ARCH_64R6;
843db0712f9SMichael Kuperstein else if (Features[Mips::FeatureMips64r2] ||
844db0712f9SMichael Kuperstein Features[Mips::FeatureMips64r3] ||
845db0712f9SMichael Kuperstein Features[Mips::FeatureMips64r5])
846cb1953f6SRafael Espindola EFlags |= ELF::EF_MIPS_ARCH_64R2;
847db0712f9SMichael Kuperstein else if (Features[Mips::FeatureMips64])
848cb1953f6SRafael Espindola EFlags |= ELF::EF_MIPS_ARCH_64;
849db0712f9SMichael Kuperstein else if (Features[Mips::FeatureMips5])
850950f48d3SDaniel Sanders EFlags |= ELF::EF_MIPS_ARCH_5;
851db0712f9SMichael Kuperstein else if (Features[Mips::FeatureMips4])
852f7b32291SDaniel Sanders EFlags |= ELF::EF_MIPS_ARCH_4;
853db0712f9SMichael Kuperstein else if (Features[Mips::FeatureMips3])
854950f48d3SDaniel Sanders EFlags |= ELF::EF_MIPS_ARCH_3;
855db0712f9SMichael Kuperstein else if (Features[Mips::FeatureMips32r6])
856950f48d3SDaniel Sanders EFlags |= ELF::EF_MIPS_ARCH_32R6;
857db0712f9SMichael Kuperstein else if (Features[Mips::FeatureMips32r2] ||
858db0712f9SMichael Kuperstein Features[Mips::FeatureMips32r3] ||
859db0712f9SMichael Kuperstein Features[Mips::FeatureMips32r5])
860cb1953f6SRafael Espindola EFlags |= ELF::EF_MIPS_ARCH_32R2;
861db0712f9SMichael Kuperstein else if (Features[Mips::FeatureMips32])
862cb1953f6SRafael Espindola EFlags |= ELF::EF_MIPS_ARCH_32;
863db0712f9SMichael Kuperstein else if (Features[Mips::FeatureMips2])
864950f48d3SDaniel Sanders EFlags |= ELF::EF_MIPS_ARCH_2;
865950f48d3SDaniel Sanders else
866950f48d3SDaniel Sanders EFlags |= ELF::EF_MIPS_ARCH_1;
867cb1953f6SRafael Espindola
868415c159eSDaniel Sanders // Machine
869415c159eSDaniel Sanders if (Features[Mips::FeatureCnMips])
870415c159eSDaniel Sanders EFlags |= ELF::EF_MIPS_MACH_OCTEON;
871415c159eSDaniel Sanders
8720051f2dcSMatheus Almeida // Other options.
873db0712f9SMichael Kuperstein if (Features[Mips::FeatureNaN2008])
8740051f2dcSMatheus Almeida EFlags |= ELF::EF_MIPS_NAN2008;
8750051f2dcSMatheus Almeida
876cb1953f6SRafael Espindola MCA.setELFHeaderEFlags(EFlags);
877cb1953f6SRafael Espindola }
87886ac5c1bSJack Carter
emitLabel(MCSymbol * S)87995fb9b93SRafael Espindola void MipsTargetELFStreamer::emitLabel(MCSymbol *S) {
88095fb9b93SRafael Espindola auto *Symbol = cast<MCSymbolELF>(S);
881c73aed1cSRafael Espindola getStreamer().getAssembler().registerSymbol(*Symbol);
88295fb9b93SRafael Espindola uint8_t Type = Symbol->getType();
88326e917cdSRafael Espindola if (Type != ELF::STT_FUNC)
88426e917cdSRafael Espindola return;
88526e917cdSRafael Espindola
8863c82a646SSimon Dardis if (isMicroMipsEnabled())
8878c006ee3SRafael Espindola Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
8886d5f7ce3SRafael Espindola }
8896d5f7ce3SRafael Espindola
finish()890972e71abSRafael Espindola void MipsTargetELFStreamer::finish() {
891972e71abSRafael Espindola MCAssembler &MCA = getStreamer().getAssembler();
89268c3747eSDaniel Sanders const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo();
893972e71abSRafael Espindola
89441ffa5d1SDaniel Sanders // .bss, .text and .data are always at least 16-byte aligned.
895967d6a69SRafael Espindola MCSection &TextSection = *OFI.getTextSection();
896bb9a71c1SRafael Espindola MCA.registerSection(TextSection);
897967d6a69SRafael Espindola MCSection &DataSection = *OFI.getDataSection();
898bb9a71c1SRafael Espindola MCA.registerSection(DataSection);
899967d6a69SRafael Espindola MCSection &BSSSection = *OFI.getBSSSection();
900bb9a71c1SRafael Espindola MCA.registerSection(BSSSection);
90141ffa5d1SDaniel Sanders
90218f805a7SGuillaume Chatelet TextSection.setAlignment(Align(std::max(16u, TextSection.getAlignment())));
90318f805a7SGuillaume Chatelet DataSection.setAlignment(Align(std::max(16u, DataSection.getAlignment())));
90418f805a7SGuillaume Chatelet BSSSection.setAlignment(Align(std::max(16u, BSSSection.getAlignment())));
90541ffa5d1SDaniel Sanders
906c07f06aeSDaniel Sanders if (RoundSectionSizes) {
907c07f06aeSDaniel Sanders // Make sections sizes a multiple of the alignment. This is useful for
908c07f06aeSDaniel Sanders // verifying the output of IAS against the output of other assemblers but
909c07f06aeSDaniel Sanders // it's not necessary to produce a correct object and increases section
910c07f06aeSDaniel Sanders // size.
9119db710a1SDaniel Sanders MCStreamer &OS = getStreamer();
9129db710a1SDaniel Sanders for (MCSection &S : MCA) {
9139db710a1SDaniel Sanders MCSectionELF &Section = static_cast<MCSectionELF &>(S);
9149db710a1SDaniel Sanders
9159db710a1SDaniel Sanders unsigned Alignment = Section.getAlignment();
9169db710a1SDaniel Sanders if (Alignment) {
917*adf4142fSFangrui Song OS.switchSection(&Section);
918689c3a25SFangrui Song if (Section.useCodeAlign())
9195e71839fSPeter Smith OS.emitCodeAlignment(Alignment, &STI, Alignment);
9209db710a1SDaniel Sanders else
9216d2d589bSFangrui Song OS.emitValueToAlignment(Alignment, 0, 1, Alignment);
9229db710a1SDaniel Sanders }
9239db710a1SDaniel Sanders }
924c07f06aeSDaniel Sanders }
9259db710a1SDaniel Sanders
926db0712f9SMichael Kuperstein const FeatureBitset &Features = STI.getFeatureBits();
927a5762816SEric Christopher
928a5762816SEric Christopher // Update e_header flags. See the FIXME and comment above in
929a5762816SEric Christopher // the constructor for a full rundown on this.
930a5762816SEric Christopher unsigned EFlags = MCA.getELFHeaderEFlags();
931a5762816SEric Christopher
932a5762816SEric Christopher // ABI
933a5762816SEric Christopher // N64 does not require any ABI bits.
934a5762816SEric Christopher if (getABI().IsO32())
935a5762816SEric Christopher EFlags |= ELF::EF_MIPS_ABI_O32;
936a5762816SEric Christopher else if (getABI().IsN32())
937a5762816SEric Christopher EFlags |= ELF::EF_MIPS_ABI2;
938a5762816SEric Christopher
939db0712f9SMichael Kuperstein if (Features[Mips::FeatureGP64Bit]) {
940a5762816SEric Christopher if (getABI().IsO32())
941a5762816SEric Christopher EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */
942db0712f9SMichael Kuperstein } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64])
943a5762816SEric Christopher EFlags |= ELF::EF_MIPS_32BITMODE;
944a5762816SEric Christopher
945ca74dd79SSimon Dardis // -mplt is not implemented but we should act as if it was
946ca74dd79SSimon Dardis // given.
947ca74dd79SSimon Dardis if (!Features[Mips::FeatureNoABICalls])
948ca74dd79SSimon Dardis EFlags |= ELF::EF_MIPS_CPIC;
949ca74dd79SSimon Dardis
950ca74dd79SSimon Dardis if (Pic)
951ca74dd79SSimon Dardis EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;
952a5762816SEric Christopher
953a5762816SEric Christopher MCA.setELFHeaderEFlags(EFlags);
954a5762816SEric Christopher
95568c3747eSDaniel Sanders // Emit all the option records.
95668c3747eSDaniel Sanders // At the moment we are only emitting .Mips.options (ODK_REGINFO) and
95768c3747eSDaniel Sanders // .reginfo.
95868c3747eSDaniel Sanders MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);
95968c3747eSDaniel Sanders MEF.EmitMipsOptionRecords();
960972e71abSRafael Espindola
961fb8a2a95SVladimir Medic emitMipsAbiFlags();
962972e71abSRafael Espindola }
963972e71abSRafael Espindola
emitAssignment(MCSymbol * S,const MCExpr * Value)96495fb9b93SRafael Espindola void MipsTargetELFStreamer::emitAssignment(MCSymbol *S, const MCExpr *Value) {
96595fb9b93SRafael Espindola auto *Symbol = cast<MCSymbolELF>(S);
96628221d8bSZoran Jovanovic // If on rhs is micromips symbol then mark Symbol as microMips.
96728221d8bSZoran Jovanovic if (Value->getKind() != MCExpr::SymbolRef)
96828221d8bSZoran Jovanovic return;
96995fb9b93SRafael Espindola const auto &RhsSym = cast<MCSymbolELF>(
97095fb9b93SRafael Espindola static_cast<const MCSymbolRefExpr *>(Value)->getSymbol());
9712cc44f50SToma Tabacu
9728c006ee3SRafael Espindola if (!(RhsSym.getOther() & ELF::STO_MIPS_MICROMIPS))
97328221d8bSZoran Jovanovic return;
97428221d8bSZoran Jovanovic
9758c006ee3SRafael Espindola Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
97628221d8bSZoran Jovanovic }
97728221d8bSZoran Jovanovic
getStreamer()97886ac5c1bSJack Carter MCELFStreamer &MipsTargetELFStreamer::getStreamer() {
97924ea09efSRafael Espindola return static_cast<MCELFStreamer &>(Streamer);
98086ac5c1bSJack Carter }
98186ac5c1bSJack Carter
emitDirectiveSetMicroMips()9826d5f7ce3SRafael Espindola void MipsTargetELFStreamer::emitDirectiveSetMicroMips() {
9836d5f7ce3SRafael Espindola MicroMipsEnabled = true;
984cdb45fa3SDaniel Sanders forbidModuleDirective();
98586ac5c1bSJack Carter }
9866d5f7ce3SRafael Espindola
emitDirectiveSetNoMicroMips()9876d5f7ce3SRafael Espindola void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() {
9886d5f7ce3SRafael Espindola MicroMipsEnabled = false;
989cdb45fa3SDaniel Sanders forbidModuleDirective();
9906d5f7ce3SRafael Espindola }
9916d5f7ce3SRafael Espindola
setUsesMicroMips()992cda908a0SDaniel Sanders void MipsTargetELFStreamer::setUsesMicroMips() {
993cda908a0SDaniel Sanders MCAssembler &MCA = getStreamer().getAssembler();
994cda908a0SDaniel Sanders unsigned Flags = MCA.getELFHeaderEFlags();
995cda908a0SDaniel Sanders Flags |= ELF::EF_MIPS_MICROMIPS;
996cda908a0SDaniel Sanders MCA.setELFHeaderEFlags(Flags);
997cda908a0SDaniel Sanders }
998cda908a0SDaniel Sanders
emitDirectiveSetMips16()9996633d57aSRafael Espindola void MipsTargetELFStreamer::emitDirectiveSetMips16() {
1000e7583756SRafael Espindola MCAssembler &MCA = getStreamer().getAssembler();
1001e7583756SRafael Espindola unsigned Flags = MCA.getELFHeaderEFlags();
1002e7583756SRafael Espindola Flags |= ELF::EF_MIPS_ARCH_ASE_M16;
1003e7583756SRafael Espindola MCA.setELFHeaderEFlags(Flags);
1004cdb45fa3SDaniel Sanders forbidModuleDirective();
10056633d57aSRafael Espindola }
10066633d57aSRafael Espindola
emitDirectiveSetNoReorder()1007eb0a8af6SRafael Espindola void MipsTargetELFStreamer::emitDirectiveSetNoReorder() {
1008cb1953f6SRafael Espindola MCAssembler &MCA = getStreamer().getAssembler();
1009cb1953f6SRafael Espindola unsigned Flags = MCA.getELFHeaderEFlags();
1010cb1953f6SRafael Espindola Flags |= ELF::EF_MIPS_NOREORDER;
1011cb1953f6SRafael Espindola MCA.setELFHeaderEFlags(Flags);
1012cdb45fa3SDaniel Sanders forbidModuleDirective();
1013eb0a8af6SRafael Espindola }
1014eb0a8af6SRafael Espindola
emitDirectiveEnd(StringRef Name)1015eb0a8af6SRafael Espindola void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {
1016d97a634fSDaniel Sanders MCAssembler &MCA = getStreamer().getAssembler();
1017d97a634fSDaniel Sanders MCContext &Context = MCA.getContext();
1018d97a634fSDaniel Sanders MCStreamer &OS = getStreamer();
1019d97a634fSDaniel Sanders
1020219fae9eSScott Egerton MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0);
1021d97a634fSDaniel Sanders
10222b561336SDaniel Sanders MCSymbol *Sym = Context.getOrCreateSymbol(Name);
1023d97a634fSDaniel Sanders const MCSymbolRefExpr *ExprRef =
10242b561336SDaniel Sanders MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Context);
1025d97a634fSDaniel Sanders
1026bb9a71c1SRafael Espindola MCA.registerSection(*Sec);
102718f805a7SGuillaume Chatelet Sec->setAlignment(Align(4));
1028d97a634fSDaniel Sanders
102915d82c62SFangrui Song OS.pushSection();
1030d97a634fSDaniel Sanders
1031*adf4142fSFangrui Song OS.switchSection(Sec);
1032d97a634fSDaniel Sanders
10336d2d589bSFangrui Song OS.emitValueImpl(ExprRef, 4);
1034d97a634fSDaniel Sanders
103577497103SFangrui Song OS.emitIntValue(GPRInfoSet ? GPRBitMask : 0, 4); // reg_mask
103677497103SFangrui Song OS.emitIntValue(GPRInfoSet ? GPROffset : 0, 4); // reg_offset
1037d97a634fSDaniel Sanders
103877497103SFangrui Song OS.emitIntValue(FPRInfoSet ? FPRBitMask : 0, 4); // fpreg_mask
103977497103SFangrui Song OS.emitIntValue(FPRInfoSet ? FPROffset : 0, 4); // fpreg_offset
1040d97a634fSDaniel Sanders
104177497103SFangrui Song OS.emitIntValue(FrameInfoSet ? FrameOffset : 0, 4); // frame_offset
104277497103SFangrui Song OS.emitIntValue(FrameInfoSet ? FrameReg : 0, 4); // frame_reg
104377497103SFangrui Song OS.emitIntValue(FrameInfoSet ? ReturnReg : 0, 4); // return_reg
1044d97a634fSDaniel Sanders
1045d97a634fSDaniel Sanders // The .end directive marks the end of a procedure. Invalidate
1046d97a634fSDaniel Sanders // the information gathered up until this point.
1047d97a634fSDaniel Sanders GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
1048d97a634fSDaniel Sanders
104915d82c62SFangrui Song OS.popSection();
10502b561336SDaniel Sanders
10512b561336SDaniel Sanders // .end also implicitly sets the size.
10522b561336SDaniel Sanders MCSymbol *CurPCSym = Context.createTempSymbol();
10536d2d589bSFangrui Song OS.emitLabel(CurPCSym);
10542b561336SDaniel Sanders const MCExpr *Size = MCBinaryExpr::createSub(
10552b561336SDaniel Sanders MCSymbolRefExpr::create(CurPCSym, MCSymbolRefExpr::VK_None, Context),
10562b561336SDaniel Sanders ExprRef, Context);
105768e9d940SSimon Dardis
105868e9d940SSimon Dardis // The ELFObjectWriter can determine the absolute size as it has access to
105968e9d940SSimon Dardis // the layout information of the assembly file, so a size expression rather
106068e9d940SSimon Dardis // than an absolute value is ok here.
10612b561336SDaniel Sanders static_cast<MCSymbolELF *>(Sym)->setSize(Size);
1062eb0a8af6SRafael Espindola }
1063eb0a8af6SRafael Espindola
emitDirectiveEnt(const MCSymbol & Symbol)10646633d57aSRafael Espindola void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {
1065d97a634fSDaniel Sanders GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
10662b561336SDaniel Sanders
10672b561336SDaniel Sanders // .ent also acts like an implicit '.type symbol, STT_FUNC'
10682b561336SDaniel Sanders static_cast<const MCSymbolELF &>(Symbol).setType(ELF::STT_FUNC);
10696633d57aSRafael Espindola }
10706633d57aSRafael Espindola
emitDirectiveAbiCalls()10710cd3c19fSJack Carter void MipsTargetELFStreamer::emitDirectiveAbiCalls() {
10720cd3c19fSJack Carter MCAssembler &MCA = getStreamer().getAssembler();
10730cd3c19fSJack Carter unsigned Flags = MCA.getELFHeaderEFlags();
1074cb1953f6SRafael Espindola Flags |= ELF::EF_MIPS_CPIC | ELF::EF_MIPS_PIC;
10750cd3c19fSJack Carter MCA.setELFHeaderEFlags(Flags);
10760cd3c19fSJack Carter }
10770051f2dcSMatheus Almeida
emitDirectiveNaN2008()10780051f2dcSMatheus Almeida void MipsTargetELFStreamer::emitDirectiveNaN2008() {
10790051f2dcSMatheus Almeida MCAssembler &MCA = getStreamer().getAssembler();
10800051f2dcSMatheus Almeida unsigned Flags = MCA.getELFHeaderEFlags();
10810051f2dcSMatheus Almeida Flags |= ELF::EF_MIPS_NAN2008;
10820051f2dcSMatheus Almeida MCA.setELFHeaderEFlags(Flags);
10830051f2dcSMatheus Almeida }
10840051f2dcSMatheus Almeida
emitDirectiveNaNLegacy()10850051f2dcSMatheus Almeida void MipsTargetELFStreamer::emitDirectiveNaNLegacy() {
10860051f2dcSMatheus Almeida MCAssembler &MCA = getStreamer().getAssembler();
10870051f2dcSMatheus Almeida unsigned Flags = MCA.getELFHeaderEFlags();
10880051f2dcSMatheus Almeida Flags &= ~ELF::EF_MIPS_NAN2008;
10890051f2dcSMatheus Almeida MCA.setELFHeaderEFlags(Flags);
10900051f2dcSMatheus Almeida }
10910051f2dcSMatheus Almeida
emitDirectiveOptionPic0()10920cd3c19fSJack Carter void MipsTargetELFStreamer::emitDirectiveOptionPic0() {
10930cd3c19fSJack Carter MCAssembler &MCA = getStreamer().getAssembler();
10940cd3c19fSJack Carter unsigned Flags = MCA.getELFHeaderEFlags();
1095f79b2814SMatheus Almeida // This option overrides other PIC options like -KPIC.
1096f79b2814SMatheus Almeida Pic = false;
10970cd3c19fSJack Carter Flags &= ~ELF::EF_MIPS_PIC;
10980cd3c19fSJack Carter MCA.setELFHeaderEFlags(Flags);
10990cd3c19fSJack Carter }
1100054234faSRafael Espindola
emitDirectiveOptionPic2()1101f79b2814SMatheus Almeida void MipsTargetELFStreamer::emitDirectiveOptionPic2() {
1102f79b2814SMatheus Almeida MCAssembler &MCA = getStreamer().getAssembler();
1103f79b2814SMatheus Almeida unsigned Flags = MCA.getELFHeaderEFlags();
1104f79b2814SMatheus Almeida Pic = true;
1105f79b2814SMatheus Almeida // NOTE: We are following the GAS behaviour here which means the directive
1106f79b2814SMatheus Almeida // 'pic2' also sets the CPIC bit in the ELF header. This is different from
1107f79b2814SMatheus Almeida // what is stated in the SYSV ABI which consider the bits EF_MIPS_PIC and
1108f79b2814SMatheus Almeida // EF_MIPS_CPIC to be mutually exclusive.
1109f79b2814SMatheus Almeida Flags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;
1110f79b2814SMatheus Almeida MCA.setELFHeaderEFlags(Flags);
1111f79b2814SMatheus Almeida }
1112f79b2814SMatheus Almeida
emitDirectiveInsn()11139ca5096fSToma Tabacu void MipsTargetELFStreamer::emitDirectiveInsn() {
11149ca5096fSToma Tabacu MipsTargetStreamer::emitDirectiveInsn();
11159ca5096fSToma Tabacu MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);
11169ca5096fSToma Tabacu MEF.createPendingLabelRelocs();
11179ca5096fSToma Tabacu }
11189ca5096fSToma Tabacu
emitFrame(unsigned StackReg,unsigned StackSize,unsigned ReturnReg_)1119054234faSRafael Espindola void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
1120d97a634fSDaniel Sanders unsigned ReturnReg_) {
1121d97a634fSDaniel Sanders MCContext &Context = getStreamer().getAssembler().getContext();
1122d97a634fSDaniel Sanders const MCRegisterInfo *RegInfo = Context.getRegisterInfo();
1123d97a634fSDaniel Sanders
1124d97a634fSDaniel Sanders FrameInfoSet = true;
1125d97a634fSDaniel Sanders FrameReg = RegInfo->getEncodingValue(StackReg);
1126d97a634fSDaniel Sanders FrameOffset = StackSize;
1127d97a634fSDaniel Sanders ReturnReg = RegInfo->getEncodingValue(ReturnReg_);
1128054234faSRafael Espindola }
112925fa291fSRafael Espindola
emitMask(unsigned CPUBitmask,int CPUTopSavedRegOff)113025fa291fSRafael Espindola void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask,
113125fa291fSRafael Espindola int CPUTopSavedRegOff) {
1132d97a634fSDaniel Sanders GPRInfoSet = true;
1133d97a634fSDaniel Sanders GPRBitMask = CPUBitmask;
1134d97a634fSDaniel Sanders GPROffset = CPUTopSavedRegOff;
113525fa291fSRafael Espindola }
113625fa291fSRafael Espindola
emitFMask(unsigned FPUBitmask,int FPUTopSavedRegOff)113725fa291fSRafael Espindola void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask,
113825fa291fSRafael Espindola int FPUTopSavedRegOff) {
1139d97a634fSDaniel Sanders FPRInfoSet = true;
1140d97a634fSDaniel Sanders FPRBitMask = FPUBitmask;
1141d97a634fSDaniel Sanders FPROffset = FPUTopSavedRegOff;
114225fa291fSRafael Espindola }
1143615b26e1SVladimir Medic
emitDirectiveCpAdd(unsigned RegNo)11442dc4eb08SSimon Atanasyan void MipsTargetELFStreamer::emitDirectiveCpAdd(unsigned RegNo) {
11452dc4eb08SSimon Atanasyan // .cpadd $reg
11462dc4eb08SSimon Atanasyan // This directive inserts code to add $gp to the argument's register
11472dc4eb08SSimon Atanasyan // when support for position independent code is enabled.
11482dc4eb08SSimon Atanasyan if (!Pic)
11492dc4eb08SSimon Atanasyan return;
11502dc4eb08SSimon Atanasyan
11512dc4eb08SSimon Atanasyan emitAddu(RegNo, RegNo, GPReg, getABI().IsN64(), &STI);
11522dc4eb08SSimon Atanasyan forbidModuleDirective();
11532dc4eb08SSimon Atanasyan }
11542dc4eb08SSimon Atanasyan
emitDirectiveCpLoad(unsigned RegNo)1155c4c202a9SToma Tabacu void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
1156525bc4f7SMatheus Almeida // .cpload $reg
1157525bc4f7SMatheus Almeida // This directive expands to:
1158525bc4f7SMatheus Almeida // lui $gp, %hi(_gp_disp)
1159525bc4f7SMatheus Almeida // addui $gp, $gp, %lo(_gp_disp)
1160525bc4f7SMatheus Almeida // addu $gp, $gp, $reg
1161525bc4f7SMatheus Almeida // when support for position independent code is enabled.
1162a5762816SEric Christopher if (!Pic || (getABI().IsN32() || getABI().IsN64()))
1163525bc4f7SMatheus Almeida return;
1164525bc4f7SMatheus Almeida
1165525bc4f7SMatheus Almeida // There's a GNU extension controlled by -mno-shared that allows
1166525bc4f7SMatheus Almeida // locally-binding symbols to be accessed using absolute addresses.
1167525bc4f7SMatheus Almeida // This is currently not supported. When supported -mno-shared makes
1168525bc4f7SMatheus Almeida // .cpload expand to:
1169525bc4f7SMatheus Almeida // lui $gp, %hi(__gnu_local_gp)
1170525bc4f7SMatheus Almeida // addiu $gp, $gp, %lo(__gnu_local_gp)
1171525bc4f7SMatheus Almeida
1172525bc4f7SMatheus Almeida StringRef SymName("_gp_disp");
1173525bc4f7SMatheus Almeida MCAssembler &MCA = getStreamer().getAssembler();
11746f482000SJim Grosbach MCSymbol *GP_Disp = MCA.getContext().getOrCreateSymbol(SymName);
1175b5d316bfSRafael Espindola MCA.registerSymbol(*GP_Disp);
1176525bc4f7SMatheus Almeida
1177525bc4f7SMatheus Almeida MCInst TmpInst;
1178525bc4f7SMatheus Almeida TmpInst.setOpcode(Mips::LUi);
1179a884afb6SSimon Atanasyan TmpInst.addOperand(MCOperand::createReg(GPReg));
1180fe98b2f5SDaniel Sanders const MCExpr *HiSym = MipsMCExpr::create(
1181fe98b2f5SDaniel Sanders MipsMCExpr::MEK_HI,
1182fe98b2f5SDaniel Sanders MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
1183fe98b2f5SDaniel Sanders MCA.getContext()),
1184fe98b2f5SDaniel Sanders MCA.getContext());
1185e9119e41SJim Grosbach TmpInst.addOperand(MCOperand::createExpr(HiSym));
1186bcd24b2dSFangrui Song getStreamer().emitInstruction(TmpInst, STI);
1187525bc4f7SMatheus Almeida
1188525bc4f7SMatheus Almeida TmpInst.clear();
1189525bc4f7SMatheus Almeida
1190525bc4f7SMatheus Almeida TmpInst.setOpcode(Mips::ADDiu);
1191a884afb6SSimon Atanasyan TmpInst.addOperand(MCOperand::createReg(GPReg));
1192a884afb6SSimon Atanasyan TmpInst.addOperand(MCOperand::createReg(GPReg));
1193fe98b2f5SDaniel Sanders const MCExpr *LoSym = MipsMCExpr::create(
1194fe98b2f5SDaniel Sanders MipsMCExpr::MEK_LO,
1195fe98b2f5SDaniel Sanders MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
1196fe98b2f5SDaniel Sanders MCA.getContext()),
1197fe98b2f5SDaniel Sanders MCA.getContext());
1198e9119e41SJim Grosbach TmpInst.addOperand(MCOperand::createExpr(LoSym));
1199bcd24b2dSFangrui Song getStreamer().emitInstruction(TmpInst, STI);
1200525bc4f7SMatheus Almeida
1201525bc4f7SMatheus Almeida TmpInst.clear();
1202525bc4f7SMatheus Almeida
1203525bc4f7SMatheus Almeida TmpInst.setOpcode(Mips::ADDu);
1204a884afb6SSimon Atanasyan TmpInst.addOperand(MCOperand::createReg(GPReg));
1205a884afb6SSimon Atanasyan TmpInst.addOperand(MCOperand::createReg(GPReg));
1206e9119e41SJim Grosbach TmpInst.addOperand(MCOperand::createReg(RegNo));
1207bcd24b2dSFangrui Song getStreamer().emitInstruction(TmpInst, STI);
1208fb8a2a95SVladimir Medic
1209cdb45fa3SDaniel Sanders forbidModuleDirective();
1210525bc4f7SMatheus Almeida }
1211d92a3fa2SMatheus Almeida
emitDirectiveCpLocal(unsigned RegNo)1212a884afb6SSimon Atanasyan void MipsTargetELFStreamer::emitDirectiveCpLocal(unsigned RegNo) {
1213a884afb6SSimon Atanasyan if (Pic)
1214a884afb6SSimon Atanasyan MipsTargetStreamer::emitDirectiveCpLocal(RegNo);
1215a884afb6SSimon Atanasyan }
1216a884afb6SSimon Atanasyan
emitDirectiveCpRestore(int Offset,function_ref<unsigned ()> GetATReg,SMLoc IDLoc,const MCSubtargetInfo * STI)1217df8510d4SDaniel Sanders bool MipsTargetELFStreamer::emitDirectiveCpRestore(
1218d3f4c05aSBenjamin Kramer int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
12197225cd52SDaniel Sanders const MCSubtargetInfo *STI) {
1220df8510d4SDaniel Sanders MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);
1221e2982adcSDaniel Sanders // .cprestore offset
1222e2982adcSDaniel Sanders // When PIC mode is enabled and the O32 ABI is used, this directive expands
1223e2982adcSDaniel Sanders // to:
1224e2982adcSDaniel Sanders // sw $gp, offset($sp)
1225e2982adcSDaniel Sanders // and adds a corresponding LW after every JAL.
1226e2982adcSDaniel Sanders
1227e2982adcSDaniel Sanders // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
1228e2982adcSDaniel Sanders // is used in non-PIC mode.
1229e2982adcSDaniel Sanders if (!Pic || (getABI().IsN32() || getABI().IsN64()))
1230df8510d4SDaniel Sanders return true;
1231df8510d4SDaniel Sanders
12327225cd52SDaniel Sanders // Store the $gp on the stack.
1233a884afb6SSimon Atanasyan emitStoreWithImmOffset(Mips::SW, GPReg, Mips::SP, Offset, GetATReg, IDLoc,
12347225cd52SDaniel Sanders STI);
1235df8510d4SDaniel Sanders return true;
1236e2982adcSDaniel Sanders }
1237e2982adcSDaniel Sanders
emitDirectiveCpsetup(unsigned RegNo,int RegOrOffset,const MCSymbol & Sym,bool IsReg)1238d92a3fa2SMatheus Almeida void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
1239d92a3fa2SMatheus Almeida int RegOrOffset,
1240d92a3fa2SMatheus Almeida const MCSymbol &Sym,
1241d92a3fa2SMatheus Almeida bool IsReg) {
1242d92a3fa2SMatheus Almeida // Only N32 and N64 emit anything for .cpsetup iff PIC is set.
1243a5762816SEric Christopher if (!Pic || !(getABI().IsN32() || getABI().IsN64()))
1244d92a3fa2SMatheus Almeida return;
1245d92a3fa2SMatheus Almeida
1246e858136dSDaniel Sanders forbidModuleDirective();
1247e858136dSDaniel Sanders
1248d92a3fa2SMatheus Almeida MCAssembler &MCA = getStreamer().getAssembler();
1249d92a3fa2SMatheus Almeida MCInst Inst;
1250d92a3fa2SMatheus Almeida
1251d92a3fa2SMatheus Almeida // Either store the old $gp in a register or on the stack
1252d92a3fa2SMatheus Almeida if (IsReg) {
1253d92a3fa2SMatheus Almeida // move $save, $gpreg
1254a884afb6SSimon Atanasyan emitRRR(Mips::OR64, RegOrOffset, GPReg, Mips::ZERO, SMLoc(), &STI);
1255d92a3fa2SMatheus Almeida } else {
1256d92a3fa2SMatheus Almeida // sd $gpreg, offset($sp)
1257a884afb6SSimon Atanasyan emitRRI(Mips::SD, GPReg, Mips::SP, RegOrOffset, SMLoc(), &STI);
1258d92a3fa2SMatheus Almeida }
1259e858136dSDaniel Sanders
1260e858136dSDaniel Sanders if (getABI().IsN32()) {
1261e858136dSDaniel Sanders MCSymbol *GPSym = MCA.getContext().getOrCreateSymbol("__gnu_local_gp");
1262e858136dSDaniel Sanders const MipsMCExpr *HiExpr = MipsMCExpr::create(
1263e858136dSDaniel Sanders MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(GPSym, MCA.getContext()),
1264e858136dSDaniel Sanders MCA.getContext());
1265e858136dSDaniel Sanders const MipsMCExpr *LoExpr = MipsMCExpr::create(
1266e858136dSDaniel Sanders MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(GPSym, MCA.getContext()),
1267e858136dSDaniel Sanders MCA.getContext());
1268e858136dSDaniel Sanders
1269e858136dSDaniel Sanders // lui $gp, %hi(__gnu_local_gp)
1270a884afb6SSimon Atanasyan emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
1271e858136dSDaniel Sanders
1272e858136dSDaniel Sanders // addiu $gp, $gp, %lo(__gnu_local_gp)
1273a884afb6SSimon Atanasyan emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(),
1274a884afb6SSimon Atanasyan &STI);
1275e858136dSDaniel Sanders
1276e858136dSDaniel Sanders return;
1277e858136dSDaniel Sanders }
1278d92a3fa2SMatheus Almeida
1279fe98b2f5SDaniel Sanders const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff(
1280fe98b2f5SDaniel Sanders MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
1281fe98b2f5SDaniel Sanders MCA.getContext());
1282fe98b2f5SDaniel Sanders const MipsMCExpr *LoExpr = MipsMCExpr::createGpOff(
1283fe98b2f5SDaniel Sanders MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
1284fe98b2f5SDaniel Sanders MCA.getContext());
12858874eac5SToma Tabacu
1286d92a3fa2SMatheus Almeida // lui $gp, %hi(%neg(%gp_rel(funcSym)))
1287a884afb6SSimon Atanasyan emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
1288d92a3fa2SMatheus Almeida
1289d92a3fa2SMatheus Almeida // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
1290a884afb6SSimon Atanasyan emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(),
1291a884afb6SSimon Atanasyan &STI);
1292d92a3fa2SMatheus Almeida
1293d92a3fa2SMatheus Almeida // daddu $gp, $gp, $funcreg
1294a884afb6SSimon Atanasyan emitRRR(Mips::DADDu, GPReg, GPReg, RegNo, SMLoc(), &STI);
1295fb8a2a95SVladimir Medic }
1296fb8a2a95SVladimir Medic
emitDirectiveCpreturn(unsigned SaveLocation,bool SaveLocationIsRegister)1297f173dda0SDaniel Sanders void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
1298f173dda0SDaniel Sanders bool SaveLocationIsRegister) {
1299f173dda0SDaniel Sanders // Only N32 and N64 emit anything for .cpreturn iff PIC is set.
1300f173dda0SDaniel Sanders if (!Pic || !(getABI().IsN32() || getABI().IsN64()))
1301f173dda0SDaniel Sanders return;
1302f173dda0SDaniel Sanders
1303f173dda0SDaniel Sanders MCInst Inst;
1304f173dda0SDaniel Sanders // Either restore the old $gp from a register or on the stack
1305f173dda0SDaniel Sanders if (SaveLocationIsRegister) {
1306f173dda0SDaniel Sanders Inst.setOpcode(Mips::OR);
1307a884afb6SSimon Atanasyan Inst.addOperand(MCOperand::createReg(GPReg));
1308f173dda0SDaniel Sanders Inst.addOperand(MCOperand::createReg(SaveLocation));
1309f173dda0SDaniel Sanders Inst.addOperand(MCOperand::createReg(Mips::ZERO));
1310f173dda0SDaniel Sanders } else {
1311f173dda0SDaniel Sanders Inst.setOpcode(Mips::LD);
1312a884afb6SSimon Atanasyan Inst.addOperand(MCOperand::createReg(GPReg));
1313f173dda0SDaniel Sanders Inst.addOperand(MCOperand::createReg(Mips::SP));
1314f173dda0SDaniel Sanders Inst.addOperand(MCOperand::createImm(SaveLocation));
1315f173dda0SDaniel Sanders }
1316bcd24b2dSFangrui Song getStreamer().emitInstruction(Inst, STI);
1317f173dda0SDaniel Sanders
1318f173dda0SDaniel Sanders forbidModuleDirective();
1319f173dda0SDaniel Sanders }
1320f173dda0SDaniel Sanders
emitMipsAbiFlags()1321fb8a2a95SVladimir Medic void MipsTargetELFStreamer::emitMipsAbiFlags() {
1322fb8a2a95SVladimir Medic MCAssembler &MCA = getStreamer().getAssembler();
1323fb8a2a95SVladimir Medic MCContext &Context = MCA.getContext();
1324fb8a2a95SVladimir Medic MCStreamer &OS = getStreamer();
13250709a7bdSRafael Espindola MCSectionELF *Sec = Context.getELFSection(
132616af9739SPetr Hosek ".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24);
1327bb9a71c1SRafael Espindola MCA.registerSection(*Sec);
132818f805a7SGuillaume Chatelet Sec->setAlignment(Align(8));
1329*adf4142fSFangrui Song OS.switchSection(Sec);
1330fb8a2a95SVladimir Medic
1331c7dbc630SDaniel Sanders OS << ABIFlagsSection;
1332d92a3fa2SMatheus Almeida }
1333