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; | ... | ... |