1234353Sdim//===-- 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 14249423Sdim#include "ARMBaseInfo.h" 15249423Sdim#include "ARMMCAsmInfo.h" 16224133Sdim#include "ARMMCTargetDesc.h" 17226633Sdim#include "InstPrinter/ARMInstPrinter.h" 18249423Sdim#include "llvm/ADT/Triple.h" 19226633Sdim#include "llvm/MC/MCCodeGenInfo.h" 20263508Sdim#include "llvm/MC/MCELFStreamer.h" 21226633Sdim#include "llvm/MC/MCInstrAnalysis.h" 22224133Sdim#include "llvm/MC/MCInstrInfo.h" 23224133Sdim#include "llvm/MC/MCRegisterInfo.h" 24224133Sdim#include "llvm/MC/MCSubtargetInfo.h" 25226633Sdim#include "llvm/Support/ErrorHandling.h" 26226633Sdim#include "llvm/Support/TargetRegistry.h" 27224133Sdim 28263508Sdimusing namespace llvm; 29263508Sdim 30224133Sdim#define GET_REGINFO_MC_DESC 31224133Sdim#include "ARMGenRegisterInfo.inc" 32224133Sdim 33263508Sdimstatic bool getMCRDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, 34263508Sdim std::string &Info) { 35263508Sdim if (STI.getFeatureBits() & llvm::ARM::HasV7Ops && 36263508Sdim (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) && 37263508Sdim (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) && 38263508Sdim // Checks for the deprecated CP15ISB encoding: 39263508Sdim // mcr p15, #0, rX, c7, c5, #4 40263508Sdim (MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) { 41263508Sdim if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) { 42263508Sdim if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) { 43263508Sdim Info = "deprecated since v7, use 'isb'"; 44263508Sdim return true; 45263508Sdim } 46263508Sdim 47263508Sdim // Checks for the deprecated CP15DSB encoding: 48263508Sdim // mcr p15, #0, rX, c7, c10, #4 49263508Sdim if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) { 50263508Sdim Info = "deprecated since v7, use 'dsb'"; 51263508Sdim return true; 52263508Sdim } 53263508Sdim } 54263508Sdim // Checks for the deprecated CP15DMB encoding: 55263508Sdim // mcr p15, #0, rX, c7, c10, #5 56263508Sdim if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 && 57263508Sdim (MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) { 58263508Sdim Info = "deprecated since v7, use 'dmb'"; 59263508Sdim return true; 60263508Sdim } 61263508Sdim } 62263508Sdim return false; 63263508Sdim} 64263508Sdim 65263508Sdimstatic bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, 66263508Sdim std::string &Info) { 67263508Sdim if (STI.getFeatureBits() & llvm::ARM::HasV8Ops && 68263508Sdim MI.getOperand(1).isImm() && MI.getOperand(1).getImm() != 8) { 69263508Sdim Info = "applying IT instruction to more than one subsequent instruction is deprecated"; 70263508Sdim return true; 71263508Sdim } 72263508Sdim 73263508Sdim return false; 74263508Sdim} 75263508Sdim 76224133Sdim#define GET_INSTRINFO_MC_DESC 77224133Sdim#include "ARMGenInstrInfo.inc" 78224133Sdim 79224133Sdim#define GET_SUBTARGETINFO_MC_DESC 80224133Sdim#include "ARMGenSubtargetInfo.inc" 81224133Sdim 82224133Sdim 83239462Sdimstd::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) { 84249423Sdim Triple triple(TT); 85249423Sdim 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 91226633Sdim // 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 101239462Sdim bool NoCPU = CPU == "generic" || CPU.empty(); 102224133Sdim std::string ARMArchFeature; 103224133Sdim if (Idx) { 104224133Sdim unsigned SubVer = TT[Idx]; 105263508Sdim if (SubVer == '8') { 106263508Sdim if (NoCPU) 107263508Sdim // v8a: FeatureDB, FeatureFPARMv8, FeatureNEON, FeatureDSPThumb2, FeatureMP, 108263508Sdim // FeatureHWDiv, FeatureHWDivARM, FeatureTrustZone, FeatureT2XtPk, FeatureCrypto, FeatureCRC 109263508Sdim ARMArchFeature = "+v8,+db,+fp-armv8,+neon,+t2dsp,+mp,+hwdiv,+hwdiv-arm,+trustzone,+t2xtpk,+crypto,+crc"; 110263508Sdim else 111263508Sdim // Use CPU to figure out the exact features 112263508Sdim ARMArchFeature = "+v8"; 113263508Sdim } else if (SubVer == '7') { 114224133Sdim if (Len >= Idx+2 && TT[Idx+1] == 'm') { 115263508Sdim isThumb = true; 116239462Sdim if (NoCPU) 117239462Sdim // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass 118239462Sdim ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass"; 119239462Sdim else 120239462Sdim // Use CPU to figure out the exact features. 121239462Sdim ARMArchFeature = "+v7"; 122224133Sdim } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') { 123239462Sdim if (NoCPU) 124239462Sdim // v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2, 125239462Sdim // FeatureT2XtPk, FeatureMClass 126239462Sdim ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk,+mclass"; 127239462Sdim else 128239462Sdim // Use CPU to figure out the exact features. 129239462Sdim ARMArchFeature = "+v7"; 130243830Sdim } else if (Len >= Idx+2 && TT[Idx+1] == 's') { 131243830Sdim if (NoCPU) 132243830Sdim // v7s: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk 133243830Sdim // Swift 134243830Sdim ARMArchFeature = "+v7,+swift,+neon,+db,+t2dsp,+t2xtpk"; 135243830Sdim else 136243830Sdim // Use CPU to figure out the exact features. 137243830Sdim ARMArchFeature = "+v7"; 138239462Sdim } else { 139239462Sdim // v7 CPUs have lots of different feature sets. If no CPU is specified, 140239462Sdim // then assume v7a (e.g. cortex-a8) feature set. Otherwise, return 141239462Sdim // the "minimum" feature set and use CPU string to figure out the exact 142239462Sdim // features. 143239462Sdim if (NoCPU) 144239462Sdim // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk 145239462Sdim ARMArchFeature = "+v7,+neon,+db,+t2dsp,+t2xtpk"; 146239462Sdim else 147239462Sdim // Use CPU to figure out the exact features. 148239462Sdim ARMArchFeature = "+v7"; 149239462Sdim } 150224133Sdim } else if (SubVer == '6') { 151224133Sdim if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') 152224133Sdim ARMArchFeature = "+v6t2"; 153239462Sdim else if (Len >= Idx+2 && TT[Idx+1] == 'm') { 154263508Sdim isThumb = true; 155239462Sdim if (NoCPU) 156239462Sdim // v6m: FeatureNoARM, FeatureMClass 157263508Sdim ARMArchFeature = "+v6m,+noarm,+mclass"; 158239462Sdim else 159239462Sdim ARMArchFeature = "+v6"; 160239462Sdim } 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 178249423Sdim if (triple.isOSNaCl()) { 179249423Sdim if (ARMArchFeature.empty()) 180249423Sdim ARMArchFeature = "+nacl-trap"; 181249423Sdim else 182249423Sdim ARMArchFeature += ",+nacl-trap"; 183249423Sdim } 184249423Sdim 185224133Sdim return ARMArchFeature; 186224133Sdim} 187224133Sdim 188224133SdimMCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(StringRef TT, StringRef CPU, 189224133Sdim StringRef FS) { 190239462Sdim 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 209226633Sdimstatic MCRegisterInfo *createARMMCRegisterInfo(StringRef Triple) { 210224133Sdim MCRegisterInfo *X = new MCRegisterInfo(); 211249423Sdim InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC); 212224133Sdim return X; 213224133Sdim} 214224133Sdim 215263508Sdimstatic 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 224226633Sdimstatic MCCodeGenInfo *createARMMCCodeGenInfo(StringRef TT, Reloc::Model RM, 225234353Sdim CodeModel::Model CM, 226234353Sdim CodeGenOpt::Level OL) { 227226633Sdim MCCodeGenInfo *X = new MCCodeGenInfo(); 228226633Sdim if (RM == Reloc::Default) { 229226633Sdim Triple TheTriple(TT); 230226633Sdim // Default relocation model on Darwin is PIC, not DynamicNoPIC. 231226633Sdim RM = TheTriple.isOSDarwin() ? Reloc::PIC_ : Reloc::DynamicNoPIC; 232226633Sdim } 233234353Sdim X->InitMCCodeGenInfo(RM, CM, OL); 234226633Sdim return X; 235226633Sdim} 236226633Sdim 237226633Sdim// This is duplicated code. Refactor this. 238226633Sdimstatic MCStreamer *createMCStreamer(const Target &T, StringRef TT, 239226633Sdim MCContext &Ctx, MCAsmBackend &MAB, 240226633Sdim raw_ostream &OS, 241226633Sdim MCCodeEmitter *Emitter, 242226633Sdim bool RelaxAll, 243226633Sdim bool NoExecStack) { 244226633Sdim Triple TheTriple(TT); 245226633Sdim 246226633Sdim if (TheTriple.isOSDarwin()) 247234353Sdim return createMachOStreamer(Ctx, MAB, OS, Emitter, false); 248226633Sdim 249226633Sdim if (TheTriple.isOSWindows()) { 250226633Sdim llvm_unreachable("ARM does not support Windows COFF format"); 251226633Sdim } 252226633Sdim 253249423Sdim return createARMELFStreamer(Ctx, MAB, OS, Emitter, false, NoExecStack, 254249423Sdim TheTriple.getArch() == Triple::thumb); 255226633Sdim} 256226633Sdim 257226633Sdimstatic MCInstPrinter *createARMMCInstPrinter(const Target &T, 258226633Sdim unsigned SyntaxVariant, 259226633Sdim const MCAsmInfo &MAI, 260234353Sdim const MCInstrInfo &MII, 261234353Sdim const MCRegisterInfo &MRI, 262226633Sdim const MCSubtargetInfo &STI) { 263226633Sdim if (SyntaxVariant == 0) 264234353Sdim return new ARMInstPrinter(MAI, MII, MRI, STI); 265226633Sdim return 0; 266226633Sdim} 267226633Sdim 268263508Sdimstatic MCRelocationInfo *createARMMCRelocationInfo(StringRef TT, 269263508Sdim MCContext &Ctx) { 270263508Sdim Triple TheTriple(TT); 271263508Sdim if (TheTriple.isEnvironmentMachO()) 272263508Sdim return createARMMachORelocationInfo(Ctx); 273263508Sdim // Default to the stock relocation info. 274263508Sdim return llvm::createMCRelocationInfo(TT, Ctx); 275263508Sdim} 276263508Sdim 277226633Sdimnamespace { 278226633Sdim 279226633Sdimclass ARMMCInstrAnalysis : public MCInstrAnalysis { 280226633Sdimpublic: 281226633Sdim ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} 282226633Sdim 283226633Sdim virtual bool isUnconditionalBranch(const MCInst &Inst) const { 284226633Sdim // BCCs with the "always" predicate are unconditional branches. 285226633Sdim if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) 286226633Sdim return true; 287226633Sdim return MCInstrAnalysis::isUnconditionalBranch(Inst); 288226633Sdim } 289226633Sdim 290226633Sdim virtual bool isConditionalBranch(const MCInst &Inst) const { 291226633Sdim // BCCs with the "always" predicate are unconditional branches. 292226633Sdim if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) 293226633Sdim return false; 294226633Sdim return MCInstrAnalysis::isConditionalBranch(Inst); 295226633Sdim } 296226633Sdim 297263508Sdim bool evaluateBranch(const MCInst &Inst, uint64_t Addr, 298263508Sdim uint64_t Size, uint64_t &Target) const { 299226633Sdim // We only handle PCRel branches for now. 300226633Sdim if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL) 301263508Sdim return false; 302226633Sdim 303226633Sdim int64_t Imm = Inst.getOperand(0).getImm(); 304226633Sdim // FIXME: This is not right for thumb. 305263508Sdim Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes. 306263508Sdim return true; 307226633Sdim } 308226633Sdim}; 309226633Sdim 310226633Sdim} 311226633Sdim 312226633Sdimstatic MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) { 313226633Sdim return new ARMMCInstrAnalysis(Info); 314226633Sdim} 315226633Sdim 316226633Sdim// Force static initialization. 317226633Sdimextern "C" void LLVMInitializeARMTargetMC() { 318226633Sdim // Register the MC asm info. 319224133Sdim RegisterMCAsmInfoFn A(TheARMTarget, createARMMCAsmInfo); 320224133Sdim RegisterMCAsmInfoFn B(TheThumbTarget, createARMMCAsmInfo); 321226633Sdim 322226633Sdim // Register the MC codegen info. 323226633Sdim TargetRegistry::RegisterMCCodeGenInfo(TheARMTarget, createARMMCCodeGenInfo); 324226633Sdim TargetRegistry::RegisterMCCodeGenInfo(TheThumbTarget, createARMMCCodeGenInfo); 325226633Sdim 326226633Sdim // Register the MC instruction info. 327226633Sdim TargetRegistry::RegisterMCInstrInfo(TheARMTarget, createARMMCInstrInfo); 328226633Sdim TargetRegistry::RegisterMCInstrInfo(TheThumbTarget, createARMMCInstrInfo); 329226633Sdim 330226633Sdim // Register the MC register info. 331226633Sdim TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo); 332226633Sdim TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo); 333226633Sdim 334226633Sdim // Register the MC subtarget info. 335226633Sdim TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget, 336226633Sdim ARM_MC::createARMMCSubtargetInfo); 337226633Sdim TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget, 338226633Sdim ARM_MC::createARMMCSubtargetInfo); 339226633Sdim 340226633Sdim // Register the MC instruction analyzer. 341226633Sdim TargetRegistry::RegisterMCInstrAnalysis(TheARMTarget, 342226633Sdim createARMMCInstrAnalysis); 343226633Sdim TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget, 344226633Sdim createARMMCInstrAnalysis); 345226633Sdim 346226633Sdim // Register the MC Code Emitter 347226633Sdim TargetRegistry::RegisterMCCodeEmitter(TheARMTarget, createARMMCCodeEmitter); 348226633Sdim TargetRegistry::RegisterMCCodeEmitter(TheThumbTarget, createARMMCCodeEmitter); 349226633Sdim 350226633Sdim // Register the asm backend. 351226633Sdim TargetRegistry::RegisterMCAsmBackend(TheARMTarget, createARMAsmBackend); 352226633Sdim TargetRegistry::RegisterMCAsmBackend(TheThumbTarget, createARMAsmBackend); 353226633Sdim 354226633Sdim // Register the object streamer. 355226633Sdim TargetRegistry::RegisterMCObjectStreamer(TheARMTarget, createMCStreamer); 356226633Sdim TargetRegistry::RegisterMCObjectStreamer(TheThumbTarget, createMCStreamer); 357226633Sdim 358263508Sdim // Register the asm streamer. 359263508Sdim TargetRegistry::RegisterAsmStreamer(TheARMTarget, createMCAsmStreamer); 360263508Sdim TargetRegistry::RegisterAsmStreamer(TheThumbTarget, createMCAsmStreamer); 361263508Sdim 362226633Sdim // Register the MCInstPrinter. 363226633Sdim TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); 364226633Sdim TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); 365263508Sdim 366263508Sdim // Register the MC relocation info. 367263508Sdim TargetRegistry::RegisterMCRelocationInfo(TheARMTarget, 368263508Sdim createARMMCRelocationInfo); 369263508Sdim TargetRegistry::RegisterMCRelocationInfo(TheThumbTarget, 370263508Sdim createARMMCRelocationInfo); 371224133Sdim} 372