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