checkasm: Use standard multiple inclusion guards
[libav.git] / tests / checkasm / checkasm.h
CommitLineData
8bc67ec2
HG
1/*
2 * Assembly testing and benchmarking tool
3 * Copyright (c) 2015 Henrik Gramner
4 * Copyright (c) 2008 Loren Merritt
5 *
6 * This file is part of Libav.
7 *
8 * Libav is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * Libav is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with Libav; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
7c82d31c
DB
23#ifndef TESTS_CHECKASM_CHECKASM_H
24#define TESTS_CHECKASM_CHECKASM_H
8bc67ec2
HG
25
26#include <stdint.h>
27#include "config.h"
28#include "libavutil/avstring.h"
711781d7 29#include "libavutil/cpu.h"
8bc67ec2
HG
30#include "libavutil/lfg.h"
31#include "libavutil/timer.h"
32
d37f2326 33void checkasm_check_bswapdsp(void);
e71b747e 34void checkasm_check_dcadsp(void);
489e6add 35void checkasm_check_fmtconvert(void);
8bc67ec2 36void checkasm_check_h264pred(void);
2cb34f82 37void checkasm_check_h264qpel(void);
0cef06df 38void checkasm_check_hevc_mc(void);
568a4323 39void checkasm_check_synth_filter(void);
3cdda78d 40void checkasm_check_v210enc(void);
8bc67ec2 41
515b69f8 42void *checkasm_check_func(void *func, const char *name, ...) av_printf_format(2, 3);
8bc67ec2
HG
43int checkasm_bench_func(void);
44void checkasm_fail_func(const char *msg, ...) av_printf_format(1, 2);
45void checkasm_update_bench(int iterations, uint64_t cycles);
46void checkasm_report(const char *name, ...) av_printf_format(1, 2);
47
9d218d57
JG
48/* float compare utilities */
49int float_near_ulp(float a, float b, unsigned max_ulp);
50int float_near_abs_eps(float a, float b, float eps);
51int float_near_abs_eps_ulp(float a, float b, float eps, unsigned max_ulp);
52int float_near_ulp_array(const float *a, const float *b, unsigned max_ulp,
53 unsigned len);
54int float_near_abs_eps_array(const float *a, const float *b, float eps,
55 unsigned len);
56int float_near_abs_eps_array_ulp(const float *a, const float *b, float eps,
57 unsigned max_ulp, unsigned len);
58
8bc67ec2
HG
59extern AVLFG checkasm_lfg;
60#define rnd() av_lfg_get(&checkasm_lfg)
61
515b69f8 62static av_unused void *func_ref, *func_new;
8bc67ec2
HG
63
64#define BENCH_RUNS 1000 /* Trade-off between accuracy and speed */
65
66/* Decide whether or not the specified function needs to be tested */
515b69f8
HG
67#define check_func(func, ...) (func_ref = checkasm_check_func((func_new = func), __VA_ARGS__))
68
69/* Declare the function prototype. The first argument is the return value, the remaining
70 * arguments are the function parameters. Naming parameters is optional. */
71#define declare_func(ret, ...) declare_new(ret, __VA_ARGS__) typedef ret func_type(__VA_ARGS__)
711781d7 72#define declare_func_emms(cpu_flags, ret, ...) declare_new_emms(cpu_flags, ret, __VA_ARGS__) typedef ret func_type(__VA_ARGS__)
8bc67ec2
HG
73
74/* Indicate that the current test has failed */
75#define fail() checkasm_fail_func("%s:%d", av_basename(__FILE__), __LINE__)
76
77/* Print the test outcome */
65c14801 78#define report checkasm_report
8bc67ec2
HG
79
80/* Call the reference function */
515b69f8 81#define call_ref(...) ((func_type *)func_ref)(__VA_ARGS__)
8bc67ec2
HG
82
83#if ARCH_X86 && HAVE_YASM
711781d7
JG
84/* Verifies that clobbered callee-saved registers are properly saved and restored
85 * and that either no MMX registers are touched or emms is issued */
515b69f8 86void checkasm_checked_call(void *func, ...);
711781d7
JG
87/* Verifies that clobbered callee-saved registers are properly saved and restored
88 * and issues emms for asm functions which are not required to do so */
89void checkasm_checked_call_emms(void *func, ...);
8bc67ec2 90
515b69f8 91#if ARCH_X86_64
8bc67ec2
HG
92/* Evil hack: detect incorrect assumptions that 32-bit ints are zero-extended to 64-bit.
93 * This is done by clobbering the stack with junk around the stack pointer and calling the
515b69f8 94 * assembly function through checked_call() with added dummy arguments which forces all
8bc67ec2
HG
95 * real arguments to be passed on the stack and not in registers. For 32-bit arguments the
96 * upper half of the 64-bit register locations on the stack will now contain junk which will
97 * cause misbehaving functions to either produce incorrect output or segfault. Note that
98 * even though this works extremely well in practice, it's technically not guaranteed
99 * and false negatives is theoretically possible, but there can never be any false positives.
100 */
101void checkasm_stack_clobber(uint64_t clobber, ...);
515b69f8
HG
102#define declare_new(ret, ...) ret (*checked_call)(void *, int, int, int, int, int, __VA_ARGS__)\
103 = (void *)checkasm_checked_call;
711781d7
JG
104#define declare_new_emms(cpu_flags, ret, ...) \
105 ret (*checked_call)(void *, int, int, int, int, int, __VA_ARGS__) = \
106 ((cpu_flags) & av_get_cpu_flags()) ? (void *)checkasm_checked_call_emms : \
107 (void *)checkasm_checked_call;
8bc67ec2
HG
108#define CLOB (UINT64_C(0xdeadbeefdeadbeef))
109#define call_new(...) (checkasm_stack_clobber(CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,\
110 CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB),\
515b69f8
HG
111 checked_call(func_new, 0, 0, 0, 0, 0, __VA_ARGS__))
112#elif ARCH_X86_32
113#define declare_new(ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = (void *)checkasm_checked_call;
711781d7
JG
114#define declare_new_emms(cpu_flags, ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = \
115 ((cpu_flags) & av_get_cpu_flags()) ? (void *)checkasm_checked_call_emms : \
116 (void *)checkasm_checked_call;
515b69f8
HG
117#define call_new(...) checked_call(func_new, __VA_ARGS__)
118#endif
26ec75ae
MS
119#elif ARCH_ARM && HAVE_ARMV5TE_EXTERNAL
120/* Use a dummy argument, to offset the real parameters by 2, not only 1.
121 * This makes sure that potential 8-byte-alignment of parameters is kept the same
122 * even when the extra parameters have been removed. */
123void checkasm_checked_call_vfp(void *func, int dummy, ...);
124void checkasm_checked_call_novfp(void *func, int dummy, ...);
125extern void (*checkasm_checked_call)(void *func, int dummy, ...);
126#define declare_new(ret, ...) ret (*checked_call)(void *, int dummy, __VA_ARGS__) = (void *)checkasm_checked_call;
127#define call_new(...) checked_call(func_new, 0, __VA_ARGS__)
fec76cd4
MS
128#elif ARCH_AARCH64 && !defined(__APPLE__)
129void checkasm_checked_call(void *func, ...);
130#define declare_new(ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = (void *)checkasm_checked_call;
131#define call_new(...) checked_call(func_new, __VA_ARGS__)
8bc67ec2 132#else
515b69f8 133#define declare_new(ret, ...)
711781d7 134#define declare_new_emms(cpu_flags, ret, ...)
515b69f8
HG
135/* Call the function */
136#define call_new(...) ((func_type *)func_new)(__VA_ARGS__)
8bc67ec2
HG
137#endif
138
26ec75ae
MS
139#ifndef declare_new_emms
140#define declare_new_emms(cpu_flags, ret, ...) declare_new(ret, __VA_ARGS__)
141#endif
142
8bc67ec2
HG
143/* Benchmark the function */
144#ifdef AV_READ_TIME
145#define bench_new(...)\
146 do {\
147 if (checkasm_bench_func()) {\
515b69f8 148 func_type *tfunc = func_new;\
8bc67ec2
HG
149 uint64_t tsum = 0;\
150 int ti, tcount = 0;\
151 for (ti = 0; ti < BENCH_RUNS; ti++) {\
152 uint64_t t = AV_READ_TIME();\
153 tfunc(__VA_ARGS__);\
154 tfunc(__VA_ARGS__);\
155 tfunc(__VA_ARGS__);\
156 tfunc(__VA_ARGS__);\
157 t = AV_READ_TIME() - t;\
158 if (t*tcount <= tsum*4 && ti > 0) {\
159 tsum += t;\
160 tcount++;\
161 }\
162 }\
163 checkasm_update_bench(tcount, tsum);\
164 }\
165 } while (0)
166#else
cb33f8d0 167#define bench_new(...) while(0)
8bc67ec2
HG
168#endif
169
7c82d31c 170#endif /* TESTS_CHECKASM_CHECKASM_H */