]> git.sur5r.net Git - cc65/commitdiff
Even more optimization, cleanup, bugfix, comments.
authorlaubzega <mileksmyk@gmail.com>
Sun, 14 Oct 2018 08:07:59 +0000 (01:07 -0700)
committerOliver Schmidt <ol.sc@web.de>
Tue, 16 Oct 2018 07:55:02 +0000 (09:55 +0200)
src/cc65/codeopt.c
src/cc65/symentry.h
src/cc65/symtab.c

index 6e547f16dc772da576b1e5a82855feafd0ae1914..f87d449005c0ab6f5db43e177f709df270dc674f 100644 (file)
@@ -614,8 +614,7 @@ static unsigned OptStackPtrOps (CodeSeg* S)
 }
 
 static unsigned OptGotoSPAdj (CodeSeg* S)
-/* Remove unnecessary SP adjustment while gotoing
-*/
+/* Optimize SP adjustment for forward 'goto' */
 {
     unsigned Changes = 0;
     unsigned I;
@@ -631,7 +630,7 @@ static unsigned OptGotoSPAdj (CodeSeg* S)
         /* Get next entry */
         L[0] = CS_GetEntry (S, I);
 
-        /* Check for the sequence */
+        /* Check for the sequence generated by g_lateadjustSP */
         if (L[0]->OPC == OP65_PHA            &&
             CS_GetEntries (S, L+1, I+1, 9)   &&
             L[1]->OPC == OP65_LDA            &&
@@ -640,48 +639,78 @@ static unsigned OptGotoSPAdj (CodeSeg* S)
             L[3]->OPC == OP65_ADC            &&
             strcmp (L[3]->Arg, "sp") == 0    &&
             L[6]->OPC == OP65_ADC            &&
-            strcmp (L[6]->Arg, "sp+1") == 0    &&
-            L[9]->OPC == OP65_JMP
-            ) {
-            printf("Goto SP adjustment found. Jump to: %s, data Label: %s\n", L[9]->Arg, L[1]->Arg);
-            adjustment = FindSPAdjustment(L[1]->Arg);
+            strcmp (L[6]->Arg, "sp+1") == 0  &&
+            L[9]->OPC == OP65_JMP) {
+            adjustment = FindSPAdjustment (L[1]->Arg);
 
             if (adjustment == 0) {
+            /* No SP adjustment needed, remove the whole sequence */
+                CS_DelEntries (S, I, 9);
+            }
+            else if (adjustment >= 65536 - 8) {
+            /* If adjustment is in range [-8, 0) we use decsp* calls */
+                char Buf[20];
+                adjustment = 65536 - adjustment;
+                xsprintf (Buf, sizeof (Buf), "decsp%u", adjustment);
+                X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, L[1]->LI);
+                CS_InsertEntry (S, X, I + 9);
+
+                /* Delete the old code */
+                CS_DelEntries (S, I, 9);
+            }
+            else if (adjustment >= 65536 - 255) {
+            /* For range [-255, -8) we have ldy #, jsr subysp */
+                adjustment = 65536 - adjustment;
+                Arg = MakeHexArg (adjustment);
+                X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
+                CS_InsertEntry (S, X, I + 9);
+                X = NewCodeEntry (OP65_JSR, AM65_ABS, "subysp", 0, L[1]->LI);
+                CS_InsertEntry (S, X, I + 10);
+
+                /* Delete the old code */
                 CS_DelEntries (S, I, 9);
             }
             else if (adjustment > 255) {
+            /* For ranges [-32768, 255) and (255, 32767) the only modification
+            ** is to replace the absolute with immediate addressing */
                 Arg = MakeHexArg (adjustment & 0xff);
                 X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[1]->LI);
-                CS_InsertEntry(S, X, I + 1);
+                CS_InsertEntry (S, X, I + 1);
                 Arg = MakeHexArg (adjustment >> 8);
                 X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[5]->LI);
-                CS_InsertEntry(S, X, I + 6);
+                CS_InsertEntry (S, X, I + 6);
 
-                CS_DelEntry(S, I + 2);
-                CS_DelEntry(S, I + 6);
+                /* Delete the old code */
+                CS_DelEntry (S, I + 2);
+                CS_DelEntry (S, I + 6);
             }
             else if (adjustment > 8) {
+            /* For range (8, 255] we have ldy #0, jsr addysp */
                 Arg = MakeHexArg (adjustment & 0xff);
                 X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
-                CS_InsertEntry (S, X, I);
+                CS_InsertEntry (S, X, I + 9);
                 X = NewCodeEntry (OP65_JSR, AM65_ABS, "addysp", 0, L[1]->LI);
-                CS_InsertEntry (S, X, I + 1);
+                CS_InsertEntry (S, X, I + 10);
 
-                CS_DelEntries(S, I + 2, 9);
+                /* Delete the old code */
+                CS_DelEntries (S, I, 9);
             }
             else {
+            /* If adjustment is in range (0, 8] we use incsp* calls */
                 char Buf[20];
                 xsprintf (Buf, sizeof (Buf), "incsp%u", adjustment);
                 X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, L[1]->LI);
-                CS_InsertEntry (S, X, I);
+                CS_InsertEntry (S, X, I + 9);
 
-                CS_DelEntries(S, I + 1, 9);
+                /* Delete the old code */
+                CS_DelEntries (S, I, 9);
             }
             /* Regenerate register info */
             CS_GenRegInfo (S);
 
             /* Remember we had changes */
             Changes++;
+
         } else {
 
             /* Next entry */
@@ -1311,7 +1340,6 @@ static unsigned RunOptGroup3 (CodeSeg* S)
         C += RunOptFunc (S, &DOptCmp6, 1);
         C += RunOptFunc (S, &DOptCmp7, 1);
         C += RunOptFunc (S, &DOptCmp9, 1);
-
         C += RunOptFunc (S, &DOptTest1, 1);
         C += RunOptFunc (S, &DOptLoad1, 1);
         C += RunOptFunc (S, &DOptJumpTarget3, 1);       /* After OptCondBranches2 */
index 630ca944c97c28fb15f92e64994e9b7b9ecaba7f..3d4bcdcc17bd24ed4789525b0bd03095424b5aad 100644 (file)
@@ -140,6 +140,7 @@ struct SymEntry {
             Collection          *DefsOrRefs;
         } L;
 
+        /* Value of SP adjustment needed after forward 'goto' */
         struct {
             unsigned short      SPAdjustment;
         } G;
index 8db6a741c8c1ad547c89e5a96e1225d78557fc4f..11314b53a4bec36d726161784ca2977ea7b9edb2 100644 (file)
@@ -226,6 +226,7 @@ void EnterGlobalLevel (void)
     /* Create and assign the tag table */
     TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
 
+    /* Create and assign the table of SP adjustment symbols */
     SPAdjustTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
 }
 
@@ -681,16 +682,14 @@ DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags)
 
 unsigned short FindSPAdjustment (const char* Name)
 {
+/* Search for an entry in the table of SP adjustments */
     SymEntry* Entry = FindSymInTable (SPAdjustTab, Name, HashStr (Name));
 
-    if (Entry) {
-            printf("L: %s sa: %d\n", Name, Entry->V.G.SPAdjustment);
-            return Entry->V.G.SPAdjustment;
+    if (!Entry) {
+        Internal ("No SP adjustment label entry found");
     }
 
-    Fatal("ICE: No label entry found");
-
-    return 0;
+    return Entry->V.G.SPAdjustment;
 }
 
 SymEntry* AddLabelSym (const char* Name, unsigned Flags)
@@ -748,11 +747,13 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
                 g_userodata();
                 g_defdatalabel (DOR->LateSP_Label);
                 g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0);
-                E = NewSymEntry (LocalLabelName(DOR->LateSP_Label), SC_SPADJUSTMENT);
+
+                /* Optimizer will need the information about the value of SP adjustment
+                ** later, so let's preserve it. */
+                E = NewSymEntry (LocalLabelName (DOR->LateSP_Label), SC_SPADJUSTMENT);
                 E->V.G.SPAdjustment = StackPtr - DOR->StackPtr;
                 AddSymEntry (SPAdjustTab, E);
 
-
                 /* Are we jumping into a block with initalization of an object that
                 ** has automatic storage duration? Let's emit a warning.
                 */