From a359b770c60bf3085c244bc9d5a5fd8fcf286bce Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 20 Sep 2012 09:41:33 -0700 Subject: target-s390: Optimize ADDU/SUBU CC testing We can easily generate some masks for logical add/subtract inline. Signed-off-by: Richard Henderson --- target-s390x/translate.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'target-s390x') diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 2949bb1fc4..04001e34d4 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -692,6 +692,49 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) account_inline_branch(s, old_cc_op); break; + case CC_OP_ADDU_32: + case CC_OP_ADDU_64: + switch (mask) { + case 8 | 2: /* vr == 0 */ + cond = TCG_COND_EQ; + break; + case 4 | 1: /* vr != 0 */ + cond = TCG_COND_NE; + break; + case 8 | 4: /* no carry -> vr >= src */ + cond = TCG_COND_GEU; + break; + case 2 | 1: /* carry -> vr < src */ + cond = TCG_COND_LTU; + break; + default: + goto do_dynamic; + } + account_inline_branch(s, old_cc_op); + break; + + case CC_OP_SUBU_32: + case CC_OP_SUBU_64: + /* Note that CC=0 is impossible; treat it as dont-care. */ + switch (mask & 7) { + case 2: /* zero -> op1 == op2 */ + cond = TCG_COND_EQ; + break; + case 4 | 1: /* !zero -> op1 != op2 */ + cond = TCG_COND_NE; + break; + case 4: /* borrow (!carry) -> op1 < op2 */ + cond = TCG_COND_LTU; + break; + case 2 | 1: /* !borrow (carry) -> op1 >= op2 */ + cond = TCG_COND_GEU; + break; + default: + goto do_dynamic; + } + account_inline_branch(s, old_cc_op); + break; + default: do_dynamic: /* Calculate cc value. */ @@ -719,6 +762,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) break; case CC_OP_LTGT_32: case CC_OP_LTUGTU_32: + case CC_OP_SUBU_32: c->is_64 = false; c->u.s32.a = tcg_temp_new_i32(); tcg_gen_trunc_i64_i32(c->u.s32.a, cc_src); @@ -735,6 +779,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) break; case CC_OP_LTGT_64: case CC_OP_LTUGTU_64: + case CC_OP_SUBU_64: c->u.s64.a = cc_src; c->u.s64.b = cc_dst; c->g1 = c->g2 = true; @@ -748,6 +793,29 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst); break; + case CC_OP_ADDU_32: + c->is_64 = false; + c->u.s32.a = tcg_temp_new_i32(); + c->u.s32.b = tcg_temp_new_i32(); + tcg_gen_trunc_i64_i32(c->u.s32.a, cc_vr); + if (cond == TCG_COND_EQ || cond == TCG_COND_NE) { + tcg_gen_movi_i32(c->u.s32.b, 0); + } else { + tcg_gen_trunc_i64_i32(c->u.s32.b, cc_src); + } + break; + + case CC_OP_ADDU_64: + c->u.s64.a = cc_vr; + c->g1 = true; + if (cond == TCG_COND_EQ || cond == TCG_COND_NE) { + c->u.s64.b = tcg_const_i64(0); + } else { + c->u.s64.b = cc_src; + c->g2 = true; + } + break; + case CC_OP_STATIC: c->is_64 = false; c->u.s32.a = cc_op; -- cgit v1.2.3