Hexagon (target/hexagon) Don't overlap dest writes with source reads

When generating TCG, make sure we have read all the operand registers
before writing to the destination registers.

This is a prerequesite for short-circuiting where the source and dest
operands could be the same.

Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20230427230012.3800327-10-tsimpson@quicinc.com>
This commit is contained in:
Taylor Simpson 2023-04-27 16:00:00 -07:00
parent 25e1d87d10
commit 71ed369725

View File

@ -971,6 +971,7 @@ static void gen_cmpi_jumpnv(DisasContext *ctx,
/* Shift left with saturation */
static void gen_shl_sat(DisasContext *ctx, TCGv dst, TCGv src, TCGv shift_amt)
{
TCGv tmp = tcg_temp_new(); /* In case dst == src */
TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
TCGv sh32 = tcg_temp_new();
TCGv dst_sar = tcg_temp_new();
@ -995,17 +996,17 @@ static void gen_shl_sat(DisasContext *ctx, TCGv dst, TCGv src, TCGv shift_amt)
*/
tcg_gen_andi_tl(sh32, shift_amt, 31);
tcg_gen_movcond_tl(TCG_COND_EQ, dst, sh32, shift_amt,
tcg_gen_movcond_tl(TCG_COND_EQ, tmp, sh32, shift_amt,
src, tcg_constant_tl(0));
tcg_gen_shl_tl(dst, dst, sh32);
tcg_gen_sar_tl(dst_sar, dst, sh32);
tcg_gen_shl_tl(tmp, tmp, sh32);
tcg_gen_sar_tl(dst_sar, tmp, sh32);
tcg_gen_movcond_tl(TCG_COND_LT, satval, src, tcg_constant_tl(0), min, max);
tcg_gen_setcond_tl(TCG_COND_NE, ovf, dst_sar, src);
tcg_gen_shli_tl(ovf, ovf, reg_field_info[USR_OVF].offset);
tcg_gen_or_tl(usr, usr, ovf);
tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, dst, satval);
tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, tmp, satval);
}
static void gen_sar(TCGv dst, TCGv src, TCGv shift_amt)
@ -1228,22 +1229,28 @@ void gen_sat_i32(TCGv dest, TCGv source, int width)
void gen_sat_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
{
gen_sat_i32(dest, source, width);
tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, dest);
TCGv tmp = tcg_temp_new(); /* In case dest == source */
gen_sat_i32(tmp, source, width);
tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp);
tcg_gen_mov_tl(dest, tmp);
}
void gen_satu_i32(TCGv dest, TCGv source, int width)
{
TCGv tmp = tcg_temp_new(); /* In case dest == source */
TCGv max_val = tcg_constant_tl((1 << width) - 1);
TCGv zero = tcg_constant_tl(0);
tcg_gen_movcond_tl(TCG_COND_GTU, dest, source, max_val, max_val, source);
tcg_gen_movcond_tl(TCG_COND_LT, dest, source, zero, zero, dest);
tcg_gen_movcond_tl(TCG_COND_GTU, tmp, source, max_val, max_val, source);
tcg_gen_movcond_tl(TCG_COND_LT, tmp, source, zero, zero, tmp);
tcg_gen_mov_tl(dest, tmp);
}
void gen_satu_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
{
gen_satu_i32(dest, source, width);
tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, dest);
TCGv tmp = tcg_temp_new(); /* In case dest == source */
gen_satu_i32(tmp, source, width);
tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp);
tcg_gen_mov_tl(dest, tmp);
}
void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width)
@ -1256,27 +1263,33 @@ void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width)
void gen_sat_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
{
TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */
TCGv_i64 ovfl_64;
gen_sat_i64(dest, source, width);
gen_sat_i64(tmp, source, width);
ovfl_64 = tcg_temp_new_i64();
tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, dest, source);
tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source);
tcg_gen_mov_i64(dest, tmp);
tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
}
void gen_satu_i64(TCGv_i64 dest, TCGv_i64 source, int width)
{
TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */
TCGv_i64 max_val = tcg_constant_i64((1LL << width) - 1LL);
TCGv_i64 zero = tcg_constant_i64(0);
tcg_gen_movcond_i64(TCG_COND_GTU, dest, source, max_val, max_val, source);
tcg_gen_movcond_i64(TCG_COND_LT, dest, source, zero, zero, dest);
tcg_gen_movcond_i64(TCG_COND_GTU, tmp, source, max_val, max_val, source);
tcg_gen_movcond_i64(TCG_COND_LT, tmp, source, zero, zero, tmp);
tcg_gen_mov_i64(dest, tmp);
}
void gen_satu_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
{
TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */
TCGv_i64 ovfl_64;
gen_satu_i64(dest, source, width);
gen_satu_i64(tmp, source, width);
ovfl_64 = tcg_temp_new_i64();
tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, dest, source);
tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source);
tcg_gen_mov_i64(dest, tmp);
tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
}