diff options
author | Rémi Denis-Courmont <remi@remlab.net> | 2022-10-06 22:15:41 +0300 |
---|---|---|
committer | Lynne <dev@lynne.ee> | 2022-10-10 02:23:18 +0200 |
commit | c962c78901d65b5416d63ffbadcc600628acd5b8 (patch) | |
tree | a89624064a72a079fed1c9c001e2d89b8e9c6c48 | |
parent | 105921251ab35b870887e0c7348016f4dff3ec5b (diff) | |
download | ffmpeg-c962c78901d65b5416d63ffbadcc600628acd5b8.tar.gz |
checkasm: RISC-V 64-bit assembler test harness
-rw-r--r-- | tests/checkasm/Makefile | 1 | ||||
-rw-r--r-- | tests/checkasm/checkasm.h | 10 | ||||
-rw-r--r-- | tests/checkasm/riscv/checkasm.S | 178 |
3 files changed, 189 insertions, 0 deletions
diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index f330d3a8ab..62d6616faf 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -63,6 +63,7 @@ CHECKASMOBJS-$(CONFIG_AVUTIL) += $(AVUTILOBJS) CHECKASMOBJS-$(ARCH_AARCH64) += aarch64/checkasm.o CHECKASMOBJS-$(HAVE_ARMV5TE_EXTERNAL) += arm/checkasm.o +CHECKASMOBJS-$(ARCH_RISCV) += riscv/checkasm.o CHECKASMOBJS-$(HAVE_X86ASM) += x86/checkasm.o CHECKASMOBJS += $(CHECKASMOBJS-yes) checkasm.o diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 97e909170f..ee9151410e 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -203,6 +203,16 @@ void checkasm_checked_call(void *func, ...); CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB),\ checked_call(func_new, 0, 0, 0, 0, 0, 0, 0, __VA_ARGS__,\ 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0)) +#elif ARCH_RISCV +void checkasm_set_function(void *); +void *checkasm_get_wrapper(void); + +#if (__riscv_xlen == 64) && defined (__riscv_d) +#define declare_new(ret, ...) \ + ret (*checked_call)(__VA_ARGS__) = checkasm_get_wrapper(); +#define call_new(...) \ + (checkasm_set_function(func_new), checked_call(__VA_ARGS__)) +#endif #else #define declare_new(ret, ...) #define declare_new_float(ret, ...) diff --git a/tests/checkasm/riscv/checkasm.S b/tests/checkasm/riscv/checkasm.S new file mode 100644 index 0000000000..73ca85f344 --- /dev/null +++ b/tests/checkasm/riscv/checkasm.S @@ -0,0 +1,178 @@ +/**************************************************************************** + * Copyright © 2022 Rémi Denis-Courmont. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. + *****************************************************************************/ + +#include "libavutil/riscv/asm.S" + +#if (__riscv_xlen == 64) + +const fail_s_reg + .asciz "callee-saved integer register clobbered" +endconst + +const fail_fs_reg + .asciz "callee-saved floating-point register clobbered" +endconst + +const fail_rsvd_reg + .asciz "unallocatable register clobbered" +endconst + + .section .tbss, "waT" + .align 3 + .hidden checked_func + .hidden saved_regs + +checked_func: + .quad 0 + +saved_regs: + /* Space to spill RA, SP, GP, TP, S0-S11 and FS0-FS11 */ + .rept 4 + 12 + 12 + .quad 0 + .endr + +func checkasm_set_function + la.tls.ie t0, checked_func + add t0, tp, t0 + sd a0, (t0) + ret +endfunc + +func checkasm_get_wrapper, v + addi sp, sp, -16 + sd fp, (sp) + sd ra, 8(sp) + addi fp, sp, 16 + + call av_get_cpu_flags + andi t0, a0, 8 /* AV_CPU_FLAG_RVV_I32 */ + + lla a0, 3f + beqz t0, 1f + lla a0, 2f +1: + ld ra, 8(sp) + ld fp, (sp) + addi sp, sp, 16 + ret + +2: /* <-- Entry point with the Vector extension --> */ + /* Clobber the vectors */ + vsetvli t0, zero, e32, m8, ta, ma + li t0, 0xdeadbeef + vmv.v.x v0, t0 + vmv.v.x v8, t0 + vmv.v.x v16, t0 + vmv.v.x v24, t0 + + /* Clobber the vector configuration */ + li t0, 0 /* Vector length: zero */ + li t1, -1 << 31 /* Vector type: illegal */ + vsetvl zero, t0, t1 + csrwi vxrm, 3 /* Rounding mode: round-to-odd */ + csrwi vxsat, 1 /* Saturation: encountered */ + +3: /* <-- Entry point without the Vector extension --> */ + /* Save RA, unallocatable and callee-saved registers */ + la.tls.ie t0, saved_regs + add t0, tp, t0 + sd ra, (t0) + sd sp, 8(t0) + sd gp, 16(t0) + sd tp, 24(t0) + .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + sd s\n, (32 + (16 * \n))(t0) + fsd fs\n, (40 + (16 * \n))(t0) + .endr + + /* Clobber the stack space right below SP */ + li t0, 0xdeadbeef1badf00d + .rept 16 + addi sp, sp, -16 + sd t0, (sp) + sd t0, 8(sp) + .endr + addi sp, sp, 256 + + /* Clobber the saved and temporary registers */ + .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + .if (\n > 0 && \n < 7) + mv t\n, t0 + .endif + fmv.d.x ft\n, t0 + mv s\n, t0 + fmv.d.x fs\n, t0 + .endr + + /* Call the tested function */ + la.tls.ie t0, checked_func + add t0, tp, t0 + ld t1, (t0) + sd zero, (t0) + jalr t1 + + /* Check special register values */ + la.tls.ie t0, saved_regs + add t0, tp, t0 + ld t1, 8(t0) + bne t1, sp, 5f + ld t1, 16(t0) + bne t1, gp, 5f + ld t1, 24(t0) // If TP was corrupted, we probably will have... + bne t1, tp, 5f // ...already crashed before we even get here. + + /* Check value of saved registers */ + li t0, 0xdeadbeef1badf00d + .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + bne t0, s\n, 6f +#ifdef __riscv_float_abi_double + /* TODO: check float ABI single too */ + fmv.x.d t1, fs\n + bne t0, t1, 7f +#endif + .endr + +4: + /* Restore RA and saved registers */ + la.tls.ie t0, saved_regs + add t0, tp, t0 + ld ra, (t0) + .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + ld s\n, (32 + (16 * \n))(t0) + fld fs\n, (40 + (16 * \n))(t0) + .endr + ret + +5: + lla a0, fail_rsvd_reg + call checkasm_fail_func + tail abort /* The test harness would probably crash anyway */ + +6: + lla a0, fail_s_reg + call checkasm_fail_func + j 4b + +7: + lla a0, fail_fs_reg + call checkasm_fail_func + j 4b +endfunc +#endif |