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 defined(__linux__)
24 #include <asm/cputable.h>
25 #include <linux/auxvec.h>
26 #include <fcntl.h>
27 #if HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 #elif defined(__OpenBSD__)
31 #include <sys/param.h>
32 #include <sys/sysctl.h>
33 #include <machine/cpu.h>
34 #elif defined(__AMIGAOS4__)
35 #include <exec/exec.h>
36 #include <interfaces/exec.h>
37 #include <proto/exec.h>
38 #endif /* __APPLE__ */
39 
40 #include "libavutil/avassert.h"
41 #include "libavutil/cpu.h"
42 #include "libavutil/cpu_internal.h"
43 
44 /**
45  * This function MAY rely on signal() or fork() in order to make sure AltiVec
46  * is present.
47  */
49 {
50 #if HAVE_ALTIVEC
51 #ifdef __AMIGAOS4__
52  ULONG result = 0;
53  extern struct ExecIFace *IExec;
54 
55  IExec->GetCPUInfoTags(GCIT_VectorUnit, &result, TAG_DONE);
56  if (result == VECTORTYPE_ALTIVEC)
57  return AV_CPU_FLAG_ALTIVEC;
58  return 0;
59 #elif defined(__APPLE__) || defined(__OpenBSD__)
60 #ifdef __OpenBSD__
61  int sels[2] = {CTL_MACHDEP, CPU_ALTIVEC};
62 #else
63  int sels[2] = {CTL_HW, HW_VECTORUNIT};
64 #endif
65  int has_vu = 0;
66  size_t len = sizeof(has_vu);
67  int err;
68 
69  err = sysctl(sels, 2, &has_vu, &len, NULL, 0);
70 
71  if (err == 0)
72  return has_vu ? AV_CPU_FLAG_ALTIVEC : 0;
73  return 0;
74 #elif defined(__linux__)
75  // The linux kernel could have the altivec support disabled
76  // even if the cpu has it.
77  int i, ret = 0;
78  int fd = open("/proc/self/auxv", O_RDONLY);
79  unsigned long buf[64] = { 0 };
80  ssize_t count;
81 
82  if (fd < 0)
83  return 0;
84 
85  while ((count = read(fd, buf, sizeof(buf))) > 0) {
86  for (i = 0; i < count / sizeof(*buf); i += 2) {
87  if (buf[i] == AT_NULL)
88  goto out;
89  if (buf[i] == AT_HWCAP) {
90  if (buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC)
92 #ifdef PPC_FEATURE_HAS_VSX
93  if (buf[i + 1] & PPC_FEATURE_HAS_VSX)
95 #endif
96  if (ret & AV_CPU_FLAG_VSX)
98  } else if (buf[i] == AT_HWCAP2) {
99 #ifdef PPC_FEATURE2_ARCH_2_07
100  if (buf[i + 1] & PPC_FEATURE2_ARCH_2_07)
102 #endif
103  }
104  }
105  }
106 
107 out:
108  close(fd);
109  return ret;
110 #elif CONFIG_RUNTIME_CPUDETECT && defined(__linux__)
111 #define PVR_G4_7400 0x000C
112 #define PVR_G5_970 0x0039
113 #define PVR_G5_970FX 0x003C
114 #define PVR_G5_970MP 0x0044
115 #define PVR_G5_970GX 0x0045
116 #define PVR_POWER6 0x003E
117 #define PVR_POWER7 0x003F
118 #define PVR_POWER8 0x004B
119 #define PVR_CELL_PPU 0x0070
120  int ret = 0;
121  int proc_ver;
122  // Support of mfspr PVR emulation added in Linux 2.6.17.
123  __asm__ volatile("mfspr %0, 287" : "=r" (proc_ver));
124  proc_ver >>= 16;
125  if (proc_ver & 0x8000 ||
126  proc_ver == PVR_G4_7400 ||
127  proc_ver == PVR_G5_970 ||
128  proc_ver == PVR_G5_970FX ||
129  proc_ver == PVR_G5_970MP ||
130  proc_ver == PVR_G5_970GX ||
131  proc_ver == PVR_POWER6 ||
132  proc_ver == PVR_POWER7 ||
133  proc_ver == PVR_POWER8 ||
134  proc_ver == PVR_CELL_PPU)
136  if (proc_ver == PVR_POWER7 ||
137  proc_ver == PVR_POWER8)
138  ret |= AV_CPU_FLAG_VSX;
139  if (proc_ver == PVR_POWER8)
141 
142  return ret;
143 #else
144  // Since we were compiled for AltiVec, just assume we have it
145  // until someone comes up with a proper way (not involving signal hacks).
146  return AV_CPU_FLAG_ALTIVEC;
147 #endif /* __AMIGAOS4__ */
148 #endif /* HAVE_ALTIVEC */
149  return 0;
150 }
151 
153 {
154  int flags = av_get_cpu_flags();
155 
156  if (flags & (AV_CPU_FLAG_ALTIVEC |
159  return 16;
160 
161  return 8;
162 }
out
FILE * out
Definition: movenc.c:54
av_get_cpu_flags
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition: cpu.c:98
AV_CPU_FLAG_VSX
#define AV_CPU_FLAG_VSX
ISA 2.06.
Definition: cpu.h:60
avassert.h
cpu_internal.h
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
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:59
cpu.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
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:48
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:61
ff_get_cpu_max_align_ppc
size_t ff_get_cpu_max_align_ppc(void)
Definition: cpu.c:152
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561