ARMAsmPrinter.cpp revision 35636281c7ab6eb128b4ced6bf7ae0b6b8458dd2
1//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to GAS-format ARM assembly language.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "asm-printer"
16#include "ARM.h"
17#include "ARMBuildAttrs.h"
18#include "ARMAddressingModes.h"
19#include "ARMConstantPoolValue.h"
20#include "InstPrinter/ARMInstPrinter.h"
21#include "ARMMachineFunctionInfo.h"
22#include "ARMMCInstLower.h"
23#include "ARMTargetMachine.h"
24#include "llvm/Analysis/DebugInfo.h"
25#include "llvm/Constants.h"
26#include "llvm/Module.h"
27#include "llvm/Type.h"
28#include "llvm/Assembly/Writer.h"
29#include "llvm/CodeGen/AsmPrinter.h"
30#include "llvm/CodeGen/MachineModuleInfoImpls.h"
31#include "llvm/CodeGen/MachineFunctionPass.h"
32#include "llvm/CodeGen/MachineJumpTableInfo.h"
33#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
34#include "llvm/MC/MCAsmInfo.h"
35#include "llvm/MC/MCContext.h"
36#include "llvm/MC/MCExpr.h"
37#include "llvm/MC/MCInst.h"
38#include "llvm/MC/MCSectionMachO.h"
39#include "llvm/MC/MCStreamer.h"
40#include "llvm/MC/MCSymbol.h"
41#include "llvm/Target/Mangler.h"
42#include "llvm/Target/TargetData.h"
43#include "llvm/Target/TargetMachine.h"
44#include "llvm/Target/TargetOptions.h"
45#include "llvm/Target/TargetRegistry.h"
46#include "llvm/ADT/SmallPtrSet.h"
47#include "llvm/ADT/SmallString.h"
48#include "llvm/ADT/StringExtras.h"
49#include "llvm/Support/CommandLine.h"
50#include "llvm/Support/Debug.h"
51#include "llvm/Support/ErrorHandling.h"
52#include "llvm/Support/raw_ostream.h"
53#include <cctype>
54using namespace llvm;
55
56namespace llvm {
57  namespace ARM {
58    enum DW_ISA {
59      DW_ISA_ARM_thumb = 1,
60      DW_ISA_ARM_arm = 2
61    };
62  }
63}
64
65namespace {
66  class ARMAsmPrinter : public AsmPrinter {
67
68    /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
69    /// make the right decision when printing asm code for different targets.
70    const ARMSubtarget *Subtarget;
71
72    /// AFI - Keep a pointer to ARMFunctionInfo for the current
73    /// MachineFunction.
74    ARMFunctionInfo *AFI;
75
76    /// MCP - Keep a pointer to constantpool entries of the current
77    /// MachineFunction.
78    const MachineConstantPool *MCP;
79
80  public:
81    explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
82      : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) {
83      Subtarget = &TM.getSubtarget<ARMSubtarget>();
84    }
85
86    virtual const char *getPassName() const {
87      return "ARM Assembly Printer";
88    }
89
90    void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
91                      const char *Modifier = 0);
92
93    virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
94                                 unsigned AsmVariant, const char *ExtraCode,
95                                 raw_ostream &O);
96    virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
97                                       unsigned AsmVariant,
98                                       const char *ExtraCode, raw_ostream &O);
99
100    void EmitJumpTable(const MachineInstr *MI);
101    void EmitJump2Table(const MachineInstr *MI);
102    virtual void EmitInstruction(const MachineInstr *MI);
103    bool runOnMachineFunction(MachineFunction &F);
104
105    virtual void EmitConstantPool() {} // we emit constant pools customly!
106    virtual void EmitFunctionEntryLabel();
107    void EmitStartOfAsmFile(Module &M);
108    void EmitEndOfAsmFile(Module &M);
109
110    void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
111
112    MachineLocation getDebugValueLocation(const MachineInstr *MI) const {
113      MachineLocation Location;
114      assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
115      // Frame address.  Currently handles register +- offset only.
116      if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm())
117        Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
118      else {
119        DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n");
120      }
121      return Location;
122    }
123
124    virtual unsigned getISAEncoding() {
125      // ARM/Darwin adds ISA to the DWARF info for each function.
126      if (!Subtarget->isTargetDarwin())
127        return 0;
128      return Subtarget->isThumb() ?
129        llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm;
130    }
131
132    MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
133                                          const MachineBasicBlock *MBB) const;
134    MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
135
136    MCSymbol *GetARMSJLJEHLabel(void) const;
137
138    /// EmitMachineConstantPoolValue - Print a machine constantpool value to
139    /// the .s file.
140    virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
141      SmallString<128> Str;
142      raw_svector_ostream OS(Str);
143      EmitMachineConstantPoolValue(MCPV, OS);
144      OutStreamer.EmitRawText(OS.str());
145    }
146
147    void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV,
148                                      raw_ostream &O) {
149      switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) {
150      case 1: O << MAI->getData8bitsDirective(0); break;
151      case 2: O << MAI->getData16bitsDirective(0); break;
152      case 4: O << MAI->getData32bitsDirective(0); break;
153      default: assert(0 && "Unknown CPV size");
154      }
155
156      ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
157
158      if (ACPV->isLSDA()) {
159        O << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber();
160      } else if (ACPV->isBlockAddress()) {
161        O << *GetBlockAddressSymbol(ACPV->getBlockAddress());
162      } else if (ACPV->isGlobalValue()) {
163        const GlobalValue *GV = ACPV->getGV();
164        bool isIndirect = Subtarget->isTargetDarwin() &&
165          Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
166        if (!isIndirect)
167          O << *Mang->getSymbol(GV);
168        else {
169          // FIXME: Remove this when Darwin transition to @GOT like syntax.
170          MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
171          O << *Sym;
172
173          MachineModuleInfoMachO &MMIMachO =
174            MMI->getObjFileInfo<MachineModuleInfoMachO>();
175          MachineModuleInfoImpl::StubValueTy &StubSym =
176            GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) :
177                                        MMIMachO.getGVStubEntry(Sym);
178          if (StubSym.getPointer() == 0)
179            StubSym = MachineModuleInfoImpl::
180              StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
181        }
182      } else {
183        assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
184        O << *GetExternalSymbolSymbol(ACPV->getSymbol());
185      }
186
187      if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
188      if (ACPV->getPCAdjustment() != 0) {
189        O << "-(" << MAI->getPrivateGlobalPrefix() << "PC"
190          << getFunctionNumber() << "_"  << ACPV->getLabelId()
191          << "+" << (unsigned)ACPV->getPCAdjustment();
192         if (ACPV->mustAddCurrentAddress())
193           O << "-.";
194         O << ')';
195      }
196    }
197  };
198} // end of anonymous namespace
199
200void ARMAsmPrinter::EmitFunctionEntryLabel() {
201  if (AFI->isThumbFunction()) {
202    OutStreamer.EmitRawText(StringRef("\t.code\t16"));
203    if (!Subtarget->isTargetDarwin())
204      OutStreamer.EmitRawText(StringRef("\t.thumb_func"));
205    else {
206      // This needs to emit to a temporary string to get properly quoted
207      // MCSymbols when they have spaces in them.
208      SmallString<128> Tmp;
209      raw_svector_ostream OS(Tmp);
210      OS << "\t.thumb_func\t" << *CurrentFnSym;
211      OutStreamer.EmitRawText(OS.str());
212    }
213  }
214
215  OutStreamer.EmitLabel(CurrentFnSym);
216}
217
218/// runOnMachineFunction - This uses the EmitInstruction()
219/// method to print assembly for each instruction.
220///
221bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
222  AFI = MF.getInfo<ARMFunctionInfo>();
223  MCP = MF.getConstantPool();
224
225  return AsmPrinter::runOnMachineFunction(MF);
226}
227
228void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
229                                 raw_ostream &O, const char *Modifier) {
230  const MachineOperand &MO = MI->getOperand(OpNum);
231  unsigned TF = MO.getTargetFlags();
232
233  switch (MO.getType()) {
234  default:
235    assert(0 && "<unknown operand type>");
236  case MachineOperand::MO_Register: {
237    unsigned Reg = MO.getReg();
238    assert(TargetRegisterInfo::isPhysicalRegister(Reg));
239    assert(!MO.getSubReg() && "Subregs should be eliminated!");
240    O << ARMInstPrinter::getRegisterName(Reg);
241    break;
242  }
243  case MachineOperand::MO_Immediate: {
244    int64_t Imm = MO.getImm();
245    O << '#';
246    if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
247        (TF == ARMII::MO_LO16))
248      O << ":lower16:";
249    else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
250             (TF == ARMII::MO_HI16))
251      O << ":upper16:";
252    O << Imm;
253    break;
254  }
255  case MachineOperand::MO_MachineBasicBlock:
256    O << *MO.getMBB()->getSymbol();
257    return;
258  case MachineOperand::MO_GlobalAddress: {
259    bool isCallOp = Modifier && !strcmp(Modifier, "call");
260    const GlobalValue *GV = MO.getGlobal();
261
262    if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
263        (TF & ARMII::MO_LO16))
264      O << ":lower16:";
265    else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
266             (TF & ARMII::MO_HI16))
267      O << ":upper16:";
268    O << *Mang->getSymbol(GV);
269
270    printOffset(MO.getOffset(), O);
271
272    if (isCallOp && Subtarget->isTargetELF() &&
273        TM.getRelocationModel() == Reloc::PIC_)
274      O << "(PLT)";
275    break;
276  }
277  case MachineOperand::MO_ExternalSymbol: {
278    bool isCallOp = Modifier && !strcmp(Modifier, "call");
279    O << *GetExternalSymbolSymbol(MO.getSymbolName());
280
281    if (isCallOp && Subtarget->isTargetELF() &&
282        TM.getRelocationModel() == Reloc::PIC_)
283      O << "(PLT)";
284    break;
285  }
286  case MachineOperand::MO_ConstantPoolIndex:
287    O << *GetCPISymbol(MO.getIndex());
288    break;
289  case MachineOperand::MO_JumpTableIndex:
290    O << *GetJTISymbol(MO.getIndex());
291    break;
292  }
293}
294
295//===--------------------------------------------------------------------===//
296
297MCSymbol *ARMAsmPrinter::
298GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
299                            const MachineBasicBlock *MBB) const {
300  SmallString<60> Name;
301  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
302    << getFunctionNumber() << '_' << uid << '_' << uid2
303    << "_set_" << MBB->getNumber();
304  return OutContext.GetOrCreateSymbol(Name.str());
305}
306
307MCSymbol *ARMAsmPrinter::
308GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
309  SmallString<60> Name;
310  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
311    << getFunctionNumber() << '_' << uid << '_' << uid2;
312  return OutContext.GetOrCreateSymbol(Name.str());
313}
314
315
316MCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel(void) const {
317  SmallString<60> Name;
318  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH"
319    << getFunctionNumber();
320  return OutContext.GetOrCreateSymbol(Name.str());
321}
322
323bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
324                                    unsigned AsmVariant, const char *ExtraCode,
325                                    raw_ostream &O) {
326  // Does this asm operand have a single letter operand modifier?
327  if (ExtraCode && ExtraCode[0]) {
328    if (ExtraCode[1] != 0) return true; // Unknown modifier.
329
330    switch (ExtraCode[0]) {
331    default: return true;  // Unknown modifier.
332    case 'a': // Print as a memory address.
333      if (MI->getOperand(OpNum).isReg()) {
334        O << "["
335          << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg())
336          << "]";
337        return false;
338      }
339      // Fallthrough
340    case 'c': // Don't print "#" before an immediate operand.
341      if (!MI->getOperand(OpNum).isImm())
342        return true;
343      O << MI->getOperand(OpNum).getImm();
344      return false;
345    case 'P': // Print a VFP double precision register.
346    case 'q': // Print a NEON quad precision register.
347      printOperand(MI, OpNum, O);
348      return false;
349    case 'Q':
350    case 'R':
351    case 'H':
352      report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!");
353      return true;
354    }
355  }
356
357  printOperand(MI, OpNum, O);
358  return false;
359}
360
361bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
362                                          unsigned OpNum, unsigned AsmVariant,
363                                          const char *ExtraCode,
364                                          raw_ostream &O) {
365  if (ExtraCode && ExtraCode[0])
366    return true; // Unknown modifier.
367
368  const MachineOperand &MO = MI->getOperand(OpNum);
369  assert(MO.isReg() && "unexpected inline asm memory operand");
370  O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
371  return false;
372}
373
374void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
375  if (Subtarget->isTargetDarwin()) {
376    Reloc::Model RelocM = TM.getRelocationModel();
377    if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
378      // Declare all the text sections up front (before the DWARF sections
379      // emitted by AsmPrinter::doInitialization) so the assembler will keep
380      // them together at the beginning of the object file.  This helps
381      // avoid out-of-range branches that are due a fundamental limitation of
382      // the way symbol offsets are encoded with the current Darwin ARM
383      // relocations.
384      const TargetLoweringObjectFileMachO &TLOFMacho =
385        static_cast<const TargetLoweringObjectFileMachO &>(
386          getObjFileLowering());
387      OutStreamer.SwitchSection(TLOFMacho.getTextSection());
388      OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
389      OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection());
390      if (RelocM == Reloc::DynamicNoPIC) {
391        const MCSection *sect =
392          OutContext.getMachOSection("__TEXT", "__symbol_stub4",
393                                     MCSectionMachO::S_SYMBOL_STUBS,
394                                     12, SectionKind::getText());
395        OutStreamer.SwitchSection(sect);
396      } else {
397        const MCSection *sect =
398          OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
399                                     MCSectionMachO::S_SYMBOL_STUBS,
400                                     16, SectionKind::getText());
401        OutStreamer.SwitchSection(sect);
402      }
403      const MCSection *StaticInitSect =
404        OutContext.getMachOSection("__TEXT", "__StaticInit",
405                                   MCSectionMachO::S_REGULAR |
406                                   MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
407                                   SectionKind::getText());
408      OutStreamer.SwitchSection(StaticInitSect);
409    }
410  }
411
412  // Use unified assembler syntax.
413  OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified);
414
415  // Emit ARM Build Attributes
416  if (Subtarget->isTargetELF()) {
417    // CPU Type
418    std::string CPUString = Subtarget->getCPUString();
419    if (CPUString != "generic")
420      OutStreamer.EmitRawText("\t.cpu " + Twine(CPUString));
421
422    // FIXME: Emit FPU type
423    if (Subtarget->hasVFP2())
424      OutStreamer.EmitRawText("\t.eabi_attribute " +
425                              Twine(ARMBuildAttrs::VFP_arch) + ", 2");
426
427    // Signal various FP modes.
428    if (!UnsafeFPMath) {
429      OutStreamer.EmitRawText("\t.eabi_attribute " +
430                              Twine(ARMBuildAttrs::ABI_FP_denormal) + ", 1");
431      OutStreamer.EmitRawText("\t.eabi_attribute " +
432                              Twine(ARMBuildAttrs::ABI_FP_exceptions) + ", 1");
433    }
434
435    if (NoInfsFPMath && NoNaNsFPMath)
436      OutStreamer.EmitRawText("\t.eabi_attribute " +
437                              Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 1");
438    else
439      OutStreamer.EmitRawText("\t.eabi_attribute " +
440                              Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 3");
441
442    // 8-bytes alignment stuff.
443    OutStreamer.EmitRawText("\t.eabi_attribute " +
444                            Twine(ARMBuildAttrs::ABI_align8_needed) + ", 1");
445    OutStreamer.EmitRawText("\t.eabi_attribute " +
446                            Twine(ARMBuildAttrs::ABI_align8_preserved) + ", 1");
447
448    // Hard float.  Use both S and D registers and conform to AAPCS-VFP.
449    if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) {
450      OutStreamer.EmitRawText("\t.eabi_attribute " +
451                              Twine(ARMBuildAttrs::ABI_HardFP_use) + ", 3");
452      OutStreamer.EmitRawText("\t.eabi_attribute " +
453                              Twine(ARMBuildAttrs::ABI_VFP_args) + ", 1");
454    }
455    // FIXME: Should we signal R9 usage?
456  }
457}
458
459
460void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
461  if (Subtarget->isTargetDarwin()) {
462    // All darwin targets use mach-o.
463    const TargetLoweringObjectFileMachO &TLOFMacho =
464      static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
465    MachineModuleInfoMachO &MMIMacho =
466      MMI->getObjFileInfo<MachineModuleInfoMachO>();
467
468    // Output non-lazy-pointers for external and common global variables.
469    MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
470
471    if (!Stubs.empty()) {
472      // Switch with ".non_lazy_symbol_pointer" directive.
473      OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
474      EmitAlignment(2);
475      for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
476        // L_foo$stub:
477        OutStreamer.EmitLabel(Stubs[i].first);
478        //   .indirect_symbol _foo
479        MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
480        OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol);
481
482        if (MCSym.getInt())
483          // External to current translation unit.
484          OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
485        else
486          // Internal to current translation unit.
487          //
488          // When we place the LSDA into the TEXT section, the type info
489          // pointers need to be indirect and pc-rel. We accomplish this by
490          // using NLPs; however, sometimes the types are local to the file.
491          // We need to fill in the value for the NLP in those cases.
492          OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
493                                                        OutContext),
494                                4/*size*/, 0/*addrspace*/);
495      }
496
497      Stubs.clear();
498      OutStreamer.AddBlankLine();
499    }
500
501    Stubs = MMIMacho.GetHiddenGVStubList();
502    if (!Stubs.empty()) {
503      OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
504      EmitAlignment(2);
505      for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
506        // L_foo$stub:
507        OutStreamer.EmitLabel(Stubs[i].first);
508        //   .long _foo
509        OutStreamer.EmitValue(MCSymbolRefExpr::
510                              Create(Stubs[i].second.getPointer(),
511                                     OutContext),
512                              4/*size*/, 0/*addrspace*/);
513      }
514
515      Stubs.clear();
516      OutStreamer.AddBlankLine();
517    }
518
519    // Funny Darwin hack: This flag tells the linker that no global symbols
520    // contain code that falls through to other global symbols (e.g. the obvious
521    // implementation of multiple entry points).  If this doesn't occur, the
522    // linker can safely perform dead code stripping.  Since LLVM never
523    // generates code that does this, it is always safe to set.
524    OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
525  }
526}
527
528//===----------------------------------------------------------------------===//
529
530static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber,
531                             unsigned LabelId, MCContext &Ctx) {
532
533  MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix)
534                       + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
535  return Label;
536}
537
538void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
539  unsigned Opcode = MI->getOpcode();
540  int OpNum = 1;
541  if (Opcode == ARM::BR_JTadd)
542    OpNum = 2;
543  else if (Opcode == ARM::BR_JTm)
544    OpNum = 3;
545
546  const MachineOperand &MO1 = MI->getOperand(OpNum);
547  const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
548  unsigned JTI = MO1.getIndex();
549
550  // Emit a label for the jump table.
551  MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
552  OutStreamer.EmitLabel(JTISymbol);
553
554  // Emit each entry of the table.
555  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
556  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
557  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
558
559  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
560    MachineBasicBlock *MBB = JTBBs[i];
561    // Construct an MCExpr for the entry. We want a value of the form:
562    // (BasicBlockAddr - TableBeginAddr)
563    //
564    // For example, a table with entries jumping to basic blocks BB0 and BB1
565    // would look like:
566    // LJTI_0_0:
567    //    .word (LBB0 - LJTI_0_0)
568    //    .word (LBB1 - LJTI_0_0)
569    const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
570
571    if (TM.getRelocationModel() == Reloc::PIC_)
572      Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol,
573                                                                   OutContext),
574                                     OutContext);
575    OutStreamer.EmitValue(Expr, 4);
576  }
577}
578
579void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
580  unsigned Opcode = MI->getOpcode();
581  int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1;
582  const MachineOperand &MO1 = MI->getOperand(OpNum);
583  const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
584  unsigned JTI = MO1.getIndex();
585
586  // Emit a label for the jump table.
587  MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
588  OutStreamer.EmitLabel(JTISymbol);
589
590  // Emit each entry of the table.
591  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
592  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
593  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
594  unsigned OffsetWidth = 4;
595  if (MI->getOpcode() == ARM::t2TBB)
596    OffsetWidth = 1;
597  else if (MI->getOpcode() == ARM::t2TBH)
598    OffsetWidth = 2;
599
600  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
601    MachineBasicBlock *MBB = JTBBs[i];
602    const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(),
603                                                      OutContext);
604    // If this isn't a TBB or TBH, the entries are direct branch instructions.
605    if (OffsetWidth == 4) {
606      MCInst BrInst;
607      BrInst.setOpcode(ARM::t2B);
608      BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr));
609      OutStreamer.EmitInstruction(BrInst);
610      continue;
611    }
612    // Otherwise it's an offset from the dispatch instruction. Construct an
613    // MCExpr for the entry. We want a value of the form:
614    // (BasicBlockAddr - TableBeginAddr) / 2
615    //
616    // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
617    // would look like:
618    // LJTI_0_0:
619    //    .byte (LBB0 - LJTI_0_0) / 2
620    //    .byte (LBB1 - LJTI_0_0) / 2
621    const MCExpr *Expr =
622      MCBinaryExpr::CreateSub(MBBSymbolExpr,
623                              MCSymbolRefExpr::Create(JTISymbol, OutContext),
624                              OutContext);
625    Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext),
626                                   OutContext);
627    OutStreamer.EmitValue(Expr, OffsetWidth);
628  }
629
630  // Make sure the instruction that follows TBB is 2-byte aligned.
631  // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
632  if (MI->getOpcode() == ARM::t2TBB)
633    EmitAlignment(1);
634}
635
636void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
637                                           raw_ostream &OS) {
638  unsigned NOps = MI->getNumOperands();
639  assert(NOps==4);
640  OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
641  // cast away const; DIetc do not take const operands for some reason.
642  DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
643  OS << V.getName();
644  OS << " <- ";
645  // Frame address.  Currently handles register +- offset only.
646  assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
647  OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
648  OS << ']';
649  OS << "+";
650  printOperand(MI, NOps-2, OS);
651}
652
653void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
654  ARMMCInstLower MCInstLowering(OutContext, *Mang, *this);
655  switch (MI->getOpcode()) {
656  case ARM::t2MOVi32imm:
657    assert(0 && "Should be lowered by thumb2it pass");
658  default: break;
659  case ARM::DBG_VALUE: {
660    if (isVerbose() && OutStreamer.hasRawTextSupport()) {
661      SmallString<128> TmpStr;
662      raw_svector_ostream OS(TmpStr);
663      PrintDebugValueComment(MI, OS);
664      OutStreamer.EmitRawText(StringRef(OS.str()));
665    }
666    return;
667  }
668  case ARM::tPICADD: {
669    // This is a pseudo op for a label + instruction sequence, which looks like:
670    // LPC0:
671    //     add r0, pc
672    // This adds the address of LPC0 to r0.
673
674    // Emit the label.
675    OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
676                          getFunctionNumber(), MI->getOperand(2).getImm(),
677                          OutContext));
678
679    // Form and emit the add.
680    MCInst AddInst;
681    AddInst.setOpcode(ARM::tADDhirr);
682    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
683    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
684    AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
685    // Add predicate operands.
686    AddInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
687    AddInst.addOperand(MCOperand::CreateReg(0));
688    OutStreamer.EmitInstruction(AddInst);
689    return;
690  }
691  case ARM::PICADD: {
692    // This is a pseudo op for a label + instruction sequence, which looks like:
693    // LPC0:
694    //     add r0, pc, r0
695    // This adds the address of LPC0 to r0.
696
697    // Emit the label.
698    OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
699                          getFunctionNumber(), MI->getOperand(2).getImm(),
700                          OutContext));
701
702    // Form and emit the add.
703    MCInst AddInst;
704    AddInst.setOpcode(ARM::ADDrr);
705    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
706    AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
707    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
708    // Add predicate operands.
709    AddInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
710    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
711    // Add 's' bit operand (always reg0 for this)
712    AddInst.addOperand(MCOperand::CreateReg(0));
713    OutStreamer.EmitInstruction(AddInst);
714    return;
715  }
716  case ARM::PICSTR:
717  case ARM::PICSTRB:
718  case ARM::PICSTRH:
719  case ARM::PICLDR:
720  case ARM::PICLDRB:
721  case ARM::PICLDRH:
722  case ARM::PICLDRSB:
723  case ARM::PICLDRSH: {
724    // This is a pseudo op for a label + instruction sequence, which looks like:
725    // LPC0:
726    //     OP r0, [pc, r0]
727    // The LCP0 label is referenced by a constant pool entry in order to get
728    // a PC-relative address at the ldr instruction.
729
730    // Emit the label.
731    OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
732                          getFunctionNumber(), MI->getOperand(2).getImm(),
733                          OutContext));
734
735    // Form and emit the load
736    unsigned Opcode;
737    switch (MI->getOpcode()) {
738    default:
739      llvm_unreachable("Unexpected opcode!");
740    case ARM::PICSTR:   Opcode = ARM::STR; break;
741    case ARM::PICSTRB:  Opcode = ARM::STRB; break;
742    case ARM::PICSTRH:  Opcode = ARM::STRH; break;
743    case ARM::PICLDR:   Opcode = ARM::LDR; break;
744    case ARM::PICLDRB:  Opcode = ARM::LDRB; break;
745    case ARM::PICLDRH:  Opcode = ARM::LDRH; break;
746    case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
747    case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
748    }
749    MCInst LdStInst;
750    LdStInst.setOpcode(Opcode);
751    LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
752    LdStInst.addOperand(MCOperand::CreateReg(ARM::PC));
753    LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
754    LdStInst.addOperand(MCOperand::CreateImm(0));
755    // Add predicate operands.
756    LdStInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
757    LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
758    OutStreamer.EmitInstruction(LdStInst);
759
760    return;
761  }
762  case ARM::CONSTPOOL_ENTRY: {
763    /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
764    /// in the function.  The first operand is the ID# for this instruction, the
765    /// second is the index into the MachineConstantPool that this is, the third
766    /// is the size in bytes of this constant pool entry.
767    unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
768    unsigned CPIdx   = (unsigned)MI->getOperand(1).getIndex();
769
770    EmitAlignment(2);
771    OutStreamer.EmitLabel(GetCPISymbol(LabelId));
772
773    const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
774    if (MCPE.isMachineConstantPoolEntry())
775      EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
776    else
777      EmitGlobalConstant(MCPE.Val.ConstVal);
778
779    return;
780  }
781  case ARM::MOVi2pieces: {
782    // FIXME: We'd like to remove the asm string in the .td file, but the
783    // This is a hack that lowers as a two instruction sequence.
784    unsigned DstReg = MI->getOperand(0).getReg();
785    unsigned ImmVal = (unsigned)MI->getOperand(1).getImm();
786
787    unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal);
788    unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal);
789
790    {
791      MCInst TmpInst;
792      TmpInst.setOpcode(ARM::MOVi);
793      TmpInst.addOperand(MCOperand::CreateReg(DstReg));
794      TmpInst.addOperand(MCOperand::CreateImm(SOImmValV1));
795
796      // Predicate.
797      TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
798      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
799
800      TmpInst.addOperand(MCOperand::CreateReg(0));          // cc_out
801      OutStreamer.EmitInstruction(TmpInst);
802    }
803
804    {
805      MCInst TmpInst;
806      TmpInst.setOpcode(ARM::ORRri);
807      TmpInst.addOperand(MCOperand::CreateReg(DstReg));     // dstreg
808      TmpInst.addOperand(MCOperand::CreateReg(DstReg));     // inreg
809      TmpInst.addOperand(MCOperand::CreateImm(SOImmValV2)); // so_imm
810      // Predicate.
811      TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
812      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
813
814      TmpInst.addOperand(MCOperand::CreateReg(0));          // cc_out
815      OutStreamer.EmitInstruction(TmpInst);
816    }
817    return;
818  }
819  case ARM::MOVi32imm: {
820    // FIXME: We'd like to remove the asm string in the .td file, but the
821    // This is a hack that lowers as a two instruction sequence.
822    unsigned DstReg = MI->getOperand(0).getReg();
823    const MachineOperand &MO = MI->getOperand(1);
824    MCOperand V1, V2;
825    if (MO.isImm()) {
826      unsigned ImmVal = (unsigned)MI->getOperand(1).getImm();
827      V1 = MCOperand::CreateImm(ImmVal & 65535);
828      V2 = MCOperand::CreateImm(ImmVal >> 16);
829    } else if (MO.isGlobal()) {
830      MCSymbol *Symbol = MCInstLowering.GetGlobalAddressSymbol(MO.getGlobal());
831      const MCSymbolRefExpr *SymRef1 =
832        MCSymbolRefExpr::Create(Symbol,
833                                MCSymbolRefExpr::VK_ARM_LO16, OutContext);
834      const MCSymbolRefExpr *SymRef2 =
835        MCSymbolRefExpr::Create(Symbol,
836                                MCSymbolRefExpr::VK_ARM_HI16, OutContext);
837      V1 = MCOperand::CreateExpr(SymRef1);
838      V2 = MCOperand::CreateExpr(SymRef2);
839    } else {
840      // FIXME: External symbol?
841      MI->dump();
842      llvm_unreachable("cannot handle this operand");
843    }
844
845    {
846      MCInst TmpInst;
847      TmpInst.setOpcode(ARM::MOVi16);
848      TmpInst.addOperand(MCOperand::CreateReg(DstReg));         // dstreg
849      TmpInst.addOperand(V1); // lower16(imm)
850
851      // Predicate.
852      TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
853      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
854
855      OutStreamer.EmitInstruction(TmpInst);
856    }
857
858    {
859      MCInst TmpInst;
860      TmpInst.setOpcode(ARM::MOVTi16);
861      TmpInst.addOperand(MCOperand::CreateReg(DstReg));         // dstreg
862      TmpInst.addOperand(MCOperand::CreateReg(DstReg));         // srcreg
863      TmpInst.addOperand(V2);   // upper16(imm)
864
865      // Predicate.
866      TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
867      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
868
869      OutStreamer.EmitInstruction(TmpInst);
870    }
871
872    return;
873  }
874  case ARM::t2TBB:
875  case ARM::t2TBH:
876  case ARM::t2BR_JT: {
877    // Lower and emit the instruction itself, then the jump table following it.
878    MCInst TmpInst;
879    MCInstLowering.Lower(MI, TmpInst);
880    OutStreamer.EmitInstruction(TmpInst);
881    EmitJump2Table(MI);
882    return;
883  }
884  case ARM::tBR_JTr:
885  case ARM::BR_JTr:
886  case ARM::BR_JTm:
887  case ARM::BR_JTadd: {
888    // Lower and emit the instruction itself, then the jump table following it.
889    MCInst TmpInst;
890    MCInstLowering.Lower(MI, TmpInst);
891    OutStreamer.EmitInstruction(TmpInst);
892    EmitJumpTable(MI);
893    return;
894  }
895  case ARM::TRAP: {
896    // Non-Darwin binutils don't yet support the "trap" mnemonic.
897    // FIXME: Remove this special case when they do.
898    if (!Subtarget->isTargetDarwin()) {
899      //.long 0xe7ffdefe @ trap
900      uint32_t Val = 0xe7ffdefeUL;
901      OutStreamer.AddComment("trap");
902      OutStreamer.EmitIntValue(Val, 4);
903      return;
904    }
905    break;
906  }
907  case ARM::tTRAP: {
908    // Non-Darwin binutils don't yet support the "trap" mnemonic.
909    // FIXME: Remove this special case when they do.
910    if (!Subtarget->isTargetDarwin()) {
911      //.short 57086 @ trap
912      uint16_t Val = 0xdefe;
913      OutStreamer.AddComment("trap");
914      OutStreamer.EmitIntValue(Val, 2);
915      return;
916    }
917    break;
918  }
919  case ARM::t2Int_eh_sjlj_setjmp:
920  case ARM::t2Int_eh_sjlj_setjmp_nofp:
921  case ARM::tInt_eh_sjlj_setjmp: {
922    // Two incoming args: GPR:$src, GPR:$val
923    // mov $val, pc
924    // adds $val, #7
925    // str $val, [$src, #4]
926    // movs r0, #0
927    // b 1f
928    // movs r0, #1
929    // 1:
930    unsigned SrcReg = MI->getOperand(0).getReg();
931    unsigned ValReg = MI->getOperand(1).getReg();
932    MCSymbol *Label = GetARMSJLJEHLabel();
933    {
934      MCInst TmpInst;
935      TmpInst.setOpcode(ARM::tMOVgpr2tgpr);
936      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
937      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
938      // 's' bit operand
939      TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
940      OutStreamer.AddComment("eh_setjmp begin");
941      OutStreamer.EmitInstruction(TmpInst);
942    }
943    {
944      MCInst TmpInst;
945      TmpInst.setOpcode(ARM::tADDi3);
946      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
947      // 's' bit operand
948      TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
949      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
950      TmpInst.addOperand(MCOperand::CreateImm(7));
951      // Predicate.
952      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
953      TmpInst.addOperand(MCOperand::CreateReg(0));
954      OutStreamer.EmitInstruction(TmpInst);
955    }
956    {
957      MCInst TmpInst;
958      TmpInst.setOpcode(ARM::tSTR);
959      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
960      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
961      // The offset immediate is #4. The operand value is scaled by 4 for the
962      // tSTR instruction.
963      TmpInst.addOperand(MCOperand::CreateImm(1));
964      TmpInst.addOperand(MCOperand::CreateReg(0));
965      // Predicate.
966      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
967      TmpInst.addOperand(MCOperand::CreateReg(0));
968      OutStreamer.EmitInstruction(TmpInst);
969    }
970    {
971      MCInst TmpInst;
972      TmpInst.setOpcode(ARM::tMOVi8);
973      TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
974      TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
975      TmpInst.addOperand(MCOperand::CreateImm(0));
976      // Predicate.
977      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
978      TmpInst.addOperand(MCOperand::CreateReg(0));
979      OutStreamer.EmitInstruction(TmpInst);
980    }
981    {
982      const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext);
983      MCInst TmpInst;
984      TmpInst.setOpcode(ARM::tB);
985      TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr));
986      OutStreamer.EmitInstruction(TmpInst);
987    }
988    {
989      MCInst TmpInst;
990      TmpInst.setOpcode(ARM::tMOVi8);
991      TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
992      TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
993      TmpInst.addOperand(MCOperand::CreateImm(1));
994      // Predicate.
995      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
996      TmpInst.addOperand(MCOperand::CreateReg(0));
997      OutStreamer.AddComment("eh_setjmp end");
998      OutStreamer.EmitInstruction(TmpInst);
999    }
1000    OutStreamer.EmitLabel(Label);
1001    return;
1002  }
1003
1004  case ARM::Int_eh_sjlj_setjmp_nofp:
1005  case ARM::Int_eh_sjlj_setjmp: {
1006    // Two incoming args: GPR:$src, GPR:$val
1007    // add $val, pc, #8
1008    // str $val, [$src, #+4]
1009    // mov r0, #0
1010    // add pc, pc, #0
1011    // mov r0, #1
1012    unsigned SrcReg = MI->getOperand(0).getReg();
1013    unsigned ValReg = MI->getOperand(1).getReg();
1014
1015    {
1016      MCInst TmpInst;
1017      TmpInst.setOpcode(ARM::ADDri);
1018      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1019      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1020      TmpInst.addOperand(MCOperand::CreateImm(8));
1021      // Predicate.
1022      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1023      TmpInst.addOperand(MCOperand::CreateReg(0));
1024      // 's' bit operand (always reg0 for this).
1025      TmpInst.addOperand(MCOperand::CreateReg(0));
1026      OutStreamer.AddComment("eh_setjmp begin");
1027      OutStreamer.EmitInstruction(TmpInst);
1028    }
1029    {
1030      MCInst TmpInst;
1031      TmpInst.setOpcode(ARM::STR);
1032      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1033      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1034      TmpInst.addOperand(MCOperand::CreateReg(0));
1035      TmpInst.addOperand(MCOperand::CreateImm(4));
1036      // Predicate.
1037      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1038      TmpInst.addOperand(MCOperand::CreateReg(0));
1039      OutStreamer.EmitInstruction(TmpInst);
1040    }
1041    {
1042      MCInst TmpInst;
1043      TmpInst.setOpcode(ARM::MOVi);
1044      TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1045      TmpInst.addOperand(MCOperand::CreateImm(0));
1046      // Predicate.
1047      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1048      TmpInst.addOperand(MCOperand::CreateReg(0));
1049      // 's' bit operand (always reg0 for this).
1050      TmpInst.addOperand(MCOperand::CreateReg(0));
1051      OutStreamer.EmitInstruction(TmpInst);
1052    }
1053    {
1054      MCInst TmpInst;
1055      TmpInst.setOpcode(ARM::ADDri);
1056      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1057      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1058      TmpInst.addOperand(MCOperand::CreateImm(0));
1059      // Predicate.
1060      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1061      TmpInst.addOperand(MCOperand::CreateReg(0));
1062      // 's' bit operand (always reg0 for this).
1063      TmpInst.addOperand(MCOperand::CreateReg(0));
1064      OutStreamer.EmitInstruction(TmpInst);
1065    }
1066    {
1067      MCInst TmpInst;
1068      TmpInst.setOpcode(ARM::MOVi);
1069      TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1070      TmpInst.addOperand(MCOperand::CreateImm(1));
1071      // Predicate.
1072      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1073      TmpInst.addOperand(MCOperand::CreateReg(0));
1074      // 's' bit operand (always reg0 for this).
1075      TmpInst.addOperand(MCOperand::CreateReg(0));
1076      OutStreamer.AddComment("eh_setjmp end");
1077      OutStreamer.EmitInstruction(TmpInst);
1078    }
1079    return;
1080  }
1081  case ARM::Int_eh_sjlj_longjmp: {
1082    // ldr sp, [$src, #8]
1083    // ldr $scratch, [$src, #4]
1084    // ldr r7, [$src]
1085    // bx $scratch
1086    unsigned SrcReg = MI->getOperand(0).getReg();
1087    unsigned ScratchReg = MI->getOperand(1).getReg();
1088    {
1089      MCInst TmpInst;
1090      TmpInst.setOpcode(ARM::LDR);
1091      TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1092      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1093      TmpInst.addOperand(MCOperand::CreateReg(0));
1094      TmpInst.addOperand(MCOperand::CreateImm(8));
1095      // Predicate.
1096      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1097      TmpInst.addOperand(MCOperand::CreateReg(0));
1098      OutStreamer.EmitInstruction(TmpInst);
1099    }
1100    {
1101      MCInst TmpInst;
1102      TmpInst.setOpcode(ARM::LDR);
1103      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1104      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1105      TmpInst.addOperand(MCOperand::CreateReg(0));
1106      TmpInst.addOperand(MCOperand::CreateImm(4));
1107      // Predicate.
1108      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1109      TmpInst.addOperand(MCOperand::CreateReg(0));
1110      OutStreamer.EmitInstruction(TmpInst);
1111    }
1112    {
1113      MCInst TmpInst;
1114      TmpInst.setOpcode(ARM::LDR);
1115      TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1116      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1117      TmpInst.addOperand(MCOperand::CreateReg(0));
1118      TmpInst.addOperand(MCOperand::CreateImm(0));
1119      // Predicate.
1120      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1121      TmpInst.addOperand(MCOperand::CreateReg(0));
1122      OutStreamer.EmitInstruction(TmpInst);
1123    }
1124    {
1125      MCInst TmpInst;
1126      TmpInst.setOpcode(ARM::BRIND);
1127      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1128      // Predicate.
1129      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1130      TmpInst.addOperand(MCOperand::CreateReg(0));
1131      OutStreamer.EmitInstruction(TmpInst);
1132    }
1133    return;
1134  }
1135  case ARM::tInt_eh_sjlj_longjmp: {
1136    // ldr $scratch, [$src, #8]
1137    // mov sp, $scratch
1138    // ldr $scratch, [$src, #4]
1139    // ldr r7, [$src]
1140    // bx $scratch
1141    unsigned SrcReg = MI->getOperand(0).getReg();
1142    unsigned ScratchReg = MI->getOperand(1).getReg();
1143    {
1144      MCInst TmpInst;
1145      TmpInst.setOpcode(ARM::tLDR);
1146      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1147      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1148      // The offset immediate is #8. The operand value is scaled by 4 for the
1149      // tSTR instruction.
1150      TmpInst.addOperand(MCOperand::CreateImm(2));
1151      TmpInst.addOperand(MCOperand::CreateReg(0));
1152      // Predicate.
1153      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1154      TmpInst.addOperand(MCOperand::CreateReg(0));
1155      OutStreamer.EmitInstruction(TmpInst);
1156    }
1157    {
1158      MCInst TmpInst;
1159      TmpInst.setOpcode(ARM::tMOVtgpr2gpr);
1160      TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1161      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1162      // Predicate.
1163      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1164      TmpInst.addOperand(MCOperand::CreateReg(0));
1165      OutStreamer.EmitInstruction(TmpInst);
1166    }
1167    {
1168      MCInst TmpInst;
1169      TmpInst.setOpcode(ARM::tLDR);
1170      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1171      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1172      TmpInst.addOperand(MCOperand::CreateImm(1));
1173      TmpInst.addOperand(MCOperand::CreateReg(0));
1174      // Predicate.
1175      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1176      TmpInst.addOperand(MCOperand::CreateReg(0));
1177      OutStreamer.EmitInstruction(TmpInst);
1178    }
1179    {
1180      MCInst TmpInst;
1181      TmpInst.setOpcode(ARM::tLDR);
1182      TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1183      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1184      TmpInst.addOperand(MCOperand::CreateImm(0));
1185      TmpInst.addOperand(MCOperand::CreateReg(0));
1186      // Predicate.
1187      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1188      TmpInst.addOperand(MCOperand::CreateReg(0));
1189      OutStreamer.EmitInstruction(TmpInst);
1190    }
1191    {
1192      MCInst TmpInst;
1193      TmpInst.setOpcode(ARM::tBX_RET_vararg);
1194      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1195      // Predicate.
1196      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1197      TmpInst.addOperand(MCOperand::CreateReg(0));
1198      OutStreamer.EmitInstruction(TmpInst);
1199    }
1200    return;
1201  }
1202  }
1203
1204  MCInst TmpInst;
1205  MCInstLowering.Lower(MI, TmpInst);
1206  OutStreamer.EmitInstruction(TmpInst);
1207}
1208
1209//===----------------------------------------------------------------------===//
1210// Target Registry Stuff
1211//===----------------------------------------------------------------------===//
1212
1213static MCInstPrinter *createARMMCInstPrinter(const Target &T,
1214                                             unsigned SyntaxVariant,
1215                                             const MCAsmInfo &MAI) {
1216  if (SyntaxVariant == 0)
1217    return new ARMInstPrinter(MAI);
1218  return 0;
1219}
1220
1221// Force static initialization.
1222extern "C" void LLVMInitializeARMAsmPrinter() {
1223  RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget);
1224  RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget);
1225
1226  TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
1227  TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);
1228}
1229
1230