diff --git a/Common/CPUDetect.h b/Common/CPUDetect.h index d6ae56fe2e..db1ea377a5 100644 --- a/Common/CPUDetect.h +++ b/Common/CPUDetect.h @@ -115,6 +115,22 @@ struct CPUInfo { bool RiscV_Zbc; bool RiscV_Zbs; + // LoongArch specific extension flags. + bool LOONGARCH_CPUCFG; + bool LOONGARCH_LAM; + bool LOONGARCH_UAL; + bool LOONGARCH_FPU; + bool LOONGARCH_LSX; + bool LOONGARCH_LASX; + bool LOONGARCH_CRC32; + bool LOONGARCH_COMPLEX; + bool LOONGARCH_CRYPTO; + bool LOONGARCH_LVZ; + bool LOONGARCH_LBT_X86; + bool LOONGARCH_LBT_ARM; + bool LOONGARCH_LBT_MIPS; + bool LOONGARCH_PTW; + // Quirks struct { // Samsung Galaxy S7 devices (Exynos 8890) have a big.LITTLE configuration where the cacheline size differs between big and LITTLE. diff --git a/Common/LoongArchCPUDetect.cpp b/Common/LoongArchCPUDetect.cpp index 8d986a44de..64f4acd9a0 100644 --- a/Common/LoongArchCPUDetect.cpp +++ b/Common/LoongArchCPUDetect.cpp @@ -41,27 +41,78 @@ const char procfile[] = "/proc/cpuinfo"; // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu const char syscpupresentfile[] = "/sys/devices/system/cpu/present"; -std::string GetCPUString() { - //TODO - std::string cpu_string; - cpu_string = "Unknown"; - return cpu_string; +class LoongArchCPUInfoParser { +public: + LoongArchCPUInfoParser(); + + int ProcessorCount(); + int TotalLogicalCount(); + +private: + std::vector> cores_; +}; + +LoongArchCPUInfoParser::LoongArchCPUInfoParser() { + std::string procdata, line; + if (!File::ReadFileToString(true, Path(procfile), procdata)) + return; + + std::istringstream file(procdata); + int index = -1; + while (std::getline(file, line)) { + if (line.length() == 0) { + index = -1; + } else { + if (index == -1) { + index = (int)cores_.size(); + cores_.push_back(std::vector()); + } + cores_[index].push_back(line); + } + } } -std::string GetCPUBrandString() { - //TODO - std::string brand_string; - brand_string = "Unknown"; - return brand_string; +int LoongArchCPUInfoParser::ProcessorCount() { + static const char *marker = "core"; + std::set coreIndex; + for (auto core : cores_) { + for (auto line : core) { + if (line.find(marker) != line.npos) + coreIndex.insert(line); + } + } + + return (int)coreIndex.size(); } -int GetCoreCount() { - // TODO - return 4; +int LoongArchCPUInfoParser::TotalLogicalCount() { + std::string presentData, line; + bool presentSuccess = File::ReadFileToString(true, Path(syscpupresentfile), presentData); + if (presentSuccess) { + std::istringstream presentFile(presentData); + + int low, high, found; + std::getline(presentFile, line); + found = sscanf(line.c_str(), "%d-%d", &low, &high); + if (found == 1){ + return 1; + } + if (found == 2){ + return high - low + 1; + } + }else{ + return 1; + } } #endif +static bool ExtensionSupported(unsigned long v, unsigned int i) { + // https://github.com/torvalds/linux/blob/master/arch/loongarch/include/uapi/asm/hwcap.h + unsigned long mask = 1 << i; + return v & mask; +} + CPUInfo cpu_info; CPUInfo::CPUInfo() { @@ -69,7 +120,8 @@ CPUInfo::CPUInfo() { } // Detects the various cpu features -void CPUInfo::Detect() { +void CPUInfo::Detect() +{ // Set some defaults here HTT = false; #if PPSSPP_ARCH(LOONGARCH64) @@ -82,30 +134,89 @@ void CPUInfo::Detect() { Mode64bit = false; #endif vendor = VENDOR_OTHER; - - truncate_cpy(brand_string, "Unknown"); + truncate_cpy(brand_string, "Loongson"); + truncate_cpy(cpu_string, "Loongson"); #if !defined(__linux__) num_cores = 1; logical_cpu_count = 1; + truncate_cpy(brand_string, "Unknown"); truncate_cpy(cpu_string, "Unknown"); #else // __linux__ - truncate_cpy(cpu_string, GetCPUString().c_str()); - truncate_cpy(brand_string, GetCPUBrandString().c_str()); - num_cores = GetCoreCount(); - logical_cpu_count = 1; + LoongArchCPUInfoParser parser; + num_cores = parser.ProcessorCount(); + logical_cpu_count = parser.TotalLogicalCount() / num_cores; + if (logical_cpu_count <= 0) + logical_cpu_count = 1; +#endif + + unsigned long hwcap = getauxval(AT_HWCAP); + LOONGARCH_CPUCFG = true; + LOONGARCH_LAM = ExtensionSupported(hwcap, 1); + LOONGARCH_UAL = ExtensionSupported(hwcap, 2); + LOONGARCH_FPU = ExtensionSupported(hwcap, 3); + LOONGARCH_LSX = ExtensionSupported(hwcap, 4); + LOONGARCH_LASX = ExtensionSupported(hwcap, 5); + LOONGARCH_CRC32 = ExtensionSupported(hwcap, 6); + LOONGARCH_COMPLEX = ExtensionSupported(hwcap, 7); + LOONGARCH_CRYPTO = ExtensionSupported(hwcap, 8); + LOONGARCH_LVZ = ExtensionSupported(hwcap, 9); + LOONGARCH_LBT_X86 = ExtensionSupported(hwcap, 10); + LOONGARCH_LBT_ARM = ExtensionSupported(hwcap, 11); + LOONGARCH_LBT_MIPS = ExtensionSupported(hwcap, 12); + LOONGARCH_PTW = ExtensionSupported(hwcap, 13); + +#ifdef USE_CPU_FEATURES + cpu_features::LoongArchInfo info = cpu_features::GetLoongArchInfo(); + LOONGARCH_CPUCFG = true; + LOONGARCH_LAM = info.features.LAM; + LOONGARCH_UAL = info.features.UAL; + LOONGARCH_FPU = info.features.FPU; + LOONGARCH_LSX = info.features.LSX; + LOONGARCH_LASX = info.features.LASX; + LOONGARCH_CRC32 = info.features.CRC32; + LOONGARCH_COMPLEX = info.features.COMPLEX; + LOONGARCH_CRYPTO = info.features.CRYPTO; + LOONGARCH_LVZ = info.features.LVZ; + LOONGARCH_LBT_X86 = info.features.LBT_X86; + LOONGARCH_LBT_ARM = info.features.LBT_ARM; + LOONGARCH_LBT_MIPS = info.features.LBT_MIPS; + LOONGARCH_PTW = info.features.PTW; #endif } std::vector CPUInfo::Features() { - // TODO - std::vector features; +std::vector features; + struct Flag { + bool &flag; + const char *str; + }; + const Flag list[] = { + { LOONGARCH_CPUCFG, "Identify CPU Features" }, + { LOONGARCH_LAM, "Atomic Memory Access Instructions" }, + { LOONGARCH_UAL, "Non-Aligned Memory Access" }, + { LOONGARCH_FPU, "Basic Floating-Point Instructions" }, + { LOONGARCH_LSX, "Loongson SIMD eXtension" }, + { LOONGARCH_LASX, "Loongson Advanced SIMD eXtension" }, + { LOONGARCH_CRC32, "Cyclic Redundancy Check Instructions" }, + { LOONGARCH_COMPLEX, "Complex Vector Operation Instructions" }, + { LOONGARCH_CRYPTO, "Encryption And Decryption Vector Instructions" }, + { LOONGARCH_LVZ, "Virtualization" }, + { LOONGARCH_LBT_X86, "X86 Binary Translation Extension" }, + { LOONGARCH_LBT_ARM, "ARM Binary Translation Extension" }, + { LOONGARCH_LBT_MIPS, "MIPS Binary Translation Extension" }, + { LOONGARCH_PTW, "Page Table Walker" }, + }; + for (auto &item : list) { + if (item.flag) { + features.push_back(item.str); + } + } return features; } - // Turn the cpu info into a string we can show std::string CPUInfo::Summarize() { std::string sum; @@ -114,9 +225,11 @@ std::string CPUInfo::Summarize() { else sum = StringFromFormat("%s, %i cores", cpu_string, num_cores); - //TODO: parse /proc/cpuinfo - + auto features = Features(); + for (std::string &feature : features) { + sum += ", " + feature; + } return sum; } -#endif // PPSSPP_ARCH(LOONGARCH64) \ No newline at end of file +#endif // PPSSPP_ARCH(LOONGARCH64) diff --git a/ext/cpu_features b/ext/cpu_features index 69c9bcd942..fd4ffc1632 160000 --- a/ext/cpu_features +++ b/ext/cpu_features @@ -1 +1 @@ -Subproject commit 69c9bcd94297ae0468c34619b1cbb351e40b3e4c +Subproject commit fd4ffc1632db7b4e763bd28ffa6fc9d761cf3587 diff --git a/ext/rcheevos b/ext/rcheevos index 813163c10c..97db619aa4 160000 --- a/ext/rcheevos +++ b/ext/rcheevos @@ -1 +1 @@ -Subproject commit 813163c10c0745322affb8342ca2ab3bb30bfcbf +Subproject commit 97db619aa4de15fe19887255e75899ae65d2e432