michael@0: /* michael@0: * Copyright © 2000 SuSE, Inc. michael@0: * Copyright © 2007 Red Hat, Inc. michael@0: * michael@0: * Permission to use, copy, modify, distribute, and sell this software and its michael@0: * documentation for any purpose is hereby granted without fee, provided that michael@0: * the above copyright notice appear in all copies and that both that michael@0: * copyright notice and this permission notice appear in supporting michael@0: * documentation, and that the name of SuSE not be used in advertising or michael@0: * publicity pertaining to distribution of the software without specific, michael@0: * written prior permission. SuSE makes no representations about the michael@0: * suitability of this software for any purpose. It is provided "as is" michael@0: * without express or implied warranty. michael@0: * michael@0: * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL michael@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE michael@0: * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES michael@0: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION michael@0: * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN michael@0: * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. michael@0: */ michael@0: #ifdef HAVE_CONFIG_H michael@0: #include michael@0: #endif michael@0: michael@0: #include "pixman-private.h" michael@0: michael@0: #ifdef USE_VMX michael@0: michael@0: /* The CPU detection code needs to be in a file not compiled with michael@0: * "-maltivec -mabi=altivec", as gcc would try to save vector register michael@0: * across function calls causing SIGILL on cpus without Altivec/vmx. michael@0: */ michael@0: #ifdef __APPLE__ michael@0: #include michael@0: michael@0: static pixman_bool_t michael@0: pixman_have_vmx (void) michael@0: { michael@0: int error, have_vmx; michael@0: size_t length = sizeof(have_vmx); michael@0: michael@0: error = sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0); michael@0: michael@0: if (error) michael@0: return FALSE; michael@0: michael@0: return have_vmx; michael@0: } michael@0: michael@0: #elif defined (__OpenBSD__) michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: static pixman_bool_t michael@0: pixman_have_vmx (void) michael@0: { michael@0: int error, have_vmx; michael@0: int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; michael@0: size_t length = sizeof(have_vmx); michael@0: michael@0: error = sysctl (mib, 2, &have_vmx, &length, NULL, 0); michael@0: michael@0: if (error != 0) michael@0: return FALSE; michael@0: michael@0: return have_vmx; michael@0: } michael@0: michael@0: #elif defined (__linux__) michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: static pixman_bool_t michael@0: pixman_have_vmx (void) michael@0: { michael@0: int have_vmx = FALSE; michael@0: int fd; michael@0: struct michael@0: { michael@0: unsigned long type; michael@0: unsigned long value; michael@0: } aux; michael@0: michael@0: fd = open ("/proc/self/auxv", O_RDONLY); michael@0: if (fd >= 0) michael@0: { michael@0: while (read (fd, &aux, sizeof (aux)) == sizeof (aux)) michael@0: { michael@0: if (aux.type == AT_HWCAP && (aux.value & PPC_FEATURE_HAS_ALTIVEC)) michael@0: { michael@0: have_vmx = TRUE; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: close (fd); michael@0: } michael@0: michael@0: return have_vmx; michael@0: } michael@0: michael@0: #else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */ michael@0: #include michael@0: #include michael@0: michael@0: static jmp_buf jump_env; michael@0: michael@0: static void michael@0: vmx_test (int sig, michael@0: siginfo_t *si, michael@0: void * unused) michael@0: { michael@0: longjmp (jump_env, 1); michael@0: } michael@0: michael@0: static pixman_bool_t michael@0: pixman_have_vmx (void) michael@0: { michael@0: struct sigaction sa, osa; michael@0: int jmp_result; michael@0: michael@0: sa.sa_flags = SA_SIGINFO; michael@0: sigemptyset (&sa.sa_mask); michael@0: sa.sa_sigaction = vmx_test; michael@0: sigaction (SIGILL, &sa, &osa); michael@0: jmp_result = setjmp (jump_env); michael@0: if (jmp_result == 0) michael@0: { michael@0: asm volatile ( "vor 0, 0, 0" ); michael@0: } michael@0: sigaction (SIGILL, &osa, NULL); michael@0: return (jmp_result == 0); michael@0: } michael@0: michael@0: #endif /* __APPLE__ */ michael@0: #endif /* USE_VMX */ michael@0: michael@0: pixman_implementation_t * michael@0: _pixman_ppc_get_implementations (pixman_implementation_t *imp) michael@0: { michael@0: #ifdef USE_VMX michael@0: if (!_pixman_disabled ("vmx") && pixman_have_vmx ()) michael@0: imp = _pixman_implementation_create_vmx (imp); michael@0: #endif michael@0: michael@0: return imp; michael@0: }