mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-13 19:50:34 +00:00
Merge branch 'update-cpufeatures' into next
This commit is contained in:
commit
8849f78eb0
@ -270,10 +270,6 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_VERSION VERSION_GREATER 3.0 AND SUPPORTED_CPU_FEATURES_ARCH)
|
if(CMAKE_VERSION VERSION_GREATER 3.0 AND SUPPORTED_CPU_FEATURES_ARCH)
|
||||||
set(BUILD_PIC ON CACHE BOOL
|
|
||||||
"Build cpu_features with Position Independent Code (PIC)."
|
|
||||||
FORCE
|
|
||||||
)
|
|
||||||
set(USE_CPU_FEATURES ON)
|
set(USE_CPU_FEATURES ON)
|
||||||
set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
|
set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
|
||||||
set(BUILD_SHARED_LIBS OFF)
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
@ -32,13 +32,11 @@ option(BUILD_TESTING "Enable test (depends on googletest)." OFF)
|
|||||||
# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways.
|
# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways.
|
||||||
# Prefer static linking from source whenever possible.
|
# Prefer static linking from source whenever possible.
|
||||||
option(BUILD_SHARED_LIBS "Build library as shared." OFF)
|
option(BUILD_SHARED_LIBS "Build library as shared." OFF)
|
||||||
# PIC
|
|
||||||
option(BUILD_PIC "Build with Position Independant Code." OFF) # Default is off at least for GCC
|
|
||||||
|
|
||||||
# Force PIC on unix when building shared libs
|
# Force PIC on unix when building shared libs
|
||||||
# see: https://en.wikipedia.org/wiki/Position-independent_code
|
# see: https://en.wikipedia.org/wiki/Position-independent_code
|
||||||
if(BUILD_SHARED_LIBS AND UNIX)
|
if(BUILD_SHARED_LIBS AND UNIX)
|
||||||
set(BUILD_PIC ON)
|
option(CMAKE_POSITION_INDEPENDENT_CODE "Build with Position Independant Code." ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(CheckIncludeFile)
|
include(CheckIncludeFile)
|
||||||
@ -110,7 +108,6 @@ add_library(utils OBJECT
|
|||||||
${PROJECT_SOURCE_DIR}/src/stack_line_reader.c
|
${PROJECT_SOURCE_DIR}/src/stack_line_reader.c
|
||||||
${PROJECT_SOURCE_DIR}/src/string_view.c
|
${PROJECT_SOURCE_DIR}/src/string_view.c
|
||||||
)
|
)
|
||||||
set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
|
|
||||||
setup_include_and_definitions(utils)
|
setup_include_and_definitions(utils)
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -131,7 +128,6 @@ if(UNIX)
|
|||||||
if(HAVE_STRONG_GETAUXVAL)
|
if(HAVE_STRONG_GETAUXVAL)
|
||||||
target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL)
|
target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL)
|
||||||
endif()
|
endif()
|
||||||
set_property(TARGET unix_based_hardware_detection PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -148,7 +144,6 @@ add_library(cpu_features ${CPU_FEATURES_HDRS} ${CPU_FEATURES_SRCS})
|
|||||||
set_target_properties(cpu_features PROPERTIES PUBLIC_HEADER "${CPU_FEATURES_HDRS}")
|
set_target_properties(cpu_features PROPERTIES PUBLIC_HEADER "${CPU_FEATURES_HDRS}")
|
||||||
setup_include_and_definitions(cpu_features)
|
setup_include_and_definitions(cpu_features)
|
||||||
target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS})
|
target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS})
|
||||||
set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
|
|
||||||
target_include_directories(cpu_features
|
target_include_directories(cpu_features
|
||||||
PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
|
PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
|
||||||
)
|
)
|
||||||
@ -237,6 +232,7 @@ install(TARGETS cpu_features list_cpu_features
|
|||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
)
|
)
|
||||||
install(EXPORT CpuFeaturesTargets
|
install(EXPORT CpuFeaturesTargets
|
||||||
NAMESPACE CpuFeatures::
|
NAMESPACE CpuFeatures::
|
||||||
|
@ -10,6 +10,11 @@
|
|||||||
|
|
||||||
CPU_FEATURES_START_CPP_NAMESPACE
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
// CPUID Vendors
|
||||||
|
#define CPU_FEATURES_VENDOR_GENUINE_INTEL "GenuineIntel"
|
||||||
|
#define CPU_FEATURES_VENDOR_AUTHENTIC_AMD "AuthenticAMD"
|
||||||
|
#define CPU_FEATURES_VENDOR_HYGON_GENUINE "HygonGenuine"
|
||||||
|
|
||||||
// See https://en.wikipedia.org/wiki/CPUID for a list of x86 cpu features.
|
// See https://en.wikipedia.org/wiki/CPUID for a list of x86 cpu features.
|
||||||
// The field names are based on the short name provided in the wikipedia tables.
|
// The field names are based on the short name provided in the wikipedia tables.
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -87,7 +87,8 @@ void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
|
|||||||
|
|
||||||
// Checks if line contains the specified whitespace separated word.
|
// Checks if line contains the specified whitespace separated word.
|
||||||
bool CpuFeatures_StringView_HasWord(const StringView line,
|
bool CpuFeatures_StringView_HasWord(const StringView line,
|
||||||
const char* const word);
|
const char* const word,
|
||||||
|
const char separator);
|
||||||
|
|
||||||
// Get key/value from line. key and value are separated by ": ".
|
// Get key/value from line. key and value are separated by ": ".
|
||||||
// key and value are cleaned up from leading and trailing whitespaces.
|
// key and value are cleaned up from leading and trailing whitespaces.
|
||||||
|
@ -107,8 +107,8 @@ static bool HandleAarch64Line(const LineResult result,
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < AARCH64_LAST_; ++i)
|
for (size_t i = 0; i < AARCH64_LAST_; ++i)
|
||||||
{
|
{
|
||||||
kSetters[i](&info->features,
|
kSetters[i](&info->features, CpuFeatures_StringView_HasWord(
|
||||||
CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
|
value, kCpuInfoFlags[i], ' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
|
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
|
||||||
|
@ -71,8 +71,8 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info,
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < ARM_LAST_; ++i)
|
for (size_t i = 0; i < ARM_LAST_; ++i)
|
||||||
{
|
{
|
||||||
kSetters[i](&info->features,
|
kSetters[i](&info->features, CpuFeatures_StringView_HasWord(
|
||||||
CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
|
value, kCpuInfoFlags[i], ' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
|
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
|
||||||
|
@ -28,8 +28,8 @@ static bool HandleMipsLine(const LineResult result,
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < MIPS_LAST_; ++i)
|
for (size_t i = 0; i < MIPS_LAST_; ++i)
|
||||||
{
|
{
|
||||||
kSetters[i](features,
|
kSetters[i](features, CpuFeatures_StringView_HasWord(
|
||||||
CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
|
value, kCpuInfoFlags[i], ' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ static bool HandlePPCLine(const LineResult result,
|
|||||||
StringView key, value;
|
StringView key, value;
|
||||||
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value))
|
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value))
|
||||||
{
|
{
|
||||||
if (CpuFeatures_StringView_HasWord(key, "platform"))
|
if (CpuFeatures_StringView_HasWord(key, "platform", ' '))
|
||||||
{
|
{
|
||||||
CpuFeatures_StringView_CopyString(value, strings->platform,
|
CpuFeatures_StringView_CopyString(value, strings->platform,
|
||||||
sizeof(strings->platform));
|
sizeof(strings->platform));
|
||||||
|
@ -88,7 +88,6 @@
|
|||||||
defined(CPU_FEATURES_OS_FREEBSD)
|
defined(CPU_FEATURES_OS_FREEBSD)
|
||||||
#include "internal/filesystem.h" // Needed to parse /proc/cpuinfo
|
#include "internal/filesystem.h" // Needed to parse /proc/cpuinfo
|
||||||
#include "internal/stack_line_reader.h" // Needed to parse /proc/cpuinfo
|
#include "internal/stack_line_reader.h" // Needed to parse /proc/cpuinfo
|
||||||
#include "internal/string_view.h" // Needed to parse /proc/cpuinfo
|
|
||||||
#elif defined(CPU_FEATURES_OS_DARWIN)
|
#elif defined(CPU_FEATURES_OS_DARWIN)
|
||||||
#if !defined(HAVE_SYSCTLBYNAME)
|
#if !defined(HAVE_SYSCTLBYNAME)
|
||||||
#error "Darwin needs support for sysctlbyname"
|
#error "Darwin needs support for sysctlbyname"
|
||||||
@ -98,6 +97,8 @@
|
|||||||
#error "Unsupported OS"
|
#error "Unsupported OS"
|
||||||
#endif // CPU_FEATURES_OS
|
#endif // CPU_FEATURES_OS
|
||||||
|
|
||||||
|
#include "internal/string_view.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Definitions for CpuId and GetXCR0Eax.
|
// Definitions for CpuId and GetXCR0Eax.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -267,6 +268,11 @@ static int IsVendor(const Leaf leaf, const char* const name)
|
|||||||
return leaf.ebx == ebx && leaf.ecx == ecx && leaf.edx == edx;
|
return leaf.ebx == ebx && leaf.ecx == ecx && leaf.edx == edx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int IsVendorByX86Info(const X86Info* info, const char* const name)
|
||||||
|
{
|
||||||
|
return memcmp(info->vendor, name, sizeof(info->vendor)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const CacheLevelInfo kEmptyCacheLevelInfo;
|
static const CacheLevelInfo kEmptyCacheLevelInfo;
|
||||||
|
|
||||||
static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg)
|
static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg)
|
||||||
@ -1129,55 +1135,52 @@ static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetByteArrayFromRegister(uint32_t result[4], const uint32_t reg)
|
// From https://www.felixcloutier.com/x86/cpuid#tbl-3-12
|
||||||
{
|
|
||||||
for (int i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
result[i] = ExtractBitRange(reg, (i + 1) * 8, i * 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info)
|
static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info)
|
||||||
{
|
{
|
||||||
Leaf leaf = SafeCpuId(max_cpuid_leaf, 2);
|
Leaf leaf = SafeCpuId(max_cpuid_leaf, 2);
|
||||||
uint32_t registers[] = {leaf.eax, leaf.ebx, leaf.ecx, leaf.edx};
|
// The least-significant byte in register EAX (register AL) will always return
|
||||||
for (int i = 0; i < 4; ++i)
|
// 01H. Software should ignore this value and not interpret it as an
|
||||||
|
// informational descriptor.
|
||||||
|
leaf.eax &= 0xFFFFFF00; // Zeroing out AL. 0 is the empty descriptor.
|
||||||
|
// The most significant bit (bit 31) of each register indicates whether the
|
||||||
|
// register contains valid information (set to 0) or is reserved (set to 1).
|
||||||
|
if (IsBitSet(leaf.eax, 31)) leaf.eax = 0;
|
||||||
|
if (IsBitSet(leaf.ebx, 31)) leaf.ebx = 0;
|
||||||
|
if (IsBitSet(leaf.ecx, 31)) leaf.ecx = 0;
|
||||||
|
if (IsBitSet(leaf.edx, 31)) leaf.edx = 0;
|
||||||
|
|
||||||
|
uint8_t data[16];
|
||||||
|
#if __STDC_VERSION__ >= 201112L
|
||||||
|
_Static_assert(sizeof(Leaf) == sizeof(data), "Leaf must be 16 bytes");
|
||||||
|
#endif
|
||||||
|
memcpy(&data, &leaf, sizeof(data));
|
||||||
|
for (size_t i = 0; i < sizeof(data); ++i)
|
||||||
{
|
{
|
||||||
if (registers[i] & (1U << 31))
|
const uint8_t descriptor = data[i];
|
||||||
{
|
if (descriptor == 0) continue;
|
||||||
continue; // register does not contains valid information
|
info->levels[info->size] = GetCacheLevelInfo(descriptor);
|
||||||
}
|
|
||||||
uint32_t bytes[4];
|
|
||||||
GetByteArrayFromRegister(bytes, registers[i]);
|
|
||||||
for (int j = 0; j < 4; ++j)
|
|
||||||
{
|
|
||||||
if (bytes[j] == 0xFF)
|
|
||||||
break; // leaf 4 should be used to fetch cache information
|
|
||||||
info->levels[info->size] = GetCacheLevelInfo(bytes[j]);
|
|
||||||
}
|
|
||||||
info->size++;
|
info->size++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info)
|
// For newer Intel CPUs uses "CPUID, eax=0x00000004".
|
||||||
|
// For newer AMD CPUs uses "CPUID, eax=0x8000001D"
|
||||||
|
static void ParseCacheInfo(const int max_cpuid_leaf, uint32_t leaf_id,
|
||||||
|
CacheInfo* info)
|
||||||
{
|
{
|
||||||
info->size = 0;
|
|
||||||
for (int cache_id = 0; cache_id < CPU_FEATURES_MAX_CACHE_LEVEL; cache_id++)
|
for (int cache_id = 0; cache_id < CPU_FEATURES_MAX_CACHE_LEVEL; cache_id++)
|
||||||
{
|
{
|
||||||
const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, 4, cache_id);
|
const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, leaf_id, cache_id);
|
||||||
CacheType cache_type = ExtractBitRange(leaf.eax, 4, 0);
|
CacheType cache_type = ExtractBitRange(leaf.eax, 4, 0);
|
||||||
if (cache_type == CPU_FEATURE_CACHE_NULL)
|
if (cache_type == CPU_FEATURE_CACHE_NULL) continue;
|
||||||
{
|
|
||||||
info->levels[cache_id] = kEmptyCacheLevelInfo;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int level = ExtractBitRange(leaf.eax, 7, 5);
|
int level = ExtractBitRange(leaf.eax, 7, 5);
|
||||||
int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1;
|
int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1;
|
||||||
int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1;
|
int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1;
|
||||||
int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1;
|
int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1;
|
||||||
int tlb_entries = leaf.ecx + 1;
|
int tlb_entries = leaf.ecx + 1;
|
||||||
int cache_size = (ways * partitioning * line_size * (tlb_entries));
|
int cache_size = (ways * partitioning * line_size * (tlb_entries));
|
||||||
info->levels[cache_id] = (CacheLevelInfo){.level = level,
|
info->levels[info->size] = (CacheLevelInfo){.level = level,
|
||||||
.cache_type = cache_type,
|
.cache_type = cache_type,
|
||||||
.cache_size = cache_size,
|
.cache_size = cache_size,
|
||||||
.ways = ways,
|
.ways = ways,
|
||||||
@ -1371,41 +1374,33 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
|
|||||||
{
|
{
|
||||||
StackLineReader reader;
|
StackLineReader reader;
|
||||||
StackLineReader_Initialize(&reader, fd);
|
StackLineReader_Initialize(&reader, fd);
|
||||||
for (;;)
|
for (bool stop = false; !stop;)
|
||||||
{
|
{
|
||||||
const LineResult result = StackLineReader_NextLine(&reader);
|
const LineResult result = StackLineReader_NextLine(&reader);
|
||||||
|
if (result.eof) stop = true;
|
||||||
const StringView line = result.line;
|
const StringView line = result.line;
|
||||||
const bool is_feature =
|
if (!CpuFeatures_StringView_StartsWith(line, str(" Features")))
|
||||||
CpuFeatures_StringView_StartsWith(line, str(" Features="));
|
continue;
|
||||||
const bool is_feature2 =
|
// Lines of interests are of the following form:
|
||||||
CpuFeatures_StringView_StartsWith(line, str(" Features2="));
|
// " Features=0x1783fbff<PSE36,MMX,FXSR,SSE,SSE2,HTT>"
|
||||||
if (is_feature || is_feature2)
|
// We first extract the comma separated values between angle brackets.
|
||||||
{
|
StringView csv = result.line;
|
||||||
// Lines of interests are of the following form:
|
int index = CpuFeatures_StringView_IndexOfChar(csv, '<');
|
||||||
// " Features=0x1783fbff<PSE36,MMX,FXSR,SSE,SSE2,HTT>"
|
if (index >= 0) csv = CpuFeatures_StringView_PopFront(csv, index + 1);
|
||||||
// We replace '<', '>' and ',' with space so we can search by
|
if (csv.size > 0 && CpuFeatures_StringView_Back(csv) == '>')
|
||||||
// whitespace separated word.
|
csv = CpuFeatures_StringView_PopBack(csv, 1);
|
||||||
// TODO: Fix CpuFeatures_StringView_HasWord to allow for different
|
if (CpuFeatures_StringView_HasWord(csv, "SSE", ','))
|
||||||
// separators.
|
features->sse = true;
|
||||||
for (size_t i = 0; i < line.size; ++i)
|
if (CpuFeatures_StringView_HasWord(csv, "SSE2", ','))
|
||||||
{
|
features->sse2 = true;
|
||||||
char* c = (char*)(&(line.ptr[i]));
|
if (CpuFeatures_StringView_HasWord(csv, "SSE3", ','))
|
||||||
if (*c == '<' || *c == '>' || *c == ',') *c = ' ';
|
features->sse3 = true;
|
||||||
}
|
if (CpuFeatures_StringView_HasWord(csv, "SSSE3", ','))
|
||||||
if (is_feature)
|
features->ssse3 = true;
|
||||||
{
|
if (CpuFeatures_StringView_HasWord(csv, "SSE4.1", ','))
|
||||||
features->sse = CpuFeatures_StringView_HasWord(line, "SSE");
|
features->sse4_1 = true;
|
||||||
features->sse2 = CpuFeatures_StringView_HasWord(line, "SSE2");
|
if (CpuFeatures_StringView_HasWord(csv, "SSE4.2", ','))
|
||||||
}
|
features->sse4_2 = true;
|
||||||
if (is_feature2)
|
|
||||||
{
|
|
||||||
features->sse3 = CpuFeatures_StringView_HasWord(line, "SSE3");
|
|
||||||
features->ssse3 = CpuFeatures_StringView_HasWord(line, "SSSE3");
|
|
||||||
features->sse4_1 = CpuFeatures_StringView_HasWord(line, "SSE4.1");
|
|
||||||
features->sse4_2 = CpuFeatures_StringView_HasWord(line, "SSE4.2");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result.eof) break;
|
|
||||||
}
|
}
|
||||||
CpuFeatures_CloseFile(fd);
|
CpuFeatures_CloseFile(fd);
|
||||||
}
|
}
|
||||||
@ -1416,25 +1411,22 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
|
|||||||
{
|
{
|
||||||
StackLineReader reader;
|
StackLineReader reader;
|
||||||
StackLineReader_Initialize(&reader, fd);
|
StackLineReader_Initialize(&reader, fd);
|
||||||
for (;;)
|
for (bool stop = false; !stop;)
|
||||||
{
|
{
|
||||||
const LineResult result = StackLineReader_NextLine(&reader);
|
const LineResult result = StackLineReader_NextLine(&reader);
|
||||||
|
if (result.eof) stop = true;
|
||||||
const StringView line = result.line;
|
const StringView line = result.line;
|
||||||
StringView key, value;
|
StringView key, value;
|
||||||
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value))
|
if (!CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value))
|
||||||
{
|
continue;
|
||||||
if (CpuFeatures_StringView_IsEquals(key, str("flags")))
|
if (!CpuFeatures_StringView_IsEquals(key, str("flags"))) continue;
|
||||||
{
|
features->sse = CpuFeatures_StringView_HasWord(value, "sse", ' ');
|
||||||
features->sse = CpuFeatures_StringView_HasWord(value, "sse");
|
features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2", ' ');
|
||||||
features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2");
|
features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3", ' ');
|
||||||
features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3");
|
features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3", ' ');
|
||||||
features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3");
|
features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1", ' ');
|
||||||
features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1");
|
features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2", ' ');
|
||||||
features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2");
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result.eof) break;
|
|
||||||
}
|
}
|
||||||
CpuFeatures_CloseFile(fd);
|
CpuFeatures_CloseFile(fd);
|
||||||
}
|
}
|
||||||
@ -1450,11 +1442,15 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
|
|||||||
|
|
||||||
// Reference
|
// Reference
|
||||||
// https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented.
|
// https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented.
|
||||||
|
static Leaf GetLeafByIdAMD(uint32_t leaf_id)
|
||||||
|
{
|
||||||
|
uint32_t max_extended = CpuId(0x80000000).eax;
|
||||||
|
return SafeCpuId(max_extended, leaf_id);
|
||||||
|
}
|
||||||
|
|
||||||
static void ParseExtraAMDCpuId(X86Info* info, OsPreserves os_preserves)
|
static void ParseExtraAMDCpuId(X86Info* info, OsPreserves os_preserves)
|
||||||
{
|
{
|
||||||
const Leaf leaf_80000000 = CpuId(0x80000000);
|
const Leaf leaf_80000001 = GetLeafByIdAMD(0x80000001);
|
||||||
const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax;
|
|
||||||
const Leaf leaf_80000001 = SafeCpuId(max_extended_cpuid_leaf, 0x80000001);
|
|
||||||
|
|
||||||
X86Features* const features = &info->features;
|
X86Features* const features = &info->features;
|
||||||
|
|
||||||
@ -1477,9 +1473,9 @@ X86Info GetX86Info(void)
|
|||||||
{
|
{
|
||||||
X86Info info = kEmptyX86Info;
|
X86Info info = kEmptyX86Info;
|
||||||
const Leaf leaf_0 = CpuId(0);
|
const Leaf leaf_0 = CpuId(0);
|
||||||
const bool is_intel = IsVendor(leaf_0, "GenuineIntel");
|
const bool is_intel = IsVendor(leaf_0, CPU_FEATURES_VENDOR_GENUINE_INTEL);
|
||||||
const bool is_amd = IsVendor(leaf_0, "AuthenticAMD");
|
const bool is_amd = IsVendor(leaf_0, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
|
||||||
const bool is_hygon = IsVendor(leaf_0, "HygonGenuine");
|
const bool is_hygon = IsVendor(leaf_0, CPU_FEATURES_VENDOR_HYGON_GENUINE);
|
||||||
SetVendor(leaf_0, info.vendor);
|
SetVendor(leaf_0, info.vendor);
|
||||||
if (is_intel || is_amd || is_hygon)
|
if (is_intel || is_amd || is_hygon)
|
||||||
{
|
{
|
||||||
@ -1498,11 +1494,25 @@ CacheInfo GetX86CacheInfo(void)
|
|||||||
{
|
{
|
||||||
CacheInfo info = kEmptyCacheInfo;
|
CacheInfo info = kEmptyCacheInfo;
|
||||||
const Leaf leaf_0 = CpuId(0);
|
const Leaf leaf_0 = CpuId(0);
|
||||||
const uint32_t max_cpuid_leaf = leaf_0.eax;
|
if (IsVendor(leaf_0, CPU_FEATURES_VENDOR_GENUINE_INTEL))
|
||||||
if (IsVendor(leaf_0, "GenuineIntel"))
|
|
||||||
{
|
{
|
||||||
ParseLeaf2(max_cpuid_leaf, &info);
|
info.size = 0;
|
||||||
ParseLeaf4(max_cpuid_leaf, &info);
|
ParseLeaf2(leaf_0.eax, &info);
|
||||||
|
ParseCacheInfo(leaf_0.eax, 4, &info);
|
||||||
|
}
|
||||||
|
else if (IsVendor(leaf_0, CPU_FEATURES_VENDOR_AUTHENTIC_AMD) ||
|
||||||
|
IsVendor(leaf_0, CPU_FEATURES_VENDOR_HYGON_GENUINE))
|
||||||
|
{
|
||||||
|
const uint32_t max_ext = CpuId(0x80000000).eax;
|
||||||
|
const uint32_t cpuid_ext = SafeCpuId(max_ext, 0x80000001).ecx;
|
||||||
|
|
||||||
|
// If CPUID Fn8000_0001_ECX[TopologyExtensions]==0
|
||||||
|
// then CPUID Fn8000_0001_E[D,C,B,A]X is reserved.
|
||||||
|
// https://www.amd.com/system/files/TechDocs/25481.pdf
|
||||||
|
if (IsBitSet(cpuid_ext, 22))
|
||||||
|
{
|
||||||
|
ParseCacheInfo(max_ext, 0x8000001D, &info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -1511,7 +1521,7 @@ CacheInfo GetX86CacheInfo(void)
|
|||||||
|
|
||||||
X86Microarchitecture GetX86Microarchitecture(const X86Info* info)
|
X86Microarchitecture GetX86Microarchitecture(const X86Info* info)
|
||||||
{
|
{
|
||||||
if (memcmp(info->vendor, "GenuineIntel", sizeof(info->vendor)) == 0)
|
if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_GENUINE_INTEL))
|
||||||
{
|
{
|
||||||
switch (CPUID(info->family, info->model))
|
switch (CPUID(info->family, info->model))
|
||||||
{
|
{
|
||||||
@ -1616,7 +1626,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info)
|
|||||||
return X86_UNKNOWN;
|
return X86_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (memcmp(info->vendor, "AuthenticAMD", sizeof(info->vendor)) == 0)
|
if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_AUTHENTIC_AMD))
|
||||||
{
|
{
|
||||||
switch (CPUID(info->family, info->model))
|
switch (CPUID(info->family, info->model))
|
||||||
{
|
{
|
||||||
@ -1726,7 +1736,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info)
|
|||||||
return X86_UNKNOWN;
|
return X86_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (memcmp(info->vendor, "HygonGenuine", sizeof(info->vendor)) == 0)
|
if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_HYGON_GENUINE))
|
||||||
{
|
{
|
||||||
switch (CPUID(info->family, info->model))
|
switch (CPUID(info->family, info->model))
|
||||||
{
|
{
|
||||||
@ -1737,23 +1747,20 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info)
|
|||||||
return X86_UNKNOWN;
|
return X86_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetString(const uint32_t max_cpuid_ext_leaf, const uint32_t leaf_id,
|
|
||||||
char* buffer)
|
|
||||||
{
|
|
||||||
const Leaf leaf = SafeCpuId(max_cpuid_ext_leaf, leaf_id);
|
|
||||||
// We allow calling memcpy from SetString which is only called when requesting
|
|
||||||
// X86BrandString.
|
|
||||||
memcpy(buffer, &leaf, sizeof(Leaf));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FillX86BrandString(char brand_string[49])
|
void FillX86BrandString(char brand_string[49])
|
||||||
{
|
{
|
||||||
const Leaf leaf_ext_0 = CpuId(0x80000000);
|
const Leaf leaf_ext_0 = CpuId(0x80000000);
|
||||||
const uint32_t max_cpuid_leaf_ext = leaf_ext_0.eax;
|
const uint32_t max_cpuid_leaf_ext = leaf_ext_0.eax;
|
||||||
SetString(max_cpuid_leaf_ext, 0x80000002, brand_string);
|
const Leaf leaves[3] = {
|
||||||
SetString(max_cpuid_leaf_ext, 0x80000003, brand_string + 16);
|
SafeCpuId(max_cpuid_leaf_ext, 0x80000002),
|
||||||
SetString(max_cpuid_leaf_ext, 0x80000004, brand_string + 32);
|
SafeCpuId(max_cpuid_leaf_ext, 0x80000003),
|
||||||
brand_string[48] = '\0';
|
SafeCpuId(max_cpuid_leaf_ext, 0x80000004),
|
||||||
|
};
|
||||||
|
#if __STDC_VERSION__ >= 201112L
|
||||||
|
_Static_assert(sizeof(leaves) == 48, "Leaves must be packed");
|
||||||
|
#endif
|
||||||
|
CpuFeatures_StringView_CopyString(view((const char*)leaves, sizeof(leaves)),
|
||||||
|
brand_string, 49);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -158,7 +158,8 @@ void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CpuFeatures_StringView_HasWord(const StringView line,
|
bool CpuFeatures_StringView_HasWord(const StringView line,
|
||||||
const char* const word_str)
|
const char* const word_str,
|
||||||
|
const char separator)
|
||||||
{
|
{
|
||||||
const StringView word = str(word_str);
|
const StringView word = str(word_str);
|
||||||
StringView remainder = line;
|
StringView remainder = line;
|
||||||
@ -176,9 +177,9 @@ bool CpuFeatures_StringView_HasWord(const StringView line,
|
|||||||
const StringView after =
|
const StringView after =
|
||||||
CpuFeatures_StringView_PopFront(line, index_of_word + word.size);
|
CpuFeatures_StringView_PopFront(line, index_of_word + word.size);
|
||||||
const bool valid_before =
|
const bool valid_before =
|
||||||
before.size == 0 || CpuFeatures_StringView_Back(before) == ' ';
|
before.size == 0 || CpuFeatures_StringView_Back(before) == separator;
|
||||||
const bool valid_after =
|
const bool valid_after =
|
||||||
after.size == 0 || CpuFeatures_StringView_Front(after) == ' ';
|
after.size == 0 || CpuFeatures_StringView_Front(after) == separator;
|
||||||
if (valid_before && valid_after) return true;
|
if (valid_before && valid_after) return true;
|
||||||
remainder =
|
remainder =
|
||||||
CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size);
|
CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size);
|
||||||
|
@ -76,26 +76,32 @@ private:
|
|||||||
uint32_t xcr0_eax_;
|
uint32_t xcr0_eax_;
|
||||||
};
|
};
|
||||||
|
|
||||||
FakeCpu* g_fake_cpu = nullptr;
|
static FakeCpu* g_fake_cpu_instance = nullptr;
|
||||||
|
|
||||||
|
static FakeCpu& cpu()
|
||||||
|
{
|
||||||
|
assert(g_fake_cpu_instance != nullptr);
|
||||||
|
return *g_fake_cpu_instance;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx)
|
extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx)
|
||||||
{
|
{
|
||||||
return g_fake_cpu->GetCpuidLeaf(leaf_id, ecx);
|
return cpu().GetCpuidLeaf(leaf_id, ecx);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); }
|
extern "C" uint32_t GetXCR0Eax(void) { return cpu().GetXCR0Eax(); }
|
||||||
|
|
||||||
#if defined(CPU_FEATURES_OS_DARWIN)
|
#if defined(CPU_FEATURES_OS_DARWIN)
|
||||||
extern "C" bool GetDarwinSysCtlByName(const char* name)
|
extern "C" bool GetDarwinSysCtlByName(const char* name)
|
||||||
{
|
{
|
||||||
return g_fake_cpu->GetDarwinSysCtlByName(name);
|
return cpu().GetDarwinSysCtlByName(name);
|
||||||
}
|
}
|
||||||
#endif // CPU_FEATURES_OS_DARWIN
|
#endif // CPU_FEATURES_OS_DARWIN
|
||||||
|
|
||||||
#if defined(CPU_FEATURES_OS_WINDOWS)
|
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature)
|
extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature)
|
||||||
{
|
{
|
||||||
return g_fake_cpu->GetWindowsIsProcessorFeaturePresent(ProcessorFeature);
|
return cpu().GetWindowsIsProcessorFeaturePresent(ProcessorFeature);
|
||||||
}
|
}
|
||||||
#endif // CPU_FEATURES_OS_WINDOWS
|
#endif // CPU_FEATURES_OS_WINDOWS
|
||||||
|
|
||||||
@ -104,14 +110,22 @@ namespace
|
|||||||
class CpuidX86Test : public ::testing::Test
|
class CpuidX86Test : public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override { g_fake_cpu = new FakeCpu(); }
|
void SetUp() override
|
||||||
void TearDown() override { delete g_fake_cpu; }
|
{
|
||||||
|
assert(g_fake_cpu_instance == nullptr);
|
||||||
|
g_fake_cpu_instance = new FakeCpu();
|
||||||
|
}
|
||||||
|
void TearDown() override
|
||||||
|
{
|
||||||
|
delete g_fake_cpu_instance;
|
||||||
|
g_fake_cpu_instance = nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(CpuidX86Test, SandyBridge)
|
TEST_F(CpuidX86Test, SandyBridge)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
cpu().SetOsBackupsExtendedRegisters(true);
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
{{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
|
{{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
@ -153,28 +167,29 @@ TEST_F(CpuidX86Test, SandyBridge)
|
|||||||
EXPECT_FALSE(features.adx);
|
EXPECT_FALSE(features.adx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int UNDEF = -1;
|
||||||
const int KiB = 1024;
|
const int KiB = 1024;
|
||||||
const int MiB = 1024 * KiB;
|
const int MiB = 1024 * KiB;
|
||||||
|
|
||||||
TEST_F(CpuidX86Test, SandyBridgeTestOsSupport)
|
TEST_F(CpuidX86Test, SandyBridgeTestOsSupport)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
{{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
|
{{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
});
|
});
|
||||||
// avx is disabled if os does not support backing up ymm registers.
|
// avx is disabled if os does not support backing up ymm registers.
|
||||||
g_fake_cpu->SetOsBackupsExtendedRegisters(false);
|
cpu().SetOsBackupsExtendedRegisters(false);
|
||||||
EXPECT_FALSE(GetX86Info().features.avx);
|
EXPECT_FALSE(GetX86Info().features.avx);
|
||||||
// avx is disabled if os does not support backing up ymm registers.
|
// avx is disabled if os does not support backing up ymm registers.
|
||||||
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
cpu().SetOsBackupsExtendedRegisters(true);
|
||||||
EXPECT_TRUE(GetX86Info().features.avx);
|
EXPECT_TRUE(GetX86Info().features.avx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CpuidX86Test, SkyLake)
|
TEST_F(CpuidX86Test, SkyLake)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
cpu().SetOsBackupsExtendedRegisters(true);
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
|
||||||
@ -189,7 +204,7 @@ TEST_F(CpuidX86Test, SkyLake)
|
|||||||
|
|
||||||
TEST_F(CpuidX86Test, Branding)
|
TEST_F(CpuidX86Test, Branding)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
|
||||||
@ -206,7 +221,7 @@ TEST_F(CpuidX86Test, Branding)
|
|||||||
|
|
||||||
TEST_F(CpuidX86Test, KabyLakeCache)
|
TEST_F(CpuidX86Test, KabyLakeCache)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
||||||
{{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
|
{{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
|
||||||
@ -256,7 +271,7 @@ TEST_F(CpuidX86Test, KabyLakeCache)
|
|||||||
|
|
||||||
TEST_F(CpuidX86Test, HSWCache)
|
TEST_F(CpuidX86Test, HSWCache)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
||||||
{{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
|
{{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
|
||||||
@ -307,7 +322,7 @@ TEST_F(CpuidX86Test, HSWCache)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0200F30_K11_Griffin_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0200F30_K11_Griffin_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K11_GRIFFIN)
|
TEST_F(CpuidX86Test, AMD_K11_GRIFFIN)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000001, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x00000001, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00200F30, 0x00020800, 0x00002001, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00200F30, 0x00020800, 0x00002001, 0x178BFBFF}},
|
||||||
{{0x80000000, 0}, Leaf{0x8000001A, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x80000000, 0}, Leaf{0x8000001A, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
@ -324,7 +339,7 @@ TEST_F(CpuidX86Test, AMD_K11_GRIFFIN)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0300F10_K12_Llano_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0300F10_K12_Llano_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K12_LLANO)
|
TEST_F(CpuidX86Test, AMD_K12_LLANO)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00300F10, 0x00040800, 0x00802009, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00300F10, 0x00040800, 0x00802009, 0x178BFBFF}},
|
||||||
{{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
@ -341,7 +356,7 @@ TEST_F(CpuidX86Test, AMD_K12_LLANO)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F01_K14_Bobcat_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F01_K14_Bobcat_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F01)
|
TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F01)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00500F01, 0x00020800, 0x00802209, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00500F01, 0x00020800, 0x00802209, 0x178BFBFF}},
|
||||||
{{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
@ -358,7 +373,7 @@ TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F01)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F10_K14_Bobcat_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F10_K14_Bobcat_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F10)
|
TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F10)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00500F10, 0x00020800, 0x00802209, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00500F10, 0x00020800, 0x00802209, 0x178BFBFF}},
|
||||||
{{0x00000002, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
{{0x00000002, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
@ -383,7 +398,7 @@ TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F10)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F20_K14_Bobcat_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F20_K14_Bobcat_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F20)
|
TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F20)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00500F20, 0x00020800, 0x00802209, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00500F20, 0x00020800, 0x00802209, 0x178BFBFF}},
|
||||||
{{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
@ -400,7 +415,7 @@ TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F20)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0670F00_K15_StoneyRidge_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0670F00_K15_StoneyRidge_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K15_EXCAVATOR_STONEY_RIDGE)
|
TEST_F(CpuidX86Test, AMD_K15_EXCAVATOR_STONEY_RIDGE)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00670F00, 0x00020800, 0x7ED8320B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00670F00, 0x00020800, 0x7ED8320B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x000001A9, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x000001A9, 0x00000000, 0x00000000}},
|
||||||
@ -426,7 +441,7 @@ TEST_F(CpuidX86Test, AMD_K15_EXCAVATOR_STONEY_RIDGE)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F20_K15_AbuDhabi_CPUID0.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F20_K15_AbuDhabi_CPUID0.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI)
|
TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00600F20, 0x00100800, 0x3E98320B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00600F20, 0x00100800, 0x3E98320B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}},
|
||||||
@ -449,10 +464,59 @@ TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI)
|
|||||||
EXPECT_STREQ(brand_string, "AMD Opteron(tm) Processor 6376 ");
|
EXPECT_STREQ(brand_string, "AMD Opteron(tm) Processor 6376 ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F20_K15_AbuDhabi_CPUID0.txt
|
||||||
|
TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI_CACHE_INFO)
|
||||||
|
{
|
||||||
|
cpu().SetLeaves({
|
||||||
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
|
{{0x00000001, 0}, Leaf{0x00600F20, 0x00100800, 0x3E98320B, 0x178BFBFF}},
|
||||||
|
{{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
|
{{0x80000001, 0}, Leaf{0x00600F20, 0x30000000, 0x01EBBFFF, 0x2FD3FBFF}},
|
||||||
|
{{0x8000001D, 0}, Leaf{0x00000121, 0x00C0003F, 0x0000003F, 0x00000000}},
|
||||||
|
{{0x8000001D, 1}, Leaf{0x00004122, 0x0040003F, 0x000001FF, 0x00000000}},
|
||||||
|
{{0x8000001D, 2}, Leaf{0x00004143, 0x03C0003F, 0x000007FF, 0x00000001}},
|
||||||
|
{{0x8000001D, 3}, Leaf{0x0001C163, 0x0BC0003F, 0x000007FF, 0x00000001}},
|
||||||
|
});
|
||||||
|
const auto info = GetX86CacheInfo();
|
||||||
|
|
||||||
|
EXPECT_EQ(info.size, 4);
|
||||||
|
EXPECT_EQ(info.levels[0].level, 1);
|
||||||
|
EXPECT_EQ(info.levels[0].cache_type, 1);
|
||||||
|
EXPECT_EQ(info.levels[0].cache_size, 16 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[0].ways, 4);
|
||||||
|
EXPECT_EQ(info.levels[0].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[0].tlb_entries, 64);
|
||||||
|
EXPECT_EQ(info.levels[0].partitioning, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[1].level, 1);
|
||||||
|
EXPECT_EQ(info.levels[1].cache_type, 2);
|
||||||
|
EXPECT_EQ(info.levels[1].cache_size, 64 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[1].ways, 2);
|
||||||
|
EXPECT_EQ(info.levels[1].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[1].tlb_entries, 512);
|
||||||
|
EXPECT_EQ(info.levels[1].partitioning, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[2].level, 2);
|
||||||
|
EXPECT_EQ(info.levels[2].cache_type, 3);
|
||||||
|
EXPECT_EQ(info.levels[2].cache_size, 2 * MiB);
|
||||||
|
EXPECT_EQ(info.levels[2].ways, 16);
|
||||||
|
EXPECT_EQ(info.levels[2].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[2].tlb_entries, 2048);
|
||||||
|
EXPECT_EQ(info.levels[2].partitioning, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[3].level, 3);
|
||||||
|
EXPECT_EQ(info.levels[3].cache_type, 3);
|
||||||
|
EXPECT_EQ(info.levels[3].cache_size, 6 * MiB);
|
||||||
|
EXPECT_EQ(info.levels[3].ways, 48);
|
||||||
|
EXPECT_EQ(info.levels[3].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[3].tlb_entries, 2048);
|
||||||
|
EXPECT_EQ(info.levels[3].partitioning, 1);
|
||||||
|
}
|
||||||
|
|
||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F12_K15_Interlagos_CPUID3.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F12_K15_Interlagos_CPUID3.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K15_BULLDOZER_INTERLAGOS)
|
TEST_F(CpuidX86Test, AMD_K15_BULLDOZER_INTERLAGOS)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00600F12, 0x000C0800, 0x1E98220B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00600F12, 0x000C0800, 0x1E98220B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
@ -478,7 +542,7 @@ TEST_F(CpuidX86Test, AMD_K15_BULLDOZER_INTERLAGOS)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K15_STREAMROLLER_GODAVARI)
|
TEST_F(CpuidX86Test, AMD_K15_STREAMROLLER_GODAVARI)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
@ -506,7 +570,7 @@ TEST_F(CpuidX86Test, AMD_K15_STREAMROLLER_GODAVARI)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0700F01_K16_Kabini_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0700F01_K16_Kabini_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K16_JAGUAR_KABINI)
|
TEST_F(CpuidX86Test, AMD_K16_JAGUAR_KABINI)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00700F01, 0x00040800, 0x3ED8220B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00700F01, 0x00040800, 0x3ED8220B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}},
|
||||||
@ -531,7 +595,7 @@ TEST_F(CpuidX86Test, AMD_K16_JAGUAR_KABINI)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0730F01_K16_Beema_CPUID2.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0730F01_K16_Beema_CPUID2.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K16_PUMA_BEEMA)
|
TEST_F(CpuidX86Test, AMD_K16_PUMA_BEEMA)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00730F01, 0x00040800, 0x7ED8220B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00730F01, 0x00040800, 0x7ED8220B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}},
|
||||||
@ -556,7 +620,7 @@ TEST_F(CpuidX86Test, AMD_K16_PUMA_BEEMA)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0820F01_K17_Dali_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0820F01_K17_Dali_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K17_ZEN_DALI)
|
TEST_F(CpuidX86Test, AMD_K17_ZEN_DALI)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00820F01, 0x00020800, 0x7ED8320B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00820F01, 0x00020800, 0x7ED8320B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x209C01A9, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x209C01A9, 0x00000000, 0x00000000}},
|
||||||
@ -581,7 +645,7 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN_DALI)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0800F82_K17_ZenP_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0800F82_K17_ZenP_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K17_ZEN_PLUS_PINNACLE_RIDGE)
|
TEST_F(CpuidX86Test, AMD_K17_ZEN_PLUS_PINNACLE_RIDGE)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00800F82, 0x00100800, 0x7ED8320B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00800F82, 0x00100800, 0x7ED8320B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x209C01A9, 0x00000000, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x209C01A9, 0x00000000, 0x00000000}},
|
||||||
@ -606,7 +670,7 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN_PLUS_PINNACLE_RIDGE)
|
|||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0840F70_K17_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0840F70_K17_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K17_ZEN2_XBOX_SERIES_X)
|
TEST_F(CpuidX86Test, AMD_K17_ZEN2_XBOX_SERIES_X)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00840F70, 0x00100800, 0x7ED8320B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00840F70, 0x00100800, 0x7ED8320B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x219C91A9, 0x00400004, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x219C91A9, 0x00400004, 0x00000000}},
|
||||||
@ -631,7 +695,7 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN2_XBOX_SERIES_X)
|
|||||||
// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID3.txt
|
// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID3.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA)
|
TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x6F677948, 0x656E6975, 0x6E65476E}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x6F677948, 0x656E6975, 0x6E65476E}},
|
||||||
{{0x00000001, 0}, Leaf{0x00900F02, 0x00100800, 0x74D83209, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00900F02, 0x00100800, 0x74D83209, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x009C01A9, 0x0040068C, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x009C01A9, 0x0040068C, 0x00000000}},
|
||||||
@ -653,10 +717,59 @@ TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA)
|
|||||||
EXPECT_STREQ(brand_string, "Hygon C86 3185 8-core Processor ");
|
EXPECT_STREQ(brand_string, "Hygon C86 3185 8-core Processor ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID.txt
|
||||||
|
TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA_CACHE_INFO)
|
||||||
|
{
|
||||||
|
cpu().SetLeaves({
|
||||||
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x6F677948, 0x656E6975, 0x6E65476E}},
|
||||||
|
{{0x00000001, 0}, Leaf{0x00900F02, 0x00100800, 0x74D83209, 0x178BFBFF}},
|
||||||
|
{{0x80000000, 0}, Leaf{0x8000001F, 0x6F677948, 0x656E6975, 0x6E65476E}},
|
||||||
|
{{0x80000001, 0}, Leaf{0x00900F02, 0x60000000, 0x35C233FF, 0x2FD3FBFF}},
|
||||||
|
{{0x8000001D, 0}, Leaf{0x00004121, 0x01C0003F, 0x0000003F, 0x00000000}},
|
||||||
|
{{0x8000001D, 1}, Leaf{0x00004122, 0x00C0003F, 0x000000FF, 0x00000000}},
|
||||||
|
{{0x8000001D, 2}, Leaf{0x00004143, 0x01C0003F, 0x000003FF, 0x00000002}},
|
||||||
|
{{0x8000001D, 3}, Leaf{0x0001C163, 0x03C0003F, 0x00001FFF, 0x00000001}},
|
||||||
|
});
|
||||||
|
const auto info = GetX86CacheInfo();
|
||||||
|
|
||||||
|
EXPECT_EQ(info.size, 4);
|
||||||
|
EXPECT_EQ(info.levels[0].level, 1);
|
||||||
|
EXPECT_EQ(info.levels[0].cache_type, 1);
|
||||||
|
EXPECT_EQ(info.levels[0].cache_size, 32 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[0].ways, 8);
|
||||||
|
EXPECT_EQ(info.levels[0].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[0].tlb_entries, 64);
|
||||||
|
EXPECT_EQ(info.levels[0].partitioning, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[1].level, 1);
|
||||||
|
EXPECT_EQ(info.levels[1].cache_type, 2);
|
||||||
|
EXPECT_EQ(info.levels[1].cache_size, 64 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[1].ways, 4);
|
||||||
|
EXPECT_EQ(info.levels[1].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[1].tlb_entries, 256);
|
||||||
|
EXPECT_EQ(info.levels[1].partitioning, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[2].level, 2);
|
||||||
|
EXPECT_EQ(info.levels[2].cache_type, 3);
|
||||||
|
EXPECT_EQ(info.levels[2].cache_size, 512 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[2].ways, 8);
|
||||||
|
EXPECT_EQ(info.levels[2].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[2].tlb_entries, 1024);
|
||||||
|
EXPECT_EQ(info.levels[2].partitioning, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[3].level, 3);
|
||||||
|
EXPECT_EQ(info.levels[3].cache_type, 3);
|
||||||
|
EXPECT_EQ(info.levels[3].cache_size, 8 * MiB);
|
||||||
|
EXPECT_EQ(info.levels[3].ways, 16);
|
||||||
|
EXPECT_EQ(info.levels[3].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[3].tlb_entries, 8192);
|
||||||
|
EXPECT_EQ(info.levels[3].partitioning, 1);
|
||||||
|
}
|
||||||
|
|
||||||
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A20F10_K19_Vermeer2_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A20F10_K19_Vermeer2_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, AMD_K19_ZEN3_VERMEER)
|
TEST_F(CpuidX86Test, AMD_K19_ZEN3_VERMEER)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
{{0x00000001, 0}, Leaf{0x00A20F10, 0x01180800, 0x7ED8320B, 0x178BFBFF}},
|
{{0x00000001, 0}, Leaf{0x00A20F10, 0x01180800, 0x7ED8320B, 0x178BFBFF}},
|
||||||
{{0x00000007, 0}, Leaf{0x00000000, 0x219C97A9, 0x0040068C, 0x00000000}},
|
{{0x00000007, 0}, Leaf{0x00000000, 0x219C97A9, 0x0040068C, 0x00000000}},
|
||||||
@ -682,21 +795,18 @@ TEST_F(CpuidX86Test, AMD_K19_ZEN3_VERMEER)
|
|||||||
TEST_F(CpuidX86Test, Nehalem)
|
TEST_F(CpuidX86Test, Nehalem)
|
||||||
{
|
{
|
||||||
// Pre AVX cpus don't have xsave
|
// Pre AVX cpus don't have xsave
|
||||||
g_fake_cpu->SetOsBackupsExtendedRegisters(false);
|
cpu().SetOsBackupsExtendedRegisters(false);
|
||||||
#if defined(CPU_FEATURES_OS_WINDOWS)
|
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
|
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
|
||||||
PF_XMMI_INSTRUCTIONS_AVAILABLE);
|
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
|
||||||
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
|
cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
|
||||||
PF_XMMI64_INSTRUCTIONS_AVAILABLE);
|
|
||||||
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
|
|
||||||
PF_SSE3_INSTRUCTIONS_AVAILABLE);
|
|
||||||
#elif defined(CPU_FEATURES_OS_DARWIN)
|
#elif defined(CPU_FEATURES_OS_DARWIN)
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse2");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse3");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
|
cpu().SetDarwinSysCtlByName("hw.optional.supplementalsse3");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse4_1");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse4_2");
|
||||||
#elif defined(CPU_FEATURES_OS_FREEBSD)
|
#elif defined(CPU_FEATURES_OS_FREEBSD)
|
||||||
auto& fs = GetEmptyFilesystem();
|
auto& fs = GetEmptyFilesystem();
|
||||||
fs.CreateFile("/var/run/dmesg.boot", R"(
|
fs.CreateFile("/var/run/dmesg.boot", R"(
|
||||||
@ -713,7 +823,7 @@ real memory = 2147418112 (2047 MB)
|
|||||||
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
|
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
|
||||||
)");
|
)");
|
||||||
#endif
|
#endif
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
{{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}},
|
{{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}},
|
||||||
{{0x00000002, 0}, Leaf{0x55035A01, 0x00F0B0E3, 0x00000000, 0x09CA212C}},
|
{{0x00000002, 0}, Leaf{0x55035A01, 0x00F0B0E3, 0x00000000, 0x09CA212C}},
|
||||||
@ -768,21 +878,18 @@ flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
|
|||||||
TEST_F(CpuidX86Test, Atom)
|
TEST_F(CpuidX86Test, Atom)
|
||||||
{
|
{
|
||||||
// Pre AVX cpus don't have xsave
|
// Pre AVX cpus don't have xsave
|
||||||
g_fake_cpu->SetOsBackupsExtendedRegisters(false);
|
cpu().SetOsBackupsExtendedRegisters(false);
|
||||||
#if defined(CPU_FEATURES_OS_WINDOWS)
|
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
|
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
|
||||||
PF_XMMI_INSTRUCTIONS_AVAILABLE);
|
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
|
||||||
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
|
cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
|
||||||
PF_XMMI64_INSTRUCTIONS_AVAILABLE);
|
|
||||||
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
|
|
||||||
PF_SSE3_INSTRUCTIONS_AVAILABLE);
|
|
||||||
#elif defined(CPU_FEATURES_OS_DARWIN)
|
#elif defined(CPU_FEATURES_OS_DARWIN)
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse2");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse3");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
|
cpu().SetDarwinSysCtlByName("hw.optional.supplementalsse3");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse4_1");
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse4_2");
|
||||||
#elif defined(CPU_FEATURES_OS_FREEBSD)
|
#elif defined(CPU_FEATURES_OS_FREEBSD)
|
||||||
auto& fs = GetEmptyFilesystem();
|
auto& fs = GetEmptyFilesystem();
|
||||||
fs.CreateFile("/var/run/dmesg.boot", R"(
|
fs.CreateFile("/var/run/dmesg.boot", R"(
|
||||||
@ -799,7 +906,7 @@ real memory = 2147418112 (2047 MB)
|
|||||||
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
|
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
|
||||||
)");
|
)");
|
||||||
#endif
|
#endif
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
{{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}},
|
{{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}},
|
||||||
{{0x00000002, 0}, Leaf{0x61B3A001, 0x0000FFC2, 0x00000000, 0x00000000}},
|
{{0x00000002, 0}, Leaf{0x61B3A001, 0x0000FFC2, 0x00000000, 0x00000000}},
|
||||||
@ -850,16 +957,68 @@ flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
|
|||||||
#endif // !defined(CPU_FEATURES_OS_WINDOWS)
|
#endif // !defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.felixcloutier.com/x86/cpuid#example-3-1--example-of-cache-and-tlb-interpretation
|
||||||
|
TEST_F(CpuidX86Test, P4_CacheInfo)
|
||||||
|
{
|
||||||
|
cpu().SetLeaves({
|
||||||
|
{{0x00000000, 0}, Leaf{0x00000002, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
|
{{0x00000001, 0}, Leaf{0x00000F0A, 0x00010808, 0x00000000, 0x3FEBFBFF}},
|
||||||
|
{{0x00000002, 0}, Leaf{0x665B5001, 0x00000000, 0x00000000, 0x007A7000}},
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto info = GetX86CacheInfo();
|
||||||
|
EXPECT_EQ(info.size, 5);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[0].level, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[0].cache_type, CPU_FEATURE_CACHE_TLB);
|
||||||
|
EXPECT_EQ(info.levels[0].cache_size, 4 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[0].ways, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[0].line_size, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[0].tlb_entries, 64);
|
||||||
|
EXPECT_EQ(info.levels[0].partitioning, 0);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[1].level, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[1].cache_type, CPU_FEATURE_CACHE_TLB);
|
||||||
|
EXPECT_EQ(info.levels[1].cache_size, 4 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[1].ways, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[1].line_size, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[1].tlb_entries, 64);
|
||||||
|
EXPECT_EQ(info.levels[1].partitioning, 0);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[2].level, 1);
|
||||||
|
EXPECT_EQ(info.levels[2].cache_type, CPU_FEATURE_CACHE_DATA);
|
||||||
|
EXPECT_EQ(info.levels[2].cache_size, 8 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[2].ways, 4);
|
||||||
|
EXPECT_EQ(info.levels[2].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[2].tlb_entries, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[2].partitioning, 0);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[3].level, 1);
|
||||||
|
EXPECT_EQ(info.levels[3].cache_type, CPU_FEATURE_CACHE_INSTRUCTION);
|
||||||
|
EXPECT_EQ(info.levels[3].cache_size, 12 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[3].ways, 8);
|
||||||
|
EXPECT_EQ(info.levels[3].line_size, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[3].tlb_entries, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[3].partitioning, 0);
|
||||||
|
|
||||||
|
EXPECT_EQ(info.levels[4].level, 2);
|
||||||
|
EXPECT_EQ(info.levels[4].cache_type, CPU_FEATURE_CACHE_DATA);
|
||||||
|
EXPECT_EQ(info.levels[4].cache_size, 256 * KiB);
|
||||||
|
EXPECT_EQ(info.levels[4].ways, 8);
|
||||||
|
EXPECT_EQ(info.levels[4].line_size, 64);
|
||||||
|
EXPECT_EQ(info.levels[4].tlb_entries, UNDEF);
|
||||||
|
EXPECT_EQ(info.levels[4].partitioning, 2);
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000673_P3_KatmaiDP_CPUID.txt
|
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000673_P3_KatmaiDP_CPUID.txt
|
||||||
TEST_F(CpuidX86Test, P3)
|
TEST_F(CpuidX86Test, P3)
|
||||||
{
|
{
|
||||||
// Pre AVX cpus don't have xsave
|
// Pre AVX cpus don't have xsave
|
||||||
g_fake_cpu->SetOsBackupsExtendedRegisters(false);
|
cpu().SetOsBackupsExtendedRegisters(false);
|
||||||
#if defined(CPU_FEATURES_OS_WINDOWS)
|
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
|
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
|
||||||
PF_XMMI_INSTRUCTIONS_AVAILABLE);
|
|
||||||
#elif defined(CPU_FEATURES_OS_DARWIN)
|
#elif defined(CPU_FEATURES_OS_DARWIN)
|
||||||
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
|
cpu().SetDarwinSysCtlByName("hw.optional.sse");
|
||||||
#elif defined(CPU_FEATURES_OS_FREEBSD)
|
#elif defined(CPU_FEATURES_OS_FREEBSD)
|
||||||
auto& fs = GetEmptyFilesystem();
|
auto& fs = GetEmptyFilesystem();
|
||||||
fs.CreateFile("/var/run/dmesg.boot", R"(
|
fs.CreateFile("/var/run/dmesg.boot", R"(
|
||||||
@ -875,7 +1034,7 @@ real memory = 2147418112 (2047 MB)
|
|||||||
flags : fpu mmx sse
|
flags : fpu mmx sse
|
||||||
)");
|
)");
|
||||||
#endif
|
#endif
|
||||||
g_fake_cpu->SetLeaves({
|
cpu().SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
{{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}},
|
{{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}},
|
||||||
{{0x00000002, 0}, Leaf{0x03020101, 0x00000000, 0x00000000, 0x0C040843}},
|
{{0x00000002, 0}, Leaf{0x03020101, 0x00000000, 0x00000000, 0x0C040843}},
|
||||||
|
@ -167,15 +167,25 @@ TEST(StringViewTest, CpuFeatures_StringView_HasWord)
|
|||||||
{
|
{
|
||||||
// Find flags at beginning, middle and end.
|
// Find flags at beginning, middle and end.
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
CpuFeatures_StringView_HasWord(str("first middle last"), "first"));
|
CpuFeatures_StringView_HasWord(str("first middle last"), "first", ' '));
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
CpuFeatures_StringView_HasWord(str("first middle last"), "middle"));
|
CpuFeatures_StringView_HasWord(str("first middle last"), "middle", ' '));
|
||||||
EXPECT_TRUE(CpuFeatures_StringView_HasWord(str("first middle last"), "last"));
|
EXPECT_TRUE(
|
||||||
|
CpuFeatures_StringView_HasWord(str("first middle last"), "last", ' '));
|
||||||
|
// Find flags at beginning, middle and end with a different separator
|
||||||
|
EXPECT_TRUE(
|
||||||
|
CpuFeatures_StringView_HasWord(str("first-middle-last"), "first", '-'));
|
||||||
|
EXPECT_TRUE(
|
||||||
|
CpuFeatures_StringView_HasWord(str("first-middle-last"), "middle", '-'));
|
||||||
|
EXPECT_TRUE(
|
||||||
|
CpuFeatures_StringView_HasWord(str("first-middle-last"), "last", '-'));
|
||||||
// Do not match partial flags
|
// Do not match partial flags
|
||||||
EXPECT_FALSE(
|
EXPECT_FALSE(
|
||||||
CpuFeatures_StringView_HasWord(str("first middle last"), "irst"));
|
CpuFeatures_StringView_HasWord(str("first middle last"), "irst", ' '));
|
||||||
EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "mid"));
|
EXPECT_FALSE(
|
||||||
EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "las"));
|
CpuFeatures_StringView_HasWord(str("first middle last"), "mid", ' '));
|
||||||
|
EXPECT_FALSE(
|
||||||
|
CpuFeatures_StringView_HasWord(str("first middle last"), "las", ' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StringViewTest, CpuFeatures_StringView_GetAttributeKeyValue)
|
TEST(StringViewTest, CpuFeatures_StringView_GetAttributeKeyValue)
|
||||||
|
Loading…
Reference in New Issue
Block a user