8 #include <botan/cpuid.h> 9 #include <botan/types.h> 10 #include <botan/get_byte.h> 11 #include <botan/mem_ops.h> 13 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) 15 #if defined(BOTAN_TARGET_OS_IS_DARWIN) 16 #include <sys/sysctl.h> 19 #if defined(BOTAN_TARGET_OS_IS_OPENBSD) 20 #include <sys/param.h> 21 #include <sys/sysctl.h> 22 #include <machine/cpu.h> 27 #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) 29 #if defined(BOTAN_BUILD_COMPILER_IS_MSVC) 32 #define CALL_CPUID(type, out) do { __cpuid((int*)out, type); } while(0) 34 #elif defined(BOTAN_BUILD_COMPILER_IS_INTEL) 36 #include <ia32intrin.h> 37 #define CALL_CPUID(type, out) do { __cpuid(out, type); } while(0) 39 #elif defined(BOTAN_BUILD_COMPILER_IS_GCC) && (BOTAN_GCC_VERSION >= 430) 49 void __attribute__((__noinline__)) call_gcc_cpuid(
Botan::u32bit type,
52 __get_cpuid(type, out, out+1, out+2, out+3);
55 #define CALL_CPUID call_gcc_cpuid 59 #elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && \ 60 (defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_GCC)) 69 #define CALL_CPUID(type, out) \ 70 asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \ 74 #warning "No method of calling CPUID for this compiler" 81 #define CALL_CPUID(type, out) \ 82 do { out[0] = out[1] = out[2] = out[3] = 0; } while(0); 87 u64bit CPUID::x86_processor_flags = 0;
88 size_t CPUID::cache_line = 32;
89 bool CPUID::altivec_capable =
false;
93 u32bit get_x86_cache_line_size()
95 const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
96 const u32bit AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };
101 if(
same_mem(cpuid + 1, INTEL_CPUID, 3))
106 else if(
same_mem(cpuid + 1, AMD_CPUID, 3))
115 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) 117 bool altivec_check_sysctl()
119 #if defined(BOTAN_TARGET_OS_IS_DARWIN) || defined(BOTAN_TARGET_OS_IS_OPENBSD) 121 #if defined(BOTAN_TARGET_OS_IS_OPENBSD) 122 int sels[2] = { CTL_MACHDEP, CPU_ALTIVEC };
125 int sels[2] = { CTL_HW, HW_VECTORUNIT };
128 size_t length =
sizeof(vector_type);
129 int error = sysctl(sels, 2, &vector_type, &length, NULL, 0);
131 if(error == 0 && vector_type > 0)
138 bool altivec_check_pvr_emul()
140 bool altivec_capable =
false;
142 #if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD) 153 const u16bit PVR_G4_7400 = 0x000C;
154 const u16bit PVR_G5_970 = 0x0039;
155 const u16bit PVR_G5_970FX = 0x003C;
156 const u16bit PVR_G5_970MP = 0x0044;
157 const u16bit PVR_G5_970GX = 0x0045;
158 const u16bit PVR_POWER6 = 0x003E;
159 const u16bit PVR_POWER7 = 0x003F;
160 const u16bit PVR_POWER7p = 0x004A;
161 const u16bit PVR_POWER8 = 0x004D;
162 const u16bit PVR_POWER8E = 0x004B;
163 const u16bit PVR_CELL_PPU = 0x0070;
166 const u16bit PVR_G4_74xx_24 = 0x800;
170 asm volatile(
"mfspr %0, 287" :
"=r" (pvr));
175 altivec_capable |= (pvr == PVR_G4_7400);
176 altivec_capable |= ((pvr >> 4) == PVR_G4_74xx_24);
177 altivec_capable |= (pvr == PVR_G5_970);
178 altivec_capable |= (pvr == PVR_G5_970FX);
179 altivec_capable |= (pvr == PVR_G5_970MP);
180 altivec_capable |= (pvr == PVR_G5_970GX);
181 altivec_capable |= (pvr == PVR_POWER6);
182 altivec_capable |= (pvr == PVR_POWER7);
183 altivec_capable |= (pvr == PVR_POWER7p);
184 altivec_capable |= (pvr == PVR_POWER8);
185 altivec_capable |= (pvr == PVR_POWER8E);
186 altivec_capable |= (pvr == PVR_CELL_PPU);
189 return altivec_capable;
201 x86_processor_flags = (
static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];
203 #if defined(BOTAN_TARGET_ARCH_IS_X86_64) 208 if(x86_processor_flags == 0)
209 x86_processor_flags |= (1 << CPUID_SSE2_BIT);
212 cache_line = get_x86_cache_line_size();
214 altivec_capable =
false;
216 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) 217 if(altivec_check_sysctl() || altivec_check_pvr_emul())
218 altivec_capable =
true;
bool same_mem(const T *p1, const T *p2, size_t n)
byte get_byte(size_t byte_num, T input)
unsigned long long u64bit
#define CALL_CPUID(type, out)