Merge coreboot and libpayload <endian.h> into commonlib

We've accumulated a number of endianness-handling and related macros
that are duplicated between coreboot and libpayload. This patch reduces
duplication by merging them into a commonlib header. This has the added
side-benefit of bringing the coreboot implementation of beXXenc/dec()
functions to libpayload, which lead to better code generation by
avoiding https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92716.

Keep the htobell()-style functions in libpayload only since they're not
needed in coreboot and not preferred. Keep the cpu_to_beXX()-style
functions in coreboot only -- maybe we should deprecate those
eventually.

This patch is explicitly copying and relicensing some of the code I
originally added as GPLv2 in commit e8e92d60c4 ("endian.h: Add
be32dec/be32enc family of functions") to BSD-3.

Change-Id: I5eb83d44a98b3aa59bba65b8e22df668874d2668
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/90308
Reviewed-by: Maximilian Brune <maximilian.brune@9elements.com>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Julius Werner 2025-12-01 15:45:15 -08:00 committed by Yu-Ping Wu
commit 02a2fe7907
4 changed files with 193 additions and 451 deletions

View file

@ -32,152 +32,20 @@
#include <arch/io.h>
#include <arch/types.h>
#include <libpayload-config.h>
#include <string.h>
/* Endian functions from glibc 2.9 / BSD "endian.h" */
#define swab16(x) __builtin_bswap16(x)
#define swab32(x) __builtin_bswap32(x)
#define swab64(x) __builtin_bswap64(x)
#if CONFIG(LP_BIG_ENDIAN)
#define htobe16(in) (in)
#define htobe32(in) (in)
#define htobe64(in) (in)
#define htole16(in) ((uint16_t)__builtin_bswap16(in))
#define htole32(in) ((uint32_t)__builtin_bswap32(in))
#define htole64(in) ((uint64_t)__builtin_bswap64(in))
#define __BIG_ENDIAN
#elif CONFIG(LP_LITTLE_ENDIAN)
#define htobe16(in) ((uint16_t)__builtin_bswap16(in))
#define htobe32(in) ((uint32_t)__builtin_bswap32(in))
#define htobe64(in) ((uint64_t)__builtin_bswap64(in))
#define htole16(in) (in)
#define htole32(in) (in)
#define htole64(in) (in)
#else
#error Cant tell if the CPU is little or big endian.
#define __LITTLE_ENDIAN
#endif /* CONFIG_*_ENDIAN */
#define be16toh(in) htobe16(in)
#define be32toh(in) htobe32(in)
#define be64toh(in) htobe64(in)
#define le16toh(in) htole16(in)
#define le32toh(in) htole32(in)
#define le64toh(in) htole64(in)
#define htonw(in) htobe16(in)
#define htonl(in) htobe32(in)
#define htonll(in) htobe64(in)
#define ntohw(in) be16toh(in)
#define ntohl(in) be32toh(in)
#define ntohll(in) be64toh(in)
/*
* Alignment-agnostic encode/decode bytestream to/from little/big endian.
*/
static inline uint16_t be16dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;
return (uint16_t)((p[0] << 8) | p[1]);
}
static inline uint32_t be32dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;
return (((uint32_t)p[0] << 24) | (uint32_t)(p[1] << 16) |
(uint32_t)(p[2] << 8) | p[3]);
}
static inline uint64_t be64dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;
return (((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) |
((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32) |
((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) |
((uint64_t)p[6] << 8) | p[7]);
}
static inline uint16_t le16dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;
return (uint16_t)((p[1] << 8) | p[0]);
}
static inline uint32_t le32dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;
return ((uint32_t)(p[3] << 24) | (uint32_t)(p[2] << 16) |
(uint32_t)(p[1] << 8) | p[0]);
}
static inline uint64_t le64dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;
return (((uint64_t)p[7] << 56) | ((uint64_t)p[6] << 48) |
((uint64_t)p[5] << 40) | ((uint64_t)p[4] << 32) |
((uint64_t)p[3] << 24) | ((uint64_t)p[2] << 16) |
((uint64_t)p[1] << 8) | p[0]);
}
static inline void bebitenc(void *pp, uint32_t u, uint8_t b)
{
uint8_t *p = (uint8_t *)pp;
int i;
for (i = 0; i < b; i++)
p[(b - 1) - i] = (u >> i*8) & 0xFF;
}
static inline void be16enc(void *pp, uint16_t u)
{
bebitenc(pp, u, 2);
}
static inline void be32enc(void *pp, uint32_t u)
{
bebitenc(pp, u, 4);
}
static inline void be64enc(void *pp, uint32_t u)
{
bebitenc(pp, u, 8);
}
static inline void lebitenc(void *pp, uint32_t u, uint8_t b)
{
uint8_t *p = (uint8_t *)pp;
int i;
for (i = 0; i < b; i++)
p[i] = (u >> i*8) & 0xFF;
}
static inline void le16enc(void *pp, uint16_t u)
{
lebitenc(pp, u, 2);
}
static inline void le32enc(void *pp, uint32_t u)
{
lebitenc(pp, u, 4);
}
static inline void le64enc(void *pp, uint32_t u)
{
lebitenc(pp, u, 8);
}
/* This include depends on previous definitions, do not move to the top. */
#include <commonlib/bsd/_endian.h>
/* Deprecated names (not in glibc / BSD) */
#define htobew(in) htobe16(in)
@ -193,74 +61,4 @@ static inline void le64enc(void *pp, uint32_t u)
#define letohl(in) le32toh(in)
#define letohll(in) le64toh(in)
/* read/write with uintptr_t address */
#define read8p(addr) read8((void *)((uintptr_t)(addr)))
#define read16p(addr) read16((void *)((uintptr_t)(addr)))
#define read32p(addr) read32((void *)((uintptr_t)(addr)))
#define read64p(addr) read64((void *)((uintptr_t)(addr)))
#define write8p(addr, value) write8((void *)((uintptr_t)(addr)), value)
#define write16p(addr, value) write16((void *)((uintptr_t)(addr)), value)
#define write32p(addr, value) write32((void *)((uintptr_t)(addr)), value)
#define write64p(addr, value) write64((void *)((uintptr_t)(addr)), value)
/* Handy bit manipulation macros */
#define __clrsetbits(endian, bits, addr, clear, set) \
write##bits(addr, hto##endian##bits((endian##bits##toh( \
read##bits(addr)) & ~((uint##bits##_t)(clear))) | (set)))
#define clrbits_le64(addr, clear) __clrsetbits(le, 64, addr, clear, 0)
#define clrbits_be64(addr, clear) __clrsetbits(be, 64, addr, clear, 0)
#define clrbits_le32(addr, clear) __clrsetbits(le, 32, addr, clear, 0)
#define clrbits_be32(addr, clear) __clrsetbits(be, 32, addr, clear, 0)
#define clrbits_le16(addr, clear) __clrsetbits(le, 16, addr, clear, 0)
#define clrbits_be16(addr, clear) __clrsetbits(be, 16, addr, clear, 0)
#define setbits_le64(addr, set) __clrsetbits(le, 64, addr, 0, set)
#define setbits_be64(addr, set) __clrsetbits(be, 64, addr, 0, set)
#define setbits_le32(addr, set) __clrsetbits(le, 32, addr, 0, set)
#define setbits_be32(addr, set) __clrsetbits(be, 32, addr, 0, set)
#define setbits_le16(addr, set) __clrsetbits(le, 16, addr, 0, set)
#define setbits_be16(addr, set) __clrsetbits(be, 16, addr, 0, set)
#define clrsetbits_le64(addr, clear, set) __clrsetbits(le, 64, addr, clear, set)
#define clrsetbits_be64(addr, clear, set) __clrsetbits(be, 64, addr, clear, set)
#define clrsetbits_le32(addr, clear, set) __clrsetbits(le, 32, addr, clear, set)
#define clrsetbits_be32(addr, clear, set) __clrsetbits(be, 32, addr, clear, set)
#define clrsetbits_le16(addr, clear, set) __clrsetbits(le, 16, addr, clear, set)
#define clrsetbits_be16(addr, clear, set) __clrsetbits(be, 16, addr, clear, set)
#define __clrsetbits_impl(bits, addr, clear, set) write##bits(addr, \
(read##bits(addr) & ~((uint##bits##_t)(clear))) | (set))
#define clrsetbits8(addr, clear, set) __clrsetbits_impl(8, addr, clear, set)
#define clrsetbits16(addr, clear, set) __clrsetbits_impl(16, addr, clear, set)
#define clrsetbits32(addr, clear, set) __clrsetbits_impl(32, addr, clear, set)
#define clrsetbits64(addr, clear, set) __clrsetbits_impl(64, addr, clear, set)
#define setbits8(addr, set) clrsetbits8(addr, 0, set)
#define setbits16(addr, set) clrsetbits16(addr, 0, set)
#define setbits32(addr, set) clrsetbits32(addr, 0, set)
#define setbits64(addr, set) clrsetbits64(addr, 0, set)
#define clrbits8(addr, clear) clrsetbits8(addr, clear, 0)
#define clrbits16(addr, clear) clrsetbits16(addr, clear, 0)
#define clrbits32(addr, clear) clrsetbits32(addr, clear, 0)
#define clrbits64(addr, clear) clrsetbits64(addr, clear, 0)
#define clrsetbits8p(addr, clear, set) clrsetbits8((void *)((uintptr_t)(addr)), clear, set)
#define clrsetbits16p(addr, clear, set) clrsetbits16((void *)((uintptr_t)(addr)), clear, set)
#define clrsetbits32p(addr, clear, set) clrsetbits32((void *)((uintptr_t)(addr)), clear, set)
#define clrsetbits64p(addr, clear, set) clrsetbits64((void *)((uintptr_t)(addr)), clear, set)
#define setbits8p(addr, set) clrsetbits8((void *)((uintptr_t)(addr)), 0, set)
#define setbits16p(addr, set) clrsetbits16((void *)((uintptr_t)(addr)), 0, set)
#define setbits32p(addr, set) clrsetbits32((void *)((uintptr_t)(addr)), 0, set)
#define setbits64p(addr, set) clrsetbits64((void *)((uintptr_t)(addr)), 0, set)
#define clrbits8p(addr, clear) clrsetbits8((void *)((uintptr_t)(addr)), clear, 0)
#define clrbits16p(addr, clear) clrsetbits16((void *)((uintptr_t)(addr)), clear, 0)
#define clrbits32p(addr, clear) clrsetbits32((void *)((uintptr_t)(addr)), clear, 0)
#define clrbits64p(addr, clear) clrsetbits64((void *)((uintptr_t)(addr)), clear, 0)
#endif /* _ENDIAN_H_ */

View file

@ -0,0 +1,170 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only */
#ifndef _COMMONLIB_BSD__ENDIAN_H_
#define _COMMONLIB_BSD__ENDIAN_H_
/*
* This header should not be included directly. Including source must define
* prerequisites like uintXX_t types, the byteswap functions swabXX(),
* __BIG_ENDIAN or __LITTLE_ENDIAN and I/O accessors readXX()/writeXX().
*/
/* Endian functions from glibc 2.9 / BSD "endian.h" */
#if defined(__BIG_ENDIAN)
#define htobe16(in) (in)
#define htobe32(in) (in)
#define htobe64(in) (in)
#define htole16(in) ((uint16_t)swab16(in))
#define htole32(in) ((uint32_t)swab32(in))
#define htole64(in) ((uint64_t)swab64(in))
#elif defined(__LITTLE_ENDIAN)
#define htobe16(in) ((uint16_t)swab16(in))
#define htobe32(in) ((uint32_t)swab32(in))
#define htobe64(in) ((uint64_t)swab64(in))
#define htole16(in) (in)
#define htole32(in) (in)
#define htole64(in) (in)
#else
#error "Including source must #define __LITTLE_ENDIAN or __BIG_ENDIAN"
#endif
#define be16toh(in) htobe16(in)
#define be32toh(in) htobe32(in)
#define be64toh(in) htobe64(in)
#define le16toh(in) htole16(in)
#define le32toh(in) htole32(in)
#define le64toh(in) htole64(in)
#define htonw(in) htobe16(in)
#define htonl(in) htobe32(in)
#define htonll(in) htobe64(in)
#define ntohw(in) be16toh(in)
#define ntohl(in) be32toh(in)
#define ntohll(in) be64toh(in)
/*
* RISC-V doesn't support misaligned access so it must use memcpy().
*/
#if defined(__COREBOOT__) && ENV_RISCV
#define __ENDIAN_RISCV_WORKAROUND 1
#else
#define __ENDIAN_RISCV_WORKAROUND 0
#endif
/*
* be16dec/be32dec/be64dec/le16dec/le32dec/le64dec family of functions.
*/
#define DEFINE_ENDIAN_DEC(endian, width) \
static inline uint##width##_t endian##width##dec(const void *p) \
{ \
if (__ENDIAN_RISCV_WORKAROUND) { \
uint##width##_t val; \
memcpy(&val, p, sizeof(val)); \
return endian##width##toh(val); \
} else { \
return endian##width##toh(*(uint##width##_t *)p); \
} \
}
DEFINE_ENDIAN_DEC(be, 16)
DEFINE_ENDIAN_DEC(be, 32)
DEFINE_ENDIAN_DEC(be, 64)
DEFINE_ENDIAN_DEC(le, 16)
DEFINE_ENDIAN_DEC(le, 32)
DEFINE_ENDIAN_DEC(le, 64)
/*
* be16enc/be32enc/be64enc/le16enc/le32enc/le64enc family of functions.
*/
#define DEFINE_ENDIAN_ENC(endian, width) \
static inline void endian##width##enc(void *p, uint##width##_t u) \
{ \
if (__ENDIAN_RISCV_WORKAROUND) { \
uint##width##_t val = hto##endian##width(u); \
memcpy(p, &val, sizeof(val)); \
} else { \
*(uint##width##_t *)p = hto##endian##width(u); \
} \
}
DEFINE_ENDIAN_ENC(be, 16)
DEFINE_ENDIAN_ENC(be, 32)
DEFINE_ENDIAN_ENC(be, 64)
DEFINE_ENDIAN_ENC(le, 16)
DEFINE_ENDIAN_ENC(le, 32)
DEFINE_ENDIAN_ENC(le, 64)
/* read/write with uintptr_t address */
#define read8p(addr) read8((void *)((uintptr_t)(addr)))
#define read16p(addr) read16((void *)((uintptr_t)(addr)))
#define read32p(addr) read32((void *)((uintptr_t)(addr)))
#define read64p(addr) read64((void *)((uintptr_t)(addr)))
#define write8p(addr, value) write8((void *)((uintptr_t)(addr)), value)
#define write16p(addr, value) write16((void *)((uintptr_t)(addr)), value)
#define write32p(addr, value) write32((void *)((uintptr_t)(addr)), value)
#define write64p(addr, value) write64((void *)((uintptr_t)(addr)), value)
/* Handy bit manipulation macros */
#define __clrsetbits(endian, bits, addr, clear, set) \
write##bits(addr, hto##endian##bits((endian##bits##toh( \
read##bits(addr)) & ~((uint##bits##_t)(clear))) | (set)))
#define clrbits_le64(addr, clear) __clrsetbits(le, 64, addr, clear, 0)
#define clrbits_be64(addr, clear) __clrsetbits(be, 64, addr, clear, 0)
#define clrbits_le32(addr, clear) __clrsetbits(le, 32, addr, clear, 0)
#define clrbits_be32(addr, clear) __clrsetbits(be, 32, addr, clear, 0)
#define clrbits_le16(addr, clear) __clrsetbits(le, 16, addr, clear, 0)
#define clrbits_be16(addr, clear) __clrsetbits(be, 16, addr, clear, 0)
#define setbits_le64(addr, set) __clrsetbits(le, 64, addr, 0, set)
#define setbits_be64(addr, set) __clrsetbits(be, 64, addr, 0, set)
#define setbits_le32(addr, set) __clrsetbits(le, 32, addr, 0, set)
#define setbits_be32(addr, set) __clrsetbits(be, 32, addr, 0, set)
#define setbits_le16(addr, set) __clrsetbits(le, 16, addr, 0, set)
#define setbits_be16(addr, set) __clrsetbits(be, 16, addr, 0, set)
#define clrsetbits_le64(addr, clear, set) __clrsetbits(le, 64, addr, clear, set)
#define clrsetbits_be64(addr, clear, set) __clrsetbits(be, 64, addr, clear, set)
#define clrsetbits_le32(addr, clear, set) __clrsetbits(le, 32, addr, clear, set)
#define clrsetbits_be32(addr, clear, set) __clrsetbits(be, 32, addr, clear, set)
#define clrsetbits_le16(addr, clear, set) __clrsetbits(le, 16, addr, clear, set)
#define clrsetbits_be16(addr, clear, set) __clrsetbits(be, 16, addr, clear, set)
#define __clrsetbits_impl(bits, addr, clear, set) write##bits(addr, \
(read##bits(addr) & ~((uint##bits##_t)(clear))) | (set))
#define clrsetbits8(addr, clear, set) __clrsetbits_impl(8, addr, clear, set)
#define clrsetbits16(addr, clear, set) __clrsetbits_impl(16, addr, clear, set)
#define clrsetbits32(addr, clear, set) __clrsetbits_impl(32, addr, clear, set)
#define clrsetbits64(addr, clear, set) __clrsetbits_impl(64, addr, clear, set)
#define setbits8(addr, set) clrsetbits8(addr, 0, set)
#define setbits16(addr, set) clrsetbits16(addr, 0, set)
#define setbits32(addr, set) clrsetbits32(addr, 0, set)
#define setbits64(addr, set) clrsetbits64(addr, 0, set)
#define clrbits8(addr, clear) clrsetbits8(addr, clear, 0)
#define clrbits16(addr, clear) clrsetbits16(addr, clear, 0)
#define clrbits32(addr, clear) clrsetbits32(addr, clear, 0)
#define clrbits64(addr, clear) clrsetbits64(addr, clear, 0)
#define clrsetbits8p(addr, clear, set) clrsetbits8((void *)((uintptr_t)(addr)), clear, set)
#define clrsetbits16p(addr, clear, set) clrsetbits16((void *)((uintptr_t)(addr)), clear, set)
#define clrsetbits32p(addr, clear, set) clrsetbits32((void *)((uintptr_t)(addr)), clear, set)
#define clrsetbits64p(addr, clear, set) clrsetbits64((void *)((uintptr_t)(addr)), clear, set)
#define setbits8p(addr, set) clrsetbits8((void *)((uintptr_t)(addr)), 0, set)
#define setbits16p(addr, set) clrsetbits16((void *)((uintptr_t)(addr)), 0, set)
#define setbits32p(addr, set) clrsetbits32((void *)((uintptr_t)(addr)), 0, set)
#define setbits64p(addr, set) clrsetbits64((void *)((uintptr_t)(addr)), 0, set)
#define clrbits8p(addr, clear) clrsetbits8((void *)((uintptr_t)(addr)), clear, 0)
#define clrbits16p(addr, clear) clrsetbits16((void *)((uintptr_t)(addr)), clear, 0)
#define clrbits32p(addr, clear) clrsetbits32((void *)((uintptr_t)(addr)), clear, 0)
#define clrbits64p(addr, clear) clrsetbits64((void *)((uintptr_t)(addr)), clear, 0)
#endif /* _COMMONLIB_BSD__ENDIAN_H_ */

View file

@ -8,39 +8,6 @@
#include <endian.h>
#include <types.h>
#define __clrsetbits_impl(bits, addr, clear, set) write##bits(addr, \
(read##bits(addr) & ~((uint##bits##_t)(clear))) | (set))
#define clrsetbits8(addr, clear, set) __clrsetbits_impl(8, addr, clear, set)
#define clrsetbits16(addr, clear, set) __clrsetbits_impl(16, addr, clear, set)
#define clrsetbits32(addr, clear, set) __clrsetbits_impl(32, addr, clear, set)
#define clrsetbits64(addr, clear, set) __clrsetbits_impl(64, addr, clear, set)
#define setbits8(addr, set) clrsetbits8(addr, 0, set)
#define setbits16(addr, set) clrsetbits16(addr, 0, set)
#define setbits32(addr, set) clrsetbits32(addr, 0, set)
#define setbits64(addr, set) clrsetbits64(addr, 0, set)
#define clrbits8(addr, clear) clrsetbits8(addr, clear, 0)
#define clrbits16(addr, clear) clrsetbits16(addr, clear, 0)
#define clrbits32(addr, clear) clrsetbits32(addr, clear, 0)
#define clrbits64(addr, clear) clrsetbits64(addr, clear, 0)
#define clrsetbits8p(addr, clear, set) clrsetbits8((void *)((uintptr_t)addr), clear, set)
#define clrsetbits16p(addr, clear, set) clrsetbits16((void *)((uintptr_t)addr), clear, set)
#define clrsetbits32p(addr, clear, set) clrsetbits32((void *)((uintptr_t)addr), clear, set)
#define clrsetbits64p(addr, clear, set) clrsetbits64((void *)((uintptr_t)addr), clear, set)
#define setbits8p(addr, set) clrsetbits8((void *)((uintptr_t)addr), 0, set)
#define setbits16p(addr, set) clrsetbits16((void *)((uintptr_t)addr), 0, set)
#define setbits32p(addr, set) clrsetbits32((void *)((uintptr_t)addr), 0, set)
#define setbits64p(addr, set) clrsetbits64((void *)((uintptr_t)addr), 0, set)
#define clrbits8p(addr, clear) clrsetbits8((void *)((uintptr_t)addr), clear, 0)
#define clrbits16p(addr, clear) clrsetbits16((void *)((uintptr_t)addr), clear, 0)
#define clrbits32p(addr, clear) clrsetbits32((void *)((uintptr_t)addr), clear, 0)
#define clrbits64p(addr, clear) clrsetbits64((void *)((uintptr_t)addr), clear, 0)
/*
* Reads a transfer buffer from 32-bit FIFO registers. fifo_stride is the
* distance in bytes between registers (e.g. pass 4 for a normal array of 32-bit
@ -222,44 +189,4 @@ static inline void buffer_to_fifo32(const void *buffer, size_t size, void *fifo,
#define READ32_BITFIELD(addr, name) \
EXTRACT_BITFIELD(read32(addr), name)
static __always_inline uint8_t read8p(const uintptr_t addr)
{
return read8((void *)addr);
}
static __always_inline uint16_t read16p(const uintptr_t addr)
{
return read16((void *)addr);
}
static __always_inline uint32_t read32p(const uintptr_t addr)
{
return read32((void *)addr);
}
static __always_inline uint64_t read64p(const uintptr_t addr)
{
return read64((void *)addr);
}
static __always_inline void write8p(const uintptr_t addr, const uint8_t value)
{
write8((void *)addr, value);
}
static __always_inline void write16p(const uintptr_t addr, const uint16_t value)
{
write16((void *)addr, value);
}
static __always_inline void write32p(const uintptr_t addr, const uint32_t value)
{
write32((void *)addr, value);
}
static __always_inline void write64p(const uintptr_t addr, const uint64_t value)
{
write64((void *)addr, value);
}
#endif /* __DEVICE_MMIO_H__ */

View file

@ -8,173 +8,20 @@
#include <string.h>
#include <swab.h>
#if defined(__LITTLE_ENDIAN)
#define cpu_to_le64(x) ((uint64_t)(x))
#define le64_to_cpu(x) ((uint64_t)(x))
#define cpu_to_le32(x) ((uint32_t)(x))
#define le32_to_cpu(x) ((uint32_t)(x))
#define cpu_to_le16(x) ((uint16_t)(x))
#define le16_to_cpu(x) ((uint16_t)(x))
#define cpu_to_be64(x) swab64(x)
#define be64_to_cpu(x) swab64(x)
#define cpu_to_be32(x) swab32(x)
#define be32_to_cpu(x) swab32(x)
#define cpu_to_be16(x) swab16(x)
#define be16_to_cpu(x) swab16(x)
#elif defined(__BIG_ENDIAN)
#define cpu_to_le64(x) swab64(x)
#define le64_to_cpu(x) swab64(x)
#define cpu_to_le32(x) swab32(x)
#define le32_to_cpu(x) swab32(x)
#define cpu_to_le16(x) swab16(x)
#define le16_to_cpu(x) swab16(x)
#define cpu_to_be64(x) ((uint64_t)(x))
#define be64_to_cpu(x) ((uint64_t)(x))
#define cpu_to_be32(x) ((uint32_t)(x))
#define be32_to_cpu(x) ((uint32_t)(x))
#define cpu_to_be16(x) ((uint16_t)(x))
#define be16_to_cpu(x) ((uint16_t)(x))
#else
#error "<arch/byteorder.h> must #define __LITTLE_ENDIAN or __BIG_ENDIAN"
#endif
/* This include depends on previous ones, do not reorder. */
#include <commonlib/bsd/_endian.h>
#define ntohll(x) be64_to_cpu(x)
#define htonll(x) cpu_to_be64(x)
#define ntohl(x) be32_to_cpu(x)
#define htonl(x) cpu_to_be32(x)
#define __clrsetbits(endian, bits, addr, clear, set) \
write##bits(addr, cpu_to_##endian##bits((endian##bits##_to_cpu( \
read##bits(addr)) & ~((uint##bits##_t)(clear))) | (set)))
#define clrbits_le64(addr, clear) __clrsetbits(le, 64, addr, clear, 0)
#define clrbits_be64(addr, clear) __clrsetbits(be, 64, addr, clear, 0)
#define clrbits_le32(addr, clear) __clrsetbits(le, 32, addr, clear, 0)
#define clrbits_be32(addr, clear) __clrsetbits(be, 32, addr, clear, 0)
#define clrbits_le16(addr, clear) __clrsetbits(le, 16, addr, clear, 0)
#define clrbits_be16(addr, clear) __clrsetbits(be, 16, addr, clear, 0)
#define setbits_le64(addr, set) __clrsetbits(le, 64, addr, 0, set)
#define setbits_be64(addr, set) __clrsetbits(be, 64, addr, 0, set)
#define setbits_le32(addr, set) __clrsetbits(le, 32, addr, 0, set)
#define setbits_be32(addr, set) __clrsetbits(be, 32, addr, 0, set)
#define setbits_le16(addr, set) __clrsetbits(le, 16, addr, 0, set)
#define setbits_be16(addr, set) __clrsetbits(be, 16, addr, 0, set)
#define clrsetbits_le64(addr, clear, set) __clrsetbits(le, 64, addr, clear, set)
#define clrsetbits_be64(addr, clear, set) __clrsetbits(be, 64, addr, clear, set)
#define clrsetbits_le32(addr, clear, set) __clrsetbits(le, 32, addr, clear, set)
#define clrsetbits_be32(addr, clear, set) __clrsetbits(be, 32, addr, clear, set)
#define clrsetbits_le16(addr, clear, set) __clrsetbits(le, 16, addr, clear, set)
#define clrsetbits_be16(addr, clear, set) __clrsetbits(be, 16, addr, clear, set)
/*
* be16dec/be32dec/be64dec/le16dec/le32dec/le64dec family of functions.
* RISC-V doesn't support misaligned access so decode it byte by byte.
*/
#define DEFINE_ENDIAN_DEC(endian, width) \
static inline uint##width##_t endian##width##dec(const void *p) \
{ \
if (ENV_RISCV) { \
uint##width##_t val; \
memcpy(&val, p, sizeof(val)); \
return endian##width##_to_cpu(val); \
} else { \
return endian##width##_to_cpu(*(uint##width##_t *)p); \
} \
}
DEFINE_ENDIAN_DEC(be, 16)
DEFINE_ENDIAN_DEC(be, 32)
DEFINE_ENDIAN_DEC(be, 64)
DEFINE_ENDIAN_DEC(le, 16)
DEFINE_ENDIAN_DEC(le, 32)
DEFINE_ENDIAN_DEC(le, 64)
/*
* be16enc/be32enc/be64enc/le16enc/le32enc/le64enc family of functions.
* RISC-V doesn't support misaligned access so encode it byte by byte.
*/
#define DEFINE_ENDIAN_ENC(endian, width) \
static inline void endian##width##enc(void *p, uint##width##_t u) \
{ \
if (ENV_RISCV) { \
uint##width##_t val = cpu_to_##endian##width(u); \
memcpy(p, &val, sizeof(val)); \
} else { \
*(uint##width##_t *)p = cpu_to_##endian##width(u); \
} \
}
DEFINE_ENDIAN_ENC(be, 16)
DEFINE_ENDIAN_ENC(be, 32)
DEFINE_ENDIAN_ENC(be, 64)
DEFINE_ENDIAN_ENC(le, 16)
DEFINE_ENDIAN_ENC(le, 32)
DEFINE_ENDIAN_ENC(le, 64)
/*
* Portable (API) endian support that can be used in code that is shared
* with userspace (man 3 endian) tools.
*/
static inline uint16_t htobe16(uint16_t host_16bits)
{
return cpu_to_be16(host_16bits);
}
static inline uint16_t htole16(uint16_t host_16bits)
{
return cpu_to_le16(host_16bits);
}
static inline uint16_t be16toh(uint16_t big_endian_16bits)
{
return be16_to_cpu(big_endian_16bits);
}
static inline uint16_t le16toh(uint16_t little_endian_16bits)
{
return le16_to_cpu(little_endian_16bits);
}
static inline uint32_t htobe32(uint32_t host_32bits)
{
return cpu_to_be32(host_32bits);
}
static inline uint32_t htole32(uint32_t host_32bits)
{
return cpu_to_le32(host_32bits);
}
static inline uint32_t be32toh(uint32_t big_endian_32bits)
{
return be32_to_cpu(big_endian_32bits);
}
static inline uint32_t le32toh(uint32_t little_endian_32bits)
{
return le32_to_cpu(little_endian_32bits);
}
static inline uint64_t htobe64(uint64_t host_64bits)
{
return cpu_to_be64(host_64bits);
}
static inline uint64_t htole64(uint64_t host_64bits)
{
return cpu_to_le64(host_64bits);
}
static inline uint64_t be64toh(uint64_t big_endian_64bits)
{
return be64_to_cpu(big_endian_64bits);
}
static inline uint64_t le64toh(uint64_t little_endian_64bits)
{
return le64_to_cpu(little_endian_64bits);
}
#define be64_to_cpu(x) be64toh(x)
#define be32_to_cpu(x) be32toh(x)
#define be16_to_cpu(x) be16toh(x)
#define le64_to_cpu(x) le64toh(x)
#define le32_to_cpu(x) le32toh(x)
#define le16_to_cpu(x) le16toh(x)
#define cpu_to_be64(x) htobe64(x)
#define cpu_to_be32(x) htobe32(x)
#define cpu_to_be16(x) htobe16(x)
#define cpu_to_le64(x) htole64(x)
#define cpu_to_le32(x) htole32(x)
#define cpu_to_le16(x) htole16(x)
#endif