diff options
-rw-r--r-- | dyngen-exec.h | 2 | ||||
-rw-r--r-- | dyngen-op.h | 9 | ||||
-rw-r--r-- | dyngen.c | 23 | ||||
-rw-r--r-- | dyngen.h | 4 | ||||
-rw-r--r-- | translate-all.c | 61 |
5 files changed, 73 insertions, 26 deletions
diff --git a/dyngen-exec.h b/dyngen-exec.h index 86087ca623..62bcbf33b5 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -211,12 +211,14 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; #ifdef __i386__ #define EXIT_TB() asm volatile ("ret") +#define GOTO_LABEL_PARAM(n) asm volatile ("jmp __op_gen_label" #n) #endif #ifdef __x86_64__ #define EXIT_TB() asm volatile ("ret") #endif #ifdef __powerpc__ #define EXIT_TB() asm volatile ("blr") +#define GOTO_LABEL_PARAM(n) asm volatile ("b __op_gen_label" #n) #endif #ifdef __s390__ #define EXIT_TB() asm volatile ("br %r14") diff --git a/dyngen-op.h b/dyngen-op.h new file mode 100644 index 0000000000..f77a4756f7 --- /dev/null +++ b/dyngen-op.h @@ -0,0 +1,9 @@ +static inline int gen_new_label(void) +{ + return nb_gen_labels++; +} + +static inline void gen_set_label(int n) +{ + gen_labels[n] = gen_opc_ptr - gen_opc_buf; +} @@ -54,7 +54,7 @@ #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) #undef ELF_USES_RELOCA -#elif defined(HOST_AMD64) +#elif defined(HOST_X86_64) #define ELF_CLASS ELFCLASS64 #define ELF_ARCH EM_X86_64 @@ -1307,7 +1307,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, p_start = text + offset; p_end = p_start + size; start_offset = offset; -#if defined(HOST_I386) || defined(HOST_AMD64) +#if defined(HOST_I386) || defined(HOST_X86_64) #ifdef CONFIG_FORMAT_COFF { uint8_t *p; @@ -1482,7 +1482,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, sym_name = get_rel_sym_name(rel); if(!sym_name) continue; - if (strstart(sym_name, "__op_param", &p)) { + if (strstart(sym_name, "__op_param", &p) || + strstart(sym_name, "__op_gen_label", &p)) { n = strtoul(p, NULL, 10); if (n > MAX_ARGS) error("too many arguments in %s", name); @@ -1525,7 +1526,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, continue; if (*sym_name && !strstart(sym_name, "__op_param", NULL) && - !strstart(sym_name, "__op_jmp", NULL)) { + !strstart(sym_name, "__op_jmp", NULL) && + !strstart(sym_name, "__op_gen_label", NULL)) { #if defined(HOST_SPARC) if (sym_name[0] == '.') { fprintf(outfile, @@ -1604,8 +1606,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, } } #endif - - if (val >= start_offset && val < start_offset + copy_size) { + if (val >= start_offset && val <= start_offset + copy_size) { n = strtol(p, NULL, 10); fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, val - start_offset); } @@ -1642,6 +1643,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, if (strstart(sym_name, "__op_param", &p)) { snprintf(name, sizeof(name), "param%s", p); + } else if (strstart(sym_name, "__op_gen_label", &p)) { + snprintf(name, sizeof(name), "gen_labels[param%s]", p); } else { snprintf(name, sizeof(name), "(long)(&%s)", sym_name); } @@ -1693,7 +1696,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, } } } -#elif defined(HOST_AMD64) +#elif defined(HOST_X86_64) { char name[256]; int type; @@ -1723,7 +1726,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend); break; default: - error("unsupported AMD64 relocation (%d)", type); + error("unsupported X86_64 relocation (%d)", type); } } } @@ -2232,7 +2235,7 @@ int gen_file(FILE *outfile, int out_type) } } else if (out_type == OUT_GEN_OP) { /* generate gen_xxx functions */ - + fprintf(outfile, "#include \"dyngen-op.h\"\n"); for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { const char *name; name = get_sym_name(sym); @@ -2250,7 +2253,7 @@ int gen_file(FILE *outfile, int out_type) fprintf(outfile, "int dyngen_code(uint8_t *gen_code_buf,\n" " uint16_t *label_offsets, uint16_t *jmp_offsets,\n" -" const uint16_t *opc_buf, const uint32_t *opparam_buf)\n" +" const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n" "{\n" " uint8_t *gen_code_ptr;\n" " const uint16_t *opc_ptr;\n" @@ -19,6 +19,7 @@ */ int __op_param1, __op_param2, __op_param3; +int __op_gen_label1, __op_gen_label2, __op_gen_label3; int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; #ifdef __i386__ @@ -203,6 +204,3 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr, } #endif /* __arm__ */ - - - diff --git a/translate-all.c b/translate-all.c index 1fbed41340..f6a7bc2b50 100644 --- a/translate-all.c +++ b/translate-all.c @@ -42,12 +42,15 @@ enum { uint16_t gen_opc_buf[OPC_BUF_SIZE]; uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; -uint32_t gen_opc_pc[OPC_BUF_SIZE]; +long gen_labels[OPC_BUF_SIZE]; +int nb_gen_labels; + +target_ulong gen_opc_pc[OPC_BUF_SIZE]; uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; #if defined(TARGET_I386) uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; #elif defined(TARGET_SPARC) -uint32_t gen_opc_npc[OPC_BUF_SIZE]; +target_ulong gen_opc_npc[OPC_BUF_SIZE]; #endif int code_copy_enabled = 1; @@ -65,6 +68,12 @@ static uint8_t op_nb_args[] = { #undef DEF }; +static const unsigned short opc_copy_size[] = { +#define DEF(s, n, copy_size) copy_size, +#include "opc.h" +#undef DEF +}; + void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) { const uint16_t *opc_ptr; @@ -90,6 +99,35 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) #endif +/* compute label info */ +static void dyngen_labels(long *gen_labels, int nb_gen_labels, + uint8_t *gen_code_buf, const uint16_t *opc_buf) +{ + uint8_t *gen_code_ptr; + int c, i; + unsigned long gen_code_addr[OPC_BUF_SIZE]; + + if (nb_gen_labels == 0) + return; + /* compute the address of each op code */ + + gen_code_ptr = gen_code_buf; + i = 0; + for(;;) { + c = opc_buf[i]; + gen_code_addr[i] =(unsigned long)gen_code_ptr; + if (c == INDEX_op_end) + break; + gen_code_ptr += opc_copy_size[c]; + i++; + } + + /* compute the address of each label */ + for(i = 0; i < nb_gen_labels; i++) { + gen_labels[i] = gen_code_addr[gen_labels[i]]; + } +} + /* return non zero if the very first instruction is invalid so that the virtual CPU can trigger an exception. @@ -121,19 +159,21 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, tb->tb_jmp_offset[2] = 0xffff; tb->tb_jmp_offset[3] = 0xffff; #endif + dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf); + gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, #ifdef USE_DIRECT_JUMP tb->tb_jmp_offset, #else NULL, #endif - gen_opc_buf, gen_opparam_buf); + gen_opc_buf, gen_opparam_buf, gen_labels); } *gen_code_size_ptr = gen_code_size; #ifdef DEBUG_DISAS if (loglevel & CPU_LOG_TB_OUT_ASM) { fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); - disas(logfile, tb->tc_ptr, *gen_code_size_ptr, 1, 0); + disas(logfile, tb->tc_ptr, *gen_code_size_ptr); fprintf(logfile, "\n"); fflush(logfile); } @@ -141,12 +181,6 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, return 0; } -static const unsigned short opc_copy_size[] = { -#define DEF(s, n, copy_size) copy_size, -#include "opc.h" -#undef DEF -}; - /* The cpu state corresponding to 'searched_pc' is restored. */ int cpu_restore_state(TranslationBlock *tb, @@ -193,11 +227,12 @@ int cpu_restore_state(TranslationBlock *tb, fprintf(logfile, "RESTORE:\n"); for(i=0;i<=j; i++) { if (gen_opc_instr_start[i]) { - fprintf(logfile, "0x%04x: 0x%08x\n", i, gen_opc_pc[i]); + fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]); } } - fprintf(logfile, "spc=0x%08lx j=0x%x eip=0x%x cs_base=%x\n", - searched_pc, j, gen_opc_pc[j] - tb->cs_base, tb->cs_base); + fprintf(logfile, "spc=0x%08lx j=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n", + searched_pc, j, gen_opc_pc[j] - tb->cs_base, + (uint32_t)tb->cs_base); } #endif env->eip = gen_opc_pc[j] - tb->cs_base; |