include/endian.h: Add 'always aligned access' support
RISC-V doesn't support unaligned access, so check for that before decoding and encoding. It is not perfectly performant, but still much better then invoking the misaligned exception handler every time there is a misaligned access. We can't modify our whole codebase to always do aligned access, because it is neither feasible in long term nor is fair to add that performance penalty onto other architectures that do support unaligned access. So this is the next best thing. On architectures that do support unaligned access the compiler will just optimize the RISCV_ENV part out and should result in the exact same binary. tested: identical binary on QEMU-aarch64 and QEMU-q35. Change-Id: I4dfccfdc2b302dd30b7ce5a29520c86add13169d Signed-off-by: Maximilian Brune <maximilian.brune@9elements.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/86609 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
parent
dcd07b37d5
commit
c444d166f3
1 changed files with 24 additions and 4 deletions
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <arch/byteorder.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <swab.h>
|
||||
|
||||
#if defined(__LITTLE_ENDIAN)
|
||||
|
|
@ -67,12 +68,22 @@
|
|||
#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. */
|
||||
/*
|
||||
* 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) \
|
||||
{ \
|
||||
return endian##width##_to_cpu(*(uint##width##_t *)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)
|
||||
|
|
@ -80,12 +91,21 @@ DEFINE_ENDIAN_DEC(le, 16)
|
|||
DEFINE_ENDIAN_DEC(le, 32)
|
||||
DEFINE_ENDIAN_DEC(le, 64)
|
||||
|
||||
/* be16enc/be32enc/be64enc/le16enc/le32enc/le64enc family of functions. */
|
||||
/*
|
||||
* 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) \
|
||||
{ \
|
||||
*(uint##width##_t *)p = cpu_to_##endian##width(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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue