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

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

index 08728cabbe428369dd5b43d332177759923dac22..c96a95ef81b05102185bef6ef70d16f830c908ea 100644 (file)
@@ -359,14 +359,15 @@ void OutputCodeEntry (const CodeEntry* E, FILE* F)
     /* Print usage info if requested by the debugging flag */
 //    if (Debug) {
        Chars += fprintf (F,
-                         "%*s; USE: %c%c%c CHG: %c%c%c",
+                         "%*s; USE: %c%c%c CHG: %c%c%c SIZE: %u",
                          30-Chars, "",
                                  (E->Use & REG_A)? 'A' : '_',
                                  (E->Use & REG_X)? 'X' : '_',
                                  (E->Use & REG_Y)? 'Y' : '_',
                                  (E->Chg & REG_A)? 'A' : '_',
                                  (E->Chg & REG_X)? 'X' : '_',
-                                 (E->Chg & REG_Y)? 'Y' : '_');
+                                 (E->Chg & REG_Y)? 'Y' : '_',
+                         E->Size);
 //    }
 
 }
index c99ee491c23de403af3ac7d6689cdb28e50b0b6d..b5e234ecd3d2cc7d010024cc417af7fa2507c549 100644 (file)
@@ -112,6 +112,11 @@ static const FuncInfo FuncInfoTable[] = {
 };
 #define FuncInfoCount  (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
 
+/* Table with names of zero page locations used by the compiler */
+static const char* ZPNameTable[] = {
+    "ptr1", "regbank", "regsave", "sp", "sreg", "tmp1"
+};
+#define ZPNameCount    (sizeof(ZPNameTable) / sizeof(ZPNameTable[0]))
 
 
 /*****************************************************************************/
@@ -150,7 +155,7 @@ void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg)
            /* A function may use the A or A/X registers if it is a fastcall
             * function. If it is not a fastcall function but a variadic one,
             * it will use the Y register (the parameter size is passed here).
-            * In all other cases, no registers are used. However, we assume 
+            * In all other cases, no registers are used. However, we assume
             * that any function will destroy all registers.
             */
            FuncDesc* D = E->V.F.Func;
@@ -164,7 +169,7 @@ void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg)
                }
            } else if ((D->Flags & FD_VARIADIC) != 0) {
                *Use = REG_Y;
-           } else {                          
+           } else {
                /* Will not use any registers */
                *Use = REG_NONE;
            }
@@ -198,6 +203,25 @@ void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg)
 
 
 
+int IsZPName (const char* Name)
+/* Return true if the given name is a zero page symbol */
+{
+    unsigned I;
+
+    /* Because of the low number of symbols, we do a linear search here */
+    for (I = 0; I < ZPNameCount; ++I) {
+       if (strcmp (Name, ZPNameTable[I]) == 0) {
+           /* Found */
+           return 1;
+       }
+    }
+
+    /* Not found */
+    return 0;
+}
+
+
+
 static unsigned char GetRegInfo2 (CodeSeg* S,
                                  CodeEntry* E,
                                  int Index,
index 87e7a1248957ff9e2cd61ddeea77d9b74e46698c..b9f2a08c0b40324beaaf3a239b05bd60f1d757b5 100644 (file)
@@ -82,6 +82,9 @@ void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg);
  * load all registers.
  */
 
+int IsZPName (const char* Name);
+/* Return true if the given name is a zero page symbol */
+
 unsigned char GetRegInfo (struct CodeSeg* S, unsigned Index);
 /* Determine register usage information for the instructions starting at the
  * given index.
index 4b9dfefa271458b797ef71f3cf98a9cbb9019aab..4590bb57ca21165758728c64cdbe6ffa43e97189 100644 (file)
@@ -130,7 +130,7 @@ static cmp_t FindBoolCmpCond (const char* Name)
 
 
 
-static int FindTosCmpCond (const char* Name)
+static cmp_t FindTosCmpCond (const char* Name)
 /* Check if this is a call to one of the TOS compare functions (tosgtax).
  * Return the condition code or CMP_INV on failure.
  */
@@ -149,37 +149,115 @@ static int FindTosCmpCond (const char* Name)
 
 
 
-static int IsUnsignedCmp (int Code)
-/* Check if this is an unsigned compare */
+static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
+/* Helper function for the replacement of routines that return a boolean
+ * followed by a conditional jump. Instead of the boolean value, the condition
+ * codes are evaluated directly.
+ * I is the index of the conditional branch, the sequence is already checked
+ * to be correct.
+ */
 {
-    CHECK (Code >= 0);
-    return CmpSignedTab [Code] == 0;
-}
+    CodeEntry* N;
+    CodeLabel* L;
 
+    /* Get the entry */
+    CodeEntry* E = GetCodeEntry (S, I);
 
+    /* Replace the conditional branch */
+    switch (Cond) {
+
+       case CMP_EQ:
+           ReplaceOPC (E, OPC_JEQ);
+           break;
+
+       case CMP_NE:
+           ReplaceOPC (E, OPC_JNE);
+           break;
+
+       case CMP_GT:
+           /* Replace by
+            *     beq @L
+            *     jpl Target
+            * @L: ...
+            */
+           if ((N = GetNextCodeEntry (S, I)) == 0) {
+               /* No such entry */
+               Internal ("Invalid program flow");
+           }
+           L = GenCodeLabel (S, N);
+           N = NewCodeEntry (OPC_BEQ, AM_BRA, L->Name, L);
+           InsertCodeEntry (S, N, I);
+           ReplaceOPC (E, OPC_JPL);
+           break;
+
+       case CMP_GE:
+           ReplaceOPC (E, OPC_JPL);
+           break;
+
+       case CMP_LT:
+           ReplaceOPC (E, OPC_JMI);
+           break;
+
+       case CMP_LE:
+           /* Replace by
+            *     jmi Target
+            *     jeq Target
+            */
+           ReplaceOPC (E, OPC_JMI);
+           L = E->JumpTo;
+           N = NewCodeEntry (OPC_JEQ, AM_BRA, L->Name, L);
+           InsertCodeEntry (S, N, I+1);
+           break;
+
+       case CMP_UGT:
+           /* Replace by
+            *     beq @L
+            *     jcs Target
+            * @L: ...
+            */
+           if ((N = GetNextCodeEntry (S, I)) == 0) {
+               /* No such entry */
+               Internal ("Invalid program flow");
+           }
+           L = GenCodeLabel (S, N);
+           N = NewCodeEntry (OPC_BEQ, AM_BRA, L->Name, L);
+           InsertCodeEntry (S, N, I);
+           ReplaceOPC (E, OPC_JCS);
+           break;
+
+       case CMP_UGE:
+           ReplaceOPC (E, OPC_JCS);
+           break;
+
+       case CMP_ULT:
+           ReplaceOPC (E, OPC_JCC);
+           break;
+
+       case CMP_ULE:
+           /* Replace by
+            *     jcc Target
+            *     jeq Target
+            */
+           ReplaceOPC (E, OPC_JCC);
+           L = E->JumpTo;
+           N = NewCodeEntry (OPC_JEQ, AM_BRA, L->Name, L);
+           InsertCodeEntry (S, N, I+1);
+           break;
+
+       default:
+           Internal ("Unknown jump condition: %d", Cond);
+
+    }
 
-static const char* MakeBoolCmp (cmp_t Cond)
-/* Create the name of a bool transformer subroutine for the given code. The
- * result is placed into a static buffer, so beware!
- */
-{
-    static char Buffer[20];
-    CHECK (Cond != CMP_INV);
-    sprintf (Buffer, "bool%s", CmpSuffixTab[Cond]);
-    return Buffer;
 }
 
 
 
-static const char* MakeTosCmp (cmp_t Cond)
-/* Create the name of a tos compare subroutine for the given code. The
- * result is placed into a static buffer, so beware!
- */
+static int IsUnsignedCmp (int Code)
+/* Check if this is an unsigned compare */
 {
-    static char Buffer[20];
-    CHECK (Cond != CMP_INV);
-    sprintf (Buffer, "tos%sax", CmpSuffixTab[Cond]);
-    return Buffer;
+    CHECK (Code >= 0);
+    return CmpSignedTab [Code] == 0;
 }
 
 
@@ -300,9 +378,6 @@ static unsigned OptBoolTransforms (CodeSeg* S)
            (N = GetNextCodeEntry (S, I)) != 0           &&
            (N->Info & OF_ZBRA) != 0) {
 
-           CodeEntry* X;
-           CodeLabel* L;
-
            /* Make the boolean transformer unnecessary by changing the
             * the conditional jump to evaluate the condition flags that
             * are set after the compare directly. Note: jeq jumps if
@@ -315,90 +390,7 @@ static unsigned OptBoolTransforms (CodeSeg* S)
            }
 
            /* Check if we can replace the code by something better */
-           switch (Cond) {
-
-               case CMP_EQ:
-                   ReplaceOPC (N, OPC_JEQ);
-                   break;
-
-               case CMP_NE:
-                   ReplaceOPC (N, OPC_JNE);
-                   break;
-
-               case CMP_GT:
-                   /* Replace by
-                    *     beq @L
-                    *     jpl Target
-                    * @L: ...
-                    */
-                   if ((X = GetNextCodeEntry (S, I+1)) == 0) {
-                       /* No such entry */
-                       goto NextEntry;
-                   }
-                   L = GenCodeLabel (S, X);
-                   X = NewCodeEntry (OPC_BEQ, AM_BRA, L->Name, L);
-                   InsertCodeEntry (S, X, I+1);
-                           ReplaceOPC (N, OPC_JPL);
-                   break;
-
-               case CMP_GE:
-                   ReplaceOPC (N, OPC_JPL);
-                   break;
-
-               case CMP_LT:
-                   ReplaceOPC (N, OPC_JMI);
-                   break;
-
-               case CMP_LE:
-                   /* Replace by
-                    *     jmi Target
-                    *     jeq Target
-                    */
-                   ReplaceOPC (N, OPC_JMI);
-                   L = N->JumpTo;
-                           X = NewCodeEntry (OPC_JEQ, AM_BRA, L->Name, L);
-                   InsertCodeEntry (S, X, I+2);
-                   break;
-
-               case CMP_UGT:
-                   /* Replace by
-                    *     beq @L
-                    *     jcs Target
-                    * @L: ...
-                    */
-                   if ((X = GetNextCodeEntry (S, I+1)) == 0) {
-                       /* No such entry */
-                       goto NextEntry;
-                   }
-                   L = GenCodeLabel (S, X);
-                   X = NewCodeEntry (OPC_BEQ, AM_BRA, L->Name, L);
-                   InsertCodeEntry (S, X, I+1);
-                           ReplaceOPC (N, OPC_JCS);
-                   break;
-
-               case CMP_UGE:
-                           ReplaceOPC (N, OPC_JCS);
-                   break;
-
-               case CMP_ULT:
-                   ReplaceOPC (N, OPC_JCC);
-                   break;
-
-               case CMP_ULE:
-                   /* Replace by
-                    *     jcc Target
-                    *     jeq Target
-                    */
-                   ReplaceOPC (N, OPC_JCC);
-                   L = N->JumpTo;
-                           X = NewCodeEntry (OPC_JEQ, AM_BRA, L->Name, L);
-                   InsertCodeEntry (S, X, I+2);
-                   break;
-
-               default:
-                   Internal ("Unknown jump condition: %d", Cond);
-
-           }
+           ReplaceCmp (S, I+1, Cond);
 
            /* Remove the call to the bool transformer */
            DelCodeEntry (S, I);
@@ -408,7 +400,6 @@ static unsigned OptBoolTransforms (CodeSeg* S)
 
        }
 
-NextEntry:
        /* Next entry */
        ++I;
 
@@ -863,6 +854,68 @@ static unsigned OptCmp4 (CodeSeg* S)
 
 
 
+static unsigned OptCmp5 (CodeSeg* S)
+/* Search for calls to compare subroutines followed by a conditional branch
+ * and replace them by cheaper versions, since the branch means that the
+ * boolean value returned by these routines is not needed (we may also check
+ * that explicitly, but for the current code generator it is always true).
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       CodeEntry* N;
+       cmp_t Cond;
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check for the sequence */
+               if (E->OPC == OPC_JSR                           &&
+           (Cond = FindTosCmpCond (E->Arg)) != CMP_INV &&
+           (N = GetNextCodeEntry (S, I)) != 0          &&
+           (N->Info & OF_ZBRA) != 0                    &&
+                   !CodeEntryHasLabel (N)) {
+
+                   /* The tos... functions will return a boolean value in a/x and
+            * the Z flag says if this value is zero or not. We will call
+            * a cheaper subroutine instead, one that does not return a
+            * boolean value but only valid flags. Note: jeq jumps if
+            * the condition is not met, jne jumps if the condition is met.
+            * Invert the code if we jump on condition not met.
+            */
+                   if (GetBranchCond (N->OPC) == BC_EQ) {
+               /* Jumps if condition false, invert condition */
+               Cond = CmpInvertTab [Cond];
+           }
+
+           /* Replace the subroutine call. */
+           DelCodeEntry (S, I);
+           E = NewCodeEntry (OPC_JSR, AM_ABS, "tosicmp", 0);
+           InsertCodeEntry (S, E, I);
+
+           /* Replace the conditional branch */
+           ReplaceCmp (S, I+1, Cond);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
 /*****************************************************************************/
 /*                           nega optimizations                             */
 /*****************************************************************************/
@@ -1136,12 +1189,12 @@ static unsigned OptNegAX3 (CodeSeg* S)
                CodeEntry* E = GetCodeEntry (S, I);
 
        /* Check for the sequence */
-               if (E->OPC == OPC_JSR                   &&
-           E->Arg[0] == '_'                    &&
-                   GetCodeEntries (S, L, I+1, 2)       &&
+               if (E->OPC == OPC_JSR                   &&
+           E->Arg[0] == '_'                    &&
+                   GetCodeEntries (S, L, I+1, 2)       &&
                    L[0]->OPC == OPC_JSR                &&
-           strncmp (L[0]->Arg,"bnega",5) == 0  &&
-           !CodeEntryHasLabel (L[0])           &&
+           strncmp (L[0]->Arg,"bnega",5) == 0  &&
+           !CodeEntryHasLabel (L[0])           &&
                    (L[1]->Info & OF_ZBRA) != 0) {
 
            /* Check if we're calling bnega or bnegax */
@@ -1230,6 +1283,7 @@ static OptFunc OptFuncs [] = {
     { OptCmp2,              "OptCmp2",                  0       },
     { OptCmp3,              "OptCmp3",                  0       },
     { OptCmp4,              "OptCmp4",                  0       },
+    { OptCmp5,              "OptCmp5",                  0       },
     /* Remove unused loads */
     { OptUnusedLoads,      "OptUnusedLoads",           0       },
     /* Optimize branch distance */
@@ -1263,8 +1317,15 @@ static OptFunc* FindOptStep (const char* Name)
 void DisableOpt (const char* Name)
 /* Disable the optimization with the given name */
 {
-    OptFunc* F  = FindOptStep (Name);
-    F->Disabled = 1;
+    if (strcmp (Name, "any") == 0) {
+       unsigned I;
+               for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
+                   OptFuncs[I].Disabled = 1;
+       }
+    } else {
+       OptFunc* F = FindOptStep (Name);
+       F->Disabled = 1;
+    }
 }
 
 
@@ -1272,8 +1333,15 @@ void DisableOpt (const char* Name)
 void EnableOpt (const char* Name)
 /* Enable the optimization with the given name */
 {
-    OptFunc* F  = FindOptStep (Name);
-    F->Disabled = 0;
+    if (strcmp (Name, "any") == 0) {
+       unsigned I;
+               for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
+                   OptFuncs[I].Disabled = 0;
+       }
+    } else {
+       OptFunc* F = FindOptStep (Name);
+       F->Disabled = 0;
+    }
 }
 
 
index 6565d2b8fc496544c2a9471dff668e0eb973c776..d378d25951be563f537819bd14b387f0bbaa19a3 100644 (file)
@@ -296,8 +296,15 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
            /* Absolute, maybe indexed */
            L = ReadToken (L, ",", Arg, sizeof (Arg));
            if (*L == '\0') {
-               /* Assume absolute */
-               AM = AM_ABS;
+               /* Absolute, zeropage or branch */
+               if ((OPC->Info & OF_BRA) != 0) {
+                   /* Branch */
+                   AM = AM_BRA;
+               } else if (IsZPName (Arg)) {
+                   AM = AM_ZP;
+               } else {
+                   AM = AM_ABS;
+               }
            } else if (*L == ',') {
                /* Indexed */
                L = SkipSpace (L+1);
@@ -308,7 +315,11 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
                    Reg = toupper (*L);
                    L = SkipSpace (L+1);
                    if (Reg == 'X') {
-                       AM = AM_ABSX;
+                       if (IsZPName (Arg)) {
+                           AM = AM_ZPX;
+                       } else {
+                           AM = AM_ABSX;
+                       }
                    } else if (Reg == 'Y') {
                        AM = AM_ABSY;
                    } else {
@@ -329,18 +340,10 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
      * if it does not exist. Ignore anything but local labels here.
      */
     Label = 0;
-    if ((OPC->Info & OF_BRA) != 0 && Arg[0] == 'L') {
-
-       unsigned Hash;
-
-       /* Addressing mode must be alsobute or something is really wrong */
-       CHECK (AM == AM_ABS);
-
-       /* Addressing mode is a branch/jump */
-       AM = AM_BRA;
+    if (AM == AM_BRA && Arg[0] == 'L') {
 
        /* Generate the hash over the label, then search for the label */
-       Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE;
+       unsigned Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE;
        Label = FindCodeLabel (S, Arg, Hash);
 
        /* If we don't have the label, it's a forward ref - create it */
@@ -959,14 +962,18 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F)
        unsigned char Use;
 
        OutputCodeEntry (CollConstAt (&S->Entries, I), F);
-
-       /* Print usage info */
-       Use = GetRegInfo ((CodeSeg*) S, I+1);
-       fprintf (F,
-                "  Use: %c%c%c\n",
-                (Use & REG_A)? 'A' : '_',
-                (Use & REG_X)? 'X' : '_',
-                (Use & REG_Y)? 'Y' : '_');
+                             
+#if 0
+       /* Print usage info */
+       Use = GetRegInfo ((CodeSeg*) S, I+1);
+       fprintf (F,
+                "  Use: %c%c%c\n",
+                (Use & REG_A)? 'A' : '_',
+                (Use & REG_X)? 'X' : '_',
+                (Use & REG_Y)? 'Y' : '_');
+#else
+       fprintf (F, "\n");
+#endif
     }
 
     /* If this is a segment for a function, leave the function */