X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcc65%2Fcoptstop.c;h=85824b64d148f6bced31f0e8338c263584f16270;hb=c6ee5a841878ccdbf9ab85d3dafdd088648b93ba;hp=50fd73b4e6b6f7d158024d262875dc5b42d1166a;hpb=fa3a7930d789e44d290a661c355bda26a7f7abd0;p=cc65 diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 50fd73b4e..85824b64d 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -58,6 +58,7 @@ typedef enum { LI_DIRECT = 0x01, /* Direct op may be used */ LI_RELOAD_Y = 0x02, /* Reload index register Y */ LI_REMOVE = 0x04, /* Load may be removed */ + LI_DUP_LOAD = 0x08, /* Duplicate load */ } LI_FLAGS; /* Structure that tells us how to load the lhs values */ @@ -258,9 +259,17 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) RI = &LI->X; } else if (E->Chg & REG_Y) { RI = &LI->Y; - } + } CHECK (RI != 0); + /* If we had a load or xfer op before, this is a duplicate load which + * can cause problems if it encountered between the pushax and the op, + * so remember it. + */ + if (RI->LoadIndex >= 0 || RI->XferIndex >= 0) { + RI->Flags |= LI_DUP_LOAD; + } + /* Remember the load */ RI->LoadIndex = I; RI->XferIndex = -1; @@ -299,6 +308,14 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) default: Internal ("Unknown XFR insn in TrackLoads"); } + /* If we had a load or xfer op before, this is a duplicate load which + * can cause problems if it encountered between the pushax and the op, + * so remember it. + */ + if (Tgt->LoadIndex >= 0 || Tgt->XferIndex >= 0) { + Tgt->Flags |= LI_DUP_LOAD; + } + /* Transfer the data */ Tgt->LoadIndex = Src->LoadIndex; Tgt->XferIndex = I; @@ -308,6 +325,17 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) } else if (CE_IsCallTo (E, "ldaxysp") && RegValIsKnown (E->RI->In.RegY)) { + /* If we had a load or xfer op before, this is a duplicate load which + * can cause problems if it encountered between the pushax and the op, + * so remember it for both registers involved. + */ + if (LI->A.LoadIndex >= 0 || LI->A.XferIndex >= 0) { + LI->A.Flags |= LI_DUP_LOAD; + } + if (LI->X.LoadIndex >= 0 || LI->X.XferIndex >= 0) { + LI->X.Flags |= LI_DUP_LOAD; + } + /* Both registers set, Y changed */ LI->A.LoadIndex = I; LI->A.XferIndex = -1; @@ -1576,6 +1604,24 @@ static int HarmlessCall (const char* Name) "asrax3", "asrax4", "bnegax", + "decax1", + "decax2", + "decax3", + "decax4", + "decax5", + "decax6", + "decax7", + "decax8", + "decaxy", + "incax1", + "incax2", + "incax3", + "incax4", + "incax5", + "incax6", + "incax7", + "incax8", + "incaxy", "ldaxidx", "ldaxysp", "negax", @@ -1659,6 +1705,10 @@ static int PreCondOk (StackOpData* D) } } } + if ((D->Rhs.A.Flags | D->Rhs.X.Flags) & LI_DUP_LOAD) { + /* Cannot optimize */ + return 0; + } /* Determine the zero page locations to use */ if ((D->UsedRegs & REG_PTR1) == REG_NONE) { @@ -1692,7 +1742,8 @@ unsigned OptStackOps (CodeSeg* S) { unsigned Changes = 0; /* Number of changes in one run */ StackOpData Data; - unsigned I; + int I; + int OldEntryCount; /* Old number of entries */ enum { Initialize, @@ -1702,9 +1753,6 @@ unsigned OptStackOps (CodeSeg* S) } State = Initialize; - /* Generate register info */ - CS_GenRegInfo (S); - /* Remember the code segment in the info struct */ Data.Code = S; @@ -1724,7 +1772,7 @@ unsigned OptStackOps (CodeSeg* S) * intermediate code for zero page use. */ I = 0; - while (I < CS_GetEntryCount (S)) { + while (I < (int)CS_GetEntryCount (S)) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); @@ -1858,6 +1906,9 @@ unsigned OptStackOps (CodeSeg* S) Data.OpEntry = CS_GetEntry (S, Data.OpIndex); Data.NextEntry = CS_GetNextEntry (S, Data.OpIndex); + /* Remember the current number of code lines */ + OldEntryCount = CS_GetEntryCount (S); + /* Adjust stack offsets to account for the upcoming removal */ AdjustStackOffset (&Data, 2); @@ -1869,12 +1920,17 @@ unsigned OptStackOps (CodeSeg* S) /* Call the optimizer function */ Changes += Data.OptFunc->Func (&Data); + /* Since the function may have added or deleted entries, + * correct the index. + */ + I += CS_GetEntryCount (S) - OldEntryCount; + /* Regenerate register info */ CS_GenRegInfo (S); /* Done */ State = Initialize; - break; + continue; } @@ -1883,9 +1939,6 @@ unsigned OptStackOps (CodeSeg* S) } - /* Free the register info */ - CS_FreeRegInfo (S); - /* Return the number of changes made */ return Changes; }