ARMAsmPrinter.cpp revision 6c6005eccd76a66ed897310fccf8aa1b90f2937b
1//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file contains a printer that converts from our internal representation 11// of machine-dependent LLVM code to GAS-format ARM assembly language. 12// 13//===----------------------------------------------------------------------===// 14 15#define DEBUG_TYPE "asm-printer" 16#include "ARM.h" 17#include "ARMBuildAttrs.h" 18#include "ARMAddressingModes.h" 19#include "ARMConstantPoolValue.h" 20#include "AsmPrinter/ARMInstPrinter.h" 21#include "ARMMachineFunctionInfo.h" 22#include "ARMMCInstLower.h" 23#include "ARMTargetMachine.h" 24#include "llvm/Analysis/DebugInfo.h" 25#include "llvm/Constants.h" 26#include "llvm/Module.h" 27#include "llvm/Type.h" 28#include "llvm/Assembly/Writer.h" 29#include "llvm/CodeGen/AsmPrinter.h" 30#include "llvm/CodeGen/MachineModuleInfoImpls.h" 31#include "llvm/CodeGen/MachineFunctionPass.h" 32#include "llvm/CodeGen/MachineJumpTableInfo.h" 33#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 34#include "llvm/MC/MCAsmInfo.h" 35#include "llvm/MC/MCContext.h" 36#include "llvm/MC/MCExpr.h" 37#include "llvm/MC/MCInst.h" 38#include "llvm/MC/MCSectionMachO.h" 39#include "llvm/MC/MCStreamer.h" 40#include "llvm/MC/MCSymbol.h" 41#include "llvm/Target/Mangler.h" 42#include "llvm/Target/TargetData.h" 43#include "llvm/Target/TargetMachine.h" 44#include "llvm/Target/TargetOptions.h" 45#include "llvm/Target/TargetRegistry.h" 46#include "llvm/ADT/SmallPtrSet.h" 47#include "llvm/ADT/SmallString.h" 48#include "llvm/ADT/StringExtras.h" 49#include "llvm/Support/CommandLine.h" 50#include "llvm/Support/Debug.h" 51#include "llvm/Support/ErrorHandling.h" 52#include "llvm/Support/raw_ostream.h" 53#include <cctype> 54using namespace llvm; 55 56namespace llvm { 57 namespace ARM { 58 enum DW_ISA { 59 DW_ISA_ARM_thumb = 1, 60 DW_ISA_ARM_arm = 2 61 }; 62 } 63} 64 65namespace { 66 class ARMAsmPrinter : public AsmPrinter { 67 68 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 69 /// make the right decision when printing asm code for different targets. 70 const ARMSubtarget *Subtarget; 71 72 /// AFI - Keep a pointer to ARMFunctionInfo for the current 73 /// MachineFunction. 74 ARMFunctionInfo *AFI; 75 76 /// MCP - Keep a pointer to constantpool entries of the current 77 /// MachineFunction. 78 const MachineConstantPool *MCP; 79 80 public: 81 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 82 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) { 83 Subtarget = &TM.getSubtarget<ARMSubtarget>(); 84 } 85 86 virtual const char *getPassName() const { 87 return "ARM Assembly Printer"; 88 } 89 90 void EmitJumpTable(const MachineInstr *MI); 91 void EmitJump2Table(const MachineInstr *MI); 92 93 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, 94 const char *Modifier = 0); 95 void printSOImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); 96 void printSOImm2PartOperand(const MachineInstr *MI, int OpNum, 97 raw_ostream &O); 98 void printSORegOperand(const MachineInstr *MI, int OpNum, 99 raw_ostream &O); 100 void printAddrMode2Operand(const MachineInstr *MI, int OpNum, 101 raw_ostream &O); 102 void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum, 103 raw_ostream &O); 104 void printAddrMode3Operand(const MachineInstr *MI, int OpNum, 105 raw_ostream &O); 106 void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum, 107 raw_ostream &O); 108 void printAddrMode4Operand(const MachineInstr *MI, int OpNum,raw_ostream &O, 109 const char *Modifier = 0); 110 void printAddrMode5Operand(const MachineInstr *MI, int OpNum,raw_ostream &O, 111 const char *Modifier = 0); 112 void printAddrMode6Operand(const MachineInstr *MI, int OpNum, 113 raw_ostream &O); 114 void printAddrMode6OffsetOperand(const MachineInstr *MI, int OpNum, 115 raw_ostream &O); 116 void printAddrModePCOperand(const MachineInstr *MI, int OpNum, 117 raw_ostream &O, 118 const char *Modifier = 0); 119 void printBitfieldInvMaskImmOperand(const MachineInstr *MI, int OpNum, 120 raw_ostream &O); 121 void printMemBOption(const MachineInstr *MI, int OpNum, 122 raw_ostream &O); 123 void printShiftImmOperand(const MachineInstr *MI, int OpNum, 124 raw_ostream &O); 125 126 void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum, 127 raw_ostream &O); 128 void printThumbITMask(const MachineInstr *MI, int OpNum, raw_ostream &O); 129 void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum, 130 raw_ostream &O); 131 void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum, 132 raw_ostream &O, 133 unsigned Scale); 134 void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum, 135 raw_ostream &O); 136 void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum, 137 raw_ostream &O); 138 void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum, 139 raw_ostream &O); 140 void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum, 141 raw_ostream &O); 142 143 void printT2SOOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); 144 void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum, 145 raw_ostream &O); 146 void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum, 147 raw_ostream &O); 148 void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum, 149 raw_ostream &O); 150 void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum, 151 raw_ostream &O); 152 void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum, 153 raw_ostream &O) {} 154 void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum, 155 raw_ostream &O); 156 157 void printCPSOptionOperand(const MachineInstr *MI, int OpNum, 158 raw_ostream &O) {} 159 void printMSRMaskOperand(const MachineInstr *MI, int OpNum, 160 raw_ostream &O) {} 161 void printNegZeroOperand(const MachineInstr *MI, int OpNum, 162 raw_ostream &O) {} 163 void printPredicateOperand(const MachineInstr *MI, int OpNum, 164 raw_ostream &O); 165 void printMandatoryPredicateOperand(const MachineInstr *MI, int OpNum, 166 raw_ostream &O); 167 void printSBitModifierOperand(const MachineInstr *MI, int OpNum, 168 raw_ostream &O); 169 void printPCLabel(const MachineInstr *MI, int OpNum, 170 raw_ostream &O); 171 void printRegisterList(const MachineInstr *MI, int OpNum, 172 raw_ostream &O); 173 void printCPInstOperand(const MachineInstr *MI, int OpNum, 174 raw_ostream &O, 175 const char *Modifier); 176 void printJTBlockOperand(const MachineInstr *MI, int OpNum, 177 raw_ostream &O); 178 void printJT2BlockOperand(const MachineInstr *MI, int OpNum, 179 raw_ostream &O); 180 void printTBAddrMode(const MachineInstr *MI, int OpNum, 181 raw_ostream &O); 182 void printNoHashImmediate(const MachineInstr *MI, int OpNum, 183 raw_ostream &O); 184 void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum, 185 raw_ostream &O); 186 void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum, 187 raw_ostream &O); 188 void printNEONModImmOperand(const MachineInstr *MI, int OpNum, 189 raw_ostream &O); 190 191 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 192 unsigned AsmVariant, const char *ExtraCode, 193 raw_ostream &O); 194 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, 195 unsigned AsmVariant, 196 const char *ExtraCode, raw_ostream &O); 197 198 void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen 199 static const char *getRegisterName(unsigned RegNo); 200 201 virtual void EmitInstruction(const MachineInstr *MI); 202 bool runOnMachineFunction(MachineFunction &F); 203 204 virtual void EmitConstantPool() {} // we emit constant pools customly! 205 virtual void EmitFunctionEntryLabel(); 206 void EmitStartOfAsmFile(Module &M); 207 void EmitEndOfAsmFile(Module &M); 208 209 void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); 210 211 MachineLocation getDebugValueLocation(const MachineInstr *MI) const { 212 MachineLocation Location; 213 assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); 214 // Frame address. Currently handles register +- offset only. 215 if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) 216 Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); 217 else { 218 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); 219 } 220 return Location; 221 } 222 223 virtual unsigned getISAEncoding() { 224 // ARM/Darwin adds ISA to the DWARF info for each function. 225 if (!Subtarget->isTargetDarwin()) 226 return 0; 227 return Subtarget->isThumb() ? 228 llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm; 229 } 230 231 MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2, 232 const MachineBasicBlock *MBB) const; 233 MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const; 234 235 MCSymbol *GetARMSJLJEHLabel(void) const; 236 237 /// EmitMachineConstantPoolValue - Print a machine constantpool value to 238 /// the .s file. 239 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 240 SmallString<128> Str; 241 raw_svector_ostream OS(Str); 242 EmitMachineConstantPoolValue(MCPV, OS); 243 OutStreamer.EmitRawText(OS.str()); 244 } 245 246 void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV, 247 raw_ostream &O) { 248 switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) { 249 case 1: O << MAI->getData8bitsDirective(0); break; 250 case 2: O << MAI->getData16bitsDirective(0); break; 251 case 4: O << MAI->getData32bitsDirective(0); break; 252 default: assert(0 && "Unknown CPV size"); 253 } 254 255 ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV); 256 257 if (ACPV->isLSDA()) { 258 O << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber(); 259 } else if (ACPV->isBlockAddress()) { 260 O << *GetBlockAddressSymbol(ACPV->getBlockAddress()); 261 } else if (ACPV->isGlobalValue()) { 262 const GlobalValue *GV = ACPV->getGV(); 263 bool isIndirect = Subtarget->isTargetDarwin() && 264 Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel()); 265 if (!isIndirect) 266 O << *Mang->getSymbol(GV); 267 else { 268 // FIXME: Remove this when Darwin transition to @GOT like syntax. 269 MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 270 O << *Sym; 271 272 MachineModuleInfoMachO &MMIMachO = 273 MMI->getObjFileInfo<MachineModuleInfoMachO>(); 274 MachineModuleInfoImpl::StubValueTy &StubSym = 275 GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) : 276 MMIMachO.getGVStubEntry(Sym); 277 if (StubSym.getPointer() == 0) 278 StubSym = MachineModuleInfoImpl:: 279 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); 280 } 281 } else { 282 assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); 283 O << *GetExternalSymbolSymbol(ACPV->getSymbol()); 284 } 285 286 if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; 287 if (ACPV->getPCAdjustment() != 0) { 288 O << "-(" << MAI->getPrivateGlobalPrefix() << "PC" 289 << getFunctionNumber() << "_" << ACPV->getLabelId() 290 << "+" << (unsigned)ACPV->getPCAdjustment(); 291 if (ACPV->mustAddCurrentAddress()) 292 O << "-."; 293 O << ')'; 294 } 295 } 296 }; 297} // end of anonymous namespace 298 299#include "ARMGenAsmWriter.inc" 300 301void ARMAsmPrinter::EmitFunctionEntryLabel() { 302 if (AFI->isThumbFunction()) { 303 OutStreamer.EmitRawText(StringRef("\t.code\t16")); 304 if (!Subtarget->isTargetDarwin()) 305 OutStreamer.EmitRawText(StringRef("\t.thumb_func")); 306 else { 307 // This needs to emit to a temporary string to get properly quoted 308 // MCSymbols when they have spaces in them. 309 SmallString<128> Tmp; 310 raw_svector_ostream OS(Tmp); 311 OS << "\t.thumb_func\t" << *CurrentFnSym; 312 OutStreamer.EmitRawText(OS.str()); 313 } 314 } 315 316 OutStreamer.EmitLabel(CurrentFnSym); 317} 318 319/// runOnMachineFunction - This uses the printInstruction() 320/// method to print assembly for each instruction. 321/// 322bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 323 AFI = MF.getInfo<ARMFunctionInfo>(); 324 MCP = MF.getConstantPool(); 325 326 return AsmPrinter::runOnMachineFunction(MF); 327} 328 329void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 330 raw_ostream &O, const char *Modifier) { 331 const MachineOperand &MO = MI->getOperand(OpNum); 332 unsigned TF = MO.getTargetFlags(); 333 334 switch (MO.getType()) { 335 default: 336 assert(0 && "<unknown operand type>"); 337 case MachineOperand::MO_Register: { 338 unsigned Reg = MO.getReg(); 339 assert(TargetRegisterInfo::isPhysicalRegister(Reg)); 340 if (Modifier && strcmp(Modifier, "lane") == 0) { 341 unsigned RegNum = getARMRegisterNumbering(Reg); 342 unsigned DReg = 343 TM.getRegisterInfo()->getMatchingSuperReg(Reg, 344 RegNum & 1 ? ARM::ssub_1 : ARM::ssub_0, &ARM::DPR_VFP2RegClass); 345 O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']'; 346 } else { 347 assert(!MO.getSubReg() && "Subregs should be eliminated!"); 348 O << getRegisterName(Reg); 349 } 350 break; 351 } 352 case MachineOperand::MO_Immediate: { 353 int64_t Imm = MO.getImm(); 354 O << '#'; 355 if ((Modifier && strcmp(Modifier, "lo16") == 0) || 356 (TF & ARMII::MO_LO16)) 357 O << ":lower16:"; 358 else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 359 (TF & ARMII::MO_HI16)) 360 O << ":upper16:"; 361 O << Imm; 362 break; 363 } 364 case MachineOperand::MO_MachineBasicBlock: 365 O << *MO.getMBB()->getSymbol(); 366 return; 367 case MachineOperand::MO_GlobalAddress: { 368 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 369 const GlobalValue *GV = MO.getGlobal(); 370 371 if ((Modifier && strcmp(Modifier, "lo16") == 0) || 372 (TF & ARMII::MO_LO16)) 373 O << ":lower16:"; 374 else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 375 (TF & ARMII::MO_HI16)) 376 O << ":upper16:"; 377 O << *Mang->getSymbol(GV); 378 379 printOffset(MO.getOffset(), O); 380 381 if (isCallOp && Subtarget->isTargetELF() && 382 TM.getRelocationModel() == Reloc::PIC_) 383 O << "(PLT)"; 384 break; 385 } 386 case MachineOperand::MO_ExternalSymbol: { 387 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 388 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 389 390 if (isCallOp && Subtarget->isTargetELF() && 391 TM.getRelocationModel() == Reloc::PIC_) 392 O << "(PLT)"; 393 break; 394 } 395 case MachineOperand::MO_ConstantPoolIndex: 396 O << *GetCPISymbol(MO.getIndex()); 397 break; 398 case MachineOperand::MO_JumpTableIndex: 399 O << *GetJTISymbol(MO.getIndex()); 400 break; 401 } 402} 403 404static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm, 405 const MCAsmInfo *MAI) { 406 // Break it up into two parts that make up a shifter immediate. 407 V = ARM_AM::getSOImmVal(V); 408 assert(V != -1 && "Not a valid so_imm value!"); 409 410 unsigned Imm = ARM_AM::getSOImmValImm(V); 411 unsigned Rot = ARM_AM::getSOImmValRot(V); 412 413 // Print low-level immediate formation info, per 414 // A5.1.3: "Data-processing operands - Immediate". 415 if (Rot) { 416 O << "#" << Imm << ", " << Rot; 417 // Pretty printed version. 418 if (VerboseAsm) { 419 O << "\t" << MAI->getCommentString() << ' '; 420 O << (int)ARM_AM::rotr32(Imm, Rot); 421 } 422 } else { 423 O << "#" << Imm; 424 } 425} 426 427/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit 428/// immediate in bits 0-7. 429void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum, 430 raw_ostream &O) { 431 const MachineOperand &MO = MI->getOperand(OpNum); 432 assert(MO.isImm() && "Not a valid so_imm value!"); 433 printSOImm(O, MO.getImm(), isVerbose(), MAI); 434} 435 436/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' 437/// followed by an 'orr' to materialize. 438void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum, 439 raw_ostream &O) { 440 const MachineOperand &MO = MI->getOperand(OpNum); 441 assert(MO.isImm() && "Not a valid so_imm value!"); 442 unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm()); 443 unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm()); 444 printSOImm(O, V1, isVerbose(), MAI); 445 O << "\n\torr"; 446 printPredicateOperand(MI, 2, O); 447 O << "\t"; 448 printOperand(MI, 0, O); 449 O << ", "; 450 printOperand(MI, 0, O); 451 O << ", "; 452 printSOImm(O, V2, isVerbose(), MAI); 453} 454 455// so_reg is a 4-operand unit corresponding to register forms of the A5.1 456// "Addressing Mode 1 - Data-processing operands" forms. This includes: 457// REG 0 0 - e.g. R5 458// REG REG 0,SH_OPC - e.g. R5, ROR R3 459// REG 0 IMM,SH_OPC - e.g. R5, LSL #3 460void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op, 461 raw_ostream &O) { 462 const MachineOperand &MO1 = MI->getOperand(Op); 463 const MachineOperand &MO2 = MI->getOperand(Op+1); 464 const MachineOperand &MO3 = MI->getOperand(Op+2); 465 466 O << getRegisterName(MO1.getReg()); 467 468 // Print the shift opc. 469 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm()); 470 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 471 if (MO2.getReg()) { 472 O << ' ' << getRegisterName(MO2.getReg()); 473 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 474 } else if (ShOpc != ARM_AM::rrx) { 475 O << " #" << ARM_AM::getSORegOffset(MO3.getImm()); 476 } 477} 478 479void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op, 480 raw_ostream &O) { 481 const MachineOperand &MO1 = MI->getOperand(Op); 482 const MachineOperand &MO2 = MI->getOperand(Op+1); 483 const MachineOperand &MO3 = MI->getOperand(Op+2); 484 485 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 486 printOperand(MI, Op, O); 487 return; 488 } 489 490 O << "[" << getRegisterName(MO1.getReg()); 491 492 if (!MO2.getReg()) { 493 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. 494 O << ", #" 495 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 496 << ARM_AM::getAM2Offset(MO3.getImm()); 497 O << "]"; 498 return; 499 } 500 501 O << ", " 502 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 503 << getRegisterName(MO2.getReg()); 504 505 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 506 O << ", " 507 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) 508 << " #" << ShImm; 509 O << "]"; 510} 511 512void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op, 513 raw_ostream &O) { 514 const MachineOperand &MO1 = MI->getOperand(Op); 515 const MachineOperand &MO2 = MI->getOperand(Op+1); 516 517 if (!MO1.getReg()) { 518 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); 519 O << "#" 520 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 521 << ImmOffs; 522 return; 523 } 524 525 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 526 << getRegisterName(MO1.getReg()); 527 528 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) 529 O << ", " 530 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) 531 << " #" << ShImm; 532} 533 534void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op, 535 raw_ostream &O) { 536 const MachineOperand &MO1 = MI->getOperand(Op); 537 const MachineOperand &MO2 = MI->getOperand(Op+1); 538 const MachineOperand &MO3 = MI->getOperand(Op+2); 539 540 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); 541 O << "[" << getRegisterName(MO1.getReg()); 542 543 if (MO2.getReg()) { 544 O << ", " 545 << (char)ARM_AM::getAM3Op(MO3.getImm()) 546 << getRegisterName(MO2.getReg()) 547 << "]"; 548 return; 549 } 550 551 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) 552 O << ", #" 553 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 554 << ImmOffs; 555 O << "]"; 556} 557 558void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op, 559 raw_ostream &O){ 560 const MachineOperand &MO1 = MI->getOperand(Op); 561 const MachineOperand &MO2 = MI->getOperand(Op+1); 562 563 if (MO1.getReg()) { 564 O << (char)ARM_AM::getAM3Op(MO2.getImm()) 565 << getRegisterName(MO1.getReg()); 566 return; 567 } 568 569 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); 570 O << "#" 571 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) 572 << ImmOffs; 573} 574 575void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op, 576 raw_ostream &O, 577 const char *Modifier) { 578 const MachineOperand &MO2 = MI->getOperand(Op+1); 579 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); 580 if (Modifier && strcmp(Modifier, "submode") == 0) { 581 O << ARM_AM::getAMSubModeStr(Mode); 582 } else if (Modifier && strcmp(Modifier, "wide") == 0) { 583 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); 584 if (Mode == ARM_AM::ia) 585 O << ".w"; 586 } else { 587 printOperand(MI, Op, O); 588 } 589} 590 591void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, 592 raw_ostream &O, 593 const char *Modifier) { 594 const MachineOperand &MO1 = MI->getOperand(Op); 595 const MachineOperand &MO2 = MI->getOperand(Op+1); 596 597 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 598 printOperand(MI, Op, O); 599 return; 600 } 601 602 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); 603 604 O << "[" << getRegisterName(MO1.getReg()); 605 606 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { 607 O << ", #" 608 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm())) 609 << ImmOffs*4; 610 } 611 O << "]"; 612} 613 614void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op, 615 raw_ostream &O) { 616 const MachineOperand &MO1 = MI->getOperand(Op); 617 const MachineOperand &MO2 = MI->getOperand(Op+1); 618 619 O << "[" << getRegisterName(MO1.getReg()); 620 if (MO2.getImm()) { 621 // FIXME: Both darwin as and GNU as violate ARM docs here. 622 O << ", :" << (MO2.getImm() << 3); 623 } 624 O << "]"; 625} 626 627void ARMAsmPrinter::printAddrMode6OffsetOperand(const MachineInstr *MI, int Op, 628 raw_ostream &O){ 629 const MachineOperand &MO = MI->getOperand(Op); 630 if (MO.getReg() == 0) 631 O << "!"; 632 else 633 O << ", " << getRegisterName(MO.getReg()); 634} 635 636void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op, 637 raw_ostream &O, 638 const char *Modifier) { 639 if (Modifier && strcmp(Modifier, "label") == 0) { 640 printPCLabel(MI, Op+1, O); 641 return; 642 } 643 644 const MachineOperand &MO1 = MI->getOperand(Op); 645 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); 646 O << "[pc, " << getRegisterName(MO1.getReg()) << "]"; 647} 648 649void 650ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op, 651 raw_ostream &O) { 652 const MachineOperand &MO = MI->getOperand(Op); 653 uint32_t v = ~MO.getImm(); 654 int32_t lsb = CountTrailingZeros_32(v); 655 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; 656 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); 657 O << "#" << lsb << ", #" << width; 658} 659 660void 661ARMAsmPrinter::printMemBOption(const MachineInstr *MI, int OpNum, 662 raw_ostream &O) { 663 unsigned val = MI->getOperand(OpNum).getImm(); 664 O << ARM_MB::MemBOptToString(val); 665} 666 667void ARMAsmPrinter::printShiftImmOperand(const MachineInstr *MI, int OpNum, 668 raw_ostream &O) { 669 unsigned ShiftOp = MI->getOperand(OpNum).getImm(); 670 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); 671 switch (Opc) { 672 case ARM_AM::no_shift: 673 return; 674 case ARM_AM::lsl: 675 O << ", lsl #"; 676 break; 677 case ARM_AM::asr: 678 O << ", asr #"; 679 break; 680 default: 681 assert(0 && "unexpected shift opcode for shift immediate operand"); 682 } 683 O << ARM_AM::getSORegOffset(ShiftOp); 684} 685 686//===--------------------------------------------------------------------===// 687 688void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op, 689 raw_ostream &O) { 690 O << "#" << MI->getOperand(Op).getImm() * 4; 691} 692 693void 694ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op, 695 raw_ostream &O) { 696 // (3 - the number of trailing zeros) is the number of then / else. 697 unsigned Mask = MI->getOperand(Op).getImm(); 698 unsigned CondBit0 = Mask >> 4 & 1; 699 unsigned NumTZ = CountTrailingZeros_32(Mask); 700 assert(NumTZ <= 3 && "Invalid IT mask!"); 701 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { 702 bool T = ((Mask >> Pos) & 1) == CondBit0; 703 if (T) 704 O << 't'; 705 else 706 O << 'e'; 707 } 708} 709 710void 711ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op, 712 raw_ostream &O) { 713 const MachineOperand &MO1 = MI->getOperand(Op); 714 const MachineOperand &MO2 = MI->getOperand(Op+1); 715 O << "[" << getRegisterName(MO1.getReg()); 716 O << ", " << getRegisterName(MO2.getReg()) << "]"; 717} 718 719void 720ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, 721 raw_ostream &O, 722 unsigned Scale) { 723 const MachineOperand &MO1 = MI->getOperand(Op); 724 const MachineOperand &MO2 = MI->getOperand(Op+1); 725 const MachineOperand &MO3 = MI->getOperand(Op+2); 726 727 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 728 printOperand(MI, Op, O); 729 return; 730 } 731 732 O << "[" << getRegisterName(MO1.getReg()); 733 if (MO3.getReg()) 734 O << ", " << getRegisterName(MO3.getReg()); 735 else if (unsigned ImmOffs = MO2.getImm()) 736 O << ", #" << ImmOffs * Scale; 737 O << "]"; 738} 739 740void 741ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op, 742 raw_ostream &O) { 743 printThumbAddrModeRI5Operand(MI, Op, O, 1); 744} 745void 746ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op, 747 raw_ostream &O) { 748 printThumbAddrModeRI5Operand(MI, Op, O, 2); 749} 750void 751ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op, 752 raw_ostream &O) { 753 printThumbAddrModeRI5Operand(MI, Op, O, 4); 754} 755 756void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op, 757 raw_ostream &O) { 758 const MachineOperand &MO1 = MI->getOperand(Op); 759 const MachineOperand &MO2 = MI->getOperand(Op+1); 760 O << "[" << getRegisterName(MO1.getReg()); 761 if (unsigned ImmOffs = MO2.getImm()) 762 O << ", #" << ImmOffs*4; 763 O << "]"; 764} 765 766//===--------------------------------------------------------------------===// 767 768// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 769// register with shift forms. 770// REG 0 0 - e.g. R5 771// REG IMM, SH_OPC - e.g. R5, LSL #3 772void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum, 773 raw_ostream &O) { 774 const MachineOperand &MO1 = MI->getOperand(OpNum); 775 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 776 777 unsigned Reg = MO1.getReg(); 778 assert(TargetRegisterInfo::isPhysicalRegister(Reg)); 779 O << getRegisterName(Reg); 780 781 // Print the shift opc. 782 assert(MO2.isImm() && "Not a valid t2_so_reg value!"); 783 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 784 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 785 if (ShOpc != ARM_AM::rrx) 786 O << " #" << ARM_AM::getSORegOffset(MO2.getImm()); 787} 788 789void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI, 790 int OpNum, 791 raw_ostream &O) { 792 const MachineOperand &MO1 = MI->getOperand(OpNum); 793 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 794 795 O << "[" << getRegisterName(MO1.getReg()); 796 797 unsigned OffImm = MO2.getImm(); 798 if (OffImm) // Don't print +0. 799 O << ", #" << OffImm; 800 O << "]"; 801} 802 803void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI, 804 int OpNum, 805 raw_ostream &O) { 806 const MachineOperand &MO1 = MI->getOperand(OpNum); 807 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 808 809 O << "[" << getRegisterName(MO1.getReg()); 810 811 int32_t OffImm = (int32_t)MO2.getImm(); 812 // Don't print +0. 813 if (OffImm < 0) 814 O << ", #-" << -OffImm; 815 else if (OffImm > 0) 816 O << ", #" << OffImm; 817 O << "]"; 818} 819 820void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI, 821 int OpNum, 822 raw_ostream &O) { 823 const MachineOperand &MO1 = MI->getOperand(OpNum); 824 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 825 826 O << "[" << getRegisterName(MO1.getReg()); 827 828 int32_t OffImm = (int32_t)MO2.getImm() / 4; 829 // Don't print +0. 830 if (OffImm < 0) 831 O << ", #-" << -OffImm * 4; 832 else if (OffImm > 0) 833 O << ", #" << OffImm * 4; 834 O << "]"; 835} 836 837void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, 838 int OpNum, 839 raw_ostream &O) { 840 const MachineOperand &MO1 = MI->getOperand(OpNum); 841 int32_t OffImm = (int32_t)MO1.getImm(); 842 // Don't print +0. 843 if (OffImm < 0) 844 O << "#-" << -OffImm; 845 else if (OffImm > 0) 846 O << "#" << OffImm; 847} 848 849void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI, 850 int OpNum, 851 raw_ostream &O) { 852 const MachineOperand &MO1 = MI->getOperand(OpNum); 853 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 854 const MachineOperand &MO3 = MI->getOperand(OpNum+2); 855 856 O << "[" << getRegisterName(MO1.getReg()); 857 858 assert(MO2.getReg() && "Invalid so_reg load / store address!"); 859 O << ", " << getRegisterName(MO2.getReg()); 860 861 unsigned ShAmt = MO3.getImm(); 862 if (ShAmt) { 863 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); 864 O << ", lsl #" << ShAmt; 865 } 866 O << "]"; 867} 868 869 870//===--------------------------------------------------------------------===// 871 872void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum, 873 raw_ostream &O) { 874 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 875 if (CC != ARMCC::AL) 876 O << ARMCondCodeToString(CC); 877} 878 879void ARMAsmPrinter::printMandatoryPredicateOperand(const MachineInstr *MI, 880 int OpNum, 881 raw_ostream &O) { 882 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 883 O << ARMCondCodeToString(CC); 884} 885 886void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum, 887 raw_ostream &O){ 888 unsigned Reg = MI->getOperand(OpNum).getReg(); 889 if (Reg) { 890 assert(Reg == ARM::CPSR && "Expect ARM CPSR register!"); 891 O << 's'; 892 } 893} 894 895void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum, 896 raw_ostream &O) { 897 int Id = (int)MI->getOperand(OpNum).getImm(); 898 O << MAI->getPrivateGlobalPrefix() 899 << "PC" << getFunctionNumber() << "_" << Id; 900} 901 902void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum, 903 raw_ostream &O) { 904 O << "{"; 905 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { 906 if (MI->getOperand(i).isImplicit()) 907 continue; 908 if ((int)i != OpNum) O << ", "; 909 printOperand(MI, i, O); 910 } 911 O << "}"; 912} 913 914void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, 915 raw_ostream &O, const char *Modifier) { 916 assert(Modifier && "This operand only works with a modifier!"); 917 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the 918 // data itself. 919 if (!strcmp(Modifier, "label")) { 920 unsigned ID = MI->getOperand(OpNum).getImm(); 921 OutStreamer.EmitLabel(GetCPISymbol(ID)); 922 } else { 923 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); 924 unsigned CPI = MI->getOperand(OpNum).getIndex(); 925 926 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; 927 928 if (MCPE.isMachineConstantPoolEntry()) { 929 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 930 } else { 931 EmitGlobalConstant(MCPE.Val.ConstVal); 932 } 933 } 934} 935 936MCSymbol *ARMAsmPrinter:: 937GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2, 938 const MachineBasicBlock *MBB) const { 939 SmallString<60> Name; 940 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() 941 << getFunctionNumber() << '_' << uid << '_' << uid2 942 << "_set_" << MBB->getNumber(); 943 return OutContext.GetOrCreateSymbol(Name.str()); 944} 945 946MCSymbol *ARMAsmPrinter:: 947GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const { 948 SmallString<60> Name; 949 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI" 950 << getFunctionNumber() << '_' << uid << '_' << uid2; 951 return OutContext.GetOrCreateSymbol(Name.str()); 952} 953 954 955MCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel(void) const { 956 SmallString<60> Name; 957 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH" 958 << getFunctionNumber(); 959 return OutContext.GetOrCreateSymbol(Name.str()); 960} 961 962void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum, 963 raw_ostream &O) { 964 assert(!Subtarget->isThumb2() && "Thumb2 should use double-jump jumptables!"); 965 966 const MachineOperand &MO1 = MI->getOperand(OpNum); 967 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 968 969 unsigned JTI = MO1.getIndex(); 970 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 971 // Can't use EmitLabel until instprinter happens, label comes out in the wrong 972 // order. 973 O << "\n" << *JTISymbol << ":\n"; 974 975 const char *JTEntryDirective = MAI->getData32bitsDirective(); 976 977 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 978 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 979 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 980 bool UseSet= MAI->hasSetDirective() && TM.getRelocationModel() == Reloc::PIC_; 981 SmallPtrSet<MachineBasicBlock*, 8> JTSets; 982 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 983 MachineBasicBlock *MBB = JTBBs[i]; 984 bool isNew = JTSets.insert(MBB); 985 986 if (UseSet && isNew) { 987 O << "\t.set\t" 988 << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB) << ',' 989 << *MBB->getSymbol() << '-' << *JTISymbol << '\n'; 990 } 991 992 O << JTEntryDirective << ' '; 993 if (UseSet) 994 O << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB); 995 else if (TM.getRelocationModel() == Reloc::PIC_) 996 O << *MBB->getSymbol() << '-' << *JTISymbol; 997 else 998 O << *MBB->getSymbol(); 999 1000 if (i != e-1) 1001 O << '\n'; 1002 } 1003} 1004 1005void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum, 1006 raw_ostream &O) { 1007 const MachineOperand &MO1 = MI->getOperand(OpNum); 1008 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 1009 unsigned JTI = MO1.getIndex(); 1010 1011 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 1012 1013 // Can't use EmitLabel until instprinter happens, label comes out in the wrong 1014 // order. 1015 O << "\n" << *JTISymbol << ":\n"; 1016 1017 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 1018 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 1019 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 1020 bool ByteOffset = false, HalfWordOffset = false; 1021 if (MI->getOpcode() == ARM::t2TBB) 1022 ByteOffset = true; 1023 else if (MI->getOpcode() == ARM::t2TBH) 1024 HalfWordOffset = true; 1025 1026 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 1027 MachineBasicBlock *MBB = JTBBs[i]; 1028 if (ByteOffset) 1029 O << MAI->getData8bitsDirective(); 1030 else if (HalfWordOffset) 1031 O << MAI->getData16bitsDirective(); 1032 1033 if (ByteOffset || HalfWordOffset) 1034 O << '(' << *MBB->getSymbol() << "-" << *JTISymbol << ")/2"; 1035 else 1036 O << "\tb.w " << *MBB->getSymbol(); 1037 1038 if (i != e-1) 1039 O << '\n'; 1040 } 1041} 1042 1043void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum, 1044 raw_ostream &O) { 1045 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg()); 1046 if (MI->getOpcode() == ARM::t2TBH) 1047 O << ", lsl #1"; 1048 O << ']'; 1049} 1050 1051void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum, 1052 raw_ostream &O) { 1053 O << MI->getOperand(OpNum).getImm(); 1054} 1055 1056void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum, 1057 raw_ostream &O) { 1058 const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); 1059 O << '#' << FP->getValueAPF().convertToFloat(); 1060 if (isVerbose()) { 1061 O << "\t\t" << MAI->getCommentString() << ' '; 1062 WriteAsOperand(O, FP, /*PrintType=*/false); 1063 } 1064} 1065 1066void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum, 1067 raw_ostream &O) { 1068 const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); 1069 O << '#' << FP->getValueAPF().convertToDouble(); 1070 if (isVerbose()) { 1071 O << "\t\t" << MAI->getCommentString() << ' '; 1072 WriteAsOperand(O, FP, /*PrintType=*/false); 1073 } 1074} 1075 1076void ARMAsmPrinter::printNEONModImmOperand(const MachineInstr *MI, int OpNum, 1077 raw_ostream &O) { 1078 unsigned EncodedImm = MI->getOperand(OpNum).getImm(); 1079 unsigned EltBits; 1080 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); 1081 O << "#0x" << utohexstr(Val); 1082} 1083 1084bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 1085 unsigned AsmVariant, const char *ExtraCode, 1086 raw_ostream &O) { 1087 // Does this asm operand have a single letter operand modifier? 1088 if (ExtraCode && ExtraCode[0]) { 1089 if (ExtraCode[1] != 0) return true; // Unknown modifier. 1090 1091 switch (ExtraCode[0]) { 1092 default: return true; // Unknown modifier. 1093 case 'a': // Print as a memory address. 1094 if (MI->getOperand(OpNum).isReg()) { 1095 O << "[" << getRegisterName(MI->getOperand(OpNum).getReg()) << "]"; 1096 return false; 1097 } 1098 // Fallthrough 1099 case 'c': // Don't print "#" before an immediate operand. 1100 if (!MI->getOperand(OpNum).isImm()) 1101 return true; 1102 printNoHashImmediate(MI, OpNum, O); 1103 return false; 1104 case 'P': // Print a VFP double precision register. 1105 case 'q': // Print a NEON quad precision register. 1106 printOperand(MI, OpNum, O); 1107 return false; 1108 case 'Q': 1109 case 'R': 1110 case 'H': 1111 report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!"); 1112 return true; 1113 } 1114 } 1115 1116 printOperand(MI, OpNum, O); 1117 return false; 1118} 1119 1120bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 1121 unsigned OpNum, unsigned AsmVariant, 1122 const char *ExtraCode, 1123 raw_ostream &O) { 1124 if (ExtraCode && ExtraCode[0]) 1125 return true; // Unknown modifier. 1126 1127 const MachineOperand &MO = MI->getOperand(OpNum); 1128 assert(MO.isReg() && "unexpected inline asm memory operand"); 1129 O << "[" << getRegisterName(MO.getReg()) << "]"; 1130 return false; 1131} 1132 1133void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { 1134 if (Subtarget->isTargetDarwin()) { 1135 Reloc::Model RelocM = TM.getRelocationModel(); 1136 if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) { 1137 // Declare all the text sections up front (before the DWARF sections 1138 // emitted by AsmPrinter::doInitialization) so the assembler will keep 1139 // them together at the beginning of the object file. This helps 1140 // avoid out-of-range branches that are due a fundamental limitation of 1141 // the way symbol offsets are encoded with the current Darwin ARM 1142 // relocations. 1143 const TargetLoweringObjectFileMachO &TLOFMacho = 1144 static_cast<const TargetLoweringObjectFileMachO &>( 1145 getObjFileLowering()); 1146 OutStreamer.SwitchSection(TLOFMacho.getTextSection()); 1147 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); 1148 OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection()); 1149 if (RelocM == Reloc::DynamicNoPIC) { 1150 const MCSection *sect = 1151 OutContext.getMachOSection("__TEXT", "__symbol_stub4", 1152 MCSectionMachO::S_SYMBOL_STUBS, 1153 12, SectionKind::getText()); 1154 OutStreamer.SwitchSection(sect); 1155 } else { 1156 const MCSection *sect = 1157 OutContext.getMachOSection("__TEXT", "__picsymbolstub4", 1158 MCSectionMachO::S_SYMBOL_STUBS, 1159 16, SectionKind::getText()); 1160 OutStreamer.SwitchSection(sect); 1161 } 1162 const MCSection *StaticInitSect = 1163 OutContext.getMachOSection("__TEXT", "__StaticInit", 1164 MCSectionMachO::S_REGULAR | 1165 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 1166 SectionKind::getText()); 1167 OutStreamer.SwitchSection(StaticInitSect); 1168 } 1169 } 1170 1171 // Use unified assembler syntax. 1172 OutStreamer.EmitRawText(StringRef("\t.syntax unified")); 1173 1174 // Emit ARM Build Attributes 1175 if (Subtarget->isTargetELF()) { 1176 // CPU Type 1177 std::string CPUString = Subtarget->getCPUString(); 1178 if (CPUString != "generic") 1179 OutStreamer.EmitRawText("\t.cpu " + Twine(CPUString)); 1180 1181 // FIXME: Emit FPU type 1182 if (Subtarget->hasVFP2()) 1183 OutStreamer.EmitRawText("\t.eabi_attribute " + 1184 Twine(ARMBuildAttrs::VFP_arch) + ", 2"); 1185 1186 // Signal various FP modes. 1187 if (!UnsafeFPMath) { 1188 OutStreamer.EmitRawText("\t.eabi_attribute " + 1189 Twine(ARMBuildAttrs::ABI_FP_denormal) + ", 1"); 1190 OutStreamer.EmitRawText("\t.eabi_attribute " + 1191 Twine(ARMBuildAttrs::ABI_FP_exceptions) + ", 1"); 1192 } 1193 1194 if (NoInfsFPMath && NoNaNsFPMath) 1195 OutStreamer.EmitRawText("\t.eabi_attribute " + 1196 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 1"); 1197 else 1198 OutStreamer.EmitRawText("\t.eabi_attribute " + 1199 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 3"); 1200 1201 // 8-bytes alignment stuff. 1202 OutStreamer.EmitRawText("\t.eabi_attribute " + 1203 Twine(ARMBuildAttrs::ABI_align8_needed) + ", 1"); 1204 OutStreamer.EmitRawText("\t.eabi_attribute " + 1205 Twine(ARMBuildAttrs::ABI_align8_preserved) + ", 1"); 1206 1207 // Hard float. Use both S and D registers and conform to AAPCS-VFP. 1208 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) { 1209 OutStreamer.EmitRawText("\t.eabi_attribute " + 1210 Twine(ARMBuildAttrs::ABI_HardFP_use) + ", 3"); 1211 OutStreamer.EmitRawText("\t.eabi_attribute " + 1212 Twine(ARMBuildAttrs::ABI_VFP_args) + ", 1"); 1213 } 1214 // FIXME: Should we signal R9 usage? 1215 } 1216} 1217 1218 1219void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { 1220 if (Subtarget->isTargetDarwin()) { 1221 // All darwin targets use mach-o. 1222 const TargetLoweringObjectFileMachO &TLOFMacho = 1223 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 1224 MachineModuleInfoMachO &MMIMacho = 1225 MMI->getObjFileInfo<MachineModuleInfoMachO>(); 1226 1227 // Output non-lazy-pointers for external and common global variables. 1228 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); 1229 1230 if (!Stubs.empty()) { 1231 // Switch with ".non_lazy_symbol_pointer" directive. 1232 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); 1233 EmitAlignment(2); 1234 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 1235 // L_foo$stub: 1236 OutStreamer.EmitLabel(Stubs[i].first); 1237 // .indirect_symbol _foo 1238 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; 1239 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol); 1240 1241 if (MCSym.getInt()) 1242 // External to current translation unit. 1243 OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); 1244 else 1245 // Internal to current translation unit. 1246 // 1247 // When we place the LSDA into the TEXT section, the type info 1248 // pointers need to be indirect and pc-rel. We accomplish this by 1249 // using NLPs; however, sometimes the types are local to the file. 1250 // We need to fill in the value for the NLP in those cases. 1251 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), 1252 OutContext), 1253 4/*size*/, 0/*addrspace*/); 1254 } 1255 1256 Stubs.clear(); 1257 OutStreamer.AddBlankLine(); 1258 } 1259 1260 Stubs = MMIMacho.GetHiddenGVStubList(); 1261 if (!Stubs.empty()) { 1262 OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 1263 EmitAlignment(2); 1264 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 1265 // L_foo$stub: 1266 OutStreamer.EmitLabel(Stubs[i].first); 1267 // .long _foo 1268 OutStreamer.EmitValue(MCSymbolRefExpr:: 1269 Create(Stubs[i].second.getPointer(), 1270 OutContext), 1271 4/*size*/, 0/*addrspace*/); 1272 } 1273 1274 Stubs.clear(); 1275 OutStreamer.AddBlankLine(); 1276 } 1277 1278 // Funny Darwin hack: This flag tells the linker that no global symbols 1279 // contain code that falls through to other global symbols (e.g. the obvious 1280 // implementation of multiple entry points). If this doesn't occur, the 1281 // linker can safely perform dead code stripping. Since LLVM never 1282 // generates code that does this, it is always safe to set. 1283 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 1284 } 1285} 1286 1287//===----------------------------------------------------------------------===// 1288 1289static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, 1290 unsigned LabelId, MCContext &Ctx) { 1291 1292 MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix) 1293 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); 1294 return Label; 1295} 1296 1297void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) { 1298 unsigned Opcode = MI->getOpcode(); 1299 int OpNum = 1; 1300 if (Opcode == ARM::BR_JTadd) 1301 OpNum = 2; 1302 else if (Opcode == ARM::BR_JTm) 1303 OpNum = 3; 1304 1305 const MachineOperand &MO1 = MI->getOperand(OpNum); 1306 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 1307 unsigned JTI = MO1.getIndex(); 1308 1309 // Emit a label for the jump table. 1310 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 1311 OutStreamer.EmitLabel(JTISymbol); 1312 1313 // Emit each entry of the table. 1314 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 1315 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 1316 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 1317 1318 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 1319 MachineBasicBlock *MBB = JTBBs[i]; 1320 // Construct an MCExpr for the entry. We want a value of the form: 1321 // (BasicBlockAddr - TableBeginAddr) 1322 // 1323 // For example, a table with entries jumping to basic blocks BB0 and BB1 1324 // would look like: 1325 // LJTI_0_0: 1326 // .word (LBB0 - LJTI_0_0) 1327 // .word (LBB1 - LJTI_0_0) 1328 const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); 1329 1330 if (TM.getRelocationModel() == Reloc::PIC_) 1331 Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol, 1332 OutContext), 1333 OutContext); 1334 OutStreamer.EmitValue(Expr, 4); 1335 } 1336} 1337 1338void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { 1339 unsigned Opcode = MI->getOpcode(); 1340 int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1; 1341 const MachineOperand &MO1 = MI->getOperand(OpNum); 1342 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 1343 unsigned JTI = MO1.getIndex(); 1344 1345 // Emit a label for the jump table. 1346 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 1347 OutStreamer.EmitLabel(JTISymbol); 1348 1349 // Emit each entry of the table. 1350 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 1351 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 1352 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 1353 unsigned OffsetWidth = 4; 1354 if (MI->getOpcode() == ARM::t2TBB) 1355 OffsetWidth = 1; 1356 else if (MI->getOpcode() == ARM::t2TBH) 1357 OffsetWidth = 2; 1358 1359 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 1360 MachineBasicBlock *MBB = JTBBs[i]; 1361 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(), 1362 OutContext); 1363 // If this isn't a TBB or TBH, the entries are direct branch instructions. 1364 if (OffsetWidth == 4) { 1365 MCInst BrInst; 1366 BrInst.setOpcode(ARM::t2B); 1367 BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr)); 1368 OutStreamer.EmitInstruction(BrInst); 1369 continue; 1370 } 1371 // Otherwise it's an offset from the dispatch instruction. Construct an 1372 // MCExpr for the entry. We want a value of the form: 1373 // (BasicBlockAddr - TableBeginAddr) / 2 1374 // 1375 // For example, a TBB table with entries jumping to basic blocks BB0 and BB1 1376 // would look like: 1377 // LJTI_0_0: 1378 // .byte (LBB0 - LJTI_0_0) / 2 1379 // .byte (LBB1 - LJTI_0_0) / 2 1380 const MCExpr *Expr = 1381 MCBinaryExpr::CreateSub(MBBSymbolExpr, 1382 MCSymbolRefExpr::Create(JTISymbol, OutContext), 1383 OutContext); 1384 Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext), 1385 OutContext); 1386 OutStreamer.EmitValue(Expr, OffsetWidth); 1387 } 1388 1389 // Make sure the instruction that follows TBB is 2-byte aligned. 1390 // FIXME: Constant island pass should insert an "ALIGN" instruction instead. 1391 if (MI->getOpcode() == ARM::t2TBB) 1392 EmitAlignment(1); 1393} 1394 1395void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, 1396 raw_ostream &OS) { 1397 unsigned NOps = MI->getNumOperands(); 1398 assert(NOps==4); 1399 OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; 1400 // cast away const; DIetc do not take const operands for some reason. 1401 DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata())); 1402 OS << V.getName(); 1403 OS << " <- "; 1404 // Frame address. Currently handles register +- offset only. 1405 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm()); 1406 OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS); 1407 OS << ']'; 1408 OS << "+"; 1409 printOperand(MI, NOps-2, OS); 1410} 1411 1412void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { 1413 ARMMCInstLower MCInstLowering(OutContext, *Mang, *this); 1414 switch (MI->getOpcode()) { 1415 case ARM::t2MOVi32imm: 1416 assert(0 && "Should be lowered by thumb2it pass"); 1417 default: break; 1418 case ARM::DBG_VALUE: { 1419 if (isVerbose() && OutStreamer.hasRawTextSupport()) { 1420 SmallString<128> TmpStr; 1421 raw_svector_ostream OS(TmpStr); 1422 PrintDebugValueComment(MI, OS); 1423 OutStreamer.EmitRawText(StringRef(OS.str())); 1424 } 1425 return; 1426 } 1427 case ARM::tPICADD: { 1428 // This is a pseudo op for a label + instruction sequence, which looks like: 1429 // LPC0: 1430 // add r0, pc 1431 // This adds the address of LPC0 to r0. 1432 1433 // Emit the label. 1434 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 1435 getFunctionNumber(), MI->getOperand(2).getImm(), 1436 OutContext)); 1437 1438 // Form and emit the add. 1439 MCInst AddInst; 1440 AddInst.setOpcode(ARM::tADDhirr); 1441 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1442 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1443 AddInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1444 // Add predicate operands. 1445 AddInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1446 AddInst.addOperand(MCOperand::CreateReg(0)); 1447 OutStreamer.EmitInstruction(AddInst); 1448 return; 1449 } 1450 case ARM::PICADD: { // FIXME: Remove asm string from td file. 1451 // This is a pseudo op for a label + instruction sequence, which looks like: 1452 // LPC0: 1453 // add r0, pc, r0 1454 // This adds the address of LPC0 to r0. 1455 1456 // Emit the label. 1457 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 1458 getFunctionNumber(), MI->getOperand(2).getImm(), 1459 OutContext)); 1460 1461 // Form and emit the add. 1462 MCInst AddInst; 1463 AddInst.setOpcode(ARM::ADDrr); 1464 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1465 AddInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1466 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); 1467 // Add predicate operands. 1468 AddInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm())); 1469 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg())); 1470 // Add 's' bit operand (always reg0 for this) 1471 AddInst.addOperand(MCOperand::CreateReg(0)); 1472 OutStreamer.EmitInstruction(AddInst); 1473 return; 1474 } 1475 case ARM::PICSTR: 1476 case ARM::PICSTRB: 1477 case ARM::PICSTRH: 1478 case ARM::PICLDR: 1479 case ARM::PICLDRB: 1480 case ARM::PICLDRH: 1481 case ARM::PICLDRSB: 1482 case ARM::PICLDRSH: { 1483 // This is a pseudo op for a label + instruction sequence, which looks like: 1484 // LPC0: 1485 // OP r0, [pc, r0] 1486 // The LCP0 label is referenced by a constant pool entry in order to get 1487 // a PC-relative address at the ldr instruction. 1488 1489 // Emit the label. 1490 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 1491 getFunctionNumber(), MI->getOperand(2).getImm(), 1492 OutContext)); 1493 1494 // Form and emit the load 1495 unsigned Opcode; 1496 switch (MI->getOpcode()) { 1497 default: 1498 llvm_unreachable("Unexpected opcode!"); 1499 case ARM::PICSTR: Opcode = ARM::STR; break; 1500 case ARM::PICSTRB: Opcode = ARM::STRB; break; 1501 case ARM::PICSTRH: Opcode = ARM::STRH; break; 1502 case ARM::PICLDR: Opcode = ARM::LDR; break; 1503 case ARM::PICLDRB: Opcode = ARM::LDRB; break; 1504 case ARM::PICLDRH: Opcode = ARM::LDRH; break; 1505 case ARM::PICLDRSB: Opcode = ARM::LDRSB; break; 1506 case ARM::PICLDRSH: Opcode = ARM::LDRSH; break; 1507 } 1508 MCInst LdStInst; 1509 LdStInst.setOpcode(Opcode); 1510 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1511 LdStInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1512 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); 1513 LdStInst.addOperand(MCOperand::CreateImm(0)); 1514 // Add predicate operands. 1515 LdStInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm())); 1516 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg())); 1517 OutStreamer.EmitInstruction(LdStInst); 1518 1519 return; 1520 } 1521 case ARM::CONSTPOOL_ENTRY: { // FIXME: Remove asm string from td file. 1522 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool 1523 /// in the function. The first operand is the ID# for this instruction, the 1524 /// second is the index into the MachineConstantPool that this is, the third 1525 /// is the size in bytes of this constant pool entry. 1526 unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); 1527 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); 1528 1529 EmitAlignment(2); 1530 OutStreamer.EmitLabel(GetCPISymbol(LabelId)); 1531 1532 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; 1533 if (MCPE.isMachineConstantPoolEntry()) 1534 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 1535 else 1536 EmitGlobalConstant(MCPE.Val.ConstVal); 1537 1538 return; 1539 } 1540 case ARM::MOVi2pieces: { // FIXME: Remove asmstring from td file. 1541 // This is a hack that lowers as a two instruction sequence. 1542 unsigned DstReg = MI->getOperand(0).getReg(); 1543 unsigned ImmVal = (unsigned)MI->getOperand(1).getImm(); 1544 1545 unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal); 1546 unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal); 1547 1548 { 1549 MCInst TmpInst; 1550 TmpInst.setOpcode(ARM::MOVi); 1551 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); 1552 TmpInst.addOperand(MCOperand::CreateImm(SOImmValV1)); 1553 1554 // Predicate. 1555 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1556 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); 1557 1558 TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out 1559 OutStreamer.EmitInstruction(TmpInst); 1560 } 1561 1562 { 1563 MCInst TmpInst; 1564 TmpInst.setOpcode(ARM::ORRri); 1565 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg 1566 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // inreg 1567 TmpInst.addOperand(MCOperand::CreateImm(SOImmValV2)); // so_imm 1568 // Predicate. 1569 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1570 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); 1571 1572 TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out 1573 OutStreamer.EmitInstruction(TmpInst); 1574 } 1575 return; 1576 } 1577 case ARM::MOVi32imm: { // FIXME: Remove asmstring from td file. 1578 // This is a hack that lowers as a two instruction sequence. 1579 unsigned DstReg = MI->getOperand(0).getReg(); 1580 const MachineOperand &MO = MI->getOperand(1); 1581 MCOperand V1, V2; 1582 if (MO.isImm()) { 1583 unsigned ImmVal = (unsigned)MI->getOperand(1).getImm(); 1584 V1 = MCOperand::CreateImm(ImmVal & 65535); 1585 V2 = MCOperand::CreateImm(ImmVal >> 16); 1586 } else if (MO.isGlobal()) { 1587 MCSymbol *Symbol = MCInstLowering.GetGlobalAddressSymbol(MO.getGlobal()); 1588 const MCSymbolRefExpr *SymRef1 = 1589 MCSymbolRefExpr::Create(Symbol, 1590 MCSymbolRefExpr::VK_ARM_LO16, OutContext); 1591 const MCSymbolRefExpr *SymRef2 = 1592 MCSymbolRefExpr::Create(Symbol, 1593 MCSymbolRefExpr::VK_ARM_HI16, OutContext); 1594 V1 = MCOperand::CreateExpr(SymRef1); 1595 V2 = MCOperand::CreateExpr(SymRef2); 1596 } else { 1597 // FIXME: External symbol? 1598 MI->dump(); 1599 llvm_unreachable("cannot handle this operand"); 1600 } 1601 1602 { 1603 MCInst TmpInst; 1604 TmpInst.setOpcode(ARM::MOVi16); 1605 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg 1606 TmpInst.addOperand(V1); // lower16(imm) 1607 1608 // Predicate. 1609 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1610 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); 1611 1612 OutStreamer.EmitInstruction(TmpInst); 1613 } 1614 1615 { 1616 MCInst TmpInst; 1617 TmpInst.setOpcode(ARM::MOVTi16); 1618 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg 1619 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // srcreg 1620 TmpInst.addOperand(V2); // upper16(imm) 1621 1622 // Predicate. 1623 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1624 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); 1625 1626 OutStreamer.EmitInstruction(TmpInst); 1627 } 1628 1629 return; 1630 } 1631 case ARM::t2TBB: 1632 case ARM::t2TBH: 1633 case ARM::t2BR_JT: { 1634 // Lower and emit the instruction itself, then the jump table following it. 1635 MCInst TmpInst; 1636 MCInstLowering.Lower(MI, TmpInst); 1637 OutStreamer.EmitInstruction(TmpInst); 1638 EmitJump2Table(MI); 1639 return; 1640 } 1641 case ARM::tBR_JTr: 1642 case ARM::BR_JTr: 1643 case ARM::BR_JTm: 1644 case ARM::BR_JTadd: { 1645 // Lower and emit the instruction itself, then the jump table following it. 1646 MCInst TmpInst; 1647 MCInstLowering.Lower(MI, TmpInst); 1648 OutStreamer.EmitInstruction(TmpInst); 1649 EmitJumpTable(MI); 1650 return; 1651 } 1652 case ARM::TRAP: { 1653 // Non-Darwin binutils don't yet support the "trap" mnemonic. 1654 // FIXME: Remove this special case when they do. 1655 if (!Subtarget->isTargetDarwin()) { 1656 //.long 0xe7ffdefe ${:comment} trap 1657 uint32_t Val = 0xe7ffdefeUL; 1658 OutStreamer.AddComment("trap"); 1659 OutStreamer.EmitIntValue(Val, 4); 1660 return; 1661 } 1662 break; 1663 } 1664 case ARM::tTRAP: { 1665 // Non-Darwin binutils don't yet support the "trap" mnemonic. 1666 // FIXME: Remove this special case when they do. 1667 if (!Subtarget->isTargetDarwin()) { 1668 //.short 57086 ${:comment} trap 1669 uint16_t Val = 0xdefe; 1670 OutStreamer.AddComment("trap"); 1671 OutStreamer.EmitIntValue(Val, 2); 1672 return; 1673 } 1674 break; 1675 } 1676 case ARM::t2Int_eh_sjlj_setjmp: 1677 case ARM::t2Int_eh_sjlj_setjmp_nofp: 1678 case ARM::tInt_eh_sjlj_setjmp: { // FIXME: Remove asmstring from td file. 1679 // Two incoming args: GPR:$src, GPR:$val 1680 // mov $val, pc 1681 // adds $val, #7 1682 // str $val, [$src, #4] 1683 // movs r0, #0 1684 // b 1f 1685 // movs r0, #1 1686 // 1: 1687 unsigned SrcReg = MI->getOperand(0).getReg(); 1688 unsigned ValReg = MI->getOperand(1).getReg(); 1689 MCSymbol *Label = GetARMSJLJEHLabel(); 1690 { 1691 MCInst TmpInst; 1692 TmpInst.setOpcode(ARM::tMOVgpr2tgpr); 1693 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1694 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1695 // 's' bit operand 1696 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); 1697 OutStreamer.AddComment("eh_setjmp begin"); 1698 OutStreamer.EmitInstruction(TmpInst); 1699 } 1700 { 1701 MCInst TmpInst; 1702 TmpInst.setOpcode(ARM::tADDi3); 1703 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1704 // 's' bit operand 1705 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); 1706 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1707 TmpInst.addOperand(MCOperand::CreateImm(7)); 1708 // Predicate. 1709 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1710 TmpInst.addOperand(MCOperand::CreateReg(0)); 1711 OutStreamer.EmitInstruction(TmpInst); 1712 } 1713 { 1714 MCInst TmpInst; 1715 TmpInst.setOpcode(ARM::tSTR); 1716 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1717 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1718 // The offset immediate is #4. The operand value is scaled by 4 for the 1719 // tSTR instruction. 1720 TmpInst.addOperand(MCOperand::CreateImm(1)); 1721 TmpInst.addOperand(MCOperand::CreateReg(0)); 1722 // Predicate. 1723 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1724 TmpInst.addOperand(MCOperand::CreateReg(0)); 1725 OutStreamer.EmitInstruction(TmpInst); 1726 } 1727 { 1728 MCInst TmpInst; 1729 TmpInst.setOpcode(ARM::tMOVi8); 1730 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); 1731 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); 1732 TmpInst.addOperand(MCOperand::CreateImm(0)); 1733 // Predicate. 1734 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1735 TmpInst.addOperand(MCOperand::CreateReg(0)); 1736 OutStreamer.EmitInstruction(TmpInst); 1737 } 1738 { 1739 const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext); 1740 MCInst TmpInst; 1741 TmpInst.setOpcode(ARM::tB); 1742 TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr)); 1743 OutStreamer.EmitInstruction(TmpInst); 1744 } 1745 { 1746 MCInst TmpInst; 1747 TmpInst.setOpcode(ARM::tMOVi8); 1748 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); 1749 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); 1750 TmpInst.addOperand(MCOperand::CreateImm(1)); 1751 // Predicate. 1752 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1753 TmpInst.addOperand(MCOperand::CreateReg(0)); 1754 OutStreamer.AddComment("eh_setjmp end"); 1755 OutStreamer.EmitInstruction(TmpInst); 1756 } 1757 OutStreamer.EmitLabel(Label); 1758 return; 1759 } 1760 1761 case ARM::Int_eh_sjlj_setjmp_nofp: 1762 case ARM::Int_eh_sjlj_setjmp: { // FIXME: Remove asmstring from td file. 1763 // Two incoming args: GPR:$src, GPR:$val 1764 // add $val, pc, #8 1765 // str $val, [$src, #+4] 1766 // mov r0, #0 1767 // add pc, pc, #0 1768 // mov r0, #1 1769 unsigned SrcReg = MI->getOperand(0).getReg(); 1770 unsigned ValReg = MI->getOperand(1).getReg(); 1771 1772 { 1773 MCInst TmpInst; 1774 TmpInst.setOpcode(ARM::ADDri); 1775 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1776 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1777 TmpInst.addOperand(MCOperand::CreateImm(8)); 1778 // Predicate. 1779 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1780 TmpInst.addOperand(MCOperand::CreateReg(0)); 1781 // 's' bit operand (always reg0 for this). 1782 TmpInst.addOperand(MCOperand::CreateReg(0)); 1783 OutStreamer.AddComment("eh_setjmp begin"); 1784 OutStreamer.EmitInstruction(TmpInst); 1785 } 1786 { 1787 MCInst TmpInst; 1788 TmpInst.setOpcode(ARM::STR); 1789 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1790 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1791 TmpInst.addOperand(MCOperand::CreateReg(0)); 1792 TmpInst.addOperand(MCOperand::CreateImm(4)); 1793 // Predicate. 1794 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1795 TmpInst.addOperand(MCOperand::CreateReg(0)); 1796 OutStreamer.EmitInstruction(TmpInst); 1797 } 1798 { 1799 MCInst TmpInst; 1800 TmpInst.setOpcode(ARM::MOVi); 1801 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); 1802 TmpInst.addOperand(MCOperand::CreateImm(0)); 1803 // Predicate. 1804 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1805 TmpInst.addOperand(MCOperand::CreateReg(0)); 1806 // 's' bit operand (always reg0 for this). 1807 TmpInst.addOperand(MCOperand::CreateReg(0)); 1808 OutStreamer.EmitInstruction(TmpInst); 1809 } 1810 { 1811 MCInst TmpInst; 1812 TmpInst.setOpcode(ARM::ADDri); 1813 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1814 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1815 TmpInst.addOperand(MCOperand::CreateImm(0)); 1816 // Predicate. 1817 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1818 TmpInst.addOperand(MCOperand::CreateReg(0)); 1819 // 's' bit operand (always reg0 for this). 1820 TmpInst.addOperand(MCOperand::CreateReg(0)); 1821 OutStreamer.EmitInstruction(TmpInst); 1822 } 1823 { 1824 MCInst TmpInst; 1825 TmpInst.setOpcode(ARM::MOVi); 1826 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); 1827 TmpInst.addOperand(MCOperand::CreateImm(1)); 1828 // Predicate. 1829 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1830 TmpInst.addOperand(MCOperand::CreateReg(0)); 1831 // 's' bit operand (always reg0 for this). 1832 TmpInst.addOperand(MCOperand::CreateReg(0)); 1833 OutStreamer.AddComment("eh_setjmp end"); 1834 OutStreamer.EmitInstruction(TmpInst); 1835 } 1836 return; 1837 } 1838 case ARM::Int_eh_sjlj_longjmp: { 1839 // ldr sp, [$src, #8] 1840 // ldr $scratch, [$src, #4] 1841 // ldr r7, [$src] 1842 // bx $scratch 1843 unsigned SrcReg = MI->getOperand(0).getReg(); 1844 unsigned ScratchReg = MI->getOperand(1).getReg(); 1845 { 1846 MCInst TmpInst; 1847 TmpInst.setOpcode(ARM::LDR); 1848 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP)); 1849 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1850 TmpInst.addOperand(MCOperand::CreateReg(0)); 1851 TmpInst.addOperand(MCOperand::CreateImm(8)); 1852 // Predicate. 1853 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1854 TmpInst.addOperand(MCOperand::CreateReg(0)); 1855 OutStreamer.EmitInstruction(TmpInst); 1856 } 1857 { 1858 MCInst TmpInst; 1859 TmpInst.setOpcode(ARM::LDR); 1860 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1861 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1862 TmpInst.addOperand(MCOperand::CreateReg(0)); 1863 TmpInst.addOperand(MCOperand::CreateImm(4)); 1864 // Predicate. 1865 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1866 TmpInst.addOperand(MCOperand::CreateReg(0)); 1867 OutStreamer.EmitInstruction(TmpInst); 1868 } 1869 { 1870 MCInst TmpInst; 1871 TmpInst.setOpcode(ARM::LDR); 1872 TmpInst.addOperand(MCOperand::CreateReg(ARM::R7)); 1873 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1874 TmpInst.addOperand(MCOperand::CreateReg(0)); 1875 TmpInst.addOperand(MCOperand::CreateImm(0)); 1876 // Predicate. 1877 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1878 TmpInst.addOperand(MCOperand::CreateReg(0)); 1879 OutStreamer.EmitInstruction(TmpInst); 1880 } 1881 { 1882 MCInst TmpInst; 1883 TmpInst.setOpcode(ARM::BRIND); 1884 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1885 // Predicate. 1886 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1887 TmpInst.addOperand(MCOperand::CreateReg(0)); 1888 OutStreamer.EmitInstruction(TmpInst); 1889 } 1890 return; 1891 } 1892 case ARM::tInt_eh_sjlj_longjmp: { 1893 // ldr $scratch, [$src, #8] 1894 // mov sp, $scratch 1895 // ldr $scratch, [$src, #4] 1896 // ldr r7, [$src] 1897 // bx $scratch 1898 unsigned SrcReg = MI->getOperand(0).getReg(); 1899 unsigned ScratchReg = MI->getOperand(1).getReg(); 1900 { 1901 MCInst TmpInst; 1902 TmpInst.setOpcode(ARM::tLDR); 1903 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1904 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1905 // The offset immediate is #8. The operand value is scaled by 4 for the 1906 // tSTR instruction. 1907 TmpInst.addOperand(MCOperand::CreateImm(2)); 1908 TmpInst.addOperand(MCOperand::CreateReg(0)); 1909 // Predicate. 1910 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1911 TmpInst.addOperand(MCOperand::CreateReg(0)); 1912 OutStreamer.EmitInstruction(TmpInst); 1913 } 1914 { 1915 MCInst TmpInst; 1916 TmpInst.setOpcode(ARM::tMOVtgpr2gpr); 1917 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP)); 1918 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1919 // Predicate. 1920 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1921 TmpInst.addOperand(MCOperand::CreateReg(0)); 1922 OutStreamer.EmitInstruction(TmpInst); 1923 } 1924 { 1925 MCInst TmpInst; 1926 TmpInst.setOpcode(ARM::tLDR); 1927 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1928 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1929 TmpInst.addOperand(MCOperand::CreateImm(1)); 1930 TmpInst.addOperand(MCOperand::CreateReg(0)); 1931 // Predicate. 1932 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1933 TmpInst.addOperand(MCOperand::CreateReg(0)); 1934 OutStreamer.EmitInstruction(TmpInst); 1935 } 1936 { 1937 MCInst TmpInst; 1938 TmpInst.setOpcode(ARM::tLDR); 1939 TmpInst.addOperand(MCOperand::CreateReg(ARM::R7)); 1940 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1941 TmpInst.addOperand(MCOperand::CreateImm(0)); 1942 TmpInst.addOperand(MCOperand::CreateReg(0)); 1943 // Predicate. 1944 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1945 TmpInst.addOperand(MCOperand::CreateReg(0)); 1946 OutStreamer.EmitInstruction(TmpInst); 1947 } 1948 { 1949 MCInst TmpInst; 1950 TmpInst.setOpcode(ARM::tBX_RET_vararg); 1951 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1952 // Predicate. 1953 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1954 TmpInst.addOperand(MCOperand::CreateReg(0)); 1955 OutStreamer.EmitInstruction(TmpInst); 1956 } 1957 return; 1958 } 1959 } 1960 1961 MCInst TmpInst; 1962 MCInstLowering.Lower(MI, TmpInst); 1963 OutStreamer.EmitInstruction(TmpInst); 1964} 1965 1966//===----------------------------------------------------------------------===// 1967// Target Registry Stuff 1968//===----------------------------------------------------------------------===// 1969 1970static MCInstPrinter *createARMMCInstPrinter(const Target &T, 1971 unsigned SyntaxVariant, 1972 const MCAsmInfo &MAI) { 1973 if (SyntaxVariant == 0) 1974 return new ARMInstPrinter(MAI); 1975 return 0; 1976} 1977 1978// Force static initialization. 1979extern "C" void LLVMInitializeARMAsmPrinter() { 1980 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); 1981 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); 1982 1983 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); 1984 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); 1985} 1986 1987