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:
parent
e1d635e871
commit
72ca87535e
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user