Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/libtheora/x86_vc/x86cpu.c
9912 views
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 *
10
* https://www.xiph.org/ *
11
* *
12
********************************************************************
13
14
CPU capability detection for x86 processors.
15
Originally written by Rudolf Marek.
16
17
function:
18
19
********************************************************************/
20
21
#include "x86cpu.h"
22
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.*/
30
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
}
45
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)
55
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
}
74
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
}
88
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
}
101
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
193
194