File: /usr/src/linux/include/asm-arm/unaligned.h

1     #ifndef __ASM_ARM_UNALIGNED_H
2     #define __ASM_ARM_UNALIGNED_H
3     
4     #include <asm/types.h>
5     
6     extern int __bug_unaligned_x(void *ptr);
7     
8     /*
9      * What is the most efficient way of loading/storing an unaligned value?
10      *
11      * That is the subject of this file.  Efficiency here is defined as
12      * minimum code size with minimum register usage for the common cases.
13      * It is currently not believed that long longs are common, so we
14      * trade efficiency for the chars, shorts and longs against the long
15      * longs.
16      *
17      * Current stats with gcc 2.7.2.2 for these functions:
18      *
19      *	ptrsize	get:	code	regs	put:	code	regs
20      *	1		1	1		1	2
21      *	2		3	2		3	2
22      *	4		7	3		7	3
23      *	8		20	6		16	6
24      *
25      * gcc 2.95.1 seems to code differently:
26      *
27      *	ptrsize	get:	code	regs	put:	code	regs
28      *	1		1	1		1	2
29      *	2		3	2		3	2
30      *	4		7	4		7	4
31      *	8		19	8		15	6
32      *
33      * which may or may not be more efficient (depending upon whether
34      * you can afford the extra registers).  Hopefully the gcc 2.95
35      * is inteligent enough to decide if it is better to use the
36      * extra register, but evidence so far seems to suggest otherwise.
37      *
38      * Unfortunately, gcc is not able to optimise the high word
39      * out of long long >> 32, or the low word from long long << 32
40      */
41     
42     #define __get_unaligned_2(__p)					\
43     	(__p[0] | __p[1] << 8)
44     
45     #define __get_unaligned_4(__p)					\
46     	(__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
47     
48     #define get_unaligned(ptr)					\
49     	({							\
50     		__typeof__(*(ptr)) __v;				\
51     		__u8 *__p = (__u8 *)(ptr);			\
52     		switch (sizeof(*(ptr))) {			\
53     		case 1:	__v = *(ptr);			break;	\
54     		case 2: __v = __get_unaligned_2(__p);	break;	\
55     		case 4: __v = __get_unaligned_4(__p);	break;	\
56     		case 8: {					\
57     				unsigned int __v1, __v2;	\
58     				__v2 = __get_unaligned_4((__p+4)); \
59     				__v1 = __get_unaligned_4(__p);	\
60     				__v = ((unsigned long long)__v2 << 32 | __v1);	\
61     			}					\
62     			break;					\
63     		default: __v = __bug_unaligned_x(__p);	break;	\
64     		}						\
65     		__v;						\
66     	})
67     
68     
69     static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
70     {
71     	*__p++ = __v;
72     	*__p++ = __v >> 8;
73     }
74     
75     static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
76     {
77     	__put_unaligned_2(__v >> 16, __p + 2);
78     	__put_unaligned_2(__v, __p);
79     }
80     
81     static inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p)
82     {
83     	/*
84     	 * tradeoff: 8 bytes of stack for all unaligned puts (2
85     	 * instructions), or an extra register in the long long
86     	 * case - go for the extra register.
87     	 */
88     	__put_unaligned_4(__v >> 32, __p+4);
89     	__put_unaligned_4(__v, __p);
90     }
91     
92     /*
93      * Try to store an unaligned value as efficiently as possible.
94      */
95     #define put_unaligned(val,ptr)					\
96     	({							\
97     		switch (sizeof(*(ptr))) {			\
98     		case 1:						\
99     			*(ptr) = (val);				\
100     			break;					\
101     		case 2: __put_unaligned_2((val),(__u8 *)(ptr));	\
102     			break;					\
103     		case 4:	__put_unaligned_4((val),(__u8 *)(ptr));	\
104     			break;					\
105     		case 8:	__put_unaligned_8((val),(__u8 *)(ptr)); \
106     			break;					\
107     		default: __bug_unaligned_x(ptr);		\
108     			break;					\
109     		}						\
110     		(void) 0;					\
111     	})
112     
113     
114     #endif
115