From 24429cc95657332e3953a21581d3220884da3d75 Mon Sep 17 00:00:00 2001 From: Siddhesh Poyarekar Date: Wed, 8 May 2019 22:14:00 +0530 Subject: [PATCH] arm: Fix up condition codes for conditional arithmetic insn When an arithmetic instruction such as add or sub are combined with a subsequent compare with zero, its following conditional branch code needs fixing up. This is necessary because one could generate an add with a subtract of the negative but such a substitution, while correct on its own, will change the effect on condition flags since while addition of two positive numbers may signal an overflow, addition of a positive and a negative number may not. So if earlier the condition code was GE, it needs to be fixed up to PL to remain correct. We did that for bit operations but not for arithmetic, so do that now. --- src/lj_asm_arm.h | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h index 37bfa40f..e585b4c2 100644 --- a/src/lj_asm_arm.h +++ b/src/lj_asm_arm.h @@ -1412,13 +1412,28 @@ static void asm_intop(ASMState *as, IRIns *ir, ARMIns ai) emit_dn(as, ai^m, dest, left); } -static void asm_intop_s(ASMState *as, IRIns *ir, ARMIns ai) +static ARMIns maybe_drop_zero_cmp(ASMState *as, ARMIns ai) { - if (as->flagmcp == as->mcp) { /* Drop cmp r, #0. */ + if (as->flagmcp == as->mcp) { /* Try to drop cmp r, #0. */ + uint32_t cc = (as->mcp[1] >> 28); as->flagmcp = NULL; - as->mcp++; - ai |= ARMI_S; + if (cc <= CC_NE) { + as->mcp++; + ai |= ARMI_S; + } else if (cc == CC_GE) { + *++as->mcp ^= ((CC_GE^CC_PL) << 28); + ai |= ARMI_S; + } else if (cc == CC_LT) { + *++as->mcp ^= ((CC_LT^CC_MI) << 28); + ai |= ARMI_S; + } /* else: other conds don't work with bit ops. */ } + return ai; +} + +static void asm_intop_s(ASMState *as, IRIns *ir, ARMIns ai) +{ + ai = maybe_drop_zero_cmp(as, ai); asm_intop(as, ir, ai); } @@ -1514,20 +1529,7 @@ static void asm_neg(ASMState *as, IRIns *ir) static void asm_bitop(ASMState *as, IRIns *ir, ARMIns ai) { - if (as->flagmcp == as->mcp) { /* Try to drop cmp r, #0. */ - uint32_t cc = (as->mcp[1] >> 28); - as->flagmcp = NULL; - if (cc <= CC_NE) { - as->mcp++; - ai |= ARMI_S; - } else if (cc == CC_GE) { - *++as->mcp ^= ((CC_GE^CC_PL) << 28); - ai |= ARMI_S; - } else if (cc == CC_LT) { - *++as->mcp ^= ((CC_LT^CC_MI) << 28); - ai |= ARMI_S; - } /* else: other conds don't work with bit ops. */ - } + ai = maybe_drop_zero_cmp(as, ai); if (ir->op2 == 0) { Reg dest = ra_dest(as, ir, RSET_GPR); uint32_t m = asm_fuseopm(as, ai, ir->op1, RSET_GPR); -- 2.21.0