1bdd1243dSDimitry Andric //===-- ARMTargetParser - Parser for ARM target features --------*- C++ -*-===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric // 9bdd1243dSDimitry Andric // This file implements a target parser to recognise ARM hardware features 10bdd1243dSDimitry Andric // such as FPU/CPU/ARCH/extensions and specific support such as HWDIV. 11bdd1243dSDimitry Andric // 12bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 13bdd1243dSDimitry Andric 14bdd1243dSDimitry Andric #include "llvm/TargetParser/ARMTargetParser.h" 15bdd1243dSDimitry Andric #include "llvm/ADT/StringSwitch.h" 16bdd1243dSDimitry Andric #include "llvm/TargetParser/ARMTargetParserCommon.h" 17bdd1243dSDimitry Andric #include "llvm/TargetParser/Triple.h" 18bdd1243dSDimitry Andric #include <cctype> 19bdd1243dSDimitry Andric 20bdd1243dSDimitry Andric using namespace llvm; 21bdd1243dSDimitry Andric 22bdd1243dSDimitry Andric static StringRef getHWDivSynonym(StringRef HWDiv) { 23bdd1243dSDimitry Andric return StringSwitch<StringRef>(HWDiv) 24bdd1243dSDimitry Andric .Case("thumb,arm", "arm,thumb") 25bdd1243dSDimitry Andric .Default(HWDiv); 26bdd1243dSDimitry Andric } 27bdd1243dSDimitry Andric 28bdd1243dSDimitry Andric // Allows partial match, ex. "v7a" matches "armv7a". 29bdd1243dSDimitry Andric ARM::ArchKind ARM::parseArch(StringRef Arch) { 30bdd1243dSDimitry Andric Arch = getCanonicalArchName(Arch); 31bdd1243dSDimitry Andric StringRef Syn = getArchSynonym(Arch); 32bdd1243dSDimitry Andric for (const auto &A : ARMArchNames) { 33bdd1243dSDimitry Andric if (A.Name.endswith(Syn)) 34bdd1243dSDimitry Andric return A.ID; 35bdd1243dSDimitry Andric } 36bdd1243dSDimitry Andric return ArchKind::INVALID; 37bdd1243dSDimitry Andric } 38bdd1243dSDimitry Andric 39bdd1243dSDimitry Andric // Version number (ex. v7 = 7). 40bdd1243dSDimitry Andric unsigned ARM::parseArchVersion(StringRef Arch) { 41bdd1243dSDimitry Andric Arch = getCanonicalArchName(Arch); 42bdd1243dSDimitry Andric switch (parseArch(Arch)) { 43bdd1243dSDimitry Andric case ArchKind::ARMV4: 44bdd1243dSDimitry Andric case ArchKind::ARMV4T: 45bdd1243dSDimitry Andric return 4; 46bdd1243dSDimitry Andric case ArchKind::ARMV5T: 47bdd1243dSDimitry Andric case ArchKind::ARMV5TE: 48bdd1243dSDimitry Andric case ArchKind::IWMMXT: 49bdd1243dSDimitry Andric case ArchKind::IWMMXT2: 50bdd1243dSDimitry Andric case ArchKind::XSCALE: 51bdd1243dSDimitry Andric case ArchKind::ARMV5TEJ: 52bdd1243dSDimitry Andric return 5; 53bdd1243dSDimitry Andric case ArchKind::ARMV6: 54bdd1243dSDimitry Andric case ArchKind::ARMV6K: 55bdd1243dSDimitry Andric case ArchKind::ARMV6T2: 56bdd1243dSDimitry Andric case ArchKind::ARMV6KZ: 57bdd1243dSDimitry Andric case ArchKind::ARMV6M: 58bdd1243dSDimitry Andric return 6; 59bdd1243dSDimitry Andric case ArchKind::ARMV7A: 60bdd1243dSDimitry Andric case ArchKind::ARMV7VE: 61bdd1243dSDimitry Andric case ArchKind::ARMV7R: 62bdd1243dSDimitry Andric case ArchKind::ARMV7M: 63bdd1243dSDimitry Andric case ArchKind::ARMV7S: 64bdd1243dSDimitry Andric case ArchKind::ARMV7EM: 65bdd1243dSDimitry Andric case ArchKind::ARMV7K: 66bdd1243dSDimitry Andric return 7; 67bdd1243dSDimitry Andric case ArchKind::ARMV8A: 68bdd1243dSDimitry Andric case ArchKind::ARMV8_1A: 69bdd1243dSDimitry Andric case ArchKind::ARMV8_2A: 70bdd1243dSDimitry Andric case ArchKind::ARMV8_3A: 71bdd1243dSDimitry Andric case ArchKind::ARMV8_4A: 72bdd1243dSDimitry Andric case ArchKind::ARMV8_5A: 73bdd1243dSDimitry Andric case ArchKind::ARMV8_6A: 74bdd1243dSDimitry Andric case ArchKind::ARMV8_7A: 75bdd1243dSDimitry Andric case ArchKind::ARMV8_8A: 76bdd1243dSDimitry Andric case ArchKind::ARMV8_9A: 77bdd1243dSDimitry Andric case ArchKind::ARMV8R: 78bdd1243dSDimitry Andric case ArchKind::ARMV8MBaseline: 79bdd1243dSDimitry Andric case ArchKind::ARMV8MMainline: 80bdd1243dSDimitry Andric case ArchKind::ARMV8_1MMainline: 81bdd1243dSDimitry Andric return 8; 82bdd1243dSDimitry Andric case ArchKind::ARMV9A: 83bdd1243dSDimitry Andric case ArchKind::ARMV9_1A: 84bdd1243dSDimitry Andric case ArchKind::ARMV9_2A: 85bdd1243dSDimitry Andric case ArchKind::ARMV9_3A: 86bdd1243dSDimitry Andric case ArchKind::ARMV9_4A: 87bdd1243dSDimitry Andric return 9; 88bdd1243dSDimitry Andric case ArchKind::INVALID: 89bdd1243dSDimitry Andric return 0; 90bdd1243dSDimitry Andric } 91bdd1243dSDimitry Andric llvm_unreachable("Unhandled architecture"); 92bdd1243dSDimitry Andric } 93bdd1243dSDimitry Andric 94bdd1243dSDimitry Andric static ARM::ProfileKind getProfileKind(ARM::ArchKind AK) { 95bdd1243dSDimitry Andric switch (AK) { 96bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6M: 97bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7M: 98bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7EM: 99bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8MMainline: 100bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8MBaseline: 101bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_1MMainline: 102bdd1243dSDimitry Andric return ARM::ProfileKind::M; 103bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7R: 104bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8R: 105bdd1243dSDimitry Andric return ARM::ProfileKind::R; 106bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7A: 107bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7VE: 108bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7K: 109bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8A: 110bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_1A: 111bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_2A: 112bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_3A: 113bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_4A: 114bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_5A: 115bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_6A: 116bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_7A: 117bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_8A: 118bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_9A: 119bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9A: 120bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9_1A: 121bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9_2A: 122bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9_3A: 123bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9_4A: 124bdd1243dSDimitry Andric return ARM::ProfileKind::A; 125bdd1243dSDimitry Andric case ARM::ArchKind::ARMV4: 126bdd1243dSDimitry Andric case ARM::ArchKind::ARMV4T: 127bdd1243dSDimitry Andric case ARM::ArchKind::ARMV5T: 128bdd1243dSDimitry Andric case ARM::ArchKind::ARMV5TE: 129bdd1243dSDimitry Andric case ARM::ArchKind::ARMV5TEJ: 130bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6: 131bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6K: 132bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6T2: 133bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6KZ: 134bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7S: 135bdd1243dSDimitry Andric case ARM::ArchKind::IWMMXT: 136bdd1243dSDimitry Andric case ARM::ArchKind::IWMMXT2: 137bdd1243dSDimitry Andric case ARM::ArchKind::XSCALE: 138bdd1243dSDimitry Andric case ARM::ArchKind::INVALID: 139bdd1243dSDimitry Andric return ARM::ProfileKind::INVALID; 140bdd1243dSDimitry Andric } 141bdd1243dSDimitry Andric llvm_unreachable("Unhandled architecture"); 142bdd1243dSDimitry Andric } 143bdd1243dSDimitry Andric 144bdd1243dSDimitry Andric // Profile A/R/M 145bdd1243dSDimitry Andric ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) { 146bdd1243dSDimitry Andric Arch = getCanonicalArchName(Arch); 147bdd1243dSDimitry Andric return getProfileKind(parseArch(Arch)); 148bdd1243dSDimitry Andric } 149bdd1243dSDimitry Andric 150*06c3fb27SDimitry Andric bool ARM::getFPUFeatures(ARM::FPUKind FPUKind, 151*06c3fb27SDimitry Andric std::vector<StringRef> &Features) { 152bdd1243dSDimitry Andric 153bdd1243dSDimitry Andric if (FPUKind >= FK_LAST || FPUKind == FK_INVALID) 154bdd1243dSDimitry Andric return false; 155bdd1243dSDimitry Andric 156bdd1243dSDimitry Andric static const struct FPUFeatureNameInfo { 157bdd1243dSDimitry Andric const char *PlusName, *MinusName; 158bdd1243dSDimitry Andric FPUVersion MinVersion; 159bdd1243dSDimitry Andric FPURestriction MaxRestriction; 160bdd1243dSDimitry Andric } FPUFeatureInfoList[] = { 161bdd1243dSDimitry Andric // We have to specify the + and - versions of the name in full so 162bdd1243dSDimitry Andric // that we can return them as static StringRefs. 163bdd1243dSDimitry Andric // 164bdd1243dSDimitry Andric // Also, the SubtargetFeatures ending in just "sp" are listed here 165bdd1243dSDimitry Andric // under FPURestriction::None, which is the only FPURestriction in 166bdd1243dSDimitry Andric // which they would be valid (since FPURestriction::SP doesn't 167bdd1243dSDimitry Andric // exist). 168bdd1243dSDimitry Andric {"+vfp2", "-vfp2", FPUVersion::VFPV2, FPURestriction::D16}, 169bdd1243dSDimitry Andric {"+vfp2sp", "-vfp2sp", FPUVersion::VFPV2, FPURestriction::SP_D16}, 170bdd1243dSDimitry Andric {"+vfp3", "-vfp3", FPUVersion::VFPV3, FPURestriction::None}, 171bdd1243dSDimitry Andric {"+vfp3d16", "-vfp3d16", FPUVersion::VFPV3, FPURestriction::D16}, 172bdd1243dSDimitry Andric {"+vfp3d16sp", "-vfp3d16sp", FPUVersion::VFPV3, FPURestriction::SP_D16}, 173bdd1243dSDimitry Andric {"+vfp3sp", "-vfp3sp", FPUVersion::VFPV3, FPURestriction::None}, 174bdd1243dSDimitry Andric {"+fp16", "-fp16", FPUVersion::VFPV3_FP16, FPURestriction::SP_D16}, 175bdd1243dSDimitry Andric {"+vfp4", "-vfp4", FPUVersion::VFPV4, FPURestriction::None}, 176bdd1243dSDimitry Andric {"+vfp4d16", "-vfp4d16", FPUVersion::VFPV4, FPURestriction::D16}, 177bdd1243dSDimitry Andric {"+vfp4d16sp", "-vfp4d16sp", FPUVersion::VFPV4, FPURestriction::SP_D16}, 178bdd1243dSDimitry Andric {"+vfp4sp", "-vfp4sp", FPUVersion::VFPV4, FPURestriction::None}, 179bdd1243dSDimitry Andric {"+fp-armv8", "-fp-armv8", FPUVersion::VFPV5, FPURestriction::None}, 180bdd1243dSDimitry Andric {"+fp-armv8d16", "-fp-armv8d16", FPUVersion::VFPV5, FPURestriction::D16}, 181bdd1243dSDimitry Andric {"+fp-armv8d16sp", "-fp-armv8d16sp", FPUVersion::VFPV5, FPURestriction::SP_D16}, 182bdd1243dSDimitry Andric {"+fp-armv8sp", "-fp-armv8sp", FPUVersion::VFPV5, FPURestriction::None}, 183bdd1243dSDimitry Andric {"+fullfp16", "-fullfp16", FPUVersion::VFPV5_FULLFP16, FPURestriction::SP_D16}, 184bdd1243dSDimitry Andric {"+fp64", "-fp64", FPUVersion::VFPV2, FPURestriction::D16}, 185bdd1243dSDimitry Andric {"+d32", "-d32", FPUVersion::VFPV3, FPURestriction::None}, 186bdd1243dSDimitry Andric }; 187bdd1243dSDimitry Andric 188bdd1243dSDimitry Andric for (const auto &Info: FPUFeatureInfoList) { 189bdd1243dSDimitry Andric if (FPUNames[FPUKind].FPUVer >= Info.MinVersion && 190bdd1243dSDimitry Andric FPUNames[FPUKind].Restriction <= Info.MaxRestriction) 191bdd1243dSDimitry Andric Features.push_back(Info.PlusName); 192bdd1243dSDimitry Andric else 193bdd1243dSDimitry Andric Features.push_back(Info.MinusName); 194bdd1243dSDimitry Andric } 195bdd1243dSDimitry Andric 196bdd1243dSDimitry Andric static const struct NeonFeatureNameInfo { 197bdd1243dSDimitry Andric const char *PlusName, *MinusName; 198bdd1243dSDimitry Andric NeonSupportLevel MinSupportLevel; 199bdd1243dSDimitry Andric } NeonFeatureInfoList[] = { 200bdd1243dSDimitry Andric {"+neon", "-neon", NeonSupportLevel::Neon}, 201bdd1243dSDimitry Andric {"+sha2", "-sha2", NeonSupportLevel::Crypto}, 202bdd1243dSDimitry Andric {"+aes", "-aes", NeonSupportLevel::Crypto}, 203bdd1243dSDimitry Andric }; 204bdd1243dSDimitry Andric 205bdd1243dSDimitry Andric for (const auto &Info: NeonFeatureInfoList) { 206bdd1243dSDimitry Andric if (FPUNames[FPUKind].NeonSupport >= Info.MinSupportLevel) 207bdd1243dSDimitry Andric Features.push_back(Info.PlusName); 208bdd1243dSDimitry Andric else 209bdd1243dSDimitry Andric Features.push_back(Info.MinusName); 210bdd1243dSDimitry Andric } 211bdd1243dSDimitry Andric 212bdd1243dSDimitry Andric return true; 213bdd1243dSDimitry Andric } 214bdd1243dSDimitry Andric 215*06c3fb27SDimitry Andric ARM::FPUKind ARM::parseFPU(StringRef FPU) { 216bdd1243dSDimitry Andric StringRef Syn = getFPUSynonym(FPU); 217bdd1243dSDimitry Andric for (const auto &F : FPUNames) { 218bdd1243dSDimitry Andric if (Syn == F.Name) 219bdd1243dSDimitry Andric return F.ID; 220bdd1243dSDimitry Andric } 221bdd1243dSDimitry Andric return FK_INVALID; 222bdd1243dSDimitry Andric } 223bdd1243dSDimitry Andric 224*06c3fb27SDimitry Andric ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(ARM::FPUKind FPUKind) { 225bdd1243dSDimitry Andric if (FPUKind >= FK_LAST) 226bdd1243dSDimitry Andric return NeonSupportLevel::None; 227bdd1243dSDimitry Andric return FPUNames[FPUKind].NeonSupport; 228bdd1243dSDimitry Andric } 229bdd1243dSDimitry Andric 230bdd1243dSDimitry Andric StringRef ARM::getFPUSynonym(StringRef FPU) { 231bdd1243dSDimitry Andric return StringSwitch<StringRef>(FPU) 232bdd1243dSDimitry Andric .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 233bdd1243dSDimitry Andric .Case("vfp2", "vfpv2") 234bdd1243dSDimitry Andric .Case("vfp3", "vfpv3") 235bdd1243dSDimitry Andric .Case("vfp4", "vfpv4") 236bdd1243dSDimitry Andric .Case("vfp3-d16", "vfpv3-d16") 237bdd1243dSDimitry Andric .Case("vfp4-d16", "vfpv4-d16") 238bdd1243dSDimitry Andric .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 239bdd1243dSDimitry Andric .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 240bdd1243dSDimitry Andric .Case("fp5-sp-d16", "fpv5-sp-d16") 241bdd1243dSDimitry Andric .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 242bdd1243dSDimitry Andric // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 243bdd1243dSDimitry Andric .Case("neon-vfpv3", "neon") 244bdd1243dSDimitry Andric .Default(FPU); 245bdd1243dSDimitry Andric } 246bdd1243dSDimitry Andric 247*06c3fb27SDimitry Andric StringRef ARM::getFPUName(ARM::FPUKind FPUKind) { 248bdd1243dSDimitry Andric if (FPUKind >= FK_LAST) 249bdd1243dSDimitry Andric return StringRef(); 250bdd1243dSDimitry Andric return FPUNames[FPUKind].Name; 251bdd1243dSDimitry Andric } 252bdd1243dSDimitry Andric 253*06c3fb27SDimitry Andric ARM::FPUVersion ARM::getFPUVersion(ARM::FPUKind FPUKind) { 254bdd1243dSDimitry Andric if (FPUKind >= FK_LAST) 255bdd1243dSDimitry Andric return FPUVersion::NONE; 256bdd1243dSDimitry Andric return FPUNames[FPUKind].FPUVer; 257bdd1243dSDimitry Andric } 258bdd1243dSDimitry Andric 259*06c3fb27SDimitry Andric ARM::FPURestriction ARM::getFPURestriction(ARM::FPUKind FPUKind) { 260bdd1243dSDimitry Andric if (FPUKind >= FK_LAST) 261bdd1243dSDimitry Andric return FPURestriction::None; 262bdd1243dSDimitry Andric return FPUNames[FPUKind].Restriction; 263bdd1243dSDimitry Andric } 264bdd1243dSDimitry Andric 265*06c3fb27SDimitry Andric ARM::FPUKind ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) { 266bdd1243dSDimitry Andric if (CPU == "generic") 267bdd1243dSDimitry Andric return ARM::ARMArchNames[static_cast<unsigned>(AK)].DefaultFPU; 268bdd1243dSDimitry Andric 269*06c3fb27SDimitry Andric return StringSwitch<ARM::FPUKind>(CPU) 270bdd1243dSDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 271bdd1243dSDimitry Andric .Case(NAME, DEFAULT_FPU) 272bdd1243dSDimitry Andric #include "llvm/TargetParser/ARMTargetParser.def" 273bdd1243dSDimitry Andric .Default(ARM::FK_INVALID); 274bdd1243dSDimitry Andric } 275bdd1243dSDimitry Andric 276bdd1243dSDimitry Andric uint64_t ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) { 277bdd1243dSDimitry Andric if (CPU == "generic") 278bdd1243dSDimitry Andric return ARM::ARMArchNames[static_cast<unsigned>(AK)].ArchBaseExtensions; 279bdd1243dSDimitry Andric 280bdd1243dSDimitry Andric return StringSwitch<uint64_t>(CPU) 281bdd1243dSDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 282bdd1243dSDimitry Andric .Case(NAME, \ 283bdd1243dSDimitry Andric ARMArchNames[static_cast<unsigned>(ArchKind::ID)].ArchBaseExtensions | \ 284bdd1243dSDimitry Andric DEFAULT_EXT) 285bdd1243dSDimitry Andric #include "llvm/TargetParser/ARMTargetParser.def" 286bdd1243dSDimitry Andric .Default(ARM::AEK_INVALID); 287bdd1243dSDimitry Andric } 288bdd1243dSDimitry Andric 289bdd1243dSDimitry Andric bool ARM::getHWDivFeatures(uint64_t HWDivKind, 290bdd1243dSDimitry Andric std::vector<StringRef> &Features) { 291bdd1243dSDimitry Andric 292bdd1243dSDimitry Andric if (HWDivKind == AEK_INVALID) 293bdd1243dSDimitry Andric return false; 294bdd1243dSDimitry Andric 295bdd1243dSDimitry Andric if (HWDivKind & AEK_HWDIVARM) 296bdd1243dSDimitry Andric Features.push_back("+hwdiv-arm"); 297bdd1243dSDimitry Andric else 298bdd1243dSDimitry Andric Features.push_back("-hwdiv-arm"); 299bdd1243dSDimitry Andric 300bdd1243dSDimitry Andric if (HWDivKind & AEK_HWDIVTHUMB) 301bdd1243dSDimitry Andric Features.push_back("+hwdiv"); 302bdd1243dSDimitry Andric else 303bdd1243dSDimitry Andric Features.push_back("-hwdiv"); 304bdd1243dSDimitry Andric 305bdd1243dSDimitry Andric return true; 306bdd1243dSDimitry Andric } 307bdd1243dSDimitry Andric 308bdd1243dSDimitry Andric bool ARM::getExtensionFeatures(uint64_t Extensions, 309bdd1243dSDimitry Andric std::vector<StringRef> &Features) { 310bdd1243dSDimitry Andric 311bdd1243dSDimitry Andric if (Extensions == AEK_INVALID) 312bdd1243dSDimitry Andric return false; 313bdd1243dSDimitry Andric 314bdd1243dSDimitry Andric for (const auto &AE : ARCHExtNames) { 315bdd1243dSDimitry Andric if ((Extensions & AE.ID) == AE.ID && !AE.Feature.empty()) 316bdd1243dSDimitry Andric Features.push_back(AE.Feature); 317bdd1243dSDimitry Andric else if (!AE.NegFeature.empty()) 318bdd1243dSDimitry Andric Features.push_back(AE.NegFeature); 319bdd1243dSDimitry Andric } 320bdd1243dSDimitry Andric 321bdd1243dSDimitry Andric return getHWDivFeatures(Extensions, Features); 322bdd1243dSDimitry Andric } 323bdd1243dSDimitry Andric 324bdd1243dSDimitry Andric StringRef ARM::getArchName(ARM::ArchKind AK) { 325bdd1243dSDimitry Andric return ARMArchNames[static_cast<unsigned>(AK)].Name; 326bdd1243dSDimitry Andric } 327bdd1243dSDimitry Andric 328bdd1243dSDimitry Andric StringRef ARM::getCPUAttr(ARM::ArchKind AK) { 329bdd1243dSDimitry Andric return ARMArchNames[static_cast<unsigned>(AK)].CPUAttr; 330bdd1243dSDimitry Andric } 331bdd1243dSDimitry Andric 332bdd1243dSDimitry Andric StringRef ARM::getSubArch(ARM::ArchKind AK) { 333bdd1243dSDimitry Andric return ARMArchNames[static_cast<unsigned>(AK)].getSubArch(); 334bdd1243dSDimitry Andric } 335bdd1243dSDimitry Andric 336bdd1243dSDimitry Andric unsigned ARM::getArchAttr(ARM::ArchKind AK) { 337bdd1243dSDimitry Andric return ARMArchNames[static_cast<unsigned>(AK)].ArchAttr; 338bdd1243dSDimitry Andric } 339bdd1243dSDimitry Andric 340bdd1243dSDimitry Andric StringRef ARM::getArchExtName(uint64_t ArchExtKind) { 341bdd1243dSDimitry Andric for (const auto &AE : ARCHExtNames) { 342bdd1243dSDimitry Andric if (ArchExtKind == AE.ID) 343bdd1243dSDimitry Andric return AE.Name; 344bdd1243dSDimitry Andric } 345bdd1243dSDimitry Andric return StringRef(); 346bdd1243dSDimitry Andric } 347bdd1243dSDimitry Andric 348bdd1243dSDimitry Andric static bool stripNegationPrefix(StringRef &Name) { 349bdd1243dSDimitry Andric if (Name.startswith("no")) { 350bdd1243dSDimitry Andric Name = Name.substr(2); 351bdd1243dSDimitry Andric return true; 352bdd1243dSDimitry Andric } 353bdd1243dSDimitry Andric return false; 354bdd1243dSDimitry Andric } 355bdd1243dSDimitry Andric 356bdd1243dSDimitry Andric StringRef ARM::getArchExtFeature(StringRef ArchExt) { 357bdd1243dSDimitry Andric bool Negated = stripNegationPrefix(ArchExt); 358bdd1243dSDimitry Andric for (const auto &AE : ARCHExtNames) { 359bdd1243dSDimitry Andric if (!AE.Feature.empty() && ArchExt == AE.Name) 360bdd1243dSDimitry Andric return StringRef(Negated ? AE.NegFeature : AE.Feature); 361bdd1243dSDimitry Andric } 362bdd1243dSDimitry Andric 363bdd1243dSDimitry Andric return StringRef(); 364bdd1243dSDimitry Andric } 365bdd1243dSDimitry Andric 366*06c3fb27SDimitry Andric static ARM::FPUKind findDoublePrecisionFPU(ARM::FPUKind InputFPUKind) { 367bdd1243dSDimitry Andric const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind]; 368bdd1243dSDimitry Andric 369bdd1243dSDimitry Andric // If the input FPU already supports double-precision, then there 370bdd1243dSDimitry Andric // isn't any different FPU we can return here. 371bdd1243dSDimitry Andric // 372bdd1243dSDimitry Andric // The current available FPURestriction values are None (no 373bdd1243dSDimitry Andric // restriction), D16 (only 16 d-regs) and SP_D16 (16 d-regs 374bdd1243dSDimitry Andric // and single precision only); there's no value representing 375bdd1243dSDimitry Andric // SP restriction without D16. So this test just means 'is it 376bdd1243dSDimitry Andric // SP only?'. 377bdd1243dSDimitry Andric if (InputFPU.Restriction != ARM::FPURestriction::SP_D16) 378bdd1243dSDimitry Andric return ARM::FK_INVALID; 379bdd1243dSDimitry Andric 380bdd1243dSDimitry Andric // Otherwise, look for an FPU entry with all the same fields, except 381bdd1243dSDimitry Andric // that SP_D16 has been replaced with just D16, representing adding 382bdd1243dSDimitry Andric // double precision and not changing anything else. 383bdd1243dSDimitry Andric for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) { 384bdd1243dSDimitry Andric if (CandidateFPU.FPUVer == InputFPU.FPUVer && 385bdd1243dSDimitry Andric CandidateFPU.NeonSupport == InputFPU.NeonSupport && 386bdd1243dSDimitry Andric CandidateFPU.Restriction == ARM::FPURestriction::D16) { 387bdd1243dSDimitry Andric return CandidateFPU.ID; 388bdd1243dSDimitry Andric } 389bdd1243dSDimitry Andric } 390bdd1243dSDimitry Andric 391bdd1243dSDimitry Andric // nothing found 392bdd1243dSDimitry Andric return ARM::FK_INVALID; 393bdd1243dSDimitry Andric } 394bdd1243dSDimitry Andric 395bdd1243dSDimitry Andric bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, 396bdd1243dSDimitry Andric StringRef ArchExt, 397bdd1243dSDimitry Andric std::vector<StringRef> &Features, 398*06c3fb27SDimitry Andric ARM::FPUKind &ArgFPUKind) { 399bdd1243dSDimitry Andric 400bdd1243dSDimitry Andric size_t StartingNumFeatures = Features.size(); 401bdd1243dSDimitry Andric const bool Negated = stripNegationPrefix(ArchExt); 402bdd1243dSDimitry Andric uint64_t ID = parseArchExt(ArchExt); 403bdd1243dSDimitry Andric 404bdd1243dSDimitry Andric if (ID == AEK_INVALID) 405bdd1243dSDimitry Andric return false; 406bdd1243dSDimitry Andric 407bdd1243dSDimitry Andric for (const auto &AE : ARCHExtNames) { 408bdd1243dSDimitry Andric if (Negated) { 409bdd1243dSDimitry Andric if ((AE.ID & ID) == ID && !AE.NegFeature.empty()) 410bdd1243dSDimitry Andric Features.push_back(AE.NegFeature); 411bdd1243dSDimitry Andric } else { 412bdd1243dSDimitry Andric if ((AE.ID & ID) == AE.ID && !AE.Feature.empty()) 413bdd1243dSDimitry Andric Features.push_back(AE.Feature); 414bdd1243dSDimitry Andric } 415bdd1243dSDimitry Andric } 416bdd1243dSDimitry Andric 417bdd1243dSDimitry Andric if (CPU == "") 418bdd1243dSDimitry Andric CPU = "generic"; 419bdd1243dSDimitry Andric 420bdd1243dSDimitry Andric if (ArchExt == "fp" || ArchExt == "fp.dp") { 421*06c3fb27SDimitry Andric ARM::FPUKind FPUKind; 422bdd1243dSDimitry Andric if (ArchExt == "fp.dp") { 423bdd1243dSDimitry Andric if (Negated) { 424bdd1243dSDimitry Andric Features.push_back("-fp64"); 425bdd1243dSDimitry Andric return true; 426bdd1243dSDimitry Andric } 427bdd1243dSDimitry Andric FPUKind = findDoublePrecisionFPU(getDefaultFPU(CPU, AK)); 428bdd1243dSDimitry Andric } else if (Negated) { 429bdd1243dSDimitry Andric FPUKind = ARM::FK_NONE; 430bdd1243dSDimitry Andric } else { 431bdd1243dSDimitry Andric FPUKind = getDefaultFPU(CPU, AK); 432bdd1243dSDimitry Andric } 433*06c3fb27SDimitry Andric ArgFPUKind = FPUKind; 434bdd1243dSDimitry Andric return ARM::getFPUFeatures(FPUKind, Features); 435bdd1243dSDimitry Andric } 436bdd1243dSDimitry Andric return StartingNumFeatures != Features.size(); 437bdd1243dSDimitry Andric } 438bdd1243dSDimitry Andric 439bdd1243dSDimitry Andric ARM::ArchKind ARM::convertV9toV8(ARM::ArchKind AK) { 440bdd1243dSDimitry Andric if (getProfileKind(AK) != ProfileKind::A) 441bdd1243dSDimitry Andric return ARM::ArchKind::INVALID; 442bdd1243dSDimitry Andric if (AK < ARM::ArchKind::ARMV9A || AK > ARM::ArchKind::ARMV9_3A) 443bdd1243dSDimitry Andric return ARM::ArchKind::INVALID; 444bdd1243dSDimitry Andric unsigned AK_v8 = static_cast<unsigned>(ARM::ArchKind::ARMV8_5A); 445bdd1243dSDimitry Andric AK_v8 += static_cast<unsigned>(AK) - 446bdd1243dSDimitry Andric static_cast<unsigned>(ARM::ArchKind::ARMV9A); 447bdd1243dSDimitry Andric return static_cast<ARM::ArchKind>(AK_v8); 448bdd1243dSDimitry Andric } 449bdd1243dSDimitry Andric 450bdd1243dSDimitry Andric StringRef ARM::getDefaultCPU(StringRef Arch) { 451bdd1243dSDimitry Andric ArchKind AK = parseArch(Arch); 452bdd1243dSDimitry Andric if (AK == ArchKind::INVALID) 453bdd1243dSDimitry Andric return StringRef(); 454bdd1243dSDimitry Andric 455bdd1243dSDimitry Andric // Look for multiple AKs to find the default for pair AK+Name. 456bdd1243dSDimitry Andric for (const auto &CPU : CPUNames) { 457bdd1243dSDimitry Andric if (CPU.ArchID == AK && CPU.Default) 458bdd1243dSDimitry Andric return CPU.Name; 459bdd1243dSDimitry Andric } 460bdd1243dSDimitry Andric 461bdd1243dSDimitry Andric // If we can't find a default then target the architecture instead 462bdd1243dSDimitry Andric return "generic"; 463bdd1243dSDimitry Andric } 464bdd1243dSDimitry Andric 465bdd1243dSDimitry Andric uint64_t ARM::parseHWDiv(StringRef HWDiv) { 466bdd1243dSDimitry Andric StringRef Syn = getHWDivSynonym(HWDiv); 467bdd1243dSDimitry Andric for (const auto &D : HWDivNames) { 468bdd1243dSDimitry Andric if (Syn == D.Name) 469bdd1243dSDimitry Andric return D.ID; 470bdd1243dSDimitry Andric } 471bdd1243dSDimitry Andric return AEK_INVALID; 472bdd1243dSDimitry Andric } 473bdd1243dSDimitry Andric 474bdd1243dSDimitry Andric uint64_t ARM::parseArchExt(StringRef ArchExt) { 475bdd1243dSDimitry Andric for (const auto &A : ARCHExtNames) { 476bdd1243dSDimitry Andric if (ArchExt == A.Name) 477bdd1243dSDimitry Andric return A.ID; 478bdd1243dSDimitry Andric } 479bdd1243dSDimitry Andric return AEK_INVALID; 480bdd1243dSDimitry Andric } 481bdd1243dSDimitry Andric 482bdd1243dSDimitry Andric ARM::ArchKind ARM::parseCPUArch(StringRef CPU) { 483bdd1243dSDimitry Andric for (const auto &C : CPUNames) { 484bdd1243dSDimitry Andric if (CPU == C.Name) 485bdd1243dSDimitry Andric return C.ArchID; 486bdd1243dSDimitry Andric } 487bdd1243dSDimitry Andric return ArchKind::INVALID; 488bdd1243dSDimitry Andric } 489bdd1243dSDimitry Andric 490bdd1243dSDimitry Andric void ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) { 491bdd1243dSDimitry Andric for (const auto &Arch : CPUNames) { 492bdd1243dSDimitry Andric if (Arch.ArchID != ArchKind::INVALID) 493bdd1243dSDimitry Andric Values.push_back(Arch.Name); 494bdd1243dSDimitry Andric } 495bdd1243dSDimitry Andric } 496bdd1243dSDimitry Andric 497bdd1243dSDimitry Andric StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) { 498bdd1243dSDimitry Andric StringRef ArchName = 499bdd1243dSDimitry Andric CPU.empty() ? TT.getArchName() : getArchName(parseCPUArch(CPU)); 500bdd1243dSDimitry Andric 501bdd1243dSDimitry Andric if (TT.isOSBinFormatMachO()) { 502bdd1243dSDimitry Andric if (TT.getEnvironment() == Triple::EABI || 503bdd1243dSDimitry Andric TT.getOS() == Triple::UnknownOS || 504bdd1243dSDimitry Andric parseArchProfile(ArchName) == ProfileKind::M) 505bdd1243dSDimitry Andric return "aapcs"; 506bdd1243dSDimitry Andric if (TT.isWatchABI()) 507bdd1243dSDimitry Andric return "aapcs16"; 508bdd1243dSDimitry Andric return "apcs-gnu"; 509bdd1243dSDimitry Andric } else if (TT.isOSWindows()) 510bdd1243dSDimitry Andric // FIXME: this is invalid for WindowsCE. 511bdd1243dSDimitry Andric return "aapcs"; 512bdd1243dSDimitry Andric 513bdd1243dSDimitry Andric // Select the default based on the platform. 514bdd1243dSDimitry Andric switch (TT.getEnvironment()) { 515bdd1243dSDimitry Andric case Triple::Android: 516bdd1243dSDimitry Andric case Triple::GNUEABI: 517bdd1243dSDimitry Andric case Triple::GNUEABIHF: 518bdd1243dSDimitry Andric case Triple::MuslEABI: 519bdd1243dSDimitry Andric case Triple::MuslEABIHF: 520bdd1243dSDimitry Andric return "aapcs-linux"; 521bdd1243dSDimitry Andric case Triple::EABIHF: 522bdd1243dSDimitry Andric case Triple::EABI: 523bdd1243dSDimitry Andric return "aapcs"; 524bdd1243dSDimitry Andric default: 525bdd1243dSDimitry Andric if (TT.isOSNetBSD()) 526bdd1243dSDimitry Andric return "apcs-gnu"; 527*06c3fb27SDimitry Andric if (TT.isOSFreeBSD() || TT.isOSOpenBSD() || TT.isOHOSFamily()) 528bdd1243dSDimitry Andric return "aapcs-linux"; 529bdd1243dSDimitry Andric return "aapcs"; 530bdd1243dSDimitry Andric } 531bdd1243dSDimitry Andric } 532bdd1243dSDimitry Andric 533bdd1243dSDimitry Andric StringRef ARM::getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch) { 534bdd1243dSDimitry Andric if (MArch.empty()) 535bdd1243dSDimitry Andric MArch = Triple.getArchName(); 536bdd1243dSDimitry Andric MArch = llvm::ARM::getCanonicalArchName(MArch); 537bdd1243dSDimitry Andric 538bdd1243dSDimitry Andric // Some defaults are forced. 539bdd1243dSDimitry Andric switch (Triple.getOS()) { 540bdd1243dSDimitry Andric case llvm::Triple::FreeBSD: 541bdd1243dSDimitry Andric case llvm::Triple::NetBSD: 542bdd1243dSDimitry Andric case llvm::Triple::OpenBSD: 543bdd1243dSDimitry Andric if (!MArch.empty() && MArch == "v6") 544bdd1243dSDimitry Andric return "arm1176jzf-s"; 545bdd1243dSDimitry Andric if (!MArch.empty() && MArch == "v7") 546bdd1243dSDimitry Andric return "cortex-a8"; 547bdd1243dSDimitry Andric break; 548bdd1243dSDimitry Andric case llvm::Triple::Win32: 549bdd1243dSDimitry Andric // FIXME: this is invalid for WindowsCE 550bdd1243dSDimitry Andric if (llvm::ARM::parseArchVersion(MArch) <= 7) 551bdd1243dSDimitry Andric return "cortex-a9"; 552bdd1243dSDimitry Andric break; 553bdd1243dSDimitry Andric case llvm::Triple::IOS: 554bdd1243dSDimitry Andric case llvm::Triple::MacOSX: 555bdd1243dSDimitry Andric case llvm::Triple::TvOS: 556bdd1243dSDimitry Andric case llvm::Triple::WatchOS: 557bdd1243dSDimitry Andric case llvm::Triple::DriverKit: 558bdd1243dSDimitry Andric if (MArch == "v7k") 559bdd1243dSDimitry Andric return "cortex-a7"; 560bdd1243dSDimitry Andric break; 561bdd1243dSDimitry Andric default: 562bdd1243dSDimitry Andric break; 563bdd1243dSDimitry Andric } 564bdd1243dSDimitry Andric 565bdd1243dSDimitry Andric if (MArch.empty()) 566bdd1243dSDimitry Andric return StringRef(); 567bdd1243dSDimitry Andric 568bdd1243dSDimitry Andric StringRef CPU = llvm::ARM::getDefaultCPU(MArch); 569bdd1243dSDimitry Andric if (!CPU.empty() && !CPU.equals("invalid")) 570bdd1243dSDimitry Andric return CPU; 571bdd1243dSDimitry Andric 572bdd1243dSDimitry Andric // If no specific architecture version is requested, return the minimum CPU 573bdd1243dSDimitry Andric // required by the OS and environment. 574bdd1243dSDimitry Andric switch (Triple.getOS()) { 575bdd1243dSDimitry Andric case llvm::Triple::NetBSD: 576bdd1243dSDimitry Andric switch (Triple.getEnvironment()) { 577bdd1243dSDimitry Andric case llvm::Triple::EABI: 578bdd1243dSDimitry Andric case llvm::Triple::EABIHF: 579bdd1243dSDimitry Andric case llvm::Triple::GNUEABI: 580bdd1243dSDimitry Andric case llvm::Triple::GNUEABIHF: 581bdd1243dSDimitry Andric return "arm926ej-s"; 582bdd1243dSDimitry Andric default: 583bdd1243dSDimitry Andric return "strongarm"; 584bdd1243dSDimitry Andric } 585bdd1243dSDimitry Andric case llvm::Triple::NaCl: 586bdd1243dSDimitry Andric case llvm::Triple::OpenBSD: 587bdd1243dSDimitry Andric return "cortex-a8"; 588bdd1243dSDimitry Andric default: 589bdd1243dSDimitry Andric switch (Triple.getEnvironment()) { 590bdd1243dSDimitry Andric case llvm::Triple::EABIHF: 591bdd1243dSDimitry Andric case llvm::Triple::GNUEABIHF: 592bdd1243dSDimitry Andric case llvm::Triple::MuslEABIHF: 593bdd1243dSDimitry Andric return "arm1176jzf-s"; 594bdd1243dSDimitry Andric default: 595bdd1243dSDimitry Andric return "arm7tdmi"; 596bdd1243dSDimitry Andric } 597bdd1243dSDimitry Andric } 598bdd1243dSDimitry Andric 599bdd1243dSDimitry Andric llvm_unreachable("invalid arch name"); 600bdd1243dSDimitry Andric } 601