FFmpeg
cpu.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "config.h"
20 
21 #ifdef __APPLE__
22 #include <sys/sysctl.h>
23 #elif HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
24 #ifdef __FreeBSD__
25 #include <machine/cpu.h>
26 #endif
27 #include <sys/auxv.h>
28 #elif defined(__linux__)
29 #include <asm/cputable.h>
30 #include <linux/auxvec.h>
31 #include <fcntl.h>
32 #if HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #elif defined(__NetBSD__) || defined(__OpenBSD__)
36 #include <sys/types.h>
37 #include <sys/sysctl.h>
38 #include <machine/cpu.h>
39 #elif defined(__AMIGAOS4__)
40 #include <exec/exec.h>
41 #include <interfaces/exec.h>
42 #include <proto/exec.h>
43 #endif /* __APPLE__ */
44 
45 #include "libavutil/avassert.h"
46 #include "libavutil/cpu.h"
47 #include "libavutil/cpu_internal.h"
48 
49 /**
50  * This function MAY rely on signal() or fork() in order to make sure AltiVec
51  * is present.
52  */
54 {
55 #if HAVE_ALTIVEC
56 #ifdef __AMIGAOS4__
57  ULONG result = 0;
58  extern struct ExecIFace *IExec;
59 
60  IExec->GetCPUInfoTags(GCIT_VectorUnit, &result, TAG_DONE);
61  if (result == VECTORTYPE_ALTIVEC)
62  return AV_CPU_FLAG_ALTIVEC;
63  return 0;
64 #elif HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
65  int flags = 0;
66 
67  unsigned long hwcap = ff_getauxval(AT_HWCAP);
68 #ifdef PPC_FEATURE2_ARCH_2_07
69  unsigned long hwcap2 = ff_getauxval(AT_HWCAP2);
70 #endif
71 
72  if (hwcap & PPC_FEATURE_HAS_ALTIVEC)
74 #ifdef PPC_FEATURE_HAS_VSX
75  if (hwcap & PPC_FEATURE_HAS_VSX)
77 #endif
78 #ifdef PPC_FEATURE2_ARCH_2_07
79  if (hwcap2 & PPC_FEATURE2_ARCH_2_07)
81 #endif
82 
83  return flags;
84 #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__)
85 #if defined(__NetBSD__) || defined(__OpenBSD__)
86  int sels[2] = {CTL_MACHDEP, CPU_ALTIVEC};
87 #else
88  int sels[2] = {CTL_HW, HW_VECTORUNIT};
89 #endif
90  int has_vu = 0;
91  size_t len = sizeof(has_vu);
92  int err;
93 
94  err = sysctl(sels, 2, &has_vu, &len, NULL, 0);
95 
96  if (err == 0)
97  return has_vu ? AV_CPU_FLAG_ALTIVEC : 0;
98  return 0;
99 #elif defined(__linux__)
100  // The linux kernel could have the altivec support disabled
101  // even if the cpu has it.
102  int i, ret = 0;
103  int fd = open("/proc/self/auxv", O_RDONLY);
104  unsigned long buf[64] = { 0 };
105  ssize_t count;
106 
107  if (fd < 0)
108  return 0;
109 
110  while ((count = read(fd, buf, sizeof(buf))) > 0) {
111  for (i = 0; i < count / sizeof(*buf); i += 2) {
112  if (buf[i] == AT_NULL)
113  goto out;
114  if (buf[i] == AT_HWCAP) {
115  if (buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC)
117 #ifdef PPC_FEATURE_HAS_VSX
118  if (buf[i + 1] & PPC_FEATURE_HAS_VSX)
119  ret |= AV_CPU_FLAG_VSX;
120 #endif
121  if (ret & AV_CPU_FLAG_VSX)
123  }
124 #ifdef AT_HWCAP2 /* not introduced until glibc 2.18 */
125  else if (buf[i] == AT_HWCAP2) {
126 #ifdef PPC_FEATURE2_ARCH_2_07
127  if (buf[i + 1] & PPC_FEATURE2_ARCH_2_07)
129 #endif
130  }
131 #endif /* AT_HWCAP2 */
132  }
133  }
134 
135 out:
136  close(fd);
137  return ret;
138 #elif CONFIG_RUNTIME_CPUDETECT && defined(__linux__)
139 #define PVR_G4_7400 0x000C
140 #define PVR_G5_970 0x0039
141 #define PVR_G5_970FX 0x003C
142 #define PVR_G5_970MP 0x0044
143 #define PVR_G5_970GX 0x0045
144 #define PVR_POWER6 0x003E
145 #define PVR_POWER7 0x003F
146 #define PVR_POWER8 0x004B
147 #define PVR_CELL_PPU 0x0070
148  int ret = 0;
149  int proc_ver;
150  // Support of mfspr PVR emulation added in Linux 2.6.17.
151  __asm__ volatile("mfspr %0, 287" : "=r" (proc_ver));
152  proc_ver >>= 16;
153  if (proc_ver & 0x8000 ||
154  proc_ver == PVR_G4_7400 ||
155  proc_ver == PVR_G5_970 ||
156  proc_ver == PVR_G5_970FX ||
157  proc_ver == PVR_G5_970MP ||
158  proc_ver == PVR_G5_970GX ||
159  proc_ver == PVR_POWER6 ||
160  proc_ver == PVR_POWER7 ||
161  proc_ver == PVR_POWER8 ||
162  proc_ver == PVR_CELL_PPU)
164  if (proc_ver == PVR_POWER7 ||
165  proc_ver == PVR_POWER8)
166  ret |= AV_CPU_FLAG_VSX;
167  if (proc_ver == PVR_POWER8)
169 
170  return ret;
171 #else
172  // Since we were compiled for AltiVec, just assume we have it
173  // until someone comes up with a proper way (not involving signal hacks).
174  return AV_CPU_FLAG_ALTIVEC;
175 #endif /* __AMIGAOS4__ */
176 #endif /* HAVE_ALTIVEC */
177  return 0;
178 }
179 
181 {
182  int flags = av_get_cpu_flags();
183 
184  if (flags & (AV_CPU_FLAG_ALTIVEC |
187  return 16;
188 
189  return 8;
190 }
out
FILE * out
Definition: movenc.c:55
av_get_cpu_flags
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition: cpu.c:107
AV_CPU_FLAG_VSX
#define AV_CPU_FLAG_VSX
ISA 2.06.
Definition: cpu.h:62
avassert.h
cpu_internal.h
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
ff_getauxval
unsigned long ff_getauxval(unsigned long type)
Definition: cpu.c:295
result
and forward the result(frame or status change) to the corresponding input. If nothing is possible
NULL
#define NULL
Definition: coverity.c:32
AV_CPU_FLAG_ALTIVEC
#define AV_CPU_FLAG_ALTIVEC
standard
Definition: cpu.h:61
cpu.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ff_get_cpu_flags_ppc
int ff_get_cpu_flags_ppc(void)
This function MAY rely on signal() or fork() in order to make sure AltiVec is present.
Definition: cpu.c:53
len
int len
Definition: vorbis_enc_data.h:426
ret
ret
Definition: filter_design.txt:187
__asm__
__asm__(".macro parse_r var r\n\t" "\\var = -1\n\t" _IFC_REG(0) _IFC_REG(1) _IFC_REG(2) _IFC_REG(3) _IFC_REG(4) _IFC_REG(5) _IFC_REG(6) _IFC_REG(7) _IFC_REG(8) _IFC_REG(9) _IFC_REG(10) _IFC_REG(11) _IFC_REG(12) _IFC_REG(13) _IFC_REG(14) _IFC_REG(15) _IFC_REG(16) _IFC_REG(17) _IFC_REG(18) _IFC_REG(19) _IFC_REG(20) _IFC_REG(21) _IFC_REG(22) _IFC_REG(23) _IFC_REG(24) _IFC_REG(25) _IFC_REG(26) _IFC_REG(27) _IFC_REG(28) _IFC_REG(29) _IFC_REG(30) _IFC_REG(31) ".iflt \\var\n\t" ".error \"Unable to parse register name \\r\"\n\t" ".endif\n\t" ".endm")
AV_CPU_FLAG_POWER8
#define AV_CPU_FLAG_POWER8
ISA 2.07.
Definition: cpu.h:63
ff_get_cpu_max_align_ppc
size_t ff_get_cpu_max_align_ppc(void)
Definition: cpu.c:180
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
read
static uint32_t BS_FUNC() read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
Definition: bitstream_template.h:231