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" 165f757f3fSDimitry Andric #include "llvm/Support/Format.h" 175f757f3fSDimitry Andric #include "llvm/Support/raw_ostream.h" 18bdd1243dSDimitry Andric #include "llvm/TargetParser/ARMTargetParserCommon.h" 19bdd1243dSDimitry Andric #include "llvm/TargetParser/Triple.h" 20bdd1243dSDimitry Andric #include <cctype> 21bdd1243dSDimitry Andric 22bdd1243dSDimitry Andric using namespace llvm; 23bdd1243dSDimitry Andric 24bdd1243dSDimitry Andric static StringRef getHWDivSynonym(StringRef HWDiv) { 25bdd1243dSDimitry Andric return StringSwitch<StringRef>(HWDiv) 26bdd1243dSDimitry Andric .Case("thumb,arm", "arm,thumb") 27bdd1243dSDimitry Andric .Default(HWDiv); 28bdd1243dSDimitry Andric } 29bdd1243dSDimitry Andric 30bdd1243dSDimitry Andric // Allows partial match, ex. "v7a" matches "armv7a". 31bdd1243dSDimitry Andric ARM::ArchKind ARM::parseArch(StringRef Arch) { 32bdd1243dSDimitry Andric Arch = getCanonicalArchName(Arch); 33bdd1243dSDimitry Andric StringRef Syn = getArchSynonym(Arch); 34bdd1243dSDimitry Andric for (const auto &A : ARMArchNames) { 355f757f3fSDimitry Andric if (A.Name.ends_with(Syn)) 36bdd1243dSDimitry Andric return A.ID; 37bdd1243dSDimitry Andric } 38bdd1243dSDimitry Andric return ArchKind::INVALID; 39bdd1243dSDimitry Andric } 40bdd1243dSDimitry Andric 41bdd1243dSDimitry Andric // Version number (ex. v7 = 7). 42bdd1243dSDimitry Andric unsigned ARM::parseArchVersion(StringRef Arch) { 43bdd1243dSDimitry Andric Arch = getCanonicalArchName(Arch); 44bdd1243dSDimitry Andric switch (parseArch(Arch)) { 45bdd1243dSDimitry Andric case ArchKind::ARMV4: 46bdd1243dSDimitry Andric case ArchKind::ARMV4T: 47bdd1243dSDimitry Andric return 4; 48bdd1243dSDimitry Andric case ArchKind::ARMV5T: 49bdd1243dSDimitry Andric case ArchKind::ARMV5TE: 50bdd1243dSDimitry Andric case ArchKind::IWMMXT: 51bdd1243dSDimitry Andric case ArchKind::IWMMXT2: 52bdd1243dSDimitry Andric case ArchKind::XSCALE: 53bdd1243dSDimitry Andric case ArchKind::ARMV5TEJ: 54bdd1243dSDimitry Andric return 5; 55bdd1243dSDimitry Andric case ArchKind::ARMV6: 56bdd1243dSDimitry Andric case ArchKind::ARMV6K: 57bdd1243dSDimitry Andric case ArchKind::ARMV6T2: 58bdd1243dSDimitry Andric case ArchKind::ARMV6KZ: 59bdd1243dSDimitry Andric case ArchKind::ARMV6M: 60bdd1243dSDimitry Andric return 6; 61bdd1243dSDimitry Andric case ArchKind::ARMV7A: 62bdd1243dSDimitry Andric case ArchKind::ARMV7VE: 63bdd1243dSDimitry Andric case ArchKind::ARMV7R: 64bdd1243dSDimitry Andric case ArchKind::ARMV7M: 65bdd1243dSDimitry Andric case ArchKind::ARMV7S: 66bdd1243dSDimitry Andric case ArchKind::ARMV7EM: 67bdd1243dSDimitry Andric case ArchKind::ARMV7K: 68bdd1243dSDimitry Andric return 7; 69bdd1243dSDimitry Andric case ArchKind::ARMV8A: 70bdd1243dSDimitry Andric case ArchKind::ARMV8_1A: 71bdd1243dSDimitry Andric case ArchKind::ARMV8_2A: 72bdd1243dSDimitry Andric case ArchKind::ARMV8_3A: 73bdd1243dSDimitry Andric case ArchKind::ARMV8_4A: 74bdd1243dSDimitry Andric case ArchKind::ARMV8_5A: 75bdd1243dSDimitry Andric case ArchKind::ARMV8_6A: 76bdd1243dSDimitry Andric case ArchKind::ARMV8_7A: 77bdd1243dSDimitry Andric case ArchKind::ARMV8_8A: 78bdd1243dSDimitry Andric case ArchKind::ARMV8_9A: 79bdd1243dSDimitry Andric case ArchKind::ARMV8R: 80bdd1243dSDimitry Andric case ArchKind::ARMV8MBaseline: 81bdd1243dSDimitry Andric case ArchKind::ARMV8MMainline: 82bdd1243dSDimitry Andric case ArchKind::ARMV8_1MMainline: 83bdd1243dSDimitry Andric return 8; 84bdd1243dSDimitry Andric case ArchKind::ARMV9A: 85bdd1243dSDimitry Andric case ArchKind::ARMV9_1A: 86bdd1243dSDimitry Andric case ArchKind::ARMV9_2A: 87bdd1243dSDimitry Andric case ArchKind::ARMV9_3A: 88bdd1243dSDimitry Andric case ArchKind::ARMV9_4A: 897a6dacacSDimitry Andric case ArchKind::ARMV9_5A: 90bdd1243dSDimitry Andric return 9; 91bdd1243dSDimitry Andric case ArchKind::INVALID: 92bdd1243dSDimitry Andric return 0; 93bdd1243dSDimitry Andric } 94bdd1243dSDimitry Andric llvm_unreachable("Unhandled architecture"); 95bdd1243dSDimitry Andric } 96bdd1243dSDimitry Andric 97bdd1243dSDimitry Andric static ARM::ProfileKind getProfileKind(ARM::ArchKind AK) { 98bdd1243dSDimitry Andric switch (AK) { 99bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6M: 100bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7M: 101bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7EM: 102bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8MMainline: 103bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8MBaseline: 104bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_1MMainline: 105bdd1243dSDimitry Andric return ARM::ProfileKind::M; 106bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7R: 107bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8R: 108bdd1243dSDimitry Andric return ARM::ProfileKind::R; 109bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7A: 110bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7VE: 111bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7K: 112bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8A: 113bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_1A: 114bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_2A: 115bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_3A: 116bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_4A: 117bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_5A: 118bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_6A: 119bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_7A: 120bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_8A: 121bdd1243dSDimitry Andric case ARM::ArchKind::ARMV8_9A: 122bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9A: 123bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9_1A: 124bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9_2A: 125bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9_3A: 126bdd1243dSDimitry Andric case ARM::ArchKind::ARMV9_4A: 1277a6dacacSDimitry Andric case ARM::ArchKind::ARMV9_5A: 128bdd1243dSDimitry Andric return ARM::ProfileKind::A; 129bdd1243dSDimitry Andric case ARM::ArchKind::ARMV4: 130bdd1243dSDimitry Andric case ARM::ArchKind::ARMV4T: 131bdd1243dSDimitry Andric case ARM::ArchKind::ARMV5T: 132bdd1243dSDimitry Andric case ARM::ArchKind::ARMV5TE: 133bdd1243dSDimitry Andric case ARM::ArchKind::ARMV5TEJ: 134bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6: 135bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6K: 136bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6T2: 137bdd1243dSDimitry Andric case ARM::ArchKind::ARMV6KZ: 138bdd1243dSDimitry Andric case ARM::ArchKind::ARMV7S: 139bdd1243dSDimitry Andric case ARM::ArchKind::IWMMXT: 140bdd1243dSDimitry Andric case ARM::ArchKind::IWMMXT2: 141bdd1243dSDimitry Andric case ARM::ArchKind::XSCALE: 142bdd1243dSDimitry Andric case ARM::ArchKind::INVALID: 143bdd1243dSDimitry Andric return ARM::ProfileKind::INVALID; 144bdd1243dSDimitry Andric } 145bdd1243dSDimitry Andric llvm_unreachable("Unhandled architecture"); 146bdd1243dSDimitry Andric } 147bdd1243dSDimitry Andric 148bdd1243dSDimitry Andric // Profile A/R/M 149bdd1243dSDimitry Andric ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) { 150bdd1243dSDimitry Andric Arch = getCanonicalArchName(Arch); 151bdd1243dSDimitry Andric return getProfileKind(parseArch(Arch)); 152bdd1243dSDimitry Andric } 153bdd1243dSDimitry Andric 15406c3fb27SDimitry Andric bool ARM::getFPUFeatures(ARM::FPUKind FPUKind, 15506c3fb27SDimitry Andric std::vector<StringRef> &Features) { 156bdd1243dSDimitry Andric 157bdd1243dSDimitry Andric if (FPUKind >= FK_LAST || FPUKind == FK_INVALID) 158bdd1243dSDimitry Andric return false; 159bdd1243dSDimitry Andric 160bdd1243dSDimitry Andric static const struct FPUFeatureNameInfo { 161bdd1243dSDimitry Andric const char *PlusName, *MinusName; 162bdd1243dSDimitry Andric FPUVersion MinVersion; 163bdd1243dSDimitry Andric FPURestriction MaxRestriction; 164bdd1243dSDimitry Andric } FPUFeatureInfoList[] = { 165bdd1243dSDimitry Andric // We have to specify the + and - versions of the name in full so 166bdd1243dSDimitry Andric // that we can return them as static StringRefs. 167bdd1243dSDimitry Andric // 168bdd1243dSDimitry Andric // Also, the SubtargetFeatures ending in just "sp" are listed here 169bdd1243dSDimitry Andric // under FPURestriction::None, which is the only FPURestriction in 170bdd1243dSDimitry Andric // which they would be valid (since FPURestriction::SP doesn't 171bdd1243dSDimitry Andric // exist). 172bdd1243dSDimitry Andric {"+vfp2", "-vfp2", FPUVersion::VFPV2, FPURestriction::D16}, 173bdd1243dSDimitry Andric {"+vfp2sp", "-vfp2sp", FPUVersion::VFPV2, FPURestriction::SP_D16}, 174bdd1243dSDimitry Andric {"+vfp3", "-vfp3", FPUVersion::VFPV3, FPURestriction::None}, 175bdd1243dSDimitry Andric {"+vfp3d16", "-vfp3d16", FPUVersion::VFPV3, FPURestriction::D16}, 176bdd1243dSDimitry Andric {"+vfp3d16sp", "-vfp3d16sp", FPUVersion::VFPV3, FPURestriction::SP_D16}, 177bdd1243dSDimitry Andric {"+vfp3sp", "-vfp3sp", FPUVersion::VFPV3, FPURestriction::None}, 178bdd1243dSDimitry Andric {"+fp16", "-fp16", FPUVersion::VFPV3_FP16, FPURestriction::SP_D16}, 179bdd1243dSDimitry Andric {"+vfp4", "-vfp4", FPUVersion::VFPV4, FPURestriction::None}, 180bdd1243dSDimitry Andric {"+vfp4d16", "-vfp4d16", FPUVersion::VFPV4, FPURestriction::D16}, 181bdd1243dSDimitry Andric {"+vfp4d16sp", "-vfp4d16sp", FPUVersion::VFPV4, FPURestriction::SP_D16}, 182bdd1243dSDimitry Andric {"+vfp4sp", "-vfp4sp", FPUVersion::VFPV4, FPURestriction::None}, 183bdd1243dSDimitry Andric {"+fp-armv8", "-fp-armv8", FPUVersion::VFPV5, FPURestriction::None}, 184bdd1243dSDimitry Andric {"+fp-armv8d16", "-fp-armv8d16", FPUVersion::VFPV5, FPURestriction::D16}, 185bdd1243dSDimitry Andric {"+fp-armv8d16sp", "-fp-armv8d16sp", FPUVersion::VFPV5, FPURestriction::SP_D16}, 186bdd1243dSDimitry Andric {"+fp-armv8sp", "-fp-armv8sp", FPUVersion::VFPV5, FPURestriction::None}, 187bdd1243dSDimitry Andric {"+fullfp16", "-fullfp16", FPUVersion::VFPV5_FULLFP16, FPURestriction::SP_D16}, 188bdd1243dSDimitry Andric {"+fp64", "-fp64", FPUVersion::VFPV2, FPURestriction::D16}, 189bdd1243dSDimitry Andric {"+d32", "-d32", FPUVersion::VFPV3, FPURestriction::None}, 190bdd1243dSDimitry Andric }; 191bdd1243dSDimitry Andric 192bdd1243dSDimitry Andric for (const auto &Info: FPUFeatureInfoList) { 193bdd1243dSDimitry Andric if (FPUNames[FPUKind].FPUVer >= Info.MinVersion && 194bdd1243dSDimitry Andric FPUNames[FPUKind].Restriction <= Info.MaxRestriction) 195bdd1243dSDimitry Andric Features.push_back(Info.PlusName); 196bdd1243dSDimitry Andric else 197bdd1243dSDimitry Andric Features.push_back(Info.MinusName); 198bdd1243dSDimitry Andric } 199bdd1243dSDimitry Andric 200bdd1243dSDimitry Andric static const struct NeonFeatureNameInfo { 201bdd1243dSDimitry Andric const char *PlusName, *MinusName; 202bdd1243dSDimitry Andric NeonSupportLevel MinSupportLevel; 203bdd1243dSDimitry Andric } NeonFeatureInfoList[] = { 204bdd1243dSDimitry Andric {"+neon", "-neon", NeonSupportLevel::Neon}, 205bdd1243dSDimitry Andric {"+sha2", "-sha2", NeonSupportLevel::Crypto}, 206bdd1243dSDimitry Andric {"+aes", "-aes", NeonSupportLevel::Crypto}, 207bdd1243dSDimitry Andric }; 208bdd1243dSDimitry Andric 209bdd1243dSDimitry Andric for (const auto &Info: NeonFeatureInfoList) { 210bdd1243dSDimitry Andric if (FPUNames[FPUKind].NeonSupport >= Info.MinSupportLevel) 211bdd1243dSDimitry Andric Features.push_back(Info.PlusName); 212bdd1243dSDimitry Andric else 213bdd1243dSDimitry Andric Features.push_back(Info.MinusName); 214bdd1243dSDimitry Andric } 215bdd1243dSDimitry Andric 216bdd1243dSDimitry Andric return true; 217bdd1243dSDimitry Andric } 218bdd1243dSDimitry Andric 21906c3fb27SDimitry Andric ARM::FPUKind ARM::parseFPU(StringRef FPU) { 220bdd1243dSDimitry Andric StringRef Syn = getFPUSynonym(FPU); 221bdd1243dSDimitry Andric for (const auto &F : FPUNames) { 222bdd1243dSDimitry Andric if (Syn == F.Name) 223bdd1243dSDimitry Andric return F.ID; 224bdd1243dSDimitry Andric } 225bdd1243dSDimitry Andric return FK_INVALID; 226bdd1243dSDimitry Andric } 227bdd1243dSDimitry Andric 22806c3fb27SDimitry Andric ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(ARM::FPUKind FPUKind) { 229bdd1243dSDimitry Andric if (FPUKind >= FK_LAST) 230bdd1243dSDimitry Andric return NeonSupportLevel::None; 231bdd1243dSDimitry Andric return FPUNames[FPUKind].NeonSupport; 232bdd1243dSDimitry Andric } 233bdd1243dSDimitry Andric 234bdd1243dSDimitry Andric StringRef ARM::getFPUSynonym(StringRef FPU) { 235bdd1243dSDimitry Andric return StringSwitch<StringRef>(FPU) 236bdd1243dSDimitry Andric .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 237bdd1243dSDimitry Andric .Case("vfp2", "vfpv2") 238bdd1243dSDimitry Andric .Case("vfp3", "vfpv3") 239bdd1243dSDimitry Andric .Case("vfp4", "vfpv4") 240bdd1243dSDimitry Andric .Case("vfp3-d16", "vfpv3-d16") 241bdd1243dSDimitry Andric .Case("vfp4-d16", "vfpv4-d16") 242bdd1243dSDimitry Andric .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 243bdd1243dSDimitry Andric .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 244bdd1243dSDimitry Andric .Case("fp5-sp-d16", "fpv5-sp-d16") 245bdd1243dSDimitry Andric .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 246bdd1243dSDimitry Andric // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 247bdd1243dSDimitry Andric .Case("neon-vfpv3", "neon") 248bdd1243dSDimitry Andric .Default(FPU); 249bdd1243dSDimitry Andric } 250bdd1243dSDimitry Andric 25106c3fb27SDimitry Andric StringRef ARM::getFPUName(ARM::FPUKind FPUKind) { 252bdd1243dSDimitry Andric if (FPUKind >= FK_LAST) 253bdd1243dSDimitry Andric return StringRef(); 254bdd1243dSDimitry Andric return FPUNames[FPUKind].Name; 255bdd1243dSDimitry Andric } 256bdd1243dSDimitry Andric 25706c3fb27SDimitry Andric ARM::FPUVersion ARM::getFPUVersion(ARM::FPUKind FPUKind) { 258bdd1243dSDimitry Andric if (FPUKind >= FK_LAST) 259bdd1243dSDimitry Andric return FPUVersion::NONE; 260bdd1243dSDimitry Andric return FPUNames[FPUKind].FPUVer; 261bdd1243dSDimitry Andric } 262bdd1243dSDimitry Andric 26306c3fb27SDimitry Andric ARM::FPURestriction ARM::getFPURestriction(ARM::FPUKind FPUKind) { 264bdd1243dSDimitry Andric if (FPUKind >= FK_LAST) 265bdd1243dSDimitry Andric return FPURestriction::None; 266bdd1243dSDimitry Andric return FPUNames[FPUKind].Restriction; 267bdd1243dSDimitry Andric } 268bdd1243dSDimitry Andric 26906c3fb27SDimitry Andric ARM::FPUKind ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) { 270bdd1243dSDimitry Andric if (CPU == "generic") 271bdd1243dSDimitry Andric return ARM::ARMArchNames[static_cast<unsigned>(AK)].DefaultFPU; 272bdd1243dSDimitry Andric 27306c3fb27SDimitry Andric return StringSwitch<ARM::FPUKind>(CPU) 274bdd1243dSDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 275bdd1243dSDimitry Andric .Case(NAME, DEFAULT_FPU) 276bdd1243dSDimitry Andric #include "llvm/TargetParser/ARMTargetParser.def" 277bdd1243dSDimitry Andric .Default(ARM::FK_INVALID); 278bdd1243dSDimitry Andric } 279bdd1243dSDimitry Andric 280bdd1243dSDimitry Andric uint64_t ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) { 281bdd1243dSDimitry Andric if (CPU == "generic") 282bdd1243dSDimitry Andric return ARM::ARMArchNames[static_cast<unsigned>(AK)].ArchBaseExtensions; 283bdd1243dSDimitry Andric 284bdd1243dSDimitry Andric return StringSwitch<uint64_t>(CPU) 285bdd1243dSDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 286bdd1243dSDimitry Andric .Case(NAME, \ 287bdd1243dSDimitry Andric ARMArchNames[static_cast<unsigned>(ArchKind::ID)].ArchBaseExtensions | \ 288bdd1243dSDimitry Andric DEFAULT_EXT) 289bdd1243dSDimitry Andric #include "llvm/TargetParser/ARMTargetParser.def" 290bdd1243dSDimitry Andric .Default(ARM::AEK_INVALID); 291bdd1243dSDimitry Andric } 292bdd1243dSDimitry Andric 293bdd1243dSDimitry Andric bool ARM::getHWDivFeatures(uint64_t HWDivKind, 294bdd1243dSDimitry Andric std::vector<StringRef> &Features) { 295bdd1243dSDimitry Andric 296bdd1243dSDimitry Andric if (HWDivKind == AEK_INVALID) 297bdd1243dSDimitry Andric return false; 298bdd1243dSDimitry Andric 299bdd1243dSDimitry Andric if (HWDivKind & AEK_HWDIVARM) 300bdd1243dSDimitry Andric Features.push_back("+hwdiv-arm"); 301bdd1243dSDimitry Andric else 302bdd1243dSDimitry Andric Features.push_back("-hwdiv-arm"); 303bdd1243dSDimitry Andric 304bdd1243dSDimitry Andric if (HWDivKind & AEK_HWDIVTHUMB) 305bdd1243dSDimitry Andric Features.push_back("+hwdiv"); 306bdd1243dSDimitry Andric else 307bdd1243dSDimitry Andric Features.push_back("-hwdiv"); 308bdd1243dSDimitry Andric 309bdd1243dSDimitry Andric return true; 310bdd1243dSDimitry Andric } 311bdd1243dSDimitry Andric 312bdd1243dSDimitry Andric bool ARM::getExtensionFeatures(uint64_t Extensions, 313bdd1243dSDimitry Andric std::vector<StringRef> &Features) { 314bdd1243dSDimitry Andric 315bdd1243dSDimitry Andric if (Extensions == AEK_INVALID) 316bdd1243dSDimitry Andric return false; 317bdd1243dSDimitry Andric 318bdd1243dSDimitry Andric for (const auto &AE : ARCHExtNames) { 319bdd1243dSDimitry Andric if ((Extensions & AE.ID) == AE.ID && !AE.Feature.empty()) 320bdd1243dSDimitry Andric Features.push_back(AE.Feature); 321bdd1243dSDimitry Andric else if (!AE.NegFeature.empty()) 322bdd1243dSDimitry Andric Features.push_back(AE.NegFeature); 323bdd1243dSDimitry Andric } 324bdd1243dSDimitry Andric 325bdd1243dSDimitry Andric return getHWDivFeatures(Extensions, Features); 326bdd1243dSDimitry Andric } 327bdd1243dSDimitry Andric 328bdd1243dSDimitry Andric StringRef ARM::getArchName(ARM::ArchKind AK) { 329bdd1243dSDimitry Andric return ARMArchNames[static_cast<unsigned>(AK)].Name; 330bdd1243dSDimitry Andric } 331bdd1243dSDimitry Andric 332bdd1243dSDimitry Andric StringRef ARM::getCPUAttr(ARM::ArchKind AK) { 333bdd1243dSDimitry Andric return ARMArchNames[static_cast<unsigned>(AK)].CPUAttr; 334bdd1243dSDimitry Andric } 335bdd1243dSDimitry Andric 336bdd1243dSDimitry Andric StringRef ARM::getSubArch(ARM::ArchKind AK) { 337bdd1243dSDimitry Andric return ARMArchNames[static_cast<unsigned>(AK)].getSubArch(); 338bdd1243dSDimitry Andric } 339bdd1243dSDimitry Andric 340bdd1243dSDimitry Andric unsigned ARM::getArchAttr(ARM::ArchKind AK) { 341bdd1243dSDimitry Andric return ARMArchNames[static_cast<unsigned>(AK)].ArchAttr; 342bdd1243dSDimitry Andric } 343bdd1243dSDimitry Andric 344bdd1243dSDimitry Andric StringRef ARM::getArchExtName(uint64_t ArchExtKind) { 345bdd1243dSDimitry Andric for (const auto &AE : ARCHExtNames) { 346bdd1243dSDimitry Andric if (ArchExtKind == AE.ID) 347bdd1243dSDimitry Andric return AE.Name; 348bdd1243dSDimitry Andric } 349bdd1243dSDimitry Andric return StringRef(); 350bdd1243dSDimitry Andric } 351bdd1243dSDimitry Andric 352bdd1243dSDimitry Andric static bool stripNegationPrefix(StringRef &Name) { 353647cbc5dSDimitry Andric return Name.consume_front("no"); 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 36606c3fb27SDimitry Andric static ARM::FPUKind findDoublePrecisionFPU(ARM::FPUKind InputFPUKind) { 3675f757f3fSDimitry Andric if (InputFPUKind == ARM::FK_INVALID || InputFPUKind == ARM::FK_NONE) 3685f757f3fSDimitry Andric return ARM::FK_INVALID; 3695f757f3fSDimitry Andric 370bdd1243dSDimitry Andric const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind]; 371bdd1243dSDimitry Andric 372bdd1243dSDimitry Andric // If the input FPU already supports double-precision, then there 373bdd1243dSDimitry Andric // isn't any different FPU we can return here. 3745f757f3fSDimitry Andric if (ARM::isDoublePrecision(InputFPU.Restriction)) 3755f757f3fSDimitry Andric return InputFPUKind; 376bdd1243dSDimitry Andric 377bdd1243dSDimitry Andric // Otherwise, look for an FPU entry with all the same fields, except 3785f757f3fSDimitry Andric // that it supports double precision. 379bdd1243dSDimitry Andric for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) { 380bdd1243dSDimitry Andric if (CandidateFPU.FPUVer == InputFPU.FPUVer && 381bdd1243dSDimitry Andric CandidateFPU.NeonSupport == InputFPU.NeonSupport && 3825f757f3fSDimitry Andric ARM::has32Regs(CandidateFPU.Restriction) == 3835f757f3fSDimitry Andric ARM::has32Regs(InputFPU.Restriction) && 3845f757f3fSDimitry Andric ARM::isDoublePrecision(CandidateFPU.Restriction)) { 3855f757f3fSDimitry Andric return CandidateFPU.ID; 3865f757f3fSDimitry Andric } 3875f757f3fSDimitry Andric } 3885f757f3fSDimitry Andric 3895f757f3fSDimitry Andric // nothing found 3905f757f3fSDimitry Andric return ARM::FK_INVALID; 3915f757f3fSDimitry Andric } 3925f757f3fSDimitry Andric 3935f757f3fSDimitry Andric static ARM::FPUKind findSinglePrecisionFPU(ARM::FPUKind InputFPUKind) { 3945f757f3fSDimitry Andric if (InputFPUKind == ARM::FK_INVALID || InputFPUKind == ARM::FK_NONE) 3955f757f3fSDimitry Andric return ARM::FK_INVALID; 3965f757f3fSDimitry Andric 3975f757f3fSDimitry Andric const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind]; 3985f757f3fSDimitry Andric 3995f757f3fSDimitry Andric // If the input FPU already is single-precision only, then there 4005f757f3fSDimitry Andric // isn't any different FPU we can return here. 4015f757f3fSDimitry Andric if (!ARM::isDoublePrecision(InputFPU.Restriction)) 4025f757f3fSDimitry Andric return InputFPUKind; 4035f757f3fSDimitry Andric 4045f757f3fSDimitry Andric // Otherwise, look for an FPU entry with all the same fields, except 4055f757f3fSDimitry Andric // that it does not support double precision. 4065f757f3fSDimitry Andric for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) { 4075f757f3fSDimitry Andric if (CandidateFPU.FPUVer == InputFPU.FPUVer && 4085f757f3fSDimitry Andric CandidateFPU.NeonSupport == InputFPU.NeonSupport && 4095f757f3fSDimitry Andric ARM::has32Regs(CandidateFPU.Restriction) == 4105f757f3fSDimitry Andric ARM::has32Regs(InputFPU.Restriction) && 4115f757f3fSDimitry Andric !ARM::isDoublePrecision(CandidateFPU.Restriction)) { 412bdd1243dSDimitry Andric return CandidateFPU.ID; 413bdd1243dSDimitry Andric } 414bdd1243dSDimitry Andric } 415bdd1243dSDimitry Andric 416bdd1243dSDimitry Andric // nothing found 417bdd1243dSDimitry Andric return ARM::FK_INVALID; 418bdd1243dSDimitry Andric } 419bdd1243dSDimitry Andric 420bdd1243dSDimitry Andric bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, 421bdd1243dSDimitry Andric StringRef ArchExt, 422bdd1243dSDimitry Andric std::vector<StringRef> &Features, 42306c3fb27SDimitry Andric ARM::FPUKind &ArgFPUKind) { 424bdd1243dSDimitry Andric 425bdd1243dSDimitry Andric size_t StartingNumFeatures = Features.size(); 426bdd1243dSDimitry Andric const bool Negated = stripNegationPrefix(ArchExt); 427bdd1243dSDimitry Andric uint64_t ID = parseArchExt(ArchExt); 428bdd1243dSDimitry Andric 429bdd1243dSDimitry Andric if (ID == AEK_INVALID) 430bdd1243dSDimitry Andric return false; 431bdd1243dSDimitry Andric 432bdd1243dSDimitry Andric for (const auto &AE : ARCHExtNames) { 433bdd1243dSDimitry Andric if (Negated) { 434bdd1243dSDimitry Andric if ((AE.ID & ID) == ID && !AE.NegFeature.empty()) 435bdd1243dSDimitry Andric Features.push_back(AE.NegFeature); 436bdd1243dSDimitry Andric } else { 437bdd1243dSDimitry Andric if ((AE.ID & ID) == AE.ID && !AE.Feature.empty()) 438bdd1243dSDimitry Andric Features.push_back(AE.Feature); 439bdd1243dSDimitry Andric } 440bdd1243dSDimitry Andric } 441bdd1243dSDimitry Andric 442bdd1243dSDimitry Andric if (CPU == "") 443bdd1243dSDimitry Andric CPU = "generic"; 444bdd1243dSDimitry Andric 445bdd1243dSDimitry Andric if (ArchExt == "fp" || ArchExt == "fp.dp") { 4465f757f3fSDimitry Andric const ARM::FPUKind DefaultFPU = getDefaultFPU(CPU, AK); 44706c3fb27SDimitry Andric ARM::FPUKind FPUKind; 448bdd1243dSDimitry Andric if (ArchExt == "fp.dp") { 4495f757f3fSDimitry Andric const bool IsDP = ArgFPUKind != ARM::FK_INVALID && 4505f757f3fSDimitry Andric ArgFPUKind != ARM::FK_NONE && 4515f757f3fSDimitry Andric isDoublePrecision(getFPURestriction(ArgFPUKind)); 452bdd1243dSDimitry Andric if (Negated) { 4535f757f3fSDimitry Andric /* If there is no FPU selected yet, we still need to set ArgFPUKind, as 4545f757f3fSDimitry Andric * leaving it as FK_INVALID, would cause default FPU to be selected 4555f757f3fSDimitry Andric * later and that could be double precision one. */ 4565f757f3fSDimitry Andric if (ArgFPUKind != ARM::FK_INVALID && !IsDP) 457bdd1243dSDimitry Andric return true; 4585f757f3fSDimitry Andric FPUKind = findSinglePrecisionFPU(DefaultFPU); 4595f757f3fSDimitry Andric if (FPUKind == ARM::FK_INVALID) 4605f757f3fSDimitry Andric FPUKind = ARM::FK_NONE; 4615f757f3fSDimitry Andric } else { 4625f757f3fSDimitry Andric if (IsDP) 4635f757f3fSDimitry Andric return true; 4645f757f3fSDimitry Andric FPUKind = findDoublePrecisionFPU(DefaultFPU); 4655f757f3fSDimitry Andric if (FPUKind == ARM::FK_INVALID) 4665f757f3fSDimitry Andric return false; 467bdd1243dSDimitry Andric } 468bdd1243dSDimitry Andric } else if (Negated) { 469bdd1243dSDimitry Andric FPUKind = ARM::FK_NONE; 470bdd1243dSDimitry Andric } else { 4715f757f3fSDimitry Andric FPUKind = DefaultFPU; 472bdd1243dSDimitry Andric } 47306c3fb27SDimitry Andric ArgFPUKind = FPUKind; 4745f757f3fSDimitry Andric return true; 475bdd1243dSDimitry Andric } 476bdd1243dSDimitry Andric return StartingNumFeatures != Features.size(); 477bdd1243dSDimitry Andric } 478bdd1243dSDimitry Andric 479bdd1243dSDimitry Andric ARM::ArchKind ARM::convertV9toV8(ARM::ArchKind AK) { 480bdd1243dSDimitry Andric if (getProfileKind(AK) != ProfileKind::A) 481bdd1243dSDimitry Andric return ARM::ArchKind::INVALID; 482bdd1243dSDimitry Andric if (AK < ARM::ArchKind::ARMV9A || AK > ARM::ArchKind::ARMV9_3A) 483bdd1243dSDimitry Andric return ARM::ArchKind::INVALID; 484bdd1243dSDimitry Andric unsigned AK_v8 = static_cast<unsigned>(ARM::ArchKind::ARMV8_5A); 485bdd1243dSDimitry Andric AK_v8 += static_cast<unsigned>(AK) - 486bdd1243dSDimitry Andric static_cast<unsigned>(ARM::ArchKind::ARMV9A); 487bdd1243dSDimitry Andric return static_cast<ARM::ArchKind>(AK_v8); 488bdd1243dSDimitry Andric } 489bdd1243dSDimitry Andric 490bdd1243dSDimitry Andric StringRef ARM::getDefaultCPU(StringRef Arch) { 491bdd1243dSDimitry Andric ArchKind AK = parseArch(Arch); 492bdd1243dSDimitry Andric if (AK == ArchKind::INVALID) 493bdd1243dSDimitry Andric return StringRef(); 494bdd1243dSDimitry Andric 495bdd1243dSDimitry Andric // Look for multiple AKs to find the default for pair AK+Name. 496bdd1243dSDimitry Andric for (const auto &CPU : CPUNames) { 497bdd1243dSDimitry Andric if (CPU.ArchID == AK && CPU.Default) 498bdd1243dSDimitry Andric return CPU.Name; 499bdd1243dSDimitry Andric } 500bdd1243dSDimitry Andric 501bdd1243dSDimitry Andric // If we can't find a default then target the architecture instead 502bdd1243dSDimitry Andric return "generic"; 503bdd1243dSDimitry Andric } 504bdd1243dSDimitry Andric 505bdd1243dSDimitry Andric uint64_t ARM::parseHWDiv(StringRef HWDiv) { 506bdd1243dSDimitry Andric StringRef Syn = getHWDivSynonym(HWDiv); 507bdd1243dSDimitry Andric for (const auto &D : HWDivNames) { 508bdd1243dSDimitry Andric if (Syn == D.Name) 509bdd1243dSDimitry Andric return D.ID; 510bdd1243dSDimitry Andric } 511bdd1243dSDimitry Andric return AEK_INVALID; 512bdd1243dSDimitry Andric } 513bdd1243dSDimitry Andric 514bdd1243dSDimitry Andric uint64_t ARM::parseArchExt(StringRef ArchExt) { 515bdd1243dSDimitry Andric for (const auto &A : ARCHExtNames) { 516bdd1243dSDimitry Andric if (ArchExt == A.Name) 517bdd1243dSDimitry Andric return A.ID; 518bdd1243dSDimitry Andric } 519bdd1243dSDimitry Andric return AEK_INVALID; 520bdd1243dSDimitry Andric } 521bdd1243dSDimitry Andric 522bdd1243dSDimitry Andric ARM::ArchKind ARM::parseCPUArch(StringRef CPU) { 523bdd1243dSDimitry Andric for (const auto &C : CPUNames) { 524bdd1243dSDimitry Andric if (CPU == C.Name) 525bdd1243dSDimitry Andric return C.ArchID; 526bdd1243dSDimitry Andric } 527bdd1243dSDimitry Andric return ArchKind::INVALID; 528bdd1243dSDimitry Andric } 529bdd1243dSDimitry Andric 530bdd1243dSDimitry Andric void ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) { 531bdd1243dSDimitry Andric for (const auto &Arch : CPUNames) { 532bdd1243dSDimitry Andric if (Arch.ArchID != ArchKind::INVALID) 533bdd1243dSDimitry Andric Values.push_back(Arch.Name); 534bdd1243dSDimitry Andric } 535bdd1243dSDimitry Andric } 536bdd1243dSDimitry Andric 537bdd1243dSDimitry Andric StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) { 538bdd1243dSDimitry Andric StringRef ArchName = 539bdd1243dSDimitry Andric CPU.empty() ? TT.getArchName() : getArchName(parseCPUArch(CPU)); 540bdd1243dSDimitry Andric 541bdd1243dSDimitry Andric if (TT.isOSBinFormatMachO()) { 542bdd1243dSDimitry Andric if (TT.getEnvironment() == Triple::EABI || 543bdd1243dSDimitry Andric TT.getOS() == Triple::UnknownOS || 544bdd1243dSDimitry Andric parseArchProfile(ArchName) == ProfileKind::M) 545bdd1243dSDimitry Andric return "aapcs"; 546bdd1243dSDimitry Andric if (TT.isWatchABI()) 547bdd1243dSDimitry Andric return "aapcs16"; 548bdd1243dSDimitry Andric return "apcs-gnu"; 549bdd1243dSDimitry Andric } else if (TT.isOSWindows()) 550bdd1243dSDimitry Andric // FIXME: this is invalid for WindowsCE. 551bdd1243dSDimitry Andric return "aapcs"; 552bdd1243dSDimitry Andric 553bdd1243dSDimitry Andric // Select the default based on the platform. 554bdd1243dSDimitry Andric switch (TT.getEnvironment()) { 555bdd1243dSDimitry Andric case Triple::Android: 556bdd1243dSDimitry Andric case Triple::GNUEABI: 557*d686ce93SDimitry Andric case Triple::GNUEABIT64: 558bdd1243dSDimitry Andric case Triple::GNUEABIHF: 559*d686ce93SDimitry Andric case Triple::GNUEABIHFT64: 560bdd1243dSDimitry Andric case Triple::MuslEABI: 561bdd1243dSDimitry Andric case Triple::MuslEABIHF: 5625f757f3fSDimitry Andric case Triple::OpenHOS: 563bdd1243dSDimitry Andric return "aapcs-linux"; 564bdd1243dSDimitry Andric case Triple::EABIHF: 565bdd1243dSDimitry Andric case Triple::EABI: 566bdd1243dSDimitry Andric return "aapcs"; 567bdd1243dSDimitry Andric default: 568bdd1243dSDimitry Andric if (TT.isOSNetBSD()) 569bdd1243dSDimitry Andric return "apcs-gnu"; 5705f757f3fSDimitry Andric if (TT.isOSFreeBSD() || TT.isOSOpenBSD() || TT.isOSHaiku() || 5715f757f3fSDimitry Andric TT.isOHOSFamily()) 572bdd1243dSDimitry Andric return "aapcs-linux"; 573bdd1243dSDimitry Andric return "aapcs"; 574bdd1243dSDimitry Andric } 575bdd1243dSDimitry Andric } 576bdd1243dSDimitry Andric 577bdd1243dSDimitry Andric StringRef ARM::getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch) { 578bdd1243dSDimitry Andric if (MArch.empty()) 579bdd1243dSDimitry Andric MArch = Triple.getArchName(); 580bdd1243dSDimitry Andric MArch = llvm::ARM::getCanonicalArchName(MArch); 581bdd1243dSDimitry Andric 582bdd1243dSDimitry Andric // Some defaults are forced. 583bdd1243dSDimitry Andric switch (Triple.getOS()) { 584bdd1243dSDimitry Andric case llvm::Triple::FreeBSD: 585bdd1243dSDimitry Andric case llvm::Triple::NetBSD: 586bdd1243dSDimitry Andric case llvm::Triple::OpenBSD: 5875f757f3fSDimitry Andric case llvm::Triple::Haiku: 588bdd1243dSDimitry Andric if (!MArch.empty() && MArch == "v6") 589bdd1243dSDimitry Andric return "arm1176jzf-s"; 590bdd1243dSDimitry Andric if (!MArch.empty() && MArch == "v7") 591bdd1243dSDimitry Andric return "cortex-a8"; 592bdd1243dSDimitry Andric break; 593bdd1243dSDimitry Andric case llvm::Triple::Win32: 594bdd1243dSDimitry Andric // FIXME: this is invalid for WindowsCE 595bdd1243dSDimitry Andric if (llvm::ARM::parseArchVersion(MArch) <= 7) 596bdd1243dSDimitry Andric return "cortex-a9"; 597bdd1243dSDimitry Andric break; 598bdd1243dSDimitry Andric case llvm::Triple::IOS: 599bdd1243dSDimitry Andric case llvm::Triple::MacOSX: 600bdd1243dSDimitry Andric case llvm::Triple::TvOS: 601bdd1243dSDimitry Andric case llvm::Triple::WatchOS: 602bdd1243dSDimitry Andric case llvm::Triple::DriverKit: 6037a6dacacSDimitry Andric case llvm::Triple::XROS: 604bdd1243dSDimitry Andric if (MArch == "v7k") 605bdd1243dSDimitry Andric return "cortex-a7"; 606bdd1243dSDimitry Andric break; 607bdd1243dSDimitry Andric default: 608bdd1243dSDimitry Andric break; 609bdd1243dSDimitry Andric } 610bdd1243dSDimitry Andric 611bdd1243dSDimitry Andric if (MArch.empty()) 612bdd1243dSDimitry Andric return StringRef(); 613bdd1243dSDimitry Andric 614bdd1243dSDimitry Andric StringRef CPU = llvm::ARM::getDefaultCPU(MArch); 6150fca6ea1SDimitry Andric if (!CPU.empty() && CPU != "invalid") 616bdd1243dSDimitry Andric return CPU; 617bdd1243dSDimitry Andric 618bdd1243dSDimitry Andric // If no specific architecture version is requested, return the minimum CPU 619bdd1243dSDimitry Andric // required by the OS and environment. 620bdd1243dSDimitry Andric switch (Triple.getOS()) { 6215f757f3fSDimitry Andric case llvm::Triple::Haiku: 6225f757f3fSDimitry Andric return "arm1176jzf-s"; 623bdd1243dSDimitry Andric case llvm::Triple::NetBSD: 624bdd1243dSDimitry Andric switch (Triple.getEnvironment()) { 625bdd1243dSDimitry Andric case llvm::Triple::EABI: 626bdd1243dSDimitry Andric case llvm::Triple::EABIHF: 627bdd1243dSDimitry Andric case llvm::Triple::GNUEABI: 628bdd1243dSDimitry Andric case llvm::Triple::GNUEABIHF: 629bdd1243dSDimitry Andric return "arm926ej-s"; 630bdd1243dSDimitry Andric default: 631bdd1243dSDimitry Andric return "strongarm"; 632bdd1243dSDimitry Andric } 633bdd1243dSDimitry Andric case llvm::Triple::NaCl: 634bdd1243dSDimitry Andric case llvm::Triple::OpenBSD: 635bdd1243dSDimitry Andric return "cortex-a8"; 636bdd1243dSDimitry Andric default: 637bdd1243dSDimitry Andric switch (Triple.getEnvironment()) { 638bdd1243dSDimitry Andric case llvm::Triple::EABIHF: 639bdd1243dSDimitry Andric case llvm::Triple::GNUEABIHF: 640*d686ce93SDimitry Andric case llvm::Triple::GNUEABIHFT64: 641bdd1243dSDimitry Andric case llvm::Triple::MuslEABIHF: 642bdd1243dSDimitry Andric return "arm1176jzf-s"; 643bdd1243dSDimitry Andric default: 644bdd1243dSDimitry Andric return "arm7tdmi"; 645bdd1243dSDimitry Andric } 646bdd1243dSDimitry Andric } 647bdd1243dSDimitry Andric 648bdd1243dSDimitry Andric llvm_unreachable("invalid arch name"); 649bdd1243dSDimitry Andric } 6505f757f3fSDimitry Andric 6515f757f3fSDimitry Andric void ARM::PrintSupportedExtensions(StringMap<StringRef> DescMap) { 6525f757f3fSDimitry Andric outs() << "All available -march extensions for ARM\n\n" 6535f757f3fSDimitry Andric << " " << left_justify("Name", 20) 6545f757f3fSDimitry Andric << (DescMap.empty() ? "\n" : "Description\n"); 6555f757f3fSDimitry Andric for (const auto &Ext : ARCHExtNames) { 6565f757f3fSDimitry Andric // Extensions without a feature cannot be used with -march. 6575f757f3fSDimitry Andric if (!Ext.Feature.empty()) { 6585f757f3fSDimitry Andric std::string Description = DescMap[Ext.Name].str(); 6595f757f3fSDimitry Andric outs() << " " 6605f757f3fSDimitry Andric << format(Description.empty() ? "%s\n" : "%-20s%s\n", 6615f757f3fSDimitry Andric Ext.Name.str().c_str(), Description.c_str()); 6625f757f3fSDimitry Andric } 6635f757f3fSDimitry Andric } 6645f757f3fSDimitry Andric } 665