LibreOffice Module tools (master) 1
cpuid.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 */
10
11#include <tools/cpuid.hxx>
12#include <cstdint>
13
14namespace cpuid
15{
16namespace
17{
18#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))
19#include <intrin.h>
20void getCpuId(uint32_t array[4], uint32_t nInfoType)
21{
22 __cpuid(reinterpret_cast<int*>(array), nInfoType);
23}
24#elif (defined(__i386__) || defined(__x86_64__))
25#include <cpuid.h>
26void getCpuId(uint32_t array[4], uint32_t nInfoType)
27{
28 __cpuid_count(nInfoType, 0, *(array + 0), *(array + 1), *(array + 2), *(array + 3));
29}
30#else
31void getCpuId(uint32_t array[4], uint32_t /*nInfoType*/)
32{
33 array[0] = array[1] = array[2] = array[3] = 0;
34}
35#endif
36
37// For AVX we need to check if OS has support for ymm registers
38bool checkAVXSupportInOS()
39{
40 uint32_t xcr0 = 0;
41#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))
42 xcr0 = uint32_t(_xgetbv(0));
43#elif (defined(__i386__) || defined(__x86_64__))
44 __asm__("xgetbv" : "=a"(xcr0) : "c"(0) : "%edx");
45#endif
46 return ((xcr0 & 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */
47}
48
49} // end anonymous namespace
50
51#define HYPER_bit (1 << 28)
52#define SSE2_bit (1 << 26)
53#define SSSE3_bit (1 << 9)
54#define SSE41_bit (1 << 19)
55#define SSE42_bit (1 << 20)
56#define XSAVE_bit (1 << 27)
57#define AVX_bit (1 << 28)
58#define AVX2_bit (1 << 5)
59#define AVX512F_bit (1 << 16)
60
62{
64
65 uint32_t info[] = { 0, 0, 0, 0 };
66 getCpuId(info, 0);
67 int nLevel = info[0];
68
69 if (nLevel >= 1)
70 {
71 uint32_t aCpuInfoArray[] = { 0, 0, 0, 0 };
72 getCpuId(aCpuInfoArray, 1);
73
74 if ((aCpuInfoArray[3] & HYPER_bit) != 0)
75 eInstructions |= InstructionSetFlags::HYPER;
76
77 if ((aCpuInfoArray[3] & SSE2_bit) != 0)
78 eInstructions |= InstructionSetFlags::SSE2;
79
80 if ((aCpuInfoArray[2] & SSSE3_bit) != 0)
81 eInstructions |= InstructionSetFlags::SSSE3;
82
83 if ((aCpuInfoArray[2] & SSE41_bit) != 0)
84 eInstructions |= InstructionSetFlags::SSE41;
85
86 if ((aCpuInfoArray[2] & SSE42_bit) != 0)
87 eInstructions |= InstructionSetFlags::SSE42;
88
89 if (((aCpuInfoArray[2] & AVX_bit) != 0) && ((aCpuInfoArray[2] & XSAVE_bit) != 0))
90 {
91 if (checkAVXSupportInOS())
92 {
93 eInstructions |= InstructionSetFlags::AVX;
94
95 if (nLevel >= 7)
96 {
97 uint32_t aExtendedInfo[] = { 0, 0, 0, 0 };
98 getCpuId(aExtendedInfo, 7);
99
100 if ((aExtendedInfo[1] & AVX2_bit) != 0)
101 eInstructions |= InstructionSetFlags::AVX2;
102 if ((aExtendedInfo[1] & AVX512F_bit) != 0)
103 eInstructions |= InstructionSetFlags::AVX512F;
104 }
105 }
106 }
107 }
108
109 return eInstructions;
110}
111
113{
115 return (eCPUFlags & eInstructions) == eInstructions;
116}
117
119{
120 OUString aString;
122 aString += "SSE2 ";
124 aString += "SSSE3 ";
126 aString += "SSE4.1 ";
128 aString += "SSE4.2 ";
130 aString += "AVX ";
132 aString += "AVX2 ";
134 aString += "AVX512F ";
135 return aString;
136}
137
138} // end cpuid
139
140/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define XSAVE_bit
Definition: cpuid.cxx:56
#define SSE2_bit
Definition: cpuid.cxx:52
#define AVX2_bit
Definition: cpuid.cxx:58
#define SSSE3_bit
Definition: cpuid.cxx:53
#define SSE41_bit
Definition: cpuid.cxx:54
#define SSE42_bit
Definition: cpuid.cxx:55
#define AVX512F_bit
Definition: cpuid.cxx:59
#define HYPER_bit
Definition: cpuid.cxx:51
#define AVX_bit
Definition: cpuid.cxx:57
register sal_uInt32 r28 __asm__("%r28")
Definition: cpuid.cxx:15
OUString instructionSetSupportedString()
Returns a string of supported instructions.
Definition: cpuid.cxx:118
bool isCpuInstructionSetSupported(InstructionSetFlags eInstructions)
Check if a certain instruction set is supported by the CPU at runtime.
Definition: cpuid.cxx:112
InstructionSetFlags
Definition: cpuid.hxx:33
InstructionSetFlags getCpuInstructionSetFlags()
Get supported instruction set flags determined at runtime by probing the CPU.
Definition: cpuid.cxx:61