]> git.sur5r.net Git - cc65/blobdiff - src/cc65/coptstore.c
Merge remote-tracking branch 'upstream/master' into a5200
[cc65] / src / cc65 / coptstore.c
index b738c38dba02ab924b51f7acae33ee7382f0fc02..fca153e968bde275c4962c6fba93f2fd044bb762 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2005, Ullrich von Bassewitz                                      */
-/*                Römerstrasse 52                                            */
+/* (C) 2002-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
 /*                                                                           */
@@ -41,7 +41,7 @@
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -62,8 +62,7 @@ unsigned OptStore1 (CodeSeg* S)
  *      ldy     #n+1
  *      jsr     ldaxysp
  *
- * and remove the useless load, provided that the next insn doesn't use flags
- * from the load.
+ * and remove the useless load.
  */
 {
     unsigned Changes = 0;
@@ -72,33 +71,32 @@ unsigned OptStore1 (CodeSeg* S)
     unsigned I = 0;
     while (I < CS_GetEntryCount (S)) {
 
-       CodeEntry* L[5];
+        CodeEntry* L[4];
 
-       /* Get next entry */
-               L[0] = CS_GetEntry (S, I);
+        /* Get next entry */
+        L[0] = CS_GetEntry (S, I);
 
         /* Check for the sequence */
         if (L[0]->OPC == OP65_LDY                           &&
-           CE_IsConstImm (L[0])                            &&
+            CE_IsConstImm (L[0])                            &&
             L[0]->Num < 0xFF                                &&
-           !CS_RangeHasLabel (S, I+1, 3)                   &&
-                   CS_GetEntries (S, L+1, I+1, 4)                  &&
+            !CS_RangeHasLabel (S, I+1, 3)                   &&
+            CS_GetEntries (S, L+1, I+1, 3)                  &&
             CE_IsCallTo (L[1], "staxysp")                   &&
             L[2]->OPC == OP65_LDY                           &&
             CE_IsKnownImm (L[2], L[0]->Num + 1)             &&
-            CE_IsCallTo (L[3], "ldaxysp")                   &&
-            !CE_UseLoadFlags (L[4])) {
+            CE_IsCallTo (L[3], "ldaxysp")) {
 
-                   /* Register has already the correct value, remove the loads */
-           CS_DelEntries (S, I+2, 2);
+            /* Register has already the correct value, remove the loads */
+            CS_DelEntries (S, I+2, 2);
 
-           /* Remember, we had changes */
-           ++Changes;
+            /* Remember, we had changes */
+            ++Changes;
 
-       }
+        }
 
-       /* Next entry */
-       ++I;
+        /* Next entry */
+        ++I;
 
     }
 
@@ -117,30 +115,27 @@ unsigned OptStore2 (CodeSeg* S)
     unsigned I;
     unsigned Changes = 0;
 
-    /* Generate register info */
-    CS_GenRegInfo (S);
-
     /* Walk over the entries */
     I = 0;
     while (I < CS_GetEntryCount (S)) {
 
-       /* Get next entry */
-               CodeEntry* E = CS_GetEntry (S, I);
+        /* Get next entry */
+        CodeEntry* E = CS_GetEntry (S, I);
 
         /* Get the input registers */
         const RegInfo* RI = E->RI;
 
-       /* Check for the call */
-               if (CE_IsCallTo (E, "staxysp")          &&
+        /* Check for the call */
+        if (CE_IsCallTo (E, "staxysp")          &&
             RegValIsKnown (RI->In.RegA)         &&
             RegValIsKnown (RI->In.RegX)         &&
             RegValIsKnown (RI->In.RegY)         &&
             !RegAXUsed (S, I+1)) {
 
             /* Get the register values */
-            unsigned char A = RI->In.RegA;
-            unsigned char X = RI->In.RegX;
-            unsigned char Y = RI->In.RegY;
+            unsigned char A = (unsigned char) RI->In.RegA;
+            unsigned char X = (unsigned char) RI->In.RegX;
+            unsigned char Y = (unsigned char) RI->In.RegY;
 
             /* Setup other variables */
             CodeEntry*  N;
@@ -165,19 +160,16 @@ unsigned OptStore2 (CodeSeg* S)
             /* Remove the call */
             CS_DelEntry (S, I);
 
-           /* Remember, we had changes */
-           ++Changes;
+            /* Remember, we had changes */
+            ++Changes;
 
-       }
+        }
 
-       /* Next entry */
-       ++I;
+        /* Next entry */
+        ++I;
 
     }
 
-    /* Free the register info */
-    CS_FreeRegInfo (S);
-
     /* Return the number of changes made */
     return Changes;
 }
@@ -193,21 +185,18 @@ unsigned OptStore3 (CodeSeg* S)
     unsigned I;
     unsigned Changes = 0;
 
-    /* Generate register info */
-    CS_GenRegInfo (S);
-
     /* Walk over the entries */
     I = 0;
     while (I < CS_GetEntryCount (S)) {
 
-       /* Get next entry */
-               CodeEntry* E = CS_GetEntry (S, I);
+        /* Get next entry */
+        CodeEntry* E = CS_GetEntry (S, I);
 
         /* Get the input registers */
         const RegInfo* RI = E->RI;
 
-       /* Check for the call */
-       if (CE_IsCallTo (E, "steaxysp")         &&
+        /* Check for the call */
+        if (CE_IsCallTo (E, "steaxysp")         &&
             RegValIsKnown (RI->In.RegA)         &&
             RegValIsKnown (RI->In.RegX)         &&
             RegValIsKnown (RI->In.RegY)         &&
@@ -216,11 +205,11 @@ unsigned OptStore3 (CodeSeg* S)
             !RegEAXUsed (S, I+1)) {
 
             /* Get the register values */
-            unsigned char A = RI->In.RegA;
-            unsigned char X = RI->In.RegX;
-            unsigned char Y = RI->In.RegY;
-            unsigned char L = RI->In.SRegLo;
-            unsigned char H = RI->In.SRegHi;
+            unsigned char A = (unsigned char) RI->In.RegA;
+            unsigned char X = (unsigned char) RI->In.RegX;
+            unsigned char Y = (unsigned char) RI->In.RegY;
+            unsigned char L = (unsigned char) RI->In.SRegLo;
+            unsigned char H = (unsigned char) RI->In.SRegHi;
 
             /* Setup other variables */
             unsigned    Done = 0;
@@ -310,19 +299,16 @@ unsigned OptStore3 (CodeSeg* S)
             /* Remove the call */
             CS_DelEntry (S, I);
 
-           /* Remember, we had changes */
-           ++Changes;
+            /* Remember, we had changes */
+            ++Changes;
 
-       }
+        }
 
-       /* Next entry */
-       ++I;
+        /* Next entry */
+        ++I;
 
     }
 
-    /* Free the register info */
-    CS_FreeRegInfo (S);
-
     /* Return the number of changes made */
     return Changes;
 }
@@ -347,16 +333,16 @@ unsigned OptStore4 (CodeSeg* S)
     unsigned I = 0;
     while (I < CS_GetEntryCount (S)) {
 
-       CodeEntry* L[5];
+        CodeEntry* L[5];
 
-       /* Get next entry */
-               L[0] = CS_GetEntry (S, I);
+        /* Get next entry */
+        L[0] = CS_GetEntry (S, I);
 
         /* Check for the sequence */
         if (L[0]->OPC == OP65_STA                           &&
             (L[0]->AM == AM65_ABS || L[0]->AM == AM65_ZP)   &&
-           !CS_RangeHasLabel (S, I+1, 3)                   &&
-                   CS_GetEntries (S, L+1, I+1, 4)                  &&
+            !CS_RangeHasLabel (S, I+1, 3)                   &&
+            CS_GetEntries (S, L+1, I+1, 4)                  &&
             L[1]->OPC == OP65_STX                           &&
             L[1]->AM == L[0]->AM                            &&
             L[2]->OPC == OP65_LDA                           &&
@@ -367,16 +353,16 @@ unsigned OptStore4 (CodeSeg* S)
             strcmp (L[1]->Arg, L[3]->Arg) == 0              &&
             !CE_UseLoadFlags (L[4])) {
 
-                   /* Register has already the correct value, remove the loads */
-           CS_DelEntries (S, I+2, 2);
+            /* Register has already the correct value, remove the loads */
+            CS_DelEntries (S, I+2, 2);
 
-           /* Remember, we had changes */
-           ++Changes;
+            /* Remember, we had changes */
+            ++Changes;
 
-       }
+        }
 
-       /* Next entry */
-       ++I;
+        /* Next entry */
+        ++I;
 
     }
 
@@ -386,3 +372,66 @@ unsigned OptStore4 (CodeSeg* S)
 
 
 
+unsigned OptStore5 (CodeSeg* S)
+/* Search for the sequence
+ *
+ *      lda     foo
+ *      ldx     bar
+ *      sta     something
+ *      stx     something-else
+ *
+ * and replace it by
+ *
+ *      lda     foo
+ *      sta     something
+ *      lda     bar
+ *      sta     something-else
+ *
+ * if X is not used later. This replacement doesn't save any cycles or bytes,
+ * but it keeps the value of X, which may be reused later.
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+        CodeEntry* L[4];
+
+        /* Get next entry */
+        L[0] = CS_GetEntry (S, I);
+
+        /* Check for the sequence */
+        if (L[0]->OPC == OP65_LDA                           &&
+            !CS_RangeHasLabel (S, I+1, 3)                   &&
+            CS_GetEntries (S, L+1, I+1, 3)                  &&
+            L[1]->OPC == OP65_LDX                           &&
+            L[2]->OPC == OP65_STA                           &&
+            L[3]->OPC == OP65_STX                           &&
+            !RegXUsed (S, I+4)) {
+
+            CodeEntry* X;
+
+            /* Insert the code after the sequence */
+            X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
+            CS_InsertEntry (S, X, I+4);
+            X = NewCodeEntry (OP65_STA, L[3]->AM, L[3]->Arg, 0, L[3]->LI);
+            CS_InsertEntry (S, X, I+5);
+
+            /* Delete the old code */
+            CS_DelEntry (S, I+3);
+            CS_DelEntry (S, I+1);
+
+            /* Remember, we had changes */
+            ++Changes;
+        }
+
+        /* Next entry */
+        ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}