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