]> git.sur5r.net Git - cc65/commitdiff
New store optimization.
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 17 Oct 2002 21:37:01 +0000 (21:37 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 17 Oct 2002 21:37:01 +0000 (21:37 +0000)
New functions RegValIsKnown and RegValIsUnknown should be used instead of
direct compares against zero, so we can change the "unknown" representation
one day.

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

12 files changed:
src/cc65/codeinfo.c
src/cc65/codeinfo.h
src/cc65/codeopt.c
src/cc65/coptind.c
src/cc65/coptpush.c
src/cc65/coptsize.c
src/cc65/coptstop.c
src/cc65/coptstore.c [new file with mode: 0644]
src/cc65/coptstore.h [new file with mode: 0644]
src/cc65/make/gcc.mak
src/cc65/make/watcom.mak
src/cc65/reginfo.h

index 74a704a9614efac21f75677575f29fef901ffe52..47d038abc3ff8313654e11580bcbd82b62de89c3 100644 (file)
@@ -590,6 +590,14 @@ int RegAXUsed (struct CodeSeg* S, unsigned Index)
 
 
 
+int RegEAXUsed (struct CodeSeg* S, unsigned Index)
+/* Check if any of the four bytes in EAX are used. */
+{
+    return (GetRegInfo (S, Index, REG_EAX) & REG_EAX) != 0;
+}
+
+
+
 unsigned GetKnownReg (unsigned Use, const RegContents* RC)
 /* Return the register or zero page location from the set in Use, thats
  * contents are known. If Use does not contain any register, or if the
index 7e4eddf983c99c699093e92bc8862fe3f6d0c4bd..4e0b16887e603c4e9c75d4baca8281d0bea6b18b 100644 (file)
@@ -154,6 +154,9 @@ int RegYUsed (struct CodeSeg* S, unsigned Index);
 int RegAXUsed (struct CodeSeg* S, unsigned Index);
 /* Check if the value in A or(!) the value in X are used. */
 
+int RegEAXUsed (struct CodeSeg* S, unsigned Index);
+/* Check if any of the four bytes in EAX are used. */
+
 unsigned GetKnownReg (unsigned Use, const struct RegContents* RC);
 /* Return the register or zero page location from the set in Use, thats
  * contents are known. If Use does not contain any register, or if the
index 1690a42bc55d123162e42f5a20439b860141ba8c..a1d824d0ac2ea4bc9524e4116de580fc1528b811 100644 (file)
@@ -55,6 +55,7 @@
 #include "coptpush.h"
 #include "coptsize.h"
 #include "coptstop.h"
+#include "coptstore.h"
 #include "coptsub.h"
 #include "copttest.h"
 #include "cpu.h"
@@ -1371,6 +1372,8 @@ static OptFunc DOptShift3         = { OptShift3,       "OptShift3",       110, 0,
 static OptFunc DOptSize1        = { OptSize1,        "OptSize1",        100, 0, 0, 0, 0, 0 };
 static OptFunc DOptSize2        = { OptSize2,        "OptSize2",        100, 0, 0, 0, 0, 0 };
 static OptFunc DOptStackOps            = { OptStackOps,     "OptStackOps",     100, 0, 0, 0, 0, 0 };
+static OptFunc DOptStore1       = { OptStore1,       "OptStore1",       220, 0, 0, 0, 0, 0 };
+static OptFunc DOptStore2       = { OptStore2,       "OptStore2",       120, 0, 0, 0, 0, 0 };
 static OptFunc DOptStoreLoad           = { OptStoreLoad,    "OptStoreLoad",      0, 0, 0, 0, 0, 0 };
 static OptFunc DOptSub1                = { OptSub1,         "OptSub1",         100, 0, 0, 0, 0, 0 };
 static OptFunc DOptSub2                = { OptSub2,         "OptSub2",         100, 0, 0, 0, 0, 0 };
@@ -1429,6 +1432,8 @@ static OptFunc* OptFuncs[] = {
     &DOptSize1,
     &DOptSize2,
     &DOptStackOps,
+    &DOptStore1,
+    &DOptStore2,
     &DOptStoreLoad,
     &DOptSub1,
     &DOptSub2,
@@ -1685,6 +1690,8 @@ static unsigned RunOptGroup1 (CodeSeg* S)
     Changes += RunOptFunc (S, &DOptShift1, 1);
     Changes += RunOptFunc (S, &DOptShift2, 1);
     Changes += RunOptFunc (S, &DOptShift3, 1);
+    Changes += RunOptFunc (S, &DOptStore1, 5);
+    Changes += RunOptFunc (S, &DOptStore2, 5);
 
     /* Return the number of changes */
     return Changes;
index 98f0c42466bda5634ac3ad60246f590bb349775b..f72d778889d59efce9e9edd8da4aa2b52043cfeb 100644 (file)
@@ -800,7 +800,7 @@ unsigned OptDupLoads (CodeSeg* S)
        switch (E->OPC) {
 
            case OP65_LDA:
-                       if (In->RegA >= 0                     && /* Value of A is known */
+                       if (RegValIsKnown (In->RegA)          && /* Value of A is known */
                            CE_KnownImm (E)                   && /* Value to be loaded is known */
                            In->RegA == (long) E->Num         && /* Both are equal */
                            (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
@@ -810,7 +810,7 @@ unsigned OptDupLoads (CodeSeg* S)
                break;
 
            case OP65_LDX:
-                       if (In->RegX >= 0                     && /* Value of X is known */
+                       if (RegValIsKnown (In->RegX)          && /* Value of X is known */
                    CE_KnownImm (E)                   && /* Value to be loaded is known */
                    In->RegX == (long) E->Num         && /* Both are equal */
                            (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
@@ -820,7 +820,7 @@ unsigned OptDupLoads (CodeSeg* S)
                break;
 
            case OP65_LDY:
-                       if (In->RegY >= 0                     && /* Value of Y is known */
+                       if (RegValIsKnown (In->RegY)          && /* Value of Y is known */
                    CE_KnownImm (E)                   && /* Value to be loaded is known */
                    In->RegY == (long) E->Num         && /* Both are equal */
                            (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
@@ -834,7 +834,7 @@ unsigned OptDupLoads (CodeSeg* S)
                 * location does already contain the value to be stored,
                 * remove the store.
                 */
-               if (In->RegA >= 0                     && /* Value of A is known */
+               if (RegValIsKnown (In->RegA)          && /* Value of A is known */
                    E->AM == AM65_ZP                  && /* Store into zp */
                    In->RegA == RegVal (E->Chg, In)) {   /* Value identical */
 
@@ -847,7 +847,7 @@ unsigned OptDupLoads (CodeSeg* S)
                 * location does already contain the value to be stored,
                 * remove the store.
                 */
-               if (In->RegX >= 0                     && /* Value of A is known */
+               if (RegValIsKnown (In->RegX)          && /* Value of A is known */
                    E->AM == AM65_ZP                  && /* Store into zp */
                            In->RegX == RegVal (E->Chg, In)) {   /* Value identical */
 
@@ -859,7 +859,7 @@ unsigned OptDupLoads (CodeSeg* S)
                 * later. STX does support the zeropage,y addressing mode,
                 * so be sure to check for that.
                 */
-                       } else if (In->RegX >= 0              &&
+                       } else if (RegValIsKnown (In->RegX)   &&
                           In->RegX == In->RegA       &&
                           E->AM != AM65_ABSY         &&
                           E->AM != AM65_ZPY) {
@@ -873,7 +873,7 @@ unsigned OptDupLoads (CodeSeg* S)
                 * location does already contain the value to be stored,
                 * remove the store.
                 */
-               if (In->RegY >= 0                     && /* Value of Y is known */
+               if (RegValIsKnown (In->RegY)          && /* Value of Y is known */
                    E->AM == AM65_ZP                  && /* Store into zp */
                            In->RegY == RegVal (E->Chg, In)) {   /* Value identical */
 
@@ -886,7 +886,7 @@ unsigned OptDupLoads (CodeSeg* S)
                 * replacement by X, but check for invalid addressing modes
                 * in this case.
                 */
-                       } else if (In->RegY >= 0) {
+                       } else if (RegValIsKnown (In->RegY)) {
                    if (In->RegY == In->RegA) {
                        CE_ReplaceOPC (E, OP65_STA);
                    } else if (In->RegY == In->RegX   &&
@@ -910,7 +910,7 @@ unsigned OptDupLoads (CodeSeg* S)
                break;
 
            case OP65_TAX:
-                if (In->RegA >= 0                     &&
+                if (RegValIsKnown (In->RegA)          &&
                    In->RegA == In->RegX              &&
                    (N = CS_GetNextEntry (S, I)) != 0 &&
                            !CE_UseLoadFlags (N)) {
@@ -920,7 +920,7 @@ unsigned OptDupLoads (CodeSeg* S)
                break;
 
            case OP65_TAY:
-                if (In->RegA >= 0                       &&
+                if (RegValIsKnown (In->RegA)            &&
                    In->RegA == In->RegY                &&
                    (N = CS_GetNextEntry (S, I)) != 0   &&
                            !CE_UseLoadFlags (N)) {
@@ -930,7 +930,7 @@ unsigned OptDupLoads (CodeSeg* S)
                break;
 
                    case OP65_TXA:
-                if (In->RegX >= 0                       &&
+                if (RegValIsKnown (In->RegX)            &&
                    In->RegX == In->RegA                &&
                    (N = CS_GetNextEntry (S, I)) != 0   &&
                            !CE_UseLoadFlags (N)) {
@@ -940,7 +940,7 @@ unsigned OptDupLoads (CodeSeg* S)
                break;
 
            case OP65_TYA:
-                if (In->RegY >= 0                       &&
+                if (RegValIsKnown (In->RegY)            &&
                    In->RegY == In->RegA                &&
                    (N = CS_GetNextEntry (S, I)) != 0   &&
                            !CE_UseLoadFlags (N)) {
@@ -961,7 +961,7 @@ unsigned OptDupLoads (CodeSeg* S)
            CS_DelEntry (S, I);
 
            /* Remember, we had changes */
-           ++Changes;
+           ++Changes;                      
 
        } else {
 
index bede323077fa2afa42264a0bd2d1dc04961e0515..887bbf9bef02a8818f457bfad984a429b414e10e 100644 (file)
@@ -80,7 +80,7 @@ unsigned OptPush1 (CodeSeg* S)
                    CS_GetEntries (S, L+1, I+1, 2)      &&
            CE_IsCallTo (L[1], "ldaxysp")       &&
                    CE_IsCallTo (L[2], "pushax")        &&
-                   (GetRegInfo (S, I+3, REG_AX) & REG_AX) == 0) {
+                   !RegAXUsed (S, I+3)) {
 
            /* Insert new code behind the pushax */
            const char* Arg;
index ab5728780ff537c758fd7cb7150122de73a7d2d3..3eaf48dce23fb082efb435e24590d6abcf88067e 100644 (file)
@@ -266,10 +266,12 @@ unsigned OptSize2 (CodeSeg* S)
     I = 0;
     while (I < CS_GetEntryCount (S)) {
 
-
        /* Get next entry */
                CodeEntry* E = CS_GetEntry (S, I);
 
+        /* Get the input registers */
+        const RegContents* In = &E->RI->In;
+
        /* Assume we have no replacement */
        CodeEntry* X = 0;
 
@@ -279,14 +281,14 @@ unsigned OptSize2 (CodeSeg* S)
            case OP65_LDA:
                if (CE_KnownImm (E)) {
                    short Val = (short) E->Num;
-                   if (Val == E->RI->In.RegX) {
+                   if (Val == In->RegX) {
                        X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, E->LI);
-                   } else if (Val == E->RI->In.RegY) {
+                   } else if (Val == In->RegY) {
                        X = NewCodeEntry (OP65_TYA, AM65_IMP, 0, 0, E->LI);
-                   } else if (E->RI->In.RegA >= 0 && CPU >= CPU_65C02) {
-                       if (Val == ((E->RI->In.RegA - 1) & 0xFF)) {
+                   } else if (RegValIsKnown (In->RegA) && CPU >= CPU_65C02) {
+                       if (Val == ((In->RegA - 1) & 0xFF)) {
                            X = NewCodeEntry (OP65_DEA, AM65_IMP, 0, 0, E->LI);
-                       } else if (Val == ((E->RI->In.RegA + 1) & 0xFF)) {
+                       } else if (Val == ((In->RegA + 1) & 0xFF)) {
                            X = NewCodeEntry (OP65_INA, AM65_IMP, 0, 0, E->LI);
                        }
                    }
@@ -296,11 +298,11 @@ unsigned OptSize2 (CodeSeg* S)
            case OP65_LDX:
                if (CE_KnownImm (E)) {
                    short Val = (short) E->Num;
-                   if (E->RI->In.RegX >= 0 && Val == ((E->RI->In.RegX - 1) & 0xFF)) {
+                   if (RegValIsKnown (In->RegX) && Val == ((In->RegX - 1) & 0xFF)) {
                        X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, E->LI);
-                   } else if (E->RI->In.RegX >= 0 && Val == ((E->RI->In.RegX + 1) & 0xFF)) {
+                           } else if (RegValIsKnown (In->RegX) && Val == ((In->RegX + 1) & 0xFF)) {
                        X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
-                   } else if (Val == E->RI->In.RegA) {
+                   } else if (Val == In->RegA) {
                        X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI);
                     }
                }
@@ -309,11 +311,11 @@ unsigned OptSize2 (CodeSeg* S)
                    case OP65_LDY:
                if (CE_KnownImm (E)) {
                    short Val = (short) E->Num;
-                   if (E->RI->In.RegY >= 0 && Val == ((E->RI->In.RegY - 1) & 0xFF)) {
+                   if (RegValIsKnown (In->RegY) && Val == ((In->RegY - 1) & 0xFF)) {
                        X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI);
-                   } else if (E->RI->In.RegY >= 0 && Val == ((E->RI->In.RegY + 1) & 0xFF)) {
+                   } else if (RegValIsKnown (In->RegY) && Val == ((In->RegY + 1) & 0xFF)) {
                        X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, E->LI);
-                   } else if (Val == E->RI->In.RegA) {
+                   } else if (Val == In->RegA) {
                        X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, E->LI);
                    }
                }
index 4e1c2e6d7ceb5b3d2b32d72271ad7d10f50839e7..557f4d357b69f57ee7d1bf196db466dcb61ae536 100644 (file)
@@ -207,9 +207,9 @@ static void CheckDirectOp (StackOpData* D)
         if (E->AM == AM65_IMM || E->AM == AM65_ZP || E->AM == AM65_ABS) {
             /* These insns are all ok and replaceable */
             D->Flags |= OP_DIRECT;
-        } else if (E->AM == AM65_ZP_INDY &&
-                   E->RI->In.RegY >= 0   &&
-                          (E->Use & REG_SP) != 0) {
+        } else if (E->AM == AM65_ZP_INDY          &&
+                   RegValIsKnown (E->RI->In.RegY) &&
+                          (E->Use & REG_SP) != 0) {      
             /* Load from stack with known offset is also ok */
             D->Flags |= (OP_DIRECT | OP_ONSTACK);
         }
@@ -337,7 +337,7 @@ static unsigned Opt_staxspidx (StackOpData* D)
     InsertEntry (D, X, D->OpIndex+1);
     X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, D->OpEntry->LI);
     InsertEntry (D, X, D->OpIndex+2);
-    if (D->OpEntry->RI->In.RegX >= 0) {
+    if (RegValIsKnown (D->OpEntry->RI->In.RegX)) {
        /* Value of X is known */
        const char* Arg = MakeHexArg (D->OpEntry->RI->In.RegX);
                X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, D->OpEntry->LI);
@@ -396,7 +396,7 @@ static unsigned Opt_tosaddax (StackOpData* D)
     } else if (D->OpEntry->RI->In.RegX == 0) {
                /* The high byte is that of the first operand plus carry */
        CodeLabel* L;
-       if (D->PushEntry->RI->In.RegX >= 0) {
+       if (RegValIsKnown (D->PushEntry->RI->In.RegX)) {
            /* Value of first op high byte is known */
            const char* Arg = MakeHexArg (D->PushEntry->RI->In.RegX);
            X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, D->OpEntry->LI);
@@ -482,7 +482,8 @@ static unsigned Opt_tosorax (StackOpData* D)
     AddOpLow (D, OP65_ORA);
 
     /* High byte */
-    if (D->PushEntry->RI->In.RegX >= 0 && D->OpEntry->RI->In.RegX >= 0) {
+    if (RegValIsKnown (D->PushEntry->RI->In.RegX) && 
+        RegValIsKnown (D->OpEntry->RI->In.RegX)) {
        /* Both values known, precalculate the result */
        const char* Arg = MakeHexArg (D->PushEntry->RI->In.RegX | D->OpEntry->RI->In.RegX);
                X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, D->OpEntry->LI);
@@ -521,7 +522,8 @@ static unsigned Opt_tosxorax (StackOpData* D)
     AddOpLow (D, OP65_EOR);
 
     /* High byte */
-    if (D->PushEntry->RI->In.RegX >= 0 && D->OpEntry->RI->In.RegX >= 0) {
+    if (RegValIsKnown (D->PushEntry->RI->In.RegX) && 
+        RegValIsKnown (D->OpEntry->RI->In.RegX)) {
        /* Both values known, precalculate the result */
        const char* Arg = MakeHexArg (D->PushEntry->RI->In.RegX ^ D->OpEntry->RI->In.RegX);
                X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, D->OpEntry->LI);
@@ -661,8 +663,8 @@ unsigned OptStackOps (CodeSeg* S)
        /* Handling depends if we're inside a sequence or not */
        if (InSeq) {
 
-                   if (((E->Use & REG_SP) != 0                         &&
-                (E->AM != AM65_ZP_INDY || E->RI->In.RegY < 0))) {
+                   if (((E->Use & REG_SP) != 0 &&
+                (E->AM != AM65_ZP_INDY || RegValIsUnknown (E->RI->In.RegY)))) {
 
                /* All this stuff is not allowed in a sequence */
                InSeq = 0;
diff --git a/src/cc65/coptstore.c b/src/cc65/coptstore.c
new file mode 100644 (file)
index 0000000..66e1a7a
--- /dev/null
@@ -0,0 +1,277 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                  coptstore.c                              */
+/*                                                                           */
+/*                                Optimize stores                            */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2002      Ullrich von Bassewitz                                       */
+/*               Wacholderweg 14                                             */
+/*               D-70597 Stuttgart                                           */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+/* cc65 */
+#include "codeent.h"
+#include "codeinfo.h"
+#include "coptstore.h"
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+static void InsertStore (CodeSeg* S, unsigned* IP, LineInfo* LI)
+{
+    CodeEntry* X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, LI);
+    CS_InsertEntry (S, X, (*IP)++);
+}
+
+
+
+unsigned OptStore1 (CodeSeg* S)
+/* Search for a call to staxysp. If the ax register is not used later, and
+ * the value is constant, just use the A register and store directly into the
+ * stack.
+ */
+{
+    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 the input registers */
+        const RegInfo* RI = E->RI;
+
+       /* 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;
+
+            /* Setup other variables */
+            CodeEntry*  N;
+            unsigned    IP = I + 1;     /* Insertion point */
+
+            /* Replace the store. We will not remove the loads, since this is
+             * too complex and will be done by other optimizer steps.
+             */
+            N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI);
+            CS_InsertEntry (S, N, IP++);
+            InsertStore (S, &IP, E->LI);
+
+            /* Check if we can store one of the other bytes */
+            if (A != X) {
+                N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (X), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+            }
+            N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI);
+            CS_InsertEntry (S, N, IP++);
+            InsertStore (S, &IP, E->LI);
+
+            /* Remove the call */
+            CS_DelEntry (S, I);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Free the register info */
+    CS_FreeRegInfo (S);
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+unsigned OptStore2 (CodeSeg* S)
+/* Search for a call to steaxysp. If the eax register is not used later, and
+ * the value is constant, just use the A register and store directly into the
+ * stack.
+ */
+{
+    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 the input registers */
+        const RegInfo* RI = E->RI;
+
+       /* Check for the call */
+       if (CE_IsCallTo (E, "steaxysp")         &&
+            RegValIsKnown (RI->In.RegA)         &&
+            RegValIsKnown (RI->In.RegX)         &&
+            RegValIsKnown (RI->In.RegY)         &&
+            RegValIsKnown (RI->In.SRegLo)       &&
+            RegValIsKnown (RI->In.SRegHi)       &&
+            !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;
+
+            /* Setup other variables */
+            unsigned    Done = 0;
+            CodeEntry*  N;
+            unsigned    IP = I + 1;     /* Insertion point */
+
+            /* Replace the store. We will not remove the loads, since this is
+             * too complex and will be done by other optimizer steps.
+             */
+            N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI);
+            CS_InsertEntry (S, N, IP++);
+            InsertStore (S, &IP, E->LI);
+            Done |= 0x01;
+
+            /* Check if we can store one of the other bytes */
+            if (A == X && (Done & 0x02) == 0) {
+                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                InsertStore (S, &IP, E->LI);
+                Done |= 0x02;
+            }
+            if (A == L && (Done & 0x04) == 0) {
+                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                InsertStore (S, &IP, E->LI);
+                Done |= 0x04;
+            }
+            if (A == H && (Done & 0x08) == 0) {
+                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                InsertStore (S, &IP, E->LI);
+                Done |= 0x08;
+            }
+
+            /* Store the second byte */
+            if ((Done & 0x02) == 0) {
+                N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (X), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                InsertStore (S, &IP, E->LI);
+                Done |= 0x02;
+            }
+
+            /* Check if we can store one of the other bytes */
+            if (X == L && (Done & 0x04) == 0) {
+                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                InsertStore (S, &IP, E->LI);
+                Done |= 0x04;
+            }
+            if (X == H && (Done & 0x08) == 0) {
+                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                InsertStore (S, &IP, E->LI);
+                Done |= 0x08;
+            }
+
+            /* Store the third byte */
+            if ((Done & 0x04) == 0) {
+                N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (L), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                InsertStore (S, &IP, E->LI);
+                Done |= 0x04;
+            }
+
+            /* Check if we can store one of the other bytes */
+            if (L == H && (Done & 0x08) == 0) {
+                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                InsertStore (S, &IP, E->LI);
+                Done |= 0x08;
+            }
+
+            /* Store the fourth byte */
+            if ((Done & 0x08) == 0) {
+                N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (H), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
+                CS_InsertEntry (S, N, IP++);
+                InsertStore (S, &IP, E->LI);
+                Done |= 0x08;
+            }
+
+            /* Remove the call */
+            CS_DelEntry (S, I);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Free the register info */
+    CS_FreeRegInfo (S);
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
diff --git a/src/cc65/coptstore.h b/src/cc65/coptstore.h
new file mode 100644 (file)
index 0000000..29a97de
--- /dev/null
@@ -0,0 +1,71 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                  coptstore.h                              */
+/*                                                                           */
+/*                                Optimize stores                            */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2002      Ullrich von Bassewitz                                       */
+/*               Wacholderweg 14                                             */
+/*               D-70597 Stuttgart                                           */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef COPTSTORE_H
+#define COPTSTORE_H
+
+
+
+/* cc65 */
+#include "codeseg.h"
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+unsigned OptStore1 (CodeSeg* S);
+/* Search for a call to staxysp. If the ax register is not used later, and
+ * the value is constant, just use the A register and store directly into the
+ * stack.
+ */
+
+unsigned OptStore2 (CodeSeg* S);               
+/* Search for a call to steaxysp. If the eax register is not used later, and
+ * the value is constant, just use the A register and store directly into the
+ * stack.
+ */
+
+
+
+/* End of coptstore.h */
+
+#endif
+
+
+
index 7bd827448f7b28a144afbeb8aebd3c1933703341..7446bb8d0fc1c9a9817f02753ec16fc2d266fb1c 100644 (file)
@@ -42,6 +42,7 @@ OBJS =        anonname.o      \
        coptpush.o      \
         coptsize.o      \
        coptstop.o      \
+        coptstore.o     \
        coptsub.o       \
        copttest.o      \
        cpu.o           \
index be067caa1bcfb55bfd3cf56ae97fc92e5799208f..b55980c18e07237a992dc20321f8fd4f69db8836 100644 (file)
@@ -87,6 +87,7 @@ OBJS =        anonname.obj    \
        coptpush.obj    \
         coptsize.obj    \
        coptstop.obj    \
+        coptstore.obj   \
        coptsub.obj     \
        copttest.obj    \
        cpu.obj         \
@@ -169,6 +170,7 @@ FILE coptneg.obj
 FILE coptpush.obj
 FILE coptsize.obj
 FILE coptstop.obj
+FILE coptstore.obj
 FILE coptsub.obj
 FILE copttest.obj
 FILE cpu.obj
index 9b2abc86658151ecae566e8743847eeb0bafc65f..ecfe08a70d986e3ad2f1685320f4c9b1461c29ad 100644 (file)
@@ -44,7 +44,7 @@
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                  Data                                    */
 /*****************************************************************************/
 
 
@@ -82,6 +82,26 @@ void RC_Invalidate (RegContents* C);
 void RC_InvalidateZP (RegContents* C);
 /* Invalidate all ZP registers */
 
+#if defined(HAVE_INLINE)
+INLINE int RegValIsKnown (short Val)
+/* Return true if the register value is known */
+{
+    return (Val >= 0);
+}
+#else
+#  define RegValIsKnown(S)      ((S) >= 0)
+#endif
+
+#if defined(HAVE_INLINE)
+INLINE int RegValIsUnknown (short Val)
+/* Return true if the register value is not known */
+{
+    return (Val < 0);
+}
+#else
+#  define RegValIsUnknown(S)      ((S) < 0)
+#endif
+
 RegInfo* NewRegInfo (const RegContents* RC);
 /* Allocate a new register info, initialize and return it. If RC is not
  * a NULL pointer, it is used to initialize both, the input and output
@@ -93,9 +113,11 @@ void FreeRegInfo (RegInfo* RI);
 
 
 
+
+
 /* End of reginfo.h */
 #endif
 
 
 
-                   
+