lavu/riscv: byte-swap operations

If the target supports the Basic bit-manipulation (Zbb) extension, then
the REV8 instruction is available to reverse byte order.

Note that this instruction only exists at the "XLEN" register size,
so we need to right shift the result down to the data width.

If Zbb is not supported, then this patchset does nothing. Support for
run-time detection is left for the future. Currently, there are no
bits in auxv/ELF HWCAP for Z-extensions, so there are no clean ways to
do this.
This commit is contained in:
Rémi Denis-Courmont 2022-09-12 18:53:19 +03:00 committed by James Almer
parent ff14e37393
commit df2057041b
2 changed files with 76 additions and 0 deletions

View File

@ -40,6 +40,8 @@
# include "arm/bswap.h"
#elif ARCH_AVR32
# include "avr32/bswap.h"
#elif ARCH_RISCV
# include "riscv/bswap.h"
#elif ARCH_SH4
# include "sh4/bswap.h"
#elif ARCH_X86

74
libavutil/riscv/bswap.h Normal file
View File

@ -0,0 +1,74 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_RISCV_BSWAP_H
#define AVUTIL_RISCV_BSWAP_H
#include <stdint.h>
#include "config.h"
#include "libavutil/attributes.h"
#if defined (__riscv_zbb) && (__riscv_zbb > 0) && HAVE_INLINE_ASM
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 */