1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
11 #include <tools/cpuid.hxx>
18 #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))
20 void getCpuId(uint32_t array
[4], uint32_t nInfoType
)
22 __cpuid(reinterpret_cast<int*>(array
), nInfoType
);
24 #elif (defined(__i386__) || defined(__x86_64__))
26 void getCpuId(uint32_t array
[4], uint32_t nInfoType
)
28 __cpuid_count(nInfoType
, 0, *(array
+ 0), *(array
+ 1), *(array
+ 2), *(array
+ 3));
31 void getCpuId(uint32_t array
[4], uint32_t /*nInfoType*/)
33 array
[0] = array
[1] = array
[2] = array
[3] = 0;
37 // For AVX we need to check if OS has support for ymm registers
38 bool checkAVXSupportInOS()
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");
46 return ((xcr0
& 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */
49 } // end anonymous namespace
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)
60 InstructionSetFlags
getCpuInstructionSetFlags()
62 InstructionSetFlags eInstructions
= InstructionSetFlags::NONE
;
64 uint32_t info
[] = { 0, 0, 0, 0 };
70 uint32_t aCpuInfoArray
[] = { 0, 0, 0, 0 };
71 getCpuId(aCpuInfoArray
, 1);
73 if ((aCpuInfoArray
[3] & HYPER_bit
) != 0)
74 eInstructions
|= InstructionSetFlags::HYPER
;
76 if ((aCpuInfoArray
[3] & SSE2_bit
) != 0)
77 eInstructions
|= InstructionSetFlags::SSE2
;
79 if ((aCpuInfoArray
[2] & SSSE3_bit
) != 0)
80 eInstructions
|= InstructionSetFlags::SSSE3
;
82 if ((aCpuInfoArray
[2] & SSE41_bit
) != 0)
83 eInstructions
|= InstructionSetFlags::SSE41
;
85 if ((aCpuInfoArray
[2] & SSE42_bit
) != 0)
86 eInstructions
|= InstructionSetFlags::SSE42
;
88 if (((aCpuInfoArray
[2] & AVX_bit
) != 0) && ((aCpuInfoArray
[2] & XSAVE_bit
) != 0))
90 if (checkAVXSupportInOS())
92 eInstructions
|= InstructionSetFlags::AVX
;
96 uint32_t aExtendedInfo
[] = { 0, 0, 0, 0 };
97 getCpuId(aExtendedInfo
, 7);
99 if ((aExtendedInfo
[1] & AVX2_bit
) != 0)
100 eInstructions
|= InstructionSetFlags::AVX2
;
106 return eInstructions
;
109 bool isCpuInstructionSetSupported(InstructionSetFlags eInstructions
)
111 static InstructionSetFlags eCPUFlags
= getCpuInstructionSetFlags();
112 return (eCPUFlags
& eInstructions
) == eInstructions
;
115 OUString
instructionSetSupportedString()
118 if (isCpuInstructionSetSupported(InstructionSetFlags::SSE2
))
120 if (isCpuInstructionSetSupported(InstructionSetFlags::SSSE3
))
122 if (isCpuInstructionSetSupported(InstructionSetFlags::SSE41
))
123 aString
+= "SSE4.1 ";
124 if (isCpuInstructionSetSupported(InstructionSetFlags::SSE42
))
125 aString
+= "SSE4.2 ";
126 if (isCpuInstructionSetSupported(InstructionSetFlags::AVX
))
128 if (isCpuInstructionSetSupported(InstructionSetFlags::AVX2
))
135 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */