]> git.sur5r.net Git - cc65/commitdiff
Working
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 20 May 2001 20:42:00 +0000 (20:42 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 20 May 2001 20:42:00 +0000 (20:42 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@735 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeinfo.c
src/cc65/codeopt.c
src/cc65/codeseg.c
src/cc65/funcdesc.c
src/cc65/funcdesc.h

index 9d41d877a6720589a9c6b136c14ca86f7b5cca86..0bbeffad1dbbc41be2c898d324d94fa66e0637f1 100644 (file)
@@ -42,7 +42,9 @@
 /* cc65 */
 #include "codeent.h"
 #include "codeseg.h"
+#include "datatype.h"
 #include "error.h"
+#include "symtab.h"
 #include "codeinfo.h"
 
 
@@ -132,20 +134,63 @@ void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg)
  * load all registers.
  */
 {
-    /* Search for the function */
-    const FuncInfo* Info = bsearch (Name, FuncInfoTable, FuncInfoCount,
-                                   sizeof(FuncInfo), CompareFuncInfo);
-
-    /* Do we know the function? */
-    if (Info) {
-       /* Use the information we have */
-               *Use = Info->Use;
-       *Chg = Info->Chg;
+    /* If the function name starts with an underline, it is an external
+     * function. Search for it in the symbol table. If the function does
+     * not start with an underline, it may be a runtime support function.
+     * Search for it in the list of builtin functions.
+     */
+    if (Name[0] == '_') {
+
+       /* Search in the symbol table, skip the leading underscore */
+       SymEntry* E = FindSym (Name+1);
+
+       /* Did we find it in the top level table? */
+       if (E && E->Owner->PrevTab == 0 && IsTypeFunc (E->Type)) {
+
+           /* A function may use the A or A/X registers if it is a fastcall
+            * function. Otherwise it does not use any registers passed by
+            * the caller. However, we assume that any function will destroy
+            * all registers.
+            */
+           FuncDesc* D = E->V.F.Func;
+           if ((D->Flags & FD_FASTCALL) != 0 && D->ParamCount > 0) {
+               /* Will use registers depending on the last param */
+               SymEntry* LastParam = D->SymTab->SymTail;
+               if (SizeOf (LastParam->Type) == 1) {
+                   *Use = REG_A;
+               } else {
+                   *Use = REG_AX;
+               }
+           } else {
+               /* Will not use any registers */
+               *Use = REG_NONE;
+           }
+
+           /* Will destroy all registers */
+           *Chg = REG_AXY;
+
+           /* Done */
+           return;
+       }
+
     } else {
-       /* Assume all registers used */
-       *Use = REG_AXY;
-       *Chg = REG_AXY;
+
+       /* Search for the function in the list of builtin functions */
+       const FuncInfo* Info = bsearch (Name, FuncInfoTable, FuncInfoCount,
+                                       sizeof(FuncInfo), CompareFuncInfo);
+
+       /* Do we know the function? */
+       if (Info) {
+           /* Use the information we have */
+           *Use = Info->Use;
+           *Chg = Info->Chg;
+           return;
+       }
     }
+
+    /* Function not found - assume all registers used */
+    *Use = REG_AXY;
+    *Chg = REG_AXY;
 }
 
 
index 2084145266613502af87127fe52140d294c82d95..4b9dfefa271458b797ef71f3cf98a9cbb9019aab 100644 (file)
@@ -243,7 +243,7 @@ static int IsLocalLoad16 (CodeSeg* S, unsigned Index,
            L[3]->OPC == OPC_DEY                      &&
            !CodeEntryHasLabel (L[3])                 &&
            IsSpLoad (L[4])                           &&
-           !CodeEntryHasLabel (L[4]));               
+           !CodeEntryHasLabel (L[4]));
 }
 
 
@@ -420,6 +420,196 @@ NextEntry:
 
 
 
+/*****************************************************************************/
+/*                          Optimize subtractions                           */
+/*****************************************************************************/
+
+
+
+static unsigned OptSub1 (CodeSeg* S)
+/* Search for the sequence
+ *
+ *     sbc     ...
+ *      bcs     L
+ *     dex
+ * L:
+ *
+ * and remove the handling of the high byte if X is not used later.
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       CodeEntry* L[3];
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check for the sequence */
+               if (E->OPC == OPC_SBC                              &&
+           GetCodeEntries (S, L, I+1, 3)                  &&
+                   (L[0]->OPC == OPC_BCS || L[0]->OPC == OPC_JCS) &&
+           L[0]->JumpTo != 0                              &&
+           !CodeEntryHasLabel (L[0])                      &&
+           L[1]->OPC == OPC_DEX                           &&
+           !CodeEntryHasLabel (L[1])                      &&
+           L[0]->JumpTo->Owner == L[2]                    &&
+           !RegXUsed (S, I+3)) {
+
+           /* Remove the bcs/dex */
+           DelCodeEntries (S, I+1, 2);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+static unsigned OptSub2 (CodeSeg* S)
+/* Search for the sequence
+ *
+ *     lda     xx
+ *      sec
+ *     sta     tmp1
+ *      lda     yy
+ *      sbc     tmp1
+ *      sta     yy
+ *
+ * and replace it by
+ *
+ *      sec
+ *      lda     yy
+ *             sbc     xx
+ *      sta     yy
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       CodeEntry* L[5];
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check for the sequence */
+               if (E->OPC == OPC_LDA                              &&
+           GetCodeEntries (S, L, I+1, 5)                  &&
+                   L[0]->OPC == OPC_SEC                           &&
+           !CodeEntryHasLabel (L[0])                      &&
+                   L[1]->OPC == OPC_STA                           &&
+           strcmp (L[1]->Arg, "tmp1") == 0                &&
+           !CodeEntryHasLabel (L[1])                      &&
+           L[2]->OPC == OPC_LDA                           &&
+                   !CodeEntryHasLabel (L[2])                      &&
+           L[3]->OPC == OPC_SBC                           &&
+           strcmp (L[3]->Arg, "tmp1") == 0                &&
+                   !CodeEntryHasLabel (L[3])                      &&
+           L[4]->OPC == OPC_STA                           &&
+           strcmp (L[4]->Arg, L[2]->Arg) == 0             &&
+                   !CodeEntryHasLabel (L[4])) {
+
+           /* Remove the store to tmp1 */
+           DelCodeEntry (S, I+2);
+
+           /* Remove the subtraction */
+           DelCodeEntry (S, I+3);
+
+           /* Move the lda to the position of the subtraction and change the
+            * op to SBC.
+            */
+           MoveCodeEntry (S, I, I+3);
+           ReplaceOPC (E, OPC_SBC);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+/*****************************************************************************/
+/*                           Optimize additions                             */
+/*****************************************************************************/
+
+
+
+static unsigned OptAdd1 (CodeSeg* S)
+/* Search for the sequence
+ *
+ *     adc     ...
+ *      bcc     L
+ *     inx
+ * L:
+ *
+ * and remove the handling of the high byte if X is not used later.
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       CodeEntry* L[3];
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check for the sequence */
+               if (E->OPC == OPC_ADC                              &&
+           GetCodeEntries (S, L, I+1, 3)                  &&
+                   (L[0]->OPC == OPC_BCC || L[0]->OPC == OPC_JCC) &&
+           L[0]->JumpTo != 0                              &&
+           !CodeEntryHasLabel (L[0])                      &&
+           L[1]->OPC == OPC_INX                           &&
+           !CodeEntryHasLabel (L[1])                      &&
+           L[0]->JumpTo->Owner == L[2]                    &&
+           !RegXUsed (S, I+3)) {
+
+           /* Remove the bcs/dex */
+           DelCodeEntries (S, I+1, 2);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
 /*****************************************************************************/
 /*                       Optimizations for compares                         */
 /*****************************************************************************/
@@ -1007,6 +1197,11 @@ struct OptFunc {
 
 /* Table with optimizer steps -  are called in this order */
 static OptFunc OptFuncs [] = {
+    /* Optimize subtractions */
+    { OptSub1,                     "OptSub1",                  0       },
+    { OptSub2,                     "OptSub2",                  0       },
+    /* Optimize additions */
+    { OptAdd1,                     "OptAdd1",                  0       },
     /* Optimize jump cascades */
     { OptJumpCascades,             "OptJumpCascades",          0       },
     /* Remove dead jumps */
@@ -1025,21 +1220,15 @@ static OptFunc OptFuncs [] = {
     { OptBoolTransforms,    "OptBoolTransforms",       0       },
     /* Optimize calls to nega */
     { OptNegA1,                    "OptNegA1",                 0       },
-    /* Optimize calls to nega */
     { OptNegA2,                    "OptNegA2",                 0       },
     /* Optimize calls to negax */
     { OptNegAX1,                   "OptNegAX1",                0       },
-    /* Optimize calls to negax */
     { OptNegAX2,                   "OptNegAX2",                0       },
-    /* Optimize calls to negax */
     { OptNegAX3,                   "OptNegAX3",                0       },
     /* Optimize compares */
     { OptCmp1,              "OptCmp1",                  0       },
-    /* Optimize compares */
     { OptCmp2,              "OptCmp2",                  0       },
-    /* Optimize compares */
     { OptCmp3,              "OptCmp3",                  0       },
-    /* Optimize compares */
     { OptCmp4,              "OptCmp4",                  0       },
     /* Remove unused loads */
     { OptUnusedLoads,      "OptUnusedLoads",           0       },
index fb971183aa0e030b24148f4ee0af6204db6da542..6565d2b8fc496544c2a9471dff668e0eb973c776 100644 (file)
@@ -889,6 +889,16 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last)
 
        /* Check if this entry has a label reference */
        if (E->JumpTo) {
+           /* If the label is a label in the label pool and this is the last
+            * reference to the label, remove the label from the pool.
+            */
+           CodeLabel* L = E->JumpTo;
+           int Index = CollIndex (&S->Labels, L);
+           if (Index >= 0 && CollCount (&L->JumpFrom) == 1) {
+               /* Delete it from the pool */
+               CollDelete (&S->Labels, Index);
+           }
+
            /* Remove the reference to the label */
            RemoveCodeLabelRef (S, E);
        }
index f5517586b2dc3d6e912cf11cbc9044dbe3ac16d1..cccff02c2fe8ac4a3db9f4925cd896e89625ff0f 100644 (file)
 
 
 
-#include "../common/xmalloc.h"
-
+/* common */
+#include "xmalloc.h"
+         
+/* cc65 */
 #include "funcdesc.h"
 
 
index eb62d3d48e788fe16bb18028ced90d5be8a7f7e9..d2c2ed57e196ef3c4d4be437b18c13770d5beefa 100644 (file)
@@ -79,7 +79,7 @@ struct FuncDesc {
 FuncDesc* NewFuncDesc (void);
 /* Create a new symbol table with the given name */
 
-void FreeFuncDesc (FuncDesc* E);
+void FreeFuncDesc (FuncDesc* D);
 /* Free a function descriptor */