xref: /third_party/ffmpeg/libavutil/mips/cpu.c (revision cabdff1a)
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