blob: 96c6f08908e616b5946ba4d225c55c915bb12a08 [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"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000016#include "MCTargetDesc/MipsABIInfo.h"
Daniel Sanders68c37472014-07-21 13:30:55 +000017#include "MipsELFStreamer.h"
Daniel Sandersfe98b2f2016-05-03 13:35:44 +000018#include "MipsMCExpr.h"
Chandler Carruth442f7842014-03-04 10:07:28 +000019#include "MipsMCTargetDesc.h"
Rafael Espindola972e71a2014-01-31 23:10:26 +000020#include "MipsTargetObjectFile.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000021#include "llvm/BinaryFormat/ELF.h"
Rafael Espindola972e71a2014-01-31 23:10:26 +000022#include "llvm/MC/MCContext.h"
Rafael Espindola972e71a2014-01-31 23:10:26 +000023#include "llvm/MC/MCSectionELF.h"
Rafael Espindolacb1953f2014-01-26 06:57:13 +000024#include "llvm/MC/MCSubtargetInfo.h"
Rafael Espindola95fb9b92015-06-02 20:38:46 +000025#include "llvm/MC/MCSymbolELF.h"
Daniel Sandersc07f06a2016-05-04 13:21:06 +000026#include "llvm/Support/CommandLine.h"
Jack Carter86ac5c12013-11-18 23:55:27 +000027#include "llvm/Support/ErrorHandling.h"
28#include "llvm/Support/FormattedStream.h"
29
30using namespace llvm;
31
Daniel Sandersc07f06a2016-05-04 13:21:06 +000032namespace {
33static cl::opt<bool> RoundSectionSizes(
34 "mips-round-section-sizes", cl::init(false),
35 cl::desc("Round section sizes up to the section alignment"), cl::Hidden);
36} // end anonymous namespace
37
Vladimir Medicfb8a2a92014-07-08 08:59:22 +000038MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000039 : MCTargetStreamer(S), ModuleDirectiveAllowed(true) {
Daniel Sandersd97a6342014-08-13 10:07:34 +000040 GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
41}
Rafael Espindola60890b82014-06-23 19:43:40 +000042void MipsTargetStreamer::emitDirectiveSetMicroMips() {}
43void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {}
Daniel Sanderscda908a2016-05-16 09:10:13 +000044void MipsTargetStreamer::setUsesMicroMips() {}
Rafael Espindola60890b82014-06-23 19:43:40 +000045void MipsTargetStreamer::emitDirectiveSetMips16() {}
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000046void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); }
47void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); }
Rafael Espindola60890b82014-06-23 19:43:40 +000048void MipsTargetStreamer::emitDirectiveSetNoReorder() {}
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000049void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); }
50void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); }
51void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); }
52void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); }
Simon Dardis805f1e02017-07-11 21:28:36 +000053void MipsTargetStreamer::emitDirectiveSetMt() {}
54void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); }
Petar Jovanovic3408caf2018-03-14 14:13:31 +000055void MipsTargetStreamer::emitDirectiveSetCRC() {}
56void MipsTargetStreamer::emitDirectiveSetNoCRC() {}
Petar Jovanovicd4349f32018-04-27 09:12:08 +000057void MipsTargetStreamer::emitDirectiveSetVirt() {}
58void MipsTargetStreamer::emitDirectiveSetNoVirt() {}
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000059void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); }
Toma Tabacu16a74492015-02-13 10:30:57 +000060void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
61 forbidModuleDirective();
62}
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000063void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); }
Rafael Espindola60890b82014-06-23 19:43:40 +000064void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {}
65void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {}
66void MipsTargetStreamer::emitDirectiveAbiCalls() {}
67void MipsTargetStreamer::emitDirectiveNaN2008() {}
68void MipsTargetStreamer::emitDirectiveNaNLegacy() {}
69void MipsTargetStreamer::emitDirectiveOptionPic0() {}
70void MipsTargetStreamer::emitDirectiveOptionPic2() {}
Toma Tabacu9ca50962015-04-16 09:53:47 +000071void MipsTargetStreamer::emitDirectiveInsn() { forbidModuleDirective(); }
Rafael Espindola60890b82014-06-23 19:43:40 +000072void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
73 unsigned ReturnReg) {}
74void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {}
75void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) {
76}
Toma Tabacu85618b32014-08-19 14:22:52 +000077void MipsTargetStreamer::emitDirectiveSetArch(StringRef Arch) {
78 forbidModuleDirective();
79}
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +000080void MipsTargetStreamer::emitDirectiveSetMips0() { forbidModuleDirective(); }
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000081void MipsTargetStreamer::emitDirectiveSetMips1() { forbidModuleDirective(); }
82void MipsTargetStreamer::emitDirectiveSetMips2() { forbidModuleDirective(); }
83void MipsTargetStreamer::emitDirectiveSetMips3() { forbidModuleDirective(); }
84void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); }
85void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); }
86void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); }
87void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); }
Daniel Sanders17793142015-02-18 16:24:50 +000088void MipsTargetStreamer::emitDirectiveSetMips32R3() { forbidModuleDirective(); }
89void MipsTargetStreamer::emitDirectiveSetMips32R5() { forbidModuleDirective(); }
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000090void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); }
91void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); }
92void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); }
Daniel Sanders17793142015-02-18 16:24:50 +000093void MipsTargetStreamer::emitDirectiveSetMips64R3() { forbidModuleDirective(); }
94void MipsTargetStreamer::emitDirectiveSetMips64R5() { forbidModuleDirective(); }
Daniel Sanderscdb45fa2014-08-14 09:18:14 +000095void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); }
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +000096void MipsTargetStreamer::emitDirectiveSetPop() { forbidModuleDirective(); }
97void MipsTargetStreamer::emitDirectiveSetPush() { forbidModuleDirective(); }
Toma Tabacu29696502015-06-02 09:48:04 +000098void MipsTargetStreamer::emitDirectiveSetSoftFloat() {
99 forbidModuleDirective();
100}
101void MipsTargetStreamer::emitDirectiveSetHardFloat() {
102 forbidModuleDirective();
103}
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000104void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }
Petar Jovanovic65f10242017-10-05 17:40:32 +0000105void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); }
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000106void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000107void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
Daniel Sandersdf8510d2016-05-11 12:48:19 +0000108bool MipsTargetStreamer::emitDirectiveCpRestore(
Benjamin Kramerd3f4c052016-06-12 16:13:55 +0000109 int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
Daniel Sandersdf8510d2016-05-11 12:48:19 +0000110 const MCSubtargetInfo *STI) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000111 forbidModuleDirective();
Daniel Sandersdf8510d2016-05-11 12:48:19 +0000112 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000113}
Rafael Espindola60890b82014-06-23 19:43:40 +0000114void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
115 const MCSymbol &Sym, bool IsReg) {
116}
Daniel Sandersf173dda2015-09-22 10:50:09 +0000117void MipsTargetStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
118 bool SaveLocationIsRegister) {}
Toma Tabacubfcbfd52015-06-23 12:34:19 +0000119
Toma Tabacua64e5402015-06-25 12:44:38 +0000120void MipsTargetStreamer::emitDirectiveModuleFP() {}
Toma Tabacubfcbfd52015-06-23 12:34:19 +0000121
Toma Tabacu3c499582015-06-25 10:56:57 +0000122void MipsTargetStreamer::emitDirectiveModuleOddSPReg() {
123 if (!ABIFlagsSection.OddSPReg && !ABIFlagsSection.Is32BitABI)
Daniel Sanders7e527422014-07-10 13:38:23 +0000124 report_fatal_error("+nooddspreg is only valid for O32");
125}
Toma Tabacu0f093132015-06-30 13:46:03 +0000126void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {}
127void MipsTargetStreamer::emitDirectiveModuleHardFloat() {}
Simon Dardis805f1e02017-07-11 21:28:36 +0000128void MipsTargetStreamer::emitDirectiveModuleMT() {}
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000129void MipsTargetStreamer::emitDirectiveModuleCRC() {}
130void MipsTargetStreamer::emitDirectiveModuleNoCRC() {}
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000131void MipsTargetStreamer::emitDirectiveModuleVirt() {}
132void MipsTargetStreamer::emitDirectiveModuleNoVirt() {}
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000133void MipsTargetStreamer::emitDirectiveSetFp(
134 MipsABIFlagsSection::FpABIKind Value) {
135 forbidModuleDirective();
136}
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000137void MipsTargetStreamer::emitDirectiveSetOddSPReg() { forbidModuleDirective(); }
138void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() {
139 forbidModuleDirective();
140}
Rafael Espindola24ea09e2014-01-26 06:06:37 +0000141
Daniel Sandersa736b372016-04-29 13:33:12 +0000142void MipsTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
143 const MCSubtargetInfo *STI) {
144 MCInst TmpInst;
145 TmpInst.setOpcode(Opcode);
146 TmpInst.addOperand(MCOperand::createReg(Reg0));
147 TmpInst.setLoc(IDLoc);
148 getStreamer().EmitInstruction(TmpInst, *STI);
149}
150
151void MipsTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1,
152 SMLoc IDLoc, const MCSubtargetInfo *STI) {
153 MCInst TmpInst;
154 TmpInst.setOpcode(Opcode);
155 TmpInst.addOperand(MCOperand::createReg(Reg0));
156 TmpInst.addOperand(Op1);
157 TmpInst.setLoc(IDLoc);
158 getStreamer().EmitInstruction(TmpInst, *STI);
159}
160
161void MipsTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm,
162 SMLoc IDLoc, const MCSubtargetInfo *STI) {
163 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI);
164}
165
166void MipsTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
167 SMLoc IDLoc, const MCSubtargetInfo *STI) {
168 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI);
169}
170
171void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2,
172 SMLoc IDLoc, const MCSubtargetInfo *STI) {
173 MCInst TmpInst;
174 TmpInst.setOpcode(Opcode);
175 TmpInst.addOperand(MCOperand::createImm(Imm1));
176 TmpInst.addOperand(MCOperand::createImm(Imm2));
177 TmpInst.setLoc(IDLoc);
178 getStreamer().EmitInstruction(TmpInst, *STI);
179}
180
181void MipsTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,
182 MCOperand Op2, SMLoc IDLoc,
183 const MCSubtargetInfo *STI) {
184 MCInst TmpInst;
185 TmpInst.setOpcode(Opcode);
186 TmpInst.addOperand(MCOperand::createReg(Reg0));
187 TmpInst.addOperand(MCOperand::createReg(Reg1));
188 TmpInst.addOperand(Op2);
189 TmpInst.setLoc(IDLoc);
190 getStreamer().EmitInstruction(TmpInst, *STI);
191}
192
193void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
194 unsigned Reg2, SMLoc IDLoc,
195 const MCSubtargetInfo *STI) {
196 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI);
197}
198
199void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,
200 int16_t Imm, SMLoc IDLoc,
201 const MCSubtargetInfo *STI) {
202 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI);
203}
204
Simon Dardisde5ed0c2017-11-14 22:26:42 +0000205void MipsTargetStreamer::emitRRIII(unsigned Opcode, unsigned Reg0,
206 unsigned Reg1, int16_t Imm0, int16_t Imm1,
207 int16_t Imm2, SMLoc IDLoc,
208 const MCSubtargetInfo *STI) {
209 MCInst TmpInst;
210 TmpInst.setOpcode(Opcode);
211 TmpInst.addOperand(MCOperand::createReg(Reg0));
212 TmpInst.addOperand(MCOperand::createReg(Reg1));
213 TmpInst.addOperand(MCOperand::createImm(Imm0));
214 TmpInst.addOperand(MCOperand::createImm(Imm1));
215 TmpInst.addOperand(MCOperand::createImm(Imm2));
216 TmpInst.setLoc(IDLoc);
217 getStreamer().EmitInstruction(TmpInst, *STI);
218}
219
Daniel Sandersa736b372016-04-29 13:33:12 +0000220void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg,
221 unsigned TrgReg, bool Is64Bit,
222 const MCSubtargetInfo *STI) {
223 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
224 STI);
225}
226
227void MipsTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg,
228 int16_t ShiftAmount, SMLoc IDLoc,
229 const MCSubtargetInfo *STI) {
230 if (ShiftAmount >= 32) {
231 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI);
232 return;
233 }
234
235 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI);
236}
237
238void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
239 const MCSubtargetInfo *STI) {
240 if (hasShortDelaySlot)
241 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI);
242 else
243 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
244}
245
246void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {
247 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
248}
249
Daniel Sanders7225cd52016-04-29 16:16:49 +0000250/// Emit the $gp restore operation for .cprestore.
251void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,
252 const MCSubtargetInfo *STI) {
253 emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc,
254 STI);
255}
256
257/// Emit a store instruction with an immediate offset.
Daniel Sandersfba875f2016-04-29 13:43:45 +0000258void MipsTargetStreamer::emitStoreWithImmOffset(
259 unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset,
Benjamin Kramerd3f4c052016-06-12 16:13:55 +0000260 function_ref<unsigned()> GetATReg, SMLoc IDLoc,
Daniel Sanders241c6792016-05-12 14:01:50 +0000261 const MCSubtargetInfo *STI) {
Daniel Sanders7225cd52016-04-29 16:16:49 +0000262 if (isInt<16>(Offset)) {
263 emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI);
264 return;
265 }
266
Daniel Sandersfba875f2016-04-29 13:43:45 +0000267 // sw $8, offset($8) => lui $at, %hi(offset)
268 // add $at, $at, $8
269 // sw $8, %lo(offset)($at)
270
Daniel Sanders241c6792016-05-12 14:01:50 +0000271 unsigned ATReg = GetATReg();
272 if (!ATReg)
273 return;
274
Daniel Sandersfba875f2016-04-29 13:43:45 +0000275 unsigned LoOffset = Offset & 0x0000ffff;
276 unsigned HiOffset = (Offset & 0xffff0000) >> 16;
277
278 // If msb of LoOffset is 1(negative number) we must increment HiOffset
279 // to account for the sign-extension of the low part.
280 if (LoOffset & 0x8000)
281 HiOffset++;
282
283 // Generate the base address in ATReg.
284 emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI);
285 if (BaseReg != Mips::ZERO)
286 emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
287 // Emit the store with the adjusted base and offset.
288 emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI);
289}
290
291/// Emit a store instruction with an symbol offset. Symbols are assumed to be
292/// out of range for a simm16 will be expanded to appropriate instructions.
293void MipsTargetStreamer::emitStoreWithSymOffset(
294 unsigned Opcode, unsigned SrcReg, unsigned BaseReg, MCOperand &HiOperand,
295 MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
296 const MCSubtargetInfo *STI) {
297 // sw $8, sym => lui $at, %hi(sym)
298 // sw $8, %lo(sym)($at)
299
300 // Generate the base address in ATReg.
301 emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI);
302 if (BaseReg != Mips::ZERO)
303 emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
304 // Emit the store with the adjusted base and offset.
305 emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI);
306}
307
Daniel Sanders7225cd52016-04-29 16:16:49 +0000308/// Emit a load instruction with an immediate offset. DstReg and TmpReg are
309/// permitted to be the same register iff DstReg is distinct from BaseReg and
310/// DstReg is a GPR. It is the callers responsibility to identify such cases
311/// and pass the appropriate register in TmpReg.
Daniel Sandersfba875f2016-04-29 13:43:45 +0000312void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg,
313 unsigned BaseReg, int64_t Offset,
314 unsigned TmpReg, SMLoc IDLoc,
315 const MCSubtargetInfo *STI) {
Daniel Sanders7225cd52016-04-29 16:16:49 +0000316 if (isInt<16>(Offset)) {
317 emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI);
318 return;
319 }
320
Daniel Sandersfba875f2016-04-29 13:43:45 +0000321 // 1) lw $8, offset($9) => lui $8, %hi(offset)
322 // add $8, $8, $9
323 // lw $8, %lo(offset)($9)
324 // 2) lw $8, offset($8) => lui $at, %hi(offset)
325 // add $at, $at, $8
326 // lw $8, %lo(offset)($at)
327
328 unsigned LoOffset = Offset & 0x0000ffff;
329 unsigned HiOffset = (Offset & 0xffff0000) >> 16;
330
331 // If msb of LoOffset is 1(negative number) we must increment HiOffset
332 // to account for the sign-extension of the low part.
333 if (LoOffset & 0x8000)
334 HiOffset++;
335
336 // Generate the base address in TmpReg.
337 emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI);
338 if (BaseReg != Mips::ZERO)
339 emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
340 // Emit the load with the adjusted base and offset.
341 emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI);
342}
343
344/// Emit a load instruction with an symbol offset. Symbols are assumed to be
345/// out of range for a simm16 will be expanded to appropriate instructions.
346/// DstReg and TmpReg are permitted to be the same register iff DstReg is a
347/// GPR. It is the callers responsibility to identify such cases and pass the
348/// appropriate register in TmpReg.
349void MipsTargetStreamer::emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg,
350 unsigned BaseReg,
351 MCOperand &HiOperand,
352 MCOperand &LoOperand,
353 unsigned TmpReg, SMLoc IDLoc,
354 const MCSubtargetInfo *STI) {
355 // 1) lw $8, sym => lui $8, %hi(sym)
356 // lw $8, %lo(sym)($8)
357 // 2) ldc1 $f0, sym => lui $at, %hi(sym)
358 // ldc1 $f0, %lo(sym)($at)
359
360 // Generate the base address in TmpReg.
361 emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
362 if (BaseReg != Mips::ZERO)
363 emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
364 // Emit the load with the adjusted base and offset.
365 emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI);
366}
367
Rafael Espindola24ea09e2014-01-26 06:06:37 +0000368MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,
369 formatted_raw_ostream &OS)
370 : MipsTargetStreamer(S), OS(OS) {}
Jack Carter6ef6cc52013-11-19 20:53:28 +0000371
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000372void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() {
373 OS << "\t.set\tmicromips\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000374 forbidModuleDirective();
Jack Carter6ef6cc52013-11-19 20:53:28 +0000375}
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000376
377void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() {
378 OS << "\t.set\tnomicromips\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000379 forbidModuleDirective();
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000380}
381
Rafael Espindola6633d572014-01-14 18:57:12 +0000382void MipsTargetAsmStreamer::emitDirectiveSetMips16() {
383 OS << "\t.set\tmips16\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000384 forbidModuleDirective();
Rafael Espindola6633d572014-01-14 18:57:12 +0000385}
386
387void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() {
388 OS << "\t.set\tnomips16\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000389 MipsTargetStreamer::emitDirectiveSetNoMips16();
Rafael Espindola6633d572014-01-14 18:57:12 +0000390}
391
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000392void MipsTargetAsmStreamer::emitDirectiveSetReorder() {
393 OS << "\t.set\treorder\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000394 MipsTargetStreamer::emitDirectiveSetReorder();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000395}
396
397void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() {
398 OS << "\t.set\tnoreorder\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000399 forbidModuleDirective();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000400}
401
402void MipsTargetAsmStreamer::emitDirectiveSetMacro() {
403 OS << "\t.set\tmacro\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000404 MipsTargetStreamer::emitDirectiveSetMacro();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000405}
406
407void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() {
408 OS << "\t.set\tnomacro\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000409 MipsTargetStreamer::emitDirectiveSetNoMacro();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000410}
411
Daniel Sanders44934432014-08-07 12:03:36 +0000412void MipsTargetAsmStreamer::emitDirectiveSetMsa() {
413 OS << "\t.set\tmsa\n";
414 MipsTargetStreamer::emitDirectiveSetMsa();
415}
416
417void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() {
418 OS << "\t.set\tnomsa\n";
419 MipsTargetStreamer::emitDirectiveSetNoMsa();
420}
421
Simon Dardis805f1e02017-07-11 21:28:36 +0000422void MipsTargetAsmStreamer::emitDirectiveSetMt() {
423 OS << "\t.set\tmt\n";
424 MipsTargetStreamer::emitDirectiveSetMt();
425}
426
427void MipsTargetAsmStreamer::emitDirectiveSetNoMt() {
428 OS << "\t.set\tnomt\n";
429 MipsTargetStreamer::emitDirectiveSetNoMt();
430}
431
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000432void MipsTargetAsmStreamer::emitDirectiveSetCRC() {
433 OS << "\t.set\tcrc\n";
434 MipsTargetStreamer::emitDirectiveSetCRC();
435}
436
437void MipsTargetAsmStreamer::emitDirectiveSetNoCRC() {
438 OS << "\t.set\tnocrc\n";
439 MipsTargetStreamer::emitDirectiveSetNoCRC();
440}
441
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000442void MipsTargetAsmStreamer::emitDirectiveSetVirt() {
443 OS << "\t.set\tvirt\n";
444 MipsTargetStreamer::emitDirectiveSetVirt();
445}
446
447void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() {
448 OS << "\t.set\tnovirt\n";
449 MipsTargetStreamer::emitDirectiveSetNoVirt();
450}
451
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000452void MipsTargetAsmStreamer::emitDirectiveSetAt() {
453 OS << "\t.set\tat\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000454 MipsTargetStreamer::emitDirectiveSetAt();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000455}
456
Toma Tabacu16a74492015-02-13 10:30:57 +0000457void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
458 OS << "\t.set\tat=$" << Twine(RegNo) << "\n";
459 MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo);
460}
461
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000462void MipsTargetAsmStreamer::emitDirectiveSetNoAt() {
463 OS << "\t.set\tnoat\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000464 MipsTargetStreamer::emitDirectiveSetNoAt();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000465}
466
467void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) {
468 OS << "\t.end\t" << Name << '\n';
469}
470
Rafael Espindola6633d572014-01-14 18:57:12 +0000471void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {
472 OS << "\t.ent\t" << Symbol.getName() << '\n';
473}
474
Jack Carter0cd3c192014-01-06 23:27:31 +0000475void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; }
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000476
477void MipsTargetAsmStreamer::emitDirectiveNaN2008() { OS << "\t.nan\t2008\n"; }
478
479void MipsTargetAsmStreamer::emitDirectiveNaNLegacy() {
480 OS << "\t.nan\tlegacy\n";
481}
482
Jack Carter0cd3c192014-01-06 23:27:31 +0000483void MipsTargetAsmStreamer::emitDirectiveOptionPic0() {
484 OS << "\t.option\tpic0\n";
485}
486
Matheus Almeidaf79b2812014-03-26 13:40:29 +0000487void MipsTargetAsmStreamer::emitDirectiveOptionPic2() {
488 OS << "\t.option\tpic2\n";
489}
490
Toma Tabacu9ca50962015-04-16 09:53:47 +0000491void MipsTargetAsmStreamer::emitDirectiveInsn() {
492 MipsTargetStreamer::emitDirectiveInsn();
493 OS << "\t.insn\n";
494}
495
Rafael Espindola054234f2014-01-27 03:53:56 +0000496void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
497 unsigned ReturnReg) {
498 OS << "\t.frame\t$"
499 << StringRef(MipsInstPrinter::getRegisterName(StackReg)).lower() << ","
500 << StackSize << ",$"
Rafael Espindola25fa2912014-01-27 04:33:11 +0000501 << StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n';
502}
503
Toma Tabacu85618b32014-08-19 14:22:52 +0000504void MipsTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) {
505 OS << "\t.set arch=" << Arch << "\n";
506 MipsTargetStreamer::emitDirectiveSetArch(Arch);
507}
508
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000509void MipsTargetAsmStreamer::emitDirectiveSetMips0() {
510 OS << "\t.set\tmips0\n";
511 MipsTargetStreamer::emitDirectiveSetMips0();
512}
Toma Tabacu26647792014-09-09 12:52:14 +0000513
Daniel Sandersf0df2212014-08-04 12:20:00 +0000514void MipsTargetAsmStreamer::emitDirectiveSetMips1() {
515 OS << "\t.set\tmips1\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000516 MipsTargetStreamer::emitDirectiveSetMips1();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000517}
518
519void MipsTargetAsmStreamer::emitDirectiveSetMips2() {
520 OS << "\t.set\tmips2\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000521 MipsTargetStreamer::emitDirectiveSetMips2();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000522}
523
524void MipsTargetAsmStreamer::emitDirectiveSetMips3() {
525 OS << "\t.set\tmips3\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000526 MipsTargetStreamer::emitDirectiveSetMips3();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000527}
528
529void MipsTargetAsmStreamer::emitDirectiveSetMips4() {
530 OS << "\t.set\tmips4\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000531 MipsTargetStreamer::emitDirectiveSetMips4();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000532}
533
534void MipsTargetAsmStreamer::emitDirectiveSetMips5() {
535 OS << "\t.set\tmips5\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000536 MipsTargetStreamer::emitDirectiveSetMips5();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000537}
538
539void MipsTargetAsmStreamer::emitDirectiveSetMips32() {
540 OS << "\t.set\tmips32\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000541 MipsTargetStreamer::emitDirectiveSetMips32();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000542}
543
Vladimir Medic615b26e2014-03-04 09:54:09 +0000544void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() {
545 OS << "\t.set\tmips32r2\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000546 MipsTargetStreamer::emitDirectiveSetMips32R2();
Vladimir Medic615b26e2014-03-04 09:54:09 +0000547}
548
Daniel Sanders17793142015-02-18 16:24:50 +0000549void MipsTargetAsmStreamer::emitDirectiveSetMips32R3() {
550 OS << "\t.set\tmips32r3\n";
551 MipsTargetStreamer::emitDirectiveSetMips32R3();
552}
553
554void MipsTargetAsmStreamer::emitDirectiveSetMips32R5() {
555 OS << "\t.set\tmips32r5\n";
556 MipsTargetStreamer::emitDirectiveSetMips32R5();
557}
558
Daniel Sandersf0df2212014-08-04 12:20:00 +0000559void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() {
560 OS << "\t.set\tmips32r6\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000561 MipsTargetStreamer::emitDirectiveSetMips32R6();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000562}
563
Matheus Almeida3b9c63d2014-03-26 15:14:32 +0000564void MipsTargetAsmStreamer::emitDirectiveSetMips64() {
565 OS << "\t.set\tmips64\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000566 MipsTargetStreamer::emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +0000567}
568
Matheus Almeidaa2cd0092014-03-26 14:52:22 +0000569void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() {
570 OS << "\t.set\tmips64r2\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000571 MipsTargetStreamer::emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +0000572}
573
Daniel Sanders17793142015-02-18 16:24:50 +0000574void MipsTargetAsmStreamer::emitDirectiveSetMips64R3() {
575 OS << "\t.set\tmips64r3\n";
576 MipsTargetStreamer::emitDirectiveSetMips64R3();
577}
578
579void MipsTargetAsmStreamer::emitDirectiveSetMips64R5() {
580 OS << "\t.set\tmips64r5\n";
581 MipsTargetStreamer::emitDirectiveSetMips64R5();
582}
583
Daniel Sandersf0df2212014-08-04 12:20:00 +0000584void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() {
585 OS << "\t.set\tmips64r6\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000586 MipsTargetStreamer::emitDirectiveSetMips64R6();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000587}
588
Vladimir Medic27c398e2014-03-05 11:05:09 +0000589void MipsTargetAsmStreamer::emitDirectiveSetDsp() {
590 OS << "\t.set\tdsp\n";
Toma Tabacu88f05ce2014-08-13 12:48:12 +0000591 MipsTargetStreamer::emitDirectiveSetDsp();
Vladimir Medic27c398e2014-03-05 11:05:09 +0000592}
Toma Tabacu9db22db2014-09-09 10:15:38 +0000593
Petar Jovanovic65f10242017-10-05 17:40:32 +0000594void MipsTargetAsmStreamer::emitDirectiveSetDspr2() {
595 OS << "\t.set\tdspr2\n";
596 MipsTargetStreamer::emitDirectiveSetDspr2();
597}
598
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000599void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() {
600 OS << "\t.set\tnodsp\n";
601 MipsTargetStreamer::emitDirectiveSetNoDsp();
602}
603
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000604void MipsTargetAsmStreamer::emitDirectiveSetPop() {
605 OS << "\t.set\tpop\n";
606 MipsTargetStreamer::emitDirectiveSetPop();
607}
Toma Tabacu9db22db2014-09-09 10:15:38 +0000608
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000609void MipsTargetAsmStreamer::emitDirectiveSetPush() {
610 OS << "\t.set\tpush\n";
611 MipsTargetStreamer::emitDirectiveSetPush();
612}
Toma Tabacu9db22db2014-09-09 10:15:38 +0000613
Toma Tabacu29696502015-06-02 09:48:04 +0000614void MipsTargetAsmStreamer::emitDirectiveSetSoftFloat() {
615 OS << "\t.set\tsoftfloat\n";
616 MipsTargetStreamer::emitDirectiveSetSoftFloat();
617}
618
619void MipsTargetAsmStreamer::emitDirectiveSetHardFloat() {
620 OS << "\t.set\thardfloat\n";
621 MipsTargetStreamer::emitDirectiveSetHardFloat();
622}
623
Rafael Espindola25fa2912014-01-27 04:33:11 +0000624// Print a 32 bit hex number with all numbers.
625static void printHex32(unsigned Value, raw_ostream &OS) {
626 OS << "0x";
627 for (int i = 7; i >= 0; i--)
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000628 OS.write_hex((Value & (0xF << (i * 4))) >> (i * 4));
Rafael Espindola25fa2912014-01-27 04:33:11 +0000629}
630
631void MipsTargetAsmStreamer::emitMask(unsigned CPUBitmask,
632 int CPUTopSavedRegOff) {
633 OS << "\t.mask \t";
634 printHex32(CPUBitmask, OS);
635 OS << ',' << CPUTopSavedRegOff << '\n';
636}
637
638void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask,
639 int FPUTopSavedRegOff) {
640 OS << "\t.fmask\t";
641 printHex32(FPUBitmask, OS);
642 OS << "," << FPUTopSavedRegOff << '\n';
Rafael Espindola054234f2014-01-27 03:53:56 +0000643}
644
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000645void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000646 OS << "\t.cpload\t$"
647 << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000648 forbidModuleDirective();
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000649}
650
Daniel Sandersdf8510d2016-05-11 12:48:19 +0000651bool MipsTargetAsmStreamer::emitDirectiveCpRestore(
Benjamin Kramerd3f4c052016-06-12 16:13:55 +0000652 int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
Daniel Sandersdf8510d2016-05-11 12:48:19 +0000653 const MCSubtargetInfo *STI) {
654 MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000655 OS << "\t.cprestore\t" << Offset << "\n";
Daniel Sandersdf8510d2016-05-11 12:48:19 +0000656 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000657}
658
Matheus Almeidad92a3fa2014-05-01 10:24:46 +0000659void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
660 int RegOrOffset,
661 const MCSymbol &Sym,
662 bool IsReg) {
663 OS << "\t.cpsetup\t$"
664 << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << ", ";
665
666 if (IsReg)
667 OS << "$"
668 << StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower();
669 else
670 OS << RegOrOffset;
671
672 OS << ", ";
673
Daniel Sanders5d796282015-09-21 09:26:55 +0000674 OS << Sym.getName();
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000675 forbidModuleDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000676}
677
Daniel Sandersf173dda2015-09-22 10:50:09 +0000678void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
679 bool SaveLocationIsRegister) {
680 OS << "\t.cpreturn";
681 forbidModuleDirective();
682}
683
Toma Tabacua64e5402015-06-25 12:44:38 +0000684void MipsTargetAsmStreamer::emitDirectiveModuleFP() {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000685 OS << "\t.module\tfp=";
Toma Tabacua64e5402015-06-25 12:44:38 +0000686 OS << ABIFlagsSection.getFpABIString(ABIFlagsSection.getFpABI()) << "\n";
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000687}
688
Daniel Sanders7e527422014-07-10 13:38:23 +0000689void MipsTargetAsmStreamer::emitDirectiveSetFp(
690 MipsABIFlagsSection::FpABIKind Value) {
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000691 MipsTargetStreamer::emitDirectiveSetFp(Value);
692
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000693 OS << "\t.set\tfp=";
Daniel Sanders7e527422014-07-10 13:38:23 +0000694 OS << ABIFlagsSection.getFpABIString(Value) << "\n";
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000695}
696
Toma Tabacu3c499582015-06-25 10:56:57 +0000697void MipsTargetAsmStreamer::emitDirectiveModuleOddSPReg() {
698 MipsTargetStreamer::emitDirectiveModuleOddSPReg();
Daniel Sanders7e527422014-07-10 13:38:23 +0000699
Toma Tabacu3c499582015-06-25 10:56:57 +0000700 OS << "\t.module\t" << (ABIFlagsSection.OddSPReg ? "" : "no") << "oddspreg\n";
Daniel Sanders7e527422014-07-10 13:38:23 +0000701}
702
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000703void MipsTargetAsmStreamer::emitDirectiveSetOddSPReg() {
704 MipsTargetStreamer::emitDirectiveSetOddSPReg();
705 OS << "\t.set\toddspreg\n";
706}
707
708void MipsTargetAsmStreamer::emitDirectiveSetNoOddSPReg() {
709 MipsTargetStreamer::emitDirectiveSetNoOddSPReg();
710 OS << "\t.set\tnooddspreg\n";
711}
712
Toma Tabacu0f093132015-06-30 13:46:03 +0000713void MipsTargetAsmStreamer::emitDirectiveModuleSoftFloat() {
714 OS << "\t.module\tsoftfloat\n";
715}
716
717void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() {
718 OS << "\t.module\thardfloat\n";
719}
720
Simon Dardis805f1e02017-07-11 21:28:36 +0000721void MipsTargetAsmStreamer::emitDirectiveModuleMT() {
722 OS << "\t.module\tmt\n";
723}
724
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000725void MipsTargetAsmStreamer::emitDirectiveModuleCRC() {
726 OS << "\t.module\tcrc\n";
727}
728
729void MipsTargetAsmStreamer::emitDirectiveModuleNoCRC() {
730 OS << "\t.module\tnocrc\n";
731}
732
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000733void MipsTargetAsmStreamer::emitDirectiveModuleVirt() {
734 OS << "\t.module\tvirt\n";
735}
736
737void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() {
738 OS << "\t.module\tnovirt\n";
739}
740
Jack Carter0cd3c192014-01-06 23:27:31 +0000741// This part is for ELF object output.
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000742MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
743 const MCSubtargetInfo &STI)
Rafael Espindola972e71a2014-01-31 23:10:26 +0000744 : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) {
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000745 MCAssembler &MCA = getStreamer().getAssembler();
Daniel Sanders8de3d3c2016-05-06 14:37:24 +0000746
747 // It's possible that MCObjectFileInfo isn't fully initialized at this point
Matthias Braunbb8507e2017-10-12 22:57:28 +0000748 // due to an initialization order problem where LLVMTargetMachine creates the
Daniel Sanders8de3d3c2016-05-06 14:37:24 +0000749 // target streamer before TargetLoweringObjectFile calls
750 // InitializeMCObjectFileInfo. There doesn't seem to be a single place that
751 // covers all cases so this statement covers most cases and direct object
752 // emission must call setPic() once MCObjectFileInfo has been initialized. The
753 // cases we don't handle here are covered by MipsAsmPrinter.
Rafael Espindola699281c2016-05-18 11:58:50 +0000754 Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent();
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000755
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000756 const FeatureBitset &Features = STI.getFeatureBits();
Eric Christophera5762812015-01-26 17:33:46 +0000757
758 // Set the header flags that we can in the constructor.
759 // FIXME: This is a fairly terrible hack. We set the rest
760 // of these in the destructor. The problem here is two-fold:
761 //
762 // a: Some of the eflags can be set/reset by directives.
763 // b: There aren't any usage paths that initialize the ABI
764 // pointer until after we initialize either an assembler
765 // or the target machine.
766 // We can fix this by making the target streamer construct
767 // the ABI, but this is fraught with wide ranging dependency
768 // issues as well.
769 unsigned EFlags = MCA.getELFHeaderEFlags();
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000770
Simon Dardis6433d5a2017-02-01 15:39:23 +0000771 // FIXME: Fix a dependency issue by instantiating the ABI object to some
772 // default based off the triple. The triple doesn't describe the target
773 // fully, but any external user of the API that uses the MCTargetStreamer
774 // would otherwise crash on assertion failure.
775
776 ABI = MipsABIInfo(
777 STI.getTargetTriple().getArch() == Triple::ArchType::mipsel ||
778 STI.getTargetTriple().getArch() == Triple::ArchType::mips
779 ? MipsABIInfo::O32()
780 : MipsABIInfo::N64());
781
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000782 // Architecture
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000783 if (Features[Mips::FeatureMips64r6])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000784 EFlags |= ELF::EF_MIPS_ARCH_64R6;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000785 else if (Features[Mips::FeatureMips64r2] ||
786 Features[Mips::FeatureMips64r3] ||
787 Features[Mips::FeatureMips64r5])
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000788 EFlags |= ELF::EF_MIPS_ARCH_64R2;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000789 else if (Features[Mips::FeatureMips64])
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000790 EFlags |= ELF::EF_MIPS_ARCH_64;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000791 else if (Features[Mips::FeatureMips5])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000792 EFlags |= ELF::EF_MIPS_ARCH_5;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000793 else if (Features[Mips::FeatureMips4])
Daniel Sandersf7b32292014-04-03 12:13:36 +0000794 EFlags |= ELF::EF_MIPS_ARCH_4;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000795 else if (Features[Mips::FeatureMips3])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000796 EFlags |= ELF::EF_MIPS_ARCH_3;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000797 else if (Features[Mips::FeatureMips32r6])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000798 EFlags |= ELF::EF_MIPS_ARCH_32R6;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000799 else if (Features[Mips::FeatureMips32r2] ||
800 Features[Mips::FeatureMips32r3] ||
801 Features[Mips::FeatureMips32r5])
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000802 EFlags |= ELF::EF_MIPS_ARCH_32R2;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000803 else if (Features[Mips::FeatureMips32])
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000804 EFlags |= ELF::EF_MIPS_ARCH_32;
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000805 else if (Features[Mips::FeatureMips2])
Daniel Sanders950f48d2014-07-04 15:21:53 +0000806 EFlags |= ELF::EF_MIPS_ARCH_2;
807 else
808 EFlags |= ELF::EF_MIPS_ARCH_1;
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000809
Daniel Sanders415c1592016-05-12 11:31:19 +0000810 // Machine
811 if (Features[Mips::FeatureCnMips])
812 EFlags |= ELF::EF_MIPS_MACH_OCTEON;
813
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000814 // Other options.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000815 if (Features[Mips::FeatureNaN2008])
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000816 EFlags |= ELF::EF_MIPS_NAN2008;
817
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000818 MCA.setELFHeaderEFlags(EFlags);
819}
Jack Carter86ac5c12013-11-18 23:55:27 +0000820
Rafael Espindola95fb9b92015-06-02 20:38:46 +0000821void MipsTargetELFStreamer::emitLabel(MCSymbol *S) {
822 auto *Symbol = cast<MCSymbolELF>(S);
Rafael Espindolac73aed12015-06-03 19:03:11 +0000823 getStreamer().getAssembler().registerSymbol(*Symbol);
Rafael Espindola95fb9b92015-06-02 20:38:46 +0000824 uint8_t Type = Symbol->getType();
Rafael Espindola26e917c2014-01-15 03:07:12 +0000825 if (Type != ELF::STT_FUNC)
826 return;
827
Simon Dardis3c82a642017-02-08 16:25:05 +0000828 if (isMicroMipsEnabled())
829 Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000830}
831
Rafael Espindola972e71a2014-01-31 23:10:26 +0000832void MipsTargetELFStreamer::finish() {
833 MCAssembler &MCA = getStreamer().getAssembler();
Daniel Sanders68c37472014-07-21 13:30:55 +0000834 const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo();
Rafael Espindola972e71a2014-01-31 23:10:26 +0000835
Daniel Sanders41ffa5d2014-07-14 15:05:51 +0000836 // .bss, .text and .data are always at least 16-byte aligned.
Rafael Espindola967d6a62015-05-21 21:02:35 +0000837 MCSection &TextSection = *OFI.getTextSection();
Rafael Espindolabb9a71c2015-05-26 15:07:25 +0000838 MCA.registerSection(TextSection);
Rafael Espindola967d6a62015-05-21 21:02:35 +0000839 MCSection &DataSection = *OFI.getDataSection();
Rafael Espindolabb9a71c2015-05-26 15:07:25 +0000840 MCA.registerSection(DataSection);
Rafael Espindola967d6a62015-05-21 21:02:35 +0000841 MCSection &BSSSection = *OFI.getBSSSection();
Rafael Espindolabb9a71c2015-05-26 15:07:25 +0000842 MCA.registerSection(BSSSection);
Daniel Sanders41ffa5d2014-07-14 15:05:51 +0000843
Rafael Espindola967d6a62015-05-21 21:02:35 +0000844 TextSection.setAlignment(std::max(16u, TextSection.getAlignment()));
845 DataSection.setAlignment(std::max(16u, DataSection.getAlignment()));
846 BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment()));
Daniel Sanders41ffa5d2014-07-14 15:05:51 +0000847
Daniel Sandersc07f06a2016-05-04 13:21:06 +0000848 if (RoundSectionSizes) {
849 // Make sections sizes a multiple of the alignment. This is useful for
850 // verifying the output of IAS against the output of other assemblers but
851 // it's not necessary to produce a correct object and increases section
852 // size.
853 MCStreamer &OS = getStreamer();
854 for (MCSection &S : MCA) {
855 MCSectionELF &Section = static_cast<MCSectionELF &>(S);
Daniel Sanders9db710a2016-04-29 12:44:07 +0000856
Daniel Sandersc07f06a2016-05-04 13:21:06 +0000857 unsigned Alignment = Section.getAlignment();
858 if (Alignment) {
859 OS.SwitchSection(&Section);
860 if (Section.UseCodeAlign())
861 OS.EmitCodeAlignment(Alignment, Alignment);
862 else
863 OS.EmitValueToAlignment(Alignment, 0, 1, Alignment);
864 }
Daniel Sanders9db710a2016-04-29 12:44:07 +0000865 }
866 }
867
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000868 const FeatureBitset &Features = STI.getFeatureBits();
Eric Christophera5762812015-01-26 17:33:46 +0000869
870 // Update e_header flags. See the FIXME and comment above in
871 // the constructor for a full rundown on this.
872 unsigned EFlags = MCA.getELFHeaderEFlags();
873
874 // ABI
875 // N64 does not require any ABI bits.
876 if (getABI().IsO32())
877 EFlags |= ELF::EF_MIPS_ABI_O32;
878 else if (getABI().IsN32())
879 EFlags |= ELF::EF_MIPS_ABI2;
880
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000881 if (Features[Mips::FeatureGP64Bit]) {
Eric Christophera5762812015-01-26 17:33:46 +0000882 if (getABI().IsO32())
883 EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000884 } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64])
Eric Christophera5762812015-01-26 17:33:46 +0000885 EFlags |= ELF::EF_MIPS_32BITMODE;
886
Simon Dardisca74dd72017-01-27 11:36:52 +0000887 // -mplt is not implemented but we should act as if it was
888 // given.
889 if (!Features[Mips::FeatureNoABICalls])
890 EFlags |= ELF::EF_MIPS_CPIC;
891
892 if (Pic)
893 EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;
Eric Christophera5762812015-01-26 17:33:46 +0000894
895 MCA.setELFHeaderEFlags(EFlags);
896
Daniel Sanders68c37472014-07-21 13:30:55 +0000897 // Emit all the option records.
898 // At the moment we are only emitting .Mips.options (ODK_REGINFO) and
899 // .reginfo.
900 MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);
901 MEF.EmitMipsOptionRecords();
Rafael Espindola972e71a2014-01-31 23:10:26 +0000902
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000903 emitMipsAbiFlags();
Rafael Espindola972e71a2014-01-31 23:10:26 +0000904}
905
Rafael Espindola95fb9b92015-06-02 20:38:46 +0000906void MipsTargetELFStreamer::emitAssignment(MCSymbol *S, const MCExpr *Value) {
907 auto *Symbol = cast<MCSymbolELF>(S);
Zoran Jovanovic28221d82014-03-20 09:44:49 +0000908 // If on rhs is micromips symbol then mark Symbol as microMips.
909 if (Value->getKind() != MCExpr::SymbolRef)
910 return;
Rafael Espindola95fb9b92015-06-02 20:38:46 +0000911 const auto &RhsSym = cast<MCSymbolELF>(
912 static_cast<const MCSymbolRefExpr *>(Value)->getSymbol());
Toma Tabacu2cc44f52015-04-16 13:37:32 +0000913
Rafael Espindola8c006ee2015-06-04 05:59:23 +0000914 if (!(RhsSym.getOther() & ELF::STO_MIPS_MICROMIPS))
Zoran Jovanovic28221d82014-03-20 09:44:49 +0000915 return;
916
Rafael Espindola8c006ee2015-06-04 05:59:23 +0000917 Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
Zoran Jovanovic28221d82014-03-20 09:44:49 +0000918}
919
Jack Carter86ac5c12013-11-18 23:55:27 +0000920MCELFStreamer &MipsTargetELFStreamer::getStreamer() {
Rafael Espindola24ea09e2014-01-26 06:06:37 +0000921 return static_cast<MCELFStreamer &>(Streamer);
Jack Carter86ac5c12013-11-18 23:55:27 +0000922}
923
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000924void MipsTargetELFStreamer::emitDirectiveSetMicroMips() {
925 MicroMipsEnabled = true;
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000926 forbidModuleDirective();
Jack Carter86ac5c12013-11-18 23:55:27 +0000927}
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000928
929void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() {
930 MicroMipsEnabled = false;
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000931 forbidModuleDirective();
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +0000932}
933
Daniel Sanderscda908a2016-05-16 09:10:13 +0000934void MipsTargetELFStreamer::setUsesMicroMips() {
935 MCAssembler &MCA = getStreamer().getAssembler();
936 unsigned Flags = MCA.getELFHeaderEFlags();
937 Flags |= ELF::EF_MIPS_MICROMIPS;
938 MCA.setELFHeaderEFlags(Flags);
939}
940
Rafael Espindola6633d572014-01-14 18:57:12 +0000941void MipsTargetELFStreamer::emitDirectiveSetMips16() {
Rafael Espindolae7583752014-01-24 16:13:20 +0000942 MCAssembler &MCA = getStreamer().getAssembler();
943 unsigned Flags = MCA.getELFHeaderEFlags();
944 Flags |= ELF::EF_MIPS_ARCH_ASE_M16;
945 MCA.setELFHeaderEFlags(Flags);
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000946 forbidModuleDirective();
Rafael Espindola6633d572014-01-14 18:57:12 +0000947}
948
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000949void MipsTargetELFStreamer::emitDirectiveSetNoReorder() {
Rafael Espindolacb1953f2014-01-26 06:57:13 +0000950 MCAssembler &MCA = getStreamer().getAssembler();
951 unsigned Flags = MCA.getELFHeaderEFlags();
952 Flags |= ELF::EF_MIPS_NOREORDER;
953 MCA.setELFHeaderEFlags(Flags);
Daniel Sanderscdb45fa2014-08-14 09:18:14 +0000954 forbidModuleDirective();
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000955}
956
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +0000957void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {
Daniel Sandersd97a6342014-08-13 10:07:34 +0000958 MCAssembler &MCA = getStreamer().getAssembler();
959 MCContext &Context = MCA.getContext();
960 MCStreamer &OS = getStreamer();
961
Scott Egerton219fae92016-02-17 11:15:16 +0000962 MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0);
Daniel Sandersd97a6342014-08-13 10:07:34 +0000963
Daniel Sanders2b561332015-11-23 16:08:03 +0000964 MCSymbol *Sym = Context.getOrCreateSymbol(Name);
Daniel Sandersd97a6342014-08-13 10:07:34 +0000965 const MCSymbolRefExpr *ExprRef =
Daniel Sanders2b561332015-11-23 16:08:03 +0000966 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Context);
Daniel Sandersd97a6342014-08-13 10:07:34 +0000967
Rafael Espindolabb9a71c2015-05-26 15:07:25 +0000968 MCA.registerSection(*Sec);
Rafael Espindola967d6a62015-05-21 21:02:35 +0000969 Sec->setAlignment(4);
Daniel Sandersd97a6342014-08-13 10:07:34 +0000970
971 OS.PushSection();
972
973 OS.SwitchSection(Sec);
974
975 OS.EmitValueImpl(ExprRef, 4);
976
977 OS.EmitIntValue(GPRInfoSet ? GPRBitMask : 0, 4); // reg_mask
978 OS.EmitIntValue(GPRInfoSet ? GPROffset : 0, 4); // reg_offset
979
980 OS.EmitIntValue(FPRInfoSet ? FPRBitMask : 0, 4); // fpreg_mask
981 OS.EmitIntValue(FPRInfoSet ? FPROffset : 0, 4); // fpreg_offset
982
983 OS.EmitIntValue(FrameInfoSet ? FrameOffset : 0, 4); // frame_offset
984 OS.EmitIntValue(FrameInfoSet ? FrameReg : 0, 4); // frame_reg
985 OS.EmitIntValue(FrameInfoSet ? ReturnReg : 0, 4); // return_reg
986
987 // The .end directive marks the end of a procedure. Invalidate
988 // the information gathered up until this point.
989 GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
990
991 OS.PopSection();
Daniel Sanders2b561332015-11-23 16:08:03 +0000992
993 // .end also implicitly sets the size.
994 MCSymbol *CurPCSym = Context.createTempSymbol();
995 OS.EmitLabel(CurPCSym);
996 const MCExpr *Size = MCBinaryExpr::createSub(
997 MCSymbolRefExpr::create(CurPCSym, MCSymbolRefExpr::VK_None, Context),
998 ExprRef, Context);
Simon Dardis68e9d942017-02-03 15:48:53 +0000999
1000 // The ELFObjectWriter can determine the absolute size as it has access to
1001 // the layout information of the assembly file, so a size expression rather
1002 // than an absolute value is ok here.
Daniel Sanders2b561332015-11-23 16:08:03 +00001003 static_cast<MCSymbolELF *>(Sym)->setSize(Size);
Rafael Espindolaeb0a8af2014-01-26 05:06:48 +00001004}
1005
Rafael Espindola6633d572014-01-14 18:57:12 +00001006void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00001007 GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
Daniel Sanders2b561332015-11-23 16:08:03 +00001008
1009 // .ent also acts like an implicit '.type symbol, STT_FUNC'
1010 static_cast<const MCSymbolELF &>(Symbol).setType(ELF::STT_FUNC);
Rafael Espindola6633d572014-01-14 18:57:12 +00001011}
1012
Jack Carter0cd3c192014-01-06 23:27:31 +00001013void MipsTargetELFStreamer::emitDirectiveAbiCalls() {
1014 MCAssembler &MCA = getStreamer().getAssembler();
1015 unsigned Flags = MCA.getELFHeaderEFlags();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00001016 Flags |= ELF::EF_MIPS_CPIC | ELF::EF_MIPS_PIC;
Jack Carter0cd3c192014-01-06 23:27:31 +00001017 MCA.setELFHeaderEFlags(Flags);
1018}
Matheus Almeida0051f2d2014-04-16 15:48:55 +00001019
1020void MipsTargetELFStreamer::emitDirectiveNaN2008() {
1021 MCAssembler &MCA = getStreamer().getAssembler();
1022 unsigned Flags = MCA.getELFHeaderEFlags();
1023 Flags |= ELF::EF_MIPS_NAN2008;
1024 MCA.setELFHeaderEFlags(Flags);
1025}
1026
1027void MipsTargetELFStreamer::emitDirectiveNaNLegacy() {
1028 MCAssembler &MCA = getStreamer().getAssembler();
1029 unsigned Flags = MCA.getELFHeaderEFlags();
1030 Flags &= ~ELF::EF_MIPS_NAN2008;
1031 MCA.setELFHeaderEFlags(Flags);
1032}
1033
Jack Carter0cd3c192014-01-06 23:27:31 +00001034void MipsTargetELFStreamer::emitDirectiveOptionPic0() {
1035 MCAssembler &MCA = getStreamer().getAssembler();
1036 unsigned Flags = MCA.getELFHeaderEFlags();
Matheus Almeidaf79b2812014-03-26 13:40:29 +00001037 // This option overrides other PIC options like -KPIC.
1038 Pic = false;
Jack Carter0cd3c192014-01-06 23:27:31 +00001039 Flags &= ~ELF::EF_MIPS_PIC;
1040 MCA.setELFHeaderEFlags(Flags);
1041}
Rafael Espindola054234f2014-01-27 03:53:56 +00001042
Matheus Almeidaf79b2812014-03-26 13:40:29 +00001043void MipsTargetELFStreamer::emitDirectiveOptionPic2() {
1044 MCAssembler &MCA = getStreamer().getAssembler();
1045 unsigned Flags = MCA.getELFHeaderEFlags();
1046 Pic = true;
1047 // NOTE: We are following the GAS behaviour here which means the directive
1048 // 'pic2' also sets the CPIC bit in the ELF header. This is different from
1049 // what is stated in the SYSV ABI which consider the bits EF_MIPS_PIC and
1050 // EF_MIPS_CPIC to be mutually exclusive.
1051 Flags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;
1052 MCA.setELFHeaderEFlags(Flags);
1053}
1054
Toma Tabacu9ca50962015-04-16 09:53:47 +00001055void MipsTargetELFStreamer::emitDirectiveInsn() {
1056 MipsTargetStreamer::emitDirectiveInsn();
1057 MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer);
1058 MEF.createPendingLabelRelocs();
1059}
1060
Rafael Espindola054234f2014-01-27 03:53:56 +00001061void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
Daniel Sandersd97a6342014-08-13 10:07:34 +00001062 unsigned ReturnReg_) {
1063 MCContext &Context = getStreamer().getAssembler().getContext();
1064 const MCRegisterInfo *RegInfo = Context.getRegisterInfo();
1065
1066 FrameInfoSet = true;
1067 FrameReg = RegInfo->getEncodingValue(StackReg);
1068 FrameOffset = StackSize;
1069 ReturnReg = RegInfo->getEncodingValue(ReturnReg_);
Rafael Espindola054234f2014-01-27 03:53:56 +00001070}
Rafael Espindola25fa2912014-01-27 04:33:11 +00001071
1072void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask,
1073 int CPUTopSavedRegOff) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00001074 GPRInfoSet = true;
1075 GPRBitMask = CPUBitmask;
1076 GPROffset = CPUTopSavedRegOff;
Rafael Espindola25fa2912014-01-27 04:33:11 +00001077}
1078
1079void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask,
1080 int FPUTopSavedRegOff) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00001081 FPRInfoSet = true;
1082 FPRBitMask = FPUBitmask;
1083 FPROffset = FPUTopSavedRegOff;
Rafael Espindola25fa2912014-01-27 04:33:11 +00001084}
Vladimir Medic615b26e2014-03-04 09:54:09 +00001085
Toma Tabacuc4c202a2014-10-01 14:53:19 +00001086void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00001087 // .cpload $reg
1088 // This directive expands to:
1089 // lui $gp, %hi(_gp_disp)
1090 // addui $gp, $gp, %lo(_gp_disp)
1091 // addu $gp, $gp, $reg
1092 // when support for position independent code is enabled.
Eric Christophera5762812015-01-26 17:33:46 +00001093 if (!Pic || (getABI().IsN32() || getABI().IsN64()))
Matheus Almeida525bc4f2014-04-30 11:28:42 +00001094 return;
1095
1096 // There's a GNU extension controlled by -mno-shared that allows
1097 // locally-binding symbols to be accessed using absolute addresses.
1098 // This is currently not supported. When supported -mno-shared makes
1099 // .cpload expand to:
1100 // lui $gp, %hi(__gnu_local_gp)
1101 // addiu $gp, $gp, %lo(__gnu_local_gp)
1102
1103 StringRef SymName("_gp_disp");
1104 MCAssembler &MCA = getStreamer().getAssembler();
Jim Grosbach6f482002015-05-18 18:43:14 +00001105 MCSymbol *GP_Disp = MCA.getContext().getOrCreateSymbol(SymName);
Rafael Espindolab5d316b2015-05-29 20:21:02 +00001106 MCA.registerSymbol(*GP_Disp);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00001107
1108 MCInst TmpInst;
1109 TmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001110 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001111 const MCExpr *HiSym = MipsMCExpr::create(
1112 MipsMCExpr::MEK_HI,
1113 MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
1114 MCA.getContext()),
1115 MCA.getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00001116 TmpInst.addOperand(MCOperand::createExpr(HiSym));
Matheus Almeida525bc4f2014-04-30 11:28:42 +00001117 getStreamer().EmitInstruction(TmpInst, STI);
1118
1119 TmpInst.clear();
1120
1121 TmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001122 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1123 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001124 const MCExpr *LoSym = MipsMCExpr::create(
1125 MipsMCExpr::MEK_LO,
1126 MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
1127 MCA.getContext()),
1128 MCA.getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00001129 TmpInst.addOperand(MCOperand::createExpr(LoSym));
Matheus Almeida525bc4f2014-04-30 11:28:42 +00001130 getStreamer().EmitInstruction(TmpInst, STI);
1131
1132 TmpInst.clear();
1133
1134 TmpInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001135 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1136 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1137 TmpInst.addOperand(MCOperand::createReg(RegNo));
Matheus Almeida525bc4f2014-04-30 11:28:42 +00001138 getStreamer().EmitInstruction(TmpInst, STI);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001139
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00001140 forbidModuleDirective();
Matheus Almeida525bc4f2014-04-30 11:28:42 +00001141}
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001142
Daniel Sandersdf8510d2016-05-11 12:48:19 +00001143bool MipsTargetELFStreamer::emitDirectiveCpRestore(
Benjamin Kramerd3f4c052016-06-12 16:13:55 +00001144 int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
Daniel Sandersdf8510d2016-05-11 12:48:19 +00001145 const MCSubtargetInfo *STI) {
1146 MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001147 // .cprestore offset
1148 // When PIC mode is enabled and the O32 ABI is used, this directive expands
1149 // to:
1150 // sw $gp, offset($sp)
1151 // and adds a corresponding LW after every JAL.
1152
1153 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
1154 // is used in non-PIC mode.
1155 if (!Pic || (getABI().IsN32() || getABI().IsN64()))
Daniel Sandersdf8510d2016-05-11 12:48:19 +00001156 return true;
1157
Daniel Sanders7225cd52016-04-29 16:16:49 +00001158 // Store the $gp on the stack.
Daniel Sanders241c6792016-05-12 14:01:50 +00001159 emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc,
Daniel Sanders7225cd52016-04-29 16:16:49 +00001160 STI);
Daniel Sandersdf8510d2016-05-11 12:48:19 +00001161 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001162}
1163
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001164void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
1165 int RegOrOffset,
1166 const MCSymbol &Sym,
1167 bool IsReg) {
1168 // Only N32 and N64 emit anything for .cpsetup iff PIC is set.
Eric Christophera5762812015-01-26 17:33:46 +00001169 if (!Pic || !(getABI().IsN32() || getABI().IsN64()))
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001170 return;
1171
Daniel Sanderse8581362016-06-14 10:13:47 +00001172 forbidModuleDirective();
1173
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001174 MCAssembler &MCA = getStreamer().getAssembler();
1175 MCInst Inst;
1176
1177 // Either store the old $gp in a register or on the stack
1178 if (IsReg) {
1179 // move $save, $gpreg
Daniel Sanderse8581362016-06-14 10:13:47 +00001180 emitRRR(Mips::OR64, RegOrOffset, Mips::GP, Mips::ZERO, SMLoc(), &STI);
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001181 } else {
1182 // sd $gpreg, offset($sp)
Daniel Sanderse8581362016-06-14 10:13:47 +00001183 emitRRI(Mips::SD, Mips::GP, Mips::SP, RegOrOffset, SMLoc(), &STI);
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001184 }
Daniel Sanderse8581362016-06-14 10:13:47 +00001185
1186 if (getABI().IsN32()) {
1187 MCSymbol *GPSym = MCA.getContext().getOrCreateSymbol("__gnu_local_gp");
1188 const MipsMCExpr *HiExpr = MipsMCExpr::create(
1189 MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(GPSym, MCA.getContext()),
1190 MCA.getContext());
1191 const MipsMCExpr *LoExpr = MipsMCExpr::create(
1192 MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(GPSym, MCA.getContext()),
1193 MCA.getContext());
1194
1195 // lui $gp, %hi(__gnu_local_gp)
1196 emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
1197
1198 // addiu $gp, $gp, %lo(__gnu_local_gp)
1199 emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
1200 SMLoc(), &STI);
1201
1202 return;
1203 }
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001204
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001205 const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff(
1206 MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
1207 MCA.getContext());
1208 const MipsMCExpr *LoExpr = MipsMCExpr::createGpOff(
1209 MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
1210 MCA.getContext());
Toma Tabacu8874eac2015-02-18 13:46:53 +00001211
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001212 // lui $gp, %hi(%neg(%gp_rel(funcSym)))
Daniel Sanderse8581362016-06-14 10:13:47 +00001213 emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001214
1215 // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
Daniel Sanderse8581362016-06-14 10:13:47 +00001216 emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
1217 SMLoc(), &STI);
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001218
1219 // daddu $gp, $gp, $funcreg
Daniel Sanderse8581362016-06-14 10:13:47 +00001220 emitRRR(Mips::DADDu, Mips::GP, Mips::GP, RegNo, SMLoc(), &STI);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001221}
1222
Daniel Sandersf173dda2015-09-22 10:50:09 +00001223void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
1224 bool SaveLocationIsRegister) {
1225 // Only N32 and N64 emit anything for .cpreturn iff PIC is set.
1226 if (!Pic || !(getABI().IsN32() || getABI().IsN64()))
1227 return;
1228
1229 MCInst Inst;
1230 // Either restore the old $gp from a register or on the stack
1231 if (SaveLocationIsRegister) {
1232 Inst.setOpcode(Mips::OR);
1233 Inst.addOperand(MCOperand::createReg(Mips::GP));
1234 Inst.addOperand(MCOperand::createReg(SaveLocation));
1235 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
1236 } else {
1237 Inst.setOpcode(Mips::LD);
1238 Inst.addOperand(MCOperand::createReg(Mips::GP));
1239 Inst.addOperand(MCOperand::createReg(Mips::SP));
1240 Inst.addOperand(MCOperand::createImm(SaveLocation));
1241 }
1242 getStreamer().EmitInstruction(Inst, STI);
1243
1244 forbidModuleDirective();
1245}
1246
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001247void MipsTargetELFStreamer::emitMipsAbiFlags() {
1248 MCAssembler &MCA = getStreamer().getAssembler();
1249 MCContext &Context = MCA.getContext();
1250 MCStreamer &OS = getStreamer();
Rafael Espindola0709a7b2015-05-21 19:20:38 +00001251 MCSectionELF *Sec = Context.getELFSection(
Rafael Espindolaba31e272015-01-29 17:33:21 +00001252 ".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24, "");
Rafael Espindolabb9a71c2015-05-26 15:07:25 +00001253 MCA.registerSection(*Sec);
Rafael Espindola967d6a62015-05-21 21:02:35 +00001254 Sec->setAlignment(8);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001255 OS.SwitchSection(Sec);
1256
Daniel Sandersc7dbc632014-07-08 10:11:38 +00001257 OS << ABIFlagsSection;
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00001258}