cpu.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * cpu.c: CPU detection code
  3.  *****************************************************************************
  4.  * Copyright (C) 1998-2004 the VideoLAN team
  5.  * $Id: 964578335f69c431fd1e23323b76abe2a783e859 $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *          Christophe Massiot <massiot@via.ecp.fr>
  9.  *          Eugenio Jarosiewicz <ej0@cise.ufl.eduEujenio>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  24.  *****************************************************************************/
  25. /*****************************************************************************
  26.  * Preamble
  27.  *****************************************************************************/
  28. #ifdef HAVE_CONFIG_H
  29. # include "config.h"
  30. #endif
  31. #include <vlc_common.h>
  32. #include <sys/types.h>
  33. #ifndef WIN32
  34. #include <unistd.h>
  35. #include <sys/wait.h>
  36. #endif
  37. #include "libvlc.h"
  38. #if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__))
  39. #include <sys/sysctl.h>
  40. #endif
  41. #if defined( __i386__ ) || defined( __x86_64__ ) || defined( __powerpc__ ) 
  42.  || defined( __ppc__ ) || defined( __ppc64__ ) || defined( __powerpc64__ )
  43. static bool check_OS_capability( const char *psz_capability, pid_t pid )
  44. {
  45. #ifndef WIN32
  46.     int status;
  47.     if( pid == -1 )
  48.         return false; /* fail safe :-/ */
  49.     while( waitpid( pid, &status, 0 ) == -1 );
  50.     if( WIFEXITED( status ) && WEXITSTATUS( status ) == 0 )
  51.         return true;
  52.     fprintf( stderr, "warning: your CPU has %s instructions, but not your "
  53.                      "operating system.n", psz_capability );
  54.     fprintf( stderr, "         some optimizations will be disabled unless "
  55.                      "you upgrade your OSn" );
  56.     return false;
  57. #else
  58. # warning FIXME!
  59. # define fork() (errno = ENOSYS, -1)
  60.     (void)pid;
  61.     (void)psz_capability;
  62.     return true;
  63. #endif
  64. }
  65. #endif
  66. /*****************************************************************************
  67.  * CPUCapabilities: get the CPU capabilities
  68.  *****************************************************************************
  69.  * This function is called to list extensions the CPU may have.
  70.  *****************************************************************************/
  71. uint32_t CPUCapabilities( void )
  72. {
  73.     uint32_t i_capabilities = CPU_CAPABILITY_NONE;
  74. #if defined( __i386__ ) || defined( __x86_64__ )
  75.      unsigned int i_eax, i_ebx, i_ecx, i_edx;
  76.      bool b_amd;
  77.     /* Needed for x86 CPU capabilities detection */
  78. #   if defined( __x86_64__ )
  79. #       define cpuid( reg )                    
  80.             asm volatile ( "cpuidnt"         
  81.                            "movl %%ebx,%1nt" 
  82.                          : "=a" ( i_eax ),     
  83.                            "=b" ( i_ebx ),     
  84.                            "=c" ( i_ecx ),     
  85.                            "=d" ( i_edx )      
  86.                          : "a"  ( reg )        
  87.                          : "cc" );
  88. #   else
  89. #       define cpuid( reg )                    
  90.             asm volatile ( "push %%ebxnt"    
  91.                            "cpuidnt"         
  92.                            "movl %%ebx,%1nt" 
  93.                            "pop %%ebxnt"     
  94.                          : "=a" ( i_eax ),     
  95.                            "=r" ( i_ebx ),     
  96.                            "=c" ( i_ecx ),     
  97.                            "=d" ( i_edx )      
  98.                          : "a"  ( reg )        
  99.                          : "cc" );
  100. #   endif
  101.     i_capabilities |= CPU_CAPABILITY_FPU;
  102. #   if defined( __i386__ )
  103.     /* check if cpuid instruction is supported */
  104.     asm volatile ( "push %%ebxnt"
  105.                    "pushfnt"
  106.                    "pop %%eaxnt"
  107.                    "movl %%eax, %%ebxnt"
  108.                    "xorl $0x200000, %%eaxnt"
  109.                    "push %%eaxnt"
  110.                    "popfnt"
  111.                    "pushfnt"
  112.                    "pop %%eaxnt"
  113.                    "movl %%ebx,%1nt"
  114.                    "pop %%ebxnt"
  115.                  : "=a" ( i_eax ),
  116.                    "=r" ( i_ebx )
  117.                  :
  118.                  : "cc" );
  119.     if( i_eax == i_ebx )
  120.         goto out;
  121. #   else
  122.     /* x86_64 supports cpuid instruction, so we dont need to check it */
  123. #   endif
  124.     i_capabilities |= CPU_CAPABILITY_486;
  125.     /* the CPU supports the CPUID instruction - get its level */
  126.     cpuid( 0x00000000 );
  127.     if( !i_eax )
  128.         goto out;
  129.     /* FIXME: this isn't correct, since some 486s have cpuid */
  130.     i_capabilities |= CPU_CAPABILITY_586;
  131.     /* borrowed from mpeg2dec */
  132.     b_amd = ( i_ebx == 0x68747541 ) && ( i_ecx == 0x444d4163 )
  133.                     && ( i_edx == 0x69746e65 );
  134.     /* test for the MMX flag */
  135.     cpuid( 0x00000001 );
  136.     if( ! (i_edx & 0x00800000) )
  137.         goto out;
  138.     i_capabilities |= CPU_CAPABILITY_MMX;
  139.     if( i_edx & 0x02000000 )
  140.     {
  141.         i_capabilities |= CPU_CAPABILITY_MMXEXT;
  142. #   ifdef CAN_COMPILE_SSE
  143.         /* We test if OS supports the SSE instructions */
  144.         pid_t pid = fork();
  145.         if( pid == 0 )
  146.         {
  147.             /* Test a SSE instruction */
  148.             __asm__ __volatile__ ( "xorps %%xmm0,%%xmm0n" : : );
  149.             _exit(0);
  150.         }
  151.         if( check_OS_capability( "SSE", pid ) )
  152.             i_capabilities |= CPU_CAPABILITY_SSE;
  153. #   endif
  154.     }
  155.     if( i_edx & 0x04000000 )
  156.     {
  157. #   if defined(CAN_COMPILE_SSE)
  158.         /* We test if OS supports the SSE2 instructions */
  159.         pid_t pid = fork();
  160.         if( pid == 0 )
  161.         {
  162.             /* Test a SSE2 instruction */
  163.             __asm__ __volatile__ ( "movupd %%xmm0, %%xmm0n" : : );
  164.             _exit(0);
  165.         }
  166.         if( check_OS_capability( "SSE2", pid ) )
  167.             i_capabilities |= CPU_CAPABILITY_SSE2;
  168. #   endif
  169.     }
  170.     /* test for additional capabilities */
  171.     cpuid( 0x80000000 );
  172.     if( i_eax < 0x80000001 )
  173.         goto out;
  174.     /* list these additional capabilities */
  175.     cpuid( 0x80000001 );
  176. #   ifdef CAN_COMPILE_3DNOW
  177.     if( i_edx & 0x80000000 )
  178.     {
  179.         pid_t pid = fork();
  180.         if( pid == 0 )
  181.         {
  182.             /* Test a 3D Now! instruction */
  183.             __asm__ __volatile__ ( "pfadd %%mm0,%%mm0n" "femmsn" : : );
  184.             _exit(0);
  185.         }
  186.         if( check_OS_capability( "3D Now!", pid ) )
  187.             i_capabilities |= CPU_CAPABILITY_3DNOW;
  188.     }
  189. #   endif
  190.     if( b_amd && ( i_edx & 0x00400000 ) )
  191.     {
  192.         i_capabilities |= CPU_CAPABILITY_MMXEXT;
  193.     }
  194. out:
  195. #elif defined( __arm__ )
  196. #   if defined( __ARM_EABI__ ) && !defined( __SOFTFP__ )
  197.     i_capabilities |= CPU_CAPABILITY_FPU;
  198. #   endif
  199. #elif defined( __powerpc__ ) || defined( __ppc__ ) || defined( __powerpc64__ ) 
  200.     || defined( __ppc64__ )
  201.     i_capabilities |= CPU_CAPABILITY_FPU;
  202. #   if defined(__APPLE__)
  203.     int selectors[2] = { CTL_HW, HW_VECTORUNIT };
  204.     int i_has_altivec = 0;
  205.     size_t i_length = sizeof( i_has_altivec );
  206.     int i_error = sysctl( selectors, 2, &i_has_altivec, &i_length, NULL, 0);
  207.     if( i_error == 0 && i_has_altivec != 0 )
  208.         i_capabilities |= CPU_CAPABILITY_ALTIVEC;
  209. #   elif defined( CAN_COMPILE_ALTIVEC )
  210.     pid_t pid = fork();
  211.     if( pid == 0 )
  212.     {
  213.         asm volatile ("mtspr 256, %0nt"
  214.                       "vand %%v0, %%v0, %%v0"
  215.                       :
  216.                       : "r" (-1));
  217.         _exit(0);
  218.     }
  219.     if( check_OS_capability( "Altivec", pid ) )
  220.         i_capabilities |= CPU_CAPABILITY_ALTIVEC;
  221. #   endif
  222. #elif defined( __sparc__ )
  223.     i_capabilities |= CPU_CAPABILITY_FPU;
  224. #elif defined( _MSC_VER ) && !defined( UNDER_CE )
  225.     i_capabilities |= CPU_CAPABILITY_FPU;
  226. #endif
  227.     return i_capabilities;
  228. }
  229. uint32_t cpu_flags = 0;
  230. /*****************************************************************************
  231.  * vlc_CPU: get pre-computed CPU capability flags
  232.  ****************************************************************************/
  233. unsigned vlc_CPU (void)
  234. {
  235.     return cpu_flags;
  236. }
  237. static vlc_memcpy_t pf_vlc_memcpy = memcpy;
  238. static vlc_memset_t pf_vlc_memset = memset;
  239. void vlc_fastmem_register (vlc_memcpy_t cpy, vlc_memset_t set)
  240. {
  241.     if (cpy)
  242.         pf_vlc_memcpy = cpy;
  243.     if (set)
  244.         pf_vlc_memset = set;
  245. }
  246. /**
  247.  * vlc_memcpy: fast CPU-dependent memcpy
  248.  */
  249. void *vlc_memcpy (void *tgt, const void *src, size_t n)
  250. {
  251.     return pf_vlc_memcpy (tgt, src, n);
  252. }
  253. /**
  254.  * vlc_memset: fast CPU-dependent memset
  255.  */
  256. void *vlc_memset (void *tgt, int c, size_t n)
  257. {
  258.     return pf_vlc_memset (tgt, c, n);
  259. }