]> git.sur5r.net Git - cc65/commitdiff
Added more size optimizations, separate module
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 8 Oct 2002 20:56:00 +0000 (20:56 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 8 Oct 2002 20:56:00 +0000 (20:56 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1453 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeent.c
src/cc65/codeinfo.c
src/cc65/codeopt.c
src/cc65/coptsize.c [new file with mode: 0644]
src/cc65/coptsize.h [new file with mode: 0644]
src/cc65/coptstop.c
src/cc65/make/gcc.mak
src/cc65/make/watcom.mak

index 50fa59a4e6673000327b39d29cdc7448ec577e86..6e96aaa071b0dc2eafa2bf1136a369022e0a142b 100644 (file)
@@ -1229,7 +1229,7 @@ void CE_Output (const CodeEntry* E, FILE* F)
        char Use [128];
        char Chg [128];
                fprintf (F,
-                        "%*s; USE: %-20s CHG: %-20s SIZE: %u\n",
+                        "%*s; USE: %-12s CHG: %-12s SIZE: %u\n",
                         30-Chars, "",
                 RegInfoDesc (E->Use, Use),
                 RegInfoDesc (E->Chg, Chg),
index 5014e71a4f1c8e179c848a2871d16633b8c194ec..3912dae9113e1ebe2c561c563fb1d5ce98d7de4a 100644 (file)
@@ -72,6 +72,8 @@ struct FuncInfo {
 };
 
 static const FuncInfo FuncInfoTable[] = {
+    { "addeq0sp",       REG_AX,               REG_AXY                        },
+    { "addeqysp",       REG_AXY,              REG_AXY                        },
     { "addysp",                REG_Y,                REG_NONE                       },
     { "aslax1",         REG_AX,                      REG_AX | REG_TMP1              },
     { "aslax2",         REG_AX,                      REG_AX | REG_TMP1              },
@@ -124,7 +126,7 @@ static const FuncInfo FuncInfoTable[] = {
     { "laddeqa",        REG_AY | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI         },
     { "ldaidx",         REG_AXY,              REG_AX | REG_PTR1                     },
     { "ldauidx",        REG_AXY,              REG_AX | REG_PTR1                     },
-    { "ldax0sp",               REG_Y,                REG_AX                         },
+    { "ldax0sp",               REG_NONE,             REG_AXY                        },
     { "ldaxi",          REG_AX,               REG_AXY | REG_PTR1            },
     { "ldaxidx",        REG_AXY,              REG_AXY | REG_PTR1                    },
     { "ldaxysp",               REG_Y,                REG_AXY                        },
@@ -135,9 +137,20 @@ static const FuncInfo FuncInfoTable[] = {
     { "lsubeqa",        REG_AY | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI         },
     { "lsubeqysp",      REG_EAXY,             REG_EAXY                       },
     { "negax",          REG_AX,               REG_AX                        },
+    { "push0",                 REG_NONE,             REG_AXY                        },
+    { "push1",                 REG_NONE,             REG_AXY                        },
+    { "push2",                 REG_NONE,             REG_AXY                        },
+    { "push3",                 REG_NONE,             REG_AXY                        },
+    { "push4",                 REG_NONE,             REG_AXY                        },
+    { "push5",                 REG_NONE,             REG_AXY                        },
+    { "push6",                 REG_NONE,             REG_AXY                        },
+    { "push7",                 REG_NONE,             REG_AXY                        },
     { "pusha",                 REG_A,                REG_Y                          },
     { "pusha0",                REG_A,                REG_XY                         },
     { "pushax",                REG_AX,               REG_Y                          },
+    { "pushc0",                REG_NONE,             REG_A | REG_Y                  },
+    { "pushc1",                REG_NONE,             REG_A | REG_Y                  },
+    { "pushc2",                REG_NONE,             REG_A | REG_Y                  },
     { "pusheax",        REG_EAX,              REG_Y                         },
     { "pushw0sp",              REG_NONE,             REG_AXY                        },
     { "pushwysp",              REG_Y,                REG_AXY                        },
@@ -158,16 +171,15 @@ static const FuncInfo FuncInfoTable[] = {
     { "staxysp",        REG_AXY,              REG_Y                         },
     { "subeq0sp",       REG_AX,               REG_AXY                        },
     { "subeqysp",       REG_AXY,              REG_AXY                        },
-    { "tsteax",         REG_EAX,              REG_Y                          },
     { "tosadda0",       REG_A,                REG_AXY                        },
     { "tosaddax",       REG_AX,               REG_AXY                        },
-    { "tosicmp",               REG_AX,               REG_AXY | REG_SREG             },
     { "tosdiva0",       REG_AX,                      REG_ALL                        },
     { "tosdivax",       REG_AX,                      REG_ALL                        },
     { "tosdiveax",      REG_EAX,                     REG_ALL                        },
     { "toseqeax",       REG_EAX,                     REG_AXY | REG_PTR1             },
     { "tosgeeax",       REG_EAX,                     REG_AXY | REG_PTR1             },
     { "tosgteax",       REG_EAX,                     REG_AXY | REG_PTR1             },
+    { "tosicmp",               REG_AX,               REG_AXY | REG_SREG             },
     { "toslcmp",        REG_EAX,                     REG_A | REG_Y | REG_PTR1       },
     { "tosleeax",       REG_EAX,                     REG_AXY | REG_PTR1             },
     { "toslteax",       REG_EAX,                     REG_AXY | REG_PTR1             },
@@ -186,6 +198,7 @@ static const FuncInfo FuncInfoTable[] = {
     { "tosumula0",      REG_AX,                      REG_ALL                        },
     { "tosumulax",      REG_AX,                      REG_ALL                        },
     { "tosumuleax",     REG_EAX,                     REG_ALL                        },
+    { "tsteax",         REG_EAX,              REG_Y                          },
     { "utsteax",        REG_EAX,              REG_Y                          },
 };
 #define FuncInfoCount  (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
index 50b014212faee11a04de5b4886931636e6e19808..1690a42bc55d123162e42f5a20439b860141ba8c 100644 (file)
@@ -53,6 +53,7 @@
 #include "coptind.h"
 #include "coptneg.h"
 #include "coptpush.h"
+#include "coptsize.h"
 #include "coptstop.h"
 #include "coptsub.h"
 #include "copttest.h"
@@ -1277,238 +1278,7 @@ static unsigned OptDecouple (CodeSeg* S)
 
        /* Insert the replacement if we have one */
        if (X) {
-           CS_InsertEntry (S, X, I+1);
-           CS_DelEntry (S, I);
-           ++Changes;
-       }
-
-       /* Next entry */
-       ++I;
-
-    }
-
-    /* Free register info */
-    CS_FreeRegInfo (S);
-
-    /* Return the number of changes made */
-    return Changes;
-}
-
-
-
-/*****************************************************************************/
-/*                            Size optimization                             */
-/*****************************************************************************/
-
-
-
-#if 0
-static unsigned OptSize1 (CodeSeg* S)
-/* Do size optimization by calling special subroutines that preload registers.
- * This routine does not work standalone, it needs a following register load
- * removal pass.
- */
-{
-    typedef struct CallDesc CallDesc;
-    struct CallDesc {
-        const char*     LongFunc;       /* Long function name */
-        short           A, X, Y;        /* Register contents */
-        const char*     ShortFunc;      /* Short function name */
-    };
-
-    static const CallDesc CallTable [] = {
-               { "staxysp",    -1,   -1,    0, "stax0sp"       },
-               { "addeqysp",   -1,   -1,    0, "addeq0sp"      },
-               { "ldaxysp",    -1,   -1,    1, "ldax0sp"       },
-               { "ldeaxysp",   -1,   -1,    3, "ldeax0sp"      },
-               { "pushax",      0,    0,   -1, "push0"         },
-               { "pushax",     -1,    0,   -1, "pusha0"        },
-               { "pushax",     -1, 0xFF,   -1, "pushaFF"       },
-               { "pushaysp",   -1,   -1,    0, "pusha0sp"      },
-               { "tosaddax",   -1,    0,   -1, "tosadda0"      },
-               { "tosandax",   -1,    0,   -1, "tosanda0"      },
-               { "tosdivax",   -1,    0,   -1, "tosdiva0"      },
-               { "toseqax",    -1,    0,   -1, "toseqa0"       },
-               { "tosgeax",    -1,    0,   -1, "tosgea0"       },
-               { "tosgtax",    -1,    0,   -1, "tosgta0"       },
-               { "laddeqysp",  -1,   -1,    0, "laddeq0sp"     },
-        { "ldaxidx",    -1,   -1,    1, "ldaxi"         },
-               { "ldeaxidx",   -1,   -1,    3, "ldeaxi"        },
-        { "ldeaxysp",   -1,   -1,    3, "ldeax0sp"      },
-               { "tosleax",    -1,    0,   -1, "toslea0"       },
-        { "lsubeqysp",  -1,   -1,    0, "lsubeq0sp"     },
-
-       "toslta0",           /* tosltax, x = 0 */
-       "tosmoda0",          /* tosmodax, x = 0 */
-       "tosmula0",          /* tosmulax, x = 0 */
-       "tosumula0",         /* tosumulax, x = 0 */
-       "tosnea0",           /* tosneax, x = 0 */
-       "tosora0",           /* tosorax, x = 0 */
-       "push1",             /* pushax, x = 0, a = 1 */
-               "push2",             /* pushax, x = 0, a = 2 */
-       "push3",             /* pushax, x = 0, a = 3 */
-       "push4",             /* pushax, x = 0, a = 4 */
-       "push5",             /* pushax, x = 0, a = 5 */
-       "push6",             /* pushax, x = 0, a = 6 */
-       "push7",             /* pushax, x = 0, a = 7 */
-       "pushc0",            /* pusha, a = 0 */
-               "pushc1",            /* pusha, a = 1 */
-       "pushc2",            /* pusha, a = 2 */
-       "tosrsuba0",         /* tosrsubax, x = 0 */
-       "tosshla0",          /* tosshlax, x = 0 */
-       "tosasla0",          /* tosaslax, x = 0 */
-       "tosshra0",          /* tosshrax, x = 0 */
-       "tosasra0",          /* tosasrax, x = 0 */
-       "steax0sp",          /* steaxsp, y = 0 */
-       "tossuba0",          /* tossubax, x = 0 */
-       "subeq0sp",          /* subeqysp, y = 0 */
-       "tosudiva0",         /* tosudivax, x = 0 */
-       "tosugea0",          /* tosugeax, x = 0 */
-               "tosugta0",          /* tosugtax, x = 0 */
-               "tosulea0",          /* tosuleax, x = 0 */
-               "tosulta0",          /* tosultax, x = 0 */
-               "tosumoda0",         /* tosumodax, x = 0 */
-               "tosxora0",          /* tosxorax, x = 0 */
-
-               "tosadd0ax",         /* tosaddeax, sreg = 0 */
-       "laddeqa",           /* laddeq, sreg = 0, x = 0 */
-       "laddeq1",           /* laddeq, sreg = 0, x = 0, a = 1 */
-               "tosand0ax",         /* tosandeax, sreg = 0 */
-       "tosdiv0ax",         /* tosdiveax, sreg = 0 */
-       "tosmod0ax",         /* tosmodeax, sreg = 0 */
-       "tosmul0ax",         /* tosmuleax, sreg = 0 */
-               "tosumul0ax",        /* tosumuleax, sreg = 0 */
-       "tosor0ax",          /* tosoreax, sreg = 0 */
-       "push0ax",           /* pusheax, sreg = 0 */
-       "tosrsub0ax",        /* tosrsubeax, sreg = 0 */
-       "tosshl0ax",         /* tosshleax, sreg = 0 */
-       "tosasl0ax",         /* tosasleax, sreg = 0 */
-       "tosshr0ax",         /* tosshreax, sreg = 0 */
-       "tosasr0ax",         /* tosasreax, sreg = 0 */
-       "tossub0ax",         /* tossubeax, sreg = 0 */
-       "lsubeqa",           /* lsubeq, sreg = 0, x = 0 */
-       "lsubeq1",           /* lsubeq, sreg = 0, x = 0, a = 1 */
-       "tosudiv0ax",        /* tosudiveax, sreg = 0 */
-       "tosumod0ax",        /* tosumodeax, sreg = 0 */
-       "tosxor0ax",         /* tosxoreax, sreg = 0 */
-
-    };
-
-    unsigned Changes = 0;
-    unsigned I;
-
-    /* Generate register info for the following step */
-    CS_GenRegInfo (S);
-
-    /* Walk over the entries */
-    I = 0;
-    while (I < CS_GetEntryCount (S)) {
-
-       /* Get next entry */
-               CodeEntry* E = CS_GetEntry (S, I);
-
-       /* Check if it's a subroutine call */
-       if (E->OPC == OP65_JSR) {
-
-           /* Check for any of the known functions */
-
-
-
-       }
-
-       /* Next entry */
-       ++I;
-
-    }
-
-    /* Free register info */
-    CS_FreeRegInfo (S);
-
-    /* Return the number of changes made */
-    return Changes;
-}
-#endif
-
-
-
-static unsigned OptSize2 (CodeSeg* S)
-/* Do size optimization by using shorter code sequences, even if this
- * introduces relations between instructions. This step must be one of the
- * last steps, because it makes further work much more difficult.
- */
-{
-    unsigned Changes = 0;
-    unsigned I;
-
-    /* Generate register info for the following step */
-    CS_GenRegInfo (S);
-
-    /* Walk over the entries */
-    I = 0;
-    while (I < CS_GetEntryCount (S)) {
-
-
-       /* Get next entry */
-               CodeEntry* E = CS_GetEntry (S, I);
-
-       /* Assume we have no replacement */
-       CodeEntry* X = 0;
-
-       /* Check the instruction */
-       switch (E->OPC) {
-
-           case OP65_LDA:
-               if (CE_KnownImm (E)) {
-                   short Val = (short) E->Num;
-                   if (Val == E->RI->In.RegX) {
-                       X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, E->LI);
-                   } else if (Val == E->RI->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)) {
-                           X = NewCodeEntry (OP65_DEA, AM65_IMP, 0, 0, E->LI);
-                       } else if (Val == ((E->RI->In.RegA + 1) & 0xFF)) {
-                           X = NewCodeEntry (OP65_INA, AM65_IMP, 0, 0, E->LI);
-                       }
-                   }
-               }
-               break;
-
-           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)) {
-                       X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, E->LI);
-                   } else if (E->RI->In.RegX >= 0 && Val == ((E->RI->In.RegX + 1) & 0xFF)) {
-                       X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
-                   } else if (Val == E->RI->In.RegA) {
-                       X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI);
-                    }
-               }
-               break;
-
-           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)) {
-                       X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI);
-                   } else if (E->RI->In.RegY >= 0 && Val == ((E->RI->In.RegY + 1) & 0xFF)) {
-                       X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, E->LI);
-                   } else if (Val == E->RI->In.RegA) {
-                       X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, E->LI);
-                   }
-               }
-               break;
-
-           default:
-               /* Avoid gcc warnings */
-               break;
-
-       }
-
-       /* Insert the replacement if we have one */
-       if (X) {
-           CS_InsertEntry (S, X, I+1);
+                   CS_InsertEntry (S, X, I+1);
            CS_DelEntry (S, I);
            ++Changes;
        }
@@ -1598,7 +1368,7 @@ static OptFunc DOptPushPop      = { OptPushPop,      "OptPushPop",        0, 0,
 static OptFunc DOptShift1              = { OptShift1,       "OptShift1",       100, 0, 0, 0, 0, 0 };
 static OptFunc DOptShift2              = { OptShift2,       "OptShift2",       100, 0, 0, 0, 0, 0 };
 static OptFunc DOptShift3              = { OptShift3,       "OptShift3",       110, 0, 0, 0, 0, 0 };
-/*static OptFunc DOptSize1        = { OptSize1,        "OptSize1",        100, 0, 0, 0, 0, 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 DOptStoreLoad           = { OptStoreLoad,    "OptStoreLoad",      0, 0, 0, 0, 0, 0 };
@@ -1656,7 +1426,7 @@ static OptFunc* OptFuncs[] = {
     &DOptShift1,
     &DOptShift2,
     &DOptShift3,
-    /*&DOptSize1,*/
+    &DOptSize1,
     &DOptSize2,
     &DOptStackOps,
     &DOptStoreLoad,
@@ -2037,16 +1807,30 @@ static unsigned RunOptGroup6 (CodeSeg* S)
     unsigned Changes = 0;
     unsigned C;
 
-    /* Optimize for size, that is replace operations by shorter ones, even
-     * if this does hinder further optimizations (no problem since we're
-     * done soon).
-     */
-    Changes += RunOptFunc (S, &DOptSize2, 1);
-
-    /* Run the jump target optimization again, since the size optimization
-     * above may have opened new oportunities.
-     */
-    Changes += RunOptFunc (S, &DOptJumpTarget, 5);
+    if (CodeSizeFactor <= 100) {
+        /* Optimize for size, that is replace operations by shorter ones, even
+         * if this does hinder further optimizations (no problem since we're
+         * done soon).
+         */
+        C = RunOptFunc (S, &DOptSize1, 1);
+        if (C) {
+            Changes += C;
+            /* Run some optimization passes again, since the size optimizations
+             * may have opened new oportunities.
+             */
+            Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
+            Changes += RunOptFunc (S, &DOptJumpTarget, 5);
+        }
+    }
+    C = RunOptFunc (S, &DOptSize2, 1);
+    if (C) {
+        Changes += C;
+        /* Run some optimization passes again, since the size optimizations
+         * may have opened new oportunities.
+         */
+        Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
+        Changes += RunOptFunc (S, &DOptJumpTarget, 5);
+    }
 
     /* Adjust branch distances */
     Changes += RunOptFunc (S, &DOptBranchDist, 3);
diff --git a/src/cc65/coptsize.c b/src/cc65/coptsize.c
new file mode 100644 (file)
index 0000000..f5db1dd
--- /dev/null
@@ -0,0 +1,349 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                coptsize.c                                */
+/*                                                                           */
+/*                              Size optimizations                           */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (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.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#include <stdlib.h>
+
+/* cc65 */
+#include "codeent.h"
+#include "codeinfo.h"
+#include "cpu.h"
+#include "coptsize.h"
+
+
+
+/*****************************************************************************/
+/*                                   Data                                    */
+/*****************************************************************************/
+
+
+
+typedef struct CallDesc CallDesc;
+struct CallDesc {
+    const char*     LongFunc;       /* Long function name */
+    short           A, X, Y;        /* Register contents */
+    const char*     ShortFunc;      /* Short function name */
+};
+
+/* Note: The table is sorted. If there is more than one entry with the same
+ * name, entries are sorted best match first, so when searching linear for
+ * a match, the first one can be used because it is also the best one (or
+ * at least none of the following ones are better).
+ */
+static const CallDesc CallTable [] = {
+    { "addeqysp",   -1,   -1,    0, "addeq0sp"      },
+    { "laddeqysp",  -1,   -1,    0, "laddeq0sp"     },
+    { "ldaxysp",    -1,   -1,    1, "ldax0sp"       },
+    { "ldeaxidx",   -1,   -1,    3, "ldeaxi"        },
+    { "ldeaxysp",   -1,   -1,    3, "ldeax0sp"      },
+    { "pusha",       0,   -1,   -1, "pushc0"        },
+    { "pusha",       1,   -1,   -1, "pushc1"        },
+    { "pusha",       2,   -1,   -1, "pushc2"        },
+    { "pushax",      0,    0,   -1, "push0"         },
+    { "pushax",      1,    0,   -1, "push1"         },
+    { "pushax",      2,    0,   -1, "push2"         },
+    { "pushax",      3,    0,   -1, "push3"         },
+    { "pushax",      4,    0,   -1, "push4"         },
+    { "pushax",      5,    0,   -1, "push5"         },
+    { "pushax",      6,    0,   -1, "push6"         },
+    { "pushax",      7,    0,   -1, "push7"         },
+    { "pushax",     -1,    0,   -1, "pusha0"        },
+    { "pushax",     -1, 0xFF,   -1, "pushaFF"       },
+    { "pushaysp",   -1,   -1,    0, "pusha0sp"      },
+    { "staxysp",    -1,   -1,    0, "stax0sp"       },
+    { "tosaddax",   -1,    0,   -1, "tosadda0"      },
+    { "tosandax",   -1,    0,   -1, "tosanda0"      },
+    { "tosdivax",   -1,    0,   -1, "tosdiva0"      },
+    { "toseqax",    -1,    0,   -1, "toseqa0"       },
+    { "tosgeax",    -1,    0,   -1, "tosgea0"       },
+    { "tosgtax",    -1,    0,   -1, "tosgta0"       },
+    { "tosleax",    -1,    0,   -1, "toslea0"       },
+    { "tosorax",    -1,    0,   -1, "tosora0"       },
+    { "ldaxidx",    -1,   -1,    1, "ldaxi"         },
+    { "ldeaxysp",   -1,   -1,    3, "ldeax0sp"      },
+    { "lsubeqysp",  -1,   -1,    0, "lsubeq0sp"     },
+    { "steaxysp",   -1,   -1,    0, "steax0sp"      },
+    { "subeqysp",   -1,   -1,    0, "subeq0sp"      },
+    { "tosaslax",   -1,    0,   -1, "tosasla0"      },
+    { "tosasrax",   -1,    0,   -1, "tosasra0"      },
+    { "tosltax",    -1,    0,   -1, "toslta0"       },
+    { "tosmodax",   -1,    0,   -1, "tosmoda0"      },
+    { "tosmulax",   -1,    0,   -1, "tosmula0"      },
+    { "tosneax",    -1,    0,   -1, "tosnea0"       },
+    { "tosrsubax",  -1,    0,   -1, "tosrsuba0"     },
+    { "tosshlax",   -1,    0,   -1, "tosshla0"      },
+    { "tosshrax",   -1,    0,   -1, "tosshra0"      },
+    { "tossubax",   -1,    0,   -1, "tossuba0"      },
+    { "tosudivax",  -1,    0,   -1, "tosudiva0"     },
+    { "tosugeax",   -1,    0,   -1, "tosugea0"      },
+    { "tosugtax",   -1,    0,   -1, "tosugta0"      },
+    { "tosuleax",   -1,    0,   -1, "tosulea0"      },
+    { "tosultax",   -1,    0,   -1, "tosulta0"      },
+    { "tosumodax",  -1,    0,   -1, "tosumoda0"     },
+    { "tosumulax",  -1,    0,   -1, "tosumula0"     },
+    { "tosxorax",   -1,    0,   -1, "tosxora0"      },
+    { "zzzzzzzz",   -1,   -1,   -1, "zzzzzzzz"      },
+
+#if 0
+    "tosadd0ax",         /* tosaddeax, sreg = 0 */
+    "laddeqa",           /* laddeq, sreg = 0, x = 0 */
+    "laddeq1",           /* laddeq, sreg = 0, x = 0, a = 1 */
+    "tosand0ax",         /* tosandeax, sreg = 0 */
+    "tosdiv0ax",         /* tosdiveax, sreg = 0 */
+    "tosmod0ax",         /* tosmodeax, sreg = 0 */
+    "tosmul0ax",         /* tosmuleax, sreg = 0 */
+    "tosumul0ax",        /* tosumuleax, sreg = 0 */
+    "tosor0ax",          /* tosoreax, sreg = 0 */
+    "push0ax",           /* pusheax, sreg = 0 */
+    "tosrsub0ax",        /* tosrsubeax, sreg = 0 */
+    "tosshl0ax",         /* tosshleax, sreg = 0 */
+    "tosasl0ax",         /* tosasleax, sreg = 0 */
+    "tosshr0ax",         /* tosshreax, sreg = 0 */
+    "tosasr0ax",         /* tosasreax, sreg = 0 */
+    "tossub0ax",         /* tossubeax, sreg = 0 */
+    "lsubeqa",           /* lsubeq, sreg = 0, x = 0 */
+    "lsubeq1",           /* lsubeq, sreg = 0, x = 0, a = 1 */
+    "tosudiv0ax",        /* tosudiveax, sreg = 0 */
+    "tosumod0ax",        /* tosumodeax, sreg = 0 */
+    "tosxor0ax",         /* tosxoreax, sreg = 0 */
+#endif
+};
+#define CALL_COUNT (sizeof(CallTable) / sizeof(CallTable[0]))
+
+
+
+/*****************************************************************************/
+/*                                         Helpers                                  */
+/*****************************************************************************/
+
+
+
+static const CallDesc* FindCall (const char* Name)
+/* Find the function with the given name. Return a pointer to the table entry
+ * or NULL if the function was not found.
+ */
+{
+    /* Do a binary search */
+    int First = 0;
+    int Last = (sizeof(CallTable) / sizeof(CallTable[0])) - 1;
+    int Current;
+    int Result;
+    int Found = 0;
+
+    while (First <= Last) {
+
+               /* Set current to mid of range */
+       Current = (Last + First) / 2;
+
+               /* Do a compare */
+               Result = strcmp (CallTable[Current].LongFunc, Name);
+       if (Result < 0) {
+           First = Current + 1;
+       } else {
+           Last = Current - 1;
+           if (Result == 0) {
+                       /* Found. Repeat the procedure until the first of all entries
+                 * with the same name is found.
+                 */
+               Found = 1;
+           }
+       }
+
+    }
+
+    /* Return the first entry if found, or NULL otherwise */
+    return Found? &CallTable[First] : 0;
+}
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+unsigned OptSize1 (CodeSeg* S)
+/* Do size optimization by calling special subroutines that preload registers.
+ * This routine does not work standalone, it needs a following register load
+ * removal pass.
+ */
+{
+    CodeEntry* E;
+    unsigned Changes = 0;
+    unsigned I;
+
+    /* Generate register info for the following step */
+    CS_GenRegInfo (S);
+
+    /* Walk over the entries */
+    I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+       /* Get next entry */
+               E = CS_GetEntry (S, I);
+
+       /* Check if it's a subroutine call */
+       if (E->OPC == OP65_JSR) {
+
+           /* Check for any of the known functions. */
+            const CallDesc* D = FindCall (E->Arg);
+            while (D && strcmp (D->LongFunc, E->Arg) == 0) {
+                /* Check the registers */
+                if ((D->A < 0 || D->A == E->RI->In.RegA) &&
+                    (D->X < 0 || D->X == E->RI->In.RegX) &&
+                    (D->Y < 0 || D->Y == E->RI->In.RegY)) {
+                    /* Ok, match for all registers */
+                    CodeEntry* X;
+                    X = NewCodeEntry (E->OPC, E->AM, D->ShortFunc, 0, E->LI);
+                    CS_InsertEntry (S, X, I+1);
+                    CS_DelEntry (S, I);
+
+                    /* Remember that we had changes */
+                    ++Changes;
+                }
+                ++D;
+            }
+        }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Free register info */
+    CS_FreeRegInfo (S);
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+unsigned OptSize2 (CodeSeg* S)
+/* Do size optimization by using shorter code sequences, even if this
+ * introduces relations between instructions. This step must be one of the
+ * last steps, because it makes further work much more difficult.
+ */
+{
+    unsigned Changes = 0;
+    unsigned I;
+
+    /* Generate register info for the following step */
+    CS_GenRegInfo (S);
+
+    /* Walk over the entries */
+    I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+
+       /* Get next entry */
+               CodeEntry* E = CS_GetEntry (S, I);
+
+       /* Assume we have no replacement */
+       CodeEntry* X = 0;
+
+       /* Check the instruction */
+       switch (E->OPC) {
+
+           case OP65_LDA:
+               if (CE_KnownImm (E)) {
+                   short Val = (short) E->Num;
+                   if (Val == E->RI->In.RegX) {
+                       X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, E->LI);
+                   } else if (Val == E->RI->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)) {
+                           X = NewCodeEntry (OP65_DEA, AM65_IMP, 0, 0, E->LI);
+                       } else if (Val == ((E->RI->In.RegA + 1) & 0xFF)) {
+                           X = NewCodeEntry (OP65_INA, AM65_IMP, 0, 0, E->LI);
+                       }
+                   }
+               }
+               break;
+
+           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)) {
+                       X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, E->LI);
+                   } else if (E->RI->In.RegX >= 0 && Val == ((E->RI->In.RegX + 1) & 0xFF)) {
+                       X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
+                   } else if (Val == E->RI->In.RegA) {
+                       X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI);
+                    }
+               }
+               break;
+
+                   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)) {
+                       X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI);
+                   } else if (E->RI->In.RegY >= 0 && Val == ((E->RI->In.RegY + 1) & 0xFF)) {
+                       X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, E->LI);
+                   } else if (Val == E->RI->In.RegA) {
+                       X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, E->LI);
+                   }
+               }
+               break;
+
+           default:
+               /* Avoid gcc warnings */
+               break;
+
+       }
+
+       /* Insert the replacement if we have one */
+       if (X) {
+           CS_InsertEntry (S, X, I+1);
+           CS_DelEntry (S, I);
+           ++Changes;
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Free register info */
+    CS_FreeRegInfo (S);
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
diff --git a/src/cc65/coptsize.h b/src/cc65/coptsize.h
new file mode 100644 (file)
index 0000000..13eeae0
--- /dev/null
@@ -0,0 +1,70 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                coptsize.c                                */
+/*                                                                           */
+/*                              Size optimizations                           */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (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 COPTSIZE_H
+#define COPTSIZE_H
+
+
+
+/* cc65 */
+#include "codeseg.h"
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+unsigned OptSize1 (CodeSeg* S);
+/* Do size optimization by calling special subroutines that preload registers.
+ * This routine does not work standalone, it needs a following register load
+ * removal pass.
+ */
+
+unsigned OptSize2 (CodeSeg* S);
+/* Do size optimization by using shorter code sequences, even if this
+ * introduces relations between instructions. This step must be one of the
+ * last steps, because it makes further work much more difficult.
+ */
+
+
+
+/* End of coptsize.h */
+#endif
+
+
+
index 360e64729adc31280eebd346cf6668401ee658da..4e1c2e6d7ceb5b3d2b32d72271ad7d10f50839e7 100644 (file)
@@ -38,8 +38,6 @@
 /* cc65 */
 #include "codeent.h"
 #include "codeinfo.h"
-#include "codeopt.h"
-#include "error.h"
 #include "coptstop.h"
 
 
index 9d33f33870ad6e6efbba17abfb1870ccf49533a4..7bd827448f7b28a144afbeb8aebd3c1933703341 100644 (file)
@@ -40,6 +40,7 @@ OBJS =        anonname.o      \
        coptind.o       \
        coptneg.o       \
        coptpush.o      \
+        coptsize.o      \
        coptstop.o      \
        coptsub.o       \
        copttest.o      \
index 72bb310877315b7ff66bac45cc3e9269140de008..be067caa1bcfb55bfd3cf56ae97fc92e5799208f 100644 (file)
@@ -85,6 +85,7 @@ OBJS =        anonname.obj    \
        coptind.obj     \
        coptneg.obj     \
        coptpush.obj    \
+        coptsize.obj    \
        coptstop.obj    \
        coptsub.obj     \
        copttest.obj    \
@@ -166,6 +167,7 @@ FILE coptcmp.obj
 FILE coptind.obj
 FILE coptneg.obj
 FILE coptpush.obj
+FILE coptsize.obj
 FILE coptstop.obj
 FILE coptsub.obj
 FILE copttest.obj
@@ -181,7 +183,7 @@ FILE exprnode.obj
 FILE funcdesc.obj
 FILE function.obj
 FILE global.obj
-FILE goto.obj            
+FILE goto.obj
 FILE hexval.obj
 FILE ident.obj
 FILE incpath.obj