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