xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsAsmPrinter.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- MipsAsmPrinter.cpp - Mips LLVM Assembly Printer --------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file contains a printer that converts from our internal representation
10*0b57cec5SDimitry Andric // of machine-dependent LLVM code to GAS-format MIPS assembly language.
11*0b57cec5SDimitry Andric //
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #include "MipsAsmPrinter.h"
15*0b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
16*0b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h"
17*0b57cec5SDimitry Andric #include "MCTargetDesc/MipsInstPrinter.h"
18*0b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCNaCl.h"
19*0b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h"
20*0b57cec5SDimitry Andric #include "Mips.h"
21*0b57cec5SDimitry Andric #include "MipsMCInstLower.h"
22*0b57cec5SDimitry Andric #include "MipsMachineFunction.h"
23*0b57cec5SDimitry Andric #include "MipsSubtarget.h"
24*0b57cec5SDimitry Andric #include "MipsTargetMachine.h"
25*0b57cec5SDimitry Andric #include "MipsTargetStreamer.h"
26*0b57cec5SDimitry Andric #include "TargetInfo/MipsTargetInfo.h"
27*0b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
28*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
29*0b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
30*0b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
31*0b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
32*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
33*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
34*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
35*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
36*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
37*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h"
38*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
39*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
40*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
41*0b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
42*0b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
43*0b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
44*0b57cec5SDimitry Andric #include "llvm/IR/Function.h"
45*0b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h"
46*0b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
47*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
48*0b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
49*0b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
50*0b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
51*0b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
52*0b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h"
53*0b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
54*0b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
55*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
56*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
57*0b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
58*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
59*0b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
60*0b57cec5SDimitry Andric #include <cassert>
61*0b57cec5SDimitry Andric #include <cstdint>
62*0b57cec5SDimitry Andric #include <map>
63*0b57cec5SDimitry Andric #include <memory>
64*0b57cec5SDimitry Andric #include <string>
65*0b57cec5SDimitry Andric #include <vector>
66*0b57cec5SDimitry Andric 
67*0b57cec5SDimitry Andric using namespace llvm;
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric #define DEBUG_TYPE "mips-asm-printer"
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric extern cl::opt<bool> EmitJalrReloc;
72*0b57cec5SDimitry Andric 
73*0b57cec5SDimitry Andric MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const {
74*0b57cec5SDimitry Andric   return static_cast<MipsTargetStreamer &>(*OutStreamer->getTargetStreamer());
75*0b57cec5SDimitry Andric }
76*0b57cec5SDimitry Andric 
77*0b57cec5SDimitry Andric bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
78*0b57cec5SDimitry Andric   Subtarget = &MF.getSubtarget<MipsSubtarget>();
79*0b57cec5SDimitry Andric 
80*0b57cec5SDimitry Andric   MipsFI = MF.getInfo<MipsFunctionInfo>();
81*0b57cec5SDimitry Andric   if (Subtarget->inMips16Mode())
82*0b57cec5SDimitry Andric     for (std::map<
83*0b57cec5SDimitry Andric              const char *,
84*0b57cec5SDimitry Andric              const Mips16HardFloatInfo::FuncSignature *>::const_iterator
85*0b57cec5SDimitry Andric              it = MipsFI->StubsNeeded.begin();
86*0b57cec5SDimitry Andric          it != MipsFI->StubsNeeded.end(); ++it) {
87*0b57cec5SDimitry Andric       const char *Symbol = it->first;
88*0b57cec5SDimitry Andric       const Mips16HardFloatInfo::FuncSignature *Signature = it->second;
89*0b57cec5SDimitry Andric       if (StubsNeeded.find(Symbol) == StubsNeeded.end())
90*0b57cec5SDimitry Andric         StubsNeeded[Symbol] = Signature;
91*0b57cec5SDimitry Andric     }
92*0b57cec5SDimitry Andric   MCP = MF.getConstantPool();
93*0b57cec5SDimitry Andric 
94*0b57cec5SDimitry Andric   // In NaCl, all indirect jump targets must be aligned to bundle size.
95*0b57cec5SDimitry Andric   if (Subtarget->isTargetNaCl())
96*0b57cec5SDimitry Andric     NaClAlignIndirectJumpTargets(MF);
97*0b57cec5SDimitry Andric 
98*0b57cec5SDimitry Andric   AsmPrinter::runOnMachineFunction(MF);
99*0b57cec5SDimitry Andric 
100*0b57cec5SDimitry Andric   emitXRayTable();
101*0b57cec5SDimitry Andric 
102*0b57cec5SDimitry Andric   return true;
103*0b57cec5SDimitry Andric }
104*0b57cec5SDimitry Andric 
105*0b57cec5SDimitry Andric bool MipsAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) {
106*0b57cec5SDimitry Andric   MCOp = MCInstLowering.LowerOperand(MO);
107*0b57cec5SDimitry Andric   return MCOp.isValid();
108*0b57cec5SDimitry Andric }
109*0b57cec5SDimitry Andric 
110*0b57cec5SDimitry Andric #include "MipsGenMCPseudoLowering.inc"
111*0b57cec5SDimitry Andric 
112*0b57cec5SDimitry Andric // Lower PseudoReturn/PseudoIndirectBranch/PseudoIndirectBranch64 to JR, JR_MM,
113*0b57cec5SDimitry Andric // JALR, or JALR64 as appropriate for the target.
114*0b57cec5SDimitry Andric void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer,
115*0b57cec5SDimitry Andric                                               const MachineInstr *MI) {
116*0b57cec5SDimitry Andric   bool HasLinkReg = false;
117*0b57cec5SDimitry Andric   bool InMicroMipsMode = Subtarget->inMicroMipsMode();
118*0b57cec5SDimitry Andric   MCInst TmpInst0;
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric   if (Subtarget->hasMips64r6()) {
121*0b57cec5SDimitry Andric     // MIPS64r6 should use (JALR64 ZERO_64, $rs)
122*0b57cec5SDimitry Andric     TmpInst0.setOpcode(Mips::JALR64);
123*0b57cec5SDimitry Andric     HasLinkReg = true;
124*0b57cec5SDimitry Andric   } else if (Subtarget->hasMips32r6()) {
125*0b57cec5SDimitry Andric     // MIPS32r6 should use (JALR ZERO, $rs)
126*0b57cec5SDimitry Andric     if (InMicroMipsMode)
127*0b57cec5SDimitry Andric       TmpInst0.setOpcode(Mips::JRC16_MMR6);
128*0b57cec5SDimitry Andric     else {
129*0b57cec5SDimitry Andric       TmpInst0.setOpcode(Mips::JALR);
130*0b57cec5SDimitry Andric       HasLinkReg = true;
131*0b57cec5SDimitry Andric     }
132*0b57cec5SDimitry Andric   } else if (Subtarget->inMicroMipsMode())
133*0b57cec5SDimitry Andric     // microMIPS should use (JR_MM $rs)
134*0b57cec5SDimitry Andric     TmpInst0.setOpcode(Mips::JR_MM);
135*0b57cec5SDimitry Andric   else {
136*0b57cec5SDimitry Andric     // Everything else should use (JR $rs)
137*0b57cec5SDimitry Andric     TmpInst0.setOpcode(Mips::JR);
138*0b57cec5SDimitry Andric   }
139*0b57cec5SDimitry Andric 
140*0b57cec5SDimitry Andric   MCOperand MCOp;
141*0b57cec5SDimitry Andric 
142*0b57cec5SDimitry Andric   if (HasLinkReg) {
143*0b57cec5SDimitry Andric     unsigned ZeroReg = Subtarget->isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
144*0b57cec5SDimitry Andric     TmpInst0.addOperand(MCOperand::createReg(ZeroReg));
145*0b57cec5SDimitry Andric   }
146*0b57cec5SDimitry Andric 
147*0b57cec5SDimitry Andric   lowerOperand(MI->getOperand(0), MCOp);
148*0b57cec5SDimitry Andric   TmpInst0.addOperand(MCOp);
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric   EmitToStreamer(OutStreamer, TmpInst0);
151*0b57cec5SDimitry Andric }
152*0b57cec5SDimitry Andric 
153*0b57cec5SDimitry Andric // If there is an MO_JALR operand, insert:
154*0b57cec5SDimitry Andric //
155*0b57cec5SDimitry Andric // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
156*0b57cec5SDimitry Andric // tmplabel:
157*0b57cec5SDimitry Andric //
158*0b57cec5SDimitry Andric // This is an optimization hint for the linker which may then replace
159*0b57cec5SDimitry Andric // an indirect call with a direct branch.
160*0b57cec5SDimitry Andric static void emitDirectiveRelocJalr(const MachineInstr &MI,
161*0b57cec5SDimitry Andric                                    MCContext &OutContext,
162*0b57cec5SDimitry Andric                                    TargetMachine &TM,
163*0b57cec5SDimitry Andric                                    MCStreamer &OutStreamer,
164*0b57cec5SDimitry Andric                                    const MipsSubtarget &Subtarget) {
165*0b57cec5SDimitry Andric   for (unsigned int I = MI.getDesc().getNumOperands(), E = MI.getNumOperands();
166*0b57cec5SDimitry Andric        I < E; ++I) {
167*0b57cec5SDimitry Andric     MachineOperand MO = MI.getOperand(I);
168*0b57cec5SDimitry Andric     if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) {
169*0b57cec5SDimitry Andric       MCSymbol *Callee = MO.getMCSymbol();
170*0b57cec5SDimitry Andric       if (Callee && !Callee->getName().empty()) {
171*0b57cec5SDimitry Andric         MCSymbol *OffsetLabel = OutContext.createTempSymbol();
172*0b57cec5SDimitry Andric         const MCExpr *OffsetExpr =
173*0b57cec5SDimitry Andric             MCSymbolRefExpr::create(OffsetLabel, OutContext);
174*0b57cec5SDimitry Andric         const MCExpr *CaleeExpr =
175*0b57cec5SDimitry Andric             MCSymbolRefExpr::create(Callee, OutContext);
176*0b57cec5SDimitry Andric         OutStreamer.EmitRelocDirective
177*0b57cec5SDimitry Andric             (*OffsetExpr,
178*0b57cec5SDimitry Andric              Subtarget.inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
179*0b57cec5SDimitry Andric              CaleeExpr, SMLoc(), *TM.getMCSubtargetInfo());
180*0b57cec5SDimitry Andric         OutStreamer.EmitLabel(OffsetLabel);
181*0b57cec5SDimitry Andric         return;
182*0b57cec5SDimitry Andric       }
183*0b57cec5SDimitry Andric     }
184*0b57cec5SDimitry Andric   }
185*0b57cec5SDimitry Andric }
186*0b57cec5SDimitry Andric 
187*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
188*0b57cec5SDimitry Andric   MipsTargetStreamer &TS = getTargetStreamer();
189*0b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
190*0b57cec5SDimitry Andric   TS.forbidModuleDirective();
191*0b57cec5SDimitry Andric 
192*0b57cec5SDimitry Andric   if (MI->isDebugValue()) {
193*0b57cec5SDimitry Andric     SmallString<128> Str;
194*0b57cec5SDimitry Andric     raw_svector_ostream OS(Str);
195*0b57cec5SDimitry Andric 
196*0b57cec5SDimitry Andric     PrintDebugValueComment(MI, OS);
197*0b57cec5SDimitry Andric     return;
198*0b57cec5SDimitry Andric   }
199*0b57cec5SDimitry Andric   if (MI->isDebugLabel())
200*0b57cec5SDimitry Andric     return;
201*0b57cec5SDimitry Andric 
202*0b57cec5SDimitry Andric   // If we just ended a constant pool, mark it as such.
203*0b57cec5SDimitry Andric   if (InConstantPool && Opc != Mips::CONSTPOOL_ENTRY) {
204*0b57cec5SDimitry Andric     OutStreamer->EmitDataRegion(MCDR_DataRegionEnd);
205*0b57cec5SDimitry Andric     InConstantPool = false;
206*0b57cec5SDimitry Andric   }
207*0b57cec5SDimitry Andric   if (Opc == Mips::CONSTPOOL_ENTRY) {
208*0b57cec5SDimitry Andric     // CONSTPOOL_ENTRY - This instruction represents a floating
209*0b57cec5SDimitry Andric     // constant pool in the function.  The first operand is the ID#
210*0b57cec5SDimitry Andric     // for this instruction, the second is the index into the
211*0b57cec5SDimitry Andric     // MachineConstantPool that this is, the third is the size in
212*0b57cec5SDimitry Andric     // bytes of this constant pool entry.
213*0b57cec5SDimitry Andric     // The required alignment is specified on the basic block holding this MI.
214*0b57cec5SDimitry Andric     //
215*0b57cec5SDimitry Andric     unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
216*0b57cec5SDimitry Andric     unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
217*0b57cec5SDimitry Andric 
218*0b57cec5SDimitry Andric     // If this is the first entry of the pool, mark it.
219*0b57cec5SDimitry Andric     if (!InConstantPool) {
220*0b57cec5SDimitry Andric       OutStreamer->EmitDataRegion(MCDR_DataRegion);
221*0b57cec5SDimitry Andric       InConstantPool = true;
222*0b57cec5SDimitry Andric     }
223*0b57cec5SDimitry Andric 
224*0b57cec5SDimitry Andric     OutStreamer->EmitLabel(GetCPISymbol(LabelId));
225*0b57cec5SDimitry Andric 
226*0b57cec5SDimitry Andric     const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
227*0b57cec5SDimitry Andric     if (MCPE.isMachineConstantPoolEntry())
228*0b57cec5SDimitry Andric       EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
229*0b57cec5SDimitry Andric     else
230*0b57cec5SDimitry Andric       EmitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal);
231*0b57cec5SDimitry Andric     return;
232*0b57cec5SDimitry Andric   }
233*0b57cec5SDimitry Andric 
234*0b57cec5SDimitry Andric   switch (Opc) {
235*0b57cec5SDimitry Andric   case Mips::PATCHABLE_FUNCTION_ENTER:
236*0b57cec5SDimitry Andric     LowerPATCHABLE_FUNCTION_ENTER(*MI);
237*0b57cec5SDimitry Andric     return;
238*0b57cec5SDimitry Andric   case Mips::PATCHABLE_FUNCTION_EXIT:
239*0b57cec5SDimitry Andric     LowerPATCHABLE_FUNCTION_EXIT(*MI);
240*0b57cec5SDimitry Andric     return;
241*0b57cec5SDimitry Andric   case Mips::PATCHABLE_TAIL_CALL:
242*0b57cec5SDimitry Andric     LowerPATCHABLE_TAIL_CALL(*MI);
243*0b57cec5SDimitry Andric     return;
244*0b57cec5SDimitry Andric   }
245*0b57cec5SDimitry Andric 
246*0b57cec5SDimitry Andric   if (EmitJalrReloc &&
247*0b57cec5SDimitry Andric       (MI->isReturn() || MI->isCall() || MI->isIndirectBranch())) {
248*0b57cec5SDimitry Andric     emitDirectiveRelocJalr(*MI, OutContext, TM, *OutStreamer, *Subtarget);
249*0b57cec5SDimitry Andric   }
250*0b57cec5SDimitry Andric 
251*0b57cec5SDimitry Andric   MachineBasicBlock::const_instr_iterator I = MI->getIterator();
252*0b57cec5SDimitry Andric   MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
253*0b57cec5SDimitry Andric 
254*0b57cec5SDimitry Andric   do {
255*0b57cec5SDimitry Andric     // Do any auto-generated pseudo lowerings.
256*0b57cec5SDimitry Andric     if (emitPseudoExpansionLowering(*OutStreamer, &*I))
257*0b57cec5SDimitry Andric       continue;
258*0b57cec5SDimitry Andric 
259*0b57cec5SDimitry Andric     if (I->getOpcode() == Mips::PseudoReturn ||
260*0b57cec5SDimitry Andric         I->getOpcode() == Mips::PseudoReturn64 ||
261*0b57cec5SDimitry Andric         I->getOpcode() == Mips::PseudoIndirectBranch ||
262*0b57cec5SDimitry Andric         I->getOpcode() == Mips::PseudoIndirectBranch64 ||
263*0b57cec5SDimitry Andric         I->getOpcode() == Mips::TAILCALLREG ||
264*0b57cec5SDimitry Andric         I->getOpcode() == Mips::TAILCALLREG64) {
265*0b57cec5SDimitry Andric       emitPseudoIndirectBranch(*OutStreamer, &*I);
266*0b57cec5SDimitry Andric       continue;
267*0b57cec5SDimitry Andric     }
268*0b57cec5SDimitry Andric 
269*0b57cec5SDimitry Andric     // The inMips16Mode() test is not permanent.
270*0b57cec5SDimitry Andric     // Some instructions are marked as pseudo right now which
271*0b57cec5SDimitry Andric     // would make the test fail for the wrong reason but
272*0b57cec5SDimitry Andric     // that will be fixed soon. We need this here because we are
273*0b57cec5SDimitry Andric     // removing another test for this situation downstream in the
274*0b57cec5SDimitry Andric     // callchain.
275*0b57cec5SDimitry Andric     //
276*0b57cec5SDimitry Andric     if (I->isPseudo() && !Subtarget->inMips16Mode()
277*0b57cec5SDimitry Andric         && !isLongBranchPseudo(I->getOpcode()))
278*0b57cec5SDimitry Andric       llvm_unreachable("Pseudo opcode found in EmitInstruction()");
279*0b57cec5SDimitry Andric 
280*0b57cec5SDimitry Andric     MCInst TmpInst0;
281*0b57cec5SDimitry Andric     MCInstLowering.Lower(&*I, TmpInst0);
282*0b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst0);
283*0b57cec5SDimitry Andric   } while ((++I != E) && I->isInsideBundle()); // Delay slot check
284*0b57cec5SDimitry Andric }
285*0b57cec5SDimitry Andric 
286*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
287*0b57cec5SDimitry Andric //
288*0b57cec5SDimitry Andric //  Mips Asm Directives
289*0b57cec5SDimitry Andric //
290*0b57cec5SDimitry Andric //  -- Frame directive "frame Stackpointer, Stacksize, RARegister"
291*0b57cec5SDimitry Andric //  Describe the stack frame.
292*0b57cec5SDimitry Andric //
293*0b57cec5SDimitry Andric //  -- Mask directives "(f)mask  bitmask, offset"
294*0b57cec5SDimitry Andric //  Tells the assembler which registers are saved and where.
295*0b57cec5SDimitry Andric //  bitmask - contain a little endian bitset indicating which registers are
296*0b57cec5SDimitry Andric //            saved on function prologue (e.g. with a 0x80000000 mask, the
297*0b57cec5SDimitry Andric //            assembler knows the register 31 (RA) is saved at prologue.
298*0b57cec5SDimitry Andric //  offset  - the position before stack pointer subtraction indicating where
299*0b57cec5SDimitry Andric //            the first saved register on prologue is located. (e.g. with a
300*0b57cec5SDimitry Andric //
301*0b57cec5SDimitry Andric //  Consider the following function prologue:
302*0b57cec5SDimitry Andric //
303*0b57cec5SDimitry Andric //    .frame  $fp,48,$ra
304*0b57cec5SDimitry Andric //    .mask   0xc0000000,-8
305*0b57cec5SDimitry Andric //       addiu $sp, $sp, -48
306*0b57cec5SDimitry Andric //       sw $ra, 40($sp)
307*0b57cec5SDimitry Andric //       sw $fp, 36($sp)
308*0b57cec5SDimitry Andric //
309*0b57cec5SDimitry Andric //    With a 0xc0000000 mask, the assembler knows the register 31 (RA) and
310*0b57cec5SDimitry Andric //    30 (FP) are saved at prologue. As the save order on prologue is from
311*0b57cec5SDimitry Andric //    left to right, RA is saved first. A -8 offset means that after the
312*0b57cec5SDimitry Andric //    stack pointer subtration, the first register in the mask (RA) will be
313*0b57cec5SDimitry Andric //    saved at address 48-8=40.
314*0b57cec5SDimitry Andric //
315*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
316*0b57cec5SDimitry Andric 
317*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
318*0b57cec5SDimitry Andric // Mask directives
319*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
320*0b57cec5SDimitry Andric 
321*0b57cec5SDimitry Andric // Create a bitmask with all callee saved registers for CPU or Floating Point
322*0b57cec5SDimitry Andric // registers. For CPU registers consider RA, GP and FP for saving if necessary.
323*0b57cec5SDimitry Andric void MipsAsmPrinter::printSavedRegsBitmask() {
324*0b57cec5SDimitry Andric   // CPU and FPU Saved Registers Bitmasks
325*0b57cec5SDimitry Andric   unsigned CPUBitmask = 0, FPUBitmask = 0;
326*0b57cec5SDimitry Andric   int CPUTopSavedRegOff, FPUTopSavedRegOff;
327*0b57cec5SDimitry Andric 
328*0b57cec5SDimitry Andric   // Set the CPU and FPU Bitmasks
329*0b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF->getFrameInfo();
330*0b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
331*0b57cec5SDimitry Andric   const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
332*0b57cec5SDimitry Andric   // size of stack area to which FP callee-saved regs are saved.
333*0b57cec5SDimitry Andric   unsigned CPURegSize = TRI->getRegSizeInBits(Mips::GPR32RegClass) / 8;
334*0b57cec5SDimitry Andric   unsigned FGR32RegSize = TRI->getRegSizeInBits(Mips::FGR32RegClass) / 8;
335*0b57cec5SDimitry Andric   unsigned AFGR64RegSize = TRI->getRegSizeInBits(Mips::AFGR64RegClass) / 8;
336*0b57cec5SDimitry Andric   bool HasAFGR64Reg = false;
337*0b57cec5SDimitry Andric   unsigned CSFPRegsSize = 0;
338*0b57cec5SDimitry Andric 
339*0b57cec5SDimitry Andric   for (const auto &I : CSI) {
340*0b57cec5SDimitry Andric     unsigned Reg = I.getReg();
341*0b57cec5SDimitry Andric     unsigned RegNum = TRI->getEncodingValue(Reg);
342*0b57cec5SDimitry Andric 
343*0b57cec5SDimitry Andric     // If it's a floating point register, set the FPU Bitmask.
344*0b57cec5SDimitry Andric     // If it's a general purpose register, set the CPU Bitmask.
345*0b57cec5SDimitry Andric     if (Mips::FGR32RegClass.contains(Reg)) {
346*0b57cec5SDimitry Andric       FPUBitmask |= (1 << RegNum);
347*0b57cec5SDimitry Andric       CSFPRegsSize += FGR32RegSize;
348*0b57cec5SDimitry Andric     } else if (Mips::AFGR64RegClass.contains(Reg)) {
349*0b57cec5SDimitry Andric       FPUBitmask |= (3 << RegNum);
350*0b57cec5SDimitry Andric       CSFPRegsSize += AFGR64RegSize;
351*0b57cec5SDimitry Andric       HasAFGR64Reg = true;
352*0b57cec5SDimitry Andric     } else if (Mips::GPR32RegClass.contains(Reg))
353*0b57cec5SDimitry Andric       CPUBitmask |= (1 << RegNum);
354*0b57cec5SDimitry Andric   }
355*0b57cec5SDimitry Andric 
356*0b57cec5SDimitry Andric   // FP Regs are saved right below where the virtual frame pointer points to.
357*0b57cec5SDimitry Andric   FPUTopSavedRegOff = FPUBitmask ?
358*0b57cec5SDimitry Andric     (HasAFGR64Reg ? -AFGR64RegSize : -FGR32RegSize) : 0;
359*0b57cec5SDimitry Andric 
360*0b57cec5SDimitry Andric   // CPU Regs are saved below FP Regs.
361*0b57cec5SDimitry Andric   CPUTopSavedRegOff = CPUBitmask ? -CSFPRegsSize - CPURegSize : 0;
362*0b57cec5SDimitry Andric 
363*0b57cec5SDimitry Andric   MipsTargetStreamer &TS = getTargetStreamer();
364*0b57cec5SDimitry Andric   // Print CPUBitmask
365*0b57cec5SDimitry Andric   TS.emitMask(CPUBitmask, CPUTopSavedRegOff);
366*0b57cec5SDimitry Andric 
367*0b57cec5SDimitry Andric   // Print FPUBitmask
368*0b57cec5SDimitry Andric   TS.emitFMask(FPUBitmask, FPUTopSavedRegOff);
369*0b57cec5SDimitry Andric }
370*0b57cec5SDimitry Andric 
371*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
372*0b57cec5SDimitry Andric // Frame and Set directives
373*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
374*0b57cec5SDimitry Andric 
375*0b57cec5SDimitry Andric /// Frame Directive
376*0b57cec5SDimitry Andric void MipsAsmPrinter::emitFrameDirective() {
377*0b57cec5SDimitry Andric   const TargetRegisterInfo &RI = *MF->getSubtarget().getRegisterInfo();
378*0b57cec5SDimitry Andric 
379*0b57cec5SDimitry Andric   unsigned stackReg  = RI.getFrameRegister(*MF);
380*0b57cec5SDimitry Andric   unsigned returnReg = RI.getRARegister();
381*0b57cec5SDimitry Andric   unsigned stackSize = MF->getFrameInfo().getStackSize();
382*0b57cec5SDimitry Andric 
383*0b57cec5SDimitry Andric   getTargetStreamer().emitFrame(stackReg, stackSize, returnReg);
384*0b57cec5SDimitry Andric }
385*0b57cec5SDimitry Andric 
386*0b57cec5SDimitry Andric /// Emit Set directives.
387*0b57cec5SDimitry Andric const char *MipsAsmPrinter::getCurrentABIString() const {
388*0b57cec5SDimitry Andric   switch (static_cast<MipsTargetMachine &>(TM).getABI().GetEnumValue()) {
389*0b57cec5SDimitry Andric   case MipsABIInfo::ABI::O32:  return "abi32";
390*0b57cec5SDimitry Andric   case MipsABIInfo::ABI::N32:  return "abiN32";
391*0b57cec5SDimitry Andric   case MipsABIInfo::ABI::N64:  return "abi64";
392*0b57cec5SDimitry Andric   default: llvm_unreachable("Unknown Mips ABI");
393*0b57cec5SDimitry Andric   }
394*0b57cec5SDimitry Andric }
395*0b57cec5SDimitry Andric 
396*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitFunctionEntryLabel() {
397*0b57cec5SDimitry Andric   MipsTargetStreamer &TS = getTargetStreamer();
398*0b57cec5SDimitry Andric 
399*0b57cec5SDimitry Andric   // NaCl sandboxing requires that indirect call instructions are masked.
400*0b57cec5SDimitry Andric   // This means that function entry points should be bundle-aligned.
401*0b57cec5SDimitry Andric   if (Subtarget->isTargetNaCl())
402*0b57cec5SDimitry Andric     EmitAlignment(std::max(MF->getAlignment(), MIPS_NACL_BUNDLE_ALIGN));
403*0b57cec5SDimitry Andric 
404*0b57cec5SDimitry Andric   if (Subtarget->inMicroMipsMode()) {
405*0b57cec5SDimitry Andric     TS.emitDirectiveSetMicroMips();
406*0b57cec5SDimitry Andric     TS.setUsesMicroMips();
407*0b57cec5SDimitry Andric     TS.updateABIInfo(*Subtarget);
408*0b57cec5SDimitry Andric   } else
409*0b57cec5SDimitry Andric     TS.emitDirectiveSetNoMicroMips();
410*0b57cec5SDimitry Andric 
411*0b57cec5SDimitry Andric   if (Subtarget->inMips16Mode())
412*0b57cec5SDimitry Andric     TS.emitDirectiveSetMips16();
413*0b57cec5SDimitry Andric   else
414*0b57cec5SDimitry Andric     TS.emitDirectiveSetNoMips16();
415*0b57cec5SDimitry Andric 
416*0b57cec5SDimitry Andric   TS.emitDirectiveEnt(*CurrentFnSym);
417*0b57cec5SDimitry Andric   OutStreamer->EmitLabel(CurrentFnSym);
418*0b57cec5SDimitry Andric }
419*0b57cec5SDimitry Andric 
420*0b57cec5SDimitry Andric /// EmitFunctionBodyStart - Targets can override this to emit stuff before
421*0b57cec5SDimitry Andric /// the first basic block in the function.
422*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitFunctionBodyStart() {
423*0b57cec5SDimitry Andric   MipsTargetStreamer &TS = getTargetStreamer();
424*0b57cec5SDimitry Andric 
425*0b57cec5SDimitry Andric   MCInstLowering.Initialize(&MF->getContext());
426*0b57cec5SDimitry Andric 
427*0b57cec5SDimitry Andric   bool IsNakedFunction = MF->getFunction().hasFnAttribute(Attribute::Naked);
428*0b57cec5SDimitry Andric   if (!IsNakedFunction)
429*0b57cec5SDimitry Andric     emitFrameDirective();
430*0b57cec5SDimitry Andric 
431*0b57cec5SDimitry Andric   if (!IsNakedFunction)
432*0b57cec5SDimitry Andric     printSavedRegsBitmask();
433*0b57cec5SDimitry Andric 
434*0b57cec5SDimitry Andric   if (!Subtarget->inMips16Mode()) {
435*0b57cec5SDimitry Andric     TS.emitDirectiveSetNoReorder();
436*0b57cec5SDimitry Andric     TS.emitDirectiveSetNoMacro();
437*0b57cec5SDimitry Andric     TS.emitDirectiveSetNoAt();
438*0b57cec5SDimitry Andric   }
439*0b57cec5SDimitry Andric }
440*0b57cec5SDimitry Andric 
441*0b57cec5SDimitry Andric /// EmitFunctionBodyEnd - Targets can override this to emit stuff after
442*0b57cec5SDimitry Andric /// the last basic block in the function.
443*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitFunctionBodyEnd() {
444*0b57cec5SDimitry Andric   MipsTargetStreamer &TS = getTargetStreamer();
445*0b57cec5SDimitry Andric 
446*0b57cec5SDimitry Andric   // There are instruction for this macros, but they must
447*0b57cec5SDimitry Andric   // always be at the function end, and we can't emit and
448*0b57cec5SDimitry Andric   // break with BB logic.
449*0b57cec5SDimitry Andric   if (!Subtarget->inMips16Mode()) {
450*0b57cec5SDimitry Andric     TS.emitDirectiveSetAt();
451*0b57cec5SDimitry Andric     TS.emitDirectiveSetMacro();
452*0b57cec5SDimitry Andric     TS.emitDirectiveSetReorder();
453*0b57cec5SDimitry Andric   }
454*0b57cec5SDimitry Andric   TS.emitDirectiveEnd(CurrentFnSym->getName());
455*0b57cec5SDimitry Andric   // Make sure to terminate any constant pools that were at the end
456*0b57cec5SDimitry Andric   // of the function.
457*0b57cec5SDimitry Andric   if (!InConstantPool)
458*0b57cec5SDimitry Andric     return;
459*0b57cec5SDimitry Andric   InConstantPool = false;
460*0b57cec5SDimitry Andric   OutStreamer->EmitDataRegion(MCDR_DataRegionEnd);
461*0b57cec5SDimitry Andric }
462*0b57cec5SDimitry Andric 
463*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) {
464*0b57cec5SDimitry Andric   AsmPrinter::EmitBasicBlockEnd(MBB);
465*0b57cec5SDimitry Andric   MipsTargetStreamer &TS = getTargetStreamer();
466*0b57cec5SDimitry Andric   if (MBB.empty())
467*0b57cec5SDimitry Andric     TS.emitDirectiveInsn();
468*0b57cec5SDimitry Andric }
469*0b57cec5SDimitry Andric 
470*0b57cec5SDimitry Andric /// isBlockOnlyReachableByFallthough - Return true if the basic block has
471*0b57cec5SDimitry Andric /// exactly one predecessor and the control transfer mechanism between
472*0b57cec5SDimitry Andric /// the predecessor and this block is a fall-through.
473*0b57cec5SDimitry Andric bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock*
474*0b57cec5SDimitry Andric                                                        MBB) const {
475*0b57cec5SDimitry Andric   // The predecessor has to be immediately before this block.
476*0b57cec5SDimitry Andric   const MachineBasicBlock *Pred = *MBB->pred_begin();
477*0b57cec5SDimitry Andric 
478*0b57cec5SDimitry Andric   // If the predecessor is a switch statement, assume a jump table
479*0b57cec5SDimitry Andric   // implementation, so it is not a fall through.
480*0b57cec5SDimitry Andric   if (const BasicBlock *bb = Pred->getBasicBlock())
481*0b57cec5SDimitry Andric     if (isa<SwitchInst>(bb->getTerminator()))
482*0b57cec5SDimitry Andric       return false;
483*0b57cec5SDimitry Andric 
484*0b57cec5SDimitry Andric   // If this is a landing pad, it isn't a fall through.  If it has no preds,
485*0b57cec5SDimitry Andric   // then nothing falls through to it.
486*0b57cec5SDimitry Andric   if (MBB->isEHPad() || MBB->pred_empty())
487*0b57cec5SDimitry Andric     return false;
488*0b57cec5SDimitry Andric 
489*0b57cec5SDimitry Andric   // If there isn't exactly one predecessor, it can't be a fall through.
490*0b57cec5SDimitry Andric   MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI;
491*0b57cec5SDimitry Andric   ++PI2;
492*0b57cec5SDimitry Andric 
493*0b57cec5SDimitry Andric   if (PI2 != MBB->pred_end())
494*0b57cec5SDimitry Andric     return false;
495*0b57cec5SDimitry Andric 
496*0b57cec5SDimitry Andric   // The predecessor has to be immediately before this block.
497*0b57cec5SDimitry Andric   if (!Pred->isLayoutSuccessor(MBB))
498*0b57cec5SDimitry Andric     return false;
499*0b57cec5SDimitry Andric 
500*0b57cec5SDimitry Andric   // If the block is completely empty, then it definitely does fall through.
501*0b57cec5SDimitry Andric   if (Pred->empty())
502*0b57cec5SDimitry Andric     return true;
503*0b57cec5SDimitry Andric 
504*0b57cec5SDimitry Andric   // Otherwise, check the last instruction.
505*0b57cec5SDimitry Andric   // Check if the last terminator is an unconditional branch.
506*0b57cec5SDimitry Andric   MachineBasicBlock::const_iterator I = Pred->end();
507*0b57cec5SDimitry Andric   while (I != Pred->begin() && !(--I)->isTerminator()) ;
508*0b57cec5SDimitry Andric 
509*0b57cec5SDimitry Andric   return !I->isBarrier();
510*0b57cec5SDimitry Andric }
511*0b57cec5SDimitry Andric 
512*0b57cec5SDimitry Andric // Print out an operand for an inline asm expression.
513*0b57cec5SDimitry Andric bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
514*0b57cec5SDimitry Andric                                      const char *ExtraCode, raw_ostream &O) {
515*0b57cec5SDimitry Andric   // Does this asm operand have a single letter operand modifier?
516*0b57cec5SDimitry Andric   if (ExtraCode && ExtraCode[0]) {
517*0b57cec5SDimitry Andric     if (ExtraCode[1] != 0) return true; // Unknown modifier.
518*0b57cec5SDimitry Andric 
519*0b57cec5SDimitry Andric     const MachineOperand &MO = MI->getOperand(OpNum);
520*0b57cec5SDimitry Andric     switch (ExtraCode[0]) {
521*0b57cec5SDimitry Andric     default:
522*0b57cec5SDimitry Andric       // See if this is a generic print operand
523*0b57cec5SDimitry Andric       return AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O);
524*0b57cec5SDimitry Andric     case 'X': // hex const int
525*0b57cec5SDimitry Andric       if ((MO.getType()) != MachineOperand::MO_Immediate)
526*0b57cec5SDimitry Andric         return true;
527*0b57cec5SDimitry Andric       O << "0x" << Twine::utohexstr(MO.getImm());
528*0b57cec5SDimitry Andric       return false;
529*0b57cec5SDimitry Andric     case 'x': // hex const int (low 16 bits)
530*0b57cec5SDimitry Andric       if ((MO.getType()) != MachineOperand::MO_Immediate)
531*0b57cec5SDimitry Andric         return true;
532*0b57cec5SDimitry Andric       O << "0x" << Twine::utohexstr(MO.getImm() & 0xffff);
533*0b57cec5SDimitry Andric       return false;
534*0b57cec5SDimitry Andric     case 'd': // decimal const int
535*0b57cec5SDimitry Andric       if ((MO.getType()) != MachineOperand::MO_Immediate)
536*0b57cec5SDimitry Andric         return true;
537*0b57cec5SDimitry Andric       O << MO.getImm();
538*0b57cec5SDimitry Andric       return false;
539*0b57cec5SDimitry Andric     case 'm': // decimal const int minus 1
540*0b57cec5SDimitry Andric       if ((MO.getType()) != MachineOperand::MO_Immediate)
541*0b57cec5SDimitry Andric         return true;
542*0b57cec5SDimitry Andric       O << MO.getImm() - 1;
543*0b57cec5SDimitry Andric       return false;
544*0b57cec5SDimitry Andric     case 'y': // exact log2
545*0b57cec5SDimitry Andric       if ((MO.getType()) != MachineOperand::MO_Immediate)
546*0b57cec5SDimitry Andric         return true;
547*0b57cec5SDimitry Andric       if (!isPowerOf2_64(MO.getImm()))
548*0b57cec5SDimitry Andric         return true;
549*0b57cec5SDimitry Andric       O << Log2_64(MO.getImm());
550*0b57cec5SDimitry Andric       return false;
551*0b57cec5SDimitry Andric     case 'z':
552*0b57cec5SDimitry Andric       // $0 if zero, regular printing otherwise
553*0b57cec5SDimitry Andric       if (MO.getType() == MachineOperand::MO_Immediate && MO.getImm() == 0) {
554*0b57cec5SDimitry Andric         O << "$0";
555*0b57cec5SDimitry Andric         return false;
556*0b57cec5SDimitry Andric       }
557*0b57cec5SDimitry Andric       // If not, call printOperand as normal.
558*0b57cec5SDimitry Andric       break;
559*0b57cec5SDimitry Andric     case 'D': // Second part of a double word register operand
560*0b57cec5SDimitry Andric     case 'L': // Low order register of a double word register operand
561*0b57cec5SDimitry Andric     case 'M': // High order register of a double word register operand
562*0b57cec5SDimitry Andric     {
563*0b57cec5SDimitry Andric       if (OpNum == 0)
564*0b57cec5SDimitry Andric         return true;
565*0b57cec5SDimitry Andric       const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
566*0b57cec5SDimitry Andric       if (!FlagsOP.isImm())
567*0b57cec5SDimitry Andric         return true;
568*0b57cec5SDimitry Andric       unsigned Flags = FlagsOP.getImm();
569*0b57cec5SDimitry Andric       unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
570*0b57cec5SDimitry Andric       // Number of registers represented by this operand. We are looking
571*0b57cec5SDimitry Andric       // for 2 for 32 bit mode and 1 for 64 bit mode.
572*0b57cec5SDimitry Andric       if (NumVals != 2) {
573*0b57cec5SDimitry Andric         if (Subtarget->isGP64bit() && NumVals == 1 && MO.isReg()) {
574*0b57cec5SDimitry Andric           unsigned Reg = MO.getReg();
575*0b57cec5SDimitry Andric           O << '$' << MipsInstPrinter::getRegisterName(Reg);
576*0b57cec5SDimitry Andric           return false;
577*0b57cec5SDimitry Andric         }
578*0b57cec5SDimitry Andric         return true;
579*0b57cec5SDimitry Andric       }
580*0b57cec5SDimitry Andric 
581*0b57cec5SDimitry Andric       unsigned RegOp = OpNum;
582*0b57cec5SDimitry Andric       if (!Subtarget->isGP64bit()){
583*0b57cec5SDimitry Andric         // Endianness reverses which register holds the high or low value
584*0b57cec5SDimitry Andric         // between M and L.
585*0b57cec5SDimitry Andric         switch(ExtraCode[0]) {
586*0b57cec5SDimitry Andric         case 'M':
587*0b57cec5SDimitry Andric           RegOp = (Subtarget->isLittle()) ? OpNum + 1 : OpNum;
588*0b57cec5SDimitry Andric           break;
589*0b57cec5SDimitry Andric         case 'L':
590*0b57cec5SDimitry Andric           RegOp = (Subtarget->isLittle()) ? OpNum : OpNum + 1;
591*0b57cec5SDimitry Andric           break;
592*0b57cec5SDimitry Andric         case 'D': // Always the second part
593*0b57cec5SDimitry Andric           RegOp = OpNum + 1;
594*0b57cec5SDimitry Andric         }
595*0b57cec5SDimitry Andric         if (RegOp >= MI->getNumOperands())
596*0b57cec5SDimitry Andric           return true;
597*0b57cec5SDimitry Andric         const MachineOperand &MO = MI->getOperand(RegOp);
598*0b57cec5SDimitry Andric         if (!MO.isReg())
599*0b57cec5SDimitry Andric           return true;
600*0b57cec5SDimitry Andric         unsigned Reg = MO.getReg();
601*0b57cec5SDimitry Andric         O << '$' << MipsInstPrinter::getRegisterName(Reg);
602*0b57cec5SDimitry Andric         return false;
603*0b57cec5SDimitry Andric       }
604*0b57cec5SDimitry Andric       break;
605*0b57cec5SDimitry Andric     }
606*0b57cec5SDimitry Andric     case 'w':
607*0b57cec5SDimitry Andric       // Print MSA registers for the 'f' constraint
608*0b57cec5SDimitry Andric       // In LLVM, the 'w' modifier doesn't need to do anything.
609*0b57cec5SDimitry Andric       // We can just call printOperand as normal.
610*0b57cec5SDimitry Andric       break;
611*0b57cec5SDimitry Andric     }
612*0b57cec5SDimitry Andric   }
613*0b57cec5SDimitry Andric 
614*0b57cec5SDimitry Andric   printOperand(MI, OpNum, O);
615*0b57cec5SDimitry Andric   return false;
616*0b57cec5SDimitry Andric }
617*0b57cec5SDimitry Andric 
618*0b57cec5SDimitry Andric bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
619*0b57cec5SDimitry Andric                                            unsigned OpNum,
620*0b57cec5SDimitry Andric                                            const char *ExtraCode,
621*0b57cec5SDimitry Andric                                            raw_ostream &O) {
622*0b57cec5SDimitry Andric   assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
623*0b57cec5SDimitry Andric   const MachineOperand &BaseMO = MI->getOperand(OpNum);
624*0b57cec5SDimitry Andric   const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
625*0b57cec5SDimitry Andric   assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
626*0b57cec5SDimitry Andric   assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
627*0b57cec5SDimitry Andric   int Offset = OffsetMO.getImm();
628*0b57cec5SDimitry Andric 
629*0b57cec5SDimitry Andric   // Currently we are expecting either no ExtraCode or 'D','M','L'.
630*0b57cec5SDimitry Andric   if (ExtraCode) {
631*0b57cec5SDimitry Andric     switch (ExtraCode[0]) {
632*0b57cec5SDimitry Andric     case 'D':
633*0b57cec5SDimitry Andric       Offset += 4;
634*0b57cec5SDimitry Andric       break;
635*0b57cec5SDimitry Andric     case 'M':
636*0b57cec5SDimitry Andric       if (Subtarget->isLittle())
637*0b57cec5SDimitry Andric         Offset += 4;
638*0b57cec5SDimitry Andric       break;
639*0b57cec5SDimitry Andric     case 'L':
640*0b57cec5SDimitry Andric       if (!Subtarget->isLittle())
641*0b57cec5SDimitry Andric         Offset += 4;
642*0b57cec5SDimitry Andric       break;
643*0b57cec5SDimitry Andric     default:
644*0b57cec5SDimitry Andric       return true; // Unknown modifier.
645*0b57cec5SDimitry Andric     }
646*0b57cec5SDimitry Andric   }
647*0b57cec5SDimitry Andric 
648*0b57cec5SDimitry Andric   O << Offset << "($" << MipsInstPrinter::getRegisterName(BaseMO.getReg())
649*0b57cec5SDimitry Andric     << ")";
650*0b57cec5SDimitry Andric 
651*0b57cec5SDimitry Andric   return false;
652*0b57cec5SDimitry Andric }
653*0b57cec5SDimitry Andric 
654*0b57cec5SDimitry Andric void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
655*0b57cec5SDimitry Andric                                   raw_ostream &O) {
656*0b57cec5SDimitry Andric   const MachineOperand &MO = MI->getOperand(opNum);
657*0b57cec5SDimitry Andric   bool closeP = false;
658*0b57cec5SDimitry Andric 
659*0b57cec5SDimitry Andric   if (MO.getTargetFlags())
660*0b57cec5SDimitry Andric     closeP = true;
661*0b57cec5SDimitry Andric 
662*0b57cec5SDimitry Andric   switch(MO.getTargetFlags()) {
663*0b57cec5SDimitry Andric   case MipsII::MO_GPREL:    O << "%gp_rel("; break;
664*0b57cec5SDimitry Andric   case MipsII::MO_GOT_CALL: O << "%call16("; break;
665*0b57cec5SDimitry Andric   case MipsII::MO_GOT:      O << "%got(";    break;
666*0b57cec5SDimitry Andric   case MipsII::MO_ABS_HI:   O << "%hi(";     break;
667*0b57cec5SDimitry Andric   case MipsII::MO_ABS_LO:   O << "%lo(";     break;
668*0b57cec5SDimitry Andric   case MipsII::MO_HIGHER:   O << "%higher("; break;
669*0b57cec5SDimitry Andric   case MipsII::MO_HIGHEST:  O << "%highest(("; break;
670*0b57cec5SDimitry Andric   case MipsII::MO_TLSGD:    O << "%tlsgd(";  break;
671*0b57cec5SDimitry Andric   case MipsII::MO_GOTTPREL: O << "%gottprel("; break;
672*0b57cec5SDimitry Andric   case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break;
673*0b57cec5SDimitry Andric   case MipsII::MO_TPREL_LO: O << "%tprel_lo("; break;
674*0b57cec5SDimitry Andric   case MipsII::MO_GPOFF_HI: O << "%hi(%neg(%gp_rel("; break;
675*0b57cec5SDimitry Andric   case MipsII::MO_GPOFF_LO: O << "%lo(%neg(%gp_rel("; break;
676*0b57cec5SDimitry Andric   case MipsII::MO_GOT_DISP: O << "%got_disp("; break;
677*0b57cec5SDimitry Andric   case MipsII::MO_GOT_PAGE: O << "%got_page("; break;
678*0b57cec5SDimitry Andric   case MipsII::MO_GOT_OFST: O << "%got_ofst("; break;
679*0b57cec5SDimitry Andric   }
680*0b57cec5SDimitry Andric 
681*0b57cec5SDimitry Andric   switch (MO.getType()) {
682*0b57cec5SDimitry Andric     case MachineOperand::MO_Register:
683*0b57cec5SDimitry Andric       O << '$'
684*0b57cec5SDimitry Andric         << StringRef(MipsInstPrinter::getRegisterName(MO.getReg())).lower();
685*0b57cec5SDimitry Andric       break;
686*0b57cec5SDimitry Andric 
687*0b57cec5SDimitry Andric     case MachineOperand::MO_Immediate:
688*0b57cec5SDimitry Andric       O << MO.getImm();
689*0b57cec5SDimitry Andric       break;
690*0b57cec5SDimitry Andric 
691*0b57cec5SDimitry Andric     case MachineOperand::MO_MachineBasicBlock:
692*0b57cec5SDimitry Andric       MO.getMBB()->getSymbol()->print(O, MAI);
693*0b57cec5SDimitry Andric       return;
694*0b57cec5SDimitry Andric 
695*0b57cec5SDimitry Andric     case MachineOperand::MO_GlobalAddress:
696*0b57cec5SDimitry Andric       PrintSymbolOperand(MO, O);
697*0b57cec5SDimitry Andric       break;
698*0b57cec5SDimitry Andric 
699*0b57cec5SDimitry Andric     case MachineOperand::MO_BlockAddress: {
700*0b57cec5SDimitry Andric       MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
701*0b57cec5SDimitry Andric       O << BA->getName();
702*0b57cec5SDimitry Andric       break;
703*0b57cec5SDimitry Andric     }
704*0b57cec5SDimitry Andric 
705*0b57cec5SDimitry Andric     case MachineOperand::MO_ConstantPoolIndex:
706*0b57cec5SDimitry Andric       O << getDataLayout().getPrivateGlobalPrefix() << "CPI"
707*0b57cec5SDimitry Andric         << getFunctionNumber() << "_" << MO.getIndex();
708*0b57cec5SDimitry Andric       if (MO.getOffset())
709*0b57cec5SDimitry Andric         O << "+" << MO.getOffset();
710*0b57cec5SDimitry Andric       break;
711*0b57cec5SDimitry Andric 
712*0b57cec5SDimitry Andric     default:
713*0b57cec5SDimitry Andric       llvm_unreachable("<unknown operand type>");
714*0b57cec5SDimitry Andric   }
715*0b57cec5SDimitry Andric 
716*0b57cec5SDimitry Andric   if (closeP) O << ")";
717*0b57cec5SDimitry Andric }
718*0b57cec5SDimitry Andric 
719*0b57cec5SDimitry Andric void MipsAsmPrinter::
720*0b57cec5SDimitry Andric printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) {
721*0b57cec5SDimitry Andric   // Load/Store memory operands -- imm($reg)
722*0b57cec5SDimitry Andric   // If PIC target the target is loaded as the
723*0b57cec5SDimitry Andric   // pattern lw $25,%call16($28)
724*0b57cec5SDimitry Andric 
725*0b57cec5SDimitry Andric   // opNum can be invalid if instruction has reglist as operand.
726*0b57cec5SDimitry Andric   // MemOperand is always last operand of instruction (base + offset).
727*0b57cec5SDimitry Andric   switch (MI->getOpcode()) {
728*0b57cec5SDimitry Andric   default:
729*0b57cec5SDimitry Andric     break;
730*0b57cec5SDimitry Andric   case Mips::SWM32_MM:
731*0b57cec5SDimitry Andric   case Mips::LWM32_MM:
732*0b57cec5SDimitry Andric     opNum = MI->getNumOperands() - 2;
733*0b57cec5SDimitry Andric     break;
734*0b57cec5SDimitry Andric   }
735*0b57cec5SDimitry Andric 
736*0b57cec5SDimitry Andric   printOperand(MI, opNum+1, O);
737*0b57cec5SDimitry Andric   O << "(";
738*0b57cec5SDimitry Andric   printOperand(MI, opNum, O);
739*0b57cec5SDimitry Andric   O << ")";
740*0b57cec5SDimitry Andric }
741*0b57cec5SDimitry Andric 
742*0b57cec5SDimitry Andric void MipsAsmPrinter::
743*0b57cec5SDimitry Andric printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) {
744*0b57cec5SDimitry Andric   // when using stack locations for not load/store instructions
745*0b57cec5SDimitry Andric   // print the same way as all normal 3 operand instructions.
746*0b57cec5SDimitry Andric   printOperand(MI, opNum, O);
747*0b57cec5SDimitry Andric   O << ", ";
748*0b57cec5SDimitry Andric   printOperand(MI, opNum+1, O);
749*0b57cec5SDimitry Andric }
750*0b57cec5SDimitry Andric 
751*0b57cec5SDimitry Andric void MipsAsmPrinter::
752*0b57cec5SDimitry Andric printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
753*0b57cec5SDimitry Andric                 const char *Modifier) {
754*0b57cec5SDimitry Andric   const MachineOperand &MO = MI->getOperand(opNum);
755*0b57cec5SDimitry Andric   O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm());
756*0b57cec5SDimitry Andric }
757*0b57cec5SDimitry Andric 
758*0b57cec5SDimitry Andric void MipsAsmPrinter::
759*0b57cec5SDimitry Andric printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) {
760*0b57cec5SDimitry Andric   for (int i = opNum, e = MI->getNumOperands(); i != e; ++i) {
761*0b57cec5SDimitry Andric     if (i != opNum) O << ", ";
762*0b57cec5SDimitry Andric     printOperand(MI, i, O);
763*0b57cec5SDimitry Andric   }
764*0b57cec5SDimitry Andric }
765*0b57cec5SDimitry Andric 
766*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
767*0b57cec5SDimitry Andric   MipsTargetStreamer &TS = getTargetStreamer();
768*0b57cec5SDimitry Andric 
769*0b57cec5SDimitry Andric   // MipsTargetStreamer has an initialization order problem when emitting an
770*0b57cec5SDimitry Andric   // object file directly (see MipsTargetELFStreamer for full details). Work
771*0b57cec5SDimitry Andric   // around it by re-initializing the PIC state here.
772*0b57cec5SDimitry Andric   TS.setPic(OutContext.getObjectFileInfo()->isPositionIndependent());
773*0b57cec5SDimitry Andric 
774*0b57cec5SDimitry Andric   // Compute MIPS architecture attributes based on the default subtarget
775*0b57cec5SDimitry Andric   // that we'd have constructed. Module level directives aren't LTO
776*0b57cec5SDimitry Andric   // clean anyhow.
777*0b57cec5SDimitry Andric   // FIXME: For ifunc related functions we could iterate over and look
778*0b57cec5SDimitry Andric   // for a feature string that doesn't match the default one.
779*0b57cec5SDimitry Andric   const Triple &TT = TM.getTargetTriple();
780*0b57cec5SDimitry Andric   StringRef CPU = MIPS_MC::selectMipsCPU(TT, TM.getTargetCPU());
781*0b57cec5SDimitry Andric   StringRef FS = TM.getTargetFeatureString();
782*0b57cec5SDimitry Andric   const MipsTargetMachine &MTM = static_cast<const MipsTargetMachine &>(TM);
783*0b57cec5SDimitry Andric   const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM, 0);
784*0b57cec5SDimitry Andric 
785*0b57cec5SDimitry Andric   bool IsABICalls = STI.isABICalls();
786*0b57cec5SDimitry Andric   const MipsABIInfo &ABI = MTM.getABI();
787*0b57cec5SDimitry Andric   if (IsABICalls) {
788*0b57cec5SDimitry Andric     TS.emitDirectiveAbiCalls();
789*0b57cec5SDimitry Andric     // FIXME: This condition should be a lot more complicated that it is here.
790*0b57cec5SDimitry Andric     //        Ideally it should test for properties of the ABI and not the ABI
791*0b57cec5SDimitry Andric     //        itself.
792*0b57cec5SDimitry Andric     //        For the moment, I'm only correcting enough to make MIPS-IV work.
793*0b57cec5SDimitry Andric     if (!isPositionIndependent() && STI.hasSym32())
794*0b57cec5SDimitry Andric       TS.emitDirectiveOptionPic0();
795*0b57cec5SDimitry Andric   }
796*0b57cec5SDimitry Andric 
797*0b57cec5SDimitry Andric   // Tell the assembler which ABI we are using
798*0b57cec5SDimitry Andric   std::string SectionName = std::string(".mdebug.") + getCurrentABIString();
799*0b57cec5SDimitry Andric   OutStreamer->SwitchSection(
800*0b57cec5SDimitry Andric       OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, 0));
801*0b57cec5SDimitry Andric 
802*0b57cec5SDimitry Andric   // NaN: At the moment we only support:
803*0b57cec5SDimitry Andric   // 1. .nan legacy (default)
804*0b57cec5SDimitry Andric   // 2. .nan 2008
805*0b57cec5SDimitry Andric   STI.isNaN2008() ? TS.emitDirectiveNaN2008()
806*0b57cec5SDimitry Andric                   : TS.emitDirectiveNaNLegacy();
807*0b57cec5SDimitry Andric 
808*0b57cec5SDimitry Andric   // TODO: handle O64 ABI
809*0b57cec5SDimitry Andric 
810*0b57cec5SDimitry Andric   TS.updateABIInfo(STI);
811*0b57cec5SDimitry Andric 
812*0b57cec5SDimitry Andric   // We should always emit a '.module fp=...' but binutils 2.24 does not accept
813*0b57cec5SDimitry Andric   // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or
814*0b57cec5SDimitry Andric   // -mfp64) and omit it otherwise.
815*0b57cec5SDimitry Andric   if ((ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) ||
816*0b57cec5SDimitry Andric       STI.useSoftFloat())
817*0b57cec5SDimitry Andric     TS.emitDirectiveModuleFP();
818*0b57cec5SDimitry Andric 
819*0b57cec5SDimitry Andric   // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not
820*0b57cec5SDimitry Andric   // accept it. We therefore emit it when it contradicts the default or an
821*0b57cec5SDimitry Andric   // option has changed the default (i.e. FPXX) and omit it otherwise.
822*0b57cec5SDimitry Andric   if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX()))
823*0b57cec5SDimitry Andric     TS.emitDirectiveModuleOddSPReg();
824*0b57cec5SDimitry Andric }
825*0b57cec5SDimitry Andric 
826*0b57cec5SDimitry Andric void MipsAsmPrinter::emitInlineAsmStart() const {
827*0b57cec5SDimitry Andric   MipsTargetStreamer &TS = getTargetStreamer();
828*0b57cec5SDimitry Andric 
829*0b57cec5SDimitry Andric   // GCC's choice of assembler options for inline assembly code ('at', 'macro'
830*0b57cec5SDimitry Andric   // and 'reorder') is different from LLVM's choice for generated code ('noat',
831*0b57cec5SDimitry Andric   // 'nomacro' and 'noreorder').
832*0b57cec5SDimitry Andric   // In order to maintain compatibility with inline assembly code which depends
833*0b57cec5SDimitry Andric   // on GCC's assembler options being used, we have to switch to those options
834*0b57cec5SDimitry Andric   // for the duration of the inline assembly block and then switch back.
835*0b57cec5SDimitry Andric   TS.emitDirectiveSetPush();
836*0b57cec5SDimitry Andric   TS.emitDirectiveSetAt();
837*0b57cec5SDimitry Andric   TS.emitDirectiveSetMacro();
838*0b57cec5SDimitry Andric   TS.emitDirectiveSetReorder();
839*0b57cec5SDimitry Andric   OutStreamer->AddBlankLine();
840*0b57cec5SDimitry Andric }
841*0b57cec5SDimitry Andric 
842*0b57cec5SDimitry Andric void MipsAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
843*0b57cec5SDimitry Andric                                       const MCSubtargetInfo *EndInfo) const {
844*0b57cec5SDimitry Andric   OutStreamer->AddBlankLine();
845*0b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetPop();
846*0b57cec5SDimitry Andric }
847*0b57cec5SDimitry Andric 
848*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitJal(const MCSubtargetInfo &STI, MCSymbol *Symbol) {
849*0b57cec5SDimitry Andric   MCInst I;
850*0b57cec5SDimitry Andric   I.setOpcode(Mips::JAL);
851*0b57cec5SDimitry Andric   I.addOperand(
852*0b57cec5SDimitry Andric       MCOperand::createExpr(MCSymbolRefExpr::create(Symbol, OutContext)));
853*0b57cec5SDimitry Andric   OutStreamer->EmitInstruction(I, STI);
854*0b57cec5SDimitry Andric }
855*0b57cec5SDimitry Andric 
856*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode,
857*0b57cec5SDimitry Andric                                   unsigned Reg) {
858*0b57cec5SDimitry Andric   MCInst I;
859*0b57cec5SDimitry Andric   I.setOpcode(Opcode);
860*0b57cec5SDimitry Andric   I.addOperand(MCOperand::createReg(Reg));
861*0b57cec5SDimitry Andric   OutStreamer->EmitInstruction(I, STI);
862*0b57cec5SDimitry Andric }
863*0b57cec5SDimitry Andric 
864*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitInstrRegReg(const MCSubtargetInfo &STI,
865*0b57cec5SDimitry Andric                                      unsigned Opcode, unsigned Reg1,
866*0b57cec5SDimitry Andric                                      unsigned Reg2) {
867*0b57cec5SDimitry Andric   MCInst I;
868*0b57cec5SDimitry Andric   //
869*0b57cec5SDimitry Andric   // Because of the current td files for Mips32, the operands for MTC1
870*0b57cec5SDimitry Andric   // appear backwards from their normal assembly order. It's not a trivial
871*0b57cec5SDimitry Andric   // change to fix this in the td file so we adjust for it here.
872*0b57cec5SDimitry Andric   //
873*0b57cec5SDimitry Andric   if (Opcode == Mips::MTC1) {
874*0b57cec5SDimitry Andric     unsigned Temp = Reg1;
875*0b57cec5SDimitry Andric     Reg1 = Reg2;
876*0b57cec5SDimitry Andric     Reg2 = Temp;
877*0b57cec5SDimitry Andric   }
878*0b57cec5SDimitry Andric   I.setOpcode(Opcode);
879*0b57cec5SDimitry Andric   I.addOperand(MCOperand::createReg(Reg1));
880*0b57cec5SDimitry Andric   I.addOperand(MCOperand::createReg(Reg2));
881*0b57cec5SDimitry Andric   OutStreamer->EmitInstruction(I, STI);
882*0b57cec5SDimitry Andric }
883*0b57cec5SDimitry Andric 
884*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitInstrRegRegReg(const MCSubtargetInfo &STI,
885*0b57cec5SDimitry Andric                                         unsigned Opcode, unsigned Reg1,
886*0b57cec5SDimitry Andric                                         unsigned Reg2, unsigned Reg3) {
887*0b57cec5SDimitry Andric   MCInst I;
888*0b57cec5SDimitry Andric   I.setOpcode(Opcode);
889*0b57cec5SDimitry Andric   I.addOperand(MCOperand::createReg(Reg1));
890*0b57cec5SDimitry Andric   I.addOperand(MCOperand::createReg(Reg2));
891*0b57cec5SDimitry Andric   I.addOperand(MCOperand::createReg(Reg3));
892*0b57cec5SDimitry Andric   OutStreamer->EmitInstruction(I, STI);
893*0b57cec5SDimitry Andric }
894*0b57cec5SDimitry Andric 
895*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitMovFPIntPair(const MCSubtargetInfo &STI,
896*0b57cec5SDimitry Andric                                       unsigned MovOpc, unsigned Reg1,
897*0b57cec5SDimitry Andric                                       unsigned Reg2, unsigned FPReg1,
898*0b57cec5SDimitry Andric                                       unsigned FPReg2, bool LE) {
899*0b57cec5SDimitry Andric   if (!LE) {
900*0b57cec5SDimitry Andric     unsigned temp = Reg1;
901*0b57cec5SDimitry Andric     Reg1 = Reg2;
902*0b57cec5SDimitry Andric     Reg2 = temp;
903*0b57cec5SDimitry Andric   }
904*0b57cec5SDimitry Andric   EmitInstrRegReg(STI, MovOpc, Reg1, FPReg1);
905*0b57cec5SDimitry Andric   EmitInstrRegReg(STI, MovOpc, Reg2, FPReg2);
906*0b57cec5SDimitry Andric }
907*0b57cec5SDimitry Andric 
908*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitSwapFPIntParams(const MCSubtargetInfo &STI,
909*0b57cec5SDimitry Andric                                          Mips16HardFloatInfo::FPParamVariant PV,
910*0b57cec5SDimitry Andric                                          bool LE, bool ToFP) {
911*0b57cec5SDimitry Andric   using namespace Mips16HardFloatInfo;
912*0b57cec5SDimitry Andric 
913*0b57cec5SDimitry Andric   unsigned MovOpc = ToFP ? Mips::MTC1 : Mips::MFC1;
914*0b57cec5SDimitry Andric   switch (PV) {
915*0b57cec5SDimitry Andric   case FSig:
916*0b57cec5SDimitry Andric     EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12);
917*0b57cec5SDimitry Andric     break;
918*0b57cec5SDimitry Andric   case FFSig:
919*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE);
920*0b57cec5SDimitry Andric     break;
921*0b57cec5SDimitry Andric   case FDSig:
922*0b57cec5SDimitry Andric     EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12);
923*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE);
924*0b57cec5SDimitry Andric     break;
925*0b57cec5SDimitry Andric   case DSig:
926*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE);
927*0b57cec5SDimitry Andric     break;
928*0b57cec5SDimitry Andric   case DDSig:
929*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE);
930*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE);
931*0b57cec5SDimitry Andric     break;
932*0b57cec5SDimitry Andric   case DFSig:
933*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE);
934*0b57cec5SDimitry Andric     EmitInstrRegReg(STI, MovOpc, Mips::A2, Mips::F14);
935*0b57cec5SDimitry Andric     break;
936*0b57cec5SDimitry Andric   case NoSig:
937*0b57cec5SDimitry Andric     return;
938*0b57cec5SDimitry Andric   }
939*0b57cec5SDimitry Andric }
940*0b57cec5SDimitry Andric 
941*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitSwapFPIntRetval(
942*0b57cec5SDimitry Andric     const MCSubtargetInfo &STI, Mips16HardFloatInfo::FPReturnVariant RV,
943*0b57cec5SDimitry Andric     bool LE) {
944*0b57cec5SDimitry Andric   using namespace Mips16HardFloatInfo;
945*0b57cec5SDimitry Andric 
946*0b57cec5SDimitry Andric   unsigned MovOpc = Mips::MFC1;
947*0b57cec5SDimitry Andric   switch (RV) {
948*0b57cec5SDimitry Andric   case FRet:
949*0b57cec5SDimitry Andric     EmitInstrRegReg(STI, MovOpc, Mips::V0, Mips::F0);
950*0b57cec5SDimitry Andric     break;
951*0b57cec5SDimitry Andric   case DRet:
952*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE);
953*0b57cec5SDimitry Andric     break;
954*0b57cec5SDimitry Andric   case CFRet:
955*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE);
956*0b57cec5SDimitry Andric     break;
957*0b57cec5SDimitry Andric   case CDRet:
958*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE);
959*0b57cec5SDimitry Andric     EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE);
960*0b57cec5SDimitry Andric     break;
961*0b57cec5SDimitry Andric   case NoFPRet:
962*0b57cec5SDimitry Andric     break;
963*0b57cec5SDimitry Andric   }
964*0b57cec5SDimitry Andric }
965*0b57cec5SDimitry Andric 
966*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitFPCallStub(
967*0b57cec5SDimitry Andric     const char *Symbol, const Mips16HardFloatInfo::FuncSignature *Signature) {
968*0b57cec5SDimitry Andric   using namespace Mips16HardFloatInfo;
969*0b57cec5SDimitry Andric 
970*0b57cec5SDimitry Andric   MCSymbol *MSymbol = OutContext.getOrCreateSymbol(StringRef(Symbol));
971*0b57cec5SDimitry Andric   bool LE = getDataLayout().isLittleEndian();
972*0b57cec5SDimitry Andric   // Construct a local MCSubtargetInfo here.
973*0b57cec5SDimitry Andric   // This is because the MachineFunction won't exist (but have not yet been
974*0b57cec5SDimitry Andric   // freed) and since we're at the global level we can use the default
975*0b57cec5SDimitry Andric   // constructed subtarget.
976*0b57cec5SDimitry Andric   std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo(
977*0b57cec5SDimitry Andric       TM.getTargetTriple().str(), TM.getTargetCPU(),
978*0b57cec5SDimitry Andric       TM.getTargetFeatureString()));
979*0b57cec5SDimitry Andric 
980*0b57cec5SDimitry Andric   //
981*0b57cec5SDimitry Andric   // .global xxxx
982*0b57cec5SDimitry Andric   //
983*0b57cec5SDimitry Andric   OutStreamer->EmitSymbolAttribute(MSymbol, MCSA_Global);
984*0b57cec5SDimitry Andric   const char *RetType;
985*0b57cec5SDimitry Andric   //
986*0b57cec5SDimitry Andric   // make the comment field identifying the return and parameter
987*0b57cec5SDimitry Andric   // types of the floating point stub
988*0b57cec5SDimitry Andric   // # Stub function to call rettype xxxx (params)
989*0b57cec5SDimitry Andric   //
990*0b57cec5SDimitry Andric   switch (Signature->RetSig) {
991*0b57cec5SDimitry Andric   case FRet:
992*0b57cec5SDimitry Andric     RetType = "float";
993*0b57cec5SDimitry Andric     break;
994*0b57cec5SDimitry Andric   case DRet:
995*0b57cec5SDimitry Andric     RetType = "double";
996*0b57cec5SDimitry Andric     break;
997*0b57cec5SDimitry Andric   case CFRet:
998*0b57cec5SDimitry Andric     RetType = "complex";
999*0b57cec5SDimitry Andric     break;
1000*0b57cec5SDimitry Andric   case CDRet:
1001*0b57cec5SDimitry Andric     RetType = "double complex";
1002*0b57cec5SDimitry Andric     break;
1003*0b57cec5SDimitry Andric   case NoFPRet:
1004*0b57cec5SDimitry Andric     RetType = "";
1005*0b57cec5SDimitry Andric     break;
1006*0b57cec5SDimitry Andric   }
1007*0b57cec5SDimitry Andric   const char *Parms;
1008*0b57cec5SDimitry Andric   switch (Signature->ParamSig) {
1009*0b57cec5SDimitry Andric   case FSig:
1010*0b57cec5SDimitry Andric     Parms = "float";
1011*0b57cec5SDimitry Andric     break;
1012*0b57cec5SDimitry Andric   case FFSig:
1013*0b57cec5SDimitry Andric     Parms = "float, float";
1014*0b57cec5SDimitry Andric     break;
1015*0b57cec5SDimitry Andric   case FDSig:
1016*0b57cec5SDimitry Andric     Parms = "float, double";
1017*0b57cec5SDimitry Andric     break;
1018*0b57cec5SDimitry Andric   case DSig:
1019*0b57cec5SDimitry Andric     Parms = "double";
1020*0b57cec5SDimitry Andric     break;
1021*0b57cec5SDimitry Andric   case DDSig:
1022*0b57cec5SDimitry Andric     Parms = "double, double";
1023*0b57cec5SDimitry Andric     break;
1024*0b57cec5SDimitry Andric   case DFSig:
1025*0b57cec5SDimitry Andric     Parms = "double, float";
1026*0b57cec5SDimitry Andric     break;
1027*0b57cec5SDimitry Andric   case NoSig:
1028*0b57cec5SDimitry Andric     Parms = "";
1029*0b57cec5SDimitry Andric     break;
1030*0b57cec5SDimitry Andric   }
1031*0b57cec5SDimitry Andric   OutStreamer->AddComment("\t# Stub function to call " + Twine(RetType) + " " +
1032*0b57cec5SDimitry Andric                           Twine(Symbol) + " (" + Twine(Parms) + ")");
1033*0b57cec5SDimitry Andric   //
1034*0b57cec5SDimitry Andric   // probably not necessary but we save and restore the current section state
1035*0b57cec5SDimitry Andric   //
1036*0b57cec5SDimitry Andric   OutStreamer->PushSection();
1037*0b57cec5SDimitry Andric   //
1038*0b57cec5SDimitry Andric   // .section mips16.call.fpxxxx,"ax",@progbits
1039*0b57cec5SDimitry Andric   //
1040*0b57cec5SDimitry Andric   MCSectionELF *M = OutContext.getELFSection(
1041*0b57cec5SDimitry Andric       ".mips16.call.fp." + std::string(Symbol), ELF::SHT_PROGBITS,
1042*0b57cec5SDimitry Andric       ELF::SHF_ALLOC | ELF::SHF_EXECINSTR);
1043*0b57cec5SDimitry Andric   OutStreamer->SwitchSection(M, nullptr);
1044*0b57cec5SDimitry Andric   //
1045*0b57cec5SDimitry Andric   // .align 2
1046*0b57cec5SDimitry Andric   //
1047*0b57cec5SDimitry Andric   OutStreamer->EmitValueToAlignment(4);
1048*0b57cec5SDimitry Andric   MipsTargetStreamer &TS = getTargetStreamer();
1049*0b57cec5SDimitry Andric   //
1050*0b57cec5SDimitry Andric   // .set nomips16
1051*0b57cec5SDimitry Andric   // .set nomicromips
1052*0b57cec5SDimitry Andric   //
1053*0b57cec5SDimitry Andric   TS.emitDirectiveSetNoMips16();
1054*0b57cec5SDimitry Andric   TS.emitDirectiveSetNoMicroMips();
1055*0b57cec5SDimitry Andric   //
1056*0b57cec5SDimitry Andric   // .ent __call_stub_fp_xxxx
1057*0b57cec5SDimitry Andric   // .type  __call_stub_fp_xxxx,@function
1058*0b57cec5SDimitry Andric   //  __call_stub_fp_xxxx:
1059*0b57cec5SDimitry Andric   //
1060*0b57cec5SDimitry Andric   std::string x = "__call_stub_fp_" + std::string(Symbol);
1061*0b57cec5SDimitry Andric   MCSymbolELF *Stub =
1062*0b57cec5SDimitry Andric       cast<MCSymbolELF>(OutContext.getOrCreateSymbol(StringRef(x)));
1063*0b57cec5SDimitry Andric   TS.emitDirectiveEnt(*Stub);
1064*0b57cec5SDimitry Andric   MCSymbol *MType =
1065*0b57cec5SDimitry Andric       OutContext.getOrCreateSymbol("__call_stub_fp_" + Twine(Symbol));
1066*0b57cec5SDimitry Andric   OutStreamer->EmitSymbolAttribute(MType, MCSA_ELF_TypeFunction);
1067*0b57cec5SDimitry Andric   OutStreamer->EmitLabel(Stub);
1068*0b57cec5SDimitry Andric 
1069*0b57cec5SDimitry Andric   // Only handle non-pic for now.
1070*0b57cec5SDimitry Andric   assert(!isPositionIndependent() &&
1071*0b57cec5SDimitry Andric          "should not be here if we are compiling pic");
1072*0b57cec5SDimitry Andric   TS.emitDirectiveSetReorder();
1073*0b57cec5SDimitry Andric   //
1074*0b57cec5SDimitry Andric   // We need to add a MipsMCExpr class to MCTargetDesc to fully implement
1075*0b57cec5SDimitry Andric   // stubs without raw text but this current patch is for compiler generated
1076*0b57cec5SDimitry Andric   // functions and they all return some value.
1077*0b57cec5SDimitry Andric   // The calling sequence for non pic is different in that case and we need
1078*0b57cec5SDimitry Andric   // to implement %lo and %hi in order to handle the case of no return value
1079*0b57cec5SDimitry Andric   // See the corresponding method in Mips16HardFloat for details.
1080*0b57cec5SDimitry Andric   //
1081*0b57cec5SDimitry Andric   // mov the return address to S2.
1082*0b57cec5SDimitry Andric   // we have no stack space to store it and we are about to make another call.
1083*0b57cec5SDimitry Andric   // We need to make sure that the enclosing function knows to save S2
1084*0b57cec5SDimitry Andric   // This should have already been handled.
1085*0b57cec5SDimitry Andric   //
1086*0b57cec5SDimitry Andric   // Mov $18, $31
1087*0b57cec5SDimitry Andric 
1088*0b57cec5SDimitry Andric   EmitInstrRegRegReg(*STI, Mips::OR, Mips::S2, Mips::RA, Mips::ZERO);
1089*0b57cec5SDimitry Andric 
1090*0b57cec5SDimitry Andric   EmitSwapFPIntParams(*STI, Signature->ParamSig, LE, true);
1091*0b57cec5SDimitry Andric 
1092*0b57cec5SDimitry Andric   // Jal xxxx
1093*0b57cec5SDimitry Andric   //
1094*0b57cec5SDimitry Andric   EmitJal(*STI, MSymbol);
1095*0b57cec5SDimitry Andric 
1096*0b57cec5SDimitry Andric   // fix return values
1097*0b57cec5SDimitry Andric   EmitSwapFPIntRetval(*STI, Signature->RetSig, LE);
1098*0b57cec5SDimitry Andric   //
1099*0b57cec5SDimitry Andric   // do the return
1100*0b57cec5SDimitry Andric   // if (Signature->RetSig == NoFPRet)
1101*0b57cec5SDimitry Andric   //  llvm_unreachable("should not be any stubs here with no return value");
1102*0b57cec5SDimitry Andric   // else
1103*0b57cec5SDimitry Andric   EmitInstrReg(*STI, Mips::JR, Mips::S2);
1104*0b57cec5SDimitry Andric 
1105*0b57cec5SDimitry Andric   MCSymbol *Tmp = OutContext.createTempSymbol();
1106*0b57cec5SDimitry Andric   OutStreamer->EmitLabel(Tmp);
1107*0b57cec5SDimitry Andric   const MCSymbolRefExpr *E = MCSymbolRefExpr::create(Stub, OutContext);
1108*0b57cec5SDimitry Andric   const MCSymbolRefExpr *T = MCSymbolRefExpr::create(Tmp, OutContext);
1109*0b57cec5SDimitry Andric   const MCExpr *T_min_E = MCBinaryExpr::createSub(T, E, OutContext);
1110*0b57cec5SDimitry Andric   OutStreamer->emitELFSize(Stub, T_min_E);
1111*0b57cec5SDimitry Andric   TS.emitDirectiveEnd(x);
1112*0b57cec5SDimitry Andric   OutStreamer->PopSection();
1113*0b57cec5SDimitry Andric }
1114*0b57cec5SDimitry Andric 
1115*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) {
1116*0b57cec5SDimitry Andric   // Emit needed stubs
1117*0b57cec5SDimitry Andric   //
1118*0b57cec5SDimitry Andric   for (std::map<
1119*0b57cec5SDimitry Andric            const char *,
1120*0b57cec5SDimitry Andric            const Mips16HardFloatInfo::FuncSignature *>::const_iterator
1121*0b57cec5SDimitry Andric            it = StubsNeeded.begin();
1122*0b57cec5SDimitry Andric        it != StubsNeeded.end(); ++it) {
1123*0b57cec5SDimitry Andric     const char *Symbol = it->first;
1124*0b57cec5SDimitry Andric     const Mips16HardFloatInfo::FuncSignature *Signature = it->second;
1125*0b57cec5SDimitry Andric     EmitFPCallStub(Symbol, Signature);
1126*0b57cec5SDimitry Andric   }
1127*0b57cec5SDimitry Andric   // return to the text section
1128*0b57cec5SDimitry Andric   OutStreamer->SwitchSection(OutContext.getObjectFileInfo()->getTextSection());
1129*0b57cec5SDimitry Andric }
1130*0b57cec5SDimitry Andric 
1131*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) {
1132*0b57cec5SDimitry Andric   const uint8_t NoopsInSledCount = Subtarget->isGP64bit() ? 15 : 11;
1133*0b57cec5SDimitry Andric   // For mips32 we want to emit the following pattern:
1134*0b57cec5SDimitry Andric   //
1135*0b57cec5SDimitry Andric   // .Lxray_sled_N:
1136*0b57cec5SDimitry Andric   //   ALIGN
1137*0b57cec5SDimitry Andric   //   B .tmpN
1138*0b57cec5SDimitry Andric   //   11 NOP instructions (44 bytes)
1139*0b57cec5SDimitry Andric   //   ADDIU T9, T9, 52
1140*0b57cec5SDimitry Andric   // .tmpN
1141*0b57cec5SDimitry Andric   //
1142*0b57cec5SDimitry Andric   // We need the 44 bytes (11 instructions) because at runtime, we'd
1143*0b57cec5SDimitry Andric   // be patching over the full 48 bytes (12 instructions) with the following
1144*0b57cec5SDimitry Andric   // pattern:
1145*0b57cec5SDimitry Andric   //
1146*0b57cec5SDimitry Andric   //   ADDIU    SP, SP, -8
1147*0b57cec5SDimitry Andric   //   NOP
1148*0b57cec5SDimitry Andric   //   SW       RA, 4(SP)
1149*0b57cec5SDimitry Andric   //   SW       T9, 0(SP)
1150*0b57cec5SDimitry Andric   //   LUI      T9, %hi(__xray_FunctionEntry/Exit)
1151*0b57cec5SDimitry Andric   //   ORI      T9, T9, %lo(__xray_FunctionEntry/Exit)
1152*0b57cec5SDimitry Andric   //   LUI      T0, %hi(function_id)
1153*0b57cec5SDimitry Andric   //   JALR     T9
1154*0b57cec5SDimitry Andric   //   ORI      T0, T0, %lo(function_id)
1155*0b57cec5SDimitry Andric   //   LW       T9, 0(SP)
1156*0b57cec5SDimitry Andric   //   LW       RA, 4(SP)
1157*0b57cec5SDimitry Andric   //   ADDIU    SP, SP, 8
1158*0b57cec5SDimitry Andric   //
1159*0b57cec5SDimitry Andric   // We add 52 bytes to t9 because we want to adjust the function pointer to
1160*0b57cec5SDimitry Andric   // the actual start of function i.e. the address just after the noop sled.
1161*0b57cec5SDimitry Andric   // We do this because gp displacement relocation is emitted at the start of
1162*0b57cec5SDimitry Andric   // of the function i.e after the nop sled and to correctly calculate the
1163*0b57cec5SDimitry Andric   // global offset table address, t9 must hold the address of the instruction
1164*0b57cec5SDimitry Andric   // containing the gp displacement relocation.
1165*0b57cec5SDimitry Andric   // FIXME: Is this correct for the static relocation model?
1166*0b57cec5SDimitry Andric   //
1167*0b57cec5SDimitry Andric   // For mips64 we want to emit the following pattern:
1168*0b57cec5SDimitry Andric   //
1169*0b57cec5SDimitry Andric   // .Lxray_sled_N:
1170*0b57cec5SDimitry Andric   //   ALIGN
1171*0b57cec5SDimitry Andric   //   B .tmpN
1172*0b57cec5SDimitry Andric   //   15 NOP instructions (60 bytes)
1173*0b57cec5SDimitry Andric   // .tmpN
1174*0b57cec5SDimitry Andric   //
1175*0b57cec5SDimitry Andric   // We need the 60 bytes (15 instructions) because at runtime, we'd
1176*0b57cec5SDimitry Andric   // be patching over the full 64 bytes (16 instructions) with the following
1177*0b57cec5SDimitry Andric   // pattern:
1178*0b57cec5SDimitry Andric   //
1179*0b57cec5SDimitry Andric   //   DADDIU   SP, SP, -16
1180*0b57cec5SDimitry Andric   //   NOP
1181*0b57cec5SDimitry Andric   //   SD       RA, 8(SP)
1182*0b57cec5SDimitry Andric   //   SD       T9, 0(SP)
1183*0b57cec5SDimitry Andric   //   LUI      T9, %highest(__xray_FunctionEntry/Exit)
1184*0b57cec5SDimitry Andric   //   ORI      T9, T9, %higher(__xray_FunctionEntry/Exit)
1185*0b57cec5SDimitry Andric   //   DSLL     T9, T9, 16
1186*0b57cec5SDimitry Andric   //   ORI      T9, T9, %hi(__xray_FunctionEntry/Exit)
1187*0b57cec5SDimitry Andric   //   DSLL     T9, T9, 16
1188*0b57cec5SDimitry Andric   //   ORI      T9, T9, %lo(__xray_FunctionEntry/Exit)
1189*0b57cec5SDimitry Andric   //   LUI      T0, %hi(function_id)
1190*0b57cec5SDimitry Andric   //   JALR     T9
1191*0b57cec5SDimitry Andric   //   ADDIU    T0, T0, %lo(function_id)
1192*0b57cec5SDimitry Andric   //   LD       T9, 0(SP)
1193*0b57cec5SDimitry Andric   //   LD       RA, 8(SP)
1194*0b57cec5SDimitry Andric   //   DADDIU   SP, SP, 16
1195*0b57cec5SDimitry Andric   //
1196*0b57cec5SDimitry Andric   OutStreamer->EmitCodeAlignment(4);
1197*0b57cec5SDimitry Andric   auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
1198*0b57cec5SDimitry Andric   OutStreamer->EmitLabel(CurSled);
1199*0b57cec5SDimitry Andric   auto Target = OutContext.createTempSymbol();
1200*0b57cec5SDimitry Andric 
1201*0b57cec5SDimitry Andric   // Emit "B .tmpN" instruction, which jumps over the nop sled to the actual
1202*0b57cec5SDimitry Andric   // start of function
1203*0b57cec5SDimitry Andric   const MCExpr *TargetExpr = MCSymbolRefExpr::create(
1204*0b57cec5SDimitry Andric       Target, MCSymbolRefExpr::VariantKind::VK_None, OutContext);
1205*0b57cec5SDimitry Andric   EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::BEQ)
1206*0b57cec5SDimitry Andric                                    .addReg(Mips::ZERO)
1207*0b57cec5SDimitry Andric                                    .addReg(Mips::ZERO)
1208*0b57cec5SDimitry Andric                                    .addExpr(TargetExpr));
1209*0b57cec5SDimitry Andric 
1210*0b57cec5SDimitry Andric   for (int8_t I = 0; I < NoopsInSledCount; I++)
1211*0b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::SLL)
1212*0b57cec5SDimitry Andric                                      .addReg(Mips::ZERO)
1213*0b57cec5SDimitry Andric                                      .addReg(Mips::ZERO)
1214*0b57cec5SDimitry Andric                                      .addImm(0));
1215*0b57cec5SDimitry Andric 
1216*0b57cec5SDimitry Andric   OutStreamer->EmitLabel(Target);
1217*0b57cec5SDimitry Andric 
1218*0b57cec5SDimitry Andric   if (!Subtarget->isGP64bit()) {
1219*0b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer,
1220*0b57cec5SDimitry Andric                    MCInstBuilder(Mips::ADDiu)
1221*0b57cec5SDimitry Andric                        .addReg(Mips::T9)
1222*0b57cec5SDimitry Andric                        .addReg(Mips::T9)
1223*0b57cec5SDimitry Andric                        .addImm(0x34));
1224*0b57cec5SDimitry Andric   }
1225*0b57cec5SDimitry Andric 
1226*0b57cec5SDimitry Andric   recordSled(CurSled, MI, Kind);
1227*0b57cec5SDimitry Andric }
1228*0b57cec5SDimitry Andric 
1229*0b57cec5SDimitry Andric void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) {
1230*0b57cec5SDimitry Andric   EmitSled(MI, SledKind::FUNCTION_ENTER);
1231*0b57cec5SDimitry Andric }
1232*0b57cec5SDimitry Andric 
1233*0b57cec5SDimitry Andric void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) {
1234*0b57cec5SDimitry Andric   EmitSled(MI, SledKind::FUNCTION_EXIT);
1235*0b57cec5SDimitry Andric }
1236*0b57cec5SDimitry Andric 
1237*0b57cec5SDimitry Andric void MipsAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) {
1238*0b57cec5SDimitry Andric   EmitSled(MI, SledKind::TAIL_CALL);
1239*0b57cec5SDimitry Andric }
1240*0b57cec5SDimitry Andric 
1241*0b57cec5SDimitry Andric void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
1242*0b57cec5SDimitry Andric                                            raw_ostream &OS) {
1243*0b57cec5SDimitry Andric   // TODO: implement
1244*0b57cec5SDimitry Andric }
1245*0b57cec5SDimitry Andric 
1246*0b57cec5SDimitry Andric // Emit .dtprelword or .dtpreldword directive
1247*0b57cec5SDimitry Andric // and value for debug thread local expression.
1248*0b57cec5SDimitry Andric void MipsAsmPrinter::EmitDebugValue(const MCExpr *Value, unsigned Size) const {
1249*0b57cec5SDimitry Andric   if (auto *MipsExpr = dyn_cast<MipsMCExpr>(Value)) {
1250*0b57cec5SDimitry Andric     if (MipsExpr && MipsExpr->getKind() == MipsMCExpr::MEK_DTPREL) {
1251*0b57cec5SDimitry Andric       switch (Size) {
1252*0b57cec5SDimitry Andric       case 4:
1253*0b57cec5SDimitry Andric         OutStreamer->EmitDTPRel32Value(MipsExpr->getSubExpr());
1254*0b57cec5SDimitry Andric         break;
1255*0b57cec5SDimitry Andric       case 8:
1256*0b57cec5SDimitry Andric         OutStreamer->EmitDTPRel64Value(MipsExpr->getSubExpr());
1257*0b57cec5SDimitry Andric         break;
1258*0b57cec5SDimitry Andric       default:
1259*0b57cec5SDimitry Andric         llvm_unreachable("Unexpected size of expression value.");
1260*0b57cec5SDimitry Andric       }
1261*0b57cec5SDimitry Andric       return;
1262*0b57cec5SDimitry Andric     }
1263*0b57cec5SDimitry Andric   }
1264*0b57cec5SDimitry Andric   AsmPrinter::EmitDebugValue(Value, Size);
1265*0b57cec5SDimitry Andric }
1266*0b57cec5SDimitry Andric 
1267*0b57cec5SDimitry Andric // Align all targets of indirect branches on bundle size.  Used only if target
1268*0b57cec5SDimitry Andric // is NaCl.
1269*0b57cec5SDimitry Andric void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) {
1270*0b57cec5SDimitry Andric   // Align all blocks that are jumped to through jump table.
1271*0b57cec5SDimitry Andric   if (MachineJumpTableInfo *JtInfo = MF.getJumpTableInfo()) {
1272*0b57cec5SDimitry Andric     const std::vector<MachineJumpTableEntry> &JT = JtInfo->getJumpTables();
1273*0b57cec5SDimitry Andric     for (unsigned I = 0; I < JT.size(); ++I) {
1274*0b57cec5SDimitry Andric       const std::vector<MachineBasicBlock*> &MBBs = JT[I].MBBs;
1275*0b57cec5SDimitry Andric 
1276*0b57cec5SDimitry Andric       for (unsigned J = 0; J < MBBs.size(); ++J)
1277*0b57cec5SDimitry Andric         MBBs[J]->setAlignment(MIPS_NACL_BUNDLE_ALIGN);
1278*0b57cec5SDimitry Andric     }
1279*0b57cec5SDimitry Andric   }
1280*0b57cec5SDimitry Andric 
1281*0b57cec5SDimitry Andric   // If basic block address is taken, block can be target of indirect branch.
1282*0b57cec5SDimitry Andric   for (auto &MBB : MF) {
1283*0b57cec5SDimitry Andric     if (MBB.hasAddressTaken())
1284*0b57cec5SDimitry Andric       MBB.setAlignment(MIPS_NACL_BUNDLE_ALIGN);
1285*0b57cec5SDimitry Andric   }
1286*0b57cec5SDimitry Andric }
1287*0b57cec5SDimitry Andric 
1288*0b57cec5SDimitry Andric bool MipsAsmPrinter::isLongBranchPseudo(int Opcode) const {
1289*0b57cec5SDimitry Andric   return (Opcode == Mips::LONG_BRANCH_LUi
1290*0b57cec5SDimitry Andric           || Opcode == Mips::LONG_BRANCH_LUi2Op
1291*0b57cec5SDimitry Andric           || Opcode == Mips::LONG_BRANCH_LUi2Op_64
1292*0b57cec5SDimitry Andric           || Opcode == Mips::LONG_BRANCH_ADDiu
1293*0b57cec5SDimitry Andric           || Opcode == Mips::LONG_BRANCH_ADDiu2Op
1294*0b57cec5SDimitry Andric           || Opcode == Mips::LONG_BRANCH_DADDiu
1295*0b57cec5SDimitry Andric           || Opcode == Mips::LONG_BRANCH_DADDiu2Op);
1296*0b57cec5SDimitry Andric }
1297*0b57cec5SDimitry Andric 
1298*0b57cec5SDimitry Andric // Force static initialization.
1299*0b57cec5SDimitry Andric extern "C" void LLVMInitializeMipsAsmPrinter() {
1300*0b57cec5SDimitry Andric   RegisterAsmPrinter<MipsAsmPrinter> X(getTheMipsTarget());
1301*0b57cec5SDimitry Andric   RegisterAsmPrinter<MipsAsmPrinter> Y(getTheMipselTarget());
1302*0b57cec5SDimitry Andric   RegisterAsmPrinter<MipsAsmPrinter> A(getTheMips64Target());
1303*0b57cec5SDimitry Andric   RegisterAsmPrinter<MipsAsmPrinter> B(getTheMips64elTarget());
1304*0b57cec5SDimitry Andric }
1305