Revision c4687878
b/dyngen-exec.h | ||
---|---|---|
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") |
b/dyngen-op.h | ||
---|---|---|
1 |
static inline int gen_new_label(void) |
|
2 |
{ |
|
3 |
return nb_gen_labels++; |
|
4 |
} |
|
5 |
|
|
6 |
static inline void gen_set_label(int n) |
|
7 |
{ |
|
8 |
gen_labels[n] = gen_opc_ptr - gen_opc_buf; |
|
9 |
} |
b/dyngen.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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" |
b/dyngen.h | ||
---|---|---|
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 | 204 |
} |
204 | 205 |
|
205 | 206 |
#endif /* __arm__ */ |
206 |
|
|
207 |
|
|
208 |
|
b/translate-all.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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; |
Also available in: Unified diff