riscv/bswap: use compiler builtins

av_bswapXX() are used in context that expect exact size types, notably
variable arguments to av_log(). On Linux RV64, uint_fast32_t is an
unsigned long, so the current inline assembler does not work properly.

Since GCC and Clang gained their byte-swap built-ins before they
supported RISC-V, we can simply defer to them. As an added bonus, the
compiler can do instruction scheduling, which it couldn't with the Zbb
inline assembler.
This commit is contained in:
Rémi Denis-Courmont 2023-04-20 20:53:56 +03:00 committed by Lynne
parent 129c7bf53f
commit 7dcb5e1ab0
1 changed files with 5 additions and 47 deletions

View File

@ -23,52 +23,10 @@
#include "config.h"
#include "libavutil/attributes.h"
#if defined (__riscv_zbb) && (__riscv_zbb > 0) && HAVE_INLINE_ASM
#if defined (__GNUC__) || defined (__clang__)
#define av_bswap16 __builtin_bswap16
#define av_bswap32 __builtin_bswap32
#define av_bswap64 __builtin_bswap64
#endif
static av_always_inline av_const uintptr_t av_bswap_xlen(uintptr_t x)
{
uintptr_t y;
__asm__("rev8 %0, %1" : "=r" (y) : "r" (x));
return y;
}
#define av_bswap16 av_bswap16
static av_always_inline av_const uint_fast16_t av_bswap16(uint_fast16_t x)
{
return av_bswap_xlen(x) >> (__riscv_xlen - 16);
}
#if (__riscv_xlen == 32)
#define av_bswap32 av_bswap_xlen
#define av_bswap64 av_bswap64
static av_always_inline av_const uint64_t av_bswap64(uint64_t x)
{
return (((uint64_t)av_bswap32(x)) << 32) | av_bswap32(x >> 32);
}
#else
#define av_bswap32 av_bswap32
static av_always_inline av_const uint_fast32_t av_bswap32(uint_fast32_t x)
{
return av_bswap_xlen(x) >> (__riscv_xlen - 32);
}
#if (__riscv_xlen == 64)
#define av_bswap64 av_bswap_xlen
#else
#define av_bswap64 av_bswap64
static av_always_inline av_const uint_fast64_t av_bswap64(uint_fast64_t x)
{
return av_bswap_xlen(x) >> (__riscv_xlen - 64);
}
#endif /* __riscv_xlen > 64 */
#endif /* __riscv_xlen > 32 */
#endif /* __riscv_zbb */
#endif /* AVUTIL_RISCV_BSWAP_H */