1235633Sdim//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions ---------------------===// 2224133Sdim// 3224133Sdim// The LLVM Compiler Infrastructure 4224133Sdim// 5224133Sdim// This file is distributed under the University of Illinois Open Source 6224133Sdim// License. See LICENSE.TXT for details. 7224133Sdim// 8224133Sdim//===----------------------------------------------------------------------===// 9224133Sdim// 10224133Sdim// This file provides ARM specific target descriptions. 11224133Sdim// 12224133Sdim//===----------------------------------------------------------------------===// 13224133Sdim 14252723Sdim#include "ARMBaseInfo.h" 15252723Sdim#include "ARMMCAsmInfo.h" 16224133Sdim#include "ARMMCTargetDesc.h" 17226890Sdim#include "InstPrinter/ARMInstPrinter.h" 18252723Sdim#include "llvm/ADT/Triple.h" 19226890Sdim#include "llvm/MC/MCCodeGenInfo.h" 20263509Sdim#include "llvm/MC/MCELFStreamer.h" 21226890Sdim#include "llvm/MC/MCInstrAnalysis.h" 22224133Sdim#include "llvm/MC/MCInstrInfo.h" 23224133Sdim#include "llvm/MC/MCRegisterInfo.h" 24224133Sdim#include "llvm/MC/MCSubtargetInfo.h" 25226890Sdim#include "llvm/Support/ErrorHandling.h" 26226890Sdim#include "llvm/Support/TargetRegistry.h" 27224133Sdim 28263509Sdimusing namespace llvm; 29263509Sdim 30224133Sdim#define GET_REGINFO_MC_DESC 31224133Sdim#include "ARMGenRegisterInfo.inc" 32224133Sdim 33263509Sdimstatic bool getMCRDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, 34263509Sdim std::string &Info) { 35263509Sdim if (STI.getFeatureBits() & llvm::ARM::HasV7Ops && 36263509Sdim (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) && 37263509Sdim (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) && 38263509Sdim // Checks for the deprecated CP15ISB encoding: 39263509Sdim // mcr p15, #0, rX, c7, c5, #4 40263509Sdim (MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) { 41263509Sdim if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) { 42263509Sdim if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) { 43263509Sdim Info = "deprecated since v7, use 'isb'"; 44263509Sdim return true; 45263509Sdim } 46263509Sdim 47263509Sdim // Checks for the deprecated CP15DSB encoding: 48263509Sdim // mcr p15, #0, rX, c7, c10, #4 49263509Sdim if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) { 50263509Sdim Info = "deprecated since v7, use 'dsb'"; 51263509Sdim return true; 52263509Sdim } 53263509Sdim } 54263509Sdim // Checks for the deprecated CP15DMB encoding: 55263509Sdim // mcr p15, #0, rX, c7, c10, #5 56263509Sdim if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 && 57263509Sdim (MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) { 58263509Sdim Info = "deprecated since v7, use 'dmb'"; 59263509Sdim return true; 60263509Sdim } 61263509Sdim } 62263509Sdim return false; 63263509Sdim} 64263509Sdim 65263509Sdimstatic bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, 66263509Sdim std::string &Info) { 67263509Sdim if (STI.getFeatureBits() & llvm::ARM::HasV8Ops && 68263509Sdim MI.getOperand(1).isImm() && MI.getOperand(1).getImm() != 8) { 69263509Sdim Info = "applying IT instruction to more than one subsequent instruction is deprecated"; 70263509Sdim return true; 71263509Sdim } 72263509Sdim 73263509Sdim return false; 74263509Sdim} 75263509Sdim 76224133Sdim#define GET_INSTRINFO_MC_DESC 77224133Sdim#include "ARMGenInstrInfo.inc" 78224133Sdim 79224133Sdim#define GET_SUBTARGETINFO_MC_DESC 80224133Sdim#include "ARMGenSubtargetInfo.inc" 81224133Sdim 82224133Sdim 83245431Sdimstd::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) { 84252723Sdim Triple triple(TT); 85252723Sdim 86224133Sdim // Set the boolean corresponding to the current target triple, or the default 87224133Sdim // if one cannot be determined, to true. 88224133Sdim unsigned Len = TT.size(); 89224133Sdim unsigned Idx = 0; 90224133Sdim 91226890Sdim // FIXME: Enhance Triple helper class to extract ARM version. 92224133Sdim bool isThumb = false; 93224133Sdim if (Len >= 5 && TT.substr(0, 4) == "armv") 94224133Sdim Idx = 4; 95224133Sdim else if (Len >= 6 && TT.substr(0, 5) == "thumb") { 96224133Sdim isThumb = true; 97224133Sdim if (Len >= 7 && TT[5] == 'v') 98224133Sdim Idx = 6; 99224133Sdim } 100224133Sdim 101245431Sdim bool NoCPU = CPU == "generic" || CPU.empty(); 102224133Sdim std::string ARMArchFeature; 103224133Sdim if (Idx) { 104224133Sdim unsigned SubVer = TT[Idx]; 105263509Sdim if (SubVer == '8') { 106263509Sdim if (NoCPU) 107263509Sdim // v8a: FeatureDB, FeatureFPARMv8, FeatureNEON, FeatureDSPThumb2, FeatureMP, 108263509Sdim // FeatureHWDiv, FeatureHWDivARM, FeatureTrustZone, FeatureT2XtPk, FeatureCrypto, FeatureCRC 109263509Sdim ARMArchFeature = "+v8,+db,+fp-armv8,+neon,+t2dsp,+mp,+hwdiv,+hwdiv-arm,+trustzone,+t2xtpk,+crypto,+crc"; 110263509Sdim else 111263509Sdim // Use CPU to figure out the exact features 112263509Sdim ARMArchFeature = "+v8"; 113263509Sdim } else if (SubVer == '7') { 114224133Sdim if (Len >= Idx+2 && TT[Idx+1] == 'm') { 115263509Sdim isThumb = true; 116245431Sdim if (NoCPU) 117245431Sdim // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass 118245431Sdim ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass"; 119245431Sdim else 120245431Sdim // Use CPU to figure out the exact features. 121245431Sdim ARMArchFeature = "+v7"; 122224133Sdim } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') { 123245431Sdim if (NoCPU) 124245431Sdim // v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2, 125245431Sdim // FeatureT2XtPk, FeatureMClass 126245431Sdim ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk,+mclass"; 127245431Sdim else 128245431Sdim // Use CPU to figure out the exact features. 129245431Sdim ARMArchFeature = "+v7"; 130245431Sdim } else if (Len >= Idx+2 && TT[Idx+1] == 's') { 131245431Sdim if (NoCPU) 132245431Sdim // v7s: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk 133245431Sdim // Swift 134245431Sdim ARMArchFeature = "+v7,+swift,+neon,+db,+t2dsp,+t2xtpk"; 135245431Sdim else 136245431Sdim // Use CPU to figure out the exact features. 137245431Sdim ARMArchFeature = "+v7"; 138245431Sdim } else { 139245431Sdim // v7 CPUs have lots of different feature sets. If no CPU is specified, 140245431Sdim // then assume v7a (e.g. cortex-a8) feature set. Otherwise, return 141245431Sdim // the "minimum" feature set and use CPU string to figure out the exact 142245431Sdim // features. 143245431Sdim if (NoCPU) 144245431Sdim // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk 145245431Sdim ARMArchFeature = "+v7,+neon,+db,+t2dsp,+t2xtpk"; 146245431Sdim else 147245431Sdim // Use CPU to figure out the exact features. 148245431Sdim ARMArchFeature = "+v7"; 149245431Sdim } 150224133Sdim } else if (SubVer == '6') { 151224133Sdim if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') 152224133Sdim ARMArchFeature = "+v6t2"; 153245431Sdim else if (Len >= Idx+2 && TT[Idx+1] == 'm') { 154263509Sdim isThumb = true; 155245431Sdim if (NoCPU) 156245431Sdim // v6m: FeatureNoARM, FeatureMClass 157263509Sdim ARMArchFeature = "+v6m,+noarm,+mclass"; 158245431Sdim else 159245431Sdim ARMArchFeature = "+v6"; 160245431Sdim } else 161224133Sdim ARMArchFeature = "+v6"; 162224133Sdim } else if (SubVer == '5') { 163224133Sdim if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') 164224133Sdim ARMArchFeature = "+v5te"; 165224133Sdim else 166224133Sdim ARMArchFeature = "+v5t"; 167224133Sdim } else if (SubVer == '4' && Len >= Idx+2 && TT[Idx+1] == 't') 168224133Sdim ARMArchFeature = "+v4t"; 169224133Sdim } 170224133Sdim 171224133Sdim if (isThumb) { 172224133Sdim if (ARMArchFeature.empty()) 173224133Sdim ARMArchFeature = "+thumb-mode"; 174224133Sdim else 175224133Sdim ARMArchFeature += ",+thumb-mode"; 176224133Sdim } 177224133Sdim 178252723Sdim if (triple.isOSNaCl()) { 179252723Sdim if (ARMArchFeature.empty()) 180252723Sdim ARMArchFeature = "+nacl-trap"; 181252723Sdim else 182252723Sdim ARMArchFeature += ",+nacl-trap"; 183252723Sdim } 184252723Sdim 185224133Sdim return ARMArchFeature; 186224133Sdim} 187224133Sdim 188224133SdimMCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(StringRef TT, StringRef CPU, 189224133Sdim StringRef FS) { 190245431Sdim std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU); 191224133Sdim if (!FS.empty()) { 192224133Sdim if (!ArchFS.empty()) 193224133Sdim ArchFS = ArchFS + "," + FS.str(); 194224133Sdim else 195224133Sdim ArchFS = FS; 196224133Sdim } 197224133Sdim 198224133Sdim MCSubtargetInfo *X = new MCSubtargetInfo(); 199224133Sdim InitARMMCSubtargetInfo(X, TT, CPU, ArchFS); 200224133Sdim return X; 201224133Sdim} 202224133Sdim 203224133Sdimstatic MCInstrInfo *createARMMCInstrInfo() { 204224133Sdim MCInstrInfo *X = new MCInstrInfo(); 205224133Sdim InitARMMCInstrInfo(X); 206224133Sdim return X; 207224133Sdim} 208224133Sdim 209226890Sdimstatic MCRegisterInfo *createARMMCRegisterInfo(StringRef Triple) { 210224133Sdim MCRegisterInfo *X = new MCRegisterInfo(); 211252723Sdim InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC); 212224133Sdim return X; 213224133Sdim} 214224133Sdim 215263509Sdimstatic MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) { 216224133Sdim Triple TheTriple(TT); 217224133Sdim 218224133Sdim if (TheTriple.isOSDarwin()) 219224133Sdim return new ARMMCAsmInfoDarwin(); 220224133Sdim 221224133Sdim return new ARMELFMCAsmInfo(); 222224133Sdim} 223224133Sdim 224226890Sdimstatic MCCodeGenInfo *createARMMCCodeGenInfo(StringRef TT, Reloc::Model RM, 225235633Sdim CodeModel::Model CM, 226235633Sdim CodeGenOpt::Level OL) { 227226890Sdim MCCodeGenInfo *X = new MCCodeGenInfo(); 228226890Sdim if (RM == Reloc::Default) { 229226890Sdim Triple TheTriple(TT); 230226890Sdim // Default relocation model on Darwin is PIC, not DynamicNoPIC. 231226890Sdim RM = TheTriple.isOSDarwin() ? Reloc::PIC_ : Reloc::DynamicNoPIC; 232226890Sdim } 233235633Sdim X->InitMCCodeGenInfo(RM, CM, OL); 234226890Sdim return X; 235226890Sdim} 236226890Sdim 237226890Sdim// This is duplicated code. Refactor this. 238226890Sdimstatic MCStreamer *createMCStreamer(const Target &T, StringRef TT, 239226890Sdim MCContext &Ctx, MCAsmBackend &MAB, 240226890Sdim raw_ostream &OS, 241226890Sdim MCCodeEmitter *Emitter, 242226890Sdim bool RelaxAll, 243226890Sdim bool NoExecStack) { 244226890Sdim Triple TheTriple(TT); 245226890Sdim 246226890Sdim if (TheTriple.isOSDarwin()) 247235633Sdim return createMachOStreamer(Ctx, MAB, OS, Emitter, false); 248226890Sdim 249226890Sdim if (TheTriple.isOSWindows()) { 250226890Sdim llvm_unreachable("ARM does not support Windows COFF format"); 251226890Sdim } 252226890Sdim 253252723Sdim return createARMELFStreamer(Ctx, MAB, OS, Emitter, false, NoExecStack, 254252723Sdim TheTriple.getArch() == Triple::thumb); 255226890Sdim} 256226890Sdim 257226890Sdimstatic MCInstPrinter *createARMMCInstPrinter(const Target &T, 258226890Sdim unsigned SyntaxVariant, 259226890Sdim const MCAsmInfo &MAI, 260235633Sdim const MCInstrInfo &MII, 261235633Sdim const MCRegisterInfo &MRI, 262226890Sdim const MCSubtargetInfo &STI) { 263226890Sdim if (SyntaxVariant == 0) 264235633Sdim return new ARMInstPrinter(MAI, MII, MRI, STI); 265226890Sdim return 0; 266226890Sdim} 267226890Sdim 268263509Sdimstatic MCRelocationInfo *createARMMCRelocationInfo(StringRef TT, 269263509Sdim MCContext &Ctx) { 270263509Sdim Triple TheTriple(TT); 271263509Sdim if (TheTriple.isEnvironmentMachO()) 272263509Sdim return createARMMachORelocationInfo(Ctx); 273263509Sdim // Default to the stock relocation info. 274263509Sdim return llvm::createMCRelocationInfo(TT, Ctx); 275263509Sdim} 276263509Sdim 277226890Sdimnamespace { 278226890Sdim 279226890Sdimclass ARMMCInstrAnalysis : public MCInstrAnalysis { 280226890Sdimpublic: 281226890Sdim ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} 282226890Sdim 283226890Sdim virtual bool isUnconditionalBranch(const MCInst &Inst) const { 284226890Sdim // BCCs with the "always" predicate are unconditional branches. 285226890Sdim if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) 286226890Sdim return true; 287226890Sdim return MCInstrAnalysis::isUnconditionalBranch(Inst); 288226890Sdim } 289226890Sdim 290226890Sdim virtual bool isConditionalBranch(const MCInst &Inst) const { 291226890Sdim // BCCs with the "always" predicate are unconditional branches. 292226890Sdim if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) 293226890Sdim return false; 294226890Sdim return MCInstrAnalysis::isConditionalBranch(Inst); 295226890Sdim } 296226890Sdim 297263509Sdim bool evaluateBranch(const MCInst &Inst, uint64_t Addr, 298263509Sdim uint64_t Size, uint64_t &Target) const { 299226890Sdim // We only handle PCRel branches for now. 300226890Sdim if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL) 301263509Sdim return false; 302226890Sdim 303226890Sdim int64_t Imm = Inst.getOperand(0).getImm(); 304226890Sdim // FIXME: This is not right for thumb. 305263509Sdim Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes. 306263509Sdim return true; 307226890Sdim } 308226890Sdim}; 309226890Sdim 310226890Sdim} 311226890Sdim 312226890Sdimstatic MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) { 313226890Sdim return new ARMMCInstrAnalysis(Info); 314226890Sdim} 315226890Sdim 316226890Sdim// Force static initialization. 317226890Sdimextern "C" void LLVMInitializeARMTargetMC() { 318226890Sdim // Register the MC asm info. 319224133Sdim RegisterMCAsmInfoFn A(TheARMTarget, createARMMCAsmInfo); 320224133Sdim RegisterMCAsmInfoFn B(TheThumbTarget, createARMMCAsmInfo); 321226890Sdim 322226890Sdim // Register the MC codegen info. 323226890Sdim TargetRegistry::RegisterMCCodeGenInfo(TheARMTarget, createARMMCCodeGenInfo); 324226890Sdim TargetRegistry::RegisterMCCodeGenInfo(TheThumbTarget, createARMMCCodeGenInfo); 325226890Sdim 326226890Sdim // Register the MC instruction info. 327226890Sdim TargetRegistry::RegisterMCInstrInfo(TheARMTarget, createARMMCInstrInfo); 328226890Sdim TargetRegistry::RegisterMCInstrInfo(TheThumbTarget, createARMMCInstrInfo); 329226890Sdim 330226890Sdim // Register the MC register info. 331226890Sdim TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo); 332226890Sdim TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo); 333226890Sdim 334226890Sdim // Register the MC subtarget info. 335226890Sdim TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget, 336226890Sdim ARM_MC::createARMMCSubtargetInfo); 337226890Sdim TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget, 338226890Sdim ARM_MC::createARMMCSubtargetInfo); 339226890Sdim 340226890Sdim // Register the MC instruction analyzer. 341226890Sdim TargetRegistry::RegisterMCInstrAnalysis(TheARMTarget, 342226890Sdim createARMMCInstrAnalysis); 343226890Sdim TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget, 344226890Sdim createARMMCInstrAnalysis); 345226890Sdim 346226890Sdim // Register the MC Code Emitter 347226890Sdim TargetRegistry::RegisterMCCodeEmitter(TheARMTarget, createARMMCCodeEmitter); 348226890Sdim TargetRegistry::RegisterMCCodeEmitter(TheThumbTarget, createARMMCCodeEmitter); 349226890Sdim 350226890Sdim // Register the asm backend. 351226890Sdim TargetRegistry::RegisterMCAsmBackend(TheARMTarget, createARMAsmBackend); 352226890Sdim TargetRegistry::RegisterMCAsmBackend(TheThumbTarget, createARMAsmBackend); 353226890Sdim 354226890Sdim // Register the object streamer. 355226890Sdim TargetRegistry::RegisterMCObjectStreamer(TheARMTarget, createMCStreamer); 356226890Sdim TargetRegistry::RegisterMCObjectStreamer(TheThumbTarget, createMCStreamer); 357226890Sdim 358263509Sdim // Register the asm streamer. 359263509Sdim TargetRegistry::RegisterAsmStreamer(TheARMTarget, createMCAsmStreamer); 360263509Sdim TargetRegistry::RegisterAsmStreamer(TheThumbTarget, createMCAsmStreamer); 361263509Sdim 362226890Sdim // Register the MCInstPrinter. 363226890Sdim TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); 364226890Sdim TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); 365263509Sdim 366263509Sdim // Register the MC relocation info. 367263509Sdim TargetRegistry::RegisterMCRelocationInfo(TheARMTarget, 368263509Sdim createARMMCRelocationInfo); 369263509Sdim TargetRegistry::RegisterMCRelocationInfo(TheThumbTarget, 370263509Sdim createARMMCRelocationInfo); 371224133Sdim} 372