VirtualBox

source: vbox/trunk/src/recompiler/softmmu_header.h@ 13762

Last change on this file since 13762 was 11982, checked in by vboxsync, 16 years ago

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

  • Property svn:eol-style set to native
File size: 11.9 KB
Line 
1/*
2 * Software MMU support
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
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.
10 *
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.
15 *
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
19 */
20
21/*
22 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Sun elects to use only
24 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
25 * a choice of LGPL license versions is made available with the language indicating
26 * that LGPLv2 or any later version may be used, or where a choice of which version
27 * of the LGPL is applied is otherwise unspecified.
28 */
29#if DATA_SIZE == 8
30#define SUFFIX q
31#define USUFFIX q
32#define DATA_TYPE uint64_t
33#elif DATA_SIZE == 4
34#define SUFFIX l
35#define USUFFIX l
36#define DATA_TYPE uint32_t
37#elif DATA_SIZE == 2
38#define SUFFIX w
39#define USUFFIX uw
40#define DATA_TYPE uint16_t
41#define DATA_STYPE int16_t
42#elif DATA_SIZE == 1
43#define SUFFIX b
44#define USUFFIX ub
45#define DATA_TYPE uint8_t
46#define DATA_STYPE int8_t
47#else
48#error unsupported data size
49#endif
50
51#if ACCESS_TYPE == 0
52
53#define CPU_MEM_INDEX 0
54#define MMUSUFFIX _mmu
55
56#elif ACCESS_TYPE == 1
57
58#define CPU_MEM_INDEX 1
59#define MMUSUFFIX _mmu
60
61#elif ACCESS_TYPE == 2
62
63#ifdef TARGET_I386
64#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
65#elif defined (TARGET_PPC)
66#define CPU_MEM_INDEX (msr_pr)
67#elif defined (TARGET_MIPS)
68#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
69#elif defined (TARGET_SPARC)
70#define CPU_MEM_INDEX ((env->psrs) == 0)
71#elif defined (TARGET_ARM)
72#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
73#elif defined (TARGET_SH4)
74#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
75#else
76#error unsupported CPU
77#endif
78#define MMUSUFFIX _mmu
79
80#elif ACCESS_TYPE == 3
81
82#ifdef TARGET_I386
83#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
84#elif defined (TARGET_PPC)
85#define CPU_MEM_INDEX (msr_pr)
86#elif defined (TARGET_MIPS)
87#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
88#elif defined (TARGET_SPARC)
89#define CPU_MEM_INDEX ((env->psrs) == 0)
90#elif defined (TARGET_ARM)
91#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
92#elif defined (TARGET_SH4)
93#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
94#else
95#error unsupported CPU
96#endif
97#define MMUSUFFIX _cmmu
98
99#else
100#error invalid ACCESS_TYPE
101#endif
102
103#if DATA_SIZE == 8
104#define RES_TYPE uint64_t
105#else
106#define RES_TYPE int
107#endif
108
109#if ACCESS_TYPE == 3
110#define ADDR_READ addr_code
111#else
112#define ADDR_READ addr_read
113#endif
114
115DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
116 int is_user);
117void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
118
119#if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
120 (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU) && (!defined(VBOX) || !defined(REM_PHYS_ADDR_IN_TLB))
121
122#define CPU_TLB_ENTRY_BITS 4
123
124static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
125{
126 int res;
127
128 asm volatile ("movl %1, %%edx\n"
129 "movl %1, %%eax\n"
130 "shrl %3, %%edx\n"
131 "andl %4, %%eax\n"
132 "andl %2, %%edx\n"
133 "leal %5(%%edx, %%ebp), %%edx\n"
134 "cmpl (%%edx), %%eax\n"
135 "movl %1, %%eax\n"
136 "je 1f\n"
137 "pushl %6\n"
138 "call %7\n"
139 "popl %%edx\n"
140 "movl %%eax, %0\n"
141 "jmp 2f\n"
142 "1:\n"
143 "addl 12(%%edx), %%eax\n"
144#if DATA_SIZE == 1
145 "movzbl (%%eax), %0\n"
146#elif DATA_SIZE == 2
147 "movzwl (%%eax), %0\n"
148#elif DATA_SIZE == 4
149 "movl (%%eax), %0\n"
150#else
151#error unsupported size
152#endif
153 "2:\n"
154 : "=r" (res)
155 : "r" (ptr),
156 "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
157 "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
158 "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
159 "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
160 "i" (CPU_MEM_INDEX),
161 "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
162 : "%eax", "%ecx", "%edx", "memory", "cc");
163 return res;
164}
165
166#if DATA_SIZE <= 2
167static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
168{
169 int res;
170
171 asm volatile ("movl %1, %%edx\n"
172 "movl %1, %%eax\n"
173 "shrl %3, %%edx\n"
174 "andl %4, %%eax\n"
175 "andl %2, %%edx\n"
176 "leal %5(%%edx, %%ebp), %%edx\n"
177 "cmpl (%%edx), %%eax\n"
178 "movl %1, %%eax\n"
179 "je 1f\n"
180 "pushl %6\n"
181 "call %7\n"
182 "popl %%edx\n"
183#if DATA_SIZE == 1
184 "movsbl %%al, %0\n"
185#elif DATA_SIZE == 2
186 "movswl %%ax, %0\n"
187#else
188#error unsupported size
189#endif
190 "jmp 2f\n"
191 "1:\n"
192 "addl 12(%%edx), %%eax\n"
193#if DATA_SIZE == 1
194 "movsbl (%%eax), %0\n"
195#elif DATA_SIZE == 2
196 "movswl (%%eax), %0\n"
197#else
198#error unsupported size
199#endif
200 "2:\n"
201 : "=r" (res)
202 : "r" (ptr),
203 "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
204 "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
205 "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
206 "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
207 "i" (CPU_MEM_INDEX),
208 "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
209 : "%eax", "%ecx", "%edx", "memory", "cc");
210 return res;
211}
212#endif
213
214#ifdef VBOX
215/* generic store macro */
216
217static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
218{
219 int index;
220 target_ulong addr;
221 unsigned long physaddr;
222 int is_user;
223
224 addr = ptr;
225 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
226 is_user = CPU_MEM_INDEX;
227 if (__builtin_expect(env->tlb_table[is_user][index].addr_write !=
228 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
229 glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
230 } else {
231 physaddr = addr + env->tlb_table[is_user][index].addend;
232 glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
233 }
234}
235
236#else /* !VBOX */
237
238static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
239{
240 asm volatile ("movl %0, %%edx\n"
241 "movl %0, %%eax\n"
242 "shrl %3, %%edx\n"
243 "andl %4, %%eax\n"
244 "andl %2, %%edx\n"
245 "leal %5(%%edx, %%ebp), %%edx\n"
246 "cmpl (%%edx), %%eax\n"
247 "movl %0, %%eax\n"
248 "je 1f\n"
249#if DATA_SIZE == 1
250 "movzbl %b1, %%edx\n"
251#elif DATA_SIZE == 2
252 "movzwl %w1, %%edx\n"
253#elif DATA_SIZE == 4
254 "movl %1, %%edx\n"
255#else
256#error unsupported size
257#endif
258 "pushl %6\n"
259 "call %7\n"
260 "popl %%eax\n"
261 "jmp 2f\n"
262 "1:\n"
263 "addl 8(%%edx), %%eax\n"
264#if DATA_SIZE == 1
265 "movb %b1, (%%eax)\n"
266#elif DATA_SIZE == 2
267 "movw %w1, (%%eax)\n"
268#elif DATA_SIZE == 4
269 "movl %1, (%%eax)\n"
270#else
271#error unsupported size
272#endif
273 "2:\n"
274 :
275 : "r" (ptr),
276/* NOTE: 'q' would be needed as constraint, but we could not use it
277 with T1 ! */
278 "r" (v),
279 "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
280 "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
281 "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
282 "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
283 "i" (CPU_MEM_INDEX),
284 "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
285 : "%eax", "%ecx", "%edx", "memory", "cc");
286}
287#endif /* !VBOX */
288
289#else
290
291/* generic load/store macros */
292
293static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
294{
295 int index;
296 RES_TYPE res;
297 target_ulong addr;
298 unsigned long physaddr;
299 int is_user;
300
301 addr = ptr;
302 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
303 is_user = CPU_MEM_INDEX;
304 if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
305 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
306 res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
307 } else {
308 physaddr = addr + env->tlb_table[is_user][index].addend;
309 res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
310 }
311 return res;
312}
313
314#if DATA_SIZE <= 2
315static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
316{
317 int res, index;
318 target_ulong addr;
319 unsigned long physaddr;
320 int is_user;
321
322 addr = ptr;
323 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
324 is_user = CPU_MEM_INDEX;
325 if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
326 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
327 res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
328 } else {
329 physaddr = addr + env->tlb_table[is_user][index].addend;
330 res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
331 }
332 return res;
333}
334#endif
335
336#if ACCESS_TYPE != 3
337
338/* generic store macro */
339
340static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
341{
342 int index;
343 target_ulong addr;
344 unsigned long physaddr;
345 int is_user;
346
347 addr = ptr;
348 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
349 is_user = CPU_MEM_INDEX;
350 if (__builtin_expect(env->tlb_table[is_user][index].addr_write !=
351 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
352 glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
353 } else {
354 physaddr = addr + env->tlb_table[is_user][index].addend;
355 glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
356 }
357}
358
359#endif /* ACCESS_TYPE != 3 */
360
361#endif /* !asm */
362
363#if ACCESS_TYPE != 3
364
365#if DATA_SIZE == 8
366static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
367{
368 union {
369 float64 d;
370 uint64_t i;
371 } u;
372 u.i = glue(ldq, MEMSUFFIX)(ptr);
373 return u.d;
374}
375
376static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
377{
378 union {
379 float64 d;
380 uint64_t i;
381 } u;
382 u.d = v;
383 glue(stq, MEMSUFFIX)(ptr, u.i);
384}
385#endif /* DATA_SIZE == 8 */
386
387#if DATA_SIZE == 4
388static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
389{
390 union {
391 float32 f;
392 uint32_t i;
393 } u;
394 u.i = glue(ldl, MEMSUFFIX)(ptr);
395 return u.f;
396}
397
398static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
399{
400 union {
401 float32 f;
402 uint32_t i;
403 } u;
404 u.f = v;
405 glue(stl, MEMSUFFIX)(ptr, u.i);
406}
407#endif /* DATA_SIZE == 4 */
408
409#endif /* ACCESS_TYPE != 3 */
410
411#undef RES_TYPE
412#undef DATA_TYPE
413#undef DATA_STYPE
414#undef SUFFIX
415#undef USUFFIX
416#undef DATA_SIZE
417#undef CPU_MEM_INDEX
418#undef MMUSUFFIX
419#undef ADDR_READ
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use