aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/utils/cpuid.cpp127
1 files changed, 74 insertions, 53 deletions
diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp
index 2ba7f9b77..d024a19c0 100644
--- a/src/utils/cpuid.cpp
+++ b/src/utils/cpuid.cpp
@@ -10,7 +10,11 @@
#include <botan/loadstor.h>
#include <botan/mem_ops.h>
-#if defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64)
+#if defined(BOTAN_TARGET_OS_IS_DARWIN)
+ #include <sys/sysctl.h>
+#endif
+
+#if defined(BOTAN_TARGET_IS_X86_FAMILY)
#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
@@ -64,6 +68,72 @@ u32bit get_x86_cache_line_size()
return 32; // default cache line guess
}
+#if defined(BOTAN_TARGET_IS_PPC_FAMILY)
+
+bool altivec_check_sysctl()
+ {
+#if defined(BOTAN_TARGET_OS_IS_DARWIN)
+
+ // From Apple's docs
+ int sels[2] = { CTL_HW, HW_VECTORUNIT };
+ int vector_type = 0;
+ size_t length = sizeof(vector_type);
+ int error = sysctl(sels, 2, &vector_type, &length, NULL, 0);
+
+ if(error == 0 && vector_type > 0)
+ return true;
+#endif
+
+ return false;
+ }
+
+bool altivec_check_pvr_emul()
+ {
+ bool altivec_capable = false;
+
+#if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD)
+
+ /*
+ On PowerPC, MSR 287 is PVR, the Processor Version Number
+ Normally it is only accessible to ring 0, but Linux and NetBSD
+ (others, too, maybe?) will trap and emulate it for us.
+
+ PVR identifiers for various AltiVec enabled CPUs. Taken from
+ PearPC and Linux sources, mostly.
+ */
+
+ const u16bit PVR_G4_7400 = 0x000C;
+ const u16bit PVR_G5_970 = 0x0039;
+ const u16bit PVR_G5_970FX = 0x003C;
+ const u16bit PVR_G5_970MP = 0x0044;
+ const u16bit PVR_G5_970GX = 0x0045;
+ const u16bit PVR_POWER6 = 0x003E;
+ const u16bit PVR_CELL_PPU = 0x0070;
+
+ // Motorola produced G4s with PVR 0x800[0123C] (at least)
+ const u16bit PVR_G4_74xx_24 = 0x800;
+
+ u32bit pvr = 0;
+
+ asm volatile("mfspr %0, 287" : "=r" (pvr));
+
+ // Top 16 bit suffice to identify model
+ pvr >>= 16;
+
+ altivec_capable |= (pvr == PVR_G4_7400);
+ altivec_capable |= ((pvr >> 8) == PVR_G4_74xx_24);
+ altivec_capable |= (pvr == PVR_G5_970);
+ altivec_capable |= (pvr == PVR_G5_970FX);
+ altivec_capable |= (pvr == PVR_G5_970MP);
+ altivec_capable |= (pvr == PVR_G5_970GX);
+ altivec_capable |= (pvr == PVR_CELL_PPU);
+#endif
+
+ return altivec_capable;
+ }
+
+#endif
+
}
/*
@@ -105,58 +175,9 @@ bool CPUID::has_altivec()
if(first_time)
{
-#if defined(BOTAN_TARGET_ARCH_IS_PPC) || defined(BOTAN_TARGET_ARCH_IS_PPC64)
-
- /*
- PVR identifiers for various AltiVec enabled CPUs. Taken from
- PearPC and Linux sources, mostly.
- */
- const u16bit PVR_G4_7400 = 0x000C;
- const u16bit PVR_G5_970 = 0x0039;
- const u16bit PVR_G5_970FX = 0x003C;
- const u16bit PVR_G5_970MP = 0x0044;
- const u16bit PVR_G5_970GX = 0x0045;
- const u16bit PVR_POWER6 = 0x003E;
- const u16bit PVR_CELL_PPU = 0x0070;
-
- // Motorola produced G4s with PVR 0x800[0123C] (at least)
- const u16bit PVR_G4_74xx_24 = 0x800;
-
- /*
- On PowerPC, MSR 287 is PVR, the Processor Version Number
-
- Normally it is only accessible to ring 0, but Linux and NetBSD
- (at least) will trap and emulate it for us. This is roughly 20x
- saner than every other approach I've seen for AltiVec detection
- (all of which are entirely OS specific, to boot).
-
- Apparently OS X doesn't support this, but then again OS X
- doesn't really support PPC anymore, so I'm not worrying about it.
-
- For OSes that aren't (known to) support the emulation, skip the
- call, leaving pvr as 0 which will cause all subsequent model
- number checks to fail (and we'll assume no AltiVec)
- */
-
-#if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD)
- #define BOTAN_TARGET_OS_SUPPORTS_MFSPR_EMUL
-#endif
-
- u32bit pvr = 0;
-
-#if defined(BOTAN_TARGET_OS_SUPPORTS_MFSPR_EMUL)
- asm volatile("mfspr %0, 287" : "=r" (pvr));
-#endif
- // Top 16 bit suffice to identify model
- pvr >>= 16;
-
- altivec_capable |= (pvr == PVR_G4_7400);
- altivec_capable |= ((pvr >> 8) == PVR_G4_74xx_24);
- altivec_capable |= (pvr == PVR_G5_970);
- altivec_capable |= (pvr == PVR_G5_970FX);
- altivec_capable |= (pvr == PVR_G5_970MP);
- altivec_capable |= (pvr == PVR_G5_970GX);
- altivec_capable |= (pvr == PVR_CELL_PPU);
+#if defined(BOTAN_TARGET_IS_PPC_FAMILY)
+ if(altivec_check_sysctl() || altivec_check_pvr_emul())
+ altivec_capable = true;
#endif
first_time = false;