From 4d5fe3854033b1b24d20fa4eb40e38dbf34c7cc9 Mon Sep 17 00:00:00 2001 From: acqn Date: Fri, 18 Sep 2020 20:23:03 +0800 Subject: [PATCH] Fixed OptStackOps when the stuff pushed on stack top is accessed before the op. --- src/cc65/codeoptutil.c | 87 ++++++++++++++++-------------------------- src/cc65/codeoptutil.h | 2 +- src/cc65/coptstop.c | 27 +++++++------ 3 files changed, 48 insertions(+), 68 deletions(-) diff --git a/src/cc65/codeoptutil.c b/src/cc65/codeoptutil.c index a4980aa3a..173d5185f 100644 --- a/src/cc65/codeoptutil.c +++ b/src/cc65/codeoptutil.c @@ -1224,66 +1224,43 @@ static int CmpHarmless (const void* Key, const void* Entry) -int HarmlessCall (const char* Name) +int HarmlessCall (const CodeEntry* E, int PushedBytes) /* Check if this is a call to a harmless subroutine that will not interrupt ** the pushax/op sequence when encountered. */ { - static const char* const Tab[] = { - "aslax1", - "aslax2", - "aslax3", - "aslax4", - "aslaxy", - "asrax1", - "asrax2", - "asrax3", - "asrax4", - "asraxy", - "bcastax", - "bnegax", - "complax", - "decax1", - "decax2", - "decax3", - "decax4", - "decax5", - "decax6", - "decax7", - "decax8", - "decaxy", - "incax1", - "incax2", - "incax3", - "incax4", - "incax5", - "incax6", - "incax7", - "incax8", - "incaxy", - "ldaidx", - "ldauidx", - "ldaxidx", - "ldaxysp", - "negax", - "shlax1", - "shlax2", - "shlax3", - "shlax4", - "shlaxy", - "shrax1", - "shrax2", - "shrax3", - "shrax4", - "shraxy", - }; + unsigned Use = 0, Chg = 0; + if (GetFuncInfo (E->Arg, &Use, &Chg) == FNCLS_BUILTIN) { + if ((Chg & REG_SP) != 0) { + return 0; + } + if ((Use & REG_SP) != 0 && + ((Use & (SLV_IND | SLV_TOP)) != SLV_IND || + RegValIsUnknown (E->RI->In.RegY) || + E->RI->In.RegY < PushedBytes)) { + /* If we are using the stack, and we don't have "indirect" + ** addressing mode, or the value of Y is unknown, or less + ** than two, we cannot cope with this piece of code. Having + ** an unknown value of Y means that we cannot correct the + ** stack offset, while having an offset less than PushedBytes + ** means that the code works with the value on stack which + ** is to be removed. + */ + return 0; + } + return 1; + } else { + static const char* const Tab[] = { + "_abs", + }; - void* R = bsearch (Name, - Tab, - sizeof (Tab) / sizeof (Tab[0]), - sizeof (Tab[0]), - CmpHarmless); - return (R != 0); + void* R = bsearch (E->Arg, + Tab, + sizeof (Tab) / sizeof (Tab[0]), + sizeof (Tab[0]), + CmpHarmless); + return (R != 0); + } } diff --git a/src/cc65/codeoptutil.h b/src/cc65/codeoptutil.h index 70aa5f462..140b11236 100644 --- a/src/cc65/codeoptutil.h +++ b/src/cc65/codeoptutil.h @@ -261,7 +261,7 @@ void RemoveRegLoads (StackOpData* D, LoadInfo* LI); void RemoveRemainders (StackOpData* D); /* Remove the code that is unnecessary after translation of the sequence */ -int HarmlessCall (const char* Name); +int HarmlessCall (const CodeEntry* E, int PushedBytes); /* Check if this is a call to a harmless subroutine that will not interrupt ** the pushax/op sequence when encountered. */ diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 01d0b039c..23636e533 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1820,20 +1820,18 @@ unsigned OptStackOps (CodeSeg* S) Data.OpEntry = E; State = FoundOp; break; - } else if (!HarmlessCall (E->Arg)) { - /* A call to an unkown subroutine: We need to start - ** over after the last pushax. Note: This will also - ** happen if we encounter a call to pushax! + } else if (!HarmlessCall (E, 2)) { + /* The call might use or change the content that we are + ** going to access later via the stack pointer. In any + ** case, we need to start over after the last pushax. + ** Note: This will also happen if we encounter a call + ** to pushax! */ I = Data.PushIndex; State = Initialize; break; } - - } else if ((E->Use & REG_SP) != 0 && - (E->AM != AM65_ZP_INDY || - RegValIsUnknown (E->RI->In.RegY) || - E->RI->In.RegY < 2)) { + } else if (((E->Chg | E->Use) & REG_SP) != 0) { /* If we are using the stack, and we don't have "indirect Y" ** addressing mode, or the value of Y is unknown, or less @@ -1843,9 +1841,14 @@ unsigned OptStackOps (CodeSeg* S) ** that the code works with the value on stack which is to ** be removed. */ - I = Data.PushIndex; - State = Initialize; - break; + if (E->AM == AM65_ZPX_IND || + ((E->Chg | E->Use) & SLV_IND) == 0 || + (RegValIsUnknown (E->RI->In.RegY) || + E->RI->In.RegY < 2)) { + I = Data.PushIndex; + State = Initialize; + break; + } }