/* * jsimdgcc.c - SIMD instruction support check (gcc) * * x86 SIMD extension for IJG JPEG library * Copyright (C) 1999-2006, MIYASAKA Masaru. * For conditions of distribution and use, see copyright notice in jsimdext.inc * * Last Modified : January 24, 2006 */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include #include static volatile int lockf /* = 0 */; static jmp_buf jmpbuf; /* * Exception handler for signal() */ LOCAL(void) exception_handler (int sig) { signal(SIGILL, SIG_DFL); longjmp(jmpbuf, 1); } /* * Check if the OS supports SIMD instructions */ GLOBAL(unsigned int) jpeg_simd_os_support (unsigned int simd) { #ifdef __GNUC__ /* gcc (i386) */ unsigned int mxcsr = 0x1F80; /* enter critical section */ __asm__ __volatile__ ( "get_lock: \n\t" "movl $1,%%eax \n\t" "xchgl %0,%%eax \n\t" /* try to get lock */ "cmpl $0,%%eax \n\t" /* test if successful */ "je critical_section \n" "spin_loop: \n\t" /*".byte 0xF3,0x90 \n\t"*/ /* "pause" on P4 (short delay) */ "cmpl $0,%0 \n\t" /* check if lock is free */ "jne spin_loop \n\t" "jmp get_lock \n" "critical_section: \n\t" : "=m" (lockf) : "m" (lockf) : "%eax" ); /* If floating point emulation is enabled (CR0.EM = 1), * executing an MMX/3DNow! instruction generates invalid * opcode exception (#UD). */ if (simd & (JSIMD_MMX | JSIMD_3DNOW)) { if (!setjmp(jmpbuf)) { signal(SIGILL, exception_handler); __asm__ __volatile__ ( ".byte 0x0F,0x77" /* emms */ ); signal(SIGILL, SIG_DFL); } else { simd &= ~(JSIMD_MMX | JSIMD_3DNOW); } } if (simd & (JSIMD_SSE | JSIMD_SSE2)) { if (!setjmp(jmpbuf)) { signal(SIGILL, exception_handler); __asm__ __volatile__ ( "leal %0,%%eax \n\t" ".byte 0x0F,0xAE,0x10 \n\t" /* ldmxcsr [eax] */ : : "m" (mxcsr) : "%eax" ); signal(SIGILL, SIG_DFL); } else { simd &= ~(JSIMD_SSE | JSIMD_SSE2); } } /* leave critical section */ lockf = 0; /* release lock */ #endif /* __GNUC__ */ return simd; }