Commit 37388b11 authored by James Almer's avatar James Almer

checkasm: add a checkasm_checked_call function that doesn't issue emms

Meant for DSP functions returning a float or double, as they'd fail if emms
is called after every run on x86_32.
Signed-off-by: 's avatarJames Almer <jamrial@gmail.com>
parent 12245ab1
...@@ -84,6 +84,7 @@ static av_unused void *func_ref, *func_new; ...@@ -84,6 +84,7 @@ static av_unused void *func_ref, *func_new;
/* Declare the function prototype. The first argument is the return value, the remaining /* Declare the function prototype. The first argument is the return value, the remaining
* arguments are the function parameters. Naming parameters is optional. */ * arguments are the function parameters. Naming parameters is optional. */
#define declare_func(ret, ...) declare_new(ret, __VA_ARGS__) typedef ret func_type(__VA_ARGS__) #define declare_func(ret, ...) declare_new(ret, __VA_ARGS__) typedef ret func_type(__VA_ARGS__)
#define declare_func_float(ret, ...) declare_new_float(ret, __VA_ARGS__) typedef ret func_type(__VA_ARGS__)
#define declare_func_emms(cpu_flags, ret, ...) declare_new_emms(cpu_flags, ret, __VA_ARGS__) typedef ret func_type(__VA_ARGS__) #define declare_func_emms(cpu_flags, ret, ...) declare_new_emms(cpu_flags, ret, __VA_ARGS__) typedef ret func_type(__VA_ARGS__)
/* Indicate that the current test has failed */ /* Indicate that the current test has failed */
...@@ -102,6 +103,9 @@ void checkasm_checked_call(void *func, ...); ...@@ -102,6 +103,9 @@ void checkasm_checked_call(void *func, ...);
/* Verifies that clobbered callee-saved registers are properly saved and restored /* Verifies that clobbered callee-saved registers are properly saved and restored
* and issues emms for asm functions which are not required to do so */ * and issues emms for asm functions which are not required to do so */
void checkasm_checked_call_emms(void *func, ...); void checkasm_checked_call_emms(void *func, ...);
/* Verifies that clobbered callee-saved registers are properly saved and restored
* but doesn't issue emms. Meant for dsp functions returning float or double */
void checkasm_checked_call_float(void *func, ...);
#if ARCH_X86_64 #if ARCH_X86_64
/* Evil hack: detect incorrect assumptions that 32-bit ints are zero-extended to 64-bit. /* Evil hack: detect incorrect assumptions that 32-bit ints are zero-extended to 64-bit.
...@@ -116,6 +120,8 @@ void checkasm_checked_call_emms(void *func, ...); ...@@ -116,6 +120,8 @@ void checkasm_checked_call_emms(void *func, ...);
void checkasm_stack_clobber(uint64_t clobber, ...); void checkasm_stack_clobber(uint64_t clobber, ...);
#define declare_new(ret, ...) ret (*checked_call)(void *, int, int, int, int, int, __VA_ARGS__)\ #define declare_new(ret, ...) ret (*checked_call)(void *, int, int, int, int, int, __VA_ARGS__)\
= (void *)checkasm_checked_call; = (void *)checkasm_checked_call;
#define declare_new_float(ret, ...) ret (*checked_call)(void *, int, int, int, int, int, __VA_ARGS__)\
= (void *)checkasm_checked_call_float;
#define declare_new_emms(cpu_flags, ret, ...) \ #define declare_new_emms(cpu_flags, ret, ...) \
ret (*checked_call)(void *, int, int, int, int, int, __VA_ARGS__) = \ ret (*checked_call)(void *, int, int, int, int, int, __VA_ARGS__) = \
((cpu_flags) & av_get_cpu_flags()) ? (void *)checkasm_checked_call_emms : \ ((cpu_flags) & av_get_cpu_flags()) ? (void *)checkasm_checked_call_emms : \
...@@ -126,6 +132,7 @@ void checkasm_stack_clobber(uint64_t clobber, ...); ...@@ -126,6 +132,7 @@ void checkasm_stack_clobber(uint64_t clobber, ...);
checked_call(func_new, 0, 0, 0, 0, 0, __VA_ARGS__)) checked_call(func_new, 0, 0, 0, 0, 0, __VA_ARGS__))
#elif ARCH_X86_32 #elif ARCH_X86_32
#define declare_new(ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = (void *)checkasm_checked_call; #define declare_new(ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = (void *)checkasm_checked_call;
#define declare_new_float(ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = (void *)checkasm_checked_call_float;
#define declare_new_emms(cpu_flags, ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = \ #define declare_new_emms(cpu_flags, ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = \
((cpu_flags) & av_get_cpu_flags()) ? (void *)checkasm_checked_call_emms : \ ((cpu_flags) & av_get_cpu_flags()) ? (void *)checkasm_checked_call_emms : \
(void *)checkasm_checked_call; (void *)checkasm_checked_call;
...@@ -151,6 +158,7 @@ void checkasm_checked_call(void *func, ...); ...@@ -151,6 +158,7 @@ void checkasm_checked_call(void *func, ...);
checked_call(func_new, 0, 0, 0, 0, 0, 0, 0, __VA_ARGS__)) checked_call(func_new, 0, 0, 0, 0, 0, 0, 0, __VA_ARGS__))
#else #else
#define declare_new(ret, ...) #define declare_new(ret, ...)
#define declare_new_float(ret, ...)
#define declare_new_emms(cpu_flags, ret, ...) #define declare_new_emms(cpu_flags, ret, ...)
/* Call the function */ /* Call the function */
#define call_new(...) ((func_type *)func_new)(__VA_ARGS__) #define call_new(...) ((func_type *)func_new)(__VA_ARGS__)
...@@ -159,6 +167,9 @@ void checkasm_checked_call(void *func, ...); ...@@ -159,6 +167,9 @@ void checkasm_checked_call(void *func, ...);
#ifndef declare_new_emms #ifndef declare_new_emms
#define declare_new_emms(cpu_flags, ret, ...) declare_new(ret, __VA_ARGS__) #define declare_new_emms(cpu_flags, ret, ...) declare_new(ret, __VA_ARGS__)
#endif #endif
#ifndef declare_new_float
#define declare_new_float(ret, ...) declare_new(ret, __VA_ARGS__)
#endif
/* Benchmark the function */ /* Benchmark the function */
#ifdef AV_READ_TIME #ifdef AV_READ_TIME
......
...@@ -169,15 +169,15 @@ cglobal checked_call%1, 2,15,16,max_args*8+8 ...@@ -169,15 +169,15 @@ cglobal checked_call%1, 2,15,16,max_args*8+8
jz .clobber_ok jz .clobber_ok
report_fail error_message report_fail error_message
.clobber_ok: .clobber_ok:
%ifnid %1, _emms %ifidn %1, _emms
emms
%elifnidn %1, _float
fstenv [rsp] fstenv [rsp]
cmp word [rsp + 8], 0xffff cmp word [rsp + 8], 0xffff
je .emms_ok je .emms_ok
report_fail error_message_emms report_fail error_message_emms
emms emms
.emms_ok: .emms_ok:
%else
emms
%endif %endif
RET RET
%endmacro %endmacro
...@@ -223,15 +223,15 @@ cglobal checked_call%1, 1,7 ...@@ -223,15 +223,15 @@ cglobal checked_call%1, 1,7
jz .clobber_ok jz .clobber_ok
report_fail error_message report_fail error_message
.clobber_ok: .clobber_ok:
%ifnid %1, _emms %ifidn %1, _emms
emms
%elifnidn %1, _float
fstenv [esp] fstenv [esp]
cmp word [esp + 8], 0xffff cmp word [esp + 8], 0xffff
je .emms_ok je .emms_ok
report_fail error_message_emms report_fail error_message_emms
emms emms
.emms_ok: .emms_ok:
%else
emms
%endif %endif
add esp, max_args*4 add esp, max_args*4
REP_RET REP_RET
...@@ -241,3 +241,4 @@ cglobal checked_call%1, 1,7 ...@@ -241,3 +241,4 @@ cglobal checked_call%1, 1,7
CHECKED_CALL CHECKED_CALL
CHECKED_CALL _emms CHECKED_CALL _emms
CHECKED_CALL _float
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment