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 by Ralf Baechle
7 * Copyright (C) 1999, 2000 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 double unaligned.
18 * This could have been implemented in plain C like IA64 but egcs 1.0.3a
19 * inflates this to 23 instructions ...
21 static inline unsigned long long __ldq_u(const unsigned long long * __addr)
23 unsigned long long __res;
25 __asm__("ulw\t%0, %1\n\t"
34 * Load word unaligned.
36 static inline unsigned long __ldl_u(const unsigned int * __addr)
48 * Load halfword unaligned.
50 static inline unsigned long __ldw_u(const unsigned short * __addr)
62 * Store doubleword ununaligned.
64 static inline void __stq_u(unsigned long __val, unsigned long long * __addr)
66 __asm__("usw\t%1, %0\n\t"
73 * Store long ununaligned.
75 static inline void __stl_u(unsigned long __val, unsigned int * __addr)
83 * Store word ununaligned.
85 static inline void __stw_u(unsigned long __val, unsigned short * __addr)
93 * get_unaligned - get value from possibly mis-aligned location
94 * @ptr: pointer to value
96 * This macro should be used for accessing values larger in size than
97 * single bytes at locations that are expected to be improperly aligned,
98 * e.g. retrieving a u16 value from a location not u16-aligned.
100 * Note that unaligned accesses can be very expensive on some architectures.
102 #define get_unaligned(ptr) \
104 __typeof__(*(ptr)) __val; \
106 switch (sizeof(*(ptr))) { \
108 __val = *(const unsigned char *)ptr; \
111 __val = __ldw_u((const unsigned short *)ptr); \
114 __val = __ldl_u((const unsigned int *)ptr); \
117 __val = __ldq_u((const unsigned long long *)ptr); \
120 __get_unaligned_bad_length(); \
128 * put_unaligned - put value to a possibly mis-aligned location
129 * @val: value to place
130 * @ptr: pointer to location
132 * This macro should be used for placing values larger in size than
133 * single bytes at locations that are expected to be improperly aligned,
134 * e.g. writing a u16 value to a location not u16-aligned.
136 * Note that unaligned accesses can be very expensive on some architectures.
138 #define put_unaligned(val,ptr) \
140 switch (sizeof(*(ptr))) { \
142 *(unsigned char *)(ptr) = (val); \
145 __stw_u(val, (unsigned short *)(ptr)); \
148 __stl_u(val, (unsigned int *)(ptr)); \
151 __stq_u(val, (unsigned long long *)(ptr)); \
154 __put_unaligned_bad_length(); \
159 #endif /* _ASM_UNALIGNED_H */