VirtualBox

source: vbox/trunk/src/recompiler/new/exec-all.h@ 2009

Last change on this file since 2009 was 1590, checked in by vboxsync, 18 years ago

Quick hack to only use physical addresses so we can dispense with the unnecessary address translation. It's all enabled by the DEFS += REM_PHYS_ADDR_IN_TLB statement in the Makefile.kmk. (Not tested with PGM_DYNAMIC_RAM_ALLOC yet, will do that tomorrow.)

  • Property svn:eol-style set to native
File size: 19.9 KB
Line 
1/*
2 * internal execution defines for qemu
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/* allow to see translation results - the slowdown should be negligible, so we leave it */
22#ifndef VBOX
23#define DEBUG_DISAS
24#endif
25
26#ifdef VBOX
27# include <VBox/tm.h>
28# include <VBox/pgm.h> /* PGM_DYNAMIC_RAM_ALLOC */
29# ifndef LOG_GROUP
30# define LOG_GROUP LOG_GROUP_REM
31# endif
32# include <VBox/log.h>
33# include "REMInternal.h"
34# include <VBox/vm.h>
35#endif /* VBOX */
36
37#ifndef glue
38#define xglue(x, y) x ## y
39#define glue(x, y) xglue(x, y)
40#define stringify(s) tostring(s)
41#define tostring(s) #s
42#endif
43
44#if __GNUC__ < 3
45#define __builtin_expect(x, n) (x)
46#endif
47
48#ifdef __i386__
49#define REGPARM(n) __attribute((regparm(n)))
50#else
51#define REGPARM(n)
52#endif
53
54/* is_jmp field values */
55#define DISAS_NEXT 0 /* next instruction can be analyzed */
56#define DISAS_JUMP 1 /* only pc was modified dynamically */
57#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
58#define DISAS_TB_JUMP 3 /* only pc was modified statically */
59
60struct TranslationBlock;
61
62/* XXX: make safe guess about sizes */
63#define MAX_OP_PER_INSTR 32
64#define OPC_BUF_SIZE 512
65#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
66
67#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
68
69extern uint16_t gen_opc_buf[OPC_BUF_SIZE];
70extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
71extern long gen_labels[OPC_BUF_SIZE];
72extern int nb_gen_labels;
73extern target_ulong gen_opc_pc[OPC_BUF_SIZE];
74extern target_ulong gen_opc_npc[OPC_BUF_SIZE];
75extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
76extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
77extern target_ulong gen_opc_jump_pc[2];
78extern uint32_t gen_opc_hflags[OPC_BUF_SIZE];
79
80typedef void (GenOpFunc)(void);
81typedef void (GenOpFunc1)(long);
82typedef void (GenOpFunc2)(long, long);
83typedef void (GenOpFunc3)(long, long, long);
84
85#if defined(TARGET_I386)
86
87void optimize_flags_init(void);
88
89#endif
90
91extern FILE *logfile;
92extern int loglevel;
93
94int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
95int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
96void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
97int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
98 int max_code_size, int *gen_code_size_ptr);
99int cpu_restore_state(struct TranslationBlock *tb,
100 CPUState *env, unsigned long searched_pc,
101 void *puc);
102int cpu_gen_code_copy(CPUState *env, struct TranslationBlock *tb,
103 int max_code_size, int *gen_code_size_ptr);
104int cpu_restore_state_copy(struct TranslationBlock *tb,
105 CPUState *env, unsigned long searched_pc,
106 void *puc);
107void cpu_resume_from_signal(CPUState *env1, void *puc);
108void cpu_exec_init(CPUState *env);
109int page_unprotect(target_ulong address, unsigned long pc, void *puc);
110void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
111 int is_cpu_write_access);
112void tb_invalidate_page_range(target_ulong start, target_ulong end);
113void tlb_flush_page(CPUState *env, target_ulong addr);
114void tlb_flush(CPUState *env, int flush_global);
115int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
116 target_phys_addr_t paddr, int prot,
117 int is_user, int is_softmmu);
118static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
119 target_phys_addr_t paddr, int prot,
120 int is_user, int is_softmmu)
121{
122 if (prot & PAGE_READ)
123 prot |= PAGE_EXEC;
124 return tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
125}
126
127#define CODE_GEN_MAX_SIZE 65536
128#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
129
130#define CODE_GEN_PHYS_HASH_BITS 15
131#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
132
133/* maximum total translate dcode allocated */
134
135/* NOTE: the translated code area cannot be too big because on some
136 archs the range of "fast" function calls is limited. Here is a
137 summary of the ranges:
138
139 i386 : signed 32 bits
140 arm : signed 26 bits
141 ppc : signed 24 bits
142 sparc : signed 32 bits
143 alpha : signed 23 bits
144*/
145
146#if defined(__alpha__)
147#define CODE_GEN_BUFFER_SIZE (2 * 1024 * 1024)
148#elif defined(__ia64)
149#define CODE_GEN_BUFFER_SIZE (4 * 1024 * 1024) /* range of addl */
150#elif defined(__powerpc__)
151#define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024)
152#else
153#define CODE_GEN_BUFFER_SIZE (16 * 1024 * 1024)
154#endif
155
156//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
157
158/* estimated block size for TB allocation */
159/* XXX: use a per code average code fragment size and modulate it
160 according to the host CPU */
161#if defined(CONFIG_SOFTMMU)
162#define CODE_GEN_AVG_BLOCK_SIZE 128
163#else
164#define CODE_GEN_AVG_BLOCK_SIZE 64
165#endif
166
167#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
168
169#if defined(__powerpc__)
170#define USE_DIRECT_JUMP
171#endif
172#if defined(__i386__) && !defined(_WIN32)
173#define USE_DIRECT_JUMP
174#endif
175#ifdef VBOX /* bird: not safe in next step because of threading & cpu_interrupt. */
176#undef USE_DIRECT_JUMP
177#endif /* VBOX */
178
179typedef struct TranslationBlock {
180 target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
181 target_ulong cs_base; /* CS base for this block */
182 unsigned int flags; /* flags defining in which context the code was generated */
183 uint16_t size; /* size of target code for this block (1 <=
184 size <= TARGET_PAGE_SIZE) */
185 uint16_t cflags; /* compile flags */
186#define CF_CODE_COPY 0x0001 /* block was generated in code copy mode */
187#define CF_TB_FP_USED 0x0002 /* fp ops are used in the TB */
188#define CF_FP_USED 0x0004 /* fp ops are used in the TB or in a chained TB */
189#define CF_SINGLE_INSN 0x0008 /* compile only a single instruction */
190#ifdef VBOX
191#define CF_RAW_MODE 0x0010 /* block was generated in raw mode */
192#endif
193
194 uint8_t *tc_ptr; /* pointer to the translated code */
195 /* next matching tb for physical address. */
196 struct TranslationBlock *phys_hash_next;
197 /* first and second physical page containing code. The lower bit
198 of the pointer tells the index in page_next[] */
199 struct TranslationBlock *page_next[2];
200 target_ulong page_addr[2];
201
202 /* the following data are used to directly call another TB from
203 the code of this one. */
204 uint16_t tb_next_offset[2]; /* offset of original jump target */
205#ifdef USE_DIRECT_JUMP
206 uint16_t tb_jmp_offset[4]; /* offset of jump instruction */
207#else
208# if defined(VBOX) && defined(__DARWIN__) && defined(__AMD64__)
209# error "First 4GB aren't reachable. jmp dword [tb_next] wont work."
210# endif
211 uint32_t tb_next[2]; /* address of jump generated code */
212#endif
213 /* list of TBs jumping to this one. This is a circular list using
214 the two least significant bits of the pointers to tell what is
215 the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
216 jmp_first */
217 struct TranslationBlock *jmp_next[2];
218 struct TranslationBlock *jmp_first;
219} TranslationBlock;
220
221static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
222{
223 target_ulong tmp;
224 tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
225 return (tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK;
226}
227
228static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
229{
230 target_ulong tmp;
231 tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
232 return (((tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK) |
233 (tmp & TB_JMP_ADDR_MASK));
234}
235
236static inline unsigned int tb_phys_hash_func(unsigned long pc)
237{
238 return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
239}
240
241TranslationBlock *tb_alloc(target_ulong pc);
242void tb_flush(CPUState *env);
243void tb_link_phys(TranslationBlock *tb,
244 target_ulong phys_pc, target_ulong phys_page2);
245
246extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
247
248extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
249extern uint8_t *code_gen_ptr;
250
251#if defined(USE_DIRECT_JUMP)
252
253#if defined(__powerpc__)
254static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
255{
256 uint32_t val, *ptr;
257
258 /* patch the branch destination */
259 ptr = (uint32_t *)jmp_addr;
260 val = *ptr;
261 val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc);
262 *ptr = val;
263 /* flush icache */
264 asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory");
265 asm volatile ("sync" : : : "memory");
266 asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory");
267 asm volatile ("sync" : : : "memory");
268 asm volatile ("isync" : : : "memory");
269}
270#elif defined(__i386__)
271static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
272{
273 /* patch the branch destination */
274 *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
275 /* no need to flush icache explicitely */
276}
277#endif
278
279static inline void tb_set_jmp_target(TranslationBlock *tb,
280 int n, unsigned long addr)
281{
282 unsigned long offset;
283
284 offset = tb->tb_jmp_offset[n];
285 tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
286 offset = tb->tb_jmp_offset[n + 2];
287 if (offset != 0xffff)
288 tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
289}
290
291#else
292
293/* set the jump target */
294static inline void tb_set_jmp_target(TranslationBlock *tb,
295 int n, unsigned long addr)
296{
297 tb->tb_next[n] = addr;
298}
299
300#endif
301
302static inline void tb_add_jump(TranslationBlock *tb, int n,
303 TranslationBlock *tb_next)
304{
305 /* NOTE: this test is only needed for thread safety */
306 if (!tb->jmp_next[n]) {
307 /* patch the native jump address */
308 tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
309
310 /* add in TB jmp circular list */
311 tb->jmp_next[n] = tb_next->jmp_first;
312 tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
313 }
314}
315
316TranslationBlock *tb_find_pc(unsigned long pc_ptr);
317
318#ifndef offsetof
319#define offsetof(type, field) ((size_t) &((type *)0)->field)
320#endif
321
322#if defined(_WIN32)
323#define ASM_DATA_SECTION ".section \".data\"\n"
324#define ASM_PREVIOUS_SECTION ".section .text\n"
325#elif defined(__APPLE__)
326#define ASM_DATA_SECTION ".data\n"
327#define ASM_PREVIOUS_SECTION ".text\n"
328#else
329#define ASM_DATA_SECTION ".section \".data\"\n"
330#define ASM_PREVIOUS_SECTION ".previous\n"
331#endif
332
333#define ASM_OP_LABEL_NAME(n, opname) \
334 ASM_NAME(__op_label) #n "." ASM_NAME(opname)
335
336#if defined(__powerpc__)
337
338/* we patch the jump instruction directly */
339#define GOTO_TB(opname, tbparam, n)\
340do {\
341 asm volatile (ASM_DATA_SECTION\
342 ASM_OP_LABEL_NAME(n, opname) ":\n"\
343 ".long 1f\n"\
344 ASM_PREVIOUS_SECTION \
345 "b " ASM_NAME(__op_jmp) #n "\n"\
346 "1:\n");\
347} while (0)
348
349#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
350
351/* we patch the jump instruction directly */
352#define GOTO_TB(opname, tbparam, n)\
353do {\
354 asm volatile (".section .data\n"\
355 ASM_OP_LABEL_NAME(n, opname) ":\n"\
356 ".long 1f\n"\
357 ASM_PREVIOUS_SECTION \
358 "jmp " ASM_NAME(__op_jmp) #n "\n"\
359 "1:\n");\
360} while (0)
361
362#else
363
364/* jump to next block operations (more portable code, does not need
365 cache flushing, but slower because of indirect jump) */
366# ifdef VBOX /* bird: GCC4 (and Ming 3.4.x?) will remove the two unused static
367 variables. I've added a dummy __asm__ statement which reference
368 the two variables to prevent this. */
369# if __GNUC__ >= 4
370# define GOTO_TB(opname, tbparam, n)\
371 do {\
372 static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
373 static void __attribute__((unused)) *__op_label ## n \
374 __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
375 __asm__ ("" : : "m" (__op_label ## n), "m" (dummy ## n));\
376 goto *(void *)(uintptr_t)(((TranslationBlock *)tbparam)->tb_next[n]);\
377 label ## n: ;\
378 dummy_label ## n: ;\
379 } while (0)
380# else
381# define GOTO_TB(opname, tbparam, n)\
382 do {\
383 static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
384 static void __attribute__((unused)) *__op_label ## n \
385 __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
386 goto *(void *)(uintptr_t)(((TranslationBlock *)tbparam)->tb_next[n]);\
387 label ## n: ;\
388 dummy_label ## n: ;\
389 } while (0)
390# endif
391# else /* !VBOX */
392#define GOTO_TB(opname, tbparam, n)\
393do {\
394 static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
395 static void __attribute__((unused)) *__op_label ## n \
396 __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
397 goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
398label ## n: ;\
399dummy_label ## n: ;\
400} while (0)
401# endif /* !VBOX */
402
403#endif
404
405extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
406extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
407extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
408
409#ifdef __powerpc__
410static inline int testandset (int *p)
411{
412 int ret;
413 __asm__ __volatile__ (
414 "0: lwarx %0,0,%1\n"
415 " xor. %0,%3,%0\n"
416 " bne 1f\n"
417 " stwcx. %2,0,%1\n"
418 " bne- 0b\n"
419 "1: "
420 : "=&r" (ret)
421 : "r" (p), "r" (1), "r" (0)
422 : "cr0", "memory");
423 return ret;
424}
425#endif
426
427#ifdef __i386__
428static inline int testandset (int *p)
429{
430 long int readval = 0;
431
432 __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
433 : "+m" (*p), "+a" (readval)
434 : "r" (1)
435 : "cc");
436 return readval;
437}
438#endif
439
440#ifdef __x86_64__
441static inline int testandset (int *p)
442{
443 long int readval = 0;
444
445 __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
446 : "+m" (*p), "+a" (readval)
447 : "r" (1)
448 : "cc");
449 return readval;
450}
451#endif
452
453#ifdef __s390__
454static inline int testandset (int *p)
455{
456 int ret;
457
458 __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
459 " jl 0b"
460 : "=&d" (ret)
461 : "r" (1), "a" (p), "0" (*p)
462 : "cc", "memory" );
463 return ret;
464}
465#endif
466
467#ifdef __alpha__
468static inline int testandset (int *p)
469{
470 int ret;
471 unsigned long one;
472
473 __asm__ __volatile__ ("0: mov 1,%2\n"
474 " ldl_l %0,%1\n"
475 " stl_c %2,%1\n"
476 " beq %2,1f\n"
477 ".subsection 2\n"
478 "1: br 0b\n"
479 ".previous"
480 : "=r" (ret), "=m" (*p), "=r" (one)
481 : "m" (*p));
482 return ret;
483}
484#endif
485
486#ifdef __sparc__
487static inline int testandset (int *p)
488{
489 int ret;
490
491 __asm__ __volatile__("ldstub [%1], %0"
492 : "=r" (ret)
493 : "r" (p)
494 : "memory");
495
496 return (ret ? 1 : 0);
497}
498#endif
499
500#ifdef __arm__
501static inline int testandset (int *spinlock)
502{
503 register unsigned int ret;
504 __asm__ __volatile__("swp %0, %1, [%2]"
505 : "=r"(ret)
506 : "0"(1), "r"(spinlock));
507
508 return ret;
509}
510#endif
511
512#ifdef __mc68000
513static inline int testandset (int *p)
514{
515 char ret;
516 __asm__ __volatile__("tas %1; sne %0"
517 : "=r" (ret)
518 : "m" (p)
519 : "cc","memory");
520 return ret;
521}
522#endif
523
524#ifdef __ia64
525#include <ia64intrin.h>
526
527static inline int testandset (int *p)
528{
529 return __sync_lock_test_and_set (p, 1);
530}
531#endif
532
533typedef int spinlock_t;
534
535#define SPIN_LOCK_UNLOCKED 0
536
537#if defined(CONFIG_USER_ONLY)
538static inline void spin_lock(spinlock_t *lock)
539{
540 while (testandset(lock));
541}
542
543static inline void spin_unlock(spinlock_t *lock)
544{
545 *lock = 0;
546}
547
548static inline int spin_trylock(spinlock_t *lock)
549{
550 return !testandset(lock);
551}
552#else
553static inline void spin_lock(spinlock_t *lock)
554{
555}
556
557static inline void spin_unlock(spinlock_t *lock)
558{
559}
560
561static inline int spin_trylock(spinlock_t *lock)
562{
563 return 1;
564}
565#endif
566
567extern spinlock_t tb_lock;
568
569extern int tb_invalidated_flag;
570
571#if !defined(CONFIG_USER_ONLY)
572
573void tlb_fill(target_ulong addr, int is_write, int is_user,
574 void *retaddr);
575
576#define ACCESS_TYPE 3
577#define MEMSUFFIX _code
578#define env cpu_single_env
579
580#define DATA_SIZE 1
581#include "softmmu_header.h"
582
583#define DATA_SIZE 2
584#include "softmmu_header.h"
585
586#define DATA_SIZE 4
587#include "softmmu_header.h"
588
589#define DATA_SIZE 8
590#include "softmmu_header.h"
591
592#undef ACCESS_TYPE
593#undef MEMSUFFIX
594#undef env
595
596#endif
597
598#if defined(CONFIG_USER_ONLY)
599static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
600{
601 return addr;
602}
603#else
604# ifdef VBOX
605target_ulong remR3PhysGetPhysicalAddressCode(CPUState *env, target_ulong addr, CPUTLBEntry *pTLBEntry);
606# if defined(PGM_DYNAMIC_RAM_ALLOC) && !defined(REM_PHYS_ADDR_IN_TLB)
607target_ulong remR3HCVirt2GCPhys(void *env, void *addr);
608# endif
609# endif
610/* NOTE: this function can trigger an exception */
611/* NOTE2: the returned address is not exactly the physical address: it
612 is the offset relative to phys_ram_base */
613static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
614{
615 int is_user, index, pd;
616
617 index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
618#if defined(TARGET_I386)
619 is_user = ((env->hflags & HF_CPL_MASK) == 3);
620#elif defined (TARGET_PPC)
621 is_user = msr_pr;
622#elif defined (TARGET_MIPS)
623 is_user = ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
624#elif defined (TARGET_SPARC)
625 is_user = (env->psrs == 0);
626#elif defined (TARGET_ARM)
627 is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR);
628#elif defined (TARGET_SH4)
629 is_user = ((env->sr & SR_MD) == 0);
630#else
631#error unimplemented CPU
632#endif
633 if (__builtin_expect(env->tlb_table[is_user][index].addr_code !=
634 (addr & TARGET_PAGE_MASK), 0)) {
635 ldub_code(addr);
636 }
637 pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
638 if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
639# ifdef VBOX
640 /* deal with non-MMIO access handlers. */
641 return remR3PhysGetPhysicalAddressCode(env, addr, &env->tlb_table[is_user][index]);
642# else
643 cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr);
644# endif
645 }
646# if defined(VBOX) && defined(REM_PHYS_ADDR_IN_TLB)
647 return addr + env->tlb_table[is_user][index].addend;
648# elif defined(VBOX) && defined(PGM_DYNAMIC_RAM_ALLOC)
649 return remR3HCVirt2GCPhys(env, (void *)(addr + env->tlb_table[is_user][index].addend));
650# else
651 return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
652# endif
653}
654#endif
655
656
657#ifdef USE_KQEMU
658#define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
659
660int kqemu_init(CPUState *env);
661int kqemu_cpu_exec(CPUState *env);
662void kqemu_flush_page(CPUState *env, target_ulong addr);
663void kqemu_flush(CPUState *env, int global);
664void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr);
665void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr);
666void kqemu_cpu_interrupt(CPUState *env);
667void kqemu_record_dump(void);
668
669static inline int kqemu_is_ok(CPUState *env)
670{
671 return(env->kqemu_enabled &&
672 (env->cr[0] & CR0_PE_MASK) &&
673 !(env->hflags & HF_INHIBIT_IRQ_MASK) &&
674 (env->eflags & IF_MASK) &&
675 !(env->eflags & VM_MASK) &&
676 (env->kqemu_enabled == 2 ||
677 ((env->hflags & HF_CPL_MASK) == 3 &&
678 (env->eflags & IOPL_MASK) != IOPL_MASK)));
679}
680
681#endif
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