2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1996, 1999, 2000, 2001 by Ralf Baechle
7 * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc.
9 #ifndef _ASM_UNALIGNED_H
10 #define _ASM_UNALIGNED_H
12 extern void __get_unaligned_bad_length(void);
13 extern void __put_unaligned_bad_length(void);
16 * Load quad unaligned.
18 static inline unsigned long __ldq_u(const unsigned long * __addr)
30 * Load long unaligned.
32 static inline unsigned long __ldl_u(const unsigned int * __addr)
44 * Load word unaligned.
46 static inline unsigned long __ldw_u(const unsigned short * __addr)
58 * Store quad ununaligned.
60 static inline void __stq_u(unsigned long __val, unsigned long * __addr)
68 * Store long ununaligned.
70 static inline void __stl_u(unsigned long __val, unsigned int * __addr)
78 * Store word ununaligned.
80 static inline void __stw_u(unsigned long __val, unsigned short * __addr)
88 * get_unaligned - get value from possibly mis-aligned location
89 * @ptr: pointer to value
91 * This macro should be used for accessing values larger in size than
92 * single bytes at locations that are expected to be improperly aligned,
93 * e.g. retrieving a u16 value from a location not u16-aligned.
95 * Note that unaligned accesses can be very expensive on some architectures.
97 #define get_unaligned(ptr) \
99 __typeof__(*(ptr)) __val; \
101 switch (sizeof(*(ptr))) { \
103 __val = *(const unsigned char *)(ptr); \
106 __val = __ldw_u((const unsigned short *)(ptr)); \
109 __val = __ldl_u((const unsigned int *)(ptr)); \
112 __val = __ldq_u((const unsigned long *)(ptr)); \
115 __get_unaligned_bad_length(); \
123 * put_unaligned - put value to a possibly mis-aligned location
124 * @val: value to place
125 * @ptr: pointer to location
127 * This macro should be used for placing values larger in size than
128 * single bytes at locations that are expected to be improperly aligned,
129 * e.g. writing a u16 value to a location not u16-aligned.
131 * Note that unaligned accesses can be very expensive on some architectures.
133 #define put_unaligned(val,ptr) \
135 switch (sizeof(*(ptr))) { \
137 *(unsigned char *)(ptr) = (val); \
140 __stw_u((val), (unsigned short *)(ptr)); \
143 __stl_u((val), (unsigned int *)(ptr)); \
146 __stq_u((val), (unsigned long long *)(ptr)); \
149 __put_unaligned_bad_length(); \
154 #endif /* _ASM_UNALIGNED_H */