#define EFLAGS_ID (1u << 21)
#define CPUID1D_SSE2 (1u << 26)
+#define CPUID1D_FXSR (1u << 24)
struct cpuid { unsigned a, b, c, d; };
return ((c.d & dbits) == dbits && (c.c & cbits) == cbits);
}
+static int xmm_registers_available_p(void)
+{
+#ifdef __GNUC__
+ unsigned f;
+ /* This hack is by Agner Fog. Use FXSAVE/FXRSTOR to figure out whether the
+ * XMM registers are actually alive.
+ */
+ if (!cpuid_features_p(CPUID1D_FXSR, 0)) return (0);
+ __asm__ ("movl %%esp, %%edx; subl $512, %%esp; andl $~15, %%esp\n"
+ "fxsave (%%esp)\n"
+ "movl 160(%%esp), %%eax; xorl $0xaaaa5555, 160(%%esp)\n"
+ "fxrstor (%%esp); fxsave (%%esp)\n"
+ "movl 160(%%esp), %%ecx; movl %%eax, 160(%%esp)\n"
+ "fxrstor (%%esp); movl %%edx, %%esp\n"
+ "xorl %%ecx, %%eax"
+ : "=a" (f)
+ : /* no inputs */
+ : "%ecx", "%edx");
+ return (f);
+#else
+ return (0);
+#endif
+}
+
#endif
/* --- @check_env@ --- *
#ifdef CPUFAM_X86
case CPUFEAT_X86_SSE2: {
CHECK_ENV("x86:sse2");
- return (cpuid_features_p(CPUID1D_SSE2, 0));
+ return (xmm_registers_available_p() &&
+ cpuid_features_p(CPUID1D_SSE2, 0));
}
#endif
default: