1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2019-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 /** 10 * This file provides portable implementation of CPUID functions: 11 * 12 * void __cpuid(int info[4], int function_id); 13 * void __cpuidex(int info[4], int function_id, int subfunction_id); 14 * int __get_cpuid(unsigned level, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx); 15 */ 16 17 #ifndef UFO_PORTABLE_CPUID_H 18 #define UFO_PORTABLE_CPUID_H 19 20 #if defined(_MSC_VER) || defined(_WIN32) 21 22 #if defined (_WIN64) && defined (_In_) 23 // NOTE: <math.h> is not necessary here. 24 // This is only an ugly workaround for a VS2008 bug that causes the compilation 25 // issue on 64-bit DEBUG configuration. 26 // Including "math.h" before "intrin.h" helps to get rid of the following warning: 27 // warning C4985: 'ceil': attributes not present on previous declaration. 28 #include <math.h> 29 #include <smmintrin.h> 30 #else 31 #include <intrin.h> 32 #endif 33 34 #if (_MSC_VER >= 1500) 35 #pragma intrinsic (__cpuid) 36 #endif 37 38 #if defined(__cplusplus) && (_MSC_VER >= 1900) 39 // __get_cpuid as lambda 40 #define __get_cpuid(_level, _peax, _pebx, _pecx, _pedx) \ 41 [](unsigned level, unsigned *peax, unsigned *pebx, unsigned *pecx, unsigned *pedx) { \ 42 int tmp[4] = { 0 }; \ 43 __cpuid(tmp, level); \ 44 *(peax) = static_cast<unsigned>(tmp[0]); \ 45 *(pebx) = static_cast<unsigned>(tmp[1]); \ 46 *(pecx) = static_cast<unsigned>(tmp[2]); \ 47 *(pedx) = static_cast<unsigned>(tmp[3]); \ 48 return 1; \ 49 } (_level, _peax, _pebx, _pecx, _pedx) 50 #else 51 static __forceinline __get_cpuid(unsigned level,unsigned * peax,unsigned * pebx,unsigned * pecx,unsigned * pedx)52 int __get_cpuid(unsigned level, unsigned *peax, unsigned *pebx, unsigned *pecx, unsigned *pedx) 53 { 54 int tmp[4] = { 0 }; 55 __cpuid(tmp, level); 56 *(peax) = (unsigned)tmp[0]; 57 *(pebx) = (unsigned)tmp[1]; 58 *(pecx) = (unsigned)tmp[2]; 59 *(pedx) = (unsigned)tmp[3]; 60 return 1; 61 } 62 #endif 63 64 #elif defined (__GNUC__) || defined(__clang__) 65 66 #include <cpuid.h> 67 #undef __cpuid // drop internal definition from cpuid.h 68 69 #define __cpuid(info, function) \ 70 (void)__get_cpuid((function), \ 71 (unsigned *)(info)+0, (unsigned *)(info)+1, \ 72 (unsigned *)(info)+2, (unsigned *)(info)+3) 73 74 #define __cpuidex(info, function, sub_function) \ 75 do { \ 76 __cpuid_count((function), (sub_function), (info)[0], (info)[1], (info)[2], (info)[3]); \ 77 } while(0) 78 #else 79 80 #error "FIXME unknown compiler" 81 82 #endif 83 84 #endif /* UFO_PORTABLE_CPUID_H */ 85