1 //===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
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"
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
{
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
{
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
));
96 class ObjectAttributeEmitter
: public AttributeEmitter
{
97 MCObjectStreamer
&Streamer
;
98 StringRef CurrentVendor
;
99 SmallString
<64> Contents
;
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
)
115 CurrentVendor
= Vendor
;
117 assert(Contents
.size() == 0);
120 void EmitAttribute(unsigned Attribute
, unsigned Value
) {
121 // FIXME: should be ULEB
122 Contents
+= Attribute
;
127 const size_t ContentsSize
= Contents
.size();
129 // Vendor size + Vendor name + '\0'
130 const size_t VendorHeaderSize
= 4 + CurrentVendor
.size() + 1;
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);
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
156 ARMFunctionInfo
*AFI
;
158 /// MCP - Keep a pointer to constantpool entries of the current
160 const MachineConstantPool
*MCP
;
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
,
178 virtual bool PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNum
,
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
);
193 // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
194 void emitAttributes();
196 // Helper for ELF .o only
197 void emitARMAttributeSection();
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());
209 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI
<< "\n");
214 virtual unsigned getISAEncoding() {
215 // ARM/Darwin adds ISA to the DWARF info for each function.
216 if (!Subtarget
->isTargetDarwin())
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
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
,
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());
257 O
<< *Mang
->getSymbol(GV
);
259 // FIXME: Remove this when Darwin transition to @GOT like syntax.
260 MCSymbol
*Sym
= GetSymbolWithGlobalValueBase(GV
, "$non_lazy_ptr");
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());
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())
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"));
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()) {
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
);
333 case MachineOperand::MO_Immediate
: {
334 int64_t Imm
= MO
.getImm();
336 if ((Modifier
&& strcmp(Modifier
, "lo16") == 0) ||
337 (TF
== ARMII::MO_LO16
))
339 else if ((Modifier
&& strcmp(Modifier
, "hi16") == 0) ||
340 (TF
== ARMII::MO_HI16
))
345 case MachineOperand::MO_MachineBasicBlock
:
346 O
<< *MO
.getMBB()->getSymbol();
348 case MachineOperand::MO_GlobalAddress
: {
349 const GlobalValue
*GV
= MO
.getGlobal();
350 if ((Modifier
&& strcmp(Modifier
, "lo16") == 0) ||
351 (TF
& ARMII::MO_LO16
))
353 else if ((Modifier
&& strcmp(Modifier
, "hi16") == 0) ||
354 (TF
& ARMII::MO_HI16
))
356 O
<< *Mang
->getSymbol(GV
);
358 printOffset(MO
.getOffset(), O
);
359 if (TF
== ARMII::MO_PLT
)
363 case MachineOperand::MO_ExternalSymbol
: {
364 O
<< *GetExternalSymbolSymbol(MO
.getSymbolName());
365 if (TF
== ARMII::MO_PLT
)
369 case MachineOperand::MO_ConstantPoolIndex
:
370 O
<< *GetCPISymbol(MO
.getIndex());
372 case MachineOperand::MO_JumpTableIndex
:
373 O
<< *GetJTISymbol(MO
.getIndex());
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
,
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()) {
418 << ARMInstPrinter::getRegisterName(MI
->getOperand(OpNum
).getReg())
423 case 'c': // Don't print "#" before an immediate operand.
424 if (!MI
->getOperand(OpNum
).isImm())
426 O
<< MI
->getOperand(OpNum
).getImm();
428 case 'P': // Print a VFP double precision register.
429 case 'q': // Print a NEON quad precision register.
430 printOperand(MI
, OpNum
, O
);
435 report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!");
440 printOperand(MI
, OpNum
, O
);
444 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
445 unsigned OpNum
, unsigned AsmVariant
,
446 const char *ExtraCode
,
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()) << "]";
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
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
);
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()) {
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());
521 for (unsigned i
= 0, e
= Stubs
.size(); i
!= e
; ++i
) {
523 OutStreamer
.EmitLabel(Stubs
[i
].first
);
524 // .indirect_symbol _foo
525 MachineModuleInfoImpl::StubValueTy
&MCSym
= Stubs
[i
].second
;
526 OutStreamer
.EmitSymbolAttribute(MCSym
.getPointer(),MCSA_IndirectSymbol
);
529 // External to current translation unit.
530 OutStreamer
.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
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(),
540 4/*size*/, 0/*addrspace*/);
544 OutStreamer
.AddBlankLine();
547 Stubs
= MMIMacho
.GetHiddenGVStubList();
548 if (!Stubs
.empty()) {
549 OutStreamer
.SwitchSection(getObjFileLowering().getDataSection());
551 for (unsigned i
= 0, e
= Stubs
.size(); i
!= e
; ++i
) {
553 OutStreamer
.EmitLabel(Stubs
[i
].first
);
555 OutStreamer
.EmitValue(MCSymbolRefExpr::
556 Create(Stubs
[i
].second
.getPointer(),
558 4/*size*/, 0/*addrspace*/);
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()
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
);
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
);
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.
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);
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();
639 void ARMAsmPrinter::emitARMAttributeSection() {
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>*
648 if (OutStreamer
.hasRawTextSupport())
651 const ARMElfTargetObjectFile
&TLOFELF
=
652 static_cast<const ARMElfTargetObjectFile
&>
653 (getObjFileLowering());
655 OutStreamer
.SwitchSection(TLOFELF
.getAttributesSection());
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
));
671 void ARMAsmPrinter::EmitJumpTable(const MachineInstr
*MI
) {
672 unsigned Opcode
= MI
->getOpcode();
674 if (Opcode
== ARM::BR_JTadd
)
676 else if (Opcode
== ARM::BR_JTm
)
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
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
,
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
)
730 else if (MI
->getOpcode() == ARM::t2TBH
)
733 for (unsigned i
= 0, e
= JTBBs
.size(); i
!= e
; ++i
) {
734 MachineBasicBlock
*MBB
= JTBBs
[i
];
735 const MCExpr
*MBBSymbolExpr
= MCSymbolRefExpr::Create(MBB
->getSymbol(),
737 // If this isn't a TBB or TBH, the entries are direct branch instructions.
738 if (OffsetWidth
== 4) {
740 BrInst
.setOpcode(ARM::t2B
);
741 BrInst
.addOperand(MCOperand::CreateExpr(MBBSymbolExpr
));
742 OutStreamer
.EmitInstruction(BrInst
);
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
752 // .byte (LBB0 - LJTI_0_0) / 2
753 // .byte (LBB1 - LJTI_0_0) / 2
755 MCBinaryExpr::CreateSub(MBBSymbolExpr
,
756 MCSymbolRefExpr::Create(JTISymbol
, OutContext
),
758 Expr
= MCBinaryExpr::CreateDiv(Expr
, MCConstantExpr::Create(2, 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
)
769 void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr
*MI
,
771 unsigned NOps
= MI
->getNumOperands();
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()));
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
);
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");
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()));
802 // This is a pseudo op for a label + instruction sequence, which looks like:
805 // This adds the address of LPC0 to r0.
808 OutStreamer
.EmitLabel(getPICLabel(MAI
->getPrivateGlobalPrefix(),
809 getFunctionNumber(), MI
->getOperand(2).getImm(),
812 // Form and emit the add.
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
);
825 // This is a pseudo op for a label + instruction sequence, which looks like:
828 // This adds the address of LPC0 to r0.
831 OutStreamer
.EmitLabel(getPICLabel(MAI
->getPrivateGlobalPrefix(),
832 getFunctionNumber(), MI
->getOperand(2).getImm(),
835 // Form and emit the add.
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
);
856 case ARM::PICLDRSH
: {
857 // This is a pseudo op for a label + instruction sequence, which looks like:
860 // The LCP0 label is referenced by a constant pool entry in order to get
861 // a PC-relative address at the ldr instruction.
864 OutStreamer
.EmitLabel(getPICLabel(MAI
->getPrivateGlobalPrefix(),
865 getFunctionNumber(), MI
->getOperand(2).getImm(),
868 // Form and emit the load
870 switch (MI
->getOpcode()) {
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;
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
);
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();
904 OutStreamer
.EmitLabel(GetCPISymbol(LabelId
));
906 const MachineConstantPoolEntry
&MCPE
= MCP
->getConstants()[CPIdx
];
907 if (MCPE
.isMachineConstantPoolEntry())
908 EmitMachineConstantPoolValue(MCPE
.Val
.MachineCPVal
);
910 EmitGlobalConstant(MCPE
.Val
.ConstVal
);
917 // Lower and emit the instruction itself, then the jump table following it.
919 MCInstLowering
.Lower(MI
, TmpInst
);
920 OutStreamer
.EmitInstruction(TmpInst
);
927 case ARM::BR_JTadd
: {
928 // Lower and emit the instruction itself, then the jump table following it.
930 MCInstLowering
.Lower(MI
, TmpInst
);
931 OutStreamer
.EmitInstruction(TmpInst
);
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);
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);
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
965 // str $val, [$src, #4]
970 unsigned SrcReg
= MI
->getOperand(0).getReg();
971 unsigned ValReg
= MI
->getOperand(1).getReg();
972 MCSymbol
*Label
= GetARMSJLJEHLabel();
975 TmpInst
.setOpcode(ARM::tMOVgpr2tgpr
);
976 TmpInst
.addOperand(MCOperand::CreateReg(ValReg
));
977 TmpInst
.addOperand(MCOperand::CreateReg(ARM::PC
));
979 TmpInst
.addOperand(MCOperand::CreateReg(ARM::CPSR
));
980 OutStreamer
.AddComment("eh_setjmp begin");
981 OutStreamer
.EmitInstruction(TmpInst
);
985 TmpInst
.setOpcode(ARM::tADDi3
);
986 TmpInst
.addOperand(MCOperand::CreateReg(ValReg
));
988 TmpInst
.addOperand(MCOperand::CreateReg(ARM::CPSR
));
989 TmpInst
.addOperand(MCOperand::CreateReg(ValReg
));
990 TmpInst
.addOperand(MCOperand::CreateImm(7));
992 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
993 TmpInst
.addOperand(MCOperand::CreateReg(0));
994 OutStreamer
.EmitInstruction(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));
1006 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1007 TmpInst
.addOperand(MCOperand::CreateReg(0));
1008 OutStreamer
.EmitInstruction(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));
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
);
1024 TmpInst
.setOpcode(ARM::tB
);
1025 TmpInst
.addOperand(MCOperand::CreateExpr(SymbolExpr
));
1026 OutStreamer
.EmitInstruction(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));
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
);
1044 case ARM::Int_eh_sjlj_setjmp_nofp
:
1045 case ARM::Int_eh_sjlj_setjmp
: {
1046 // Two incoming args: GPR:$src, GPR:$val
1048 // str $val, [$src, #+4]
1052 unsigned SrcReg
= MI
->getOperand(0).getReg();
1053 unsigned ValReg
= MI
->getOperand(1).getReg();
1057 TmpInst
.setOpcode(ARM::ADDri
);
1058 TmpInst
.addOperand(MCOperand::CreateReg(ValReg
));
1059 TmpInst
.addOperand(MCOperand::CreateReg(ARM::PC
));
1060 TmpInst
.addOperand(MCOperand::CreateImm(8));
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
);
1071 TmpInst
.setOpcode(ARM::STRi12
);
1072 TmpInst
.addOperand(MCOperand::CreateReg(ValReg
));
1073 TmpInst
.addOperand(MCOperand::CreateReg(SrcReg
));
1074 TmpInst
.addOperand(MCOperand::CreateImm(4));
1076 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1077 TmpInst
.addOperand(MCOperand::CreateReg(0));
1078 OutStreamer
.EmitInstruction(TmpInst
);
1082 TmpInst
.setOpcode(ARM::MOVi
);
1083 TmpInst
.addOperand(MCOperand::CreateReg(ARM::R0
));
1084 TmpInst
.addOperand(MCOperand::CreateImm(0));
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
);
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));
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
);
1107 TmpInst
.setOpcode(ARM::MOVi
);
1108 TmpInst
.addOperand(MCOperand::CreateReg(ARM::R0
));
1109 TmpInst
.addOperand(MCOperand::CreateImm(1));
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
);
1120 case ARM::Int_eh_sjlj_longjmp
: {
1121 // ldr sp, [$src, #8]
1122 // ldr $scratch, [$src, #4]
1125 unsigned SrcReg
= MI
->getOperand(0).getReg();
1126 unsigned ScratchReg
= MI
->getOperand(1).getReg();
1129 TmpInst
.setOpcode(ARM::LDRi12
);
1130 TmpInst
.addOperand(MCOperand::CreateReg(ARM::SP
));
1131 TmpInst
.addOperand(MCOperand::CreateReg(SrcReg
));
1132 TmpInst
.addOperand(MCOperand::CreateImm(8));
1134 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1135 TmpInst
.addOperand(MCOperand::CreateReg(0));
1136 OutStreamer
.EmitInstruction(TmpInst
);
1140 TmpInst
.setOpcode(ARM::LDRi12
);
1141 TmpInst
.addOperand(MCOperand::CreateReg(ScratchReg
));
1142 TmpInst
.addOperand(MCOperand::CreateReg(SrcReg
));
1143 TmpInst
.addOperand(MCOperand::CreateImm(4));
1145 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1146 TmpInst
.addOperand(MCOperand::CreateReg(0));
1147 OutStreamer
.EmitInstruction(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));
1156 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1157 TmpInst
.addOperand(MCOperand::CreateReg(0));
1158 OutStreamer
.EmitInstruction(TmpInst
);
1162 TmpInst
.setOpcode(ARM::BRIND
);
1163 TmpInst
.addOperand(MCOperand::CreateReg(ScratchReg
));
1165 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1166 TmpInst
.addOperand(MCOperand::CreateReg(0));
1167 OutStreamer
.EmitInstruction(TmpInst
);
1171 case ARM::tInt_eh_sjlj_longjmp
: {
1172 // ldr $scratch, [$src, #8]
1174 // ldr $scratch, [$src, #4]
1177 unsigned SrcReg
= MI
->getOperand(0).getReg();
1178 unsigned ScratchReg
= MI
->getOperand(1).getReg();
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));
1189 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1190 TmpInst
.addOperand(MCOperand::CreateReg(0));
1191 OutStreamer
.EmitInstruction(TmpInst
);
1195 TmpInst
.setOpcode(ARM::tMOVtgpr2gpr
);
1196 TmpInst
.addOperand(MCOperand::CreateReg(ARM::SP
));
1197 TmpInst
.addOperand(MCOperand::CreateReg(ScratchReg
));
1199 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1200 TmpInst
.addOperand(MCOperand::CreateReg(0));
1201 OutStreamer
.EmitInstruction(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));
1211 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1212 TmpInst
.addOperand(MCOperand::CreateReg(0));
1213 OutStreamer
.EmitInstruction(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));
1223 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1224 TmpInst
.addOperand(MCOperand::CreateReg(0));
1225 OutStreamer
.EmitInstruction(TmpInst
);
1229 TmpInst
.setOpcode(ARM::tBX_RET_vararg
);
1230 TmpInst
.addOperand(MCOperand::CreateReg(ScratchReg
));
1232 TmpInst
.addOperand(MCOperand::CreateImm(ARMCC::AL
));
1233 TmpInst
.addOperand(MCOperand::CreateReg(0));
1234 OutStreamer
.EmitInstruction(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
);
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
);