]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - include/unaligned.h
Update xfsprogs to latest kernel headers and functions
[thirdparty/xfsprogs-dev.git] / include / unaligned.h
1 #ifndef _UNALIGNED_H_
2 #define _UNALIGNED_H_
3
4 /*
5 * For the benefit of those who are trying to port Linux to another
6 * architecture, here are some C-language equivalents.
7 *
8 * This is based almost entirely upon Richard Henderson's
9 * asm-alpha/unaligned.h implementation. Some comments were
10 * taken from David Mosberger's asm-ia64/unaligned.h header.
11 */
12
13 /*
14 * The main single-value unaligned transfer routines.
15 */
16 #define get_unaligned(ptr) \
17 __get_unaligned((ptr), sizeof(*(ptr)))
18 #define put_unaligned(x,ptr) \
19 __put_unaligned((__u64)(x), (ptr), sizeof(*(ptr)))
20
21 /*
22 * This function doesn't actually exist. The idea is that when
23 * someone uses the macros below with an unsupported size (datatype),
24 * the linker will alert us to the problem via an unresolved reference
25 * error.
26 */
27 extern void bad_unaligned_access_length(void) __attribute__((noreturn));
28
29 struct __una_u64 { __u64 x __attribute__((packed)); };
30 struct __una_u32 { __u32 x __attribute__((packed)); };
31 struct __una_u16 { __u16 x __attribute__((packed)); };
32
33 /*
34 * Elemental unaligned loads
35 */
36
37 static inline __u64 __uldq(const __u64 *addr)
38 {
39 const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
40 return ptr->x;
41 }
42
43 static inline __u32 __uldl(const __u32 *addr)
44 {
45 const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
46 return ptr->x;
47 }
48
49 static inline __u16 __uldw(const __u16 *addr)
50 {
51 const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
52 return ptr->x;
53 }
54
55 /*
56 * Elemental unaligned stores
57 */
58
59 static inline void __ustq(__u64 val, __u64 *addr)
60 {
61 struct __una_u64 *ptr = (struct __una_u64 *) addr;
62 ptr->x = val;
63 }
64
65 static inline void __ustl(__u32 val, __u32 *addr)
66 {
67 struct __una_u32 *ptr = (struct __una_u32 *) addr;
68 ptr->x = val;
69 }
70
71 static inline void __ustw(__u16 val, __u16 *addr)
72 {
73 struct __una_u16 *ptr = (struct __una_u16 *) addr;
74 ptr->x = val;
75 }
76
77 #define __get_unaligned(ptr, size) ({ \
78 const void *__gu_p = ptr; \
79 __u64 val; \
80 switch (size) { \
81 case 1: \
82 val = *(const __u8 *)__gu_p; \
83 break; \
84 case 2: \
85 val = __uldw(__gu_p); \
86 break; \
87 case 4: \
88 val = __uldl(__gu_p); \
89 break; \
90 case 8: \
91 val = __uldq(__gu_p); \
92 break; \
93 default: \
94 bad_unaligned_access_length(); \
95 }; \
96 (__typeof__(*(ptr)))val; \
97 })
98
99 #define __put_unaligned(val, ptr, size) \
100 do { \
101 void *__gu_p = ptr; \
102 switch (size) { \
103 case 1: \
104 *(__u8 *)__gu_p = val; \
105 break; \
106 case 2: \
107 __ustw(val, __gu_p); \
108 break; \
109 case 4: \
110 __ustl(val, __gu_p); \
111 break; \
112 case 8: \
113 __ustq(val, __gu_p); \
114 break; \
115 default: \
116 bad_unaligned_access_length(); \
117 }; \
118 } while(0)
119
120 #endif /* _UNALIGNED_H */