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_CELL_PPU = 0x0070;
163 const u16bit PVR_G4_74xx_24 = 0x800;
167 asm volatile(
"mfspr %0, 287" :
"=r" (pvr));
172 altivec_capable |= (pvr == PVR_G4_7400);
173 altivec_capable |= ((pvr >> 4) == PVR_G4_74xx_24);
174 altivec_capable |= (pvr == PVR_G5_970);
175 altivec_capable |= (pvr == PVR_G5_970FX);
176 altivec_capable |= (pvr == PVR_G5_970MP);
177 altivec_capable |= (pvr == PVR_G5_970GX);
178 altivec_capable |= (pvr == PVR_POWER6);
179 altivec_capable |= (pvr == PVR_POWER7);
180 altivec_capable |= (pvr == PVR_CELL_PPU);
183 return altivec_capable;
195 x86_processor_flags = (
static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];
197 #if defined(BOTAN_TARGET_ARCH_IS_X86_64)
202 if(x86_processor_flags == 0)
203 x86_processor_flags |= (1 << CPUID_SSE2_BIT);
206 cache_line = get_x86_cache_line_size();
208 altivec_capable =
false;
210 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
211 if(altivec_check_sysctl() || altivec_check_pvr_emul())
212 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)