media/libtheora/lib/x86_vc/x86cpu.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /********************************************************************
michael@0 2 * *
michael@0 3 * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
michael@0 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
michael@0 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
michael@0 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
michael@0 7 * *
michael@0 8 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
michael@0 9 * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
michael@0 10 * *
michael@0 11 ********************************************************************
michael@0 12
michael@0 13 CPU capability detection for x86 processors.
michael@0 14 Originally written by Rudolf Marek.
michael@0 15
michael@0 16 function:
michael@0 17 last mod: $Id: x86cpu.c 17410 2010-09-21 21:53:48Z tterribe $
michael@0 18
michael@0 19 ********************************************************************/
michael@0 20
michael@0 21 #include "x86cpu.h"
michael@0 22
michael@0 23 #if !defined(OC_X86_ASM)
michael@0 24 ogg_uint32_t oc_cpu_flags_get(void){
michael@0 25 return 0;
michael@0 26 }
michael@0 27 #else
michael@0 28 /*Why does MSVC need this complicated rigamarole?
michael@0 29 At this point I honestly do not care.*/
michael@0 30
michael@0 31 /*Visual C cpuid helper function.
michael@0 32 For VS2005 we could as well use the _cpuid builtin, but that wouldn't work
michael@0 33 for VS2003 users, so we do it in inline assembler.*/
michael@0 34 static void oc_cpuid_helper(ogg_uint32_t _cpu_info[4],ogg_uint32_t _op){
michael@0 35 _asm{
michael@0 36 mov eax,[_op]
michael@0 37 mov esi,_cpu_info
michael@0 38 cpuid
michael@0 39 mov [esi+0],eax
michael@0 40 mov [esi+4],ebx
michael@0 41 mov [esi+8],ecx
michael@0 42 mov [esi+12],edx
michael@0 43 }
michael@0 44 }
michael@0 45
michael@0 46 # define cpuid(_op,_eax,_ebx,_ecx,_edx) \
michael@0 47 do{ \
michael@0 48 ogg_uint32_t cpu_info[4]; \
michael@0 49 oc_cpuid_helper(cpu_info,_op); \
michael@0 50 (_eax)=cpu_info[0]; \
michael@0 51 (_ebx)=cpu_info[1]; \
michael@0 52 (_ecx)=cpu_info[2]; \
michael@0 53 (_edx)=cpu_info[3]; \
michael@0 54 }while(0)
michael@0 55
michael@0 56 static void oc_detect_cpuid_helper(ogg_uint32_t *_eax,ogg_uint32_t *_ebx){
michael@0 57 _asm{
michael@0 58 pushfd
michael@0 59 pushfd
michael@0 60 pop eax
michael@0 61 mov ebx,eax
michael@0 62 xor eax,200000h
michael@0 63 push eax
michael@0 64 popfd
michael@0 65 pushfd
michael@0 66 pop eax
michael@0 67 popfd
michael@0 68 mov ecx,_eax
michael@0 69 mov [ecx],eax
michael@0 70 mov ecx,_ebx
michael@0 71 mov [ecx],ebx
michael@0 72 }
michael@0 73 }
michael@0 74
michael@0 75 static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
michael@0 76 ogg_uint32_t flags;
michael@0 77 /*If there isn't even MMX, give up.*/
michael@0 78 if(!(_edx&0x00800000))return 0;
michael@0 79 flags=OC_CPU_X86_MMX;
michael@0 80 if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;
michael@0 81 if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;
michael@0 82 if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;
michael@0 83 if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;
michael@0 84 if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;
michael@0 85 if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;
michael@0 86 return flags;
michael@0 87 }
michael@0 88
michael@0 89 static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
michael@0 90 ogg_uint32_t flags;
michael@0 91 /*If there isn't even MMX, give up.*/
michael@0 92 if(!(_edx&0x00800000))return 0;
michael@0 93 flags=OC_CPU_X86_MMX;
michael@0 94 if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;
michael@0 95 if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;
michael@0 96 if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;
michael@0 97 if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;
michael@0 98 if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;
michael@0 99 return flags;
michael@0 100 }
michael@0 101
michael@0 102 ogg_uint32_t oc_cpu_flags_get(void){
michael@0 103 ogg_uint32_t flags;
michael@0 104 ogg_uint32_t eax;
michael@0 105 ogg_uint32_t ebx;
michael@0 106 ogg_uint32_t ecx;
michael@0 107 ogg_uint32_t edx;
michael@0 108 # if !defined(__amd64__)&&!defined(__x86_64__)
michael@0 109 /*Not all x86-32 chips support cpuid, so we have to check.*/
michael@0 110 oc_detect_cpuid_helper(&eax,&ebx);
michael@0 111 /*No cpuid.*/
michael@0 112 if(eax==ebx)return 0;
michael@0 113 # endif
michael@0 114 cpuid(0,eax,ebx,ecx,edx);
michael@0 115 /* l e t n I e n i u n e G*/
michael@0 116 if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547||
michael@0 117 /* 6 8 x M T e n i u n e G*/
michael@0 118 ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){
michael@0 119 int family;
michael@0 120 int model;
michael@0 121 /*Intel, Transmeta (tested with Crusoe TM5800):*/
michael@0 122 cpuid(1,eax,ebx,ecx,edx);
michael@0 123 flags=oc_parse_intel_flags(edx,ecx);
michael@0 124 family=(eax>>8)&0xF;
michael@0 125 model=(eax>>4)&0xF;
michael@0 126 /*The SSE unit on the Pentium M and Core Duo is much slower than the MMX
michael@0 127 unit, so don't use it.*/
michael@0 128 if(family==6&&(model==9||model==13||model==14)){
michael@0 129 flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI);
michael@0 130 }
michael@0 131 }
michael@0 132 /* D M A c i t n e h t u A*/
michael@0 133 else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541||
michael@0 134 /* C S N y b e d o e G*/
michael@0 135 ecx==0x43534e20&&edx==0x79622065&&ebx==0x646f6547){
michael@0 136 /*AMD, Geode:*/
michael@0 137 cpuid(0x80000000,eax,ebx,ecx,edx);
michael@0 138 if(eax<0x80000001)flags=0;
michael@0 139 else{
michael@0 140 cpuid(0x80000001,eax,ebx,ecx,edx);
michael@0 141 flags=oc_parse_amd_flags(edx,ecx);
michael@0 142 }
michael@0 143 /*Also check for SSE.*/
michael@0 144 cpuid(1,eax,ebx,ecx,edx);
michael@0 145 flags|=oc_parse_intel_flags(edx,ecx);
michael@0 146 }
michael@0 147 /*Technically some VIA chips can be configured in the BIOS to return any
michael@0 148 string here the user wants.
michael@0 149 There is a special detection method that can be used to identify such
michael@0 150 processors, but in my opinion, if the user really wants to change it, they
michael@0 151 deserve what they get.*/
michael@0 152 /* s l u a H r u a t n e C*/
michael@0 153 else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){
michael@0 154 /*VIA:*/
michael@0 155 /*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)
michael@0 156 chips (thanks to the engineers from Centaur Technology who provided it).
michael@0 157 These chips support Intel-like cpuid info.
michael@0 158 The C3-2 (Nehemiah) cores appear to, as well.*/
michael@0 159 cpuid(1,eax,ebx,ecx,edx);
michael@0 160 flags=oc_parse_intel_flags(edx,ecx);
michael@0 161 if(eax>=0x80000001){
michael@0 162 /*The (non-Nehemiah) C3 processors support AMD-like cpuid info.
michael@0 163 We need to check this even if the Intel test succeeds to pick up 3DNow!
michael@0 164 support on these processors.
michael@0 165 Unlike actual AMD processors, we cannot _rely_ on this info, since
michael@0 166 some cores (e.g., the 693 stepping of the Nehemiah) claim to support
michael@0 167 this function, yet return edx=0, despite the Intel test indicating
michael@0 168 MMX support.
michael@0 169 Therefore the features detected here are strictly added to those
michael@0 170 detected by the Intel test.*/
michael@0 171 /*TODO: How about earlier chips?*/
michael@0 172 cpuid(0x80000001,eax,ebx,ecx,edx);
michael@0 173 /*Note: As of the C7, this function returns Intel-style extended feature
michael@0 174 flags, not AMD-style.
michael@0 175 Currently, this only defines bits 11, 20, and 29 (0x20100800), which
michael@0 176 do not conflict with any of the AMD flags we inspect.
michael@0 177 For the remaining bits, Intel tells us, "Do not count on their value",
michael@0 178 but VIA assures us that they will all be zero (at least on the C7 and
michael@0 179 Isaiah chips).
michael@0 180 In the (unlikely) event a future processor uses bits 18, 19, 30, or 31
michael@0 181 (0xC0C00000) for something else, we will have to add code to detect
michael@0 182 the model to decide when it is appropriate to inspect them.*/
michael@0 183 flags|=oc_parse_amd_flags(edx,ecx);
michael@0 184 }
michael@0 185 }
michael@0 186 else{
michael@0 187 /*Implement me.*/
michael@0 188 flags=0;
michael@0 189 }
michael@0 190 return flags;
michael@0 191 }
michael@0 192 #endif

mercurial