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