]> git.sur5r.net Git - cc65/commitdiff
More optimizations
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 25 Sep 2001 12:34:34 +0000 (12:34 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 25 Sep 2001 12:34:34 +0000 (12:34 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@970 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codegen.c
src/cc65/codeopt.c
src/cc65/opcodes.c
src/cc65/opcodes.h

index d936c1572609d1a1fd4513439a99d603ba8ef426..83944f5034cb9e9de4343bffb4c042e06d41d949 100644 (file)
@@ -170,7 +170,7 @@ void g_preamble (void)
     AddTextLine ("\t.debuginfo\t%s", (DebugInfo != 0)? "on" : "off");
 
     /* Import the stack pointer for direct auto variable access */
-    AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank, tmp1, ptr1");
+    AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank, tmp1, ptr1, ptr2");
 
     /* Define long branch macros */
     AddTextLine ("\t.macpack\tlongbranch");
@@ -608,7 +608,7 @@ void g_getimmed (unsigned Flags, unsigned long Val, unsigned Offs)
                if (B2 == B4) {
                    AddCodeLine ("stx sreg+1");
                    Done |= 0x08;
-               }
+               }
                if ((Done & 0x04) == 0 && B1 != B3) {
                    AddCodeLine ("lda #$%02X", B3);
                    AddCodeLine ("sta sreg");
@@ -1701,11 +1701,27 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val)
                    /* FALLTHROUGH */
 
                case CF_INT:
-           if (flags & CF_CONST) {
-               g_getimmed (flags, val, 0);
-           }
            ldyconst (offs);
-           AddCodeLine ("jsr addeqysp");
+           if (flags & CF_CONST) {
+               if (CodeSizeFactor >= 400) {
+                   AddCodeLine ("clc");
+                   AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
+                   AddCodeLine ("adc (sp),y");
+                   AddCodeLine ("sta (sp),y");
+                   AddCodeLine ("iny");
+                   AddCodeLine ("lda #$%02X", (int) ((val >> 8) & 0xFF));
+                   AddCodeLine ("adc (sp),y");
+                   AddCodeLine ("sta (sp),y");
+                   AddCodeLine ("tax");
+                   AddCodeLine ("dey");
+                   AddCodeLine ("lda (sp),y");
+               } else {
+                   g_getimmed (flags, val, 0);
+                   AddCodeLine ("jsr addeqysp");
+               }
+           } else {
+               AddCodeLine ("jsr addeqysp");
+           }
                    break;
 
                case CF_LONG:
index 7be0efb9c0f6725cf1a6e7f7514f9d0cf249110a..789c177d1d73ce38820dd386cac5b4df8967c9a5 100644 (file)
@@ -256,6 +256,20 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
 
 
 
+static int GetCmpRegVal (const CodeEntry* E)
+/* Return the register value for an immediate compare */
+{
+    switch (E->OPC) {
+       case OP65_CMP: return E->RI->In.RegA;
+       case OP65_CPX: return E->RI->In.RegX;
+       case OP65_CPY: return E->RI->In.RegY;
+       default:       Internal ("Invalid opcode in GetCmpRegVal");
+                      return 0;  /* Not reached */
+    }
+}
+
+
+
 static int IsCmpToZero (const CodeEntry* E)
 /* Check if the given instrcuction is a compare to zero instruction */
 {
@@ -937,6 +951,10 @@ static unsigned OptCmp2 (CodeSeg* S)
  *             lda/and/ora/eor ...
  *     cmp #$00
  *     jeq/jne
+ * or
+ *             lda/and/ora/eor ...
+ *     cmp #$00
+ *     jsr boolxx
  *
  * and remove the cmp.
  */
@@ -963,11 +981,13 @@ static unsigned OptCmp2 (CodeSeg* S)
             E->OPC == OP65_PLA ||
             E->OPC == OP65_SBC ||
             E->OPC == OP65_TXA ||
-            E->OPC == OP65_TYA)                  &&
-           CS_GetEntries (S, L, I+1, 2)          &&
-                   IsCmpToZero (L[0])                    &&
-           !CE_HasLabel (L[0])                   &&
-                   (L[1]->Info & OF_FBRA) != 0           &&
+            E->OPC == OP65_TYA)                       &&
+           CS_GetEntries (S, L, I+1, 2)               &&
+                   IsCmpToZero (L[0])                         &&
+           !CE_HasLabel (L[0])                        &&
+                   ((L[1]->Info & OF_FBRA) != 0         ||
+            (L[1]->OPC == OP65_JSR        &&
+             FindBoolCmpCond (L[1]->Arg) != CMP_INV)) &&
            !CE_HasLabel (L[1])) {
 
            /* Remove the compare */
@@ -985,7 +1005,7 @@ static unsigned OptCmp2 (CodeSeg* S)
 
     /* Return the number of changes made */
     return Changes;
-}
+}                
 
 
 
@@ -1128,7 +1148,7 @@ static unsigned OptCmp4 (CodeSeg* S)
            ++Changes;
        }
 
-       /* Next entry */
+       /* Next entry */
        ++I;
 
     }
@@ -1171,7 +1191,7 @@ static unsigned OptCmp5 (CodeSeg* S)
             * 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];
@@ -1245,6 +1265,110 @@ static unsigned OptCmp6 (CodeSeg* S)
 
 
 
+static unsigned OptCmp7 (CodeSeg* S)
+/* Check for register compares where the contents of the register and therefore
+ * the result of the compare is known.
+ */
+{
+    unsigned Changes = 0;
+    unsigned I;
+
+    /* Generate register info for this step */
+    CS_GenRegInfo (S);
+
+    /* Walk over the entries */
+    I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+       int RegVal;
+
+       /* Get next entry */
+               CodeEntry* E = CS_GetEntry (S, I);
+
+       /* Check for a compare against an immediate value */
+               if ((E->Info & OF_CMP) != 0           &&
+           (RegVal = GetCmpRegVal (E)) >= 0  &&
+           CE_KnownImm (E)) {
+
+           /* We are able to evaluate the compare at compile time. Check if
+            * one or more branches are ahead.
+            */
+           unsigned JumpsChanged = 0;
+           CodeEntry* N;
+           while ((N = CS_GetNextEntry (S, I)) != 0 &&   /* Followed by something.. */
+                  (N->Info & OF_CBRA) != 0          &&   /* ..that is a cond branch.. */
+                  !CE_HasLabel (N)) {                    /* ..and has no label */
+
+               /* Evaluate the branch condition */
+               int Cond;
+               switch (GetBranchCond (N->OPC)) {
+                   case BC_CC:
+                       Cond = ((unsigned char)RegVal) < ((unsigned char)E->Num);
+                       break;
+
+                   case BC_CS:
+                       Cond = ((unsigned char)RegVal) >= ((unsigned char)E->Num);
+                       break;
+
+                   case BC_EQ:
+                       Cond = ((unsigned char)RegVal) == ((unsigned char)E->Num);
+                       break;
+
+                   case BC_MI:
+                               Cond = ((signed char)RegVal) < ((signed char)E->Num);
+                       break;
+
+                   case BC_NE:
+                       Cond = ((unsigned char)RegVal) != ((unsigned char)E->Num);
+                       break;
+
+                   case BC_PL:
+                               Cond = ((signed char)RegVal) >= ((signed char)E->Num);
+                       break;
+
+                   case BC_VC:
+                   case BC_VS:
+               }
+
+               /* If the condition is false, we may remove the jump. Otherwise
+                * the branch will always be taken, so we may replace it by a
+                * jump (and bail out).
+                */
+               if (!Cond) {
+                   CS_DelEntry (S, I+1);
+               } else {
+                   CodeLabel* L = N->JumpTo;
+                   CodeEntry* X = NewCodeEntry (OP65_JMP, AM65_BRA, L->Name, L, N->LI);
+                   CS_InsertEntry (S, X, I+2);
+                   CS_DelEntry (S, I+1);
+               }
+
+               /* Remember, we had changes */
+               ++JumpsChanged;
+               ++Changes;
+           }
+
+           /* If we have made changes above, we may also remove the compare */
+           if (JumpsChanged) {
+               CS_DelEntry (S, I);
+           }
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Free register info */
+    CS_FreeRegInfo (S);
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
 /*****************************************************************************/
 /*                             Optimize tests                               */
 /*****************************************************************************/
@@ -1319,10 +1443,10 @@ static unsigned OptTest1 (CodeSeg* S)
 
                /* Remove the two other insns */
                CS_DelEntry (S, I+1);
-               CS_DelEntry (S, I);
+               CS_DelEntry (S, I);
 
-               /* We had changes */
-               ++Changes;
+               /* We had changes */
+               ++Changes;
            }
        }
 
@@ -2576,6 +2700,7 @@ static OptFunc OptFuncs [] = {
     OptEntry (OptCmp4, optMain),
     OptEntry (OptCmp5, optMain),
     OptEntry (OptCmp6, optMain),
+    OptEntry (OptCmp7, optMain),
     /* Optimize tests */
     OptEntry (OptTest1, optMain),
     /* Remove unused loads */
index fa8b1d5751233f274676565cfe5dd5f591c512d9..a849e7b8c73c1cb86d5262b8fd91ec52faa34956 100644 (file)
@@ -189,21 +189,21 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
                0,                                      /* size */
                REG_A,                                  /* use */
                REG_NONE,                               /* chg */
-       OF_SETF                                 /* flags */
+               OF_SETF | OF_CMP                        /* flags */
     },
     {   OP65_CPX,                                      /* opcode */
                "cpx",                                  /* mnemonic */
                0,                                      /* size */
                REG_X,                                  /* use */
                REG_NONE,                               /* chg */
-       OF_SETF                                 /* flags */
+       OF_SETF | OF_CMP                        /* flags */
     },
     {   OP65_CPY,                                      /* opcode */
                "cpy",                                  /* mnemonic */
                0,                                      /* size */
                REG_Y,                                  /* use */
                REG_NONE,                               /* chg */
-       OF_SETF                                 /* flags */
+       OF_SETF | OF_CMP                        /* flags */
     },
     {   OP65_DEA,                                      /* opcode */
                "dea",                                  /* mnemonic */
@@ -581,7 +581,7 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
 
 static int FindCmp (const void* Key, const void* Desc)
 /* Compare function for FindOpcode */
-{                                              
+{
     return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
 }
 
index 5ae3349a2461c112df7f826e6527caa8367f4dfe..ec798db22c217ce5e9ea05484c20eb3e60b66a89 100644 (file)
@@ -187,6 +187,7 @@ typedef enum {
 #define OF_CALL         0x0200U /* A subroutine call */
 #define OF_REG_INCDEC   0x0400U /* A register increment or decrement */
 #define OF_SETF         0x0800U /* Insn will set all load flags (not carry) */
+#define OF_CMP          0x1000U /* A compare A/X/Y instruction */
 
 /* Combined infos */
 #define OF_BRA         (OF_UBRA | OF_CBRA)     /* Operation is a jump/branch */