]> git.sur5r.net Git - cc65/commitdiff
Transform tosshlax and friends into a sequence that doesn't use the stack if
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 6 Jul 2012 20:01:46 +0000 (20:01 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 6 Jul 2012 20:01:46 +0000 (20:01 +0000)
possible.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5764 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeopt.c
src/cc65/coptstop.c

index 509a6aa41d396a17babfd568cb28b1ec5d649c54..69cbae2df2954f20709c6cea020b6ad48e311969 100644 (file)
@@ -1606,7 +1606,7 @@ static unsigned RunOptGroup3 (CodeSeg* S)
                C += RunOptFunc (S, &DOptBNegA2, 1);
         C += RunOptFunc (S, &DOptNegAX1, 1);
         C += RunOptFunc (S, &DOptNegAX2, 1);
-               C += RunOptFunc (S, &DOptStackOps, 1);
+               C += RunOptFunc (S, &DOptStackOps, 3);
                C += RunOptFunc (S, &DOptSub1, 1);
                C += RunOptFunc (S, &DOptSub2, 1);
                C += RunOptFunc (S, &DOptSub3, 1);
@@ -1760,7 +1760,7 @@ static unsigned RunOptGroup7 (CodeSeg* S)
         Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
         Changes += RunOptFunc (S, &DOptJumpTarget1, 5);
         Changes += RunOptFunc (S, &DOptStore5, 1);
-        Changes += RunOptFunc (S, &DOptTransfers1, 1); 
+        Changes += RunOptFunc (S, &DOptTransfers1, 1);
         Changes += RunOptFunc (S, &DOptTransfers3, 1);
     }
 
index 85824b64d148f6bced31f0e8338c263584f16270..03ca80b412bd0db3018d07fa7c9ed8aa8bb51015 100644 (file)
@@ -716,7 +716,7 @@ static int IsRegVar (StackOpData* D)
 
 
 /*****************************************************************************/
-/*                      Actual optimization functions                       */
+/*                      Actual optimization functions                       */
 /*****************************************************************************/
 
 
@@ -832,6 +832,71 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer
 
 
 
+static unsigned Opt_tosshift (StackOpData* D, const char* Name)
+/* Optimize shift sequences. */
+{
+    CodeEntry*  X;
+
+    /* Store the value into the zeropage instead of pushing it */
+    ReplacePushByStore (D);
+
+    /* Inline the compare */
+    D->IP = D->OpIndex+1;
+
+    /* tay */
+    X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, D->OpEntry->LI);
+    InsertEntry (D, X, D->IP++);
+
+    /* If the lhs is direct (but not stack relative), we can just reload the
+     * data later.
+     */
+    if ((D->Lhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT &&
+        (D->Lhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) {
+
+        CodeEntry* LoadX = D->Lhs.X.LoadEntry;
+        CodeEntry* LoadA = D->Lhs.A.LoadEntry;
+
+        /* lda */
+        X = NewCodeEntry (OP65_LDA, LoadA->AM, LoadA->Arg, 0, D->OpEntry->LI);
+        InsertEntry (D, X, D->IP++);
+
+        /* ldx */
+        X = NewCodeEntry (OP65_LDX, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI);
+        InsertEntry (D, X, D->IP++);
+
+        /* Lhs load entries can be removed */
+        D->Lhs.X.Flags |= LI_REMOVE;
+        D->Lhs.A.Flags |= LI_REMOVE;
+
+    } else {
+
+        /* Save lhs into zeropage and reload later */
+        AddStoreX (D);
+        AddStoreA (D);
+
+        /* lda zp */
+        X = NewCodeEntry (OP65_LDA, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI);
+        InsertEntry (D, X, D->IP++);
+
+        /* ldx zp+1 */
+        X = NewCodeEntry (OP65_LDX, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI);
+        InsertEntry (D, X, D->IP++);
+
+    }
+
+    /* jsr shlaxy/aslaxy/whatever */
+    X = NewCodeEntry (OP65_JSR, AM65_ABS, Name, 0, D->OpEntry->LI);
+    InsertEntry (D, X, D->IP++);
+
+    /* Remove the push and the call to the tossubax function */
+    RemoveRemainders (D);
+
+    /* We changed the sequence */
+    return 1;
+}
+
+
+
 static unsigned Opt___bzero (StackOpData* D)
 /* Optimize the __bzero sequence */
 {
@@ -1169,6 +1234,22 @@ static unsigned Opt_tosandax (StackOpData* D)
 
 
 
+static unsigned Opt_tosaslax (StackOpData* D)
+/* Optimize the tosaslax sequence */
+{
+    return Opt_tosshift (D, "aslaxy");
+}
+
+
+
+static unsigned Opt_tosasrax (StackOpData* D)
+/* Optimize the tosasrax sequence */
+{
+    return Opt_tosshift (D, "asraxy");
+}
+
+
+
 static unsigned Opt_toseqax (StackOpData* D)
 /* Optimize the toseqax sequence */
 {
@@ -1237,7 +1318,7 @@ static unsigned Opt_tosltax (StackOpData* D)
     CodeLabel* L;
 
 
-    /* Inline the sbc */
+    /* Inline the compare */
     D->IP = D->OpIndex+1;
 
     /* Must be true because of OP_RHS_LOAD */
@@ -1314,6 +1395,22 @@ static unsigned Opt_tosorax (StackOpData* D)
 
 
 
+static unsigned Opt_tosshlax (StackOpData* D)
+/* Optimize the tosshlax sequence */
+{
+    return Opt_tosshift (D, "shlaxy");
+}
+
+
+
+static unsigned Opt_tosshrax (StackOpData* D)
+/* Optimize the tosshrax sequence */
+{
+    return Opt_tosshift (D, "shraxy");
+}
+
+
+
 static unsigned Opt_tossubax (StackOpData* D)
 /* Optimize the tossubax sequence. Note: subtraction is not commutative! */
 {
@@ -1547,11 +1644,18 @@ static const OptFuncDesc FuncTable[] = {
     { "staxspidx",  Opt_staxspidx, REG_AX,   OP_NONE                    },
     { "tosaddax",   Opt_tosaddax,  REG_NONE, OP_NONE                    },
     { "tosandax",   Opt_tosandax,  REG_NONE, OP_NONE                    },
+    { "tosaslax",   Opt_tosaslax,  REG_NONE, OP_NONE                    },
+#if 0 
+    /* Library routine missing */
+    { "tosasrax",   Opt_tosasrax,  REG_NONE, OP_NONE                    },
+#endif
     { "toseqax",    Opt_toseqax,   REG_NONE, OP_NONE                    },
     { "tosgeax",    Opt_tosgeax,   REG_NONE, OP_RHS_LOAD_DIRECT         },
     { "tosltax",    Opt_tosltax,   REG_NONE, OP_RHS_LOAD_DIRECT         },
     { "tosneax",    Opt_tosneax,   REG_NONE, OP_NONE                    },
     { "tosorax",    Opt_tosorax,   REG_NONE, OP_NONE                    },
+    { "tosshlax",   Opt_tosshlax,  REG_NONE, OP_NONE                    },
+    { "tosshrax",   Opt_tosshrax,  REG_NONE, OP_NONE                    },
     { "tossubax",   Opt_tossubax,  REG_NONE, OP_RHS_LOAD_DIRECT         },
     { "tosugeax",   Opt_tosugeax,  REG_NONE, OP_RHS_LOAD_DIRECT         },
     { "tosugtax",   Opt_tosugtax,  REG_NONE, OP_RHS_LOAD_DIRECT         },
@@ -1599,11 +1703,13 @@ static int HarmlessCall (const char* Name)
         "aslax2",
         "aslax3",
         "aslax4",
+        "aslaxy",
         "asrax1",
         "asrax2",
         "asrax3",
         "asrax4",
         "bnegax",
+        "complax",
         "decax1",
         "decax2",
         "decax3",
@@ -1629,6 +1735,7 @@ static int HarmlessCall (const char* Name)
         "shlax2",
         "shlax3",
         "shlax4",
+        "shlaxy",
         "shrax1",
         "shrax2",
         "shrax3",
@@ -1744,6 +1851,9 @@ unsigned OptStackOps (CodeSeg* S)
     StackOpData         Data;
     int                 I;
     int                 OldEntryCount;  /* Old number of entries */
+    unsigned            UsedRegs;       /* Registers used */
+    unsigned            ChangedRegs;    /* Registers changed */
+
 
     enum {
         Initialize,
@@ -1782,6 +1892,7 @@ unsigned OptStackOps (CodeSeg* S)
 
             case Initialize:
                 ResetStackOpData (&Data);
+                UsedRegs = ChangedRegs = REG_NONE;
                 State = Search;
                 /* FALLTHROUGH */
 
@@ -1868,6 +1979,17 @@ unsigned OptStackOps (CodeSeg* S)
                     Data.UsedRegs |= (E->Use | E->Chg);
                     TrackLoads (&Data.Rhs, E, I);
                 }
+                /* If the registers from the push (A/X) are used before they're
+                 * changed, we cannot change the sequence, because this would
+                 * with a high probability change the register contents.
+                 */
+                UsedRegs |= E->Use;
+                if ((UsedRegs & ~ChangedRegs) & REG_AX) {
+                    I = Data.PushIndex;
+                    State = Initialize;
+                    break;
+                }
+                ChangedRegs |= E->Chg;
                 break;
 
             case FoundOp: