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 "libavutil/cpu.h" 20#include "libavutil/cpu_internal.h" 21#include "config.h" 22#if defined __linux__ || defined __ANDROID__ 23#include <stdint.h> 24#include <stdio.h> 25#include <string.h> 26#include <sys/auxv.h> 27#include "asmdefs.h" 28#include "libavutil/avstring.h" 29#endif 30 31#if defined __linux__ || defined __ANDROID__ 32 33#define HWCAP_LOONGSON_CPUCFG (1 << 14) 34 35static int cpucfg_available(void) 36{ 37 return getauxval(AT_HWCAP) & HWCAP_LOONGSON_CPUCFG; 38} 39 40/* Most toolchains have no CPUCFG support yet */ 41static uint32_t read_cpucfg(uint32_t reg) 42{ 43 uint32_t __res; 44 45 __asm__ __volatile__( 46 "parse_r __res,%0\n\t" 47 "parse_r reg,%1\n\t" 48 ".insn \n\t" 49 ".word (0xc8080118 | (reg << 21) | (__res << 11))\n\t" 50 :"=r"(__res) 51 :"r"(reg) 52 : 53 ); 54 return __res; 55} 56 57#define LOONGSON_CFG1 0x1 58 59#define LOONGSON_CFG1_MMI (1 << 4) 60#define LOONGSON_CFG1_MSA1 (1 << 5) 61 62static int cpu_flags_cpucfg(void) 63{ 64 int flags = 0; 65 uint32_t cfg1 = read_cpucfg(LOONGSON_CFG1); 66 67 if (cfg1 & LOONGSON_CFG1_MMI) 68 flags |= AV_CPU_FLAG_MMI; 69 70 if (cfg1 & LOONGSON_CFG1_MSA1) 71 flags |= AV_CPU_FLAG_MSA; 72 73 return flags; 74} 75 76static int cpu_flags_cpuinfo(void) 77{ 78 FILE *f = fopen("/proc/cpuinfo", "r"); 79 char buf[200]; 80 int flags = 0; 81 82 if (!f) 83 return -1; 84 85 while (fgets(buf, sizeof(buf), f)) { 86 /* Legacy kernel may not export MMI in ASEs implemented */ 87 if (av_strstart(buf, "cpu model", NULL)) { 88 if (strstr(buf, "Loongson-3 ")) 89 flags |= AV_CPU_FLAG_MMI; 90 } 91 92 if (av_strstart(buf, "ASEs implemented", NULL)) { 93 if (strstr(buf, " loongson-mmi")) 94 flags |= AV_CPU_FLAG_MMI; 95 if (strstr(buf, " msa")) 96 flags |= AV_CPU_FLAG_MSA; 97 98 break; 99 } 100 } 101 fclose(f); 102 return flags; 103} 104#endif 105 106int ff_get_cpu_flags_mips(void) 107{ 108#if defined __linux__ || defined __ANDROID__ 109 if (cpucfg_available()) 110 return cpu_flags_cpucfg(); 111 else 112 return cpu_flags_cpuinfo(); 113#else 114 /* Assume no SIMD ASE supported */ 115 return 0; 116#endif 117} 118 119size_t ff_get_cpu_max_align_mips(void) 120{ 121 int flags = av_get_cpu_flags(); 122 123 if (flags & AV_CPU_FLAG_MSA) 124 return 16; 125 126 /* 127 * MMI itself is 64-bit but quad word load & store 128 * needs 128-bit align. 129 */ 130 if (flags & AV_CPU_FLAG_MMI) 131 return 16; 132 133 return 8; 134} 135