target/s390x: Improve ADD LOGICAL WITH CARRY

Now that ADD LOGICAL outputs carry, we can use that as input directly.
It also means we can re-use CC_OP_ADDU and produce an output carry
directly from ADD LOGICAL WITH CARRY.

Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20201214221356.68039-3-richard.henderson@linaro.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
Richard Henderson 2020-12-14 16:13:54 -06:00 committed by Cornelia Huck
parent ff26d287bd
commit 3bcc3fa799
5 changed files with 36 additions and 69 deletions

View File

@ -144,16 +144,6 @@ static uint32_t cc_calc_add_64(int64_t a1, int64_t a2, int64_t ar)
} }
} }
static uint32_t cc_calc_addc_64(uint64_t a1, uint64_t a2, uint64_t ar)
{
/* Recover a2 + carry_in. */
uint64_t a2c = ar - a1;
/* Check for a2+carry_in overflow, then a1+a2c overflow. */
int carry_out = (a2c < a2) || (ar < a1);
return (ar != 0) + 2 * carry_out;
}
static uint32_t cc_calc_sub_64(int64_t a1, int64_t a2, int64_t ar) static uint32_t cc_calc_sub_64(int64_t a1, int64_t a2, int64_t ar)
{ {
if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) { if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
@ -240,16 +230,6 @@ static uint32_t cc_calc_add_32(int32_t a1, int32_t a2, int32_t ar)
} }
} }
static uint32_t cc_calc_addc_32(uint32_t a1, uint32_t a2, uint32_t ar)
{
/* Recover a2 + carry_in. */
uint32_t a2c = ar - a1;
/* Check for a2+carry_in overflow, then a1+a2c overflow. */
int carry_out = (a2c < a2) || (ar < a1);
return (ar != 0) + 2 * carry_out;
}
static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar) static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar)
{ {
if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) { if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
@ -485,9 +465,6 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_ADD_64: case CC_OP_ADD_64:
r = cc_calc_add_64(src, dst, vr); r = cc_calc_add_64(src, dst, vr);
break; break;
case CC_OP_ADDC_64:
r = cc_calc_addc_64(src, dst, vr);
break;
case CC_OP_SUB_64: case CC_OP_SUB_64:
r = cc_calc_sub_64(src, dst, vr); r = cc_calc_sub_64(src, dst, vr);
break; break;
@ -513,9 +490,6 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_ADD_32: case CC_OP_ADD_32:
r = cc_calc_add_32(src, dst, vr); r = cc_calc_add_32(src, dst, vr);
break; break;
case CC_OP_ADDC_32:
r = cc_calc_addc_32(src, dst, vr);
break;
case CC_OP_SUB_32: case CC_OP_SUB_32:
r = cc_calc_sub_32(src, dst, vr); r = cc_calc_sub_32(src, dst, vr);
break; break;

View File

@ -403,14 +403,12 @@ const char *cc_name(enum cc_op cc_op)
[CC_OP_LTGT0_32] = "CC_OP_LTGT0_32", [CC_OP_LTGT0_32] = "CC_OP_LTGT0_32",
[CC_OP_LTGT0_64] = "CC_OP_LTGT0_64", [CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
[CC_OP_ADD_64] = "CC_OP_ADD_64", [CC_OP_ADD_64] = "CC_OP_ADD_64",
[CC_OP_ADDC_64] = "CC_OP_ADDC_64",
[CC_OP_SUB_64] = "CC_OP_SUB_64", [CC_OP_SUB_64] = "CC_OP_SUB_64",
[CC_OP_SUBU_64] = "CC_OP_SUBU_64", [CC_OP_SUBU_64] = "CC_OP_SUBU_64",
[CC_OP_SUBB_64] = "CC_OP_SUBB_64", [CC_OP_SUBB_64] = "CC_OP_SUBB_64",
[CC_OP_ABS_64] = "CC_OP_ABS_64", [CC_OP_ABS_64] = "CC_OP_ABS_64",
[CC_OP_NABS_64] = "CC_OP_NABS_64", [CC_OP_NABS_64] = "CC_OP_NABS_64",
[CC_OP_ADD_32] = "CC_OP_ADD_32", [CC_OP_ADD_32] = "CC_OP_ADD_32",
[CC_OP_ADDC_32] = "CC_OP_ADDC_32",
[CC_OP_SUB_32] = "CC_OP_SUB_32", [CC_OP_SUB_32] = "CC_OP_SUB_32",
[CC_OP_SUBU_32] = "CC_OP_SUBU_32", [CC_OP_SUBU_32] = "CC_OP_SUBU_32",
[CC_OP_SUBB_32] = "CC_OP_SUBB_32", [CC_OP_SUBB_32] = "CC_OP_SUBB_32",

View File

@ -82,10 +82,10 @@
C(0xcc0a, ALSIH, RIL_a, HW, r1_sr32, i2_32u, new, r1_32h, add, addu32) C(0xcc0a, ALSIH, RIL_a, HW, r1_sr32, i2_32u, new, r1_32h, add, addu32)
C(0xcc0b, ALSIHN, RIL_a, HW, r1_sr32, i2_32u, new, r1_32h, add, 0) C(0xcc0b, ALSIHN, RIL_a, HW, r1_sr32, i2_32u, new, r1_32h, add, 0)
/* ADD LOGICAL WITH CARRY */ /* ADD LOGICAL WITH CARRY */
C(0xb998, ALCR, RRE, Z, r1, r2, new, r1_32, addc, addc32) C(0xb998, ALCR, RRE, Z, r1_32u, r2_32u, new, r1_32, addc32, addu32)
C(0xb988, ALCGR, RRE, Z, r1, r2, r1, 0, addc, addc64) C(0xb988, ALCGR, RRE, Z, r1, r2, r1, 0, addc64, addu64)
C(0xe398, ALC, RXY_a, Z, r1, m2_32u, new, r1_32, addc, addc32) C(0xe398, ALC, RXY_a, Z, r1_32u, m2_32u, new, r1_32, addc32, addu32)
C(0xe388, ALCG, RXY_a, Z, r1, m2_64, r1, 0, addc, addc64) C(0xe388, ALCG, RXY_a, Z, r1, m2_64, r1, 0, addc64, addu64)
/* AND */ /* AND */
C(0x1400, NR, RR_a, Z, r1, r2, new, r1_32, and, nz32) C(0x1400, NR, RR_a, Z, r1, r2, new, r1_32, and, nz32)

View File

@ -170,7 +170,6 @@ enum cc_op {
CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */ CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
CC_OP_ADD_64, /* overflow on add (64bit) */ CC_OP_ADD_64, /* overflow on add (64bit) */
CC_OP_ADDC_64, /* overflow on unsigned add-carry (64bit) */
CC_OP_SUB_64, /* overflow on subtraction (64bit) */ CC_OP_SUB_64, /* overflow on subtraction (64bit) */
CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */ CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */
CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */ CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
@ -179,7 +178,6 @@ enum cc_op {
CC_OP_MULS_64, /* overflow on signed multiply (64bit) */ CC_OP_MULS_64, /* overflow on signed multiply (64bit) */
CC_OP_ADD_32, /* overflow on add (32bit) */ CC_OP_ADD_32, /* overflow on add (32bit) */
CC_OP_ADDC_32, /* overflow on unsigned add-carry (32bit) */
CC_OP_SUB_32, /* overflow on subtraction (32bit) */ CC_OP_SUB_32, /* overflow on subtraction (32bit) */
CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */ CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */
CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */ CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */

View File

@ -600,12 +600,10 @@ static void gen_op_calc_cc(DisasContext *s)
dummy = tcg_const_i64(0); dummy = tcg_const_i64(0);
/* FALLTHRU */ /* FALLTHRU */
case CC_OP_ADD_64: case CC_OP_ADD_64:
case CC_OP_ADDC_64:
case CC_OP_SUB_64: case CC_OP_SUB_64:
case CC_OP_SUBU_64: case CC_OP_SUBU_64:
case CC_OP_SUBB_64: case CC_OP_SUBB_64:
case CC_OP_ADD_32: case CC_OP_ADD_32:
case CC_OP_ADDC_32:
case CC_OP_SUB_32: case CC_OP_SUB_32:
case CC_OP_SUBU_32: case CC_OP_SUBU_32:
case CC_OP_SUBB_32: case CC_OP_SUBB_32:
@ -665,12 +663,10 @@ static void gen_op_calc_cc(DisasContext *s)
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy); gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
break; break;
case CC_OP_ADD_64: case CC_OP_ADD_64:
case CC_OP_ADDC_64:
case CC_OP_SUB_64: case CC_OP_SUB_64:
case CC_OP_SUBU_64: case CC_OP_SUBU_64:
case CC_OP_SUBB_64: case CC_OP_SUBB_64:
case CC_OP_ADD_32: case CC_OP_ADD_32:
case CC_OP_ADDC_32:
case CC_OP_SUB_32: case CC_OP_SUB_32:
case CC_OP_SUBU_32: case CC_OP_SUBU_32:
case CC_OP_SUBB_32: case CC_OP_SUBB_32:
@ -1443,30 +1439,41 @@ static DisasJumpType op_addu64(DisasContext *s, DisasOps *o)
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_addc(DisasContext *s, DisasOps *o) /* Compute carry into cc_src. */
static void compute_carry(DisasContext *s)
{ {
DisasCompare cmp; switch (s->cc_op) {
TCGv_i64 carry; case CC_OP_ADDU:
/* The carry value is already in cc_src (1,0). */
tcg_gen_add_i64(o->out, o->in1, o->in2); break;
default:
/* The carry flag is the msb of CC, therefore the branch mask that would gen_op_calc_cc(s);
create that comparison is 3. Feeding the generated comparison to /* fall through */
setcond produces the carry flag that we desire. */ case CC_OP_STATIC:
disas_jcc(s, &cmp, 3); /* The carry flag is the msb of CC; compute into cc_src. */
carry = tcg_temp_new_i64(); tcg_gen_extu_i32_i64(cc_src, cc_op);
if (cmp.is_64) { tcg_gen_shri_i64(cc_src, cc_src, 1);
tcg_gen_setcond_i64(cmp.cond, carry, cmp.u.s64.a, cmp.u.s64.b); break;
} else {
TCGv_i32 t = tcg_temp_new_i32();
tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
tcg_gen_extu_i32_i64(carry, t);
tcg_temp_free_i32(t);
} }
free_compare(&cmp); }
static DisasJumpType op_addc32(DisasContext *s, DisasOps *o)
{
compute_carry(s);
tcg_gen_add_i64(o->out, o->in1, o->in2);
tcg_gen_add_i64(o->out, o->out, cc_src);
return DISAS_NEXT;
}
static DisasJumpType op_addc64(DisasContext *s, DisasOps *o)
{
compute_carry(s);
TCGv_i64 zero = tcg_const_i64(0);
tcg_gen_add2_i64(o->out, cc_src, o->in1, zero, cc_src, zero);
tcg_gen_add2_i64(o->out, cc_src, o->out, cc_src, o->in2, zero);
tcg_temp_free_i64(zero);
tcg_gen_add_i64(o->out, o->out, carry);
tcg_temp_free_i64(carry);
return DISAS_NEXT; return DISAS_NEXT;
} }
@ -5217,16 +5224,6 @@ static void cout_addu64(DisasContext *s, DisasOps *o)
gen_op_update2_cc_i64(s, CC_OP_ADDU, cc_src, o->out); gen_op_update2_cc_i64(s, CC_OP_ADDU, cc_src, o->out);
} }
static void cout_addc32(DisasContext *s, DisasOps *o)
{
gen_op_update3_cc_i64(s, CC_OP_ADDC_32, o->in1, o->in2, o->out);
}
static void cout_addc64(DisasContext *s, DisasOps *o)
{
gen_op_update3_cc_i64(s, CC_OP_ADDC_64, o->in1, o->in2, o->out);
}
static void cout_cmps32(DisasContext *s, DisasOps *o) static void cout_cmps32(DisasContext *s, DisasOps *o)
{ {
gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2); gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);