aboutsummaryrefslogtreecommitdiff
path: root/files/source/cpu_id.cc
diff options
context:
space:
mode:
Diffstat (limited to 'files/source/cpu_id.cc')
-rw-r--r--files/source/cpu_id.cc100
1 files changed, 88 insertions, 12 deletions
diff --git a/files/source/cpu_id.cc b/files/source/cpu_id.cc
index 56fe60e4..0c4a1581 100644
--- a/files/source/cpu_id.cc
+++ b/files/source/cpu_id.cc
@@ -40,7 +40,6 @@ extern "C" {
// cpu_info_ variable for SIMD instruction sets detected.
LIBYUV_API int cpu_info_ = 0;
-// TODO(fbarchard): Consider using int for cpuid so casting is not needed.
// Low level cpuid for X86.
#if (defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \
defined(__x86_64__)) && \
@@ -108,14 +107,14 @@ void CpuId(int eax, int ecx, int* cpu_info) {
// }
// For VS2013 and earlier 32 bit, the _xgetbv(0) optimizer produces bad code.
// https://code.google.com/p/libyuv/issues/detail?id=529
-#if defined(_M_IX86) && (_MSC_VER < 1900)
+#if defined(_M_IX86) && defined(_MSC_VER) && (_MSC_VER < 1900)
#pragma optimize("g", off)
#endif
#if (defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \
defined(__x86_64__)) && \
!defined(__pnacl__) && !defined(__CLR_VER) && !defined(__native_client__)
// X86 CPUs have xgetbv to detect OS saves high parts of ymm registers.
-int GetXCR0() {
+static int GetXCR0() {
int xcr0 = 0;
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219)
xcr0 = (int)_xgetbv(0); // VS2010 SP1 required. NOLINT
@@ -129,7 +128,7 @@ int GetXCR0() {
#define GetXCR0() 0
#endif // defined(_M_IX86) || defined(_M_X64) ..
// Return optimization to previous setting.
-#if defined(_M_IX86) && (_MSC_VER < 1900)
+#if defined(_M_IX86) && defined(_MSC_VER) && (_MSC_VER < 1900)
#pragma optimize("g", on)
#endif
@@ -137,13 +136,14 @@ int GetXCR0() {
// For Arm, but public to allow testing on any CPU
LIBYUV_API SAFEBUFFERS int ArmCpuCaps(const char* cpuinfo_name) {
char cpuinfo_line[512];
- FILE* f = fopen(cpuinfo_name, "r");
+ FILE* f = fopen(cpuinfo_name, "re");
if (!f) {
// Assume Neon if /proc/cpuinfo is unavailable.
// This will occur for Chrome sandbox for Pepper or Render process.
return kCpuHasNEON;
}
- while (fgets(cpuinfo_line, sizeof(cpuinfo_line) - 1, f)) {
+ memset(cpuinfo_line, 0, sizeof(cpuinfo_line));
+ while (fgets(cpuinfo_line, sizeof(cpuinfo_line), f)) {
if (memcmp(cpuinfo_line, "Features", 8) == 0) {
char* p = strstr(cpuinfo_line, " neon");
if (p && (p[5] == ' ' || p[5] == '\n')) {
@@ -162,17 +162,90 @@ LIBYUV_API SAFEBUFFERS int ArmCpuCaps(const char* cpuinfo_name) {
return 0;
}
-// TODO(fbarchard): Consider read_msa_ir().
+LIBYUV_API SAFEBUFFERS int RiscvCpuCaps(const char* cpuinfo_name) {
+ char cpuinfo_line[512];
+ int flag = 0;
+ FILE* f = fopen(cpuinfo_name, "re");
+ if (!f) {
+#if defined(__riscv_vector)
+ // Assume RVV if /proc/cpuinfo is unavailable.
+ // This will occur for Chrome sandbox for Pepper or Render process.
+ return kCpuHasRVV;
+#else
+ return 0;
+#endif
+ }
+ memset(cpuinfo_line, 0, sizeof(cpuinfo_line));
+ while (fgets(cpuinfo_line, sizeof(cpuinfo_line), f)) {
+ if (memcmp(cpuinfo_line, "isa", 3) == 0) {
+ // ISA string must begin with rv64{i,e,g} for a 64-bit processor.
+ char* isa = strstr(cpuinfo_line, "rv64");
+ if (isa) {
+ size_t isa_len = strlen(isa);
+ char* extensions;
+ size_t extensions_len = 0;
+ size_t std_isa_len;
+ // Remove the new-line character at the end of string
+ if (isa[isa_len - 1] == '\n') {
+ isa[--isa_len] = '\0';
+ }
+ // 5 ISA characters
+ if (isa_len < 5) {
+ fclose(f);
+ return 0;
+ }
+ // Skip {i,e,g} canonical checking.
+ // Skip rvxxx
+ isa += 5;
+ // Find the very first occurrence of 's', 'x' or 'z'.
+ // To detect multi-letter standard, non-standard, and
+ // supervisor-level extensions.
+ extensions = strpbrk(isa, "zxs");
+ if (extensions) {
+ // Multi-letter extensions are seperated by a single underscore
+ // as described in RISC-V User-Level ISA V2.2.
+ char* ext = strtok(extensions, "_");
+ extensions_len = strlen(extensions);
+ while (ext) {
+ // Search for the ZVFH (Vector FP16) extension.
+ if (!strcmp(ext, "zvfh")) {
+ flag |= kCpuHasRVVZVFH;
+ }
+ ext = strtok(NULL, "_");
+ }
+ }
+ std_isa_len = isa_len - extensions_len - 5;
+ // Detect the v in the standard single-letter extensions.
+ if (memchr(isa, 'v', std_isa_len)) {
+ // The RVV implied the F extension.
+ flag |= kCpuHasRVV;
+ }
+ }
+ }
+#if defined(__riscv_vector)
+ // Assume RVV if /proc/cpuinfo is from x86 host running QEMU.
+ else if ((memcmp(cpuinfo_line, "vendor_id\t: GenuineIntel", 24) == 0) ||
+ (memcmp(cpuinfo_line, "vendor_id\t: AuthenticAMD", 24) == 0)) {
+ fclose(f);
+ return kCpuHasRVV;
+ }
+#endif
+ }
+ fclose(f);
+ return flag;
+}
+
LIBYUV_API SAFEBUFFERS int MipsCpuCaps(const char* cpuinfo_name) {
char cpuinfo_line[512];
- int flag = 0x0;
- FILE* f = fopen(cpuinfo_name, "r");
+ int flag = 0;
+ FILE* f = fopen(cpuinfo_name, "re");
if (!f) {
// Assume nothing if /proc/cpuinfo is unavailable.
// This will occur for Chrome sandbox for Pepper or Render process.
return 0;
}
- while (fgets(cpuinfo_line, sizeof(cpuinfo_line) - 1, f)) {
+ memset(cpuinfo_line, 0, sizeof(cpuinfo_line));
+ while (fgets(cpuinfo_line, sizeof(cpuinfo_line), f)) {
if (memcmp(cpuinfo_line, "cpu model", 9) == 0) {
// Workaround early kernel without MSA in ASEs line.
if (strstr(cpuinfo_line, "Loongson-2K")) {
@@ -191,14 +264,13 @@ LIBYUV_API SAFEBUFFERS int MipsCpuCaps(const char* cpuinfo_name) {
return flag;
}
-// TODO(fbarchard): Consider read_loongarch_ir().
#define LOONGARCH_CFG2 0x2
#define LOONGARCH_CFG2_LSX (1 << 6)
#define LOONGARCH_CFG2_LASX (1 << 7)
#if defined(__loongarch__)
LIBYUV_API SAFEBUFFERS int LoongarchCpuCaps(void) {
- int flag = 0x0;
+ int flag = 0;
uint32_t cfg2 = 0;
__asm__ volatile("cpucfg %0, %1 \n\t" : "+&r"(cfg2) : "r"(LOONGARCH_CFG2));
@@ -277,6 +349,10 @@ static SAFEBUFFERS int GetCpuFlags(void) {
#endif
cpu_info |= kCpuHasARM;
#endif // __arm__
+#if defined(__riscv) && defined(__linux__)
+ cpu_info = RiscvCpuCaps("/proc/cpuinfo");
+ cpu_info |= kCpuHasRISCV;
+#endif // __riscv
cpu_info |= kCpuInitialized;
return cpu_info;
}