summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavutil/cpu.c10
-rw-r--r--libavutil/cpu.h3
-rw-r--r--libavutil/cpu_internal.h2
-rw-r--r--libavutil/mips/Makefile2
-rw-r--r--libavutil/mips/cpu.c134
-rw-r--r--libavutil/mips/cpu.h28
-rw-r--r--libavutil/tests/cpu.c3
-rw-r--r--tests/checkasm/checkasm.c3
8 files changed, 184 insertions, 1 deletions
diff --git a/libavutil/cpu.c b/libavutil/cpu.c
index 6548cc3042..52f6b9a3bf 100644
--- a/libavutil/cpu.c
+++ b/libavutil/cpu.c
@@ -51,6 +51,8 @@ static atomic_int cpu_flags = ATOMIC_VAR_INIT(-1);
static int get_cpu_flags(void)
{
+ if (ARCH_MIPS)
+ return ff_get_cpu_flags_mips();
if (ARCH_AARCH64)
return ff_get_cpu_flags_aarch64();
if (ARCH_ARM)
@@ -169,6 +171,9 @@ int av_parse_cpu_flags(const char *s)
{ "armv8", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8 }, .unit = "flags" },
{ "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" },
{ "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" },
+#elif ARCH_MIPS
+ { "mmi", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMI }, .unit = "flags" },
+ { "msa", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA }, .unit = "flags" },
#endif
{ NULL },
};
@@ -250,6 +255,9 @@ int av_parse_cpu_caps(unsigned *flags, const char *s)
{ "armv8", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8 }, .unit = "flags" },
{ "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" },
{ "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" },
+#elif ARCH_MIPS
+ { "mmi", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMI }, .unit = "flags" },
+ { "msa", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA }, .unit = "flags" },
#endif
{ NULL },
};
@@ -308,6 +316,8 @@ int av_cpu_count(void)
size_t av_cpu_max_align(void)
{
+ if (ARCH_MIPS)
+ return ff_get_cpu_max_align_mips();
if (ARCH_AARCH64)
return ff_get_cpu_max_align_aarch64();
if (ARCH_ARM)
diff --git a/libavutil/cpu.h b/libavutil/cpu.h
index 8bb9eb606b..83099dd969 100644
--- a/libavutil/cpu.h
+++ b/libavutil/cpu.h
@@ -71,6 +71,9 @@
#define AV_CPU_FLAG_VFP_VM (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations
#define AV_CPU_FLAG_SETEND (1 <<16)
+#define AV_CPU_FLAG_MMI (1 << 0)
+#define AV_CPU_FLAG_MSA (1 << 1)
+
/**
* Return the flags which specify extensions supported by the CPU.
* The returned value is affected by av_force_cpu_flags() if that was used
diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h
index 37122d1c5f..889764320b 100644
--- a/libavutil/cpu_internal.h
+++ b/libavutil/cpu_internal.h
@@ -41,11 +41,13 @@
#define CPUEXT_FAST(flags, cpuext) CPUEXT_SUFFIX_FAST(flags, , cpuext)
#define CPUEXT_SLOW(flags, cpuext) CPUEXT_SUFFIX_SLOW(flags, , cpuext)
+int ff_get_cpu_flags_mips(void);
int ff_get_cpu_flags_aarch64(void);
int ff_get_cpu_flags_arm(void);
int ff_get_cpu_flags_ppc(void);
int ff_get_cpu_flags_x86(void);
+size_t ff_get_cpu_max_align_mips(void);
size_t ff_get_cpu_max_align_aarch64(void);
size_t ff_get_cpu_max_align_arm(void);
size_t ff_get_cpu_max_align_ppc(void);
diff --git a/libavutil/mips/Makefile b/libavutil/mips/Makefile
index dbfa5aa341..5f8c9b64e9 100644
--- a/libavutil/mips/Makefile
+++ b/libavutil/mips/Makefile
@@ -1 +1 @@
-OBJS += mips/float_dsp_mips.o
+OBJS += mips/float_dsp_mips.o mips/cpu.o
diff --git a/libavutil/mips/cpu.c b/libavutil/mips/cpu.c
new file mode 100644
index 0000000000..59619d54de
--- /dev/null
+++ b/libavutil/mips/cpu.c
@@ -0,0 +1,134 @@
+/*
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/auxv.h>
+#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 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;
+}
diff --git a/libavutil/mips/cpu.h b/libavutil/mips/cpu.h
new file mode 100644
index 0000000000..615dc49759
--- /dev/null
+++ b/libavutil/mips/cpu.h
@@ -0,0 +1,28 @@
+/*
+ * 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
+ */
+
+#ifndef AVUTIL_MIPS_CPU_H
+#define AVUTIL_MIPS_CPU_H
+
+#include "libavutil/cpu.h"
+#include "libavutil/cpu_internal.h"
+
+#define have_mmi(flags) CPUEXT(flags, MMI)
+#define have_msa(flags) CPUEXT(flags, MSA)
+
+#endif /* AVUTIL_MIPS_CPU_H */
diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c
index ce45b715a0..c853371fb3 100644
--- a/libavutil/tests/cpu.c
+++ b/libavutil/tests/cpu.c
@@ -49,6 +49,9 @@ static const struct {
{ AV_CPU_FLAG_SETEND, "setend" },
#elif ARCH_PPC
{ AV_CPU_FLAG_ALTIVEC, "altivec" },
+#elif ARCH_MIPS
+ { AV_CPU_FLAG_MMI, "mmi" },
+ { AV_CPU_FLAG_MSA, "msa" },
#elif ARCH_X86
{ AV_CPU_FLAG_MMX, "mmx" },
{ AV_CPU_FLAG_MMXEXT, "mmxext" },
diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index 899f68bb32..b3ac76c325 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -213,6 +213,9 @@ static const struct {
{ "ALTIVEC", "altivec", AV_CPU_FLAG_ALTIVEC },
{ "VSX", "vsx", AV_CPU_FLAG_VSX },
{ "POWER8", "power8", AV_CPU_FLAG_POWER8 },
+#elif ARCH_MIPS
+ { "MMI", "mmi", AV_CPU_FLAG_MMI },
+ { "MSA", "msa", AV_CPU_FLAG_MSA },
#elif ARCH_X86
{ "MMX", "mmx", AV_CPU_FLAG_MMX|AV_CPU_FLAG_CMOV },
{ "MMXEXT", "mmxext", AV_CPU_FLAG_MMXEXT },