/* * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/cpu.h" #include "libavutil/cpu_internal.h" #include "config.h" #if defined __linux__ || defined __ANDROID__ #include #include #include #include #include "asmdefs.h" #include "libavutil/avstring.h" #endif #if defined __linux__ || defined __ANDROID__ #define HWCAP_LOONGSON_CPUCFG (1 << 14) static int cpucfg_available(void) { return ff_getauxval(AT_HWCAP) & HWCAP_LOONGSON_CPUCFG; } /* Most toolchains have no CPUCFG support yet */ static uint32_t read_cpucfg(uint32_t reg) { uint32_t __res; __asm__ __volatile__( "parse_r __res,%0\n\t" "parse_r reg,%1\n\t" ".insn \n\t" ".word (0xc8080118 | (reg << 21) | (__res << 11))\n\t" :"=r"(__res) :"r"(reg) : ); return __res; } #define LOONGSON_CFG1 0x1 #define LOONGSON_CFG1_MMI (1 << 4) #define LOONGSON_CFG1_MSA1 (1 << 5) static int cpu_flags_cpucfg(void) { int flags = 0; uint32_t cfg1 = read_cpucfg(LOONGSON_CFG1); if (cfg1 & LOONGSON_CFG1_MMI) flags |= AV_CPU_FLAG_MMI; if (cfg1 & LOONGSON_CFG1_MSA1) flags |= AV_CPU_FLAG_MSA; return flags; } static int cpu_flags_cpuinfo(void) { FILE *f = fopen("/proc/cpuinfo", "r"); char buf[200]; int flags = 0; if (!f) return -1; while (fgets(buf, sizeof(buf), f)) { /* Legacy kernel may not export MMI in ASEs implemented */ if (av_strstart(buf, "cpu model", NULL)) { if (strstr(buf, "Loongson-3 ")) flags |= AV_CPU_FLAG_MMI; } if (av_strstart(buf, "ASEs implemented", NULL)) { if (strstr(buf, " loongson-mmi")) flags |= AV_CPU_FLAG_MMI; if (strstr(buf, " msa")) flags |= AV_CPU_FLAG_MSA; break; } } fclose(f); return flags; } #endif int ff_get_cpu_flags_mips(void) { #if defined __linux__ || defined __ANDROID__ if (cpucfg_available()) return cpu_flags_cpucfg(); else return cpu_flags_cpuinfo(); #else /* Assume no SIMD ASE supported */ return 0; #endif } size_t ff_get_cpu_max_align_mips(void) { int flags = av_get_cpu_flags(); if (flags & AV_CPU_FLAG_MSA) return 16; /* * MMI itself is 64-bit but quad word load & store * needs 128-bit align. */ if (flags & AV_CPU_FLAG_MMI) return 16; return 8; }