]> git.sur5r.net Git - cc65/blobdiff - src/cc65/coptstop.c
Added dummy classification macros for the remaining targets - even for those that...
[cc65] / src / cc65 / coptstop.c
index 50fd73b4e6b6f7d158024d262875dc5b42d1166a..85824b64d148f6bced31f0e8338c263584f16270 100644 (file)
@@ -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;
 }