Fix typo in ppc icache flush.
[qemu/mini2440.git] / softmmu_header.h
blobe79592f83031e2d591eb03b6291461d2bb7b8caa
1 /*
2 * Software MMU support
3 *
4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #if DATA_SIZE == 8
21 #define SUFFIX q
22 #define USUFFIX q
23 #define DATA_TYPE uint64_t
24 #elif DATA_SIZE == 4
25 #define SUFFIX l
26 #define USUFFIX l
27 #define DATA_TYPE uint32_t
28 #elif DATA_SIZE == 2
29 #define SUFFIX w
30 #define USUFFIX uw
31 #define DATA_TYPE uint16_t
32 #define DATA_STYPE int16_t
33 #elif DATA_SIZE == 1
34 #define SUFFIX b
35 #define USUFFIX ub
36 #define DATA_TYPE uint8_t
37 #define DATA_STYPE int8_t
38 #else
39 #error unsupported data size
40 #endif
42 #if ACCESS_TYPE == 0
44 #define CPU_MEM_INDEX 0
45 #define MMUSUFFIX _mmu
47 #elif ACCESS_TYPE == 1
49 #define CPU_MEM_INDEX 1
50 #define MMUSUFFIX _mmu
52 #elif ACCESS_TYPE == 2
54 #ifdef TARGET_I386
55 #define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
56 #elif defined (TARGET_PPC)
57 #define CPU_MEM_INDEX (msr_pr)
58 #elif defined (TARGET_MIPS)
59 #define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
60 #elif defined (TARGET_SPARC)
61 #define CPU_MEM_INDEX ((env->psrs) == 0)
62 #elif defined (TARGET_ARM)
63 #define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
64 #else
65 #error unsupported CPU
66 #endif
67 #define MMUSUFFIX _mmu
69 #elif ACCESS_TYPE == 3
71 #ifdef TARGET_I386
72 #define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
73 #elif defined (TARGET_PPC)
74 #define CPU_MEM_INDEX (msr_pr)
75 #elif defined (TARGET_MIPS)
76 #define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
77 #elif defined (TARGET_SPARC)
78 #define CPU_MEM_INDEX ((env->psrs) == 0)
79 #elif defined (TARGET_ARM)
80 #define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
81 #else
82 #error unsupported CPU
83 #endif
84 #define MMUSUFFIX _cmmu
86 #else
87 #error invalid ACCESS_TYPE
88 #endif
90 #if DATA_SIZE == 8
91 #define RES_TYPE uint64_t
92 #else
93 #define RES_TYPE int
94 #endif
96 #if ACCESS_TYPE == 3
97 #define ADDR_READ addr_code
98 #else
99 #define ADDR_READ addr_read
100 #endif
102 DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
103 int is_user);
104 void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
106 #if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
107 (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
109 #define CPU_TLB_ENTRY_BITS 4
111 static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
113 int res;
115 asm volatile ("movl %1, %%edx\n"
116 "movl %1, %%eax\n"
117 "shrl %3, %%edx\n"
118 "andl %4, %%eax\n"
119 "andl %2, %%edx\n"
120 "leal %5(%%edx, %%ebp), %%edx\n"
121 "cmpl (%%edx), %%eax\n"
122 "movl %1, %%eax\n"
123 "je 1f\n"
124 "pushl %6\n"
125 "call %7\n"
126 "popl %%edx\n"
127 "movl %%eax, %0\n"
128 "jmp 2f\n"
129 "1:\n"
130 "addl 12(%%edx), %%eax\n"
131 #if DATA_SIZE == 1
132 "movzbl (%%eax), %0\n"
133 #elif DATA_SIZE == 2
134 "movzwl (%%eax), %0\n"
135 #elif DATA_SIZE == 4
136 "movl (%%eax), %0\n"
137 #else
138 #error unsupported size
139 #endif
140 "2:\n"
141 : "=r" (res)
142 : "r" (ptr),
143 "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
144 "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
145 "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
146 "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
147 "i" (CPU_MEM_INDEX),
148 "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
149 : "%eax", "%ecx", "%edx", "memory", "cc");
150 return res;
153 #if DATA_SIZE <= 2
154 static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
156 int res;
158 asm volatile ("movl %1, %%edx\n"
159 "movl %1, %%eax\n"
160 "shrl %3, %%edx\n"
161 "andl %4, %%eax\n"
162 "andl %2, %%edx\n"
163 "leal %5(%%edx, %%ebp), %%edx\n"
164 "cmpl (%%edx), %%eax\n"
165 "movl %1, %%eax\n"
166 "je 1f\n"
167 "pushl %6\n"
168 "call %7\n"
169 "popl %%edx\n"
170 #if DATA_SIZE == 1
171 "movsbl %%al, %0\n"
172 #elif DATA_SIZE == 2
173 "movswl %%ax, %0\n"
174 #else
175 #error unsupported size
176 #endif
177 "jmp 2f\n"
178 "1:\n"
179 "addl 12(%%edx), %%eax\n"
180 #if DATA_SIZE == 1
181 "movsbl (%%eax), %0\n"
182 #elif DATA_SIZE == 2
183 "movswl (%%eax), %0\n"
184 #else
185 #error unsupported size
186 #endif
187 "2:\n"
188 : "=r" (res)
189 : "r" (ptr),
190 "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
191 "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
192 "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
193 "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
194 "i" (CPU_MEM_INDEX),
195 "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
196 : "%eax", "%ecx", "%edx", "memory", "cc");
197 return res;
199 #endif
201 static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
203 asm volatile ("movl %0, %%edx\n"
204 "movl %0, %%eax\n"
205 "shrl %3, %%edx\n"
206 "andl %4, %%eax\n"
207 "andl %2, %%edx\n"
208 "leal %5(%%edx, %%ebp), %%edx\n"
209 "cmpl (%%edx), %%eax\n"
210 "movl %0, %%eax\n"
211 "je 1f\n"
212 #if DATA_SIZE == 1
213 "movzbl %b1, %%edx\n"
214 #elif DATA_SIZE == 2
215 "movzwl %w1, %%edx\n"
216 #elif DATA_SIZE == 4
217 "movl %1, %%edx\n"
218 #else
219 #error unsupported size
220 #endif
221 "pushl %6\n"
222 "call %7\n"
223 "popl %%eax\n"
224 "jmp 2f\n"
225 "1:\n"
226 "addl 8(%%edx), %%eax\n"
227 #if DATA_SIZE == 1
228 "movb %b1, (%%eax)\n"
229 #elif DATA_SIZE == 2
230 "movw %w1, (%%eax)\n"
231 #elif DATA_SIZE == 4
232 "movl %1, (%%eax)\n"
233 #else
234 #error unsupported size
235 #endif
236 "2:\n"
238 : "r" (ptr),
239 /* NOTE: 'q' would be needed as constraint, but we could not use it
240 with T1 ! */
241 "r" (v),
242 "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
243 "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
244 "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
245 "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
246 "i" (CPU_MEM_INDEX),
247 "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
248 : "%eax", "%ecx", "%edx", "memory", "cc");
251 #else
253 /* generic load/store macros */
255 static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
257 int index;
258 RES_TYPE res;
259 target_ulong addr;
260 unsigned long physaddr;
261 int is_user;
263 addr = ptr;
264 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
265 is_user = CPU_MEM_INDEX;
266 if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
267 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
268 res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
269 } else {
270 physaddr = addr + env->tlb_table[is_user][index].addend;
271 res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
273 return res;
276 #if DATA_SIZE <= 2
277 static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
279 int res, index;
280 target_ulong addr;
281 unsigned long physaddr;
282 int is_user;
284 addr = ptr;
285 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
286 is_user = CPU_MEM_INDEX;
287 if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
288 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
289 res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
290 } else {
291 physaddr = addr + env->tlb_table[is_user][index].addend;
292 res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
294 return res;
296 #endif
298 #if ACCESS_TYPE != 3
300 /* generic store macro */
302 static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
304 int index;
305 target_ulong addr;
306 unsigned long physaddr;
307 int is_user;
309 addr = ptr;
310 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
311 is_user = CPU_MEM_INDEX;
312 if (__builtin_expect(env->tlb_table[is_user][index].addr_write !=
313 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
314 glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
315 } else {
316 physaddr = addr + env->tlb_table[is_user][index].addend;
317 glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
321 #endif /* ACCESS_TYPE != 3 */
323 #endif /* !asm */
325 #if ACCESS_TYPE != 3
327 #if DATA_SIZE == 8
328 static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
330 union {
331 float64 d;
332 uint64_t i;
333 } u;
334 u.i = glue(ldq, MEMSUFFIX)(ptr);
335 return u.d;
338 static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
340 union {
341 float64 d;
342 uint64_t i;
343 } u;
344 u.d = v;
345 glue(stq, MEMSUFFIX)(ptr, u.i);
347 #endif /* DATA_SIZE == 8 */
349 #if DATA_SIZE == 4
350 static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
352 union {
353 float32 f;
354 uint32_t i;
355 } u;
356 u.i = glue(ldl, MEMSUFFIX)(ptr);
357 return u.f;
360 static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
362 union {
363 float32 f;
364 uint32_t i;
365 } u;
366 u.f = v;
367 glue(stl, MEMSUFFIX)(ptr, u.i);
369 #endif /* DATA_SIZE == 4 */
371 #endif /* ACCESS_TYPE != 3 */
373 #undef RES_TYPE
374 #undef DATA_TYPE
375 #undef DATA_STYPE
376 #undef SUFFIX
377 #undef USUFFIX
378 #undef DATA_SIZE
379 #undef CPU_MEM_INDEX
380 #undef MMUSUFFIX
381 #undef ADDR_READ