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);
87u64bit CPUID::x86_processor_flags = 0;
88size_t CPUID::cache_line = 32;
89bool CPUID::altivec_capable =
false;
93u32bit 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)
117bool 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)
138bool 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;
#define CALL_CPUID(type, out)
byte get_byte(size_t byte_num, T input)
unsigned long long u64bit
bool same_mem(const T *p1, const T *p2, size_t n)