VirtualBox

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

Last change on this file since 3261 was 2422, checked in by vboxsync, 18 years ago

Removed the old recompiler code.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette