^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef __ASM_SH_UNALIGNED_SH4A_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define __ASM_SH_UNALIGNED_SH4A_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * SH-4A has support for unaligned 32-bit loads, and 32-bit loads only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Support for 64-bit accesses are done through shifting and masking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * relative to the endianness. Unaligned stores are not supported by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * instruction encoding, so these continue to use the packed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * The same note as with the movli.l/movco.l pair applies here, as long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * as the load is guaranteed to be inlined, nothing else will hook in to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * r0 and we get the return value for free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * NOTE: Due to the fact we require r0 encoding, care should be taken to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * avoid mixing these heavily with other r0 consumers, such as the atomic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * ops. Failure to adhere to this can result in the compiler running out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * of spill registers and blowing up when building at low optimization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * levels. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34777.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/unaligned/packed_struct.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static inline u16 sh4a_get_unaligned_cpu16(const u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #ifdef __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return p[0] | p[1] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return p[0] << 8 | p[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static __always_inline u32 sh4a_get_unaligned_cpu32(const u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long unaligned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) __asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) "movua.l @%1, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) : "=z" (unaligned)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) : "r" (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return unaligned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Even though movua.l supports auto-increment on the read side, it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * only store to r0 due to instruction encoding constraints, so just let
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * the compiler sort it out on its own.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static inline u64 sh4a_get_unaligned_cpu64(const u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #ifdef __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return (u64)sh4a_get_unaligned_cpu32(p + 4) << 32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) sh4a_get_unaligned_cpu32(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return (u64)sh4a_get_unaligned_cpu32(p) << 32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) sh4a_get_unaligned_cpu32(p + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static inline u16 get_unaligned_le16(const void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return le16_to_cpu(sh4a_get_unaligned_cpu16(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static inline u32 get_unaligned_le32(const void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return le32_to_cpu(sh4a_get_unaligned_cpu32(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static inline u64 get_unaligned_le64(const void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return le64_to_cpu(sh4a_get_unaligned_cpu64(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static inline u16 get_unaligned_be16(const void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return be16_to_cpu(sh4a_get_unaligned_cpu16(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static inline u32 get_unaligned_be32(const void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return be32_to_cpu(sh4a_get_unaligned_cpu32(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static inline u64 get_unaligned_be64(const void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return be64_to_cpu(sh4a_get_unaligned_cpu64(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static inline void nonnative_put_le16(u16 val, u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *p++ = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *p++ = val >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static inline void nonnative_put_le32(u32 val, u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) nonnative_put_le16(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) nonnative_put_le16(val >> 16, p + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static inline void nonnative_put_le64(u64 val, u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) nonnative_put_le32(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) nonnative_put_le32(val >> 32, p + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static inline void nonnative_put_be16(u16 val, u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *p++ = val >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *p++ = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static inline void nonnative_put_be32(u32 val, u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) nonnative_put_be16(val >> 16, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) nonnative_put_be16(val, p + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static inline void nonnative_put_be64(u64 val, u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) nonnative_put_be32(val >> 32, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) nonnative_put_be32(val, p + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static inline void put_unaligned_le16(u16 val, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #ifdef __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) __put_unaligned_cpu16(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) nonnative_put_le16(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static inline void put_unaligned_le32(u32 val, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #ifdef __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) __put_unaligned_cpu32(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) nonnative_put_le32(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static inline void put_unaligned_le64(u64 val, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #ifdef __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) __put_unaligned_cpu64(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) nonnative_put_le64(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static inline void put_unaligned_be16(u16 val, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) __put_unaligned_cpu16(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) nonnative_put_be16(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static inline void put_unaligned_be32(u32 val, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) __put_unaligned_cpu32(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) nonnative_put_be32(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static inline void put_unaligned_be64(u64 val, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) __put_unaligned_cpu64(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) nonnative_put_be64(val, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * While it's a bit non-obvious, even though the generic le/be wrappers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * use the __get/put_xxx prefixing, they actually wrap in to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * non-prefixed get/put_xxx variants as provided above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #include <linux/unaligned/generic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #ifdef __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) # define get_unaligned __get_unaligned_le
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) # define put_unaligned __put_unaligned_le
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) # define get_unaligned __get_unaligned_be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) # define put_unaligned __put_unaligned_be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #endif /* __ASM_SH_UNALIGNED_SH4A_H */