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" 16235633Sdim#include "ARMAsmPrinter.h" 17212793Sdim#include "ARM.h" 18212793Sdim#include "ARMBuildAttrs.h" 19212793Sdim#include "ARMConstantPoolValue.h" 20263509Sdim#include "ARMFPUName.h" 21212793Sdim#include "ARMMachineFunctionInfo.h" 22212793Sdim#include "ARMTargetMachine.h" 23218893Sdim#include "ARMTargetObjectFile.h" 24218893Sdim#include "InstPrinter/ARMInstPrinter.h" 25226890Sdim#include "MCTargetDesc/ARMAddressingModes.h" 26226890Sdim#include "MCTargetDesc/ARMMCExpr.h" 27245431Sdim#include "llvm/ADT/SetVector.h" 28245431Sdim#include "llvm/ADT/SmallString.h" 29212793Sdim#include "llvm/Assembly/Writer.h" 30212793Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 31212793Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h" 32252723Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h" 33252723Sdim#include "llvm/DebugInfo.h" 34252723Sdim#include "llvm/IR/Constants.h" 35252723Sdim#include "llvm/IR/DataLayout.h" 36252723Sdim#include "llvm/IR/Module.h" 37252723Sdim#include "llvm/IR/Type.h" 38212793Sdim#include "llvm/MC/MCAsmInfo.h" 39218893Sdim#include "llvm/MC/MCAssembler.h" 40212793Sdim#include "llvm/MC/MCContext.h" 41252723Sdim#include "llvm/MC/MCELFStreamer.h" 42212793Sdim#include "llvm/MC/MCInst.h" 43252723Sdim#include "llvm/MC/MCInstBuilder.h" 44252723Sdim#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" 50252723Sdim#include "llvm/Support/ELF.h" 51212793Sdim#include "llvm/Support/ErrorHandling.h" 52226890Sdim#include "llvm/Support/TargetRegistry.h" 53212793Sdim#include "llvm/Support/raw_ostream.h" 54252723Sdim#include "llvm/Target/Mangler.h" 55252723Sdim#include "llvm/Target/TargetMachine.h" 56212793Sdim#include <cctype> 57212793Sdimusing namespace llvm; 58212793Sdim 59221345Sdim/// EmitDwarfRegOp - Emit dwarf register operation. 60263509Sdimvoid ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc, 61263509Sdim bool Indirect) const { 62221345Sdim const TargetRegisterInfo *RI = TM.getRegisterInfo(); 63263509Sdim if (RI->getDwarfRegNum(MLoc.getReg(), false) != -1) { 64263509Sdim AsmPrinter::EmitDwarfRegOp(MLoc, Indirect); 65263509Sdim return; 66263509Sdim } 67263509Sdim assert(MLoc.isReg() && !Indirect && 68263509Sdim "This doesn't support offset/indirection - implement it if needed"); 69263509Sdim unsigned Reg = MLoc.getReg(); 70263509Sdim if (Reg >= ARM::S0 && Reg <= ARM::S31) { 71263509Sdim assert(ARM::S0 + 31 == ARM::S31 && "Unexpected ARM S register numbering"); 72263509Sdim // S registers are described as bit-pieces of a register 73263509Sdim // S[2x] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 0) 74263509Sdim // S[2x+1] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 32) 75226890Sdim 76263509Sdim unsigned SReg = Reg - ARM::S0; 77263509Sdim bool odd = SReg & 0x1; 78263509Sdim unsigned Rx = 256 + (SReg >> 1); 79221345Sdim 80263509Sdim OutStreamer.AddComment("DW_OP_regx for S register"); 81263509Sdim EmitInt8(dwarf::DW_OP_regx); 82221345Sdim 83263509Sdim OutStreamer.AddComment(Twine(SReg)); 84263509Sdim EmitULEB128(Rx); 85221345Sdim 86263509Sdim if (odd) { 87263509Sdim OutStreamer.AddComment("DW_OP_bit_piece 32 32"); 88263509Sdim EmitInt8(dwarf::DW_OP_bit_piece); 89263509Sdim EmitULEB128(32); 90263509Sdim EmitULEB128(32); 91263509Sdim } else { 92263509Sdim OutStreamer.AddComment("DW_OP_bit_piece 32 0"); 93263509Sdim EmitInt8(dwarf::DW_OP_bit_piece); 94263509Sdim EmitULEB128(32); 95263509Sdim EmitULEB128(0); 96263509Sdim } 97263509Sdim } else if (Reg >= ARM::Q0 && Reg <= ARM::Q15) { 98263509Sdim assert(ARM::Q0 + 15 == ARM::Q15 && "Unexpected ARM Q register numbering"); 99263509Sdim // Q registers Q0-Q15 are described by composing two D registers together. 100263509Sdim // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1) 101263509Sdim // DW_OP_piece(8) 102221345Sdim 103263509Sdim unsigned QReg = Reg - ARM::Q0; 104263509Sdim unsigned D1 = 256 + 2 * QReg; 105263509Sdim unsigned D2 = D1 + 1; 106226890Sdim 107263509Sdim OutStreamer.AddComment("DW_OP_regx for Q register: D1"); 108263509Sdim EmitInt8(dwarf::DW_OP_regx); 109263509Sdim EmitULEB128(D1); 110263509Sdim OutStreamer.AddComment("DW_OP_piece 8"); 111263509Sdim EmitInt8(dwarf::DW_OP_piece); 112263509Sdim EmitULEB128(8); 113221345Sdim 114263509Sdim OutStreamer.AddComment("DW_OP_regx for Q register: D2"); 115263509Sdim EmitInt8(dwarf::DW_OP_regx); 116263509Sdim EmitULEB128(D2); 117263509Sdim OutStreamer.AddComment("DW_OP_piece 8"); 118263509Sdim EmitInt8(dwarf::DW_OP_piece); 119263509Sdim EmitULEB128(8); 120221345Sdim } 121221345Sdim} 122221345Sdim 123245431Sdimvoid ARMAsmPrinter::EmitFunctionBodyEnd() { 124245431Sdim // Make sure to terminate any constant pools that were at the end 125245431Sdim // of the function. 126245431Sdim if (!InConstantPool) 127245431Sdim return; 128245431Sdim InConstantPool = false; 129245431Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 130245431Sdim} 131245431Sdim 132212793Sdimvoid ARMAsmPrinter::EmitFunctionEntryLabel() { 133212793Sdim if (AFI->isThumbFunction()) { 134218893Sdim OutStreamer.EmitAssemblerFlag(MCAF_Code16); 135223017Sdim OutStreamer.EmitThumbFunc(CurrentFnSym); 136212793Sdim } 137212793Sdim 138212793Sdim OutStreamer.EmitLabel(CurrentFnSym); 139212793Sdim} 140212793Sdim 141235633Sdimvoid ARMAsmPrinter::EmitXXStructor(const Constant *CV) { 142245431Sdim uint64_t Size = TM.getDataLayout()->getTypeAllocSize(CV->getType()); 143235633Sdim assert(Size && "C++ constructor pointer had zero size!"); 144235633Sdim 145235633Sdim const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts()); 146235633Sdim assert(GV && "C++ constructor pointer was not a GlobalValue!"); 147235633Sdim 148263509Sdim const MCExpr *E = MCSymbolRefExpr::Create(getSymbol(GV), 149235633Sdim (Subtarget->isTargetDarwin() 150235633Sdim ? MCSymbolRefExpr::VK_None 151235633Sdim : MCSymbolRefExpr::VK_ARM_TARGET1), 152235633Sdim OutContext); 153235633Sdim 154235633Sdim OutStreamer.EmitValue(E, Size); 155235633Sdim} 156235633Sdim 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()) { 173235633Sdim 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!"); 178252723Sdim if(ARM::GPRPairRegClass.contains(Reg)) { 179252723Sdim const MachineFunction &MF = *MI->getParent()->getParent(); 180252723Sdim const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); 181252723Sdim Reg = TRI->getSubReg(Reg, ARM::gsub_0); 182252723Sdim } 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:"; 209263509Sdim 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 242252723SdimMCSymbol *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]) { 257245431Sdim default: 258245431Sdim // See if this is a generic print operand 259245431Sdim 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(); 281245431Sdim // Find the 'd' register that has this 's' register as a sub-register, 282245431Sdim // and determine the lane number. 283245431Sdim for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) { 284245431Sdim if (!ARM::DPRRegClass.contains(*SR)) 285245431Sdim continue; 286245431Sdim bool Lane0 = TRI->getSubReg(*SR, ARM::ssub_0) == Reg; 287245431Sdim O << ARMInstPrinter::getRegisterName(*SR) << (Lane0 ? "[0]" : "[1]"); 288245431Sdim return false; 289245431Sdim } 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. 310263509Sdim O << "{"; 311263509Sdim if (ARM::GPRPairRegClass.contains(RegBegin)) { 312263509Sdim const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); 313263509Sdim unsigned Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0); 314263509Sdim O << ARMInstPrinter::getRegisterName(Reg0) << ", ";; 315263509Sdim RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1); 316263509Sdim } 317263509Sdim O << ARMInstPrinter::getRegisterName(RegBegin); 318226890Sdim 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()) { 325226890Sdim O << ", " 326223017Sdim << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg()); 327223017Sdim RegOps++; 328223017Sdim } 329223017Sdim 330223017Sdim O << "}"; 331223017Sdim 332223017Sdim return false; 333212793Sdim } 334226890Sdim case 'R': // The most significant register of a pair. 335226890Sdim case 'Q': { // The least significant register of a pair. 336226890Sdim if (OpNum == 0) 337226890Sdim return true; 338226890Sdim const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); 339226890Sdim if (!FlagsOP.isImm()) 340226890Sdim return true; 341226890Sdim unsigned Flags = FlagsOP.getImm(); 342263509Sdim 343263509Sdim // This operand may not be the one that actually provides the register. If 344263509Sdim // it's tied to a previous one then we should refer instead to that one 345263509Sdim // for registers and their classes. 346263509Sdim unsigned TiedIdx; 347263509Sdim if (InlineAsm::isUseOperandTiedToDef(Flags, TiedIdx)) { 348263509Sdim for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) { 349263509Sdim unsigned OpFlags = MI->getOperand(OpNum).getImm(); 350263509Sdim OpNum += InlineAsm::getNumOperandRegisters(OpFlags) + 1; 351263509Sdim } 352263509Sdim Flags = MI->getOperand(OpNum).getImm(); 353263509Sdim 354263509Sdim // Later code expects OpNum to be pointing at the register rather than 355263509Sdim // the flags. 356263509Sdim OpNum += 1; 357263509Sdim } 358263509Sdim 359226890Sdim unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); 360263509Sdim unsigned RC; 361263509Sdim InlineAsm::hasRegClassConstraint(Flags, RC); 362263509Sdim if (RC == ARM::GPRPairRegClassID) { 363263509Sdim if (NumVals != 1) 364263509Sdim return true; 365263509Sdim const MachineOperand &MO = MI->getOperand(OpNum); 366263509Sdim if (!MO.isReg()) 367263509Sdim return true; 368263509Sdim const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); 369263509Sdim unsigned Reg = TRI->getSubReg(MO.getReg(), ExtraCode[0] == 'Q' ? 370263509Sdim ARM::gsub_0 : ARM::gsub_1); 371263509Sdim O << ARMInstPrinter::getRegisterName(Reg); 372263509Sdim return false; 373263509Sdim } 374226890Sdim if (NumVals != 2) 375226890Sdim return true; 376226890Sdim unsigned RegOp = ExtraCode[0] == 'Q' ? OpNum : OpNum + 1; 377226890Sdim if (RegOp >= MI->getNumOperands()) 378226890Sdim return true; 379226890Sdim const MachineOperand &MO = MI->getOperand(RegOp); 380226890Sdim if (!MO.isReg()) 381226890Sdim return true; 382226890Sdim unsigned Reg = MO.getReg(); 383226890Sdim O << ARMInstPrinter::getRegisterName(Reg); 384226890Sdim return false; 385226890Sdim } 386226890Sdim 387235633Sdim case 'e': // The low doubleword register of a NEON quad register. 388235633Sdim case 'f': { // The high doubleword register of a NEON quad register. 389235633Sdim if (!MI->getOperand(OpNum).isReg()) 390235633Sdim return true; 391235633Sdim unsigned Reg = MI->getOperand(OpNum).getReg(); 392235633Sdim if (!ARM::QPRRegClass.contains(Reg)) 393235633Sdim return true; 394235633Sdim const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); 395235633Sdim unsigned SubReg = TRI->getSubReg(Reg, ExtraCode[0] == 'e' ? 396235633Sdim ARM::dsub_0 : ARM::dsub_1); 397235633Sdim O << ARMInstPrinter::getRegisterName(SubReg); 398235633Sdim return false; 399235633Sdim } 400235633Sdim 401245431Sdim // This modifier is not yet supported. 402223017Sdim case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1. 403223017Sdim return true; 404245431Sdim case 'H': { // The highest-numbered register of a pair. 405245431Sdim const MachineOperand &MO = MI->getOperand(OpNum); 406245431Sdim if (!MO.isReg()) 407245431Sdim return true; 408245431Sdim const MachineFunction &MF = *MI->getParent()->getParent(); 409245431Sdim const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); 410252723Sdim unsigned Reg = MO.getReg(); 411252723Sdim if(!ARM::GPRPairRegClass.contains(Reg)) 412252723Sdim return false; 413252723Sdim Reg = TRI->getSubReg(Reg, ARM::gsub_1); 414245431Sdim O << ARMInstPrinter::getRegisterName(Reg); 415245431Sdim return false; 416223017Sdim } 417245431Sdim } 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. 431226890Sdim 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 } 442226890Sdim 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()); 462245431Sdim 463245431Sdim // Collect the set of sections our functions will go into. 464245431Sdim SetVector<const MCSection *, SmallVector<const MCSection *, 8>, 465245431Sdim SmallPtrSet<const MCSection *, 8> > TextSections; 466245431Sdim // Default text section comes first. 467245431Sdim TextSections.insert(TLOFMacho.getTextSection()); 468245431Sdim // Now any user defined text sections from function attributes. 469245431Sdim for (Module::iterator F = M.begin(), e = M.end(); F != e; ++F) 470245431Sdim if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage()) 471245431Sdim TextSections.insert(TLOFMacho.SectionForGlobal(F, Mang, TM)); 472245431Sdim // Now the coalescable sections. 473245431Sdim TextSections.insert(TLOFMacho.getTextCoalSection()); 474245431Sdim TextSections.insert(TLOFMacho.getConstTextCoalSection()); 475245431Sdim 476245431Sdim // Emit the sections in the .s file header to fix the order. 477245431Sdim for (unsigned i = 0, e = TextSections.size(); i != e; ++i) 478245431Sdim OutStreamer.SwitchSection(TextSections[i]); 479245431Sdim 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 506235633Sdim 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. 535252723Sdim 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), 545252723Sdim 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), 563252723Sdim 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 586263509Sdimstatic ARMBuildAttrs::CPUArch getArchForCPU(StringRef CPU, 587263509Sdim const ARMSubtarget *Subtarget) { 588263509Sdim if (CPU == "xscale") 589263509Sdim return ARMBuildAttrs::v5TEJ; 590218893Sdim 591263509Sdim if (Subtarget->hasV8Ops()) 592263509Sdim return ARMBuildAttrs::v8; 593263509Sdim else if (Subtarget->hasV7Ops()) { 594263509Sdim if (Subtarget->isMClass() && Subtarget->hasThumb2DSP()) 595263509Sdim return ARMBuildAttrs::v7E_M; 596263509Sdim return ARMBuildAttrs::v7; 597245431Sdim } else if (Subtarget->hasV6T2Ops()) 598263509Sdim return ARMBuildAttrs::v6T2; 599263509Sdim else if (Subtarget->hasV6MOps()) 600263509Sdim return ARMBuildAttrs::v6S_M; 601245431Sdim else if (Subtarget->hasV6Ops()) 602263509Sdim return ARMBuildAttrs::v6; 603245431Sdim else if (Subtarget->hasV5TEOps()) 604263509Sdim return ARMBuildAttrs::v5TE; 605245431Sdim else if (Subtarget->hasV5TOps()) 606263509Sdim return ARMBuildAttrs::v5T; 607245431Sdim else if (Subtarget->hasV4TOps()) 608263509Sdim return ARMBuildAttrs::v4T; 609263509Sdim else 610263509Sdim return ARMBuildAttrs::v4; 611263509Sdim} 612218893Sdim 613263509Sdimvoid ARMAsmPrinter::emitAttributes() { 614263509Sdim MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); 615263509Sdim ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); 616221345Sdim 617263509Sdim ATS.switchVendor("aeabi"); 618235633Sdim 619263509Sdim std::string CPUString = Subtarget->getCPUString(); 620221345Sdim 621263509Sdim if (CPUString != "generic") 622263509Sdim ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString); 623263509Sdim 624263509Sdim ATS.emitAttribute(ARMBuildAttrs::CPU_arch, 625263509Sdim getArchForCPU(CPUString, Subtarget)); 626263509Sdim 627263509Sdim if (Subtarget->isAClass()) { 628263509Sdim ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile, 629263509Sdim ARMBuildAttrs::ApplicationProfile); 630263509Sdim } else if (Subtarget->isRClass()) { 631263509Sdim ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile, 632263509Sdim ARMBuildAttrs::RealTimeProfile); 633263509Sdim } else if (Subtarget->isMClass()){ 634263509Sdim ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile, 635263509Sdim ARMBuildAttrs::MicroControllerProfile); 636221345Sdim } 637218893Sdim 638263509Sdim ATS.emitAttribute(ARMBuildAttrs::ARM_ISA_use, Subtarget->hasARMOps() ? 639263509Sdim ARMBuildAttrs::Allowed : ARMBuildAttrs::Not_Allowed); 640263509Sdim if (Subtarget->isThumb1Only()) { 641263509Sdim ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use, 642263509Sdim ARMBuildAttrs::Allowed); 643263509Sdim } else if (Subtarget->hasThumb2()) { 644263509Sdim ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use, 645263509Sdim ARMBuildAttrs::AllowThumb32); 646263509Sdim } 647263509Sdim 648221345Sdim if (Subtarget->hasNEON()) { 649263509Sdim /* NEON is not exactly a VFP architecture, but GAS emit one of 650263509Sdim * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */ 651263509Sdim if (Subtarget->hasFPARMv8()) { 652263509Sdim if (Subtarget->hasCrypto()) 653263509Sdim ATS.emitFPU(ARM::CRYPTO_NEON_FP_ARMV8); 654263509Sdim else 655263509Sdim ATS.emitFPU(ARM::NEON_FP_ARMV8); 656263509Sdim } 657263509Sdim else if (Subtarget->hasVFP4()) 658263509Sdim ATS.emitFPU(ARM::NEON_VFPV4); 659263509Sdim else 660263509Sdim ATS.emitFPU(ARM::NEON); 661263509Sdim // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture 662263509Sdim if (Subtarget->hasV8Ops()) 663263509Sdim ATS.emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch, 664263509Sdim ARMBuildAttrs::AllowNeonARMv8); 665263509Sdim } else { 666263509Sdim if (Subtarget->hasFPARMv8()) 667263509Sdim ATS.emitFPU(ARM::FP_ARMV8); 668263509Sdim else if (Subtarget->hasVFP4()) 669263509Sdim ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV4_D16 : ARM::VFPV4); 670263509Sdim else if (Subtarget->hasVFP3()) 671263509Sdim ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV3_D16 : ARM::VFPV3); 672263509Sdim else if (Subtarget->hasVFP2()) 673263509Sdim ATS.emitFPU(ARM::VFPV2); 674221345Sdim } 675221345Sdim 676218893Sdim // Signal various FP modes. 677235633Sdim if (!TM.Options.UnsafeFPMath) { 678263509Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, ARMBuildAttrs::Allowed); 679263509Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 680263509Sdim ARMBuildAttrs::Allowed); 681218893Sdim } 682218893Sdim 683235633Sdim if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath) 684263509Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 685263509Sdim ARMBuildAttrs::Allowed); 686218893Sdim else 687263509Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 688263509Sdim ARMBuildAttrs::AllowIEE754); 689218893Sdim 690218893Sdim // FIXME: add more flags to ARMBuildAttrs.h 691218893Sdim // 8-bytes alignment stuff. 692263509Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1); 693263509Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1); 694218893Sdim 695263509Sdim // ABI_HardFP_use attribute to indicate single precision FP. 696263509Sdim if (Subtarget->isFPOnlySP()) 697263509Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_HardFP_use, 698263509Sdim ARMBuildAttrs::HardFPSinglePrecision); 699263509Sdim 700218893Sdim // Hard float. Use both S and D registers and conform to AAPCS-VFP. 701263509Sdim if (Subtarget->isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard) 702263509Sdim ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS); 703263509Sdim 704218893Sdim // FIXME: Should we signal R9 usage? 705218893Sdim 706263509Sdim if (Subtarget->hasFP16()) 707263509Sdim ATS.emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP); 708218893Sdim 709263509Sdim if (Subtarget->hasMPExtension()) 710263509Sdim ATS.emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP); 711263509Sdim 712263509Sdim if (Subtarget->hasDivide()) { 713263509Sdim // Check if hardware divide is only available in thumb2 or ARM as well. 714263509Sdim ATS.emitAttribute(ARMBuildAttrs::DIV_use, 715263509Sdim Subtarget->hasDivideInARMMode() ? ARMBuildAttrs::AllowDIVExt : 716263509Sdim ARMBuildAttrs::AllowDIVIfExists); 717263509Sdim } 718263509Sdim 719263509Sdim if (Subtarget->hasTrustZone() && Subtarget->hasVirtualization()) 720263509Sdim ATS.emitAttribute(ARMBuildAttrs::Virtualization_use, 721263509Sdim ARMBuildAttrs::AllowTZVirtualization); 722263509Sdim else if (Subtarget->hasTrustZone()) 723263509Sdim ATS.emitAttribute(ARMBuildAttrs::Virtualization_use, 724263509Sdim ARMBuildAttrs::AllowTZ); 725263509Sdim else if (Subtarget->hasVirtualization()) 726263509Sdim ATS.emitAttribute(ARMBuildAttrs::Virtualization_use, 727263509Sdim ARMBuildAttrs::AllowVirtualization); 728263509Sdim 729263509Sdim 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 } 774235633Sdim 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) 781263509Sdim 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:: 792263509Sdim StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); 793218893Sdim return MCSym; 794218893Sdim} 795218893Sdim 796218893Sdimvoid ARMAsmPrinter:: 797218893SdimEmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 798245431Sdim 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()) { 809226890Sdim const BlockAddress *BA = 810226890Sdim cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress(); 811226890Sdim MCSym = GetBlockAddressSymbol(BA); 812218893Sdim } else if (ACPV->isGlobalValue()) { 813226890Sdim const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV(); 814218893Sdim MCSym = GetARMGVSymbol(GV); 815226890Sdim } else if (ACPV->isMachineBasicBlock()) { 816226890Sdim const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB(); 817226890Sdim MCSym = MBB->getSymbol(); 818218893Sdim } else { 819218893Sdim assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); 820226890Sdim const char *Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol(); 821226890Sdim 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 869245431Sdim // Mark the jump table as data-in-code. 870245431Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionJT32); 871245431Sdim 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); 893226890Sdim // If we're generating a table of Thumb addresses in static relocation 894226890Sdim // model, we need to add one to keep interworking correctly. 895226890Sdim else if (AFI->isThumbFunction()) 896226890Sdim Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(1,OutContext), 897226890Sdim OutContext); 898218893Sdim OutStreamer.EmitValue(Expr, 4); 899218893Sdim } 900245431Sdim // Mark the end of jump table data-in-code region. 901245431Sdim 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; 919245431Sdim if (MI->getOpcode() == ARM::t2TBB_JT) { 920218893Sdim OffsetWidth = 1; 921245431Sdim // Mark the jump table as data-in-code. 922245431Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionJT8); 923245431Sdim } else if (MI->getOpcode() == ARM::t2TBH_JT) { 924218893Sdim OffsetWidth = 2; 925245431Sdim // Mark the jump table as data-in-code. 926245431Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionJT16); 927245431Sdim } 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) { 935252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2B) 936252723Sdim .addExpr(MBBSymbolExpr) 937252723Sdim .addImm(ARMCC::AL) 938252723Sdim .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 } 958245431Sdim // Mark the end of jump table data-in-code region. 32-bit offsets use 959245431Sdim // actual branch instructions here, so we don't mark those as a data-region 960245431Sdim // at all. 961245431Sdim if (OffsetWidth != 4) 962245431Sdim 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 969263509Sdim MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); 970263509Sdim 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. 992235633Sdim 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(); 1006235633Sdim 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; 1016245431Sdim i != NumOps; ++i) { 1017245431Sdim const MachineOperand &MO = MI->getOperand(i); 1018245431Sdim // Actually, there should never be any impdef stuff here. Skip it 1019245431Sdim // temporary to workaround PR11902. 1020245431Sdim if (MO.isImplicit()) 1021245431Sdim continue; 1022245431Sdim RegList.push_back(MO.getReg()); 1023245431Sdim } 1024221345Sdim break; 1025226890Sdim case ARM::STR_PRE_IMM: 1026226890Sdim case ARM::STR_PRE_REG: 1027235633Sdim 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 } 1033263509Sdim 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(); 1041235633Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1042221345Sdim case ARM::MOVr: 1043235633Sdim case ARM::tMOVr: 1044221345Sdim Offset = 0; 1045221345Sdim break; 1046221345Sdim case ARM::ADDri: 1047221345Sdim Offset = -MI->getOperand(2).getImm(); 1048221345Sdim break; 1049221345Sdim case ARM::SUBri: 1050235633Sdim 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. 1081263509Sdim 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. 1085263509Sdim ATS.emitPad(Offset); 1086221345Sdim } else { 1087221345Sdim MI->dump(); 1088235633Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1089221345Sdim } 1090221345Sdim } else if (DstReg == ARM::SP) { 1091221345Sdim // FIXME: .movsp goes here 1092221345Sdim MI->dump(); 1093235633Sdim llvm_unreachable("Unsupported opcode for unwinding information"); 1094221345Sdim } 1095221345Sdim else { 1096221345Sdim MI->dump(); 1097235633Sdim 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) { 1109245431Sdim // If we just ended a constant pool, mark it as such. 1110245431Sdim if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) { 1111245431Sdim OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); 1112245431Sdim InConstantPool = false; 1113245431Sdim } 1114226890Sdim 1115226890Sdim // Emit unwinding stuff for frame-related instructions 1116226890Sdim if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup)) 1117226890Sdim EmitUnwindingInstruction(MI); 1118226890Sdim 1119224145Sdim // Do any auto-generated pseudo lowerings. 1120224145Sdim if (emitPseudoExpansionLowering(OutStreamer, MI)) 1121224145Sdim return; 1122224145Sdim 1123226890Sdim assert(!convertAddSubFlagsOpcode(MI->getOpcode()) && 1124226890Sdim "Pseudo flag setting opcode should be expanded early"); 1125226890Sdim 1126224145Sdim // Check for manual lowerings. 1127218893Sdim unsigned Opc = MI->getOpcode(); 1128218893Sdim switch (Opc) { 1129235633Sdim case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass"); 1130263509Sdim 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 1135252723Sdim MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex()); 1136252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() == 1137252723Sdim ARM::t2LEApcrel ? ARM::t2ADR 1138252723Sdim : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR 1139252723Sdim : ARM::ADR)) 1140252723Sdim .addReg(MI->getOperand(0).getReg()) 1141252723Sdim .addExpr(MCSymbolRefExpr::Create(CPISymbol, OutContext)) 1142252723Sdim // Add predicate operands. 1143252723Sdim .addImm(MI->getOperand(2).getImm()) 1144252723Sdim .addReg(MI->getOperand(3).getReg())); 1145218893Sdim return; 1146218893Sdim } 1147218893Sdim case ARM::LEApcrelJT: 1148218893Sdim case ARM::tLEApcrelJT: 1149218893Sdim case ARM::t2LEApcrelJT: { 1150252723Sdim MCSymbol *JTIPICSymbol = 1151252723Sdim GetARMJTIPICJumpTableLabel2(MI->getOperand(1).getIndex(), 1152252723Sdim MI->getOperand(2).getImm()); 1153252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() == 1154252723Sdim ARM::t2LEApcrelJT ? ARM::t2ADR 1155252723Sdim : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR 1156252723Sdim : ARM::ADR)) 1157252723Sdim .addReg(MI->getOperand(0).getReg()) 1158252723Sdim .addExpr(MCSymbolRefExpr::Create(JTIPICSymbol, OutContext)) 1159252723Sdim // Add predicate operands. 1160252723Sdim .addImm(MI->getOperand(3).getImm()) 1161252723Sdim .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: { 1167252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1168252723Sdim .addReg(ARM::LR) 1169252723Sdim .addReg(ARM::PC) 1170218893Sdim // Add predicate operands. 1171252723Sdim .addImm(ARMCC::AL) 1172252723Sdim .addReg(0) 1173218893Sdim // Add 's' bit operand (always reg0 for this) 1174252723Sdim .addReg(0)); 1175252723Sdim 1176252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX) 1177252723Sdim .addReg(MI->getOperand(0).getReg())); 1178218893Sdim return; 1179218893Sdim } 1180223017Sdim case ARM::tBX_CALL: { 1181252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1182252723Sdim .addReg(ARM::LR) 1183252723Sdim .addReg(ARM::PC) 1184224145Sdim // Add predicate operands. 1185252723Sdim .addImm(ARMCC::AL) 1186252723Sdim .addReg(0)); 1187252723Sdim 1188252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX) 1189252723Sdim .addReg(MI->getOperand(0).getReg()) 1190223017Sdim // Add predicate operands. 1191252723Sdim .addImm(ARMCC::AL) 1192252723Sdim .addReg(0)); 1193223017Sdim return; 1194223017Sdim } 1195218893Sdim case ARM::BMOVPCRX_CALL: { 1196252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1197252723Sdim .addReg(ARM::LR) 1198252723Sdim .addReg(ARM::PC) 1199218893Sdim // Add predicate operands. 1200252723Sdim .addImm(ARMCC::AL) 1201252723Sdim .addReg(0) 1202218893Sdim // Add 's' bit operand (always reg0 for this) 1203252723Sdim .addReg(0)); 1204252723Sdim 1205252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1206252723Sdim .addReg(ARM::PC) 1207252723Sdim .addReg(MI->getOperand(0).getReg()) 1208218893Sdim // Add predicate operands. 1209252723Sdim .addImm(ARMCC::AL) 1210252723Sdim .addReg(0) 1211218893Sdim // Add 's' bit operand (always reg0 for this) 1212252723Sdim .addReg(0)); 1213218893Sdim return; 1214218893Sdim } 1215235633Sdim case ARM::BMOVPCB_CALL: { 1216252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr) 1217252723Sdim .addReg(ARM::LR) 1218252723Sdim .addReg(ARM::PC) 1219235633Sdim // Add predicate operands. 1220252723Sdim .addImm(ARMCC::AL) 1221252723Sdim .addReg(0) 1222235633Sdim // Add 's' bit operand (always reg0 for this) 1223252723Sdim .addReg(0)); 1224252723Sdim 1225252723Sdim const GlobalValue *GV = MI->getOperand(0).getGlobal(); 1226263509Sdim MCSymbol *GVSym = getSymbol(GV); 1227252723Sdim const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext); 1228252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::Bcc) 1229252723Sdim .addExpr(GVSymExpr) 1230235633Sdim // Add predicate operands. 1231252723Sdim .addImm(ARMCC::AL) 1232252723Sdim .addReg(0)); 1233235633Sdim return; 1234235633Sdim } 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. 1320252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDhirr) 1321252723Sdim .addReg(MI->getOperand(0).getReg()) 1322252723Sdim .addReg(MI->getOperand(0).getReg()) 1323252723Sdim .addReg(ARM::PC) 1324252723Sdim // Add predicate operands. 1325252723Sdim .addImm(ARMCC::AL) 1326252723Sdim .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. 1341252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr) 1342252723Sdim .addReg(MI->getOperand(0).getReg()) 1343252723Sdim .addReg(ARM::PC) 1344252723Sdim .addReg(MI->getOperand(1).getReg()) 1345252723Sdim // Add predicate operands. 1346252723Sdim .addImm(MI->getOperand(3).getImm()) 1347252723Sdim .addReg(MI->getOperand(4).getReg()) 1348252723Sdim // Add 's' bit operand (always reg0 for this) 1349252723Sdim .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 } 1385252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(Opcode) 1386252723Sdim .addReg(MI->getOperand(0).getReg()) 1387252723Sdim .addReg(ARM::PC) 1388252723Sdim .addReg(MI->getOperand(1).getReg()) 1389252723Sdim .addImm(0) 1390252723Sdim // Add predicate operands. 1391252723Sdim .addImm(MI->getOperand(3).getImm()) 1392252723Sdim .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. 1401235633Sdim /// 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 1405245431Sdim // If this is the first entry of the pool, mark it. 1406245431Sdim if (!InConstantPool) { 1407245431Sdim OutStreamer.EmitDataRegion(MCDR_DataRegion); 1408245431Sdim InConstantPool = true; 1409245431Sdim } 1410245431Sdim 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. 1422252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1423252723Sdim .addReg(ARM::PC) 1424252723Sdim .addReg(MI->getOperand(0).getReg()) 1425252723Sdim // Add predicate operands. 1426252723Sdim .addImm(ARMCC::AL) 1427252723Sdim .addReg(0)); 1428252723Sdim 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. 1435252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBB) 1436252723Sdim .addReg(ARM::PC) 1437252723Sdim .addReg(MI->getOperand(0).getReg()) 1438252723Sdim // Add predicate operands. 1439252723Sdim .addImm(ARMCC::AL) 1440252723Sdim .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. 1450252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBH) 1451252723Sdim .addReg(ARM::PC) 1452252723Sdim .addReg(MI->getOperand(0).getReg()) 1453252723Sdim // Add predicate operands. 1454252723Sdim .addImm(ARMCC::AL) 1455252723Sdim .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 1516252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr) 1517252723Sdim .addReg(ARM::PC) 1518252723Sdim .addReg(MI->getOperand(0).getReg()) 1519252723Sdim .addReg(MI->getOperand(1).getReg()) 1520252723Sdim // Add predicate operands. 1521252723Sdim .addImm(ARMCC::AL) 1522252723Sdim .addReg(0) 1523252723Sdim // Add 's' bit operand (always reg0 for this) 1524252723Sdim .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 } 1542252723Sdim case ARM::TRAPNaCl: { 1543252723Sdim //.long 0xe7fedef0 @ trap 1544252723Sdim uint32_t Val = 0xe7fedef0UL; 1545252723Sdim OutStreamer.AddComment("trap"); 1546252723Sdim OutStreamer.EmitIntValue(Val, 4); 1547252723Sdim return; 1548252723Sdim } 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(); 1575252723Sdim OutStreamer.AddComment("eh_setjmp begin"); 1576252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1577252723Sdim .addReg(ValReg) 1578252723Sdim .addReg(ARM::PC) 1579224145Sdim // Predicate. 1580252723Sdim .addImm(ARMCC::AL) 1581252723Sdim .addReg(0)); 1582252723Sdim 1583252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDi3) 1584252723Sdim .addReg(ValReg) 1585218893Sdim // 's' bit operand 1586252723Sdim .addReg(ARM::CPSR) 1587252723Sdim .addReg(ValReg) 1588252723Sdim .addImm(7) 1589218893Sdim // Predicate. 1590252723Sdim .addImm(ARMCC::AL) 1591252723Sdim .addReg(0)); 1592252723Sdim 1593252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tSTRi) 1594252723Sdim .addReg(ValReg) 1595252723Sdim .addReg(SrcReg) 1596218893Sdim // The offset immediate is #4. The operand value is scaled by 4 for the 1597218893Sdim // tSTR instruction. 1598252723Sdim .addImm(1) 1599218893Sdim // Predicate. 1600252723Sdim .addImm(ARMCC::AL) 1601252723Sdim .addReg(0)); 1602252723Sdim 1603252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8) 1604252723Sdim .addReg(ARM::R0) 1605252723Sdim .addReg(ARM::CPSR) 1606252723Sdim .addImm(0) 1607218893Sdim // Predicate. 1608252723Sdim .addImm(ARMCC::AL) 1609252723Sdim .addReg(0)); 1610252723Sdim 1611252723Sdim const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext); 1612252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tB) 1613252723Sdim .addExpr(SymbolExpr) 1614252723Sdim .addImm(ARMCC::AL) 1615252723Sdim .addReg(0)); 1616252723Sdim 1617252723Sdim OutStreamer.AddComment("eh_setjmp end"); 1618252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8) 1619252723Sdim .addReg(ARM::R0) 1620252723Sdim .addReg(ARM::CPSR) 1621252723Sdim .addImm(1) 1622218893Sdim // Predicate. 1623252723Sdim .addImm(ARMCC::AL) 1624252723Sdim .addReg(0)); 1625252723Sdim 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 1641252723Sdim OutStreamer.AddComment("eh_setjmp begin"); 1642252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri) 1643252723Sdim .addReg(ValReg) 1644252723Sdim .addReg(ARM::PC) 1645252723Sdim .addImm(8) 1646212793Sdim // Predicate. 1647252723Sdim .addImm(ARMCC::AL) 1648252723Sdim .addReg(0) 1649218893Sdim // 's' bit operand (always reg0 for this). 1650252723Sdim .addReg(0)); 1651252723Sdim 1652252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::STRi12) 1653252723Sdim .addReg(ValReg) 1654252723Sdim .addReg(SrcReg) 1655252723Sdim .addImm(4) 1656218893Sdim // Predicate. 1657252723Sdim .addImm(ARMCC::AL) 1658252723Sdim .addReg(0)); 1659252723Sdim 1660252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi) 1661252723Sdim .addReg(ARM::R0) 1662252723Sdim .addImm(0) 1663218893Sdim // Predicate. 1664252723Sdim .addImm(ARMCC::AL) 1665252723Sdim .addReg(0) 1666218893Sdim // 's' bit operand (always reg0 for this). 1667252723Sdim .addReg(0)); 1668252723Sdim 1669252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri) 1670252723Sdim .addReg(ARM::PC) 1671252723Sdim .addReg(ARM::PC) 1672252723Sdim .addImm(0) 1673218893Sdim // Predicate. 1674252723Sdim .addImm(ARMCC::AL) 1675252723Sdim .addReg(0) 1676218893Sdim // 's' bit operand (always reg0 for this). 1677252723Sdim .addReg(0)); 1678252723Sdim 1679252723Sdim OutStreamer.AddComment("eh_setjmp end"); 1680252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi) 1681252723Sdim .addReg(ARM::R0) 1682252723Sdim .addImm(1) 1683218893Sdim // Predicate. 1684252723Sdim .addImm(ARMCC::AL) 1685252723Sdim .addReg(0) 1686218893Sdim // 's' bit operand (always reg0 for this). 1687252723Sdim .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(); 1697252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12) 1698252723Sdim .addReg(ARM::SP) 1699252723Sdim .addReg(SrcReg) 1700252723Sdim .addImm(8) 1701218893Sdim // Predicate. 1702252723Sdim .addImm(ARMCC::AL) 1703252723Sdim .addReg(0)); 1704252723Sdim 1705252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12) 1706252723Sdim .addReg(ScratchReg) 1707252723Sdim .addReg(SrcReg) 1708252723Sdim .addImm(4) 1709212793Sdim // Predicate. 1710252723Sdim .addImm(ARMCC::AL) 1711252723Sdim .addReg(0)); 1712252723Sdim 1713252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12) 1714252723Sdim .addReg(ARM::R7) 1715252723Sdim .addReg(SrcReg) 1716252723Sdim .addImm(0) 1717212793Sdim // Predicate. 1718252723Sdim .addImm(ARMCC::AL) 1719252723Sdim .addReg(0)); 1720252723Sdim 1721252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX) 1722252723Sdim .addReg(ScratchReg) 1723218893Sdim // Predicate. 1724252723Sdim .addImm(ARMCC::AL) 1725252723Sdim .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(); 1736252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi) 1737252723Sdim .addReg(ScratchReg) 1738252723Sdim .addReg(SrcReg) 1739218893Sdim // The offset immediate is #8. The operand value is scaled by 4 for the 1740218893Sdim // tLDR instruction. 1741252723Sdim .addImm(2) 1742218893Sdim // Predicate. 1743252723Sdim .addImm(ARMCC::AL) 1744252723Sdim .addReg(0)); 1745252723Sdim 1746252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr) 1747252723Sdim .addReg(ARM::SP) 1748252723Sdim .addReg(ScratchReg) 1749218893Sdim // Predicate. 1750252723Sdim .addImm(ARMCC::AL) 1751252723Sdim .addReg(0)); 1752252723Sdim 1753252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi) 1754252723Sdim .addReg(ScratchReg) 1755252723Sdim .addReg(SrcReg) 1756252723Sdim .addImm(1) 1757218893Sdim // Predicate. 1758252723Sdim .addImm(ARMCC::AL) 1759252723Sdim .addReg(0)); 1760252723Sdim 1761252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi) 1762252723Sdim .addReg(ARM::R7) 1763252723Sdim .addReg(SrcReg) 1764252723Sdim .addImm(0) 1765218893Sdim // Predicate. 1766252723Sdim .addImm(ARMCC::AL) 1767252723Sdim .addReg(0)); 1768252723Sdim 1769252723Sdim OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX) 1770252723Sdim .addReg(ScratchReg) 1771218893Sdim // Predicate. 1772252723Sdim .addImm(ARMCC::AL) 1773252723Sdim .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