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)51 static 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