1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-02 04:41:35 +00:00

Fixed OptStackOps when the stuff pushed on stack top is accessed before the op.

This commit is contained in:
acqn 2020-09-18 20:23:03 +08:00 committed by Oliver Schmidt
parent 79be6dec16
commit 4d5fe38540
3 changed files with 48 additions and 68 deletions

View File

@ -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 /* Check if this is a call to a harmless subroutine that will not interrupt
** the pushax/op sequence when encountered. ** the pushax/op sequence when encountered.
*/ */
{ {
static const char* const Tab[] = { unsigned Use = 0, Chg = 0;
"aslax1", if (GetFuncInfo (E->Arg, &Use, &Chg) == FNCLS_BUILTIN) {
"aslax2", if ((Chg & REG_SP) != 0) {
"aslax3", return 0;
"aslax4", }
"aslaxy", if ((Use & REG_SP) != 0 &&
"asrax1", ((Use & (SLV_IND | SLV_TOP)) != SLV_IND ||
"asrax2", RegValIsUnknown (E->RI->In.RegY) ||
"asrax3", E->RI->In.RegY < PushedBytes)) {
"asrax4", /* If we are using the stack, and we don't have "indirect"
"asraxy", ** addressing mode, or the value of Y is unknown, or less
"bcastax", ** than two, we cannot cope with this piece of code. Having
"bnegax", ** an unknown value of Y means that we cannot correct the
"complax", ** stack offset, while having an offset less than PushedBytes
"decax1", ** means that the code works with the value on stack which
"decax2", ** is to be removed.
"decax3", */
"decax4", return 0;
"decax5", }
"decax6", return 1;
"decax7", } else {
"decax8", static const char* const Tab[] = {
"decaxy", "_abs",
"incax1", };
"incax2",
"incax3",
"incax4",
"incax5",
"incax6",
"incax7",
"incax8",
"incaxy",
"ldaidx",
"ldauidx",
"ldaxidx",
"ldaxysp",
"negax",
"shlax1",
"shlax2",
"shlax3",
"shlax4",
"shlaxy",
"shrax1",
"shrax2",
"shrax3",
"shrax4",
"shraxy",
};
void* R = bsearch (Name, void* R = bsearch (E->Arg,
Tab, Tab,
sizeof (Tab) / sizeof (Tab[0]), sizeof (Tab) / sizeof (Tab[0]),
sizeof (Tab[0]), sizeof (Tab[0]),
CmpHarmless); CmpHarmless);
return (R != 0); return (R != 0);
}
} }

View File

@ -261,7 +261,7 @@ void RemoveRegLoads (StackOpData* D, LoadInfo* LI);
void RemoveRemainders (StackOpData* D); void RemoveRemainders (StackOpData* D);
/* Remove the code that is unnecessary after translation of the sequence */ /* 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 /* Check if this is a call to a harmless subroutine that will not interrupt
** the pushax/op sequence when encountered. ** the pushax/op sequence when encountered.
*/ */

View File

@ -1820,20 +1820,18 @@ unsigned OptStackOps (CodeSeg* S)
Data.OpEntry = E; Data.OpEntry = E;
State = FoundOp; State = FoundOp;
break; break;
} else if (!HarmlessCall (E->Arg)) { } else if (!HarmlessCall (E, 2)) {
/* A call to an unkown subroutine: We need to start /* The call might use or change the content that we are
** over after the last pushax. Note: This will also ** going to access later via the stack pointer. In any
** happen if we encounter a call to pushax! ** 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; I = Data.PushIndex;
State = Initialize; State = Initialize;
break; break;
} }
} else if (((E->Chg | E->Use) & REG_SP) != 0) {
} else if ((E->Use & REG_SP) != 0 &&
(E->AM != AM65_ZP_INDY ||
RegValIsUnknown (E->RI->In.RegY) ||
E->RI->In.RegY < 2)) {
/* If we are using the stack, and we don't have "indirect Y" /* If we are using the stack, and we don't have "indirect Y"
** addressing mode, or the value of Y is unknown, or less ** 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 ** that the code works with the value on stack which is to
** be removed. ** be removed.
*/ */
I = Data.PushIndex; if (E->AM == AM65_ZPX_IND ||
State = Initialize; ((E->Chg | E->Use) & SLV_IND) == 0 ||
break; (RegValIsUnknown (E->RI->In.RegY) ||
E->RI->In.RegY < 2)) {
I = Data.PushIndex;
State = Initialize;
break;
}
} }