summaryrefslogtreecommitdiff
path: root/tcg
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-02-10 02:41:15 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-02-10 02:41:15 +0000
commit2ba1eeb62c29d23238b95dc7e9ade3444b49f0a1 (patch)
tree5aff38fd46aa4f7ac75447eddf432a6ccb244cc1 /tcg
parent41df841110c6102ee20faae9a172e69a5d4a7f2d (diff)
downloadqemu-2ba1eeb62c29d23238b95dc7e9ade3444b49f0a1.tar.gz
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
Diffstat (limited to 'tcg')
-rw-r--r--tcg/tcg.c39
-rw-r--r--tcg/tcg.h3
2 files changed, 23 insertions, 19 deletions
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 9d3765f708..4ddc62ff17 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -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);
}
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 11e9d8aca6..11ffb0cd46 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -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);