mirror of https://github.com/xemu-project/xemu.git
target/hppa: Fix do_add, do_sub for hppa64
Select the proper carry bit for input to the arithmetic and for output for the condition. Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
72ca87535e
commit
bdcccc17ac
|
@ -1094,13 +1094,15 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
|
||||||
TCGv_reg in2, unsigned shift, bool is_l,
|
TCGv_reg in2, unsigned shift, bool is_l,
|
||||||
bool is_tsv, bool is_tc, bool is_c, unsigned cf)
|
bool is_tsv, bool is_tc, bool is_c, unsigned cf)
|
||||||
{
|
{
|
||||||
TCGv_reg dest, cb, cb_msb, sv, tmp;
|
TCGv_reg dest, cb, cb_msb, cb_cond, sv, tmp;
|
||||||
unsigned c = cf >> 1;
|
unsigned c = cf >> 1;
|
||||||
DisasCond cond;
|
DisasCond cond;
|
||||||
|
bool d = false;
|
||||||
|
|
||||||
dest = tcg_temp_new();
|
dest = tcg_temp_new();
|
||||||
cb = NULL;
|
cb = NULL;
|
||||||
cb_msb = NULL;
|
cb_msb = NULL;
|
||||||
|
cb_cond = NULL;
|
||||||
|
|
||||||
if (shift) {
|
if (shift) {
|
||||||
tmp = tcg_temp_new();
|
tmp = tcg_temp_new();
|
||||||
|
@ -1111,19 +1113,22 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
|
||||||
if (!is_l || cond_need_cb(c)) {
|
if (!is_l || cond_need_cb(c)) {
|
||||||
TCGv_reg zero = tcg_constant_reg(0);
|
TCGv_reg zero = tcg_constant_reg(0);
|
||||||
cb_msb = tcg_temp_new();
|
cb_msb = tcg_temp_new();
|
||||||
|
cb = tcg_temp_new();
|
||||||
|
|
||||||
tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
|
tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
|
||||||
if (is_c) {
|
if (is_c) {
|
||||||
tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
|
tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb,
|
||||||
|
get_psw_carry(ctx, d), zero);
|
||||||
}
|
}
|
||||||
if (!is_l) {
|
tcg_gen_xor_reg(cb, in1, in2);
|
||||||
cb = tcg_temp_new();
|
tcg_gen_xor_reg(cb, cb, dest);
|
||||||
tcg_gen_xor_reg(cb, in1, in2);
|
if (cond_need_cb(c)) {
|
||||||
tcg_gen_xor_reg(cb, cb, dest);
|
cb_cond = get_carry(ctx, d, cb, cb_msb);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tcg_gen_add_reg(dest, in1, in2);
|
tcg_gen_add_reg(dest, in1, in2);
|
||||||
if (is_c) {
|
if (is_c) {
|
||||||
tcg_gen_add_reg(dest, dest, cpu_psw_cb_msb);
|
tcg_gen_add_reg(dest, dest, get_psw_carry(ctx, d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1138,7 +1143,7 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit any conditional trap before any writeback. */
|
/* Emit any conditional trap before any writeback. */
|
||||||
cond = do_cond(cf, dest, cb_msb, sv);
|
cond = do_cond(cf, dest, cb_cond, sv);
|
||||||
if (is_tc) {
|
if (is_tc) {
|
||||||
tmp = tcg_temp_new();
|
tmp = tcg_temp_new();
|
||||||
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
|
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
|
||||||
|
@ -1192,6 +1197,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
|
||||||
TCGv_reg dest, sv, cb, cb_msb, zero, tmp;
|
TCGv_reg dest, sv, cb, cb_msb, zero, tmp;
|
||||||
unsigned c = cf >> 1;
|
unsigned c = cf >> 1;
|
||||||
DisasCond cond;
|
DisasCond cond;
|
||||||
|
bool d = false;
|
||||||
|
|
||||||
dest = tcg_temp_new();
|
dest = tcg_temp_new();
|
||||||
cb = tcg_temp_new();
|
cb = tcg_temp_new();
|
||||||
|
@ -1201,15 +1207,17 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
|
||||||
if (is_b) {
|
if (is_b) {
|
||||||
/* DEST,C = IN1 + ~IN2 + C. */
|
/* DEST,C = IN1 + ~IN2 + C. */
|
||||||
tcg_gen_not_reg(cb, in2);
|
tcg_gen_not_reg(cb, in2);
|
||||||
tcg_gen_add2_reg(dest, cb_msb, in1, zero, cpu_psw_cb_msb, zero);
|
tcg_gen_add2_reg(dest, cb_msb, in1, zero, get_psw_carry(ctx, d), zero);
|
||||||
tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cb, zero);
|
tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cb, zero);
|
||||||
tcg_gen_xor_reg(cb, cb, in1);
|
tcg_gen_xor_reg(cb, cb, in1);
|
||||||
tcg_gen_xor_reg(cb, cb, dest);
|
tcg_gen_xor_reg(cb, cb, dest);
|
||||||
} else {
|
} else {
|
||||||
/* DEST,C = IN1 + ~IN2 + 1. We can produce the same result in fewer
|
/*
|
||||||
operations by seeding the high word with 1 and subtracting. */
|
* DEST,C = IN1 + ~IN2 + 1. We can produce the same result in fewer
|
||||||
tcg_gen_movi_reg(cb_msb, 1);
|
* operations by seeding the high word with 1 and subtracting.
|
||||||
tcg_gen_sub2_reg(dest, cb_msb, in1, cb_msb, in2, zero);
|
*/
|
||||||
|
TCGv_reg one = tcg_constant_reg(1);
|
||||||
|
tcg_gen_sub2_reg(dest, cb_msb, in1, one, in2, zero);
|
||||||
tcg_gen_eqv_reg(cb, in1, in2);
|
tcg_gen_eqv_reg(cb, in1, in2);
|
||||||
tcg_gen_xor_reg(cb, cb, dest);
|
tcg_gen_xor_reg(cb, cb, dest);
|
||||||
}
|
}
|
||||||
|
@ -1227,7 +1235,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
|
||||||
if (!is_b) {
|
if (!is_b) {
|
||||||
cond = do_sub_cond(cf, dest, in1, in2, sv);
|
cond = do_sub_cond(cf, dest, in1, in2, sv);
|
||||||
} else {
|
} else {
|
||||||
cond = do_cond(cf, dest, cb_msb, sv);
|
cond = do_cond(cf, dest, get_carry(ctx, d, cb, cb_msb), sv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit any conditional trap before any writeback. */
|
/* Emit any conditional trap before any writeback. */
|
||||||
|
@ -3019,18 +3027,24 @@ static bool trans_cmpbi(DisasContext *ctx, arg_cmpbi *a)
|
||||||
static bool do_addb(DisasContext *ctx, unsigned r, TCGv_reg in1,
|
static bool do_addb(DisasContext *ctx, unsigned r, TCGv_reg in1,
|
||||||
unsigned c, unsigned f, unsigned n, int disp)
|
unsigned c, unsigned f, unsigned n, int disp)
|
||||||
{
|
{
|
||||||
TCGv_reg dest, in2, sv, cb_msb;
|
TCGv_reg dest, in2, sv, cb_cond;
|
||||||
DisasCond cond;
|
DisasCond cond;
|
||||||
|
bool d = false;
|
||||||
|
|
||||||
in2 = load_gpr(ctx, r);
|
in2 = load_gpr(ctx, r);
|
||||||
dest = tcg_temp_new();
|
dest = tcg_temp_new();
|
||||||
sv = NULL;
|
sv = NULL;
|
||||||
cb_msb = NULL;
|
cb_cond = NULL;
|
||||||
|
|
||||||
if (cond_need_cb(c)) {
|
if (cond_need_cb(c)) {
|
||||||
cb_msb = tcg_temp_new();
|
TCGv_reg cb = tcg_temp_new();
|
||||||
|
TCGv_reg cb_msb = tcg_temp_new();
|
||||||
|
|
||||||
tcg_gen_movi_reg(cb_msb, 0);
|
tcg_gen_movi_reg(cb_msb, 0);
|
||||||
tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb);
|
tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb);
|
||||||
|
tcg_gen_xor_reg(cb, in1, in2);
|
||||||
|
tcg_gen_xor_reg(cb, cb, dest);
|
||||||
|
cb_cond = get_carry(ctx, d, cb, cb_msb);
|
||||||
} else {
|
} else {
|
||||||
tcg_gen_add_reg(dest, in1, in2);
|
tcg_gen_add_reg(dest, in1, in2);
|
||||||
}
|
}
|
||||||
|
@ -3038,7 +3052,7 @@ static bool do_addb(DisasContext *ctx, unsigned r, TCGv_reg in1,
|
||||||
sv = do_add_sv(ctx, dest, in1, in2);
|
sv = do_add_sv(ctx, dest, in1, in2);
|
||||||
}
|
}
|
||||||
|
|
||||||
cond = do_cond(c * 2 + f, dest, cb_msb, sv);
|
cond = do_cond(c * 2 + f, dest, cb_cond, sv);
|
||||||
save_gpr(ctx, r, dest);
|
save_gpr(ctx, r, dest);
|
||||||
return do_cbranch(ctx, disp, n, &cond);
|
return do_cbranch(ctx, disp, n, &cond);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue