]> git.sesse.net Git - vlc/blob - src/posix/linux_cpu.c
Linux: add detection for SSE4A
[vlc] / src / posix / linux_cpu.c
1 /*****************************************************************************
2  * linux_cpu.c: CPU detection code for Linux
3  *****************************************************************************
4  * Copyright (C) 2012 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <vlc_common.h>
28 #include <vlc_cpu.h>
29
30 #undef CPU_FLAGS
31 #if defined (__arm__)
32 # define CPU_FLAGS "Features\t:"
33
34 #elif defined (__i386__) || defined (__x86_64__)
35 # define CPU_FLAGS "flags\t\t:"
36
37 #elif defined (__powerpc__) || defined (__powerpc64__)
38 # define CPU_FLAGS "cpu\t\t:"
39
40 #endif
41
42 #ifdef CPU_FLAGS
43 static uint32_t cpu_flags = 0;
44
45 static void vlc_CPU_init (void)
46 {
47     FILE *info = fopen ("/proc/cpuinfo", "rt");
48     if (info == NULL)
49         return;
50
51     char *line = NULL;
52     size_t linelen = 0;
53     uint_fast32_t all_caps = 0xFFFFFFFF;
54
55     while (getline (&line, &linelen, info) != -1)
56     {
57         if (strncmp (line, CPU_FLAGS, strlen (CPU_FLAGS)))
58             continue;
59
60         char *p = line, *cap;
61         uint_fast32_t core_caps = 0;
62
63         while ((cap = strsep (&p, " ")) != NULL)
64         {
65 #if defined (__arm__)
66 # ifndef __ARM_NEON__
67             if (!strcmp (cap, "neon"))
68                 core_caps |= CPU_CAPABILITY_NEON;
69 # endif
70
71 #elif defined (__i386__) || defined (__x86_64__)
72 # ifndef __MMX__
73             if (!strcmp (cap, "mmx"))
74                 core_caps |= CPU_CAPABILITY_MMX;
75 # endif
76 # ifndef __SSE__
77             if (!strcmp (cap, "sse"))
78                 core_caps |= CPU_CAPABILITY_SSE | CPU_CAPABILITY_MMXEXT;
79             if (!strcmp (cap, "mmxext"))
80                 core_caps |= CPU_CAPABILITY_MMXEXT;
81 # endif
82 # ifndef __SSE2__
83             if (!strcmp (cap, "sse2"))
84                 core_caps |= CPU_CAPABILITY_SSE2;
85 # endif
86 # ifndef __SSE3__
87             if (!strcmp (cap, "pni"))
88                 core_caps |= CPU_CAPABILITY_SSE3;
89 # endif
90 # ifndef __SSSE3__
91             if (!strcmp (cap, "ssse3"))
92                 core_caps |= CPU_CAPABILITY_SSSE3;
93 # endif
94 # ifndef __SSE4_1__
95             if (!strcmp (cap, "sse4_1"))
96                 core_caps |= CPU_CAPABILITY_SSE4_1;
97 # endif
98 # ifndef __SSE4_2__
99             if (!strcmp (cap, "sse4_2"))
100                 core_caps |= CPU_CAPABILITY_SSE4_1;
101 # endif
102             if (!strcmp (cap, "sse4a"))
103                 core_caps |= CPU_CAPABILITY_SSE4A;
104 # ifndef __3dNOW__
105             if (!strcmp (cap, "3dnow"))
106                 core_caps |= CPU_CAPABILITY_3DNOW;
107 # endif
108
109 #elif defined (__powerpc__) || defined (__powerpc64__)
110             if (!strcmp (cap, "altivec supported"))
111                 core_caps |= CPU_CAPABILITY_ALTIVEC;
112 #endif
113         }
114
115         /* Take the intersection of capabilities of each processor */
116         all_caps &= core_caps;
117     }
118     fclose (info);
119     free (line);
120
121     if (all_caps == 0xFFFFFFFF) /* Error parsing of cpuinfo? */
122         all_caps = 0; /* Do not assume any capability! */
123
124     /* Always enable capabilities that were forced during compilation */
125 #if defined (__arm__)
126 # ifdef __ARM_NEON__
127     all_caps |= CPU_CAPABILITY_NEON;
128 # endif
129
130 #elif defined (__i386__) || defined (__x86_64__)
131 # ifdef __MMX__
132     all_caps |= CPU_CAPABILITY_MMX;
133 # endif
134 # ifdef __SSE__
135     all_caps |= CPU_CAPABILITY_SSE | CPU_CAPABILITY_MMXEXT;
136 # endif
137 # ifdef __SSE2__
138     all_caps |= CPU_CAPABILITY_SSE2;
139 # endif
140 # ifdef __SSE3__
141     all_caps |= CPU_CAPABILITY_SSE3;
142 # endif
143 # ifdef __SSSE3__
144     all_caps |= CPU_CAPABILITY_SSSE3;
145 # endif
146 # ifdef __SSE4_1__
147     all_caps |= CPU_CAPABILITY_SSE4_1;
148 # endif
149 # ifdef __SSE4_2__
150     all_caps |= CPU_CAPABILITY_SSE4_2;
151 # endif
152 # ifdef __3dNOW__
153     all_caps |= CPU_CAPABILITY_3DNOW;
154 # endif
155
156 #endif
157     cpu_flags = all_caps;
158 }
159
160 unsigned vlc_CPU (void)
161 {
162     static pthread_once_t once = PTHREAD_ONCE_INIT;
163
164     pthread_once (&once, vlc_CPU_init);
165     return cpu_flags;
166 }
167 #else /* CPU_FLAGS */
168 unsigned vlc_CPU (void)
169 {
170     return 0;
171 }
172 #endif