media/libtheora/lib/x86/x86cpu.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libtheora/lib/x86/x86cpu.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,182 @@
     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 +# if defined(__amd64__)||defined(__x86_64__)
    1.32 +/*On x86-64, gcc seems to be able to figure out how to save %rbx for us when
    1.33 +   compiling with -fPIC.*/
    1.34 +#  define cpuid(_op,_eax,_ebx,_ecx,_edx) \
    1.35 +  __asm__ __volatile__( \
    1.36 +   "cpuid\n\t" \
    1.37 +   :[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
    1.38 +   :"a"(_op) \
    1.39 +   :"cc" \
    1.40 +  )
    1.41 +# else
    1.42 +/*On x86-32, not so much.*/
    1.43 +#  define cpuid(_op,_eax,_ebx,_ecx,_edx) \
    1.44 +  __asm__ __volatile__( \
    1.45 +   "xchgl %%ebx,%[ebx]\n\t" \
    1.46 +   "cpuid\n\t" \
    1.47 +   "xchgl %%ebx,%[ebx]\n\t" \
    1.48 +   :[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
    1.49 +   :"a"(_op) \
    1.50 +   :"cc" \
    1.51 +  )
    1.52 +# endif
    1.53 +
    1.54 +static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
    1.55 +  ogg_uint32_t flags;
    1.56 +  /*If there isn't even MMX, give up.*/
    1.57 +  if(!(_edx&0x00800000))return 0;
    1.58 +  flags=OC_CPU_X86_MMX;
    1.59 +  if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;
    1.60 +  if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;
    1.61 +  if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;
    1.62 +  if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;
    1.63 +  if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;
    1.64 +  if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;
    1.65 +  return flags;
    1.66 +}
    1.67 +
    1.68 +static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
    1.69 +  ogg_uint32_t flags;
    1.70 +  /*If there isn't even MMX, give up.*/
    1.71 +  if(!(_edx&0x00800000))return 0;
    1.72 +  flags=OC_CPU_X86_MMX;
    1.73 +  if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;
    1.74 +  if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;
    1.75 +  if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;
    1.76 +  if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;
    1.77 +  if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;
    1.78 +  return flags;
    1.79 +}
    1.80 +
    1.81 +ogg_uint32_t oc_cpu_flags_get(void){
    1.82 +  ogg_uint32_t flags;
    1.83 +  ogg_uint32_t eax;
    1.84 +  ogg_uint32_t ebx;
    1.85 +  ogg_uint32_t ecx;
    1.86 +  ogg_uint32_t edx;
    1.87 +# if !defined(__amd64__)&&!defined(__x86_64__)
    1.88 +  /*Not all x86-32 chips support cpuid, so we have to check.*/
    1.89 +  __asm__ __volatile__(
    1.90 +   "pushfl\n\t"
    1.91 +   "pushfl\n\t"
    1.92 +   "popl %[a]\n\t"
    1.93 +   "movl %[a],%[b]\n\t"
    1.94 +   "xorl $0x200000,%[a]\n\t"
    1.95 +   "pushl %[a]\n\t"
    1.96 +   "popfl\n\t"
    1.97 +   "pushfl\n\t"
    1.98 +   "popl %[a]\n\t"
    1.99 +   "popfl\n\t"
   1.100 +   :[a]"=r"(eax),[b]"=r"(ebx)
   1.101 +   :
   1.102 +   :"cc"
   1.103 +  );
   1.104 +  /*No cpuid.*/
   1.105 +  if(eax==ebx)return 0;
   1.106 +# endif
   1.107 +  cpuid(0,eax,ebx,ecx,edx);
   1.108 +  /*         l e t n          I e n i          u n e G*/
   1.109 +  if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547||
   1.110 +   /*      6 8 x M          T e n i          u n e G*/
   1.111 +   ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){
   1.112 +    int family;
   1.113 +    int model;
   1.114 +    /*Intel, Transmeta (tested with Crusoe TM5800):*/
   1.115 +    cpuid(1,eax,ebx,ecx,edx);
   1.116 +    flags=oc_parse_intel_flags(edx,ecx);
   1.117 +    family=(eax>>8)&0xF;
   1.118 +    model=(eax>>4)&0xF;
   1.119 +    /*The SSE unit on the Pentium M and Core Duo is much slower than the MMX
   1.120 +       unit, so don't use it.*/
   1.121 +    if(family==6&&(model==9||model==13||model==14)){
   1.122 +      flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI);
   1.123 +    }
   1.124 +  }
   1.125 +  /*              D M A c          i t n e          h t u A*/
   1.126 +  else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541||
   1.127 +   /*      C S N            y b   e          d o e G*/
   1.128 +   ecx==0x43534e20&&edx==0x79622065&&ebx==0x646f6547){
   1.129 +    /*AMD, Geode:*/
   1.130 +    cpuid(0x80000000,eax,ebx,ecx,edx);
   1.131 +    if(eax<0x80000001)flags=0;
   1.132 +    else{
   1.133 +      cpuid(0x80000001,eax,ebx,ecx,edx);
   1.134 +      flags=oc_parse_amd_flags(edx,ecx);
   1.135 +    }
   1.136 +    /*Also check for SSE.*/
   1.137 +    cpuid(1,eax,ebx,ecx,edx);
   1.138 +    flags|=oc_parse_intel_flags(edx,ecx);
   1.139 +  }
   1.140 +  /*Technically some VIA chips can be configured in the BIOS to return any
   1.141 +     string here the user wants.
   1.142 +    There is a special detection method that can be used to identify such
   1.143 +     processors, but in my opinion, if the user really wants to change it, they
   1.144 +     deserve what they get.*/
   1.145 +  /*              s l u a          H r u a          t n e C*/
   1.146 +  else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){
   1.147 +    /*VIA:*/
   1.148 +    /*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)
   1.149 +       chips (thanks to the engineers from Centaur Technology who provided it).
   1.150 +      These chips support Intel-like cpuid info.
   1.151 +      The C3-2 (Nehemiah) cores appear to, as well.*/
   1.152 +    cpuid(1,eax,ebx,ecx,edx);
   1.153 +    flags=oc_parse_intel_flags(edx,ecx);
   1.154 +    if(eax>=0x80000001){
   1.155 +      /*The (non-Nehemiah) C3 processors support AMD-like cpuid info.
   1.156 +        We need to check this even if the Intel test succeeds to pick up 3DNow!
   1.157 +         support on these processors.
   1.158 +        Unlike actual AMD processors, we cannot _rely_ on this info, since
   1.159 +         some cores (e.g., the 693 stepping of the Nehemiah) claim to support
   1.160 +         this function, yet return edx=0, despite the Intel test indicating
   1.161 +         MMX support.
   1.162 +        Therefore the features detected here are strictly added to those
   1.163 +         detected by the Intel test.*/
   1.164 +      /*TODO: How about earlier chips?*/
   1.165 +      cpuid(0x80000001,eax,ebx,ecx,edx);
   1.166 +      /*Note: As of the C7, this function returns Intel-style extended feature
   1.167 +         flags, not AMD-style.
   1.168 +        Currently, this only defines bits 11, 20, and 29 (0x20100800), which
   1.169 +         do not conflict with any of the AMD flags we inspect.
   1.170 +        For the remaining bits, Intel tells us, "Do not count on their value",
   1.171 +         but VIA assures us that they will all be zero (at least on the C7 and
   1.172 +         Isaiah chips).
   1.173 +        In the (unlikely) event a future processor uses bits 18, 19, 30, or 31
   1.174 +         (0xC0C00000) for something else, we will have to add code to detect
   1.175 +         the model to decide when it is appropriate to inspect them.*/
   1.176 +      flags|=oc_parse_amd_flags(edx,ecx);
   1.177 +    }
   1.178 +  }
   1.179 +  else{
   1.180 +    /*Implement me.*/
   1.181 +    flags=0;
   1.182 +  }
   1.183 +  return flags;
   1.184 +}
   1.185 +#endif

mercurial