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 #ifndef AT_HWCAP
50 #define AT_HWCAP 16
51 #endif
52 #ifndef AT_HWCAP2
53 #define AT_HWCAP2 26
54 #endif
55 
56 #define HWCAP_PPC_VSX (1U << 7)
57 #define HWCAP_PPC_ALTIVEC (1U << 28)
58 #define HWCAP2_PPC_ARCH_2_07 (1U << 31)
59 
60 /**
61  * This function MAY rely on signal() or fork() in order to make sure AltiVec
62  * is present.
63  */
65 {
66 #if HAVE_ALTIVEC
67 #ifdef __AMIGAOS4__
68  ULONG result = 0;
69  extern struct ExecIFace *IExec;
70 
71  IExec->GetCPUInfoTags(GCIT_VectorUnit, &result, TAG_DONE);
72  if (result == VECTORTYPE_ALTIVEC)
73  return AV_CPU_FLAG_ALTIVEC;
74  return 0;
75 #elif HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
76  int flags = 0;
77 
78  unsigned long hwcap = ff_getauxval(AT_HWCAP);
79  unsigned long hwcap2 = ff_getauxval(AT_HWCAP2);
80 
81  if (hwcap & HWCAP_PPC_ALTIVEC)
83  if (hwcap & HWCAP_PPC_VSX)
85  if (hwcap2 & HWCAP2_PPC_ARCH_2_07)
87 
88  return flags;
89 #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__)
90 #if defined(__NetBSD__) || defined(__OpenBSD__)
91  int sels[2] = {CTL_MACHDEP, CPU_ALTIVEC};
92 #else
93  int sels[2] = {CTL_HW, HW_VECTORUNIT};
94 #endif
95  int has_vu = 0;
96  size_t len = sizeof(has_vu);
97  int err;
98 
99  err = sysctl(sels, 2, &has_vu, &len, NULL, 0);
100 
101  if (err == 0)
102  return has_vu ? AV_CPU_FLAG_ALTIVEC : 0;
103  return 0;
104 #elif defined(__linux__)
105  // The linux kernel could have the altivec support disabled
106  // even if the cpu has it.
107  int i, ret = 0;
108  int fd = open("/proc/self/auxv", O_RDONLY);
109  unsigned long buf[64] = { 0 };
110  ssize_t count;
111 
112  if (fd < 0)
113  return 0;
114 
115  while ((count = read(fd, buf, sizeof(buf))) > 0) {
116  for (i = 0; i < count / sizeof(*buf); i += 2) {
117  if (buf[i] == AT_NULL)
118  goto out;
119  if (buf[i] == AT_HWCAP) {
120  if (buf[i + 1] & HWCAP_PPC_ALTIVEC)
122  if (buf[i + 1] & HWCAP_PPC_VSX)
123  ret |= AV_CPU_FLAG_VSX;
124  if (ret & AV_CPU_FLAG_VSX)
126  }
127  else if (buf[i] == AT_HWCAP2) {
128  if (buf[i + 1] & HWCAP2_PPC_ARCH_2_07)
130  }
131  }
132  }
133 
134 out:
135  close(fd);
136  return ret;
137 #elif CONFIG_RUNTIME_CPUDETECT && defined(__linux__)
138 #define PVR_G4_7400 0x000C
139 #define PVR_G5_970 0x0039
140 #define PVR_G5_970FX 0x003C
141 #define PVR_G5_970MP 0x0044
142 #define PVR_G5_970GX 0x0045
143 #define PVR_POWER6 0x003E
144 #define PVR_POWER7 0x003F
145 #define PVR_POWER8 0x004B
146 #define PVR_CELL_PPU 0x0070
147  int ret = 0;
148  int proc_ver;
149  // Support of mfspr PVR emulation added in Linux 2.6.17.
150  __asm__ volatile("mfspr %0, 287" : "=r" (proc_ver));
151  proc_ver >>= 16;
152  if (proc_ver & 0x8000 ||
153  proc_ver == PVR_G4_7400 ||
154  proc_ver == PVR_G5_970 ||
155  proc_ver == PVR_G5_970FX ||
156  proc_ver == PVR_G5_970MP ||
157  proc_ver == PVR_G5_970GX ||
158  proc_ver == PVR_POWER6 ||
159  proc_ver == PVR_POWER7 ||
160  proc_ver == PVR_POWER8 ||
161  proc_ver == PVR_CELL_PPU)
163  if (proc_ver == PVR_POWER7 ||
164  proc_ver == PVR_POWER8)
165  ret |= AV_CPU_FLAG_VSX;
166  if (proc_ver == PVR_POWER8)
168 
169  return ret;
170 #else
171  // Since we were compiled for AltiVec, just assume we have it
172  // until someone comes up with a proper way (not involving signal hacks).
173  return AV_CPU_FLAG_ALTIVEC;
174 #endif /* __AMIGAOS4__ */
175 #endif /* HAVE_ALTIVEC */
176  return 0;
177 }
178 
180 {
181  int flags = av_get_cpu_flags();
182 
183  if (flags & (AV_CPU_FLAG_ALTIVEC |
186  return 16;
187 
188  return 8;
189 }
AT_HWCAP
#define AT_HWCAP
Definition: cpu.c:50
out
FILE * out
Definition: movenc.c:55
HWCAP_PPC_ALTIVEC
#define HWCAP_PPC_ALTIVEC
Definition: cpu.c:57
av_get_cpu_flags
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition: cpu.c:109
HWCAP_PPC_VSX
#define HWCAP_PPC_VSX
Definition: cpu.c:56
AV_CPU_FLAG_VSX
#define AV_CPU_FLAG_VSX
ISA 2.06.
Definition: cpu.h:62
HWCAP2_PPC_ARCH_2_07
#define HWCAP2_PPC_ARCH_2_07
Definition: cpu.c:58
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:301
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:64
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:179
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
AT_HWCAP2
#define AT_HWCAP2
Definition: cpu.c:53
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