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> 54 using namespace llvm; 55 56 static cl::opt<bool> 57 EnableMCInst("enable-arm-mcinst-printer", cl::Hidden, 58 cl::desc("enable experimental asmprinter gunk in the arm backend")); 59 60 namespace llvm { 61 namespace ARM { 62 enum DW_ISA { 63 DW_ISA_ARM_thumb = 1, 64 DW_ISA_ARM_arm = 2 65 }; 66 } 67 } 68 69 namespace { 70 class ARMAsmPrinter : public AsmPrinter { 71 72 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 73 /// make the right decision when printing asm code for different targets. 74 const ARMSubtarget *Subtarget; 75 76 /// AFI - Keep a pointer to ARMFunctionInfo for the current 77 /// MachineFunction. 78 ARMFunctionInfo *AFI; 79 80 /// MCP - Keep a pointer to constantpool entries of the current 81 /// MachineFunction. 82 const MachineConstantPool *MCP; 83 84 public: 85 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 86 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) { 87 Subtarget = &TM.getSubtarget<ARMSubtarget>(); 88 } 89 90 virtual const char *getPassName() const { 91 return "ARM Assembly Printer"; 92 } 93 94 void printInstructionThroughMCStreamer(const MachineInstr *MI); 95 96 97 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, 98 const char *Modifier = 0); 99 void printSOImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); 100 void printSOImm2PartOperand(const MachineInstr *MI, int OpNum, 101 raw_ostream &O); 102 void printSORegOperand(const MachineInstr *MI, int OpNum, 103 raw_ostream &O); 104 void printAddrMode2Operand(const MachineInstr *MI, int OpNum, 105 raw_ostream &O); 106 void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum, 107 raw_ostream &O); 108 void printAddrMode3Operand(const MachineInstr *MI, int OpNum, 109 raw_ostream &O); 110 void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum, 111 raw_ostream &O); 112 void printAddrMode4Operand(const MachineInstr *MI, int OpNum,raw_ostream &O, 113 const char *Modifier = 0); 114 void printAddrMode5Operand(const MachineInstr *MI, int OpNum,raw_ostream &O, 115 const char *Modifier = 0); 116 void printAddrMode6Operand(const MachineInstr *MI, int OpNum, 117 raw_ostream &O); 118 void printAddrMode6OffsetOperand(const MachineInstr *MI, int OpNum, 119 raw_ostream &O); 120 void printAddrModePCOperand(const MachineInstr *MI, int OpNum, 121 raw_ostream &O, 122 const char *Modifier = 0); 123 void printBitfieldInvMaskImmOperand(const MachineInstr *MI, int OpNum, 124 raw_ostream &O); 125 void printMemBOption(const MachineInstr *MI, int OpNum, 126 raw_ostream &O); 127 void printShiftImmOperand(const MachineInstr *MI, int OpNum, 128 raw_ostream &O); 129 130 void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum, 131 raw_ostream &O); 132 void printThumbITMask(const MachineInstr *MI, int OpNum, raw_ostream &O); 133 void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum, 134 raw_ostream &O); 135 void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum, 136 raw_ostream &O, 137 unsigned Scale); 138 void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum, 139 raw_ostream &O); 140 void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum, 141 raw_ostream &O); 142 void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum, 143 raw_ostream &O); 144 void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum, 145 raw_ostream &O); 146 147 void printT2SOOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); 148 void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum, 149 raw_ostream &O); 150 void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum, 151 raw_ostream &O); 152 void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum, 153 raw_ostream &O); 154 void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum, 155 raw_ostream &O); 156 void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum, 157 raw_ostream &O) {} 158 void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum, 159 raw_ostream &O); 160 161 void printCPSOptionOperand(const MachineInstr *MI, int OpNum, 162 raw_ostream &O) {} 163 void printMSRMaskOperand(const MachineInstr *MI, int OpNum, 164 raw_ostream &O) {} 165 void printNegZeroOperand(const MachineInstr *MI, int OpNum, 166 raw_ostream &O) {} 167 void printPredicateOperand(const MachineInstr *MI, int OpNum, 168 raw_ostream &O); 169 void printMandatoryPredicateOperand(const MachineInstr *MI, int OpNum, 170 raw_ostream &O); 171 void printSBitModifierOperand(const MachineInstr *MI, int OpNum, 172 raw_ostream &O); 173 void printPCLabel(const MachineInstr *MI, int OpNum, 174 raw_ostream &O); 175 void printRegisterList(const MachineInstr *MI, int OpNum, 176 raw_ostream &O); 177 void printCPInstOperand(const MachineInstr *MI, int OpNum, 178 raw_ostream &O, 179 const char *Modifier); 180 void printJTBlockOperand(const MachineInstr *MI, int OpNum, 181 raw_ostream &O); 182 void printJT2BlockOperand(const MachineInstr *MI, int OpNum, 183 raw_ostream &O); 184 void printTBAddrMode(const MachineInstr *MI, int OpNum, 185 raw_ostream &O); 186 void printNoHashImmediate(const MachineInstr *MI, int OpNum, 187 raw_ostream &O); 188 void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum, 189 raw_ostream &O); 190 void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum, 191 raw_ostream &O); 192 void printNEONModImmOperand(const MachineInstr *MI, int OpNum, 193 raw_ostream &O); 194 195 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 196 unsigned AsmVariant, const char *ExtraCode, 197 raw_ostream &O); 198 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, 199 unsigned AsmVariant, 200 const char *ExtraCode, raw_ostream &O); 201 202 void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen 203 static const char *getRegisterName(unsigned RegNo); 204 205 virtual void EmitInstruction(const MachineInstr *MI); 206 bool runOnMachineFunction(MachineFunction &F); 207 208 virtual void EmitConstantPool() {} // we emit constant pools customly! 209 virtual void EmitFunctionEntryLabel(); 210 void EmitStartOfAsmFile(Module &M); 211 void EmitEndOfAsmFile(Module &M); 212 213 MachineLocation getDebugValueLocation(const MachineInstr *MI) const { 214 MachineLocation Location; 215 assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); 216 // Frame address. Currently handles register +- offset only. 217 if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) 218 Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); 219 else { 220 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); 221 } 222 return Location; 223 } 224 225 virtual unsigned getISAEncoding() { 226 // ARM/Darwin adds ISA to the DWARF info for each function. 227 if (!Subtarget->isTargetDarwin()) 228 return 0; 229 return Subtarget->isThumb() ? 230 llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm; 231 } 232 233 MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2, 234 const MachineBasicBlock *MBB) const; 235 MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) 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 301 void 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 /// 322 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 323 AFI = MF.getInfo<ARMFunctionInfo>(); 324 MCP = MF.getConstantPool(); 325 326 return AsmPrinter::runOnMachineFunction(MF); 327 } 328 329 void 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, "dregpair") == 0) { 341 unsigned DRegLo = TM.getRegisterInfo()->getSubReg(Reg, ARM::dsub_0); 342 unsigned DRegHi = TM.getRegisterInfo()->getSubReg(Reg, ARM::dsub_1); 343 O << '{' 344 << getRegisterName(DRegLo) << ", " << getRegisterName(DRegHi) 345 << '}'; 346 } else if (Modifier && strcmp(Modifier, "lane") == 0) { 347 unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg); 348 unsigned DReg = 349 TM.getRegisterInfo()->getMatchingSuperReg(Reg, 350 RegNum & 1 ? ARM::ssub_1 : ARM::ssub_0, &ARM::DPR_VFP2RegClass); 351 O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']'; 352 } else { 353 assert(!MO.getSubReg() && "Subregs should be eliminated!"); 354 O << getRegisterName(Reg); 355 } 356 break; 357 } 358 case MachineOperand::MO_Immediate: { 359 int64_t Imm = MO.getImm(); 360 O << '#'; 361 if ((Modifier && strcmp(Modifier, "lo16") == 0) || 362 (TF & ARMII::MO_LO16)) 363 O << ":lower16:"; 364 else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 365 (TF & ARMII::MO_HI16)) 366 O << ":upper16:"; 367 O << Imm; 368 break; 369 } 370 case MachineOperand::MO_MachineBasicBlock: 371 O << *MO.getMBB()->getSymbol(); 372 return; 373 case MachineOperand::MO_GlobalAddress: { 374 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 375 const GlobalValue *GV = MO.getGlobal(); 376 377 if ((Modifier && strcmp(Modifier, "lo16") == 0) || 378 (TF & ARMII::MO_LO16)) 379 O << ":lower16:"; 380 else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 381 (TF & ARMII::MO_HI16)) 382 O << ":upper16:"; 383 O << *Mang->getSymbol(GV); 384 385 printOffset(MO.getOffset(), O); 386 387 if (isCallOp && Subtarget->isTargetELF() && 388 TM.getRelocationModel() == Reloc::PIC_) 389 O << "(PLT)"; 390 break; 391 } 392 case MachineOperand::MO_ExternalSymbol: { 393 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 394 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 395 396 if (isCallOp && Subtarget->isTargetELF() && 397 TM.getRelocationModel() == Reloc::PIC_) 398 O << "(PLT)"; 399 break; 400 } 401 case MachineOperand::MO_ConstantPoolIndex: 402 O << *GetCPISymbol(MO.getIndex()); 403 break; 404 case MachineOperand::MO_JumpTableIndex: 405 O << *GetJTISymbol(MO.getIndex()); 406 break; 407 } 408 } 409 410 static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm, 411 const MCAsmInfo *MAI) { 412 // Break it up into two parts that make up a shifter immediate. 413 V = ARM_AM::getSOImmVal(V); 414 assert(V != -1 && "Not a valid so_imm value!"); 415 416 unsigned Imm = ARM_AM::getSOImmValImm(V); 417 unsigned Rot = ARM_AM::getSOImmValRot(V); 418 419 // Print low-level immediate formation info, per 420 // A5.1.3: "Data-processing operands - Immediate". 421 if (Rot) { 422 O << "#" << Imm << ", " << Rot; 423 // Pretty printed version. 424 if (VerboseAsm) { 425 O << "\t" << MAI->getCommentString() << ' '; 426 O << (int)ARM_AM::rotr32(Imm, Rot); 427 } 428 } else { 429 O << "#" << Imm; 430 } 431 } 432 433 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit 434 /// immediate in bits 0-7. 435 void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum, 436 raw_ostream &O) { 437 const MachineOperand &MO = MI->getOperand(OpNum); 438 assert(MO.isImm() && "Not a valid so_imm value!"); 439 printSOImm(O, MO.getImm(), isVerbose(), MAI); 440 } 441 442 /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' 443 /// followed by an 'orr' to materialize. 444 void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum, 445 raw_ostream &O) { 446 const MachineOperand &MO = MI->getOperand(OpNum); 447 assert(MO.isImm() && "Not a valid so_imm value!"); 448 unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm()); 449 unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm()); 450 printSOImm(O, V1, isVerbose(), MAI); 451 O << "\n\torr"; 452 printPredicateOperand(MI, 2, O); 453 O << "\t"; 454 printOperand(MI, 0, O); 455 O << ", "; 456 printOperand(MI, 0, O); 457 O << ", "; 458 printSOImm(O, V2, isVerbose(), MAI); 459 } 460 461 // so_reg is a 4-operand unit corresponding to register forms of the A5.1 462 // "Addressing Mode 1 - Data-processing operands" forms. This includes: 463 // REG 0 0 - e.g. R5 464 // REG REG 0,SH_OPC - e.g. R5, ROR R3 465 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3 466 void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op, 467 raw_ostream &O) { 468 const MachineOperand &MO1 = MI->getOperand(Op); 469 const MachineOperand &MO2 = MI->getOperand(Op+1); 470 const MachineOperand &MO3 = MI->getOperand(Op+2); 471 472 O << getRegisterName(MO1.getReg()); 473 474 // Print the shift opc. 475 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm()); 476 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 477 if (MO2.getReg()) { 478 O << ' ' << getRegisterName(MO2.getReg()); 479 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 480 } else if (ShOpc != ARM_AM::rrx) { 481 O << " #" << ARM_AM::getSORegOffset(MO3.getImm()); 482 } 483 } 484 485 void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op, 486 raw_ostream &O) { 487 const MachineOperand &MO1 = MI->getOperand(Op); 488 const MachineOperand &MO2 = MI->getOperand(Op+1); 489 const MachineOperand &MO3 = MI->getOperand(Op+2); 490 491 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 492 printOperand(MI, Op, O); 493 return; 494 } 495 496 O << "[" << getRegisterName(MO1.getReg()); 497 498 if (!MO2.getReg()) { 499 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. 500 O << ", #" 501 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 502 << ARM_AM::getAM2Offset(MO3.getImm()); 503 O << "]"; 504 return; 505 } 506 507 O << ", " 508 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) 509 << getRegisterName(MO2.getReg()); 510 511 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 512 O << ", " 513 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) 514 << " #" << ShImm; 515 O << "]"; 516 } 517 518 void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op, 519 raw_ostream &O) { 520 const MachineOperand &MO1 = MI->getOperand(Op); 521 const MachineOperand &MO2 = MI->getOperand(Op+1); 522 523 if (!MO1.getReg()) { 524 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); 525 O << "#" 526 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 527 << ImmOffs; 528 return; 529 } 530 531 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) 532 << getRegisterName(MO1.getReg()); 533 534 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) 535 O << ", " 536 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) 537 << " #" << ShImm; 538 } 539 540 void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op, 541 raw_ostream &O) { 542 const MachineOperand &MO1 = MI->getOperand(Op); 543 const MachineOperand &MO2 = MI->getOperand(Op+1); 544 const MachineOperand &MO3 = MI->getOperand(Op+2); 545 546 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); 547 O << "[" << getRegisterName(MO1.getReg()); 548 549 if (MO2.getReg()) { 550 O << ", " 551 << (char)ARM_AM::getAM3Op(MO3.getImm()) 552 << getRegisterName(MO2.getReg()) 553 << "]"; 554 return; 555 } 556 557 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) 558 O << ", #" 559 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) 560 << ImmOffs; 561 O << "]"; 562 } 563 564 void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op, 565 raw_ostream &O){ 566 const MachineOperand &MO1 = MI->getOperand(Op); 567 const MachineOperand &MO2 = MI->getOperand(Op+1); 568 569 if (MO1.getReg()) { 570 O << (char)ARM_AM::getAM3Op(MO2.getImm()) 571 << getRegisterName(MO1.getReg()); 572 return; 573 } 574 575 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); 576 O << "#" 577 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) 578 << ImmOffs; 579 } 580 581 void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op, 582 raw_ostream &O, 583 const char *Modifier) { 584 const MachineOperand &MO2 = MI->getOperand(Op+1); 585 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); 586 if (Modifier && strcmp(Modifier, "submode") == 0) { 587 O << ARM_AM::getAMSubModeStr(Mode); 588 } else if (Modifier && strcmp(Modifier, "wide") == 0) { 589 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); 590 if (Mode == ARM_AM::ia) 591 O << ".w"; 592 } else { 593 printOperand(MI, Op, O); 594 } 595 } 596 597 void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, 598 raw_ostream &O, 599 const char *Modifier) { 600 const MachineOperand &MO1 = MI->getOperand(Op); 601 const MachineOperand &MO2 = MI->getOperand(Op+1); 602 603 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 604 printOperand(MI, Op, O); 605 return; 606 } 607 608 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); 609 610 O << "[" << getRegisterName(MO1.getReg()); 611 612 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { 613 O << ", #" 614 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm())) 615 << ImmOffs*4; 616 } 617 O << "]"; 618 } 619 620 void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op, 621 raw_ostream &O) { 622 const MachineOperand &MO1 = MI->getOperand(Op); 623 const MachineOperand &MO2 = MI->getOperand(Op+1); 624 625 O << "[" << getRegisterName(MO1.getReg()); 626 if (MO2.getImm()) { 627 // FIXME: Both darwin as and GNU as violate ARM docs here. 628 O << ", :" << (MO2.getImm() << 3); 629 } 630 O << "]"; 631 } 632 633 void ARMAsmPrinter::printAddrMode6OffsetOperand(const MachineInstr *MI, int Op, 634 raw_ostream &O){ 635 const MachineOperand &MO = MI->getOperand(Op); 636 if (MO.getReg() == 0) 637 O << "!"; 638 else 639 O << ", " << getRegisterName(MO.getReg()); 640 } 641 642 void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op, 643 raw_ostream &O, 644 const char *Modifier) { 645 if (Modifier && strcmp(Modifier, "label") == 0) { 646 printPCLabel(MI, Op+1, O); 647 return; 648 } 649 650 const MachineOperand &MO1 = MI->getOperand(Op); 651 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); 652 O << "[pc, " << getRegisterName(MO1.getReg()) << "]"; 653 } 654 655 void 656 ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op, 657 raw_ostream &O) { 658 const MachineOperand &MO = MI->getOperand(Op); 659 uint32_t v = ~MO.getImm(); 660 int32_t lsb = CountTrailingZeros_32(v); 661 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; 662 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); 663 O << "#" << lsb << ", #" << width; 664 } 665 666 void 667 ARMAsmPrinter::printMemBOption(const MachineInstr *MI, int OpNum, 668 raw_ostream &O) { 669 unsigned val = MI->getOperand(OpNum).getImm(); 670 O << ARM_MB::MemBOptToString(val); 671 } 672 673 void ARMAsmPrinter::printShiftImmOperand(const MachineInstr *MI, int OpNum, 674 raw_ostream &O) { 675 unsigned ShiftOp = MI->getOperand(OpNum).getImm(); 676 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); 677 switch (Opc) { 678 case ARM_AM::no_shift: 679 return; 680 case ARM_AM::lsl: 681 O << ", lsl #"; 682 break; 683 case ARM_AM::asr: 684 O << ", asr #"; 685 break; 686 default: 687 assert(0 && "unexpected shift opcode for shift immediate operand"); 688 } 689 O << ARM_AM::getSORegOffset(ShiftOp); 690 } 691 692 //===--------------------------------------------------------------------===// 693 694 void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op, 695 raw_ostream &O) { 696 O << "#" << MI->getOperand(Op).getImm() * 4; 697 } 698 699 void 700 ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op, 701 raw_ostream &O) { 702 // (3 - the number of trailing zeros) is the number of then / else. 703 unsigned Mask = MI->getOperand(Op).getImm(); 704 unsigned CondBit0 = Mask >> 4 & 1; 705 unsigned NumTZ = CountTrailingZeros_32(Mask); 706 assert(NumTZ <= 3 && "Invalid IT mask!"); 707 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { 708 bool T = ((Mask >> Pos) & 1) == CondBit0; 709 if (T) 710 O << 't'; 711 else 712 O << 'e'; 713 } 714 } 715 716 void 717 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op, 718 raw_ostream &O) { 719 const MachineOperand &MO1 = MI->getOperand(Op); 720 const MachineOperand &MO2 = MI->getOperand(Op+1); 721 O << "[" << getRegisterName(MO1.getReg()); 722 O << ", " << getRegisterName(MO2.getReg()) << "]"; 723 } 724 725 void 726 ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, 727 raw_ostream &O, 728 unsigned Scale) { 729 const MachineOperand &MO1 = MI->getOperand(Op); 730 const MachineOperand &MO2 = MI->getOperand(Op+1); 731 const MachineOperand &MO3 = MI->getOperand(Op+2); 732 733 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. 734 printOperand(MI, Op, O); 735 return; 736 } 737 738 O << "[" << getRegisterName(MO1.getReg()); 739 if (MO3.getReg()) 740 O << ", " << getRegisterName(MO3.getReg()); 741 else if (unsigned ImmOffs = MO2.getImm()) 742 O << ", #" << ImmOffs * Scale; 743 O << "]"; 744 } 745 746 void 747 ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op, 748 raw_ostream &O) { 749 printThumbAddrModeRI5Operand(MI, Op, O, 1); 750 } 751 void 752 ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op, 753 raw_ostream &O) { 754 printThumbAddrModeRI5Operand(MI, Op, O, 2); 755 } 756 void 757 ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op, 758 raw_ostream &O) { 759 printThumbAddrModeRI5Operand(MI, Op, O, 4); 760 } 761 762 void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op, 763 raw_ostream &O) { 764 const MachineOperand &MO1 = MI->getOperand(Op); 765 const MachineOperand &MO2 = MI->getOperand(Op+1); 766 O << "[" << getRegisterName(MO1.getReg()); 767 if (unsigned ImmOffs = MO2.getImm()) 768 O << ", #" << ImmOffs*4; 769 O << "]"; 770 } 771 772 //===--------------------------------------------------------------------===// 773 774 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 775 // register with shift forms. 776 // REG 0 0 - e.g. R5 777 // REG IMM, SH_OPC - e.g. R5, LSL #3 778 void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum, 779 raw_ostream &O) { 780 const MachineOperand &MO1 = MI->getOperand(OpNum); 781 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 782 783 unsigned Reg = MO1.getReg(); 784 assert(TargetRegisterInfo::isPhysicalRegister(Reg)); 785 O << getRegisterName(Reg); 786 787 // Print the shift opc. 788 assert(MO2.isImm() && "Not a valid t2_so_reg value!"); 789 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm()); 790 O << ", " << ARM_AM::getShiftOpcStr(ShOpc); 791 if (ShOpc != ARM_AM::rrx) 792 O << " #" << ARM_AM::getSORegOffset(MO2.getImm()); 793 } 794 795 void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI, 796 int OpNum, 797 raw_ostream &O) { 798 const MachineOperand &MO1 = MI->getOperand(OpNum); 799 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 800 801 O << "[" << getRegisterName(MO1.getReg()); 802 803 unsigned OffImm = MO2.getImm(); 804 if (OffImm) // Don't print +0. 805 O << ", #" << OffImm; 806 O << "]"; 807 } 808 809 void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI, 810 int OpNum, 811 raw_ostream &O) { 812 const MachineOperand &MO1 = MI->getOperand(OpNum); 813 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 814 815 O << "[" << getRegisterName(MO1.getReg()); 816 817 int32_t OffImm = (int32_t)MO2.getImm(); 818 // Don't print +0. 819 if (OffImm < 0) 820 O << ", #-" << -OffImm; 821 else if (OffImm > 0) 822 O << ", #" << OffImm; 823 O << "]"; 824 } 825 826 void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI, 827 int OpNum, 828 raw_ostream &O) { 829 const MachineOperand &MO1 = MI->getOperand(OpNum); 830 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 831 832 O << "[" << getRegisterName(MO1.getReg()); 833 834 int32_t OffImm = (int32_t)MO2.getImm() / 4; 835 // Don't print +0. 836 if (OffImm < 0) 837 O << ", #-" << -OffImm * 4; 838 else if (OffImm > 0) 839 O << ", #" << OffImm * 4; 840 O << "]"; 841 } 842 843 void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, 844 int OpNum, 845 raw_ostream &O) { 846 const MachineOperand &MO1 = MI->getOperand(OpNum); 847 int32_t OffImm = (int32_t)MO1.getImm(); 848 // Don't print +0. 849 if (OffImm < 0) 850 O << "#-" << -OffImm; 851 else if (OffImm > 0) 852 O << "#" << OffImm; 853 } 854 855 void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI, 856 int OpNum, 857 raw_ostream &O) { 858 const MachineOperand &MO1 = MI->getOperand(OpNum); 859 const MachineOperand &MO2 = MI->getOperand(OpNum+1); 860 const MachineOperand &MO3 = MI->getOperand(OpNum+2); 861 862 O << "[" << getRegisterName(MO1.getReg()); 863 864 assert(MO2.getReg() && "Invalid so_reg load / store address!"); 865 O << ", " << getRegisterName(MO2.getReg()); 866 867 unsigned ShAmt = MO3.getImm(); 868 if (ShAmt) { 869 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); 870 O << ", lsl #" << ShAmt; 871 } 872 O << "]"; 873 } 874 875 876 //===--------------------------------------------------------------------===// 877 878 void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum, 879 raw_ostream &O) { 880 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 881 if (CC != ARMCC::AL) 882 O << ARMCondCodeToString(CC); 883 } 884 885 void ARMAsmPrinter::printMandatoryPredicateOperand(const MachineInstr *MI, 886 int OpNum, 887 raw_ostream &O) { 888 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); 889 O << ARMCondCodeToString(CC); 890 } 891 892 void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum, 893 raw_ostream &O){ 894 unsigned Reg = MI->getOperand(OpNum).getReg(); 895 if (Reg) { 896 assert(Reg == ARM::CPSR && "Expect ARM CPSR register!"); 897 O << 's'; 898 } 899 } 900 901 void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum, 902 raw_ostream &O) { 903 int Id = (int)MI->getOperand(OpNum).getImm(); 904 O << MAI->getPrivateGlobalPrefix() 905 << "PC" << getFunctionNumber() << "_" << Id; 906 } 907 908 void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum, 909 raw_ostream &O) { 910 O << "{"; 911 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { 912 if (MI->getOperand(i).isImplicit()) 913 continue; 914 if ((int)i != OpNum) O << ", "; 915 printOperand(MI, i, O); 916 } 917 O << "}"; 918 } 919 920 void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, 921 raw_ostream &O, const char *Modifier) { 922 assert(Modifier && "This operand only works with a modifier!"); 923 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the 924 // data itself. 925 if (!strcmp(Modifier, "label")) { 926 unsigned ID = MI->getOperand(OpNum).getImm(); 927 OutStreamer.EmitLabel(GetCPISymbol(ID)); 928 } else { 929 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); 930 unsigned CPI = MI->getOperand(OpNum).getIndex(); 931 932 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; 933 934 if (MCPE.isMachineConstantPoolEntry()) { 935 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 936 } else { 937 EmitGlobalConstant(MCPE.Val.ConstVal); 938 } 939 } 940 } 941 942 MCSymbol *ARMAsmPrinter:: 943 GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2, 944 const MachineBasicBlock *MBB) const { 945 SmallString<60> Name; 946 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() 947 << getFunctionNumber() << '_' << uid << '_' << uid2 948 << "_set_" << MBB->getNumber(); 949 return OutContext.GetOrCreateSymbol(Name.str()); 950 } 951 952 MCSymbol *ARMAsmPrinter:: 953 GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const { 954 SmallString<60> Name; 955 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI" 956 << getFunctionNumber() << '_' << uid << '_' << uid2; 957 return OutContext.GetOrCreateSymbol(Name.str()); 958 } 959 960 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum, 961 raw_ostream &O) { 962 assert(!Subtarget->isThumb2() && "Thumb2 should use double-jump jumptables!"); 963 964 const MachineOperand &MO1 = MI->getOperand(OpNum); 965 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 966 967 unsigned JTI = MO1.getIndex(); 968 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 969 // Can't use EmitLabel until instprinter happens, label comes out in the wrong 970 // order. 971 O << "\n" << *JTISymbol << ":\n"; 972 973 const char *JTEntryDirective = MAI->getData32bitsDirective(); 974 975 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 976 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 977 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 978 bool UseSet= MAI->hasSetDirective() && TM.getRelocationModel() == Reloc::PIC_; 979 SmallPtrSet<MachineBasicBlock*, 8> JTSets; 980 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 981 MachineBasicBlock *MBB = JTBBs[i]; 982 bool isNew = JTSets.insert(MBB); 983 984 if (UseSet && isNew) { 985 O << "\t.set\t" 986 << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB) << ',' 987 << *MBB->getSymbol() << '-' << *JTISymbol << '\n'; 988 } 989 990 O << JTEntryDirective << ' '; 991 if (UseSet) 992 O << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB); 993 else if (TM.getRelocationModel() == Reloc::PIC_) 994 O << *MBB->getSymbol() << '-' << *JTISymbol; 995 else 996 O << *MBB->getSymbol(); 997 998 if (i != e-1) 999 O << '\n'; 1000 } 1001 } 1002 1003 void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum, 1004 raw_ostream &O) { 1005 const MachineOperand &MO1 = MI->getOperand(OpNum); 1006 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 1007 unsigned JTI = MO1.getIndex(); 1008 1009 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 1010 1011 // Can't use EmitLabel until instprinter happens, label comes out in the wrong 1012 // order. 1013 O << "\n" << *JTISymbol << ":\n"; 1014 1015 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 1016 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 1017 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 1018 bool ByteOffset = false, HalfWordOffset = false; 1019 if (MI->getOpcode() == ARM::t2TBB) 1020 ByteOffset = true; 1021 else if (MI->getOpcode() == ARM::t2TBH) 1022 HalfWordOffset = true; 1023 1024 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 1025 MachineBasicBlock *MBB = JTBBs[i]; 1026 if (ByteOffset) 1027 O << MAI->getData8bitsDirective(); 1028 else if (HalfWordOffset) 1029 O << MAI->getData16bitsDirective(); 1030 1031 if (ByteOffset || HalfWordOffset) 1032 O << '(' << *MBB->getSymbol() << "-" << *JTISymbol << ")/2"; 1033 else 1034 O << "\tb.w " << *MBB->getSymbol(); 1035 1036 if (i != e-1) 1037 O << '\n'; 1038 } 1039 } 1040 1041 void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum, 1042 raw_ostream &O) { 1043 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg()); 1044 if (MI->getOpcode() == ARM::t2TBH) 1045 O << ", lsl #1"; 1046 O << ']'; 1047 } 1048 1049 void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum, 1050 raw_ostream &O) { 1051 O << MI->getOperand(OpNum).getImm(); 1052 } 1053 1054 void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum, 1055 raw_ostream &O) { 1056 const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); 1057 O << '#' << FP->getValueAPF().convertToFloat(); 1058 if (isVerbose()) { 1059 O << "\t\t" << MAI->getCommentString() << ' '; 1060 WriteAsOperand(O, FP, /*PrintType=*/false); 1061 } 1062 } 1063 1064 void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum, 1065 raw_ostream &O) { 1066 const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); 1067 O << '#' << FP->getValueAPF().convertToDouble(); 1068 if (isVerbose()) { 1069 O << "\t\t" << MAI->getCommentString() << ' '; 1070 WriteAsOperand(O, FP, /*PrintType=*/false); 1071 } 1072 } 1073 1074 void ARMAsmPrinter::printNEONModImmOperand(const MachineInstr *MI, int OpNum, 1075 raw_ostream &O) { 1076 unsigned EncodedImm = MI->getOperand(OpNum).getImm(); 1077 unsigned EltBits; 1078 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); 1079 O << "#0x" << utohexstr(Val); 1080 } 1081 1082 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 1083 unsigned AsmVariant, const char *ExtraCode, 1084 raw_ostream &O) { 1085 // Does this asm operand have a single letter operand modifier? 1086 if (ExtraCode && ExtraCode[0]) { 1087 if (ExtraCode[1] != 0) return true; // Unknown modifier. 1088 1089 switch (ExtraCode[0]) { 1090 default: return true; // Unknown modifier. 1091 case 'a': // Print as a memory address. 1092 if (MI->getOperand(OpNum).isReg()) { 1093 O << "[" << getRegisterName(MI->getOperand(OpNum).getReg()) << "]"; 1094 return false; 1095 } 1096 // Fallthrough 1097 case 'c': // Don't print "#" before an immediate operand. 1098 if (!MI->getOperand(OpNum).isImm()) 1099 return true; 1100 printNoHashImmediate(MI, OpNum, O); 1101 return false; 1102 case 'P': // Print a VFP double precision register. 1103 case 'q': // Print a NEON quad precision register. 1104 printOperand(MI, OpNum, O); 1105 return false; 1106 case 'Q': 1107 case 'R': 1108 case 'H': 1109 report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!"); 1110 return true; 1111 } 1112 } 1113 1114 printOperand(MI, OpNum, O); 1115 return false; 1116 } 1117 1118 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 1119 unsigned OpNum, unsigned AsmVariant, 1120 const char *ExtraCode, 1121 raw_ostream &O) { 1122 if (ExtraCode && ExtraCode[0]) 1123 return true; // Unknown modifier. 1124 1125 const MachineOperand &MO = MI->getOperand(OpNum); 1126 assert(MO.isReg() && "unexpected inline asm memory operand"); 1127 O << "[" << getRegisterName(MO.getReg()) << "]"; 1128 return false; 1129 } 1130 1131 void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { 1132 if (EnableMCInst) { 1133 printInstructionThroughMCStreamer(MI); 1134 return; 1135 } 1136 1137 if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY) 1138 EmitAlignment(2); 1139 1140 SmallString<128> Str; 1141 raw_svector_ostream OS(Str); 1142 if (MI->getOpcode() == ARM::DBG_VALUE) { 1143 unsigned NOps = MI->getNumOperands(); 1144 assert(NOps==4); 1145 OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; 1146 // cast away const; DIetc do not take const operands for some reason. 1147 DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata())); 1148 OS << V.getName(); 1149 OS << " <- "; 1150 // Frame address. Currently handles register +- offset only. 1151 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm()); 1152 OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS); 1153 OS << ']'; 1154 OS << "+"; 1155 printOperand(MI, NOps-2, OS); 1156 OutStreamer.EmitRawText(OS.str()); 1157 return; 1158 } 1159 1160 printInstruction(MI, OS); 1161 OutStreamer.EmitRawText(OS.str()); 1162 1163 // Make sure the instruction that follows TBB is 2-byte aligned. 1164 // FIXME: Constant island pass should insert an "ALIGN" instruction instead. 1165 if (MI->getOpcode() == ARM::t2TBB) 1166 EmitAlignment(1); 1167 } 1168 1169 void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { 1170 if (Subtarget->isTargetDarwin()) { 1171 Reloc::Model RelocM = TM.getRelocationModel(); 1172 if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) { 1173 // Declare all the text sections up front (before the DWARF sections 1174 // emitted by AsmPrinter::doInitialization) so the assembler will keep 1175 // them together at the beginning of the object file. This helps 1176 // avoid out-of-range branches that are due a fundamental limitation of 1177 // the way symbol offsets are encoded with the current Darwin ARM 1178 // relocations. 1179 const TargetLoweringObjectFileMachO &TLOFMacho = 1180 static_cast<const TargetLoweringObjectFileMachO &>( 1181 getObjFileLowering()); 1182 OutStreamer.SwitchSection(TLOFMacho.getTextSection()); 1183 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); 1184 OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection()); 1185 if (RelocM == Reloc::DynamicNoPIC) { 1186 const MCSection *sect = 1187 OutContext.getMachOSection("__TEXT", "__symbol_stub4", 1188 MCSectionMachO::S_SYMBOL_STUBS, 1189 12, SectionKind::getText()); 1190 OutStreamer.SwitchSection(sect); 1191 } else { 1192 const MCSection *sect = 1193 OutContext.getMachOSection("__TEXT", "__picsymbolstub4", 1194 MCSectionMachO::S_SYMBOL_STUBS, 1195 16, SectionKind::getText()); 1196 OutStreamer.SwitchSection(sect); 1197 } 1198 const MCSection *StaticInitSect = 1199 OutContext.getMachOSection("__TEXT", "__StaticInit", 1200 MCSectionMachO::S_REGULAR | 1201 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 1202 SectionKind::getText()); 1203 OutStreamer.SwitchSection(StaticInitSect); 1204 } 1205 } 1206 1207 // Use unified assembler syntax. 1208 OutStreamer.EmitRawText(StringRef("\t.syntax unified")); 1209 1210 // Emit ARM Build Attributes 1211 if (Subtarget->isTargetELF()) { 1212 // CPU Type 1213 std::string CPUString = Subtarget->getCPUString(); 1214 if (CPUString != "generic") 1215 OutStreamer.EmitRawText("\t.cpu " + Twine(CPUString)); 1216 1217 // FIXME: Emit FPU type 1218 if (Subtarget->hasVFP2()) 1219 OutStreamer.EmitRawText("\t.eabi_attribute " + 1220 Twine(ARMBuildAttrs::VFP_arch) + ", 2"); 1221 1222 // Signal various FP modes. 1223 if (!UnsafeFPMath) { 1224 OutStreamer.EmitRawText("\t.eabi_attribute " + 1225 Twine(ARMBuildAttrs::ABI_FP_denormal) + ", 1"); 1226 OutStreamer.EmitRawText("\t.eabi_attribute " + 1227 Twine(ARMBuildAttrs::ABI_FP_exceptions) + ", 1"); 1228 } 1229 1230 if (NoInfsFPMath && NoNaNsFPMath) 1231 OutStreamer.EmitRawText("\t.eabi_attribute " + 1232 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 1"); 1233 else 1234 OutStreamer.EmitRawText("\t.eabi_attribute " + 1235 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 3"); 1236 1237 // 8-bytes alignment stuff. 1238 OutStreamer.EmitRawText("\t.eabi_attribute " + 1239 Twine(ARMBuildAttrs::ABI_align8_needed) + ", 1"); 1240 OutStreamer.EmitRawText("\t.eabi_attribute " + 1241 Twine(ARMBuildAttrs::ABI_align8_preserved) + ", 1"); 1242 1243 // Hard float. Use both S and D registers and conform to AAPCS-VFP. 1244 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) { 1245 OutStreamer.EmitRawText("\t.eabi_attribute " + 1246 Twine(ARMBuildAttrs::ABI_HardFP_use) + ", 3"); 1247 OutStreamer.EmitRawText("\t.eabi_attribute " + 1248 Twine(ARMBuildAttrs::ABI_VFP_args) + ", 1"); 1249 } 1250 // FIXME: Should we signal R9 usage? 1251 } 1252 } 1253 1254 1255 void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { 1256 if (Subtarget->isTargetDarwin()) { 1257 // All darwin targets use mach-o. 1258 const TargetLoweringObjectFileMachO &TLOFMacho = 1259 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 1260 MachineModuleInfoMachO &MMIMacho = 1261 MMI->getObjFileInfo<MachineModuleInfoMachO>(); 1262 1263 // Output non-lazy-pointers for external and common global variables. 1264 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); 1265 1266 if (!Stubs.empty()) { 1267 // Switch with ".non_lazy_symbol_pointer" directive. 1268 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); 1269 EmitAlignment(2); 1270 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 1271 // L_foo$stub: 1272 OutStreamer.EmitLabel(Stubs[i].first); 1273 // .indirect_symbol _foo 1274 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; 1275 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol); 1276 1277 if (MCSym.getInt()) 1278 // External to current translation unit. 1279 OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); 1280 else 1281 // Internal to current translation unit. 1282 // 1283 // When we place the LSDA into the TEXT section, the type info pointers 1284 // need to be indirect and pc-rel. We accomplish this by using NLPs. 1285 // However, sometimes the types are local to the file. So we need to 1286 // fill in the value for the NLP in those cases. 1287 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), 1288 OutContext), 1289 4/*size*/, 0/*addrspace*/); 1290 } 1291 1292 Stubs.clear(); 1293 OutStreamer.AddBlankLine(); 1294 } 1295 1296 Stubs = MMIMacho.GetHiddenGVStubList(); 1297 if (!Stubs.empty()) { 1298 OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 1299 EmitAlignment(2); 1300 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 1301 // L_foo$stub: 1302 OutStreamer.EmitLabel(Stubs[i].first); 1303 // .long _foo 1304 OutStreamer.EmitValue(MCSymbolRefExpr:: 1305 Create(Stubs[i].second.getPointer(), 1306 OutContext), 1307 4/*size*/, 0/*addrspace*/); 1308 } 1309 1310 Stubs.clear(); 1311 OutStreamer.AddBlankLine(); 1312 } 1313 1314 // Funny Darwin hack: This flag tells the linker that no global symbols 1315 // contain code that falls through to other global symbols (e.g. the obvious 1316 // implementation of multiple entry points). If this doesn't occur, the 1317 // linker can safely perform dead code stripping. Since LLVM never 1318 // generates code that does this, it is always safe to set. 1319 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 1320 } 1321 } 1322 1323 //===----------------------------------------------------------------------===// 1324 1325 void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { 1326 ARMMCInstLower MCInstLowering(OutContext, *Mang, *this); 1327 switch (MI->getOpcode()) { 1328 case ARM::t2MOVi32imm: 1329 assert(0 && "Should be lowered by thumb2it pass"); 1330 default: break; 1331 case ARM::PICADD: { // FIXME: Remove asm string from td file. 1332 // This is a pseudo op for a label + instruction sequence, which looks like: 1333 // LPC0: 1334 // add r0, pc, r0 1335 // This adds the address of LPC0 to r0. 1336 1337 // Emit the label. 1338 // FIXME: MOVE TO SHARED PLACE. 1339 unsigned Id = (unsigned)MI->getOperand(2).getImm(); 1340 const char *Prefix = MAI->getPrivateGlobalPrefix(); 1341 MCSymbol *Label =OutContext.GetOrCreateSymbol(Twine(Prefix) 1342 + "PC" + Twine(getFunctionNumber()) + "_" + Twine(Id)); 1343 OutStreamer.EmitLabel(Label); 1344 1345 1346 // Form and emit tha dd. 1347 MCInst AddInst; 1348 AddInst.setOpcode(ARM::ADDrr); 1349 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); 1350 AddInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1351 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); 1352 OutStreamer.EmitInstruction(AddInst); 1353 return; 1354 } 1355 case ARM::CONSTPOOL_ENTRY: { // FIXME: Remove asm string from td file. 1356 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool 1357 /// in the function. The first operand is the ID# for this instruction, the 1358 /// second is the index into the MachineConstantPool that this is, the third 1359 /// is the size in bytes of this constant pool entry. 1360 unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); 1361 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); 1362 1363 EmitAlignment(2); 1364 OutStreamer.EmitLabel(GetCPISymbol(LabelId)); 1365 1366 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; 1367 if (MCPE.isMachineConstantPoolEntry()) 1368 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 1369 else 1370 EmitGlobalConstant(MCPE.Val.ConstVal); 1371 1372 return; 1373 } 1374 case ARM::MOVi2pieces: { // FIXME: Remove asmstring from td file. 1375 // This is a hack that lowers as a two instruction sequence. 1376 unsigned DstReg = MI->getOperand(0).getReg(); 1377 unsigned ImmVal = (unsigned)MI->getOperand(1).getImm(); 1378 1379 unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal); 1380 unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal); 1381 1382 { 1383 MCInst TmpInst; 1384 TmpInst.setOpcode(ARM::MOVi); 1385 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); 1386 TmpInst.addOperand(MCOperand::CreateImm(SOImmValV1)); 1387 1388 // Predicate. 1389 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1390 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); 1391 1392 TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out 1393 OutStreamer.EmitInstruction(TmpInst); 1394 } 1395 1396 { 1397 MCInst TmpInst; 1398 TmpInst.setOpcode(ARM::ORRri); 1399 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg 1400 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // inreg 1401 TmpInst.addOperand(MCOperand::CreateImm(SOImmValV2)); // so_imm 1402 // Predicate. 1403 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1404 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); 1405 1406 TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out 1407 OutStreamer.EmitInstruction(TmpInst); 1408 } 1409 return; 1410 } 1411 case ARM::MOVi32imm: { // FIXME: Remove asmstring from td file. 1412 // This is a hack that lowers as a two instruction sequence. 1413 unsigned DstReg = MI->getOperand(0).getReg(); 1414 const MachineOperand &MO = MI->getOperand(1); 1415 MCOperand V1, V2; 1416 if (MO.isImm()) { 1417 unsigned ImmVal = (unsigned)MI->getOperand(1).getImm(); 1418 V1 = MCOperand::CreateImm(ImmVal & 65535); 1419 V2 = MCOperand::CreateImm(ImmVal >> 16); 1420 } else if (MO.isGlobal()) { 1421 MCSymbol *Symbol = MCInstLowering.GetGlobalAddressSymbol(MO); 1422 const MCSymbolRefExpr *SymRef1 = 1423 MCSymbolRefExpr::Create(Symbol, 1424 MCSymbolRefExpr::VK_ARM_LO16, OutContext); 1425 const MCSymbolRefExpr *SymRef2 = 1426 MCSymbolRefExpr::Create(Symbol, 1427 MCSymbolRefExpr::VK_ARM_HI16, OutContext); 1428 V1 = MCOperand::CreateExpr(SymRef1); 1429 V2 = MCOperand::CreateExpr(SymRef2); 1430 } else { 1431 MI->dump(); 1432 llvm_unreachable("cannot handle this operand"); 1433 } 1434 1435 { 1436 MCInst TmpInst; 1437 TmpInst.setOpcode(ARM::MOVi16); 1438 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg 1439 TmpInst.addOperand(V1); // lower16(imm) 1440 1441 // Predicate. 1442 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1443 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); 1444 1445 OutStreamer.EmitInstruction(TmpInst); 1446 } 1447 1448 { 1449 MCInst TmpInst; 1450 TmpInst.setOpcode(ARM::MOVTi16); 1451 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg 1452 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // srcreg 1453 TmpInst.addOperand(V2); // upper16(imm) 1454 1455 // Predicate. 1456 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); 1457 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); 1458 1459 OutStreamer.EmitInstruction(TmpInst); 1460 } 1461 1462 return; 1463 } 1464 } 1465 1466 MCInst TmpInst; 1467 MCInstLowering.Lower(MI, TmpInst); 1468 OutStreamer.EmitInstruction(TmpInst); 1469 } 1470 1471 //===----------------------------------------------------------------------===// 1472 // Target Registry Stuff 1473 //===----------------------------------------------------------------------===// 1474 1475 static MCInstPrinter *createARMMCInstPrinter(const Target &T, 1476 unsigned SyntaxVariant, 1477 const MCAsmInfo &MAI) { 1478 if (SyntaxVariant == 0) 1479 return new ARMInstPrinter(MAI, false); 1480 return 0; 1481 } 1482 1483 // Force static initialization. 1484 extern "C" void LLVMInitializeARMAsmPrinter() { 1485 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); 1486 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); 1487 1488 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); 1489 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); 1490 } 1491 1492