1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __ASM_GENERIC_UNALIGNED_H 3 #define __ASM_GENERIC_UNALIGNED_H 4 5 /* 6 * This is the most generic implementation of unaligned accesses 7 * and should work almost anywhere. 8 */ 9 #include <linux/unaligned/packed_struct.h> 10 #include <asm/byteorder.h> 11 12 #define __get_unaligned_t(type, ptr) ({ \ 13 const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ 14 __pptr->x; \ 15 }) 16 17 #define __put_unaligned_t(type, val, ptr) do { \ 18 struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ 19 __pptr->x = (val); \ 20 } while (0) 21 22 #define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr)) 23 #define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr)) 24 25 static inline u16 get_unaligned_le16(const void *p) 26 { 27 return le16_to_cpu(__get_unaligned_t(__le16, p)); 28 } 29 30 static inline u32 get_unaligned_le32(const void *p) 31 { 32 return le32_to_cpu(__get_unaligned_t(__le32, p)); 33 } 34 35 static inline u64 get_unaligned_le64(const void *p) 36 { 37 return le64_to_cpu(__get_unaligned_t(__le64, p)); 38 } 39 40 static inline void put_unaligned_le16(u16 val, void *p) 41 { 42 __put_unaligned_t(__le16, cpu_to_le16(val), p); 43 } 44 45 static inline void put_unaligned_le32(u32 val, void *p) 46 { 47 __put_unaligned_t(__le32, cpu_to_le32(val), p); 48 } 49 50 static inline void put_unaligned_le64(u64 val, void *p) 51 { 52 __put_unaligned_t(__le64, cpu_to_le64(val), p); 53 } 54 55 static inline u16 get_unaligned_be16(const void *p) 56 { 57 return be16_to_cpu(__get_unaligned_t(__be16, p)); 58 } 59 60 static inline u32 get_unaligned_be32(const void *p) 61 { 62 return be32_to_cpu(__get_unaligned_t(__be32, p)); 63 } 64 65 static inline u64 get_unaligned_be64(const void *p) 66 { 67 return be64_to_cpu(__get_unaligned_t(__be64, p)); 68 } 69 70 static inline void put_unaligned_be16(u16 val, void *p) 71 { 72 __put_unaligned_t(__be16, cpu_to_be16(val), p); 73 } 74 75 static inline void put_unaligned_be32(u32 val, void *p) 76 { 77 __put_unaligned_t(__be32, cpu_to_be32(val), p); 78 } 79 80 static inline void put_unaligned_be64(u64 val, void *p) 81 { 82 __put_unaligned_t(__be64, cpu_to_be64(val), p); 83 } 84 85 static inline u32 __get_unaligned_be24(const u8 *p) 86 { 87 return p[0] << 16 | p[1] << 8 | p[2]; 88 } 89 90 static inline u32 get_unaligned_be24(const void *p) 91 { 92 return __get_unaligned_be24(p); 93 } 94 95 static inline u32 __get_unaligned_le24(const u8 *p) 96 { 97 return p[0] | p[1] << 8 | p[2] << 16; 98 } 99 100 static inline u32 get_unaligned_le24(const void *p) 101 { 102 return __get_unaligned_le24(p); 103 } 104 105 static inline void __put_unaligned_be24(const u32 val, u8 *p) 106 { 107 *p++ = (val >> 16) & 0xff; 108 *p++ = (val >> 8) & 0xff; 109 *p++ = val & 0xff; 110 } 111 112 static inline void put_unaligned_be24(const u32 val, void *p) 113 { 114 __put_unaligned_be24(val, p); 115 } 116 117 static inline void __put_unaligned_le24(const u32 val, u8 *p) 118 { 119 *p++ = val & 0xff; 120 *p++ = (val >> 8) & 0xff; 121 *p++ = (val >> 16) & 0xff; 122 } 123 124 static inline void put_unaligned_le24(const u32 val, void *p) 125 { 126 __put_unaligned_le24(val, p); 127 } 128 129 static inline void __put_unaligned_be48(const u64 val, u8 *p) 130 { 131 *p++ = (val >> 40) & 0xff; 132 *p++ = (val >> 32) & 0xff; 133 *p++ = (val >> 24) & 0xff; 134 *p++ = (val >> 16) & 0xff; 135 *p++ = (val >> 8) & 0xff; 136 *p++ = val & 0xff; 137 } 138 139 static inline void put_unaligned_be48(const u64 val, void *p) 140 { 141 __put_unaligned_be48(val, p); 142 } 143 144 static inline u64 __get_unaligned_be48(const u8 *p) 145 { 146 return (u64)p[0] << 40 | (u64)p[1] << 32 | (u64)p[2] << 24 | 147 p[3] << 16 | p[4] << 8 | p[5]; 148 } 149 150 static inline u64 get_unaligned_be48(const void *p) 151 { 152 return __get_unaligned_be48(p); 153 } 154 155 #endif /* __ASM_GENERIC_UNALIGNED_H */ 156