Index: src/OFSystemInfo.h ================================================================== --- src/OFSystemInfo.h +++ src/OFSystemInfo.h @@ -238,67 +238,55 @@ + (bool)supportsEnhanced3DNow; /** * @brief Returns whether the CPU supports SSE. * - * @note This only checks CPU support and assumes OS support! - * * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE */ + (bool)supportsSSE; /** * @brief Returns whether the CPU supports SSE2. * - * @note This only checks CPU support and assumes OS support! - * * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE2 */ + (bool)supportsSSE2; /** * @brief Returns whether the CPU supports SSE3. * - * @note This only checks CPU support and assumes OS support! - * * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE3 */ + (bool)supportsSSE3; /** * @brief Returns whether the CPU supports SSSE3. * - * @note This only checks CPU support and assumes OS support! - * * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSSE3 */ + (bool)supportsSSSE3; /** * @brief Returns whether the CPU supports SSE4.1. * - * @note This only checks CPU support and assumes OS support! - * * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE4.1 */ + (bool)supportsSSE41; /** * @brief Returns whether the CPU supports SSE4.2. * - * @note This only checks CPU support and assumes OS support! - * * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE4.2 */ + (bool)supportsSSE42; Index: src/OFSystemInfo.m ================================================================== --- src/OFSystemInfo.m +++ src/OFSystemInfo.m @@ -16,10 +16,12 @@ #define __NO_EXT_QNX #include "config.h" #include /* include any libc header to get the libc defines */ +#include +#include #include "unistd_wrapper.h" #include "platform.h" @@ -115,10 +117,36 @@ #if defined(OF_AMD64) || defined(OF_X86) struct X86Regs { uint32_t eax, ebx, ecx, edx; }; + +static bool SSESupport; +static jmp_buf SSETestEnv; + +static void +SSETestSIGILLHandler(int signum) +{ + longjmp(SSETestEnv, 1); +} + +static void +SSETest(void) +{ + void (*oldHandler)(int) = signal(SIGILL, SSETestSIGILLHandler); + + if (setjmp(SSETestEnv) == 0) { + __asm__ __volatile__ ( + "movaps %%xmm0, %%xmm0" + ::: "xmm0" /* clang is unhappy if we don't clobber it */ + ); + SSESupport = true; + } else + SSESupport = false; + + signal(SIGILL, oldHandler); +} #endif static size_t pageSize = 4096; static size_t numberOfCPUs = 1; static OFString *operatingSystemName = nil; @@ -343,10 +371,19 @@ { long tmp; if (self != [OFSystemInfo class]) return; + +#if defined(OF_AMD64) || defined(OF_X86) + /* + * Do this as early as possible, as it involves signals. + * Required as cpuid can return SSE support while the OS has not + * enabled it. + */ + SSETest(); +#endif #if defined(OF_WINDOWS) SYSTEM_INFO si; GetSystemInfo(&si); pageSize = si.dwPageSize; @@ -775,36 +812,42 @@ x86CPUID(0x80000001, 0).edx & (1u << 30)); } + (bool)supportsSSE { - return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 25)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 25)); } + (bool)supportsSSE2 { - return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 26)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 26)); } + (bool)supportsSSE3 { - return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 0)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 0)); } + (bool)supportsSSSE3 { - return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 9)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 9)); } + (bool)supportsSSE41 { - return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 19)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 19)); } + (bool)supportsSSE42 { - return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 20)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 20)); } + (bool)supportsAVX { return ((x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 28)) &&