diff options
author | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-02-10 02:41:15 +0000 |
---|---|---|
committer | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-02-10 02:41:15 +0000 |
commit | 2ba1eeb62c29d23238b95dc7e9ade3444b49f0a1 (patch) | |
tree | 5aff38fd46aa4f7ac75447eddf432a6ccb244cc1 | |
parent | 41df841110c6102ee20faae9a172e69a5d4a7f2d (diff) | |
download | qemu-2ba1eeb62c29d23238b95dc7e9ade3444b49f0a1.zip qemu-2ba1eeb62c29d23238b95dc7e9ade3444b49f0a1.tar.gz qemu-2ba1eeb62c29d23238b95dc7e9ade3444b49f0a1.tar.bz2 |
Fix TCG relocation bug (exposed by fault after brcond op). Add FIXME for
annother potential bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3968 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | tcg/tcg.c | 39 | ||||
-rw-r--r-- | tcg/tcg.h | 3 | ||||
-rw-r--r-- | translate-all.c | 3 |
3 files changed, 24 insertions, 21 deletions
@@ -97,6 +97,9 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, l = &s->labels[label_index]; if (l->has_value) { + /* FIXME: This is wrong. We can not resolve the relocation + immediately because the caller has not yet written the + initial value. */ patch_reloc(code_ptr, type, l->u.value + addend); } else { /* add a new relocation entry */ @@ -1649,8 +1652,7 @@ void dump_op_count(void) static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, - int do_search_pc, - const uint8_t *searched_pc) + long search_pc) { int opc, op_index, macro_op_index; const TCGOpDef *def; @@ -1754,7 +1756,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, } #endif tcg_reg_alloc_bb_end(s); - if (do_search_pc) { + if (search_pc >= 0) { s->code_ptr += def->copy_size; args += def->nb_args; } else { @@ -1771,13 +1773,11 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, } args += def->nb_args; next: ; - if (do_search_pc) { - if (searched_pc < s->code_ptr) { - if (macro_op_index >= 0) - return macro_op_index; - else - return op_index; - } + if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) { + if (macro_op_index >= 0) + return macro_op_index; + else + return op_index; } op_index++; #ifndef NDEBUG @@ -1802,7 +1802,7 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf) } #endif - tcg_gen_code_common(s, gen_code_buf, 0, NULL); + tcg_gen_code_common(s, gen_code_buf, -1); /* flush instruction cache */ flush_icache_range((unsigned long)gen_code_buf, @@ -1810,11 +1810,16 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf) return s->code_ptr - gen_code_buf; } -/* return the index of the micro operation such as the pc after is < - search_pc. Note: gen_code_buf is accessed during the operation, but - its content should not be modified. Return -1 if not found. */ -int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, - const uint8_t *searched_pc) +static uint8_t *dummy_code_buf; + +/* Return the index of the micro operation such as the pc after is < + offset bytes from the start of the TB. + We have to use a dummy code buffer here to avoid clobbering the + oringinal code. Because we terminate code generation part way through + we can end up with unresolved relocations. Return -1 if not found. */ +int dyngen_code_search_pc(TCGContext *s, long offset) { - return tcg_gen_code_common(s, gen_code_buf, 1, searched_pc); + if (!dummy_code_buf) + dummy_code_buf = qemu_malloc(code_gen_max_block_size()); + return tcg_gen_code_common(s, dummy_code_buf, offset); } @@ -257,8 +257,7 @@ void tcg_context_init(TCGContext *s); void tcg_func_start(TCGContext *s); int dyngen_code(TCGContext *s, uint8_t *gen_code_buf); -int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, - const uint8_t *searched_pc); +int dyngen_code_search_pc(TCGContext *s, long offset); void tcg_set_frame(TCGContext *s, int reg, tcg_target_long start, tcg_target_long size); diff --git a/translate-all.c b/translate-all.c index 9639612..2000083 100644 --- a/translate-all.c +++ b/translate-all.c @@ -187,8 +187,7 @@ int cpu_restore_state(TranslationBlock *tb, s->tb_jmp_offset = NULL; s->tb_next = tb->tb_next; #endif - j = dyngen_code_search_pc(s, (uint8_t *)tc_ptr, - (void *)searched_pc); + j = dyngen_code_search_pc(s, searched_pc - tc_ptr); if (j < 0) return -1; /* now find start of instruction before */ |