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