#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
-/* #pragma GCC target "sse2,ssse3,pclmul" */
+#if BR_AES_X86NI_GCC_OLD
+#pragma GCC push_options
+#pragma GCC target("sse2,ssse3,pclmul")
+#endif
#include <tmmintrin.h>
#include <wmmintrin.h>
#include <cpuid.h>
+#if BR_AES_X86NI_GCC_OLD
+#pragma GCC pop_options
+#endif
#endif
#if BR_AES_X86NI_MSC
#define BR_TARGET(x)
#endif
+/*
+ * GCC versions from 4.4 to 4.8 (inclusive) must use a special #pragma
+ * to activate extra opcodes before including the relevant intrinsic
+ * headers. But these don't work with Clang (which does not need them
+ * either).
+ */
+#if BR_AES_X86NI_GCC && !defined BR_AES_X86NI_GCC_OLD
+#if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ <= 8 && !__clang__
+#define BR_AES_X86NI_GCC_OLD 1
+#endif
+#endif
+
/*
* POWER8 crypto support. We rely on compiler macros for the
* architecture, since we do not have a reliable, simple way to detect
#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
+#if BR_AES_X86NI_GCC_OLD
+#pragma GCC push_options
+#pragma GCC target("sse2,sse4.1,aes,pclmul")
+#endif
#include <wmmintrin.h>
#include <cpuid.h>
+#if BR_AES_X86NI_GCC_OLD
+#pragma GCC pop_options
+#endif
#endif
#if BR_AES_X86NI_MSC
#undef MASK
}
+/*
+ * Per-function attributes appear unreliable on old GCC, so we use the
+ * pragma for all remaining functions in this file.
+ */
+#if BR_AES_X86NI_GCC_OLD
+#pragma GCC target("sse2,sse4.1,aes,pclmul")
+#endif
+
BR_TARGET("sse2,aes")
static inline __m128i
expand_step128(__m128i k, __m128i k2)
#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
+#if BR_AES_X86NI_GCC_OLD
+#pragma GCC target("sse2,sse4.1,aes,pclmul")
+#endif
#include <wmmintrin.h>
#endif
#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
+#if BR_AES_X86NI_GCC_OLD
+#pragma GCC target("sse2,sse4.1,aes,pclmul")
+#endif
#include <wmmintrin.h>
#endif
#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
+#if BR_AES_X86NI_GCC_OLD
+#pragma GCC target("sse2,sse4.1,aes,pclmul")
+#endif
#include <smmintrin.h>
#include <wmmintrin.h>
#define bswap32 __builtin_bswap32