media/libtheora/lib/x86_vc/x86cpu.c

changeset 0
6474c204b198
     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

mercurial