avutil/emms: Add ff_assert[01]_fpu()

These will be used to mark and check parts of the code
where the floating point state is supposed to be not
clobbered. They are an improvement on the (deprecated)
av_assert0_fpu() because of proper file and line number
information; they also reset the floating point state
if the assert is actually triggered.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt
2026-02-27 08:14:12 +01:00
parent 7763155395
commit ac46514327

View File

@@ -19,8 +19,12 @@
#ifndef AVUTIL_EMMS_H
#define AVUTIL_EMMS_H
#include <stdint.h>
#include <stdlib.h>
#include "config.h"
#include "libavutil/attributes.h"
#include "libavutil/log.h"
#if ARCH_X86
@@ -50,6 +54,28 @@ static av_always_inline void emms_c(void)
#endif
__asm__ volatile ("emms" ::: "memory");
}
static inline void ff_assert0_fpu(const char *file, int line_number)
{
uint16_t state[14];
__asm__ volatile (
"fstenv %0 \n\t"
: "+m" (state)
:
: "memory"
);
if ((state[4] & 3) != 3) {
emms_c();
av_log(NULL, AV_LOG_PANIC,
"Invalid floating point state assertion "
"triggered at line %u in file %s\n",
line_number, file);
abort();
}
}
#define ff_assert0_fpu() ff_assert0_fpu(__FILE__, __LINE__)
#elif HAVE_MMX && HAVE_MM_EMPTY
# include <mmintrin.h>
# define emms_c _mm_empty
@@ -63,4 +89,14 @@ static av_always_inline void emms_c(void)
# define emms_c() do {} while(0)
#endif
#ifndef ff_assert0_fpu
#define ff_assert0_fpu() ((void)0)
#endif
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 1
#define ff_assert1_fpu() ff_assert0_fpu()
#else
#define ff_assert1_fpu() ((void)0)
#endif
#endif /* AVUTIL_EMMS_H */