Independent JPEG Group's JPEG software release 6b with x86 SIMD extension for IJG JPEG library version 1.02
96 lines
2.2 KiB
C
96 lines
2.2 KiB
C
/*
|
|
* 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;
|
|
}
|