1 //===-- ARMMCTargetDesc.cpp - ARM Target Descriptions ---------------------===// 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 provides ARM specific target descriptions. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "ARMBaseInfo.h" 15 #include "ARMMCAsmInfo.h" 16 #include "ARMMCTargetDesc.h" 17 #include "InstPrinter/ARMInstPrinter.h" 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/MC/MCCodeGenInfo.h" 20 #include "llvm/MC/MCELFStreamer.h" 21 #include "llvm/MC/MCInstrAnalysis.h" 22 #include "llvm/MC/MCInstrInfo.h" 23 #include "llvm/MC/MCRegisterInfo.h" 24 #include "llvm/MC/MCSubtargetInfo.h" 25 #include "llvm/Support/ErrorHandling.h" 26 #include "llvm/Support/TargetRegistry.h" 27 28 using namespace llvm; 29 30 #define GET_REGINFO_MC_DESC 31 #include "ARMGenRegisterInfo.inc" 32 33 static bool getMCRDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, 34 std::string &Info) { 35 if (STI.getFeatureBits() & llvm::ARM::HasV7Ops && 36 (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) && 37 (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) && 38 // Checks for the deprecated CP15ISB encoding: 39 // mcr p15, #0, rX, c7, c5, #4 40 (MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) { 41 if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) { 42 if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) { 43 Info = "deprecated since v7, use 'isb'"; 44 return true; 45 } 46 47 // Checks for the deprecated CP15DSB encoding: 48 // mcr p15, #0, rX, c7, c10, #4 49 if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) { 50 Info = "deprecated since v7, use 'dsb'"; 51 return true; 52 } 53 } 54 // Checks for the deprecated CP15DMB encoding: 55 // mcr p15, #0, rX, c7, c10, #5 56 if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 && 57 (MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) { 58 Info = "deprecated since v7, use 'dmb'"; 59 return true; 60 } 61 } 62 return false; 63 } 64 65 static bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, 66 std::string &Info) { 67 if (STI.getFeatureBits() & llvm::ARM::HasV8Ops && 68 MI.getOperand(1).isImm() && MI.getOperand(1).getImm() != 8) { 69 Info = "applying IT instruction to more than one subsequent instruction is deprecated"; 70 return true; 71 } 72 73 return false; 74 } 75 76 #define GET_INSTRINFO_MC_DESC 77 #include "ARMGenInstrInfo.inc" 78 79 #define GET_SUBTARGETINFO_MC_DESC 80 #include "ARMGenSubtargetInfo.inc" 81 82 83 std::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) { 84 Triple triple(TT); 85 86 // Set the boolean corresponding to the current target triple, or the default 87 // if one cannot be determined, to true. 88 unsigned Len = TT.size(); 89 unsigned Idx = 0; 90 91 // FIXME: Enhance Triple helper class to extract ARM version. 92 bool isThumb = false; 93 if (Len >= 5 && TT.substr(0, 4) == "armv") 94 Idx = 4; 95 else if (Len >= 6 && TT.substr(0, 5) == "thumb") { 96 isThumb = true; 97 if (Len >= 7 && TT[5] == 'v') 98 Idx = 6; 99 } 100 101 bool NoCPU = CPU == "generic" || CPU.empty(); 102 std::string ARMArchFeature; 103 if (Idx) { 104 unsigned SubVer = TT[Idx]; 105 if (SubVer == '8') { 106 if (NoCPU) 107 // v8a: FeatureDB, FeatureFPARMv8, FeatureNEON, FeatureDSPThumb2, FeatureMP, 108 // FeatureHWDiv, FeatureHWDivARM, FeatureTrustZone, FeatureT2XtPk, FeatureCrypto, FeatureCRC 109 ARMArchFeature = "+v8,+db,+fp-armv8,+neon,+t2dsp,+mp,+hwdiv,+hwdiv-arm,+trustzone,+t2xtpk,+crypto,+crc"; 110 else 111 // Use CPU to figure out the exact features 112 ARMArchFeature = "+v8"; 113 } else if (SubVer == '7') { 114 if (Len >= Idx+2 && TT[Idx+1] == 'm') { 115 isThumb = true; 116 if (NoCPU) 117 // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass 118 ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass"; 119 else 120 // Use CPU to figure out the exact features. 121 ARMArchFeature = "+v7"; 122 } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') { 123 if (NoCPU) 124 // v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2, 125 // FeatureT2XtPk, FeatureMClass 126 ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk,+mclass"; 127 else 128 // Use CPU to figure out the exact features. 129 ARMArchFeature = "+v7"; 130 } else if (Len >= Idx+2 && TT[Idx+1] == 's') { 131 if (NoCPU) 132 // v7s: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk 133 // Swift 134 ARMArchFeature = "+v7,+swift,+neon,+db,+t2dsp,+t2xtpk"; 135 else 136 // Use CPU to figure out the exact features. 137 ARMArchFeature = "+v7"; 138 } else { 139 // v7 CPUs have lots of different feature sets. If no CPU is specified, 140 // then assume v7a (e.g. cortex-a8) feature set. Otherwise, return 141 // the "minimum" feature set and use CPU string to figure out the exact 142 // features. 143 if (NoCPU) 144 // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk 145 ARMArchFeature = "+v7,+neon,+db,+t2dsp,+t2xtpk"; 146 else 147 // Use CPU to figure out the exact features. 148 ARMArchFeature = "+v7"; 149 } 150 } else if (SubVer == '6') { 151 if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') 152 ARMArchFeature = "+v6t2"; 153 else if (Len >= Idx+2 && TT[Idx+1] == 'm') { 154 isThumb = true; 155 if (NoCPU) 156 // v6m: FeatureNoARM, FeatureMClass 157 ARMArchFeature = "+v6m,+noarm,+mclass"; 158 else 159 ARMArchFeature = "+v6"; 160 } else 161 ARMArchFeature = "+v6"; 162 } else if (SubVer == '5') { 163 if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') 164 ARMArchFeature = "+v5te"; 165 else 166 ARMArchFeature = "+v5t"; 167 } else if (SubVer == '4' && Len >= Idx+2 && TT[Idx+1] == 't') 168 ARMArchFeature = "+v4t"; 169 } 170 171 if (isThumb) { 172 if (ARMArchFeature.empty()) 173 ARMArchFeature = "+thumb-mode"; 174 else 175 ARMArchFeature += ",+thumb-mode"; 176 } 177 178 if (triple.isOSNaCl()) { 179 if (ARMArchFeature.empty()) 180 ARMArchFeature = "+nacl-trap"; 181 else 182 ARMArchFeature += ",+nacl-trap"; 183 } 184 185 return ARMArchFeature; 186 } 187 188 MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(StringRef TT, StringRef CPU, 189 StringRef FS) { 190 std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU); 191 if (!FS.empty()) { 192 if (!ArchFS.empty()) 193 ArchFS = ArchFS + "," + FS.str(); 194 else 195 ArchFS = FS; 196 } 197 198 MCSubtargetInfo *X = new MCSubtargetInfo(); 199 InitARMMCSubtargetInfo(X, TT, CPU, ArchFS); 200 return X; 201 } 202 203 static MCInstrInfo *createARMMCInstrInfo() { 204 MCInstrInfo *X = new MCInstrInfo(); 205 InitARMMCInstrInfo(X); 206 return X; 207 } 208 209 static MCRegisterInfo *createARMMCRegisterInfo(StringRef Triple) { 210 MCRegisterInfo *X = new MCRegisterInfo(); 211 InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC); 212 return X; 213 } 214 215 static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) { 216 Triple TheTriple(TT); 217 218 if (TheTriple.isOSDarwin()) 219 return new ARMMCAsmInfoDarwin(); 220 221 return new ARMELFMCAsmInfo(); 222 } 223 224 static MCCodeGenInfo *createARMMCCodeGenInfo(StringRef TT, Reloc::Model RM, 225 CodeModel::Model CM, 226 CodeGenOpt::Level OL) { 227 MCCodeGenInfo *X = new MCCodeGenInfo(); 228 if (RM == Reloc::Default) { 229 Triple TheTriple(TT); 230 // Default relocation model on Darwin is PIC, not DynamicNoPIC. 231 RM = TheTriple.isOSDarwin() ? Reloc::PIC_ : Reloc::DynamicNoPIC; 232 } 233 X->InitMCCodeGenInfo(RM, CM, OL); 234 return X; 235 } 236 237 // This is duplicated code. Refactor this. 238 static MCStreamer *createMCStreamer(const Target &T, StringRef TT, 239 MCContext &Ctx, MCAsmBackend &MAB, 240 raw_ostream &OS, 241 MCCodeEmitter *Emitter, 242 bool RelaxAll, 243 bool NoExecStack) { 244 Triple TheTriple(TT); 245 246 if (TheTriple.isOSDarwin()) 247 return createMachOStreamer(Ctx, MAB, OS, Emitter, false); 248 249 if (TheTriple.isOSWindows()) { 250 llvm_unreachable("ARM does not support Windows COFF format"); 251 } 252 253 return createARMELFStreamer(Ctx, MAB, OS, Emitter, false, NoExecStack, 254 TheTriple.getArch() == Triple::thumb); 255 } 256 257 static MCInstPrinter *createARMMCInstPrinter(const Target &T, 258 unsigned SyntaxVariant, 259 const MCAsmInfo &MAI, 260 const MCInstrInfo &MII, 261 const MCRegisterInfo &MRI, 262 const MCSubtargetInfo &STI) { 263 if (SyntaxVariant == 0) 264 return new ARMInstPrinter(MAI, MII, MRI, STI); 265 return 0; 266 } 267 268 static MCRelocationInfo *createARMMCRelocationInfo(StringRef TT, 269 MCContext &Ctx) { 270 Triple TheTriple(TT); 271 if (TheTriple.isEnvironmentMachO()) 272 return createARMMachORelocationInfo(Ctx); 273 // Default to the stock relocation info. 274 return llvm::createMCRelocationInfo(TT, Ctx); 275 } 276 277 namespace { 278 279 class ARMMCInstrAnalysis : public MCInstrAnalysis { 280 public: 281 ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} 282 283 virtual bool isUnconditionalBranch(const MCInst &Inst) const { 284 // BCCs with the "always" predicate are unconditional branches. 285 if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) 286 return true; 287 return MCInstrAnalysis::isUnconditionalBranch(Inst); 288 } 289 290 virtual bool isConditionalBranch(const MCInst &Inst) const { 291 // BCCs with the "always" predicate are unconditional branches. 292 if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) 293 return false; 294 return MCInstrAnalysis::isConditionalBranch(Inst); 295 } 296 297 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, 298 uint64_t Size, uint64_t &Target) const { 299 // We only handle PCRel branches for now. 300 if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL) 301 return false; 302 303 int64_t Imm = Inst.getOperand(0).getImm(); 304 // FIXME: This is not right for thumb. 305 Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes. 306 return true; 307 } 308 }; 309 310 } 311 312 static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) { 313 return new ARMMCInstrAnalysis(Info); 314 } 315 316 // Force static initialization. 317 extern "C" void LLVMInitializeARMTargetMC() { 318 // Register the MC asm info. 319 RegisterMCAsmInfoFn A(TheARMTarget, createARMMCAsmInfo); 320 RegisterMCAsmInfoFn B(TheThumbTarget, createARMMCAsmInfo); 321 322 // Register the MC codegen info. 323 TargetRegistry::RegisterMCCodeGenInfo(TheARMTarget, createARMMCCodeGenInfo); 324 TargetRegistry::RegisterMCCodeGenInfo(TheThumbTarget, createARMMCCodeGenInfo); 325 326 // Register the MC instruction info. 327 TargetRegistry::RegisterMCInstrInfo(TheARMTarget, createARMMCInstrInfo); 328 TargetRegistry::RegisterMCInstrInfo(TheThumbTarget, createARMMCInstrInfo); 329 330 // Register the MC register info. 331 TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo); 332 TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo); 333 334 // Register the MC subtarget info. 335 TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget, 336 ARM_MC::createARMMCSubtargetInfo); 337 TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget, 338 ARM_MC::createARMMCSubtargetInfo); 339 340 // Register the MC instruction analyzer. 341 TargetRegistry::RegisterMCInstrAnalysis(TheARMTarget, 342 createARMMCInstrAnalysis); 343 TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget, 344 createARMMCInstrAnalysis); 345 346 // Register the MC Code Emitter 347 TargetRegistry::RegisterMCCodeEmitter(TheARMTarget, createARMMCCodeEmitter); 348 TargetRegistry::RegisterMCCodeEmitter(TheThumbTarget, createARMMCCodeEmitter); 349 350 // Register the asm backend. 351 TargetRegistry::RegisterMCAsmBackend(TheARMTarget, createARMAsmBackend); 352 TargetRegistry::RegisterMCAsmBackend(TheThumbTarget, createARMAsmBackend); 353 354 // Register the object streamer. 355 TargetRegistry::RegisterMCObjectStreamer(TheARMTarget, createMCStreamer); 356 TargetRegistry::RegisterMCObjectStreamer(TheThumbTarget, createMCStreamer); 357 358 // Register the asm streamer. 359 TargetRegistry::RegisterAsmStreamer(TheARMTarget, createMCAsmStreamer); 360 TargetRegistry::RegisterAsmStreamer(TheThumbTarget, createMCAsmStreamer); 361 362 // Register the MCInstPrinter. 363 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); 364 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); 365 366 // Register the MC relocation info. 367 TargetRegistry::RegisterMCRelocationInfo(TheARMTarget, 368 createARMMCRelocationInfo); 369 TargetRegistry::RegisterMCRelocationInfo(TheThumbTarget, 370 createARMMCRelocationInfo); 371 } 372