| /** |
| * This file has no copyright assigned and is placed in the Public Domain. |
| * This file is part of the mingw-w64 runtime package. |
| * No warranty is given; refer to the file DISCLAIMER.PD within this package. |
| */ |
| |
| #if defined(__i386__) |
| #include <windows.h> |
| |
| struct illegal_instruction_establisher_frame { |
| EXCEPTION_REGISTRATION_RECORD exception_record; |
| BOOL illegal_instruction_occured; |
| }; |
| |
| #if defined(__i386__) |
| /* We need to make sure that we align the stack to 16 bytes for the sake of SSE */ |
| __attribute__((force_align_arg_pointer)) |
| #endif |
| static EXCEPTION_DISPOSITION __cdecl |
| illegal_instruction_handler(EXCEPTION_RECORD *ExceptionRecord, |
| PVOID EstablisherFrame, |
| CONTEXT *ContextRecord, |
| PVOID DispatcherContext __attribute__ ((unused))) |
| { |
| |
| if (!(ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING) && |
| !(ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) && |
| ExceptionRecord->ExceptionCode == STATUS_ILLEGAL_INSTRUCTION) |
| { |
| ((struct illegal_instruction_establisher_frame *)EstablisherFrame)->illegal_instruction_occured = TRUE; |
| ContextRecord->Eip += 3; /* skip "movaps %%xmm0, %%xmm0" */ |
| return ExceptionContinueExecution; |
| } |
| |
| return ExceptionContinueSearch; |
| } |
| |
| int __mingw_has_sse (void); |
| static int __has_sse = -1; |
| |
| int __mingw_has_sse(void) |
| { |
| int cpuInfo[4], infoType = 1; |
| int o_flag, n_flag; |
| |
| if (__has_sse != -1) |
| return __has_sse; |
| |
| __asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (o_flag)); |
| n_flag = o_flag ^ 0x200000; |
| __asm__ volatile ("pushl %0\n\tpopfl" : : "g" (n_flag)); |
| __asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (n_flag)); |
| if (n_flag == o_flag) |
| { |
| __has_sse = 0; |
| return 0; |
| } |
| |
| __asm__ __volatile__ ( |
| "cpuid" |
| : "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]), |
| "=d" (cpuInfo[3]) |
| : "a" (infoType)); |
| if (!(cpuInfo[3] & 0x2000000)) |
| { |
| __has_sse = 0; |
| return 0; |
| } |
| |
| /* Pre-Win2k systems do not have to enable CR4.OSFXSR and then |
| * SSE instructions cannot be used even when CPU has SSE support. |
| * So these systems has to be marked as without SSE support. |
| * Try to execute SSE nop "movaps %%xmm0, %%xmm0" and check if system |
| * throws SEH exception STATUS_ILLEGAL_INSTRUCTION or not. |
| * Note that IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) |
| * cannot be used as PF_XMMI_INSTRUCTIONS_AVAILABLE flag is not returned |
| * on pre-Win2k systems, even when system properly enabled CR4.OSFXSR. |
| */ |
| struct illegal_instruction_establisher_frame establisher_frame = { |
| .exception_record = { |
| .Next = (EXCEPTION_REGISTRATION_RECORD *)__readfsdword (0), |
| .Handler = (PEXCEPTION_ROUTINE)(INT_PTR)illegal_instruction_handler, |
| }, |
| .illegal_instruction_occured = FALSE, |
| }; |
| __writefsdword (0, (DWORD)&establisher_frame); |
| __asm__ volatile ("movaps %%xmm0, %%xmm0" :); |
| __writefsdword (0, (DWORD)establisher_frame.exception_record.Next); |
| if (establisher_frame.illegal_instruction_occured) |
| { |
| __has_sse = 0; |
| return 0; |
| } |
| |
| __has_sse = 1; |
| return 1; |
| } |
| #endif /* __i386__ */ |