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