media/libtheora/lib/x86/x86cpu.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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 # if defined(__amd64__)||defined(__x86_64__)
michael@0 29 /*On x86-64, gcc seems to be able to figure out how to save %rbx for us when
michael@0 30 compiling with -fPIC.*/
michael@0 31 # define cpuid(_op,_eax,_ebx,_ecx,_edx) \
michael@0 32 __asm__ __volatile__( \
michael@0 33 "cpuid\n\t" \
michael@0 34 :[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
michael@0 35 :"a"(_op) \
michael@0 36 :"cc" \
michael@0 37 )
michael@0 38 # else
michael@0 39 /*On x86-32, not so much.*/
michael@0 40 # define cpuid(_op,_eax,_ebx,_ecx,_edx) \
michael@0 41 __asm__ __volatile__( \
michael@0 42 "xchgl %%ebx,%[ebx]\n\t" \
michael@0 43 "cpuid\n\t" \
michael@0 44 "xchgl %%ebx,%[ebx]\n\t" \
michael@0 45 :[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
michael@0 46 :"a"(_op) \
michael@0 47 :"cc" \
michael@0 48 )
michael@0 49 # endif
michael@0 50
michael@0 51 static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
michael@0 52 ogg_uint32_t flags;
michael@0 53 /*If there isn't even MMX, give up.*/
michael@0 54 if(!(_edx&0x00800000))return 0;
michael@0 55 flags=OC_CPU_X86_MMX;
michael@0 56 if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;
michael@0 57 if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;
michael@0 58 if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;
michael@0 59 if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;
michael@0 60 if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;
michael@0 61 if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;
michael@0 62 return flags;
michael@0 63 }
michael@0 64
michael@0 65 static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
michael@0 66 ogg_uint32_t flags;
michael@0 67 /*If there isn't even MMX, give up.*/
michael@0 68 if(!(_edx&0x00800000))return 0;
michael@0 69 flags=OC_CPU_X86_MMX;
michael@0 70 if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;
michael@0 71 if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;
michael@0 72 if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;
michael@0 73 if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;
michael@0 74 if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;
michael@0 75 return flags;
michael@0 76 }
michael@0 77
michael@0 78 ogg_uint32_t oc_cpu_flags_get(void){
michael@0 79 ogg_uint32_t flags;
michael@0 80 ogg_uint32_t eax;
michael@0 81 ogg_uint32_t ebx;
michael@0 82 ogg_uint32_t ecx;
michael@0 83 ogg_uint32_t edx;
michael@0 84 # if !defined(__amd64__)&&!defined(__x86_64__)
michael@0 85 /*Not all x86-32 chips support cpuid, so we have to check.*/
michael@0 86 __asm__ __volatile__(
michael@0 87 "pushfl\n\t"
michael@0 88 "pushfl\n\t"
michael@0 89 "popl %[a]\n\t"
michael@0 90 "movl %[a],%[b]\n\t"
michael@0 91 "xorl $0x200000,%[a]\n\t"
michael@0 92 "pushl %[a]\n\t"
michael@0 93 "popfl\n\t"
michael@0 94 "pushfl\n\t"
michael@0 95 "popl %[a]\n\t"
michael@0 96 "popfl\n\t"
michael@0 97 :[a]"=r"(eax),[b]"=r"(ebx)
michael@0 98 :
michael@0 99 :"cc"
michael@0 100 );
michael@0 101 /*No cpuid.*/
michael@0 102 if(eax==ebx)return 0;
michael@0 103 # endif
michael@0 104 cpuid(0,eax,ebx,ecx,edx);
michael@0 105 /* l e t n I e n i u n e G*/
michael@0 106 if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547||
michael@0 107 /* 6 8 x M T e n i u n e G*/
michael@0 108 ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){
michael@0 109 int family;
michael@0 110 int model;
michael@0 111 /*Intel, Transmeta (tested with Crusoe TM5800):*/
michael@0 112 cpuid(1,eax,ebx,ecx,edx);
michael@0 113 flags=oc_parse_intel_flags(edx,ecx);
michael@0 114 family=(eax>>8)&0xF;
michael@0 115 model=(eax>>4)&0xF;
michael@0 116 /*The SSE unit on the Pentium M and Core Duo is much slower than the MMX
michael@0 117 unit, so don't use it.*/
michael@0 118 if(family==6&&(model==9||model==13||model==14)){
michael@0 119 flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI);
michael@0 120 }
michael@0 121 }
michael@0 122 /* D M A c i t n e h t u A*/
michael@0 123 else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541||
michael@0 124 /* C S N y b e d o e G*/
michael@0 125 ecx==0x43534e20&&edx==0x79622065&&ebx==0x646f6547){
michael@0 126 /*AMD, Geode:*/
michael@0 127 cpuid(0x80000000,eax,ebx,ecx,edx);
michael@0 128 if(eax<0x80000001)flags=0;
michael@0 129 else{
michael@0 130 cpuid(0x80000001,eax,ebx,ecx,edx);
michael@0 131 flags=oc_parse_amd_flags(edx,ecx);
michael@0 132 }
michael@0 133 /*Also check for SSE.*/
michael@0 134 cpuid(1,eax,ebx,ecx,edx);
michael@0 135 flags|=oc_parse_intel_flags(edx,ecx);
michael@0 136 }
michael@0 137 /*Technically some VIA chips can be configured in the BIOS to return any
michael@0 138 string here the user wants.
michael@0 139 There is a special detection method that can be used to identify such
michael@0 140 processors, but in my opinion, if the user really wants to change it, they
michael@0 141 deserve what they get.*/
michael@0 142 /* s l u a H r u a t n e C*/
michael@0 143 else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){
michael@0 144 /*VIA:*/
michael@0 145 /*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)
michael@0 146 chips (thanks to the engineers from Centaur Technology who provided it).
michael@0 147 These chips support Intel-like cpuid info.
michael@0 148 The C3-2 (Nehemiah) cores appear to, as well.*/
michael@0 149 cpuid(1,eax,ebx,ecx,edx);
michael@0 150 flags=oc_parse_intel_flags(edx,ecx);
michael@0 151 if(eax>=0x80000001){
michael@0 152 /*The (non-Nehemiah) C3 processors support AMD-like cpuid info.
michael@0 153 We need to check this even if the Intel test succeeds to pick up 3DNow!
michael@0 154 support on these processors.
michael@0 155 Unlike actual AMD processors, we cannot _rely_ on this info, since
michael@0 156 some cores (e.g., the 693 stepping of the Nehemiah) claim to support
michael@0 157 this function, yet return edx=0, despite the Intel test indicating
michael@0 158 MMX support.
michael@0 159 Therefore the features detected here are strictly added to those
michael@0 160 detected by the Intel test.*/
michael@0 161 /*TODO: How about earlier chips?*/
michael@0 162 cpuid(0x80000001,eax,ebx,ecx,edx);
michael@0 163 /*Note: As of the C7, this function returns Intel-style extended feature
michael@0 164 flags, not AMD-style.
michael@0 165 Currently, this only defines bits 11, 20, and 29 (0x20100800), which
michael@0 166 do not conflict with any of the AMD flags we inspect.
michael@0 167 For the remaining bits, Intel tells us, "Do not count on their value",
michael@0 168 but VIA assures us that they will all be zero (at least on the C7 and
michael@0 169 Isaiah chips).
michael@0 170 In the (unlikely) event a future processor uses bits 18, 19, 30, or 31
michael@0 171 (0xC0C00000) for something else, we will have to add code to detect
michael@0 172 the model to decide when it is appropriate to inspect them.*/
michael@0 173 flags|=oc_parse_amd_flags(edx,ecx);
michael@0 174 }
michael@0 175 }
michael@0 176 else{
michael@0 177 /*Implement me.*/
michael@0 178 flags=0;
michael@0 179 }
michael@0 180 return flags;
michael@0 181 }
michael@0 182 #endif

mercurial