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 | 211 | |
| 212 | 212 | #ifdef __i386__ |
| 213 | 213 | #define EXIT_TB() asm volatile ("ret") |
| 214 | +#define GOTO_LABEL_PARAM(n) asm volatile ("jmp __op_gen_label" #n) | |
| 214 | 215 | #endif |
| 215 | 216 | #ifdef __x86_64__ |
| 216 | 217 | #define EXIT_TB() asm volatile ("ret") |
| 217 | 218 | #endif |
| 218 | 219 | #ifdef __powerpc__ |
| 219 | 220 | #define EXIT_TB() asm volatile ("blr") |
| 221 | +#define GOTO_LABEL_PARAM(n) asm volatile ("b __op_gen_label" #n) | |
| 220 | 222 | #endif |
| 221 | 223 | #ifdef __s390__ |
| 222 | 224 | #define EXIT_TB() asm volatile ("br %r14") | ... | ... |
dyngen-op.h
0 → 100644
dyngen.c
| ... | ... | @@ -54,7 +54,7 @@ |
| 54 | 54 | #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) |
| 55 | 55 | #undef ELF_USES_RELOCA |
| 56 | 56 | |
| 57 | -#elif defined(HOST_AMD64) | |
| 57 | +#elif defined(HOST_X86_64) | |
| 58 | 58 | |
| 59 | 59 | #define ELF_CLASS ELFCLASS64 |
| 60 | 60 | #define ELF_ARCH EM_X86_64 |
| ... | ... | @@ -1307,7 +1307,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 1307 | 1307 | p_start = text + offset; |
| 1308 | 1308 | p_end = p_start + size; |
| 1309 | 1309 | start_offset = offset; |
| 1310 | -#if defined(HOST_I386) || defined(HOST_AMD64) | |
| 1310 | +#if defined(HOST_I386) || defined(HOST_X86_64) | |
| 1311 | 1311 | #ifdef CONFIG_FORMAT_COFF |
| 1312 | 1312 | { |
| 1313 | 1313 | uint8_t *p; |
| ... | ... | @@ -1482,7 +1482,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 1482 | 1482 | sym_name = get_rel_sym_name(rel); |
| 1483 | 1483 | if(!sym_name) |
| 1484 | 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 | 1487 | n = strtoul(p, NULL, 10); |
| 1487 | 1488 | if (n > MAX_ARGS) |
| 1488 | 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 | 1526 | continue; |
| 1526 | 1527 | if (*sym_name && |
| 1527 | 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 | 1531 | #if defined(HOST_SPARC) |
| 1530 | 1532 | if (sym_name[0] == '.') { |
| 1531 | 1533 | fprintf(outfile, |
| ... | ... | @@ -1604,8 +1606,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 1604 | 1606 | } |
| 1605 | 1607 | } |
| 1606 | 1608 | #endif |
| 1607 | - | |
| 1608 | - if (val >= start_offset && val < start_offset + copy_size) { | |
| 1609 | + if (val >= start_offset && val <= start_offset + copy_size) { | |
| 1609 | 1610 | n = strtol(p, NULL, 10); |
| 1610 | 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 | 1643 | |
| 1643 | 1644 | if (strstart(sym_name, "__op_param", &p)) { |
| 1644 | 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 | 1648 | } else { |
| 1646 | 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 | 1696 | } |
| 1694 | 1697 | } |
| 1695 | 1698 | } |
| 1696 | -#elif defined(HOST_AMD64) | |
| 1699 | +#elif defined(HOST_X86_64) | |
| 1697 | 1700 | { |
| 1698 | 1701 | char name[256]; |
| 1699 | 1702 | int type; |
| ... | ... | @@ -1723,7 +1726,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 1723 | 1726 | rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend); |
| 1724 | 1727 | break; |
| 1725 | 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 | 2235 | } |
| 2233 | 2236 | } else if (out_type == OUT_GEN_OP) { |
| 2234 | 2237 | /* generate gen_xxx functions */ |
| 2235 | - | |
| 2238 | + fprintf(outfile, "#include \"dyngen-op.h\"\n"); | |
| 2236 | 2239 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
| 2237 | 2240 | const char *name; |
| 2238 | 2241 | name = get_sym_name(sym); |
| ... | ... | @@ -2250,7 +2253,7 @@ int gen_file(FILE *outfile, int out_type) |
| 2250 | 2253 | fprintf(outfile, |
| 2251 | 2254 | "int dyngen_code(uint8_t *gen_code_buf,\n" |
| 2252 | 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 | 2257 | "{\n" |
| 2255 | 2258 | " uint8_t *gen_code_ptr;\n" |
| 2256 | 2259 | " const uint16_t *opc_ptr;\n" | ... | ... |
dyngen.h
| ... | ... | @@ -19,6 +19,7 @@ |
| 19 | 19 | */ |
| 20 | 20 | |
| 21 | 21 | int __op_param1, __op_param2, __op_param3; |
| 22 | +int __op_gen_label1, __op_gen_label2, __op_gen_label3; | |
| 22 | 23 | int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; |
| 23 | 24 | |
| 24 | 25 | #ifdef __i386__ |
| ... | ... | @@ -203,6 +204,3 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr, |
| 203 | 204 | } |
| 204 | 205 | |
| 205 | 206 | #endif /* __arm__ */ |
| 206 | - | |
| 207 | - | |
| 208 | - | ... | ... |
translate-all.c
| ... | ... | @@ -42,12 +42,15 @@ enum { |
| 42 | 42 | |
| 43 | 43 | uint16_t gen_opc_buf[OPC_BUF_SIZE]; |
| 44 | 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 | 49 | uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; |
| 47 | 50 | #if defined(TARGET_I386) |
| 48 | 51 | uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; |
| 49 | 52 | #elif defined(TARGET_SPARC) |
| 50 | -uint32_t gen_opc_npc[OPC_BUF_SIZE]; | |
| 53 | +target_ulong gen_opc_npc[OPC_BUF_SIZE]; | |
| 51 | 54 | #endif |
| 52 | 55 | |
| 53 | 56 | int code_copy_enabled = 1; |
| ... | ... | @@ -65,6 +68,12 @@ static uint8_t op_nb_args[] = { |
| 65 | 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 | 77 | void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) |
| 69 | 78 | { |
| 70 | 79 | const uint16_t *opc_ptr; |
| ... | ... | @@ -90,6 +99,35 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) |
| 90 | 99 | |
| 91 | 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 | 131 | /* return non zero if the very first instruction is invalid so that |
| 94 | 132 | the virtual CPU can trigger an exception. |
| 95 | 133 | |
| ... | ... | @@ -121,19 +159,21 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, |
| 121 | 159 | tb->tb_jmp_offset[2] = 0xffff; |
| 122 | 160 | tb->tb_jmp_offset[3] = 0xffff; |
| 123 | 161 | #endif |
| 162 | + dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf); | |
| 163 | + | |
| 124 | 164 | gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, |
| 125 | 165 | #ifdef USE_DIRECT_JUMP |
| 126 | 166 | tb->tb_jmp_offset, |
| 127 | 167 | #else |
| 128 | 168 | NULL, |
| 129 | 169 | #endif |
| 130 | - gen_opc_buf, gen_opparam_buf); | |
| 170 | + gen_opc_buf, gen_opparam_buf, gen_labels); | |
| 131 | 171 | } |
| 132 | 172 | *gen_code_size_ptr = gen_code_size; |
| 133 | 173 | #ifdef DEBUG_DISAS |
| 134 | 174 | if (loglevel & CPU_LOG_TB_OUT_ASM) { |
| 135 | 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 | 177 | fprintf(logfile, "\n"); |
| 138 | 178 | fflush(logfile); |
| 139 | 179 | } |
| ... | ... | @@ -141,12 +181,6 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, |
| 141 | 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 | 184 | /* The cpu state corresponding to 'searched_pc' is restored. |
| 151 | 185 | */ |
| 152 | 186 | int cpu_restore_state(TranslationBlock *tb, |
| ... | ... | @@ -193,11 +227,12 @@ int cpu_restore_state(TranslationBlock *tb, |
| 193 | 227 | fprintf(logfile, "RESTORE:\n"); |
| 194 | 228 | for(i=0;i<=j; i++) { |
| 195 | 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 | 237 | #endif |
| 203 | 238 | env->eip = gen_opc_pc[j] - tb->cs_base; | ... | ... |