1 /* 2 getcpucpuflags: get cpuflags for ia32 3 4 copyright ?-2007 by the mpg123 project - free software under the terms of the LGPL 2.1 5 see COPYING and AUTHORS files in distribution or http:#mpg123.org 6 initially written by KIMURA Takuhiro (for 3DNow!) 7 extended for general use by Thomas Orgis 8 */ 9 10 #ifndef MPG123_H_GETCPUFLAGS 11 #define MPG123_H_GETCPUFLAGS 12 13 #include "config.h" 14 15 /* standard level flags part 1 (ECX)*/ 16 #define FLAG_SSE3 0x00000001 17 #define FLAG_SSSE3 0x00000200 18 #define FLAG_AVX 0x1C000000 19 /* standard level flags part 2 (EDX) */ 20 #define FLAG2_MMX 0x00800000 21 #define FLAG2_SSE 0x02000000 22 #define FLAG2_SSE2 0x04000000 23 #define FLAG2_FPU 0x00000001 24 /* cpuid extended level 1 (AMD) */ 25 #define XFLAG_MMX 0x00800000 26 #define XFLAG_3DNOW 0x80000000 27 #define XFLAG_3DNOWEXT 0x40000000 28 /* eXtended Control Register 0 */ 29 #define XCR0FLAG_AVX 0x00000006 30 31 32 struct cpuflags 33 { 34 #if defined(OPT_ARM) || defined(OPT_NEON) || defined(OPT_NEON64) 35 unsigned int has_neon; 36 #else 37 unsigned int id; 38 unsigned int std; 39 unsigned int std2; 40 unsigned int ext; 41 unsigned int xcr0_lo; 42 #endif 43 }; 44 45 unsigned int getcpuflags(struct cpuflags* cf); 46 47 #ifdef WANT_GETCPUFLAGS 48 #include <string.h> 49 // Wrapper needed for ignorant clang memory sanitizer that chokes 50 // because it does not know the assembly code intialized the vlaues. wrap_getcpuflags(struct cpuflags * cf)51static unsigned int wrap_getcpuflags(struct cpuflags* cf) 52 { 53 memset(cf, 0, sizeof(*cf)); 54 return getcpuflags(cf); 55 } 56 #endif 57 58 #if ((defined OPT_X86) || (defined OPT_X86_64) || (defined OPT_NEON) || (defined OPT_NEON64)) && (defined OPT_MULTI) 59 60 // We really evaluate the CPU flags. 61 #define OPT_CPU_FLAGS 62 63 /* checks the family */ 64 #define cpu_i586(s) ( ((s.id & 0xf00)>>8) == 0 || ((s.id & 0xf00)>>8) > 4 ) 65 /* checking some flags... */ 66 #define cpu_fpu(s) (FLAG2_FPU & s.std2) 67 #define cpu_mmx(s) (FLAG2_MMX & s.std2 || XFLAG_MMX & s.ext) 68 #define cpu_3dnow(s) (XFLAG_3DNOW & s.ext) 69 #define cpu_3dnowext(s) (XFLAG_3DNOWEXT & s.ext) 70 #define cpu_sse(s) (FLAG2_SSE & s.std2) 71 #define cpu_sse2(s) (FLAG2_SSE2 & s.std2) 72 #define cpu_sse3(s) (FLAG_SSE3 & s.std) 73 #define cpu_avx(s) ((FLAG_AVX & s.std) == FLAG_AVX && (XCR0FLAG_AVX & s.xcr0_lo) == XCR0FLAG_AVX) 74 #define cpu_fast_sse(s) ((((s.id & 0xf00)>>8) == 6 && FLAG_SSSE3 & s.std) /* for Intel/VIA; family 6 CPUs with SSSE3 */ || \ 75 (((s.id & 0xf00)>>8) == 0xf && (((s.id & 0x0ff00000)>>20) > 0 && ((s.id & 0x0ff00000)>>20) != 5))) /* for AMD; family > 0xF CPUs except Bobcat */ 76 #define cpu_neon(s) (s.has_neon) 77 78 #else 79 80 /* Faking stuff for non-multi builds. The same code for synth function choice is used. 81 Just no runtime dependency of result... */ 82 #define cpu_flags nothing 83 #define cpu_i586(s) 1 84 #define cpu_fpu(s) 1 85 #define cpu_mmx(s) 1 86 #define cpu_3dnow(s) 1 87 #define cpu_3dnowext(s) 1 88 #define cpu_sse(s) 1 89 #define cpu_sse2(s) 1 90 #define cpu_sse3(s) 1 91 #define cpu_avx(s) 1 92 #define cpu_neon(s) 1 93 94 #endif 95 96 97 #endif 98