1c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* libFLAC - Free Lossless Audio Codec library 2c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson 3c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 4c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Redistribution and use in source and binary forms, with or without 5c74663799493f2b1e6123c18def94295d0afab7Kenny Root * modification, are permitted provided that the following conditions 6c74663799493f2b1e6123c18def94295d0afab7Kenny Root * are met: 7c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 8c74663799493f2b1e6123c18def94295d0afab7Kenny Root * - Redistributions of source code must retain the above copyright 9c74663799493f2b1e6123c18def94295d0afab7Kenny Root * notice, this list of conditions and the following disclaimer. 10c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 11c74663799493f2b1e6123c18def94295d0afab7Kenny Root * - Redistributions in binary form must reproduce the above copyright 12c74663799493f2b1e6123c18def94295d0afab7Kenny Root * notice, this list of conditions and the following disclaimer in the 13c74663799493f2b1e6123c18def94295d0afab7Kenny Root * documentation and/or other materials provided with the distribution. 14c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 15c74663799493f2b1e6123c18def94295d0afab7Kenny Root * - Neither the name of the Xiph.org Foundation nor the names of its 16c74663799493f2b1e6123c18def94295d0afab7Kenny Root * contributors may be used to endorse or promote products derived from 17c74663799493f2b1e6123c18def94295d0afab7Kenny Root * this software without specific prior written permission. 18c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 19c74663799493f2b1e6123c18def94295d0afab7Kenny Root * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20c74663799493f2b1e6123c18def94295d0afab7Kenny Root * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21c74663799493f2b1e6123c18def94295d0afab7Kenny Root * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22c74663799493f2b1e6123c18def94295d0afab7Kenny Root * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 23c74663799493f2b1e6123c18def94295d0afab7Kenny Root * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24c74663799493f2b1e6123c18def94295d0afab7Kenny Root * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25c74663799493f2b1e6123c18def94295d0afab7Kenny Root * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26c74663799493f2b1e6123c18def94295d0afab7Kenny Root * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27c74663799493f2b1e6123c18def94295d0afab7Kenny Root * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28c74663799493f2b1e6123c18def94295d0afab7Kenny Root * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29c74663799493f2b1e6123c18def94295d0afab7Kenny Root * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 31c74663799493f2b1e6123c18def94295d0afab7Kenny Root 32c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if HAVE_CONFIG_H 33c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <config.h> 34c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 35c74663799493f2b1e6123c18def94295d0afab7Kenny Root 36c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include "private/cpu.h" 37c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <stdlib.h> 38c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <stdio.h> 39c74663799493f2b1e6123c18def94295d0afab7Kenny Root 40c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if defined FLAC__CPU_IA32 41c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <signal.h> 42c74663799493f2b1e6123c18def94295d0afab7Kenny Root#elif defined FLAC__CPU_PPC 43c74663799493f2b1e6123c18def94295d0afab7Kenny Root# if !defined FLAC__NO_ASM 44c74663799493f2b1e6123c18def94295d0afab7Kenny Root# if defined FLAC__SYS_DARWIN 45c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <sys/sysctl.h> 46c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <mach/mach.h> 47c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <mach/mach_host.h> 48c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <mach/host_info.h> 49c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <mach/machine.h> 50c74663799493f2b1e6123c18def94295d0afab7Kenny Root# ifndef CPU_SUBTYPE_POWERPC_970 51c74663799493f2b1e6123c18def94295d0afab7Kenny Root# define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) 52c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 53c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else /* FLAC__SYS_DARWIN */ 54c74663799493f2b1e6123c18def94295d0afab7Kenny Root 55c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <signal.h> 56c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <setjmp.h> 57c74663799493f2b1e6123c18def94295d0afab7Kenny Root 58c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic sigjmp_buf jmpbuf; 59c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic volatile sig_atomic_t canjump = 0; 60c74663799493f2b1e6123c18def94295d0afab7Kenny Root 61c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void sigill_handler (int sig) 62c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 63c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (!canjump) { 64c74663799493f2b1e6123c18def94295d0afab7Kenny Root signal (sig, SIG_DFL); 65c74663799493f2b1e6123c18def94295d0afab7Kenny Root raise (sig); 66c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 67c74663799493f2b1e6123c18def94295d0afab7Kenny Root canjump = 0; 68c74663799493f2b1e6123c18def94295d0afab7Kenny Root siglongjmp (jmpbuf, 1); 69c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 70c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif /* FLAC__SYS_DARWIN */ 71c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif /* FLAC__NO_ASM */ 72c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif /* FLAC__CPU_PPC */ 73c74663799493f2b1e6123c18def94295d0afab7Kenny Root 74c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if defined (__NetBSD__) || defined(__OpenBSD__) 75c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <sys/param.h> 76c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <sys/sysctl.h> 77c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <machine/cpu.h> 78c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 79c74663799493f2b1e6123c18def94295d0afab7Kenny Root 80c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 81c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <sys/types.h> 82c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <sys/sysctl.h> 83c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 84c74663799493f2b1e6123c18def94295d0afab7Kenny Root 85c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if defined(__APPLE__) 86c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* how to get sysctlbyname()? */ 87c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 88c74663799493f2b1e6123c18def94295d0afab7Kenny Root 89c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* these are flags in EDX of CPUID AX=00000001 */ 90c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000; 91c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000; 92c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000; 93c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000; 94c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000; 95c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* these are flags in ECX of CPUID AX=00000001 */ 96c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_SSE3 = 0x00000001; 97c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_SSSE3 = 0x00000200; 98c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* these are flags in EDX of CPUID AX=80000001 */ 99c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW = 0x80000000; 100c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW = 0x40000000; 101c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000; 102c74663799493f2b1e6123c18def94295d0afab7Kenny Root 103c74663799493f2b1e6123c18def94295d0afab7Kenny Root 104c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* 105c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Extra stuff needed for detection of OS support for SSE on IA-32 106c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 107c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM && !defined FLAC__NO_SSE_OS && !defined FLAC__SSE_OS 108c74663799493f2b1e6123c18def94295d0afab7Kenny Root# if defined(__linux__) 109c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* 110c74663799493f2b1e6123c18def94295d0afab7Kenny Root * If the OS doesn't support SSE, we will get here with a SIGILL. We 111c74663799493f2b1e6123c18def94295d0afab7Kenny Root * modify the return address to jump over the offending SSE instruction 112c74663799493f2b1e6123c18def94295d0afab7Kenny Root * and also the operation following it that indicates the instruction 113c74663799493f2b1e6123c18def94295d0afab7Kenny Root * executed successfully. In this way we use no global variables and 114c74663799493f2b1e6123c18def94295d0afab7Kenny Root * stay thread-safe. 115c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 116c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 3 + 3 + 6: 117c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 3 bytes for "xorps xmm0,xmm0" 118c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 3 bytes for estimate of how long the follwing "inc var" instruction is 119c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 6 bytes extra in case our estimate is wrong 120c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 12 bytes puts us in the NOP "landing zone" 121c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 122c74663799493f2b1e6123c18def94295d0afab7Kenny Root# undef USE_OBSOLETE_SIGCONTEXT_FLAVOR /* #define this to use the older signal handler method */ 123c74663799493f2b1e6123c18def94295d0afab7Kenny Root# ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR 124c74663799493f2b1e6123c18def94295d0afab7Kenny Root static void sigill_handler_sse_os(int signal, struct sigcontext sc) 125c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 126c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)signal; 127c74663799493f2b1e6123c18def94295d0afab7Kenny Root sc.eip += 3 + 3 + 6; 128c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 129c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else 130c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <sys/ucontext.h> 131c74663799493f2b1e6123c18def94295d0afab7Kenny Root static void sigill_handler_sse_os(int signal, siginfo_t *si, void *uc) 132c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 133c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)signal, (void)si; 134c74663799493f2b1e6123c18def94295d0afab7Kenny Root ((ucontext_t*)uc)->uc_mcontext.gregs[14/*REG_EIP*/] += 3 + 3 + 6; 135c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 136c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 137c74663799493f2b1e6123c18def94295d0afab7Kenny Root# elif defined(_MSC_VER) 138c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <windows.h> 139c74663799493f2b1e6123c18def94295d0afab7Kenny Root# undef USE_TRY_CATCH_FLAVOR /* #define this to use the try/catch method for catching illegal opcode exception */ 140c74663799493f2b1e6123c18def94295d0afab7Kenny Root# ifdef USE_TRY_CATCH_FLAVOR 141c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else 142c74663799493f2b1e6123c18def94295d0afab7Kenny Root LONG CALLBACK sigill_handler_sse_os(EXCEPTION_POINTERS *ep) 143c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 144c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(ep->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) { 145c74663799493f2b1e6123c18def94295d0afab7Kenny Root ep->ContextRecord->Eip += 3 + 3 + 6; 146c74663799493f2b1e6123c18def94295d0afab7Kenny Root return EXCEPTION_CONTINUE_EXECUTION; 147c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 148c74663799493f2b1e6123c18def94295d0afab7Kenny Root return EXCEPTION_CONTINUE_SEARCH; 149c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 150c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 151c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 152c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 153c74663799493f2b1e6123c18def94295d0afab7Kenny Root 154c74663799493f2b1e6123c18def94295d0afab7Kenny Root 155c74663799493f2b1e6123c18def94295d0afab7Kenny Rootvoid FLAC__cpu_info(FLAC__CPUInfo *info) 156c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 157c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* 158c74663799493f2b1e6123c18def94295d0afab7Kenny Root * IA32-specific 159c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 160c74663799493f2b1e6123c18def94295d0afab7Kenny Root#ifdef FLAC__CPU_IA32 161c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->type = FLAC__CPUINFO_TYPE_IA32; 162c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if !defined FLAC__NO_ASM && defined FLAC__HAS_NASM 163c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->use_asm = true; /* we assume a minimum of 80386 with FLAC__CPU_IA32 */ 164c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.cpuid = FLAC__cpu_have_cpuid_asm_ia32()? true : false; 165c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.bswap = info->data.ia32.cpuid; /* CPUID => BSWAP since it came after */ 166c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.cmov = false; 167c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.mmx = false; 168c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = false; 169c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.sse = false; 170c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.sse2 = false; 171c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.sse3 = false; 172c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.ssse3 = false; 173c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32._3dnow = false; 174c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.ext3dnow = false; 175c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.extmmx = false; 176c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(info->data.ia32.cpuid) { 177c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* http://www.sandpile.org/ia32/cpuid.htm */ 178c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__uint32 flags_edx, flags_ecx; 179c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx); 180c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.cmov = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false; 181c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.mmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_MMX )? true : false; 182c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = (flags_edx & FLAC__CPUINFO_IA32_CPUID_FXSR )? true : false; 183c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.sse = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE )? true : false; 184c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.sse2 = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE2 )? true : false; 185c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false; 186c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false; 187c74663799493f2b1e6123c18def94295d0afab7Kenny Root 188c74663799493f2b1e6123c18def94295d0afab7Kenny Root#ifdef FLAC__USE_3DNOW 189c74663799493f2b1e6123c18def94295d0afab7Kenny Root flags_edx = FLAC__cpu_info_extended_amd_asm_ia32(); 190c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32._3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW )? true : false; 191c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.ext3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW)? true : false; 192c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.extmmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX )? true : false; 193c74663799493f2b1e6123c18def94295d0afab7Kenny Root#else 194c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32._3dnow = info->data.ia32.ext3dnow = info->data.ia32.extmmx = false; 195c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 196c74663799493f2b1e6123c18def94295d0afab7Kenny Root 197c74663799493f2b1e6123c18def94295d0afab7Kenny Root#ifdef DEBUG 198c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, "CPU info (IA-32):\n"); 199c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " CPUID ...... %c\n", info->data.ia32.cpuid ? 'Y' : 'n'); 200c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " BSWAP ...... %c\n", info->data.ia32.bswap ? 'Y' : 'n'); 201c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " CMOV ....... %c\n", info->data.ia32.cmov ? 'Y' : 'n'); 202c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " MMX ........ %c\n", info->data.ia32.mmx ? 'Y' : 'n'); 203c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " FXSR ....... %c\n", info->data.ia32.fxsr ? 'Y' : 'n'); 204c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " SSE ........ %c\n", info->data.ia32.sse ? 'Y' : 'n'); 205c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " SSE2 ....... %c\n", info->data.ia32.sse2 ? 'Y' : 'n'); 206c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " SSE3 ....... %c\n", info->data.ia32.sse3 ? 'Y' : 'n'); 207c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " SSSE3 ...... %c\n", info->data.ia32.ssse3 ? 'Y' : 'n'); 208c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " 3DNow! ..... %c\n", info->data.ia32._3dnow ? 'Y' : 'n'); 209c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " 3DNow!-ext . %c\n", info->data.ia32.ext3dnow? 'Y' : 'n'); 210c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " 3DNow!-MMX . %c\n", info->data.ia32.extmmx ? 'Y' : 'n'); 211c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 212c74663799493f2b1e6123c18def94295d0afab7Kenny Root 213c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* 214c74663799493f2b1e6123c18def94295d0afab7Kenny Root * now have to check for OS support of SSE/SSE2 215c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 216c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(info->data.ia32.fxsr || info->data.ia32.sse || info->data.ia32.sse2) { 217c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if defined FLAC__NO_SSE_OS 218c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* assume user knows better than us; turn it off */ 219c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; 220c74663799493f2b1e6123c18def94295d0afab7Kenny Root#elif defined FLAC__SSE_OS 221c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* assume user knows better than us; leave as detected above */ 222c74663799493f2b1e6123c18def94295d0afab7Kenny Root#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__APPLE__) 223c74663799493f2b1e6123c18def94295d0afab7Kenny Root int sse = 0; 224c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t len; 225c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* at least one of these must work: */ 226c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = sizeof(sse); sse = sse || (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) == 0 && sse); 227c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = sizeof(sse); sse = sse || (sysctlbyname("hw.optional.sse" , &sse, &len, NULL, 0) == 0 && sse); /* __APPLE__ ? */ 228c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!sse) 229c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; 230c74663799493f2b1e6123c18def94295d0afab7Kenny Root#elif defined(__NetBSD__) || defined (__OpenBSD__) 231c74663799493f2b1e6123c18def94295d0afab7Kenny Root# if __NetBSD_Version__ >= 105250000 || (defined __OpenBSD__) 232c74663799493f2b1e6123c18def94295d0afab7Kenny Root int val = 0, mib[2] = { CTL_MACHDEP, CPU_SSE }; 233c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t len = sizeof(val); 234c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) 235c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; 236c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { /* double-check SSE2 */ 237c74663799493f2b1e6123c18def94295d0afab7Kenny Root mib[1] = CPU_SSE2; 238c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = sizeof(val); 239c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) 240c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; 241c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 242c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else 243c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; 244c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 245c74663799493f2b1e6123c18def94295d0afab7Kenny Root#elif defined(__linux__) 246c74663799493f2b1e6123c18def94295d0afab7Kenny Root int sse = 0; 247c74663799493f2b1e6123c18def94295d0afab7Kenny Root struct sigaction sigill_save; 248c74663799493f2b1e6123c18def94295d0afab7Kenny Root#ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR 249c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == sigaction(SIGILL, NULL, &sigill_save) && signal(SIGILL, (void (*)(int))sigill_handler_sse_os) != SIG_ERR) 250c74663799493f2b1e6123c18def94295d0afab7Kenny Root#else 251c74663799493f2b1e6123c18def94295d0afab7Kenny Root struct sigaction sigill_sse; 252c74663799493f2b1e6123c18def94295d0afab7Kenny Root sigill_sse.sa_sigaction = sigill_handler_sse_os; 253c74663799493f2b1e6123c18def94295d0afab7Kenny Root __sigemptyset(&sigill_sse.sa_mask); 254c74663799493f2b1e6123c18def94295d0afab7Kenny Root sigill_sse.sa_flags = SA_SIGINFO | SA_RESETHAND; /* SA_RESETHAND just in case our SIGILL return jump breaks, so we don't get stuck in a loop */ 255c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == sigaction(SIGILL, &sigill_sse, &sigill_save)) 256c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 257c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 258c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */ 259c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* see sigill_handler_sse_os() for an explanation of the following: */ 260c74663799493f2b1e6123c18def94295d0afab7Kenny Root asm volatile ( 261c74663799493f2b1e6123c18def94295d0afab7Kenny Root "xorl %0,%0\n\t" /* for some reason, still need to do this to clear 'sse' var */ 262c74663799493f2b1e6123c18def94295d0afab7Kenny Root "xorps %%xmm0,%%xmm0\n\t" /* will cause SIGILL if unsupported by OS */ 263c74663799493f2b1e6123c18def94295d0afab7Kenny Root "incl %0\n\t" /* SIGILL handler will jump over this */ 264c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* landing zone */ 265c74663799493f2b1e6123c18def94295d0afab7Kenny Root "nop\n\t" /* SIGILL jump lands here if "inc" is 9 bytes */ 266c74663799493f2b1e6123c18def94295d0afab7Kenny Root "nop\n\t" 267c74663799493f2b1e6123c18def94295d0afab7Kenny Root "nop\n\t" 268c74663799493f2b1e6123c18def94295d0afab7Kenny Root "nop\n\t" 269c74663799493f2b1e6123c18def94295d0afab7Kenny Root "nop\n\t" 270c74663799493f2b1e6123c18def94295d0afab7Kenny Root "nop\n\t" 271c74663799493f2b1e6123c18def94295d0afab7Kenny Root "nop\n\t" /* SIGILL jump lands here if "inc" is 3 bytes (expected) */ 272c74663799493f2b1e6123c18def94295d0afab7Kenny Root "nop\n\t" 273c74663799493f2b1e6123c18def94295d0afab7Kenny Root "nop" /* SIGILL jump lands here if "inc" is 1 byte */ 274c74663799493f2b1e6123c18def94295d0afab7Kenny Root : "=r"(sse) 275c74663799493f2b1e6123c18def94295d0afab7Kenny Root : "r"(sse) 276c74663799493f2b1e6123c18def94295d0afab7Kenny Root ); 277c74663799493f2b1e6123c18def94295d0afab7Kenny Root 278c74663799493f2b1e6123c18def94295d0afab7Kenny Root sigaction(SIGILL, &sigill_save, NULL); 279c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 280c74663799493f2b1e6123c18def94295d0afab7Kenny Root 281c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!sse) 282c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; 283c74663799493f2b1e6123c18def94295d0afab7Kenny Root#elif defined(_MSC_VER) 284c74663799493f2b1e6123c18def94295d0afab7Kenny Root# ifdef USE_TRY_CATCH_FLAVOR 285c74663799493f2b1e6123c18def94295d0afab7Kenny Root _try { 286c74663799493f2b1e6123c18def94295d0afab7Kenny Root __asm { 287c74663799493f2b1e6123c18def94295d0afab7Kenny Root# if _MSC_VER <= 1200 288c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* VC6 assembler doesn't know SSE, have to emit bytecode instead */ 289c74663799493f2b1e6123c18def94295d0afab7Kenny Root _emit 0x0F 290c74663799493f2b1e6123c18def94295d0afab7Kenny Root _emit 0x57 291c74663799493f2b1e6123c18def94295d0afab7Kenny Root _emit 0xC0 292c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else 293c74663799493f2b1e6123c18def94295d0afab7Kenny Root xorps xmm0,xmm0 294c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 295c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 296c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 297c74663799493f2b1e6123c18def94295d0afab7Kenny Root _except(EXCEPTION_EXECUTE_HANDLER) { 298c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION) 299c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; 300c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 301c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else 302c74663799493f2b1e6123c18def94295d0afab7Kenny Root int sse = 0; 303c74663799493f2b1e6123c18def94295d0afab7Kenny Root LPTOP_LEVEL_EXCEPTION_FILTER save = SetUnhandledExceptionFilter(sigill_handler_sse_os); 304c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* see GCC version above for explanation */ 305c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* http://msdn2.microsoft.com/en-us/library/4ks26t93.aspx */ 306c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* http://www.codeproject.com/cpp/gccasm.asp */ 307c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* http://www.hick.org/~mmiller/msvc_inline_asm.html */ 308c74663799493f2b1e6123c18def94295d0afab7Kenny Root __asm { 309c74663799493f2b1e6123c18def94295d0afab7Kenny Root# if _MSC_VER <= 1200 310c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* VC6 assembler doesn't know SSE, have to emit bytecode instead */ 311c74663799493f2b1e6123c18def94295d0afab7Kenny Root _emit 0x0F 312c74663799493f2b1e6123c18def94295d0afab7Kenny Root _emit 0x57 313c74663799493f2b1e6123c18def94295d0afab7Kenny Root _emit 0xC0 314c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else 315c74663799493f2b1e6123c18def94295d0afab7Kenny Root xorps xmm0,xmm0 316c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 317c74663799493f2b1e6123c18def94295d0afab7Kenny Root inc sse 318c74663799493f2b1e6123c18def94295d0afab7Kenny Root nop 319c74663799493f2b1e6123c18def94295d0afab7Kenny Root nop 320c74663799493f2b1e6123c18def94295d0afab7Kenny Root nop 321c74663799493f2b1e6123c18def94295d0afab7Kenny Root nop 322c74663799493f2b1e6123c18def94295d0afab7Kenny Root nop 323c74663799493f2b1e6123c18def94295d0afab7Kenny Root nop 324c74663799493f2b1e6123c18def94295d0afab7Kenny Root nop 325c74663799493f2b1e6123c18def94295d0afab7Kenny Root nop 326c74663799493f2b1e6123c18def94295d0afab7Kenny Root nop 327c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 328c74663799493f2b1e6123c18def94295d0afab7Kenny Root SetUnhandledExceptionFilter(save); 329c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!sse) 330c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; 331c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 332c74663799493f2b1e6123c18def94295d0afab7Kenny Root#else 333c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* no way to test, disable to be safe */ 334c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; 335c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 336c74663799493f2b1e6123c18def94295d0afab7Kenny Root#ifdef DEBUG 337c74663799493f2b1e6123c18def94295d0afab7Kenny Root fprintf(stderr, " SSE OS sup . %c\n", info->data.ia32.sse ? 'Y' : 'n'); 338c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 339c74663799493f2b1e6123c18def94295d0afab7Kenny Root 340c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 341c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 342c74663799493f2b1e6123c18def94295d0afab7Kenny Root#else 343c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->use_asm = false; 344c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 345c74663799493f2b1e6123c18def94295d0afab7Kenny Root 346c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* 347c74663799493f2b1e6123c18def94295d0afab7Kenny Root * PPC-specific 348c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 349c74663799493f2b1e6123c18def94295d0afab7Kenny Root#elif defined FLAC__CPU_PPC 350c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->type = FLAC__CPUINFO_TYPE_PPC; 351c74663799493f2b1e6123c18def94295d0afab7Kenny Root# if !defined FLAC__NO_ASM 352c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->use_asm = true; 353c74663799493f2b1e6123c18def94295d0afab7Kenny Root# ifdef FLAC__USE_ALTIVEC 354c74663799493f2b1e6123c18def94295d0afab7Kenny Root# if defined FLAC__SYS_DARWIN 355c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 356c74663799493f2b1e6123c18def94295d0afab7Kenny Root int val = 0, mib[2] = { CTL_HW, HW_VECTORUNIT }; 357c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t len = sizeof(val); 358c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ppc.altivec = !(sysctl(mib, 2, &val, &len, NULL, 0) || !val); 359c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 360c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 361c74663799493f2b1e6123c18def94295d0afab7Kenny Root host_basic_info_data_t hostInfo; 362c74663799493f2b1e6123c18def94295d0afab7Kenny Root mach_msg_type_number_t infoCount; 363c74663799493f2b1e6123c18def94295d0afab7Kenny Root 364c74663799493f2b1e6123c18def94295d0afab7Kenny Root infoCount = HOST_BASIC_INFO_COUNT; 365c74663799493f2b1e6123c18def94295d0afab7Kenny Root host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount); 366c74663799493f2b1e6123c18def94295d0afab7Kenny Root 367c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ppc.ppc64 = (hostInfo.cpu_type == CPU_TYPE_POWERPC) && (hostInfo.cpu_subtype == CPU_SUBTYPE_POWERPC_970); 368c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 369c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else /* FLAC__USE_ALTIVEC && !FLAC__SYS_DARWIN */ 370c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 371c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* no Darwin, do it the brute-force way */ 372c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* @@@@@@ this is not thread-safe; replace with SSE OS method above or remove */ 373c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ppc.altivec = 0; 374c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ppc.ppc64 = 0; 375c74663799493f2b1e6123c18def94295d0afab7Kenny Root 376c74663799493f2b1e6123c18def94295d0afab7Kenny Root signal (SIGILL, sigill_handler); 377c74663799493f2b1e6123c18def94295d0afab7Kenny Root canjump = 0; 378c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (!sigsetjmp (jmpbuf, 1)) { 379c74663799493f2b1e6123c18def94295d0afab7Kenny Root canjump = 1; 380c74663799493f2b1e6123c18def94295d0afab7Kenny Root 381c74663799493f2b1e6123c18def94295d0afab7Kenny Root asm volatile ( 382c74663799493f2b1e6123c18def94295d0afab7Kenny Root "mtspr 256, %0\n\t" 383c74663799493f2b1e6123c18def94295d0afab7Kenny Root "vand %%v0, %%v0, %%v0" 384c74663799493f2b1e6123c18def94295d0afab7Kenny Root : 385c74663799493f2b1e6123c18def94295d0afab7Kenny Root : "r" (-1) 386c74663799493f2b1e6123c18def94295d0afab7Kenny Root ); 387c74663799493f2b1e6123c18def94295d0afab7Kenny Root 388c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ppc.altivec = 1; 389c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 390c74663799493f2b1e6123c18def94295d0afab7Kenny Root canjump = 0; 391c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (!sigsetjmp (jmpbuf, 1)) { 392c74663799493f2b1e6123c18def94295d0afab7Kenny Root int x = 0; 393c74663799493f2b1e6123c18def94295d0afab7Kenny Root canjump = 1; 394c74663799493f2b1e6123c18def94295d0afab7Kenny Root 395c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* PPC64 hardware implements the cntlzd instruction */ 396c74663799493f2b1e6123c18def94295d0afab7Kenny Root asm volatile ("cntlzd %0, %1" : "=r" (x) : "r" (x) ); 397c74663799493f2b1e6123c18def94295d0afab7Kenny Root 398c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ppc.ppc64 = 1; 399c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 400c74663799493f2b1e6123c18def94295d0afab7Kenny Root signal (SIGILL, SIG_DFL); /*@@@@@@ should save and restore old signal */ 401c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 402c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 403c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else /* !FLAC__USE_ALTIVEC */ 404c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ppc.altivec = 0; 405c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->data.ppc.ppc64 = 0; 406c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 407c74663799493f2b1e6123c18def94295d0afab7Kenny Root# else 408c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->use_asm = false; 409c74663799493f2b1e6123c18def94295d0afab7Kenny Root# endif 410c74663799493f2b1e6123c18def94295d0afab7Kenny Root 411c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* 412c74663799493f2b1e6123c18def94295d0afab7Kenny Root * unknown CPI 413c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 414c74663799493f2b1e6123c18def94295d0afab7Kenny Root#else 415c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->type = FLAC__CPUINFO_TYPE_UNKNOWN; 416c74663799493f2b1e6123c18def94295d0afab7Kenny Root info->use_asm = false; 417c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 418c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 419