]> git.proxmox.com Git - mirror_qemu.git/commitdiff
labels support in dyngen
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 3 Jan 2005 23:44:44 +0000 (23:44 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 3 Jan 2005 23:44:44 +0000 (23:44 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1196 c046a42c-6fe2-441c-8c8c-71466251a162

dyngen-exec.h
dyngen-op.h [new file with mode: 0644]
dyngen.c
dyngen.h
translate-all.c

index 86087ca623b443cafaaa9249ef0e6d7516952f26..62bcbf33b59023fc3eb393780bf3cd398f0e74c2 100644 (file)
@@ -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 (file)
index 0000000..f77a475
--- /dev/null
@@ -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;
+}
index ad0e83410253fec4fb2a451c69baca62657fae2e..1138ca4551a8cb6a48e3aed580aae48815382212 100644 (file)
--- 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"
index a00ded775ec4825f427ac3d4aaaafbdf49d13ed7..f1ce2484c8c46616d766dcb633744d87185e0243 100644 (file)
--- 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__ */
-
-                       
-                   
index 1fbed41340ddc539951e6fd4ae449f8032c18014..f6a7bc2b5052c2cfc253af100966cd3d4f67d07c 100644 (file)
@@ -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;