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