tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

x86cpu.c (5261B)


      1 /* Copyright (c) 2014, Cisco Systems, INC
      2   Written by XiangMingZhu WeiZhou MinPeng YanWang
      3 
      4   Redistribution and use in source and binary forms, with or without
      5   modification, are permitted provided that the following conditions
      6   are met:
      7 
      8   - Redistributions of source code must retain the above copyright
      9   notice, this list of conditions and the following disclaimer.
     10 
     11   - Redistributions in binary form must reproduce the above copyright
     12   notice, this list of conditions and the following disclaimer in the
     13   documentation and/or other materials provided with the distribution.
     14 
     15   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     18   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     19   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     23   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     24   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     25   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 */
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include "config.h"
     30 #endif
     31 
     32 #include "cpu_support.h"
     33 #include "macros.h"
     34 #include "main.h"
     35 #include "pitch.h"
     36 #include "x86cpu.h"
     37 
     38 #if defined(OPUS_HAVE_RTCD) && \
     39  ((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
     40  (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
     41  (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
     42  (defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)))
     43 
     44 #if defined(_MSC_VER)
     45 
     46 #include <intrin.h>
     47 static _inline void cpuid(unsigned int CPUInfo[4], unsigned int InfoType)
     48 {
     49    __cpuid((int*)CPUInfo, InfoType);
     50 }
     51 
     52 #else
     53 
     54 #if defined(CPU_INFO_BY_C)
     55 #include <cpuid.h>
     56 #endif
     57 
     58 static void cpuid(unsigned int CPUInfo[4], unsigned int InfoType)
     59 {
     60 #if defined(CPU_INFO_BY_ASM)
     61 #if defined(__i386__) && defined(__PIC__)
     62 /* %ebx is PIC register in 32-bit, so mustn't clobber it. */
     63    __asm__ __volatile__ (
     64        "xchg %%ebx, %1\n"
     65        "cpuid\n"
     66        "xchg %%ebx, %1\n":
     67        "=a" (CPUInfo[0]),
     68        "=r" (CPUInfo[1]),
     69        "=c" (CPUInfo[2]),
     70        "=d" (CPUInfo[3]) :
     71        /* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */
     72        "0" (InfoType), "2" (0)
     73    );
     74 #else
     75    __asm__ __volatile__ (
     76        "cpuid":
     77        "=a" (CPUInfo[0]),
     78        "=b" (CPUInfo[1]),
     79        "=c" (CPUInfo[2]),
     80        "=d" (CPUInfo[3]) :
     81        /* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */
     82        "0" (InfoType), "2" (0)
     83    );
     84 #endif
     85 #elif defined(CPU_INFO_BY_C)
     86    /* We use __get_cpuid_count to clear ECX to avoid a valgrind false-positive
     87        prior to v3.17.0.*/
     88    if (!__get_cpuid_count(InfoType, 0, &(CPUInfo[0]), &(CPUInfo[1]), &(CPUInfo[2]), &(CPUInfo[3]))) {
     89        /* Our function cannot fail, but __get_cpuid{_count} can.
     90           Returning all zeroes will effectively disable all SIMD, which is
     91            what we want on CPUs that don't support CPUID. */
     92        CPUInfo[3] = CPUInfo[2] = CPUInfo[1] = CPUInfo[0] = 0;
     93    }
     94 #else
     95 # error "Configured to use x86 RTCD, but no CPU detection method available. " \
     96 "Reconfigure with --disable-rtcd (or send patches)."
     97 #endif
     98 }
     99 
    100 #endif
    101 
    102 typedef struct CPU_Feature{
    103    /*  SIMD: 128-bit */
    104    int HW_SSE;
    105    int HW_SSE2;
    106    int HW_SSE41;
    107    /*  SIMD: 256-bit */
    108    int HW_AVX2;
    109 } CPU_Feature;
    110 
    111 static void opus_cpu_feature_check(CPU_Feature *cpu_feature)
    112 {
    113    unsigned int info[4];
    114    unsigned int nIds = 0;
    115 
    116    cpuid(info, 0);
    117    nIds = info[0];
    118 
    119    if (nIds >= 1){
    120        cpuid(info, 1);
    121        cpu_feature->HW_SSE = (info[3] & (1 << 25)) != 0;
    122        cpu_feature->HW_SSE2 = (info[3] & (1 << 26)) != 0;
    123        cpu_feature->HW_SSE41 = (info[2] & (1 << 19)) != 0;
    124        cpu_feature->HW_AVX2 = (info[2] & (1 << 28)) != 0 && (info[2] & (1 << 12)) != 0;
    125        if (cpu_feature->HW_AVX2 && nIds >= 7) {
    126            cpuid(info, 7);
    127            cpu_feature->HW_AVX2 = cpu_feature->HW_AVX2 && (info[1] & (1 << 5)) != 0;
    128        } else {
    129            cpu_feature->HW_AVX2 = 0;
    130        }
    131    }
    132    else {
    133        cpu_feature->HW_SSE = 0;
    134        cpu_feature->HW_SSE2 = 0;
    135        cpu_feature->HW_SSE41 = 0;
    136        cpu_feature->HW_AVX2 = 0;
    137    }
    138 }
    139 
    140 static int opus_select_arch_impl(void)
    141 {
    142    CPU_Feature cpu_feature;
    143    int arch;
    144 
    145    opus_cpu_feature_check(&cpu_feature);
    146 
    147    arch = 0;
    148    if (!cpu_feature.HW_SSE)
    149    {
    150       return arch;
    151    }
    152    arch++;
    153 
    154    if (!cpu_feature.HW_SSE2)
    155    {
    156       return arch;
    157    }
    158    arch++;
    159 
    160    if (!cpu_feature.HW_SSE41)
    161    {
    162        return arch;
    163    }
    164    arch++;
    165 
    166    if (!cpu_feature.HW_AVX2)
    167    {
    168        return arch;
    169    }
    170    arch++;
    171 
    172    return arch;
    173 }
    174 
    175 int opus_select_arch(void) {
    176    int arch = opus_select_arch_impl();
    177 #ifdef FUZZING
    178    /* Randomly downgrade the architecture. */
    179    arch = rand()%(arch+1);
    180 #endif
    181    return arch;
    182 }
    183 
    184 #endif