diff options
author | lloyd <[email protected]> | 2009-10-29 07:54:52 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-10-29 07:54:52 +0000 |
commit | 077ad13c6f97ab79ecb585c0f584bb8963096098 (patch) | |
tree | 6129c91e2944f831098ae7cbf52e85ff32e7620c /src/utils/cpuid.cpp | |
parent | 0cf1ad7aca8506bbd541641cb1ebc0c73c62bcd2 (diff) | |
parent | 1419961fbc1ef832940d0f5184c3d71797270ef9 (diff) |
propagate from branch 'net.randombit.botan' (head 4fd7eb9630271d3c1dfed21987ef864680d4ce7b)
to branch 'net.randombit.botan.general-simd' (head 91df868149cdc4754d340e6103028acc82182609)
Diffstat (limited to 'src/utils/cpuid.cpp')
-rw-r--r-- | src/utils/cpuid.cpp | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp index f79e3a912..2d3b5d92c 100644 --- a/src/utils/cpuid.cpp +++ b/src/utils/cpuid.cpp @@ -98,4 +98,64 @@ u32bit CPUID::cache_line_size() return cl_size; } +bool CPUID::has_altivec() + { + static bool first_time = true; + static bool altivec_capable = false; + + 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; + + u32bit pvr = 0; + /* + 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 this (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, leave pvr + as 0 which will cause all subsequent model number checks to fail. + */ +#if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD) + 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); +#endif + + first_time = false; + } + + return altivec_capable; + } + } |