#include "config.h"
+#include <assert.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#if CPUFAM_X86 || CPUFAM_AMD64
+enum {
+ CPUID_1_D, /* eax = 1 => edx&?? */
# define CPUID1D_SSE2 (1u << 26)
# define CPUID1D_FXSR (1u << 24)
+
+ CPUID_1_C, /* eax = 1 => ecx&?? */
# define CPUID1C_PCLMUL (1u << 1)
# define CPUID1C_SSSE3 (1u << 9)
# define CPUID1C_AESNI (1u << 25)
# define CPUID1C_AVX (1u << 28)
# define CPUID1C_RDRAND (1u << 30)
+};
+
struct cpuid { unsigned a, b, c, d; };
extern int dispatch_x86ish_cpuid(struct cpuid *, unsigned a, unsigned c);
extern int dispatch_x86ish_xmmregisters_p(void);
static unsigned cpuid_maxleaf(void)
{ struct cpuid c; cpuid(&c, 0, 0); return (c.a); }
-/* --- @cpuid_features_p@ --- *
+/* --- @cpuid_feature_p@ --- *
*
- * Arguments: @unsigned dbits@ = bits to check in EDX
- * @unsigned cbits@ = bits to check in ECX
+ * Arguments: @unsigned leaf@ = leaf to look up
+ * @unsigned bits@ = bits to check
*
- * Returns: Nonzero if all the requested bits are set in the CPUID result
- * on leaf 1.
+ * Returns: Nonzero if all the requested bits are set in the requested
+ * CPUID result.
*/
-static int cpuid_features_p(unsigned dbits, unsigned cbits)
+static int cpuid_feature_p(unsigned leaf, unsigned bits)
{
struct cpuid c;
- if (cpuid_maxleaf() < 1) return (0);
- cpuid(&c, 1, 0);
- return ((c.d & dbits) == dbits && (c.c & cbits) == cbits);
+ unsigned r;
+
+ switch (leaf) {
+ case CPUID_1_D:
+ if (cpuid_maxleaf() < 1) return (0);
+ cpuid(&c, 1, 0); r = c.d;
+ break;
+ case CPUID_1_C:
+ if (cpuid_maxleaf() < 1) return (0);
+ cpuid(&c, 1, 0); r = c.c;
+ break;
+ default:
+ assert(!"unknown cpuid leaf");
+ }
+ return ((r&bits) == bits);
}
/* --- @xmm_registers_available_p@ --- *
if (!p) return (-1);
for (;;) {
- while (isspace((unsigned char)*p)) p++;
+ while (ISSPACE(*p)) p++;
if (!*p) return (-1);
switch (*p) {
case '+': d = +1; p++; break;
case '-': d = 0; p++; break;
default: d = -1; break;
}
- for (q = p; *q && !isspace((unsigned char)*q); q++);
+ for (q = p; *q && !ISSPACE(*q); q++);
if (d >= 0) {
for (pp = ftok; p < q && *pp && *p == *pp; p++, pp++);
if ((p == q && !*pp) || (*p == '*' && p + 1 == q)) return (d);
int IGNORABLE f;
IGNORE(f);
#define CASE_CPUFEAT(feat, ftok, cond) case CPUFEAT_##feat: \
- if ((f = feat_debug(ftok, "environment override", \
- check_env(ftok))) >= 0) \
+ if ((f = feat_debug(ftok, "environment override", check_env(ftok))) >= 0) \
return (f); \
else \
return (feat_debug(ftok, "runtime probe", cond));
switch (feat) {
#if CPUFAM_X86 || CPUFAM_AMD64
CASE_CPUFEAT(X86_SSE2, "x86:sse2",
- cpuid_features_p(CPUID1D_SSE2, 0) &&
+ cpuid_feature_p(CPUID_1_D, CPUID1D_SSE2) &&
xmm_registers_available_p());
CASE_CPUFEAT(X86_AESNI, "x86:aesni",
- cpuid_features_p(CPUID1D_SSE2, CPUID1C_AESNI) &&
+ cpuid_feature_p(CPUID_1_D, CPUID1C_AESNI) &&
xmm_registers_available_p());
CASE_CPUFEAT(X86_RDRAND, "x86:rdrand",
- cpuid_features_p(0, CPUID1C_RDRAND) && rdrand_works_p());
+ cpuid_feature_p(CPUID_1_C, CPUID1C_RDRAND) &&
+ rdrand_works_p());
CASE_CPUFEAT(X86_AVX, "x86:avx",
- cpuid_features_p(0, CPUID1C_AVX) &&
+ cpuid_feature_p(CPUID_1_C, CPUID1C_AVX) &&
xmm_registers_available_p());
CASE_CPUFEAT(X86_SSSE3, "x86:ssse3",
- cpuid_features_p(0, CPUID1C_SSSE3) &&
+ cpuid_feature_p(CPUID_1_C, CPUID1C_SSSE3) &&
xmm_registers_available_p());
CASE_CPUFEAT(X86_PCLMUL, "x86:pclmul",
- cpuid_features_p(0, CPUID1C_PCLMUL) &&
+ cpuid_feature_p(CPUID_1_C, CPUID1C_PCLMUL) &&
xmm_registers_available_p());
#endif
#ifdef CAPMAP