Message ID | 20201017022901.78425-5-richard.henderson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | target/s390x: Improve carry computation | expand |
On 17.10.20 04:29, Richard Henderson wrote: > Now that SUB LOGICAL outputs carry, we can use that as input directly. > It also means we can re-use CC_OP_ZC and produce an output carry > directly from SUB LOGICAL WITH BORROW. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > target/s390x/internal.h | 2 -- > target/s390x/cc_helper.c | 32 ----------------- > target/s390x/helper.c | 2 -- > target/s390x/translate.c | 74 ++++++++++++++++++++------------------ > target/s390x/insn-data.def | 8 ++--- > 5 files changed, 44 insertions(+), 74 deletions(-) > > diff --git a/target/s390x/internal.h b/target/s390x/internal.h > index 4077047494..11515bb617 100644 > --- a/target/s390x/internal.h > +++ b/target/s390x/internal.h > @@ -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) */ > diff --git a/target/s390x/cc_helper.c b/target/s390x/cc_helper.c > index c7728d1225..e7039d0d18 100644 > --- a/target/s390x/cc_helper.c > +++ b/target/s390x/cc_helper.c > @@ -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; > diff --git a/target/s390x/helper.c b/target/s390x/helper.c > index fa3aa500e5..7678994feb 100644 > --- a/target/s390x/helper.c > +++ b/target/s390x/helper.c > @@ -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", > diff --git a/target/s390x/translate.c b/target/s390x/translate.c > index 48494a86cc..0d8235a5fb 100644 > --- a/target/s390x/translate.c > +++ b/target/s390x/translate.c > @@ -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; > @@ -4744,29 +4740,49 @@ 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: > + 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: Can you give me a hint how we're converting the carry into a borrow? Can we apply something similar to compute_carry()? > + tcg_gen_subi_i64(cc_src, cc_src, 1); > + break; -- Thanks, David / dhildenb
On 10/20/20 7:17 AM, David Hildenbrand wrote: >> + case CC_OP_ADDU: > > Can you give me a hint how we're converting the carry into a borrow? > > Can we apply something similar to compute_carry()? > >> + tcg_gen_subi_i64(cc_src, cc_src, 1); Right here: subtract one. carry = {1,0} -> borrow = {0,-1} I'll add some more comments for v2. r~
diff --git a/target/s390x/internal.h b/target/s390x/internal.h index 4077047494..11515bb617 100644 --- a/target/s390x/internal.h +++ b/target/s390x/internal.h @@ -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) */ diff --git a/target/s390x/cc_helper.c b/target/s390x/cc_helper.c index c7728d1225..e7039d0d18 100644 --- a/target/s390x/cc_helper.c +++ b/target/s390x/cc_helper.c @@ -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; diff --git a/target/s390x/helper.c b/target/s390x/helper.c index fa3aa500e5..7678994feb 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -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", diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 48494a86cc..0d8235a5fb 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -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; @@ -4744,29 +4740,49 @@ 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: + 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: + 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; } @@ -5305,16 +5321,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); diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 65ee998484..d91051843c 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -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)
Now that SUB LOGICAL outputs carry, we can use that as input directly. It also means we can re-use CC_OP_ZC and produce an output carry directly from SUB LOGICAL WITH BORROW. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/s390x/internal.h | 2 -- target/s390x/cc_helper.c | 32 ----------------- target/s390x/helper.c | 2 -- target/s390x/translate.c | 74 ++++++++++++++++++++------------------ target/s390x/insn-data.def | 8 ++--- 5 files changed, 44 insertions(+), 74 deletions(-)