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" 20263508Sdim#include "ARMFPUName.h" 21212793Sdim#include "ARMMachineFunctionInfo.h" 22212793Sdim#include "ARMTargetMachine.h" 23218893Sdim#include "ARMTargetObjectFile.h" 24218893Sdim#include "InstPrinter/ARMInstPrinter.h" 25226633Sdim#include "MCTargetDesc/ARMAddressingModes.h" 26226633Sdim#include "MCTargetDesc/ARMMCExpr.h" 27243830Sdim#include "llvm/ADT/SetVector.h" 28243830Sdim#include "llvm/ADT/SmallString.h" 29212793Sdim#include "llvm/Assembly/Writer.h" 30212793Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 31212793Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h" 32249423Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h" 33249423Sdim#include "llvm/DebugInfo.h" 34249423Sdim#include "llvm/IR/Constants.h" 35249423Sdim#include "llvm/IR/DataLayout.h" 36249423Sdim#include "llvm/IR/Module.h" 37249423Sdim#include "llvm/IR/Type.h" 38212793Sdim#include "llvm/MC/MCAsmInfo.h" 39218893Sdim#include "llvm/MC/MCAssembler.h" 40212793Sdim#include "llvm/MC/MCContext.h" 41249423Sdim#include "llvm/MC/MCELFStreamer.h" 42212793Sdim#include "llvm/MC/MCInst.h" 43249423Sdim#include "llvm/MC/MCInstBuilder.h" 44249423Sdim#include "llvm/MC/MCObjectStreamer.h" 45212793Sdim#include "llvm/MC/MCSectionMachO.h" 46212793Sdim#include "llvm/MC/MCStreamer.h" 47212793Sdim#include "llvm/MC/MCSymbol.h" 48212793Sdim#include "llvm/Support/CommandLine.h" 49212793Sdim#include "llvm/Support/Debug.h" 50249423Sdim#include "llvm/Support/ELF.h" 51212793Sdim#include "llvm/Support/ErrorHandling.h" 52226633Sdim#include "llvm/Support/TargetRegistry.h" 53212793Sdim#include "llvm/Support/raw_ostream.h" 54249423Sdim#include "llvm/Target/Mangler.h" 55249423Sdim#include "llvm/Target/TargetMachine.h" 56212793Sdim#include <cctype> 57212793Sdimusing namespace llvm; 58212793Sdim 59221345Sdim/// EmitDwarfRegOp - Emit dwarf register operation. 60263508Sdimvoid ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc, 61263508Sdim bool Indirect) const { 62221345Sdim const TargetRegisterInfo *RI = TM.getRegisterInfo(); 63263508Sdim if (RI->getDwarfRegNum(MLoc.getReg(), false) != -1) { 64263508Sdim AsmPrinter::EmitDwarfRegOp(MLoc, Indirect); 65263508Sdim return; 66263508Sdim } 67263508Sdim assert(MLoc.isReg() && !Indirect && 68263508Sdim "This doesn't support offset/indirection - implement it if needed"); 69263508Sdim unsigned Reg = MLoc.getReg(); 70263508Sdim if (Reg >= ARM::S0 && Reg <= ARM::S31) { 71263508Sdim assert(ARM::S0 + 31 == ARM::S31 && "Unexpected ARM S register numbering"); 72263508Sdim // S registers are described as bit-pieces of a register 73263508Sdim // S[2x] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 0) 74263508Sdim // S[2x+1] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 32) 75226633Sdim 76263508Sdim unsigned SReg = Reg - ARM::S0; 77263508Sdim bool odd = SReg & 0x1; 78263508Sdim unsigned Rx = 256 + (SReg >> 1); 79221345Sdim 80263508Sdim OutStreamer.AddComment("DW_OP_regx for S register"); 81263508Sdim EmitInt8(dwarf::DW_OP_regx); 82221345Sdim 83263508Sdim OutStreamer.AddComment(Twine(SReg)); 84263508Sdim EmitULEB128(Rx); 85221345Sdim 86263508Sdim if (odd) { 87263508Sdim OutStreamer.AddComment("DW_OP_bit_piece 32 32"); 88263508Sdim EmitInt8(dwarf::DW_OP_bit_piece); 89263508Sdim EmitULEB128(32); 90263508Sdim EmitULEB128(32); 91263508Sdim } else { 92263508Sdim OutStreamer.AddComment("DW_OP_bit_piece 32 0"); 93263508Sdim EmitInt8(dwarf::DW_OP_bit_piece); 94263508Sdim EmitULEB128(32); 95263508Sdim EmitULEB128(0); 96263508Sdim } 97263508Sdim } else if (Reg >= ARM::Q0 && Reg <= ARM::Q15) { 98263508Sdim assert(ARM::Q0 + 15 == ARM::Q15 && "Unexpected ARM Q register numbering"); 99263508Sdim // Q registers Q0-Q15 are described by composing two D registers together. 100263508Sdim // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1) 101263508Sdim // DW_OP_piece(8) 102221345Sdim 103263508Sdim unsigned QReg = Reg - ARM::Q0; 104263508Sdim unsigned D1 = 256 + 2 * QReg; 105263508Sdim unsigned D2 = D1 + 1; 106226633Sdim 107263508Sdim OutStreamer.AddComment("DW_OP_regx for Q register: D1"); 108263508Sdim EmitInt8(dwarf::DW_OP_regx); 109263508Sdim EmitULEB128(D1); 110263508Sdim OutStreamer.AddComment("DW_OP_piece 8"); 111263508Sdim EmitInt8(dwarf::DW_OP_piece); 112263508Sdim EmitULEB128(8); 113221345Sdim 114263508Sdim OutStreamer.AddComment("DW_OP_regx for Q register: D2"); 115263508Sdim EmitInt8(dwarf::DW_OP_regx); 116263508Sdim EmitULEB128(D2); 117263508Sdim OutStreamer.AddComment("DW_OP_piece 8"); 118263508Sdim EmitInt8(dwarf::DW_OP_piece); 119263508Sdim EmitULEB128(8); 120221345Sdim } 121221345Sdim} 122221345Sdim 123239462Sdimvoid ARMAsmPrinter::EmitFunctionBodyEnd() { 124239462Sdim // Make sure to terminate any constant pools that were at the end 125239462Sdim // of the function. 126239462Sdim if (!InConstantPool) 127239462Sdim return; 128239462Sdim InConstantPool = false; 129239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 130239462Sdim} 131239462Sdim 132212793Sdimvoid ARMAsmPrinter::EmitFunctionEntryLabel() { 133212793Sdim if (AFI->isThumbFunction()) { 134218893Sdim OutStreamer.EmitAssemblerFlag(MCAF_Code16); 135223017Sdim OutStreamer.EmitThumbFunc(CurrentFnSym); 136212793Sdim } 137212793Sdim 138212793Sdim OutStreamer.EmitLabel(CurrentFnSym); 139212793Sdim} 140212793Sdim 141234353Sdimvoid ARMAsmPrinter::EmitXXStructor(const Constant *CV) { 142243830Sdim uint64_t Size = TM.getDataLayout()->getTypeAllocSize(CV->getType()); 143234353Sdim assert(Size && "C++ constructor pointer had zero size!"); 144234353Sdim 145234353Sdim const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts()); 146234353Sdim assert(GV && "C++ constructor pointer was not a GlobalValue!"); 147234353Sdim 148263508Sdim const MCExpr *E = MCSymbolRefExpr::Create(getSymbol(GV), 149234353Sdim (Subtarget->isTargetDarwin() 150234353Sdim ? MCSymbolRefExpr::VK_None 151234353Sdim : MCSymbolRefExpr::VK_ARM_TARGET1), 152234353Sdim OutContext); 153234353Sdim 154234353Sdim OutStreamer.EmitValue(E, Size); 155234353Sdim} 156234353Sdim 157218893Sdim/// runOnMachineFunction - This uses the EmitInstruction() 158212793Sdim/// method to print assembly for each instruction. 159212793Sdim/// 160212793Sdimbool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 161212793Sdim AFI = MF.getInfo<ARMFunctionInfo>(); 162212793Sdim MCP = MF.getConstantPool(); 163212793Sdim 164212793Sdim return AsmPrinter::runOnMachineFunction(MF); 165212793Sdim} 166212793Sdim 167212793Sdimvoid ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 168212793Sdim raw_ostream &O, const char *Modifier) { 169212793Sdim const MachineOperand &MO = MI->getOperand(OpNum); 170212793Sdim unsigned TF = MO.getTargetFlags(); 171212793Sdim 172212793Sdim switch (MO.getType()) { 173234353Sdim default: llvm_unreachable("<unknown operand type>"); 174212793Sdim case MachineOperand::MO_Register: { 175212793Sdim unsigned Reg = MO.getReg(); 176212793Sdim assert(TargetRegisterInfo::isPhysicalRegister(Reg)); 177218893Sdim assert(!MO.getSubReg() && "Subregs should be eliminated!"); 178249423Sdim if(ARM::GPRPairRegClass.contains(Reg)) { 179249423Sdim const MachineFunction &MF = *MI->getParent()->getParent(); 180249423Sdim const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); 181249423Sdim Reg = TRI->getSubReg(Reg, ARM::gsub_0); 182249423Sdim } 183218893Sdim O << ARMInstPrinter::getRegisterName(Reg); 184212793Sdim break; 185212793Sdim } 186212793Sdim case MachineOperand::MO_Immediate: { 187212793Sdim int64_t Imm = MO.getImm(); 188212793Sdim O << '#'; 189212793Sdim if ((Modifier && strcmp(Modifier, "lo16") == 0) || 190218893Sdim (TF == ARMII::MO_LO16)) 191212793Sdim O << ":lower16:"; 192212793Sdim else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 193218893Sdim (TF == ARMII::MO_HI16)) 194212793Sdim O << ":upper16:"; 195212793Sdim O << Imm; 196212793Sdim break; 197212793Sdim } 198212793Sdim case MachineOperand::MO_MachineBasicBlock: 199212793Sdim O << *MO.getMBB()->getSymbol(); 200212793Sdim return; 201212793Sdim case MachineOperand::MO_GlobalAddress: { 202212793Sdim const GlobalValue *GV = MO.getGlobal(); 203212793Sdim if ((Modifier && strcmp(Modifier, "lo16") == 0) || 204212793Sdim (TF & ARMII::MO_LO16)) 205212793Sdim O << ":lower16:"; 206212793Sdim else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 207212793Sdim (TF & ARMII::MO_HI16)) 208212793Sdim O << ":upper16:"; 209263508Sdim O << *getSymbol(GV); 210212793Sdim 211212793Sdim printOffset(MO.getOffset(), O); 212218893Sdim if (TF == ARMII::MO_PLT) 213212793Sdim O << "(PLT)"; 214212793Sdim break; 215212793Sdim } 216212793Sdim case MachineOperand::MO_ExternalSymbol: { 217212793Sdim O << *GetExternalSymbolSymbol(MO.getSymbolName()); 218218893Sdim if (TF == ARMII::MO_PLT) 219212793Sdim O << "(PLT)"; 220212793Sdim break; 221212793Sdim } 222212793Sdim case MachineOperand::MO_ConstantPoolIndex: 223212793Sdim O << *GetCPISymbol(MO.getIndex()); 224212793Sdim break; 225212793Sdim case MachineOperand::MO_JumpTableIndex: 226212793Sdim O << *GetJTISymbol(MO.getIndex()); 227212793Sdim break; 228212793Sdim } 229212793Sdim} 230212793Sdim 231212793Sdim//===--------------------------------------------------------------------===// 232212793Sdim 233212793SdimMCSymbol *ARMAsmPrinter:: 234212793SdimGetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const { 235212793Sdim SmallString<60> Name; 236212793Sdim raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI" 237212793Sdim << getFunctionNumber() << '_' << uid << '_' << uid2; 238212793Sdim return OutContext.GetOrCreateSymbol(Name.str()); 239212793Sdim} 240212793Sdim 241212793Sdim 242249423SdimMCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel() const { 243218893Sdim SmallString<60> Name; 244218893Sdim raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH" 245218893Sdim << getFunctionNumber(); 246218893Sdim return OutContext.GetOrCreateSymbol(Name.str()); 247212793Sdim} 248212793Sdim 249212793Sdimbool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 250212793Sdim unsigned AsmVariant, const char *ExtraCode, 251212793Sdim raw_ostream &O) { 252212793Sdim // Does this asm operand have a single letter operand modifier? 253212793Sdim if (ExtraCode && ExtraCode[0]) { 254212793Sdim if (ExtraCode[1] != 0) return true; // Unknown modifier. 255212793Sdim 256212793Sdim switch (ExtraCode[0]) { 257239462Sdim default: 258239462Sdim // See if this is a generic print operand 259239462Sdim return AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O); 260212793Sdim case 'a': // Print as a memory address. 261212793Sdim if (MI->getOperand(OpNum).isReg()) { 262218893Sdim O << "[" 263218893Sdim << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg()) 264218893Sdim << "]"; 265212793Sdim return false; 266212793Sdim } 267212793Sdim // Fallthrough 268212793Sdim case 'c': // Don't print "#" before an immediate operand. 269212793Sdim if (!MI->getOperand(OpNum).isImm()) 270212793Sdim return true; 271218893Sdim O << MI->getOperand(OpNum).getImm(); 272212793Sdim return false; 273212793Sdim case 'P': // Print a VFP double precision register. 274212793Sdim case 'q': // Print a NEON quad precision register. 275212793Sdim printOperand(MI, OpNum, O); 276212793Sdim return false; 277223017Sdim case 'y': // Print a VFP single precision register as indexed double. 278223017Sdim if (MI->getOperand(OpNum).isReg()) { 279223017Sdim unsigned Reg = MI->getOperand(OpNum).getReg(); 280223017Sdim const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); 281239462Sdim // Find the 'd' register that has this 's' register as a sub-register, 282239462Sdim // and determine the lane number. 283239462Sdim for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) { 284239462Sdim if (!ARM::DPRRegClass.contains(*SR)) 285239462Sdim continue; 286239462Sdim bool Lane0 = TRI->getSubReg(*SR, ARM::ssub_0) == Reg; 287239462Sdim O << ARMInstPrinter::getRegisterName(*SR) << (Lane0 ? "[0]" : "[1]"); 288239462Sdim return false; 289239462Sdim } 290223017Sdim } 291212793Sdim return true; 292223017Sdim case 'B': // Bitwise inverse of integer or symbol without a preceding #. 293223017Sdim if (!MI->getOperand(OpNum).isImm()) 294223017Sdim return true; 295223017Sdim O << ~(MI->getOperand(OpNum).getImm()); 296223017Sdim return false; 297223017Sdim case 'L': // The low 16 bits of an immediate constant. 298223017Sdim if (!MI->getOperand(OpNum).isImm()) 299223017Sdim return true; 300223017Sdim O << (MI->getOperand(OpNum).getImm() & 0xffff); 301223017Sdim return false; 302223017Sdim case 'M': { // A register range suitable for LDM/STM. 303223017Sdim if (!MI->getOperand(OpNum).isReg()) 304223017Sdim return true; 305223017Sdim const MachineOperand &MO = MI->getOperand(OpNum); 306223017Sdim unsigned RegBegin = MO.getReg(); 307223017Sdim // This takes advantage of the 2 operand-ness of ldm/stm and that we've 308223017Sdim // already got the operands in registers that are operands to the 309223017Sdim // inline asm statement. 310263508Sdim O << "{"; 311263508Sdim if (ARM::GPRPairRegClass.contains(RegBegin)) { 312263508Sdim const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); 313263508Sdim unsigned Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0); 314263508Sdim O << ARMInstPrinter::getRegisterName(Reg0) << ", ";; 315263508Sdim RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1); 316263508Sdim } 317263508Sdim O << ARMInstPrinter::getRegisterName(RegBegin); 318226633Sdim 319223017Sdim // FIXME: The register allocator not only may not have given us the 320223017Sdim // registers in sequence, but may not be in ascending registers. This 321223017Sdim // will require changes in the register allocator that'll need to be 322223017Sdim // propagated down here if the operands change. 323223017Sdim unsigned RegOps = OpNum + 1; 324223017Sdim while (MI->getOperand(RegOps).isReg()) { 325226633Sdim O << ", " 326223017Sdim << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg()); 327223017Sdim RegOps++; 328223017Sdim } 329223017Sdim 330223017Sdim O << "}"; 331223017Sdim 332223017Sdim return false; 333212793Sdim } 334226633Sdim case 'R': // The most significant register of a pair. 335226633Sdim case 'Q': { // The least significant register of a pair. 336226633Sdim if (OpNum == 0) 337226633Sdim return true; 338226633Sdim const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); 339226633Sdim if (!FlagsOP.isImm()) 340226633Sdim return true; 341226633Sdim unsigned Flags = FlagsOP.getImm(); 342263508Sdim 343263508Sdim // This operand may not be the one that actually provides the register. If 344263508Sdim // it's tied to a previous one then we should refer instead to that one 345263508Sdim // for registers and their classes. 346263508Sdim unsigned TiedIdx; 347263508Sdim if (InlineAsm::isUseOperandTiedToDef(Flags, TiedIdx)) { 348263508Sdim for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) { 349263508Sdim unsigned OpFlags = MI->getOperand(OpNum).getImm(); 350263508Sdim OpNum += InlineAsm::getNumOperandRegisters(OpFlags) + 1; 351263508Sdim } 352263508Sdim Flags = MI->getOperand(OpNum).getImm(); 353263508Sdim 354263508Sdim // Later code expects OpNum to be pointing at the register rather than 355263508Sdim // the flags. 356263508Sdim OpNum += 1; 357263508Sdim } 358263508Sdim 359226633Sdim unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); 360263508Sdim unsigned RC; 361263508Sdim InlineAsm::hasRegClassConstraint(Flags, RC); 362263508Sdim if (RC == ARM::GPRPairRegClassID) { 363263508Sdim if (NumVals != 1) 364263508Sdim return true; 365263508Sdim const MachineOperand &MO = MI->getOperand(OpNum); 366263508Sdim if (!MO.isReg()) 367263508Sdim return true; 368263508Sdim const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); 369263508Sdim unsigned Reg = TRI->getSubReg(MO.getReg(), ExtraCode[0] == 'Q' ? 370263508Sdim ARM::gsub_0 : ARM::gsub_1); 371263508Sdim O << ARMInstPrinter::getRegisterName(Reg); 372263508Sdim return false; 373263508Sdim } 374226633Sdim if (NumVals != 2) 375226633Sdim return true; 376226633Sdim unsigned RegOp = ExtraCode[0] == 'Q' ? OpNum : OpNum + 1; 377226633Sdim if (RegOp >= MI->getNumOperands()) 378226633Sdim return true; 379226633Sdim const MachineOperand &MO = MI->getOperand(RegOp); 380226633Sdim if (!MO.isReg()) 381226633Sdim return true; 382226633Sdim unsigned Reg = MO.getReg(); 383226633Sdim O << ARMInstPrinter::getRegisterName(Reg); 384226633Sdim return false; 385226633Sdim } 386226633Sdim 387234353Sdim case 'e': // The low doubleword register of a NEON quad register. 388234353Sdim case 'f': { // The high doubleword register of a NEON quad register. 389234353Sdim if (!MI->getOperand(OpNum).isReg()) 390234353Sdim return true; 391234353Sdim unsigned Reg = MI->getOperand(OpNum).getReg(); 392234353Sdim if (!ARM::QPRRegClass.contains(Reg)) 393234353Sdim return true; 394234353Sdim const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); 395234353Sdim unsigned SubReg = TRI->getSubReg(Reg, ExtraCode[0] == 'e' ? 396234353Sdim ARM::dsub_0 : ARM::dsub_1); 397234353Sdim O << ARMInstPrinter::getRegisterName(SubReg); 398234353Sdim return false; 399234353Sdim } 400234353Sdim 401239462Sdim // This modifier is not yet supported. 402223017Sdim case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1. 403223017Sdim return true; 404239462Sdim case 'H': { // The highest-numbered register of a pair. 405239462Sdim const MachineOperand &MO = MI->getOperand(OpNum); 406239462Sdim if (!MO.isReg()) 407239462Sdim return true; 408239462Sdim const MachineFunction &MF = *MI->getParent()->getParent(); 409239462Sdim const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); 410249423Sdim unsigned Reg = MO.getReg(); 411249423Sdim if(!ARM::GPRPairRegClass.contains(Reg)) 412249423Sdim return false; 413249423Sdim Reg = TRI->getSubReg(Reg, ARM::gsub_1); 414239462Sdim O << ARMInstPrinter::getRegisterName(Reg); 415239462Sdim return false; 416223017Sdim } 417239462Sdim } 418212793Sdim } 419212793Sdim 420212793Sdim printOperand(MI, OpNum, O); 421212793Sdim return false; 422212793Sdim} 423212793Sdim 424212793Sdimbool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 425212793Sdim unsigned OpNum, unsigned AsmVariant, 426212793Sdim const char *ExtraCode, 427212793Sdim raw_ostream &O) { 428223017Sdim // Does this asm operand have a single letter operand modifier? 429223017Sdim if (ExtraCode && ExtraCode[0]) { 430223017Sdim if (ExtraCode[1] != 0) return true; // Unknown modifier. 431226633Sdim 432223017Sdim switch (ExtraCode[0]) { 433223017Sdim case 'A': // A memory operand for a VLD1/VST1 instruction. 434223017Sdim default: return true; // Unknown modifier. 435223017Sdim case 'm': // The base register of a memory operand. 436223017Sdim if (!MI->getOperand(OpNum).isReg()) 437223017Sdim return true; 438223017Sdim O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg()); 439223017Sdim return false; 440223017Sdim } 441223017Sdim } 442226633Sdim 443212793Sdim const MachineOperand &MO = MI->getOperand(OpNum); 444212793Sdim assert(MO.isReg() && "unexpected inline asm memory operand"); 445218893Sdim O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]"; 446212793Sdim return false; 447212793Sdim} 448212793Sdim 449212793Sdimvoid ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { 450212793Sdim if (Subtarget->isTargetDarwin()) { 451212793Sdim Reloc::Model RelocM = TM.getRelocationModel(); 452212793Sdim if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) { 453212793Sdim // Declare all the text sections up front (before the DWARF sections 454212793Sdim // emitted by AsmPrinter::doInitialization) so the assembler will keep 455212793Sdim // them together at the beginning of the object file. This helps 456212793Sdim // avoid out-of-range branches that are due a fundamental limitation of 457212793Sdim // the way symbol offsets are encoded with the current Darwin ARM 458212793Sdim // relocations. 459212793Sdim const TargetLoweringObjectFileMachO &TLOFMacho = 460212793Sdim static_cast<const TargetLoweringObjectFileMachO &>( 461212793Sdim getObjFileLowering()); 462243830Sdim 463243830Sdim // Collect the set of sections our functions will go into. 464243830Sdim SetVector<const MCSection *, SmallVector<const MCSection *, 8>, 465243830Sdim SmallPtrSet<const MCSection *, 8> > TextSections; 466243830Sdim // Default text section comes first. 467243830Sdim TextSections.insert(TLOFMacho.getTextSection()); 468243830Sdim // Now any user defined text sections from function attributes. 469243830Sdim for (Module::iterator F = M.begin(), e = M.end(); F != e; ++F) 470243830Sdim if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage()) 471243830Sdim TextSections.insert(TLOFMacho.SectionForGlobal(F, Mang, TM)); 472243830Sdim // Now the coalescable sections. 473243830Sdim TextSections.insert(TLOFMacho.getTextCoalSection()); 474243830Sdim TextSections.insert(TLOFMacho.getConstTextCoalSection()); 475243830Sdim 476243830Sdim // Emit the sections in the .s file header to fix the order. 477243830Sdim for (unsigned i = 0, e = TextSections.size(); i != e; ++i) 478243830Sdim OutStreamer.SwitchSection(TextSections[i]); 479243830Sdim 480212793Sdim if (RelocM == Reloc::DynamicNoPIC) { 481212793Sdim const MCSection *sect = 482212793Sdim OutContext.getMachOSection("__TEXT", "__symbol_stub4", 483212793Sdim MCSectionMachO::S_SYMBOL_STUBS, 484212793Sdim 12, SectionKind::getText()); 485212793Sdim OutStreamer.SwitchSection(sect); 486212793Sdim } else { 487212793Sdim const MCSection *sect = 488212793Sdim OutContext.getMachOSection("__TEXT", "__picsymbolstub4", 489212793Sdim MCSectionMachO::S_SYMBOL_STUBS, 490212793Sdim 16, SectionKind::getText()); 491212793Sdim OutStreamer.SwitchSection(sect); 492212793Sdim } 493212793Sdim const MCSection *StaticInitSect = 494212793Sdim OutContext.getMachOSection("__TEXT", "__StaticInit", 495212793Sdim MCSectionMachO::S_REGULAR | 496212793Sdim MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 497212793Sdim SectionKind::getText()); 498212793Sdim OutStreamer.SwitchSection(StaticInitSect); 499212793Sdim } 500212793Sdim } 501212793Sdim 502212793Sdim // Use unified assembler syntax. 503218893Sdim OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified); 504212793Sdim 505212793Sdim // Emit ARM Build Attributes 506234353Sdim if (Subtarget->isTargetELF()) 507218893Sdim emitAttributes(); 508212793Sdim} 509212793Sdim 510212793Sdim 511212793Sdimvoid ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { 512212793Sdim if (Subtarget->isTargetDarwin()) { 513212793Sdim // All darwin targets use mach-o. 514212793Sdim const TargetLoweringObjectFileMachO &TLOFMacho = 515212793Sdim static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 516212793Sdim MachineModuleInfoMachO &MMIMacho = 517212793Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>(); 518212793Sdim 519212793Sdim // Output non-lazy-pointers for external and common global variables. 520212793Sdim MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); 521212793Sdim 522212793Sdim if (!Stubs.empty()) { 523212793Sdim // Switch with ".non_lazy_symbol_pointer" directive. 524212793Sdim OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); 525212793Sdim EmitAlignment(2); 526212793Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 527212793Sdim // L_foo$stub: 528212793Sdim OutStreamer.EmitLabel(Stubs[i].first); 529212793Sdim // .indirect_symbol _foo 530212793Sdim MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; 531212793Sdim OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol); 532212793Sdim 533212793Sdim if (MCSym.getInt()) 534212793Sdim // External to current translation unit. 535249423Sdim OutStreamer.EmitIntValue(0, 4/*size*/); 536212793Sdim else 537212793Sdim // Internal to current translation unit. 538212793Sdim // 539218893Sdim // When we place the LSDA into the TEXT section, the type info 540218893Sdim // pointers need to be indirect and pc-rel. We accomplish this by 541218893Sdim // using NLPs; however, sometimes the types are local to the file. 542218893Sdim // We need to fill in the value for the NLP in those cases. 543212793Sdim OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), 544212793Sdim OutContext), 545249423Sdim 4/*size*/); 546212793Sdim } 547212793Sdim 548212793Sdim Stubs.clear(); 549212793Sdim OutStreamer.AddBlankLine(); 550212793Sdim } 551212793Sdim 552212793Sdim Stubs = MMIMacho.GetHiddenGVStubList(); 553212793Sdim if (!Stubs.empty()) { 554212793Sdim OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 555212793Sdim EmitAlignment(2); 556212793Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 557212793Sdim // L_foo$stub: 558212793Sdim OutStreamer.EmitLabel(Stubs[i].first); 559212793Sdim // .long _foo 560212793Sdim OutStreamer.EmitValue(MCSymbolRefExpr:: 561212793Sdim Create(Stubs[i].second.getPointer(), 562212793Sdim OutContext), 563249423Sdim 4/*size*/); 564212793Sdim } 565212793Sdim 566212793Sdim Stubs.clear(); 567212793Sdim OutStreamer.AddBlankLine(); 568212793Sdim } 569212793Sdim 570212793Sdim // Funny Darwin hack: This flag tells the linker that no global symbols 571212793Sdim // contain code that falls through to other global symbols (e.g. the obvious 572212793Sdim // implementation of multiple entry points). If this doesn't occur, the 573212793Sdim // linker can safely perform dead code stripping. Since LLVM never 574212793Sdim // generates code that does this, it is always safe to set. 575212793Sdim OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 576212793Sdim } 577212793Sdim} 578212793Sdim 579212793Sdim//===----------------------------------------------------------------------===// 580218893Sdim// Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile() 581218893Sdim// FIXME: 582218893Sdim// The following seem like one-off assembler flags, but they actually need 583218893Sdim// to appear in the .ARM.attributes section in ELF. 584218893Sdim// Instead of subclassing the MCELFStreamer, we do the work here. 585212793Sdim 586263508Sdimstatic ARMBuildAttrs::CPUArch getArchForCPU(StringRef CPU, 587263508Sdim const ARMSubtarget *Subtarget) { 588263508Sdim if (CPU == "xscale") 589263508Sdim return ARMBuildAttrs::v5TEJ; 590218893Sdim 591263508Sdim if (Subtarget->hasV8Ops()) 592263508Sdim return ARMBuildAttrs::v8; 593263508Sdim else if (Subtarget->hasV7Ops()) { 594263508Sdim if (Subtarget->isMClass() && Subtarget->hasThumb2DSP()) 595263508Sdim return ARMBuildAttrs::v7E_M; 596263508Sdim return ARMBuildAttrs::v7; 597243830Sdim } else if (Subtarget->hasV6T2Ops()) 598263508Sdim return ARMBuildAttrs::v6T2; 599263508Sdim else if (Subtarget->hasV6MOps()) 600263508Sdim return ARMBuildAttrs::v6S_M; 601243830Sdim else if (Subtarget->hasV6Ops()) 602263508Sdim return ARMBuildAttrs::v6; 603243830Sdim else if (Subtarget->hasV5TEOps()) 604263508Sdim return ARMBuildAttrs::v5TE; 605243830Sdim else if (Subtarget->hasV5TOps()) 606263508Sdim return ARMBuildAttrs::v5T; 607243830Sdim else if (Subtarget->hasV4TOps()) 608263508Sdim return ARMBuildAttrs::v4T; 609263508Sdim else 610263508Sdim return ARMBuildAttrs::v4; 611263508Sdim} 612218893Sdim 613263508Sdimvoid ARMAsmPrinter::emitAttributes() { 614263508Sdim MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); 615263508Sdim ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); 616221345Sdim 617263508Sdim ATS.switchVendor("aeabi"); 618234353Sdim 619263508Sdim std::string CPUString = Subtarget->getCPUString(); 620221345Sdim 621263508Sdim if (CPUString != "generic") 622263508Sdim ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString); 623263508Sdim 624263508Sdim ATS.emitAttribute(ARMBuildAttrs::CPU_arch, 625263508Sdim getArchForCPU(CPUString, Subtarget)); 626263508Sdim 627263508Sdim if (Subtarget->isAClass()) { 628263508Sdim ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile, 629263508Sdim ARMBuildAttrs::ApplicationProfile); 630263508Sdim } else if (Subtarget->isRClass()) { 631263508Sdim ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile, 632263508Sdim ARMBuildAttrs::RealTimeProfile); 633263508Sdim } else if (Subtarget->isMClass()){ 634263508Sdim ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile, 635263508Sdim ARMBuildAttrs::MicroControllerProfile); 636221345Sdim } 637218893Sdim 638263508Sdim ATS.emitAttribute(ARMBuildAttrs::ARM_ISA_use, Subtarget->hasARMOps() ? 639263508Sdim ARMBuildAttrs::Allowed : ARMBuildAttrs::Not_Allowed); 640263508Sdim if (Subtarget->isThumb1Only()) { 641263508Sdim ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use, 642263508Sdim ARMBuildAttrs::Allowed); 643263508Sdim } else if (Subtarget->hasThumb2()) { 644263508Sdim ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use, 645263508Sdim ARMBuildAttrs::AllowThumb32); 646263508Sdim } 647263508Sdim 648221345Sdim if (Subtarget->hasNEON()) { 649263508Sdim /* NEON is not exactly a VFP architecture, but GAS emit one of 650263508Sdim * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */ 651263508Sdim if (Subtarget->hasFPARMv8()) { 652263508Sdim if (Subtarget->hasCrypto()) 653263508Sdim ATS.emitFPU(ARM::CRYPTO_NEON_FP_ARMV8); 654263508Sdim else 655263508Sdim ATS.emitFPU(ARM::NEON_FP_ARMV8); 656263508Sdim } 657263508Sdim else if (Subtarget->hasVFP4()) 658263508Sdim ATS.emitFPU(ARM::NEON_VFPV4); 659263508Sdim else 660263508Sdim ATS.emitFPU(ARM::NEON); 661263508Sdim // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture 662263508Sdim if (Subtarget->hasV8Ops()) 663263508Sdim ATS.emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch, 664263508Sdim ARMBuildAttrs::AllowNeonARMv8); 665263508Sdim } else { 666263508Sdim if (Subtarget->hasFPARMv8()) 667263508Sdim ATS.emitFPU(ARM::FP_ARMV8); 668263508Sdim else if (Subtarget->hasVFP4()) 669263508Sdim ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV4_D16 : ARM::VFPV4); 670263508Sdim else if (Subtarget->hasVFP3()) 671263508Sdim ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV3_D16 : ARM::VFPV3); 672263508Sdim else if (Subtarget->hasVFP2()) 673263508Sdim ATS.emitFPU(ARM::VFPV2); 674221345Sdim } 675221345Sdim 676218893Sdim // Signal various FP modes. 677234353Sdim if (!TM.Options.UnsafeFPMath) { 678263508Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, ARMBuildAttrs::Allowed); 679263508Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 680263508Sdim ARMBuildAttrs::Allowed); 681218893Sdim } 682218893Sdim 683234353Sdim if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath) 684263508Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 685263508Sdim ARMBuildAttrs::Allowed); 686218893Sdim else 687263508Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 688263508Sdim ARMBuildAttrs::AllowIEE754); 689218893Sdim 690218893Sdim // FIXME: add more flags to ARMBuildAttrs.h 691218893Sdim // 8-bytes alignment stuff. 692263508Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1); 693263508Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1); 694218893Sdim 695263508Sdim // ABI_HardFP_use attribute to indicate single precision FP. 696263508Sdim if (Subtarget->isFPOnlySP()) 697263508Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_HardFP_use, 698263508Sdim ARMBuildAttrs::HardFPSinglePrecision); 699263508Sdim 700218893Sdim // Hard float. Use both S and D registers and conform to AAPCS-VFP. 701263508Sdim if (Subtarget->isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard) 702263508Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS); 703263508Sdim 704218893Sdim // FIXME: Should we signal R9 usage? 705218893Sdim 706263508Sdim if (Subtarget->hasFP16()) 707263508Sdim ATS.emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP); 708218893Sdim 709263508Sdim if (Subtarget->hasMPExtension()) 710263508Sdim ATS.emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP); 711263508Sdim 712263508Sdim if (Subtarget->hasDivide()) { 713263508Sdim // Check if hardware divide is only available in thumb2 or ARM as well. 714263508Sdim ATS.emitAttribute(ARMBuildAttrs::DIV_use, 715263508Sdim Subtarget->hasDivideInARMMode() ? ARMBuildAttrs::AllowDIVExt : 716263508Sdim ARMBuildAttrs::AllowDIVIfExists); 717263508Sdim } 718263508Sdim 719263508Sdim if (Subtarget->hasTrustZone() && Subtarget->hasVirtualization()) 720263508Sdim ATS.emitAttribute(ARMBuildAttrs::Virtualization_use, 721263508Sdim ARMBuildAttrs::AllowTZVirtualization); 722263508Sdim else if (Subtarget->hasTrustZone()) 723263508Sdim ATS.emitAttribute(ARMBuildAttrs::Virtualization_use, 724263508Sdim ARMBuildAttrs::AllowTZ); 725263508Sdim else if (Subtarget->hasVirtualization()) 726263508Sdim ATS.emitAttribute(ARMBuildAttrs::Virtualization_use, 727263508Sdim ARMBuildAttrs::AllowVirtualization); 728263508Sdim 729263508Sdim ATS.finishAttributeSection(); 730218893Sdim} 731218893Sdim 732218893Sdimvoid ARMAsmPrinter::emitARMAttributeSection() { 733218893Sdim // <format-version> 734218893Sdim // [ <section-length> "vendor-name" 735218893Sdim // [ <file-tag> <size> <attribute>* 736218893Sdim // | <section-tag> <size> <section-number>* 0 <attribute>* 737218893Sdim // | <symbol-tag> <size> <symbol-number>* 0 <attribute>* 738218893Sdim // ]+ 739218893Sdim // ]* 740218893Sdim 741218893Sdim if (OutStreamer.hasRawTextSupport()) 742218893Sdim return; 743218893Sdim 744218893Sdim const ARMElfTargetObjectFile &TLOFELF = 745218893Sdim static_cast<const ARMElfTargetObjectFile &> 746218893Sdim (getObjFileLowering()); 747218893Sdim 748218893Sdim OutStreamer.SwitchSection(TLOFELF.getAttributesSection()); 749218893Sdim 750218893Sdim // Format version 751218893Sdim OutStreamer.EmitIntValue(0x41, 1); 752218893Sdim} 753218893Sdim 754218893Sdim//===----------------------------------------------------------------------===// 755218893Sdim 756218893Sdimstatic MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, 757218893Sdim unsigned LabelId, MCContext &Ctx) { 758218893Sdim 759218893Sdim MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix) 760218893Sdim + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); 761218893Sdim return Label; 762218893Sdim} 763218893Sdim 764218893Sdimstatic MCSymbolRefExpr::VariantKind 765218893SdimgetModifierVariantKind(ARMCP::ARMCPModifier Modifier) { 766218893Sdim switch (Modifier) { 767218893Sdim case ARMCP::no_modifier: return MCSymbolRefExpr::VK_None; 768218893Sdim case ARMCP::TLSGD: return MCSymbolRefExpr::VK_ARM_TLSGD; 769218893Sdim case ARMCP::TPOFF: return MCSymbolRefExpr::VK_ARM_TPOFF; 770218893Sdim case ARMCP::GOTTPOFF: return MCSymbolRefExpr::VK_ARM_GOTTPOFF; 771218893Sdim case ARMCP::GOT: return MCSymbolRefExpr::VK_ARM_GOT; 772218893Sdim case ARMCP::GOTOFF: return MCSymbolRefExpr::VK_ARM_GOTOFF; 773218893Sdim } 774234353Sdim llvm_unreachable("Invalid ARMCPModifier!"); 775218893Sdim} 776218893Sdim 777218893SdimMCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV) { 778218893Sdim bool isIndirect = Subtarget->isTargetDarwin() && 779218893Sdim Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel()); 780218893Sdim if (!isIndirect) 781263508Sdim return getSymbol(GV); 782218893Sdim 783218893Sdim // FIXME: Remove this when Darwin transition to @GOT like syntax. 784218893Sdim MCSymbol *MCSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 785218893Sdim MachineModuleInfoMachO &MMIMachO = 786218893Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>(); 787218893Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 788218893Sdim GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(MCSym) : 789218893Sdim MMIMachO.getGVStubEntry(MCSym); 790218893Sdim if (StubSym.getPointer() == 0) 791218893Sdim StubSym = MachineModuleInfoImpl:: 792263508Sdim StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); 793218893Sdim return MCSym; 794218893Sdim} 795218893Sdim 796218893Sdimvoid ARMAsmPrinter:: 797218893SdimEmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 798243830Sdim int Size = TM.getDataLayout()->getTypeAllocSize(MCPV->getType()); 799218893Sdim 800218893Sdim ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV); 801218893Sdim 802218893Sdim MCSymbol *MCSym; 803218893Sdim if (ACPV->isLSDA()) { 804218893Sdim SmallString<128> Str; 805218893Sdim raw_svector_ostream OS(Str); 806218893Sdim OS << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber(); 807218893Sdim MCSym = OutContext.GetOrCreateSymbol(OS.str()); 808218893Sdim } else if (ACPV->isBlockAddress()) { 809226633Sdim const BlockAddress *BA = 810226633Sdim cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress(); 811226633Sdim MCSym = GetBlockAddressSymbol(BA); 812218893Sdim } else if (ACPV->isGlobalValue()) { 813226633Sdim const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV(); 814218893Sdim MCSym = GetARMGVSymbol(GV); 815226633Sdim } else if (ACPV->isMachineBasicBlock()) { 816226633Sdim const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB(); 817226633Sdim MCSym = MBB->getSymbol(); 818218893Sdim } else { 819218893Sdim assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); 820226633Sdim const char *Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol(); 821226633Sdim MCSym = GetExternalSymbolSymbol(Sym); 822218893Sdim } 823218893Sdim 824218893Sdim // Create an MCSymbol for the reference. 825218893Sdim const MCExpr *Expr = 826218893Sdim MCSymbolRefExpr::Create(MCSym, getModifierVariantKind(ACPV->getModifier()), 827218893Sdim OutContext); 828218893Sdim 829218893Sdim if (ACPV->getPCAdjustment()) { 830218893Sdim MCSymbol *PCLabel = getPICLabel(MAI->getPrivateGlobalPrefix(), 831218893Sdim getFunctionNumber(), 832218893Sdim ACPV->getLabelId(), 833218893Sdim OutContext); 834218893Sdim const MCExpr *PCRelExpr = MCSymbolRefExpr::Create(PCLabel, OutContext); 835218893Sdim PCRelExpr = 836218893Sdim MCBinaryExpr::CreateAdd(PCRelExpr, 837218893Sdim MCConstantExpr::Create(ACPV->getPCAdjustment(), 838218893Sdim OutContext), 839218893Sdim OutContext); 840218893Sdim if (ACPV->mustAddCurrentAddress()) { 841218893Sdim // We want "(<expr> - .)", but MC doesn't have a concept of the '.' 842218893Sdim // label, so just emit a local label end reference that instead. 843218893Sdim MCSymbol *DotSym = OutContext.CreateTempSymbol(); 844218893Sdim OutStreamer.EmitLabel(DotSym); 845218893Sdim const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext); 846218893Sdim PCRelExpr = MCBinaryExpr::CreateSub(PCRelExpr, DotExpr, OutContext); 847218893Sdim } 848218893Sdim Expr = MCBinaryExpr::CreateSub(Expr, PCRelExpr, OutContext); 849218893Sdim } 850218893Sdim OutStreamer.EmitValue(Expr, Size); 851218893Sdim} 852218893Sdim 853218893Sdimvoid ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) { 854218893Sdim unsigned Opcode = MI->getOpcode(); 855218893Sdim int OpNum = 1; 856218893Sdim if (Opcode == ARM::BR_JTadd) 857218893Sdim OpNum = 2; 858218893Sdim else if (Opcode == ARM::BR_JTm) 859218893Sdim OpNum = 3; 860218893Sdim 861218893Sdim const MachineOperand &MO1 = MI->getOperand(OpNum); 862218893Sdim const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 863218893Sdim unsigned JTI = MO1.getIndex(); 864218893Sdim 865218893Sdim // Emit a label for the jump table. 866218893Sdim MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 867218893Sdim OutStreamer.EmitLabel(JTISymbol); 868218893Sdim 869239462Sdim // Mark the jump table as data-in-code. 870239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionJT32); 871239462Sdim 872218893Sdim // Emit each entry of the table. 873218893Sdim const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 874218893Sdim const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 875218893Sdim const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 876218893Sdim 877218893Sdim for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 878218893Sdim MachineBasicBlock *MBB = JTBBs[i]; 879218893Sdim // Construct an MCExpr for the entry. We want a value of the form: 880218893Sdim // (BasicBlockAddr - TableBeginAddr) 881218893Sdim // 882218893Sdim // For example, a table with entries jumping to basic blocks BB0 and BB1 883218893Sdim // would look like: 884218893Sdim // LJTI_0_0: 885218893Sdim // .word (LBB0 - LJTI_0_0) 886218893Sdim // .word (LBB1 - LJTI_0_0) 887218893Sdim const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); 888218893Sdim 889218893Sdim if (TM.getRelocationModel() == Reloc::PIC_) 890218893Sdim Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol, 891218893Sdim OutContext), 892218893Sdim OutContext); 893226633Sdim // If we're generating a table of Thumb addresses in static relocation 894226633Sdim // model, we need to add one to keep interworking correctly. 895226633Sdim else if (AFI->isThumbFunction()) 896226633Sdim Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(1,OutContext), 897226633Sdim OutContext); 898218893Sdim OutStreamer.EmitValue(Expr, 4); 899218893Sdim } 900239462Sdim // Mark the end of jump table data-in-code region. 901239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 902218893Sdim} 903218893Sdim 904218893Sdimvoid ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { 905218893Sdim unsigned Opcode = MI->getOpcode(); 906218893Sdim int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1; 907218893Sdim const MachineOperand &MO1 = MI->getOperand(OpNum); 908218893Sdim const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 909218893Sdim unsigned JTI = MO1.getIndex(); 910218893Sdim 911218893Sdim MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 912218893Sdim OutStreamer.EmitLabel(JTISymbol); 913218893Sdim 914218893Sdim // Emit each entry of the table. 915218893Sdim const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 916218893Sdim const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 917218893Sdim const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 918218893Sdim unsigned OffsetWidth = 4; 919239462Sdim if (MI->getOpcode() == ARM::t2TBB_JT) { 920218893Sdim OffsetWidth = 1; 921239462Sdim // Mark the jump table as data-in-code. 922239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionJT8); 923239462Sdim } else if (MI->getOpcode() == ARM::t2TBH_JT) { 924218893Sdim OffsetWidth = 2; 925239462Sdim // Mark the jump table as data-in-code. 926239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionJT16); 927239462Sdim } 928218893Sdim 929218893Sdim for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 930218893Sdim MachineBasicBlock *MBB = JTBBs[i]; 931218893Sdim const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(), 932218893Sdim OutContext); 933218893Sdim // If this isn't a TBB or TBH, the entries are direct branch instructions. 934218893Sdim if (OffsetWidth == 4) { 935249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2B) 936249423Sdim .addExpr(MBBSymbolExpr) 937249423Sdim .addImm(ARMCC::AL) 938249423Sdim .addReg(0)); 939218893Sdim continue; 940218893Sdim } 941218893Sdim // Otherwise it's an offset from the dispatch instruction. Construct an 942218893Sdim // MCExpr for the entry. We want a value of the form: 943218893Sdim // (BasicBlockAddr - TableBeginAddr) / 2 944218893Sdim // 945218893Sdim // For example, a TBB table with entries jumping to basic blocks BB0 and BB1 946218893Sdim // would look like: 947218893Sdim // LJTI_0_0: 948218893Sdim // .byte (LBB0 - LJTI_0_0) / 2 949218893Sdim // .byte (LBB1 - LJTI_0_0) / 2 950218893Sdim const MCExpr *Expr = 951218893Sdim MCBinaryExpr::CreateSub(MBBSymbolExpr, 952218893Sdim MCSymbolRefExpr::Create(JTISymbol, OutContext), 953218893Sdim OutContext); 954218893Sdim Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext), 955218893Sdim OutContext); 956218893Sdim OutStreamer.EmitValue(Expr, OffsetWidth); 957218893Sdim } 958239462Sdim // Mark the end of jump table data-in-code region. 32-bit offsets use 959239462Sdim // actual branch instructions here, so we don't mark those as a data-region 960239462Sdim // at all. 961239462Sdim if (OffsetWidth != 4) 962239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 963218893Sdim} 964218893Sdim 965221345Sdimvoid ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { 966221345Sdim assert(MI->getFlag(MachineInstr::FrameSetup) && 967221345Sdim "Only instruction which are involved into frame setup code are allowed"); 968221345Sdim 969263508Sdim MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); 970263508Sdim ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); 971221345Sdim const MachineFunction &MF = *MI->getParent()->getParent(); 972221345Sdim const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); 973221345Sdim const ARMFunctionInfo &AFI = *MF.getInfo<ARMFunctionInfo>(); 974221345Sdim 975221345Sdim unsigned FramePtr = RegInfo->getFrameRegister(MF); 976221345Sdim unsigned Opc = MI->getOpcode(); 977221345Sdim unsigned SrcReg, DstReg; 978221345Sdim 979221345Sdim if (Opc == ARM::tPUSH || Opc == ARM::tLDRpci) { 980221345Sdim // Two special cases: 981221345Sdim // 1) tPUSH does not have src/dst regs. 982221345Sdim // 2) for Thumb1 code we sometimes materialize the constant via constpool 983221345Sdim // load. Yes, this is pretty fragile, but for now I don't see better 984221345Sdim // way... :( 985221345Sdim SrcReg = DstReg = ARM::SP; 986221345Sdim } else { 987221345Sdim SrcReg = MI->getOperand(1).getReg(); 988221345Sdim DstReg = MI->getOperand(0).getReg(); 989221345Sdim } 990221345Sdim 991221345Sdim // Try to figure out the unwinding opcode out of src / dst regs. 992234353Sdim if (MI->mayStore()) { 993221345Sdim // Register saves. 994221345Sdim assert(DstReg == ARM::SP && 995221345Sdim "Only stack pointer as a destination reg is supported"); 996221345Sdim 997221345Sdim SmallVector<unsigned, 4> RegList; 998221345Sdim // Skip src & dst reg, and pred ops. 999221345Sdim unsigned StartOp = 2 + 2; 1000221345Sdim // Use all the operands. 1001221345Sdim unsigned NumOffset = 0; 1002221345Sdim 1003221345Sdim switch (Opc) { 1004221345Sdim default: 1005221345Sdim MI->dump(); 1006234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1007221345Sdim case ARM::tPUSH: 1008221345Sdim // Special case here: no src & dst reg, but two extra imp ops. 1009221345Sdim StartOp = 2; NumOffset = 2; 1010221345Sdim case ARM::STMDB_UPD: 1011221345Sdim case ARM::t2STMDB_UPD: 1012221345Sdim case ARM::VSTMDDB_UPD: 1013221345Sdim assert(SrcReg == ARM::SP && 1014221345Sdim "Only stack pointer as a source reg is supported"); 1015221345Sdim for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset; 1016239462Sdim i != NumOps; ++i) { 1017239462Sdim const MachineOperand &MO = MI->getOperand(i); 1018239462Sdim // Actually, there should never be any impdef stuff here. Skip it 1019239462Sdim // temporary to workaround PR11902. 1020239462Sdim if (MO.isImplicit()) 1021239462Sdim continue; 1022239462Sdim RegList.push_back(MO.getReg()); 1023239462Sdim } 1024221345Sdim break; 1025226633Sdim case ARM::STR_PRE_IMM: 1026226633Sdim case ARM::STR_PRE_REG: 1027234353Sdim case ARM::t2STR_PRE: 1028221345Sdim assert(MI->getOperand(2).getReg() == ARM::SP && 1029221345Sdim "Only stack pointer as a source reg is supported"); 1030221345Sdim RegList.push_back(SrcReg); 1031221345Sdim break; 1032221345Sdim } 1033263508Sdim ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD); 1034221345Sdim } else { 1035221345Sdim // Changes of stack / frame pointer. 1036221345Sdim if (SrcReg == ARM::SP) { 1037221345Sdim int64_t Offset = 0; 1038221345Sdim switch (Opc) { 1039221345Sdim default: 1040221345Sdim MI->dump(); 1041234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1042221345Sdim case ARM::MOVr: 1043234353Sdim case ARM::tMOVr: 1044221345Sdim Offset = 0; 1045221345Sdim break; 1046221345Sdim case ARM::ADDri: 1047221345Sdim Offset = -MI->getOperand(2).getImm(); 1048221345Sdim break; 1049221345Sdim case ARM::SUBri: 1050234353Sdim case ARM::t2SUBri: 1051224145Sdim Offset = MI->getOperand(2).getImm(); 1052221345Sdim break; 1053221345Sdim case ARM::tSUBspi: 1054224145Sdim Offset = MI->getOperand(2).getImm()*4; 1055221345Sdim break; 1056221345Sdim case ARM::tADDspi: 1057221345Sdim case ARM::tADDrSPi: 1058221345Sdim Offset = -MI->getOperand(2).getImm()*4; 1059221345Sdim break; 1060221345Sdim case ARM::tLDRpci: { 1061221345Sdim // Grab the constpool index and check, whether it corresponds to 1062221345Sdim // original or cloned constpool entry. 1063221345Sdim unsigned CPI = MI->getOperand(1).getIndex(); 1064221345Sdim const MachineConstantPool *MCP = MF.getConstantPool(); 1065221345Sdim if (CPI >= MCP->getConstants().size()) 1066221345Sdim CPI = AFI.getOriginalCPIdx(CPI); 1067221345Sdim assert(CPI != -1U && "Invalid constpool index"); 1068221345Sdim 1069221345Sdim // Derive the actual offset. 1070221345Sdim const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI]; 1071221345Sdim assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry"); 1072221345Sdim // FIXME: Check for user, it should be "add" instruction! 1073221345Sdim Offset = -cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue(); 1074221345Sdim break; 1075221345Sdim } 1076221345Sdim } 1077221345Sdim 1078221345Sdim if (DstReg == FramePtr && FramePtr != ARM::SP) 1079221345Sdim // Set-up of the frame pointer. Positive values correspond to "add" 1080221345Sdim // instruction. 1081263508Sdim ATS.emitSetFP(FramePtr, ARM::SP, -Offset); 1082221345Sdim else if (DstReg == ARM::SP) { 1083221345Sdim // Change of SP by an offset. Positive values correspond to "sub" 1084221345Sdim // instruction. 1085263508Sdim ATS.emitPad(Offset); 1086221345Sdim } else { 1087221345Sdim MI->dump(); 1088234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1089221345Sdim } 1090221345Sdim } else if (DstReg == ARM::SP) { 1091221345Sdim // FIXME: .movsp goes here 1092221345Sdim MI->dump(); 1093234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1094221345Sdim } 1095221345Sdim else { 1096221345Sdim MI->dump(); 1097234353Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1098221345Sdim } 1099221345Sdim } 1100221345Sdim} 1101221345Sdim 1102221345Sdimextern cl::opt<bool> EnableARMEHABI; 1103221345Sdim 1104224145Sdim// Simple pseudo-instructions have their lowering (with expansion to real 1105224145Sdim// instructions) auto-generated. 1106224145Sdim#include "ARMGenMCPseudoLowering.inc" 1107224145Sdim 1108218893Sdimvoid ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { 1109239462Sdim // If we just ended a constant pool, mark it as such. 1110239462Sdim if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) { 1111239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 1112239462Sdim InConstantPool = false; 1113239462Sdim } 1114226633Sdim 1115226633Sdim // Emit unwinding stuff for frame-related instructions 1116226633Sdim if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup)) 1117226633Sdim EmitUnwindingInstruction(MI); 1118226633Sdim 1119224145Sdim // Do any auto-generated pseudo lowerings. 1120224145Sdim if (emitPseudoExpansionLowering(OutStreamer, MI)) 1121224145Sdim return; 1122224145Sdim 1123226633Sdim assert(!convertAddSubFlagsOpcode(MI->getOpcode()) && 1124226633Sdim "Pseudo flag setting opcode should be expanded early"); 1125226633Sdim 1126224145Sdim // Check for manual lowerings. 1127218893Sdim unsigned Opc = MI->getOpcode(); 1128218893Sdim switch (Opc) { 1129234353Sdim case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass"); 1130263508Sdim case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing"); 1131218893Sdim case ARM::LEApcrel: 1132218893Sdim case ARM::tLEApcrel: 1133218893Sdim case ARM::t2LEApcrel: { 1134218893Sdim // FIXME: Need to also handle globals and externals 1135249423Sdim MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex()); 1136249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() == 1137249423Sdim ARM::t2LEApcrel ? ARM::t2ADR 1138249423Sdim : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR 1139249423Sdim : ARM::ADR)) 1140249423Sdim .addReg(MI->getOperand(0).getReg()) 1141249423Sdim .addExpr(MCSymbolRefExpr::Create(CPISymbol, OutContext)) 1142249423Sdim // Add predicate operands. 1143249423Sdim .addImm(MI->getOperand(2).getImm()) 1144249423Sdim .addReg(MI->getOperand(3).getReg())); 1145218893Sdim return; 1146218893Sdim } 1147218893Sdim case ARM::LEApcrelJT: 1148218893Sdim case ARM::tLEApcrelJT: 1149218893Sdim case ARM::t2LEApcrelJT: { 1150249423Sdim MCSymbol *JTIPICSymbol = 1151249423Sdim GetARMJTIPICJumpTableLabel2(MI->getOperand(1).getIndex(), 1152249423Sdim MI->getOperand(2).getImm()); 1153249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() == 1154249423Sdim ARM::t2LEApcrelJT ? ARM::t2ADR 1155249423Sdim : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR 1156249423Sdim : ARM::ADR)) 1157249423Sdim .addReg(MI->getOperand(0).getReg()) 1158249423Sdim .addExpr(MCSymbolRefExpr::Create(JTIPICSymbol, OutContext)) 1159249423Sdim // Add predicate operands. 1160249423Sdim .addImm(MI->getOperand(3).getImm()) 1161249423Sdim .addReg(MI->getOperand(4).getReg())); 1162218893Sdim return; 1163218893Sdim } 1164221345Sdim // Darwin call instructions are just normal call instructions with different 1165221345Sdim // clobber semantics (they clobber R9). 1166218893Sdim case ARM::BX_CALL: { 1167249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1168249423Sdim .addReg(ARM::LR) 1169249423Sdim .addReg(ARM::PC) 1170218893Sdim // Add predicate operands. 1171249423Sdim .addImm(ARMCC::AL) 1172249423Sdim .addReg(0) 1173218893Sdim // Add 's' bit operand (always reg0 for this) 1174249423Sdim .addReg(0)); 1175249423Sdim 1176249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX) 1177249423Sdim .addReg(MI->getOperand(0).getReg())); 1178218893Sdim return; 1179218893Sdim } 1180223017Sdim case ARM::tBX_CALL: { 1181249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1182249423Sdim .addReg(ARM::LR) 1183249423Sdim .addReg(ARM::PC) 1184224145Sdim // Add predicate operands. 1185249423Sdim .addImm(ARMCC::AL) 1186249423Sdim .addReg(0)); 1187249423Sdim 1188249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX) 1189249423Sdim .addReg(MI->getOperand(0).getReg()) 1190223017Sdim // Add predicate operands. 1191249423Sdim .addImm(ARMCC::AL) 1192249423Sdim .addReg(0)); 1193223017Sdim return; 1194223017Sdim } 1195218893Sdim case ARM::BMOVPCRX_CALL: { 1196249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1197249423Sdim .addReg(ARM::LR) 1198249423Sdim .addReg(ARM::PC) 1199218893Sdim // Add predicate operands. 1200249423Sdim .addImm(ARMCC::AL) 1201249423Sdim .addReg(0) 1202218893Sdim // Add 's' bit operand (always reg0 for this) 1203249423Sdim .addReg(0)); 1204249423Sdim 1205249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1206249423Sdim .addReg(ARM::PC) 1207249423Sdim .addReg(MI->getOperand(0).getReg()) 1208218893Sdim // Add predicate operands. 1209249423Sdim .addImm(ARMCC::AL) 1210249423Sdim .addReg(0) 1211218893Sdim // Add 's' bit operand (always reg0 for this) 1212249423Sdim .addReg(0)); 1213218893Sdim return; 1214218893Sdim } 1215234353Sdim case ARM::BMOVPCB_CALL: { 1216249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1217249423Sdim .addReg(ARM::LR) 1218249423Sdim .addReg(ARM::PC) 1219234353Sdim // Add predicate operands. 1220249423Sdim .addImm(ARMCC::AL) 1221249423Sdim .addReg(0) 1222234353Sdim // Add 's' bit operand (always reg0 for this) 1223249423Sdim .addReg(0)); 1224249423Sdim 1225249423Sdim const GlobalValue *GV = MI->getOperand(0).getGlobal(); 1226263508Sdim MCSymbol *GVSym = getSymbol(GV); 1227249423Sdim const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext); 1228249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::Bcc) 1229249423Sdim .addExpr(GVSymExpr) 1230234353Sdim // Add predicate operands. 1231249423Sdim .addImm(ARMCC::AL) 1232249423Sdim .addReg(0)); 1233234353Sdim return; 1234234353Sdim } 1235218893Sdim case ARM::MOVi16_ga_pcrel: 1236218893Sdim case ARM::t2MOVi16_ga_pcrel: { 1237218893Sdim MCInst TmpInst; 1238218893Sdim TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16); 1239218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1240218893Sdim 1241218893Sdim unsigned TF = MI->getOperand(1).getTargetFlags(); 1242218893Sdim bool isPIC = TF == ARMII::MO_LO16_NONLAZY_PIC; 1243218893Sdim const GlobalValue *GV = MI->getOperand(1).getGlobal(); 1244218893Sdim MCSymbol *GVSym = GetARMGVSymbol(GV); 1245218893Sdim const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext); 1246218893Sdim if (isPIC) { 1247218893Sdim MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(), 1248218893Sdim getFunctionNumber(), 1249218893Sdim MI->getOperand(2).getImm(), OutContext); 1250218893Sdim const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext); 1251218893Sdim unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4; 1252218893Sdim const MCExpr *PCRelExpr = 1253218893Sdim ARMMCExpr::CreateLower16(MCBinaryExpr::CreateSub(GVSymExpr, 1254218893Sdim MCBinaryExpr::CreateAdd(LabelSymExpr, 1255218893Sdim MCConstantExpr::Create(PCAdj, OutContext), 1256218893Sdim OutContext), OutContext), OutContext); 1257218893Sdim TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr)); 1258218893Sdim } else { 1259218893Sdim const MCExpr *RefExpr= ARMMCExpr::CreateLower16(GVSymExpr, OutContext); 1260218893Sdim TmpInst.addOperand(MCOperand::CreateExpr(RefExpr)); 1261218893Sdim } 1262218893Sdim 1263218893Sdim // Add predicate operands. 1264218893Sdim TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1265218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1266218893Sdim // Add 's' bit operand (always reg0 for this) 1267218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1268218893Sdim OutStreamer.EmitInstruction(TmpInst); 1269218893Sdim return; 1270218893Sdim } 1271218893Sdim case ARM::MOVTi16_ga_pcrel: 1272218893Sdim case ARM::t2MOVTi16_ga_pcrel: { 1273218893Sdim MCInst TmpInst; 1274218893Sdim TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel 1275218893Sdim ? ARM::MOVTi16 : ARM::t2MOVTi16); 1276218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1277218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); 1278218893Sdim 1279218893Sdim unsigned TF = MI->getOperand(2).getTargetFlags(); 1280218893Sdim bool isPIC = TF == ARMII::MO_HI16_NONLAZY_PIC; 1281218893Sdim const GlobalValue *GV = MI->getOperand(2).getGlobal(); 1282218893Sdim MCSymbol *GVSym = GetARMGVSymbol(GV); 1283218893Sdim const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext); 1284218893Sdim if (isPIC) { 1285218893Sdim MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(), 1286218893Sdim getFunctionNumber(), 1287218893Sdim MI->getOperand(3).getImm(), OutContext); 1288218893Sdim const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext); 1289218893Sdim unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4; 1290218893Sdim const MCExpr *PCRelExpr = 1291218893Sdim ARMMCExpr::CreateUpper16(MCBinaryExpr::CreateSub(GVSymExpr, 1292218893Sdim MCBinaryExpr::CreateAdd(LabelSymExpr, 1293218893Sdim MCConstantExpr::Create(PCAdj, OutContext), 1294218893Sdim OutContext), OutContext), OutContext); 1295218893Sdim TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr)); 1296218893Sdim } else { 1297218893Sdim const MCExpr *RefExpr= ARMMCExpr::CreateUpper16(GVSymExpr, OutContext); 1298218893Sdim TmpInst.addOperand(MCOperand::CreateExpr(RefExpr)); 1299218893Sdim } 1300218893Sdim // Add predicate operands. 1301218893Sdim TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1302218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1303218893Sdim // Add 's' bit operand (always reg0 for this) 1304218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1305218893Sdim OutStreamer.EmitInstruction(TmpInst); 1306218893Sdim return; 1307218893Sdim } 1308218893Sdim case ARM::tPICADD: { 1309212793Sdim // This is a pseudo op for a label + instruction sequence, which looks like: 1310212793Sdim // LPC0: 1311218893Sdim // add r0, pc 1312218893Sdim // This adds the address of LPC0 to r0. 1313218893Sdim 1314218893Sdim // Emit the label. 1315218893Sdim OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 1316218893Sdim getFunctionNumber(), MI->getOperand(2).getImm(), 1317218893Sdim OutContext)); 1318218893Sdim 1319218893Sdim // Form and emit the add. 1320249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDhirr) 1321249423Sdim .addReg(MI->getOperand(0).getReg()) 1322249423Sdim .addReg(MI->getOperand(0).getReg()) 1323249423Sdim .addReg(ARM::PC) 1324249423Sdim // Add predicate operands. 1325249423Sdim .addImm(ARMCC::AL) 1326249423Sdim .addReg(0)); 1327218893Sdim return; 1328218893Sdim } 1329218893Sdim case ARM::PICADD: { 1330218893Sdim // This is a pseudo op for a label + instruction sequence, which looks like: 1331218893Sdim // LPC0: 1332212793Sdim // add r0, pc, r0 1333212793Sdim // This adds the address of LPC0 to r0. 1334212793Sdim 1335212793Sdim // Emit the label. 1336218893Sdim OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 1337218893Sdim getFunctionNumber(), MI->getOperand(2).getImm(), 1338218893Sdim OutContext)); 1339212793Sdim 1340218893Sdim // Form and emit the add. 1341249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr) 1342249423Sdim .addReg(MI->getOperand(0).getReg()) 1343249423Sdim .addReg(ARM::PC) 1344249423Sdim .addReg(MI->getOperand(1).getReg()) 1345249423Sdim // Add predicate operands. 1346249423Sdim .addImm(MI->getOperand(3).getImm()) 1347249423Sdim .addReg(MI->getOperand(4).getReg()) 1348249423Sdim // Add 's' bit operand (always reg0 for this) 1349249423Sdim .addReg(0)); 1350212793Sdim return; 1351212793Sdim } 1352218893Sdim case ARM::PICSTR: 1353218893Sdim case ARM::PICSTRB: 1354218893Sdim case ARM::PICSTRH: 1355218893Sdim case ARM::PICLDR: 1356218893Sdim case ARM::PICLDRB: 1357218893Sdim case ARM::PICLDRH: 1358218893Sdim case ARM::PICLDRSB: 1359218893Sdim case ARM::PICLDRSH: { 1360218893Sdim // This is a pseudo op for a label + instruction sequence, which looks like: 1361218893Sdim // LPC0: 1362218893Sdim // OP r0, [pc, r0] 1363218893Sdim // The LCP0 label is referenced by a constant pool entry in order to get 1364218893Sdim // a PC-relative address at the ldr instruction. 1365218893Sdim 1366218893Sdim // Emit the label. 1367218893Sdim OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 1368218893Sdim getFunctionNumber(), MI->getOperand(2).getImm(), 1369218893Sdim OutContext)); 1370218893Sdim 1371218893Sdim // Form and emit the load 1372218893Sdim unsigned Opcode; 1373218893Sdim switch (MI->getOpcode()) { 1374218893Sdim default: 1375218893Sdim llvm_unreachable("Unexpected opcode!"); 1376218893Sdim case ARM::PICSTR: Opcode = ARM::STRrs; break; 1377218893Sdim case ARM::PICSTRB: Opcode = ARM::STRBrs; break; 1378218893Sdim case ARM::PICSTRH: Opcode = ARM::STRH; break; 1379218893Sdim case ARM::PICLDR: Opcode = ARM::LDRrs; break; 1380218893Sdim case ARM::PICLDRB: Opcode = ARM::LDRBrs; break; 1381218893Sdim case ARM::PICLDRH: Opcode = ARM::LDRH; break; 1382218893Sdim case ARM::PICLDRSB: Opcode = ARM::LDRSB; break; 1383218893Sdim case ARM::PICLDRSH: Opcode = ARM::LDRSH; break; 1384218893Sdim } 1385249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(Opcode) 1386249423Sdim .addReg(MI->getOperand(0).getReg()) 1387249423Sdim .addReg(ARM::PC) 1388249423Sdim .addReg(MI->getOperand(1).getReg()) 1389249423Sdim .addImm(0) 1390249423Sdim // Add predicate operands. 1391249423Sdim .addImm(MI->getOperand(3).getImm()) 1392249423Sdim .addReg(MI->getOperand(4).getReg())); 1393218893Sdim 1394218893Sdim return; 1395218893Sdim } 1396218893Sdim case ARM::CONSTPOOL_ENTRY: { 1397212793Sdim /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool 1398212793Sdim /// in the function. The first operand is the ID# for this instruction, the 1399212793Sdim /// second is the index into the MachineConstantPool that this is, the third 1400212793Sdim /// is the size in bytes of this constant pool entry. 1401234353Sdim /// The required alignment is specified on the basic block holding this MI. 1402212793Sdim unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); 1403212793Sdim unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); 1404212793Sdim 1405239462Sdim // If this is the first entry of the pool, mark it. 1406239462Sdim if (!InConstantPool) { 1407239462Sdim OutStreamer.EmitDataRegion(MCDR_DataRegion); 1408239462Sdim InConstantPool = true; 1409239462Sdim } 1410239462Sdim 1411212793Sdim OutStreamer.EmitLabel(GetCPISymbol(LabelId)); 1412212793Sdim 1413212793Sdim const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; 1414212793Sdim if (MCPE.isMachineConstantPoolEntry()) 1415212793Sdim EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 1416212793Sdim else 1417212793Sdim EmitGlobalConstant(MCPE.Val.ConstVal); 1418212793Sdim return; 1419212793Sdim } 1420218893Sdim case ARM::t2BR_JT: { 1421218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1422249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1423249423Sdim .addReg(ARM::PC) 1424249423Sdim .addReg(MI->getOperand(0).getReg()) 1425249423Sdim // Add predicate operands. 1426249423Sdim .addImm(ARMCC::AL) 1427249423Sdim .addReg(0)); 1428249423Sdim 1429218893Sdim // Output the data for the jump table itself 1430218893Sdim EmitJump2Table(MI); 1431218893Sdim return; 1432218893Sdim } 1433218893Sdim case ARM::t2TBB_JT: { 1434218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1435249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBB) 1436249423Sdim .addReg(ARM::PC) 1437249423Sdim .addReg(MI->getOperand(0).getReg()) 1438249423Sdim // Add predicate operands. 1439249423Sdim .addImm(ARMCC::AL) 1440249423Sdim .addReg(0)); 1441212793Sdim 1442218893Sdim // Output the data for the jump table itself 1443218893Sdim EmitJump2Table(MI); 1444218893Sdim // Make sure the next instruction is 2-byte aligned. 1445218893Sdim EmitAlignment(1); 1446218893Sdim return; 1447218893Sdim } 1448218893Sdim case ARM::t2TBH_JT: { 1449218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1450249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBH) 1451249423Sdim .addReg(ARM::PC) 1452249423Sdim .addReg(MI->getOperand(0).getReg()) 1453249423Sdim // Add predicate operands. 1454249423Sdim .addImm(ARMCC::AL) 1455249423Sdim .addReg(0)); 1456212793Sdim 1457218893Sdim // Output the data for the jump table itself 1458218893Sdim EmitJump2Table(MI); 1459218893Sdim return; 1460218893Sdim } 1461218893Sdim case ARM::tBR_JTr: 1462218893Sdim case ARM::BR_JTr: { 1463218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1464218893Sdim // mov pc, target 1465218893Sdim MCInst TmpInst; 1466218893Sdim unsigned Opc = MI->getOpcode() == ARM::BR_JTr ? 1467224145Sdim ARM::MOVr : ARM::tMOVr; 1468218893Sdim TmpInst.setOpcode(Opc); 1469218893Sdim TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1470218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1471218893Sdim // Add predicate operands. 1472218893Sdim TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1473218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1474218893Sdim // Add 's' bit operand (always reg0 for this) 1475218893Sdim if (Opc == ARM::MOVr) 1476218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1477218893Sdim OutStreamer.EmitInstruction(TmpInst); 1478212793Sdim 1479218893Sdim // Make sure the Thumb jump table is 4-byte aligned. 1480224145Sdim if (Opc == ARM::tMOVr) 1481218893Sdim EmitAlignment(2); 1482218893Sdim 1483218893Sdim // Output the data for the jump table itself 1484218893Sdim EmitJumpTable(MI); 1485218893Sdim return; 1486218893Sdim } 1487218893Sdim case ARM::BR_JTm: { 1488218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1489218893Sdim // ldr pc, target 1490218893Sdim MCInst TmpInst; 1491218893Sdim if (MI->getOperand(1).getReg() == 0) { 1492218893Sdim // literal offset 1493218893Sdim TmpInst.setOpcode(ARM::LDRi12); 1494218893Sdim TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1495218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1496212793Sdim TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1497218893Sdim } else { 1498218893Sdim TmpInst.setOpcode(ARM::LDRrs); 1499218893Sdim TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1500218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1501218893Sdim TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); 1502218893Sdim TmpInst.addOperand(MCOperand::CreateImm(0)); 1503218893Sdim } 1504218893Sdim // Add predicate operands. 1505218893Sdim TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1506218893Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); 1507218893Sdim OutStreamer.EmitInstruction(TmpInst); 1508212793Sdim 1509218893Sdim // Output the data for the jump table itself 1510218893Sdim EmitJumpTable(MI); 1511218893Sdim return; 1512218893Sdim } 1513218893Sdim case ARM::BR_JTadd: { 1514218893Sdim // Lower and emit the instruction itself, then the jump table following it. 1515218893Sdim // add pc, target, idx 1516249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr) 1517249423Sdim .addReg(ARM::PC) 1518249423Sdim .addReg(MI->getOperand(0).getReg()) 1519249423Sdim .addReg(MI->getOperand(1).getReg()) 1520249423Sdim // Add predicate operands. 1521249423Sdim .addImm(ARMCC::AL) 1522249423Sdim .addReg(0) 1523249423Sdim // Add 's' bit operand (always reg0 for this) 1524249423Sdim .addReg(0)); 1525218893Sdim 1526218893Sdim // Output the data for the jump table itself 1527218893Sdim EmitJumpTable(MI); 1528218893Sdim return; 1529218893Sdim } 1530218893Sdim case ARM::TRAP: { 1531218893Sdim // Non-Darwin binutils don't yet support the "trap" mnemonic. 1532218893Sdim // FIXME: Remove this special case when they do. 1533218893Sdim if (!Subtarget->isTargetDarwin()) { 1534218893Sdim //.long 0xe7ffdefe @ trap 1535218893Sdim uint32_t Val = 0xe7ffdefeUL; 1536218893Sdim OutStreamer.AddComment("trap"); 1537218893Sdim OutStreamer.EmitIntValue(Val, 4); 1538218893Sdim return; 1539218893Sdim } 1540218893Sdim break; 1541218893Sdim } 1542249423Sdim case ARM::TRAPNaCl: { 1543249423Sdim //.long 0xe7fedef0 @ trap 1544249423Sdim uint32_t Val = 0xe7fedef0UL; 1545249423Sdim OutStreamer.AddComment("trap"); 1546249423Sdim OutStreamer.EmitIntValue(Val, 4); 1547249423Sdim return; 1548249423Sdim } 1549218893Sdim case ARM::tTRAP: { 1550218893Sdim // Non-Darwin binutils don't yet support the "trap" mnemonic. 1551218893Sdim // FIXME: Remove this special case when they do. 1552218893Sdim if (!Subtarget->isTargetDarwin()) { 1553218893Sdim //.short 57086 @ trap 1554218893Sdim uint16_t Val = 0xdefe; 1555218893Sdim OutStreamer.AddComment("trap"); 1556218893Sdim OutStreamer.EmitIntValue(Val, 2); 1557218893Sdim return; 1558218893Sdim } 1559218893Sdim break; 1560218893Sdim } 1561218893Sdim case ARM::t2Int_eh_sjlj_setjmp: 1562218893Sdim case ARM::t2Int_eh_sjlj_setjmp_nofp: 1563218893Sdim case ARM::tInt_eh_sjlj_setjmp: { 1564218893Sdim // Two incoming args: GPR:$src, GPR:$val 1565218893Sdim // mov $val, pc 1566218893Sdim // adds $val, #7 1567218893Sdim // str $val, [$src, #4] 1568218893Sdim // movs r0, #0 1569218893Sdim // b 1f 1570218893Sdim // movs r0, #1 1571218893Sdim // 1: 1572218893Sdim unsigned SrcReg = MI->getOperand(0).getReg(); 1573218893Sdim unsigned ValReg = MI->getOperand(1).getReg(); 1574218893Sdim MCSymbol *Label = GetARMSJLJEHLabel(); 1575249423Sdim OutStreamer.AddComment("eh_setjmp begin"); 1576249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1577249423Sdim .addReg(ValReg) 1578249423Sdim .addReg(ARM::PC) 1579224145Sdim // Predicate. 1580249423Sdim .addImm(ARMCC::AL) 1581249423Sdim .addReg(0)); 1582249423Sdim 1583249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDi3) 1584249423Sdim .addReg(ValReg) 1585218893Sdim // 's' bit operand 1586249423Sdim .addReg(ARM::CPSR) 1587249423Sdim .addReg(ValReg) 1588249423Sdim .addImm(7) 1589218893Sdim // Predicate. 1590249423Sdim .addImm(ARMCC::AL) 1591249423Sdim .addReg(0)); 1592249423Sdim 1593249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tSTRi) 1594249423Sdim .addReg(ValReg) 1595249423Sdim .addReg(SrcReg) 1596218893Sdim // The offset immediate is #4. The operand value is scaled by 4 for the 1597218893Sdim // tSTR instruction. 1598249423Sdim .addImm(1) 1599218893Sdim // Predicate. 1600249423Sdim .addImm(ARMCC::AL) 1601249423Sdim .addReg(0)); 1602249423Sdim 1603249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8) 1604249423Sdim .addReg(ARM::R0) 1605249423Sdim .addReg(ARM::CPSR) 1606249423Sdim .addImm(0) 1607218893Sdim // Predicate. 1608249423Sdim .addImm(ARMCC::AL) 1609249423Sdim .addReg(0)); 1610249423Sdim 1611249423Sdim const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext); 1612249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tB) 1613249423Sdim .addExpr(SymbolExpr) 1614249423Sdim .addImm(ARMCC::AL) 1615249423Sdim .addReg(0)); 1616249423Sdim 1617249423Sdim OutStreamer.AddComment("eh_setjmp end"); 1618249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8) 1619249423Sdim .addReg(ARM::R0) 1620249423Sdim .addReg(ARM::CPSR) 1621249423Sdim .addImm(1) 1622218893Sdim // Predicate. 1623249423Sdim .addImm(ARMCC::AL) 1624249423Sdim .addReg(0)); 1625249423Sdim 1626218893Sdim OutStreamer.EmitLabel(Label); 1627218893Sdim return; 1628218893Sdim } 1629212793Sdim 1630218893Sdim case ARM::Int_eh_sjlj_setjmp_nofp: 1631218893Sdim case ARM::Int_eh_sjlj_setjmp: { 1632218893Sdim // Two incoming args: GPR:$src, GPR:$val 1633218893Sdim // add $val, pc, #8 1634218893Sdim // str $val, [$src, #+4] 1635218893Sdim // mov r0, #0 1636218893Sdim // add pc, pc, #0 1637218893Sdim // mov r0, #1 1638218893Sdim unsigned SrcReg = MI->getOperand(0).getReg(); 1639218893Sdim unsigned ValReg = MI->getOperand(1).getReg(); 1640218893Sdim 1641249423Sdim OutStreamer.AddComment("eh_setjmp begin"); 1642249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri) 1643249423Sdim .addReg(ValReg) 1644249423Sdim .addReg(ARM::PC) 1645249423Sdim .addImm(8) 1646212793Sdim // Predicate. 1647249423Sdim .addImm(ARMCC::AL) 1648249423Sdim .addReg(0) 1649218893Sdim // 's' bit operand (always reg0 for this). 1650249423Sdim .addReg(0)); 1651249423Sdim 1652249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::STRi12) 1653249423Sdim .addReg(ValReg) 1654249423Sdim .addReg(SrcReg) 1655249423Sdim .addImm(4) 1656218893Sdim // Predicate. 1657249423Sdim .addImm(ARMCC::AL) 1658249423Sdim .addReg(0)); 1659249423Sdim 1660249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi) 1661249423Sdim .addReg(ARM::R0) 1662249423Sdim .addImm(0) 1663218893Sdim // Predicate. 1664249423Sdim .addImm(ARMCC::AL) 1665249423Sdim .addReg(0) 1666218893Sdim // 's' bit operand (always reg0 for this). 1667249423Sdim .addReg(0)); 1668249423Sdim 1669249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri) 1670249423Sdim .addReg(ARM::PC) 1671249423Sdim .addReg(ARM::PC) 1672249423Sdim .addImm(0) 1673218893Sdim // Predicate. 1674249423Sdim .addImm(ARMCC::AL) 1675249423Sdim .addReg(0) 1676218893Sdim // 's' bit operand (always reg0 for this). 1677249423Sdim .addReg(0)); 1678249423Sdim 1679249423Sdim OutStreamer.AddComment("eh_setjmp end"); 1680249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi) 1681249423Sdim .addReg(ARM::R0) 1682249423Sdim .addImm(1) 1683218893Sdim // Predicate. 1684249423Sdim .addImm(ARMCC::AL) 1685249423Sdim .addReg(0) 1686218893Sdim // 's' bit operand (always reg0 for this). 1687249423Sdim .addReg(0)); 1688212793Sdim return; 1689212793Sdim } 1690218893Sdim case ARM::Int_eh_sjlj_longjmp: { 1691218893Sdim // ldr sp, [$src, #8] 1692218893Sdim // ldr $scratch, [$src, #4] 1693218893Sdim // ldr r7, [$src] 1694218893Sdim // bx $scratch 1695218893Sdim unsigned SrcReg = MI->getOperand(0).getReg(); 1696218893Sdim unsigned ScratchReg = MI->getOperand(1).getReg(); 1697249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12) 1698249423Sdim .addReg(ARM::SP) 1699249423Sdim .addReg(SrcReg) 1700249423Sdim .addImm(8) 1701218893Sdim // Predicate. 1702249423Sdim .addImm(ARMCC::AL) 1703249423Sdim .addReg(0)); 1704249423Sdim 1705249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12) 1706249423Sdim .addReg(ScratchReg) 1707249423Sdim .addReg(SrcReg) 1708249423Sdim .addImm(4) 1709212793Sdim // Predicate. 1710249423Sdim .addImm(ARMCC::AL) 1711249423Sdim .addReg(0)); 1712249423Sdim 1713249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12) 1714249423Sdim .addReg(ARM::R7) 1715249423Sdim .addReg(SrcReg) 1716249423Sdim .addImm(0) 1717212793Sdim // Predicate. 1718249423Sdim .addImm(ARMCC::AL) 1719249423Sdim .addReg(0)); 1720249423Sdim 1721249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX) 1722249423Sdim .addReg(ScratchReg) 1723218893Sdim // Predicate. 1724249423Sdim .addImm(ARMCC::AL) 1725249423Sdim .addReg(0)); 1726212793Sdim return; 1727212793Sdim } 1728218893Sdim case ARM::tInt_eh_sjlj_longjmp: { 1729218893Sdim // ldr $scratch, [$src, #8] 1730218893Sdim // mov sp, $scratch 1731218893Sdim // ldr $scratch, [$src, #4] 1732218893Sdim // ldr r7, [$src] 1733218893Sdim // bx $scratch 1734218893Sdim unsigned SrcReg = MI->getOperand(0).getReg(); 1735218893Sdim unsigned ScratchReg = MI->getOperand(1).getReg(); 1736249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi) 1737249423Sdim .addReg(ScratchReg) 1738249423Sdim .addReg(SrcReg) 1739218893Sdim // The offset immediate is #8. The operand value is scaled by 4 for the 1740218893Sdim // tLDR instruction. 1741249423Sdim .addImm(2) 1742218893Sdim // Predicate. 1743249423Sdim .addImm(ARMCC::AL) 1744249423Sdim .addReg(0)); 1745249423Sdim 1746249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1747249423Sdim .addReg(ARM::SP) 1748249423Sdim .addReg(ScratchReg) 1749218893Sdim // Predicate. 1750249423Sdim .addImm(ARMCC::AL) 1751249423Sdim .addReg(0)); 1752249423Sdim 1753249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi) 1754249423Sdim .addReg(ScratchReg) 1755249423Sdim .addReg(SrcReg) 1756249423Sdim .addImm(1) 1757218893Sdim // Predicate. 1758249423Sdim .addImm(ARMCC::AL) 1759249423Sdim .addReg(0)); 1760249423Sdim 1761249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi) 1762249423Sdim .addReg(ARM::R7) 1763249423Sdim .addReg(SrcReg) 1764249423Sdim .addImm(0) 1765218893Sdim // Predicate. 1766249423Sdim .addImm(ARMCC::AL) 1767249423Sdim .addReg(0)); 1768249423Sdim 1769249423Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX) 1770249423Sdim .addReg(ScratchReg) 1771218893Sdim // Predicate. 1772249423Sdim .addImm(ARMCC::AL) 1773249423Sdim .addReg(0)); 1774218893Sdim return; 1775212793Sdim } 1776221345Sdim } 1777221345Sdim 1778212793Sdim MCInst TmpInst; 1779218893Sdim LowerARMMachineInstrToMCInst(MI, TmpInst, *this); 1780221345Sdim 1781212793Sdim OutStreamer.EmitInstruction(TmpInst); 1782212793Sdim} 1783212793Sdim 1784212793Sdim//===----------------------------------------------------------------------===// 1785212793Sdim// Target Registry Stuff 1786212793Sdim//===----------------------------------------------------------------------===// 1787212793Sdim 1788212793Sdim// Force static initialization. 1789212793Sdimextern "C" void LLVMInitializeARMAsmPrinter() { 1790212793Sdim RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); 1791212793Sdim RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); 1792212793Sdim} 1793