1bdd1243dSDimitry Andric //===-- Host.cpp - Implement OS Host Detection ------------------*- 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 the operating system Host detection. 10bdd1243dSDimitry Andric // 11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 12bdd1243dSDimitry Andric 13bdd1243dSDimitry Andric #include "llvm/TargetParser/Host.h" 14bdd1243dSDimitry Andric #include "llvm/ADT/SmallVector.h" 15bdd1243dSDimitry Andric #include "llvm/ADT/StringMap.h" 16bdd1243dSDimitry Andric #include "llvm/ADT/StringRef.h" 17bdd1243dSDimitry Andric #include "llvm/ADT/StringSwitch.h" 18bdd1243dSDimitry Andric #include "llvm/Config/llvm-config.h" 19bdd1243dSDimitry Andric #include "llvm/Support/MemoryBuffer.h" 20bdd1243dSDimitry Andric #include "llvm/Support/raw_ostream.h" 21bdd1243dSDimitry Andric #include "llvm/TargetParser/Triple.h" 22bdd1243dSDimitry Andric #include "llvm/TargetParser/X86TargetParser.h" 23bdd1243dSDimitry Andric #include <string.h> 24bdd1243dSDimitry Andric 25bdd1243dSDimitry Andric // Include the platform-specific parts of this class. 26bdd1243dSDimitry Andric #ifdef LLVM_ON_UNIX 27bdd1243dSDimitry Andric #include "Unix/Host.inc" 28bdd1243dSDimitry Andric #include <sched.h> 29bdd1243dSDimitry Andric #endif 30bdd1243dSDimitry Andric #ifdef _WIN32 31bdd1243dSDimitry Andric #include "Windows/Host.inc" 32bdd1243dSDimitry Andric #endif 33bdd1243dSDimitry Andric #ifdef _MSC_VER 34bdd1243dSDimitry Andric #include <intrin.h> 35bdd1243dSDimitry Andric #endif 36bdd1243dSDimitry Andric #ifdef __MVS__ 37bdd1243dSDimitry Andric #include "llvm/Support/BCD.h" 38bdd1243dSDimitry Andric #endif 39bdd1243dSDimitry Andric #if defined(__APPLE__) 40bdd1243dSDimitry Andric #include <mach/host_info.h> 41bdd1243dSDimitry Andric #include <mach/mach.h> 42bdd1243dSDimitry Andric #include <mach/mach_host.h> 43bdd1243dSDimitry Andric #include <mach/machine.h> 44bdd1243dSDimitry Andric #include <sys/param.h> 45bdd1243dSDimitry Andric #include <sys/sysctl.h> 46bdd1243dSDimitry Andric #endif 47bdd1243dSDimitry Andric #ifdef _AIX 48bdd1243dSDimitry Andric #include <sys/systemcfg.h> 49bdd1243dSDimitry Andric #endif 50bdd1243dSDimitry Andric #if defined(__sun__) && defined(__svr4__) 51bdd1243dSDimitry Andric #include <kstat.h> 52bdd1243dSDimitry Andric #endif 53bdd1243dSDimitry Andric 54bdd1243dSDimitry Andric #define DEBUG_TYPE "host-detection" 55bdd1243dSDimitry Andric 56bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 57bdd1243dSDimitry Andric // 58bdd1243dSDimitry Andric // Implementations of the CPU detection routines 59bdd1243dSDimitry Andric // 60bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 61bdd1243dSDimitry Andric 62bdd1243dSDimitry Andric using namespace llvm; 63bdd1243dSDimitry Andric 64bdd1243dSDimitry Andric static std::unique_ptr<llvm::MemoryBuffer> 65bdd1243dSDimitry Andric LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() { 66bdd1243dSDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 67bdd1243dSDimitry Andric llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); 68bdd1243dSDimitry Andric if (std::error_code EC = Text.getError()) { 69bdd1243dSDimitry Andric llvm::errs() << "Can't read " 70bdd1243dSDimitry Andric << "/proc/cpuinfo: " << EC.message() << "\n"; 71bdd1243dSDimitry Andric return nullptr; 72bdd1243dSDimitry Andric } 73bdd1243dSDimitry Andric return std::move(*Text); 74bdd1243dSDimitry Andric } 75bdd1243dSDimitry Andric 76bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) { 77bdd1243dSDimitry Andric // Access to the Processor Version Register (PVR) on PowerPC is privileged, 78bdd1243dSDimitry Andric // and so we must use an operating-system interface to determine the current 79bdd1243dSDimitry Andric // processor type. On Linux, this is exposed through the /proc/cpuinfo file. 80bdd1243dSDimitry Andric const char *generic = "generic"; 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric // The cpu line is second (after the 'processor: 0' line), so if this 83bdd1243dSDimitry Andric // buffer is too small then something has changed (or is wrong). 84bdd1243dSDimitry Andric StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin(); 85bdd1243dSDimitry Andric StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end(); 86bdd1243dSDimitry Andric 87bdd1243dSDimitry Andric StringRef::const_iterator CIP = CPUInfoStart; 88bdd1243dSDimitry Andric 89bdd1243dSDimitry Andric StringRef::const_iterator CPUStart = nullptr; 90bdd1243dSDimitry Andric size_t CPULen = 0; 91bdd1243dSDimitry Andric 92bdd1243dSDimitry Andric // We need to find the first line which starts with cpu, spaces, and a colon. 93bdd1243dSDimitry Andric // After the colon, there may be some additional spaces and then the cpu type. 94bdd1243dSDimitry Andric while (CIP < CPUInfoEnd && CPUStart == nullptr) { 95bdd1243dSDimitry Andric if (CIP < CPUInfoEnd && *CIP == '\n') 96bdd1243dSDimitry Andric ++CIP; 97bdd1243dSDimitry Andric 98bdd1243dSDimitry Andric if (CIP < CPUInfoEnd && *CIP == 'c') { 99bdd1243dSDimitry Andric ++CIP; 100bdd1243dSDimitry Andric if (CIP < CPUInfoEnd && *CIP == 'p') { 101bdd1243dSDimitry Andric ++CIP; 102bdd1243dSDimitry Andric if (CIP < CPUInfoEnd && *CIP == 'u') { 103bdd1243dSDimitry Andric ++CIP; 104bdd1243dSDimitry Andric while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) 105bdd1243dSDimitry Andric ++CIP; 106bdd1243dSDimitry Andric 107bdd1243dSDimitry Andric if (CIP < CPUInfoEnd && *CIP == ':') { 108bdd1243dSDimitry Andric ++CIP; 109bdd1243dSDimitry Andric while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) 110bdd1243dSDimitry Andric ++CIP; 111bdd1243dSDimitry Andric 112bdd1243dSDimitry Andric if (CIP < CPUInfoEnd) { 113bdd1243dSDimitry Andric CPUStart = CIP; 114bdd1243dSDimitry Andric while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' && 115bdd1243dSDimitry Andric *CIP != ',' && *CIP != '\n')) 116bdd1243dSDimitry Andric ++CIP; 117bdd1243dSDimitry Andric CPULen = CIP - CPUStart; 118bdd1243dSDimitry Andric } 119bdd1243dSDimitry Andric } 120bdd1243dSDimitry Andric } 121bdd1243dSDimitry Andric } 122bdd1243dSDimitry Andric } 123bdd1243dSDimitry Andric 124bdd1243dSDimitry Andric if (CPUStart == nullptr) 125bdd1243dSDimitry Andric while (CIP < CPUInfoEnd && *CIP != '\n') 126bdd1243dSDimitry Andric ++CIP; 127bdd1243dSDimitry Andric } 128bdd1243dSDimitry Andric 129bdd1243dSDimitry Andric if (CPUStart == nullptr) 130bdd1243dSDimitry Andric return generic; 131bdd1243dSDimitry Andric 132bdd1243dSDimitry Andric return StringSwitch<const char *>(StringRef(CPUStart, CPULen)) 133bdd1243dSDimitry Andric .Case("604e", "604e") 134bdd1243dSDimitry Andric .Case("604", "604") 135bdd1243dSDimitry Andric .Case("7400", "7400") 136bdd1243dSDimitry Andric .Case("7410", "7400") 137bdd1243dSDimitry Andric .Case("7447", "7400") 138bdd1243dSDimitry Andric .Case("7455", "7450") 139bdd1243dSDimitry Andric .Case("G4", "g4") 140bdd1243dSDimitry Andric .Case("POWER4", "970") 141bdd1243dSDimitry Andric .Case("PPC970FX", "970") 142bdd1243dSDimitry Andric .Case("PPC970MP", "970") 143bdd1243dSDimitry Andric .Case("G5", "g5") 144bdd1243dSDimitry Andric .Case("POWER5", "g5") 145bdd1243dSDimitry Andric .Case("A2", "a2") 146bdd1243dSDimitry Andric .Case("POWER6", "pwr6") 147bdd1243dSDimitry Andric .Case("POWER7", "pwr7") 148bdd1243dSDimitry Andric .Case("POWER8", "pwr8") 149bdd1243dSDimitry Andric .Case("POWER8E", "pwr8") 150bdd1243dSDimitry Andric .Case("POWER8NVL", "pwr8") 151bdd1243dSDimitry Andric .Case("POWER9", "pwr9") 152bdd1243dSDimitry Andric .Case("POWER10", "pwr10") 153bdd1243dSDimitry Andric // FIXME: If we get a simulator or machine with the capabilities of 154bdd1243dSDimitry Andric // mcpu=future, we should revisit this and add the name reported by the 155bdd1243dSDimitry Andric // simulator/machine. 156bdd1243dSDimitry Andric .Default(generic); 157bdd1243dSDimitry Andric } 158bdd1243dSDimitry Andric 159bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) { 160bdd1243dSDimitry Andric // The cpuid register on arm is not accessible from user space. On Linux, 161bdd1243dSDimitry Andric // it is exposed through the /proc/cpuinfo file. 162bdd1243dSDimitry Andric 163bdd1243dSDimitry Andric // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line 164bdd1243dSDimitry Andric // in all cases. 165bdd1243dSDimitry Andric SmallVector<StringRef, 32> Lines; 166bdd1243dSDimitry Andric ProcCpuinfoContent.split(Lines, "\n"); 167bdd1243dSDimitry Andric 168bdd1243dSDimitry Andric // Look for the CPU implementer line. 169bdd1243dSDimitry Andric StringRef Implementer; 170bdd1243dSDimitry Andric StringRef Hardware; 171bdd1243dSDimitry Andric StringRef Part; 172bdd1243dSDimitry Andric for (unsigned I = 0, E = Lines.size(); I != E; ++I) { 1735f757f3fSDimitry Andric if (Lines[I].starts_with("CPU implementer")) 174bdd1243dSDimitry Andric Implementer = Lines[I].substr(15).ltrim("\t :"); 1755f757f3fSDimitry Andric if (Lines[I].starts_with("Hardware")) 176bdd1243dSDimitry Andric Hardware = Lines[I].substr(8).ltrim("\t :"); 1775f757f3fSDimitry Andric if (Lines[I].starts_with("CPU part")) 178bdd1243dSDimitry Andric Part = Lines[I].substr(8).ltrim("\t :"); 179bdd1243dSDimitry Andric } 180bdd1243dSDimitry Andric 181bdd1243dSDimitry Andric if (Implementer == "0x41") { // ARM Ltd. 182bdd1243dSDimitry Andric // MSM8992/8994 may give cpu part for the core that the kernel is running on, 183bdd1243dSDimitry Andric // which is undeterministic and wrong. Always return cortex-a53 for these SoC. 1845f757f3fSDimitry Andric if (Hardware.ends_with("MSM8994") || Hardware.ends_with("MSM8996")) 185bdd1243dSDimitry Andric return "cortex-a53"; 186bdd1243dSDimitry Andric 187bdd1243dSDimitry Andric 188bdd1243dSDimitry Andric // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The 189bdd1243dSDimitry Andric // values correspond to the "Part number" in the CP15/c0 register. The 190bdd1243dSDimitry Andric // contents are specified in the various processor manuals. 191bdd1243dSDimitry Andric // This corresponds to the Main ID Register in Technical Reference Manuals. 192bdd1243dSDimitry Andric // and is used in programs like sys-utils 193bdd1243dSDimitry Andric return StringSwitch<const char *>(Part) 194bdd1243dSDimitry Andric .Case("0x926", "arm926ej-s") 195bdd1243dSDimitry Andric .Case("0xb02", "mpcore") 196bdd1243dSDimitry Andric .Case("0xb36", "arm1136j-s") 197bdd1243dSDimitry Andric .Case("0xb56", "arm1156t2-s") 198bdd1243dSDimitry Andric .Case("0xb76", "arm1176jz-s") 199*0fca6ea1SDimitry Andric .Case("0xc05", "cortex-a5") 200*0fca6ea1SDimitry Andric .Case("0xc07", "cortex-a7") 201bdd1243dSDimitry Andric .Case("0xc08", "cortex-a8") 202bdd1243dSDimitry Andric .Case("0xc09", "cortex-a9") 203bdd1243dSDimitry Andric .Case("0xc0f", "cortex-a15") 204*0fca6ea1SDimitry Andric .Case("0xc0e", "cortex-a17") 205bdd1243dSDimitry Andric .Case("0xc20", "cortex-m0") 206bdd1243dSDimitry Andric .Case("0xc23", "cortex-m3") 207bdd1243dSDimitry Andric .Case("0xc24", "cortex-m4") 208*0fca6ea1SDimitry Andric .Case("0xc27", "cortex-m7") 209*0fca6ea1SDimitry Andric .Case("0xd20", "cortex-m23") 210*0fca6ea1SDimitry Andric .Case("0xd21", "cortex-m33") 2115f757f3fSDimitry Andric .Case("0xd24", "cortex-m52") 212bdd1243dSDimitry Andric .Case("0xd22", "cortex-m55") 213*0fca6ea1SDimitry Andric .Case("0xd23", "cortex-m85") 214*0fca6ea1SDimitry Andric .Case("0xc18", "cortex-r8") 215*0fca6ea1SDimitry Andric .Case("0xd13", "cortex-r52") 216*0fca6ea1SDimitry Andric .Case("0xd16", "cortex-r52plus") 217*0fca6ea1SDimitry Andric .Case("0xd15", "cortex-r82") 218*0fca6ea1SDimitry Andric .Case("0xd14", "cortex-r82ae") 219bdd1243dSDimitry Andric .Case("0xd02", "cortex-a34") 220bdd1243dSDimitry Andric .Case("0xd04", "cortex-a35") 221bdd1243dSDimitry Andric .Case("0xd03", "cortex-a53") 222bdd1243dSDimitry Andric .Case("0xd05", "cortex-a55") 223bdd1243dSDimitry Andric .Case("0xd46", "cortex-a510") 2245f757f3fSDimitry Andric .Case("0xd80", "cortex-a520") 225*0fca6ea1SDimitry Andric .Case("0xd88", "cortex-a520ae") 226bdd1243dSDimitry Andric .Case("0xd07", "cortex-a57") 227*0fca6ea1SDimitry Andric .Case("0xd06", "cortex-a65") 228*0fca6ea1SDimitry Andric .Case("0xd43", "cortex-a65ae") 229bdd1243dSDimitry Andric .Case("0xd08", "cortex-a72") 230bdd1243dSDimitry Andric .Case("0xd09", "cortex-a73") 231bdd1243dSDimitry Andric .Case("0xd0a", "cortex-a75") 232bdd1243dSDimitry Andric .Case("0xd0b", "cortex-a76") 233*0fca6ea1SDimitry Andric .Case("0xd0e", "cortex-a76ae") 234bdd1243dSDimitry Andric .Case("0xd0d", "cortex-a77") 235bdd1243dSDimitry Andric .Case("0xd41", "cortex-a78") 236*0fca6ea1SDimitry Andric .Case("0xd42", "cortex-a78ae") 237*0fca6ea1SDimitry Andric .Case("0xd4b", "cortex-a78c") 238bdd1243dSDimitry Andric .Case("0xd47", "cortex-a710") 239bdd1243dSDimitry Andric .Case("0xd4d", "cortex-a715") 2405f757f3fSDimitry Andric .Case("0xd81", "cortex-a720") 241*0fca6ea1SDimitry Andric .Case("0xd89", "cortex-a720ae") 242*0fca6ea1SDimitry Andric .Case("0xd87", "cortex-a725") 243bdd1243dSDimitry Andric .Case("0xd44", "cortex-x1") 244bdd1243dSDimitry Andric .Case("0xd4c", "cortex-x1c") 245bdd1243dSDimitry Andric .Case("0xd48", "cortex-x2") 246bdd1243dSDimitry Andric .Case("0xd4e", "cortex-x3") 2475f757f3fSDimitry Andric .Case("0xd82", "cortex-x4") 248*0fca6ea1SDimitry Andric .Case("0xd85", "cortex-x925") 249*0fca6ea1SDimitry Andric .Case("0xd4a", "neoverse-e1") 250bdd1243dSDimitry Andric .Case("0xd0c", "neoverse-n1") 251bdd1243dSDimitry Andric .Case("0xd49", "neoverse-n2") 252*0fca6ea1SDimitry Andric .Case("0xd8e", "neoverse-n3") 253bdd1243dSDimitry Andric .Case("0xd40", "neoverse-v1") 254bdd1243dSDimitry Andric .Case("0xd4f", "neoverse-v2") 255*0fca6ea1SDimitry Andric .Case("0xd84", "neoverse-v3") 256*0fca6ea1SDimitry Andric .Case("0xd83", "neoverse-v3ae") 257bdd1243dSDimitry Andric .Default("generic"); 258bdd1243dSDimitry Andric } 259bdd1243dSDimitry Andric 260bdd1243dSDimitry Andric if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium. 261bdd1243dSDimitry Andric return StringSwitch<const char *>(Part) 262bdd1243dSDimitry Andric .Case("0x516", "thunderx2t99") 263bdd1243dSDimitry Andric .Case("0x0516", "thunderx2t99") 264bdd1243dSDimitry Andric .Case("0xaf", "thunderx2t99") 265bdd1243dSDimitry Andric .Case("0x0af", "thunderx2t99") 266bdd1243dSDimitry Andric .Case("0xa1", "thunderxt88") 267bdd1243dSDimitry Andric .Case("0x0a1", "thunderxt88") 268bdd1243dSDimitry Andric .Default("generic"); 269bdd1243dSDimitry Andric } 270bdd1243dSDimitry Andric 271bdd1243dSDimitry Andric if (Implementer == "0x46") { // Fujitsu Ltd. 272bdd1243dSDimitry Andric return StringSwitch<const char *>(Part) 273bdd1243dSDimitry Andric .Case("0x001", "a64fx") 274bdd1243dSDimitry Andric .Default("generic"); 275bdd1243dSDimitry Andric } 276bdd1243dSDimitry Andric 277bdd1243dSDimitry Andric if (Implementer == "0x4e") { // NVIDIA Corporation 278bdd1243dSDimitry Andric return StringSwitch<const char *>(Part) 279bdd1243dSDimitry Andric .Case("0x004", "carmel") 280bdd1243dSDimitry Andric .Default("generic"); 281bdd1243dSDimitry Andric } 282bdd1243dSDimitry Andric 283bdd1243dSDimitry Andric if (Implementer == "0x48") // HiSilicon Technologies, Inc. 284bdd1243dSDimitry Andric // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The 285bdd1243dSDimitry Andric // values correspond to the "Part number" in the CP15/c0 register. The 286bdd1243dSDimitry Andric // contents are specified in the various processor manuals. 287bdd1243dSDimitry Andric return StringSwitch<const char *>(Part) 288bdd1243dSDimitry Andric .Case("0xd01", "tsv110") 289bdd1243dSDimitry Andric .Default("generic"); 290bdd1243dSDimitry Andric 291bdd1243dSDimitry Andric if (Implementer == "0x51") // Qualcomm Technologies, Inc. 292bdd1243dSDimitry Andric // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The 293bdd1243dSDimitry Andric // values correspond to the "Part number" in the CP15/c0 register. The 294bdd1243dSDimitry Andric // contents are specified in the various processor manuals. 295bdd1243dSDimitry Andric return StringSwitch<const char *>(Part) 296bdd1243dSDimitry Andric .Case("0x06f", "krait") // APQ8064 297bdd1243dSDimitry Andric .Case("0x201", "kryo") 298bdd1243dSDimitry Andric .Case("0x205", "kryo") 299bdd1243dSDimitry Andric .Case("0x211", "kryo") 300bdd1243dSDimitry Andric .Case("0x800", "cortex-a73") // Kryo 2xx Gold 301bdd1243dSDimitry Andric .Case("0x801", "cortex-a73") // Kryo 2xx Silver 302bdd1243dSDimitry Andric .Case("0x802", "cortex-a75") // Kryo 3xx Gold 303bdd1243dSDimitry Andric .Case("0x803", "cortex-a75") // Kryo 3xx Silver 304bdd1243dSDimitry Andric .Case("0x804", "cortex-a76") // Kryo 4xx Gold 305bdd1243dSDimitry Andric .Case("0x805", "cortex-a76") // Kryo 4xx/5xx Silver 306bdd1243dSDimitry Andric .Case("0xc00", "falkor") 307bdd1243dSDimitry Andric .Case("0xc01", "saphira") 308*0fca6ea1SDimitry Andric .Case("0x001", "oryon-1") 309bdd1243dSDimitry Andric .Default("generic"); 310bdd1243dSDimitry Andric if (Implementer == "0x53") { // Samsung Electronics Co., Ltd. 311bdd1243dSDimitry Andric // The Exynos chips have a convoluted ID scheme that doesn't seem to follow 312bdd1243dSDimitry Andric // any predictive pattern across variants and parts. 313bdd1243dSDimitry Andric unsigned Variant = 0, Part = 0; 314bdd1243dSDimitry Andric 315bdd1243dSDimitry Andric // Look for the CPU variant line, whose value is a 1 digit hexadecimal 316bdd1243dSDimitry Andric // number, corresponding to the Variant bits in the CP15/C0 register. 317bdd1243dSDimitry Andric for (auto I : Lines) 318bdd1243dSDimitry Andric if (I.consume_front("CPU variant")) 319bdd1243dSDimitry Andric I.ltrim("\t :").getAsInteger(0, Variant); 320bdd1243dSDimitry Andric 321bdd1243dSDimitry Andric // Look for the CPU part line, whose value is a 3 digit hexadecimal 322bdd1243dSDimitry Andric // number, corresponding to the PartNum bits in the CP15/C0 register. 323bdd1243dSDimitry Andric for (auto I : Lines) 324bdd1243dSDimitry Andric if (I.consume_front("CPU part")) 325bdd1243dSDimitry Andric I.ltrim("\t :").getAsInteger(0, Part); 326bdd1243dSDimitry Andric 327bdd1243dSDimitry Andric unsigned Exynos = (Variant << 12) | Part; 328bdd1243dSDimitry Andric switch (Exynos) { 329bdd1243dSDimitry Andric default: 330bdd1243dSDimitry Andric // Default by falling through to Exynos M3. 331bdd1243dSDimitry Andric [[fallthrough]]; 332bdd1243dSDimitry Andric case 0x1002: 333bdd1243dSDimitry Andric return "exynos-m3"; 334bdd1243dSDimitry Andric case 0x1003: 335bdd1243dSDimitry Andric return "exynos-m4"; 336bdd1243dSDimitry Andric } 337bdd1243dSDimitry Andric } 338bdd1243dSDimitry Andric 3397a6dacacSDimitry Andric if (Implementer == "0x6d") { // Microsoft Corporation. 3407a6dacacSDimitry Andric // The Microsoft Azure Cobalt 100 CPU is handled as a Neoverse N2. 3417a6dacacSDimitry Andric return StringSwitch<const char *>(Part) 3427a6dacacSDimitry Andric .Case("0xd49", "neoverse-n2") 3437a6dacacSDimitry Andric .Default("generic"); 3447a6dacacSDimitry Andric } 3457a6dacacSDimitry Andric 346bdd1243dSDimitry Andric if (Implementer == "0xc0") { // Ampere Computing 347bdd1243dSDimitry Andric return StringSwitch<const char *>(Part) 348bdd1243dSDimitry Andric .Case("0xac3", "ampere1") 349bdd1243dSDimitry Andric .Case("0xac4", "ampere1a") 3504c2d3b02SDimitry Andric .Case("0xac5", "ampere1b") 351bdd1243dSDimitry Andric .Default("generic"); 352bdd1243dSDimitry Andric } 353bdd1243dSDimitry Andric 354bdd1243dSDimitry Andric return "generic"; 355bdd1243dSDimitry Andric } 356bdd1243dSDimitry Andric 357bdd1243dSDimitry Andric namespace { 358bdd1243dSDimitry Andric StringRef getCPUNameFromS390Model(unsigned int Id, bool HaveVectorSupport) { 359bdd1243dSDimitry Andric switch (Id) { 360bdd1243dSDimitry Andric case 2064: // z900 not supported by LLVM 361bdd1243dSDimitry Andric case 2066: 362bdd1243dSDimitry Andric case 2084: // z990 not supported by LLVM 363bdd1243dSDimitry Andric case 2086: 364bdd1243dSDimitry Andric case 2094: // z9-109 not supported by LLVM 365bdd1243dSDimitry Andric case 2096: 366bdd1243dSDimitry Andric return "generic"; 367bdd1243dSDimitry Andric case 2097: 368bdd1243dSDimitry Andric case 2098: 369bdd1243dSDimitry Andric return "z10"; 370bdd1243dSDimitry Andric case 2817: 371bdd1243dSDimitry Andric case 2818: 372bdd1243dSDimitry Andric return "z196"; 373bdd1243dSDimitry Andric case 2827: 374bdd1243dSDimitry Andric case 2828: 375bdd1243dSDimitry Andric return "zEC12"; 376bdd1243dSDimitry Andric case 2964: 377bdd1243dSDimitry Andric case 2965: 378bdd1243dSDimitry Andric return HaveVectorSupport? "z13" : "zEC12"; 379bdd1243dSDimitry Andric case 3906: 380bdd1243dSDimitry Andric case 3907: 381bdd1243dSDimitry Andric return HaveVectorSupport? "z14" : "zEC12"; 382bdd1243dSDimitry Andric case 8561: 383bdd1243dSDimitry Andric case 8562: 384bdd1243dSDimitry Andric return HaveVectorSupport? "z15" : "zEC12"; 385bdd1243dSDimitry Andric case 3931: 386bdd1243dSDimitry Andric case 3932: 387bdd1243dSDimitry Andric default: 388bdd1243dSDimitry Andric return HaveVectorSupport? "z16" : "zEC12"; 389bdd1243dSDimitry Andric } 390bdd1243dSDimitry Andric } 391bdd1243dSDimitry Andric } // end anonymous namespace 392bdd1243dSDimitry Andric 393bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) { 394bdd1243dSDimitry Andric // STIDP is a privileged operation, so use /proc/cpuinfo instead. 395bdd1243dSDimitry Andric 396bdd1243dSDimitry Andric // The "processor 0:" line comes after a fair amount of other information, 397bdd1243dSDimitry Andric // including a cache breakdown, but this should be plenty. 398bdd1243dSDimitry Andric SmallVector<StringRef, 32> Lines; 399bdd1243dSDimitry Andric ProcCpuinfoContent.split(Lines, "\n"); 400bdd1243dSDimitry Andric 401bdd1243dSDimitry Andric // Look for the CPU features. 402bdd1243dSDimitry Andric SmallVector<StringRef, 32> CPUFeatures; 403bdd1243dSDimitry Andric for (unsigned I = 0, E = Lines.size(); I != E; ++I) 4045f757f3fSDimitry Andric if (Lines[I].starts_with("features")) { 405bdd1243dSDimitry Andric size_t Pos = Lines[I].find(':'); 406bdd1243dSDimitry Andric if (Pos != StringRef::npos) { 407bdd1243dSDimitry Andric Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' '); 408bdd1243dSDimitry Andric break; 409bdd1243dSDimitry Andric } 410bdd1243dSDimitry Andric } 411bdd1243dSDimitry Andric 412bdd1243dSDimitry Andric // We need to check for the presence of vector support independently of 413bdd1243dSDimitry Andric // the machine type, since we may only use the vector register set when 414bdd1243dSDimitry Andric // supported by the kernel (and hypervisor). 415bdd1243dSDimitry Andric bool HaveVectorSupport = false; 416bdd1243dSDimitry Andric for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { 417bdd1243dSDimitry Andric if (CPUFeatures[I] == "vx") 418bdd1243dSDimitry Andric HaveVectorSupport = true; 419bdd1243dSDimitry Andric } 420bdd1243dSDimitry Andric 421bdd1243dSDimitry Andric // Now check the processor machine type. 422bdd1243dSDimitry Andric for (unsigned I = 0, E = Lines.size(); I != E; ++I) { 4235f757f3fSDimitry Andric if (Lines[I].starts_with("processor ")) { 424bdd1243dSDimitry Andric size_t Pos = Lines[I].find("machine = "); 425bdd1243dSDimitry Andric if (Pos != StringRef::npos) { 426bdd1243dSDimitry Andric Pos += sizeof("machine = ") - 1; 427bdd1243dSDimitry Andric unsigned int Id; 428bdd1243dSDimitry Andric if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) 429bdd1243dSDimitry Andric return getCPUNameFromS390Model(Id, HaveVectorSupport); 430bdd1243dSDimitry Andric } 431bdd1243dSDimitry Andric break; 432bdd1243dSDimitry Andric } 433bdd1243dSDimitry Andric } 434bdd1243dSDimitry Andric 435bdd1243dSDimitry Andric return "generic"; 436bdd1243dSDimitry Andric } 437bdd1243dSDimitry Andric 438bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForRISCV(StringRef ProcCpuinfoContent) { 439bdd1243dSDimitry Andric // There are 24 lines in /proc/cpuinfo 440bdd1243dSDimitry Andric SmallVector<StringRef> Lines; 441bdd1243dSDimitry Andric ProcCpuinfoContent.split(Lines, "\n"); 442bdd1243dSDimitry Andric 443bdd1243dSDimitry Andric // Look for uarch line to determine cpu name 444bdd1243dSDimitry Andric StringRef UArch; 445bdd1243dSDimitry Andric for (unsigned I = 0, E = Lines.size(); I != E; ++I) { 4465f757f3fSDimitry Andric if (Lines[I].starts_with("uarch")) { 447bdd1243dSDimitry Andric UArch = Lines[I].substr(5).ltrim("\t :"); 448bdd1243dSDimitry Andric break; 449bdd1243dSDimitry Andric } 450bdd1243dSDimitry Andric } 451bdd1243dSDimitry Andric 452bdd1243dSDimitry Andric return StringSwitch<const char *>(UArch) 453bdd1243dSDimitry Andric .Case("sifive,u74-mc", "sifive-u74") 454bdd1243dSDimitry Andric .Case("sifive,bullet0", "sifive-u74") 455*0fca6ea1SDimitry Andric .Default(""); 456bdd1243dSDimitry Andric } 457bdd1243dSDimitry Andric 458bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForBPF() { 459bdd1243dSDimitry Andric #if !defined(__linux__) || !defined(__x86_64__) 460bdd1243dSDimitry Andric return "generic"; 461bdd1243dSDimitry Andric #else 462bdd1243dSDimitry Andric uint8_t v3_insns[40] __attribute__ ((aligned (8))) = 463bdd1243dSDimitry Andric /* BPF_MOV64_IMM(BPF_REG_0, 0) */ 464bdd1243dSDimitry Andric { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 465bdd1243dSDimitry Andric /* BPF_MOV64_IMM(BPF_REG_2, 1) */ 466bdd1243dSDimitry Andric 0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 467bdd1243dSDimitry Andric /* BPF_JMP32_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */ 468bdd1243dSDimitry Andric 0xae, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 469bdd1243dSDimitry Andric /* BPF_MOV64_IMM(BPF_REG_0, 1) */ 470bdd1243dSDimitry Andric 0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 471bdd1243dSDimitry Andric /* BPF_EXIT_INSN() */ 472bdd1243dSDimitry Andric 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; 473bdd1243dSDimitry Andric 474bdd1243dSDimitry Andric uint8_t v2_insns[40] __attribute__ ((aligned (8))) = 475bdd1243dSDimitry Andric /* BPF_MOV64_IMM(BPF_REG_0, 0) */ 476bdd1243dSDimitry Andric { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 477bdd1243dSDimitry Andric /* BPF_MOV64_IMM(BPF_REG_2, 1) */ 478bdd1243dSDimitry Andric 0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 479bdd1243dSDimitry Andric /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */ 480bdd1243dSDimitry Andric 0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 481bdd1243dSDimitry Andric /* BPF_MOV64_IMM(BPF_REG_0, 1) */ 482bdd1243dSDimitry Andric 0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 483bdd1243dSDimitry Andric /* BPF_EXIT_INSN() */ 484bdd1243dSDimitry Andric 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; 485bdd1243dSDimitry Andric 486bdd1243dSDimitry Andric struct bpf_prog_load_attr { 487bdd1243dSDimitry Andric uint32_t prog_type; 488bdd1243dSDimitry Andric uint32_t insn_cnt; 489bdd1243dSDimitry Andric uint64_t insns; 490bdd1243dSDimitry Andric uint64_t license; 491bdd1243dSDimitry Andric uint32_t log_level; 492bdd1243dSDimitry Andric uint32_t log_size; 493bdd1243dSDimitry Andric uint64_t log_buf; 494bdd1243dSDimitry Andric uint32_t kern_version; 495bdd1243dSDimitry Andric uint32_t prog_flags; 496bdd1243dSDimitry Andric } attr = {}; 497bdd1243dSDimitry Andric attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */ 498bdd1243dSDimitry Andric attr.insn_cnt = 5; 499bdd1243dSDimitry Andric attr.insns = (uint64_t)v3_insns; 500bdd1243dSDimitry Andric attr.license = (uint64_t)"DUMMY"; 501bdd1243dSDimitry Andric 502bdd1243dSDimitry Andric int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, 503bdd1243dSDimitry Andric sizeof(attr)); 504bdd1243dSDimitry Andric if (fd >= 0) { 505bdd1243dSDimitry Andric close(fd); 506bdd1243dSDimitry Andric return "v3"; 507bdd1243dSDimitry Andric } 508bdd1243dSDimitry Andric 509bdd1243dSDimitry Andric /* Clear the whole attr in case its content changed by syscall. */ 510bdd1243dSDimitry Andric memset(&attr, 0, sizeof(attr)); 511bdd1243dSDimitry Andric attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */ 512bdd1243dSDimitry Andric attr.insn_cnt = 5; 513bdd1243dSDimitry Andric attr.insns = (uint64_t)v2_insns; 514bdd1243dSDimitry Andric attr.license = (uint64_t)"DUMMY"; 515bdd1243dSDimitry Andric fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr)); 516bdd1243dSDimitry Andric if (fd >= 0) { 517bdd1243dSDimitry Andric close(fd); 518bdd1243dSDimitry Andric return "v2"; 519bdd1243dSDimitry Andric } 520bdd1243dSDimitry Andric return "v1"; 521bdd1243dSDimitry Andric #endif 522bdd1243dSDimitry Andric } 523bdd1243dSDimitry Andric 524bdd1243dSDimitry Andric #if defined(__i386__) || defined(_M_IX86) || \ 525bdd1243dSDimitry Andric defined(__x86_64__) || defined(_M_X64) 526bdd1243dSDimitry Andric 527bdd1243dSDimitry Andric // The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max). 528bdd1243dSDimitry Andric // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID 529bdd1243dSDimitry Andric // support. Consequently, for i386, the presence of CPUID is checked first 530bdd1243dSDimitry Andric // via the corresponding eflags bit. 531bdd1243dSDimitry Andric // Removal of cpuid.h header motivated by PR30384 532bdd1243dSDimitry Andric // Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp 533bdd1243dSDimitry Andric // or test-suite, but are used in external projects e.g. libstdcxx 534bdd1243dSDimitry Andric static bool isCpuIdSupported() { 535bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__) 536bdd1243dSDimitry Andric #if defined(__i386__) 537bdd1243dSDimitry Andric int __cpuid_supported; 538bdd1243dSDimitry Andric __asm__(" pushfl\n" 539bdd1243dSDimitry Andric " popl %%eax\n" 540bdd1243dSDimitry Andric " movl %%eax,%%ecx\n" 541bdd1243dSDimitry Andric " xorl $0x00200000,%%eax\n" 542bdd1243dSDimitry Andric " pushl %%eax\n" 543bdd1243dSDimitry Andric " popfl\n" 544bdd1243dSDimitry Andric " pushfl\n" 545bdd1243dSDimitry Andric " popl %%eax\n" 546bdd1243dSDimitry Andric " movl $0,%0\n" 547bdd1243dSDimitry Andric " cmpl %%eax,%%ecx\n" 548bdd1243dSDimitry Andric " je 1f\n" 549bdd1243dSDimitry Andric " movl $1,%0\n" 550bdd1243dSDimitry Andric "1:" 551bdd1243dSDimitry Andric : "=r"(__cpuid_supported) 552bdd1243dSDimitry Andric : 553bdd1243dSDimitry Andric : "eax", "ecx"); 554bdd1243dSDimitry Andric if (!__cpuid_supported) 555bdd1243dSDimitry Andric return false; 556bdd1243dSDimitry Andric #endif 557bdd1243dSDimitry Andric return true; 558bdd1243dSDimitry Andric #endif 559bdd1243dSDimitry Andric return true; 560bdd1243dSDimitry Andric } 561bdd1243dSDimitry Andric 562bdd1243dSDimitry Andric /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in 563bdd1243dSDimitry Andric /// the specified arguments. If we can't run cpuid on the host, return true. 564bdd1243dSDimitry Andric static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, 565bdd1243dSDimitry Andric unsigned *rECX, unsigned *rEDX) { 566bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__) 567bdd1243dSDimitry Andric #if defined(__x86_64__) 568bdd1243dSDimitry Andric // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. 569bdd1243dSDimitry Andric // FIXME: should we save this for Clang? 570bdd1243dSDimitry Andric __asm__("movq\t%%rbx, %%rsi\n\t" 571bdd1243dSDimitry Andric "cpuid\n\t" 572bdd1243dSDimitry Andric "xchgq\t%%rbx, %%rsi\n\t" 573bdd1243dSDimitry Andric : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 574bdd1243dSDimitry Andric : "a"(value)); 575bdd1243dSDimitry Andric return false; 576bdd1243dSDimitry Andric #elif defined(__i386__) 577bdd1243dSDimitry Andric __asm__("movl\t%%ebx, %%esi\n\t" 578bdd1243dSDimitry Andric "cpuid\n\t" 579bdd1243dSDimitry Andric "xchgl\t%%ebx, %%esi\n\t" 580bdd1243dSDimitry Andric : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 581bdd1243dSDimitry Andric : "a"(value)); 582bdd1243dSDimitry Andric return false; 583bdd1243dSDimitry Andric #else 584bdd1243dSDimitry Andric return true; 585bdd1243dSDimitry Andric #endif 586bdd1243dSDimitry Andric #elif defined(_MSC_VER) 587bdd1243dSDimitry Andric // The MSVC intrinsic is portable across x86 and x64. 588bdd1243dSDimitry Andric int registers[4]; 589bdd1243dSDimitry Andric __cpuid(registers, value); 590bdd1243dSDimitry Andric *rEAX = registers[0]; 591bdd1243dSDimitry Andric *rEBX = registers[1]; 592bdd1243dSDimitry Andric *rECX = registers[2]; 593bdd1243dSDimitry Andric *rEDX = registers[3]; 594bdd1243dSDimitry Andric return false; 595bdd1243dSDimitry Andric #else 596bdd1243dSDimitry Andric return true; 597bdd1243dSDimitry Andric #endif 598bdd1243dSDimitry Andric } 599bdd1243dSDimitry Andric 600bdd1243dSDimitry Andric namespace llvm { 601bdd1243dSDimitry Andric namespace sys { 602bdd1243dSDimitry Andric namespace detail { 603bdd1243dSDimitry Andric namespace x86 { 604bdd1243dSDimitry Andric 605bdd1243dSDimitry Andric VendorSignatures getVendorSignature(unsigned *MaxLeaf) { 606bdd1243dSDimitry Andric unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 607bdd1243dSDimitry Andric if (MaxLeaf == nullptr) 608bdd1243dSDimitry Andric MaxLeaf = &EAX; 609bdd1243dSDimitry Andric else 610bdd1243dSDimitry Andric *MaxLeaf = 0; 611bdd1243dSDimitry Andric 612bdd1243dSDimitry Andric if (!isCpuIdSupported()) 613bdd1243dSDimitry Andric return VendorSignatures::UNKNOWN; 614bdd1243dSDimitry Andric 615bdd1243dSDimitry Andric if (getX86CpuIDAndInfo(0, MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1) 616bdd1243dSDimitry Andric return VendorSignatures::UNKNOWN; 617bdd1243dSDimitry Andric 618bdd1243dSDimitry Andric // "Genu ineI ntel" 619bdd1243dSDimitry Andric if (EBX == 0x756e6547 && EDX == 0x49656e69 && ECX == 0x6c65746e) 620bdd1243dSDimitry Andric return VendorSignatures::GENUINE_INTEL; 621bdd1243dSDimitry Andric 622bdd1243dSDimitry Andric // "Auth enti cAMD" 623bdd1243dSDimitry Andric if (EBX == 0x68747541 && EDX == 0x69746e65 && ECX == 0x444d4163) 624bdd1243dSDimitry Andric return VendorSignatures::AUTHENTIC_AMD; 625bdd1243dSDimitry Andric 626bdd1243dSDimitry Andric return VendorSignatures::UNKNOWN; 627bdd1243dSDimitry Andric } 628bdd1243dSDimitry Andric 629bdd1243dSDimitry Andric } // namespace x86 630bdd1243dSDimitry Andric } // namespace detail 631bdd1243dSDimitry Andric } // namespace sys 632bdd1243dSDimitry Andric } // namespace llvm 633bdd1243dSDimitry Andric 634bdd1243dSDimitry Andric using namespace llvm::sys::detail::x86; 635bdd1243dSDimitry Andric 636bdd1243dSDimitry Andric /// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return 637bdd1243dSDimitry Andric /// the 4 values in the specified arguments. If we can't run cpuid on the host, 638bdd1243dSDimitry Andric /// return true. 639bdd1243dSDimitry Andric static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, 640bdd1243dSDimitry Andric unsigned *rEAX, unsigned *rEBX, unsigned *rECX, 641bdd1243dSDimitry Andric unsigned *rEDX) { 642bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__) 643bdd1243dSDimitry Andric #if defined(__x86_64__) 644bdd1243dSDimitry Andric // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. 645bdd1243dSDimitry Andric // FIXME: should we save this for Clang? 646bdd1243dSDimitry Andric __asm__("movq\t%%rbx, %%rsi\n\t" 647bdd1243dSDimitry Andric "cpuid\n\t" 648bdd1243dSDimitry Andric "xchgq\t%%rbx, %%rsi\n\t" 649bdd1243dSDimitry Andric : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 650bdd1243dSDimitry Andric : "a"(value), "c"(subleaf)); 651bdd1243dSDimitry Andric return false; 652bdd1243dSDimitry Andric #elif defined(__i386__) 653bdd1243dSDimitry Andric __asm__("movl\t%%ebx, %%esi\n\t" 654bdd1243dSDimitry Andric "cpuid\n\t" 655bdd1243dSDimitry Andric "xchgl\t%%ebx, %%esi\n\t" 656bdd1243dSDimitry Andric : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 657bdd1243dSDimitry Andric : "a"(value), "c"(subleaf)); 658bdd1243dSDimitry Andric return false; 659bdd1243dSDimitry Andric #else 660bdd1243dSDimitry Andric return true; 661bdd1243dSDimitry Andric #endif 662bdd1243dSDimitry Andric #elif defined(_MSC_VER) 663bdd1243dSDimitry Andric int registers[4]; 664bdd1243dSDimitry Andric __cpuidex(registers, value, subleaf); 665bdd1243dSDimitry Andric *rEAX = registers[0]; 666bdd1243dSDimitry Andric *rEBX = registers[1]; 667bdd1243dSDimitry Andric *rECX = registers[2]; 668bdd1243dSDimitry Andric *rEDX = registers[3]; 669bdd1243dSDimitry Andric return false; 670bdd1243dSDimitry Andric #else 671bdd1243dSDimitry Andric return true; 672bdd1243dSDimitry Andric #endif 673bdd1243dSDimitry Andric } 674bdd1243dSDimitry Andric 675bdd1243dSDimitry Andric // Read control register 0 (XCR0). Used to detect features such as AVX. 676bdd1243dSDimitry Andric static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) { 677bdd1243dSDimitry Andric #if defined(__GNUC__) || defined(__clang__) 678bdd1243dSDimitry Andric // Check xgetbv; this uses a .byte sequence instead of the instruction 679bdd1243dSDimitry Andric // directly because older assemblers do not include support for xgetbv and 680bdd1243dSDimitry Andric // there is no easy way to conditionally compile based on the assembler used. 681bdd1243dSDimitry Andric __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0)); 682bdd1243dSDimitry Andric return false; 683bdd1243dSDimitry Andric #elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) 684bdd1243dSDimitry Andric unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); 685bdd1243dSDimitry Andric *rEAX = Result; 686bdd1243dSDimitry Andric *rEDX = Result >> 32; 687bdd1243dSDimitry Andric return false; 688bdd1243dSDimitry Andric #else 689bdd1243dSDimitry Andric return true; 690bdd1243dSDimitry Andric #endif 691bdd1243dSDimitry Andric } 692bdd1243dSDimitry Andric 693bdd1243dSDimitry Andric static void detectX86FamilyModel(unsigned EAX, unsigned *Family, 694bdd1243dSDimitry Andric unsigned *Model) { 695bdd1243dSDimitry Andric *Family = (EAX >> 8) & 0xf; // Bits 8 - 11 696bdd1243dSDimitry Andric *Model = (EAX >> 4) & 0xf; // Bits 4 - 7 697bdd1243dSDimitry Andric if (*Family == 6 || *Family == 0xf) { 698bdd1243dSDimitry Andric if (*Family == 0xf) 699bdd1243dSDimitry Andric // Examine extended family ID if family ID is F. 700bdd1243dSDimitry Andric *Family += (EAX >> 20) & 0xff; // Bits 20 - 27 701bdd1243dSDimitry Andric // Examine extended model ID if family ID is 6 or F. 702bdd1243dSDimitry Andric *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 703bdd1243dSDimitry Andric } 704bdd1243dSDimitry Andric } 705bdd1243dSDimitry Andric 706*0fca6ea1SDimitry Andric #define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0 707bdd1243dSDimitry Andric 708*0fca6ea1SDimitry Andric static StringRef getIntelProcessorTypeAndSubtype(unsigned Family, 709*0fca6ea1SDimitry Andric unsigned Model, 710*0fca6ea1SDimitry Andric const unsigned *Features, 711*0fca6ea1SDimitry Andric unsigned *Type, 712*0fca6ea1SDimitry Andric unsigned *Subtype) { 713bdd1243dSDimitry Andric StringRef CPU; 714bdd1243dSDimitry Andric 715bdd1243dSDimitry Andric switch (Family) { 716bdd1243dSDimitry Andric case 3: 717bdd1243dSDimitry Andric CPU = "i386"; 718bdd1243dSDimitry Andric break; 719bdd1243dSDimitry Andric case 4: 720bdd1243dSDimitry Andric CPU = "i486"; 721bdd1243dSDimitry Andric break; 722bdd1243dSDimitry Andric case 5: 723bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_MMX)) { 724bdd1243dSDimitry Andric CPU = "pentium-mmx"; 725bdd1243dSDimitry Andric break; 726bdd1243dSDimitry Andric } 727bdd1243dSDimitry Andric CPU = "pentium"; 728bdd1243dSDimitry Andric break; 729bdd1243dSDimitry Andric case 6: 730bdd1243dSDimitry Andric switch (Model) { 731bdd1243dSDimitry Andric case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile 732bdd1243dSDimitry Andric // processor, Intel Core 2 Quad processor, Intel Core 2 Quad 733bdd1243dSDimitry Andric // mobile processor, Intel Core 2 Extreme processor, Intel 734bdd1243dSDimitry Andric // Pentium Dual-Core processor, Intel Xeon processor, model 735bdd1243dSDimitry Andric // 0Fh. All processors are manufactured using the 65 nm process. 736bdd1243dSDimitry Andric case 0x16: // Intel Celeron processor model 16h. All processors are 737bdd1243dSDimitry Andric // manufactured using the 65 nm process 738bdd1243dSDimitry Andric CPU = "core2"; 739bdd1243dSDimitry Andric *Type = X86::INTEL_CORE2; 740bdd1243dSDimitry Andric break; 741bdd1243dSDimitry Andric case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model 742bdd1243dSDimitry Andric // 17h. All processors are manufactured using the 45 nm process. 743bdd1243dSDimitry Andric // 744bdd1243dSDimitry Andric // 45nm: Penryn , Wolfdale, Yorkfield (XE) 745bdd1243dSDimitry Andric case 0x1d: // Intel Xeon processor MP. All processors are manufactured using 746bdd1243dSDimitry Andric // the 45 nm process. 747bdd1243dSDimitry Andric CPU = "penryn"; 748bdd1243dSDimitry Andric *Type = X86::INTEL_CORE2; 749bdd1243dSDimitry Andric break; 750bdd1243dSDimitry Andric case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All 751bdd1243dSDimitry Andric // processors are manufactured using the 45 nm process. 752bdd1243dSDimitry Andric case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. 753bdd1243dSDimitry Andric // As found in a Summer 2010 model iMac. 754bdd1243dSDimitry Andric case 0x1f: 755bdd1243dSDimitry Andric case 0x2e: // Nehalem EX 756bdd1243dSDimitry Andric CPU = "nehalem"; 757bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 758bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_NEHALEM; 759bdd1243dSDimitry Andric break; 760bdd1243dSDimitry Andric case 0x25: // Intel Core i7, laptop version. 761bdd1243dSDimitry Andric case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All 762bdd1243dSDimitry Andric // processors are manufactured using the 32 nm process. 763bdd1243dSDimitry Andric case 0x2f: // Westmere EX 764bdd1243dSDimitry Andric CPU = "westmere"; 765bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 766bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_WESTMERE; 767bdd1243dSDimitry Andric break; 768bdd1243dSDimitry Andric case 0x2a: // Intel Core i7 processor. All processors are manufactured 769bdd1243dSDimitry Andric // using the 32 nm process. 770bdd1243dSDimitry Andric case 0x2d: 771bdd1243dSDimitry Andric CPU = "sandybridge"; 772bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 773bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_SANDYBRIDGE; 774bdd1243dSDimitry Andric break; 775bdd1243dSDimitry Andric case 0x3a: 776bdd1243dSDimitry Andric case 0x3e: // Ivy Bridge EP 777bdd1243dSDimitry Andric CPU = "ivybridge"; 778bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 779bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_IVYBRIDGE; 780bdd1243dSDimitry Andric break; 781bdd1243dSDimitry Andric 782bdd1243dSDimitry Andric // Haswell: 783bdd1243dSDimitry Andric case 0x3c: 784bdd1243dSDimitry Andric case 0x3f: 785bdd1243dSDimitry Andric case 0x45: 786bdd1243dSDimitry Andric case 0x46: 787bdd1243dSDimitry Andric CPU = "haswell"; 788bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 789bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_HASWELL; 790bdd1243dSDimitry Andric break; 791bdd1243dSDimitry Andric 792bdd1243dSDimitry Andric // Broadwell: 793bdd1243dSDimitry Andric case 0x3d: 794bdd1243dSDimitry Andric case 0x47: 795bdd1243dSDimitry Andric case 0x4f: 796bdd1243dSDimitry Andric case 0x56: 797bdd1243dSDimitry Andric CPU = "broadwell"; 798bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 799bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_BROADWELL; 800bdd1243dSDimitry Andric break; 801bdd1243dSDimitry Andric 802bdd1243dSDimitry Andric // Skylake: 803bdd1243dSDimitry Andric case 0x4e: // Skylake mobile 804bdd1243dSDimitry Andric case 0x5e: // Skylake desktop 805bdd1243dSDimitry Andric case 0x8e: // Kaby Lake mobile 806bdd1243dSDimitry Andric case 0x9e: // Kaby Lake desktop 807bdd1243dSDimitry Andric case 0xa5: // Comet Lake-H/S 808bdd1243dSDimitry Andric case 0xa6: // Comet Lake-U 809bdd1243dSDimitry Andric CPU = "skylake"; 810bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 811bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_SKYLAKE; 812bdd1243dSDimitry Andric break; 813bdd1243dSDimitry Andric 814bdd1243dSDimitry Andric // Rocketlake: 815bdd1243dSDimitry Andric case 0xa7: 816bdd1243dSDimitry Andric CPU = "rocketlake"; 817bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 818bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_ROCKETLAKE; 819bdd1243dSDimitry Andric break; 820bdd1243dSDimitry Andric 821bdd1243dSDimitry Andric // Skylake Xeon: 822bdd1243dSDimitry Andric case 0x55: 823bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 824bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_AVX512BF16)) { 825bdd1243dSDimitry Andric CPU = "cooperlake"; 826bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_COOPERLAKE; 827bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_AVX512VNNI)) { 828bdd1243dSDimitry Andric CPU = "cascadelake"; 829bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_CASCADELAKE; 830bdd1243dSDimitry Andric } else { 831bdd1243dSDimitry Andric CPU = "skylake-avx512"; 832bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; 833bdd1243dSDimitry Andric } 834bdd1243dSDimitry Andric break; 835bdd1243dSDimitry Andric 836bdd1243dSDimitry Andric // Cannonlake: 837bdd1243dSDimitry Andric case 0x66: 838bdd1243dSDimitry Andric CPU = "cannonlake"; 839bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 840bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_CANNONLAKE; 841bdd1243dSDimitry Andric break; 842bdd1243dSDimitry Andric 843bdd1243dSDimitry Andric // Icelake: 844bdd1243dSDimitry Andric case 0x7d: 845bdd1243dSDimitry Andric case 0x7e: 846bdd1243dSDimitry Andric CPU = "icelake-client"; 847bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 848bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT; 849bdd1243dSDimitry Andric break; 850bdd1243dSDimitry Andric 851bdd1243dSDimitry Andric // Tigerlake: 852bdd1243dSDimitry Andric case 0x8c: 853bdd1243dSDimitry Andric case 0x8d: 854bdd1243dSDimitry Andric CPU = "tigerlake"; 855bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 856bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_TIGERLAKE; 857bdd1243dSDimitry Andric break; 858bdd1243dSDimitry Andric 859bdd1243dSDimitry Andric // Alderlake: 860bdd1243dSDimitry Andric case 0x97: 861bdd1243dSDimitry Andric case 0x9a: 8625f757f3fSDimitry Andric // Gracemont 8635f757f3fSDimitry Andric case 0xbe: 864bdd1243dSDimitry Andric // Raptorlake: 865bdd1243dSDimitry Andric case 0xb7: 8665f757f3fSDimitry Andric case 0xba: 8675f757f3fSDimitry Andric case 0xbf: 868bdd1243dSDimitry Andric // Meteorlake: 869bdd1243dSDimitry Andric case 0xaa: 870bdd1243dSDimitry Andric case 0xac: 871bdd1243dSDimitry Andric CPU = "alderlake"; 872bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 873bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_ALDERLAKE; 874bdd1243dSDimitry Andric break; 875bdd1243dSDimitry Andric 8765f757f3fSDimitry Andric // Arrowlake: 8775f757f3fSDimitry Andric case 0xc5: 8785f757f3fSDimitry Andric CPU = "arrowlake"; 8795f757f3fSDimitry Andric *Type = X86::INTEL_COREI7; 8805f757f3fSDimitry Andric *Subtype = X86::INTEL_COREI7_ARROWLAKE; 8815f757f3fSDimitry Andric break; 8825f757f3fSDimitry Andric 8835f757f3fSDimitry Andric // Arrowlake S: 8845f757f3fSDimitry Andric case 0xc6: 8855f757f3fSDimitry Andric // Lunarlake: 8865f757f3fSDimitry Andric case 0xbd: 8875f757f3fSDimitry Andric CPU = "arrowlake-s"; 8885f757f3fSDimitry Andric *Type = X86::INTEL_COREI7; 8895f757f3fSDimitry Andric *Subtype = X86::INTEL_COREI7_ARROWLAKE_S; 8905f757f3fSDimitry Andric break; 8915f757f3fSDimitry Andric 8925f757f3fSDimitry Andric // Pantherlake: 8935f757f3fSDimitry Andric case 0xcc: 8945f757f3fSDimitry Andric CPU = "pantherlake"; 8955f757f3fSDimitry Andric *Type = X86::INTEL_COREI7; 8965f757f3fSDimitry Andric *Subtype = X86::INTEL_COREI7_PANTHERLAKE; 8975f757f3fSDimitry Andric break; 8985f757f3fSDimitry Andric 899bdd1243dSDimitry Andric // Graniterapids: 900bdd1243dSDimitry Andric case 0xad: 901bdd1243dSDimitry Andric CPU = "graniterapids"; 902bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 903bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_GRANITERAPIDS; 904bdd1243dSDimitry Andric break; 905bdd1243dSDimitry Andric 90606c3fb27SDimitry Andric // Granite Rapids D: 90706c3fb27SDimitry Andric case 0xae: 90806c3fb27SDimitry Andric CPU = "graniterapids-d"; 90906c3fb27SDimitry Andric *Type = X86::INTEL_COREI7; 91006c3fb27SDimitry Andric *Subtype = X86::INTEL_COREI7_GRANITERAPIDS_D; 91106c3fb27SDimitry Andric break; 91206c3fb27SDimitry Andric 913bdd1243dSDimitry Andric // Icelake Xeon: 914bdd1243dSDimitry Andric case 0x6a: 915bdd1243dSDimitry Andric case 0x6c: 916bdd1243dSDimitry Andric CPU = "icelake-server"; 917bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 918bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER; 919bdd1243dSDimitry Andric break; 920bdd1243dSDimitry Andric 921bdd1243dSDimitry Andric // Emerald Rapids: 922bdd1243dSDimitry Andric case 0xcf: 923bdd1243dSDimitry Andric // Sapphire Rapids: 924bdd1243dSDimitry Andric case 0x8f: 925bdd1243dSDimitry Andric CPU = "sapphirerapids"; 926bdd1243dSDimitry Andric *Type = X86::INTEL_COREI7; 927bdd1243dSDimitry Andric *Subtype = X86::INTEL_COREI7_SAPPHIRERAPIDS; 928bdd1243dSDimitry Andric break; 929bdd1243dSDimitry Andric 930bdd1243dSDimitry Andric case 0x1c: // Most 45 nm Intel Atom processors 931bdd1243dSDimitry Andric case 0x26: // 45 nm Atom Lincroft 932bdd1243dSDimitry Andric case 0x27: // 32 nm Atom Medfield 933bdd1243dSDimitry Andric case 0x35: // 32 nm Atom Midview 934bdd1243dSDimitry Andric case 0x36: // 32 nm Atom Midview 935bdd1243dSDimitry Andric CPU = "bonnell"; 936bdd1243dSDimitry Andric *Type = X86::INTEL_BONNELL; 937bdd1243dSDimitry Andric break; 938bdd1243dSDimitry Andric 939bdd1243dSDimitry Andric // Atom Silvermont codes from the Intel software optimization guide. 940bdd1243dSDimitry Andric case 0x37: 941bdd1243dSDimitry Andric case 0x4a: 942bdd1243dSDimitry Andric case 0x4d: 943bdd1243dSDimitry Andric case 0x5a: 944bdd1243dSDimitry Andric case 0x5d: 945bdd1243dSDimitry Andric case 0x4c: // really airmont 946bdd1243dSDimitry Andric CPU = "silvermont"; 947bdd1243dSDimitry Andric *Type = X86::INTEL_SILVERMONT; 948bdd1243dSDimitry Andric break; 949bdd1243dSDimitry Andric // Goldmont: 950bdd1243dSDimitry Andric case 0x5c: // Apollo Lake 951bdd1243dSDimitry Andric case 0x5f: // Denverton 952bdd1243dSDimitry Andric CPU = "goldmont"; 953bdd1243dSDimitry Andric *Type = X86::INTEL_GOLDMONT; 954bdd1243dSDimitry Andric break; 955bdd1243dSDimitry Andric case 0x7a: 956bdd1243dSDimitry Andric CPU = "goldmont-plus"; 957bdd1243dSDimitry Andric *Type = X86::INTEL_GOLDMONT_PLUS; 958bdd1243dSDimitry Andric break; 959bdd1243dSDimitry Andric case 0x86: 9605f757f3fSDimitry Andric case 0x8a: // Lakefield 9615f757f3fSDimitry Andric case 0x96: // Elkhart Lake 9625f757f3fSDimitry Andric case 0x9c: // Jasper Lake 963bdd1243dSDimitry Andric CPU = "tremont"; 964bdd1243dSDimitry Andric *Type = X86::INTEL_TREMONT; 965bdd1243dSDimitry Andric break; 966bdd1243dSDimitry Andric 967bdd1243dSDimitry Andric // Sierraforest: 968bdd1243dSDimitry Andric case 0xaf: 969bdd1243dSDimitry Andric CPU = "sierraforest"; 970bdd1243dSDimitry Andric *Type = X86::INTEL_SIERRAFOREST; 971bdd1243dSDimitry Andric break; 972bdd1243dSDimitry Andric 973bdd1243dSDimitry Andric // Grandridge: 974bdd1243dSDimitry Andric case 0xb6: 975bdd1243dSDimitry Andric CPU = "grandridge"; 976bdd1243dSDimitry Andric *Type = X86::INTEL_GRANDRIDGE; 977bdd1243dSDimitry Andric break; 978bdd1243dSDimitry Andric 9795f757f3fSDimitry Andric // Clearwaterforest: 9805f757f3fSDimitry Andric case 0xdd: 9815f757f3fSDimitry Andric CPU = "clearwaterforest"; 9825f757f3fSDimitry Andric *Type = X86::INTEL_CLEARWATERFOREST; 9835f757f3fSDimitry Andric break; 9845f757f3fSDimitry Andric 985bdd1243dSDimitry Andric // Xeon Phi (Knights Landing + Knights Mill): 986bdd1243dSDimitry Andric case 0x57: 987bdd1243dSDimitry Andric CPU = "knl"; 988bdd1243dSDimitry Andric *Type = X86::INTEL_KNL; 989bdd1243dSDimitry Andric break; 990bdd1243dSDimitry Andric case 0x85: 991bdd1243dSDimitry Andric CPU = "knm"; 992bdd1243dSDimitry Andric *Type = X86::INTEL_KNM; 993bdd1243dSDimitry Andric break; 994bdd1243dSDimitry Andric 995bdd1243dSDimitry Andric default: // Unknown family 6 CPU, try to guess. 996bdd1243dSDimitry Andric // Don't both with Type/Subtype here, they aren't used by the caller. 997bdd1243dSDimitry Andric // They're used above to keep the code in sync with compiler-rt. 998bdd1243dSDimitry Andric // TODO detect tigerlake host from model 999bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_AVX512VP2INTERSECT)) { 1000bdd1243dSDimitry Andric CPU = "tigerlake"; 1001bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_AVX512VBMI2)) { 1002bdd1243dSDimitry Andric CPU = "icelake-client"; 1003bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_AVX512VBMI)) { 1004bdd1243dSDimitry Andric CPU = "cannonlake"; 1005bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_AVX512BF16)) { 1006bdd1243dSDimitry Andric CPU = "cooperlake"; 1007bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_AVX512VNNI)) { 1008bdd1243dSDimitry Andric CPU = "cascadelake"; 1009bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_AVX512VL)) { 1010bdd1243dSDimitry Andric CPU = "skylake-avx512"; 1011bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_CLFLUSHOPT)) { 1012bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_SHA)) 1013bdd1243dSDimitry Andric CPU = "goldmont"; 1014bdd1243dSDimitry Andric else 1015bdd1243dSDimitry Andric CPU = "skylake"; 1016bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_ADX)) { 1017bdd1243dSDimitry Andric CPU = "broadwell"; 1018bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_AVX2)) { 1019bdd1243dSDimitry Andric CPU = "haswell"; 1020bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_AVX)) { 1021bdd1243dSDimitry Andric CPU = "sandybridge"; 1022bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_SSE4_2)) { 1023bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_MOVBE)) 1024bdd1243dSDimitry Andric CPU = "silvermont"; 1025bdd1243dSDimitry Andric else 1026bdd1243dSDimitry Andric CPU = "nehalem"; 1027bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_SSE4_1)) { 1028bdd1243dSDimitry Andric CPU = "penryn"; 1029bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_SSSE3)) { 1030bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_MOVBE)) 1031bdd1243dSDimitry Andric CPU = "bonnell"; 1032bdd1243dSDimitry Andric else 1033bdd1243dSDimitry Andric CPU = "core2"; 1034bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_64BIT)) { 1035bdd1243dSDimitry Andric CPU = "core2"; 1036bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_SSE3)) { 1037bdd1243dSDimitry Andric CPU = "yonah"; 1038bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_SSE2)) { 1039bdd1243dSDimitry Andric CPU = "pentium-m"; 1040bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_SSE)) { 1041bdd1243dSDimitry Andric CPU = "pentium3"; 1042bdd1243dSDimitry Andric } else if (testFeature(X86::FEATURE_MMX)) { 1043bdd1243dSDimitry Andric CPU = "pentium2"; 1044bdd1243dSDimitry Andric } else { 1045bdd1243dSDimitry Andric CPU = "pentiumpro"; 1046bdd1243dSDimitry Andric } 1047bdd1243dSDimitry Andric break; 1048bdd1243dSDimitry Andric } 1049bdd1243dSDimitry Andric break; 1050bdd1243dSDimitry Andric case 15: { 1051bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_64BIT)) { 1052bdd1243dSDimitry Andric CPU = "nocona"; 1053bdd1243dSDimitry Andric break; 1054bdd1243dSDimitry Andric } 1055bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_SSE3)) { 1056bdd1243dSDimitry Andric CPU = "prescott"; 1057bdd1243dSDimitry Andric break; 1058bdd1243dSDimitry Andric } 1059bdd1243dSDimitry Andric CPU = "pentium4"; 1060bdd1243dSDimitry Andric break; 1061bdd1243dSDimitry Andric } 1062bdd1243dSDimitry Andric default: 1063bdd1243dSDimitry Andric break; // Unknown. 1064bdd1243dSDimitry Andric } 1065bdd1243dSDimitry Andric 1066bdd1243dSDimitry Andric return CPU; 1067bdd1243dSDimitry Andric } 1068bdd1243dSDimitry Andric 1069*0fca6ea1SDimitry Andric static const char *getAMDProcessorTypeAndSubtype(unsigned Family, 1070*0fca6ea1SDimitry Andric unsigned Model, 1071bdd1243dSDimitry Andric const unsigned *Features, 1072*0fca6ea1SDimitry Andric unsigned *Type, 1073*0fca6ea1SDimitry Andric unsigned *Subtype) { 1074*0fca6ea1SDimitry Andric const char *CPU = 0; 1075bdd1243dSDimitry Andric 1076bdd1243dSDimitry Andric switch (Family) { 1077bdd1243dSDimitry Andric case 4: 1078bdd1243dSDimitry Andric CPU = "i486"; 1079bdd1243dSDimitry Andric break; 1080bdd1243dSDimitry Andric case 5: 1081bdd1243dSDimitry Andric CPU = "pentium"; 1082bdd1243dSDimitry Andric switch (Model) { 1083bdd1243dSDimitry Andric case 6: 1084bdd1243dSDimitry Andric case 7: 1085bdd1243dSDimitry Andric CPU = "k6"; 1086bdd1243dSDimitry Andric break; 1087bdd1243dSDimitry Andric case 8: 1088bdd1243dSDimitry Andric CPU = "k6-2"; 1089bdd1243dSDimitry Andric break; 1090bdd1243dSDimitry Andric case 9: 1091bdd1243dSDimitry Andric case 13: 1092bdd1243dSDimitry Andric CPU = "k6-3"; 1093bdd1243dSDimitry Andric break; 1094bdd1243dSDimitry Andric case 10: 1095bdd1243dSDimitry Andric CPU = "geode"; 1096bdd1243dSDimitry Andric break; 1097bdd1243dSDimitry Andric } 1098bdd1243dSDimitry Andric break; 1099bdd1243dSDimitry Andric case 6: 1100bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_SSE)) { 1101bdd1243dSDimitry Andric CPU = "athlon-xp"; 1102bdd1243dSDimitry Andric break; 1103bdd1243dSDimitry Andric } 1104bdd1243dSDimitry Andric CPU = "athlon"; 1105bdd1243dSDimitry Andric break; 1106bdd1243dSDimitry Andric case 15: 1107bdd1243dSDimitry Andric if (testFeature(X86::FEATURE_SSE3)) { 1108bdd1243dSDimitry Andric CPU = "k8-sse3"; 1109bdd1243dSDimitry Andric break; 1110bdd1243dSDimitry Andric } 1111bdd1243dSDimitry Andric CPU = "k8"; 1112bdd1243dSDimitry Andric break; 1113bdd1243dSDimitry Andric case 16: 1114bdd1243dSDimitry Andric CPU = "amdfam10"; 1115bdd1243dSDimitry Andric *Type = X86::AMDFAM10H; // "amdfam10" 1116bdd1243dSDimitry Andric switch (Model) { 1117bdd1243dSDimitry Andric case 2: 1118bdd1243dSDimitry Andric *Subtype = X86::AMDFAM10H_BARCELONA; 1119bdd1243dSDimitry Andric break; 1120bdd1243dSDimitry Andric case 4: 1121bdd1243dSDimitry Andric *Subtype = X86::AMDFAM10H_SHANGHAI; 1122bdd1243dSDimitry Andric break; 1123bdd1243dSDimitry Andric case 8: 1124bdd1243dSDimitry Andric *Subtype = X86::AMDFAM10H_ISTANBUL; 1125bdd1243dSDimitry Andric break; 1126bdd1243dSDimitry Andric } 1127bdd1243dSDimitry Andric break; 1128bdd1243dSDimitry Andric case 20: 1129bdd1243dSDimitry Andric CPU = "btver1"; 1130bdd1243dSDimitry Andric *Type = X86::AMD_BTVER1; 1131bdd1243dSDimitry Andric break; 1132bdd1243dSDimitry Andric case 21: 1133bdd1243dSDimitry Andric CPU = "bdver1"; 1134bdd1243dSDimitry Andric *Type = X86::AMDFAM15H; 1135bdd1243dSDimitry Andric if (Model >= 0x60 && Model <= 0x7f) { 1136bdd1243dSDimitry Andric CPU = "bdver4"; 1137bdd1243dSDimitry Andric *Subtype = X86::AMDFAM15H_BDVER4; 1138bdd1243dSDimitry Andric break; // 60h-7Fh: Excavator 1139bdd1243dSDimitry Andric } 1140bdd1243dSDimitry Andric if (Model >= 0x30 && Model <= 0x3f) { 1141bdd1243dSDimitry Andric CPU = "bdver3"; 1142bdd1243dSDimitry Andric *Subtype = X86::AMDFAM15H_BDVER3; 1143bdd1243dSDimitry Andric break; // 30h-3Fh: Steamroller 1144bdd1243dSDimitry Andric } 1145bdd1243dSDimitry Andric if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) { 1146bdd1243dSDimitry Andric CPU = "bdver2"; 1147bdd1243dSDimitry Andric *Subtype = X86::AMDFAM15H_BDVER2; 1148bdd1243dSDimitry Andric break; // 02h, 10h-1Fh: Piledriver 1149bdd1243dSDimitry Andric } 1150bdd1243dSDimitry Andric if (Model <= 0x0f) { 1151bdd1243dSDimitry Andric *Subtype = X86::AMDFAM15H_BDVER1; 1152bdd1243dSDimitry Andric break; // 00h-0Fh: Bulldozer 1153bdd1243dSDimitry Andric } 1154bdd1243dSDimitry Andric break; 1155bdd1243dSDimitry Andric case 22: 1156bdd1243dSDimitry Andric CPU = "btver2"; 1157bdd1243dSDimitry Andric *Type = X86::AMD_BTVER2; 1158bdd1243dSDimitry Andric break; 1159bdd1243dSDimitry Andric case 23: 1160bdd1243dSDimitry Andric CPU = "znver1"; 1161bdd1243dSDimitry Andric *Type = X86::AMDFAM17H; 1162cb14a3feSDimitry Andric if ((Model >= 0x30 && Model <= 0x3f) || (Model == 0x47) || 1163cb14a3feSDimitry Andric (Model >= 0x60 && Model <= 0x67) || (Model >= 0x68 && Model <= 0x6f) || 1164cb14a3feSDimitry Andric (Model >= 0x70 && Model <= 0x7f) || (Model >= 0x84 && Model <= 0x87) || 1165cb14a3feSDimitry Andric (Model >= 0x90 && Model <= 0x97) || (Model >= 0x98 && Model <= 0x9f) || 1166cb14a3feSDimitry Andric (Model >= 0xa0 && Model <= 0xaf)) { 1167cb14a3feSDimitry Andric // Family 17h Models 30h-3Fh (Starship) Zen 2 1168cb14a3feSDimitry Andric // Family 17h Models 47h (Cardinal) Zen 2 1169cb14a3feSDimitry Andric // Family 17h Models 60h-67h (Renoir) Zen 2 1170cb14a3feSDimitry Andric // Family 17h Models 68h-6Fh (Lucienne) Zen 2 1171cb14a3feSDimitry Andric // Family 17h Models 70h-7Fh (Matisse) Zen 2 1172cb14a3feSDimitry Andric // Family 17h Models 84h-87h (ProjectX) Zen 2 1173cb14a3feSDimitry Andric // Family 17h Models 90h-97h (VanGogh) Zen 2 1174cb14a3feSDimitry Andric // Family 17h Models 98h-9Fh (Mero) Zen 2 1175cb14a3feSDimitry Andric // Family 17h Models A0h-AFh (Mendocino) Zen 2 1176bdd1243dSDimitry Andric CPU = "znver2"; 1177bdd1243dSDimitry Andric *Subtype = X86::AMDFAM17H_ZNVER2; 1178cb14a3feSDimitry Andric break; 1179bdd1243dSDimitry Andric } 1180cb14a3feSDimitry Andric if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x20 && Model <= 0x2f)) { 1181cb14a3feSDimitry Andric // Family 17h Models 10h-1Fh (Raven1) Zen 1182cb14a3feSDimitry Andric // Family 17h Models 10h-1Fh (Picasso) Zen+ 1183cb14a3feSDimitry Andric // Family 17h Models 20h-2Fh (Raven2 x86) Zen 1184bdd1243dSDimitry Andric *Subtype = X86::AMDFAM17H_ZNVER1; 1185cb14a3feSDimitry Andric break; 1186bdd1243dSDimitry Andric } 1187bdd1243dSDimitry Andric break; 1188bdd1243dSDimitry Andric case 25: 1189bdd1243dSDimitry Andric CPU = "znver3"; 1190bdd1243dSDimitry Andric *Type = X86::AMDFAM19H; 1191647cbc5dSDimitry Andric if (Model <= 0x0f || (Model >= 0x20 && Model <= 0x2f) || 1192cb14a3feSDimitry Andric (Model >= 0x30 && Model <= 0x3f) || (Model >= 0x40 && Model <= 0x4f) || 1193cb14a3feSDimitry Andric (Model >= 0x50 && Model <= 0x5f)) { 1194cb14a3feSDimitry Andric // Family 19h Models 00h-0Fh (Genesis, Chagall) Zen 3 1195cb14a3feSDimitry Andric // Family 19h Models 20h-2Fh (Vermeer) Zen 3 1196cb14a3feSDimitry Andric // Family 19h Models 30h-3Fh (Badami) Zen 3 1197cb14a3feSDimitry Andric // Family 19h Models 40h-4Fh (Rembrandt) Zen 3+ 1198cb14a3feSDimitry Andric // Family 19h Models 50h-5Fh (Cezanne) Zen 3 1199bdd1243dSDimitry Andric *Subtype = X86::AMDFAM19H_ZNVER3; 1200bdd1243dSDimitry Andric break; 1201bdd1243dSDimitry Andric } 1202cb14a3feSDimitry Andric if ((Model >= 0x10 && Model <= 0x1f) || (Model >= 0x60 && Model <= 0x6f) || 1203cb14a3feSDimitry Andric (Model >= 0x70 && Model <= 0x77) || (Model >= 0x78 && Model <= 0x7f) || 1204cb14a3feSDimitry Andric (Model >= 0xa0 && Model <= 0xaf)) { 1205cb14a3feSDimitry Andric // Family 19h Models 10h-1Fh (Stones; Storm Peak) Zen 4 1206cb14a3feSDimitry Andric // Family 19h Models 60h-6Fh (Raphael) Zen 4 1207cb14a3feSDimitry Andric // Family 19h Models 70h-77h (Phoenix, Hawkpoint1) Zen 4 1208cb14a3feSDimitry Andric // Family 19h Models 78h-7Fh (Phoenix 2, Hawkpoint2) Zen 4 1209cb14a3feSDimitry Andric // Family 19h Models A0h-AFh (Stones-Dense) Zen 4 1210bdd1243dSDimitry Andric CPU = "znver4"; 1211bdd1243dSDimitry Andric *Subtype = X86::AMDFAM19H_ZNVER4; 1212bdd1243dSDimitry Andric break; // "znver4" 1213bdd1243dSDimitry Andric } 1214*0fca6ea1SDimitry Andric break; // family 19h 1215bdd1243dSDimitry Andric default: 1216bdd1243dSDimitry Andric break; // Unknown AMD CPU. 1217bdd1243dSDimitry Andric } 1218bdd1243dSDimitry Andric 1219bdd1243dSDimitry Andric return CPU; 1220bdd1243dSDimitry Andric } 1221bdd1243dSDimitry Andric 1222*0fca6ea1SDimitry Andric #undef testFeature 1223*0fca6ea1SDimitry Andric 1224bdd1243dSDimitry Andric static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf, 1225bdd1243dSDimitry Andric unsigned *Features) { 1226bdd1243dSDimitry Andric unsigned EAX, EBX; 1227bdd1243dSDimitry Andric 1228bdd1243dSDimitry Andric auto setFeature = [&](unsigned F) { 1229bdd1243dSDimitry Andric Features[F / 32] |= 1U << (F % 32); 1230bdd1243dSDimitry Andric }; 1231bdd1243dSDimitry Andric 1232bdd1243dSDimitry Andric if ((EDX >> 15) & 1) 1233bdd1243dSDimitry Andric setFeature(X86::FEATURE_CMOV); 1234bdd1243dSDimitry Andric if ((EDX >> 23) & 1) 1235bdd1243dSDimitry Andric setFeature(X86::FEATURE_MMX); 1236bdd1243dSDimitry Andric if ((EDX >> 25) & 1) 1237bdd1243dSDimitry Andric setFeature(X86::FEATURE_SSE); 1238bdd1243dSDimitry Andric if ((EDX >> 26) & 1) 1239bdd1243dSDimitry Andric setFeature(X86::FEATURE_SSE2); 1240bdd1243dSDimitry Andric 1241bdd1243dSDimitry Andric if ((ECX >> 0) & 1) 1242bdd1243dSDimitry Andric setFeature(X86::FEATURE_SSE3); 1243bdd1243dSDimitry Andric if ((ECX >> 1) & 1) 1244bdd1243dSDimitry Andric setFeature(X86::FEATURE_PCLMUL); 1245bdd1243dSDimitry Andric if ((ECX >> 9) & 1) 1246bdd1243dSDimitry Andric setFeature(X86::FEATURE_SSSE3); 1247bdd1243dSDimitry Andric if ((ECX >> 12) & 1) 1248bdd1243dSDimitry Andric setFeature(X86::FEATURE_FMA); 1249bdd1243dSDimitry Andric if ((ECX >> 19) & 1) 1250bdd1243dSDimitry Andric setFeature(X86::FEATURE_SSE4_1); 1251bdd1243dSDimitry Andric if ((ECX >> 20) & 1) { 1252bdd1243dSDimitry Andric setFeature(X86::FEATURE_SSE4_2); 1253bdd1243dSDimitry Andric setFeature(X86::FEATURE_CRC32); 1254bdd1243dSDimitry Andric } 1255bdd1243dSDimitry Andric if ((ECX >> 23) & 1) 1256bdd1243dSDimitry Andric setFeature(X86::FEATURE_POPCNT); 1257bdd1243dSDimitry Andric if ((ECX >> 25) & 1) 1258bdd1243dSDimitry Andric setFeature(X86::FEATURE_AES); 1259bdd1243dSDimitry Andric 1260bdd1243dSDimitry Andric if ((ECX >> 22) & 1) 1261bdd1243dSDimitry Andric setFeature(X86::FEATURE_MOVBE); 1262bdd1243dSDimitry Andric 1263bdd1243dSDimitry Andric // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV 1264bdd1243dSDimitry Andric // indicates that the AVX registers will be saved and restored on context 1265bdd1243dSDimitry Andric // switch, then we have full AVX support. 1266bdd1243dSDimitry Andric const unsigned AVXBits = (1 << 27) | (1 << 28); 1267bdd1243dSDimitry Andric bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) && 1268bdd1243dSDimitry Andric ((EAX & 0x6) == 0x6); 1269bdd1243dSDimitry Andric #if defined(__APPLE__) 1270bdd1243dSDimitry Andric // Darwin lazily saves the AVX512 context on first use: trust that the OS will 1271bdd1243dSDimitry Andric // save the AVX512 context if we use AVX512 instructions, even the bit is not 1272bdd1243dSDimitry Andric // set right now. 1273bdd1243dSDimitry Andric bool HasAVX512Save = true; 1274bdd1243dSDimitry Andric #else 1275bdd1243dSDimitry Andric // AVX512 requires additional context to be saved by the OS. 1276bdd1243dSDimitry Andric bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0); 1277bdd1243dSDimitry Andric #endif 1278bdd1243dSDimitry Andric 1279bdd1243dSDimitry Andric if (HasAVX) 1280bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX); 1281bdd1243dSDimitry Andric 1282bdd1243dSDimitry Andric bool HasLeaf7 = 1283bdd1243dSDimitry Andric MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); 1284bdd1243dSDimitry Andric 1285bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 3) & 1)) 1286bdd1243dSDimitry Andric setFeature(X86::FEATURE_BMI); 1287bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX) 1288bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX2); 1289bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 8) & 1)) 1290bdd1243dSDimitry Andric setFeature(X86::FEATURE_BMI2); 12915678d1d9SDimitry Andric if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save) { 1292bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512F); 12935678d1d9SDimitry Andric setFeature(X86::FEATURE_EVEX512); 12945678d1d9SDimitry Andric } 1295bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save) 1296bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512DQ); 1297bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 19) & 1)) 1298bdd1243dSDimitry Andric setFeature(X86::FEATURE_ADX); 1299bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save) 1300bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512IFMA); 1301bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 23) & 1)) 1302bdd1243dSDimitry Andric setFeature(X86::FEATURE_CLFLUSHOPT); 1303bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save) 1304bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512CD); 1305bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 29) & 1)) 1306bdd1243dSDimitry Andric setFeature(X86::FEATURE_SHA); 1307bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save) 1308bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512BW); 1309bdd1243dSDimitry Andric if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save) 1310bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512VL); 1311bdd1243dSDimitry Andric 1312bdd1243dSDimitry Andric if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save) 1313bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512VBMI); 1314bdd1243dSDimitry Andric if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save) 1315bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512VBMI2); 1316bdd1243dSDimitry Andric if (HasLeaf7 && ((ECX >> 8) & 1)) 1317bdd1243dSDimitry Andric setFeature(X86::FEATURE_GFNI); 1318bdd1243dSDimitry Andric if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX) 1319bdd1243dSDimitry Andric setFeature(X86::FEATURE_VPCLMULQDQ); 1320bdd1243dSDimitry Andric if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save) 1321bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512VNNI); 1322bdd1243dSDimitry Andric if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save) 1323bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512BITALG); 1324bdd1243dSDimitry Andric if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save) 1325bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512VPOPCNTDQ); 1326bdd1243dSDimitry Andric 1327bdd1243dSDimitry Andric if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save) 1328bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX5124VNNIW); 1329bdd1243dSDimitry Andric if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save) 1330bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX5124FMAPS); 1331bdd1243dSDimitry Andric if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save) 1332bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512VP2INTERSECT); 1333bdd1243dSDimitry Andric 13348a4dda33SDimitry Andric // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't 13358a4dda33SDimitry Andric // return all 0s for invalid subleaves so check the limit. 1336bdd1243dSDimitry Andric bool HasLeaf7Subleaf1 = 13378a4dda33SDimitry Andric HasLeaf7 && EAX >= 1 && 13388a4dda33SDimitry Andric !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX); 1339bdd1243dSDimitry Andric if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save) 1340bdd1243dSDimitry Andric setFeature(X86::FEATURE_AVX512BF16); 1341bdd1243dSDimitry Andric 1342bdd1243dSDimitry Andric unsigned MaxExtLevel; 1343bdd1243dSDimitry Andric getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX); 1344bdd1243dSDimitry Andric 1345bdd1243dSDimitry Andric bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 && 1346bdd1243dSDimitry Andric !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 1347bdd1243dSDimitry Andric if (HasExtLeaf1 && ((ECX >> 6) & 1)) 1348bdd1243dSDimitry Andric setFeature(X86::FEATURE_SSE4_A); 1349bdd1243dSDimitry Andric if (HasExtLeaf1 && ((ECX >> 11) & 1)) 1350bdd1243dSDimitry Andric setFeature(X86::FEATURE_XOP); 1351bdd1243dSDimitry Andric if (HasExtLeaf1 && ((ECX >> 16) & 1)) 1352bdd1243dSDimitry Andric setFeature(X86::FEATURE_FMA4); 1353bdd1243dSDimitry Andric 1354bdd1243dSDimitry Andric if (HasExtLeaf1 && ((EDX >> 29) & 1)) 1355bdd1243dSDimitry Andric setFeature(X86::FEATURE_64BIT); 1356bdd1243dSDimitry Andric } 1357bdd1243dSDimitry Andric 1358bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1359bdd1243dSDimitry Andric unsigned MaxLeaf = 0; 1360bdd1243dSDimitry Andric const VendorSignatures Vendor = getVendorSignature(&MaxLeaf); 1361bdd1243dSDimitry Andric if (Vendor == VendorSignatures::UNKNOWN) 1362bdd1243dSDimitry Andric return "generic"; 1363bdd1243dSDimitry Andric 1364bdd1243dSDimitry Andric unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 1365bdd1243dSDimitry Andric getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX); 1366bdd1243dSDimitry Andric 1367bdd1243dSDimitry Andric unsigned Family = 0, Model = 0; 1368bdd1243dSDimitry Andric unsigned Features[(X86::CPU_FEATURE_MAX + 31) / 32] = {0}; 1369bdd1243dSDimitry Andric detectX86FamilyModel(EAX, &Family, &Model); 1370bdd1243dSDimitry Andric getAvailableFeatures(ECX, EDX, MaxLeaf, Features); 1371bdd1243dSDimitry Andric 1372bdd1243dSDimitry Andric // These aren't consumed in this file, but we try to keep some source code the 1373bdd1243dSDimitry Andric // same or similar to compiler-rt. 1374bdd1243dSDimitry Andric unsigned Type = 0; 1375bdd1243dSDimitry Andric unsigned Subtype = 0; 1376bdd1243dSDimitry Andric 1377bdd1243dSDimitry Andric StringRef CPU; 1378bdd1243dSDimitry Andric 1379bdd1243dSDimitry Andric if (Vendor == VendorSignatures::GENUINE_INTEL) { 1380bdd1243dSDimitry Andric CPU = getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type, 1381bdd1243dSDimitry Andric &Subtype); 1382bdd1243dSDimitry Andric } else if (Vendor == VendorSignatures::AUTHENTIC_AMD) { 1383bdd1243dSDimitry Andric CPU = getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, 1384bdd1243dSDimitry Andric &Subtype); 1385bdd1243dSDimitry Andric } 1386bdd1243dSDimitry Andric 1387bdd1243dSDimitry Andric if (!CPU.empty()) 1388bdd1243dSDimitry Andric return CPU; 1389bdd1243dSDimitry Andric 1390bdd1243dSDimitry Andric return "generic"; 1391bdd1243dSDimitry Andric } 1392bdd1243dSDimitry Andric 1393bdd1243dSDimitry Andric #elif defined(__APPLE__) && defined(__powerpc__) 1394bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1395bdd1243dSDimitry Andric host_basic_info_data_t hostInfo; 1396bdd1243dSDimitry Andric mach_msg_type_number_t infoCount; 1397bdd1243dSDimitry Andric 1398bdd1243dSDimitry Andric infoCount = HOST_BASIC_INFO_COUNT; 1399bdd1243dSDimitry Andric mach_port_t hostPort = mach_host_self(); 1400bdd1243dSDimitry Andric host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo, 1401bdd1243dSDimitry Andric &infoCount); 1402bdd1243dSDimitry Andric mach_port_deallocate(mach_task_self(), hostPort); 1403bdd1243dSDimitry Andric 1404bdd1243dSDimitry Andric if (hostInfo.cpu_type != CPU_TYPE_POWERPC) 1405bdd1243dSDimitry Andric return "generic"; 1406bdd1243dSDimitry Andric 1407bdd1243dSDimitry Andric switch (hostInfo.cpu_subtype) { 1408bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_601: 1409bdd1243dSDimitry Andric return "601"; 1410bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_602: 1411bdd1243dSDimitry Andric return "602"; 1412bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_603: 1413bdd1243dSDimitry Andric return "603"; 1414bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_603e: 1415bdd1243dSDimitry Andric return "603e"; 1416bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_603ev: 1417bdd1243dSDimitry Andric return "603ev"; 1418bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_604: 1419bdd1243dSDimitry Andric return "604"; 1420bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_604e: 1421bdd1243dSDimitry Andric return "604e"; 1422bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_620: 1423bdd1243dSDimitry Andric return "620"; 1424bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_750: 1425bdd1243dSDimitry Andric return "750"; 1426bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_7400: 1427bdd1243dSDimitry Andric return "7400"; 1428bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_7450: 1429bdd1243dSDimitry Andric return "7450"; 1430bdd1243dSDimitry Andric case CPU_SUBTYPE_POWERPC_970: 1431bdd1243dSDimitry Andric return "970"; 1432bdd1243dSDimitry Andric default:; 1433bdd1243dSDimitry Andric } 1434bdd1243dSDimitry Andric 1435bdd1243dSDimitry Andric return "generic"; 1436bdd1243dSDimitry Andric } 1437bdd1243dSDimitry Andric #elif defined(__linux__) && defined(__powerpc__) 1438bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1439bdd1243dSDimitry Andric std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1440bdd1243dSDimitry Andric StringRef Content = P ? P->getBuffer() : ""; 1441bdd1243dSDimitry Andric return detail::getHostCPUNameForPowerPC(Content); 1442bdd1243dSDimitry Andric } 1443bdd1243dSDimitry Andric #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__)) 1444bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1445bdd1243dSDimitry Andric std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1446bdd1243dSDimitry Andric StringRef Content = P ? P->getBuffer() : ""; 1447bdd1243dSDimitry Andric return detail::getHostCPUNameForARM(Content); 1448bdd1243dSDimitry Andric } 1449bdd1243dSDimitry Andric #elif defined(__linux__) && defined(__s390x__) 1450bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1451bdd1243dSDimitry Andric std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1452bdd1243dSDimitry Andric StringRef Content = P ? P->getBuffer() : ""; 1453bdd1243dSDimitry Andric return detail::getHostCPUNameForS390x(Content); 1454bdd1243dSDimitry Andric } 1455bdd1243dSDimitry Andric #elif defined(__MVS__) 1456bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1457bdd1243dSDimitry Andric // Get pointer to Communications Vector Table (CVT). 1458bdd1243dSDimitry Andric // The pointer is located at offset 16 of the Prefixed Save Area (PSA). 1459bdd1243dSDimitry Andric // It is stored as 31 bit pointer and will be zero-extended to 64 bit. 1460bdd1243dSDimitry Andric int *StartToCVTOffset = reinterpret_cast<int *>(0x10); 1461bdd1243dSDimitry Andric // Since its stored as a 31-bit pointer, get the 4 bytes from the start 1462bdd1243dSDimitry Andric // of address. 1463bdd1243dSDimitry Andric int ReadValue = *StartToCVTOffset; 1464bdd1243dSDimitry Andric // Explicitly clear the high order bit. 1465bdd1243dSDimitry Andric ReadValue = (ReadValue & 0x7FFFFFFF); 1466bdd1243dSDimitry Andric char *CVT = reinterpret_cast<char *>(ReadValue); 1467bdd1243dSDimitry Andric // The model number is located in the CVT prefix at offset -6 and stored as 1468bdd1243dSDimitry Andric // signless packed decimal. 1469bdd1243dSDimitry Andric uint16_t Id = *(uint16_t *)&CVT[-6]; 1470bdd1243dSDimitry Andric // Convert number to integer. 1471bdd1243dSDimitry Andric Id = decodePackedBCD<uint16_t>(Id, false); 1472bdd1243dSDimitry Andric // Check for vector support. It's stored in field CVTFLAG5 (offset 244), 1473bdd1243dSDimitry Andric // bit CVTVEF (X'80'). The facilities list is part of the PSA but the vector 1474bdd1243dSDimitry Andric // extension can only be used if bit CVTVEF is on. 1475bdd1243dSDimitry Andric bool HaveVectorSupport = CVT[244] & 0x80; 1476bdd1243dSDimitry Andric return getCPUNameFromS390Model(Id, HaveVectorSupport); 1477bdd1243dSDimitry Andric } 1478bdd1243dSDimitry Andric #elif defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) 1479bdd1243dSDimitry Andric #define CPUFAMILY_ARM_SWIFT 0x1e2d6381 1480bdd1243dSDimitry Andric #define CPUFAMILY_ARM_CYCLONE 0x37a09642 1481bdd1243dSDimitry Andric #define CPUFAMILY_ARM_TYPHOON 0x2c91a47e 1482bdd1243dSDimitry Andric #define CPUFAMILY_ARM_TWISTER 0x92fb37c8 1483bdd1243dSDimitry Andric #define CPUFAMILY_ARM_HURRICANE 0x67ceee93 1484bdd1243dSDimitry Andric #define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6 1485bdd1243dSDimitry Andric #define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f 1486bdd1243dSDimitry Andric #define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2 1487bdd1243dSDimitry Andric #define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb3 1488*0fca6ea1SDimitry Andric #define CPUFAMILY_ARM_BLIZZARD_AVALANCHE 0xda33d83d 1489*0fca6ea1SDimitry Andric #define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea 1490bdd1243dSDimitry Andric 1491bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1492bdd1243dSDimitry Andric uint32_t Family; 1493bdd1243dSDimitry Andric size_t Length = sizeof(Family); 1494bdd1243dSDimitry Andric sysctlbyname("hw.cpufamily", &Family, &Length, NULL, 0); 1495bdd1243dSDimitry Andric 1496bdd1243dSDimitry Andric switch (Family) { 1497bdd1243dSDimitry Andric case CPUFAMILY_ARM_SWIFT: 1498bdd1243dSDimitry Andric return "swift"; 1499bdd1243dSDimitry Andric case CPUFAMILY_ARM_CYCLONE: 1500bdd1243dSDimitry Andric return "apple-a7"; 1501bdd1243dSDimitry Andric case CPUFAMILY_ARM_TYPHOON: 1502bdd1243dSDimitry Andric return "apple-a8"; 1503bdd1243dSDimitry Andric case CPUFAMILY_ARM_TWISTER: 1504bdd1243dSDimitry Andric return "apple-a9"; 1505bdd1243dSDimitry Andric case CPUFAMILY_ARM_HURRICANE: 1506bdd1243dSDimitry Andric return "apple-a10"; 1507bdd1243dSDimitry Andric case CPUFAMILY_ARM_MONSOON_MISTRAL: 1508bdd1243dSDimitry Andric return "apple-a11"; 1509bdd1243dSDimitry Andric case CPUFAMILY_ARM_VORTEX_TEMPEST: 1510bdd1243dSDimitry Andric return "apple-a12"; 1511bdd1243dSDimitry Andric case CPUFAMILY_ARM_LIGHTNING_THUNDER: 1512bdd1243dSDimitry Andric return "apple-a13"; 1513bdd1243dSDimitry Andric case CPUFAMILY_ARM_FIRESTORM_ICESTORM: 1514bdd1243dSDimitry Andric return "apple-m1"; 1515*0fca6ea1SDimitry Andric case CPUFAMILY_ARM_BLIZZARD_AVALANCHE: 1516*0fca6ea1SDimitry Andric return "apple-m2"; 1517*0fca6ea1SDimitry Andric case CPUFAMILY_ARM_EVEREST_SAWTOOTH: 1518*0fca6ea1SDimitry Andric return "apple-m3"; 1519bdd1243dSDimitry Andric default: 1520bdd1243dSDimitry Andric // Default to the newest CPU we know about. 1521*0fca6ea1SDimitry Andric return "apple-m3"; 1522bdd1243dSDimitry Andric } 1523bdd1243dSDimitry Andric } 1524bdd1243dSDimitry Andric #elif defined(_AIX) 1525bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1526bdd1243dSDimitry Andric switch (_system_configuration.implementation) { 1527bdd1243dSDimitry Andric case POWER_4: 1528bdd1243dSDimitry Andric if (_system_configuration.version == PV_4_3) 1529bdd1243dSDimitry Andric return "970"; 1530bdd1243dSDimitry Andric return "pwr4"; 1531bdd1243dSDimitry Andric case POWER_5: 1532bdd1243dSDimitry Andric if (_system_configuration.version == PV_5) 1533bdd1243dSDimitry Andric return "pwr5"; 1534bdd1243dSDimitry Andric return "pwr5x"; 1535bdd1243dSDimitry Andric case POWER_6: 1536bdd1243dSDimitry Andric if (_system_configuration.version == PV_6_Compat) 1537bdd1243dSDimitry Andric return "pwr6"; 1538bdd1243dSDimitry Andric return "pwr6x"; 1539bdd1243dSDimitry Andric case POWER_7: 1540bdd1243dSDimitry Andric return "pwr7"; 1541bdd1243dSDimitry Andric case POWER_8: 1542bdd1243dSDimitry Andric return "pwr8"; 1543bdd1243dSDimitry Andric case POWER_9: 1544bdd1243dSDimitry Andric return "pwr9"; 1545bdd1243dSDimitry Andric // TODO: simplify this once the macro is available in all OS levels. 1546bdd1243dSDimitry Andric #ifdef POWER_10 1547bdd1243dSDimitry Andric case POWER_10: 1548bdd1243dSDimitry Andric #else 1549bdd1243dSDimitry Andric case 0x40000: 1550bdd1243dSDimitry Andric #endif 1551bdd1243dSDimitry Andric return "pwr10"; 1552bdd1243dSDimitry Andric default: 1553bdd1243dSDimitry Andric return "generic"; 1554bdd1243dSDimitry Andric } 1555bdd1243dSDimitry Andric } 155606c3fb27SDimitry Andric #elif defined(__loongarch__) 155706c3fb27SDimitry Andric StringRef sys::getHostCPUName() { 155806c3fb27SDimitry Andric // Use processor id to detect cpu name. 155906c3fb27SDimitry Andric uint32_t processor_id; 156006c3fb27SDimitry Andric __asm__("cpucfg %[prid], $zero\n\t" : [prid] "=r"(processor_id)); 15611db9f3b2SDimitry Andric // Refer PRID_SERIES_MASK in linux kernel: arch/loongarch/include/asm/cpu.h. 15621db9f3b2SDimitry Andric switch (processor_id & 0xf000) { 156306c3fb27SDimitry Andric case 0xc000: // Loongson 64bit, 4-issue 156406c3fb27SDimitry Andric return "la464"; 1565*0fca6ea1SDimitry Andric case 0xd000: // Loongson 64bit, 6-issue 1566*0fca6ea1SDimitry Andric return "la664"; 156706c3fb27SDimitry Andric // TODO: Others. 156806c3fb27SDimitry Andric default: 156906c3fb27SDimitry Andric break; 157006c3fb27SDimitry Andric } 157106c3fb27SDimitry Andric return "generic"; 157206c3fb27SDimitry Andric } 1573bdd1243dSDimitry Andric #elif defined(__riscv) 1574bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1575bdd1243dSDimitry Andric #if defined(__linux__) 1576bdd1243dSDimitry Andric std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1577bdd1243dSDimitry Andric StringRef Content = P ? P->getBuffer() : ""; 1578*0fca6ea1SDimitry Andric StringRef Name = detail::getHostCPUNameForRISCV(Content); 1579*0fca6ea1SDimitry Andric if (!Name.empty()) 1580*0fca6ea1SDimitry Andric return Name; 1581*0fca6ea1SDimitry Andric #endif 1582bdd1243dSDimitry Andric #if __riscv_xlen == 64 1583bdd1243dSDimitry Andric return "generic-rv64"; 1584bdd1243dSDimitry Andric #elif __riscv_xlen == 32 1585bdd1243dSDimitry Andric return "generic-rv32"; 1586bdd1243dSDimitry Andric #else 1587bdd1243dSDimitry Andric #error "Unhandled value of __riscv_xlen" 1588bdd1243dSDimitry Andric #endif 1589bdd1243dSDimitry Andric } 1590bdd1243dSDimitry Andric #elif defined(__sparc__) 1591bdd1243dSDimitry Andric #if defined(__linux__) 1592bdd1243dSDimitry Andric StringRef sys::detail::getHostCPUNameForSPARC(StringRef ProcCpuinfoContent) { 1593bdd1243dSDimitry Andric SmallVector<StringRef> Lines; 1594bdd1243dSDimitry Andric ProcCpuinfoContent.split(Lines, "\n"); 1595bdd1243dSDimitry Andric 1596bdd1243dSDimitry Andric // Look for cpu line to determine cpu name 1597bdd1243dSDimitry Andric StringRef Cpu; 1598bdd1243dSDimitry Andric for (unsigned I = 0, E = Lines.size(); I != E; ++I) { 15995f757f3fSDimitry Andric if (Lines[I].starts_with("cpu")) { 1600bdd1243dSDimitry Andric Cpu = Lines[I].substr(5).ltrim("\t :"); 1601bdd1243dSDimitry Andric break; 1602bdd1243dSDimitry Andric } 1603bdd1243dSDimitry Andric } 1604bdd1243dSDimitry Andric 1605bdd1243dSDimitry Andric return StringSwitch<const char *>(Cpu) 1606bdd1243dSDimitry Andric .StartsWith("SuperSparc", "supersparc") 1607bdd1243dSDimitry Andric .StartsWith("HyperSparc", "hypersparc") 1608bdd1243dSDimitry Andric .StartsWith("SpitFire", "ultrasparc") 1609bdd1243dSDimitry Andric .StartsWith("BlackBird", "ultrasparc") 1610bdd1243dSDimitry Andric .StartsWith("Sabre", " ultrasparc") 1611bdd1243dSDimitry Andric .StartsWith("Hummingbird", "ultrasparc") 1612bdd1243dSDimitry Andric .StartsWith("Cheetah", "ultrasparc3") 1613bdd1243dSDimitry Andric .StartsWith("Jalapeno", "ultrasparc3") 1614bdd1243dSDimitry Andric .StartsWith("Jaguar", "ultrasparc3") 1615bdd1243dSDimitry Andric .StartsWith("Panther", "ultrasparc3") 1616bdd1243dSDimitry Andric .StartsWith("Serrano", "ultrasparc3") 1617bdd1243dSDimitry Andric .StartsWith("UltraSparc T1", "niagara") 1618bdd1243dSDimitry Andric .StartsWith("UltraSparc T2", "niagara2") 1619bdd1243dSDimitry Andric .StartsWith("UltraSparc T3", "niagara3") 1620bdd1243dSDimitry Andric .StartsWith("UltraSparc T4", "niagara4") 1621bdd1243dSDimitry Andric .StartsWith("UltraSparc T5", "niagara4") 1622bdd1243dSDimitry Andric .StartsWith("LEON", "leon3") 1623bdd1243dSDimitry Andric // niagara7/m8 not supported by LLVM yet. 1624bdd1243dSDimitry Andric .StartsWith("SPARC-M7", "niagara4" /* "niagara7" */) 1625bdd1243dSDimitry Andric .StartsWith("SPARC-S7", "niagara4" /* "niagara7" */) 1626bdd1243dSDimitry Andric .StartsWith("SPARC-M8", "niagara4" /* "m8" */) 1627bdd1243dSDimitry Andric .Default("generic"); 1628bdd1243dSDimitry Andric } 1629bdd1243dSDimitry Andric #endif 1630bdd1243dSDimitry Andric 1631bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { 1632bdd1243dSDimitry Andric #if defined(__linux__) 1633bdd1243dSDimitry Andric std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1634bdd1243dSDimitry Andric StringRef Content = P ? P->getBuffer() : ""; 1635bdd1243dSDimitry Andric return detail::getHostCPUNameForSPARC(Content); 1636bdd1243dSDimitry Andric #elif defined(__sun__) && defined(__svr4__) 1637bdd1243dSDimitry Andric char *buf = NULL; 1638bdd1243dSDimitry Andric kstat_ctl_t *kc; 1639bdd1243dSDimitry Andric kstat_t *ksp; 1640bdd1243dSDimitry Andric kstat_named_t *brand = NULL; 1641bdd1243dSDimitry Andric 1642bdd1243dSDimitry Andric kc = kstat_open(); 1643bdd1243dSDimitry Andric if (kc != NULL) { 1644bdd1243dSDimitry Andric ksp = kstat_lookup(kc, const_cast<char *>("cpu_info"), -1, NULL); 1645bdd1243dSDimitry Andric if (ksp != NULL && kstat_read(kc, ksp, NULL) != -1 && 1646bdd1243dSDimitry Andric ksp->ks_type == KSTAT_TYPE_NAMED) 1647bdd1243dSDimitry Andric brand = 1648bdd1243dSDimitry Andric (kstat_named_t *)kstat_data_lookup(ksp, const_cast<char *>("brand")); 1649bdd1243dSDimitry Andric if (brand != NULL && brand->data_type == KSTAT_DATA_STRING) 1650bdd1243dSDimitry Andric buf = KSTAT_NAMED_STR_PTR(brand); 1651bdd1243dSDimitry Andric } 1652bdd1243dSDimitry Andric kstat_close(kc); 1653bdd1243dSDimitry Andric 1654bdd1243dSDimitry Andric return StringSwitch<const char *>(buf) 1655bdd1243dSDimitry Andric .Case("TMS390S10", "supersparc") // Texas Instruments microSPARC I 1656bdd1243dSDimitry Andric .Case("TMS390Z50", "supersparc") // Texas Instruments SuperSPARC I 1657bdd1243dSDimitry Andric .Case("TMS390Z55", 1658bdd1243dSDimitry Andric "supersparc") // Texas Instruments SuperSPARC I with SuperCache 1659bdd1243dSDimitry Andric .Case("MB86904", "supersparc") // Fujitsu microSPARC II 1660bdd1243dSDimitry Andric .Case("MB86907", "supersparc") // Fujitsu TurboSPARC 1661bdd1243dSDimitry Andric .Case("RT623", "hypersparc") // Ross hyperSPARC 1662bdd1243dSDimitry Andric .Case("RT625", "hypersparc") 1663bdd1243dSDimitry Andric .Case("RT626", "hypersparc") 1664bdd1243dSDimitry Andric .Case("UltraSPARC-I", "ultrasparc") 1665bdd1243dSDimitry Andric .Case("UltraSPARC-II", "ultrasparc") 1666bdd1243dSDimitry Andric .Case("UltraSPARC-IIe", "ultrasparc") 1667bdd1243dSDimitry Andric .Case("UltraSPARC-IIi", "ultrasparc") 1668bdd1243dSDimitry Andric .Case("SPARC64-III", "ultrasparc") 1669bdd1243dSDimitry Andric .Case("SPARC64-IV", "ultrasparc") 1670bdd1243dSDimitry Andric .Case("UltraSPARC-III", "ultrasparc3") 1671bdd1243dSDimitry Andric .Case("UltraSPARC-III+", "ultrasparc3") 1672bdd1243dSDimitry Andric .Case("UltraSPARC-IIIi", "ultrasparc3") 1673bdd1243dSDimitry Andric .Case("UltraSPARC-IIIi+", "ultrasparc3") 1674bdd1243dSDimitry Andric .Case("UltraSPARC-IV", "ultrasparc3") 1675bdd1243dSDimitry Andric .Case("UltraSPARC-IV+", "ultrasparc3") 1676bdd1243dSDimitry Andric .Case("SPARC64-V", "ultrasparc3") 1677bdd1243dSDimitry Andric .Case("SPARC64-VI", "ultrasparc3") 1678bdd1243dSDimitry Andric .Case("SPARC64-VII", "ultrasparc3") 1679bdd1243dSDimitry Andric .Case("UltraSPARC-T1", "niagara") 1680bdd1243dSDimitry Andric .Case("UltraSPARC-T2", "niagara2") 1681bdd1243dSDimitry Andric .Case("UltraSPARC-T2", "niagara2") 1682bdd1243dSDimitry Andric .Case("UltraSPARC-T2+", "niagara2") 1683bdd1243dSDimitry Andric .Case("SPARC-T3", "niagara3") 1684bdd1243dSDimitry Andric .Case("SPARC-T4", "niagara4") 1685bdd1243dSDimitry Andric .Case("SPARC-T5", "niagara4") 1686bdd1243dSDimitry Andric // niagara7/m8 not supported by LLVM yet. 1687bdd1243dSDimitry Andric .Case("SPARC-M7", "niagara4" /* "niagara7" */) 1688bdd1243dSDimitry Andric .Case("SPARC-S7", "niagara4" /* "niagara7" */) 1689bdd1243dSDimitry Andric .Case("SPARC-M8", "niagara4" /* "m8" */) 1690bdd1243dSDimitry Andric .Default("generic"); 1691bdd1243dSDimitry Andric #else 1692bdd1243dSDimitry Andric return "generic"; 1693bdd1243dSDimitry Andric #endif 1694bdd1243dSDimitry Andric } 1695bdd1243dSDimitry Andric #else 1696bdd1243dSDimitry Andric StringRef sys::getHostCPUName() { return "generic"; } 1697bdd1243dSDimitry Andric namespace llvm { 1698bdd1243dSDimitry Andric namespace sys { 1699bdd1243dSDimitry Andric namespace detail { 1700bdd1243dSDimitry Andric namespace x86 { 1701bdd1243dSDimitry Andric 1702bdd1243dSDimitry Andric VendorSignatures getVendorSignature(unsigned *MaxLeaf) { 1703bdd1243dSDimitry Andric return VendorSignatures::UNKNOWN; 1704bdd1243dSDimitry Andric } 1705bdd1243dSDimitry Andric 1706bdd1243dSDimitry Andric } // namespace x86 1707bdd1243dSDimitry Andric } // namespace detail 1708bdd1243dSDimitry Andric } // namespace sys 1709bdd1243dSDimitry Andric } // namespace llvm 1710bdd1243dSDimitry Andric #endif 1711bdd1243dSDimitry Andric 1712bdd1243dSDimitry Andric #if defined(__i386__) || defined(_M_IX86) || \ 1713bdd1243dSDimitry Andric defined(__x86_64__) || defined(_M_X64) 1714*0fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() { 1715bdd1243dSDimitry Andric unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 1716bdd1243dSDimitry Andric unsigned MaxLevel; 1717*0fca6ea1SDimitry Andric StringMap<bool> Features; 1718bdd1243dSDimitry Andric 1719bdd1243dSDimitry Andric if (getX86CpuIDAndInfo(0, &MaxLevel, &EBX, &ECX, &EDX) || MaxLevel < 1) 1720*0fca6ea1SDimitry Andric return Features; 1721bdd1243dSDimitry Andric 1722bdd1243dSDimitry Andric getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX); 1723bdd1243dSDimitry Andric 1724bdd1243dSDimitry Andric Features["cx8"] = (EDX >> 8) & 1; 1725bdd1243dSDimitry Andric Features["cmov"] = (EDX >> 15) & 1; 1726bdd1243dSDimitry Andric Features["mmx"] = (EDX >> 23) & 1; 1727bdd1243dSDimitry Andric Features["fxsr"] = (EDX >> 24) & 1; 1728bdd1243dSDimitry Andric Features["sse"] = (EDX >> 25) & 1; 1729bdd1243dSDimitry Andric Features["sse2"] = (EDX >> 26) & 1; 1730bdd1243dSDimitry Andric 1731bdd1243dSDimitry Andric Features["sse3"] = (ECX >> 0) & 1; 1732bdd1243dSDimitry Andric Features["pclmul"] = (ECX >> 1) & 1; 1733bdd1243dSDimitry Andric Features["ssse3"] = (ECX >> 9) & 1; 1734bdd1243dSDimitry Andric Features["cx16"] = (ECX >> 13) & 1; 1735bdd1243dSDimitry Andric Features["sse4.1"] = (ECX >> 19) & 1; 1736bdd1243dSDimitry Andric Features["sse4.2"] = (ECX >> 20) & 1; 1737bdd1243dSDimitry Andric Features["crc32"] = Features["sse4.2"]; 1738bdd1243dSDimitry Andric Features["movbe"] = (ECX >> 22) & 1; 1739bdd1243dSDimitry Andric Features["popcnt"] = (ECX >> 23) & 1; 1740bdd1243dSDimitry Andric Features["aes"] = (ECX >> 25) & 1; 1741bdd1243dSDimitry Andric Features["rdrnd"] = (ECX >> 30) & 1; 1742bdd1243dSDimitry Andric 1743bdd1243dSDimitry Andric // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV 1744bdd1243dSDimitry Andric // indicates that the AVX registers will be saved and restored on context 1745bdd1243dSDimitry Andric // switch, then we have full AVX support. 1746bdd1243dSDimitry Andric bool HasXSave = ((ECX >> 27) & 1) && !getX86XCR0(&EAX, &EDX); 1747bdd1243dSDimitry Andric bool HasAVXSave = HasXSave && ((ECX >> 28) & 1) && ((EAX & 0x6) == 0x6); 1748bdd1243dSDimitry Andric #if defined(__APPLE__) 1749bdd1243dSDimitry Andric // Darwin lazily saves the AVX512 context on first use: trust that the OS will 1750bdd1243dSDimitry Andric // save the AVX512 context if we use AVX512 instructions, even the bit is not 1751bdd1243dSDimitry Andric // set right now. 1752bdd1243dSDimitry Andric bool HasAVX512Save = true; 1753bdd1243dSDimitry Andric #else 1754bdd1243dSDimitry Andric // AVX512 requires additional context to be saved by the OS. 1755bdd1243dSDimitry Andric bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0); 1756bdd1243dSDimitry Andric #endif 1757bdd1243dSDimitry Andric // AMX requires additional context to be saved by the OS. 1758bdd1243dSDimitry Andric const unsigned AMXBits = (1 << 17) | (1 << 18); 1759bdd1243dSDimitry Andric bool HasAMXSave = HasXSave && ((EAX & AMXBits) == AMXBits); 1760bdd1243dSDimitry Andric 1761bdd1243dSDimitry Andric Features["avx"] = HasAVXSave; 1762bdd1243dSDimitry Andric Features["fma"] = ((ECX >> 12) & 1) && HasAVXSave; 1763bdd1243dSDimitry Andric // Only enable XSAVE if OS has enabled support for saving YMM state. 1764bdd1243dSDimitry Andric Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave; 1765bdd1243dSDimitry Andric Features["f16c"] = ((ECX >> 29) & 1) && HasAVXSave; 1766bdd1243dSDimitry Andric 1767bdd1243dSDimitry Andric unsigned MaxExtLevel; 1768bdd1243dSDimitry Andric getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX); 1769bdd1243dSDimitry Andric 1770bdd1243dSDimitry Andric bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 && 1771bdd1243dSDimitry Andric !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 1772bdd1243dSDimitry Andric Features["sahf"] = HasExtLeaf1 && ((ECX >> 0) & 1); 1773bdd1243dSDimitry Andric Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1); 1774bdd1243dSDimitry Andric Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1); 1775bdd1243dSDimitry Andric Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1); 1776bdd1243dSDimitry Andric Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave; 1777bdd1243dSDimitry Andric Features["lwp"] = HasExtLeaf1 && ((ECX >> 15) & 1); 1778bdd1243dSDimitry Andric Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave; 1779bdd1243dSDimitry Andric Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1); 1780bdd1243dSDimitry Andric Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1); 1781bdd1243dSDimitry Andric 1782bdd1243dSDimitry Andric Features["64bit"] = HasExtLeaf1 && ((EDX >> 29) & 1); 1783bdd1243dSDimitry Andric 1784bdd1243dSDimitry Andric // Miscellaneous memory related features, detected by 1785bdd1243dSDimitry Andric // using the 0x80000008 leaf of the CPUID instruction 1786bdd1243dSDimitry Andric bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 && 1787bdd1243dSDimitry Andric !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX); 1788bdd1243dSDimitry Andric Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1); 1789bdd1243dSDimitry Andric Features["rdpru"] = HasExtLeaf8 && ((EBX >> 4) & 1); 1790bdd1243dSDimitry Andric Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1); 1791bdd1243dSDimitry Andric 1792bdd1243dSDimitry Andric bool HasLeaf7 = 1793bdd1243dSDimitry Andric MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); 1794bdd1243dSDimitry Andric 1795bdd1243dSDimitry Andric Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1); 1796bdd1243dSDimitry Andric Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1); 1797bdd1243dSDimitry Andric Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1); 1798bdd1243dSDimitry Andric // AVX2 is only supported if we have the OS save support from AVX. 1799bdd1243dSDimitry Andric Features["avx2"] = HasLeaf7 && ((EBX >> 5) & 1) && HasAVXSave; 1800bdd1243dSDimitry Andric Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1); 1801bdd1243dSDimitry Andric Features["invpcid"] = HasLeaf7 && ((EBX >> 10) & 1); 1802bdd1243dSDimitry Andric Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1); 1803bdd1243dSDimitry Andric // AVX512 is only supported if the OS supports the context save for it. 1804bdd1243dSDimitry Andric Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save; 1805fcfb2d63SDimitry Andric if (Features["avx512f"]) 1806fcfb2d63SDimitry Andric Features["evex512"] = true; 1807bdd1243dSDimitry Andric Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save; 1808bdd1243dSDimitry Andric Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1); 1809bdd1243dSDimitry Andric Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1); 1810bdd1243dSDimitry Andric Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save; 1811bdd1243dSDimitry Andric Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1); 1812bdd1243dSDimitry Andric Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1); 1813bdd1243dSDimitry Andric Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save; 1814bdd1243dSDimitry Andric Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1); 1815bdd1243dSDimitry Andric Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save; 1816bdd1243dSDimitry Andric Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save; 1817bdd1243dSDimitry Andric 1818bdd1243dSDimitry Andric Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save; 1819bdd1243dSDimitry Andric Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1); 1820bdd1243dSDimitry Andric Features["waitpkg"] = HasLeaf7 && ((ECX >> 5) & 1); 1821bdd1243dSDimitry Andric Features["avx512vbmi2"] = HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save; 1822bdd1243dSDimitry Andric Features["shstk"] = HasLeaf7 && ((ECX >> 7) & 1); 1823bdd1243dSDimitry Andric Features["gfni"] = HasLeaf7 && ((ECX >> 8) & 1); 1824bdd1243dSDimitry Andric Features["vaes"] = HasLeaf7 && ((ECX >> 9) & 1) && HasAVXSave; 1825bdd1243dSDimitry Andric Features["vpclmulqdq"] = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave; 1826bdd1243dSDimitry Andric Features["avx512vnni"] = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save; 1827bdd1243dSDimitry Andric Features["avx512bitalg"] = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save; 1828bdd1243dSDimitry Andric Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save; 1829bdd1243dSDimitry Andric Features["rdpid"] = HasLeaf7 && ((ECX >> 22) & 1); 1830bdd1243dSDimitry Andric Features["kl"] = HasLeaf7 && ((ECX >> 23) & 1); // key locker 1831bdd1243dSDimitry Andric Features["cldemote"] = HasLeaf7 && ((ECX >> 25) & 1); 1832bdd1243dSDimitry Andric Features["movdiri"] = HasLeaf7 && ((ECX >> 27) & 1); 1833bdd1243dSDimitry Andric Features["movdir64b"] = HasLeaf7 && ((ECX >> 28) & 1); 1834bdd1243dSDimitry Andric Features["enqcmd"] = HasLeaf7 && ((ECX >> 29) & 1); 1835bdd1243dSDimitry Andric 1836bdd1243dSDimitry Andric Features["uintr"] = HasLeaf7 && ((EDX >> 5) & 1); 1837bdd1243dSDimitry Andric Features["avx512vp2intersect"] = 1838bdd1243dSDimitry Andric HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save; 1839bdd1243dSDimitry Andric Features["serialize"] = HasLeaf7 && ((EDX >> 14) & 1); 1840bdd1243dSDimitry Andric Features["tsxldtrk"] = HasLeaf7 && ((EDX >> 16) & 1); 1841bdd1243dSDimitry Andric // There are two CPUID leafs which information associated with the pconfig 1842bdd1243dSDimitry Andric // instruction: 1843bdd1243dSDimitry Andric // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th 1844bdd1243dSDimitry Andric // bit of EDX), while the EAX=0x1b leaf returns information on the 1845bdd1243dSDimitry Andric // availability of specific pconfig leafs. 1846bdd1243dSDimitry Andric // The target feature here only refers to the the first of these two. 1847bdd1243dSDimitry Andric // Users might need to check for the availability of specific pconfig 1848bdd1243dSDimitry Andric // leaves using cpuid, since that information is ignored while 1849bdd1243dSDimitry Andric // detecting features using the "-march=native" flag. 1850bdd1243dSDimitry Andric // For more info, see X86 ISA docs. 1851bdd1243dSDimitry Andric Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1); 1852bdd1243dSDimitry Andric Features["amx-bf16"] = HasLeaf7 && ((EDX >> 22) & 1) && HasAMXSave; 1853bdd1243dSDimitry Andric Features["avx512fp16"] = HasLeaf7 && ((EDX >> 23) & 1) && HasAVX512Save; 1854bdd1243dSDimitry Andric Features["amx-tile"] = HasLeaf7 && ((EDX >> 24) & 1) && HasAMXSave; 1855bdd1243dSDimitry Andric Features["amx-int8"] = HasLeaf7 && ((EDX >> 25) & 1) && HasAMXSave; 18568a4dda33SDimitry Andric // EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't 18578a4dda33SDimitry Andric // return all 0s for invalid subleaves so check the limit. 1858bdd1243dSDimitry Andric bool HasLeaf7Subleaf1 = 18598a4dda33SDimitry Andric HasLeaf7 && EAX >= 1 && 18608a4dda33SDimitry Andric !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX); 186106c3fb27SDimitry Andric Features["sha512"] = HasLeaf7Subleaf1 && ((EAX >> 0) & 1); 186206c3fb27SDimitry Andric Features["sm3"] = HasLeaf7Subleaf1 && ((EAX >> 1) & 1); 186306c3fb27SDimitry Andric Features["sm4"] = HasLeaf7Subleaf1 && ((EAX >> 2) & 1); 1864bdd1243dSDimitry Andric Features["raoint"] = HasLeaf7Subleaf1 && ((EAX >> 3) & 1); 1865bdd1243dSDimitry Andric Features["avxvnni"] = HasLeaf7Subleaf1 && ((EAX >> 4) & 1) && HasAVXSave; 1866bdd1243dSDimitry Andric Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save; 1867bdd1243dSDimitry Andric Features["amx-fp16"] = HasLeaf7Subleaf1 && ((EAX >> 21) & 1) && HasAMXSave; 1868bdd1243dSDimitry Andric Features["cmpccxadd"] = HasLeaf7Subleaf1 && ((EAX >> 7) & 1); 1869bdd1243dSDimitry Andric Features["hreset"] = HasLeaf7Subleaf1 && ((EAX >> 22) & 1); 1870bdd1243dSDimitry Andric Features["avxifma"] = HasLeaf7Subleaf1 && ((EAX >> 23) & 1) && HasAVXSave; 1871bdd1243dSDimitry Andric Features["avxvnniint8"] = HasLeaf7Subleaf1 && ((EDX >> 4) & 1) && HasAVXSave; 1872bdd1243dSDimitry Andric Features["avxneconvert"] = HasLeaf7Subleaf1 && ((EDX >> 5) & 1) && HasAVXSave; 187306c3fb27SDimitry Andric Features["amx-complex"] = HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave; 187406c3fb27SDimitry Andric Features["avxvnniint16"] = HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave; 1875bdd1243dSDimitry Andric Features["prefetchi"] = HasLeaf7Subleaf1 && ((EDX >> 14) & 1); 18765f757f3fSDimitry Andric Features["usermsr"] = HasLeaf7Subleaf1 && ((EDX >> 15) & 1); 18775f757f3fSDimitry Andric Features["avx10.1-256"] = HasLeaf7Subleaf1 && ((EDX >> 19) & 1); 1878*0fca6ea1SDimitry Andric bool HasAPXF = HasLeaf7Subleaf1 && ((EDX >> 21) & 1); 1879*0fca6ea1SDimitry Andric Features["egpr"] = HasAPXF; 1880*0fca6ea1SDimitry Andric Features["push2pop2"] = HasAPXF; 1881*0fca6ea1SDimitry Andric Features["ppx"] = HasAPXF; 1882*0fca6ea1SDimitry Andric Features["ndd"] = HasAPXF; 1883*0fca6ea1SDimitry Andric Features["ccmp"] = HasAPXF; 1884*0fca6ea1SDimitry Andric Features["cf"] = HasAPXF; 1885bdd1243dSDimitry Andric 1886bdd1243dSDimitry Andric bool HasLeafD = MaxLevel >= 0xd && 1887bdd1243dSDimitry Andric !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX); 1888bdd1243dSDimitry Andric 1889bdd1243dSDimitry Andric // Only enable XSAVE if OS has enabled support for saving YMM state. 1890bdd1243dSDimitry Andric Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave; 1891bdd1243dSDimitry Andric Features["xsavec"] = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave; 1892bdd1243dSDimitry Andric Features["xsaves"] = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave; 1893bdd1243dSDimitry Andric 1894bdd1243dSDimitry Andric bool HasLeaf14 = MaxLevel >= 0x14 && 1895bdd1243dSDimitry Andric !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX); 1896bdd1243dSDimitry Andric 1897bdd1243dSDimitry Andric Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1); 1898bdd1243dSDimitry Andric 1899bdd1243dSDimitry Andric bool HasLeaf19 = 1900bdd1243dSDimitry Andric MaxLevel >= 0x19 && !getX86CpuIDAndInfo(0x19, &EAX, &EBX, &ECX, &EDX); 1901bdd1243dSDimitry Andric Features["widekl"] = HasLeaf7 && HasLeaf19 && ((EBX >> 2) & 1); 1902bdd1243dSDimitry Andric 19035f757f3fSDimitry Andric bool HasLeaf24 = 19045f757f3fSDimitry Andric MaxLevel >= 0x24 && !getX86CpuIDAndInfo(0x24, &EAX, &EBX, &ECX, &EDX); 19055f757f3fSDimitry Andric Features["avx10.1-512"] = 19065f757f3fSDimitry Andric Features["avx10.1-256"] && HasLeaf24 && ((EBX >> 18) & 1); 19075f757f3fSDimitry Andric 1908*0fca6ea1SDimitry Andric return Features; 1909bdd1243dSDimitry Andric } 1910bdd1243dSDimitry Andric #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__)) 1911*0fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() { 1912*0fca6ea1SDimitry Andric StringMap<bool> Features; 1913bdd1243dSDimitry Andric std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); 1914bdd1243dSDimitry Andric if (!P) 1915*0fca6ea1SDimitry Andric return Features; 1916bdd1243dSDimitry Andric 1917bdd1243dSDimitry Andric SmallVector<StringRef, 32> Lines; 1918bdd1243dSDimitry Andric P->getBuffer().split(Lines, "\n"); 1919bdd1243dSDimitry Andric 1920bdd1243dSDimitry Andric SmallVector<StringRef, 32> CPUFeatures; 1921bdd1243dSDimitry Andric 1922bdd1243dSDimitry Andric // Look for the CPU features. 1923bdd1243dSDimitry Andric for (unsigned I = 0, E = Lines.size(); I != E; ++I) 19245f757f3fSDimitry Andric if (Lines[I].starts_with("Features")) { 1925bdd1243dSDimitry Andric Lines[I].split(CPUFeatures, ' '); 1926bdd1243dSDimitry Andric break; 1927bdd1243dSDimitry Andric } 1928bdd1243dSDimitry Andric 1929bdd1243dSDimitry Andric #if defined(__aarch64__) 1930bdd1243dSDimitry Andric // Keep track of which crypto features we have seen 1931bdd1243dSDimitry Andric enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 }; 1932bdd1243dSDimitry Andric uint32_t crypto = 0; 1933bdd1243dSDimitry Andric #endif 1934bdd1243dSDimitry Andric 1935bdd1243dSDimitry Andric for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { 1936bdd1243dSDimitry Andric StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I]) 1937bdd1243dSDimitry Andric #if defined(__aarch64__) 1938bdd1243dSDimitry Andric .Case("asimd", "neon") 1939bdd1243dSDimitry Andric .Case("fp", "fp-armv8") 1940bdd1243dSDimitry Andric .Case("crc32", "crc") 1941bdd1243dSDimitry Andric .Case("atomics", "lse") 1942bdd1243dSDimitry Andric .Case("sve", "sve") 1943bdd1243dSDimitry Andric .Case("sve2", "sve2") 1944bdd1243dSDimitry Andric #else 1945bdd1243dSDimitry Andric .Case("half", "fp16") 1946bdd1243dSDimitry Andric .Case("neon", "neon") 1947bdd1243dSDimitry Andric .Case("vfpv3", "vfp3") 1948bdd1243dSDimitry Andric .Case("vfpv3d16", "vfp3d16") 1949bdd1243dSDimitry Andric .Case("vfpv4", "vfp4") 1950bdd1243dSDimitry Andric .Case("idiva", "hwdiv-arm") 1951bdd1243dSDimitry Andric .Case("idivt", "hwdiv") 1952bdd1243dSDimitry Andric #endif 1953bdd1243dSDimitry Andric .Default(""); 1954bdd1243dSDimitry Andric 1955bdd1243dSDimitry Andric #if defined(__aarch64__) 1956bdd1243dSDimitry Andric // We need to check crypto separately since we need all of the crypto 1957bdd1243dSDimitry Andric // extensions to enable the subtarget feature 1958bdd1243dSDimitry Andric if (CPUFeatures[I] == "aes") 1959bdd1243dSDimitry Andric crypto |= CAP_AES; 1960bdd1243dSDimitry Andric else if (CPUFeatures[I] == "pmull") 1961bdd1243dSDimitry Andric crypto |= CAP_PMULL; 1962bdd1243dSDimitry Andric else if (CPUFeatures[I] == "sha1") 1963bdd1243dSDimitry Andric crypto |= CAP_SHA1; 1964bdd1243dSDimitry Andric else if (CPUFeatures[I] == "sha2") 1965bdd1243dSDimitry Andric crypto |= CAP_SHA2; 1966bdd1243dSDimitry Andric #endif 1967bdd1243dSDimitry Andric 1968bdd1243dSDimitry Andric if (LLVMFeatureStr != "") 1969bdd1243dSDimitry Andric Features[LLVMFeatureStr] = true; 1970bdd1243dSDimitry Andric } 1971bdd1243dSDimitry Andric 1972bdd1243dSDimitry Andric #if defined(__aarch64__) 1973bdd1243dSDimitry Andric // If we have all crypto bits we can add the feature 1974bdd1243dSDimitry Andric if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2)) 1975bdd1243dSDimitry Andric Features["crypto"] = true; 1976bdd1243dSDimitry Andric #endif 1977bdd1243dSDimitry Andric 1978*0fca6ea1SDimitry Andric return Features; 1979bdd1243dSDimitry Andric } 1980bdd1243dSDimitry Andric #elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64)) 1981*0fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() { 1982*0fca6ea1SDimitry Andric StringMap<bool> Features; 1983*0fca6ea1SDimitry Andric 1984bdd1243dSDimitry Andric if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE)) 1985bdd1243dSDimitry Andric Features["neon"] = true; 1986bdd1243dSDimitry Andric if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) 1987bdd1243dSDimitry Andric Features["crc"] = true; 1988bdd1243dSDimitry Andric if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) 1989bdd1243dSDimitry Andric Features["crypto"] = true; 1990bdd1243dSDimitry Andric 1991*0fca6ea1SDimitry Andric return Features; 1992bdd1243dSDimitry Andric } 199306c3fb27SDimitry Andric #elif defined(__linux__) && defined(__loongarch__) 199406c3fb27SDimitry Andric #include <sys/auxv.h> 1995*0fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() { 199606c3fb27SDimitry Andric unsigned long hwcap = getauxval(AT_HWCAP); 199706c3fb27SDimitry Andric bool HasFPU = hwcap & (1UL << 3); // HWCAP_LOONGARCH_FPU 199806c3fb27SDimitry Andric uint32_t cpucfg2 = 0x2; 199906c3fb27SDimitry Andric __asm__("cpucfg %[cpucfg2], %[cpucfg2]\n\t" : [cpucfg2] "+r"(cpucfg2)); 200006c3fb27SDimitry Andric 2001*0fca6ea1SDimitry Andric StringMap<bool> Features; 2002*0fca6ea1SDimitry Andric 200306c3fb27SDimitry Andric Features["f"] = HasFPU && (cpucfg2 & (1U << 1)); // CPUCFG.2.FP_SP 200406c3fb27SDimitry Andric Features["d"] = HasFPU && (cpucfg2 & (1U << 2)); // CPUCFG.2.FP_DP 200506c3fb27SDimitry Andric 200606c3fb27SDimitry Andric Features["lsx"] = hwcap & (1UL << 4); // HWCAP_LOONGARCH_LSX 200706c3fb27SDimitry Andric Features["lasx"] = hwcap & (1UL << 5); // HWCAP_LOONGARCH_LASX 200806c3fb27SDimitry Andric Features["lvz"] = hwcap & (1UL << 9); // HWCAP_LOONGARCH_LVZ 200906c3fb27SDimitry Andric 2010*0fca6ea1SDimitry Andric return Features; 2011*0fca6ea1SDimitry Andric } 2012*0fca6ea1SDimitry Andric #elif defined(__linux__) && defined(__riscv) 2013*0fca6ea1SDimitry Andric // struct riscv_hwprobe 2014*0fca6ea1SDimitry Andric struct RISCVHwProbe { 2015*0fca6ea1SDimitry Andric int64_t Key; 2016*0fca6ea1SDimitry Andric uint64_t Value; 2017*0fca6ea1SDimitry Andric }; 2018*0fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() { 2019*0fca6ea1SDimitry Andric RISCVHwProbe Query[]{{/*RISCV_HWPROBE_KEY_BASE_BEHAVIOR=*/3, 0}, 2020*0fca6ea1SDimitry Andric {/*RISCV_HWPROBE_KEY_IMA_EXT_0=*/4, 0}}; 2021*0fca6ea1SDimitry Andric int Ret = syscall(/*__NR_riscv_hwprobe=*/258, /*pairs=*/Query, 2022*0fca6ea1SDimitry Andric /*pair_count=*/std::size(Query), /*cpu_count=*/0, 2023*0fca6ea1SDimitry Andric /*cpus=*/0, /*flags=*/0); 2024*0fca6ea1SDimitry Andric if (Ret != 0) 2025*0fca6ea1SDimitry Andric return {}; 2026*0fca6ea1SDimitry Andric 2027*0fca6ea1SDimitry Andric StringMap<bool> Features; 2028*0fca6ea1SDimitry Andric uint64_t BaseMask = Query[0].Value; 2029*0fca6ea1SDimitry Andric // Check whether RISCV_HWPROBE_BASE_BEHAVIOR_IMA is set. 2030*0fca6ea1SDimitry Andric if (BaseMask & 1) { 2031*0fca6ea1SDimitry Andric Features["i"] = true; 2032*0fca6ea1SDimitry Andric Features["m"] = true; 2033*0fca6ea1SDimitry Andric Features["a"] = true; 2034*0fca6ea1SDimitry Andric } 2035*0fca6ea1SDimitry Andric 2036*0fca6ea1SDimitry Andric uint64_t ExtMask = Query[1].Value; 2037*0fca6ea1SDimitry Andric Features["f"] = ExtMask & (1 << 0); // RISCV_HWPROBE_IMA_FD 2038*0fca6ea1SDimitry Andric Features["d"] = ExtMask & (1 << 0); // RISCV_HWPROBE_IMA_FD 2039*0fca6ea1SDimitry Andric Features["c"] = ExtMask & (1 << 1); // RISCV_HWPROBE_IMA_C 2040*0fca6ea1SDimitry Andric Features["v"] = ExtMask & (1 << 2); // RISCV_HWPROBE_IMA_V 2041*0fca6ea1SDimitry Andric Features["zba"] = ExtMask & (1 << 3); // RISCV_HWPROBE_EXT_ZBA 2042*0fca6ea1SDimitry Andric Features["zbb"] = ExtMask & (1 << 4); // RISCV_HWPROBE_EXT_ZBB 2043*0fca6ea1SDimitry Andric Features["zbs"] = ExtMask & (1 << 5); // RISCV_HWPROBE_EXT_ZBS 2044*0fca6ea1SDimitry Andric Features["zicboz"] = ExtMask & (1 << 6); // RISCV_HWPROBE_EXT_ZICBOZ 2045*0fca6ea1SDimitry Andric Features["zbc"] = ExtMask & (1 << 7); // RISCV_HWPROBE_EXT_ZBC 2046*0fca6ea1SDimitry Andric Features["zbkb"] = ExtMask & (1 << 8); // RISCV_HWPROBE_EXT_ZBKB 2047*0fca6ea1SDimitry Andric Features["zbkc"] = ExtMask & (1 << 9); // RISCV_HWPROBE_EXT_ZBKC 2048*0fca6ea1SDimitry Andric Features["zbkx"] = ExtMask & (1 << 10); // RISCV_HWPROBE_EXT_ZBKX 2049*0fca6ea1SDimitry Andric Features["zknd"] = ExtMask & (1 << 11); // RISCV_HWPROBE_EXT_ZKND 2050*0fca6ea1SDimitry Andric Features["zkne"] = ExtMask & (1 << 12); // RISCV_HWPROBE_EXT_ZKNE 2051*0fca6ea1SDimitry Andric Features["zknh"] = ExtMask & (1 << 13); // RISCV_HWPROBE_EXT_ZKNH 2052*0fca6ea1SDimitry Andric Features["zksed"] = ExtMask & (1 << 14); // RISCV_HWPROBE_EXT_ZKSED 2053*0fca6ea1SDimitry Andric Features["zksh"] = ExtMask & (1 << 15); // RISCV_HWPROBE_EXT_ZKSH 2054*0fca6ea1SDimitry Andric Features["zkt"] = ExtMask & (1 << 16); // RISCV_HWPROBE_EXT_ZKT 2055*0fca6ea1SDimitry Andric Features["zvbb"] = ExtMask & (1 << 17); // RISCV_HWPROBE_EXT_ZVBB 2056*0fca6ea1SDimitry Andric Features["zvbc"] = ExtMask & (1 << 18); // RISCV_HWPROBE_EXT_ZVBC 2057*0fca6ea1SDimitry Andric Features["zvkb"] = ExtMask & (1 << 19); // RISCV_HWPROBE_EXT_ZVKB 2058*0fca6ea1SDimitry Andric Features["zvkg"] = ExtMask & (1 << 20); // RISCV_HWPROBE_EXT_ZVKG 2059*0fca6ea1SDimitry Andric Features["zvkned"] = ExtMask & (1 << 21); // RISCV_HWPROBE_EXT_ZVKNED 2060*0fca6ea1SDimitry Andric Features["zvknha"] = ExtMask & (1 << 22); // RISCV_HWPROBE_EXT_ZVKNHA 2061*0fca6ea1SDimitry Andric Features["zvknhb"] = ExtMask & (1 << 23); // RISCV_HWPROBE_EXT_ZVKNHB 2062*0fca6ea1SDimitry Andric Features["zvksed"] = ExtMask & (1 << 24); // RISCV_HWPROBE_EXT_ZVKSED 2063*0fca6ea1SDimitry Andric Features["zvksh"] = ExtMask & (1 << 25); // RISCV_HWPROBE_EXT_ZVKSH 2064*0fca6ea1SDimitry Andric Features["zvkt"] = ExtMask & (1 << 26); // RISCV_HWPROBE_EXT_ZVKT 2065*0fca6ea1SDimitry Andric Features["zfh"] = ExtMask & (1 << 27); // RISCV_HWPROBE_EXT_ZFH 2066*0fca6ea1SDimitry Andric Features["zfhmin"] = ExtMask & (1 << 28); // RISCV_HWPROBE_EXT_ZFHMIN 2067*0fca6ea1SDimitry Andric Features["zihintntl"] = ExtMask & (1 << 29); // RISCV_HWPROBE_EXT_ZIHINTNTL 2068*0fca6ea1SDimitry Andric Features["zvfh"] = ExtMask & (1 << 30); // RISCV_HWPROBE_EXT_ZVFH 2069*0fca6ea1SDimitry Andric Features["zvfhmin"] = ExtMask & (1ULL << 31); // RISCV_HWPROBE_EXT_ZVFHMIN 2070*0fca6ea1SDimitry Andric Features["zfa"] = ExtMask & (1ULL << 32); // RISCV_HWPROBE_EXT_ZFA 2071*0fca6ea1SDimitry Andric Features["ztso"] = ExtMask & (1ULL << 33); // RISCV_HWPROBE_EXT_ZTSO 2072*0fca6ea1SDimitry Andric // TODO: Re-enable zacas when it is marked non-experimental again. 2073*0fca6ea1SDimitry Andric // Features["zacas"] = ExtMask & (1ULL << 34); // RISCV_HWPROBE_EXT_ZACAS 2074*0fca6ea1SDimitry Andric Features["zicond"] = ExtMask & (1ULL << 35); // RISCV_HWPROBE_EXT_ZICOND 2075*0fca6ea1SDimitry Andric Features["zihintpause"] = 2076*0fca6ea1SDimitry Andric ExtMask & (1ULL << 36); // RISCV_HWPROBE_EXT_ZIHINTPAUSE 2077*0fca6ea1SDimitry Andric 2078*0fca6ea1SDimitry Andric // TODO: set unaligned-scalar-mem if RISCV_HWPROBE_KEY_MISALIGNED_PERF returns 2079*0fca6ea1SDimitry Andric // RISCV_HWPROBE_MISALIGNED_FAST. 2080*0fca6ea1SDimitry Andric 2081*0fca6ea1SDimitry Andric return Features; 208206c3fb27SDimitry Andric } 2083bdd1243dSDimitry Andric #else 2084*0fca6ea1SDimitry Andric const StringMap<bool> sys::getHostCPUFeatures() { return {}; } 2085bdd1243dSDimitry Andric #endif 2086bdd1243dSDimitry Andric 208706c3fb27SDimitry Andric #if __APPLE__ 208806c3fb27SDimitry Andric /// \returns the \p triple, but with the Host's arch spliced in. 208906c3fb27SDimitry Andric static Triple withHostArch(Triple T) { 209006c3fb27SDimitry Andric #if defined(__arm__) 209106c3fb27SDimitry Andric T.setArch(Triple::arm); 209206c3fb27SDimitry Andric T.setArchName("arm"); 209306c3fb27SDimitry Andric #elif defined(__arm64e__) 209406c3fb27SDimitry Andric T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64e); 209506c3fb27SDimitry Andric T.setArchName("arm64e"); 209606c3fb27SDimitry Andric #elif defined(__aarch64__) 209706c3fb27SDimitry Andric T.setArch(Triple::aarch64); 209806c3fb27SDimitry Andric T.setArchName("arm64"); 209906c3fb27SDimitry Andric #elif defined(__x86_64h__) 210006c3fb27SDimitry Andric T.setArch(Triple::x86_64); 210106c3fb27SDimitry Andric T.setArchName("x86_64h"); 210206c3fb27SDimitry Andric #elif defined(__x86_64__) 210306c3fb27SDimitry Andric T.setArch(Triple::x86_64); 210406c3fb27SDimitry Andric T.setArchName("x86_64"); 21055f757f3fSDimitry Andric #elif defined(__i386__) 21065f757f3fSDimitry Andric T.setArch(Triple::x86); 21075f757f3fSDimitry Andric T.setArchName("i386"); 210806c3fb27SDimitry Andric #elif defined(__powerpc__) 210906c3fb27SDimitry Andric T.setArch(Triple::ppc); 211006c3fb27SDimitry Andric T.setArchName("powerpc"); 211106c3fb27SDimitry Andric #else 211206c3fb27SDimitry Andric # error "Unimplemented host arch fixup" 211306c3fb27SDimitry Andric #endif 211406c3fb27SDimitry Andric return T; 211506c3fb27SDimitry Andric } 211606c3fb27SDimitry Andric #endif 211706c3fb27SDimitry Andric 2118bdd1243dSDimitry Andric std::string sys::getProcessTriple() { 2119bdd1243dSDimitry Andric std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE); 2120bdd1243dSDimitry Andric Triple PT(Triple::normalize(TargetTripleString)); 2121bdd1243dSDimitry Andric 212206c3fb27SDimitry Andric #if __APPLE__ 212306c3fb27SDimitry Andric /// In Universal builds, LLVM_HOST_TRIPLE will have the wrong arch in one of 212406c3fb27SDimitry Andric /// the slices. This fixes that up. 212506c3fb27SDimitry Andric PT = withHostArch(PT); 212606c3fb27SDimitry Andric #endif 212706c3fb27SDimitry Andric 2128bdd1243dSDimitry Andric if (sizeof(void *) == 8 && PT.isArch32Bit()) 2129bdd1243dSDimitry Andric PT = PT.get64BitArchVariant(); 2130bdd1243dSDimitry Andric if (sizeof(void *) == 4 && PT.isArch64Bit()) 2131bdd1243dSDimitry Andric PT = PT.get32BitArchVariant(); 2132bdd1243dSDimitry Andric 2133bdd1243dSDimitry Andric return PT.str(); 2134bdd1243dSDimitry Andric } 2135bdd1243dSDimitry Andric 2136bdd1243dSDimitry Andric void sys::printDefaultTargetAndDetectedCPU(raw_ostream &OS) { 2137bdd1243dSDimitry Andric #if LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO 2138bdd1243dSDimitry Andric std::string CPU = std::string(sys::getHostCPUName()); 2139bdd1243dSDimitry Andric if (CPU == "generic") 2140bdd1243dSDimitry Andric CPU = "(unknown)"; 2141bdd1243dSDimitry Andric OS << " Default target: " << sys::getDefaultTargetTriple() << '\n' 2142bdd1243dSDimitry Andric << " Host CPU: " << CPU << '\n'; 2143bdd1243dSDimitry Andric #endif 2144bdd1243dSDimitry Andric } 2145