aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/log.txt1
-rw-r--r--src/engine/sse2_eng/eng_sse2.cpp7
-rw-r--r--src/utils/cpuid.cpp108
-rw-r--r--src/utils/cpuid.h51
-rw-r--r--src/utils/info.txt2
5 files changed, 169 insertions, 0 deletions
diff --git a/doc/log.txt b/doc/log.txt
index df48d532c..5bb2d3ee1 100644
--- a/doc/log.txt
+++ b/doc/log.txt
@@ -1,6 +1,7 @@
* 1.9.1-pre, 2009-??-??
- Enable SSE2 optimizations under Visual C++
+ - Add runtime checking for SSE2 availability
- Add an implementation of Blue Midnight Wish (BMW-512)
- Alter Skein-512 to match the tweaked 1.2 specification
diff --git a/src/engine/sse2_eng/eng_sse2.cpp b/src/engine/sse2_eng/eng_sse2.cpp
index 9f68a070e..07c625c7c 100644
--- a/src/engine/sse2_eng/eng_sse2.cpp
+++ b/src/engine/sse2_eng/eng_sse2.cpp
@@ -6,6 +6,7 @@
*/
#include <botan/eng_sse2.h>
+#include <botan/cpuid.h>
#if defined(BOTAN_HAS_SHA1_SSE2)
#include <botan/sha1_sse2.h>
@@ -21,6 +22,9 @@ BlockCipher*
SSE2_Assembler_Engine::find_block_cipher(const SCAN_Name& request,
Algorithm_Factory&) const
{
+ if(!CPUID::has_sse2())
+ return 0;
+
#if defined(BOTAN_HAS_SERPENT_SSE2)
if(request.algo_name() == "Serpent")
return new Serpent_SSE2;
@@ -33,6 +37,9 @@ HashFunction*
SSE2_Assembler_Engine::find_hash(const SCAN_Name& request,
Algorithm_Factory&) const
{
+ if(!CPUID::has_sse2())
+ return 0;
+
#if defined(BOTAN_HAS_SHA1_SSE2)
if(request.algo_name() == "SHA-160")
return new SHA_160_SSE2;
diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp
new file mode 100644
index 000000000..4f22ef867
--- /dev/null
+++ b/src/utils/cpuid.cpp
@@ -0,0 +1,108 @@
+/**
+* Runtime CPU detection
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cpuid.h>
+#include <botan/types.h>
+
+#if defined(_MSC_VER)
+ #include <intrin.h>
+#endif
+
+namespace Botan {
+
+namespace CPUID {
+
+namespace {
+
+/*
+* Call the x86 CPUID instruction and return the contents of ecx and
+* edx, which contain the feature masks.
+*/
+u64bit x86_processor_flags()
+ {
+ static u64bit proc_flags = 0;
+
+ if(proc_flags)
+ return proc_flags;
+
+#if defined(BOTAN_TARGET_ARCH_IS_X86) || defined(BOTAN_TARGET_ARCH_IS_AMD64)
+
+#if defined(__GNUG__)
+
+ u32bit a = 1, b = 0, c = 0, d = 0;
+
+#if defined(__i386__) && defined(__PIC__)
+ // ebx is used in PIC on 32-bit x86, so save and restore it
+ asm("xchgl %%ebx, %1\n\t"
+ "cpuid\n\t"
+ "xchgl %%ebx, %1\n\t"
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) : "0" (a));
+#else
+ // if not PIC or in 64-bit mode, can smash ebx
+ asm("cpuid" : "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "0" (a));
+
+#endif
+
+ proc_flags = ((u64bit)c << 32) | d;
+
+#elif defined(_MSC_VER)
+
+ int cpuinfo[4] = { 0 };
+ __cpuid(cpuinfo, 1);
+
+ proc_flags = ((u64bit)cpuinfo[2] << 32) | cpuinfo[3];
+
+#endif
+
+#endif
+
+ return proc_flags;
+ }
+
+enum CPUID_bits {
+ CPUID_RDTSC_BIT = 4,
+ CPUID_SSE2_BIT = 26,
+ CPUID_SSSE3_BIT = 41,
+ CPUID_SSE41_BIT = 51,
+ CPUID_SSE42_BIT = 52
+};
+
+}
+
+u32bit cache_line_size()
+ {
+ return 32; // FIXME!
+ }
+
+bool has_rdtsc()
+ {
+ return ((x86_processor_flags() >> CPUID_RDTSC_BIT) & 1);
+ }
+
+bool has_sse2()
+ {
+ return ((x86_processor_flags() >> CPUID_SSE2_BIT) & 1);
+ }
+
+bool has_ssse3()
+ {
+ return ((x86_processor_flags() >> CPUID_SSSE3_BIT) & 1);
+ }
+
+bool has_sse41()
+ {
+ return ((x86_processor_flags() >> CPUID_SSE41_BIT) & 1);
+ }
+
+bool has_sse42()
+ {
+ return ((x86_processor_flags() >> CPUID_SSE42_BIT) & 1);
+ }
+
+}
+
+}
diff --git a/src/utils/cpuid.h b/src/utils/cpuid.h
new file mode 100644
index 000000000..557590db8
--- /dev/null
+++ b/src/utils/cpuid.h
@@ -0,0 +1,51 @@
+/**
+* Runtime CPU detection
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CPUID_H__
+#define BOTAN_CPUID_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+namespace CPUID {
+
+/**
+* Return a best guess of the cache line size
+*/
+u32bit cache_line_size();
+
+/**
+* Check if the processor supports RDTSC
+*/
+bool has_rdtsc();
+
+/**
+* Check if the processor supports SSE2
+*/
+bool has_sse2();
+
+/**
+* Check if the processor supports SSSE3
+*/
+bool has_ssse3();
+
+/**
+* Check if the processor supports SSE4.1
+*/
+bool has_sse41();
+
+/**
+* Check if the processor supports SSE4.2
+*/
+bool has_sse42();
+
+}
+
+}
+
+#endif
diff --git a/src/utils/info.txt b/src/utils/info.txt
index 68981729f..f530fb03a 100644
--- a/src/utils/info.txt
+++ b/src/utils/info.txt
@@ -13,6 +13,8 @@ bit_ops.h
bswap.h
charset.cpp
charset.h
+cpuid.cpp
+cpuid.h
exceptn.cpp
exceptn.h
loadstor.h