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"
16235633Sdim#include "ARMAsmPrinter.h"
17212793Sdim#include "ARM.h"
18212793Sdim#include "ARMBuildAttrs.h"
19212793Sdim#include "ARMConstantPoolValue.h"
20263509Sdim#include "ARMFPUName.h"
21212793Sdim#include "ARMMachineFunctionInfo.h"
22212793Sdim#include "ARMTargetMachine.h"
23218893Sdim#include "ARMTargetObjectFile.h"
24218893Sdim#include "InstPrinter/ARMInstPrinter.h"
25226890Sdim#include "MCTargetDesc/ARMAddressingModes.h"
26226890Sdim#include "MCTargetDesc/ARMMCExpr.h"
27245431Sdim#include "llvm/ADT/SetVector.h"
28245431Sdim#include "llvm/ADT/SmallString.h"
29212793Sdim#include "llvm/Assembly/Writer.h"
30212793Sdim#include "llvm/CodeGen/MachineFunctionPass.h"
31212793Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h"
32252723Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h"
33252723Sdim#include "llvm/DebugInfo.h"
34252723Sdim#include "llvm/IR/Constants.h"
35252723Sdim#include "llvm/IR/DataLayout.h"
36252723Sdim#include "llvm/IR/Module.h"
37252723Sdim#include "llvm/IR/Type.h"
38212793Sdim#include "llvm/MC/MCAsmInfo.h"
39218893Sdim#include "llvm/MC/MCAssembler.h"
40212793Sdim#include "llvm/MC/MCContext.h"
41252723Sdim#include "llvm/MC/MCELFStreamer.h"
42212793Sdim#include "llvm/MC/MCInst.h"
43252723Sdim#include "llvm/MC/MCInstBuilder.h"
44252723Sdim#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"
50252723Sdim#include "llvm/Support/ELF.h"
51212793Sdim#include "llvm/Support/ErrorHandling.h"
52226890Sdim#include "llvm/Support/TargetRegistry.h"
53212793Sdim#include "llvm/Support/raw_ostream.h"
54252723Sdim#include "llvm/Target/Mangler.h"
55252723Sdim#include "llvm/Target/TargetMachine.h"
56212793Sdim#include <cctype>
57212793Sdimusing namespace llvm;
58212793Sdim
59221345Sdim/// EmitDwarfRegOp - Emit dwarf register operation.
60263509Sdimvoid ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc,
61263509Sdim                                   bool Indirect) const {
62221345Sdim  const TargetRegisterInfo *RI = TM.getRegisterInfo();
63263509Sdim  if (RI->getDwarfRegNum(MLoc.getReg(), false) != -1) {
64263509Sdim    AsmPrinter::EmitDwarfRegOp(MLoc, Indirect);
65263509Sdim    return;
66263509Sdim  }
67263509Sdim  assert(MLoc.isReg() && !Indirect &&
68263509Sdim         "This doesn't support offset/indirection - implement it if needed");
69263509Sdim  unsigned Reg = MLoc.getReg();
70263509Sdim  if (Reg >= ARM::S0 && Reg <= ARM::S31) {
71263509Sdim    assert(ARM::S0 + 31 == ARM::S31 && "Unexpected ARM S register numbering");
72263509Sdim    // S registers are described as bit-pieces of a register
73263509Sdim    // S[2x] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 0)
74263509Sdim    // S[2x+1] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 32)
75226890Sdim
76263509Sdim    unsigned SReg = Reg - ARM::S0;
77263509Sdim    bool odd = SReg & 0x1;
78263509Sdim    unsigned Rx = 256 + (SReg >> 1);
79221345Sdim
80263509Sdim    OutStreamer.AddComment("DW_OP_regx for S register");
81263509Sdim    EmitInt8(dwarf::DW_OP_regx);
82221345Sdim
83263509Sdim    OutStreamer.AddComment(Twine(SReg));
84263509Sdim    EmitULEB128(Rx);
85221345Sdim
86263509Sdim    if (odd) {
87263509Sdim      OutStreamer.AddComment("DW_OP_bit_piece 32 32");
88263509Sdim      EmitInt8(dwarf::DW_OP_bit_piece);
89263509Sdim      EmitULEB128(32);
90263509Sdim      EmitULEB128(32);
91263509Sdim    } else {
92263509Sdim      OutStreamer.AddComment("DW_OP_bit_piece 32 0");
93263509Sdim      EmitInt8(dwarf::DW_OP_bit_piece);
94263509Sdim      EmitULEB128(32);
95263509Sdim      EmitULEB128(0);
96263509Sdim    }
97263509Sdim  } else if (Reg >= ARM::Q0 && Reg <= ARM::Q15) {
98263509Sdim    assert(ARM::Q0 + 15 == ARM::Q15 && "Unexpected ARM Q register numbering");
99263509Sdim    // Q registers Q0-Q15 are described by composing two D registers together.
100263509Sdim    // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1)
101263509Sdim    // DW_OP_piece(8)
102221345Sdim
103263509Sdim    unsigned QReg = Reg - ARM::Q0;
104263509Sdim    unsigned D1 = 256 + 2 * QReg;
105263509Sdim    unsigned D2 = D1 + 1;
106226890Sdim
107263509Sdim    OutStreamer.AddComment("DW_OP_regx for Q register: D1");
108263509Sdim    EmitInt8(dwarf::DW_OP_regx);
109263509Sdim    EmitULEB128(D1);
110263509Sdim    OutStreamer.AddComment("DW_OP_piece 8");
111263509Sdim    EmitInt8(dwarf::DW_OP_piece);
112263509Sdim    EmitULEB128(8);
113221345Sdim
114263509Sdim    OutStreamer.AddComment("DW_OP_regx for Q register: D2");
115263509Sdim    EmitInt8(dwarf::DW_OP_regx);
116263509Sdim    EmitULEB128(D2);
117263509Sdim    OutStreamer.AddComment("DW_OP_piece 8");
118263509Sdim    EmitInt8(dwarf::DW_OP_piece);
119263509Sdim    EmitULEB128(8);
120221345Sdim  }
121221345Sdim}
122221345Sdim
123245431Sdimvoid ARMAsmPrinter::EmitFunctionBodyEnd() {
124245431Sdim  // Make sure to terminate any constant pools that were at the end
125245431Sdim  // of the function.
126245431Sdim  if (!InConstantPool)
127245431Sdim    return;
128245431Sdim  InConstantPool = false;
129245431Sdim  OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
130245431Sdim}
131245431Sdim
132212793Sdimvoid ARMAsmPrinter::EmitFunctionEntryLabel() {
133212793Sdim  if (AFI->isThumbFunction()) {
134218893Sdim    OutStreamer.EmitAssemblerFlag(MCAF_Code16);
135223017Sdim    OutStreamer.EmitThumbFunc(CurrentFnSym);
136212793Sdim  }
137212793Sdim
138212793Sdim  OutStreamer.EmitLabel(CurrentFnSym);
139212793Sdim}
140212793Sdim
141235633Sdimvoid ARMAsmPrinter::EmitXXStructor(const Constant *CV) {
142245431Sdim  uint64_t Size = TM.getDataLayout()->getTypeAllocSize(CV->getType());
143235633Sdim  assert(Size && "C++ constructor pointer had zero size!");
144235633Sdim
145235633Sdim  const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts());
146235633Sdim  assert(GV && "C++ constructor pointer was not a GlobalValue!");
147235633Sdim
148263509Sdim  const MCExpr *E = MCSymbolRefExpr::Create(getSymbol(GV),
149235633Sdim                                            (Subtarget->isTargetDarwin()
150235633Sdim                                             ? MCSymbolRefExpr::VK_None
151235633Sdim                                             : MCSymbolRefExpr::VK_ARM_TARGET1),
152235633Sdim                                            OutContext);
153235633Sdim
154235633Sdim  OutStreamer.EmitValue(E, Size);
155235633Sdim}
156235633Sdim
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()) {
173235633Sdim  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!");
178252723Sdim    if(ARM::GPRPairRegClass.contains(Reg)) {
179252723Sdim      const MachineFunction &MF = *MI->getParent()->getParent();
180252723Sdim      const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
181252723Sdim      Reg = TRI->getSubReg(Reg, ARM::gsub_0);
182252723Sdim    }
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:";
209263509Sdim    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
242252723SdimMCSymbol *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]) {
257245431Sdim    default:
258245431Sdim      // See if this is a generic print operand
259245431Sdim      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();
281245431Sdim        // Find the 'd' register that has this 's' register as a sub-register,
282245431Sdim        // and determine the lane number.
283245431Sdim        for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) {
284245431Sdim          if (!ARM::DPRRegClass.contains(*SR))
285245431Sdim            continue;
286245431Sdim          bool Lane0 = TRI->getSubReg(*SR, ARM::ssub_0) == Reg;
287245431Sdim          O << ARMInstPrinter::getRegisterName(*SR) << (Lane0 ? "[0]" : "[1]");
288245431Sdim          return false;
289245431Sdim        }
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.
310263509Sdim      O << "{";
311263509Sdim      if (ARM::GPRPairRegClass.contains(RegBegin)) {
312263509Sdim        const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
313263509Sdim        unsigned Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0);
314263509Sdim        O << ARMInstPrinter::getRegisterName(Reg0) << ", ";;
315263509Sdim        RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1);
316263509Sdim      }
317263509Sdim      O << ARMInstPrinter::getRegisterName(RegBegin);
318226890Sdim
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()) {
325226890Sdim        O << ", "
326223017Sdim          << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg());
327223017Sdim        RegOps++;
328223017Sdim      }
329223017Sdim
330223017Sdim      O << "}";
331223017Sdim
332223017Sdim      return false;
333212793Sdim    }
334226890Sdim    case 'R': // The most significant register of a pair.
335226890Sdim    case 'Q': { // The least significant register of a pair.
336226890Sdim      if (OpNum == 0)
337226890Sdim        return true;
338226890Sdim      const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
339226890Sdim      if (!FlagsOP.isImm())
340226890Sdim        return true;
341226890Sdim      unsigned Flags = FlagsOP.getImm();
342263509Sdim
343263509Sdim      // This operand may not be the one that actually provides the register. If
344263509Sdim      // it's tied to a previous one then we should refer instead to that one
345263509Sdim      // for registers and their classes.
346263509Sdim      unsigned TiedIdx;
347263509Sdim      if (InlineAsm::isUseOperandTiedToDef(Flags, TiedIdx)) {
348263509Sdim        for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) {
349263509Sdim          unsigned OpFlags = MI->getOperand(OpNum).getImm();
350263509Sdim          OpNum += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
351263509Sdim        }
352263509Sdim        Flags = MI->getOperand(OpNum).getImm();
353263509Sdim
354263509Sdim        // Later code expects OpNum to be pointing at the register rather than
355263509Sdim        // the flags.
356263509Sdim        OpNum += 1;
357263509Sdim      }
358263509Sdim
359226890Sdim      unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
360263509Sdim      unsigned RC;
361263509Sdim      InlineAsm::hasRegClassConstraint(Flags, RC);
362263509Sdim      if (RC == ARM::GPRPairRegClassID) {
363263509Sdim        if (NumVals != 1)
364263509Sdim          return true;
365263509Sdim        const MachineOperand &MO = MI->getOperand(OpNum);
366263509Sdim        if (!MO.isReg())
367263509Sdim          return true;
368263509Sdim        const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
369263509Sdim        unsigned Reg = TRI->getSubReg(MO.getReg(), ExtraCode[0] == 'Q' ?
370263509Sdim            ARM::gsub_0 : ARM::gsub_1);
371263509Sdim        O << ARMInstPrinter::getRegisterName(Reg);
372263509Sdim        return false;
373263509Sdim      }
374226890Sdim      if (NumVals != 2)
375226890Sdim        return true;
376226890Sdim      unsigned RegOp = ExtraCode[0] == 'Q' ? OpNum : OpNum + 1;
377226890Sdim      if (RegOp >= MI->getNumOperands())
378226890Sdim        return true;
379226890Sdim      const MachineOperand &MO = MI->getOperand(RegOp);
380226890Sdim      if (!MO.isReg())
381226890Sdim        return true;
382226890Sdim      unsigned Reg = MO.getReg();
383226890Sdim      O << ARMInstPrinter::getRegisterName(Reg);
384226890Sdim      return false;
385226890Sdim    }
386226890Sdim
387235633Sdim    case 'e': // The low doubleword register of a NEON quad register.
388235633Sdim    case 'f': { // The high doubleword register of a NEON quad register.
389235633Sdim      if (!MI->getOperand(OpNum).isReg())
390235633Sdim        return true;
391235633Sdim      unsigned Reg = MI->getOperand(OpNum).getReg();
392235633Sdim      if (!ARM::QPRRegClass.contains(Reg))
393235633Sdim        return true;
394235633Sdim      const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
395235633Sdim      unsigned SubReg = TRI->getSubReg(Reg, ExtraCode[0] == 'e' ?
396235633Sdim                                       ARM::dsub_0 : ARM::dsub_1);
397235633Sdim      O << ARMInstPrinter::getRegisterName(SubReg);
398235633Sdim      return false;
399235633Sdim    }
400235633Sdim
401245431Sdim    // This modifier is not yet supported.
402223017Sdim    case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.
403223017Sdim      return true;
404245431Sdim    case 'H': { // The highest-numbered register of a pair.
405245431Sdim      const MachineOperand &MO = MI->getOperand(OpNum);
406245431Sdim      if (!MO.isReg())
407245431Sdim        return true;
408245431Sdim      const MachineFunction &MF = *MI->getParent()->getParent();
409245431Sdim      const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
410252723Sdim      unsigned Reg = MO.getReg();
411252723Sdim      if(!ARM::GPRPairRegClass.contains(Reg))
412252723Sdim        return false;
413252723Sdim      Reg = TRI->getSubReg(Reg, ARM::gsub_1);
414245431Sdim      O << ARMInstPrinter::getRegisterName(Reg);
415245431Sdim      return false;
416223017Sdim    }
417245431Sdim    }
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.
431226890Sdim
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  }
442226890Sdim
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());
462245431Sdim
463245431Sdim      // Collect the set of sections our functions will go into.
464245431Sdim      SetVector<const MCSection *, SmallVector<const MCSection *, 8>,
465245431Sdim        SmallPtrSet<const MCSection *, 8> > TextSections;
466245431Sdim      // Default text section comes first.
467245431Sdim      TextSections.insert(TLOFMacho.getTextSection());
468245431Sdim      // Now any user defined text sections from function attributes.
469245431Sdim      for (Module::iterator F = M.begin(), e = M.end(); F != e; ++F)
470245431Sdim        if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage())
471245431Sdim          TextSections.insert(TLOFMacho.SectionForGlobal(F, Mang, TM));
472245431Sdim      // Now the coalescable sections.
473245431Sdim      TextSections.insert(TLOFMacho.getTextCoalSection());
474245431Sdim      TextSections.insert(TLOFMacho.getConstTextCoalSection());
475245431Sdim
476245431Sdim      // Emit the sections in the .s file header to fix the order.
477245431Sdim      for (unsigned i = 0, e = TextSections.size(); i != e; ++i)
478245431Sdim        OutStreamer.SwitchSection(TextSections[i]);
479245431Sdim
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
506235633Sdim  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.
535252723Sdim          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),
545252723Sdim                                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),
563252723Sdim                              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
586263509Sdimstatic ARMBuildAttrs::CPUArch getArchForCPU(StringRef CPU,
587263509Sdim                                            const ARMSubtarget *Subtarget) {
588263509Sdim  if (CPU == "xscale")
589263509Sdim    return ARMBuildAttrs::v5TEJ;
590218893Sdim
591263509Sdim  if (Subtarget->hasV8Ops())
592263509Sdim    return ARMBuildAttrs::v8;
593263509Sdim  else if (Subtarget->hasV7Ops()) {
594263509Sdim    if (Subtarget->isMClass() && Subtarget->hasThumb2DSP())
595263509Sdim      return ARMBuildAttrs::v7E_M;
596263509Sdim    return ARMBuildAttrs::v7;
597245431Sdim  } else if (Subtarget->hasV6T2Ops())
598263509Sdim    return ARMBuildAttrs::v6T2;
599263509Sdim  else if (Subtarget->hasV6MOps())
600263509Sdim    return ARMBuildAttrs::v6S_M;
601245431Sdim  else if (Subtarget->hasV6Ops())
602263509Sdim    return ARMBuildAttrs::v6;
603245431Sdim  else if (Subtarget->hasV5TEOps())
604263509Sdim    return ARMBuildAttrs::v5TE;
605245431Sdim  else if (Subtarget->hasV5TOps())
606263509Sdim    return ARMBuildAttrs::v5T;
607245431Sdim  else if (Subtarget->hasV4TOps())
608263509Sdim    return ARMBuildAttrs::v4T;
609263509Sdim  else
610263509Sdim    return ARMBuildAttrs::v4;
611263509Sdim}
612218893Sdim
613263509Sdimvoid ARMAsmPrinter::emitAttributes() {
614263509Sdim  MCTargetStreamer &TS = OutStreamer.getTargetStreamer();
615263509Sdim  ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
616221345Sdim
617263509Sdim  ATS.switchVendor("aeabi");
618235633Sdim
619263509Sdim  std::string CPUString = Subtarget->getCPUString();
620221345Sdim
621263509Sdim  if (CPUString != "generic")
622263509Sdim    ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);
623263509Sdim
624263509Sdim  ATS.emitAttribute(ARMBuildAttrs::CPU_arch,
625263509Sdim                    getArchForCPU(CPUString, Subtarget));
626263509Sdim
627263509Sdim  if (Subtarget->isAClass()) {
628263509Sdim    ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
629263509Sdim                      ARMBuildAttrs::ApplicationProfile);
630263509Sdim  } else if (Subtarget->isRClass()) {
631263509Sdim    ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
632263509Sdim                      ARMBuildAttrs::RealTimeProfile);
633263509Sdim  } else if (Subtarget->isMClass()){
634263509Sdim    ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
635263509Sdim                      ARMBuildAttrs::MicroControllerProfile);
636221345Sdim  }
637218893Sdim
638263509Sdim  ATS.emitAttribute(ARMBuildAttrs::ARM_ISA_use, Subtarget->hasARMOps() ?
639263509Sdim                      ARMBuildAttrs::Allowed : ARMBuildAttrs::Not_Allowed);
640263509Sdim  if (Subtarget->isThumb1Only()) {
641263509Sdim    ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
642263509Sdim                      ARMBuildAttrs::Allowed);
643263509Sdim  } else if (Subtarget->hasThumb2()) {
644263509Sdim    ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
645263509Sdim                      ARMBuildAttrs::AllowThumb32);
646263509Sdim  }
647263509Sdim
648221345Sdim  if (Subtarget->hasNEON()) {
649263509Sdim    /* NEON is not exactly a VFP architecture, but GAS emit one of
650263509Sdim     * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */
651263509Sdim    if (Subtarget->hasFPARMv8()) {
652263509Sdim      if (Subtarget->hasCrypto())
653263509Sdim        ATS.emitFPU(ARM::CRYPTO_NEON_FP_ARMV8);
654263509Sdim      else
655263509Sdim        ATS.emitFPU(ARM::NEON_FP_ARMV8);
656263509Sdim    }
657263509Sdim    else if (Subtarget->hasVFP4())
658263509Sdim      ATS.emitFPU(ARM::NEON_VFPV4);
659263509Sdim    else
660263509Sdim      ATS.emitFPU(ARM::NEON);
661263509Sdim    // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture
662263509Sdim    if (Subtarget->hasV8Ops())
663263509Sdim      ATS.emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
664263509Sdim                        ARMBuildAttrs::AllowNeonARMv8);
665263509Sdim  } else {
666263509Sdim    if (Subtarget->hasFPARMv8())
667263509Sdim      ATS.emitFPU(ARM::FP_ARMV8);
668263509Sdim    else if (Subtarget->hasVFP4())
669263509Sdim      ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV4_D16 : ARM::VFPV4);
670263509Sdim    else if (Subtarget->hasVFP3())
671263509Sdim      ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV3_D16 : ARM::VFPV3);
672263509Sdim    else if (Subtarget->hasVFP2())
673263509Sdim      ATS.emitFPU(ARM::VFPV2);
674221345Sdim  }
675221345Sdim
676218893Sdim  // Signal various FP modes.
677235633Sdim  if (!TM.Options.UnsafeFPMath) {
678263509Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, ARMBuildAttrs::Allowed);
679263509Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions,
680263509Sdim                      ARMBuildAttrs::Allowed);
681218893Sdim  }
682218893Sdim
683235633Sdim  if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath)
684263509Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
685263509Sdim                      ARMBuildAttrs::Allowed);
686218893Sdim  else
687263509Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
688263509Sdim                      ARMBuildAttrs::AllowIEE754);
689218893Sdim
690218893Sdim  // FIXME: add more flags to ARMBuildAttrs.h
691218893Sdim  // 8-bytes alignment stuff.
692263509Sdim  ATS.emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
693263509Sdim  ATS.emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
694218893Sdim
695263509Sdim  // ABI_HardFP_use attribute to indicate single precision FP.
696263509Sdim  if (Subtarget->isFPOnlySP())
697263509Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_HardFP_use,
698263509Sdim                      ARMBuildAttrs::HardFPSinglePrecision);
699263509Sdim
700218893Sdim  // Hard float.  Use both S and D registers and conform to AAPCS-VFP.
701263509Sdim  if (Subtarget->isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard)
702263509Sdim    ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS);
703263509Sdim
704218893Sdim  // FIXME: Should we signal R9 usage?
705218893Sdim
706263509Sdim  if (Subtarget->hasFP16())
707263509Sdim      ATS.emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP);
708218893Sdim
709263509Sdim  if (Subtarget->hasMPExtension())
710263509Sdim      ATS.emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP);
711263509Sdim
712263509Sdim  if (Subtarget->hasDivide()) {
713263509Sdim    // Check if hardware divide is only available in thumb2 or ARM as well.
714263509Sdim    ATS.emitAttribute(ARMBuildAttrs::DIV_use,
715263509Sdim      Subtarget->hasDivideInARMMode() ? ARMBuildAttrs::AllowDIVExt :
716263509Sdim                                        ARMBuildAttrs::AllowDIVIfExists);
717263509Sdim  }
718263509Sdim
719263509Sdim  if (Subtarget->hasTrustZone() && Subtarget->hasVirtualization())
720263509Sdim      ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
721263509Sdim                        ARMBuildAttrs::AllowTZVirtualization);
722263509Sdim  else if (Subtarget->hasTrustZone())
723263509Sdim      ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
724263509Sdim                        ARMBuildAttrs::AllowTZ);
725263509Sdim  else if (Subtarget->hasVirtualization())
726263509Sdim      ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
727263509Sdim                        ARMBuildAttrs::AllowVirtualization);
728263509Sdim
729263509Sdim  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  }
774235633Sdim  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)
781263509Sdim    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::
792263509Sdim      StubValueTy(getSymbol(GV), !GV->hasInternalLinkage());
793218893Sdim  return MCSym;
794218893Sdim}
795218893Sdim
796218893Sdimvoid ARMAsmPrinter::
797218893SdimEmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
798245431Sdim  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()) {
809226890Sdim    const BlockAddress *BA =
810226890Sdim      cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress();
811226890Sdim    MCSym = GetBlockAddressSymbol(BA);
812218893Sdim  } else if (ACPV->isGlobalValue()) {
813226890Sdim    const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV();
814218893Sdim    MCSym = GetARMGVSymbol(GV);
815226890Sdim  } else if (ACPV->isMachineBasicBlock()) {
816226890Sdim    const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
817226890Sdim    MCSym = MBB->getSymbol();
818218893Sdim  } else {
819218893Sdim    assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
820226890Sdim    const char *Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol();
821226890Sdim    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
869245431Sdim  // Mark the jump table as data-in-code.
870245431Sdim  OutStreamer.EmitDataRegion(MCDR_DataRegionJT32);
871245431Sdim
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);
893226890Sdim    // If we're generating a table of Thumb addresses in static relocation
894226890Sdim    // model, we need to add one to keep interworking correctly.
895226890Sdim    else if (AFI->isThumbFunction())
896226890Sdim      Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(1,OutContext),
897226890Sdim                                     OutContext);
898218893Sdim    OutStreamer.EmitValue(Expr, 4);
899218893Sdim  }
900245431Sdim  // Mark the end of jump table data-in-code region.
901245431Sdim  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;
919245431Sdim  if (MI->getOpcode() == ARM::t2TBB_JT) {
920218893Sdim    OffsetWidth = 1;
921245431Sdim    // Mark the jump table as data-in-code.
922245431Sdim    OutStreamer.EmitDataRegion(MCDR_DataRegionJT8);
923245431Sdim  } else if (MI->getOpcode() == ARM::t2TBH_JT) {
924218893Sdim    OffsetWidth = 2;
925245431Sdim    // Mark the jump table as data-in-code.
926245431Sdim    OutStreamer.EmitDataRegion(MCDR_DataRegionJT16);
927245431Sdim  }
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) {
935252723Sdim      OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2B)
936252723Sdim        .addExpr(MBBSymbolExpr)
937252723Sdim        .addImm(ARMCC::AL)
938252723Sdim        .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  }
958245431Sdim  // Mark the end of jump table data-in-code region. 32-bit offsets use
959245431Sdim  // actual branch instructions here, so we don't mark those as a data-region
960245431Sdim  // at all.
961245431Sdim  if (OffsetWidth != 4)
962245431Sdim    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
969263509Sdim  MCTargetStreamer &TS = OutStreamer.getTargetStreamer();
970263509Sdim  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.
992235633Sdim  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();
1006235633Sdim      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;
1016245431Sdim           i != NumOps; ++i) {
1017245431Sdim        const MachineOperand &MO = MI->getOperand(i);
1018245431Sdim        // Actually, there should never be any impdef stuff here. Skip it
1019245431Sdim        // temporary to workaround PR11902.
1020245431Sdim        if (MO.isImplicit())
1021245431Sdim          continue;
1022245431Sdim        RegList.push_back(MO.getReg());
1023245431Sdim      }
1024221345Sdim      break;
1025226890Sdim    case ARM::STR_PRE_IMM:
1026226890Sdim    case ARM::STR_PRE_REG:
1027235633Sdim    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    }
1033263509Sdim    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();
1041235633Sdim        llvm_unreachable("Unsupported opcode for unwinding information");
1042221345Sdim      case ARM::MOVr:
1043235633Sdim      case ARM::tMOVr:
1044221345Sdim        Offset = 0;
1045221345Sdim        break;
1046221345Sdim      case ARM::ADDri:
1047221345Sdim        Offset = -MI->getOperand(2).getImm();
1048221345Sdim        break;
1049221345Sdim      case ARM::SUBri:
1050235633Sdim      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.
1081263509Sdim        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.
1085263509Sdim        ATS.emitPad(Offset);
1086221345Sdim      } else {
1087221345Sdim        MI->dump();
1088235633Sdim        llvm_unreachable("Unsupported opcode for unwinding information");
1089221345Sdim      }
1090221345Sdim    } else if (DstReg == ARM::SP) {
1091221345Sdim      // FIXME: .movsp goes here
1092221345Sdim      MI->dump();
1093235633Sdim      llvm_unreachable("Unsupported opcode for unwinding information");
1094221345Sdim    }
1095221345Sdim    else {
1096221345Sdim      MI->dump();
1097235633Sdim      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) {
1109245431Sdim  // If we just ended a constant pool, mark it as such.
1110245431Sdim  if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
1111245431Sdim    OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
1112245431Sdim    InConstantPool = false;
1113245431Sdim  }
1114226890Sdim
1115226890Sdim  // Emit unwinding stuff for frame-related instructions
1116226890Sdim  if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup))
1117226890Sdim    EmitUnwindingInstruction(MI);
1118226890Sdim
1119224145Sdim  // Do any auto-generated pseudo lowerings.
1120224145Sdim  if (emitPseudoExpansionLowering(OutStreamer, MI))
1121224145Sdim    return;
1122224145Sdim
1123226890Sdim  assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&
1124226890Sdim         "Pseudo flag setting opcode should be expanded early");
1125226890Sdim
1126224145Sdim  // Check for manual lowerings.
1127218893Sdim  unsigned Opc = MI->getOpcode();
1128218893Sdim  switch (Opc) {
1129235633Sdim  case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");
1130263509Sdim  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
1135252723Sdim    MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex());
1136252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() ==
1137252723Sdim                                              ARM::t2LEApcrel ? ARM::t2ADR
1138252723Sdim                  : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
1139252723Sdim                     : ARM::ADR))
1140252723Sdim      .addReg(MI->getOperand(0).getReg())
1141252723Sdim      .addExpr(MCSymbolRefExpr::Create(CPISymbol, OutContext))
1142252723Sdim      // Add predicate operands.
1143252723Sdim      .addImm(MI->getOperand(2).getImm())
1144252723Sdim      .addReg(MI->getOperand(3).getReg()));
1145218893Sdim    return;
1146218893Sdim  }
1147218893Sdim  case ARM::LEApcrelJT:
1148218893Sdim  case ARM::tLEApcrelJT:
1149218893Sdim  case ARM::t2LEApcrelJT: {
1150252723Sdim    MCSymbol *JTIPICSymbol =
1151252723Sdim      GetARMJTIPICJumpTableLabel2(MI->getOperand(1).getIndex(),
1152252723Sdim                                  MI->getOperand(2).getImm());
1153252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() ==
1154252723Sdim                                              ARM::t2LEApcrelJT ? ARM::t2ADR
1155252723Sdim                  : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
1156252723Sdim                     : ARM::ADR))
1157252723Sdim      .addReg(MI->getOperand(0).getReg())
1158252723Sdim      .addExpr(MCSymbolRefExpr::Create(JTIPICSymbol, OutContext))
1159252723Sdim      // Add predicate operands.
1160252723Sdim      .addImm(MI->getOperand(3).getImm())
1161252723Sdim      .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: {
1167252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
1168252723Sdim      .addReg(ARM::LR)
1169252723Sdim      .addReg(ARM::PC)
1170218893Sdim      // Add predicate operands.
1171252723Sdim      .addImm(ARMCC::AL)
1172252723Sdim      .addReg(0)
1173218893Sdim      // Add 's' bit operand (always reg0 for this)
1174252723Sdim      .addReg(0));
1175252723Sdim
1176252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX)
1177252723Sdim      .addReg(MI->getOperand(0).getReg()));
1178218893Sdim    return;
1179218893Sdim  }
1180223017Sdim  case ARM::tBX_CALL: {
1181252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
1182252723Sdim      .addReg(ARM::LR)
1183252723Sdim      .addReg(ARM::PC)
1184224145Sdim      // Add predicate operands.
1185252723Sdim      .addImm(ARMCC::AL)
1186252723Sdim      .addReg(0));
1187252723Sdim
1188252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX)
1189252723Sdim      .addReg(MI->getOperand(0).getReg())
1190223017Sdim      // Add predicate operands.
1191252723Sdim      .addImm(ARMCC::AL)
1192252723Sdim      .addReg(0));
1193223017Sdim    return;
1194223017Sdim  }
1195218893Sdim  case ARM::BMOVPCRX_CALL: {
1196252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
1197252723Sdim      .addReg(ARM::LR)
1198252723Sdim      .addReg(ARM::PC)
1199218893Sdim      // Add predicate operands.
1200252723Sdim      .addImm(ARMCC::AL)
1201252723Sdim      .addReg(0)
1202218893Sdim      // Add 's' bit operand (always reg0 for this)
1203252723Sdim      .addReg(0));
1204252723Sdim
1205252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
1206252723Sdim      .addReg(ARM::PC)
1207252723Sdim      .addReg(MI->getOperand(0).getReg())
1208218893Sdim      // Add predicate operands.
1209252723Sdim      .addImm(ARMCC::AL)
1210252723Sdim      .addReg(0)
1211218893Sdim      // Add 's' bit operand (always reg0 for this)
1212252723Sdim      .addReg(0));
1213218893Sdim    return;
1214218893Sdim  }
1215235633Sdim  case ARM::BMOVPCB_CALL: {
1216252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
1217252723Sdim      .addReg(ARM::LR)
1218252723Sdim      .addReg(ARM::PC)
1219235633Sdim      // Add predicate operands.
1220252723Sdim      .addImm(ARMCC::AL)
1221252723Sdim      .addReg(0)
1222235633Sdim      // Add 's' bit operand (always reg0 for this)
1223252723Sdim      .addReg(0));
1224252723Sdim
1225252723Sdim    const GlobalValue *GV = MI->getOperand(0).getGlobal();
1226263509Sdim    MCSymbol *GVSym = getSymbol(GV);
1227252723Sdim    const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
1228252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::Bcc)
1229252723Sdim      .addExpr(GVSymExpr)
1230235633Sdim      // Add predicate operands.
1231252723Sdim      .addImm(ARMCC::AL)
1232252723Sdim      .addReg(0));
1233235633Sdim    return;
1234235633Sdim  }
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.
1320252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDhirr)
1321252723Sdim      .addReg(MI->getOperand(0).getReg())
1322252723Sdim      .addReg(MI->getOperand(0).getReg())
1323252723Sdim      .addReg(ARM::PC)
1324252723Sdim      // Add predicate operands.
1325252723Sdim      .addImm(ARMCC::AL)
1326252723Sdim      .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.
1341252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr)
1342252723Sdim      .addReg(MI->getOperand(0).getReg())
1343252723Sdim      .addReg(ARM::PC)
1344252723Sdim      .addReg(MI->getOperand(1).getReg())
1345252723Sdim      // Add predicate operands.
1346252723Sdim      .addImm(MI->getOperand(3).getImm())
1347252723Sdim      .addReg(MI->getOperand(4).getReg())
1348252723Sdim      // Add 's' bit operand (always reg0 for this)
1349252723Sdim      .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    }
1385252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(Opcode)
1386252723Sdim      .addReg(MI->getOperand(0).getReg())
1387252723Sdim      .addReg(ARM::PC)
1388252723Sdim      .addReg(MI->getOperand(1).getReg())
1389252723Sdim      .addImm(0)
1390252723Sdim      // Add predicate operands.
1391252723Sdim      .addImm(MI->getOperand(3).getImm())
1392252723Sdim      .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.
1401235633Sdim    /// 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
1405245431Sdim    // If this is the first entry of the pool, mark it.
1406245431Sdim    if (!InConstantPool) {
1407245431Sdim      OutStreamer.EmitDataRegion(MCDR_DataRegion);
1408245431Sdim      InConstantPool = true;
1409245431Sdim    }
1410245431Sdim
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.
1422252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
1423252723Sdim      .addReg(ARM::PC)
1424252723Sdim      .addReg(MI->getOperand(0).getReg())
1425252723Sdim      // Add predicate operands.
1426252723Sdim      .addImm(ARMCC::AL)
1427252723Sdim      .addReg(0));
1428252723Sdim
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.
1435252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBB)
1436252723Sdim      .addReg(ARM::PC)
1437252723Sdim      .addReg(MI->getOperand(0).getReg())
1438252723Sdim      // Add predicate operands.
1439252723Sdim      .addImm(ARMCC::AL)
1440252723Sdim      .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.
1450252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBH)
1451252723Sdim      .addReg(ARM::PC)
1452252723Sdim      .addReg(MI->getOperand(0).getReg())
1453252723Sdim      // Add predicate operands.
1454252723Sdim      .addImm(ARMCC::AL)
1455252723Sdim      .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
1516252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr)
1517252723Sdim      .addReg(ARM::PC)
1518252723Sdim      .addReg(MI->getOperand(0).getReg())
1519252723Sdim      .addReg(MI->getOperand(1).getReg())
1520252723Sdim      // Add predicate operands.
1521252723Sdim      .addImm(ARMCC::AL)
1522252723Sdim      .addReg(0)
1523252723Sdim      // Add 's' bit operand (always reg0 for this)
1524252723Sdim      .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  }
1542252723Sdim  case ARM::TRAPNaCl: {
1543252723Sdim    //.long 0xe7fedef0 @ trap
1544252723Sdim    uint32_t Val = 0xe7fedef0UL;
1545252723Sdim    OutStreamer.AddComment("trap");
1546252723Sdim    OutStreamer.EmitIntValue(Val, 4);
1547252723Sdim    return;
1548252723Sdim  }
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();
1575252723Sdim    OutStreamer.AddComment("eh_setjmp begin");
1576252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
1577252723Sdim      .addReg(ValReg)
1578252723Sdim      .addReg(ARM::PC)
1579224145Sdim      // Predicate.
1580252723Sdim      .addImm(ARMCC::AL)
1581252723Sdim      .addReg(0));
1582252723Sdim
1583252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDi3)
1584252723Sdim      .addReg(ValReg)
1585218893Sdim      // 's' bit operand
1586252723Sdim      .addReg(ARM::CPSR)
1587252723Sdim      .addReg(ValReg)
1588252723Sdim      .addImm(7)
1589218893Sdim      // Predicate.
1590252723Sdim      .addImm(ARMCC::AL)
1591252723Sdim      .addReg(0));
1592252723Sdim
1593252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tSTRi)
1594252723Sdim      .addReg(ValReg)
1595252723Sdim      .addReg(SrcReg)
1596218893Sdim      // The offset immediate is #4. The operand value is scaled by 4 for the
1597218893Sdim      // tSTR instruction.
1598252723Sdim      .addImm(1)
1599218893Sdim      // Predicate.
1600252723Sdim      .addImm(ARMCC::AL)
1601252723Sdim      .addReg(0));
1602252723Sdim
1603252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8)
1604252723Sdim      .addReg(ARM::R0)
1605252723Sdim      .addReg(ARM::CPSR)
1606252723Sdim      .addImm(0)
1607218893Sdim      // Predicate.
1608252723Sdim      .addImm(ARMCC::AL)
1609252723Sdim      .addReg(0));
1610252723Sdim
1611252723Sdim    const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext);
1612252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tB)
1613252723Sdim      .addExpr(SymbolExpr)
1614252723Sdim      .addImm(ARMCC::AL)
1615252723Sdim      .addReg(0));
1616252723Sdim
1617252723Sdim    OutStreamer.AddComment("eh_setjmp end");
1618252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8)
1619252723Sdim      .addReg(ARM::R0)
1620252723Sdim      .addReg(ARM::CPSR)
1621252723Sdim      .addImm(1)
1622218893Sdim      // Predicate.
1623252723Sdim      .addImm(ARMCC::AL)
1624252723Sdim      .addReg(0));
1625252723Sdim
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
1641252723Sdim    OutStreamer.AddComment("eh_setjmp begin");
1642252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri)
1643252723Sdim      .addReg(ValReg)
1644252723Sdim      .addReg(ARM::PC)
1645252723Sdim      .addImm(8)
1646212793Sdim      // Predicate.
1647252723Sdim      .addImm(ARMCC::AL)
1648252723Sdim      .addReg(0)
1649218893Sdim      // 's' bit operand (always reg0 for this).
1650252723Sdim      .addReg(0));
1651252723Sdim
1652252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::STRi12)
1653252723Sdim      .addReg(ValReg)
1654252723Sdim      .addReg(SrcReg)
1655252723Sdim      .addImm(4)
1656218893Sdim      // Predicate.
1657252723Sdim      .addImm(ARMCC::AL)
1658252723Sdim      .addReg(0));
1659252723Sdim
1660252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi)
1661252723Sdim      .addReg(ARM::R0)
1662252723Sdim      .addImm(0)
1663218893Sdim      // Predicate.
1664252723Sdim      .addImm(ARMCC::AL)
1665252723Sdim      .addReg(0)
1666218893Sdim      // 's' bit operand (always reg0 for this).
1667252723Sdim      .addReg(0));
1668252723Sdim
1669252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri)
1670252723Sdim      .addReg(ARM::PC)
1671252723Sdim      .addReg(ARM::PC)
1672252723Sdim      .addImm(0)
1673218893Sdim      // Predicate.
1674252723Sdim      .addImm(ARMCC::AL)
1675252723Sdim      .addReg(0)
1676218893Sdim      // 's' bit operand (always reg0 for this).
1677252723Sdim      .addReg(0));
1678252723Sdim
1679252723Sdim    OutStreamer.AddComment("eh_setjmp end");
1680252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi)
1681252723Sdim      .addReg(ARM::R0)
1682252723Sdim      .addImm(1)
1683218893Sdim      // Predicate.
1684252723Sdim      .addImm(ARMCC::AL)
1685252723Sdim      .addReg(0)
1686218893Sdim      // 's' bit operand (always reg0 for this).
1687252723Sdim      .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();
1697252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12)
1698252723Sdim      .addReg(ARM::SP)
1699252723Sdim      .addReg(SrcReg)
1700252723Sdim      .addImm(8)
1701218893Sdim      // Predicate.
1702252723Sdim      .addImm(ARMCC::AL)
1703252723Sdim      .addReg(0));
1704252723Sdim
1705252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12)
1706252723Sdim      .addReg(ScratchReg)
1707252723Sdim      .addReg(SrcReg)
1708252723Sdim      .addImm(4)
1709212793Sdim      // Predicate.
1710252723Sdim      .addImm(ARMCC::AL)
1711252723Sdim      .addReg(0));
1712252723Sdim
1713252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12)
1714252723Sdim      .addReg(ARM::R7)
1715252723Sdim      .addReg(SrcReg)
1716252723Sdim      .addImm(0)
1717212793Sdim      // Predicate.
1718252723Sdim      .addImm(ARMCC::AL)
1719252723Sdim      .addReg(0));
1720252723Sdim
1721252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX)
1722252723Sdim      .addReg(ScratchReg)
1723218893Sdim      // Predicate.
1724252723Sdim      .addImm(ARMCC::AL)
1725252723Sdim      .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();
1736252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi)
1737252723Sdim      .addReg(ScratchReg)
1738252723Sdim      .addReg(SrcReg)
1739218893Sdim      // The offset immediate is #8. The operand value is scaled by 4 for the
1740218893Sdim      // tLDR instruction.
1741252723Sdim      .addImm(2)
1742218893Sdim      // Predicate.
1743252723Sdim      .addImm(ARMCC::AL)
1744252723Sdim      .addReg(0));
1745252723Sdim
1746252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
1747252723Sdim      .addReg(ARM::SP)
1748252723Sdim      .addReg(ScratchReg)
1749218893Sdim      // Predicate.
1750252723Sdim      .addImm(ARMCC::AL)
1751252723Sdim      .addReg(0));
1752252723Sdim
1753252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi)
1754252723Sdim      .addReg(ScratchReg)
1755252723Sdim      .addReg(SrcReg)
1756252723Sdim      .addImm(1)
1757218893Sdim      // Predicate.
1758252723Sdim      .addImm(ARMCC::AL)
1759252723Sdim      .addReg(0));
1760252723Sdim
1761252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi)
1762252723Sdim      .addReg(ARM::R7)
1763252723Sdim      .addReg(SrcReg)
1764252723Sdim      .addImm(0)
1765218893Sdim      // Predicate.
1766252723Sdim      .addImm(ARMCC::AL)
1767252723Sdim      .addReg(0));
1768252723Sdim
1769252723Sdim    OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX)
1770252723Sdim      .addReg(ScratchReg)
1771218893Sdim      // Predicate.
1772252723Sdim      .addImm(ARMCC::AL)
1773252723Sdim      .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