The "GR-PEACH_Audio_Playback_7InchLCD_Sample" is a sample code that can provides high-resolution audio playback of FLAC format files. It also allows the user to audio-playback control functions such as play, pause, and stop by manipulating key switches.

Dependencies:   GR-PEACH_video R_BSP TLV320_RBSP USBHost_custom

Fork of GR-PEACH_Audio_Playback_Sample by Renesas

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cpu.c Source File

cpu.c

00001 /* libFLAC - Free Lossless Audio Codec library
00002  * Copyright (C) 2001-2009  Josh Coalson
00003  * Copyright (C) 2011-2014  Xiph.Org Foundation
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  * notice, this list of conditions and the following disclaimer.
00011  *
00012  * - Redistributions in binary form must reproduce the above copyright
00013  * notice, this list of conditions and the following disclaimer in the
00014  * documentation and/or other materials provided with the distribution.
00015  *
00016  * - Neither the name of the Xiph.org Foundation nor the names of its
00017  * contributors may be used to endorse or promote products derived from
00018  * this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00023  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
00024  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #ifdef HAVE_CONFIG_H
00034 #  include <config.h>
00035 #endif
00036 
00037 #include "private/cpu.h"
00038 #include <stdlib.h>
00039 #include <memory.h>
00040 #ifdef DEBUG
00041 # include <stdio.h>
00042 #endif
00043 
00044 #if defined FLAC__CPU_IA32
00045 # include <signal.h>
00046 
00047 static void disable_sse(FLAC__CPUInfo *info)
00048 {
00049     info->ia32.sse   = false;
00050     info->ia32.sse2  = false;
00051     info->ia32.sse3  = false;
00052     info->ia32.ssse3 = false;
00053     info->ia32.sse41 = false;
00054     info->ia32.sse42 = false;
00055 }
00056 
00057 static void disable_avx(FLAC__CPUInfo *info)
00058 {
00059     info->ia32.avx     = false;
00060     info->ia32.avx2    = false;
00061     info->ia32.fma     = false;
00062 }
00063 
00064 #elif defined FLAC__CPU_X86_64
00065 
00066 static void disable_avx(FLAC__CPUInfo *info)
00067 {
00068     info->x86.avx     = false;
00069     info->x86.avx2    = false;
00070     info->x86.fma     = false;
00071 }
00072 #endif
00073 
00074 #if defined (__NetBSD__) || defined(__OpenBSD__)
00075 #include <sys/param.h>
00076 #include <sys/sysctl.h>
00077 #include <machine/cpu.h>
00078 #endif
00079 
00080 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
00081 #include <sys/types.h>
00082 #include <sys/sysctl.h>
00083 #endif
00084 
00085 #if defined(__APPLE__)
00086 /* how to get sysctlbyname()? */
00087 #endif
00088 
00089 #ifdef FLAC__CPU_IA32
00090 /* these are flags in EDX of CPUID AX=00000001 */
00091 static const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000;
00092 static const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000;
00093 static const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000;
00094 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000;
00095 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000;
00096 #endif
00097 
00098 /* these are flags in ECX of CPUID AX=00000001 */
00099 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE3 = 0x00000001;
00100 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSSE3 = 0x00000200;
00101 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE41 = 0x00080000;
00102 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE42 = 0x00100000;
00103 
00104 #if defined FLAC__AVX_SUPPORTED
00105 /* these are flags in ECX of CPUID AX=00000001 */
00106 static const unsigned FLAC__CPUINFO_IA32_CPUID_OSXSAVE = 0x08000000;
00107 static const unsigned FLAC__CPUINFO_IA32_CPUID_AVX = 0x10000000;
00108 static const unsigned FLAC__CPUINFO_IA32_CPUID_FMA = 0x00001000;
00109 /* these are flags in EBX of CPUID AX=00000007 */
00110 static const unsigned FLAC__CPUINFO_IA32_CPUID_AVX2 = 0x00000020;
00111 #endif
00112 
00113 /*
00114  * Extra stuff needed for detection of OS support for SSE on IA-32
00115  */
00116 #if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && (defined FLAC__HAS_NASM || defined FLAC__HAS_X86INTRIN) && !defined FLAC__NO_SSE_OS && !defined FLAC__SSE_OS
00117 # if defined(__linux__)
00118 /*
00119  * If the OS doesn't support SSE, we will get here with a SIGILL.  We
00120  * modify the return address to jump over the offending SSE instruction
00121  * and also the operation following it that indicates the instruction
00122  * executed successfully.  In this way we use no global variables and
00123  * stay thread-safe.
00124  *
00125  * 3 + 3 + 6:
00126  *   3 bytes for "xorps xmm0,xmm0"
00127  *   3 bytes for estimate of how long the follwing "inc var" instruction is
00128  *   6 bytes extra in case our estimate is wrong
00129  * 12 bytes puts us in the NOP "landing zone"
00130  */
00131 #   include <sys/ucontext.h>
00132     static void sigill_handler_sse_os(int signal, siginfo_t *si, void *uc)
00133     {
00134         (void)signal, (void)si;
00135         ((ucontext_t*)uc)->uc_mcontext.gregs[14/*REG_EIP*/] += 3 + 3 + 6;
00136     }
00137 # elif defined(_MSC_VER)
00138 #  include <windows.h>
00139 # endif
00140 #endif
00141 
00142 
00143 void FLAC__cpu_info(FLAC__CPUInfo *info)
00144 {
00145 /*
00146  * IA32-specific
00147  */
00148 #ifdef FLAC__CPU_IA32
00149     FLAC__bool ia32_fxsr = false;
00150     FLAC__bool ia32_osxsave = false;
00151     (void) ia32_fxsr; (void) ia32_osxsave; /* to avoid warnings about unused variables */
00152     memset(info, 0, sizeof(*info));
00153     info->type = FLAC__CPUINFO_TYPE_IA32;
00154 #if !defined FLAC__NO_ASM && (defined FLAC__HAS_NASM || defined FLAC__HAS_X86INTRIN)
00155     info->use_asm = true; /* we assume a minimum of 80386 with FLAC__CPU_IA32 */
00156 #ifdef FLAC__HAS_X86INTRIN
00157     if(!FLAC__cpu_have_cpuid_x86())
00158         return;
00159 #else
00160     if(!FLAC__cpu_have_cpuid_asm_ia32())
00161         return;
00162 #endif
00163     {
00164         /* http://www.sandpile.org/x86/cpuid.htm */
00165 #ifdef FLAC__HAS_X86INTRIN
00166         FLAC__uint32 flags_eax, flags_ebx, flags_ecx, flags_edx;
00167         FLAC__cpu_info_x86(1, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
00168 #else
00169         FLAC__uint32 flags_ecx, flags_edx;
00170         FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx);
00171 #endif
00172         info->ia32.cmov  = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false;
00173         info->ia32.mmx   = (flags_edx & FLAC__CPUINFO_IA32_CPUID_MMX  )? true : false;
00174               ia32_fxsr  = (flags_edx & FLAC__CPUINFO_IA32_CPUID_FXSR )? true : false;
00175         info->ia32.sse   = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE  )? true : false;
00176         info->ia32.sse2  = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE2 )? true : false;
00177         info->ia32.sse3  = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false;
00178         info->ia32.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false;
00179         info->ia32.sse41 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE41)? true : false;
00180         info->ia32.sse42 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE42)? true : false;
00181 #if defined FLAC__HAS_X86INTRIN && defined FLAC__AVX_SUPPORTED
00182             ia32_osxsave = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_OSXSAVE)? true : false;
00183         info->ia32.avx   = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_AVX    )? true : false;
00184         info->ia32.fma   = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_FMA    )? true : false;
00185         FLAC__cpu_info_x86(7, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
00186         info->ia32.avx2  = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2   )? true : false;
00187 #endif
00188     }
00189 
00190 #ifdef DEBUG
00191     fprintf(stderr, "CPU info (IA-32):\n");
00192     fprintf(stderr, "  CMOV ....... %c\n", info->ia32.cmov    ? 'Y' : 'n');
00193     fprintf(stderr, "  MMX ........ %c\n", info->ia32.mmx     ? 'Y' : 'n');
00194     fprintf(stderr, "  SSE ........ %c\n", info->ia32.sse     ? 'Y' : 'n');
00195     fprintf(stderr, "  SSE2 ....... %c\n", info->ia32.sse2    ? 'Y' : 'n');
00196     fprintf(stderr, "  SSE3 ....... %c\n", info->ia32.sse3    ? 'Y' : 'n');
00197     fprintf(stderr, "  SSSE3 ...... %c\n", info->ia32.ssse3   ? 'Y' : 'n');
00198     fprintf(stderr, "  SSE41 ...... %c\n", info->ia32.sse41   ? 'Y' : 'n');
00199     fprintf(stderr, "  SSE42 ...... %c\n", info->ia32.sse42   ? 'Y' : 'n');
00200 # if defined FLAC__HAS_X86INTRIN && defined FLAC__AVX_SUPPORTED
00201     fprintf(stderr, "  AVX ........ %c\n", info->ia32.avx     ? 'Y' : 'n');
00202     fprintf(stderr, "  FMA ........ %c\n", info->ia32.fma     ? 'Y' : 'n');
00203     fprintf(stderr, "  AVX2 ....... %c\n", info->ia32.avx2    ? 'Y' : 'n');
00204 # endif
00205 #endif
00206 
00207     /*
00208      * now have to check for OS support of SSE instructions
00209      */
00210     if(info->ia32.sse) {
00211 #if defined FLAC__NO_SSE_OS
00212         /* assume user knows better than us; turn it off */
00213         disable_sse(info);
00214 #elif defined FLAC__SSE_OS
00215         /* assume user knows better than us; leave as detected above */
00216 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__APPLE__)
00217         int sse = 0;
00218         size_t len;
00219         /* at least one of these must work: */
00220         len = sizeof(sse); sse = sse || (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) == 0 && sse);
00221         len = sizeof(sse); sse = sse || (sysctlbyname("hw.optional.sse"   , &sse, &len, NULL, 0) == 0 && sse); /* __APPLE__ ? */
00222         if(!sse)
00223             disable_sse(info);
00224 #elif defined(__NetBSD__) || defined (__OpenBSD__)
00225 # if __NetBSD_Version__ >= 105250000 || (defined __OpenBSD__)
00226         int val = 0, mib[2] = { CTL_MACHDEP, CPU_SSE };
00227         size_t len = sizeof(val);
00228         if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val)
00229             disable_sse(info);
00230         else { /* double-check SSE2 */
00231             mib[1] = CPU_SSE2;
00232             len = sizeof(val);
00233             if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) {
00234                 disable_sse(info);
00235                 info->ia32.sse = true;
00236             }
00237         }
00238 # else
00239         disable_sse(info);
00240 # endif
00241 #elif defined(__linux__)
00242         int sse = 0;
00243         struct sigaction sigill_save;
00244         struct sigaction sigill_sse;
00245         sigill_sse.sa_sigaction = sigill_handler_sse_os;
00246         __sigemptyset(&sigill_sse.sa_mask);
00247         sigill_sse.sa_flags = SA_SIGINFO | SA_RESETHAND; /* SA_RESETHAND just in case our SIGILL return jump breaks, so we don't get stuck in a loop */
00248         if(0 == sigaction(SIGILL, &sigill_sse, &sigill_save))
00249         {
00250             /* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */
00251             /* see sigill_handler_sse_os() for an explanation of the following: */
00252             asm volatile (
00253                 "xorps %%xmm0,%%xmm0\n\t" /* will cause SIGILL if unsupported by OS */
00254                 "incl %0\n\t"             /* SIGILL handler will jump over this */
00255                 /* landing zone */
00256                 "nop\n\t" /* SIGILL jump lands here if "inc" is 9 bytes */
00257                 "nop\n\t"
00258                 "nop\n\t"
00259                 "nop\n\t"
00260                 "nop\n\t"
00261                 "nop\n\t"
00262                 "nop\n\t" /* SIGILL jump lands here if "inc" is 3 bytes (expected) */
00263                 "nop\n\t"
00264                 "nop"     /* SIGILL jump lands here if "inc" is 1 byte */
00265                 : "=r"(sse)
00266                 : "0"(sse)
00267             );
00268 
00269             sigaction(SIGILL, &sigill_save, NULL);
00270         }
00271 
00272         if(!sse)
00273             disable_sse(info);
00274 #elif defined(_MSC_VER)
00275         __try {
00276             __asm {
00277                 xorps xmm0,xmm0
00278             }
00279         }
00280         __except(EXCEPTION_EXECUTE_HANDLER) {
00281             if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
00282                 disable_sse(info);
00283         }
00284 #elif defined(__GNUC__) /* MinGW goes here */
00285         int sse = 0;
00286         /* Based on the idea described in Agner Fog's manual "Optimizing subroutines in assembly language" */
00287         /* In theory, not guaranteed to detect lack of OS SSE support on some future Intel CPUs, but in practice works (see the aforementioned manual) */
00288         if (ia32_fxsr) {
00289             struct {
00290                 FLAC__uint32 buff[128];
00291             } __attribute__((aligned(16))) fxsr;
00292             FLAC__uint32 old_val, new_val;
00293 
00294             asm volatile ("fxsave %0"  : "=m" (fxsr) : "m" (fxsr));
00295             old_val = fxsr.buff[50];
00296             fxsr.buff[50] ^= 0x0013c0de;                             /* change value in the buffer */
00297             asm volatile ("fxrstor %0" : "=m" (fxsr) : "m" (fxsr));  /* try to change SSE register */
00298             fxsr.buff[50] = old_val;                                 /* restore old value in the buffer */
00299             asm volatile ("fxsave %0 " : "=m" (fxsr) : "m" (fxsr));  /* old value will be overwritten if SSE register was changed */
00300             new_val = fxsr.buff[50];                                 /* == old_val if FXRSTOR didn't change SSE register and (old_val ^ 0x0013c0de) otherwise */
00301             fxsr.buff[50] = old_val;                                 /* again restore old value in the buffer */
00302             asm volatile ("fxrstor %0" : "=m" (fxsr) : "m" (fxsr));  /* restore old values of registers */
00303 
00304             if ((old_val^new_val) == 0x0013c0de)
00305                 sse = 1;
00306         }
00307         if(!sse)
00308             disable_sse(info);
00309 #else
00310         /* no way to test, disable to be safe */
00311         disable_sse(info);
00312 #endif
00313 #ifdef DEBUG
00314         fprintf(stderr, "  SSE OS sup . %c\n", info->ia32.sse ? 'Y' : 'n');
00315 #endif
00316     }
00317     else /* info->ia32.sse == false */
00318         disable_sse(info);
00319 
00320     /*
00321      * now have to check for OS support of AVX instructions
00322      */
00323     if(info->ia32.avx && ia32_osxsave) {
00324         FLAC__uint32 ecr = FLAC__cpu_xgetbv_x86();
00325         if ((ecr & 0x6) != 0x6)
00326             disable_avx(info);
00327 #ifdef DEBUG
00328         fprintf(stderr, "  AVX OS sup . %c\n", info->ia32.avx ? 'Y' : 'n');
00329 #endif
00330     }
00331     else /* no OS AVX support*/
00332         disable_avx(info);
00333 #else
00334     info->use_asm = false;
00335 #endif
00336 
00337 /*
00338  * x86-64-specific
00339  */
00340 #elif defined FLAC__CPU_X86_64
00341     FLAC__bool x86_osxsave = false;
00342     (void) x86_osxsave; /* to avoid warnings about unused variables */
00343     memset(info, 0, sizeof(*info));
00344     info->type = FLAC__CPUINFO_TYPE_X86_64;
00345 #if !defined FLAC__NO_ASM && defined FLAC__HAS_X86INTRIN
00346     info->use_asm = true;
00347     {
00348         /* http://www.sandpile.org/x86/cpuid.htm */
00349         FLAC__uint32 flags_eax, flags_ebx, flags_ecx, flags_edx;
00350         FLAC__cpu_info_x86(1, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
00351         info->x86.sse3  = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false;
00352         info->x86.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false;
00353         info->x86.sse41 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE41)? true : false;
00354         info->x86.sse42 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE42)? true : false;
00355 #if defined FLAC__AVX_SUPPORTED
00356             x86_osxsave = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_OSXSAVE)? true : false;
00357         info->x86.avx   = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_AVX    )? true : false;
00358         info->x86.fma   = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_FMA    )? true : false;
00359         FLAC__cpu_info_x86(7, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
00360         info->x86.avx2  = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2   )? true : false;
00361 #endif
00362     }
00363 #ifdef DEBUG
00364     fprintf(stderr, "CPU info (x86-64):\n");
00365     fprintf(stderr, "  SSE3 ....... %c\n", info->x86.sse3  ? 'Y' : 'n');
00366     fprintf(stderr, "  SSSE3 ...... %c\n", info->x86.ssse3 ? 'Y' : 'n');
00367     fprintf(stderr, "  SSE41 ...... %c\n", info->x86.sse41 ? 'Y' : 'n');
00368     fprintf(stderr, "  SSE42 ...... %c\n", info->x86.sse42 ? 'Y' : 'n');
00369 # if defined FLAC__AVX_SUPPORTED
00370     fprintf(stderr, "  AVX ........ %c\n", info->x86.avx   ? 'Y' : 'n');
00371     fprintf(stderr, "  FMA ........ %c\n", info->x86.fma   ? 'Y' : 'n');
00372     fprintf(stderr, "  AVX2 ....... %c\n", info->x86.avx2  ? 'Y' : 'n');
00373 # endif
00374 #endif
00375 
00376     /*
00377      * now have to check for OS support of AVX instructions
00378      */
00379     if(info->x86.avx && x86_osxsave) {
00380         FLAC__uint32 ecr = FLAC__cpu_xgetbv_x86();
00381         if ((ecr & 0x6) != 0x6)
00382             disable_avx(info);
00383 #ifdef DEBUG
00384         fprintf(stderr, "  AVX OS sup . %c\n", info->x86.avx ? 'Y' : 'n');
00385 #endif
00386     }
00387     else /* no OS AVX support*/
00388         disable_avx(info);
00389 #else
00390     info->use_asm = false;
00391 #endif
00392 
00393 /*
00394  * unknown CPU
00395  */
00396 #else
00397     info->type = FLAC__CPUINFO_TYPE_UNKNOWN;
00398     info->use_asm = false;
00399 #endif
00400 }
00401 
00402 #if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
00403 
00404 #if defined _MSC_VER
00405 #include <intrin.h> /* for __cpuid() and _xgetbv() */
00406 #elif defined __GNUC__ && defined HAVE_CPUID_H
00407 #include <cpuid.h> /* for __get_cpuid() and __get_cpuid_max() */
00408 #endif
00409 
00410 FLAC__uint32 FLAC__cpu_have_cpuid_x86(void)
00411 {
00412 #ifdef FLAC__CPU_X86_64
00413     return 1;
00414 #else
00415 # if defined _MSC_VER || defined __INTEL_COMPILER /* Do they support CPUs w/o CPUID support (or OSes that work on those CPUs)? */
00416     FLAC__uint32 flags1, flags2;
00417     __asm {
00418         pushfd
00419         pushfd
00420         pop     eax
00421         mov     flags1, eax
00422         xor     eax, 0x200000
00423         push    eax
00424         popfd
00425         pushfd
00426         pop     eax
00427         mov     flags2, eax
00428         popfd
00429     }
00430     if (((flags1^flags2) & 0x200000) != 0)
00431         return 1;
00432     else
00433         return 0;
00434 # elif defined __GNUC__ && defined HAVE_CPUID_H
00435     if (__get_cpuid_max(0, 0) != 0)
00436         return 1;
00437     else
00438         return 0;
00439 # else
00440     return 0;
00441 # endif
00442 #endif
00443 }
00444 
00445 void FLAC__cpu_info_x86(FLAC__uint32 level, FLAC__uint32 *eax, FLAC__uint32 *ebx, FLAC__uint32 *ecx, FLAC__uint32 *edx)
00446 {
00447 #if defined _MSC_VER || defined __INTEL_COMPILER
00448     int cpuinfo[4];
00449     int ext = level & 0x80000000;
00450     __cpuid(cpuinfo, ext);
00451     if((unsigned)cpuinfo[0] < level) {
00452         *eax = *ebx = *ecx = *edx = 0;
00453         return;
00454     }
00455 #if defined FLAC__AVX_SUPPORTED
00456     __cpuidex(cpuinfo, level, 0); /* for AVX2 detection */
00457 #else
00458     __cpuid(cpuinfo, level); /* some old compilers don't support __cpuidex */
00459 #endif
00460     *eax = cpuinfo[0]; *ebx = cpuinfo[1]; *ecx = cpuinfo[2]; *edx = cpuinfo[3];
00461 #elif defined __GNUC__ && defined HAVE_CPUID_H
00462     FLAC__uint32 ext = level & 0x80000000;
00463     __cpuid(ext, *eax, *ebx, *ecx, *edx);
00464     if (*eax < level) {
00465         *eax = *ebx = *ecx = *edx = 0;
00466         return;
00467     }
00468     __cpuid_count(level, 0, *eax, *ebx, *ecx, *edx);
00469 #else
00470     *eax = *ebx = *ecx = *edx = 0;
00471 #endif
00472 }
00473 
00474 FLAC__uint32 FLAC__cpu_xgetbv_x86(void)
00475 {
00476 #if (defined _MSC_VER || defined __INTEL_COMPILER) && defined FLAC__AVX_SUPPORTED
00477     return (FLAC__uint32)_xgetbv(0);
00478 #elif defined __GNUC__
00479     FLAC__uint32 lo, hi;
00480     asm volatile (".byte 0x0f, 0x01, 0xd0" : "=a"(lo), "=d"(hi) : "c" (0));
00481     return lo;
00482 #else
00483     return 0;
00484 #endif
00485 }
00486 
00487 #endif /* (FLAC__CPU_IA32 || FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN */