1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include "libavutil/cpu.h" 20cabdff1aSopenharmony_ci#include "libavutil/cpu_internal.h" 21cabdff1aSopenharmony_ci#include "config.h" 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#define CORE_FLAG(f) \ 24cabdff1aSopenharmony_ci (AV_CPU_FLAG_ ## f * (HAVE_ ## f ## _EXTERNAL || HAVE_ ## f ## _INLINE)) 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#define CORE_CPU_FLAGS \ 27cabdff1aSopenharmony_ci (CORE_FLAG(ARMV5TE) | \ 28cabdff1aSopenharmony_ci CORE_FLAG(ARMV6) | \ 29cabdff1aSopenharmony_ci CORE_FLAG(ARMV6T2) | \ 30cabdff1aSopenharmony_ci CORE_FLAG(VFP) | \ 31cabdff1aSopenharmony_ci CORE_FLAG(VFPV3) | \ 32cabdff1aSopenharmony_ci CORE_FLAG(NEON)) 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci#if defined __linux__ || defined __ANDROID__ 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci#include <stdint.h> 37cabdff1aSopenharmony_ci#include <stdio.h> 38cabdff1aSopenharmony_ci#include <string.h> 39cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci#if HAVE_GETAUXVAL 42cabdff1aSopenharmony_ci#include <sys/auxv.h> 43cabdff1aSopenharmony_ci#endif 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci#define AT_HWCAP 16 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci/* Relevant HWCAP values from kernel headers */ 48cabdff1aSopenharmony_ci#define HWCAP_VFP (1 << 6) 49cabdff1aSopenharmony_ci#define HWCAP_EDSP (1 << 7) 50cabdff1aSopenharmony_ci#define HWCAP_THUMBEE (1 << 11) 51cabdff1aSopenharmony_ci#define HWCAP_NEON (1 << 12) 52cabdff1aSopenharmony_ci#define HWCAP_VFPv3 (1 << 13) 53cabdff1aSopenharmony_ci#define HWCAP_TLS (1 << 15) 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_cistatic int get_auxval(uint32_t *hwcap) 56cabdff1aSopenharmony_ci{ 57cabdff1aSopenharmony_ci#if HAVE_GETAUXVAL 58cabdff1aSopenharmony_ci unsigned long ret = getauxval(AT_HWCAP); 59cabdff1aSopenharmony_ci if (ret == 0) 60cabdff1aSopenharmony_ci return -1; 61cabdff1aSopenharmony_ci *hwcap = ret; 62cabdff1aSopenharmony_ci return 0; 63cabdff1aSopenharmony_ci#else 64cabdff1aSopenharmony_ci return -1; 65cabdff1aSopenharmony_ci#endif 66cabdff1aSopenharmony_ci} 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_cistatic int get_hwcap(uint32_t *hwcap) 69cabdff1aSopenharmony_ci{ 70cabdff1aSopenharmony_ci struct { uint32_t a_type; uint32_t a_val; } auxv; 71cabdff1aSopenharmony_ci FILE *f = fopen("/proc/self/auxv", "r"); 72cabdff1aSopenharmony_ci int err = -1; 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci if (!f) 75cabdff1aSopenharmony_ci return -1; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci while (fread(&auxv, sizeof(auxv), 1, f) > 0) { 78cabdff1aSopenharmony_ci if (auxv.a_type == AT_HWCAP) { 79cabdff1aSopenharmony_ci *hwcap = auxv.a_val; 80cabdff1aSopenharmony_ci err = 0; 81cabdff1aSopenharmony_ci break; 82cabdff1aSopenharmony_ci } 83cabdff1aSopenharmony_ci } 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci fclose(f); 86cabdff1aSopenharmony_ci return err; 87cabdff1aSopenharmony_ci} 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_cistatic int get_cpuinfo(uint32_t *hwcap) 90cabdff1aSopenharmony_ci{ 91cabdff1aSopenharmony_ci FILE *f = fopen("/proc/cpuinfo", "r"); 92cabdff1aSopenharmony_ci char buf[200]; 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci if (!f) 95cabdff1aSopenharmony_ci return -1; 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci *hwcap = 0; 98cabdff1aSopenharmony_ci while (fgets(buf, sizeof(buf), f)) { 99cabdff1aSopenharmony_ci if (av_strstart(buf, "Features", NULL)) { 100cabdff1aSopenharmony_ci if (strstr(buf, " edsp ")) 101cabdff1aSopenharmony_ci *hwcap |= HWCAP_EDSP; 102cabdff1aSopenharmony_ci if (strstr(buf, " tls ")) 103cabdff1aSopenharmony_ci *hwcap |= HWCAP_TLS; 104cabdff1aSopenharmony_ci if (strstr(buf, " thumbee ")) 105cabdff1aSopenharmony_ci *hwcap |= HWCAP_THUMBEE; 106cabdff1aSopenharmony_ci if (strstr(buf, " vfp ")) 107cabdff1aSopenharmony_ci *hwcap |= HWCAP_VFP; 108cabdff1aSopenharmony_ci if (strstr(buf, " vfpv3 ")) 109cabdff1aSopenharmony_ci *hwcap |= HWCAP_VFPv3; 110cabdff1aSopenharmony_ci if (strstr(buf, " neon ") || strstr(buf, " asimd ")) 111cabdff1aSopenharmony_ci *hwcap |= HWCAP_NEON; 112cabdff1aSopenharmony_ci if (strstr(buf, " fp ")) // Listed on 64 bit ARMv8 kernels 113cabdff1aSopenharmony_ci *hwcap |= HWCAP_VFP | HWCAP_VFPv3; 114cabdff1aSopenharmony_ci break; 115cabdff1aSopenharmony_ci } 116cabdff1aSopenharmony_ci } 117cabdff1aSopenharmony_ci fclose(f); 118cabdff1aSopenharmony_ci return 0; 119cabdff1aSopenharmony_ci} 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ciint ff_get_cpu_flags_arm(void) 122cabdff1aSopenharmony_ci{ 123cabdff1aSopenharmony_ci int flags = CORE_CPU_FLAGS; 124cabdff1aSopenharmony_ci uint32_t hwcap; 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci if (get_auxval(&hwcap) < 0) 127cabdff1aSopenharmony_ci if (get_hwcap(&hwcap) < 0) 128cabdff1aSopenharmony_ci if (get_cpuinfo(&hwcap) < 0) 129cabdff1aSopenharmony_ci return flags; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci#define check_cap(cap, flag) do { \ 132cabdff1aSopenharmony_ci if (hwcap & HWCAP_ ## cap) \ 133cabdff1aSopenharmony_ci flags |= AV_CPU_FLAG_ ## flag; \ 134cabdff1aSopenharmony_ci } while (0) 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci /* No flags explicitly indicate v6 or v6T2 so check others which 137cabdff1aSopenharmony_ci imply support. */ 138cabdff1aSopenharmony_ci check_cap(EDSP, ARMV5TE); 139cabdff1aSopenharmony_ci check_cap(TLS, ARMV6); 140cabdff1aSopenharmony_ci check_cap(THUMBEE, ARMV6T2); 141cabdff1aSopenharmony_ci check_cap(VFP, VFP); 142cabdff1aSopenharmony_ci check_cap(VFPv3, VFPV3); 143cabdff1aSopenharmony_ci check_cap(NEON, NEON); 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci /* The v6 checks above are not reliable so let higher flags 146cabdff1aSopenharmony_ci trickle down. */ 147cabdff1aSopenharmony_ci if (flags & (AV_CPU_FLAG_VFPV3 | AV_CPU_FLAG_NEON)) 148cabdff1aSopenharmony_ci flags |= AV_CPU_FLAG_ARMV6T2; 149cabdff1aSopenharmony_ci else if (flags & (AV_CPU_FLAG_ARMV6T2 | AV_CPU_FLAG_ARMV6)) 150cabdff1aSopenharmony_ci /* Some functions use the 'setend' instruction which is deprecated on ARMv8 151cabdff1aSopenharmony_ci * and serializing on some ARMv7 cores. This ensures such functions 152cabdff1aSopenharmony_ci * are only enabled on ARMv6. */ 153cabdff1aSopenharmony_ci flags |= AV_CPU_FLAG_SETEND; 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci if (flags & AV_CPU_FLAG_ARMV6T2) 156cabdff1aSopenharmony_ci flags |= AV_CPU_FLAG_ARMV6; 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_ci /* set the virtual VFPv2 vector mode flag */ 159cabdff1aSopenharmony_ci if ((flags & AV_CPU_FLAG_VFP) && !(flags & (AV_CPU_FLAG_VFPV3 | AV_CPU_FLAG_NEON))) 160cabdff1aSopenharmony_ci flags |= AV_CPU_FLAG_VFP_VM; 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_ci return flags; 163cabdff1aSopenharmony_ci} 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci#else 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ciint ff_get_cpu_flags_arm(void) 168cabdff1aSopenharmony_ci{ 169cabdff1aSopenharmony_ci return AV_CPU_FLAG_ARMV5TE * HAVE_ARMV5TE | 170cabdff1aSopenharmony_ci AV_CPU_FLAG_ARMV6 * HAVE_ARMV6 | 171cabdff1aSopenharmony_ci AV_CPU_FLAG_ARMV6T2 * HAVE_ARMV6T2 | 172cabdff1aSopenharmony_ci AV_CPU_FLAG_VFP * HAVE_VFP | 173cabdff1aSopenharmony_ci AV_CPU_FLAG_VFPV3 * HAVE_VFPV3 | 174cabdff1aSopenharmony_ci AV_CPU_FLAG_NEON * HAVE_NEON | 175cabdff1aSopenharmony_ci AV_CPU_FLAG_SETEND * !(HAVE_NEON | HAVE_VFPV3); 176cabdff1aSopenharmony_ci} 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci#endif 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_cisize_t ff_get_cpu_max_align_arm(void) 181cabdff1aSopenharmony_ci{ 182cabdff1aSopenharmony_ci int flags = av_get_cpu_flags(); 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci if (flags & AV_CPU_FLAG_NEON) 185cabdff1aSopenharmony_ci return 16; 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci return 8; 188cabdff1aSopenharmony_ci} 189