Home | History | Annotate | Download | only in Support
      1 //===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements a target parser to recognise hardware features such as
     11 // FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm/Support/ARMBuildAttributes.h"
     16 #include "llvm/Support/TargetParser.h"
     17 #include "llvm/ADT/StringExtras.h"
     18 #include "llvm/ADT/StringSwitch.h"
     19 #include "llvm/ADT/Twine.h"
     20 #include <cctype>
     21 
     22 using namespace llvm;
     23 using namespace ARM;
     24 
     25 namespace {
     26 
     27 // List of canonical FPU names (use getFPUSynonym) and which architectural
     28 // features they correspond to (use getFPUFeatures).
     29 // FIXME: TableGen this.
     30 // The entries must appear in the order listed in ARM::FPUKind for correct indexing
     31 static const struct {
     32   const char *NameCStr;
     33   size_t NameLength;
     34   ARM::FPUKind ID;
     35   ARM::FPUVersion FPUVersion;
     36   ARM::NeonSupportLevel NeonSupport;
     37   ARM::FPURestriction Restriction;
     38 
     39   StringRef getName() const { return StringRef(NameCStr, NameLength); }
     40 } FPUNames[] = {
     41 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
     42   { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
     43 #include "llvm/Support/ARMTargetParser.def"
     44 };
     45 
     46 // List of canonical arch names (use getArchSynonym).
     47 // This table also provides the build attribute fields for CPU arch
     48 // and Arch ID, according to the Addenda to the ARM ABI, chapters
     49 // 2.4 and 2.3.5.2 respectively.
     50 // FIXME: SubArch values were simplified to fit into the expectations
     51 // of the triples and are not conforming with their official names.
     52 // Check to see if the expectation should be changed.
     53 // FIXME: TableGen this.
     54 static const struct {
     55   const char *NameCStr;
     56   size_t NameLength;
     57   const char *CPUAttrCStr;
     58   size_t CPUAttrLength;
     59   const char *SubArchCStr;
     60   size_t SubArchLength;
     61   unsigned DefaultFPU;
     62   unsigned ArchBaseExtensions;
     63   ARM::ArchKind ID;
     64   ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
     65 
     66   StringRef getName() const { return StringRef(NameCStr, NameLength); }
     67 
     68   // CPU class in build attributes.
     69   StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
     70 
     71   // Sub-Arch name.
     72   StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
     73 } ARCHNames[] = {
     74 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
     75   {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
     76    sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
     77 #include "llvm/Support/ARMTargetParser.def"
     78 };
     79 
     80 // List of Arch Extension names.
     81 // FIXME: TableGen this.
     82 static const struct {
     83   const char *NameCStr;
     84   size_t NameLength;
     85   unsigned ID;
     86   const char *Feature;
     87   const char *NegFeature;
     88 
     89   StringRef getName() const { return StringRef(NameCStr, NameLength); }
     90 } ARCHExtNames[] = {
     91 #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
     92   { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
     93 #include "llvm/Support/ARMTargetParser.def"
     94 };
     95 
     96 // List of HWDiv names (use getHWDivSynonym) and which architectural
     97 // features they correspond to (use getHWDivFeatures).
     98 // FIXME: TableGen this.
     99 static const struct {
    100   const char *NameCStr;
    101   size_t NameLength;
    102   unsigned ID;
    103 
    104   StringRef getName() const { return StringRef(NameCStr, NameLength); }
    105 } HWDivNames[] = {
    106 #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
    107 #include "llvm/Support/ARMTargetParser.def"
    108 };
    109 
    110 // List of CPU names and their arches.
    111 // The same CPU can have multiple arches and can be default on multiple arches.
    112 // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
    113 // When this becomes table-generated, we'd probably need two tables.
    114 // FIXME: TableGen this.
    115 static const struct {
    116   const char *NameCStr;
    117   size_t NameLength;
    118   ARM::ArchKind ArchID;
    119   bool Default; // is $Name the default CPU for $ArchID ?
    120   unsigned DefaultExtensions;
    121 
    122   StringRef getName() const { return StringRef(NameCStr, NameLength); }
    123 } CPUNames[] = {
    124 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
    125   { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
    126 #include "llvm/Support/ARMTargetParser.def"
    127 };
    128 
    129 } // namespace
    130 
    131 // ======================================================= //
    132 // Information by ID
    133 // ======================================================= //
    134 
    135 StringRef llvm::ARM::getFPUName(unsigned FPUKind) {
    136   if (FPUKind >= ARM::FK_LAST)
    137     return StringRef();
    138   return FPUNames[FPUKind].getName();
    139 }
    140 
    141 unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
    142   if (FPUKind >= ARM::FK_LAST)
    143     return 0;
    144   return FPUNames[FPUKind].FPUVersion;
    145 }
    146 
    147 unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
    148   if (FPUKind >= ARM::FK_LAST)
    149     return 0;
    150   return FPUNames[FPUKind].NeonSupport;
    151 }
    152 
    153 unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
    154   if (FPUKind >= ARM::FK_LAST)
    155     return 0;
    156   return FPUNames[FPUKind].Restriction;
    157 }
    158 
    159 unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
    160   if (CPU == "generic")
    161     return ARCHNames[ArchKind].DefaultFPU;
    162 
    163   return StringSwitch<unsigned>(CPU)
    164 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
    165     .Case(NAME, DEFAULT_FPU)
    166 #include "llvm/Support/ARMTargetParser.def"
    167     .Default(ARM::FK_INVALID);
    168 }
    169 
    170 unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
    171   if (CPU == "generic")
    172     return ARCHNames[ArchKind].ArchBaseExtensions;
    173 
    174   return StringSwitch<unsigned>(CPU)
    175 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
    176     .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
    177 #include "llvm/Support/ARMTargetParser.def"
    178     .Default(ARM::AEK_INVALID);
    179 }
    180 
    181 bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
    182                                  std::vector<const char *> &Features) {
    183 
    184   if (HWDivKind == ARM::AEK_INVALID)
    185     return false;
    186 
    187   if (HWDivKind & ARM::AEK_HWDIVARM)
    188     Features.push_back("+hwdiv-arm");
    189   else
    190     Features.push_back("-hwdiv-arm");
    191 
    192   if (HWDivKind & ARM::AEK_HWDIV)
    193     Features.push_back("+hwdiv");
    194   else
    195     Features.push_back("-hwdiv");
    196 
    197   return true;
    198 }
    199 
    200 bool llvm::ARM::getExtensionFeatures(unsigned Extensions,
    201                                      std::vector<const char *> &Features) {
    202 
    203   if (Extensions == ARM::AEK_INVALID)
    204     return false;
    205 
    206   if (Extensions & ARM::AEK_CRC)
    207     Features.push_back("+crc");
    208   else
    209     Features.push_back("-crc");
    210 
    211   if (Extensions & ARM::AEK_DSP)
    212     Features.push_back("+dsp");
    213   else
    214     Features.push_back("-dsp");
    215 
    216   return getHWDivFeatures(Extensions, Features);
    217 }
    218 
    219 bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
    220                                std::vector<const char *> &Features) {
    221 
    222   if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
    223     return false;
    224 
    225   // fp-only-sp and d16 subtarget features are independent of each other, so we
    226   // must enable/disable both.
    227   switch (FPUNames[FPUKind].Restriction) {
    228   case ARM::FR_SP_D16:
    229     Features.push_back("+fp-only-sp");
    230     Features.push_back("+d16");
    231     break;
    232   case ARM::FR_D16:
    233     Features.push_back("-fp-only-sp");
    234     Features.push_back("+d16");
    235     break;
    236   case ARM::FR_None:
    237     Features.push_back("-fp-only-sp");
    238     Features.push_back("-d16");
    239     break;
    240   }
    241 
    242   // FPU version subtarget features are inclusive of lower-numbered ones, so
    243   // enable the one corresponding to this version and disable all that are
    244   // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
    245   // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
    246   switch (FPUNames[FPUKind].FPUVersion) {
    247   case ARM::FV_VFPV5:
    248     Features.push_back("+fp-armv8");
    249     break;
    250   case ARM::FV_VFPV4:
    251     Features.push_back("+vfp4");
    252     Features.push_back("-fp-armv8");
    253     break;
    254   case ARM::FV_VFPV3_FP16:
    255     Features.push_back("+vfp3");
    256     Features.push_back("+fp16");
    257     Features.push_back("-vfp4");
    258     Features.push_back("-fp-armv8");
    259     break;
    260   case ARM::FV_VFPV3:
    261     Features.push_back("+vfp3");
    262     Features.push_back("-fp16");
    263     Features.push_back("-vfp4");
    264     Features.push_back("-fp-armv8");
    265     break;
    266   case ARM::FV_VFPV2:
    267     Features.push_back("+vfp2");
    268     Features.push_back("-vfp3");
    269     Features.push_back("-fp16");
    270     Features.push_back("-vfp4");
    271     Features.push_back("-fp-armv8");
    272     break;
    273   case ARM::FV_NONE:
    274     Features.push_back("-vfp2");
    275     Features.push_back("-vfp3");
    276     Features.push_back("-fp16");
    277     Features.push_back("-vfp4");
    278     Features.push_back("-fp-armv8");
    279     break;
    280   }
    281 
    282   // crypto includes neon, so we handle this similarly to FPU version.
    283   switch (FPUNames[FPUKind].NeonSupport) {
    284   case ARM::NS_Crypto:
    285     Features.push_back("+neon");
    286     Features.push_back("+crypto");
    287     break;
    288   case ARM::NS_Neon:
    289     Features.push_back("+neon");
    290     Features.push_back("-crypto");
    291     break;
    292   case ARM::NS_None:
    293     Features.push_back("-neon");
    294     Features.push_back("-crypto");
    295     break;
    296   }
    297 
    298   return true;
    299 }
    300 
    301 StringRef llvm::ARM::getArchName(unsigned ArchKind) {
    302   if (ArchKind >= ARM::AK_LAST)
    303     return StringRef();
    304   return ARCHNames[ArchKind].getName();
    305 }
    306 
    307 StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) {
    308   if (ArchKind >= ARM::AK_LAST)
    309     return StringRef();
    310   return ARCHNames[ArchKind].getCPUAttr();
    311 }
    312 
    313 StringRef llvm::ARM::getSubArch(unsigned ArchKind) {
    314   if (ArchKind >= ARM::AK_LAST)
    315     return StringRef();
    316   return ARCHNames[ArchKind].getSubArch();
    317 }
    318 
    319 unsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
    320   if (ArchKind >= ARM::AK_LAST)
    321     return ARMBuildAttrs::CPUArch::Pre_v4;
    322   return ARCHNames[ArchKind].ArchAttr;
    323 }
    324 
    325 StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
    326   for (const auto AE : ARCHExtNames) {
    327     if (ArchExtKind == AE.ID)
    328       return AE.getName();
    329   }
    330   return StringRef();
    331 }
    332 
    333 const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) {
    334   if (ArchExt.startswith("no")) {
    335     StringRef ArchExtBase(ArchExt.substr(2));
    336     for (const auto AE : ARCHExtNames) {
    337       if (AE.NegFeature && ArchExtBase == AE.getName())
    338         return AE.NegFeature;
    339     }
    340   }
    341   for (const auto AE : ARCHExtNames) {
    342     if (AE.Feature && ArchExt == AE.getName())
    343       return AE.Feature;
    344   }
    345 
    346   return nullptr;
    347 }
    348 
    349 StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
    350   for (const auto D : HWDivNames) {
    351     if (HWDivKind == D.ID)
    352       return D.getName();
    353   }
    354   return StringRef();
    355 }
    356 
    357 StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
    358   unsigned AK = parseArch(Arch);
    359   if (AK == ARM::AK_INVALID)
    360     return StringRef();
    361 
    362   // Look for multiple AKs to find the default for pair AK+Name.
    363   for (const auto CPU : CPUNames) {
    364     if (CPU.ArchID == AK && CPU.Default)
    365       return CPU.getName();
    366   }
    367 
    368   // If we can't find a default then target the architecture instead
    369   return "generic";
    370 }
    371 
    372 // ======================================================= //
    373 // Parsers
    374 // ======================================================= //
    375 
    376 static StringRef getHWDivSynonym(StringRef HWDiv) {
    377   return StringSwitch<StringRef>(HWDiv)
    378       .Case("thumb,arm", "arm,thumb")
    379       .Default(HWDiv);
    380 }
    381 
    382 static StringRef getFPUSynonym(StringRef FPU) {
    383   return StringSwitch<StringRef>(FPU)
    384       .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
    385       .Case("vfp2", "vfpv2")
    386       .Case("vfp3", "vfpv3")
    387       .Case("vfp4", "vfpv4")
    388       .Case("vfp3-d16", "vfpv3-d16")
    389       .Case("vfp4-d16", "vfpv4-d16")
    390       .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
    391       .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
    392       .Case("fp5-sp-d16", "fpv5-sp-d16")
    393       .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
    394       // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
    395       .Case("neon-vfpv3", "neon")
    396       .Default(FPU);
    397 }
    398 
    399 static StringRef getArchSynonym(StringRef Arch) {
    400   return StringSwitch<StringRef>(Arch)
    401       .Case("v5", "v5t")
    402       .Case("v5e", "v5te")
    403       .Case("v6j", "v6")
    404       .Case("v6hl", "v6k")
    405       .Cases("v6m", "v6sm", "v6s-m", "v6-m")
    406       .Cases("v6z", "v6zk", "v6kz")
    407       .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
    408       .Case("v7r", "v7-r")
    409       .Case("v7m", "v7-m")
    410       .Case("v7em", "v7e-m")
    411       .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
    412       .Case("v8.1a", "v8.1-a")
    413       .Case("v8.2a", "v8.2-a")
    414       .Default(Arch);
    415 }
    416 
    417 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
    418 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
    419 // "v.+", if the latter, return unmodified string, minus 'eb'.
    420 // If invalid, return empty string.
    421 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
    422   size_t offset = StringRef::npos;
    423   StringRef A = Arch;
    424   StringRef Error = "";
    425 
    426   // Begins with "arm" / "thumb", move past it.
    427   if (A.startswith("arm64"))
    428     offset = 5;
    429   else if (A.startswith("arm"))
    430     offset = 3;
    431   else if (A.startswith("thumb"))
    432     offset = 5;
    433   else if (A.startswith("aarch64")) {
    434     offset = 7;
    435     // AArch64 uses "_be", not "eb" suffix.
    436     if (A.find("eb") != StringRef::npos)
    437       return Error;
    438     if (A.substr(offset, 3) == "_be")
    439       offset += 3;
    440   }
    441 
    442   // Ex. "armebv7", move past the "eb".
    443   if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
    444     offset += 2;
    445   // Or, if it ends with eb ("armv7eb"), chop it off.
    446   else if (A.endswith("eb"))
    447     A = A.substr(0, A.size() - 2);
    448   // Trim the head
    449   if (offset != StringRef::npos)
    450     A = A.substr(offset);
    451 
    452   // Empty string means offset reached the end, which means it's valid.
    453   if (A.empty())
    454     return Arch;
    455 
    456   // Only match non-marketing names
    457   if (offset != StringRef::npos) {
    458     // Must start with 'vN'.
    459     if (A[0] != 'v' || !std::isdigit(A[1]))
    460       return Error;
    461     // Can't have an extra 'eb'.
    462     if (A.find("eb") != StringRef::npos)
    463       return Error;
    464   }
    465 
    466   // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
    467   return A;
    468 }
    469 
    470 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
    471   StringRef Syn = getHWDivSynonym(HWDiv);
    472   for (const auto D : HWDivNames) {
    473     if (Syn == D.getName())
    474       return D.ID;
    475   }
    476   return ARM::AEK_INVALID;
    477 }
    478 
    479 unsigned llvm::ARM::parseFPU(StringRef FPU) {
    480   StringRef Syn = getFPUSynonym(FPU);
    481   for (const auto F : FPUNames) {
    482     if (Syn == F.getName())
    483       return F.ID;
    484   }
    485   return ARM::FK_INVALID;
    486 }
    487 
    488 // Allows partial match, ex. "v7a" matches "armv7a".
    489 unsigned llvm::ARM::parseArch(StringRef Arch) {
    490   Arch = getCanonicalArchName(Arch);
    491   StringRef Syn = getArchSynonym(Arch);
    492   for (const auto A : ARCHNames) {
    493     if (A.getName().endswith(Syn))
    494       return A.ID;
    495   }
    496   return ARM::AK_INVALID;
    497 }
    498 
    499 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
    500   for (const auto A : ARCHExtNames) {
    501     if (ArchExt == A.getName())
    502       return A.ID;
    503   }
    504   return ARM::AEK_INVALID;
    505 }
    506 
    507 unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
    508   for (const auto C : CPUNames) {
    509     if (CPU == C.getName())
    510       return C.ArchID;
    511   }
    512   return ARM::AK_INVALID;
    513 }
    514 
    515 // ARM, Thumb, AArch64
    516 unsigned llvm::ARM::parseArchISA(StringRef Arch) {
    517   return StringSwitch<unsigned>(Arch)
    518       .StartsWith("aarch64", ARM::IK_AARCH64)
    519       .StartsWith("arm64", ARM::IK_AARCH64)
    520       .StartsWith("thumb", ARM::IK_THUMB)
    521       .StartsWith("arm", ARM::IK_ARM)
    522       .Default(ARM::EK_INVALID);
    523 }
    524 
    525 // Little/Big endian
    526 unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
    527   if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
    528       Arch.startswith("aarch64_be"))
    529     return ARM::EK_BIG;
    530 
    531   if (Arch.startswith("arm") || Arch.startswith("thumb")) {
    532     if (Arch.endswith("eb"))
    533       return ARM::EK_BIG;
    534     else
    535       return ARM::EK_LITTLE;
    536   }
    537 
    538   if (Arch.startswith("aarch64"))
    539     return ARM::EK_LITTLE;
    540 
    541   return ARM::EK_INVALID;
    542 }
    543 
    544 // Profile A/R/M
    545 unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
    546   Arch = getCanonicalArchName(Arch);
    547   switch (parseArch(Arch)) {
    548   case ARM::AK_ARMV6M:
    549   case ARM::AK_ARMV7M:
    550   case ARM::AK_ARMV7EM:
    551     return ARM::PK_M;
    552   case ARM::AK_ARMV7R:
    553     return ARM::PK_R;
    554   case ARM::AK_ARMV7A:
    555   case ARM::AK_ARMV7K:
    556   case ARM::AK_ARMV8A:
    557   case ARM::AK_ARMV8_1A:
    558   case ARM::AK_ARMV8_2A:
    559     return ARM::PK_A;
    560   }
    561   return ARM::PK_INVALID;
    562 }
    563 
    564 // Version number (ex. v7 = 7).
    565 unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
    566   Arch = getCanonicalArchName(Arch);
    567   switch (parseArch(Arch)) {
    568   case ARM::AK_ARMV2:
    569   case ARM::AK_ARMV2A:
    570     return 2;
    571   case ARM::AK_ARMV3:
    572   case ARM::AK_ARMV3M:
    573     return 3;
    574   case ARM::AK_ARMV4:
    575   case ARM::AK_ARMV4T:
    576     return 4;
    577   case ARM::AK_ARMV5T:
    578   case ARM::AK_ARMV5TE:
    579   case ARM::AK_IWMMXT:
    580   case ARM::AK_IWMMXT2:
    581   case ARM::AK_XSCALE:
    582   case ARM::AK_ARMV5TEJ:
    583     return 5;
    584   case ARM::AK_ARMV6:
    585   case ARM::AK_ARMV6K:
    586   case ARM::AK_ARMV6T2:
    587   case ARM::AK_ARMV6KZ:
    588   case ARM::AK_ARMV6M:
    589     return 6;
    590   case ARM::AK_ARMV7A:
    591   case ARM::AK_ARMV7R:
    592   case ARM::AK_ARMV7M:
    593   case ARM::AK_ARMV7S:
    594   case ARM::AK_ARMV7EM:
    595   case ARM::AK_ARMV7K:
    596     return 7;
    597   case ARM::AK_ARMV8A:
    598   case ARM::AK_ARMV8_1A:
    599   case ARM::AK_ARMV8_2A:
    600     return 8;
    601   }
    602   return 0;
    603 }
    604