target/hppa: Fix trans_ds for hppa64

This instruction always uses the input carry from bit 32,
but produces all 16 output carry bits.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-09-16 16:28:23 -07:00
parent e1d635e871
commit 72ca87535e

View file

@ -803,6 +803,12 @@ static bool cond_need_cb(int c)
return c == 4 || c == 5;
}
/* Need extensions from TCGv_i32 to TCGv_reg. */
static bool cond_need_ext(DisasContext *ctx, bool d)
{
return TARGET_REGISTER_BITS == 64 && !d;
}
/*
* Compute conditional for arithmetic. See Page 5-3, Table 5-1, of
* the Parisc 1.1 Architecture Reference Manual for details.
@ -1040,6 +1046,22 @@ static DisasCond do_unit_cond(unsigned cf, TCGv_reg res,
return cond;
}
static TCGv_reg get_carry(DisasContext *ctx, bool d,
TCGv_reg cb, TCGv_reg cb_msb)
{
if (cond_need_ext(ctx, d)) {
TCGv_reg t = tcg_temp_new();
tcg_gen_extract_reg(t, cb, 32, 1);
return t;
}
return cb_msb;
}
static TCGv_reg get_psw_carry(DisasContext *ctx, bool d)
{
return get_carry(ctx, d, cpu_psw_cb, cpu_psw_cb_msb);
}
/* Compute signed overflow for addition. */
static TCGv_reg do_add_sv(DisasContext *ctx, TCGv_reg res,
TCGv_reg in1, TCGv_reg in2)
@ -2712,6 +2734,7 @@ static bool trans_dcor_i(DisasContext *ctx, arg_rr_cf *a)
static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
{
TCGv_reg dest, add1, add2, addc, zero, in1, in2;
TCGv_reg cout;
nullify_over(ctx);
@ -2726,18 +2749,20 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
/* Form R1 << 1 | PSW[CB]{8}. */
tcg_gen_add_reg(add1, in1, in1);
tcg_gen_add_reg(add1, add1, cpu_psw_cb_msb);
tcg_gen_add_reg(add1, add1, get_psw_carry(ctx, false));
/* Add or subtract R2, depending on PSW[V]. Proper computation of
carry{8} requires that we subtract via + ~R2 + 1, as described in
the manual. By extracting and masking V, we can produce the
proper inputs to the addition without movcond. */
tcg_gen_sari_reg(addc, cpu_psw_v, TARGET_REGISTER_BITS - 1);
/*
* Add or subtract R2, depending on PSW[V]. Proper computation of
* carry requires that we subtract via + ~R2 + 1, as described in
* the manual. By extracting and masking V, we can produce the
* proper inputs to the addition without movcond.
*/
tcg_gen_sextract_reg(addc, cpu_psw_v, 31, 1);
tcg_gen_xor_reg(add2, in2, addc);
tcg_gen_andi_reg(addc, addc, 1);
/* ??? This is only correct for 32-bit. */
tcg_gen_add2_i32(dest, cpu_psw_cb_msb, add1, zero, add2, zero);
tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero);
tcg_gen_add2_reg(dest, cpu_psw_cb_msb, add1, zero, add2, zero);
tcg_gen_add2_reg(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero);
/* Write back the result register. */
save_gpr(ctx, a->t, dest);
@ -2747,7 +2772,8 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
tcg_gen_xor_reg(cpu_psw_cb, cpu_psw_cb, dest);
/* Write back PSW[V] for the division step. */
tcg_gen_neg_reg(cpu_psw_v, cpu_psw_cb_msb);
cout = get_psw_carry(ctx, false);
tcg_gen_neg_reg(cpu_psw_v, cout);
tcg_gen_xor_reg(cpu_psw_v, cpu_psw_v, in2);
/* Install the new nullification. */
@ -2757,7 +2783,7 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
/* ??? The lshift is supposed to contribute to overflow. */
sv = do_add_sv(ctx, dest, add1, add2);
}
ctx->null_cond = do_cond(a->cf, dest, cpu_psw_cb_msb, sv);
ctx->null_cond = do_cond(a->cf, dest, cout, sv);
}
return nullify_end(ctx);