Revision dab2ed99 exec-i386.c
b/exec-i386.c | ||
---|---|---|
38 | 38 |
#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS) |
39 | 39 |
|
40 | 40 |
typedef struct TranslationBlock { |
41 |
unsigned long pc; /* simulated PC corresponding to this block */ |
|
41 |
unsigned long pc; /* simulated PC corresponding to this block (EIP + CS base) */ |
|
42 |
unsigned long cs_base; /* CS base for this block */ |
|
42 | 43 |
unsigned int flags; /* flags defining in which context the code was generated */ |
43 | 44 |
uint8_t *tc_ptr; /* pointer to the translated code */ |
44 | 45 |
struct TranslationBlock *hash_next; /* next matching block */ |
... | ... | |
140 | 141 |
/* find a translation block in the translation cache. If not found, |
141 | 142 |
allocate a new one */ |
142 | 143 |
static inline TranslationBlock *tb_find_and_alloc(unsigned long pc, |
144 |
unsigned long cs_base, |
|
143 | 145 |
unsigned int flags) |
144 | 146 |
{ |
145 | 147 |
TranslationBlock **ptb, *tb; |
... | ... | |
151 | 153 |
tb = *ptb; |
152 | 154 |
if (!tb) |
153 | 155 |
break; |
154 |
if (tb->pc == pc && tb->flags == flags) |
|
156 |
if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
|
|
155 | 157 |
return tb; |
156 | 158 |
ptb = &tb->hash_next; |
157 | 159 |
} |
... | ... | |
161 | 163 |
tb = &tbs[nb_tbs++]; |
162 | 164 |
*ptb = tb; |
163 | 165 |
tb->pc = pc; |
166 |
tb->cs_base = cs_base; |
|
164 | 167 |
tb->flags = flags; |
165 | 168 |
tb->tc_ptr = NULL; |
166 | 169 |
tb->hash_next = NULL; |
... | ... | |
198 | 201 |
int code_gen_size, ret; |
199 | 202 |
void (*gen_func)(void); |
200 | 203 |
TranslationBlock *tb; |
201 |
uint8_t *tc_ptr; |
|
204 |
uint8_t *tc_ptr, *cs_base, *pc;
|
|
202 | 205 |
unsigned int flags; |
203 | 206 |
|
204 | 207 |
/* first we save global registers */ |
... | ... | |
251 | 254 |
/* we compute the CPU state. We assume it will not |
252 | 255 |
change during the whole generated block. */ |
253 | 256 |
flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT; |
257 |
flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT; |
|
254 | 258 |
flags |= (((unsigned long)env->seg_cache[R_DS].base | |
255 | 259 |
(unsigned long)env->seg_cache[R_ES].base | |
256 | 260 |
(unsigned long)env->seg_cache[R_SS].base) != 0) << |
257 | 261 |
GEN_FLAG_ADDSEG_SHIFT; |
258 |
tb = tb_find_and_alloc((unsigned long)env->pc, flags); |
|
262 |
cs_base = env->seg_cache[R_CS].base; |
|
263 |
pc = cs_base + env->eip; |
|
264 |
tb = tb_find_and_alloc((unsigned long)pc, (unsigned long)cs_base, |
|
265 |
flags); |
|
259 | 266 |
tc_ptr = tb->tc_ptr; |
260 | 267 |
if (!tb->tc_ptr) { |
261 | 268 |
/* if no translated code available, then translate it now */ |
262 | 269 |
tc_ptr = code_gen_ptr; |
263 | 270 |
cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE, |
264 |
&code_gen_size, (uint8_t *)env->pc, flags);
|
|
271 |
&code_gen_size, pc, cs_base, flags);
|
|
265 | 272 |
tb->tc_ptr = tc_ptr; |
266 | 273 |
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); |
267 | 274 |
} |
Also available in: Unified diff