base_cpudep.c.svn-base

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 327 行

SVN-BASE
327
字号
/*run-time cpu feature detection codemm, alphabet soup...Glenn Kennard <d98gk@efd.lth.se>*/#include "fitz-base.h"/* global run-time constant */unsigned fz_cpuflags = 0;#ifndef HAVE_CPUDEPvoid fz_accelerate(void){}void fz_cpudetect(void){}#else#ifndef WIN32#include <signal.h> /* signal/sigaction */#include <setjmp.h> /* sigsetjmp/siglongjmp */#endif/*#ifdef WIN32#define sigjmp_buf jmp_buf#define sigsetjmp(a,b) setjmp(a)#define siglongjmp longjmp#endif*/typedef struct {	void (*test)(void);	const unsigned flag;	const char *name;} featuretest;#if defined(ARCH_X86) || defined(ARCH_X86_64)#ifdef __GNUC__static void mmx(void){ __asm__ ("pand %mm0, %mm0\n\t"); }static void m3dnow(void){ __asm__ ("pavgusb %mm0, %mm0\n\t"); }static void mmxext(void) /* aka  Extended 3DNow! */{ __asm__ ("pmaxsw %mm0, %mm0\n\t"); }static void sse(void){ __asm__ ("andps %xmm0, %xmm0\n\t"); }static void sse2(void){ __asm__ ("andpd %xmm0, %xmm0\n\t"); }/*static void sse3(void){ __asm__ ("haddps %%xmm0, %%xmm0\n\t" : : : "%xmm0"); }*/#elsestatic void mmx(void){ __asm pand mm0, mm0; }static void m3dnow(void){ __asm pavgusb mm0, mm0; }static void mmxext(void) /* aka  Extended 3DNow! */{ __asm pmaxsw mm0, mm0; }static void sse(void){ __asm andps xmm0, xmm0; }static void sse2(void){ __asm andpd xmm0, xmm0; }#endif#ifdef ARCH_X86_64static void amd64(void)#ifdef __GNUC__{ __asm__ ("and %rax, %rax\n\t"); }#else{ __asm and rax, rax; }#endif#endifstatic const featuretest features[] = {	{ mmx, HAVE_MMX, "mmx" },	{ m3dnow, HAVE_3DNOW, "3dnow" },	{ mmxext, HAVE_MMXEXT, "mmxext" },	{ sse, HAVE_SSE, "sse" },	{ sse2, HAVE_SSE2, "sse2" },/*	{ sse3, HAVE_SSE3, "sse3" }, */#ifdef ARCH_X86_64	{ amd64, HAVE_AMD64, "amd64" }#endif};#endif#if defined(ARCH_SPARC)static void vis(void)/*Stupidly Sun assembler decides to mark anything using VIS instructions in theELF header, which causes link errors if using the following (which alsorequires passing -xarch=v8plusa|v9a passed to the assembler so it accepts theinstruction in the first place, v9a for 64 bit binaries):{ __asm__ ("fand %f8, %f8, %f8\n\t"); }so instead we just emit the opcode directly, bypassing that check.*/{ __asm__ (".word 0x91B20E08"); }/* static void vis2(void){ __asm__ ("edge8n %%l0, %%l0, %%l0\n\t" : : : "%l0"); } */static const featuretest features[] = {	{ vis, HAVE_VIS, "vis" }};#endif#if defined(ARCH_PPC)static void altivec(void){ __asm__ ("vand v0, v0, v0\n\t"); }static const featuretest features[] = {	{ altivec, HAVE_ALTIVEC, "altivec" },};#endifstatic intenabled(char *env, const char *ext){	int len;	char *s;	if (!env)		return 1;	len = strlen(ext);	s = env;	while ((s = strstr(s, ext)))	{		int atstart = s == env || *(s-1) == ',' || *(s-1) == ' ';		s += len;		if (atstart && (*s == ' ' || *s == ',' || *s == '\0')) {			return 1;		}	}	return 0;}static voiddumpflags(void){	unsigned f = fz_cpuflags;	int i, n;	fputs("detected cpu features:", stdout);	n = 0;	for (i = 0; i < sizeof(features) / sizeof(featuretest); i++)	{		if (f & features[i].flag)		{			fputc(' ', stdout);			fputs(features[i].name, stdout);			n ++;		}	}	if (!n)		fputs(" none", stdout);	fputc('\n', stdout);}#ifndef WIN32static sigjmp_buf jmpbuf;static volatile sig_atomic_t canjump;static voidsigillhandler(int sig){	if (!canjump) {		signal(sig, SIG_DFL);		raise(sig);	}	canjump = 0;	siglongjmp(jmpbuf, 1);}void fz_cpudetect(void){	static int hasrun = 0;	unsigned flags = 0;	int i;	void (*oldhandler)(int) = NULL;	void (*tmphandler)(int);	char *env;	if (hasrun)		return;	hasrun = 1;	env = getenv("CPUACCEL");	for (i = 0; i < sizeof(features) / sizeof(featuretest); i++)	{		canjump = 0;		tmphandler = signal(SIGILL, sigillhandler);		if (!oldhandler)			oldhandler = tmphandler;		if (sigsetjmp(jmpbuf, 1))		{			/* test failed - disable feature */			flags &= ~features[i].flag;			continue;		}		canjump = 1;		features[i].test();#if defined(ARCH_X86) || defined(ARCH_X86_64)		/* reset mmx/x87 pipeline state */		if (features[i].flag & (HAVE_MMX | HAVE_3DNOW | HAVE_MMXEXT)) {			__asm__ __volatile__ ("emms\n\t");		}#endif		/* if we got here the test succeeded */		if (enabled(env, features[i].name))			flags |= features[i].flag;		else			flags &= ~features[i].flag;	}	/* restore previous signal handler */	signal(SIGILL, oldhandler);	fz_cpuflags = flags;#if defined(ARCH_X86) || defined(ARCH_X86_64)	__asm__ __volatile__ ("emms\n\t");#endif	dumpflags();}/*static __attribute__((constructor, used)) void fzcpudetect(void){	fz_cpudetect();}*/#else /* WIN32 */void fz_cpudetect(void){	static int hasrun = 0;	unsigned flags = 0;	int i;	char *env;	if (hasrun)		return;	hasrun = 1;	env = getenv("CPUACCEL");	for (i = 0; i < sizeof(features) / sizeof(featuretest); i++)	{		__try		{			features[i].test();		}		__except(EXCEPTION_EXECUTE_HANDLER)		{			/* test failed - disable feature */			flags &= ~features[i].flag;			continue;		}#if defined(ARCH_X86) || defined(ARCH_X86_64)		if (features[i].flag & (HAVE_MMX | HAVE_3DNOW | HAVE_MMXEXT)) {			/* reset mmx/x87 pipeline state */			__asm emms;		}#endif		/* if we got here the test succeeded */		if (enabled(env, features[i].name))			flags |= features[i].flag;		else			flags &= ~features[i].flag;	}	fz_cpuflags = flags;	dumpflags();}#endif#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?