1ff0cc061SDimitry Andric //===-- TargetParser - Parser for target features ---------------*- C++ -*-===// 2ff0cc061SDimitry Andric // 3ff0cc061SDimitry Andric // The LLVM Compiler Infrastructure 4ff0cc061SDimitry Andric // 5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source 6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details. 7ff0cc061SDimitry Andric // 8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===// 9ff0cc061SDimitry Andric // 10ff0cc061SDimitry Andric // This file implements a target parser to recognise hardware features such as 11ff0cc061SDimitry Andric // FPU/CPU/ARCH names as well as specific support such as HDIV, etc. 12ff0cc061SDimitry Andric // 13ff0cc061SDimitry Andric //===----------------------------------------------------------------------===// 14ff0cc061SDimitry Andric 15ff0cc061SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h" 16ff0cc061SDimitry Andric #include "llvm/Support/TargetParser.h" 17ff0cc061SDimitry Andric #include "llvm/ADT/StringExtras.h" 18ff0cc061SDimitry Andric #include "llvm/ADT/StringSwitch.h" 19ff0cc061SDimitry Andric #include <cctype> 20ff0cc061SDimitry Andric 21ff0cc061SDimitry Andric using namespace llvm; 22ff0cc061SDimitry Andric 23ff0cc061SDimitry Andric namespace { 24ff0cc061SDimitry Andric 25ff0cc061SDimitry Andric // List of canonical FPU names (use getFPUSynonym) 26ff0cc061SDimitry Andric // FIXME: TableGen this. 27ff0cc061SDimitry Andric struct { 28ff0cc061SDimitry Andric const char * Name; 29ff0cc061SDimitry Andric ARM::FPUKind ID; 30ff0cc061SDimitry Andric } FPUNames[] = { 31ff0cc061SDimitry Andric { "invalid", ARM::FK_INVALID }, 32ff0cc061SDimitry Andric { "vfp", ARM::FK_VFP }, 33ff0cc061SDimitry Andric { "vfpv2", ARM::FK_VFPV2 }, 34ff0cc061SDimitry Andric { "vfpv3", ARM::FK_VFPV3 }, 35ff0cc061SDimitry Andric { "vfpv3-d16", ARM::FK_VFPV3_D16 }, 36ff0cc061SDimitry Andric { "vfpv4", ARM::FK_VFPV4 }, 37ff0cc061SDimitry Andric { "vfpv4-d16", ARM::FK_VFPV4_D16 }, 38ff0cc061SDimitry Andric { "fpv5-d16", ARM::FK_FPV5_D16 }, 39ff0cc061SDimitry Andric { "fp-armv8", ARM::FK_FP_ARMV8 }, 40ff0cc061SDimitry Andric { "neon", ARM::FK_NEON }, 41ff0cc061SDimitry Andric { "neon-vfpv4", ARM::FK_NEON_VFPV4 }, 42ff0cc061SDimitry Andric { "neon-fp-armv8", ARM::FK_NEON_FP_ARMV8 }, 43ff0cc061SDimitry Andric { "crypto-neon-fp-armv8", ARM::FK_CRYPTO_NEON_FP_ARMV8 }, 44ff0cc061SDimitry Andric { "softvfp", ARM::FK_SOFTVFP } 45ff0cc061SDimitry Andric }; 46ff0cc061SDimitry Andric // List of canonical arch names (use getArchSynonym) 47ff0cc061SDimitry Andric // FIXME: TableGen this. 48ff0cc061SDimitry Andric struct { 49ff0cc061SDimitry Andric const char *Name; 50ff0cc061SDimitry Andric ARM::ArchKind ID; 51ff0cc061SDimitry Andric const char *DefaultCPU; 52ff0cc061SDimitry Andric ARMBuildAttrs::CPUArch DefaultArch; 53ff0cc061SDimitry Andric } ARCHNames[] = { 54ff0cc061SDimitry Andric { "invalid", ARM::AK_INVALID, nullptr, ARMBuildAttrs::CPUArch::Pre_v4 }, 55ff0cc061SDimitry Andric { "armv2", ARM::AK_ARMV2, "2", ARMBuildAttrs::CPUArch::v4 }, 56ff0cc061SDimitry Andric { "armv2a", ARM::AK_ARMV2A, "2A", ARMBuildAttrs::CPUArch::v4 }, 57ff0cc061SDimitry Andric { "armv3", ARM::AK_ARMV3, "3", ARMBuildAttrs::CPUArch::v4 }, 58ff0cc061SDimitry Andric { "armv3m", ARM::AK_ARMV3M, "3M", ARMBuildAttrs::CPUArch::v4 }, 59ff0cc061SDimitry Andric { "armv4", ARM::AK_ARMV4, "4", ARMBuildAttrs::CPUArch::v4 }, 60ff0cc061SDimitry Andric { "armv4t", ARM::AK_ARMV4T, "4T", ARMBuildAttrs::CPUArch::v4T }, 61ff0cc061SDimitry Andric { "armv5", ARM::AK_ARMV5, "5", ARMBuildAttrs::CPUArch::v5T }, 62ff0cc061SDimitry Andric { "armv5t", ARM::AK_ARMV5T, "5T", ARMBuildAttrs::CPUArch::v5T }, 63ff0cc061SDimitry Andric { "armv5te", ARM::AK_ARMV5TE, "5TE", ARMBuildAttrs::CPUArch::v5TE }, 64ff0cc061SDimitry Andric { "armv6", ARM::AK_ARMV6, "6", ARMBuildAttrs::CPUArch::v6 }, 65ff0cc061SDimitry Andric { "armv6j", ARM::AK_ARMV6J, "6J", ARMBuildAttrs::CPUArch::v6 }, 66ff0cc061SDimitry Andric { "armv6k", ARM::AK_ARMV6K, "6K", ARMBuildAttrs::CPUArch::v6K }, 67ff0cc061SDimitry Andric { "armv6t2", ARM::AK_ARMV6T2, "6T2", ARMBuildAttrs::CPUArch::v6T2 }, 68ff0cc061SDimitry Andric { "armv6z", ARM::AK_ARMV6Z, "6Z", ARMBuildAttrs::CPUArch::v6KZ }, 69ff0cc061SDimitry Andric { "armv6zk", ARM::AK_ARMV6ZK, "6ZK", ARMBuildAttrs::CPUArch::v6KZ }, 70ff0cc061SDimitry Andric { "armv6-m", ARM::AK_ARMV6M, "6-M", ARMBuildAttrs::CPUArch::v6_M }, 71ff0cc061SDimitry Andric { "armv7", ARM::AK_ARMV7, "7", ARMBuildAttrs::CPUArch::v7 }, 72ff0cc061SDimitry Andric { "armv7-a", ARM::AK_ARMV7A, "7-A", ARMBuildAttrs::CPUArch::v7 }, 73ff0cc061SDimitry Andric { "armv7-r", ARM::AK_ARMV7R, "7-R", ARMBuildAttrs::CPUArch::v7 }, 74ff0cc061SDimitry Andric { "armv7-m", ARM::AK_ARMV7M, "7-M", ARMBuildAttrs::CPUArch::v7 }, 75ff0cc061SDimitry Andric { "armv8-a", ARM::AK_ARMV8A, "8-A", ARMBuildAttrs::CPUArch::v8 }, 76ff0cc061SDimitry Andric { "armv8.1-a", ARM::AK_ARMV8_1A, "8.1-A", ARMBuildAttrs::CPUArch::v8 }, 77ff0cc061SDimitry Andric // Non-standard Arch names. 78ff0cc061SDimitry Andric { "iwmmxt", ARM::AK_IWMMXT, "iwmmxt", ARMBuildAttrs::CPUArch::v5TE }, 79ff0cc061SDimitry Andric { "iwmmxt2", ARM::AK_IWMMXT2, "iwmmxt2", ARMBuildAttrs::CPUArch::v5TE }, 80ff0cc061SDimitry Andric { "xscale", ARM::AK_XSCALE, "xscale", ARMBuildAttrs::CPUArch::v5TE }, 81ff0cc061SDimitry Andric { "armv5e", ARM::AK_ARMV5E, "5E", ARMBuildAttrs::CPUArch::v5TE }, 82ff0cc061SDimitry Andric { "armv5tej", ARM::AK_ARMV5TEJ, "5TE", ARMBuildAttrs::CPUArch::v5TE }, 83ff0cc061SDimitry Andric { "armv6sm", ARM::AK_ARMV6SM, "6-M", ARMBuildAttrs::CPUArch::v6_M }, 84ff0cc061SDimitry Andric { "armv6hl", ARM::AK_ARMV6HL, "6-M", ARMBuildAttrs::CPUArch::v6_M }, 85ff0cc061SDimitry Andric { "armv7e-m", ARM::AK_ARMV7EM, "7E-M", ARMBuildAttrs::CPUArch::v7E_M }, 86ff0cc061SDimitry Andric { "armv7l", ARM::AK_ARMV7L, "7-L", ARMBuildAttrs::CPUArch::v7 }, 87ff0cc061SDimitry Andric { "armv7hl", ARM::AK_ARMV7HL, "7H-L", ARMBuildAttrs::CPUArch::v7 }, 88ff0cc061SDimitry Andric { "armv7s", ARM::AK_ARMV7S, "7-S", ARMBuildAttrs::CPUArch::v7 } 89ff0cc061SDimitry Andric }; 90ff0cc061SDimitry Andric // List of canonical ARCH names (use getARCHSynonym) 91ff0cc061SDimitry Andric // FIXME: TableGen this. 92ff0cc061SDimitry Andric struct { 93ff0cc061SDimitry Andric const char *Name; 94ff0cc061SDimitry Andric ARM::ArchExtKind ID; 95ff0cc061SDimitry Andric } ARCHExtNames[] = { 96ff0cc061SDimitry Andric { "invalid", ARM::AEK_INVALID }, 97ff0cc061SDimitry Andric { "crc", ARM::AEK_CRC }, 98ff0cc061SDimitry Andric { "crypto", ARM::AEK_CRYPTO }, 99ff0cc061SDimitry Andric { "fp", ARM::AEK_FP }, 100ff0cc061SDimitry Andric { "idiv", ARM::AEK_HWDIV }, 101ff0cc061SDimitry Andric { "mp", ARM::AEK_MP }, 102ff0cc061SDimitry Andric { "sec", ARM::AEK_SEC }, 103ff0cc061SDimitry Andric { "virt", ARM::AEK_VIRT } 104ff0cc061SDimitry Andric }; 105ff0cc061SDimitry Andric // List of CPU names and their arches. 106ff0cc061SDimitry Andric // The same CPU can have multiple arches and can be default on multiple arches. 107ff0cc061SDimitry Andric // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. 108ff0cc061SDimitry Andric // FIXME: TableGen this. 109ff0cc061SDimitry Andric struct { 110ff0cc061SDimitry Andric const char *Name; 111ff0cc061SDimitry Andric ARM::ArchKind ArchID; 112ff0cc061SDimitry Andric bool Default; 113ff0cc061SDimitry Andric } CPUNames[] = { 114ff0cc061SDimitry Andric { "arm2", ARM::AK_ARMV2, true }, 115ff0cc061SDimitry Andric { "arm6", ARM::AK_ARMV3, true }, 116ff0cc061SDimitry Andric { "arm7m", ARM::AK_ARMV3M, true }, 117ff0cc061SDimitry Andric { "strongarm", ARM::AK_ARMV4, true }, 118ff0cc061SDimitry Andric { "arm7tdmi", ARM::AK_ARMV4T, true }, 119ff0cc061SDimitry Andric { "arm7tdmi-s", ARM::AK_ARMV4T, false }, 120ff0cc061SDimitry Andric { "arm710t", ARM::AK_ARMV4T, false }, 121ff0cc061SDimitry Andric { "arm720t", ARM::AK_ARMV4T, false }, 122ff0cc061SDimitry Andric { "arm9", ARM::AK_ARMV4T, false }, 123ff0cc061SDimitry Andric { "arm9tdmi", ARM::AK_ARMV4T, false }, 124ff0cc061SDimitry Andric { "arm920", ARM::AK_ARMV4T, false }, 125ff0cc061SDimitry Andric { "arm920t", ARM::AK_ARMV4T, false }, 126ff0cc061SDimitry Andric { "arm922t", ARM::AK_ARMV4T, false }, 127ff0cc061SDimitry Andric { "arm9312", ARM::AK_ARMV4T, false }, 128ff0cc061SDimitry Andric { "arm940t", ARM::AK_ARMV4T, false }, 129ff0cc061SDimitry Andric { "ep9312", ARM::AK_ARMV4T, false }, 130ff0cc061SDimitry Andric { "arm10tdmi", ARM::AK_ARMV5, true }, 131ff0cc061SDimitry Andric { "arm10tdmi", ARM::AK_ARMV5T, true }, 132ff0cc061SDimitry Andric { "arm1020t", ARM::AK_ARMV5T, false }, 133ff0cc061SDimitry Andric { "xscale", ARM::AK_XSCALE, true }, 134ff0cc061SDimitry Andric { "xscale", ARM::AK_ARMV5TE, false }, 135ff0cc061SDimitry Andric { "arm9e", ARM::AK_ARMV5TE, false }, 136ff0cc061SDimitry Andric { "arm926ej-s", ARM::AK_ARMV5TE, false }, 137ff0cc061SDimitry Andric { "arm946ej-s", ARM::AK_ARMV5TE, false }, 138ff0cc061SDimitry Andric { "arm966e-s", ARM::AK_ARMV5TE, false }, 139ff0cc061SDimitry Andric { "arm968e-s", ARM::AK_ARMV5TE, false }, 140ff0cc061SDimitry Andric { "arm1020e", ARM::AK_ARMV5TE, false }, 141ff0cc061SDimitry Andric { "arm1022e", ARM::AK_ARMV5TE, true }, 142ff0cc061SDimitry Andric { "iwmmxt", ARM::AK_ARMV5TE, false }, 143ff0cc061SDimitry Andric { "iwmmxt", ARM::AK_IWMMXT, true }, 144ff0cc061SDimitry Andric { "arm1136jf-s", ARM::AK_ARMV6, true }, 145ff0cc061SDimitry Andric { "arm1136j-s", ARM::AK_ARMV6J, true }, 146ff0cc061SDimitry Andric { "arm1136jz-s", ARM::AK_ARMV6J, false }, 147ff0cc061SDimitry Andric { "arm1176j-s", ARM::AK_ARMV6K, false }, 148ff0cc061SDimitry Andric { "mpcore", ARM::AK_ARMV6K, false }, 149ff0cc061SDimitry Andric { "mpcorenovfp", ARM::AK_ARMV6K, false }, 150ff0cc061SDimitry Andric { "arm1176jzf-s", ARM::AK_ARMV6K, true }, 151ff0cc061SDimitry Andric { "arm1176jzf-s", ARM::AK_ARMV6Z, true }, 152ff0cc061SDimitry Andric { "arm1176jzf-s", ARM::AK_ARMV6ZK, true }, 153ff0cc061SDimitry Andric { "arm1156t2-s", ARM::AK_ARMV6T2, true }, 154ff0cc061SDimitry Andric { "arm1156t2f-s", ARM::AK_ARMV6T2, false }, 155ff0cc061SDimitry Andric { "cortex-m0", ARM::AK_ARMV6M, true }, 156ff0cc061SDimitry Andric { "cortex-m0plus", ARM::AK_ARMV6M, false }, 157ff0cc061SDimitry Andric { "cortex-m1", ARM::AK_ARMV6M, false }, 158ff0cc061SDimitry Andric { "sc000", ARM::AK_ARMV6M, false }, 159ff0cc061SDimitry Andric { "cortex-a8", ARM::AK_ARMV7, true }, 160ff0cc061SDimitry Andric { "cortex-a5", ARM::AK_ARMV7A, false }, 161ff0cc061SDimitry Andric { "cortex-a7", ARM::AK_ARMV7A, false }, 162ff0cc061SDimitry Andric { "cortex-a8", ARM::AK_ARMV7A, true }, 163ff0cc061SDimitry Andric { "cortex-a9", ARM::AK_ARMV7A, false }, 164ff0cc061SDimitry Andric { "cortex-a12", ARM::AK_ARMV7A, false }, 165ff0cc061SDimitry Andric { "cortex-a15", ARM::AK_ARMV7A, false }, 166ff0cc061SDimitry Andric { "cortex-a17", ARM::AK_ARMV7A, false }, 167ff0cc061SDimitry Andric { "krait", ARM::AK_ARMV7A, false }, 168ff0cc061SDimitry Andric { "cortex-r4", ARM::AK_ARMV7R, true }, 169ff0cc061SDimitry Andric { "cortex-r4f", ARM::AK_ARMV7R, false }, 170ff0cc061SDimitry Andric { "cortex-r5", ARM::AK_ARMV7R, false }, 171ff0cc061SDimitry Andric { "cortex-r7", ARM::AK_ARMV7R, false }, 172ff0cc061SDimitry Andric { "sc300", ARM::AK_ARMV7M, false }, 173ff0cc061SDimitry Andric { "cortex-m3", ARM::AK_ARMV7M, true }, 174ff0cc061SDimitry Andric { "cortex-m4", ARM::AK_ARMV7M, false }, 175ff0cc061SDimitry Andric { "cortex-m7", ARM::AK_ARMV7M, false }, 176ff0cc061SDimitry Andric { "cortex-a53", ARM::AK_ARMV8A, true }, 177ff0cc061SDimitry Andric { "cortex-a57", ARM::AK_ARMV8A, false }, 178ff0cc061SDimitry Andric { "cortex-a72", ARM::AK_ARMV8A, false }, 179ff0cc061SDimitry Andric { "cyclone", ARM::AK_ARMV8A, false }, 180ff0cc061SDimitry Andric { "generic", ARM::AK_ARMV8_1A, true }, 181ff0cc061SDimitry Andric // Non-standard Arch names. 182ff0cc061SDimitry Andric { "arm1022e", ARM::AK_ARMV5E, true }, 183ff0cc061SDimitry Andric { "arm926ej-s", ARM::AK_ARMV5TEJ, true }, 184ff0cc061SDimitry Andric { "cortex-m0", ARM::AK_ARMV6SM, true }, 185ff0cc061SDimitry Andric { "arm1176jzf-s", ARM::AK_ARMV6HL, true }, 186ff0cc061SDimitry Andric { "cortex-a8", ARM::AK_ARMV7L, true }, 187ff0cc061SDimitry Andric { "cortex-a8", ARM::AK_ARMV7HL, true }, 188ff0cc061SDimitry Andric { "cortex-m4", ARM::AK_ARMV7EM, true }, 189ff0cc061SDimitry Andric { "swift", ARM::AK_ARMV7S, true }, 190ff0cc061SDimitry Andric // Invalid CPU 191ff0cc061SDimitry Andric { "invalid", ARM::AK_INVALID, true } 192ff0cc061SDimitry Andric }; 193ff0cc061SDimitry Andric 194ff0cc061SDimitry Andric } // namespace 195ff0cc061SDimitry Andric 196ff0cc061SDimitry Andric namespace llvm { 197ff0cc061SDimitry Andric 198ff0cc061SDimitry Andric // ======================================================= // 199ff0cc061SDimitry Andric // Information by ID 200ff0cc061SDimitry Andric // ======================================================= // 201ff0cc061SDimitry Andric 202ff0cc061SDimitry Andric const char *ARMTargetParser::getFPUName(unsigned FPUKind) { 203ff0cc061SDimitry Andric if (FPUKind >= ARM::FK_LAST) 204ff0cc061SDimitry Andric return nullptr; 205ff0cc061SDimitry Andric return FPUNames[FPUKind].Name; 206ff0cc061SDimitry Andric } 207ff0cc061SDimitry Andric 208ff0cc061SDimitry Andric const char *ARMTargetParser::getArchName(unsigned ArchKind) { 209ff0cc061SDimitry Andric if (ArchKind >= ARM::AK_LAST) 210ff0cc061SDimitry Andric return nullptr; 211ff0cc061SDimitry Andric return ARCHNames[ArchKind].Name; 212ff0cc061SDimitry Andric } 213ff0cc061SDimitry Andric 214ff0cc061SDimitry Andric const char *ARMTargetParser::getArchDefaultCPUName(unsigned ArchKind) { 215ff0cc061SDimitry Andric if (ArchKind >= ARM::AK_LAST) 216ff0cc061SDimitry Andric return nullptr; 217ff0cc061SDimitry Andric return ARCHNames[ArchKind].DefaultCPU; 218ff0cc061SDimitry Andric } 219ff0cc061SDimitry Andric 220ff0cc061SDimitry Andric unsigned ARMTargetParser::getArchDefaultCPUArch(unsigned ArchKind) { 221ff0cc061SDimitry Andric if (ArchKind >= ARM::AK_LAST) 222ff0cc061SDimitry Andric return ARMBuildAttrs::CPUArch::Pre_v4; 223ff0cc061SDimitry Andric return ARCHNames[ArchKind].DefaultArch; 224ff0cc061SDimitry Andric } 225ff0cc061SDimitry Andric 226ff0cc061SDimitry Andric const char *ARMTargetParser::getArchExtName(unsigned ArchExtKind) { 227ff0cc061SDimitry Andric if (ArchExtKind >= ARM::AEK_LAST) 228ff0cc061SDimitry Andric return nullptr; 229ff0cc061SDimitry Andric return ARCHExtNames[ArchExtKind].Name; 230ff0cc061SDimitry Andric } 231ff0cc061SDimitry Andric 232ff0cc061SDimitry Andric const char *ARMTargetParser::getDefaultCPU(StringRef Arch) { 233ff0cc061SDimitry Andric unsigned AK = parseArch(Arch); 234ff0cc061SDimitry Andric if (AK == ARM::AK_INVALID) 235ff0cc061SDimitry Andric return nullptr; 236ff0cc061SDimitry Andric 237ff0cc061SDimitry Andric // Look for multiple AKs to find the default for pair AK+Name. 238ff0cc061SDimitry Andric for (const auto CPU : CPUNames) { 239ff0cc061SDimitry Andric if (CPU.ArchID == AK && CPU.Default) 240ff0cc061SDimitry Andric return CPU.Name; 241ff0cc061SDimitry Andric } 242ff0cc061SDimitry Andric return nullptr; 243ff0cc061SDimitry Andric } 244ff0cc061SDimitry Andric 245ff0cc061SDimitry Andric // ======================================================= // 246ff0cc061SDimitry Andric // Parsers 247ff0cc061SDimitry Andric // ======================================================= // 248ff0cc061SDimitry Andric 249ff0cc061SDimitry Andric StringRef ARMTargetParser::getFPUSynonym(StringRef FPU) { 250ff0cc061SDimitry Andric return StringSwitch<StringRef>(FPU) 251ff0cc061SDimitry Andric .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 252ff0cc061SDimitry Andric .Case("vfp2", "vfpv2") 253ff0cc061SDimitry Andric .Case("vfp3", "vfpv3") 254ff0cc061SDimitry Andric .Case("vfp4", "vfpv4") 255ff0cc061SDimitry Andric .Case("vfp3-d16", "vfpv3-d16") 256ff0cc061SDimitry Andric .Case("vfp4-d16", "vfpv4-d16") 257ff0cc061SDimitry Andric // FIXME: sp-16 is NOT the same as d16 258ff0cc061SDimitry Andric .Cases("fp4-sp-d16", "fpv4-sp-d16", "vfpv4-d16") 259ff0cc061SDimitry Andric .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 260ff0cc061SDimitry Andric .Cases("fp5-sp-d16", "fpv5-sp-d16", "fpv5-d16") 261ff0cc061SDimitry Andric .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 262ff0cc061SDimitry Andric // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 263ff0cc061SDimitry Andric .Case("neon-vfpv3", "neon") 264ff0cc061SDimitry Andric .Default(FPU); 265ff0cc061SDimitry Andric } 266ff0cc061SDimitry Andric 267ff0cc061SDimitry Andric StringRef ARMTargetParser::getArchSynonym(StringRef Arch) { 268ff0cc061SDimitry Andric return StringSwitch<StringRef>(Arch) 269ff0cc061SDimitry Andric .Cases("armv6m", "v6m", "armv6-m") 270ff0cc061SDimitry Andric .Cases("armv7a", "v7a", "armv7-a") 271ff0cc061SDimitry Andric .Cases("armv7r", "v7r", "armv7-r") 272ff0cc061SDimitry Andric .Cases("armv7m", "v7m", "armv7-m") 273ff0cc061SDimitry Andric .Cases("armv7em", "v7em", "armv7e-m") 274ff0cc061SDimitry Andric .Cases("armv8", "v8", "armv8-a") 275ff0cc061SDimitry Andric .Cases("armv8a", "v8a", "armv8-a") 276ff0cc061SDimitry Andric .Cases("armv8.1a", "v8.1a", "armv8.1-a") 277ff0cc061SDimitry Andric .Cases("aarch64", "arm64", "armv8-a") 278ff0cc061SDimitry Andric .Default(Arch); 279ff0cc061SDimitry Andric } 280ff0cc061SDimitry Andric 281ff0cc061SDimitry Andric // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but 282ff0cc061SDimitry Andric // (iwmmxt|xscale)(eb)? is also permitted. If the former, return 283ff0cc061SDimitry Andric // "v.+", if the latter, return unmodified string, minus 'eb'. 284ff0cc061SDimitry Andric // If invalid, return empty string. 285ff0cc061SDimitry Andric StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) { 286ff0cc061SDimitry Andric size_t offset = StringRef::npos; 287ff0cc061SDimitry Andric StringRef A = Arch; 288ff0cc061SDimitry Andric StringRef Error = ""; 289ff0cc061SDimitry Andric 290ff0cc061SDimitry Andric // Begins with "arm" / "thumb", move past it. 291ff0cc061SDimitry Andric if (A.startswith("arm64")) 292ff0cc061SDimitry Andric offset = 5; 293ff0cc061SDimitry Andric else if (A.startswith("arm")) 294ff0cc061SDimitry Andric offset = 3; 295ff0cc061SDimitry Andric else if (A.startswith("thumb")) 296ff0cc061SDimitry Andric offset = 5; 297ff0cc061SDimitry Andric else if (A.startswith("aarch64")) { 298ff0cc061SDimitry Andric offset = 7; 299ff0cc061SDimitry Andric // AArch64 uses "_be", not "eb" suffix. 300ff0cc061SDimitry Andric if (A.find("eb") != StringRef::npos) 301ff0cc061SDimitry Andric return Error; 302ff0cc061SDimitry Andric if (A.substr(offset,3) == "_be") 303ff0cc061SDimitry Andric offset += 3; 304ff0cc061SDimitry Andric } 305ff0cc061SDimitry Andric 306ff0cc061SDimitry Andric // Ex. "armebv7", move past the "eb". 307ff0cc061SDimitry Andric if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 308ff0cc061SDimitry Andric offset += 2; 309ff0cc061SDimitry Andric // Or, if it ends with eb ("armv7eb"), chop it off. 310ff0cc061SDimitry Andric else if (A.endswith("eb")) 311ff0cc061SDimitry Andric A = A.substr(0, A.size() - 2); 312ff0cc061SDimitry Andric // Trim the head 313ff0cc061SDimitry Andric if (offset != StringRef::npos) 314ff0cc061SDimitry Andric A = A.substr(offset); 315ff0cc061SDimitry Andric 316ff0cc061SDimitry Andric // Empty string means offset reached the end, which means it's valid. 317ff0cc061SDimitry Andric if (A.empty()) 318ff0cc061SDimitry Andric return Arch; 319ff0cc061SDimitry Andric 320ff0cc061SDimitry Andric // Only match non-marketing names 321ff0cc061SDimitry Andric if (offset != StringRef::npos) { 322ff0cc061SDimitry Andric // Must start with 'vN'. 323ff0cc061SDimitry Andric if (A[0] != 'v' || !std::isdigit(A[1])) 324ff0cc061SDimitry Andric return Error; 325ff0cc061SDimitry Andric // Can't have an extra 'eb'. 326ff0cc061SDimitry Andric if (A.find("eb") != StringRef::npos) 327ff0cc061SDimitry Andric return Error; 328ff0cc061SDimitry Andric } 329ff0cc061SDimitry Andric 330ff0cc061SDimitry Andric // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 331ff0cc061SDimitry Andric return A; 332ff0cc061SDimitry Andric } 333ff0cc061SDimitry Andric 334ff0cc061SDimitry Andric unsigned ARMTargetParser::parseFPU(StringRef FPU) { 335ff0cc061SDimitry Andric StringRef Syn = getFPUSynonym(FPU); 336ff0cc061SDimitry Andric for (const auto F : FPUNames) { 337ff0cc061SDimitry Andric if (Syn == F.Name) 338ff0cc061SDimitry Andric return F.ID; 339ff0cc061SDimitry Andric } 340ff0cc061SDimitry Andric return ARM::FK_INVALID; 341ff0cc061SDimitry Andric } 342ff0cc061SDimitry Andric 343ff0cc061SDimitry Andric // Allows partial match, ex. "v7a" matches "armv7a". 344ff0cc061SDimitry Andric unsigned ARMTargetParser::parseArch(StringRef Arch) { 345ff0cc061SDimitry Andric StringRef Syn = getArchSynonym(Arch); 346ff0cc061SDimitry Andric for (const auto A : ARCHNames) { 347ff0cc061SDimitry Andric if (StringRef(A.Name).endswith(Syn)) 348ff0cc061SDimitry Andric return A.ID; 349ff0cc061SDimitry Andric } 350ff0cc061SDimitry Andric return ARM::AK_INVALID; 351ff0cc061SDimitry Andric } 352ff0cc061SDimitry Andric 353ff0cc061SDimitry Andric unsigned ARMTargetParser::parseArchExt(StringRef ArchExt) { 354ff0cc061SDimitry Andric for (const auto A : ARCHExtNames) { 355ff0cc061SDimitry Andric if (ArchExt == A.Name) 356ff0cc061SDimitry Andric return A.ID; 357ff0cc061SDimitry Andric } 358ff0cc061SDimitry Andric return ARM::AEK_INVALID; 359ff0cc061SDimitry Andric } 360ff0cc061SDimitry Andric 361ff0cc061SDimitry Andric unsigned ARMTargetParser::parseCPUArch(StringRef CPU) { 362ff0cc061SDimitry Andric for (const auto C : CPUNames) { 363ff0cc061SDimitry Andric if (CPU == C.Name) 364ff0cc061SDimitry Andric return C.ArchID; 365ff0cc061SDimitry Andric } 366ff0cc061SDimitry Andric return ARM::AK_INVALID; 367ff0cc061SDimitry Andric } 368ff0cc061SDimitry Andric 369ff0cc061SDimitry Andric // ARM, Thumb, AArch64 370ff0cc061SDimitry Andric unsigned ARMTargetParser::parseArchISA(StringRef Arch) { 371ff0cc061SDimitry Andric return StringSwitch<unsigned>(Arch) 372ff0cc061SDimitry Andric .StartsWith("aarch64", ARM::IK_AARCH64) 373ff0cc061SDimitry Andric .StartsWith("arm64", ARM::IK_AARCH64) 374ff0cc061SDimitry Andric .StartsWith("thumb", ARM::IK_THUMB) 375ff0cc061SDimitry Andric .StartsWith("arm", ARM::IK_ARM) 376ff0cc061SDimitry Andric .Default(ARM::EK_INVALID); 377ff0cc061SDimitry Andric } 378ff0cc061SDimitry Andric 379ff0cc061SDimitry Andric // Little/Big endian 380ff0cc061SDimitry Andric unsigned ARMTargetParser::parseArchEndian(StringRef Arch) { 381ff0cc061SDimitry Andric if (Arch.startswith("armeb") || 382ff0cc061SDimitry Andric Arch.startswith("thumbeb") || 383ff0cc061SDimitry Andric Arch.startswith("aarch64_be")) 384ff0cc061SDimitry Andric return ARM::EK_BIG; 385ff0cc061SDimitry Andric 386ff0cc061SDimitry Andric if (Arch.startswith("arm") || Arch.startswith("thumb")) { 387ff0cc061SDimitry Andric if (Arch.endswith("eb")) 388ff0cc061SDimitry Andric return ARM::EK_BIG; 389ff0cc061SDimitry Andric else 390ff0cc061SDimitry Andric return ARM::EK_LITTLE; 391ff0cc061SDimitry Andric } 392ff0cc061SDimitry Andric 393ff0cc061SDimitry Andric if (Arch.startswith("aarch64")) 394ff0cc061SDimitry Andric return ARM::EK_LITTLE; 395ff0cc061SDimitry Andric 396ff0cc061SDimitry Andric return ARM::EK_INVALID; 397ff0cc061SDimitry Andric } 398ff0cc061SDimitry Andric 399ff0cc061SDimitry Andric // Profile A/R/M 400ff0cc061SDimitry Andric unsigned ARMTargetParser::parseArchProfile(StringRef Arch) { 401ff0cc061SDimitry Andric Arch = getCanonicalArchName(Arch); 402ff0cc061SDimitry Andric switch(parseArch(Arch)) { 403ff0cc061SDimitry Andric case ARM::AK_ARMV6M: 404ff0cc061SDimitry Andric case ARM::AK_ARMV7M: 405ff0cc061SDimitry Andric case ARM::AK_ARMV6SM: 406ff0cc061SDimitry Andric case ARM::AK_ARMV7EM: 407ff0cc061SDimitry Andric return ARM::PK_M; 408ff0cc061SDimitry Andric case ARM::AK_ARMV7R: 409ff0cc061SDimitry Andric return ARM::PK_R; 410ff0cc061SDimitry Andric case ARM::AK_ARMV7: 411ff0cc061SDimitry Andric case ARM::AK_ARMV7A: 412ff0cc061SDimitry Andric case ARM::AK_ARMV8A: 413ff0cc061SDimitry Andric case ARM::AK_ARMV8_1A: 414ff0cc061SDimitry Andric return ARM::PK_A; 415ff0cc061SDimitry Andric } 416ff0cc061SDimitry Andric return ARM::PK_INVALID; 417ff0cc061SDimitry Andric } 418ff0cc061SDimitry Andric 419ff0cc061SDimitry Andric // Version number (ex. v7 = 7). 420ff0cc061SDimitry Andric unsigned ARMTargetParser::parseArchVersion(StringRef Arch) { 421ff0cc061SDimitry Andric Arch = getCanonicalArchName(Arch); 422ff0cc061SDimitry Andric switch(parseArch(Arch)) { 423ff0cc061SDimitry Andric case ARM::AK_ARMV2: 424ff0cc061SDimitry Andric case ARM::AK_ARMV2A: 425ff0cc061SDimitry Andric return 2; 426ff0cc061SDimitry Andric case ARM::AK_ARMV3: 427ff0cc061SDimitry Andric case ARM::AK_ARMV3M: 428ff0cc061SDimitry Andric return 3; 429ff0cc061SDimitry Andric case ARM::AK_ARMV4: 430ff0cc061SDimitry Andric case ARM::AK_ARMV4T: 431ff0cc061SDimitry Andric return 4; 432ff0cc061SDimitry Andric case ARM::AK_ARMV5: 433ff0cc061SDimitry Andric case ARM::AK_ARMV5T: 434ff0cc061SDimitry Andric case ARM::AK_ARMV5TE: 435ff0cc061SDimitry Andric case ARM::AK_IWMMXT: 436ff0cc061SDimitry Andric case ARM::AK_IWMMXT2: 437ff0cc061SDimitry Andric case ARM::AK_XSCALE: 438ff0cc061SDimitry Andric case ARM::AK_ARMV5E: 439ff0cc061SDimitry Andric case ARM::AK_ARMV5TEJ: 440ff0cc061SDimitry Andric return 5; 441ff0cc061SDimitry Andric case ARM::AK_ARMV6: 442ff0cc061SDimitry Andric case ARM::AK_ARMV6J: 443ff0cc061SDimitry Andric case ARM::AK_ARMV6K: 444ff0cc061SDimitry Andric case ARM::AK_ARMV6T2: 445ff0cc061SDimitry Andric case ARM::AK_ARMV6Z: 446ff0cc061SDimitry Andric case ARM::AK_ARMV6ZK: 447ff0cc061SDimitry Andric case ARM::AK_ARMV6M: 448ff0cc061SDimitry Andric case ARM::AK_ARMV6SM: 449ff0cc061SDimitry Andric case ARM::AK_ARMV6HL: 450ff0cc061SDimitry Andric return 6; 451ff0cc061SDimitry Andric case ARM::AK_ARMV7: 452ff0cc061SDimitry Andric case ARM::AK_ARMV7A: 453ff0cc061SDimitry Andric case ARM::AK_ARMV7R: 454ff0cc061SDimitry Andric case ARM::AK_ARMV7M: 455ff0cc061SDimitry Andric case ARM::AK_ARMV7L: 456ff0cc061SDimitry Andric case ARM::AK_ARMV7HL: 457ff0cc061SDimitry Andric case ARM::AK_ARMV7S: 458ff0cc061SDimitry Andric case ARM::AK_ARMV7EM: 459ff0cc061SDimitry Andric return 7; 460ff0cc061SDimitry Andric case ARM::AK_ARMV8A: 461ff0cc061SDimitry Andric case ARM::AK_ARMV8_1A: 462ff0cc061SDimitry Andric return 8; 463ff0cc061SDimitry Andric } 464ff0cc061SDimitry Andric return 0; 465ff0cc061SDimitry Andric } 466ff0cc061SDimitry Andric 467ff0cc061SDimitry Andric } // namespace llvm 468