aboutsummaryrefslogtreecommitdiff
path: root/target/s390x/translate.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2020-12-14 16:13:54 -0600
committerCornelia Huck <cohuck@redhat.com>2020-12-21 18:11:33 +0100
commit3bcc3fa79902d72ab6385bb135e4c3e34931a697 (patch)
tree121c3d691bfb719ada6808802aec50738cc913ab /target/s390x/translate.c
parentff26d287bddc189fd5a084cc96078da1257b0826 (diff)
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>
Diffstat (limited to 'target/s390x/translate.c')
-rw-r--r--target/s390x/translate.c63
1 files changed, 30 insertions, 33 deletions
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index b473233edf..d1d97e4696 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -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:
@@ -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:
@@ -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;
}
@@ -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);