From 2e952f300fa29fbbfbdb9986c826bfec708834be Mon Sep 17 00:00:00 2001 From: yuanhecai Date: Wed, 28 Jun 2023 10:52:35 +0800 Subject: [PATCH] Add loongarch support --- include/common/attributes.h | 2 +- meson.build | 10 ++++++-- src/cpu.c | 2 ++ src/cpu.h | 2 ++ src/loongarch/cpu.c | 47 +++++++++++++++++++++++++++++++++++++ src/loongarch/cpu.h | 37 +++++++++++++++++++++++++++++ src/meson.build | 4 ++++ tests/checkasm/checkasm.c | 3 +++ tests/checkasm/checkasm.h | 17 ++++++++++++++ tools/dav1d_cli_parse.c | 5 ++++ 10 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 src/loongarch/cpu.c create mode 100644 src/loongarch/cpu.h diff --git a/include/common/attributes.h b/include/common/attributes.h index 71c34f25..d8dac047 100644 --- a/include/common/attributes.h +++ b/include/common/attributes.h @@ -60,7 +60,7 @@ #define ALIGN_64_VAL 64 #define ALIGN_32_VAL 32 #define ALIGN_16_VAL 16 -#elif ARCH_X86_32 || ARCH_ARM || ARCH_AARCH64 || ARCH_PPC64LE +#elif ARCH_X86_32 || ARCH_ARM || ARCH_AARCH64 || ARCH_PPC64LE || ARCH_LOONGARCH /* ARM doesn't benefit from anything more than 16-byte alignment. */ #define ALIGN_64_VAL 16 #define ALIGN_32_VAL 16 diff --git a/meson.build b/meson.build index 2b88f3c4..0892a4f7 100644 --- a/meson.build +++ b/meson.build @@ -66,7 +66,8 @@ is_asm_enabled = (get_option('enable_asm') == true and (host_machine.cpu_family() == 'x86_64' and cc.get_define('__ILP32__').strip() == '') or host_machine.cpu_family() == 'aarch64' or host_machine.cpu_family().startswith('arm') or - host_machine.cpu() == 'ppc64le')) + host_machine.cpu() == 'ppc64le' or + host_machine.cpu_family().startswith('loongarch'))) cdata.set10('HAVE_ASM', is_asm_enabled) if is_asm_enabled and get_option('b_sanitize') == 'memory' @@ -232,7 +233,8 @@ endif if (host_machine.cpu_family() == 'aarch64' or host_machine.cpu_family().startswith('arm') or - host_machine.cpu() == 'ppc64le') + host_machine.cpu() == 'ppc64le' or + host_machine.cpu_family().startswith('loongarch')) if cc.has_function('getauxval', prefix : '#include ', args : test_args) cdata.set('HAVE_GETAUXVAL', 1) endif @@ -379,6 +381,10 @@ endif cdata.set10('ARCH_PPC64LE', host_machine.cpu() == 'ppc64le') +cdata.set10('ARCH_LOONGARCH', host_machine.cpu_family().startswith('loongarch')) +cdata.set10('ARCH_LOONGARCH32', host_machine.cpu_family() == 'loongarch32') +cdata.set10('ARCH_LOONGARCH64', host_machine.cpu_family() == 'loongarch64') + # meson's cc.symbols_have_underscore_prefix() is unfortunately unrelieably # when additional flags like '-fprofile-instr-generate' are passed via CFLAGS # see following meson issue https://github.com/mesonbuild/meson/issues/5482 diff --git a/src/cpu.c b/src/cpu.c index d24148c3..5d6fc49a 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -56,6 +56,8 @@ COLD void dav1d_init_cpu(void) { // memory sanitizer is inherently incompatible with asm #if ARCH_AARCH64 || ARCH_ARM dav1d_cpu_flags = dav1d_get_cpu_flags_arm(); +#elif ARCH_LOONGARCH + dav1d_cpu_flags = dav1d_get_cpu_flags_loongarch(); #elif ARCH_PPC64LE dav1d_cpu_flags = dav1d_get_cpu_flags_ppc(); #elif ARCH_X86 diff --git a/src/cpu.h b/src/cpu.h index 8f70fefe..d42530ee 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -37,6 +37,8 @@ #if ARCH_AARCH64 || ARCH_ARM #include "src/arm/cpu.h" +#elif ARCH_LOONGARCH +#include "src/loongarch/cpu.h" #elif ARCH_PPC64LE #include "src/ppc/cpu.h" #elif ARCH_X86 diff --git a/src/loongarch/cpu.c b/src/loongarch/cpu.c new file mode 100644 index 00000000..a79ade54 --- /dev/null +++ b/src/loongarch/cpu.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2023, VideoLAN and dav1d authors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "common/attributes.h" +#include "src/loongarch/cpu.h" + +#if defined(HAVE_GETAUXVAL) +#include + +#define LA_HWCAP_LSX ( 1 << 4 ) +#define LA_HWCAP_LASX ( 1 << 5 ) +#endif + +COLD unsigned dav1d_get_cpu_flags_loongarch(void) { + unsigned flags = 0; +#if defined(HAVE_GETAUXVAL) + unsigned long hw_cap = getauxval(AT_HWCAP); + flags |= (hw_cap & LA_HWCAP_LSX) ? DAV1D_LOONGARCH_CPU_FLAG_LSX : 0; + flags |= (hw_cap & LA_HWCAP_LASX) ? DAV1D_LOONGARCH_CPU_FLAG_LASX : 0; +#endif + + return flags; +} diff --git a/src/loongarch/cpu.h b/src/loongarch/cpu.h new file mode 100644 index 00000000..d00ff67d --- /dev/null +++ b/src/loongarch/cpu.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2023, VideoLAN and dav1d authors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DAV1D_SRC_LOONGARCH_CPU_H +#define DAV1D_SRC_LOONGARCH_CPU_H + +enum CpuFlags { + DAV1D_LOONGARCH_CPU_FLAG_LSX = 1 << 0, + DAV1D_LOONGARCH_CPU_FLAG_LASX = 1 << 1, +}; + +unsigned dav1d_get_cpu_flags_loongarch(void); + +#endif /* DAV1D_SRC_LOONGARCH_CPU_H */ diff --git a/src/meson.build b/src/meson.build index 3a34e76a..ac2a25b5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -235,6 +235,10 @@ if is_asm_enabled 'ppc/cdef_tmpl.c', 'ppc/looprestoration_tmpl.c', ) + elif host_machine.cpu_family().startswith('loongarch') + libdav1d_sources += files( + 'loongarch/cpu.c', + ) endif endif diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 26a85604..d4d51bb2 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -104,6 +104,9 @@ static const struct { { "NEON", "neon", DAV1D_ARM_CPU_FLAG_NEON }, #elif ARCH_PPC64LE { "VSX", "vsx", DAV1D_PPC_CPU_FLAG_VSX }, +#elif ARCH_LOONGARCH + { "LSX", "lsx", DAV1D_LOONGARCH_CPU_FLAG_LSX }, + { "LASX", "lasx", DAV1D_LOONGARCH_CPU_FLAG_LASX }, #endif { 0 } }; diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index bf69bbbb..e323319b 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -197,6 +197,23 @@ static inline uint64_t readtime(void) { return (((uint64_t)tbu) << 32) | (uint64_t)tbl; } #define readtime readtime +#elif ARCH_LOONGARCH +static inline uint64_t readtime(void) { +#if ARCH_LOONGARCH64 + uint64_t a, id; + __asm__ __volatile__("rdtime.d %0, %1" + : "=r"(a), "=r"(id) + :: ); + return a; +#else + uint32_t a, id; + __asm__ __volatile__("rdtimel.w %0, %1" + : "=r"(a), "=r"(id) + :: ); + return (uint64_t)a; +#endif +} +#define readtime readtime #endif /* Verifies that clobbered callee-saved registers diff --git a/tools/dav1d_cli_parse.c b/tools/dav1d_cli_parse.c index 4d747c03..5d22e263 100644 --- a/tools/dav1d_cli_parse.c +++ b/tools/dav1d_cli_parse.c @@ -101,6 +101,8 @@ static const struct option long_opts[] = { #if ARCH_AARCH64 || ARCH_ARM #define ALLOWED_CPU_MASKS " or 'neon'" +#elif ARCH_LOONGARCH +#define ALLOWED_CPU_MASKS ", 'lsx' or 'lasx'" #elif ARCH_PPC64LE #define ALLOWED_CPU_MASKS " or 'vsx'" #elif ARCH_X86 @@ -216,6 +218,9 @@ enum CpuMask { static const EnumParseTable cpu_mask_tbl[] = { #if ARCH_AARCH64 || ARCH_ARM { "neon", DAV1D_ARM_CPU_FLAG_NEON }, +#elif ARCH_LOONGARCH + { "lsx", DAV1D_LOONGARCH_CPU_FLAG_LSX }, + { "lasx", DAV1D_LOONGARCH_CPU_FLAG_LASX }, #elif ARCH_PPC64LE { "vsx", DAV1D_PPC_CPU_FLAG_VSX }, #elif ARCH_X86