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