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