]> git.sesse.net Git - vlc/blob - src/posix/linux_cpu.c
Check for ARM NEON at build-time if possible
[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             if (!strcmp (cap, "neon"))
67                 core_caps |= VLC_CPU_ARM_NEON;
68
69 #elif defined (__i386__) || defined (__x86_64__)
70 # ifndef __MMX__
71             if (!strcmp (cap, "mmx"))
72                 core_caps |= CPU_CAPABILITY_MMX;
73 # endif
74 # ifndef __SSE__
75             if (!strcmp (cap, "sse"))
76                 core_caps |= CPU_CAPABILITY_SSE | CPU_CAPABILITY_MMXEXT;
77             if (!strcmp (cap, "mmxext"))
78                 core_caps |= CPU_CAPABILITY_MMXEXT;
79 # endif
80 # ifndef __SSE2__
81             if (!strcmp (cap, "sse2"))
82                 core_caps |= CPU_CAPABILITY_SSE2;
83 # endif
84 # ifndef __SSE3__
85             if (!strcmp (cap, "pni"))
86                 core_caps |= CPU_CAPABILITY_SSE3;
87 # endif
88 # ifndef __SSSE3__
89             if (!strcmp (cap, "ssse3"))
90                 core_caps |= CPU_CAPABILITY_SSSE3;
91 # endif
92 # ifndef __SSE4_1__
93             if (!strcmp (cap, "sse4_1"))
94                 core_caps |= CPU_CAPABILITY_SSE4_1;
95 # endif
96 # ifndef __SSE4_2__
97             if (!strcmp (cap, "sse4_2"))
98                 core_caps |= CPU_CAPABILITY_SSE4_1;
99 # endif
100             if (!strcmp (cap, "sse4a"))
101                 core_caps |= CPU_CAPABILITY_SSE4A;
102 # ifndef __3dNOW__
103             if (!strcmp (cap, "3dnow"))
104                 core_caps |= CPU_CAPABILITY_3DNOW;
105 # endif
106
107 #elif defined (__powerpc__) || defined (__powerpc64__)
108             if (!strcmp (cap, "altivec supported"))
109                 core_caps |= CPU_CAPABILITY_ALTIVEC;
110 #endif
111         }
112
113         /* Take the intersection of capabilities of each processor */
114         all_caps &= core_caps;
115     }
116     fclose (info);
117     free (line);
118
119     if (all_caps == 0xFFFFFFFF) /* Error parsing of cpuinfo? */
120         all_caps = 0; /* Do not assume any capability! */
121
122     /* Always enable capabilities that were forced during compilation */
123 #if defined (__i386__) || defined (__x86_64__)
124 # ifdef __MMX__
125     all_caps |= CPU_CAPABILITY_MMX;
126 # endif
127 # ifdef __SSE__
128     all_caps |= CPU_CAPABILITY_SSE | CPU_CAPABILITY_MMXEXT;
129 # endif
130 # ifdef __SSE2__
131     all_caps |= CPU_CAPABILITY_SSE2;
132 # endif
133 # ifdef __SSE3__
134     all_caps |= CPU_CAPABILITY_SSE3;
135 # endif
136 # ifdef __SSSE3__
137     all_caps |= CPU_CAPABILITY_SSSE3;
138 # endif
139 # ifdef __SSE4_1__
140     all_caps |= CPU_CAPABILITY_SSE4_1;
141 # endif
142 # ifdef __SSE4_2__
143     all_caps |= CPU_CAPABILITY_SSE4_2;
144 # endif
145 # ifdef __3dNOW__
146     all_caps |= CPU_CAPABILITY_3DNOW;
147 # endif
148
149 #endif
150     cpu_flags = all_caps;
151 }
152
153 unsigned vlc_CPU (void)
154 {
155     static pthread_once_t once = PTHREAD_ONCE_INIT;
156
157     pthread_once (&once, vlc_CPU_init);
158     return cpu_flags;
159 }
160 #else /* CPU_FLAGS */
161 unsigned vlc_CPU (void)
162 {
163     return 0;
164 }
165 #endif