tcg/mips: fix branch offset during retranslation

Branch offsets should only be overwritten during relocation, to support
partial retranslation.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Aurelien Jarno 2010-03-29 02:09:23 +02:00
parent 91dbed4ba1
commit 6d8ff4d85c

View File

@ -341,6 +341,17 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i
tcg_out32(s, inst); tcg_out32(s, inst);
} }
/*
* Type branch
*/
static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
{
/* We need to keep the offset unchanged for retranslation */
uint16_t offset = (uint16_t)(*(uint32_t *) &s->code_ptr);
tcg_out_opc_imm(s, opc, rt, rs, offset);
}
/* /*
* Type sa * Type sa
*/ */
@ -471,42 +482,42 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
switch (cond) { switch (cond) {
case TCG_COND_EQ: case TCG_COND_EQ:
tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0); tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
break; break;
case TCG_COND_NE: case TCG_COND_NE:
tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0); tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
break; break;
case TCG_COND_LT: case TCG_COND_LT:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_LTU: case TCG_COND_LTU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2); tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_GE: case TCG_COND_GE:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_GEU: case TCG_COND_GEU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2); tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_LE: case TCG_COND_LE:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_LEU: case TCG_COND_LEU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1); tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_GT: case TCG_COND_GT:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_GTU: case TCG_COND_GTU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1); tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break; break;
default: default:
tcg_abort(); tcg_abort();
@ -555,7 +566,7 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
} }
label_ptr = s->code_ptr; label_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0); tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
tcg_out_nop(s); tcg_out_nop(s);
switch(cond) { switch(cond) {
@ -794,20 +805,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
# if TARGET_LONG_BITS == 64 # if TARGET_LONG_BITS == 64
label3_ptr = s->code_ptr; label3_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0); tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
tcg_out_nop(s); tcg_out_nop(s);
tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0, tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh); offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
label1_ptr = s->code_ptr; label1_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0); tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
tcg_out_nop(s); tcg_out_nop(s);
reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr); reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
# else # else
label1_ptr = s->code_ptr; label1_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
tcg_out_nop(s); tcg_out_nop(s);
# endif # endif
@ -849,7 +860,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
} }
label2_ptr = s->code_ptr; label2_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
tcg_out_nop(s); tcg_out_nop(s);
/* label1: fast path */ /* label1: fast path */
@ -982,20 +993,20 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
# if TARGET_LONG_BITS == 64 # if TARGET_LONG_BITS == 64
label3_ptr = s->code_ptr; label3_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0); tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
tcg_out_nop(s); tcg_out_nop(s);
tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0, tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh); offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
label1_ptr = s->code_ptr; label1_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0); tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
tcg_out_nop(s); tcg_out_nop(s);
reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr); reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
# else # else
label1_ptr = s->code_ptr; label1_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
tcg_out_nop(s); tcg_out_nop(s);
# endif # endif
@ -1036,7 +1047,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_nop(s); tcg_out_nop(s);
label2_ptr = s->code_ptr; label2_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
tcg_out_nop(s); tcg_out_nop(s);
/* label1: fast path */ /* label1: fast path */