34 #include "lv_common.h"
37 #if defined(VISUAL_ARCH_POWERPC)
38 #if defined(VISUAL_OS_DARWIN)
39 #include <sys/sysctl.h>
46 #if defined(VISUAL_OS_HPUX)
47 #include <sys/mpctl.h>
50 #if defined(VISUAL_OS_NETBSD) || defined(VISUAL_OS_OPENBSD)
51 #include <sys/param.h>
52 #include <sys/sysctl.h>
53 #include <machine/cpu.h>
56 #if defined(VISUAL_OS_FREEBSD)
57 #include <sys/types.h>
58 #include <sys/sysctl.h>
61 #if defined(VISUAL_OS_LINUX)
65 #if defined(VISUAL_OS_WIN32)
69 #if defined(VISUAL_OS_ANDROID)
70 #include <cpu-features.h>
73 #define TEST_BIT(x, n) (((x) >> (n)) & 1)
94 static VisCPU cpu_caps;
95 static int cpu_initialized = FALSE;
98 #if defined(VISUAL_ARCH_X86) //x86 (linux katmai handler check thing)
99 #if defined(VISUAL_OS_LINUX)
100 static void sigill_handler_sse (
int signal,
struct sigcontext sc)
114 cpu_caps.hasSSE = FALSE;
117 static void sigfpe_handler_sse (
int signal,
struct sigcontext sc)
119 if (sc.fpstate->magic != 0xffff) {
123 sc.fpstate->mxcsr |= 0x00000200;
124 sc.fpstate->mxcsr &= 0xfffffffb;
132 #if defined(VISUAL_OS_WIN32)
133 LONG CALLBACK win32_sig_handler_sse (EXCEPTION_POINTERS* ep)
135 if (ep->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) {
136 ep->ContextRecord->Eip +=3;
137 cpu_caps.hasSSE = FALSE;
138 return EXCEPTION_CONTINUE_EXECUTION;
140 return EXCEPTION_CONTINUE_SEARCH;
145 #if defined(VISUAL_ARCH_POWERPC) && !defined(VISUAL_OS_DARWIN)
146 static sigjmp_buf powerpc_jmpbuf;
147 static volatile sig_atomic_t powerpc_canjump = 0;
149 static void sigill_handler (
int sig)
151 if (!powerpc_canjump) {
152 signal (sig, SIG_DFL);
157 siglongjmp (powerpc_jmpbuf, 1);
160 static void check_os_altivec_support (
void)
162 #if defined(VISUAL_OS_DARWIN)
163 int sels[2] = {CTL_HW, HW_VECTORUNIT};
165 visual_size_t len =
sizeof(has_vu);
168 err = sysctl (sels, 2, &has_vu, &len, NULL, 0);
172 cpu_caps.hasAltiVec = 1;
176 signal (SIGILL, sigill_handler);
177 if (sigsetjmp (powerpc_jmpbuf, 1)) {
178 signal (SIGILL, SIG_DFL);
184 "vand %%v0, %%v0, %%v0"
188 signal (SIGILL, SIG_DFL);
189 cpu_caps.hasAltiVec = 1;
201 #if defined(VISUAL_ARCH_X86)
202 static void check_os_katmai_support (
void)
204 #if defined(VISUAL_OS_FREEBSD)
205 int has_sse = 0, ret;
206 visual_size_t len =
sizeof(has_sse);
208 ret = sysctlbyname (
"hw.instruction_sse", &has_sse, &len, NULL, 0);
210 cpu_caps.hasSSE = FALSE;
212 #elif defined(VISUAL_OS_NETBSD) || defined(VISUAL_OS_OPENBSD)
213 int has_sse, has_sse2, ret, mib[2];
214 visual_size_t varlen;
216 mib[0] = CTL_MACHDEP;
218 varlen =
sizeof(has_sse);
220 ret = sysctl (mib, 2, &has_sse, &varlen, NULL, 0);
221 if (ret < 0 || !has_sse) {
222 cpu_caps.hasSSE = FALSE;
224 cpu_caps.hasSSE = TRUE;
228 varlen =
sizeof (has_sse2);
229 ret = sysctl (mib, 2, &has_sse2, &varlen, NULL, 0);
230 if (ret < 0 || !has_sse2) {
231 cpu_caps.hasSSE2 = FALSE;
233 cpu_caps.hasSSE2 = TRUE;
235 cpu_caps.hasSSE = FALSE;
237 #elif defined(VISUAL_OS_WIN32)
238 LPTOP_LEVEL_EXCEPTION_FILTER exc_fil;
239 if (cpu_caps.hasSSE) {
240 exc_fil = SetUnhandledExceptionFilter (win32_sig_handler_sse);
241 __asm __volatile (
"xorps %xmm0, %xmm0");
242 SetUnhandledExceptionFilter (exc_fil);
244 #elif defined(VISUAL_OS_LINUX)
245 struct sigaction saved_sigill;
246 struct sigaction saved_sigfpe;
250 sigaction (SIGILL, NULL, &saved_sigill);
251 sigaction (SIGFPE, NULL, &saved_sigfpe);
253 signal (SIGILL, (
void (*)(
int)) sigill_handler_sse);
254 signal (SIGFPE, (
void (*)(
int)) sigfpe_handler_sse);
262 if (cpu_caps.hasSSE) {
263 __asm __volatile (
"xorps %xmm1, %xmm0");
284 sigaction (SIGILL, &saved_sigill, NULL);
285 sigaction (SIGFPE, &saved_sigfpe, NULL);
291 cpu_caps.hasSSE = FALSE;
297 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
298 static int has_cpuid (
void)
300 #if defined(VISUAL_ARCH_X86)
307 "xorl $0x200000, %0\n"
317 #elif defined(VISUAL_ARCH_X86_64)
325 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
326 static void cpuid (
unsigned int ax,
unsigned int *p)
329 (
"movl %%ebx, %%esi\n\t"
332 :
"=a" (p[0]),
"=S" (p[1]),
333 "=c" (p[2]),
"=d" (p[3])
338 static unsigned int get_number_of_cores (
void)
342 #if defined(VISUAL_OS_LINUX) || defined(VISUAL_OS_SOLARIS) || defined(VISUAL_OS_AIX)
344 int ncpus = sysconf (_SC_NPROCESSORS_ONLN);
346 return ncpus != -1 ? ncpus : 1;
348 #elif defined(VISUAL_OS_NETBSD) || defined(VISUAL_OS_FREEBSD) || defined(VISUAL_OS_OPENBSD) || defined(VISUAL_OS_DARWIN)
352 visual_size_t len =
sizeof (ncpus);
357 sysctl (mib, 2, &ncpus, &len, NULL, 0);
359 return ncpus >= 1 ? ncpus : 1;
361 #elif defined(VISUAL_OS_HPUX)
363 return mpctl (MPC_GETNUMSPUS, NULL, NULL);
365 #elif defined(VISUAL_OS_IRIX)
367 return sysconf (_SC_NPROC_ONLN);
369 #elif defined(VISUAL_OS_ANDROID)
371 return android_getCpuCount ();
373 #elif defined(VISUAL_OS_WIN32)
375 SYSTEM_INFO system_info;
377 GetSystemInfo (&system_info);
379 return system_info.dwNumberOfProcessors;
390 #if defined(VISUAL_ARCH_MIPS)
392 #elif defined(VISUAL_ARCH_ALPHA)
394 #elif defined(VISUAL_ARCH_SPARC)
396 #elif defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
398 #elif defined(VISUAL_ARCH_POWERPC)
400 #elif defined(VISUAL_ARCH_ARM)
407 static void print_cpu_info (
void)
412 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
421 #elif defined(VISUAL_ARCH_POWERPC)
423 #elif defined(VISUAL_ARCH_ARM)
431 void visual_cpu_initialize ()
433 visual_mem_set (&cpu_caps, 0,
sizeof (VisCPU));
435 cpu_caps.type = get_cpu_type ();
436 cpu_caps.num_cores = get_number_of_cores ();
438 #if defined(VISUAL_ARCH_ARM)
439 # if defined(VISUAL_OS_ANDROID)
440 if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM) {
441 uint64_t type = android_getCpuFeatures ();
443 if (type & ANDROID_CPU_ARM_FEATURE_ARMv7)
444 cpu_caps.hasARMv7 = TRUE;
446 if (type & ANDROID_CPU_ARM_FEATURE_VFPv3)
447 cpu_caps.hasVFPv3 = TRUE;
449 if (type & ANDROID_CPU_ARM_FEATURE_NEON)
450 cpu_caps.hasNeon = TRUE;
452 if(type & ANDROID_CPU_ARM_FEATURE_LDREX_STREX)
453 cpu_caps.hasLDREX_STREX = TRUE;
458 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
464 cpu_caps.cacheline = 32;
466 unsigned int regs[4];
467 unsigned int regs2[4];
470 cpuid (0x00000000, regs);
472 if (regs[0] >= 0x00000001) {
473 unsigned int cacheline;
475 cpuid (0x00000001, regs2);
477 cpu_caps.x86cpuType = (regs2[0] >> 8) & 0xf;
478 if (cpu_caps.x86cpuType == 0xf)
479 cpu_caps.x86cpuType = 8 + ((regs2[0] >> 20) & 255);
482 cpu_caps.hasMMX = TEST_BIT (regs2[3], 23);
483 cpu_caps.hasSSE = TEST_BIT (regs2[3], 25);
484 cpu_caps.hasSSE2 = TEST_BIT (regs2[3], 26);
485 cpu_caps.hasMMX2 = cpu_caps.hasSSE;
487 cacheline = ((regs2[1] >> 8) & 0xFF) * 8;
489 cpu_caps.cacheline = cacheline;
492 cpuid (0x80000000, regs);
494 if (regs[0] >= 0x80000001) {
496 cpuid (0x80000001, regs2);
498 cpu_caps.hasMMX |= TEST_BIT (regs2[3], 23);
499 cpu_caps.hasMMX2 |= TEST_BIT (regs2[3], 22);
500 cpu_caps.has3DNow = TEST_BIT (regs2[3], 31);
501 cpu_caps.has3DNowExt = TEST_BIT (regs2[3], 30);
504 if (regs[0] >= 0x80000006) {
505 cpuid (0x80000006, regs2);
506 cpu_caps.cacheline = regs2[2] & 0xFF;
509 #if defined(VISUAL_ARCH_X86)
511 check_os_katmai_support ();
513 if (!cpu_caps.hasSSE)
514 cpu_caps.hasSSE2 = FALSE;
519 #if defined(VISUAL_ARCH_POWERPC)
520 check_os_altivec_support ();
525 cpu_initialized = TRUE;
532 return cpu_caps.type;
537 visual_return_val_if_fail (cpu_initialized, 1);
539 return cpu_caps.num_cores;
544 visual_return_val_if_fail (cpu_initialized, FALSE);
546 return cpu_caps.hasMMX;
551 visual_return_val_if_fail (cpu_initialized, FALSE);
553 return cpu_caps.hasMMX2;
558 visual_return_val_if_fail (cpu_initialized, FALSE);
560 return cpu_caps.hasSSE;
564 visual_return_val_if_fail (cpu_initialized, FALSE);
566 return cpu_caps.hasSSE2;
571 visual_return_val_if_fail (cpu_initialized, FALSE);
573 return cpu_caps.has3DNow;
578 visual_return_val_if_fail (cpu_initialized, FALSE);
580 return cpu_caps.has3DNowExt;
585 visual_return_val_if_fail (cpu_initialized, FALSE);
587 return cpu_caps.hasAltiVec;
592 visual_return_val_if_fail (cpu_initialized, FALSE);
594 return cpu_caps.hasARMv7;
599 visual_return_val_if_fail (cpu_initialized, FALSE);
601 return cpu_caps.hasVFPv3;
606 visual_return_val_if_fail (cpu_initialized, FALSE);
608 return cpu_caps.hasNeon;
613 visual_return_val_if_fail (cpu_initialized, FALSE);
615 return cpu_caps.hasLDREX_STREX;