aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2012-09-21 11:00:23 -0700
committerRichard Henderson <rth@twiddle.net>2012-09-21 22:02:21 +0200
commitf4bf0b912e780978a37979f7a9fad40f99aa2241 (patch)
treeb199860e5dc89c3c7de53b13d8764db5f8109a50
parent5bbd2cae8e087b4329e17c3f44439096e4c3ec6a (diff)
tcg-sparc: Preserve branch destinations during retranslation
Signed-off-by: Richard Henderson <rth@twiddle.net>
-rw-r--r--tcg/sparc/tcg-target.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 1db0c9d4c3..876da4f6b9 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -488,30 +488,33 @@ static inline void tcg_out_nop(TCGContext *s)
static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
{
TCGLabel *l = &s->labels[label_index];
+ uint32_t off22;
if (l->has_value) {
- tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2)
- | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr)));
+ off22 = INSN_OFF22(l->u.value - (unsigned long)s->code_ptr);
} else {
+ /* Make sure to preserve destinations during retranslation. */
+ off22 = *(uint32_t *)s->code_ptr & INSN_OFF22(-1);
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0);
- tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | 0));
}
+ tcg_out32(s, INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | off22);
}
#if TCG_TARGET_REG_BITS == 64
static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
{
TCGLabel *l = &s->labels[label_index];
+ uint32_t off19;
if (l->has_value) {
- tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
- (0x5 << 19) |
- INSN_OFF19(l->u.value - (unsigned long)s->code_ptr)));
+ off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr);
} else {
+ /* Make sure to preserve destinations during retranslation. */
+ off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1);
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label_index, 0);
- tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
- (0x5 << 19) | 0));
}
+ tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
+ (0x5 << 19) | off19));
}
#endif