LCOV - code coverage report
Current view: top level - media/libtheora/lib/x86 - x86cpu.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 45 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13