1f5f373fcSRenato Golin //===-- TargetParser - Parser for target features ---------------*- C++ -*-===// 2f5f373fcSRenato Golin // 3f5f373fcSRenato Golin // The LLVM Compiler Infrastructure 4f5f373fcSRenato Golin // 5f5f373fcSRenato Golin // This file is distributed under the University of Illinois Open Source 6f5f373fcSRenato Golin // License. See LICENSE.TXT for details. 7f5f373fcSRenato Golin // 8f5f373fcSRenato Golin //===----------------------------------------------------------------------===// 9f5f373fcSRenato Golin // 10f5f373fcSRenato Golin // This file implements a target parser to recognise hardware features such as 11f5f373fcSRenato Golin // FPU/CPU/ARCH names as well as specific support such as HDIV, etc. 12f5f373fcSRenato Golin // 13f5f373fcSRenato Golin //===----------------------------------------------------------------------===// 14f5f373fcSRenato Golin 15f5f373fcSRenato Golin #include "llvm/Support/ARMBuildAttributes.h" 16f5f373fcSRenato Golin #include "llvm/Support/TargetParser.h" 17f5f373fcSRenato Golin #include "llvm/ADT/StringExtras.h" 18f5f373fcSRenato Golin #include "llvm/ADT/StringSwitch.h" 19ebdd12cbSRenato Golin #include <cctype> 20f5f373fcSRenato Golin 21f5f373fcSRenato Golin using namespace llvm; 22799e880eSChandler Carruth using namespace ARM; 23f5f373fcSRenato Golin 24f5f373fcSRenato Golin namespace { 25f5f373fcSRenato Golin 26d03d2292SJohn Brawn // List of canonical FPU names (use getFPUSynonym) and which architectural 27d03d2292SJohn Brawn // features they correspond to (use getFPUFeatures). 28f5f373fcSRenato Golin // FIXME: TableGen this. 29d5526303SJaved Absar // The entries must appear in the order listed in ARM::FPUKind for correct indexing 30f5f373fcSRenato Golin struct { 313309ef6fSChandler Carruth const char *NameCStr; 323309ef6fSChandler Carruth size_t NameLength; 33f5f373fcSRenato Golin ARM::FPUKind ID; 34d5526303SJaved Absar ARM::FPUVersion FPUVersion; 35d03d2292SJohn Brawn ARM::NeonSupportLevel NeonSupport; 36d03d2292SJohn Brawn ARM::FPURestriction Restriction; 373309ef6fSChandler Carruth 383309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 39f5f373fcSRenato Golin } FPUNames[] = { 40799e880eSChandler Carruth #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ 413309ef6fSChandler Carruth { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION }, 42799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 43f5f373fcSRenato Golin }; 44d03d2292SJohn Brawn 45f7c0d5f2SRenato Golin // List of canonical arch names (use getArchSynonym). 46f7c0d5f2SRenato Golin // This table also provides the build attribute fields for CPU arch 47f7c0d5f2SRenato Golin // and Arch ID, according to the Addenda to the ARM ABI, chapters 48f7c0d5f2SRenato Golin // 2.4 and 2.3.5.2 respectively. 4942dad647SRenato Golin // FIXME: SubArch values were simplified to fit into the expectations 5042dad647SRenato Golin // of the triples and are not conforming with their official names. 5142dad647SRenato Golin // Check to see if the expectation should be changed. 52f5f373fcSRenato Golin // FIXME: TableGen this. 53f5f373fcSRenato Golin struct { 543309ef6fSChandler Carruth const char *NameCStr; 553309ef6fSChandler Carruth size_t NameLength; 56f5f373fcSRenato Golin ARM::ArchKind ID; 573309ef6fSChandler Carruth const char *CPUAttrCStr; 583309ef6fSChandler Carruth size_t CPUAttrLength; 593309ef6fSChandler Carruth const char *SubArchCStr; 603309ef6fSChandler Carruth size_t SubArchLength; 61f7c0d5f2SRenato Golin ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. 62ea33e5e8SAlexandros Lamprineas unsigned ArchBaseExtensions; 633309ef6fSChandler Carruth 643309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 653309ef6fSChandler Carruth 663309ef6fSChandler Carruth // CPU class in build attributes. 673309ef6fSChandler Carruth StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } 683309ef6fSChandler Carruth 693309ef6fSChandler Carruth // Sub-Arch name. 703309ef6fSChandler Carruth StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } 71f5f373fcSRenato Golin } ARCHNames[] = { 72ea33e5e8SAlexandros Lamprineas #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_BASE_EXT) \ 733309ef6fSChandler Carruth {NAME, sizeof(NAME) - 1, ID, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ 74ea33e5e8SAlexandros Lamprineas sizeof(SUB_ARCH) - 1, ARCH_ATTR, ARCH_BASE_EXT}, 75799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 76f5f373fcSRenato Golin }; 773309ef6fSChandler Carruth 78e1326cadSRenato Golin // List of Arch Extension names. 79f5f373fcSRenato Golin // FIXME: TableGen this. 80f5f373fcSRenato Golin struct { 813309ef6fSChandler Carruth const char *NameCStr; 823309ef6fSChandler Carruth size_t NameLength; 834ea70755SAlexandros Lamprineas unsigned ID; 843309ef6fSChandler Carruth 853309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 86f5f373fcSRenato Golin } ARCHExtNames[] = { 873309ef6fSChandler Carruth #define ARM_ARCH_EXT_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, 88799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 89f5f373fcSRenato Golin }; 903309ef6fSChandler Carruth 914ea70755SAlexandros Lamprineas // List of HWDiv names (use getHWDivSynonym) and which architectural 924ea70755SAlexandros Lamprineas // features they correspond to (use getHWDivFeatures). 934ea70755SAlexandros Lamprineas // FIXME: TableGen this. 944ea70755SAlexandros Lamprineas struct { 953309ef6fSChandler Carruth const char *NameCStr; 963309ef6fSChandler Carruth size_t NameLength; 974ea70755SAlexandros Lamprineas unsigned ID; 983309ef6fSChandler Carruth 993309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 1004ea70755SAlexandros Lamprineas } HWDivNames[] = { 1013309ef6fSChandler Carruth #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, 102799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 1034ea70755SAlexandros Lamprineas }; 1043309ef6fSChandler Carruth 105e8048f0dSRenato Golin // List of CPU names and their arches. 106e8048f0dSRenato Golin // The same CPU can have multiple arches and can be default on multiple arches. 107e8048f0dSRenato Golin // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. 1087374fcdbSRenato Golin // When this becomes table-generated, we'd probably need two tables. 109e8048f0dSRenato Golin // FIXME: TableGen this. 110e8048f0dSRenato Golin struct { 1113309ef6fSChandler Carruth const char *NameCStr; 1123309ef6fSChandler Carruth size_t NameLength; 113e8048f0dSRenato Golin ARM::ArchKind ArchID; 114fcd93d53SAlexandros Lamprineas bool Default; // is $Name the default CPU for $ArchID ? 115ea33e5e8SAlexandros Lamprineas unsigned DefaultExtensions; 1163309ef6fSChandler Carruth 1173309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 118e8048f0dSRenato Golin } CPUNames[] = { 119ea33e5e8SAlexandros Lamprineas #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 120ea33e5e8SAlexandros Lamprineas { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT }, 121799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 122e8048f0dSRenato Golin }; 123f5f373fcSRenato Golin 124f5f373fcSRenato Golin } // namespace 125f5f373fcSRenato Golin 126f5f373fcSRenato Golin // ======================================================= // 127f5f373fcSRenato Golin // Information by ID 128f5f373fcSRenato Golin // ======================================================= // 129f5f373fcSRenato Golin 1303309ef6fSChandler Carruth StringRef llvm::ARM::getFPUName(unsigned FPUKind) { 131e8048f0dSRenato Golin if (FPUKind >= ARM::FK_LAST) 1323309ef6fSChandler Carruth return StringRef(); 1333309ef6fSChandler Carruth return FPUNames[FPUKind].getName(); 134f5f373fcSRenato Golin } 135f5f373fcSRenato Golin 136bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) { 137d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST) 138d03d2292SJohn Brawn return 0; 139d03d2292SJohn Brawn return FPUNames[FPUKind].FPUVersion; 140d03d2292SJohn Brawn } 141d03d2292SJohn Brawn 142bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) { 143d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST) 144d03d2292SJohn Brawn return 0; 145d03d2292SJohn Brawn return FPUNames[FPUKind].NeonSupport; 146d03d2292SJohn Brawn } 147d03d2292SJohn Brawn 148bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) { 149d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST) 150d03d2292SJohn Brawn return 0; 151d03d2292SJohn Brawn return FPUNames[FPUKind].Restriction; 152d03d2292SJohn Brawn } 153d03d2292SJohn Brawn 154bb47b9a3SChandler Carruth unsigned llvm::ARM::getDefaultFPU(StringRef CPU) { 155822d54a2SChandler Carruth return StringSwitch<unsigned>(CPU) 156ea33e5e8SAlexandros Lamprineas #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 157822d54a2SChandler Carruth .Case(NAME, DEFAULT_FPU) 158822d54a2SChandler Carruth #include "llvm/Support/ARMTargetParser.def" 159822d54a2SChandler Carruth .Default(ARM::FK_INVALID); 160fcd93d53SAlexandros Lamprineas } 161fcd93d53SAlexandros Lamprineas 162bb47b9a3SChandler Carruth bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, 1634ea70755SAlexandros Lamprineas std::vector<const char *> &Features) { 1644ea70755SAlexandros Lamprineas 1654ea70755SAlexandros Lamprineas if (HWDivKind == ARM::AEK_INVALID) 1664ea70755SAlexandros Lamprineas return false; 1674ea70755SAlexandros Lamprineas 1684ea70755SAlexandros Lamprineas if (HWDivKind & ARM::AEK_HWDIVARM) 1694ea70755SAlexandros Lamprineas Features.push_back("+hwdiv-arm"); 1704ea70755SAlexandros Lamprineas else 1714ea70755SAlexandros Lamprineas Features.push_back("-hwdiv-arm"); 1724ea70755SAlexandros Lamprineas 1734ea70755SAlexandros Lamprineas if (HWDivKind & ARM::AEK_HWDIV) 1744ea70755SAlexandros Lamprineas Features.push_back("+hwdiv"); 1754ea70755SAlexandros Lamprineas else 1764ea70755SAlexandros Lamprineas Features.push_back("-hwdiv"); 1774ea70755SAlexandros Lamprineas 1784ea70755SAlexandros Lamprineas return true; 1794ea70755SAlexandros Lamprineas } 1804ea70755SAlexandros Lamprineas 181ea33e5e8SAlexandros Lamprineas bool llvm::ARM::getExtensionFeatures(unsigned Extensions, 182ea33e5e8SAlexandros Lamprineas std::vector<const char *> &Features) { 183ea33e5e8SAlexandros Lamprineas 184ea33e5e8SAlexandros Lamprineas if (Extensions == ARM::AEK_INVALID) 185ea33e5e8SAlexandros Lamprineas return false; 186ea33e5e8SAlexandros Lamprineas 187ea33e5e8SAlexandros Lamprineas if (Extensions & ARM::AEK_CRC) 188ea33e5e8SAlexandros Lamprineas Features.push_back("+crc"); 189ea33e5e8SAlexandros Lamprineas else 190ea33e5e8SAlexandros Lamprineas Features.push_back("-crc"); 191ea33e5e8SAlexandros Lamprineas 192cf296444SArtyom Skrobov if (Extensions & ARM::AEK_DSP) 1935a6e3945SArtyom Skrobov Features.push_back("+dsp"); 194cf296444SArtyom Skrobov else 1955a6e3945SArtyom Skrobov Features.push_back("-dsp"); 196cf296444SArtyom Skrobov 197ea33e5e8SAlexandros Lamprineas return getHWDivFeatures(Extensions, Features); 198ea33e5e8SAlexandros Lamprineas } 199ea33e5e8SAlexandros Lamprineas 200bb47b9a3SChandler Carruth bool llvm::ARM::getFPUFeatures(unsigned FPUKind, 201d03d2292SJohn Brawn std::vector<const char *> &Features) { 202d03d2292SJohn Brawn 203d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) 204d03d2292SJohn Brawn return false; 205d03d2292SJohn Brawn 206d03d2292SJohn Brawn // fp-only-sp and d16 subtarget features are independent of each other, so we 207d03d2292SJohn Brawn // must enable/disable both. 208d03d2292SJohn Brawn switch (FPUNames[FPUKind].Restriction) { 209d03d2292SJohn Brawn case ARM::FR_SP_D16: 210d03d2292SJohn Brawn Features.push_back("+fp-only-sp"); 211d03d2292SJohn Brawn Features.push_back("+d16"); 212d03d2292SJohn Brawn break; 213d03d2292SJohn Brawn case ARM::FR_D16: 214d03d2292SJohn Brawn Features.push_back("-fp-only-sp"); 215d03d2292SJohn Brawn Features.push_back("+d16"); 216d03d2292SJohn Brawn break; 217d03d2292SJohn Brawn case ARM::FR_None: 218d03d2292SJohn Brawn Features.push_back("-fp-only-sp"); 219d03d2292SJohn Brawn Features.push_back("-d16"); 220d03d2292SJohn Brawn break; 221d03d2292SJohn Brawn } 222d03d2292SJohn Brawn 223d03d2292SJohn Brawn // FPU version subtarget features are inclusive of lower-numbered ones, so 224d03d2292SJohn Brawn // enable the one corresponding to this version and disable all that are 225d9e39d53SJohn Brawn // higher. We also have to make sure to disable fp16 when vfp4 is disabled, 226d9e39d53SJohn Brawn // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16. 227d03d2292SJohn Brawn switch (FPUNames[FPUKind].FPUVersion) { 228d5526303SJaved Absar case ARM::FV_VFPV5: 229d03d2292SJohn Brawn Features.push_back("+fp-armv8"); 230d03d2292SJohn Brawn break; 231d5526303SJaved Absar case ARM::FV_VFPV4: 232d03d2292SJohn Brawn Features.push_back("+vfp4"); 233d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 234d03d2292SJohn Brawn break; 235d5526303SJaved Absar case ARM::FV_VFPV3_FP16: 236d5526303SJaved Absar Features.push_back("+vfp3"); 237d5526303SJaved Absar Features.push_back("+fp16"); 238d5526303SJaved Absar Features.push_back("-vfp4"); 239d5526303SJaved Absar Features.push_back("-fp-armv8"); 240d5526303SJaved Absar break; 241d5526303SJaved Absar case ARM::FV_VFPV3: 242d03d2292SJohn Brawn Features.push_back("+vfp3"); 243d9e39d53SJohn Brawn Features.push_back("-fp16"); 244d03d2292SJohn Brawn Features.push_back("-vfp4"); 245d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 246d03d2292SJohn Brawn break; 247d5526303SJaved Absar case ARM::FV_VFPV2: 248d03d2292SJohn Brawn Features.push_back("+vfp2"); 249d03d2292SJohn Brawn Features.push_back("-vfp3"); 250d9e39d53SJohn Brawn Features.push_back("-fp16"); 251d03d2292SJohn Brawn Features.push_back("-vfp4"); 252d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 253d03d2292SJohn Brawn break; 254d5526303SJaved Absar case ARM::FV_NONE: 255d03d2292SJohn Brawn Features.push_back("-vfp2"); 256d03d2292SJohn Brawn Features.push_back("-vfp3"); 257d9e39d53SJohn Brawn Features.push_back("-fp16"); 258d03d2292SJohn Brawn Features.push_back("-vfp4"); 259d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 260d03d2292SJohn Brawn break; 261d03d2292SJohn Brawn } 262d03d2292SJohn Brawn 263d03d2292SJohn Brawn // crypto includes neon, so we handle this similarly to FPU version. 264d03d2292SJohn Brawn switch (FPUNames[FPUKind].NeonSupport) { 265d03d2292SJohn Brawn case ARM::NS_Crypto: 266ea33e5e8SAlexandros Lamprineas Features.push_back("+neon"); 267d03d2292SJohn Brawn Features.push_back("+crypto"); 268d03d2292SJohn Brawn break; 269d03d2292SJohn Brawn case ARM::NS_Neon: 270d03d2292SJohn Brawn Features.push_back("+neon"); 271d03d2292SJohn Brawn Features.push_back("-crypto"); 272d03d2292SJohn Brawn break; 273d03d2292SJohn Brawn case ARM::NS_None: 274d03d2292SJohn Brawn Features.push_back("-neon"); 275d03d2292SJohn Brawn Features.push_back("-crypto"); 276d03d2292SJohn Brawn break; 277d03d2292SJohn Brawn } 278d03d2292SJohn Brawn 279d03d2292SJohn Brawn return true; 280d03d2292SJohn Brawn } 281d03d2292SJohn Brawn 2823309ef6fSChandler Carruth StringRef llvm::ARM::getArchName(unsigned ArchKind) { 283e8048f0dSRenato Golin if (ArchKind >= ARM::AK_LAST) 2843309ef6fSChandler Carruth return StringRef(); 2853309ef6fSChandler Carruth return ARCHNames[ArchKind].getName(); 286f5f373fcSRenato Golin } 287f5f373fcSRenato Golin 2883309ef6fSChandler Carruth StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) { 289e8048f0dSRenato Golin if (ArchKind >= ARM::AK_LAST) 2903309ef6fSChandler Carruth return StringRef(); 2913309ef6fSChandler Carruth return ARCHNames[ArchKind].getCPUAttr(); 292f5f373fcSRenato Golin } 293f5f373fcSRenato Golin 2943309ef6fSChandler Carruth StringRef llvm::ARM::getSubArch(unsigned ArchKind) { 29542dad647SRenato Golin if (ArchKind >= ARM::AK_LAST) 2963309ef6fSChandler Carruth return StringRef(); 2973309ef6fSChandler Carruth return ARCHNames[ArchKind].getSubArch(); 29842dad647SRenato Golin } 29942dad647SRenato Golin 300bb47b9a3SChandler Carruth unsigned llvm::ARM::getArchAttr(unsigned ArchKind) { 301e8048f0dSRenato Golin if (ArchKind >= ARM::AK_LAST) 302e8048f0dSRenato Golin return ARMBuildAttrs::CPUArch::Pre_v4; 303f7c0d5f2SRenato Golin return ARCHNames[ArchKind].ArchAttr; 304f5f373fcSRenato Golin } 305f5f373fcSRenato Golin 3063309ef6fSChandler Carruth StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { 3074ea70755SAlexandros Lamprineas for (const auto AE : ARCHExtNames) { 3084ea70755SAlexandros Lamprineas if (ArchExtKind == AE.ID) 3093309ef6fSChandler Carruth return AE.getName(); 3104ea70755SAlexandros Lamprineas } 3113309ef6fSChandler Carruth return StringRef(); 3124ea70755SAlexandros Lamprineas } 3134ea70755SAlexandros Lamprineas 3143309ef6fSChandler Carruth StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { 3154ea70755SAlexandros Lamprineas for (const auto D : HWDivNames) { 3164ea70755SAlexandros Lamprineas if (HWDivKind == D.ID) 3173309ef6fSChandler Carruth return D.getName(); 3184ea70755SAlexandros Lamprineas } 3193309ef6fSChandler Carruth return StringRef(); 320e8048f0dSRenato Golin } 321e8048f0dSRenato Golin 322ea33e5e8SAlexandros Lamprineas unsigned llvm::ARM::getDefaultExtensions(StringRef CPU) { 323ea33e5e8SAlexandros Lamprineas for (const auto C : CPUNames) { 324ea33e5e8SAlexandros Lamprineas if (CPU == C.getName()) 325ea33e5e8SAlexandros Lamprineas return (ARCHNames[C.ArchID].ArchBaseExtensions | C.DefaultExtensions); 326ea33e5e8SAlexandros Lamprineas } 327ea33e5e8SAlexandros Lamprineas return ARM::AEK_INVALID; 328ea33e5e8SAlexandros Lamprineas } 329ea33e5e8SAlexandros Lamprineas 3303309ef6fSChandler Carruth StringRef llvm::ARM::getDefaultCPU(StringRef Arch) { 331e8048f0dSRenato Golin unsigned AK = parseArch(Arch); 332e8048f0dSRenato Golin if (AK == ARM::AK_INVALID) 3333309ef6fSChandler Carruth return StringRef(); 334e8048f0dSRenato Golin 335e8048f0dSRenato Golin // Look for multiple AKs to find the default for pair AK+Name. 336e8048f0dSRenato Golin for (const auto CPU : CPUNames) { 337e8048f0dSRenato Golin if (CPU.ArchID == AK && CPU.Default) 3383309ef6fSChandler Carruth return CPU.getName(); 339e8048f0dSRenato Golin } 3403309ef6fSChandler Carruth return StringRef(); 341f5f373fcSRenato Golin } 342f5f373fcSRenato Golin 343f5f373fcSRenato Golin // ======================================================= // 344f5f373fcSRenato Golin // Parsers 345f5f373fcSRenato Golin // ======================================================= // 346f5f373fcSRenato Golin 347bb47b9a3SChandler Carruth static StringRef getHWDivSynonym(StringRef HWDiv) { 3484ea70755SAlexandros Lamprineas return StringSwitch<StringRef>(HWDiv) 3494ea70755SAlexandros Lamprineas .Case("thumb,arm", "arm,thumb") 3504ea70755SAlexandros Lamprineas .Default(HWDiv); 3514ea70755SAlexandros Lamprineas } 3524ea70755SAlexandros Lamprineas 353bb47b9a3SChandler Carruth static StringRef getFPUSynonym(StringRef FPU) { 354f5f373fcSRenato Golin return StringSwitch<StringRef>(FPU) 355f5f373fcSRenato Golin .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 356f5f373fcSRenato Golin .Case("vfp2", "vfpv2") 357f5f373fcSRenato Golin .Case("vfp3", "vfpv3") 358f5f373fcSRenato Golin .Case("vfp4", "vfpv4") 359f5f373fcSRenato Golin .Case("vfp3-d16", "vfpv3-d16") 360f5f373fcSRenato Golin .Case("vfp4-d16", "vfpv4-d16") 361985c04e8SJohn Brawn .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 362f5f373fcSRenato Golin .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 363985c04e8SJohn Brawn .Case("fp5-sp-d16", "fpv5-sp-d16") 364f5f373fcSRenato Golin .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 365f5f373fcSRenato Golin // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 366f5f373fcSRenato Golin .Case("neon-vfpv3", "neon") 367f5f373fcSRenato Golin .Default(FPU); 368f5f373fcSRenato Golin } 369f5f373fcSRenato Golin 370bb47b9a3SChandler Carruth static StringRef getArchSynonym(StringRef Arch) { 371f5f373fcSRenato Golin return StringSwitch<StringRef>(Arch) 372*2c2f378fSArtyom Skrobov .Case("v5", "v5t") 373*2c2f378fSArtyom Skrobov .Case("v5e", "v5te") 374*2c2f378fSArtyom Skrobov .Case("v6hl", "v6k") 375*2c2f378fSArtyom Skrobov .Cases("v6m", "v6sm", "v6s-m", "v6-m") 376*2c2f378fSArtyom Skrobov .Cases("v7", "v7a", "v7hl", "v7l", "v7-a") 37785aebc8cSArtyom Skrobov .Case("v7r", "v7-r") 37885aebc8cSArtyom Skrobov .Case("v7m", "v7-m") 37985aebc8cSArtyom Skrobov .Case("v7em", "v7e-m") 380acd1cd66SArtyom Skrobov .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") 38185aebc8cSArtyom Skrobov .Case("v8.1a", "v8.1-a") 382f5f373fcSRenato Golin .Default(Arch); 383f5f373fcSRenato Golin } 384f5f373fcSRenato Golin 385e8048f0dSRenato Golin // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but 386e8048f0dSRenato Golin // (iwmmxt|xscale)(eb)? is also permitted. If the former, return 387ebdd12cbSRenato Golin // "v.+", if the latter, return unmodified string, minus 'eb'. 388ebdd12cbSRenato Golin // If invalid, return empty string. 389bb47b9a3SChandler Carruth StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { 390e8048f0dSRenato Golin size_t offset = StringRef::npos; 391e8048f0dSRenato Golin StringRef A = Arch; 392b6b9e056SRenato Golin StringRef Error = ""; 393e8048f0dSRenato Golin 394e8048f0dSRenato Golin // Begins with "arm" / "thumb", move past it. 395ebdd12cbSRenato Golin if (A.startswith("arm64")) 396ebdd12cbSRenato Golin offset = 5; 397ebdd12cbSRenato Golin else if (A.startswith("arm")) 398e8048f0dSRenato Golin offset = 3; 399e8048f0dSRenato Golin else if (A.startswith("thumb")) 400e8048f0dSRenato Golin offset = 5; 401b6b9e056SRenato Golin else if (A.startswith("aarch64")) { 402b6b9e056SRenato Golin offset = 7; 403b6b9e056SRenato Golin // AArch64 uses "_be", not "eb" suffix. 404b6b9e056SRenato Golin if (A.find("eb") != StringRef::npos) 405b6b9e056SRenato Golin return Error; 406b6b9e056SRenato Golin if (A.substr(offset, 3) == "_be") 407b6b9e056SRenato Golin offset += 3; 408b6b9e056SRenato Golin } 409b6b9e056SRenato Golin 410e8048f0dSRenato Golin // Ex. "armebv7", move past the "eb". 411e8048f0dSRenato Golin if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 412e8048f0dSRenato Golin offset += 2; 413e8048f0dSRenato Golin // Or, if it ends with eb ("armv7eb"), chop it off. 414e8048f0dSRenato Golin else if (A.endswith("eb")) 415e8048f0dSRenato Golin A = A.substr(0, A.size() - 2); 416ebdd12cbSRenato Golin // Trim the head 417ebdd12cbSRenato Golin if (offset != StringRef::npos) 418e8048f0dSRenato Golin A = A.substr(offset); 419e8048f0dSRenato Golin 420ebdd12cbSRenato Golin // Empty string means offset reached the end, which means it's valid. 421e8048f0dSRenato Golin if (A.empty()) 422e8048f0dSRenato Golin return Arch; 423e8048f0dSRenato Golin 424ebdd12cbSRenato Golin // Only match non-marketing names 425ebdd12cbSRenato Golin if (offset != StringRef::npos) { 426ebdd12cbSRenato Golin // Must start with 'vN'. 427ebdd12cbSRenato Golin if (A[0] != 'v' || !std::isdigit(A[1])) 428b6b9e056SRenato Golin return Error; 429ebdd12cbSRenato Golin // Can't have an extra 'eb'. 430ebdd12cbSRenato Golin if (A.find("eb") != StringRef::npos) 431ebdd12cbSRenato Golin return Error; 432ebdd12cbSRenato Golin } 433e8048f0dSRenato Golin 434ebdd12cbSRenato Golin // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 435e8048f0dSRenato Golin return A; 436e8048f0dSRenato Golin } 437e8048f0dSRenato Golin 438bb47b9a3SChandler Carruth unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { 4394ea70755SAlexandros Lamprineas StringRef Syn = getHWDivSynonym(HWDiv); 4404ea70755SAlexandros Lamprineas for (const auto D : HWDivNames) { 4413309ef6fSChandler Carruth if (Syn == D.getName()) 4424ea70755SAlexandros Lamprineas return D.ID; 4434ea70755SAlexandros Lamprineas } 4444ea70755SAlexandros Lamprineas return ARM::AEK_INVALID; 4454ea70755SAlexandros Lamprineas } 4464ea70755SAlexandros Lamprineas 447bb47b9a3SChandler Carruth unsigned llvm::ARM::parseFPU(StringRef FPU) { 448f5f373fcSRenato Golin StringRef Syn = getFPUSynonym(FPU); 449f5f373fcSRenato Golin for (const auto F : FPUNames) { 4503309ef6fSChandler Carruth if (Syn == F.getName()) 451f5f373fcSRenato Golin return F.ID; 452f5f373fcSRenato Golin } 45335de35d0SRenato Golin return ARM::FK_INVALID; 454f5f373fcSRenato Golin } 455f5f373fcSRenato Golin 456e8048f0dSRenato Golin // Allows partial match, ex. "v7a" matches "armv7a". 457bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArch(StringRef Arch) { 45885aebc8cSArtyom Skrobov Arch = getCanonicalArchName(Arch); 459f5f373fcSRenato Golin StringRef Syn = getArchSynonym(Arch); 460f5f373fcSRenato Golin for (const auto A : ARCHNames) { 4613309ef6fSChandler Carruth if (A.getName().endswith(Syn)) 462f5f373fcSRenato Golin return A.ID; 463f5f373fcSRenato Golin } 46435de35d0SRenato Golin return ARM::AK_INVALID; 465f5f373fcSRenato Golin } 466f5f373fcSRenato Golin 467bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { 468f5f373fcSRenato Golin for (const auto A : ARCHExtNames) { 4693309ef6fSChandler Carruth if (ArchExt == A.getName()) 470f5f373fcSRenato Golin return A.ID; 471f5f373fcSRenato Golin } 47235de35d0SRenato Golin return ARM::AEK_INVALID; 473f5f373fcSRenato Golin } 474f5f373fcSRenato Golin 475bb47b9a3SChandler Carruth unsigned llvm::ARM::parseCPUArch(StringRef CPU) { 476e8048f0dSRenato Golin for (const auto C : CPUNames) { 4773309ef6fSChandler Carruth if (CPU == C.getName()) 478e8048f0dSRenato Golin return C.ArchID; 479e8048f0dSRenato Golin } 480e8048f0dSRenato Golin return ARM::AK_INVALID; 481e8048f0dSRenato Golin } 482e8048f0dSRenato Golin 483b6b9e056SRenato Golin // ARM, Thumb, AArch64 484bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchISA(StringRef Arch) { 485b6b9e056SRenato Golin return StringSwitch<unsigned>(Arch) 486b6b9e056SRenato Golin .StartsWith("aarch64", ARM::IK_AARCH64) 487b6b9e056SRenato Golin .StartsWith("arm64", ARM::IK_AARCH64) 488b6b9e056SRenato Golin .StartsWith("thumb", ARM::IK_THUMB) 489b6b9e056SRenato Golin .StartsWith("arm", ARM::IK_ARM) 490b6b9e056SRenato Golin .Default(ARM::EK_INVALID); 491b6b9e056SRenato Golin } 492b6b9e056SRenato Golin 493b6b9e056SRenato Golin // Little/Big endian 494bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchEndian(StringRef Arch) { 4954fc3a986SChandler Carruth if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || 496b6b9e056SRenato Golin Arch.startswith("aarch64_be")) 497b6b9e056SRenato Golin return ARM::EK_BIG; 498b6b9e056SRenato Golin 499b6b9e056SRenato Golin if (Arch.startswith("arm") || Arch.startswith("thumb")) { 500b6b9e056SRenato Golin if (Arch.endswith("eb")) 501b6b9e056SRenato Golin return ARM::EK_BIG; 502b6b9e056SRenato Golin else 503b6b9e056SRenato Golin return ARM::EK_LITTLE; 504b6b9e056SRenato Golin } 505b6b9e056SRenato Golin 506b6b9e056SRenato Golin if (Arch.startswith("aarch64")) 507b6b9e056SRenato Golin return ARM::EK_LITTLE; 508b6b9e056SRenato Golin 509b6b9e056SRenato Golin return ARM::EK_INVALID; 510b6b9e056SRenato Golin } 511b6b9e056SRenato Golin 512fadc2108SRenato Golin // Profile A/R/M 513bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchProfile(StringRef Arch) { 514fadc2108SRenato Golin Arch = getCanonicalArchName(Arch); 515fadc2108SRenato Golin switch (parseArch(Arch)) { 516fadc2108SRenato Golin case ARM::AK_ARMV6M: 517fadc2108SRenato Golin case ARM::AK_ARMV7M: 518fadc2108SRenato Golin case ARM::AK_ARMV7EM: 519fadc2108SRenato Golin return ARM::PK_M; 520fadc2108SRenato Golin case ARM::AK_ARMV7R: 521fadc2108SRenato Golin return ARM::PK_R; 522fadc2108SRenato Golin case ARM::AK_ARMV7A: 5232d4d1615STim Northover case ARM::AK_ARMV7K: 524fadc2108SRenato Golin case ARM::AK_ARMV8A: 525fadc2108SRenato Golin case ARM::AK_ARMV8_1A: 526fadc2108SRenato Golin return ARM::PK_A; 527fadc2108SRenato Golin } 528fadc2108SRenato Golin return ARM::PK_INVALID; 529fadc2108SRenato Golin } 530fadc2108SRenato Golin 531ebdd12cbSRenato Golin // Version number (ex. v7 = 7). 532bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchVersion(StringRef Arch) { 533fadc2108SRenato Golin Arch = getCanonicalArchName(Arch); 534fadc2108SRenato Golin switch (parseArch(Arch)) { 535fadc2108SRenato Golin case ARM::AK_ARMV2: 536fadc2108SRenato Golin case ARM::AK_ARMV2A: 537fadc2108SRenato Golin return 2; 538fadc2108SRenato Golin case ARM::AK_ARMV3: 539fadc2108SRenato Golin case ARM::AK_ARMV3M: 540fadc2108SRenato Golin return 3; 541fadc2108SRenato Golin case ARM::AK_ARMV4: 542fadc2108SRenato Golin case ARM::AK_ARMV4T: 543fadc2108SRenato Golin return 4; 544fadc2108SRenato Golin case ARM::AK_ARMV5T: 545fadc2108SRenato Golin case ARM::AK_ARMV5TE: 546fadc2108SRenato Golin case ARM::AK_IWMMXT: 547fadc2108SRenato Golin case ARM::AK_IWMMXT2: 548fadc2108SRenato Golin case ARM::AK_XSCALE: 549fadc2108SRenato Golin case ARM::AK_ARMV5TEJ: 550fadc2108SRenato Golin return 5; 551fadc2108SRenato Golin case ARM::AK_ARMV6: 552fadc2108SRenato Golin case ARM::AK_ARMV6J: 553fadc2108SRenato Golin case ARM::AK_ARMV6K: 554fadc2108SRenato Golin case ARM::AK_ARMV6T2: 555fadc2108SRenato Golin case ARM::AK_ARMV6Z: 556fadc2108SRenato Golin case ARM::AK_ARMV6ZK: 557fadc2108SRenato Golin case ARM::AK_ARMV6M: 558fadc2108SRenato Golin return 6; 559fadc2108SRenato Golin case ARM::AK_ARMV7A: 560fadc2108SRenato Golin case ARM::AK_ARMV7R: 561fadc2108SRenato Golin case ARM::AK_ARMV7M: 562fadc2108SRenato Golin case ARM::AK_ARMV7S: 563fadc2108SRenato Golin case ARM::AK_ARMV7EM: 564366dd9fdSVedant Kumar case ARM::AK_ARMV7K: 565fadc2108SRenato Golin return 7; 566fadc2108SRenato Golin case ARM::AK_ARMV8A: 567fadc2108SRenato Golin case ARM::AK_ARMV8_1A: 568fadc2108SRenato Golin return 8; 569fadc2108SRenato Golin } 570fadc2108SRenato Golin return 0; 571fadc2108SRenato Golin } 572