Skip to content

Commit

Permalink
target/s390x: Improve ADD LOGICAL WITH CARRY
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rth7680 authored and cohuck committed Dec 21, 2020
1 parent ff26d28 commit 3bcc3fa
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 67 deletions.
26 changes: 0 additions & 26 deletions target/s390x/cc_helper.c
Expand Up @@ -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)
{
if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
Expand Down Expand Up @@ -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)
{
if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
Expand Down Expand Up @@ -485,9 +465,6 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_ADD_64:
r = cc_calc_add_64(src, dst, vr);
break;
case CC_OP_ADDC_64:
r = cc_calc_addc_64(src, dst, vr);
break;
case CC_OP_SUB_64:
r = cc_calc_sub_64(src, dst, vr);
break;
Expand All @@ -513,9 +490,6 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_ADD_32:
r = cc_calc_add_32(src, dst, vr);
break;
case CC_OP_ADDC_32:
r = cc_calc_addc_32(src, dst, vr);
break;
case CC_OP_SUB_32:
r = cc_calc_sub_32(src, dst, vr);
break;
Expand Down
2 changes: 0 additions & 2 deletions target/s390x/helper.c
Expand Up @@ -403,14 +403,12 @@ const char *cc_name(enum cc_op cc_op)
[CC_OP_LTGT0_32] = "CC_OP_LTGT0_32",
[CC_OP_LTGT0_64] = "CC_OP_LTGT0_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_SUBU_64] = "CC_OP_SUBU_64",
[CC_OP_SUBB_64] = "CC_OP_SUBB_64",
[CC_OP_ABS_64] = "CC_OP_ABS_64",
[CC_OP_NABS_64] = "CC_OP_NABS_64",
[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_SUBU_32] = "CC_OP_SUBU_32",
[CC_OP_SUBB_32] = "CC_OP_SUBB_32",
Expand Down
8 changes: 4 additions & 4 deletions target/s390x/insn-data.def
Expand Up @@ -82,10 +82,10 @@
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)
/* ADD LOGICAL WITH CARRY */
C(0xb998, ALCR, RRE, Z, r1, r2, new, r1_32, addc, addc32)
C(0xb988, ALCGR, RRE, Z, r1, r2, r1, 0, addc, addc64)
C(0xe398, ALC, RXY_a, Z, r1, m2_32u, new, r1_32, addc, addc32)
C(0xe388, ALCG, RXY_a, Z, r1, m2_64, r1, 0, addc, addc64)
C(0xb998, ALCR, RRE, Z, r1_32u, r2_32u, new, r1_32, addc32, addu32)
C(0xb988, ALCGR, RRE, Z, r1, r2, r1, 0, addc64, addu64)
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, addc64, addu64)

/* AND */
C(0x1400, NR, RR_a, Z, r1, r2, new, r1_32, and, nz32)
Expand Down
2 changes: 0 additions & 2 deletions target/s390x/internal.h
Expand Up @@ -170,7 +170,6 @@ enum cc_op {
CC_OP_LTGT0_64, /* signed less/greater than 0 (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_SUBU_64, /* overflow on unsigned subtraction (64bit) */
CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
Expand All @@ -179,7 +178,6 @@ enum cc_op {
CC_OP_MULS_64, /* overflow on signed multiply (64bit) */

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_SUBU_32, /* overflow on unsigned subtraction (32bit) */
CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
Expand Down
63 changes: 30 additions & 33 deletions target/s390x/translate.c
Expand Up @@ -600,12 +600,10 @@ static void gen_op_calc_cc(DisasContext *s)
dummy = tcg_const_i64(0);
/* FALLTHRU */
case CC_OP_ADD_64:
case CC_OP_ADDC_64:
case CC_OP_SUB_64:
case CC_OP_SUBU_64:
case CC_OP_SUBB_64:
case CC_OP_ADD_32:
case CC_OP_ADDC_32:
case CC_OP_SUB_32:
case CC_OP_SUBU_32:
case CC_OP_SUBB_32:
Expand Down Expand Up @@ -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);
break;
case CC_OP_ADD_64:
case CC_OP_ADDC_64:
case CC_OP_SUB_64:
case CC_OP_SUBU_64:
case CC_OP_SUBB_64:
case CC_OP_ADD_32:
case CC_OP_ADDC_32:
case CC_OP_SUB_32:
case CC_OP_SUBU_32:
case CC_OP_SUBB_32:
Expand Down Expand Up @@ -1443,30 +1439,41 @@ static DisasJumpType op_addu64(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}

static DisasJumpType op_addc(DisasContext *s, DisasOps *o)
/* Compute carry into cc_src. */
static void compute_carry(DisasContext *s)
{
DisasCompare cmp;
TCGv_i64 carry;
switch (s->cc_op) {
case CC_OP_ADDU:
/* The carry value is already in cc_src (1,0). */
break;
default:
gen_op_calc_cc(s);
/* fall through */
case CC_OP_STATIC:
/* The carry flag is the msb of CC; compute into cc_src. */
tcg_gen_extu_i32_i64(cc_src, cc_op);
tcg_gen_shri_i64(cc_src, cc_src, 1);
break;
}
}

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;
}

/* The carry flag is the msb of CC, therefore the branch mask that would
create that comparison is 3. Feeding the generated comparison to
setcond produces the carry flag that we desire. */
disas_jcc(s, &cmp, 3);
carry = tcg_temp_new_i64();
if (cmp.is_64) {
tcg_gen_setcond_i64(cmp.cond, carry, cmp.u.s64.a, cmp.u.s64.b);
} 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_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;
}

Expand Down Expand Up @@ -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);
}

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)
{
gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
Expand Down

0 comments on commit 3bcc3fa

Please sign in to comment.