Skip to content

Commit

Permalink
target/hppa: Fix trans_ds for hppa64
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rth7680 committed Nov 7, 2023
1 parent e1d635e commit 72ca875
Showing 1 changed file with 37 additions and 11 deletions.
48 changes: 37 additions & 11 deletions target/hppa/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand All @@ -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. */
Expand All @@ -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);
Expand Down

0 comments on commit 72ca875

Please sign in to comment.