FFmpeg
tests.c
Go to the documentation of this file.
1 #include "tests.h"
2 
3 #if ARCH_RISCV
4 
5 /* Re-use helpers from main checkasm library */
6 #include "src/cpu.h"
7 
8 uint64_t selftest_get_cpu_flags_riscv(void)
9 {
10  uint64_t flags = SELFTEST_CPU_FLAG_RVI;
11  if (checkasm_has_float())
12  flags |= SELFTEST_CPU_FLAG_RVF;
13  if (checkasm_has_vector())
14  flags |= SELFTEST_CPU_FLAG_RVV;
15  return flags;
16 }
17 
18 DEF_COPY_FUNC(copy_rvv);
19 DEF_COPY_GETTER(SELFTEST_CPU_FLAG_RVV, copy_rvv)
20 
21 DEF_NOOP_FUNC(clobber_ra);
22 DEF_NOOP_FUNC(clobber_sp);
23 DEF_NOOP_FUNC(clobber_gp);
24 DEF_NOOP_FUNC(clobber_t0);
25 DEF_NOOP_FUNC(clobber_t1);
26 DEF_NOOP_FUNC(clobber_t2);
27 DEF_NOOP_FUNC(clobber_s0);
28 DEF_NOOP_FUNC(clobber_s1);
29 DEF_NOOP_FUNC(clobber_a0);
30 DEF_NOOP_FUNC(clobber_a1);
31 DEF_NOOP_FUNC(clobber_a2);
32 DEF_NOOP_FUNC(clobber_a3);
33 DEF_NOOP_FUNC(clobber_a4);
34 DEF_NOOP_FUNC(clobber_a5);
35 DEF_NOOP_FUNC(clobber_a6);
36 DEF_NOOP_FUNC(clobber_a7);
37 DEF_NOOP_FUNC(clobber_s2);
38 DEF_NOOP_FUNC(clobber_s3);
39 DEF_NOOP_FUNC(clobber_s4);
40 DEF_NOOP_FUNC(clobber_s5);
41 DEF_NOOP_FUNC(clobber_s6);
42 DEF_NOOP_FUNC(clobber_s7);
43 DEF_NOOP_FUNC(clobber_s8);
44 DEF_NOOP_FUNC(clobber_s9);
45 DEF_NOOP_FUNC(clobber_s10);
46 DEF_NOOP_FUNC(clobber_s11);
47 DEF_NOOP_FUNC(clobber_t3);
48 DEF_NOOP_FUNC(clobber_t4);
49 DEF_NOOP_FUNC(clobber_t5);
50 DEF_NOOP_FUNC(clobber_t6);
51 
52 DEF_NOOP_FUNC(clobber_ft0);
53 DEF_NOOP_FUNC(clobber_ft1);
54 DEF_NOOP_FUNC(clobber_ft2);
55 DEF_NOOP_FUNC(clobber_ft3);
56 DEF_NOOP_FUNC(clobber_ft4);
57 DEF_NOOP_FUNC(clobber_ft5);
58 DEF_NOOP_FUNC(clobber_ft6);
59 DEF_NOOP_FUNC(clobber_ft7);
60 DEF_NOOP_FUNC(clobber_fs0);
61 DEF_NOOP_FUNC(clobber_fs1);
62 DEF_NOOP_FUNC(clobber_fa0);
63 DEF_NOOP_FUNC(clobber_fa1);
64 DEF_NOOP_FUNC(clobber_fa2);
65 DEF_NOOP_FUNC(clobber_fa3);
66 DEF_NOOP_FUNC(clobber_fa4);
67 DEF_NOOP_FUNC(clobber_fa5);
68 DEF_NOOP_FUNC(clobber_fa6);
69 DEF_NOOP_FUNC(clobber_fa7);
70 DEF_NOOP_FUNC(clobber_fs2);
71 DEF_NOOP_FUNC(clobber_fs3);
72 DEF_NOOP_FUNC(clobber_fs4);
73 DEF_NOOP_FUNC(clobber_fs5);
74 DEF_NOOP_FUNC(clobber_fs6);
75 DEF_NOOP_FUNC(clobber_fs7);
76 DEF_NOOP_FUNC(clobber_fs8);
77 DEF_NOOP_FUNC(clobber_fs9);
78 DEF_NOOP_FUNC(clobber_fs10);
79 DEF_NOOP_FUNC(clobber_fs11);
80 DEF_NOOP_FUNC(clobber_ft8);
81 DEF_NOOP_FUNC(clobber_ft9);
82 DEF_NOOP_FUNC(clobber_ft10);
83 DEF_NOOP_FUNC(clobber_ft11);
84 
85 DEF_NOOP_FUNC(sigill_riscv);
86 DEF_NOOP_FUNC(corrupt_stack_riscv);
87 DEF_NOOP_GETTER(SELFTEST_CPU_FLAG_RVI, sigill_riscv)
88 DEF_NOOP_GETTER(SELFTEST_CPU_FLAG_RVI, corrupt_stack_riscv)
89 
90 typedef struct RiscvRegister {
91  const char *name;
92  noop_func *clobber;
93 } RiscvRegister;
94 
95 static const RiscvRegister registers_safe[] = {
96  { "ra", selftest_clobber_ra },
97  { "t0", selftest_clobber_t0 },
98  { "t1", selftest_clobber_t1 },
99  { "t2", selftest_clobber_t2 },
100  { "t3", selftest_clobber_t3 },
101  { "t4", selftest_clobber_t4 },
102  { "t5", selftest_clobber_t5 },
103  { "t6", selftest_clobber_t6 },
104  { "a0", selftest_clobber_a0 },
105  { "a1", selftest_clobber_a1 },
106  { "a2", selftest_clobber_a2 },
107  { "a3", selftest_clobber_a3 },
108  { "a4", selftest_clobber_a4 },
109  { "a5", selftest_clobber_a5 },
110  { "a6", selftest_clobber_a6 },
111  { "a7", selftest_clobber_a7 },
112  { NULL, NULL }
113 };
114 
115 static const RiscvRegister float_registers_safe[] = {
116  { "ft0", selftest_clobber_ft0 },
117  { "ft1", selftest_clobber_ft1 },
118  { "ft2", selftest_clobber_ft2 },
119  { "ft3", selftest_clobber_ft3 },
120  { "ft4", selftest_clobber_ft4 },
121  { "ft5", selftest_clobber_ft5 },
122  { "ft6", selftest_clobber_ft6 },
123  { "ft7", selftest_clobber_ft7 },
124 #ifdef __riscv_float_abi_soft
125  { "fs0", selftest_clobber_fs0 },
126  { "fs1", selftest_clobber_fs1 },
127 #endif
128  { "fa0", selftest_clobber_fa0 },
129  { "fa1", selftest_clobber_fa1 },
130  { "fa2", selftest_clobber_fa2 },
131  { "fa3", selftest_clobber_fa3 },
132  { "fa4", selftest_clobber_fa4 },
133  { "fa5", selftest_clobber_fa5 },
134  { "fa6", selftest_clobber_fa6 },
135  { "fa7", selftest_clobber_fa7 },
136 #ifdef __riscv_float_abi_soft
137  { "fs2", selftest_clobber_fs2 },
138  { "fs3", selftest_clobber_fs3 },
139  { "fs4", selftest_clobber_fs4 },
140  { "fs5", selftest_clobber_fs5 },
141  { "fs6", selftest_clobber_fs6 },
142  { "fs7", selftest_clobber_fs7 },
143  { "fs8", selftest_clobber_fs8 },
144  { "fs9", selftest_clobber_fs9 },
145  { "fs10", selftest_clobber_fs10 },
146  { "fs11", selftest_clobber_fs11 },
147 #endif
148  { "ft8", selftest_clobber_ft8 },
149  { "ft9", selftest_clobber_ft9 },
150  { "ft10", selftest_clobber_ft10 },
151  { "ft11", selftest_clobber_ft11 },
152  { NULL, NULL },
153 };
154 
155 static const RiscvRegister registers_unsafe[] = {
156  { "s0", selftest_clobber_s0 },
157  { "s1", selftest_clobber_s1 },
158  { "s2", selftest_clobber_s2 },
159  { "s3", selftest_clobber_s3 },
160  { "s4", selftest_clobber_s4 },
161  { "s5", selftest_clobber_s5 },
162  { "s6", selftest_clobber_s6 },
163  { "s7", selftest_clobber_s7 },
164  { "s8", selftest_clobber_s8 },
165  { "s9", selftest_clobber_s9 },
166  { "s10", selftest_clobber_s10 },
167  { "s11", selftest_clobber_s11 },
168  { "sp", selftest_clobber_sp },
169  { "gp", selftest_clobber_gp },
170  /* Can't clobber tp because checkasm.S saves registers in TLS */
171  { NULL, NULL }
172 };
173 
174 static const RiscvRegister float_registers_unsafe[] = {
175 #ifndef __riscv_float_abi_soft
176  { "fs0", selftest_clobber_fs0 },
177  { "fs1", selftest_clobber_fs1 },
178  { "fs2", selftest_clobber_fs2 },
179  { "fs3", selftest_clobber_fs3 },
180  { "fs4", selftest_clobber_fs4 },
181  { "fs5", selftest_clobber_fs5 },
182  { "fs6", selftest_clobber_fs6 },
183  { "fs7", selftest_clobber_fs7 },
184  { "fs8", selftest_clobber_fs8 },
185  { "fs9", selftest_clobber_fs9 },
186  { "fs10", selftest_clobber_fs10 },
187  { "fs11", selftest_clobber_fs11 },
188 #endif
189  { NULL, NULL }
190 };
191 
192 static void check_clobber(uint64_t mask, unsigned char letter,
193  const RiscvRegister *registers)
194 {
195  const uint64_t flag = checkasm_get_cpu_flags() & mask;
196  checkasm_declare(void, int);
197 
198  for (int i = 0; registers[i].name; i++) {
199  noop_func *const func = flag ? registers[i].clobber : NULL;
200  if (checkasm_check_func(func, "clobber_%s", registers[i].name)) {
202  }
203  }
204 
205  checkasm_report("clobber_%c", letter);
206 }
207 
208 void selftest_check_riscv(void)
209 {
210  selftest_test_copy(get_copy_rvv(), "copy_rvv", 1);
211  check_clobber(SELFTEST_CPU_FLAG_RVI, 'x', registers_safe);
212  check_clobber(SELFTEST_CPU_FLAG_RVF, 'f', float_registers_safe);
213 
214  if (!checkasm_should_fail(1))
215  return;
216  selftest_test_noop(get_sigill_riscv(), "sigill");
217  selftest_test_noop(get_corrupt_stack_riscv(), "corrupt_stack");
218  check_clobber(SELFTEST_CPU_FLAG_RVI, 'x', registers_unsafe);
219  check_clobber(SELFTEST_CPU_FLAG_RVF, 'f', float_registers_unsafe);
220 }
221 
222 #endif
flags
const SwsFlags flags[]
Definition: swscale.c:85
selftest_check_riscv
void selftest_check_riscv(void)
func
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:66
DEF_COPY_FUNC
#define DEF_COPY_FUNC(NAME)
Definition: tests.h:78
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
checkasm_check_func
#define checkasm_check_func(func,...)
Check if a function should be tested and set up function references.
Definition: test.h:77
flag
int flag
Definition: cpu.c:40
mask
int mask
Definition: mediacodecdec_common.c:154
DEF_COPY_GETTER
#define DEF_COPY_GETTER(FLAG, NAME)
Definition: tests.h:81
NULL
#define NULL
Definition: coverity.c:32
noop_func
void() noop_func(int unused)
Do nothing.
Definition: tests.h:94
selftest_test_copy
void selftest_test_copy(copy_func fun, const char *name, const int min_width)
Definition: generic.c:37
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
cpu.h
checkasm_declare
#define checkasm_declare(ret,...)
Declare a function signature for testing.
Definition: test.h:205
checkasm_report
CHECKASM_API void checkasm_report(const char *name,...) CHECKASM_PRINTF(1
Report test outcome for a named group of functions.
checkasm_get_cpu_flags
CHECKASM_API CheckasmCpu checkasm_get_cpu_flags(void)
Get the current active set of CPU flags.
Definition: checkasm.c:121
tests.h
DEF_NOOP_GETTER
#define DEF_NOOP_GETTER(FLAG, NAME)
Definition: tests.h:98
selftest_test_noop
void selftest_test_noop(noop_func fun, const char *name)
Definition: generic.c:83
DEF_NOOP_FUNC
#define DEF_NOOP_FUNC(NAME)
Definition: tests.h:97
checkasm_should_fail
CHECKASM_API int checkasm_should_fail(CheckasmCpu cpu_flags)
Mark a block of tests as expected to fail.
Definition: checkasm.c:1017
checkasm_call_new
#define checkasm_call_new(...)
Call the implementation being tested with validation.
Definition: test.h:381
selftest_get_cpu_flags_riscv
uint64_t selftest_get_cpu_flags_riscv(void)