blob: d6ad75b1c1a33fdc5fca5e17a15fdf6ad6792cac [file] [log] [blame]
/*
* 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 <setjmp.h>
#include <signal.h>
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;
}