1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libtheora/lib/x86_vc/x86cpu.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,192 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * 1.7 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 1.8 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 1.9 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 1.10 + * * 1.11 + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * 1.12 + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * 1.13 + * * 1.14 + ******************************************************************** 1.15 + 1.16 + CPU capability detection for x86 processors. 1.17 + Originally written by Rudolf Marek. 1.18 + 1.19 + function: 1.20 + last mod: $Id: x86cpu.c 17410 2010-09-21 21:53:48Z tterribe $ 1.21 + 1.22 + ********************************************************************/ 1.23 + 1.24 +#include "x86cpu.h" 1.25 + 1.26 +#if !defined(OC_X86_ASM) 1.27 +ogg_uint32_t oc_cpu_flags_get(void){ 1.28 + return 0; 1.29 +} 1.30 +#else 1.31 +/*Why does MSVC need this complicated rigamarole? 1.32 + At this point I honestly do not care.*/ 1.33 + 1.34 +/*Visual C cpuid helper function. 1.35 + For VS2005 we could as well use the _cpuid builtin, but that wouldn't work 1.36 + for VS2003 users, so we do it in inline assembler.*/ 1.37 +static void oc_cpuid_helper(ogg_uint32_t _cpu_info[4],ogg_uint32_t _op){ 1.38 + _asm{ 1.39 + mov eax,[_op] 1.40 + mov esi,_cpu_info 1.41 + cpuid 1.42 + mov [esi+0],eax 1.43 + mov [esi+4],ebx 1.44 + mov [esi+8],ecx 1.45 + mov [esi+12],edx 1.46 + } 1.47 +} 1.48 + 1.49 +# define cpuid(_op,_eax,_ebx,_ecx,_edx) \ 1.50 + do{ \ 1.51 + ogg_uint32_t cpu_info[4]; \ 1.52 + oc_cpuid_helper(cpu_info,_op); \ 1.53 + (_eax)=cpu_info[0]; \ 1.54 + (_ebx)=cpu_info[1]; \ 1.55 + (_ecx)=cpu_info[2]; \ 1.56 + (_edx)=cpu_info[3]; \ 1.57 + }while(0) 1.58 + 1.59 +static void oc_detect_cpuid_helper(ogg_uint32_t *_eax,ogg_uint32_t *_ebx){ 1.60 + _asm{ 1.61 + pushfd 1.62 + pushfd 1.63 + pop eax 1.64 + mov ebx,eax 1.65 + xor eax,200000h 1.66 + push eax 1.67 + popfd 1.68 + pushfd 1.69 + pop eax 1.70 + popfd 1.71 + mov ecx,_eax 1.72 + mov [ecx],eax 1.73 + mov ecx,_ebx 1.74 + mov [ecx],ebx 1.75 + } 1.76 +} 1.77 + 1.78 +static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){ 1.79 + ogg_uint32_t flags; 1.80 + /*If there isn't even MMX, give up.*/ 1.81 + if(!(_edx&0x00800000))return 0; 1.82 + flags=OC_CPU_X86_MMX; 1.83 + if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE; 1.84 + if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2; 1.85 + if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI; 1.86 + if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3; 1.87 + if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1; 1.88 + if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2; 1.89 + return flags; 1.90 +} 1.91 + 1.92 +static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){ 1.93 + ogg_uint32_t flags; 1.94 + /*If there isn't even MMX, give up.*/ 1.95 + if(!(_edx&0x00800000))return 0; 1.96 + flags=OC_CPU_X86_MMX; 1.97 + if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT; 1.98 + if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW; 1.99 + if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT; 1.100 + if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A; 1.101 + if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5; 1.102 + return flags; 1.103 +} 1.104 + 1.105 +ogg_uint32_t oc_cpu_flags_get(void){ 1.106 + ogg_uint32_t flags; 1.107 + ogg_uint32_t eax; 1.108 + ogg_uint32_t ebx; 1.109 + ogg_uint32_t ecx; 1.110 + ogg_uint32_t edx; 1.111 +# if !defined(__amd64__)&&!defined(__x86_64__) 1.112 + /*Not all x86-32 chips support cpuid, so we have to check.*/ 1.113 + oc_detect_cpuid_helper(&eax,&ebx); 1.114 + /*No cpuid.*/ 1.115 + if(eax==ebx)return 0; 1.116 +# endif 1.117 + cpuid(0,eax,ebx,ecx,edx); 1.118 + /* l e t n I e n i u n e G*/ 1.119 + if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547|| 1.120 + /* 6 8 x M T e n i u n e G*/ 1.121 + ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){ 1.122 + int family; 1.123 + int model; 1.124 + /*Intel, Transmeta (tested with Crusoe TM5800):*/ 1.125 + cpuid(1,eax,ebx,ecx,edx); 1.126 + flags=oc_parse_intel_flags(edx,ecx); 1.127 + family=(eax>>8)&0xF; 1.128 + model=(eax>>4)&0xF; 1.129 + /*The SSE unit on the Pentium M and Core Duo is much slower than the MMX 1.130 + unit, so don't use it.*/ 1.131 + if(family==6&&(model==9||model==13||model==14)){ 1.132 + flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI); 1.133 + } 1.134 + } 1.135 + /* D M A c i t n e h t u A*/ 1.136 + else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541|| 1.137 + /* C S N y b e d o e G*/ 1.138 + ecx==0x43534e20&&edx==0x79622065&&ebx==0x646f6547){ 1.139 + /*AMD, Geode:*/ 1.140 + cpuid(0x80000000,eax,ebx,ecx,edx); 1.141 + if(eax<0x80000001)flags=0; 1.142 + else{ 1.143 + cpuid(0x80000001,eax,ebx,ecx,edx); 1.144 + flags=oc_parse_amd_flags(edx,ecx); 1.145 + } 1.146 + /*Also check for SSE.*/ 1.147 + cpuid(1,eax,ebx,ecx,edx); 1.148 + flags|=oc_parse_intel_flags(edx,ecx); 1.149 + } 1.150 + /*Technically some VIA chips can be configured in the BIOS to return any 1.151 + string here the user wants. 1.152 + There is a special detection method that can be used to identify such 1.153 + processors, but in my opinion, if the user really wants to change it, they 1.154 + deserve what they get.*/ 1.155 + /* s l u a H r u a t n e C*/ 1.156 + else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){ 1.157 + /*VIA:*/ 1.158 + /*I only have documentation for the C7 (Esther) and Isaiah (forthcoming) 1.159 + chips (thanks to the engineers from Centaur Technology who provided it). 1.160 + These chips support Intel-like cpuid info. 1.161 + The C3-2 (Nehemiah) cores appear to, as well.*/ 1.162 + cpuid(1,eax,ebx,ecx,edx); 1.163 + flags=oc_parse_intel_flags(edx,ecx); 1.164 + if(eax>=0x80000001){ 1.165 + /*The (non-Nehemiah) C3 processors support AMD-like cpuid info. 1.166 + We need to check this even if the Intel test succeeds to pick up 3DNow! 1.167 + support on these processors. 1.168 + Unlike actual AMD processors, we cannot _rely_ on this info, since 1.169 + some cores (e.g., the 693 stepping of the Nehemiah) claim to support 1.170 + this function, yet return edx=0, despite the Intel test indicating 1.171 + MMX support. 1.172 + Therefore the features detected here are strictly added to those 1.173 + detected by the Intel test.*/ 1.174 + /*TODO: How about earlier chips?*/ 1.175 + cpuid(0x80000001,eax,ebx,ecx,edx); 1.176 + /*Note: As of the C7, this function returns Intel-style extended feature 1.177 + flags, not AMD-style. 1.178 + Currently, this only defines bits 11, 20, and 29 (0x20100800), which 1.179 + do not conflict with any of the AMD flags we inspect. 1.180 + For the remaining bits, Intel tells us, "Do not count on their value", 1.181 + but VIA assures us that they will all be zero (at least on the C7 and 1.182 + Isaiah chips). 1.183 + In the (unlikely) event a future processor uses bits 18, 19, 30, or 31 1.184 + (0xC0C00000) for something else, we will have to add code to detect 1.185 + the model to decide when it is appropriate to inspect them.*/ 1.186 + flags|=oc_parse_amd_flags(edx,ecx); 1.187 + } 1.188 + } 1.189 + else{ 1.190 + /*Implement me.*/ 1.191 + flags=0; 1.192 + } 1.193 + return flags; 1.194 +} 1.195 +#endif