diff --git a/Common/ArmCPUDetect.cpp b/Common/ArmCPUDetect.cpp index bceff9d370..6924376692 100644 --- a/Common/ArmCPUDetect.cpp +++ b/Common/ArmCPUDetect.cpp @@ -48,6 +48,56 @@ char *GetCPUString() fclose(fp); return cpu_string; } + +unsigned char GetCPUImplementer() +{ + const char marker[] = "CPU implementer\t: "; + char *implementer_string = 0; + unsigned char implementer = 0; + char buf[1024]; + + File::IOFile file(procfile, "r"); + auto const fp = file.GetHandle(); + if (!fp) + return 0; + + while (fgets(buf, sizeof(buf), fp)) + { + if (strncmp(buf, marker, sizeof(marker) - 1)) + continue; + implementer_string = buf + sizeof(marker) - 1; + implementer_string = strndup(implementer_string, strlen(implementer_string) - 1); // Strip the newline + sscanf(implementer_string, "0x%02hhx", &implementer); + break; + } + return implementer; +} + +unsigned short GetCPUPart() +{ + const char marker[] = "CPU part\t: "; + char *part_string = 0; + unsigned short part = 0; + char buf[1024]; + + File::IOFile file(procfile, "r"); + auto const fp = file.GetHandle(); + if (!fp) + return 0; + + while (fgets(buf, sizeof(buf), fp)) + { + if (strncmp(buf, marker, sizeof(marker) - 1)) + continue; + part_string = buf + sizeof(marker) - 1; + part_string = strndup(part_string, strlen(part_string) - 1); // Strip the newline + sscanf(part_string, "0x%03hx", &part); + break; + } + return part; + +} + bool CheckCPUFeature(const char *feature) { const char marker[] = "Features\t: "; @@ -187,6 +237,9 @@ void CPUInfo::Detect() bVFPv4 = CheckCPUFeature("vfpv4"); bIDIVa = CheckCPUFeature("idiva"); bIDIVt = CheckCPUFeature("idivt"); + // Qualcomm Krait supports IDIVA but it doesn't report it. Check for krait. + if (GetCPUImplementer() == 0x51 && GetCPUPart() == 0x6F) // Krait(300) is 0x6F, Scorpion is 0x4D + bIDIVa = bIDIVt = true; // These two require ARMv8 or higher bFP = CheckCPUFeature("fp"); bASIMD = CheckCPUFeature("asimd");