1212793Sdim//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
2212793Sdim//
3212793Sdim//                     The LLVM Compiler Infrastructure
4212793Sdim//
5212793Sdim// This file is distributed under the University of Illinois Open Source
6212793Sdim// License. See LICENSE.TXT for details.
7212793Sdim//
8212793Sdim//===----------------------------------------------------------------------===//
9212793Sdim//
10212793Sdim// This file contains a printer that converts from our internal representation
11212793Sdim// of machine-dependent LLVM code to GAS-format ARM assembly language.
12212793Sdim//
13212793Sdim//===----------------------------------------------------------------------===//
14212793Sdim
15212793Sdim#define DEBUG_TYPE "asm-printer"
16234353Sdim#include "ARMAsmPrinter.h"
17212793Sdim#include "ARM.h"
18212793Sdim#include "ARMBuildAttrs.h"
19212793Sdim#include "ARMConstantPoolValue.h"
20263508Sdim#include "ARMFPUName.h"
21212793Sdim#include "ARMMachineFunctionInfo.h"
22212793Sdim#include "ARMTargetMachine.h"
23218893Sdim#include "ARMTargetObjectFile.h"
24218893Sdim#include "InstPrinter/ARMInstPrinter.h"
25226633Sdim#include "MCTargetDesc/ARMAddressingModes.h"
26226633Sdim#include "MCTargetDesc/ARMMCExpr.h"
27243830Sdim#include "llvm/ADT/SetVector.h"
28243830Sdim#include "llvm/ADT/SmallString.h"
29212793Sdim#include "llvm/Assembly/Writer.h"
30212793Sdim#include "llvm/CodeGen/MachineFunctionPass.h"
31212793Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h"
32249423Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h"
33249423Sdim#include "llvm/DebugInfo.h"
34249423Sdim#include "llvm/IR/Constants.h"
35249423Sdim#include "llvm/IR/DataLayout.h"
36249423Sdim#include "llvm/IR/Module.h"
37249423Sdim#include "llvm/IR/Type.h"
38212793Sdim#include "llvm/MC/MCAsmInfo.h"
39218893Sdim#include "llvm/MC/MCAssembler.h"
40212793Sdim#include "llvm/MC/MCContext.h"
41249423Sdim#include "llvm/MC/MCELFStreamer.h"
42212793Sdim#include "llvm/MC/MCInst.h"
43249423Sdim#include "llvm/MC/MCInstBuilder.h"
44249423Sdim#include "llvm/MC/MCObjectStreamer.h"
45212793Sdim#include "llvm/MC/MCSectionMachO.h"
46212793Sdim#include "llvm/MC/MCStreamer.h"
47212793Sdim#include "llvm/MC/MCSymbol.h"
48212793Sdim#include "llvm/Support/CommandLine.h"
49212793Sdim#include "llvm/Support/Debug.h"
50249423Sdim#include "llvm/Support/ELF.h"
51212793Sdim#include "llvm/Support/ErrorHandling.h"
52226633Sdim#include "llvm/Support/TargetRegistry.h"
53212793Sdim#include "llvm/Support/raw_ostream.h"
54249423Sdim#include "llvm/Target/Mangler.h"
55249423Sdim#include "llvm/Target/TargetMachine.h"
56212793Sdim#include <cctype>
57212793Sdimusing namespace llvm;
58212793Sdim
59221345Sdim/// EmitDwarfRegOp - Emit dwarf register operation.
60263508Sdimvoid ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc,
61263508Sdim                                   bool Indirect) const {
62221345Sdim  const TargetRegisterInfo *RI = TM.getRegisterInfo();
63263508Sdim  if (RI->getDwarfRegNum(MLoc.getReg(), false) != -1) {
64263508Sdim    AsmPrinter::EmitDwarfRegOp(MLoc, Indirect);
65263508Sdim    return;
66263508Sdim  }
67263508Sdim  assert(MLoc.isReg() && !Indirect &&
68263508Sdim         "This doesn't support offset/indirection - implement it if needed");
69263508Sdim  unsigned Reg = MLoc.getReg();
70263508Sdim  if (Reg >= ARM::S0 && Reg <= ARM::S31) {
71263508Sdim    assert(ARM::S0 + 31 == ARM::S31 && "Unexpected ARM S register numbering");
72263508Sdim    // S registers are described as bit-pieces of a register
73263508Sdim    // S[2x] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 0)
74263508Sdim    // S[2x+1] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 32)
75226633Sdim
76263508Sdim    unsigned SReg = Reg - ARM::S0;
77263508Sdim    bool odd = SReg & 0x1;
78263508Sdim    unsigned Rx = 256 + (SReg >> 1);
79221345Sdim
80263508Sdim    OutStreamer.AddComment("DW_OP_regx for S register");
81263508Sdim    EmitInt8(dwarf::DW_OP_regx);
82221345Sdim
83263508Sdim    OutStreamer.AddComment(Twine(SReg));
84263508Sdim    EmitULEB128(Rx);
85221345Sdim
86263508Sdim    if (odd) {
87263508Sdim      OutStreamer.AddComment("DW_OP_bit_piece 32 32");
88263508Sdim      EmitInt8(dwarf::DW_OP_bit_piece);
89263508Sdim      EmitULEB128(32);
90263508Sdim      EmitULEB128(32);
91263508Sdim    } else {
92263508Sdim      OutStreamer.AddComment("DW_OP_bit_piece 32 0");
93263508Sdim      EmitInt8(dwarf::DW_OP_bit_piece);
94263508Sdim      EmitULEB128(32);
95263508Sdim      EmitULEB128(0);
96263508Sdim    }
97263508Sdim  } else if (Reg >= ARM::Q0 && Reg <= ARM::Q15) {
98263508Sdim    assert(ARM::Q0 + 15 == ARM::Q15 && "Unexpected ARM Q register numbering");
99263508Sdim    // Q registers Q0-Q15 are described by composing two D registers together.
100263508Sdim    // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1)
101263508Sdim    // DW_OP_piece(8)
102221345Sdim
103263508Sdim    unsigned QReg = Reg - ARM::Q0;
104263508Sdim    unsigned D1 = 256 + 2 * QReg;
105263508Sdim    unsigned D2 = D1 + 1;
106226633Sdim
107263508Sdim    OutStreamer.AddComment("DW_OP_regx for Q register: D1");
108263508Sdim    EmitInt8(dwarf::DW_OP_regx);
109263508Sdim    EmitULEB128(D1);
110263508Sdim    OutStreamer.AddComment("DW_OP_piece 8");
111263508Sdim    EmitInt8(dwarf::DW_OP_piece);
112263508Sdim    EmitULEB128(8);
113221345Sdim
114263508Sdim    OutStreamer.AddComment("DW_OP_regx for Q register: D2");
115263508Sdim    EmitInt8(dwarf::DW_OP_regx);
116263508Sdim    EmitULEB128(D2);
117263508Sdim    OutStreamer.AddComment("DW_OP_piece 8");
118263508Sdim    EmitInt8(dwarf::DW_OP_piece);
119263508Sdim    EmitULEB128(8);
120221345Sdim  }
121221345Sdim}
122221345Sdim
123239462Sdimvoid ARMAsmPrinter::EmitFunctionBodyEnd() {
124239462Sdim  // Make sure to terminate any constant pools that were at the end
125239462Sdim  // of the function.
126239462Sdim  if (!InConstantPool)
127239462Sdim    return;
128239462Sdim  InConstantPool = false;
129239462Sdim  OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
130239462Sdim}
131239462Sdim
132212793Sdimvoid ARMAsmPrinter::EmitFunctionEntryLabel() {
133212793Sdim  if (AFI->isThumbFunction()) {
134218893Sdim    OutStreamer.EmitAssemblerFlag(MCAF_Code16);
135223017Sdim    OutStreamer.EmitThumbFunc(CurrentFnSym);
136212793Sdim  }
137212793Sdim
138212793Sdim  OutStreamer.EmitLabel(CurrentFnSym);
139212793Sdim}
140212793Sdim
141234353Sdimvoid ARMAsmPrinter::EmitXXStructor(const Constant *CV) {
142243830Sdim  uint64_t Size = TM.getDataLayout()->getTypeAllocSize(CV->getType());
143234353Sdim  assert(Size && "C++ constructor pointer had zero size!");
144234353Sdim
145234353Sdim  const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts());
146234353Sdim  assert(GV && "C++ constructor pointer was not a GlobalValue!");
147234353Sdim
148263508Sdim  const MCExpr *E = MCSymbolRefExpr::Create(getSymbol(GV),
149234353Sdim                                            (Subtarget->isTargetDarwin()
150234353Sdim                                             ? MCSymbolRefExpr::VK_None
151234353Sdim                                             : MCSymbolRefExpr::VK_ARM_TARGET1),
152234353Sdim                                            OutContext);
153234353Sdim
154234353Sdim  OutStreamer.EmitValue(E, Size);
155234353Sdim}
156234353Sdim
157218893Sdim/// runOnMachineFunction - This uses the EmitInstruction()
158212793Sdim/// method to print assembly for each instruction.
159212793Sdim///
160212793Sdimbool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
161212793Sdim  AFI = MF.getInfo<ARMFunctionInfo>();
162212793Sdim  MCP = MF.getConstantPool();
163212793Sdim
164212793Sdim  return AsmPrinter::runOnMachineFunction(MF);
165212793Sdim}
166212793Sdim
167212793Sdimvoid ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
168212793Sdim                                 raw_ostream &O, const char *Modifier) {
169212793Sdim  const MachineOperand &MO = MI->getOperand(OpNum);
170212793Sdim  unsigned TF = MO.getTargetFlags();
171212793Sdim
172212793Sdim  switch (MO.getType()) {
173234353Sdim  default: llvm_unreachable("<unknown operand type>");
174212793Sdim  case MachineOperand::MO_Register: {
175212793Sdim    unsigned Reg = MO.getReg();
176212793Sdim    assert(TargetRegisterInfo::isPhysicalRegister(Reg));
177218893Sdim    assert(!MO.getSubReg() && "Subregs should be eliminated!");
178249423Sdim    if(ARM::GPRPairRegClass.contains(Reg)) {
179249423Sdim      const MachineFunction &MF = *MI->getParent()->getParent();
180249423Sdim      const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
181249423Sdim      Reg = TRI->getSubReg(Reg, ARM::gsub_0);
182249423Sdim    }
183218893Sdim    O << ARMInstPrinter::getRegisterName(Reg);
184212793Sdim    break;
185212793Sdim  }
186212793Sdim  case MachineOperand::MO_Immediate: {
187212793Sdim    int64_t Imm = MO.getImm();
188212793Sdim    O << '#';
189212793Sdim    if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
190218893Sdim        (TF == ARMII::MO_LO16))
191212793Sdim      O << ":lower16:";
192212793Sdim    else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
193218893Sdim             (TF == ARMII::MO_HI16))
194212793Sdim      O << ":upper16:";
195212793Sdim    O << Imm;
196212793Sdim    break;
197212793Sdim  }
198212793Sdim  case MachineOperand::MO_MachineBasicBlock:
199212793Sdim    O << *MO.getMBB()->getSymbol();
200212793Sdim    return;
201212793Sdim  case MachineOperand::MO_GlobalAddress: {
202212793Sdim    const GlobalValue *GV = MO.getGlobal();
203212793Sdim    if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
204212793Sdim        (TF & ARMII::MO_LO16))
205212793Sdim      O << ":lower16:";
206212793Sdim    else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
207212793Sdim             (TF & ARMII::MO_HI16))
208212793Sdim      O << ":upper16:";
209263508Sdim    O << *getSymbol(GV);
210212793Sdim
211212793Sdim    printOffset(MO.getOffset(), O);
212218893Sdim    if (TF == ARMII::MO_PLT)
213212793Sdim      O << "(PLT)";
214212793Sdim    break;
215212793Sdim  }
216212793Sdim  case MachineOperand::MO_ExternalSymbol: {
217212793Sdim    O << *GetExternalSymbolSymbol(MO.getSymbolName());
218218893Sdim    if (TF == ARMII::MO_PLT)
219212793Sdim      O << "(PLT)";
220212793Sdim    break;
221212793Sdim  }
222212793Sdim  case MachineOperand::MO_ConstantPoolIndex:
223212793Sdim    O << *GetCPISymbol(MO.getIndex());
224212793Sdim    break;
225212793Sdim  case MachineOperand::MO_JumpTableIndex:
226212793Sdim    O << *GetJTISymbol(MO.getIndex());
227212793Sdim    break;
228212793Sdim  }
229212793Sdim}
230212793Sdim
231212793Sdim//===--------------------------------------------------------------------===//
232212793Sdim
233212793SdimMCSymbol *ARMAsmPrinter::
234212793SdimGetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
235212793Sdim  SmallString<60> Name;
236212793Sdim  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
237212793Sdim    << getFunctionNumber() << '_' << uid << '_' << uid2;
238212793Sdim  return OutContext.GetOrCreateSymbol(Name.str());
239212793Sdim}
240212793Sdim
241212793Sdim
242249423SdimMCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel() const {
243218893Sdim  SmallString<60> Name;
244218893Sdim  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH"
245218893Sdim    << getFunctionNumber();
246218893Sdim  return OutContext.GetOrCreateSymbol(Name.str());
247212793Sdim}
248212793Sdim
249212793Sdimbool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
250212793Sdim                                    unsigned AsmVariant, const char *ExtraCode,
251212793Sdim                                    raw_ostream &O) {
252212793Sdim  // Does this asm operand have a single letter operand modifier?
253212793Sdim  if (ExtraCode && ExtraCode[0]) {
254212793Sdim    if (ExtraCode[1] != 0) return true; // Unknown modifier.
255212793Sdim
256212793Sdim    switch (ExtraCode[0]) {
257239462Sdim    default:
258239462Sdim      // See if this is a generic print operand
259239462Sdim      return AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O);
260212793Sdim    case 'a': // Print as a memory address.
261212793Sdim      if (MI->getOperand(OpNum).isReg()) {
262218893Sdim        O << "["
263218893Sdim          << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg())
264218893Sdim          << "]";
265212793Sdim        return false;
266212793Sdim      }
267212793Sdim      // Fallthrough
268212793Sdim    case 'c': // Don't print "#" before an immediate operand.
269212793Sdim      if (!MI->getOperand(OpNum).isImm())
270212793Sdim        return true;
271218893Sdim      O << MI->getOperand(OpNum).getImm();
272212793Sdim      return false;
273212793Sdim    case 'P': // Print a VFP double precision register.
274212793Sdim    case 'q': // Print a NEON quad precision register.
275212793Sdim      printOperand(MI, OpNum, O);
276212793Sdim      return false;
277223017Sdim    case 'y': // Print a VFP single precision register as indexed double.
278223017Sdim      if (MI->getOperand(OpNum).isReg()) {
279223017Sdim        unsigned Reg = MI->getOperand(OpNum).getReg();
280223017Sdim        const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
281239462Sdim        // Find the 'd' register that has this 's' register as a sub-register,
282239462Sdim        // and determine the lane number.
283239462Sdim        for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) {
284239462Sdim          if (!ARM::DPRRegClass.contains(*SR))
285239462Sdim            continue;
286239462Sdim          bool Lane0 = TRI->getSubReg(*SR, ARM::ssub_0) == Reg;
287239462Sdim          O << ARMInstPrinter::getRegisterName(*SR) << (Lane0 ? "[0]" : "[1]");
288239462Sdim          return false;
289239462Sdim        }
290223017Sdim      }
291212793Sdim      return true;
292223017Sdim    case 'B': // Bitwise inverse of integer or symbol without a preceding #.
293223017Sdim      if (!MI->getOperand(OpNum).isImm())
294223017Sdim        return true;
295223017Sdim      O << ~(MI->getOperand(OpNum).getImm());
296223017Sdim      return false;
297223017Sdim    case 'L': // The low 16 bits of an immediate constant.
298223017Sdim      if (!MI->getOperand(OpNum).isImm())
299223017Sdim        return true;
300223017Sdim      O << (MI->getOperand(OpNum).getImm() & 0xffff);
301223017Sdim      return false;
302223017Sdim    case 'M': { // A register range suitable for LDM/STM.
303223017Sdim      if (!MI->getOperand(OpNum).isReg())
304223017Sdim        return true;
305223017Sdim      const MachineOperand &MO = MI->getOperand(OpNum);
306223017Sdim      unsigned RegBegin = MO.getReg();
307223017Sdim      // This takes advantage of the 2 operand-ness of ldm/stm and that we've
308223017Sdim      // already got the operands in registers that are operands to the
309223017Sdim      // inline asm statement.
310263508Sdim      O << "{";
311263508Sdim      if (ARM::GPRPairRegClass.contains(RegBegin)) {
312263508Sdim        const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
313263508Sdim        unsigned Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0);
314263508Sdim        O << ARMInstPrinter::getRegisterName(Reg0) << ", ";;
315263508Sdim        RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1);
316263508Sdim      }
317263508Sdim      O << ARMInstPrinter::getRegisterName(RegBegin);
318226633Sdim
319223017Sdim      // FIXME: The register allocator not only may not have given us the
320223017Sdim      // registers in sequence, but may not be in ascending registers. This
321223017Sdim      // will require changes in the register allocator that'll need to be
322223017Sdim      // propagated down here if the operands change.
323223017Sdim      unsigned RegOps = OpNum + 1;
324223017Sdim      while (MI->getOperand(RegOps).isReg()) {
325226633Sdim        O << ", "
326223017Sdim          << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg());
327223017Sdim        RegOps++;
328223017Sdim      }
329223017Sdim
330223017Sdim      O << "}";
331223017Sdim
332223017Sdim      return false;
333212793Sdim    }
334226633Sdim    case 'R': // The most significant register of a pair.
335226633Sdim    case 'Q': { // The least significant register of a pair.
336226633Sdim      if (OpNum == 0)
337226633Sdim        return true;
338226633Sdim      const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
339226633Sdim      if (!FlagsOP.isImm())
340226633Sdim        return true;
341226633Sdim      unsigned Flags = FlagsOP.getImm();
342263508Sdim
343263508Sdim      // This operand may not be the one that actually provides the register. If
344263508Sdim      // it's tied to a previous one then we should refer instead to that one
345263508Sdim      // for registers and their classes.
346263508Sdim      unsigned TiedIdx;
347263508Sdim      if (InlineAsm::isUseOperandTiedToDef(Flags, TiedIdx)) {
348263508Sdim        for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) {
349263508Sdim          unsigned OpFlags = MI->getOperand(OpNum).getImm();
350263508Sdim          OpNum += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
351263508Sdim        }
352263508Sdim        Flags = MI->getOperand(OpNum).getImm();
353263508Sdim
354263508Sdim        // Later code expects OpNum to be pointing at the register rather than
355263508Sdim        // the flags.
356263508Sdim        OpNum += 1;
357263508Sdim      }
358263508Sdim
359226633Sdim      unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
360263508Sdim      unsigned RC;
361263508Sdim      InlineAsm::hasRegClassConstraint(Flags, RC);
362263508Sdim      if (RC == ARM::GPRPairRegClassID) {
363263508Sdim        if (NumVals != 1)
364263508Sdim          return true;
365263508Sdim        const MachineOperand &MO = MI->getOperand(OpNum);
366263508Sdim        if (!MO.isReg())
367263508Sdim          return true;
368263508Sdim        const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
369263508Sdim        unsigned Reg = TRI->getSubReg(MO.getReg(), ExtraCode[0] == 'Q' ?
370263508Sdim            ARM::gsub_0 : ARM::gsub_1);
371263508Sdim        O << ARMInstPrinter::getRegisterName(Reg);
372263508Sdim        return false;
373263508Sdim      }
374226633Sdim      if (NumVals != 2)
375226633Sdim        return true;
376226633Sdim      unsigned RegOp = ExtraCode[0] == 'Q' ? OpNum : OpNum + 1;
377226633Sdim      if (RegOp >= MI->getNumOperands())
378226633Sdim        return true;
379226633Sdim      const MachineOperand &MO = MI->getOperand(RegOp);
380226633Sdim      if (!MO.isReg())
381226633Sdim        return true;
382226633Sdim      unsigned Reg = MO.getReg();
383226633Sdim      O << ARMInstPrinter::getRegisterName(Reg);
384226633Sdim      return false;
385226633Sdim    }
386226633Sdim
387234353Sdim    case 'e': // The low doubleword register of a NEON quad register.
388234353Sdim    case 'f': { // The high doubleword register of a NEON quad register.
389234353Sdim      if (!MI->getOperand(OpNum).isReg())
390234353Sdim        return true;
391234353Sdim      unsigned Reg = MI->getOperand(OpNum).getReg();
392234353Sdim      if (!ARM::QPRRegClass.contains(Reg))
393234353Sdim        return true;
394234353Sdim      const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
395234353Sdim      unsigned SubReg = TRI->getSubReg(Reg, ExtraCode[0] == 'e' ?
396234353Sdim                                       ARM::dsub_0 : ARM::dsub_1);
397234353Sdim      O << ARMInstPrinter::getRegisterName(SubReg);
398234353Sdim      return false;
399234353Sdim    }
400234353Sdim
401239462Sdim    // This modifier is not yet supported.
402223017Sdim    case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.
403223017Sdim      return true;
404239462Sdim    case 'H': { // The highest-numbered register of a pair.
405239462Sdim      const MachineOperand &MO = MI->getOperand(OpNum);
406239462Sdim      if (!MO.isReg())
407239462Sdim        return true;
408239462Sdim      const MachineFunction &MF = *MI->getParent()->getParent();
409239462Sdim      const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
410249423Sdim      unsigned Reg = MO.getReg();
411249423Sdim      if(!ARM::GPRPairRegClass.contains(Reg))
412249423Sdim        return false;
413249423Sdim      Reg = TRI->getSubReg(Reg, ARM::gsub_1);
414239462Sdim      O << ARMInstPrinter::getRegisterName(Reg);
415239462Sdim      return false;
416223017Sdim    }
417239462Sdim    }
418212793Sdim  }
419212793Sdim
420212793Sdim  printOperand(MI, OpNum, O);
421212793Sdim  return false;
422212793Sdim}
423212793Sdim
424212793Sdimbool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
425212793Sdim                                          unsigned OpNum, unsigned AsmVariant,
426212793Sdim                                          const char *ExtraCode,
427212793Sdim                                          raw_ostream &O) {
428223017Sdim  // Does this asm operand have a single letter operand modifier?
429223017Sdim  if (ExtraCode && ExtraCode[0]) {
430223017Sdim    if (ExtraCode[1] != 0) return true; // Unknown modifier.
431226633Sdim
432223017Sdim    switch (ExtraCode[0]) {
433223017Sdim      case 'A': // A memory operand for a VLD1/VST1 instruction.
434223017Sdim      default: return true;  // Unknown modifier.
435223017Sdim      case 'm': // The base register of a memory operand.
436223017Sdim        if (!MI->getOperand(OpNum).isReg())
437223017Sdim          return true;
438223017Sdim        O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg());
439223017Sdim        return false;
440223017Sdim    }
441223017Sdim  }
442226633Sdim
443212793Sdim  const MachineOperand &MO = MI->getOperand(OpNum);
444212793Sdim  assert(MO.isReg() && "unexpected inline asm memory operand");
445218893Sdim  O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
446212793Sdim  return false;
447212793Sdim}
448212793Sdim
449212793Sdimvoid ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
450212793Sdim  if (Subtarget->isTargetDarwin()) {
451212793Sdim    Reloc::Model RelocM = TM.getRelocationModel();
452212793Sdim    if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
453212793Sdim      // Declare all the text sections up front (before the DWARF sections
454212793Sdim      // emitted by AsmPrinter::doInitialization) so the assembler will keep
455212793Sdim      // them together at the beginning of the object file.  This helps
456212793Sdim      // avoid out-of-range branches that are due a fundamental limitation of
457212793Sdim      // the way symbol offsets are encoded with the current Darwin ARM
458212793Sdim      // relocations.
459212793Sdim      const TargetLoweringObjectFileMachO &TLOFMacho =
460212793Sdim        static_cast<const TargetLoweringObjectFileMachO &>(
461212793Sdim          getObjFileLowering());
462243830Sdim
463243830Sdim      // Collect the set of sections our functions will go into.
464243830Sdim      SetVector<const MCSection *, SmallVector<const MCSection *, 8>,
465243830Sdim        SmallPtrSet<const MCSection *, 8> > TextSections;
466243830Sdim      // Default text section comes first.
467243830Sdim      TextSections.insert(TLOFMacho.getTextSection());
468243830Sdim      // Now any user defined text sections from function attributes.
469243830Sdim      for (Module::iterator F = M.begin(), e = M.end(); F != e; ++F)
470243830Sdim        if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage())
471243830Sdim          TextSections.insert(TLOFMacho.SectionForGlobal(F, Mang, TM));
472243830Sdim      // Now the coalescable sections.
473243830Sdim      TextSections.insert(TLOFMacho.getTextCoalSection());
474243830Sdim      TextSections.insert(TLOFMacho.getConstTextCoalSection());
475243830Sdim
476243830Sdim      // Emit the sections in the .s file header to fix the order.
477243830Sdim      for (unsigned i = 0, e = TextSections.size(); i != e; ++i)
478243830Sdim        OutStreamer.SwitchSection(TextSections[i]);
479243830Sdim
480212793Sdim      if (RelocM == Reloc::DynamicNoPIC) {
481212793Sdim        const MCSection *sect =
482212793Sdim          OutContext.getMachOSection("__TEXT", "__symbol_stub4",
483212793Sdim                                     MCSectionMachO::S_SYMBOL_STUBS,
484212793Sdim                                     12, SectionKind::getText());
485212793Sdim        OutStreamer.SwitchSection(sect);
486212793Sdim      } else {
487212793Sdim        const MCSection *sect =
488212793Sdim          OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
489212793Sdim                                     MCSectionMachO::S_SYMBOL_STUBS,
490212793Sdim                                     16, SectionKind::getText());
491212793Sdim        OutStreamer.SwitchSection(sect);
492212793Sdim      }
493212793Sdim      const MCSection *StaticInitSect =
494212793Sdim        OutContext.getMachOSection("__TEXT", "__StaticInit",
495212793Sdim                                   MCSectionMachO::S_REGULAR |
496212793Sdim                                   MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
497212793Sdim                                   SectionKind::getText());
498212793Sdim      OutStreamer.SwitchSection(StaticInitSect);
499212793Sdim    }
500212793Sdim  }
501212793Sdim
502212793Sdim  // Use unified assembler syntax.
503218893Sdim  OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified);
504212793Sdim
505212793Sdim  // Emit ARM Build Attributes
506234353Sdim  if (Subtarget->isTargetELF())
507218893Sdim    emitAttributes();
508212793Sdim}
509212793Sdim
510212793Sdim
511212793Sdimvoid ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
512212793Sdim  if (Subtarget->isTargetDarwin()) {
513212793Sdim    // All darwin targets use mach-o.
514212793Sdim    const TargetLoweringObjectFileMachO &TLOFMacho =
515212793Sdim      static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
516212793Sdim    MachineModuleInfoMachO &MMIMacho =
517212793Sdim      MMI->getObjFileInfo<MachineModuleInfoMachO>();
518212793Sdim
519212793Sdim    // Output non-lazy-pointers for external and common global variables.
520212793Sdim    MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
521212793Sdim
522212793Sdim    if (!Stubs.empty()) {
523212793Sdim      // Switch with ".non_lazy_symbol_pointer" directive.
524212793Sdim      OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
525212793Sdim      EmitAlignment(2);
526212793Sdim      for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
527212793Sdim        // L_foo$stub:
528212793Sdim        OutStreamer.EmitLabel(Stubs[i].first);
529212793Sdim        //   .indirect_symbol _foo
530212793Sdim        MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
531212793Sdim        OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol);
532212793Sdim
533212793Sdim        if (MCSym.getInt())
534212793Sdim          // External to current translation unit.
535249423Sdim          OutStreamer.EmitIntValue(0, 4/*size*/);
536212793Sdim        else
537212793Sdim          // Internal to current translation unit.
538212793Sdim          //
539218893Sdim          // When we place the LSDA into the TEXT section, the type info
540218893Sdim          // pointers need to be indirect and pc-rel. We accomplish this by
541218893Sdim          // using NLPs; however, sometimes the types are local to the file.
542218893Sdim          // We need to fill in the value for the NLP in those cases.
543212793Sdim          OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
544212793Sdim                                                        OutContext),
545249423Sdim                                4/*size*/);
546212793Sdim      }
547212793Sdim
548212793Sdim      Stubs.clear();
549212793Sdim      OutStreamer.AddBlankLine();
550212793Sdim    }
551212793Sdim
552212793Sdim    Stubs = MMIMacho.GetHiddenGVStubList();
553212793Sdim    if (!Stubs.empty()) {
554212793Sdim      OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
555212793Sdim      EmitAlignment(2);
556212793Sdim      for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
557212793Sdim        // L_foo$stub:
558212793Sdim        OutStreamer.EmitLabel(Stubs[i].first);
559212793Sdim        //   .long _foo
560212793Sdim        OutStreamer.EmitValue(MCSymbolRefExpr::
561212793Sdim                              Create(Stubs[i].second.getPointer(),
562212793Sdim                                     OutContext),
563249423Sdim                              4/*size*/);
564212793Sdim      }
565212793Sdim
566212793Sdim      Stubs.clear();
567212793Sdim      OutStreamer.AddBlankLine();
568212793Sdim    }
569212793Sdim
570212793Sdim    // Funny Darwin hack: This flag tells the linker that no global symbols
571212793Sdim    // contain code that falls through to other global symbols (e.g. the obvious
572212793Sdim    // implementation of multiple entry points).  If this doesn't occur, the
573212793Sdim    // linker can safely perform dead code stripping.  Since LLVM never
574212793Sdim    // generates code that does this, it is always safe to set.
575212793Sdim    OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
576212793Sdim  }
577212793Sdim}
578212793Sdim
579212793Sdim//===----------------------------------------------------------------------===//
580218893Sdim// Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile()
581218893Sdim// FIXME:
582218893Sdim// The following seem like one-off assembler flags, but they actually need
583218893Sdim// to appear in the .ARM.attributes section in ELF.
584218893Sdim// Instead of subclassing the MCELFStreamer, we do the work here.
585212793Sdim
586263508Sdimstatic ARMBuildAttrs::CPUArch getArchForCPU(StringRef CPU,
587263508Sdim                                            const ARMSubtarget *Subtarget) {
588263508Sdim  if (CPU == "xscale")
589263508Sdim    return ARMBuildAttrs::v5TEJ;
590218893Sdim
591263508Sdim  if (Subtarget->hasV8Ops())
592263508Sdim    return ARMBuildAttrs::v8;
593263508Sdim  else if (Subtarget->hasV7Ops()) {
594263508Sdim    if (Subtarget->isMClass() && Subtarget->hasThumb2DSP())
595263508Sdim      return ARMBuildAttrs::v7E_M;
596263508Sdim    return ARMBuildAttrs::v7;
597243830Sdim  } else if (Subtarget->hasV6T2Ops())
598263508Sdim    return ARMBuildAttrs::v6T2;
599263508Sdim  else if (Subtarget->hasV6MOps())
600263508Sdim    return ARMBuildAttrs::v6S_M;
601243830Sdim  else if (Subtarget->hasV6Ops())
602263508Sdim    return ARMBuildAttrs::v6;
603243830Sdim  else if (Subtarget->hasV5TEOps())
604263508Sdim    return ARMBuildAttrs::v5TE;
605243830Sdim  else if (Subtarget->hasV5TOps())
606263508Sdim    return ARMBuildAttrs::v5T;
607243830Sdim  else if (Subtarget->hasV4TOps())
608263508Sdim    return ARMBuildAttrs::v4T;
609263508Sdim  else
610263508Sdim    return ARMBuildAttrs::v4;
611263508Sdim}
612218893Sdim
613263508Sdimvoid ARMAsmPrinter::emitAttributes() {
614263508Sdim  MCTargetStreamer &TS = OutStreamer.getTargetStreamer();
615263508Sdim  ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
616221345Sdim
617263508Sdim  ATS.switchVendor("aeabi");
618234353Sdim
619263508Sdim  std::string CPUString = Subtarget->getCPUString();
620221345Sdim
621263508Sdim  if (CPUString != "generic")
622263508Sdim    ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);
623263508Sdim
624263508Sdim  ATS.emitAttribute(ARMBuildAttrs::CPU_arch,
625263508Sdim                    getArchForCPU(CPUString, Subtarget));
626263508Sdim
627263508Sdim  if (Subtarget->isAClass()) {
628263508Sdim    ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
629263508Sdim                      ARMBuildAttrs::ApplicationProfile);
630263508Sdim  } else if (Subtarget->isRClass()) {
631263508Sdim    ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
632263508Sdim                      ARMBuildAttrs::RealTimeProfile);
633263508Sdim  } else if (Subtarget->isMClass()){
634263508Sdim    ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
635263508Sdim                      ARMBuildAttrs::MicroControllerProfile);
636221345Sdim  }
637218893Sdim
638263508Sdim  ATS.emitAttribute(ARMBuildAttrs::ARM_ISA_use, Subtarget->hasARMOps() ?
639263508Sdim                      ARMBuildAttrs::Allowed : ARMBuildAttrs::Not_Allowed);
640263508Sdim  if (Subtarget->isThumb1Only()) {
641263508Sdim    ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
642263508Sdim                      ARMBuildAttrs::Allowed);
643263508Sdim  } else if (Subtarget->hasThumb2()) {
644263508Sdim    ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
645263508Sdim                      ARMBuildAttrs::AllowThumb32);
646263508Sdim  }
647263508Sdim
648221345Sdim  if (Subtarget->hasNEON()) {
649263508Sdim    /* NEON is not exactly a VFP architecture, but GAS emit one of
650263508Sdim     * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */
651263508Sdim    if (Subtarget->hasFPARMv8()) {
652263508Sdim      if (Subtarget->hasCrypto())
653263508Sdim        ATS.emitFPU(ARM::CRYPTO_NEON_FP_ARMV8);
654263508Sdim      else
655263508Sdim        ATS.emitFPU(ARM::NEON_FP_ARMV8);
656263508Sdim    }
657263508Sdim    else if (Subtarget->hasVFP4())
658263508Sdim      ATS.emitFPU(ARM::NEON_VFPV4);
659263508Sdim    else
660263508Sdim      ATS.emitFPU(ARM::NEON);
661263508Sdim    // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture
662263508Sdim    if (Subtarget->hasV8Ops())
663263508Sdim      ATS.emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
664263508Sdim                        ARMBuildAttrs::AllowNeonARMv8);
665263508Sdim  } else {
666263508Sdim    if (Subtarget->hasFPARMv8())
667263508Sdim      ATS.emitFPU(ARM::FP_ARMV8);
668263508Sdim    else if (Subtarget->hasVFP4())
669263508Sdim      ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV4_D16 : ARM::VFPV4);
670263508Sdim    else if (Subtarget->hasVFP3())
671263508Sdim      ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV3_D16 : ARM::VFPV3);
672263508Sdim    else if (Subtarget->hasVFP2())
673263508Sdim      ATS.emitFPU(ARM::VFPV2);
674221345Sdim  }
675221345Sdim
676218893Sdim  // Signal various FP modes.
677234353Sdim  if (!TM.Options.UnsafeFPMath) {
678263508Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, ARMBuildAttrs::Allowed);
679263508Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions,
680263508Sdim                      ARMBuildAttrs::Allowed);
681218893Sdim  }
682218893Sdim
683234353Sdim  if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath)
684263508Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
685263508Sdim                      ARMBuildAttrs::Allowed);
686218893Sdim  else
687263508Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
688263508Sdim                      ARMBuildAttrs::AllowIEE754);
689218893Sdim
690218893Sdim  // FIXME: add more flags to ARMBuildAttrs.h
691218893Sdim  // 8-bytes alignment stuff.
692263508Sdim  ATS.emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
693263508Sdim  ATS.emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
694218893Sdim
695263508Sdim  // ABI_HardFP_use attribute to indicate single precision FP.
696263508Sdim  if (Subtarget->isFPOnlySP())
697263508Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_HardFP_use,
698263508Sdim                      ARMBuildAttrs::HardFPSinglePrecision);
699263508Sdim
700218893Sdim  // Hard float.  Use both S and D registers and conform to AAPCS-VFP.
701263508Sdim  if (Subtarget->isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard)
702263508Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS);
703263508Sdim
704218893Sdim  // FIXME: Should we signal R9 usage?
705218893Sdim
706263508Sdim  if (Subtarget->hasFP16())
707263508Sdim      ATS.emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP);
708218893Sdim
709263508Sdim  if (Subtarget->hasMPExtension())
710263508Sdim      ATS.emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP);
711263508Sdim
712263508Sdim  if (Subtarget->hasDivide()) {
713263508Sdim    // Check if hardware divide is only available in thumb2 or ARM as well.
714263508Sdim    ATS.emitAttribute(ARMBuildAttrs::DIV_use,
715263508Sdim      Subtarget->hasDivideInARMMode() ? ARMBuildAttrs::AllowDIVExt :
716263508Sdim                                        ARMBuildAttrs::AllowDIVIfExists);
717263508Sdim  }
718263508Sdim
719263508Sdim  if (Subtarget->hasTrustZone() && Subtarget->hasVirtualization())
720263508Sdim      ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
721263508Sdim                        ARMBuildAttrs::AllowTZVirtualization);
722263508Sdim  else if (Subtarget->hasTrustZone())
723263508Sdim      ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
724263508Sdim                        ARMBuildAttrs::AllowTZ);
725263508Sdim  else if (Subtarget->hasVirtualization())
726263508Sdim      ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
727263508Sdim                        ARMBuildAttrs::AllowVirtualization);
728263508Sdim
729263508Sdim  ATS.finishAttributeSection();
730218893Sdim}
731218893Sdim
732218893Sdimvoid ARMAsmPrinter::emitARMAttributeSection() {
733218893Sdim  // <format-version>
734218893Sdim  // [ <section-length> "vendor-name"
735218893Sdim  // [ <file-tag> <size> <attribute>*
736218893Sdim  //   | <section-tag> <size> <section-number>* 0 <attribute>*
737218893Sdim  //   | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
738218893Sdim  //   ]+
739218893Sdim  // ]*
740218893Sdim
741218893Sdim  if (OutStreamer.hasRawTextSupport())
742218893Sdim    return;
743218893Sdim
744218893Sdim  const ARMElfTargetObjectFile &TLOFELF =
745218893Sdim    static_cast<const ARMElfTargetObjectFile &>
746218893Sdim    (getObjFileLowering());
747218893Sdim
748218893Sdim  OutStreamer.SwitchSection(TLOFELF.getAttributesSection());
749218893Sdim
750218893Sdim  // Format version
751218893Sdim  OutStreamer.EmitIntValue(0x41, 1);
752218893Sdim}
753218893Sdim
754218893Sdim//===----------------------------------------------------------------------===//
755218893Sdim
756218893Sdimstatic MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber,
757218893Sdim                             unsigned LabelId, MCContext &Ctx) {
758218893Sdim
759218893Sdim  MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix)
760218893Sdim                       + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
761218893Sdim  return Label;
762218893Sdim}
763218893Sdim
764218893Sdimstatic MCSymbolRefExpr::VariantKind
765218893SdimgetModifierVariantKind(ARMCP::ARMCPModifier Modifier) {
766218893Sdim  switch (Modifier) {
767218893Sdim  case ARMCP::no_modifier: return MCSymbolRefExpr::VK_None;
768218893Sdim  case ARMCP::TLSGD:       return MCSymbolRefExpr::VK_ARM_TLSGD;
769218893Sdim  case ARMCP::TPOFF:       return MCSymbolRefExpr::VK_ARM_TPOFF;
770218893Sdim  case ARMCP::GOTTPOFF:    return MCSymbolRefExpr::VK_ARM_GOTTPOFF;
771218893Sdim  case ARMCP::GOT:         return MCSymbolRefExpr::VK_ARM_GOT;
772218893Sdim  case ARMCP::GOTOFF:      return MCSymbolRefExpr::VK_ARM_GOTOFF;
773218893Sdim  }
774234353Sdim  llvm_unreachable("Invalid ARMCPModifier!");
775218893Sdim}
776218893Sdim
777218893SdimMCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV) {
778218893Sdim  bool isIndirect = Subtarget->isTargetDarwin() &&
779218893Sdim    Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
780218893Sdim  if (!isIndirect)
781263508Sdim    return getSymbol(GV);
782218893Sdim
783218893Sdim  // FIXME: Remove this when Darwin transition to @GOT like syntax.
784218893Sdim  MCSymbol *MCSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
785218893Sdim  MachineModuleInfoMachO &MMIMachO =
786218893Sdim    MMI->getObjFileInfo<MachineModuleInfoMachO>();
787218893Sdim  MachineModuleInfoImpl::StubValueTy &StubSym =
788218893Sdim    GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(MCSym) :
789218893Sdim    MMIMachO.getGVStubEntry(MCSym);
790218893Sdim  if (StubSym.getPointer() == 0)
791218893Sdim    StubSym = MachineModuleInfoImpl::
792263508Sdim      StubValueTy(getSymbol(GV), !GV->hasInternalLinkage());
793218893Sdim  return MCSym;
794218893Sdim}
795218893Sdim
796218893Sdimvoid ARMAsmPrinter::
797218893SdimEmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
798243830Sdim  int Size = TM.getDataLayout()->getTypeAllocSize(MCPV->getType());
799218893Sdim
800218893Sdim  ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
801218893Sdim
802218893Sdim  MCSymbol *MCSym;
803218893Sdim  if (ACPV->isLSDA()) {
804218893Sdim    SmallString<128> Str;
805218893Sdim    raw_svector_ostream OS(Str);
806218893Sdim    OS << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber();
807218893Sdim    MCSym = OutContext.GetOrCreateSymbol(OS.str());
808218893Sdim  } else if (ACPV->isBlockAddress()) {
809226633Sdim    const BlockAddress *BA =
810226633Sdim      cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress();
811226633Sdim    MCSym = GetBlockAddressSymbol(BA);
812218893Sdim  } else if (ACPV->isGlobalValue()) {
813226633Sdim    const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV();
814218893Sdim    MCSym = GetARMGVSymbol(GV);
815226633Sdim  } else if (ACPV->isMachineBasicBlock()) {
816226633Sdim    const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
817226633Sdim    MCSym = MBB->getSymbol();
818218893Sdim  } else {
819218893Sdim    assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
820226633Sdim    const char *Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol();
821226633Sdim    MCSym = GetExternalSymbolSymbol(Sym);
822218893Sdim  }
823218893Sdim
824218893Sdim  // Create an MCSymbol for the reference.
825218893Sdim  const MCExpr *Expr =
826218893Sdim    MCSymbolRefExpr::Create(MCSym, getModifierVariantKind(ACPV->getModifier()),
827218893Sdim                            OutContext);
828218893Sdim
829218893Sdim  if (ACPV->getPCAdjustment()) {
830218893Sdim    MCSymbol *PCLabel = getPICLabel(MAI->getPrivateGlobalPrefix(),
831218893Sdim                                    getFunctionNumber(),
832218893Sdim                                    ACPV->getLabelId(),
833218893Sdim                                    OutContext);
834218893Sdim    const MCExpr *PCRelExpr = MCSymbolRefExpr::Create(PCLabel, OutContext);
835218893Sdim    PCRelExpr =
836218893Sdim      MCBinaryExpr::CreateAdd(PCRelExpr,
837218893Sdim                              MCConstantExpr::Create(ACPV->getPCAdjustment(),
838218893Sdim                                                     OutContext),
839218893Sdim                              OutContext);
840218893Sdim    if (ACPV->mustAddCurrentAddress()) {
841218893Sdim      // We want "(<expr> - .)", but MC doesn't have a concept of the '.'
842218893Sdim      // label, so just emit a local label end reference that instead.
843218893Sdim      MCSymbol *DotSym = OutContext.CreateTempSymbol();
844218893Sdim      OutStreamer.EmitLabel(DotSym);
845218893Sdim      const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext);
846218893Sdim      PCRelExpr = MCBinaryExpr::CreateSub(PCRelExpr, DotExpr, OutContext);
847218893Sdim    }
848218893Sdim    Expr = MCBinaryExpr::CreateSub(Expr, PCRelExpr, OutContext);
849218893Sdim  }
850218893Sdim  OutStreamer.EmitValue(Expr, Size);
851218893Sdim}
852218893Sdim
853218893Sdimvoid ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
854218893Sdim  unsigned Opcode = MI->getOpcode();
855218893Sdim  int OpNum = 1;
856218893Sdim  if (Opcode == ARM::BR_JTadd)
857218893Sdim    OpNum = 2;
858218893Sdim  else if (Opcode == ARM::BR_JTm)
859218893Sdim    OpNum = 3;
860218893Sdim
861218893Sdim  const MachineOperand &MO1 = MI->getOperand(OpNum);
862218893Sdim  const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
863218893Sdim  unsigned JTI = MO1.getIndex();
864218893Sdim
865218893Sdim  // Emit a label for the jump table.
866218893Sdim  MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
867218893Sdim  OutStreamer.EmitLabel(JTISymbol);
868218893Sdim
869239462Sdim  // Mark the jump table as data-in-code.
870239462Sdim  OutStreamer.EmitDataRegion(MCDR_DataRegionJT32);
871239462Sdim
872218893Sdim  // Emit each entry of the table.
873218893Sdim  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
874218893Sdim  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
875218893Sdim  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
876218893Sdim
877218893Sdim  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
878218893Sdim    MachineBasicBlock *MBB = JTBBs[i];
879218893Sdim    // Construct an MCExpr for the entry. We want a value of the form:
880218893Sdim    // (BasicBlockAddr - TableBeginAddr)
881218893Sdim    //
882218893Sdim    // For example, a table with entries jumping to basic blocks BB0 and BB1
883218893Sdim    // would look like:
884218893Sdim    // LJTI_0_0:
885218893Sdim    //    .word (LBB0 - LJTI_0_0)
886218893Sdim    //    .word (LBB1 - LJTI_0_0)
887218893Sdim    const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
888218893Sdim
889218893Sdim    if (TM.getRelocationModel() == Reloc::PIC_)
890218893Sdim      Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol,
891218893Sdim                                                                   OutContext),
892218893Sdim                                     OutContext);
893226633Sdim    // If we're generating a table of Thumb addresses in static relocation
894226633Sdim    // model, we need to add one to keep interworking correctly.
895226633Sdim    else if (AFI->isThumbFunction())
896226633Sdim      Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(1,OutContext),
897226633Sdim                                     OutContext);
898218893Sdim    OutStreamer.EmitValue(Expr, 4);
899218893Sdim  }
900239462Sdim  // Mark the end of jump table data-in-code region.
901239462Sdim  OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
902218893Sdim}
903218893Sdim
904218893Sdimvoid ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
905218893Sdim  unsigned Opcode = MI->getOpcode();
906218893Sdim  int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1;
907218893Sdim  const MachineOperand &MO1 = MI->getOperand(OpNum);
908218893Sdim  const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
909218893Sdim  unsigned JTI = MO1.getIndex();
910218893Sdim
911218893Sdim  MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
912218893Sdim  OutStreamer.EmitLabel(JTISymbol);
913218893Sdim
914218893Sdim  // Emit each entry of the table.
915218893Sdim  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
916218893Sdim  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
917218893Sdim  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
918218893Sdim  unsigned OffsetWidth = 4;
919239462Sdim  if (MI->getOpcode() == ARM::t2TBB_JT) {
920218893Sdim    OffsetWidth = 1;
921239462Sdim    // Mark the jump table as data-in-code.
922239462Sdim    OutStreamer.EmitDataRegion(MCDR_DataRegionJT8);
923239462Sdim  } else if (MI->getOpcode() == ARM::t2TBH_JT) {
924218893Sdim    OffsetWidth = 2;
925239462Sdim    // Mark the jump table as data-in-code.
926239462Sdim    OutStreamer.EmitDataRegion(MCDR_DataRegionJT16);
927239462Sdim  }
928218893Sdim
929218893Sdim  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
930218893Sdim    MachineBasicBlock *MBB = JTBBs[i];
931218893Sdim    const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(),
932218893Sdim                                                      OutContext);
933218893Sdim    // If this isn't a TBB or TBH, the entries are direct branch instructions.
934218893Sdim    if (OffsetWidth == 4) {
935249423Sdim      OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2B)
936249423Sdim        .addExpr(MBBSymbolExpr)
937249423Sdim        .addImm(ARMCC::AL)
938249423Sdim        .addReg(0));
939218893Sdim      continue;
940218893Sdim    }
941218893Sdim    // Otherwise it's an offset from the dispatch instruction. Construct an
942218893Sdim    // MCExpr for the entry. We want a value of the form:
943218893Sdim    // (BasicBlockAddr - TableBeginAddr) / 2
944218893Sdim    //
945218893Sdim    // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
946218893Sdim    // would look like:
947218893Sdim    // LJTI_0_0:
948218893Sdim    //    .byte (LBB0 - LJTI_0_0) / 2
949218893Sdim    //    .byte (LBB1 - LJTI_0_0) / 2
950218893Sdim    const MCExpr *Expr =
951218893Sdim      MCBinaryExpr::CreateSub(MBBSymbolExpr,
952218893Sdim                              MCSymbolRefExpr::Create(JTISymbol, OutContext),
953218893Sdim                              OutContext);
954218893Sdim    Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext),
955218893Sdim                                   OutContext);
956218893Sdim    OutStreamer.EmitValue(Expr, OffsetWidth);
957218893Sdim  }
958239462Sdim  // Mark the end of jump table data-in-code region. 32-bit offsets use
959239462Sdim  // actual branch instructions here, so we don't mark those as a data-region
960239462Sdim  // at all.
961239462Sdim  if (OffsetWidth != 4)
962239462Sdim    OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
963218893Sdim}
964218893Sdim
965221345Sdimvoid ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
966221345Sdim  assert(MI->getFlag(MachineInstr::FrameSetup) &&
967221345Sdim      "Only instruction which are involved into frame setup code are allowed");
968221345Sdim
969263508Sdim  MCTargetStreamer &TS = OutStreamer.getTargetStreamer();
970263508Sdim  ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
971221345Sdim  const MachineFunction &MF = *MI->getParent()->getParent();
972221345Sdim  const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
973221345Sdim  const ARMFunctionInfo &AFI = *MF.getInfo<ARMFunctionInfo>();
974221345Sdim
975221345Sdim  unsigned FramePtr = RegInfo->getFrameRegister(MF);
976221345Sdim  unsigned Opc = MI->getOpcode();
977221345Sdim  unsigned SrcReg, DstReg;
978221345Sdim
979221345Sdim  if (Opc == ARM::tPUSH || Opc == ARM::tLDRpci) {
980221345Sdim    // Two special cases:
981221345Sdim    // 1) tPUSH does not have src/dst regs.
982221345Sdim    // 2) for Thumb1 code we sometimes materialize the constant via constpool
983221345Sdim    // load. Yes, this is pretty fragile, but for now I don't see better
984221345Sdim    // way... :(
985221345Sdim    SrcReg = DstReg = ARM::SP;
986221345Sdim  } else {
987221345Sdim    SrcReg = MI->getOperand(1).getReg();
988221345Sdim    DstReg = MI->getOperand(0).getReg();
989221345Sdim  }
990221345Sdim
991221345Sdim  // Try to figure out the unwinding opcode out of src / dst regs.
992234353Sdim  if (MI->mayStore()) {
993221345Sdim    // Register saves.
994221345Sdim    assert(DstReg == ARM::SP &&
995221345Sdim           "Only stack pointer as a destination reg is supported");
996221345Sdim
997221345Sdim    SmallVector<unsigned, 4> RegList;
998221345Sdim    // Skip src & dst reg, and pred ops.
999221345Sdim    unsigned StartOp = 2 + 2;
1000221345Sdim    // Use all the operands.
1001221345Sdim    unsigned NumOffset = 0;
1002221345Sdim
1003221345Sdim    switch (Opc) {
1004221345Sdim    default:
1005221345Sdim      MI->dump();
1006234353Sdim      llvm_unreachable("Unsupported opcode for unwinding information");
1007221345Sdim    case ARM::tPUSH:
1008221345Sdim      // Special case here: no src & dst reg, but two extra imp ops.
1009221345Sdim      StartOp = 2; NumOffset = 2;
1010221345Sdim    case ARM::STMDB_UPD:
1011221345Sdim    case ARM::t2STMDB_UPD:
1012221345Sdim    case ARM::VSTMDDB_UPD:
1013221345Sdim      assert(SrcReg == ARM::SP &&
1014221345Sdim             "Only stack pointer as a source reg is supported");
1015221345Sdim      for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset;
1016239462Sdim           i != NumOps; ++i) {
1017239462Sdim        const MachineOperand &MO = MI->getOperand(i);
1018239462Sdim        // Actually, there should never be any impdef stuff here. Skip it
1019239462Sdim        // temporary to workaround PR11902.
1020239462Sdim        if (MO.isImplicit())
1021239462Sdim          continue;
1022239462Sdim        RegList.push_back(MO.getReg());
1023239462Sdim      }
1024221345Sdim      break;
1025226633Sdim    case ARM::STR_PRE_IMM:
1026226633Sdim    case ARM::STR_PRE_REG:
1027234353Sdim    case ARM::t2STR_PRE:
1028221345Sdim      assert(MI->getOperand(2).getReg() == ARM::SP &&
1029221345Sdim             "Only stack pointer as a source reg is supported");
1030221345Sdim      RegList.push_back(SrcReg);
1031221345Sdim      break;
1032221345Sdim    }
1033263508Sdim    ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD);
1034221345Sdim  } else {
1035221345Sdim    // Changes of stack / frame pointer.
1036221345Sdim    if (SrcReg == ARM::SP) {
1037221345Sdim      int64_t Offset = 0;
1038221345Sdim      switch (Opc) {
1039221345Sdim      default:
1040221345Sdim        MI->dump();
1041234353Sdim        llvm_unreachable("Unsupported opcode for unwinding information");
1042221345Sdim      case ARM::MOVr:
1043234353Sdim      case ARM::tMOVr:
1044221345Sdim        Offset = 0;
1045221345Sdim        break;
1046221345Sdim      case ARM::ADDri:
1047221345Sdim        Offset = -MI->getOperand(2).getImm();
1048221345Sdim        break;
1049221345Sdim      case ARM::SUBri:
1050234353Sdim      case ARM::t2SUBri:
1051224145Sdim        Offset = MI->getOperand(2).getImm();
1052221345Sdim        break;
1053221345Sdim      case ARM::tSUBspi:
1054224145Sdim        Offset = MI->getOperand(2).getImm()*4;
1055221345Sdim        break;
1056221345Sdim      case ARM::tADDspi:
1057221345Sdim      case ARM::tADDrSPi:
1058221345Sdim        Offset = -MI->getOperand(2).getImm()*4;
1059221345Sdim        break;
1060221345Sdim      case ARM::tLDRpci: {
1061221345Sdim        // Grab the constpool index and check, whether it corresponds to
1062221345Sdim        // original or cloned constpool entry.
1063221345Sdim        unsigned CPI = MI->getOperand(1).getIndex();
1064221345Sdim        const MachineConstantPool *MCP = MF.getConstantPool();
1065221345Sdim        if (CPI >= MCP->getConstants().size())
1066221345Sdim          CPI = AFI.getOriginalCPIdx(CPI);
1067221345Sdim        assert(CPI != -1U && "Invalid constpool index");
1068221345Sdim
1069221345Sdim        // Derive the actual offset.
1070221345Sdim        const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
1071221345Sdim        assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry");
1072221345Sdim        // FIXME: Check for user, it should be "add" instruction!
1073221345Sdim        Offset = -cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue();
1074221345Sdim        break;
1075221345Sdim      }
1076221345Sdim      }
1077221345Sdim
1078221345Sdim      if (DstReg == FramePtr && FramePtr != ARM::SP)
1079221345Sdim        // Set-up of the frame pointer. Positive values correspond to "add"
1080221345Sdim        // instruction.
1081263508Sdim        ATS.emitSetFP(FramePtr, ARM::SP, -Offset);
1082221345Sdim      else if (DstReg == ARM::SP) {
1083221345Sdim        // Change of SP by an offset. Positive values correspond to "sub"
1084221345Sdim        // instruction.
1085263508Sdim        ATS.emitPad(Offset);
1086221345Sdim      } else {
1087221345Sdim        MI->dump();
1088234353Sdim        llvm_unreachable("Unsupported opcode for unwinding information");
1089221345Sdim      }
1090221345Sdim    } else if (DstReg == ARM::SP) {
1091221345Sdim      // FIXME: .movsp goes here
1092221345Sdim      MI->dump();
1093234353Sdim      llvm_unreachable("Unsupported opcode for unwinding information");
1094221345Sdim    }
1095221345Sdim    else {
1096221345Sdim      MI->dump();
1097234353Sdim      llvm_unreachable("Unsupported opcode for unwinding information");
1098221345Sdim    }
1099221345Sdim  }
1100221345Sdim}
1101221345Sdim
1102221345Sdimextern cl::opt<bool> EnableARMEHABI;
1103221345Sdim
1104224145Sdim// Simple pseudo-instructions have their lowering (with expansion to real
1105224145Sdim// instructions) auto-generated.
1106224145Sdim#include "ARMGenMCPseudoLowering.inc"
1107224145Sdim
1108218893Sdimvoid ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
1109239462Sdim  // If we just ended a constant pool, mark it as such.
1110239462Sdim  if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
1111239462Sdim    OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
1112239462Sdim    InConstantPool = false;
1113239462Sdim  }
1114226633Sdim
1115226633Sdim  // Emit unwinding stuff for frame-related instructions
1116226633Sdim  if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup))
1117226633Sdim    EmitUnwindingInstruction(MI);
1118226633Sdim
1119224145Sdim  // Do any auto-generated pseudo lowerings.
1120224145Sdim  if (emitPseudoExpansionLowering(OutStreamer, MI))
1121224145Sdim    return;
1122224145Sdim
1123226633Sdim  assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&
1124226633Sdim         "Pseudo flag setting opcode should be expanded early");
1125226633Sdim
1126224145Sdim  // Check for manual lowerings.
1127218893Sdim  unsigned Opc = MI->getOpcode();
1128218893Sdim  switch (Opc) {
1129234353Sdim  case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");
1130263508Sdim  case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing");
1131218893Sdim  case ARM::LEApcrel:
1132218893Sdim  case ARM::tLEApcrel:
1133218893Sdim  case ARM::t2LEApcrel: {
1134218893Sdim    // FIXME: Need to also handle globals and externals
1135249423Sdim    MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex());
1136249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() ==
1137249423Sdim                                              ARM::t2LEApcrel ? ARM::t2ADR
1138249423Sdim                  : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
1139249423Sdim                     : ARM::ADR))
1140249423Sdim      .addReg(MI->getOperand(0).getReg())
1141249423Sdim      .addExpr(MCSymbolRefExpr::Create(CPISymbol, OutContext))
1142249423Sdim      // Add predicate operands.
1143249423Sdim      .addImm(MI->getOperand(2).getImm())
1144249423Sdim      .addReg(MI->getOperand(3).getReg()));
1145218893Sdim    return;
1146218893Sdim  }
1147218893Sdim  case ARM::LEApcrelJT:
1148218893Sdim  case ARM::tLEApcrelJT:
1149218893Sdim  case ARM::t2LEApcrelJT: {
1150249423Sdim    MCSymbol *JTIPICSymbol =
1151249423Sdim      GetARMJTIPICJumpTableLabel2(MI->getOperand(1).getIndex(),
1152249423Sdim                                  MI->getOperand(2).getImm());
1153249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() ==
1154249423Sdim                                              ARM::t2LEApcrelJT ? ARM::t2ADR
1155249423Sdim                  : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
1156249423Sdim                     : ARM::ADR))
1157249423Sdim      .addReg(MI->getOperand(0).getReg())
1158249423Sdim      .addExpr(MCSymbolRefExpr::Create(JTIPICSymbol, OutContext))
1159249423Sdim      // Add predicate operands.
1160249423Sdim      .addImm(MI->getOperand(3).getImm())
1161249423Sdim      .addReg(MI->getOperand(4).getReg()));
1162218893Sdim    return;
1163218893Sdim  }
1164221345Sdim  // Darwin call instructions are just normal call instructions with different
1165221345Sdim  // clobber semantics (they clobber R9).
1166218893Sdim  case ARM::BX_CALL: {
1167249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
1168249423Sdim      .addReg(ARM::LR)
1169249423Sdim      .addReg(ARM::PC)
1170218893Sdim      // Add predicate operands.
1171249423Sdim      .addImm(ARMCC::AL)
1172249423Sdim      .addReg(0)
1173218893Sdim      // Add 's' bit operand (always reg0 for this)
1174249423Sdim      .addReg(0));
1175249423Sdim
1176249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX)
1177249423Sdim      .addReg(MI->getOperand(0).getReg()));
1178218893Sdim    return;
1179218893Sdim  }
1180223017Sdim  case ARM::tBX_CALL: {
1181249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
1182249423Sdim      .addReg(ARM::LR)
1183249423Sdim      .addReg(ARM::PC)
1184224145Sdim      // Add predicate operands.
1185249423Sdim      .addImm(ARMCC::AL)
1186249423Sdim      .addReg(0));
1187249423Sdim
1188249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX)
1189249423Sdim      .addReg(MI->getOperand(0).getReg())
1190223017Sdim      // Add predicate operands.
1191249423Sdim      .addImm(ARMCC::AL)
1192249423Sdim      .addReg(0));
1193223017Sdim    return;
1194223017Sdim  }
1195218893Sdim  case ARM::BMOVPCRX_CALL: {
1196249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
1197249423Sdim      .addReg(ARM::LR)
1198249423Sdim      .addReg(ARM::PC)
1199218893Sdim      // Add predicate operands.
1200249423Sdim      .addImm(ARMCC::AL)
1201249423Sdim      .addReg(0)
1202218893Sdim      // Add 's' bit operand (always reg0 for this)
1203249423Sdim      .addReg(0));
1204249423Sdim
1205249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
1206249423Sdim      .addReg(ARM::PC)
1207249423Sdim      .addReg(MI->getOperand(0).getReg())
1208218893Sdim      // Add predicate operands.
1209249423Sdim      .addImm(ARMCC::AL)
1210249423Sdim      .addReg(0)
1211218893Sdim      // Add 's' bit operand (always reg0 for this)
1212249423Sdim      .addReg(0));
1213218893Sdim    return;
1214218893Sdim  }
1215234353Sdim  case ARM::BMOVPCB_CALL: {
1216249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
1217249423Sdim      .addReg(ARM::LR)
1218249423Sdim      .addReg(ARM::PC)
1219234353Sdim      // Add predicate operands.
1220249423Sdim      .addImm(ARMCC::AL)
1221249423Sdim      .addReg(0)
1222234353Sdim      // Add 's' bit operand (always reg0 for this)
1223249423Sdim      .addReg(0));
1224249423Sdim
1225249423Sdim    const GlobalValue *GV = MI->getOperand(0).getGlobal();
1226263508Sdim    MCSymbol *GVSym = getSymbol(GV);
1227249423Sdim    const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
1228249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::Bcc)
1229249423Sdim      .addExpr(GVSymExpr)
1230234353Sdim      // Add predicate operands.
1231249423Sdim      .addImm(ARMCC::AL)
1232249423Sdim      .addReg(0));
1233234353Sdim    return;
1234234353Sdim  }
1235218893Sdim  case ARM::MOVi16_ga_pcrel:
1236218893Sdim  case ARM::t2MOVi16_ga_pcrel: {
1237218893Sdim    MCInst TmpInst;
1238218893Sdim    TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16);
1239218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1240218893Sdim
1241218893Sdim    unsigned TF = MI->getOperand(1).getTargetFlags();
1242218893Sdim    bool isPIC = TF == ARMII::MO_LO16_NONLAZY_PIC;
1243218893Sdim    const GlobalValue *GV = MI->getOperand(1).getGlobal();
1244218893Sdim    MCSymbol *GVSym = GetARMGVSymbol(GV);
1245218893Sdim    const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
1246218893Sdim    if (isPIC) {
1247218893Sdim      MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(),
1248218893Sdim                                       getFunctionNumber(),
1249218893Sdim                                       MI->getOperand(2).getImm(), OutContext);
1250218893Sdim      const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext);
1251218893Sdim      unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
1252218893Sdim      const MCExpr *PCRelExpr =
1253218893Sdim        ARMMCExpr::CreateLower16(MCBinaryExpr::CreateSub(GVSymExpr,
1254218893Sdim                                  MCBinaryExpr::CreateAdd(LabelSymExpr,
1255218893Sdim                                      MCConstantExpr::Create(PCAdj, OutContext),
1256218893Sdim                                          OutContext), OutContext), OutContext);
1257218893Sdim      TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr));
1258218893Sdim    } else {
1259218893Sdim      const MCExpr *RefExpr= ARMMCExpr::CreateLower16(GVSymExpr, OutContext);
1260218893Sdim      TmpInst.addOperand(MCOperand::CreateExpr(RefExpr));
1261218893Sdim    }
1262218893Sdim
1263218893Sdim    // Add predicate operands.
1264218893Sdim    TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1265218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(0));
1266218893Sdim    // Add 's' bit operand (always reg0 for this)
1267218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(0));
1268218893Sdim    OutStreamer.EmitInstruction(TmpInst);
1269218893Sdim    return;
1270218893Sdim  }
1271218893Sdim  case ARM::MOVTi16_ga_pcrel:
1272218893Sdim  case ARM::t2MOVTi16_ga_pcrel: {
1273218893Sdim    MCInst TmpInst;
1274218893Sdim    TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel
1275218893Sdim                      ? ARM::MOVTi16 : ARM::t2MOVTi16);
1276218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1277218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
1278218893Sdim
1279218893Sdim    unsigned TF = MI->getOperand(2).getTargetFlags();
1280218893Sdim    bool isPIC = TF == ARMII::MO_HI16_NONLAZY_PIC;
1281218893Sdim    const GlobalValue *GV = MI->getOperand(2).getGlobal();
1282218893Sdim    MCSymbol *GVSym = GetARMGVSymbol(GV);
1283218893Sdim    const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
1284218893Sdim    if (isPIC) {
1285218893Sdim      MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(),
1286218893Sdim                                       getFunctionNumber(),
1287218893Sdim                                       MI->getOperand(3).getImm(), OutContext);
1288218893Sdim      const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext);
1289218893Sdim      unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
1290218893Sdim      const MCExpr *PCRelExpr =
1291218893Sdim        ARMMCExpr::CreateUpper16(MCBinaryExpr::CreateSub(GVSymExpr,
1292218893Sdim                                   MCBinaryExpr::CreateAdd(LabelSymExpr,
1293218893Sdim                                      MCConstantExpr::Create(PCAdj, OutContext),
1294218893Sdim                                          OutContext), OutContext), OutContext);
1295218893Sdim      TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr));
1296218893Sdim    } else {
1297218893Sdim      const MCExpr *RefExpr= ARMMCExpr::CreateUpper16(GVSymExpr, OutContext);
1298218893Sdim      TmpInst.addOperand(MCOperand::CreateExpr(RefExpr));
1299218893Sdim    }
1300218893Sdim    // Add predicate operands.
1301218893Sdim    TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1302218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(0));
1303218893Sdim    // Add 's' bit operand (always reg0 for this)
1304218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(0));
1305218893Sdim    OutStreamer.EmitInstruction(TmpInst);
1306218893Sdim    return;
1307218893Sdim  }
1308218893Sdim  case ARM::tPICADD: {
1309212793Sdim    // This is a pseudo op for a label + instruction sequence, which looks like:
1310212793Sdim    // LPC0:
1311218893Sdim    //     add r0, pc
1312218893Sdim    // This adds the address of LPC0 to r0.
1313218893Sdim
1314218893Sdim    // Emit the label.
1315218893Sdim    OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
1316218893Sdim                          getFunctionNumber(), MI->getOperand(2).getImm(),
1317218893Sdim                          OutContext));
1318218893Sdim
1319218893Sdim    // Form and emit the add.
1320249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDhirr)
1321249423Sdim      .addReg(MI->getOperand(0).getReg())
1322249423Sdim      .addReg(MI->getOperand(0).getReg())
1323249423Sdim      .addReg(ARM::PC)
1324249423Sdim      // Add predicate operands.
1325249423Sdim      .addImm(ARMCC::AL)
1326249423Sdim      .addReg(0));
1327218893Sdim    return;
1328218893Sdim  }
1329218893Sdim  case ARM::PICADD: {
1330218893Sdim    // This is a pseudo op for a label + instruction sequence, which looks like:
1331218893Sdim    // LPC0:
1332212793Sdim    //     add r0, pc, r0
1333212793Sdim    // This adds the address of LPC0 to r0.
1334212793Sdim
1335212793Sdim    // Emit the label.
1336218893Sdim    OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
1337218893Sdim                          getFunctionNumber(), MI->getOperand(2).getImm(),
1338218893Sdim                          OutContext));
1339212793Sdim
1340218893Sdim    // Form and emit the add.
1341249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr)
1342249423Sdim      .addReg(MI->getOperand(0).getReg())
1343249423Sdim      .addReg(ARM::PC)
1344249423Sdim      .addReg(MI->getOperand(1).getReg())
1345249423Sdim      // Add predicate operands.
1346249423Sdim      .addImm(MI->getOperand(3).getImm())
1347249423Sdim      .addReg(MI->getOperand(4).getReg())
1348249423Sdim      // Add 's' bit operand (always reg0 for this)
1349249423Sdim      .addReg(0));
1350212793Sdim    return;
1351212793Sdim  }
1352218893Sdim  case ARM::PICSTR:
1353218893Sdim  case ARM::PICSTRB:
1354218893Sdim  case ARM::PICSTRH:
1355218893Sdim  case ARM::PICLDR:
1356218893Sdim  case ARM::PICLDRB:
1357218893Sdim  case ARM::PICLDRH:
1358218893Sdim  case ARM::PICLDRSB:
1359218893Sdim  case ARM::PICLDRSH: {
1360218893Sdim    // This is a pseudo op for a label + instruction sequence, which looks like:
1361218893Sdim    // LPC0:
1362218893Sdim    //     OP r0, [pc, r0]
1363218893Sdim    // The LCP0 label is referenced by a constant pool entry in order to get
1364218893Sdim    // a PC-relative address at the ldr instruction.
1365218893Sdim
1366218893Sdim    // Emit the label.
1367218893Sdim    OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
1368218893Sdim                          getFunctionNumber(), MI->getOperand(2).getImm(),
1369218893Sdim                          OutContext));
1370218893Sdim
1371218893Sdim    // Form and emit the load
1372218893Sdim    unsigned Opcode;
1373218893Sdim    switch (MI->getOpcode()) {
1374218893Sdim    default:
1375218893Sdim      llvm_unreachable("Unexpected opcode!");
1376218893Sdim    case ARM::PICSTR:   Opcode = ARM::STRrs; break;
1377218893Sdim    case ARM::PICSTRB:  Opcode = ARM::STRBrs; break;
1378218893Sdim    case ARM::PICSTRH:  Opcode = ARM::STRH; break;
1379218893Sdim    case ARM::PICLDR:   Opcode = ARM::LDRrs; break;
1380218893Sdim    case ARM::PICLDRB:  Opcode = ARM::LDRBrs; break;
1381218893Sdim    case ARM::PICLDRH:  Opcode = ARM::LDRH; break;
1382218893Sdim    case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
1383218893Sdim    case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
1384218893Sdim    }
1385249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(Opcode)
1386249423Sdim      .addReg(MI->getOperand(0).getReg())
1387249423Sdim      .addReg(ARM::PC)
1388249423Sdim      .addReg(MI->getOperand(1).getReg())
1389249423Sdim      .addImm(0)
1390249423Sdim      // Add predicate operands.
1391249423Sdim      .addImm(MI->getOperand(3).getImm())
1392249423Sdim      .addReg(MI->getOperand(4).getReg()));
1393218893Sdim
1394218893Sdim    return;
1395218893Sdim  }
1396218893Sdim  case ARM::CONSTPOOL_ENTRY: {
1397212793Sdim    /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
1398212793Sdim    /// in the function.  The first operand is the ID# for this instruction, the
1399212793Sdim    /// second is the index into the MachineConstantPool that this is, the third
1400212793Sdim    /// is the size in bytes of this constant pool entry.
1401234353Sdim    /// The required alignment is specified on the basic block holding this MI.
1402212793Sdim    unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
1403212793Sdim    unsigned CPIdx   = (unsigned)MI->getOperand(1).getIndex();
1404212793Sdim
1405239462Sdim    // If this is the first entry of the pool, mark it.
1406239462Sdim    if (!InConstantPool) {
1407239462Sdim      OutStreamer.EmitDataRegion(MCDR_DataRegion);
1408239462Sdim      InConstantPool = true;
1409239462Sdim    }
1410239462Sdim
1411212793Sdim    OutStreamer.EmitLabel(GetCPISymbol(LabelId));
1412212793Sdim
1413212793Sdim    const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
1414212793Sdim    if (MCPE.isMachineConstantPoolEntry())
1415212793Sdim      EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
1416212793Sdim    else
1417212793Sdim      EmitGlobalConstant(MCPE.Val.ConstVal);
1418212793Sdim    return;
1419212793Sdim  }
1420218893Sdim  case ARM::t2BR_JT: {
1421218893Sdim    // Lower and emit the instruction itself, then the jump table following it.
1422249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
1423249423Sdim      .addReg(ARM::PC)
1424249423Sdim      .addReg(MI->getOperand(0).getReg())
1425249423Sdim      // Add predicate operands.
1426249423Sdim      .addImm(ARMCC::AL)
1427249423Sdim      .addReg(0));
1428249423Sdim
1429218893Sdim    // Output the data for the jump table itself
1430218893Sdim    EmitJump2Table(MI);
1431218893Sdim    return;
1432218893Sdim  }
1433218893Sdim  case ARM::t2TBB_JT: {
1434218893Sdim    // Lower and emit the instruction itself, then the jump table following it.
1435249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBB)
1436249423Sdim      .addReg(ARM::PC)
1437249423Sdim      .addReg(MI->getOperand(0).getReg())
1438249423Sdim      // Add predicate operands.
1439249423Sdim      .addImm(ARMCC::AL)
1440249423Sdim      .addReg(0));
1441212793Sdim
1442218893Sdim    // Output the data for the jump table itself
1443218893Sdim    EmitJump2Table(MI);
1444218893Sdim    // Make sure the next instruction is 2-byte aligned.
1445218893Sdim    EmitAlignment(1);
1446218893Sdim    return;
1447218893Sdim  }
1448218893Sdim  case ARM::t2TBH_JT: {
1449218893Sdim    // Lower and emit the instruction itself, then the jump table following it.
1450249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBH)
1451249423Sdim      .addReg(ARM::PC)
1452249423Sdim      .addReg(MI->getOperand(0).getReg())
1453249423Sdim      // Add predicate operands.
1454249423Sdim      .addImm(ARMCC::AL)
1455249423Sdim      .addReg(0));
1456212793Sdim
1457218893Sdim    // Output the data for the jump table itself
1458218893Sdim    EmitJump2Table(MI);
1459218893Sdim    return;
1460218893Sdim  }
1461218893Sdim  case ARM::tBR_JTr:
1462218893Sdim  case ARM::BR_JTr: {
1463218893Sdim    // Lower and emit the instruction itself, then the jump table following it.
1464218893Sdim    // mov pc, target
1465218893Sdim    MCInst TmpInst;
1466218893Sdim    unsigned Opc = MI->getOpcode() == ARM::BR_JTr ?
1467224145Sdim      ARM::MOVr : ARM::tMOVr;
1468218893Sdim    TmpInst.setOpcode(Opc);
1469218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1470218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1471218893Sdim    // Add predicate operands.
1472218893Sdim    TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1473218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(0));
1474218893Sdim    // Add 's' bit operand (always reg0 for this)
1475218893Sdim    if (Opc == ARM::MOVr)
1476218893Sdim      TmpInst.addOperand(MCOperand::CreateReg(0));
1477218893Sdim    OutStreamer.EmitInstruction(TmpInst);
1478212793Sdim
1479218893Sdim    // Make sure the Thumb jump table is 4-byte aligned.
1480224145Sdim    if (Opc == ARM::tMOVr)
1481218893Sdim      EmitAlignment(2);
1482218893Sdim
1483218893Sdim    // Output the data for the jump table itself
1484218893Sdim    EmitJumpTable(MI);
1485218893Sdim    return;
1486218893Sdim  }
1487218893Sdim  case ARM::BR_JTm: {
1488218893Sdim    // Lower and emit the instruction itself, then the jump table following it.
1489218893Sdim    // ldr pc, target
1490218893Sdim    MCInst TmpInst;
1491218893Sdim    if (MI->getOperand(1).getReg() == 0) {
1492218893Sdim      // literal offset
1493218893Sdim      TmpInst.setOpcode(ARM::LDRi12);
1494218893Sdim      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1495218893Sdim      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1496212793Sdim      TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1497218893Sdim    } else {
1498218893Sdim      TmpInst.setOpcode(ARM::LDRrs);
1499218893Sdim      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1500218893Sdim      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1501218893Sdim      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
1502218893Sdim      TmpInst.addOperand(MCOperand::CreateImm(0));
1503218893Sdim    }
1504218893Sdim    // Add predicate operands.
1505218893Sdim    TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1506218893Sdim    TmpInst.addOperand(MCOperand::CreateReg(0));
1507218893Sdim    OutStreamer.EmitInstruction(TmpInst);
1508212793Sdim
1509218893Sdim    // Output the data for the jump table itself
1510218893Sdim    EmitJumpTable(MI);
1511218893Sdim    return;
1512218893Sdim  }
1513218893Sdim  case ARM::BR_JTadd: {
1514218893Sdim    // Lower and emit the instruction itself, then the jump table following it.
1515218893Sdim    // add pc, target, idx
1516249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr)
1517249423Sdim      .addReg(ARM::PC)
1518249423Sdim      .addReg(MI->getOperand(0).getReg())
1519249423Sdim      .addReg(MI->getOperand(1).getReg())
1520249423Sdim      // Add predicate operands.
1521249423Sdim      .addImm(ARMCC::AL)
1522249423Sdim      .addReg(0)
1523249423Sdim      // Add 's' bit operand (always reg0 for this)
1524249423Sdim      .addReg(0));
1525218893Sdim
1526218893Sdim    // Output the data for the jump table itself
1527218893Sdim    EmitJumpTable(MI);
1528218893Sdim    return;
1529218893Sdim  }
1530218893Sdim  case ARM::TRAP: {
1531218893Sdim    // Non-Darwin binutils don't yet support the "trap" mnemonic.
1532218893Sdim    // FIXME: Remove this special case when they do.
1533218893Sdim    if (!Subtarget->isTargetDarwin()) {
1534218893Sdim      //.long 0xe7ffdefe @ trap
1535218893Sdim      uint32_t Val = 0xe7ffdefeUL;
1536218893Sdim      OutStreamer.AddComment("trap");
1537218893Sdim      OutStreamer.EmitIntValue(Val, 4);
1538218893Sdim      return;
1539218893Sdim    }
1540218893Sdim    break;
1541218893Sdim  }
1542249423Sdim  case ARM::TRAPNaCl: {
1543249423Sdim    //.long 0xe7fedef0 @ trap
1544249423Sdim    uint32_t Val = 0xe7fedef0UL;
1545249423Sdim    OutStreamer.AddComment("trap");
1546249423Sdim    OutStreamer.EmitIntValue(Val, 4);
1547249423Sdim    return;
1548249423Sdim  }
1549218893Sdim  case ARM::tTRAP: {
1550218893Sdim    // Non-Darwin binutils don't yet support the "trap" mnemonic.
1551218893Sdim    // FIXME: Remove this special case when they do.
1552218893Sdim    if (!Subtarget->isTargetDarwin()) {
1553218893Sdim      //.short 57086 @ trap
1554218893Sdim      uint16_t Val = 0xdefe;
1555218893Sdim      OutStreamer.AddComment("trap");
1556218893Sdim      OutStreamer.EmitIntValue(Val, 2);
1557218893Sdim      return;
1558218893Sdim    }
1559218893Sdim    break;
1560218893Sdim  }
1561218893Sdim  case ARM::t2Int_eh_sjlj_setjmp:
1562218893Sdim  case ARM::t2Int_eh_sjlj_setjmp_nofp:
1563218893Sdim  case ARM::tInt_eh_sjlj_setjmp: {
1564218893Sdim    // Two incoming args: GPR:$src, GPR:$val
1565218893Sdim    // mov $val, pc
1566218893Sdim    // adds $val, #7
1567218893Sdim    // str $val, [$src, #4]
1568218893Sdim    // movs r0, #0
1569218893Sdim    // b 1f
1570218893Sdim    // movs r0, #1
1571218893Sdim    // 1:
1572218893Sdim    unsigned SrcReg = MI->getOperand(0).getReg();
1573218893Sdim    unsigned ValReg = MI->getOperand(1).getReg();
1574218893Sdim    MCSymbol *Label = GetARMSJLJEHLabel();
1575249423Sdim    OutStreamer.AddComment("eh_setjmp begin");
1576249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
1577249423Sdim      .addReg(ValReg)
1578249423Sdim      .addReg(ARM::PC)
1579224145Sdim      // Predicate.
1580249423Sdim      .addImm(ARMCC::AL)
1581249423Sdim      .addReg(0));
1582249423Sdim
1583249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDi3)
1584249423Sdim      .addReg(ValReg)
1585218893Sdim      // 's' bit operand
1586249423Sdim      .addReg(ARM::CPSR)
1587249423Sdim      .addReg(ValReg)
1588249423Sdim      .addImm(7)
1589218893Sdim      // Predicate.
1590249423Sdim      .addImm(ARMCC::AL)
1591249423Sdim      .addReg(0));
1592249423Sdim
1593249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tSTRi)
1594249423Sdim      .addReg(ValReg)
1595249423Sdim      .addReg(SrcReg)
1596218893Sdim      // The offset immediate is #4. The operand value is scaled by 4 for the
1597218893Sdim      // tSTR instruction.
1598249423Sdim      .addImm(1)
1599218893Sdim      // Predicate.
1600249423Sdim      .addImm(ARMCC::AL)
1601249423Sdim      .addReg(0));
1602249423Sdim
1603249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8)
1604249423Sdim      .addReg(ARM::R0)
1605249423Sdim      .addReg(ARM::CPSR)
1606249423Sdim      .addImm(0)
1607218893Sdim      // Predicate.
1608249423Sdim      .addImm(ARMCC::AL)
1609249423Sdim      .addReg(0));
1610249423Sdim
1611249423Sdim    const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext);
1612249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tB)
1613249423Sdim      .addExpr(SymbolExpr)
1614249423Sdim      .addImm(ARMCC::AL)
1615249423Sdim      .addReg(0));
1616249423Sdim
1617249423Sdim    OutStreamer.AddComment("eh_setjmp end");
1618249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8)
1619249423Sdim      .addReg(ARM::R0)
1620249423Sdim      .addReg(ARM::CPSR)
1621249423Sdim      .addImm(1)
1622218893Sdim      // Predicate.
1623249423Sdim      .addImm(ARMCC::AL)
1624249423Sdim      .addReg(0));
1625249423Sdim
1626218893Sdim    OutStreamer.EmitLabel(Label);
1627218893Sdim    return;
1628218893Sdim  }
1629212793Sdim
1630218893Sdim  case ARM::Int_eh_sjlj_setjmp_nofp:
1631218893Sdim  case ARM::Int_eh_sjlj_setjmp: {
1632218893Sdim    // Two incoming args: GPR:$src, GPR:$val
1633218893Sdim    // add $val, pc, #8
1634218893Sdim    // str $val, [$src, #+4]
1635218893Sdim    // mov r0, #0
1636218893Sdim    // add pc, pc, #0
1637218893Sdim    // mov r0, #1
1638218893Sdim    unsigned SrcReg = MI->getOperand(0).getReg();
1639218893Sdim    unsigned ValReg = MI->getOperand(1).getReg();
1640218893Sdim
1641249423Sdim    OutStreamer.AddComment("eh_setjmp begin");
1642249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri)
1643249423Sdim      .addReg(ValReg)
1644249423Sdim      .addReg(ARM::PC)
1645249423Sdim      .addImm(8)
1646212793Sdim      // Predicate.
1647249423Sdim      .addImm(ARMCC::AL)
1648249423Sdim      .addReg(0)
1649218893Sdim      // 's' bit operand (always reg0 for this).
1650249423Sdim      .addReg(0));
1651249423Sdim
1652249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::STRi12)
1653249423Sdim      .addReg(ValReg)
1654249423Sdim      .addReg(SrcReg)
1655249423Sdim      .addImm(4)
1656218893Sdim      // Predicate.
1657249423Sdim      .addImm(ARMCC::AL)
1658249423Sdim      .addReg(0));
1659249423Sdim
1660249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi)
1661249423Sdim      .addReg(ARM::R0)
1662249423Sdim      .addImm(0)
1663218893Sdim      // Predicate.
1664249423Sdim      .addImm(ARMCC::AL)
1665249423Sdim      .addReg(0)
1666218893Sdim      // 's' bit operand (always reg0 for this).
1667249423Sdim      .addReg(0));
1668249423Sdim
1669249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri)
1670249423Sdim      .addReg(ARM::PC)
1671249423Sdim      .addReg(ARM::PC)
1672249423Sdim      .addImm(0)
1673218893Sdim      // Predicate.
1674249423Sdim      .addImm(ARMCC::AL)
1675249423Sdim      .addReg(0)
1676218893Sdim      // 's' bit operand (always reg0 for this).
1677249423Sdim      .addReg(0));
1678249423Sdim
1679249423Sdim    OutStreamer.AddComment("eh_setjmp end");
1680249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi)
1681249423Sdim      .addReg(ARM::R0)
1682249423Sdim      .addImm(1)
1683218893Sdim      // Predicate.
1684249423Sdim      .addImm(ARMCC::AL)
1685249423Sdim      .addReg(0)
1686218893Sdim      // 's' bit operand (always reg0 for this).
1687249423Sdim      .addReg(0));
1688212793Sdim    return;
1689212793Sdim  }
1690218893Sdim  case ARM::Int_eh_sjlj_longjmp: {
1691218893Sdim    // ldr sp, [$src, #8]
1692218893Sdim    // ldr $scratch, [$src, #4]
1693218893Sdim    // ldr r7, [$src]
1694218893Sdim    // bx $scratch
1695218893Sdim    unsigned SrcReg = MI->getOperand(0).getReg();
1696218893Sdim    unsigned ScratchReg = MI->getOperand(1).getReg();
1697249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12)
1698249423Sdim      .addReg(ARM::SP)
1699249423Sdim      .addReg(SrcReg)
1700249423Sdim      .addImm(8)
1701218893Sdim      // Predicate.
1702249423Sdim      .addImm(ARMCC::AL)
1703249423Sdim      .addReg(0));
1704249423Sdim
1705249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12)
1706249423Sdim      .addReg(ScratchReg)
1707249423Sdim      .addReg(SrcReg)
1708249423Sdim      .addImm(4)
1709212793Sdim      // Predicate.
1710249423Sdim      .addImm(ARMCC::AL)
1711249423Sdim      .addReg(0));
1712249423Sdim
1713249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12)
1714249423Sdim      .addReg(ARM::R7)
1715249423Sdim      .addReg(SrcReg)
1716249423Sdim      .addImm(0)
1717212793Sdim      // Predicate.
1718249423Sdim      .addImm(ARMCC::AL)
1719249423Sdim      .addReg(0));
1720249423Sdim
1721249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX)
1722249423Sdim      .addReg(ScratchReg)
1723218893Sdim      // Predicate.
1724249423Sdim      .addImm(ARMCC::AL)
1725249423Sdim      .addReg(0));
1726212793Sdim    return;
1727212793Sdim  }
1728218893Sdim  case ARM::tInt_eh_sjlj_longjmp: {
1729218893Sdim    // ldr $scratch, [$src, #8]
1730218893Sdim    // mov sp, $scratch
1731218893Sdim    // ldr $scratch, [$src, #4]
1732218893Sdim    // ldr r7, [$src]
1733218893Sdim    // bx $scratch
1734218893Sdim    unsigned SrcReg = MI->getOperand(0).getReg();
1735218893Sdim    unsigned ScratchReg = MI->getOperand(1).getReg();
1736249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi)
1737249423Sdim      .addReg(ScratchReg)
1738249423Sdim      .addReg(SrcReg)
1739218893Sdim      // The offset immediate is #8. The operand value is scaled by 4 for the
1740218893Sdim      // tLDR instruction.
1741249423Sdim      .addImm(2)
1742218893Sdim      // Predicate.
1743249423Sdim      .addImm(ARMCC::AL)
1744249423Sdim      .addReg(0));
1745249423Sdim
1746249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
1747249423Sdim      .addReg(ARM::SP)
1748249423Sdim      .addReg(ScratchReg)
1749218893Sdim      // Predicate.
1750249423Sdim      .addImm(ARMCC::AL)
1751249423Sdim      .addReg(0));
1752249423Sdim
1753249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi)
1754249423Sdim      .addReg(ScratchReg)
1755249423Sdim      .addReg(SrcReg)
1756249423Sdim      .addImm(1)
1757218893Sdim      // Predicate.
1758249423Sdim      .addImm(ARMCC::AL)
1759249423Sdim      .addReg(0));
1760249423Sdim
1761249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi)
1762249423Sdim      .addReg(ARM::R7)
1763249423Sdim      .addReg(SrcReg)
1764249423Sdim      .addImm(0)
1765218893Sdim      // Predicate.
1766249423Sdim      .addImm(ARMCC::AL)
1767249423Sdim      .addReg(0));
1768249423Sdim
1769249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX)
1770249423Sdim      .addReg(ScratchReg)
1771218893Sdim      // Predicate.
1772249423Sdim      .addImm(ARMCC::AL)
1773249423Sdim      .addReg(0));
1774218893Sdim    return;
1775212793Sdim  }
1776221345Sdim  }
1777221345Sdim
1778212793Sdim  MCInst TmpInst;
1779218893Sdim  LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
1780221345Sdim
1781212793Sdim  OutStreamer.EmitInstruction(TmpInst);
1782212793Sdim}
1783212793Sdim
1784212793Sdim//===----------------------------------------------------------------------===//
1785212793Sdim// Target Registry Stuff
1786212793Sdim//===----------------------------------------------------------------------===//
1787212793Sdim
1788212793Sdim// Force static initialization.
1789212793Sdimextern "C" void LLVMInitializeARMAsmPrinter() {
1790212793Sdim  RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget);
1791212793Sdim  RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget);
1792212793Sdim}
1793