target/s390x: Improve SUB LOGICAL WITH BORROW

Now that SUB LOGICAL outputs borrow, we can use that as input directly.
It also means we can re-use CC_OP_SUBU and produce an output borrow
directly from SUB LOGICAL WITH BORROW.

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

View File

@ -164,19 +164,6 @@ static uint32_t cc_calc_sub_64(int64_t a1, int64_t a2, int64_t ar)
}
}
static uint32_t cc_calc_subb_64(uint64_t a1, uint64_t a2, uint64_t ar)
{
int borrow_out;
if (ar != a1 - a2) { /* difference means borrow-in */
borrow_out = (a2 >= a1);
} else {
borrow_out = (a2 > a1);
}
return (ar != 0) + 2 * !borrow_out;
}
static uint32_t cc_calc_abs_64(int64_t dst)
{
if ((uint64_t)dst == 0x8000000000000000ULL) {
@ -237,19 +224,6 @@ static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar)
}
}
static uint32_t cc_calc_subb_32(uint32_t a1, uint32_t a2, uint32_t ar)
{
int borrow_out;
if (ar != a1 - a2) { /* difference means borrow-in */
borrow_out = (a2 >= a1);
} else {
borrow_out = (a2 > a1);
}
return (ar != 0) + 2 * !borrow_out;
}
static uint32_t cc_calc_abs_32(int32_t dst)
{
if ((uint32_t)dst == 0x80000000UL) {
@ -450,9 +424,6 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_SUB_64:
r = cc_calc_sub_64(src, dst, vr);
break;
case CC_OP_SUBB_64:
r = cc_calc_subb_64(src, dst, vr);
break;
case CC_OP_ABS_64:
r = cc_calc_abs_64(dst);
break;
@ -472,9 +443,6 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_SUB_32:
r = cc_calc_sub_32(src, dst, vr);
break;
case CC_OP_SUBB_32:
r = cc_calc_subb_32(src, dst, vr);
break;
case CC_OP_ABS_32:
r = cc_calc_abs_32(dst);
break;

View File

@ -405,12 +405,10 @@ const char *cc_name(enum cc_op cc_op)
[CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
[CC_OP_ADD_64] = "CC_OP_ADD_64",
[CC_OP_SUB_64] = "CC_OP_SUB_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_SUB_32] = "CC_OP_SUB_32",
[CC_OP_SUBB_32] = "CC_OP_SUBB_32",
[CC_OP_ABS_32] = "CC_OP_ABS_32",
[CC_OP_NABS_32] = "CC_OP_NABS_32",
[CC_OP_COMP_32] = "CC_OP_COMP_32",

View File

@ -916,10 +916,10 @@
C(0xc205, SLFI, RIL_a, EI, r1_32u, i2_32u, new, r1_32, sub, subu32)
C(0xc204, SLGFI, RIL_a, EI, r1, i2_32u, r1, 0, subu64, subu64)
/* SUBTRACT LOGICAL WITH BORROW */
C(0xb999, SLBR, RRE, Z, r1, r2, new, r1_32, subb, subb32)
C(0xb989, SLBGR, RRE, Z, r1, r2, r1, 0, subb, subb64)
C(0xe399, SLB, RXY_a, Z, r1, m2_32u, new, r1_32, subb, subb32)
C(0xe389, SLBG, RXY_a, Z, r1, m2_64, r1, 0, subb, subb64)
C(0xb999, SLBR, RRE, Z, r1_32u, r2_32u, new, r1_32, subb32, subu32)
C(0xb989, SLBGR, RRE, Z, r1, r2, r1, 0, subb64, subu64)
C(0xe399, SLB, RXY_a, Z, r1_32u, m2_32u, new, r1_32, subb32, subu32)
C(0xe389, SLBG, RXY_a, Z, r1, m2_64, r1, 0, subb64, subu64)
/* SUPERVISOR CALL */
C(0x0a00, SVC, I, Z, 0, 0, 0, 0, svc, 0)

View File

@ -172,14 +172,12 @@ enum cc_op {
CC_OP_ADD_64, /* overflow on add (64bit) */
CC_OP_SUB_64, /* overflow on subtraction (64bit) */
CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
CC_OP_ABS_64, /* sign eval on abs (64bit) */
CC_OP_NABS_64, /* sign eval on nabs (64bit) */
CC_OP_MULS_64, /* overflow on signed multiply (64bit) */
CC_OP_ADD_32, /* overflow on add (32bit) */
CC_OP_SUB_32, /* overflow on subtraction (32bit) */
CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
CC_OP_ABS_32, /* sign eval on abs (64bit) */
CC_OP_NABS_32, /* sign eval on nabs (64bit) */
CC_OP_MULS_32, /* overflow on signed multiply (32bit) */

View File

@ -601,10 +601,8 @@ static void gen_op_calc_cc(DisasContext *s)
/* FALLTHRU */
case CC_OP_ADD_64:
case CC_OP_SUB_64:
case CC_OP_SUBB_64:
case CC_OP_ADD_32:
case CC_OP_SUB_32:
case CC_OP_SUBB_32:
local_cc_op = tcg_const_i32(s->cc_op);
break;
case CC_OP_CONST0:
@ -663,10 +661,8 @@ static void gen_op_calc_cc(DisasContext *s)
break;
case CC_OP_ADD_64:
case CC_OP_SUB_64:
case CC_OP_SUBB_64:
case CC_OP_ADD_32:
case CC_OP_SUB_32:
case CC_OP_SUBB_32:
/* 3 arguments */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr);
break;
@ -4746,29 +4742,51 @@ static DisasJumpType op_subu64(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
static DisasJumpType op_subb(DisasContext *s, DisasOps *o)
/* Compute borrow (0, -1) into cc_src. */
static void compute_borrow(DisasContext *s)
{
DisasCompare cmp;
TCGv_i64 borrow;
tcg_gen_sub_i64(o->out, o->in1, o->in2);
/* The !borrow flag is the msb of CC. Since we want the inverse of
that, we ask for a comparison of CC=0 | CC=1 -> mask of 8 | 4. */
disas_jcc(s, &cmp, 8 | 4);
borrow = tcg_temp_new_i64();
if (cmp.is_64) {
tcg_gen_setcond_i64(cmp.cond, borrow, 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(borrow, t);
tcg_temp_free_i32(t);
switch (s->cc_op) {
case CC_OP_SUBU:
/* The borrow value is already in cc_src (0,-1). */
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);
/* fall through */
case CC_OP_ADDU:
/* Convert carry (1,0) to borrow (0,-1). */
tcg_gen_subi_i64(cc_src, cc_src, 1);
break;
}
free_compare(&cmp);
}
static DisasJumpType op_subb32(DisasContext *s, DisasOps *o)
{
compute_borrow(s);
/* Borrow is {0, -1}, so add to subtract. */
tcg_gen_add_i64(o->out, o->in1, cc_src);
tcg_gen_sub_i64(o->out, o->out, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_subb64(DisasContext *s, DisasOps *o)
{
compute_borrow(s);
/*
* Borrow is {0, -1}, so add to subtract; replicate the
* borrow input to produce 128-bit -1 for the addition.
*/
TCGv_i64 zero = tcg_const_i64(0);
tcg_gen_add2_i64(o->out, cc_src, o->in1, zero, cc_src, cc_src);
tcg_gen_sub2_i64(o->out, cc_src, o->out, cc_src, o->in2, zero);
tcg_temp_free_i64(zero);
tcg_gen_sub_i64(o->out, o->out, borrow);
tcg_temp_free_i64(borrow);
return DISAS_NEXT;
}
@ -5307,16 +5325,6 @@ static void cout_subu64(DisasContext *s, DisasOps *o)
gen_op_update2_cc_i64(s, CC_OP_SUBU, cc_src, o->out);
}
static void cout_subb32(DisasContext *s, DisasOps *o)
{
gen_op_update3_cc_i64(s, CC_OP_SUBB_32, o->in1, o->in2, o->out);
}
static void cout_subb64(DisasContext *s, DisasOps *o)
{
gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
}
static void cout_tm32(DisasContext *s, DisasOps *o)
{
gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2);