experimental code copy support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@623 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
3a1d9b8bbb
commit
58fe2f10f0
12
exec-all.h
12
exec-all.h
@ -79,7 +79,13 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
|
||||
int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
|
||||
int max_code_size, int *gen_code_size_ptr);
|
||||
int cpu_restore_state(struct TranslationBlock *tb,
|
||||
CPUState *env, unsigned long searched_pc);
|
||||
CPUState *env, unsigned long searched_pc,
|
||||
void *puc);
|
||||
int cpu_gen_code_copy(CPUState *env, struct TranslationBlock *tb,
|
||||
int max_code_size, int *gen_code_size_ptr);
|
||||
int cpu_restore_state_copy(struct TranslationBlock *tb,
|
||||
CPUState *env, unsigned long searched_pc,
|
||||
void *puc);
|
||||
void cpu_exec_init(void);
|
||||
int page_unprotect(unsigned long address);
|
||||
void tb_invalidate_page_range(target_ulong start, target_ulong end);
|
||||
@ -145,6 +151,9 @@ typedef struct TranslationBlock {
|
||||
unsigned int flags; /* flags defining in which context the code was generated */
|
||||
uint16_t size; /* size of target code for this block (1 <=
|
||||
size <= TARGET_PAGE_SIZE) */
|
||||
uint16_t cflags; /* compile flags */
|
||||
#define CF_CODE_COPY 0x0001 /* block was generated in code copy mode */
|
||||
|
||||
uint8_t *tc_ptr; /* pointer to the translated code */
|
||||
struct TranslationBlock *hash_next; /* next matching tb for virtual address */
|
||||
/* next matching tb for physical address. */
|
||||
@ -552,4 +561,3 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
|
||||
return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -378,7 +378,11 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
|
||||
|
||||
/* the CPU emulator uses some host signals to detect exceptions,
|
||||
we we forward to it some signals */
|
||||
if (host_signum == SIGSEGV || host_signum == SIGBUS) {
|
||||
if (host_signum == SIGSEGV || host_signum == SIGBUS
|
||||
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
|
||||
|| host_signum == SIGFPE
|
||||
#endif
|
||||
) {
|
||||
if (cpu_signal_handler(host_signum, info, puc))
|
||||
return;
|
||||
}
|
||||
|
@ -24,6 +24,10 @@
|
||||
|
||||
#include "cpu-defs.h"
|
||||
|
||||
#if defined(__i386__) && !defined(CONFIG_SOFTMMU)
|
||||
#define USE_CODE_COPY
|
||||
#endif
|
||||
|
||||
#define R_EAX 0
|
||||
#define R_ECX 1
|
||||
#define R_EDX 2
|
||||
@ -121,6 +125,7 @@
|
||||
#define HF_SS32_MASK (1 << HF_SS32_SHIFT)
|
||||
#define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT)
|
||||
#define HF_PE_MASK (1 << HF_PE_SHIFT)
|
||||
#define HF_TF_MASK (1 << HF_TF_SHIFT)
|
||||
|
||||
#define CR0_PE_MASK (1 << 0)
|
||||
#define CR0_TS_MASK (1 << 3)
|
||||
@ -297,6 +302,10 @@ typedef struct CPUX86State {
|
||||
uint32_t sysenter_cs;
|
||||
uint32_t sysenter_esp;
|
||||
uint32_t sysenter_eip;
|
||||
|
||||
/* temporary data for USE_CODE_COPY mode */
|
||||
uint32_t tmp0;
|
||||
uint32_t saved_esp;
|
||||
|
||||
/* exception/interrupt handling */
|
||||
jmp_buf jmp_env;
|
||||
|
@ -869,7 +869,7 @@ void do_interrupt(int intno, int is_int, int error_code,
|
||||
{
|
||||
extern FILE *stdout;
|
||||
static int count;
|
||||
if (env->cr[0] & CR0_PE_MASK) {
|
||||
if (env->cr[0] & CR0_PE_MASK) {
|
||||
fprintf(stdout, "%d: v=%02x e=%04x i=%d CPL=%d CS:EIP=%04x:%08x SS:ESP=%04x:%08x",
|
||||
count, intno, error_code, is_int,
|
||||
env->hflags & HF_CPL_MASK,
|
||||
@ -2489,7 +2489,7 @@ void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr)
|
||||
if (tb) {
|
||||
/* the PC is inside the translated code. It means that we have
|
||||
a virtual CPU fault */
|
||||
cpu_restore_state(tb, env, pc);
|
||||
cpu_restore_state(tb, env, pc, NULL);
|
||||
}
|
||||
}
|
||||
raise_exception_err(EXCP0E_PAGE, env->error_code);
|
||||
|
1544
target-i386/translate-copy.c
Normal file
1544
target-i386/translate-copy.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -48,6 +48,8 @@ uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
|
||||
uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
|
||||
#endif
|
||||
|
||||
int code_copy_enabled = 1;
|
||||
|
||||
#ifdef DEBUG_DISAS
|
||||
static const char *op_str[] = {
|
||||
#define DEF(s, n, copy_size) #s,
|
||||
@ -98,30 +100,38 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb,
|
||||
uint8_t *gen_code_buf;
|
||||
int gen_code_size;
|
||||
|
||||
if (gen_intermediate_code(env, tb) < 0)
|
||||
return -1;
|
||||
#ifdef USE_CODE_COPY
|
||||
if (code_copy_enabled &&
|
||||
cpu_gen_code_copy(env, tb, max_code_size, &gen_code_size) == 0) {
|
||||
/* nothing more to do */
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (gen_intermediate_code(env, tb) < 0)
|
||||
return -1;
|
||||
|
||||
/* generate machine code */
|
||||
tb->tb_next_offset[0] = 0xffff;
|
||||
tb->tb_next_offset[1] = 0xffff;
|
||||
gen_code_buf = tb->tc_ptr;
|
||||
/* generate machine code */
|
||||
tb->tb_next_offset[0] = 0xffff;
|
||||
tb->tb_next_offset[1] = 0xffff;
|
||||
gen_code_buf = tb->tc_ptr;
|
||||
#ifdef USE_DIRECT_JUMP
|
||||
/* the following two entries are optional (only used for string ops) */
|
||||
tb->tb_jmp_offset[2] = 0xffff;
|
||||
tb->tb_jmp_offset[3] = 0xffff;
|
||||
/* the following two entries are optional (only used for string ops) */
|
||||
tb->tb_jmp_offset[2] = 0xffff;
|
||||
tb->tb_jmp_offset[3] = 0xffff;
|
||||
#endif
|
||||
gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
|
||||
gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
|
||||
#ifdef USE_DIRECT_JUMP
|
||||
tb->tb_jmp_offset,
|
||||
tb->tb_jmp_offset,
|
||||
#else
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
gen_opc_buf, gen_opparam_buf);
|
||||
gen_opc_buf, gen_opparam_buf);
|
||||
}
|
||||
*gen_code_size_ptr = gen_code_size;
|
||||
#ifdef DEBUG_DISAS
|
||||
if (loglevel && 0) {
|
||||
if (loglevel) {
|
||||
fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
|
||||
disas(logfile, gen_code_buf, *gen_code_size_ptr, 1, 0);
|
||||
disas(logfile, tb->tc_ptr, *gen_code_size_ptr, 1, 0);
|
||||
fprintf(logfile, "\n");
|
||||
fflush(logfile);
|
||||
}
|
||||
@ -138,12 +148,18 @@ static const unsigned short opc_copy_size[] = {
|
||||
/* The cpu state corresponding to 'searched_pc' is restored.
|
||||
*/
|
||||
int cpu_restore_state(TranslationBlock *tb,
|
||||
CPUState *env, unsigned long searched_pc)
|
||||
CPUState *env, unsigned long searched_pc,
|
||||
void *puc)
|
||||
{
|
||||
int j, c;
|
||||
unsigned long tc_ptr;
|
||||
uint16_t *opc_ptr;
|
||||
|
||||
#ifdef USE_CODE_COPY
|
||||
if (tb->cflags & CF_CODE_COPY) {
|
||||
return cpu_restore_state_copy(tb, env, searched_pc, puc);
|
||||
}
|
||||
#endif
|
||||
if (gen_intermediate_code_pc(env, tb) < 0)
|
||||
return -1;
|
||||
|
||||
@ -190,6 +206,7 @@ int cpu_restore_state(TranslationBlock *tb,
|
||||
#elif defined(TARGET_ARM)
|
||||
env->regs[15] = gen_opc_pc[j];
|
||||
#elif defined(TARGET_SPARC)
|
||||
/* XXX: restore npc too */
|
||||
env->pc = gen_opc_pc[j];
|
||||
#elif defined(TARGET_PPC)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user