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