1212793Sdim//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===// 2212793Sdim// 3212793Sdim// The LLVM Compiler Infrastructure 4212793Sdim// 5212793Sdim// This file is distributed under the University of Illinois Open Source 6212793Sdim// License. See LICENSE.TXT for details. 7212793Sdim// 8212793Sdim//===----------------------------------------------------------------------===// 9212793Sdim// 10212793Sdim// This file contains a printer that converts from our internal representation 11212793Sdim// of machine-dependent LLVM code to GAS-format ARM assembly language. 12212793Sdim// 13212793Sdim//===----------------------------------------------------------------------===// 14212793Sdim 15212793Sdim#define DEBUG_TYPE "asm-printer" 16234353Sdim#include "ARMAsmPrinter.h" 17212793Sdim#include "ARM.h" 18212793Sdim#include "ARMBuildAttrs.h" 19212793Sdim#include "ARMConstantPoolValue.h" 20212793Sdim#include "ARMMachineFunctionInfo.h" 21212793Sdim#include "ARMTargetMachine.h" 22218893Sdim#include "ARMTargetObjectFile.h" 23218893Sdim#include "InstPrinter/ARMInstPrinter.h" 24226633Sdim#include "MCTargetDesc/ARMAddressingModes.h" 25226633Sdim#include "MCTargetDesc/ARMMCExpr.h" 26243830Sdim#include "llvm/ADT/SetVector.h" 27243830Sdim#include "llvm/ADT/SmallString.h" 28212793Sdim#include "llvm/Assembly/Writer.h" 29212793Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 30212793Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h" 31249423Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h" 32249423Sdim#include "llvm/DebugInfo.h" 33249423Sdim#include "llvm/IR/Constants.h" 34249423Sdim#include "llvm/IR/DataLayout.h" 35249423Sdim#include "llvm/IR/Module.h" 36249423Sdim#include "llvm/IR/Type.h" 37212793Sdim#include "llvm/MC/MCAsmInfo.h" 38218893Sdim#include "llvm/MC/MCAssembler.h" 39212793Sdim#include "llvm/MC/MCContext.h" 40249423Sdim#include "llvm/MC/MCELFStreamer.h" 41212793Sdim#include "llvm/MC/MCInst.h" 42249423Sdim#include "llvm/MC/MCInstBuilder.h" 43249423Sdim#include "llvm/MC/MCObjectStreamer.h" 44212793Sdim#include "llvm/MC/MCSectionMachO.h" 45212793Sdim#include "llvm/MC/MCStreamer.h" 46212793Sdim#include "llvm/MC/MCSymbol.h" 47212793Sdim#include "llvm/Support/CommandLine.h" 48212793Sdim#include "llvm/Support/Debug.h" 49249423Sdim#include "llvm/Support/ELF.h" 50212793Sdim#include "llvm/Support/ErrorHandling.h" 51226633Sdim#include "llvm/Support/TargetRegistry.h" 52212793Sdim#include "llvm/Support/raw_ostream.h" 53249423Sdim#include "llvm/Target/Mangler.h" 54249423Sdim#include "llvm/Target/TargetMachine.h" 55212793Sdim#include <cctype> 56212793Sdimusing namespace llvm; 57212793Sdim 58212793Sdimnamespace { 59212793Sdim 60218893Sdim // Per section and per symbol attributes are not supported. 61218893Sdim // To implement them we would need the ability to delay this emission 62218893Sdim // until the assembly file is fully parsed/generated as only then do we 63218893Sdim // know the symbol and section numbers. 64218893Sdim class AttributeEmitter { 65218893Sdim public: 66218893Sdim virtual void MaybeSwitchVendor(StringRef Vendor) = 0; 67218893Sdim virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0; 68218893Sdim virtual void EmitTextAttribute(unsigned Attribute, StringRef String) = 0; 69218893Sdim virtual void Finish() = 0; 70218893Sdim virtual ~AttributeEmitter() {} 71218893Sdim }; 72212793Sdim 73218893Sdim class AsmAttributeEmitter : public AttributeEmitter { 74218893Sdim MCStreamer &Streamer; 75212793Sdim 76218893Sdim public: 77218893Sdim AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {} 78218893Sdim void MaybeSwitchVendor(StringRef Vendor) { } 79212793Sdim 80218893Sdim void EmitAttribute(unsigned Attribute, unsigned Value) { 81218893Sdim Streamer.EmitRawText("\t.eabi_attribute " + 82218893Sdim Twine(Attribute) + ", " + Twine(Value)); 83212793Sdim } 84212793Sdim 85218893Sdim void EmitTextAttribute(unsigned Attribute, StringRef String) { 86218893Sdim switch (Attribute) { 87234353Sdim default: llvm_unreachable("Unsupported Text attribute in ASM Mode"); 88218893Sdim case ARMBuildAttrs::CPU_name: 89234353Sdim Streamer.EmitRawText(StringRef("\t.cpu ") + String.lower()); 90218893Sdim break; 91221345Sdim /* GAS requires .fpu to be emitted regardless of EABI attribute */ 92221345Sdim case ARMBuildAttrs::Advanced_SIMD_arch: 93221345Sdim case ARMBuildAttrs::VFP_arch: 94234353Sdim Streamer.EmitRawText(StringRef("\t.fpu ") + String.lower()); 95226633Sdim break; 96218893Sdim } 97212793Sdim } 98218893Sdim void Finish() { } 99218893Sdim }; 100212793Sdim 101218893Sdim class ObjectAttributeEmitter : public AttributeEmitter { 102226633Sdim // This structure holds all attributes, accounting for 103226633Sdim // their string/numeric value, so we can later emmit them 104226633Sdim // in declaration order, keeping all in the same vector 105226633Sdim struct AttributeItemType { 106226633Sdim enum { 107226633Sdim HiddenAttribute = 0, 108226633Sdim NumericAttribute, 109226633Sdim TextAttribute 110226633Sdim } Type; 111226633Sdim unsigned Tag; 112226633Sdim unsigned IntValue; 113226633Sdim StringRef StringValue; 114226633Sdim } AttributeItem; 115226633Sdim 116218893Sdim MCObjectStreamer &Streamer; 117218893Sdim StringRef CurrentVendor; 118226633Sdim SmallVector<AttributeItemType, 64> Contents; 119212793Sdim 120226633Sdim // Account for the ULEB/String size of each item, 121226633Sdim // not just the number of items 122226633Sdim size_t ContentsSize; 123226633Sdim // FIXME: this should be in a more generic place, but 124226633Sdim // getULEBSize() is in MCAsmInfo and will be moved to MCDwarf 125226633Sdim size_t getULEBSize(int Value) { 126226633Sdim size_t Size = 0; 127226633Sdim do { 128226633Sdim Value >>= 7; 129226633Sdim Size += sizeof(int8_t); // Is this really necessary? 130226633Sdim } while (Value); 131226633Sdim return Size; 132226633Sdim } 133226633Sdim 134218893Sdim public: 135218893Sdim ObjectAttributeEmitter(MCObjectStreamer &Streamer_) : 136226633Sdim Streamer(Streamer_), CurrentVendor(""), ContentsSize(0) { } 137212793Sdim 138218893Sdim void MaybeSwitchVendor(StringRef Vendor) { 139218893Sdim assert(!Vendor.empty() && "Vendor cannot be empty."); 140212793Sdim 141218893Sdim if (CurrentVendor.empty()) 142218893Sdim CurrentVendor = Vendor; 143218893Sdim else if (CurrentVendor == Vendor) 144218893Sdim return; 145218893Sdim else 146218893Sdim Finish(); 147212793Sdim 148218893Sdim CurrentVendor = Vendor; 149212793Sdim 150218893Sdim assert(Contents.size() == 0); 151218893Sdim } 152212793Sdim 153218893Sdim void EmitAttribute(unsigned Attribute, unsigned Value) { 154226633Sdim AttributeItemType attr = { 155226633Sdim AttributeItemType::NumericAttribute, 156226633Sdim Attribute, 157226633Sdim Value, 158226633Sdim StringRef("") 159226633Sdim }; 160226633Sdim ContentsSize += getULEBSize(Attribute); 161226633Sdim ContentsSize += getULEBSize(Value); 162226633Sdim Contents.push_back(attr); 163212793Sdim } 164212793Sdim 165218893Sdim void EmitTextAttribute(unsigned Attribute, StringRef String) { 166226633Sdim AttributeItemType attr = { 167226633Sdim AttributeItemType::TextAttribute, 168226633Sdim Attribute, 169226633Sdim 0, 170226633Sdim String 171226633Sdim }; 172226633Sdim ContentsSize += getULEBSize(Attribute); 173226633Sdim // String + \0 174226633Sdim ContentsSize += String.size()+1; 175226633Sdim 176226633Sdim Contents.push_back(attr); 177212793Sdim } 178212793Sdim 179218893Sdim void Finish() { 180218893Sdim // Vendor size + Vendor name + '\0' 181218893Sdim const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1; 182212793Sdim 183218893Sdim // Tag + Tag Size 184218893Sdim const size_t TagHeaderSize = 1 + 4; 185212793Sdim 186218893Sdim Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4); 187249423Sdim Streamer.EmitBytes(CurrentVendor); 188218893Sdim Streamer.EmitIntValue(0, 1); // '\0' 189212793Sdim 190218893Sdim Streamer.EmitIntValue(ARMBuildAttrs::File, 1); 191218893Sdim Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4); 192212793Sdim 193226633Sdim // Size should have been accounted for already, now 194226633Sdim // emit each field as its type (ULEB or String) 195226633Sdim for (unsigned int i=0; i<Contents.size(); ++i) { 196226633Sdim AttributeItemType item = Contents[i]; 197249423Sdim Streamer.EmitULEB128IntValue(item.Tag); 198226633Sdim switch (item.Type) { 199234353Sdim default: llvm_unreachable("Invalid attribute type"); 200226633Sdim case AttributeItemType::NumericAttribute: 201249423Sdim Streamer.EmitULEB128IntValue(item.IntValue); 202226633Sdim break; 203226633Sdim case AttributeItemType::TextAttribute: 204249423Sdim Streamer.EmitBytes(item.StringValue.upper()); 205226633Sdim Streamer.EmitIntValue(0, 1); // '\0' 206226633Sdim break; 207226633Sdim } 208226633Sdim } 209212793Sdim 210218893Sdim Contents.clear(); 211212793Sdim } 212212793Sdim }; 213218893Sdim 214212793Sdim} // end of anonymous namespace 215212793Sdim 216218893SdimMachineLocation ARMAsmPrinter:: 217218893SdimgetDebugValueLocation(const MachineInstr *MI) const { 218218893Sdim MachineLocation Location; 219218893Sdim assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); 220218893Sdim // Frame address. Currently handles register +- offset only. 221218893Sdim if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) 222218893Sdim Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); 223218893Sdim else { 224218893Sdim DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); 225218893Sdim } 226218893Sdim return Location; 227218893Sdim} 228212793Sdim 229221345Sdim/// EmitDwarfRegOp - Emit dwarf register operation. 230221345Sdimvoid ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const { 231221345Sdim const TargetRegisterInfo *RI = TM.getRegisterInfo(); 232221345Sdim if (RI->getDwarfRegNum(MLoc.getReg(), false) != -1) 233221345Sdim AsmPrinter::EmitDwarfRegOp(MLoc); 234221345Sdim else { 235221345Sdim unsigned Reg = MLoc.getReg(); 236221345Sdim if (Reg >= ARM::S0 && Reg <= ARM::S31) { 237221345Sdim assert(ARM::S0 + 31 == ARM::S31 && "Unexpected ARM S register numbering"); 238221345Sdim // S registers are described as bit-pieces of a register 239221345Sdim // S[2x] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 0) 240221345Sdim // S[2x+1] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 32) 241226633Sdim 242221345Sdim unsigned SReg = Reg - ARM::S0; 243221345Sdim bool odd = SReg & 0x1; 244221345Sdim unsigned Rx = 256 + (SReg >> 1); 245221345Sdim 246221345Sdim OutStreamer.AddComment("DW_OP_regx for S register"); 247221345Sdim EmitInt8(dwarf::DW_OP_regx); 248221345Sdim 249221345Sdim OutStreamer.AddComment(Twine(SReg)); 250221345Sdim EmitULEB128(Rx); 251221345Sdim 252221345Sdim if (odd) { 253221345Sdim OutStreamer.AddComment("DW_OP_bit_piece 32 32"); 254221345Sdim EmitInt8(dwarf::DW_OP_bit_piece); 255221345Sdim EmitULEB128(32); 256221345Sdim EmitULEB128(32); 257221345Sdim } else { 258221345Sdim OutStreamer.AddComment("DW_OP_bit_piece 32 0"); 259221345Sdim EmitInt8(dwarf::DW_OP_bit_piece); 260221345Sdim EmitULEB128(32); 261221345Sdim EmitULEB128(0); 262221345Sdim } 263221345Sdim } else if (Reg >= ARM::Q0 && Reg <= ARM::Q15) { 264221345Sdim assert(ARM::Q0 + 15 == ARM::Q15 && "Unexpected ARM Q register numbering"); 265221345Sdim // Q registers Q0-Q15 are described by composing two D registers together. 266226633Sdim // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1) 267226633Sdim // DW_OP_piece(8) 268221345Sdim 269221345Sdim unsigned QReg = Reg - ARM::Q0; 270221345Sdim unsigned D1 = 256 + 2 * QReg; 271221345Sdim unsigned D2 = D1 + 1; 272226633Sdim 273221345Sdim OutStreamer.AddComment("DW_OP_regx for Q register: D1"); 274221345Sdim EmitInt8(dwarf::DW_OP_regx); 275221345Sdim EmitULEB128(D1); 276221345Sdim OutStreamer.AddComment("DW_OP_piece 8"); 277221345Sdim EmitInt8(dwarf::DW_OP_piece); 278221345Sdim EmitULEB128(8); 279221345Sdim 280221345Sdim OutStreamer.AddComment("DW_OP_regx for Q register: D2"); 281221345Sdim EmitInt8(dwarf::DW_OP_regx); 282221345Sdim EmitULEB128(D2); 283221345Sdim OutStreamer.AddComment("DW_OP_piece 8"); 284221345Sdim EmitInt8(dwarf::DW_OP_piece); 285221345Sdim EmitULEB128(8); 286221345Sdim } 287221345Sdim } 288221345Sdim} 289221345Sdim 290239462Sdimvoid ARMAsmPrinter::EmitFunctionBodyEnd() { 291239462Sdim // Make sure to terminate any constant pools that were at the end 292239462Sdim // of the function. 293239462Sdim if (!InConstantPool) 294239462Sdim return; 295239462Sdim InConstantPool = false; 296239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 297239462Sdim} 298239462Sdim 299212793Sdimvoid ARMAsmPrinter::EmitFunctionEntryLabel() { 300212793Sdim if (AFI->isThumbFunction()) { 301218893Sdim OutStreamer.EmitAssemblerFlag(MCAF_Code16); 302223017Sdim OutStreamer.EmitThumbFunc(CurrentFnSym); 303212793Sdim } 304212793Sdim 305212793Sdim OutStreamer.EmitLabel(CurrentFnSym); 306212793Sdim} 307212793Sdim 308234353Sdimvoid ARMAsmPrinter::EmitXXStructor(const Constant *CV) { 309243830Sdim uint64_t Size = TM.getDataLayout()->getTypeAllocSize(CV->getType()); 310234353Sdim assert(Size && "C++ constructor pointer had zero size!"); 311234353Sdim 312234353Sdim const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts()); 313234353Sdim assert(GV && "C++ constructor pointer was not a GlobalValue!"); 314234353Sdim 315234353Sdim const MCExpr *E = MCSymbolRefExpr::Create(Mang->getSymbol(GV), 316234353Sdim (Subtarget->isTargetDarwin() 317234353Sdim ? MCSymbolRefExpr::VK_None 318234353Sdim : MCSymbolRefExpr::VK_ARM_TARGET1), 319234353Sdim OutContext); 320234353Sdim 321234353Sdim OutStreamer.EmitValue(E, Size); 322234353Sdim} 323234353Sdim 324218893Sdim/// runOnMachineFunction - This uses the EmitInstruction() 325212793Sdim/// method to print assembly for each instruction. 326212793Sdim/// 327212793Sdimbool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 328212793Sdim AFI = MF.getInfo<ARMFunctionInfo>(); 329212793Sdim MCP = MF.getConstantPool(); 330212793Sdim 331212793Sdim return AsmPrinter::runOnMachineFunction(MF); 332212793Sdim} 333212793Sdim 334212793Sdimvoid ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 335212793Sdim raw_ostream &O, const char *Modifier) { 336212793Sdim const MachineOperand &MO = MI->getOperand(OpNum); 337212793Sdim unsigned TF = MO.getTargetFlags(); 338212793Sdim 339212793Sdim switch (MO.getType()) { 340234353Sdim default: llvm_unreachable("<unknown operand type>"); 341212793Sdim case MachineOperand::MO_Register: { 342212793Sdim unsigned Reg = MO.getReg(); 343212793Sdim assert(TargetRegisterInfo::isPhysicalRegister(Reg)); 344218893Sdim assert(!MO.getSubReg() && "Subregs should be eliminated!"); 345249423Sdim if(ARM::GPRPairRegClass.contains(Reg)) { 346249423Sdim const MachineFunction &MF = *MI->getParent()->getParent(); 347249423Sdim const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); 348249423Sdim Reg = TRI->getSubReg(Reg, ARM::gsub_0); 349249423Sdim } 350218893Sdim O << ARMInstPrinter::getRegisterName(Reg); 351212793Sdim break; 352212793Sdim } 353212793Sdim case MachineOperand::MO_Immediate: { 354212793Sdim int64_t Imm = MO.getImm(); 355212793Sdim O << '#'; 356212793Sdim if ((Modifier && strcmp(Modifier, "lo16") == 0) || 357218893Sdim (TF == ARMII::MO_LO16)) 358212793Sdim O << ":lower16:"; 359212793Sdim else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 360218893Sdim (TF == ARMII::MO_HI16)) 361212793Sdim O << ":upper16:"; 362212793Sdim O << Imm; 363212793Sdim break; 364212793Sdim } 365212793Sdim case MachineOperand::MO_MachineBasicBlock: 366212793Sdim O << *MO.getMBB()->getSymbol(); 367212793Sdim return; 368212793Sdim case MachineOperand::MO_GlobalAddress: { 369212793Sdim const GlobalValue *GV = MO.getGlobal(); 370212793Sdim if ((Modifier && strcmp(Modifier, "lo16") == 0) || 371212793Sdim (TF & ARMII::MO_LO16)) 372212793Sdim O << ":lower16:"; 373212793Sdim else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 374212793Sdim (TF & ARMII::MO_HI16)) 375212793Sdim O << ":upper16:"; 376212793Sdim O << *Mang->getSymbol(GV); 377212793Sdim 378212793Sdim printOffset(MO.getOffset(), O); 379218893Sdim if (TF == ARMII::MO_PLT) 380212793Sdim O << "(PLT)"; 381212793Sdim break; 382212793Sdim } 383212793Sdim case MachineOperand::MO_ExternalSymbol: { 384212793Sdim O << *GetExternalSymbolSymbol(MO.getSymbolName()); 385218893Sdim if (TF == ARMII::MO_PLT) 386212793Sdim O << "(PLT)"; 387212793Sdim break; 388212793Sdim } 389212793Sdim case MachineOperand::MO_ConstantPoolIndex: 390212793Sdim O << *GetCPISymbol(MO.getIndex()); 391212793Sdim break; 392212793Sdim case MachineOperand::MO_JumpTableIndex: 393212793Sdim O << *GetJTISymbol(MO.getIndex()); 394212793Sdim break; 395212793Sdim } 396212793Sdim} 397212793Sdim 398212793Sdim//===--------------------------------------------------------------------===// 399212793Sdim 400212793SdimMCSymbol *ARMAsmPrinter:: 401212793SdimGetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const { 402212793Sdim SmallString<60> Name; 403212793Sdim raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI" 404212793Sdim << getFunctionNumber() << '_' << uid << '_' << uid2; 405212793Sdim return OutContext.GetOrCreateSymbol(Name.str()); 406212793Sdim} 407212793Sdim 408212793Sdim 409249423SdimMCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel() const { 410218893Sdim SmallString<60> Name; 411218893Sdim raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH" 412218893Sdim << getFunctionNumber(); 413218893Sdim return OutContext.GetOrCreateSymbol(Name.str()); 414212793Sdim} 415212793Sdim 416212793Sdimbool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 417212793Sdim unsigned AsmVariant, const char *ExtraCode, 418212793Sdim raw_ostream &O) { 419212793Sdim // Does this asm operand have a single letter operand modifier? 420212793Sdim if (ExtraCode && ExtraCode[0]) { 421212793Sdim if (ExtraCode[1] != 0) return true; // Unknown modifier. 422212793Sdim 423212793Sdim switch (ExtraCode[0]) { 424239462Sdim default: 425239462Sdim // See if this is a generic print operand 426239462Sdim return AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O); 427212793Sdim case 'a': // Print as a memory address. 428212793Sdim if (MI->getOperand(OpNum).isReg()) { 429218893Sdim O << "[" 430218893Sdim << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg()) 431218893Sdim << "]"; 432212793Sdim return false; 433212793Sdim } 434212793Sdim // Fallthrough 435212793Sdim case 'c': // Don't print "#" before an immediate operand. 436212793Sdim if (!MI->getOperand(OpNum).isImm()) 437212793Sdim return true; 438218893Sdim O << MI->getOperand(OpNum).getImm(); 439212793Sdim return false; 440212793Sdim case 'P': // Print a VFP double precision register. 441212793Sdim case 'q': // Print a NEON quad precision register. 442212793Sdim printOperand(MI, OpNum, O); 443212793Sdim return false; 444223017Sdim case 'y': // Print a VFP single precision register as indexed double. 445223017Sdim if (MI->getOperand(OpNum).isReg()) { 446223017Sdim unsigned Reg = MI->getOperand(OpNum).getReg(); 447223017Sdim const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); 448239462Sdim // Find the 'd' register that has this 's' register as a sub-register, 449239462Sdim // and determine the lane number. 450239462Sdim for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) { 451239462Sdim if (!ARM::DPRRegClass.contains(*SR)) 452239462Sdim continue; 453239462Sdim bool Lane0 = TRI->getSubReg(*SR, ARM::ssub_0) == Reg; 454239462Sdim O << ARMInstPrinter::getRegisterName(*SR) << (Lane0 ? "[0]" : "[1]"); 455239462Sdim return false; 456239462Sdim } 457223017Sdim } 458212793Sdim return true; 459223017Sdim case 'B': // Bitwise inverse of integer or symbol without a preceding #. 460223017Sdim if (!MI->getOperand(OpNum).isImm()) 461223017Sdim return true; 462223017Sdim O << ~(MI->getOperand(OpNum).getImm()); 463223017Sdim return false; 464223017Sdim case 'L': // The low 16 bits of an immediate constant. 465223017Sdim if (!MI->getOperand(OpNum).isImm()) 466223017Sdim return true; 467223017Sdim O << (MI->getOperand(OpNum).getImm() & 0xffff); 468223017Sdim return false; 469223017Sdim case 'M': { // A register range suitable for LDM/STM. 470223017Sdim if (!MI->getOperand(OpNum).isReg()) 471223017Sdim return true; 472223017Sdim const MachineOperand &MO = MI->getOperand(OpNum); 473223017Sdim unsigned RegBegin = MO.getReg(); 474223017Sdim // This takes advantage of the 2 operand-ness of ldm/stm and that we've 475223017Sdim // already got the operands in registers that are operands to the 476223017Sdim // inline asm statement. 477226633Sdim 478223017Sdim O << "{" << ARMInstPrinter::getRegisterName(RegBegin); 479226633Sdim 480223017Sdim // FIXME: The register allocator not only may not have given us the 481223017Sdim // registers in sequence, but may not be in ascending registers. This 482223017Sdim // will require changes in the register allocator that'll need to be 483223017Sdim // propagated down here if the operands change. 484223017Sdim unsigned RegOps = OpNum + 1; 485223017Sdim while (MI->getOperand(RegOps).isReg()) { 486226633Sdim O << ", " 487223017Sdim << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg()); 488223017Sdim RegOps++; 489223017Sdim } 490223017Sdim 491223017Sdim O << "}"; 492223017Sdim 493223017Sdim return false; 494212793Sdim } 495226633Sdim case 'R': // The most significant register of a pair. 496226633Sdim case 'Q': { // The least significant register of a pair. 497226633Sdim if (OpNum == 0) 498226633Sdim return true; 499226633Sdim const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); 500226633Sdim if (!FlagsOP.isImm()) 501226633Sdim return true; 502226633Sdim unsigned Flags = FlagsOP.getImm(); 503226633Sdim unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); 504226633Sdim if (NumVals != 2) 505226633Sdim return true; 506226633Sdim unsigned RegOp = ExtraCode[0] == 'Q' ? OpNum : OpNum + 1; 507226633Sdim if (RegOp >= MI->getNumOperands()) 508226633Sdim return true; 509226633Sdim const MachineOperand &MO = MI->getOperand(RegOp); 510226633Sdim if (!MO.isReg()) 511226633Sdim return true; 512226633Sdim unsigned Reg = MO.getReg(); 513226633Sdim O << ARMInstPrinter::getRegisterName(Reg); 514226633Sdim return false; 515226633Sdim } 516226633Sdim 517234353Sdim case 'e': // The low doubleword register of a NEON quad register. 518234353Sdim case 'f': { // The high doubleword register of a NEON quad register. 519234353Sdim if (!MI->getOperand(OpNum).isReg()) 520234353Sdim return true; 521234353Sdim unsigned Reg = MI->getOperand(OpNum).getReg(); 522234353Sdim if (!ARM::QPRRegClass.contains(Reg)) 523234353Sdim return true; 524234353Sdim const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); 525234353Sdim unsigned SubReg = TRI->getSubReg(Reg, ExtraCode[0] == 'e' ? 526234353Sdim ARM::dsub_0 : ARM::dsub_1); 527234353Sdim O << ARMInstPrinter::getRegisterName(SubReg); 528234353Sdim return false; 529234353Sdim } 530234353Sdim 531239462Sdim // This modifier is not yet supported. 532223017Sdim case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1. 533223017Sdim return true; 534239462Sdim case 'H': { // The highest-numbered register of a pair. 535239462Sdim const MachineOperand &MO = MI->getOperand(OpNum); 536239462Sdim if (!MO.isReg()) 537239462Sdim return true; 538239462Sdim const MachineFunction &MF = *MI->getParent()->getParent(); 539239462Sdim const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); 540249423Sdim unsigned Reg = MO.getReg(); 541249423Sdim if(!ARM::GPRPairRegClass.contains(Reg)) 542249423Sdim return false; 543249423Sdim Reg = TRI->getSubReg(Reg, ARM::gsub_1); 544239462Sdim O << ARMInstPrinter::getRegisterName(Reg); 545239462Sdim return false; 546223017Sdim } 547239462Sdim } 548212793Sdim } 549212793Sdim 550212793Sdim printOperand(MI, OpNum, O); 551212793Sdim return false; 552212793Sdim} 553212793Sdim 554212793Sdimbool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 555212793Sdim unsigned OpNum, unsigned AsmVariant, 556212793Sdim const char *ExtraCode, 557212793Sdim raw_ostream &O) { 558223017Sdim // Does this asm operand have a single letter operand modifier? 559223017Sdim if (ExtraCode && ExtraCode[0]) { 560223017Sdim if (ExtraCode[1] != 0) return true; // Unknown modifier. 561226633Sdim 562223017Sdim switch (ExtraCode[0]) { 563223017Sdim case 'A': // A memory operand for a VLD1/VST1 instruction. 564223017Sdim default: return true; // Unknown modifier. 565223017Sdim case 'm': // The base register of a memory operand. 566223017Sdim if (!MI->getOperand(OpNum).isReg()) 567223017Sdim return true; 568223017Sdim O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg()); 569223017Sdim return false; 570223017Sdim } 571223017Sdim } 572226633Sdim 573212793Sdim const MachineOperand &MO = MI->getOperand(OpNum); 574212793Sdim assert(MO.isReg() && "unexpected inline asm memory operand"); 575218893Sdim O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]"; 576212793Sdim return false; 577212793Sdim} 578212793Sdim 579212793Sdimvoid ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { 580212793Sdim if (Subtarget->isTargetDarwin()) { 581212793Sdim Reloc::Model RelocM = TM.getRelocationModel(); 582212793Sdim if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) { 583212793Sdim // Declare all the text sections up front (before the DWARF sections 584212793Sdim // emitted by AsmPrinter::doInitialization) so the assembler will keep 585212793Sdim // them together at the beginning of the object file. This helps 586212793Sdim // avoid out-of-range branches that are due a fundamental limitation of 587212793Sdim // the way symbol offsets are encoded with the current Darwin ARM 588212793Sdim // relocations. 589212793Sdim const TargetLoweringObjectFileMachO &TLOFMacho = 590212793Sdim static_cast<const TargetLoweringObjectFileMachO &>( 591212793Sdim getObjFileLowering()); 592243830Sdim 593243830Sdim // Collect the set of sections our functions will go into. 594243830Sdim SetVector<const MCSection *, SmallVector<const MCSection *, 8>, 595243830Sdim SmallPtrSet<const MCSection *, 8> > TextSections; 596243830Sdim // Default text section comes first. 597243830Sdim TextSections.insert(TLOFMacho.getTextSection()); 598243830Sdim // Now any user defined text sections from function attributes. 599243830Sdim for (Module::iterator F = M.begin(), e = M.end(); F != e; ++F) 600243830Sdim if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage()) 601243830Sdim TextSections.insert(TLOFMacho.SectionForGlobal(F, Mang, TM)); 602243830Sdim // Now the coalescable sections. 603243830Sdim TextSections.insert(TLOFMacho.getTextCoalSection()); 604243830Sdim TextSections.insert(TLOFMacho.getConstTextCoalSection()); 605243830Sdim 606243830Sdim // Emit the sections in the .s file header to fix the order. 607243830Sdim for (unsigned i = 0, e = TextSections.size(); i != e; ++i) 608243830Sdim OutStreamer.SwitchSection(TextSections[i]); 609243830Sdim 610212793Sdim if (RelocM == Reloc::DynamicNoPIC) { 611212793Sdim const MCSection *sect = 612212793Sdim OutContext.getMachOSection("__TEXT", "__symbol_stub4", 613212793Sdim MCSectionMachO::S_SYMBOL_STUBS, 614212793Sdim 12, SectionKind::getText()); 615212793Sdim OutStreamer.SwitchSection(sect); 616212793Sdim } else { 617212793Sdim const MCSection *sect = 618212793Sdim OutContext.getMachOSection("__TEXT", "__picsymbolstub4", 619212793Sdim MCSectionMachO::S_SYMBOL_STUBS, 620212793Sdim 16, SectionKind::getText()); 621212793Sdim OutStreamer.SwitchSection(sect); 622212793Sdim } 623212793Sdim const MCSection *StaticInitSect = 624212793Sdim OutContext.getMachOSection("__TEXT", "__StaticInit", 625212793Sdim MCSectionMachO::S_REGULAR | 626212793Sdim MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 627212793Sdim SectionKind::getText()); 628212793Sdim OutStreamer.SwitchSection(StaticInitSect); 629212793Sdim } 630212793Sdim } 631212793Sdim 632212793Sdim // Use unified assembler syntax. 633218893Sdim OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified); 634212793Sdim 635212793Sdim // Emit ARM Build Attributes 636234353Sdim if (Subtarget->isTargetELF()) 637218893Sdim emitAttributes(); 638212793Sdim} 639212793Sdim 640212793Sdim 641212793Sdimvoid ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { 642212793Sdim if (Subtarget->isTargetDarwin()) { 643212793Sdim // All darwin targets use mach-o. 644212793Sdim const TargetLoweringObjectFileMachO &TLOFMacho = 645212793Sdim static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 646212793Sdim MachineModuleInfoMachO &MMIMacho = 647212793Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>(); 648212793Sdim 649212793Sdim // Output non-lazy-pointers for external and common global variables. 650212793Sdim MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); 651212793Sdim 652212793Sdim if (!Stubs.empty()) { 653212793Sdim // Switch with ".non_lazy_symbol_pointer" directive. 654212793Sdim OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); 655212793Sdim EmitAlignment(2); 656212793Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 657212793Sdim // L_foo$stub: 658212793Sdim OutStreamer.EmitLabel(Stubs[i].first); 659212793Sdim // .indirect_symbol _foo 660212793Sdim MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; 661212793Sdim OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol); 662212793Sdim 663212793Sdim if (MCSym.getInt()) 664212793Sdim // External to current translation unit. 665249423Sdim OutStreamer.EmitIntValue(0, 4/*size*/); 666212793Sdim else 667212793Sdim // Internal to current translation unit. 668212793Sdim // 669218893Sdim // When we place the LSDA into the TEXT section, the type info 670218893Sdim // pointers need to be indirect and pc-rel. We accomplish this by 671218893Sdim // using NLPs; however, sometimes the types are local to the file. 672218893Sdim // We need to fill in the value for the NLP in those cases. 673212793Sdim OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), 674212793Sdim OutContext), 675249423Sdim 4/*size*/); 676212793Sdim } 677212793Sdim 678212793Sdim Stubs.clear(); 679212793Sdim OutStreamer.AddBlankLine(); 680212793Sdim } 681212793Sdim 682212793Sdim Stubs = MMIMacho.GetHiddenGVStubList(); 683212793Sdim if (!Stubs.empty()) { 684212793Sdim OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 685212793Sdim EmitAlignment(2); 686212793Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 687212793Sdim // L_foo$stub: 688212793Sdim OutStreamer.EmitLabel(Stubs[i].first); 689212793Sdim // .long _foo 690212793Sdim OutStreamer.EmitValue(MCSymbolRefExpr:: 691212793Sdim Create(Stubs[i].second.getPointer(), 692212793Sdim OutContext), 693249423Sdim 4/*size*/); 694212793Sdim } 695212793Sdim 696212793Sdim Stubs.clear(); 697212793Sdim OutStreamer.AddBlankLine(); 698212793Sdim } 699212793Sdim 700212793Sdim // Funny Darwin hack: This flag tells the linker that no global symbols 701212793Sdim // contain code that falls through to other global symbols (e.g. the obvious 702212793Sdim // implementation of multiple entry points). If this doesn't occur, the 703212793Sdim // linker can safely perform dead code stripping. Since LLVM never 704212793Sdim // generates code that does this, it is always safe to set. 705212793Sdim OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 706212793Sdim } 707249423Sdim // FIXME: This should eventually end up somewhere else where more 708249423Sdim // intelligent flag decisions can be made. For now we are just maintaining 709249423Sdim // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default. 710249423Sdim if (MCELFStreamer *MES = dyn_cast<MCELFStreamer>(&OutStreamer)) 711249423Sdim MES->getAssembler().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5); 712212793Sdim} 713212793Sdim 714212793Sdim//===----------------------------------------------------------------------===// 715218893Sdim// Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile() 716218893Sdim// FIXME: 717218893Sdim// The following seem like one-off assembler flags, but they actually need 718218893Sdim// to appear in the .ARM.attributes section in ELF. 719218893Sdim// Instead of subclassing the MCELFStreamer, we do the work here. 720212793Sdim 721218893Sdimvoid ARMAsmPrinter::emitAttributes() { 722218893Sdim 723218893Sdim emitARMAttributeSection(); 724218893Sdim 725221345Sdim /* GAS expect .fpu to be emitted, regardless of VFP build attribute */ 726221345Sdim bool emitFPU = false; 727218893Sdim AttributeEmitter *AttrEmitter; 728221345Sdim if (OutStreamer.hasRawTextSupport()) { 729218893Sdim AttrEmitter = new AsmAttributeEmitter(OutStreamer); 730221345Sdim emitFPU = true; 731221345Sdim } else { 732218893Sdim MCObjectStreamer &O = static_cast<MCObjectStreamer&>(OutStreamer); 733218893Sdim AttrEmitter = new ObjectAttributeEmitter(O); 734218893Sdim } 735218893Sdim 736218893Sdim AttrEmitter->MaybeSwitchVendor("aeabi"); 737218893Sdim 738218893Sdim std::string CPUString = Subtarget->getCPUString(); 739218893Sdim 740218893Sdim if (CPUString == "cortex-a8" || 741218893Sdim Subtarget->isCortexA8()) { 742218893Sdim AttrEmitter->EmitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a8"); 743218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v7); 744218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch_profile, 745218893Sdim ARMBuildAttrs::ApplicationProfile); 746218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, 747218893Sdim ARMBuildAttrs::Allowed); 748218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, 749218893Sdim ARMBuildAttrs::AllowThumb32); 750218893Sdim // Fixme: figure out when this is emitted. 751218893Sdim //AttrEmitter->EmitAttribute(ARMBuildAttrs::WMMX_arch, 752218893Sdim // ARMBuildAttrs::AllowWMMXv1); 753218893Sdim // 754218893Sdim 755218893Sdim /// ADD additional Else-cases here! 756223017Sdim } else if (CPUString == "xscale") { 757223017Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v5TEJ); 758223017Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, 759223017Sdim ARMBuildAttrs::Allowed); 760223017Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, 761223017Sdim ARMBuildAttrs::Allowed); 762218893Sdim } else if (CPUString == "generic") { 763243830Sdim // For a generic CPU, we assume a standard v7a architecture in Subtarget. 764243830Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v7); 765243830Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch_profile, 766243830Sdim ARMBuildAttrs::ApplicationProfile); 767218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, 768218893Sdim ARMBuildAttrs::Allowed); 769218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, 770243830Sdim ARMBuildAttrs::AllowThumb32); 771243830Sdim } else if (Subtarget->hasV7Ops()) { 772243830Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v7); 773243830Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, 774243830Sdim ARMBuildAttrs::AllowThumb32); 775243830Sdim } else if (Subtarget->hasV6T2Ops()) 776243830Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v6T2); 777243830Sdim else if (Subtarget->hasV6Ops()) 778243830Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v6); 779243830Sdim else if (Subtarget->hasV5TEOps()) 780243830Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v5TE); 781243830Sdim else if (Subtarget->hasV5TOps()) 782243830Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v5T); 783243830Sdim else if (Subtarget->hasV4TOps()) 784243830Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v4T); 785218893Sdim 786221345Sdim if (Subtarget->hasNEON() && emitFPU) { 787221345Sdim /* NEON is not exactly a VFP architecture, but GAS emit one of 788234353Sdim * neon/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */ 789234353Sdim if (Subtarget->hasVFP4()) 790234353Sdim AttrEmitter->EmitTextAttribute(ARMBuildAttrs::Advanced_SIMD_arch, 791234353Sdim "neon-vfpv4"); 792234353Sdim else 793234353Sdim AttrEmitter->EmitTextAttribute(ARMBuildAttrs::Advanced_SIMD_arch, "neon"); 794221345Sdim /* If emitted for NEON, omit from VFP below, since you can have both 795221345Sdim * NEON and VFP in build attributes but only one .fpu */ 796221345Sdim emitFPU = false; 797221345Sdim } 798221345Sdim 799234353Sdim /* VFPv4 + .fpu */ 800234353Sdim if (Subtarget->hasVFP4()) { 801234353Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 802234353Sdim ARMBuildAttrs::AllowFPv4A); 803234353Sdim if (emitFPU) 804234353Sdim AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv4"); 805234353Sdim 806221345Sdim /* VFPv3 + .fpu */ 807234353Sdim } else if (Subtarget->hasVFP3()) { 808218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 809221345Sdim ARMBuildAttrs::AllowFPv3A); 810221345Sdim if (emitFPU) 811221345Sdim AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv3"); 812221345Sdim 813221345Sdim /* VFPv2 + .fpu */ 814221345Sdim } else if (Subtarget->hasVFP2()) { 815221345Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 816218893Sdim ARMBuildAttrs::AllowFPv2); 817221345Sdim if (emitFPU) 818221345Sdim AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv2"); 819221345Sdim } 820218893Sdim 821221345Sdim /* TODO: ARMBuildAttrs::Allowed is not completely accurate, 822224145Sdim * since NEON can have 1 (allowed) or 2 (MAC operations) */ 823221345Sdim if (Subtarget->hasNEON()) { 824221345Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::Advanced_SIMD_arch, 825221345Sdim ARMBuildAttrs::Allowed); 826221345Sdim } 827221345Sdim 828218893Sdim // Signal various FP modes. 829234353Sdim if (!TM.Options.UnsafeFPMath) { 830218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal, 831218893Sdim ARMBuildAttrs::Allowed); 832218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 833218893Sdim ARMBuildAttrs::Allowed); 834218893Sdim } 835218893Sdim 836234353Sdim if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath) 837218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 838218893Sdim ARMBuildAttrs::Allowed); 839218893Sdim else 840218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 841218893Sdim ARMBuildAttrs::AllowIEE754); 842218893Sdim 843218893Sdim // FIXME: add more flags to ARMBuildAttrs.h 844218893Sdim // 8-bytes alignment stuff. 845218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1); 846218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1); 847218893Sdim 848218893Sdim // Hard float. Use both S and D registers and conform to AAPCS-VFP. 849234353Sdim if (Subtarget->isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard) { 850218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3); 851218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_VFP_args, 1); 852218893Sdim } 853218893Sdim // FIXME: Should we signal R9 usage? 854218893Sdim 855218893Sdim if (Subtarget->hasDivide()) 856218893Sdim AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use, 1); 857218893Sdim 858218893Sdim AttrEmitter->Finish(); 859218893Sdim delete AttrEmitter; 860218893Sdim} 861218893Sdim 862218893Sdimvoid ARMAsmPrinter::emitARMAttributeSection() { 863218893Sdim // <format-version> 864218893Sdim // [ <section-length> "vendor-name" 865218893Sdim // [ <file-tag> <size> <attribute>* 866218893Sdim // | <section-tag> <size> <section-number>* 0 <attribute>* 867218893Sdim // | <symbol-tag> <size> <symbol-number>* 0 <attribute>* 868218893Sdim // ]+ 869218893Sdim // ]* 870218893Sdim 871218893Sdim if (OutStreamer.hasRawTextSupport()) 872218893Sdim return; 873218893Sdim 874218893Sdim const ARMElfTargetObjectFile &TLOFELF = 875218893Sdim static_cast<const ARMElfTargetObjectFile &> 876218893Sdim (getObjFileLowering()); 877218893Sdim 878218893Sdim OutStreamer.SwitchSection(TLOFELF.getAttributesSection()); 879218893Sdim 880218893Sdim // Format version 881218893Sdim OutStreamer.EmitIntValue(0x41, 1); 882218893Sdim} 883218893Sdim 884218893Sdim//===----------------------------------------------------------------------===// 885218893Sdim 886218893Sdimstatic MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, 887218893Sdim unsigned LabelId, MCContext &Ctx) { 888218893Sdim 889218893Sdim MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix) 890218893Sdim + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); 891218893Sdim return Label; 892218893Sdim} 893218893Sdim 894218893Sdimstatic MCSymbolRefExpr::VariantKind 895218893SdimgetModifierVariantKind(ARMCP::ARMCPModifier Modifier) { 896218893Sdim switch (Modifier) { 897218893Sdim case ARMCP::no_modifier: return MCSymbolRefExpr::VK_None; 898218893Sdim case ARMCP::TLSGD: return MCSymbolRefExpr::VK_ARM_TLSGD; 899218893Sdim case ARMCP::TPOFF: return MCSymbolRefExpr::VK_ARM_TPOFF; 900218893Sdim case ARMCP::GOTTPOFF: return MCSymbolRefExpr::VK_ARM_GOTTPOFF; 901218893Sdim case ARMCP::GOT: return MCSymbolRefExpr::VK_ARM_GOT; 902218893Sdim case ARMCP::GOTOFF: return MCSymbolRefExpr::VK_ARM_GOTOFF; 903218893Sdim } 904234353Sdim llvm_unreachable("Invalid ARMCPModifier!"); 905218893Sdim} 906218893Sdim 907218893SdimMCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV) { 908218893Sdim bool isIndirect = Subtarget->isTargetDarwin() && 909218893Sdim Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel()); 910218893Sdim if (!isIndirect) 911218893Sdim return Mang->getSymbol(GV); 912218893Sdim 913218893Sdim // FIXME: Remove this when Darwin transition to @GOT like syntax. 914218893Sdim MCSymbol *MCSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 915218893Sdim MachineModuleInfoMachO &MMIMachO = 916218893Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>(); 917218893Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 918218893Sdim GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(MCSym) : 919218893Sdim MMIMachO.getGVStubEntry(MCSym); 920218893Sdim if (StubSym.getPointer() == 0) 921218893Sdim StubSym = MachineModuleInfoImpl:: 922218893Sdim StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); 923218893Sdim return MCSym; 924218893Sdim} 925218893Sdim 926218893Sdimvoid ARMAsmPrinter:: 927218893SdimEmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 928243830Sdim int Size = TM.getDataLayout()->getTypeAllocSize(MCPV->getType()); 929218893Sdim 930218893Sdim ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV); 931218893Sdim 932218893Sdim MCSymbol *MCSym; 933218893Sdim if (ACPV->isLSDA()) { 934218893Sdim SmallString<128> Str; 935218893Sdim raw_svector_ostream OS(Str); 936218893Sdim OS << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber(); 937218893Sdim MCSym = OutContext.GetOrCreateSymbol(OS.str()); 938218893Sdim } else if (ACPV->isBlockAddress()) { 939226633Sdim const BlockAddress *BA = 940226633Sdim cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress(); 941226633Sdim MCSym = GetBlockAddressSymbol(BA); 942218893Sdim } else if (ACPV->isGlobalValue()) { 943226633Sdim const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV(); 944218893Sdim MCSym = GetARMGVSymbol(GV); 945226633Sdim } else if (ACPV->isMachineBasicBlock()) { 946226633Sdim const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB(); 947226633Sdim MCSym = MBB->getSymbol(); 948218893Sdim } else { 949218893Sdim assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); 950226633Sdim const char *Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol(); 951226633Sdim MCSym = GetExternalSymbolSymbol(Sym); 952218893Sdim } 953218893Sdim 954218893Sdim // Create an MCSymbol for the reference. 955218893Sdim const MCExpr *Expr = 956218893Sdim MCSymbolRefExpr::Create(MCSym, getModifierVariantKind(ACPV->getModifier()), 957218893Sdim OutContext); 958218893Sdim 959218893Sdim if (ACPV->getPCAdjustment()) { 960218893Sdim MCSymbol *PCLabel = getPICLabel(MAI->getPrivateGlobalPrefix(), 961218893Sdim getFunctionNumber(), 962218893Sdim ACPV->getLabelId(), 963218893Sdim OutContext); 964218893Sdim const MCExpr *PCRelExpr = MCSymbolRefExpr::Create(PCLabel, OutContext); 965218893Sdim PCRelExpr = 966218893Sdim MCBinaryExpr::CreateAdd(PCRelExpr, 967218893Sdim MCConstantExpr::Create(ACPV->getPCAdjustment(), 968218893Sdim OutContext), 969218893Sdim OutContext); 970218893Sdim if (ACPV->mustAddCurrentAddress()) { 971218893Sdim // We want "(<expr> - .)", but MC doesn't have a concept of the '.' 972218893Sdim // label, so just emit a local label end reference that instead. 973218893Sdim MCSymbol *DotSym = OutContext.CreateTempSymbol(); 974218893Sdim OutStreamer.EmitLabel(DotSym); 975218893Sdim const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext); 976218893Sdim PCRelExpr = MCBinaryExpr::CreateSub(PCRelExpr, DotExpr, OutContext); 977218893Sdim } 978218893Sdim Expr = MCBinaryExpr::CreateSub(Expr, PCRelExpr, OutContext); 979218893Sdim } 980218893Sdim OutStreamer.EmitValue(Expr, Size); 981218893Sdim} 982218893Sdim 983218893Sdimvoid ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) { 984218893Sdim unsigned Opcode = MI->getOpcode(); 985218893Sdim int OpNum = 1; 986218893Sdim if (Opcode == ARM::BR_JTadd) 987218893Sdim OpNum = 2; 988218893Sdim else if (Opcode == ARM::BR_JTm) 989218893Sdim OpNum = 3; 990218893Sdim 991218893Sdim const MachineOperand &MO1 = MI->getOperand(OpNum); 992218893Sdim const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 993218893Sdim unsigned JTI = MO1.getIndex(); 994218893Sdim 995218893Sdim // Emit a label for the jump table. 996218893Sdim MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 997218893Sdim OutStreamer.EmitLabel(JTISymbol); 998218893Sdim 999239462Sdim // Mark the jump table as data-in-code. 1000239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionJT32); 1001239462Sdim 1002218893Sdim // Emit each entry of the table. 1003218893Sdim const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 1004218893Sdim const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 1005218893Sdim const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 1006218893Sdim 1007218893Sdim for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 1008218893Sdim MachineBasicBlock *MBB = JTBBs[i]; 1009218893Sdim // Construct an MCExpr for the entry. We want a value of the form: 1010218893Sdim // (BasicBlockAddr - TableBeginAddr) 1011218893Sdim // 1012218893Sdim // For example, a table with entries jumping to basic blocks BB0 and BB1 1013218893Sdim // would look like: 1014218893Sdim // LJTI_0_0: 1015218893Sdim // .word (LBB0 - LJTI_0_0) 1016218893Sdim // .word (LBB1 - LJTI_0_0) 1017218893Sdim const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); 1018218893Sdim 1019218893Sdim if (TM.getRelocationModel() == Reloc::PIC_) 1020218893Sdim Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol, 1021218893Sdim OutContext), 1022218893Sdim OutContext); 1023226633Sdim // If we're generating a table of Thumb addresses in static relocation 1024226633Sdim // model, we need to add one to keep interworking correctly. 1025226633Sdim else if (AFI->isThumbFunction()) 1026226633Sdim Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(1,OutContext), 1027226633Sdim OutContext); 1028218893Sdim OutStreamer.EmitValue(Expr, 4); 1029218893Sdim } 1030239462Sdim // Mark the end of jump table data-in-code region. 1031239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 1032218893Sdim} 1033218893Sdim 1034218893Sdimvoid ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { 1035218893Sdim unsigned Opcode = MI->getOpcode(); 1036218893Sdim int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1; 1037218893Sdim const MachineOperand &MO1 = MI->getOperand(OpNum); 1038218893Sdim const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 1039218893Sdim unsigned JTI = MO1.getIndex(); 1040218893Sdim 1041218893Sdim MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 1042218893Sdim OutStreamer.EmitLabel(JTISymbol); 1043218893Sdim 1044218893Sdim // Emit each entry of the table. 1045218893Sdim const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 1046218893Sdim const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 1047218893Sdim const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 1048218893Sdim unsigned OffsetWidth = 4; 1049239462Sdim if (MI->getOpcode() == ARM::t2TBB_JT) { 1050218893Sdim OffsetWidth = 1; 1051239462Sdim // Mark the jump table as data-in-code. 1052239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionJT8); 1053239462Sdim } else if (MI->getOpcode() == ARM::t2TBH_JT) { 1054218893Sdim OffsetWidth = 2; 1055239462Sdim // Mark the jump table as data-in-code. 1056239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionJT16); 1057239462Sdim } 1058218893Sdim 1059218893Sdim for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 1060218893Sdim MachineBasicBlock *MBB = JTBBs[i]; 1061218893Sdim const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(), 1062218893Sdim OutContext); 1063218893Sdim // If this isn't a TBB or TBH, the entries are direct branch instructions. 1064218893Sdim if (OffsetWidth == 4) { 1065249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2B) 1066249423Sdim .addExpr(MBBSymbolExpr) 1067249423Sdim .addImm(ARMCC::AL) 1068249423Sdim .addReg(0)); 1069218893Sdim continue; 1070218893Sdim } 1071218893Sdim // Otherwise it's an offset from the dispatch instruction. Construct an 1072218893Sdim // MCExpr for the entry. We want a value of the form: 1073218893Sdim // (BasicBlockAddr - TableBeginAddr) / 2 1074218893Sdim // 1075218893Sdim // For example, a TBB table with entries jumping to basic blocks BB0 and BB1 1076218893Sdim // would look like: 1077218893Sdim // LJTI_0_0: 1078218893Sdim // .byte (LBB0 - LJTI_0_0) / 2 1079218893Sdim // .byte (LBB1 - LJTI_0_0) / 2 1080218893Sdim const MCExpr *Expr = 1081218893Sdim MCBinaryExpr::CreateSub(MBBSymbolExpr, 1082218893Sdim MCSymbolRefExpr::Create(JTISymbol, OutContext), 1083218893Sdim OutContext); 1084218893Sdim Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext), 1085218893Sdim OutContext); 1086218893Sdim OutStreamer.EmitValue(Expr, OffsetWidth); 1087218893Sdim } 1088239462Sdim // Mark the end of jump table data-in-code region. 32-bit offsets use 1089239462Sdim // actual branch instructions here, so we don't mark those as a data-region 1090239462Sdim // at all. 1091239462Sdim if (OffsetWidth != 4) 1092239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 1093218893Sdim} 1094218893Sdim 1095218893Sdimvoid ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, 1096218893Sdim raw_ostream &OS) { 1097218893Sdim unsigned NOps = MI->getNumOperands(); 1098218893Sdim assert(NOps==4); 1099218893Sdim OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; 1100218893Sdim // cast away const; DIetc do not take const operands for some reason. 1101218893Sdim DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata())); 1102218893Sdim OS << V.getName(); 1103218893Sdim OS << " <- "; 1104218893Sdim // Frame address. Currently handles register +- offset only. 1105218893Sdim assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm()); 1106218893Sdim OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS); 1107218893Sdim OS << ']'; 1108218893Sdim OS << "+"; 1109218893Sdim printOperand(MI, NOps-2, OS); 1110218893Sdim} 1111218893Sdim 1112221345Sdimvoid ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { 1113221345Sdim assert(MI->getFlag(MachineInstr::FrameSetup) && 1114221345Sdim "Only instruction which are involved into frame setup code are allowed"); 1115221345Sdim 1116221345Sdim const MachineFunction &MF = *MI->getParent()->getParent(); 1117221345Sdim const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); 1118221345Sdim const ARMFunctionInfo &AFI = *MF.getInfo<ARMFunctionInfo>(); 1119221345Sdim 1120221345Sdim unsigned FramePtr = RegInfo->getFrameRegister(MF); 1121221345Sdim unsigned Opc = MI->getOpcode(); 1122221345Sdim unsigned SrcReg, DstReg; 1123221345Sdim 1124221345Sdim if (Opc == ARM::tPUSH || Opc == ARM::tLDRpci) { 1125221345Sdim // Two special cases: 1126221345Sdim // 1) tPUSH does not have src/dst regs. 1127221345Sdim // 2) for Thumb1 code we sometimes materialize the constant via constpool 1128221345Sdim // load. Yes, this is pretty fragile, but for now I don't see better 1129221345Sdim // way... :( 1130221345Sdim SrcReg = DstReg = ARM::SP; 1131221345Sdim } else { 1132221345Sdim SrcReg = MI->getOperand(1).getReg(); 1133221345Sdim DstReg = MI->getOperand(0).getReg(); 1134221345Sdim } 1135221345Sdim 1136221345Sdim // Try to figure out the unwinding opcode out of src / dst regs. 1137234353Sdim if (MI->mayStore()) { 1138221345Sdim // Register saves. 1139221345Sdim assert(DstReg == ARM::SP && 1140221345Sdim "Only stack pointer as a destination reg is supported"); 1141221345Sdim 1142221345Sdim SmallVector<unsigned, 4> RegList; 1143221345Sdim // Skip src & dst reg, and pred ops. 1144221345Sdim unsigned StartOp = 2 + 2; 1145221345Sdim // Use all the operands. 1146221345Sdim unsigned NumOffset = 0; 1147221345Sdim 1148221345Sdim switch (Opc) { 1149221345Sdim default: 1150221345Sdim MI->dump(); 1151234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1152221345Sdim case ARM::tPUSH: 1153221345Sdim // Special case here: no src & dst reg, but two extra imp ops. 1154221345Sdim StartOp = 2; NumOffset = 2; 1155221345Sdim case ARM::STMDB_UPD: 1156221345Sdim case ARM::t2STMDB_UPD: 1157221345Sdim case ARM::VSTMDDB_UPD: 1158221345Sdim assert(SrcReg == ARM::SP && 1159221345Sdim "Only stack pointer as a source reg is supported"); 1160221345Sdim for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset; 1161239462Sdim i != NumOps; ++i) { 1162239462Sdim const MachineOperand &MO = MI->getOperand(i); 1163239462Sdim // Actually, there should never be any impdef stuff here. Skip it 1164239462Sdim // temporary to workaround PR11902. 1165239462Sdim if (MO.isImplicit()) 1166239462Sdim continue; 1167239462Sdim RegList.push_back(MO.getReg()); 1168239462Sdim } 1169221345Sdim break; 1170226633Sdim case ARM::STR_PRE_IMM: 1171226633Sdim case ARM::STR_PRE_REG: 1172234353Sdim case ARM::t2STR_PRE: 1173221345Sdim assert(MI->getOperand(2).getReg() == ARM::SP && 1174221345Sdim "Only stack pointer as a source reg is supported"); 1175221345Sdim RegList.push_back(SrcReg); 1176221345Sdim break; 1177221345Sdim } 1178221345Sdim OutStreamer.EmitRegSave(RegList, Opc == ARM::VSTMDDB_UPD); 1179221345Sdim } else { 1180221345Sdim // Changes of stack / frame pointer. 1181221345Sdim if (SrcReg == ARM::SP) { 1182221345Sdim int64_t Offset = 0; 1183221345Sdim switch (Opc) { 1184221345Sdim default: 1185221345Sdim MI->dump(); 1186234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1187221345Sdim case ARM::MOVr: 1188234353Sdim case ARM::tMOVr: 1189221345Sdim Offset = 0; 1190221345Sdim break; 1191221345Sdim case ARM::ADDri: 1192221345Sdim Offset = -MI->getOperand(2).getImm(); 1193221345Sdim break; 1194221345Sdim case ARM::SUBri: 1195234353Sdim case ARM::t2SUBri: 1196224145Sdim Offset = MI->getOperand(2).getImm(); 1197221345Sdim break; 1198221345Sdim case ARM::tSUBspi: 1199224145Sdim Offset = MI->getOperand(2).getImm()*4; 1200221345Sdim break; 1201221345Sdim case ARM::tADDspi: 1202221345Sdim case ARM::tADDrSPi: 1203221345Sdim Offset = -MI->getOperand(2).getImm()*4; 1204221345Sdim break; 1205221345Sdim case ARM::tLDRpci: { 1206221345Sdim // Grab the constpool index and check, whether it corresponds to 1207221345Sdim // original or cloned constpool entry. 1208221345Sdim unsigned CPI = MI->getOperand(1).getIndex(); 1209221345Sdim const MachineConstantPool *MCP = MF.getConstantPool(); 1210221345Sdim if (CPI >= MCP->getConstants().size()) 1211221345Sdim CPI = AFI.getOriginalCPIdx(CPI); 1212221345Sdim assert(CPI != -1U && "Invalid constpool index"); 1213221345Sdim 1214221345Sdim // Derive the actual offset. 1215221345Sdim const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI]; 1216221345Sdim assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry"); 1217221345Sdim // FIXME: Check for user, it should be "add" instruction! 1218221345Sdim Offset = -cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue(); 1219221345Sdim break; 1220221345Sdim } 1221221345Sdim } 1222221345Sdim 1223221345Sdim if (DstReg == FramePtr && FramePtr != ARM::SP) 1224221345Sdim // Set-up of the frame pointer. Positive values correspond to "add" 1225221345Sdim // instruction. 1226221345Sdim OutStreamer.EmitSetFP(FramePtr, ARM::SP, -Offset); 1227221345Sdim else if (DstReg == ARM::SP) { 1228221345Sdim // Change of SP by an offset. Positive values correspond to "sub" 1229221345Sdim // instruction. 1230221345Sdim OutStreamer.EmitPad(Offset); 1231221345Sdim } else { 1232221345Sdim MI->dump(); 1233234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1234221345Sdim } 1235221345Sdim } else if (DstReg == ARM::SP) { 1236221345Sdim // FIXME: .movsp goes here 1237221345Sdim MI->dump(); 1238234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1239221345Sdim } 1240221345Sdim else { 1241221345Sdim MI->dump(); 1242234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1243221345Sdim } 1244221345Sdim } 1245221345Sdim} 1246221345Sdim 1247221345Sdimextern cl::opt<bool> EnableARMEHABI; 1248221345Sdim 1249224145Sdim// Simple pseudo-instructions have their lowering (with expansion to real 1250224145Sdim// instructions) auto-generated. 1251224145Sdim#include "ARMGenMCPseudoLowering.inc" 1252224145Sdim 1253218893Sdimvoid ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { 1254239462Sdim // If we just ended a constant pool, mark it as such. 1255239462Sdim if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) { 1256239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 1257239462Sdim InConstantPool = false; 1258239462Sdim } 1259226633Sdim 1260226633Sdim // Emit unwinding stuff for frame-related instructions 1261226633Sdim if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup)) 1262226633Sdim EmitUnwindingInstruction(MI); 1263226633Sdim 1264224145Sdim // Do any auto-generated pseudo lowerings. 1265224145Sdim if (emitPseudoExpansionLowering(OutStreamer, MI)) 1266224145Sdim return; 1267224145Sdim 1268226633Sdim assert(!convertAddSubFlagsOpcode(MI->getOpcode()) && 1269226633Sdim "Pseudo flag setting opcode should be expanded early"); 1270226633Sdim 1271224145Sdim // Check for manual lowerings. 1272218893Sdim unsigned Opc = MI->getOpcode(); 1273218893Sdim switch (Opc) { 1274234353Sdim case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass"); 1275218893Sdim case ARM::DBG_VALUE: { 1276218893Sdim if (isVerbose() && OutStreamer.hasRawTextSupport()) { 1277218893Sdim SmallString<128> TmpStr; 1278218893Sdim raw_svector_ostream OS(TmpStr); 1279218893Sdim PrintDebugValueComment(MI, OS); 1280218893Sdim OutStreamer.EmitRawText(StringRef(OS.str())); 1281218893Sdim } 1282218893Sdim return; 1283218893Sdim } 1284218893Sdim case ARM::LEApcrel: 1285218893Sdim case ARM::tLEApcrel: 1286218893Sdim case ARM::t2LEApcrel: { 1287218893Sdim // FIXME: Need to also handle globals and externals 1288249423Sdim MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex()); 1289249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() == 1290249423Sdim ARM::t2LEApcrel ? ARM::t2ADR 1291249423Sdim : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR 1292249423Sdim : ARM::ADR)) 1293249423Sdim .addReg(MI->getOperand(0).getReg()) 1294249423Sdim .addExpr(MCSymbolRefExpr::Create(CPISymbol, OutContext)) 1295249423Sdim // Add predicate operands. 1296249423Sdim .addImm(MI->getOperand(2).getImm()) 1297249423Sdim .addReg(MI->getOperand(3).getReg())); 1298218893Sdim return; 1299218893Sdim } 1300218893Sdim case ARM::LEApcrelJT: 1301218893Sdim case ARM::tLEApcrelJT: 1302218893Sdim case ARM::t2LEApcrelJT: { 1303249423Sdim MCSymbol *JTIPICSymbol = 1304249423Sdim GetARMJTIPICJumpTableLabel2(MI->getOperand(1).getIndex(), 1305249423Sdim MI->getOperand(2).getImm()); 1306249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() == 1307249423Sdim ARM::t2LEApcrelJT ? ARM::t2ADR 1308249423Sdim : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR 1309249423Sdim : ARM::ADR)) 1310249423Sdim .addReg(MI->getOperand(0).getReg()) 1311249423Sdim .addExpr(MCSymbolRefExpr::Create(JTIPICSymbol, OutContext)) 1312249423Sdim // Add predicate operands. 1313249423Sdim .addImm(MI->getOperand(3).getImm()) 1314249423Sdim .addReg(MI->getOperand(4).getReg())); 1315218893Sdim return; 1316218893Sdim } 1317221345Sdim // Darwin call instructions are just normal call instructions with different 1318221345Sdim // clobber semantics (they clobber R9). 1319218893Sdim case ARM::BX_CALL: { 1320249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1321249423Sdim .addReg(ARM::LR) 1322249423Sdim .addReg(ARM::PC) 1323218893Sdim // Add predicate operands. 1324249423Sdim .addImm(ARMCC::AL) 1325249423Sdim .addReg(0) 1326218893Sdim // Add 's' bit operand (always reg0 for this) 1327249423Sdim .addReg(0)); 1328249423Sdim 1329249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX) 1330249423Sdim .addReg(MI->getOperand(0).getReg())); 1331218893Sdim return; 1332218893Sdim } 1333223017Sdim case ARM::tBX_CALL: { 1334249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1335249423Sdim .addReg(ARM::LR) 1336249423Sdim .addReg(ARM::PC) 1337224145Sdim // Add predicate operands. 1338249423Sdim .addImm(ARMCC::AL) 1339249423Sdim .addReg(0)); 1340249423Sdim 1341249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX) 1342249423Sdim .addReg(MI->getOperand(0).getReg()) 1343223017Sdim // Add predicate operands. 1344249423Sdim .addImm(ARMCC::AL) 1345249423Sdim .addReg(0)); 1346223017Sdim return; 1347223017Sdim } 1348218893Sdim case ARM::BMOVPCRX_CALL: { 1349249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1350249423Sdim .addReg(ARM::LR) 1351249423Sdim .addReg(ARM::PC) 1352218893Sdim // Add predicate operands. 1353249423Sdim .addImm(ARMCC::AL) 1354249423Sdim .addReg(0) 1355218893Sdim // Add 's' bit operand (always reg0 for this) 1356249423Sdim .addReg(0)); 1357249423Sdim 1358249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1359249423Sdim .addReg(ARM::PC) 1360249423Sdim .addReg(MI->getOperand(0).getReg()) 1361218893Sdim // Add predicate operands. 1362249423Sdim .addImm(ARMCC::AL) 1363249423Sdim .addReg(0) 1364218893Sdim // Add 's' bit operand (always reg0 for this) 1365249423Sdim .addReg(0)); 1366218893Sdim return; 1367218893Sdim } 1368234353Sdim case ARM::BMOVPCB_CALL: { 1369249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1370249423Sdim .addReg(ARM::LR) 1371249423Sdim .addReg(ARM::PC) 1372234353Sdim // Add predicate operands. 1373249423Sdim .addImm(ARMCC::AL) 1374249423Sdim .addReg(0) 1375234353Sdim // Add 's' bit operand (always reg0 for this) 1376249423Sdim .addReg(0)); 1377249423Sdim 1378249423Sdim const GlobalValue *GV = MI->getOperand(0).getGlobal(); 1379249423Sdim MCSymbol *GVSym = Mang->getSymbol(GV); 1380249423Sdim const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext); 1381249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::Bcc) 1382249423Sdim .addExpr(GVSymExpr) 1383234353Sdim // Add predicate operands. 1384249423Sdim .addImm(ARMCC::AL) 1385249423Sdim .addReg(0)); 1386234353Sdim return; 1387234353Sdim } 1388218893Sdim case ARM::MOVi16_ga_pcrel: 1389218893Sdim case ARM::t2MOVi16_ga_pcrel: { 1390218893Sdim MCInst TmpInst; 1391218893Sdim TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16); 1392218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1393218893Sdim 1394218893Sdim unsigned TF = MI->getOperand(1).getTargetFlags(); 1395218893Sdim bool isPIC = TF == ARMII::MO_LO16_NONLAZY_PIC; 1396218893Sdim const GlobalValue *GV = MI->getOperand(1).getGlobal(); 1397218893Sdim MCSymbol *GVSym = GetARMGVSymbol(GV); 1398218893Sdim const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext); 1399218893Sdim if (isPIC) { 1400218893Sdim MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(), 1401218893Sdim getFunctionNumber(), 1402218893Sdim MI->getOperand(2).getImm(), OutContext); 1403218893Sdim const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext); 1404218893Sdim unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4; 1405218893Sdim const MCExpr *PCRelExpr = 1406218893Sdim ARMMCExpr::CreateLower16(MCBinaryExpr::CreateSub(GVSymExpr, 1407218893Sdim MCBinaryExpr::CreateAdd(LabelSymExpr, 1408218893Sdim MCConstantExpr::Create(PCAdj, OutContext), 1409218893Sdim OutContext), OutContext), OutContext); 1410218893Sdim TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr)); 1411218893Sdim } else { 1412218893Sdim const MCExpr *RefExpr= ARMMCExpr::CreateLower16(GVSymExpr, OutContext); 1413218893Sdim TmpInst.addOperand(MCOperand::CreateExpr(RefExpr)); 1414218893Sdim } 1415218893Sdim 1416218893Sdim // Add predicate operands. 1417218893Sdim TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1418218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1419218893Sdim // Add 's' bit operand (always reg0 for this) 1420218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1421218893Sdim OutStreamer.EmitInstruction(TmpInst); 1422218893Sdim return; 1423218893Sdim } 1424218893Sdim case ARM::MOVTi16_ga_pcrel: 1425218893Sdim case ARM::t2MOVTi16_ga_pcrel: { 1426218893Sdim MCInst TmpInst; 1427218893Sdim TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel 1428218893Sdim ? ARM::MOVTi16 : ARM::t2MOVTi16); 1429218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1430218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); 1431218893Sdim 1432218893Sdim unsigned TF = MI->getOperand(2).getTargetFlags(); 1433218893Sdim bool isPIC = TF == ARMII::MO_HI16_NONLAZY_PIC; 1434218893Sdim const GlobalValue *GV = MI->getOperand(2).getGlobal(); 1435218893Sdim MCSymbol *GVSym = GetARMGVSymbol(GV); 1436218893Sdim const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext); 1437218893Sdim if (isPIC) { 1438218893Sdim MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(), 1439218893Sdim getFunctionNumber(), 1440218893Sdim MI->getOperand(3).getImm(), OutContext); 1441218893Sdim const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext); 1442218893Sdim unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4; 1443218893Sdim const MCExpr *PCRelExpr = 1444218893Sdim ARMMCExpr::CreateUpper16(MCBinaryExpr::CreateSub(GVSymExpr, 1445218893Sdim MCBinaryExpr::CreateAdd(LabelSymExpr, 1446218893Sdim MCConstantExpr::Create(PCAdj, OutContext), 1447218893Sdim OutContext), OutContext), OutContext); 1448218893Sdim TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr)); 1449218893Sdim } else { 1450218893Sdim const MCExpr *RefExpr= ARMMCExpr::CreateUpper16(GVSymExpr, OutContext); 1451218893Sdim TmpInst.addOperand(MCOperand::CreateExpr(RefExpr)); 1452218893Sdim } 1453218893Sdim // Add predicate operands. 1454218893Sdim TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1455218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1456218893Sdim // Add 's' bit operand (always reg0 for this) 1457218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1458218893Sdim OutStreamer.EmitInstruction(TmpInst); 1459218893Sdim return; 1460218893Sdim } 1461218893Sdim case ARM::tPICADD: { 1462212793Sdim // This is a pseudo op for a label + instruction sequence, which looks like: 1463212793Sdim // LPC0: 1464218893Sdim // add r0, pc 1465218893Sdim // This adds the address of LPC0 to r0. 1466218893Sdim 1467218893Sdim // Emit the label. 1468218893Sdim OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 1469218893Sdim getFunctionNumber(), MI->getOperand(2).getImm(), 1470218893Sdim OutContext)); 1471218893Sdim 1472218893Sdim // Form and emit the add. 1473249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDhirr) 1474249423Sdim .addReg(MI->getOperand(0).getReg()) 1475249423Sdim .addReg(MI->getOperand(0).getReg()) 1476249423Sdim .addReg(ARM::PC) 1477249423Sdim // Add predicate operands. 1478249423Sdim .addImm(ARMCC::AL) 1479249423Sdim .addReg(0)); 1480218893Sdim return; 1481218893Sdim } 1482218893Sdim case ARM::PICADD: { 1483218893Sdim // This is a pseudo op for a label + instruction sequence, which looks like: 1484218893Sdim // LPC0: 1485212793Sdim // add r0, pc, r0 1486212793Sdim // This adds the address of LPC0 to r0. 1487212793Sdim 1488212793Sdim // Emit the label. 1489218893Sdim OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 1490218893Sdim getFunctionNumber(), MI->getOperand(2).getImm(), 1491218893Sdim OutContext)); 1492212793Sdim 1493218893Sdim // Form and emit the add. 1494249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr) 1495249423Sdim .addReg(MI->getOperand(0).getReg()) 1496249423Sdim .addReg(ARM::PC) 1497249423Sdim .addReg(MI->getOperand(1).getReg()) 1498249423Sdim // Add predicate operands. 1499249423Sdim .addImm(MI->getOperand(3).getImm()) 1500249423Sdim .addReg(MI->getOperand(4).getReg()) 1501249423Sdim // Add 's' bit operand (always reg0 for this) 1502249423Sdim .addReg(0)); 1503212793Sdim return; 1504212793Sdim } 1505218893Sdim case ARM::PICSTR: 1506218893Sdim case ARM::PICSTRB: 1507218893Sdim case ARM::PICSTRH: 1508218893Sdim case ARM::PICLDR: 1509218893Sdim case ARM::PICLDRB: 1510218893Sdim case ARM::PICLDRH: 1511218893Sdim case ARM::PICLDRSB: 1512218893Sdim case ARM::PICLDRSH: { 1513218893Sdim // This is a pseudo op for a label + instruction sequence, which looks like: 1514218893Sdim // LPC0: 1515218893Sdim // OP r0, [pc, r0] 1516218893Sdim // The LCP0 label is referenced by a constant pool entry in order to get 1517218893Sdim // a PC-relative address at the ldr instruction. 1518218893Sdim 1519218893Sdim // Emit the label. 1520218893Sdim OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 1521218893Sdim getFunctionNumber(), MI->getOperand(2).getImm(), 1522218893Sdim OutContext)); 1523218893Sdim 1524218893Sdim // Form and emit the load 1525218893Sdim unsigned Opcode; 1526218893Sdim switch (MI->getOpcode()) { 1527218893Sdim default: 1528218893Sdim llvm_unreachable("Unexpected opcode!"); 1529218893Sdim case ARM::PICSTR: Opcode = ARM::STRrs; break; 1530218893Sdim case ARM::PICSTRB: Opcode = ARM::STRBrs; break; 1531218893Sdim case ARM::PICSTRH: Opcode = ARM::STRH; break; 1532218893Sdim case ARM::PICLDR: Opcode = ARM::LDRrs; break; 1533218893Sdim case ARM::PICLDRB: Opcode = ARM::LDRBrs; break; 1534218893Sdim case ARM::PICLDRH: Opcode = ARM::LDRH; break; 1535218893Sdim case ARM::PICLDRSB: Opcode = ARM::LDRSB; break; 1536218893Sdim case ARM::PICLDRSH: Opcode = ARM::LDRSH; break; 1537218893Sdim } 1538249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(Opcode) 1539249423Sdim .addReg(MI->getOperand(0).getReg()) 1540249423Sdim .addReg(ARM::PC) 1541249423Sdim .addReg(MI->getOperand(1).getReg()) 1542249423Sdim .addImm(0) 1543249423Sdim // Add predicate operands. 1544249423Sdim .addImm(MI->getOperand(3).getImm()) 1545249423Sdim .addReg(MI->getOperand(4).getReg())); 1546218893Sdim 1547218893Sdim return; 1548218893Sdim } 1549218893Sdim case ARM::CONSTPOOL_ENTRY: { 1550212793Sdim /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool 1551212793Sdim /// in the function. The first operand is the ID# for this instruction, the 1552212793Sdim /// second is the index into the MachineConstantPool that this is, the third 1553212793Sdim /// is the size in bytes of this constant pool entry. 1554234353Sdim /// The required alignment is specified on the basic block holding this MI. 1555212793Sdim unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); 1556212793Sdim unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); 1557212793Sdim 1558239462Sdim // If this is the first entry of the pool, mark it. 1559239462Sdim if (!InConstantPool) { 1560239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegion); 1561239462Sdim InConstantPool = true; 1562239462Sdim } 1563239462Sdim 1564212793Sdim OutStreamer.EmitLabel(GetCPISymbol(LabelId)); 1565212793Sdim 1566212793Sdim const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; 1567212793Sdim if (MCPE.isMachineConstantPoolEntry()) 1568212793Sdim EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 1569212793Sdim else 1570212793Sdim EmitGlobalConstant(MCPE.Val.ConstVal); 1571212793Sdim return; 1572212793Sdim } 1573218893Sdim case ARM::t2BR_JT: { 1574218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1575249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1576249423Sdim .addReg(ARM::PC) 1577249423Sdim .addReg(MI->getOperand(0).getReg()) 1578249423Sdim // Add predicate operands. 1579249423Sdim .addImm(ARMCC::AL) 1580249423Sdim .addReg(0)); 1581249423Sdim 1582218893Sdim // Output the data for the jump table itself 1583218893Sdim EmitJump2Table(MI); 1584218893Sdim return; 1585218893Sdim } 1586218893Sdim case ARM::t2TBB_JT: { 1587218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1588249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBB) 1589249423Sdim .addReg(ARM::PC) 1590249423Sdim .addReg(MI->getOperand(0).getReg()) 1591249423Sdim // Add predicate operands. 1592249423Sdim .addImm(ARMCC::AL) 1593249423Sdim .addReg(0)); 1594212793Sdim 1595218893Sdim // Output the data for the jump table itself 1596218893Sdim EmitJump2Table(MI); 1597218893Sdim // Make sure the next instruction is 2-byte aligned. 1598218893Sdim EmitAlignment(1); 1599218893Sdim return; 1600218893Sdim } 1601218893Sdim case ARM::t2TBH_JT: { 1602218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1603249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBH) 1604249423Sdim .addReg(ARM::PC) 1605249423Sdim .addReg(MI->getOperand(0).getReg()) 1606249423Sdim // Add predicate operands. 1607249423Sdim .addImm(ARMCC::AL) 1608249423Sdim .addReg(0)); 1609212793Sdim 1610218893Sdim // Output the data for the jump table itself 1611218893Sdim EmitJump2Table(MI); 1612218893Sdim return; 1613218893Sdim } 1614218893Sdim case ARM::tBR_JTr: 1615218893Sdim case ARM::BR_JTr: { 1616218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1617218893Sdim // mov pc, target 1618218893Sdim MCInst TmpInst; 1619218893Sdim unsigned Opc = MI->getOpcode() == ARM::BR_JTr ? 1620224145Sdim ARM::MOVr : ARM::tMOVr; 1621218893Sdim TmpInst.setOpcode(Opc); 1622218893Sdim TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1623218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1624218893Sdim // Add predicate operands. 1625218893Sdim TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1626218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1627218893Sdim // Add 's' bit operand (always reg0 for this) 1628218893Sdim if (Opc == ARM::MOVr) 1629218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1630218893Sdim OutStreamer.EmitInstruction(TmpInst); 1631212793Sdim 1632218893Sdim // Make sure the Thumb jump table is 4-byte aligned. 1633224145Sdim if (Opc == ARM::tMOVr) 1634218893Sdim EmitAlignment(2); 1635218893Sdim 1636218893Sdim // Output the data for the jump table itself 1637218893Sdim EmitJumpTable(MI); 1638218893Sdim return; 1639218893Sdim } 1640218893Sdim case ARM::BR_JTm: { 1641218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1642218893Sdim // ldr pc, target 1643218893Sdim MCInst TmpInst; 1644218893Sdim if (MI->getOperand(1).getReg() == 0) { 1645218893Sdim // literal offset 1646218893Sdim TmpInst.setOpcode(ARM::LDRi12); 1647218893Sdim TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1648218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1649212793Sdim TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1650218893Sdim } else { 1651218893Sdim TmpInst.setOpcode(ARM::LDRrs); 1652218893Sdim TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1653218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1654218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); 1655218893Sdim TmpInst.addOperand(MCOperand::CreateImm(0)); 1656218893Sdim } 1657218893Sdim // Add predicate operands. 1658218893Sdim TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1659218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1660218893Sdim OutStreamer.EmitInstruction(TmpInst); 1661212793Sdim 1662218893Sdim // Output the data for the jump table itself 1663218893Sdim EmitJumpTable(MI); 1664218893Sdim return; 1665218893Sdim } 1666218893Sdim case ARM::BR_JTadd: { 1667218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1668218893Sdim // add pc, target, idx 1669249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr) 1670249423Sdim .addReg(ARM::PC) 1671249423Sdim .addReg(MI->getOperand(0).getReg()) 1672249423Sdim .addReg(MI->getOperand(1).getReg()) 1673249423Sdim // Add predicate operands. 1674249423Sdim .addImm(ARMCC::AL) 1675249423Sdim .addReg(0) 1676249423Sdim // Add 's' bit operand (always reg0 for this) 1677249423Sdim .addReg(0)); 1678218893Sdim 1679218893Sdim // Output the data for the jump table itself 1680218893Sdim EmitJumpTable(MI); 1681218893Sdim return; 1682218893Sdim } 1683218893Sdim case ARM::TRAP: { 1684218893Sdim // Non-Darwin binutils don't yet support the "trap" mnemonic. 1685218893Sdim // FIXME: Remove this special case when they do. 1686218893Sdim if (!Subtarget->isTargetDarwin()) { 1687218893Sdim //.long 0xe7ffdefe @ trap 1688218893Sdim uint32_t Val = 0xe7ffdefeUL; 1689218893Sdim OutStreamer.AddComment("trap"); 1690218893Sdim OutStreamer.EmitIntValue(Val, 4); 1691218893Sdim return; 1692218893Sdim } 1693218893Sdim break; 1694218893Sdim } 1695249423Sdim case ARM::TRAPNaCl: { 1696249423Sdim //.long 0xe7fedef0 @ trap 1697249423Sdim uint32_t Val = 0xe7fedef0UL; 1698249423Sdim OutStreamer.AddComment("trap"); 1699249423Sdim OutStreamer.EmitIntValue(Val, 4); 1700249423Sdim return; 1701249423Sdim } 1702218893Sdim case ARM::tTRAP: { 1703218893Sdim // Non-Darwin binutils don't yet support the "trap" mnemonic. 1704218893Sdim // FIXME: Remove this special case when they do. 1705218893Sdim if (!Subtarget->isTargetDarwin()) { 1706218893Sdim //.short 57086 @ trap 1707218893Sdim uint16_t Val = 0xdefe; 1708218893Sdim OutStreamer.AddComment("trap"); 1709218893Sdim OutStreamer.EmitIntValue(Val, 2); 1710218893Sdim return; 1711218893Sdim } 1712218893Sdim break; 1713218893Sdim } 1714218893Sdim case ARM::t2Int_eh_sjlj_setjmp: 1715218893Sdim case ARM::t2Int_eh_sjlj_setjmp_nofp: 1716218893Sdim case ARM::tInt_eh_sjlj_setjmp: { 1717218893Sdim // Two incoming args: GPR:$src, GPR:$val 1718218893Sdim // mov $val, pc 1719218893Sdim // adds $val, #7 1720218893Sdim // str $val, [$src, #4] 1721218893Sdim // movs r0, #0 1722218893Sdim // b 1f 1723218893Sdim // movs r0, #1 1724218893Sdim // 1: 1725218893Sdim unsigned SrcReg = MI->getOperand(0).getReg(); 1726218893Sdim unsigned ValReg = MI->getOperand(1).getReg(); 1727218893Sdim MCSymbol *Label = GetARMSJLJEHLabel(); 1728249423Sdim OutStreamer.AddComment("eh_setjmp begin"); 1729249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1730249423Sdim .addReg(ValReg) 1731249423Sdim .addReg(ARM::PC) 1732224145Sdim // Predicate. 1733249423Sdim .addImm(ARMCC::AL) 1734249423Sdim .addReg(0)); 1735249423Sdim 1736249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDi3) 1737249423Sdim .addReg(ValReg) 1738218893Sdim // 's' bit operand 1739249423Sdim .addReg(ARM::CPSR) 1740249423Sdim .addReg(ValReg) 1741249423Sdim .addImm(7) 1742218893Sdim // Predicate. 1743249423Sdim .addImm(ARMCC::AL) 1744249423Sdim .addReg(0)); 1745249423Sdim 1746249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tSTRi) 1747249423Sdim .addReg(ValReg) 1748249423Sdim .addReg(SrcReg) 1749218893Sdim // The offset immediate is #4. The operand value is scaled by 4 for the 1750218893Sdim // tSTR instruction. 1751249423Sdim .addImm(1) 1752218893Sdim // Predicate. 1753249423Sdim .addImm(ARMCC::AL) 1754249423Sdim .addReg(0)); 1755249423Sdim 1756249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8) 1757249423Sdim .addReg(ARM::R0) 1758249423Sdim .addReg(ARM::CPSR) 1759249423Sdim .addImm(0) 1760218893Sdim // Predicate. 1761249423Sdim .addImm(ARMCC::AL) 1762249423Sdim .addReg(0)); 1763249423Sdim 1764249423Sdim const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext); 1765249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tB) 1766249423Sdim .addExpr(SymbolExpr) 1767249423Sdim .addImm(ARMCC::AL) 1768249423Sdim .addReg(0)); 1769249423Sdim 1770249423Sdim OutStreamer.AddComment("eh_setjmp end"); 1771249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8) 1772249423Sdim .addReg(ARM::R0) 1773249423Sdim .addReg(ARM::CPSR) 1774249423Sdim .addImm(1) 1775218893Sdim // Predicate. 1776249423Sdim .addImm(ARMCC::AL) 1777249423Sdim .addReg(0)); 1778249423Sdim 1779218893Sdim OutStreamer.EmitLabel(Label); 1780218893Sdim return; 1781218893Sdim } 1782212793Sdim 1783218893Sdim case ARM::Int_eh_sjlj_setjmp_nofp: 1784218893Sdim case ARM::Int_eh_sjlj_setjmp: { 1785218893Sdim // Two incoming args: GPR:$src, GPR:$val 1786218893Sdim // add $val, pc, #8 1787218893Sdim // str $val, [$src, #+4] 1788218893Sdim // mov r0, #0 1789218893Sdim // add pc, pc, #0 1790218893Sdim // mov r0, #1 1791218893Sdim unsigned SrcReg = MI->getOperand(0).getReg(); 1792218893Sdim unsigned ValReg = MI->getOperand(1).getReg(); 1793218893Sdim 1794249423Sdim OutStreamer.AddComment("eh_setjmp begin"); 1795249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri) 1796249423Sdim .addReg(ValReg) 1797249423Sdim .addReg(ARM::PC) 1798249423Sdim .addImm(8) 1799212793Sdim // Predicate. 1800249423Sdim .addImm(ARMCC::AL) 1801249423Sdim .addReg(0) 1802218893Sdim // 's' bit operand (always reg0 for this). 1803249423Sdim .addReg(0)); 1804249423Sdim 1805249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::STRi12) 1806249423Sdim .addReg(ValReg) 1807249423Sdim .addReg(SrcReg) 1808249423Sdim .addImm(4) 1809218893Sdim // Predicate. 1810249423Sdim .addImm(ARMCC::AL) 1811249423Sdim .addReg(0)); 1812249423Sdim 1813249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi) 1814249423Sdim .addReg(ARM::R0) 1815249423Sdim .addImm(0) 1816218893Sdim // Predicate. 1817249423Sdim .addImm(ARMCC::AL) 1818249423Sdim .addReg(0) 1819218893Sdim // 's' bit operand (always reg0 for this). 1820249423Sdim .addReg(0)); 1821249423Sdim 1822249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri) 1823249423Sdim .addReg(ARM::PC) 1824249423Sdim .addReg(ARM::PC) 1825249423Sdim .addImm(0) 1826218893Sdim // Predicate. 1827249423Sdim .addImm(ARMCC::AL) 1828249423Sdim .addReg(0) 1829218893Sdim // 's' bit operand (always reg0 for this). 1830249423Sdim .addReg(0)); 1831249423Sdim 1832249423Sdim OutStreamer.AddComment("eh_setjmp end"); 1833249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi) 1834249423Sdim .addReg(ARM::R0) 1835249423Sdim .addImm(1) 1836218893Sdim // Predicate. 1837249423Sdim .addImm(ARMCC::AL) 1838249423Sdim .addReg(0) 1839218893Sdim // 's' bit operand (always reg0 for this). 1840249423Sdim .addReg(0)); 1841212793Sdim return; 1842212793Sdim } 1843218893Sdim case ARM::Int_eh_sjlj_longjmp: { 1844218893Sdim // ldr sp, [$src, #8] 1845218893Sdim // ldr $scratch, [$src, #4] 1846218893Sdim // ldr r7, [$src] 1847218893Sdim // bx $scratch 1848218893Sdim unsigned SrcReg = MI->getOperand(0).getReg(); 1849218893Sdim unsigned ScratchReg = MI->getOperand(1).getReg(); 1850249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12) 1851249423Sdim .addReg(ARM::SP) 1852249423Sdim .addReg(SrcReg) 1853249423Sdim .addImm(8) 1854218893Sdim // Predicate. 1855249423Sdim .addImm(ARMCC::AL) 1856249423Sdim .addReg(0)); 1857249423Sdim 1858249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12) 1859249423Sdim .addReg(ScratchReg) 1860249423Sdim .addReg(SrcReg) 1861249423Sdim .addImm(4) 1862212793Sdim // Predicate. 1863249423Sdim .addImm(ARMCC::AL) 1864249423Sdim .addReg(0)); 1865249423Sdim 1866249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12) 1867249423Sdim .addReg(ARM::R7) 1868249423Sdim .addReg(SrcReg) 1869249423Sdim .addImm(0) 1870212793Sdim // Predicate. 1871249423Sdim .addImm(ARMCC::AL) 1872249423Sdim .addReg(0)); 1873249423Sdim 1874249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX) 1875249423Sdim .addReg(ScratchReg) 1876218893Sdim // Predicate. 1877249423Sdim .addImm(ARMCC::AL) 1878249423Sdim .addReg(0)); 1879212793Sdim return; 1880212793Sdim } 1881218893Sdim case ARM::tInt_eh_sjlj_longjmp: { 1882218893Sdim // ldr $scratch, [$src, #8] 1883218893Sdim // mov sp, $scratch 1884218893Sdim // ldr $scratch, [$src, #4] 1885218893Sdim // ldr r7, [$src] 1886218893Sdim // bx $scratch 1887218893Sdim unsigned SrcReg = MI->getOperand(0).getReg(); 1888218893Sdim unsigned ScratchReg = MI->getOperand(1).getReg(); 1889249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi) 1890249423Sdim .addReg(ScratchReg) 1891249423Sdim .addReg(SrcReg) 1892218893Sdim // The offset immediate is #8. The operand value is scaled by 4 for the 1893218893Sdim // tLDR instruction. 1894249423Sdim .addImm(2) 1895218893Sdim // Predicate. 1896249423Sdim .addImm(ARMCC::AL) 1897249423Sdim .addReg(0)); 1898249423Sdim 1899249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1900249423Sdim .addReg(ARM::SP) 1901249423Sdim .addReg(ScratchReg) 1902218893Sdim // Predicate. 1903249423Sdim .addImm(ARMCC::AL) 1904249423Sdim .addReg(0)); 1905249423Sdim 1906249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi) 1907249423Sdim .addReg(ScratchReg) 1908249423Sdim .addReg(SrcReg) 1909249423Sdim .addImm(1) 1910218893Sdim // Predicate. 1911249423Sdim .addImm(ARMCC::AL) 1912249423Sdim .addReg(0)); 1913249423Sdim 1914249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi) 1915249423Sdim .addReg(ARM::R7) 1916249423Sdim .addReg(SrcReg) 1917249423Sdim .addImm(0) 1918218893Sdim // Predicate. 1919249423Sdim .addImm(ARMCC::AL) 1920249423Sdim .addReg(0)); 1921249423Sdim 1922249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX) 1923249423Sdim .addReg(ScratchReg) 1924218893Sdim // Predicate. 1925249423Sdim .addImm(ARMCC::AL) 1926249423Sdim .addReg(0)); 1927218893Sdim return; 1928212793Sdim } 1929221345Sdim } 1930221345Sdim 1931212793Sdim MCInst TmpInst; 1932218893Sdim LowerARMMachineInstrToMCInst(MI, TmpInst, *this); 1933221345Sdim 1934212793Sdim OutStreamer.EmitInstruction(TmpInst); 1935212793Sdim} 1936212793Sdim 1937212793Sdim//===----------------------------------------------------------------------===// 1938212793Sdim// Target Registry Stuff 1939212793Sdim//===----------------------------------------------------------------------===// 1940212793Sdim 1941212793Sdim// Force static initialization. 1942212793Sdimextern "C" void LLVMInitializeARMAsmPrinter() { 1943212793Sdim RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); 1944212793Sdim RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); 1945212793Sdim} 1946