]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* unaligned.h: unaligned access handler |
2 | * | |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells ([email protected]) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the License, or (at your option) any later version. | |
10 | */ | |
11 | ||
12 | #ifndef _ASM_UNALIGNED_H | |
13 | #define _ASM_UNALIGNED_H | |
14 | ||
1da177e4 LT |
15 | |
16 | /* | |
17 | * Unaligned accesses on uClinux can't be performed in a fault handler - the | |
18 | * CPU detects them as imprecise exceptions making this impossible. | |
19 | * | |
20 | * With the FR451, however, they are precise, and so we used to fix them up in | |
21 | * the memory access fault handler. However, instruction bundling make this | |
22 | * impractical. So, now we fall back to using memcpy. | |
23 | */ | |
24 | #ifdef CONFIG_MMU | |
25 | ||
26 | /* | |
27 | * The asm statement in the macros below is a way to get GCC to copy a | |
28 | * value from one variable to another without having any clue it's | |
29 | * actually doing so, so that it won't have any idea that the values | |
30 | * in the two variables are related. | |
31 | */ | |
32 | ||
33 | #define get_unaligned(ptr) ({ \ | |
34 | typeof((*(ptr))) __x; \ | |
35 | void *__ptrcopy; \ | |
36 | asm("" : "=r" (__ptrcopy) : "0" (ptr)); \ | |
37 | memcpy(&__x, __ptrcopy, sizeof(*(ptr))); \ | |
38 | __x; \ | |
39 | }) | |
40 | ||
41 | #define put_unaligned(val, ptr) ({ \ | |
42 | typeof((*(ptr))) __x = (val); \ | |
43 | void *__ptrcopy; \ | |
44 | asm("" : "=r" (__ptrcopy) : "0" (ptr)); \ | |
45 | memcpy(__ptrcopy, &__x, sizeof(*(ptr))); \ | |
46 | }) | |
47 | ||
48 | extern int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0); | |
49 | ||
50 | #else | |
51 | ||
52 | #define get_unaligned(ptr) \ | |
53 | ({ \ | |
54 | typeof(*(ptr)) x; \ | |
55 | const char *__p = (const char *) (ptr); \ | |
56 | \ | |
57 | switch (sizeof(x)) { \ | |
58 | case 1: \ | |
59 | x = *(ptr); \ | |
60 | break; \ | |
61 | case 2: \ | |
62 | { \ | |
63 | uint8_t a; \ | |
64 | asm(" ldub%I2 %M2,%0 \n" \ | |
65 | " ldub%I3.p %M3,%1 \n" \ | |
66 | " slli %0,#8,%0 \n" \ | |
67 | " or %0,%1,%0 \n" \ | |
68 | : "=&r"(x), "=&r"(a) \ | |
69 | : "m"(__p[0]), "m"(__p[1]) \ | |
70 | ); \ | |
71 | break; \ | |
72 | } \ | |
73 | \ | |
74 | case 4: \ | |
75 | { \ | |
76 | uint8_t a; \ | |
77 | asm(" ldub%I2 %M2,%0 \n" \ | |
78 | " ldub%I3.p %M3,%1 \n" \ | |
79 | " slli %0,#8,%0 \n" \ | |
80 | " or %0,%1,%0 \n" \ | |
81 | " ldub%I4.p %M4,%1 \n" \ | |
82 | " slli %0,#8,%0 \n" \ | |
83 | " or %0,%1,%0 \n" \ | |
84 | " ldub%I5.p %M5,%1 \n" \ | |
85 | " slli %0,#8,%0 \n" \ | |
86 | " or %0,%1,%0 \n" \ | |
87 | : "=&r"(x), "=&r"(a) \ | |
88 | : "m"(__p[0]), "m"(__p[1]), "m"(__p[2]), "m"(__p[3]) \ | |
89 | ); \ | |
90 | break; \ | |
91 | } \ | |
92 | \ | |
93 | case 8: \ | |
94 | { \ | |
95 | union { uint64_t x; u32 y[2]; } z; \ | |
96 | uint8_t a; \ | |
97 | asm(" ldub%I3 %M3,%0 \n" \ | |
98 | " ldub%I4.p %M4,%2 \n" \ | |
99 | " slli %0,#8,%0 \n" \ | |
100 | " or %0,%2,%0 \n" \ | |
101 | " ldub%I5.p %M5,%2 \n" \ | |
102 | " slli %0,#8,%0 \n" \ | |
103 | " or %0,%2,%0 \n" \ | |
104 | " ldub%I6.p %M6,%2 \n" \ | |
105 | " slli %0,#8,%0 \n" \ | |
106 | " or %0,%2,%0 \n" \ | |
107 | " ldub%I7 %M7,%1 \n" \ | |
108 | " ldub%I8.p %M8,%2 \n" \ | |
109 | " slli %1,#8,%1 \n" \ | |
110 | " or %1,%2,%1 \n" \ | |
111 | " ldub%I9.p %M9,%2 \n" \ | |
112 | " slli %1,#8,%1 \n" \ | |
113 | " or %1,%2,%1 \n" \ | |
114 | " ldub%I10.p %M10,%2 \n" \ | |
115 | " slli %1,#8,%1 \n" \ | |
116 | " or %1,%2,%1 \n" \ | |
117 | : "=&r"(z.y[0]), "=&r"(z.y[1]), "=&r"(a) \ | |
118 | : "m"(__p[0]), "m"(__p[1]), "m"(__p[2]), "m"(__p[3]), \ | |
119 | "m"(__p[4]), "m"(__p[5]), "m"(__p[6]), "m"(__p[7]) \ | |
120 | ); \ | |
121 | x = z.x; \ | |
122 | break; \ | |
123 | } \ | |
124 | \ | |
125 | default: \ | |
126 | x = 0; \ | |
127 | BUG(); \ | |
128 | break; \ | |
129 | } \ | |
130 | \ | |
131 | x; \ | |
132 | }) | |
133 | ||
134 | #define put_unaligned(val, ptr) \ | |
135 | do { \ | |
136 | char *__p = (char *) (ptr); \ | |
137 | int x; \ | |
138 | \ | |
139 | switch (sizeof(*ptr)) { \ | |
140 | case 2: \ | |
141 | { \ | |
142 | asm(" stb%I1.p %0,%M1 \n" \ | |
143 | " srli %0,#8,%0 \n" \ | |
144 | " stb%I2 %0,%M2 \n" \ | |
145 | : "=r"(x), "=m"(__p[1]), "=m"(__p[0]) \ | |
146 | : "0"(val) \ | |
147 | ); \ | |
148 | break; \ | |
149 | } \ | |
150 | \ | |
151 | case 4: \ | |
152 | { \ | |
153 | asm(" stb%I1.p %0,%M1 \n" \ | |
154 | " srli %0,#8,%0 \n" \ | |
155 | " stb%I2.p %0,%M2 \n" \ | |
156 | " srli %0,#8,%0 \n" \ | |
157 | " stb%I3.p %0,%M3 \n" \ | |
158 | " srli %0,#8,%0 \n" \ | |
159 | " stb%I4 %0,%M4 \n" \ | |
160 | : "=r"(x), "=m"(__p[3]), "=m"(__p[2]), "=m"(__p[1]), "=m"(__p[0]) \ | |
161 | : "0"(val) \ | |
162 | ); \ | |
163 | break; \ | |
164 | } \ | |
165 | \ | |
166 | case 8: \ | |
167 | { \ | |
168 | uint32_t __high, __low; \ | |
169 | __high = (uint64_t)val >> 32; \ | |
170 | __low = val & 0xffffffff; \ | |
171 | asm(" stb%I2.p %0,%M2 \n" \ | |
172 | " srli %0,#8,%0 \n" \ | |
173 | " stb%I3.p %0,%M3 \n" \ | |
174 | " srli %0,#8,%0 \n" \ | |
175 | " stb%I4.p %0,%M4 \n" \ | |
176 | " srli %0,#8,%0 \n" \ | |
177 | " stb%I5.p %0,%M5 \n" \ | |
178 | " srli %0,#8,%0 \n" \ | |
179 | " stb%I6.p %1,%M6 \n" \ | |
180 | " srli %1,#8,%1 \n" \ | |
181 | " stb%I7.p %1,%M7 \n" \ | |
182 | " srli %1,#8,%1 \n" \ | |
183 | " stb%I8.p %1,%M8 \n" \ | |
184 | " srli %1,#8,%1 \n" \ | |
185 | " stb%I9 %1,%M9 \n" \ | |
186 | : "=&r"(__low), "=&r"(__high), "=m"(__p[7]), "=m"(__p[6]), \ | |
187 | "=m"(__p[5]), "=m"(__p[4]), "=m"(__p[3]), "=m"(__p[2]), \ | |
188 | "=m"(__p[1]), "=m"(__p[0]) \ | |
189 | : "0"(__low), "1"(__high) \ | |
190 | ); \ | |
191 | break; \ | |
192 | } \ | |
193 | \ | |
194 | default: \ | |
195 | *(ptr) = (val); \ | |
196 | break; \ | |
197 | } \ | |
198 | } while(0) | |
199 | ||
200 | #endif | |
201 | ||
202 | #endif |