Commit c46878786af930f8f06695371ee80ffa8acf98ef
1 parent
0fa85d43
labels support in dyngen
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1196 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
73 additions
and
26 deletions
dyngen-exec.h
| @@ -211,12 +211,14 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; | @@ -211,12 +211,14 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; | ||
| 211 | 211 | ||
| 212 | #ifdef __i386__ | 212 | #ifdef __i386__ |
| 213 | #define EXIT_TB() asm volatile ("ret") | 213 | #define EXIT_TB() asm volatile ("ret") |
| 214 | +#define GOTO_LABEL_PARAM(n) asm volatile ("jmp __op_gen_label" #n) | ||
| 214 | #endif | 215 | #endif |
| 215 | #ifdef __x86_64__ | 216 | #ifdef __x86_64__ |
| 216 | #define EXIT_TB() asm volatile ("ret") | 217 | #define EXIT_TB() asm volatile ("ret") |
| 217 | #endif | 218 | #endif |
| 218 | #ifdef __powerpc__ | 219 | #ifdef __powerpc__ |
| 219 | #define EXIT_TB() asm volatile ("blr") | 220 | #define EXIT_TB() asm volatile ("blr") |
| 221 | +#define GOTO_LABEL_PARAM(n) asm volatile ("b __op_gen_label" #n) | ||
| 220 | #endif | 222 | #endif |
| 221 | #ifdef __s390__ | 223 | #ifdef __s390__ |
| 222 | #define EXIT_TB() asm volatile ("br %r14") | 224 | #define EXIT_TB() asm volatile ("br %r14") |
dyngen-op.h
0 → 100644
dyngen.c
| @@ -54,7 +54,7 @@ | @@ -54,7 +54,7 @@ | ||
| 54 | #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) | 54 | #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) |
| 55 | #undef ELF_USES_RELOCA | 55 | #undef ELF_USES_RELOCA |
| 56 | 56 | ||
| 57 | -#elif defined(HOST_AMD64) | 57 | +#elif defined(HOST_X86_64) |
| 58 | 58 | ||
| 59 | #define ELF_CLASS ELFCLASS64 | 59 | #define ELF_CLASS ELFCLASS64 |
| 60 | #define ELF_ARCH EM_X86_64 | 60 | #define ELF_ARCH EM_X86_64 |
| @@ -1307,7 +1307,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1307,7 +1307,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 1307 | p_start = text + offset; | 1307 | p_start = text + offset; |
| 1308 | p_end = p_start + size; | 1308 | p_end = p_start + size; |
| 1309 | start_offset = offset; | 1309 | start_offset = offset; |
| 1310 | -#if defined(HOST_I386) || defined(HOST_AMD64) | 1310 | +#if defined(HOST_I386) || defined(HOST_X86_64) |
| 1311 | #ifdef CONFIG_FORMAT_COFF | 1311 | #ifdef CONFIG_FORMAT_COFF |
| 1312 | { | 1312 | { |
| 1313 | uint8_t *p; | 1313 | uint8_t *p; |
| @@ -1482,7 +1482,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1482,7 +1482,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 1482 | sym_name = get_rel_sym_name(rel); | 1482 | sym_name = get_rel_sym_name(rel); |
| 1483 | if(!sym_name) | 1483 | if(!sym_name) |
| 1484 | continue; | 1484 | continue; |
| 1485 | - if (strstart(sym_name, "__op_param", &p)) { | 1485 | + if (strstart(sym_name, "__op_param", &p) || |
| 1486 | + strstart(sym_name, "__op_gen_label", &p)) { | ||
| 1486 | n = strtoul(p, NULL, 10); | 1487 | n = strtoul(p, NULL, 10); |
| 1487 | if (n > MAX_ARGS) | 1488 | if (n > MAX_ARGS) |
| 1488 | error("too many arguments in %s", name); | 1489 | error("too many arguments in %s", name); |
| @@ -1525,7 +1526,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1525,7 +1526,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 1525 | continue; | 1526 | continue; |
| 1526 | if (*sym_name && | 1527 | if (*sym_name && |
| 1527 | !strstart(sym_name, "__op_param", NULL) && | 1528 | !strstart(sym_name, "__op_param", NULL) && |
| 1528 | - !strstart(sym_name, "__op_jmp", NULL)) { | 1529 | + !strstart(sym_name, "__op_jmp", NULL) && |
| 1530 | + !strstart(sym_name, "__op_gen_label", NULL)) { | ||
| 1529 | #if defined(HOST_SPARC) | 1531 | #if defined(HOST_SPARC) |
| 1530 | if (sym_name[0] == '.') { | 1532 | if (sym_name[0] == '.') { |
| 1531 | fprintf(outfile, | 1533 | fprintf(outfile, |
| @@ -1604,8 +1606,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1604,8 +1606,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 1604 | } | 1606 | } |
| 1605 | } | 1607 | } |
| 1606 | #endif | 1608 | #endif |
| 1607 | - | ||
| 1608 | - if (val >= start_offset && val < start_offset + copy_size) { | 1609 | + if (val >= start_offset && val <= start_offset + copy_size) { |
| 1609 | n = strtol(p, NULL, 10); | 1610 | n = strtol(p, NULL, 10); |
| 1610 | fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, val - start_offset); | 1611 | fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, val - start_offset); |
| 1611 | } | 1612 | } |
| @@ -1642,6 +1643,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1642,6 +1643,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 1642 | 1643 | ||
| 1643 | if (strstart(sym_name, "__op_param", &p)) { | 1644 | if (strstart(sym_name, "__op_param", &p)) { |
| 1644 | snprintf(name, sizeof(name), "param%s", p); | 1645 | snprintf(name, sizeof(name), "param%s", p); |
| 1646 | + } else if (strstart(sym_name, "__op_gen_label", &p)) { | ||
| 1647 | + snprintf(name, sizeof(name), "gen_labels[param%s]", p); | ||
| 1645 | } else { | 1648 | } else { |
| 1646 | snprintf(name, sizeof(name), "(long)(&%s)", sym_name); | 1649 | snprintf(name, sizeof(name), "(long)(&%s)", sym_name); |
| 1647 | } | 1650 | } |
| @@ -1693,7 +1696,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1693,7 +1696,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 1693 | } | 1696 | } |
| 1694 | } | 1697 | } |
| 1695 | } | 1698 | } |
| 1696 | -#elif defined(HOST_AMD64) | 1699 | +#elif defined(HOST_X86_64) |
| 1697 | { | 1700 | { |
| 1698 | char name[256]; | 1701 | char name[256]; |
| 1699 | int type; | 1702 | int type; |
| @@ -1723,7 +1726,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1723,7 +1726,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 1723 | rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend); | 1726 | rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend); |
| 1724 | break; | 1727 | break; |
| 1725 | default: | 1728 | default: |
| 1726 | - error("unsupported AMD64 relocation (%d)", type); | 1729 | + error("unsupported X86_64 relocation (%d)", type); |
| 1727 | } | 1730 | } |
| 1728 | } | 1731 | } |
| 1729 | } | 1732 | } |
| @@ -2232,7 +2235,7 @@ int gen_file(FILE *outfile, int out_type) | @@ -2232,7 +2235,7 @@ int gen_file(FILE *outfile, int out_type) | ||
| 2232 | } | 2235 | } |
| 2233 | } else if (out_type == OUT_GEN_OP) { | 2236 | } else if (out_type == OUT_GEN_OP) { |
| 2234 | /* generate gen_xxx functions */ | 2237 | /* generate gen_xxx functions */ |
| 2235 | - | 2238 | + fprintf(outfile, "#include \"dyngen-op.h\"\n"); |
| 2236 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { | 2239 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
| 2237 | const char *name; | 2240 | const char *name; |
| 2238 | name = get_sym_name(sym); | 2241 | name = get_sym_name(sym); |
| @@ -2250,7 +2253,7 @@ int gen_file(FILE *outfile, int out_type) | @@ -2250,7 +2253,7 @@ int gen_file(FILE *outfile, int out_type) | ||
| 2250 | fprintf(outfile, | 2253 | fprintf(outfile, |
| 2251 | "int dyngen_code(uint8_t *gen_code_buf,\n" | 2254 | "int dyngen_code(uint8_t *gen_code_buf,\n" |
| 2252 | " uint16_t *label_offsets, uint16_t *jmp_offsets,\n" | 2255 | " uint16_t *label_offsets, uint16_t *jmp_offsets,\n" |
| 2253 | -" const uint16_t *opc_buf, const uint32_t *opparam_buf)\n" | 2256 | +" const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n" |
| 2254 | "{\n" | 2257 | "{\n" |
| 2255 | " uint8_t *gen_code_ptr;\n" | 2258 | " uint8_t *gen_code_ptr;\n" |
| 2256 | " const uint16_t *opc_ptr;\n" | 2259 | " const uint16_t *opc_ptr;\n" |
dyngen.h
| @@ -19,6 +19,7 @@ | @@ -19,6 +19,7 @@ | ||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | int __op_param1, __op_param2, __op_param3; | 21 | int __op_param1, __op_param2, __op_param3; |
| 22 | +int __op_gen_label1, __op_gen_label2, __op_gen_label3; | ||
| 22 | int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; | 23 | int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; |
| 23 | 24 | ||
| 24 | #ifdef __i386__ | 25 | #ifdef __i386__ |
| @@ -203,6 +204,3 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr, | @@ -203,6 +204,3 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr, | ||
| 203 | } | 204 | } |
| 204 | 205 | ||
| 205 | #endif /* __arm__ */ | 206 | #endif /* __arm__ */ |
| 206 | - | ||
| 207 | - | ||
| 208 | - |
translate-all.c
| @@ -42,12 +42,15 @@ enum { | @@ -42,12 +42,15 @@ enum { | ||
| 42 | 42 | ||
| 43 | uint16_t gen_opc_buf[OPC_BUF_SIZE]; | 43 | uint16_t gen_opc_buf[OPC_BUF_SIZE]; |
| 44 | uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; | 44 | uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; |
| 45 | -uint32_t gen_opc_pc[OPC_BUF_SIZE]; | 45 | +long gen_labels[OPC_BUF_SIZE]; |
| 46 | +int nb_gen_labels; | ||
| 47 | + | ||
| 48 | +target_ulong gen_opc_pc[OPC_BUF_SIZE]; | ||
| 46 | uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | 49 | uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; |
| 47 | #if defined(TARGET_I386) | 50 | #if defined(TARGET_I386) |
| 48 | uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; | 51 | uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; |
| 49 | #elif defined(TARGET_SPARC) | 52 | #elif defined(TARGET_SPARC) |
| 50 | -uint32_t gen_opc_npc[OPC_BUF_SIZE]; | 53 | +target_ulong gen_opc_npc[OPC_BUF_SIZE]; |
| 51 | #endif | 54 | #endif |
| 52 | 55 | ||
| 53 | int code_copy_enabled = 1; | 56 | int code_copy_enabled = 1; |
| @@ -65,6 +68,12 @@ static uint8_t op_nb_args[] = { | @@ -65,6 +68,12 @@ static uint8_t op_nb_args[] = { | ||
| 65 | #undef DEF | 68 | #undef DEF |
| 66 | }; | 69 | }; |
| 67 | 70 | ||
| 71 | +static const unsigned short opc_copy_size[] = { | ||
| 72 | +#define DEF(s, n, copy_size) copy_size, | ||
| 73 | +#include "opc.h" | ||
| 74 | +#undef DEF | ||
| 75 | +}; | ||
| 76 | + | ||
| 68 | void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | 77 | void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) |
| 69 | { | 78 | { |
| 70 | const uint16_t *opc_ptr; | 79 | const uint16_t *opc_ptr; |
| @@ -90,6 +99,35 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | @@ -90,6 +99,35 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | ||
| 90 | 99 | ||
| 91 | #endif | 100 | #endif |
| 92 | 101 | ||
| 102 | +/* compute label info */ | ||
| 103 | +static void dyngen_labels(long *gen_labels, int nb_gen_labels, | ||
| 104 | + uint8_t *gen_code_buf, const uint16_t *opc_buf) | ||
| 105 | +{ | ||
| 106 | + uint8_t *gen_code_ptr; | ||
| 107 | + int c, i; | ||
| 108 | + unsigned long gen_code_addr[OPC_BUF_SIZE]; | ||
| 109 | + | ||
| 110 | + if (nb_gen_labels == 0) | ||
| 111 | + return; | ||
| 112 | + /* compute the address of each op code */ | ||
| 113 | + | ||
| 114 | + gen_code_ptr = gen_code_buf; | ||
| 115 | + i = 0; | ||
| 116 | + for(;;) { | ||
| 117 | + c = opc_buf[i]; | ||
| 118 | + gen_code_addr[i] =(unsigned long)gen_code_ptr; | ||
| 119 | + if (c == INDEX_op_end) | ||
| 120 | + break; | ||
| 121 | + gen_code_ptr += opc_copy_size[c]; | ||
| 122 | + i++; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + /* compute the address of each label */ | ||
| 126 | + for(i = 0; i < nb_gen_labels; i++) { | ||
| 127 | + gen_labels[i] = gen_code_addr[gen_labels[i]]; | ||
| 128 | + } | ||
| 129 | +} | ||
| 130 | + | ||
| 93 | /* return non zero if the very first instruction is invalid so that | 131 | /* return non zero if the very first instruction is invalid so that |
| 94 | the virtual CPU can trigger an exception. | 132 | the virtual CPU can trigger an exception. |
| 95 | 133 | ||
| @@ -121,19 +159,21 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, | @@ -121,19 +159,21 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, | ||
| 121 | tb->tb_jmp_offset[2] = 0xffff; | 159 | tb->tb_jmp_offset[2] = 0xffff; |
| 122 | tb->tb_jmp_offset[3] = 0xffff; | 160 | tb->tb_jmp_offset[3] = 0xffff; |
| 123 | #endif | 161 | #endif |
| 162 | + dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf); | ||
| 163 | + | ||
| 124 | gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, | 164 | gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, |
| 125 | #ifdef USE_DIRECT_JUMP | 165 | #ifdef USE_DIRECT_JUMP |
| 126 | tb->tb_jmp_offset, | 166 | tb->tb_jmp_offset, |
| 127 | #else | 167 | #else |
| 128 | NULL, | 168 | NULL, |
| 129 | #endif | 169 | #endif |
| 130 | - gen_opc_buf, gen_opparam_buf); | 170 | + gen_opc_buf, gen_opparam_buf, gen_labels); |
| 131 | } | 171 | } |
| 132 | *gen_code_size_ptr = gen_code_size; | 172 | *gen_code_size_ptr = gen_code_size; |
| 133 | #ifdef DEBUG_DISAS | 173 | #ifdef DEBUG_DISAS |
| 134 | if (loglevel & CPU_LOG_TB_OUT_ASM) { | 174 | if (loglevel & CPU_LOG_TB_OUT_ASM) { |
| 135 | fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); | 175 | fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); |
| 136 | - disas(logfile, tb->tc_ptr, *gen_code_size_ptr, 1, 0); | 176 | + disas(logfile, tb->tc_ptr, *gen_code_size_ptr); |
| 137 | fprintf(logfile, "\n"); | 177 | fprintf(logfile, "\n"); |
| 138 | fflush(logfile); | 178 | fflush(logfile); |
| 139 | } | 179 | } |
| @@ -141,12 +181,6 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, | @@ -141,12 +181,6 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, | ||
| 141 | return 0; | 181 | return 0; |
| 142 | } | 182 | } |
| 143 | 183 | ||
| 144 | -static const unsigned short opc_copy_size[] = { | ||
| 145 | -#define DEF(s, n, copy_size) copy_size, | ||
| 146 | -#include "opc.h" | ||
| 147 | -#undef DEF | ||
| 148 | -}; | ||
| 149 | - | ||
| 150 | /* The cpu state corresponding to 'searched_pc' is restored. | 184 | /* The cpu state corresponding to 'searched_pc' is restored. |
| 151 | */ | 185 | */ |
| 152 | int cpu_restore_state(TranslationBlock *tb, | 186 | int cpu_restore_state(TranslationBlock *tb, |
| @@ -193,11 +227,12 @@ int cpu_restore_state(TranslationBlock *tb, | @@ -193,11 +227,12 @@ int cpu_restore_state(TranslationBlock *tb, | ||
| 193 | fprintf(logfile, "RESTORE:\n"); | 227 | fprintf(logfile, "RESTORE:\n"); |
| 194 | for(i=0;i<=j; i++) { | 228 | for(i=0;i<=j; i++) { |
| 195 | if (gen_opc_instr_start[i]) { | 229 | if (gen_opc_instr_start[i]) { |
| 196 | - fprintf(logfile, "0x%04x: 0x%08x\n", i, gen_opc_pc[i]); | 230 | + fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]); |
| 197 | } | 231 | } |
| 198 | } | 232 | } |
| 199 | - fprintf(logfile, "spc=0x%08lx j=0x%x eip=0x%x cs_base=%x\n", | ||
| 200 | - searched_pc, j, gen_opc_pc[j] - tb->cs_base, tb->cs_base); | 233 | + fprintf(logfile, "spc=0x%08lx j=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n", |
| 234 | + searched_pc, j, gen_opc_pc[j] - tb->cs_base, | ||
| 235 | + (uint32_t)tb->cs_base); | ||
| 201 | } | 236 | } |
| 202 | #endif | 237 | #endif |
| 203 | env->eip = gen_opc_pc[j] - tb->cs_base; | 238 | env->eip = gen_opc_pc[j] - tb->cs_base; |