aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dyngen-exec.h2
-rw-r--r--dyngen-op.h9
-rw-r--r--dyngen.c23
-rw-r--r--dyngen.h4
-rw-r--r--translate-all.c61
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;
+}
diff --git a/dyngen.c b/dyngen.c
index ad0e834102..1138ca4551 100644
--- a/dyngen.c
+++ b/dyngen.c
@@ -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"
diff --git a/dyngen.h b/dyngen.h
index a00ded775e..f1ce2484c8 100644
--- a/dyngen.h
+++ b/dyngen.h
@@ -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;