blob: 5eec7213b9f436ca2624abafc4a77fc723c8d588 [file] [log] [blame]
Jack Carter86ac5c12013-11-18 23:55:27 +00001//===-- MipsTargetStreamer.cpp - Mips Target Streamer Methods -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file provides Mips specific target streamer methods.
11//
12//===----------------------------------------------------------------------===//
13
Mehdi Aminib550cb12016-04-18 09:17:29 +000014#include "MipsTargetStreamer.h"
Rafael Espindola054234f2014-01-27 03:53:56 +000015#include "InstPrinter/MipsInstPrinter.h"
Daniel Sanders68c37472014-07-21 13:30:55 +000016#include "MipsELFStreamer.h"
Chandler Carruth442f7842014-03-04 10:07:28 +000017#include "MipsMCTargetDesc.h"
Rafael Espindola972e71a2014-01-31 23:10:26 +000018#include "MipsTargetObjectFile.h"
Rafael Espindola972e71a2014-01-31 23:10:26 +000019#include "llvm/MC/MCContext.h"
Rafael Espindola972e71a2014-01-31 23:10:26 +000020#include "llvm/MC/MCSectionELF.h"
Rafael Espindolacb1953f2014-01-26 06:57:13 +000021#include "llvm/MC/MCSubtargetInfo.h"
Rafael Espindola95fb9b92015-06-02 20:38:46 +000022#include "llvm/MC/MCSymbolELF.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000023#include "llvm/Support/ELF.h"
Jack Carter86ac5c12013-11-18 23:55:27 +000024#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/FormattedStream.h"
26
27using namespace llvm;
28
Vladimir Medicfb8a2a92014-07-08 08:59:22 +000029MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000030 : MCTargetStreamer(S), ModuleDirectiveAllowed(true) {
Daniel Sandersd97a6342014-08-13 10:07:34 +000031 GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
32}
Rafael Espindola60890b82014-06-23 19:43:40 +000033void MipsTargetStreamer::emitDirectiveSetMicroMips() {}
34void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {}
35void MipsTargetStreamer::emitDirectiveSetMips16() {}
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000036void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); }
37void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); }
Rafael Espindola60890b82014-06-23 19:43:40 +000038void MipsTargetStreamer::emitDirectiveSetNoReorder() {}
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000039void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); }
40void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); }
41void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); }
42void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); }
43void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); }
Toma Tabacu16a74492015-02-13 10:30:57 +000044void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
45 forbidModuleDirective();
46}
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000047void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); }
Rafael Espindola60890b82014-06-23 19:43:40 +000048void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {}
49void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {}
50void MipsTargetStreamer::emitDirectiveAbiCalls() {}
51void MipsTargetStreamer::emitDirectiveNaN2008() {}
52void MipsTargetStreamer::emitDirectiveNaNLegacy() {}
53void MipsTargetStreamer::emitDirectiveOptionPic0() {}
54void MipsTargetStreamer::emitDirectiveOptionPic2() {}
Toma Tabacu9ca50962015-04-16 09:53:47 +000055void MipsTargetStreamer::emitDirectiveInsn() { forbidModuleDirective(); }
Rafael Espindola60890b82014-06-23 19:43:40 +000056void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
57 unsigned ReturnReg) {}
58void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {}
59void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) {
60}
Toma Tabacu85618b32014-08-19 14:22:52 +000061void MipsTargetStreamer::emitDirectiveSetArch(StringRef Arch) {
62 forbidModuleDirective();
63}
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +000064void MipsTargetStreamer::emitDirectiveSetMips0() { forbidModuleDirective(); }
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000065void MipsTargetStreamer::emitDirectiveSetMips1() { forbidModuleDirective(); }
66void MipsTargetStreamer::emitDirectiveSetMips2() { forbidModuleDirective(); }
67void MipsTargetStreamer::emitDirectiveSetMips3() { forbidModuleDirective(); }
68void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); }
69void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); }
70void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); }
71void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); }
Daniel Sanders17793142015-02-18 16:24:50 +000072void MipsTargetStreamer::emitDirectiveSetMips32R3() { forbidModuleDirective(); }
73void MipsTargetStreamer::emitDirectiveSetMips32R5() { forbidModuleDirective(); }
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000074void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); }
75void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); }
76void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); }
Daniel Sanders17793142015-02-18 16:24:50 +000077void MipsTargetStreamer::emitDirectiveSetMips64R3() { forbidModuleDirective(); }
78void MipsTargetStreamer::emitDirectiveSetMips64R5() { forbidModuleDirective(); }
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000079void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); }
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +000080void MipsTargetStreamer::emitDirectiveSetPop() { forbidModuleDirective(); }
81void MipsTargetStreamer::emitDirectiveSetPush() { forbidModuleDirective(); }
Toma Tabacu29696502015-06-02 09:48:04 +000082void MipsTargetStreamer::emitDirectiveSetSoftFloat() {
83 forbidModuleDirective();
84}
85void MipsTargetStreamer::emitDirectiveSetHardFloat() {
86 forbidModuleDirective();
87}
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000088void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }
Toma Tabacu351b2fe2014-09-17 09:01:54 +000089void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
Toma Tabacuc4c202a2014-10-01 14:53:19 +000090void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
Daniel Sanders7225cd52016-04-29 16:16:49 +000091void MipsTargetStreamer::emitDirectiveCpRestore(int Offset, unsigned ATReg,
92 SMLoc IDLoc,
93 const MCSubtargetInfo *STI) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +000094 forbidModuleDirective();
95}
Rafael Espindola60890b82014-06-23 19:43:40 +000096void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
97 const MCSymbol &Sym, bool IsReg) {
98}
Daniel Sandersf173dda2015-09-22 10:50:09 +000099void MipsTargetStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
100 bool SaveLocationIsRegister) {}
Toma Tabacubfcbfd52015-06-23 12:34:19 +0000101
Toma Tabacua64e5402015-06-25 12:44:38 +0000102void MipsTargetStreamer::emitDirectiveModuleFP() {}
Toma Tabacubfcbfd52015-06-23 12:34:19 +0000103
Toma Tabacu3c499582015-06-25 10:56:57 +0000104void MipsTargetStreamer::emitDirectiveModuleOddSPReg() {
105 if (!ABIFlagsSection.OddSPReg && !ABIFlagsSection.Is32BitABI)
Daniel Sanders7e527422014-07-10 13:38:23 +0000106 report_fatal_error("+nooddspreg is only valid for O32");
107}
Toma Tabacu0f093132015-06-30 13:46:03 +0000108void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {}
109void MipsTargetStreamer::emitDirectiveModuleHardFloat() {}
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000110void MipsTargetStreamer::emitDirectiveSetFp(
111 MipsABIFlagsSection::FpABIKind Value) {
112 forbidModuleDirective();
113}
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000114void MipsTargetStreamer::emitDirectiveSetOddSPReg() { forbidModuleDirective(); }
115void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() {
116 forbidModuleDirective();
117}
Rafael Espindola24ea09e2014-01-26 06:06:37 +0000118
Daniel Sandersa736b372016-04-29 13:33:12 +0000119void MipsTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
120 const MCSubtargetInfo *STI) {
121 MCInst TmpInst;
122 TmpInst.setOpcode(Opcode);
123 TmpInst.addOperand(MCOperand::createReg(Reg0));
124 TmpInst.setLoc(IDLoc);
125 getStreamer().EmitInstruction(TmpInst, *STI);
126}
127
128void MipsTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1,
129 SMLoc IDLoc, const MCSubtargetInfo *STI) {
130 MCInst TmpInst;
131 TmpInst.setOpcode(Opcode);
132 TmpInst.addOperand(MCOperand::createReg(Reg0));
133 TmpInst.addOperand(Op1);
134 TmpInst.setLoc(IDLoc);
135 getStreamer().EmitInstruction(TmpInst, *STI);
136}
137
138void MipsTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm,
139 SMLoc IDLoc, const MCSubtargetInfo *STI) {
140 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI);
141}
142
143void MipsTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
144 SMLoc IDLoc, const MCSubtargetInfo *STI) {
145 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI);
146}
147
148void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2,
149 SMLoc IDLoc, const MCSubtargetInfo *STI) {
150 MCInst TmpInst;
151 TmpInst.setOpcode(Opcode);
152 TmpInst.addOperand(MCOperand::createImm(Imm1));
153 TmpInst.addOperand(MCOperand::createImm(Imm2));
154 TmpInst.setLoc(IDLoc);
155 getStreamer().EmitInstruction(TmpInst, *STI);
156}
157
158void MipsTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,
159 MCOperand Op2, SMLoc IDLoc,
160 const MCSubtargetInfo *STI) {
161 MCInst TmpInst;
162 TmpInst.setOpcode(Opcode);
163 TmpInst.addOperand(MCOperand::createReg(Reg0));
164 TmpInst.addOperand(MCOperand::createReg(Reg1));
165 TmpInst.addOperand(Op2);
166 TmpInst.setLoc(IDLoc);
167 getStreamer().EmitInstruction(TmpInst, *STI);
168}
169
170void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
171 unsigned Reg2, SMLoc IDLoc,
172 const MCSubtargetInfo *STI) {
173 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI);
174}
175
176void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,
177 int16_t Imm, SMLoc IDLoc,
178 const MCSubtargetInfo *STI) {
179 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI);
180}
181
182void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg,
183 unsigned TrgReg, bool Is64Bit,
184 const MCSubtargetInfo *STI) {
185 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
186 STI);
187}
188
189void MipsTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg,
190 int16_t ShiftAmount, SMLoc IDLoc,
191 const MCSubtargetInfo *STI) {
192 if (ShiftAmount >= 32) {
193 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI);
194 return;
195 }
196
197 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI);
198}
199
200void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
201 const MCSubtargetInfo *STI) {
202 if (hasShortDelaySlot)
203 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI);
204 else
205 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
206}
207
208void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {
209 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
210}
211
Daniel Sanders7225cd52016-04-29 16:16:49 +0000212/// Emit the $gp restore operation for .cprestore.
213void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,
214 const MCSubtargetInfo *STI) {
215 emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc,
216 STI);
217}
218
219/// Emit a store instruction with an immediate offset.
Daniel Sandersfba875f2016-04-29 13:43:45 +0000220void MipsTargetStreamer::emitStoreWithImmOffset(
221 unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset,
222 unsigned ATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) {
Daniel Sanders7225cd52016-04-29 16:16:49 +0000223 if (isInt<16>(Offset)) {
224 emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI);
225 return;
226 }
227
Daniel Sandersfba875f2016-04-29 13:43:45 +0000228 // sw $8, offset($8) => lui $at, %hi(offset)
229 // add $at, $at, $8
230 // sw $8, %lo(offset)($at)
231
232 unsigned LoOffset = Offset & 0x0000ffff;
233 unsigned HiOffset = (Offset & 0xffff0000) >> 16;
234
235 // If msb of LoOffset is 1(negative number) we must increment HiOffset
236 // to account for the sign-extension of the low part.
237 if (LoOffset & 0x8000)
238 HiOffset++;
239
240 // Generate the base address in ATReg.
241 emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI);
242 if (BaseReg != Mips::ZERO)
243 emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
244 // Emit the store with the adjusted base and offset.
245 emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI);
246}
247
248/// Emit a store instruction with an symbol offset. Symbols are assumed to be
249/// out of range for a simm16 will be expanded to appropriate instructions.
250void MipsTargetStreamer::emitStoreWithSymOffset(
251 unsigned Opcode, unsigned SrcReg, unsigned BaseReg, MCOperand &HiOperand,
252 MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
253 const MCSubtargetInfo *STI) {
254 // sw $8, sym => lui $at, %hi(sym)
255 // sw $8, %lo(sym)($at)
256
257 // Generate the base address in ATReg.
258 emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI);
259 if (BaseReg != Mips::ZERO)
260 emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
261 // Emit the store with the adjusted base and offset.
262 emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI);
263}
264
Daniel Sanders7225cd52016-04-29 16:16:49 +0000265/// Emit a load instruction with an immediate offset. DstReg and TmpReg are
266/// permitted to be the same register iff DstReg is distinct from BaseReg and
267/// DstReg is a GPR. It is the callers responsibility to identify such cases
268/// and pass the appropriate register in TmpReg.
Daniel Sandersfba875f2016-04-29 13:43:45 +0000269void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg,
270 unsigned BaseReg, int64_t Offset,
271 unsigned TmpReg, SMLoc IDLoc,
272 const MCSubtargetInfo *STI) {
Daniel Sanders7225cd52016-04-29 16:16:49 +0000273 if (isInt<16>(Offset)) {
274 emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI);
275 return;
276 }
277
Daniel Sandersfba875f2016-04-29 13:43:45 +0000278 // 1) lw $8, offset($9) => lui $8, %hi(offset)
279 // add $8, $8, $9
280 // lw $8, %lo(offset)($9)
281 // 2) lw $8, offset($8) => lui $at, %hi(offset)
282 // add $at, $at, $8
283 // lw $8, %lo(offset)($at)
284
285 unsigned LoOffset = Offset & 0x0000ffff;
286 unsigned HiOffset = (Offset & 0xffff0000) >> 16;
287
288 // If msb of LoOffset is 1(negative number) we must increment HiOffset
289 // to account for the sign-extension of the low part.
290 if (LoOffset & 0x8000)
291 HiOffset++;
292
293 // Generate the base address in TmpReg.
294 emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI);
295 if (BaseReg != Mips::ZERO)
296 emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
297 // Emit the load with the adjusted base and offset.
298 emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI);
299}
300
301/// Emit a load instruction with an symbol offset. Symbols are assumed to be
302/// out of range for a simm16 will be expanded to appropriate instructions.
303/// DstReg and TmpReg are permitted to be the same register iff DstReg is a
304/// GPR. It is the callers responsibility to identify such cases and pass the
305/// appropriate register in TmpReg.
306void MipsTargetStreamer::emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg,
307 unsigned BaseReg,
308 MCOperand &HiOperand,
309 MCOperand &LoOperand,
310 unsigned TmpReg, SMLoc IDLoc,
311 const MCSubtargetInfo *STI) {
312 // 1) lw $8, sym => lui $8, %hi(sym)
313 // lw $8, %lo(sym)($8)
314 // 2) ldc1 $f0, sym => lui $at, %hi(sym)
315 // ldc1 $f0, %lo(sym)($at)
316
317 // Generate the base address in TmpReg.
318 emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
319 if (BaseReg != Mips::ZERO)
320 emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
321 // Emit the load with the adjusted base and offset.
322 emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI);
323}
324
Rafael Espindola24ea09e2014-01-26 06:06:37 +0000325MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,
326 formatted_raw_ostream &OS)
327 : MipsTargetStreamer(S), OS(OS) {}
Jack Carter6ef6cc52013-11-19 20:53:28 +0000328
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000329void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() {
330 OS << "\t.set\tmicromips\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000331 forbidModuleDirective();
Jack Carter6ef6cc52013-11-19 20:53:28 +0000332}
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000333
334void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() {
335 OS << "\t.set\tnomicromips\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000336 forbidModuleDirective();
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000337}
338
Rafael Espindola6633d572014-01-14 18:57:12 +0000339void MipsTargetAsmStreamer::emitDirectiveSetMips16() {
340 OS << "\t.set\tmips16\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000341 forbidModuleDirective();
Rafael Espindola6633d572014-01-14 18:57:12 +0000342}
343
344void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() {
345 OS << "\t.set\tnomips16\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000346 MipsTargetStreamer::emitDirectiveSetNoMips16();
Rafael Espindola6633d572014-01-14 18:57:12 +0000347}
348
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000349void MipsTargetAsmStreamer::emitDirectiveSetReorder() {
350 OS << "\t.set\treorder\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000351 MipsTargetStreamer::emitDirectiveSetReorder();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000352}
353
354void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() {
355 OS << "\t.set\tnoreorder\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000356 forbidModuleDirective();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000357}
358
359void MipsTargetAsmStreamer::emitDirectiveSetMacro() {
360 OS << "\t.set\tmacro\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000361 MipsTargetStreamer::emitDirectiveSetMacro();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000362}
363
364void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() {
365 OS << "\t.set\tnomacro\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000366 MipsTargetStreamer::emitDirectiveSetNoMacro();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000367}
368
Daniel Sanders44934432014-08-07 12:03:36 +0000369void MipsTargetAsmStreamer::emitDirectiveSetMsa() {
370 OS << "\t.set\tmsa\n";
371 MipsTargetStreamer::emitDirectiveSetMsa();
372}
373
374void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() {
375 OS << "\t.set\tnomsa\n";
376 MipsTargetStreamer::emitDirectiveSetNoMsa();
377}
378
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000379void MipsTargetAsmStreamer::emitDirectiveSetAt() {
380 OS << "\t.set\tat\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000381 MipsTargetStreamer::emitDirectiveSetAt();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000382}
383
Toma Tabacu16a74492015-02-13 10:30:57 +0000384void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
385 OS << "\t.set\tat=$" << Twine(RegNo) << "\n";
386 MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo);
387}
388
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000389void MipsTargetAsmStreamer::emitDirectiveSetNoAt() {
390 OS << "\t.set\tnoat\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000391 MipsTargetStreamer::emitDirectiveSetNoAt();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000392}
393
394void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) {
395 OS << "\t.end\t" << Name << '\n';
396}
397
Rafael Espindola6633d572014-01-14 18:57:12 +0000398void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {
399 OS << "\t.ent\t" << Symbol.getName() << '\n';
400}
401
Jack Carter0cd3c192014-01-06 23:27:31 +0000402void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; }
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000403
404void MipsTargetAsmStreamer::emitDirectiveNaN2008() { OS << "\t.nan\t2008\n"; }
405
406void MipsTargetAsmStreamer::emitDirectiveNaNLegacy() {
407 OS << "\t.nan\tlegacy\n";
408}
409
Jack Carter0cd3c192014-01-06 23:27:31 +0000410void MipsTargetAsmStreamer::emitDirectiveOptionPic0() {
411 OS << "\t.option\tpic0\n";
412}
413
Matheus Almeidaf79b2812014-03-26 13:40:29 +0000414void MipsTargetAsmStreamer::emitDirectiveOptionPic2() {
415 OS << "\t.option\tpic2\n";
416}
417
Toma Tabacu9ca50962015-04-16 09:53:47 +0000418void MipsTargetAsmStreamer::emitDirectiveInsn() {
419 MipsTargetStreamer::emitDirectiveInsn();
420 OS << "\t.insn\n";
421}
422
Rafael Espindola054234f2014-01-27 03:53:56 +0000423void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
424 unsigned ReturnReg) {
425 OS << "\t.frame\t$"
426 << StringRef(MipsInstPrinter::getRegisterName(StackReg)).lower() << ","
427 << StackSize << ",$"
Rafael Espindola25fa2912014-01-27 04:33:11 +0000428 << StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n';
429}
430
Toma Tabacu85618b32014-08-19 14:22:52 +0000431void MipsTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) {
432 OS << "\t.set arch=" << Arch << "\n";
433 MipsTargetStreamer::emitDirectiveSetArch(Arch);
434}
435
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000436void MipsTargetAsmStreamer::emitDirectiveSetMips0() {
437 OS << "\t.set\tmips0\n";
438 MipsTargetStreamer::emitDirectiveSetMips0();
439}
Toma Tabacu26647792014-09-09 12:52:14 +0000440
Daniel Sandersf0df2212014-08-04 12:20:00 +0000441void MipsTargetAsmStreamer::emitDirectiveSetMips1() {
442 OS << "\t.set\tmips1\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000443 MipsTargetStreamer::emitDirectiveSetMips1();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000444}
445
446void MipsTargetAsmStreamer::emitDirectiveSetMips2() {
447 OS << "\t.set\tmips2\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000448 MipsTargetStreamer::emitDirectiveSetMips2();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000449}
450
451void MipsTargetAsmStreamer::emitDirectiveSetMips3() {
452 OS << "\t.set\tmips3\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000453 MipsTargetStreamer::emitDirectiveSetMips3();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000454}
455
456void MipsTargetAsmStreamer::emitDirectiveSetMips4() {
457 OS << "\t.set\tmips4\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000458 MipsTargetStreamer::emitDirectiveSetMips4();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000459}
460
461void MipsTargetAsmStreamer::emitDirectiveSetMips5() {
462 OS << "\t.set\tmips5\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000463 MipsTargetStreamer::emitDirectiveSetMips5();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000464}
465
466void MipsTargetAsmStreamer::emitDirectiveSetMips32() {
467 OS << "\t.set\tmips32\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000468 MipsTargetStreamer::emitDirectiveSetMips32();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000469}
470
Vladimir Medic615b26e2014-03-04 09:54:09 +0000471void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() {
472 OS << "\t.set\tmips32r2\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000473 MipsTargetStreamer::emitDirectiveSetMips32R2();
Vladimir Medic615b26e2014-03-04 09:54:09 +0000474}
475
Daniel Sanders17793142015-02-18 16:24:50 +0000476void MipsTargetAsmStreamer::emitDirectiveSetMips32R3() {
477 OS << "\t.set\tmips32r3\n";
478 MipsTargetStreamer::emitDirectiveSetMips32R3();
479}
480
481void MipsTargetAsmStreamer::emitDirectiveSetMips32R5() {
482 OS << "\t.set\tmips32r5\n";
483 MipsTargetStreamer::emitDirectiveSetMips32R5();
484}
485
Daniel Sandersf0df2212014-08-04 12:20:00 +0000486void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() {
487 OS << "\t.set\tmips32r6\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000488 MipsTargetStreamer::emitDirectiveSetMips32R6();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000489}
490
Matheus Almeida3b9c63d2014-03-26 15:14:32 +0000491void MipsTargetAsmStreamer::emitDirectiveSetMips64() {
492 OS << "\t.set\tmips64\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000493 MipsTargetStreamer::emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +0000494}
495
Matheus Almeidaa2cd0092014-03-26 14:52:22 +0000496void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() {
497 OS << "\t.set\tmips64r2\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000498 MipsTargetStreamer::emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +0000499}
500
Daniel Sanders17793142015-02-18 16:24:50 +0000501void MipsTargetAsmStreamer::emitDirectiveSetMips64R3() {
502 OS << "\t.set\tmips64r3\n";
503 MipsTargetStreamer::emitDirectiveSetMips64R3();
504}
505
506void MipsTargetAsmStreamer::emitDirectiveSetMips64R5() {
507 OS << "\t.set\tmips64r5\n";
508 MipsTargetStreamer::emitDirectiveSetMips64R5();
509}
510
Daniel Sandersf0df2212014-08-04 12:20:00 +0000511void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() {
512 OS << "\t.set\tmips64r6\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000513 MipsTargetStreamer::emitDirectiveSetMips64R6();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000514}
515
Vladimir Medic27c398e2014-03-05 11:05:09 +0000516void MipsTargetAsmStreamer::emitDirectiveSetDsp() {
517 OS << "\t.set\tdsp\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000518 MipsTargetStreamer::emitDirectiveSetDsp();
Vladimir Medic27c398e2014-03-05 11:05:09 +0000519}
Toma Tabacu9db22db2014-09-09 10:15:38 +0000520
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000521void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() {
522 OS << "\t.set\tnodsp\n";
523 MipsTargetStreamer::emitDirectiveSetNoDsp();
524}
525
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000526void MipsTargetAsmStreamer::emitDirectiveSetPop() {
527 OS << "\t.set\tpop\n";
528 MipsTargetStreamer::emitDirectiveSetPop();
529}
Toma Tabacu9db22db2014-09-09 10:15:38 +0000530
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000531void MipsTargetAsmStreamer::emitDirectiveSetPush() {
532 OS << "\t.set\tpush\n";
533 MipsTargetStreamer::emitDirectiveSetPush();
534}
Toma Tabacu9db22db2014-09-09 10:15:38 +0000535
Toma Tabacu29696502015-06-02 09:48:04 +0000536void MipsTargetAsmStreamer::emitDirectiveSetSoftFloat() {
537 OS << "\t.set\tsoftfloat\n";
538 MipsTargetStreamer::emitDirectiveSetSoftFloat();
539}
540
541void MipsTargetAsmStreamer::emitDirectiveSetHardFloat() {
542 OS << "\t.set\thardfloat\n";
543 MipsTargetStreamer::emitDirectiveSetHardFloat();
544}
545
Rafael Espindola25fa2912014-01-27 04:33:11 +0000546// Print a 32 bit hex number with all numbers.
547static void printHex32(unsigned Value, raw_ostream &OS) {
548 OS << "0x";
549 for (int i = 7; i >= 0; i--)
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000550 OS.write_hex((Value & (0xF << (i * 4))) >> (i * 4));
Rafael Espindola25fa2912014-01-27 04:33:11 +0000551}
552
553void MipsTargetAsmStreamer::emitMask(unsigned CPUBitmask,
554 int CPUTopSavedRegOff) {
555 OS << "\t.mask \t";
556 printHex32(CPUBitmask, OS);
557 OS << ',' << CPUTopSavedRegOff << '\n';
558}
559
560void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask,
561 int FPUTopSavedRegOff) {
562 OS << "\t.fmask\t";
563 printHex32(FPUBitmask, OS);
564 OS << "," << FPUTopSavedRegOff << '\n';
Rafael Espindola054234f2014-01-27 03:53:56 +0000565}
566
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000567void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000568 OS << "\t.cpload\t$"
569 << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000570 forbidModuleDirective();
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000571}
572
Daniel Sanders7225cd52016-04-29 16:16:49 +0000573void MipsTargetAsmStreamer::emitDirectiveCpRestore(int Offset, unsigned ATReg,
574 SMLoc IDLoc,
575 const MCSubtargetInfo *STI) {
576 MipsTargetStreamer::emitDirectiveCpRestore(Offset, ATReg, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000577 OS << "\t.cprestore\t" << Offset << "\n";
578}
579
Matheus Almeidad92a3fa2014-05-01 10:24:46 +0000580void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
581 int RegOrOffset,
582 const MCSymbol &Sym,
583 bool IsReg) {
584 OS << "\t.cpsetup\t$"
585 << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << ", ";
586
587 if (IsReg)
588 OS << "$"
589 << StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower();
590 else
591 OS << RegOrOffset;
592
593 OS << ", ";
594
Daniel Sanders5d796282015-09-21 09:26:55 +0000595 OS << Sym.getName();
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000596 forbidModuleDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000597}
598
Daniel Sandersf173dda2015-09-22 10:50:09 +0000599void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
600 bool SaveLocationIsRegister) {
601 OS << "\t.cpreturn";
602 forbidModuleDirective();
603}
604
Toma Tabacua64e5402015-06-25 12:44:38 +0000605void MipsTargetAsmStreamer::emitDirectiveModuleFP() {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000606 OS << "\t.module\tfp=";
Toma Tabacua64e5402015-06-25 12:44:38 +0000607 OS << ABIFlagsSection.getFpABIString(ABIFlagsSection.getFpABI()) << "\n";
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000608}
609
Daniel Sanders7e527422014-07-10 13:38:23 +0000610void MipsTargetAsmStreamer::emitDirectiveSetFp(
611 MipsABIFlagsSection::FpABIKind Value) {
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000612 MipsTargetStreamer::emitDirectiveSetFp(Value);
613
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000614 OS << "\t.set\tfp=";
Daniel Sanders7e527422014-07-10 13:38:23 +0000615 OS << ABIFlagsSection.getFpABIString(Value) << "\n";
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000616}
617
Toma Tabacu3c499582015-06-25 10:56:57 +0000618void MipsTargetAsmStreamer::emitDirectiveModuleOddSPReg() {
619 MipsTargetStreamer::emitDirectiveModuleOddSPReg();
Daniel Sanders7e527422014-07-10 13:38:23 +0000620
Toma Tabacu3c499582015-06-25 10:56:57 +0000621 OS << "\t.module\t" << (ABIFlagsSection.OddSPReg ? "" : "no") << "oddspreg\n";
Daniel Sanders7e527422014-07-10 13:38:23 +0000622}
623
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000624void MipsTargetAsmStreamer::emitDirectiveSetOddSPReg() {
625 MipsTargetStreamer::emitDirectiveSetOddSPReg();
626 OS << "\t.set\toddspreg\n";
627}
628
629void MipsTargetAsmStreamer::emitDirectiveSetNoOddSPReg() {
630 MipsTargetStreamer::emitDirectiveSetNoOddSPReg();
631 OS << "\t.set\tnooddspreg\n";
632}
633
Toma Tabacu0f093132015-06-30 13:46:03 +0000634void MipsTargetAsmStreamer::emitDirectiveModuleSoftFloat() {
635 OS << "\t.module\tsoftfloat\n";
636}
637
638void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() {
639 OS << "\t.module\thardfloat\n";
640}
641
Jack Carter0cd3c192014-01-06 23:27:31 +0000642// This part is for ELF object output.
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000643MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
644 const MCSubtargetInfo &STI)
Rafael Espindola972e71a2014-01-31 23:10:26 +0000645 : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) {
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000646 MCAssembler &MCA = getStreamer().getAssembler();
Simon Atanasyanc99ce682015-03-24 12:24:56 +0000647 Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_;
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000648
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000649 const FeatureBitset &Features = STI.getFeatureBits();
Eric Christophera5762812015-01-26 17:33:46 +0000650
651 // Set the header flags that we can in the constructor.
652 // FIXME: This is a fairly terrible hack. We set the rest
653 // of these in the destructor. The problem here is two-fold:
654 //
655 // a: Some of the eflags can be set/reset by directives.
656 // b: There aren't any usage paths that initialize the ABI
657 // pointer until after we initialize either an assembler
658 // or the target machine.
659 // We can fix this by making the target streamer construct
660 // the ABI, but this is fraught with wide ranging dependency
661 // issues as well.
662 unsigned EFlags = MCA.getELFHeaderEFlags();
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000663
664 // Architecture
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000665 if (Features[Mips::FeatureMips64r6])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000666 EFlags |= ELF::EF_MIPS_ARCH_64R6;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000667 else if (Features[Mips::FeatureMips64r2] ||
668 Features[Mips::FeatureMips64r3] ||
669 Features[Mips::FeatureMips64r5])
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000670 EFlags |= ELF::EF_MIPS_ARCH_64R2;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000671 else if (Features[Mips::FeatureMips64])
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000672 EFlags |= ELF::EF_MIPS_ARCH_64;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000673 else if (Features[Mips::FeatureMips5])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000674 EFlags |= ELF::EF_MIPS_ARCH_5;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000675 else if (Features[Mips::FeatureMips4])
Daniel Sandersf7b32292014-04-03 12:13:36 +0000676 EFlags |= ELF::EF_MIPS_ARCH_4;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000677 else if (Features[Mips::FeatureMips3])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000678 EFlags |= ELF::EF_MIPS_ARCH_3;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000679 else if (Features[Mips::FeatureMips32r6])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000680 EFlags |= ELF::EF_MIPS_ARCH_32R6;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000681 else if (Features[Mips::FeatureMips32r2] ||
682 Features[Mips::FeatureMips32r3] ||
683 Features[Mips::FeatureMips32r5])
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000684 EFlags |= ELF::EF_MIPS_ARCH_32R2;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000685 else if (Features[Mips::FeatureMips32])
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000686 EFlags |= ELF::EF_MIPS_ARCH_32;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000687 else if (Features[Mips::FeatureMips2])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000688 EFlags |= ELF::EF_MIPS_ARCH_2;
689 else
690 EFlags |= ELF::EF_MIPS_ARCH_1;
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000691
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000692 // Other options.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000693 if (Features[Mips::FeatureNaN2008])
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000694 EFlags |= ELF::EF_MIPS_NAN2008;
695
Daniel Sanders16ec6c12014-07-17 09:52:56 +0000696 // -mabicalls and -mplt are not implemented but we should act as if they were
697 // given.
698 EFlags |= ELF::EF_MIPS_CPIC;
Daniel Sanders16ec6c12014-07-17 09:52:56 +0000699
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000700 MCA.setELFHeaderEFlags(EFlags);
701}
Jack Carter86ac5c12013-11-18 23:55:27 +0000702
Rafael Espindola95fb9b92015-06-02 20:38:46 +0000703void MipsTargetELFStreamer::emitLabel(MCSymbol *S) {
704 auto *Symbol = cast<MCSymbolELF>(S);
Rafael Espindola26e917c2014-01-15 03:07:12 +0000705 if (!isMicroMipsEnabled())
706 return;
Rafael Espindolac73aed12015-06-03 19:03:11 +0000707 getStreamer().getAssembler().registerSymbol(*Symbol);
Rafael Espindola95fb9b92015-06-02 20:38:46 +0000708 uint8_t Type = Symbol->getType();
Rafael Espindola26e917c2014-01-15 03:07:12 +0000709 if (Type != ELF::STT_FUNC)
710 return;
711
Rafael Espindola8c006ee2015-06-04 05:59:23 +0000712 Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000713}
714
Rafael Espindola972e71a2014-01-31 23:10:26 +0000715void MipsTargetELFStreamer::finish() {
716 MCAssembler &MCA = getStreamer().getAssembler();
Daniel Sanders68c37472014-07-21 13:30:55 +0000717 const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo();
Rafael Espindola972e71a2014-01-31 23:10:26 +0000718
Daniel Sanders41ffa5d2014-07-14 15:05:51 +0000719 // .bss, .text and .data are always at least 16-byte aligned.
Rafael Espindola967d6a62015-05-21 21:02:35 +0000720 MCSection &TextSection = *OFI.getTextSection();
Rafael Espindolabb9a71c2015-05-26 15:07:25 +0000721 MCA.registerSection(TextSection);
Rafael Espindola967d6a62015-05-21 21:02:35 +0000722 MCSection &DataSection = *OFI.getDataSection();
Rafael Espindolabb9a71c2015-05-26 15:07:25 +0000723 MCA.registerSection(DataSection);
Rafael Espindola967d6a62015-05-21 21:02:35 +0000724 MCSection &BSSSection = *OFI.getBSSSection();
Rafael Espindolabb9a71c2015-05-26 15:07:25 +0000725 MCA.registerSection(BSSSection);
Daniel Sanders41ffa5d2014-07-14 15:05:51 +0000726
Rafael Espindola967d6a62015-05-21 21:02:35 +0000727 TextSection.setAlignment(std::max(16u, TextSection.getAlignment()));
728 DataSection.setAlignment(std::max(16u, DataSection.getAlignment()));
729 BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment()));
Daniel Sanders41ffa5d2014-07-14 15:05:51 +0000730
Daniel Sanders9db710a2016-04-29 12:44:07 +0000731 // Make sections sizes a multiple of the alignment.
732 MCStreamer &OS = getStreamer();
733 for (MCSection &S : MCA) {
734 MCSectionELF &Section = static_cast<MCSectionELF &>(S);
735
736 unsigned Alignment = Section.getAlignment();
737 if (Alignment) {
738 OS.SwitchSection(&Section);
739 if (Section.UseCodeAlign())
740 OS.EmitCodeAlignment(Alignment, Alignment);
741 else
742 OS.EmitValueToAlignment(Alignment, 0, 1, Alignment);
743 }
744 }
745
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000746 const FeatureBitset &Features = STI.getFeatureBits();
Eric Christophera5762812015-01-26 17:33:46 +0000747
748 // Update e_header flags. See the FIXME and comment above in
749 // the constructor for a full rundown on this.
750 unsigned EFlags = MCA.getELFHeaderEFlags();
751
752 // ABI
753 // N64 does not require any ABI bits.
754 if (getABI().IsO32())
755 EFlags |= ELF::EF_MIPS_ABI_O32;
756 else if (getABI().IsN32())
757 EFlags |= ELF::EF_MIPS_ABI2;
758
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000759 if (Features[Mips::FeatureGP64Bit]) {
Eric Christophera5762812015-01-26 17:33:46 +0000760 if (getABI().IsO32())
761 EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000762 } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64])
Eric Christophera5762812015-01-26 17:33:46 +0000763 EFlags |= ELF::EF_MIPS_32BITMODE;
764
765 // If we've set the cpic eflag and we're n64, go ahead and set the pic
766 // one as well.
767 if (EFlags & ELF::EF_MIPS_CPIC && getABI().IsN64())
768 EFlags |= ELF::EF_MIPS_PIC;
769
770 MCA.setELFHeaderEFlags(EFlags);
771
Daniel Sanders68c37472014-07-21 13:30:55 +0000772 // Emit all the option records.
773 // At the moment we are only emitting .Mips.options (ODK_REGINFO) and
774 // .reginfo.
775 MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);
776 MEF.EmitMipsOptionRecords();
Rafael Espindola972e71a2014-01-31 23:10:26 +0000777
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000778 emitMipsAbiFlags();
Rafael Espindola972e71a2014-01-31 23:10:26 +0000779}
780
Rafael Espindola95fb9b92015-06-02 20:38:46 +0000781void MipsTargetELFStreamer::emitAssignment(MCSymbol *S, const MCExpr *Value) {
782 auto *Symbol = cast<MCSymbolELF>(S);
Zoran Jovanovic28221d82014-03-20 09:44:49 +0000783 // If on rhs is micromips symbol then mark Symbol as microMips.
784 if (Value->getKind() != MCExpr::SymbolRef)
785 return;
Rafael Espindola95fb9b92015-06-02 20:38:46 +0000786 const auto &RhsSym = cast<MCSymbolELF>(
787 static_cast<const MCSymbolRefExpr *>(Value)->getSymbol());
Toma Tabacu2cc44f52015-04-16 13:37:32 +0000788
Rafael Espindola8c006ee2015-06-04 05:59:23 +0000789 if (!(RhsSym.getOther() & ELF::STO_MIPS_MICROMIPS))
Zoran Jovanovic28221d82014-03-20 09:44:49 +0000790 return;
791
Rafael Espindola8c006ee2015-06-04 05:59:23 +0000792 Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
Zoran Jovanovic28221d82014-03-20 09:44:49 +0000793}
794
Jack Carter86ac5c12013-11-18 23:55:27 +0000795MCELFStreamer &MipsTargetELFStreamer::getStreamer() {
Rafael Espindola24ea09e2014-01-26 06:06:37 +0000796 return static_cast<MCELFStreamer &>(Streamer);
Jack Carter86ac5c12013-11-18 23:55:27 +0000797}
798
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000799void MipsTargetELFStreamer::emitDirectiveSetMicroMips() {
800 MicroMipsEnabled = true;
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000801
802 MCAssembler &MCA = getStreamer().getAssembler();
803 unsigned Flags = MCA.getELFHeaderEFlags();
804 Flags |= ELF::EF_MIPS_MICROMIPS;
805 MCA.setELFHeaderEFlags(Flags);
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000806 forbidModuleDirective();
Jack Carter86ac5c12013-11-18 23:55:27 +0000807}
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000808
809void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() {
810 MicroMipsEnabled = false;
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000811 forbidModuleDirective();
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000812}
813
Rafael Espindola6633d572014-01-14 18:57:12 +0000814void MipsTargetELFStreamer::emitDirectiveSetMips16() {
Rafael Espindolae7583752014-01-24 16:13:20 +0000815 MCAssembler &MCA = getStreamer().getAssembler();
816 unsigned Flags = MCA.getELFHeaderEFlags();
817 Flags |= ELF::EF_MIPS_ARCH_ASE_M16;
818 MCA.setELFHeaderEFlags(Flags);
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000819 forbidModuleDirective();
Rafael Espindola6633d572014-01-14 18:57:12 +0000820}
821
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000822void MipsTargetELFStreamer::emitDirectiveSetNoReorder() {
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000823 MCAssembler &MCA = getStreamer().getAssembler();
824 unsigned Flags = MCA.getELFHeaderEFlags();
825 Flags |= ELF::EF_MIPS_NOREORDER;
826 MCA.setELFHeaderEFlags(Flags);
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000827 forbidModuleDirective();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000828}
829
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000830void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {
Daniel Sandersd97a6342014-08-13 10:07:34 +0000831 MCAssembler &MCA = getStreamer().getAssembler();
832 MCContext &Context = MCA.getContext();
833 MCStreamer &OS = getStreamer();
834
Scott Egerton219fae92016-02-17 11:15:16 +0000835 MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0);
Daniel Sandersd97a6342014-08-13 10:07:34 +0000836
Daniel Sanders2b561332015-11-23 16:08:03 +0000837 MCSymbol *Sym = Context.getOrCreateSymbol(Name);
Daniel Sandersd97a6342014-08-13 10:07:34 +0000838 const MCSymbolRefExpr *ExprRef =
Daniel Sanders2b561332015-11-23 16:08:03 +0000839 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Context);
Daniel Sandersd97a6342014-08-13 10:07:34 +0000840
Rafael Espindolabb9a71c2015-05-26 15:07:25 +0000841 MCA.registerSection(*Sec);
Rafael Espindola967d6a62015-05-21 21:02:35 +0000842 Sec->setAlignment(4);
Daniel Sandersd97a6342014-08-13 10:07:34 +0000843
844 OS.PushSection();
845
846 OS.SwitchSection(Sec);
847
848 OS.EmitValueImpl(ExprRef, 4);
849
850 OS.EmitIntValue(GPRInfoSet ? GPRBitMask : 0, 4); // reg_mask
851 OS.EmitIntValue(GPRInfoSet ? GPROffset : 0, 4); // reg_offset
852
853 OS.EmitIntValue(FPRInfoSet ? FPRBitMask : 0, 4); // fpreg_mask
854 OS.EmitIntValue(FPRInfoSet ? FPROffset : 0, 4); // fpreg_offset
855
856 OS.EmitIntValue(FrameInfoSet ? FrameOffset : 0, 4); // frame_offset
857 OS.EmitIntValue(FrameInfoSet ? FrameReg : 0, 4); // frame_reg
858 OS.EmitIntValue(FrameInfoSet ? ReturnReg : 0, 4); // return_reg
859
860 // The .end directive marks the end of a procedure. Invalidate
861 // the information gathered up until this point.
862 GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
863
864 OS.PopSection();
Daniel Sanders2b561332015-11-23 16:08:03 +0000865
866 // .end also implicitly sets the size.
867 MCSymbol *CurPCSym = Context.createTempSymbol();
868 OS.EmitLabel(CurPCSym);
869 const MCExpr *Size = MCBinaryExpr::createSub(
870 MCSymbolRefExpr::create(CurPCSym, MCSymbolRefExpr::VK_None, Context),
871 ExprRef, Context);
872 int64_t AbsSize;
873 if (!Size->evaluateAsAbsolute(AbsSize, MCA))
874 llvm_unreachable("Function size must be evaluatable as absolute");
875 Size = MCConstantExpr::create(AbsSize, Context);
876 static_cast<MCSymbolELF *>(Sym)->setSize(Size);
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000877}
878
Rafael Espindola6633d572014-01-14 18:57:12 +0000879void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {
Daniel Sandersd97a6342014-08-13 10:07:34 +0000880 GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
Daniel Sanders2b561332015-11-23 16:08:03 +0000881
882 // .ent also acts like an implicit '.type symbol, STT_FUNC'
883 static_cast<const MCSymbolELF &>(Symbol).setType(ELF::STT_FUNC);
Rafael Espindola6633d572014-01-14 18:57:12 +0000884}
885
Jack Carter0cd3c192014-01-06 23:27:31 +0000886void MipsTargetELFStreamer::emitDirectiveAbiCalls() {
887 MCAssembler &MCA = getStreamer().getAssembler();
888 unsigned Flags = MCA.getELFHeaderEFlags();
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000889 Flags |= ELF::EF_MIPS_CPIC | ELF::EF_MIPS_PIC;
Jack Carter0cd3c192014-01-06 23:27:31 +0000890 MCA.setELFHeaderEFlags(Flags);
891}
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000892
893void MipsTargetELFStreamer::emitDirectiveNaN2008() {
894 MCAssembler &MCA = getStreamer().getAssembler();
895 unsigned Flags = MCA.getELFHeaderEFlags();
896 Flags |= ELF::EF_MIPS_NAN2008;
897 MCA.setELFHeaderEFlags(Flags);
898}
899
900void MipsTargetELFStreamer::emitDirectiveNaNLegacy() {
901 MCAssembler &MCA = getStreamer().getAssembler();
902 unsigned Flags = MCA.getELFHeaderEFlags();
903 Flags &= ~ELF::EF_MIPS_NAN2008;
904 MCA.setELFHeaderEFlags(Flags);
905}
906
Jack Carter0cd3c192014-01-06 23:27:31 +0000907void MipsTargetELFStreamer::emitDirectiveOptionPic0() {
908 MCAssembler &MCA = getStreamer().getAssembler();
909 unsigned Flags = MCA.getELFHeaderEFlags();
Matheus Almeidaf79b2812014-03-26 13:40:29 +0000910 // This option overrides other PIC options like -KPIC.
911 Pic = false;
Jack Carter0cd3c192014-01-06 23:27:31 +0000912 Flags &= ~ELF::EF_MIPS_PIC;
913 MCA.setELFHeaderEFlags(Flags);
914}
Rafael Espindola054234f2014-01-27 03:53:56 +0000915
Matheus Almeidaf79b2812014-03-26 13:40:29 +0000916void MipsTargetELFStreamer::emitDirectiveOptionPic2() {
917 MCAssembler &MCA = getStreamer().getAssembler();
918 unsigned Flags = MCA.getELFHeaderEFlags();
919 Pic = true;
920 // NOTE: We are following the GAS behaviour here which means the directive
921 // 'pic2' also sets the CPIC bit in the ELF header. This is different from
922 // what is stated in the SYSV ABI which consider the bits EF_MIPS_PIC and
923 // EF_MIPS_CPIC to be mutually exclusive.
924 Flags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;
925 MCA.setELFHeaderEFlags(Flags);
926}
927
Toma Tabacu9ca50962015-04-16 09:53:47 +0000928void MipsTargetELFStreamer::emitDirectiveInsn() {
929 MipsTargetStreamer::emitDirectiveInsn();
930 MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);
931 MEF.createPendingLabelRelocs();
932}
933
Rafael Espindola054234f2014-01-27 03:53:56 +0000934void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
Daniel Sandersd97a6342014-08-13 10:07:34 +0000935 unsigned ReturnReg_) {
936 MCContext &Context = getStreamer().getAssembler().getContext();
937 const MCRegisterInfo *RegInfo = Context.getRegisterInfo();
938
939 FrameInfoSet = true;
940 FrameReg = RegInfo->getEncodingValue(StackReg);
941 FrameOffset = StackSize;
942 ReturnReg = RegInfo->getEncodingValue(ReturnReg_);
Rafael Espindola054234f2014-01-27 03:53:56 +0000943}
Rafael Espindola25fa2912014-01-27 04:33:11 +0000944
945void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask,
946 int CPUTopSavedRegOff) {
Daniel Sandersd97a6342014-08-13 10:07:34 +0000947 GPRInfoSet = true;
948 GPRBitMask = CPUBitmask;
949 GPROffset = CPUTopSavedRegOff;
Rafael Espindola25fa2912014-01-27 04:33:11 +0000950}
951
952void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask,
953 int FPUTopSavedRegOff) {
Daniel Sandersd97a6342014-08-13 10:07:34 +0000954 FPRInfoSet = true;
955 FPRBitMask = FPUBitmask;
956 FPROffset = FPUTopSavedRegOff;
Rafael Espindola25fa2912014-01-27 04:33:11 +0000957}
Vladimir Medic615b26e2014-03-04 09:54:09 +0000958
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000959void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000960 // .cpload $reg
961 // This directive expands to:
962 // lui $gp, %hi(_gp_disp)
963 // addui $gp, $gp, %lo(_gp_disp)
964 // addu $gp, $gp, $reg
965 // when support for position independent code is enabled.
Eric Christophera5762812015-01-26 17:33:46 +0000966 if (!Pic || (getABI().IsN32() || getABI().IsN64()))
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000967 return;
968
969 // There's a GNU extension controlled by -mno-shared that allows
970 // locally-binding symbols to be accessed using absolute addresses.
971 // This is currently not supported. When supported -mno-shared makes
972 // .cpload expand to:
973 // lui $gp, %hi(__gnu_local_gp)
974 // addiu $gp, $gp, %lo(__gnu_local_gp)
975
976 StringRef SymName("_gp_disp");
977 MCAssembler &MCA = getStreamer().getAssembler();
Jim Grosbach6f482002015-05-18 18:43:14 +0000978 MCSymbol *GP_Disp = MCA.getContext().getOrCreateSymbol(SymName);
Rafael Espindolab5d316b2015-05-29 20:21:02 +0000979 MCA.registerSymbol(*GP_Disp);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000980
981 MCInst TmpInst;
982 TmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +0000983 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
Jim Grosbach13760bd2015-05-30 01:25:56 +0000984 const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::create(
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000985 "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +0000986 TmpInst.addOperand(MCOperand::createExpr(HiSym));
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000987 getStreamer().EmitInstruction(TmpInst, STI);
988
989 TmpInst.clear();
990
991 TmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +0000992 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
993 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
Jim Grosbach13760bd2015-05-30 01:25:56 +0000994 const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::create(
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000995 "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +0000996 TmpInst.addOperand(MCOperand::createExpr(LoSym));
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000997 getStreamer().EmitInstruction(TmpInst, STI);
998
999 TmpInst.clear();
1000
1001 TmpInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001002 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1003 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1004 TmpInst.addOperand(MCOperand::createReg(RegNo));
Matheus Almeida525bc4f2014-04-30 11:28:42 +00001005 getStreamer().EmitInstruction(TmpInst, STI);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001006
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00001007 forbidModuleDirective();
Matheus Almeida525bc4f2014-04-30 11:28:42 +00001008}
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001009
Daniel Sanders7225cd52016-04-29 16:16:49 +00001010void MipsTargetELFStreamer::emitDirectiveCpRestore(int Offset, unsigned ATReg,
1011 SMLoc IDLoc,
1012 const MCSubtargetInfo *STI) {
1013 MipsTargetStreamer::emitDirectiveCpRestore(Offset, ATReg, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001014 // .cprestore offset
1015 // When PIC mode is enabled and the O32 ABI is used, this directive expands
1016 // to:
1017 // sw $gp, offset($sp)
1018 // and adds a corresponding LW after every JAL.
1019
1020 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
1021 // is used in non-PIC mode.
1022 if (!Pic || (getABI().IsN32() || getABI().IsN64()))
1023 return;
1024
Daniel Sanders7225cd52016-04-29 16:16:49 +00001025 // Store the $gp on the stack.
1026 emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, ATReg, IDLoc,
1027 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001028}
1029
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001030void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
1031 int RegOrOffset,
1032 const MCSymbol &Sym,
1033 bool IsReg) {
1034 // Only N32 and N64 emit anything for .cpsetup iff PIC is set.
Eric Christophera5762812015-01-26 17:33:46 +00001035 if (!Pic || !(getABI().IsN32() || getABI().IsN64()))
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001036 return;
1037
1038 MCAssembler &MCA = getStreamer().getAssembler();
1039 MCInst Inst;
1040
1041 // Either store the old $gp in a register or on the stack
1042 if (IsReg) {
1043 // move $save, $gpreg
Vasileios Kalintiris1c78ca62015-08-11 08:56:25 +00001044 Inst.setOpcode(Mips::OR64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001045 Inst.addOperand(MCOperand::createReg(RegOrOffset));
1046 Inst.addOperand(MCOperand::createReg(Mips::GP));
1047 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001048 } else {
1049 // sd $gpreg, offset($sp)
1050 Inst.setOpcode(Mips::SD);
Jim Grosbache9119e42015-05-13 18:37:00 +00001051 Inst.addOperand(MCOperand::createReg(Mips::GP));
1052 Inst.addOperand(MCOperand::createReg(Mips::SP));
1053 Inst.addOperand(MCOperand::createImm(RegOrOffset));
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001054 }
1055 getStreamer().EmitInstruction(Inst, STI);
1056 Inst.clear();
1057
Jim Grosbach13760bd2015-05-30 01:25:56 +00001058 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
Toma Tabacu8874eac2015-02-18 13:46:53 +00001059 &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext());
Jim Grosbach13760bd2015-05-30 01:25:56 +00001060 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
Toma Tabacu8874eac2015-02-18 13:46:53 +00001061 &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext());
1062
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001063 // lui $gp, %hi(%neg(%gp_rel(funcSym)))
1064 Inst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001065 Inst.addOperand(MCOperand::createReg(Mips::GP));
1066 Inst.addOperand(MCOperand::createExpr(HiExpr));
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001067 getStreamer().EmitInstruction(Inst, STI);
1068 Inst.clear();
1069
1070 // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
1071 Inst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001072 Inst.addOperand(MCOperand::createReg(Mips::GP));
1073 Inst.addOperand(MCOperand::createReg(Mips::GP));
1074 Inst.addOperand(MCOperand::createExpr(LoExpr));
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001075 getStreamer().EmitInstruction(Inst, STI);
1076 Inst.clear();
1077
1078 // daddu $gp, $gp, $funcreg
1079 Inst.setOpcode(Mips::DADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001080 Inst.addOperand(MCOperand::createReg(Mips::GP));
1081 Inst.addOperand(MCOperand::createReg(Mips::GP));
1082 Inst.addOperand(MCOperand::createReg(RegNo));
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001083 getStreamer().EmitInstruction(Inst, STI);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001084
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00001085 forbidModuleDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001086}
1087
Daniel Sandersf173dda2015-09-22 10:50:09 +00001088void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
1089 bool SaveLocationIsRegister) {
1090 // Only N32 and N64 emit anything for .cpreturn iff PIC is set.
1091 if (!Pic || !(getABI().IsN32() || getABI().IsN64()))
1092 return;
1093
1094 MCInst Inst;
1095 // Either restore the old $gp from a register or on the stack
1096 if (SaveLocationIsRegister) {
1097 Inst.setOpcode(Mips::OR);
1098 Inst.addOperand(MCOperand::createReg(Mips::GP));
1099 Inst.addOperand(MCOperand::createReg(SaveLocation));
1100 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
1101 } else {
1102 Inst.setOpcode(Mips::LD);
1103 Inst.addOperand(MCOperand::createReg(Mips::GP));
1104 Inst.addOperand(MCOperand::createReg(Mips::SP));
1105 Inst.addOperand(MCOperand::createImm(SaveLocation));
1106 }
1107 getStreamer().EmitInstruction(Inst, STI);
1108
1109 forbidModuleDirective();
1110}
1111
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001112void MipsTargetELFStreamer::emitMipsAbiFlags() {
1113 MCAssembler &MCA = getStreamer().getAssembler();
1114 MCContext &Context = MCA.getContext();
1115 MCStreamer &OS = getStreamer();
Rafael Espindola0709a7b2015-05-21 19:20:38 +00001116 MCSectionELF *Sec = Context.getELFSection(
Rafael Espindolaba31e272015-01-29 17:33:21 +00001117 ".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24, "");
Rafael Espindolabb9a71c2015-05-26 15:07:25 +00001118 MCA.registerSection(*Sec);
Rafael Espindola967d6a62015-05-21 21:02:35 +00001119 Sec->setAlignment(8);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001120 OS.SwitchSection(Sec);
1121
Daniel Sandersc7dbc632014-07-08 10:11:38 +00001122 OS << ABIFlagsSection;
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001123}