]> git.sur5r.net Git - cc65/commitdiff
Optimizations
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 4 Oct 2001 11:34:18 +0000 (11:34 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 4 Oct 2001 11:34:18 +0000 (11:34 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1009 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codegen.c
src/cc65/coptstop.c

index 214f1e42ba78e6dd14fa09970b5783def04833ff..2e1ebc63b9ef480bce8169504d9a4bcfbf918e67 100644 (file)
@@ -2409,7 +2409,7 @@ void g_truejump (unsigned flags attribute ((unused)), unsigned label)
 
 
 
-void g_falsejump (unsigned flags attribute ((unused)), unsigned label)   
+void g_falsejump (unsigned flags attribute ((unused)), unsigned label)
 /* Jump to label if zero flag set */
 {
     AddCodeLine ("jeq %s", LocalLabelName (label));
@@ -2813,7 +2813,7 @@ void g_and (unsigned flags, unsigned long val)
                        AddCodeLine ("and #$%02X", (unsigned char)(val >> 8));
                        AddCodeLine ("tax");
                        ldaconst (0);
-                   } else {
+                   } else {
                        AddCodeLine ("tay");
                        AddCodeLine ("txa");
                        AddCodeLine ("and #$%02X", (unsigned char)(val >> 8));
@@ -2879,57 +2879,62 @@ void g_asr (unsigned flags, unsigned long val)
 
            case CF_CHAR:
            case CF_INT:
-               if (val >= 1 && val <= 4) {
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("jsr shrax%ld", val);
-                   } else {
-                       AddCodeLine ("jsr asrax%ld", val);
-                   }
-                   return;
-               } else if (val == 8 && (flags & CF_UNSIGNED)) {
+                       if (val >= 8 && (flags & CF_UNSIGNED)) {
                    AddCodeLine ("txa");
                    ldxconst (0);
-                   return;
-               }
-               break;
+                   val -= 8;
+                   if (val == 0) {
+                       /* Done */
+                       return;
+                   }
+               }
+               if (val >= 1 && val <= 4) {
+                   if (flags & CF_UNSIGNED) {
+                       AddCodeLine ("jsr shrax%ld", val);
+                   } else {
+                       AddCodeLine ("jsr asrax%ld", val);
+                   }
+                   return;
+                       }
+               break;
 
-           case CF_LONG:
-               if (val >= 1 && val <= 4) {
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("jsr shreax%ld", val);
-                   } else {
-                       AddCodeLine ("jsr asreax%ld", val);
-                   }
-                   return;
-               } else if (val == 8 && (flags & CF_UNSIGNED)) {
-                   AddCodeLine ("txa");
-                   AddCodeLine ("ldx sreg");
-                   AddCodeLine ("ldy sreg+1");
-                   AddCodeLine ("sty sreg");
-                   AddCodeLine ("ldy #$00");
+           case CF_LONG:
+               if (val >= 1 && val <= 4) {
+                   if (flags & CF_UNSIGNED) {
+                       AddCodeLine ("jsr shreax%ld", val);
+                   } else {
+                       AddCodeLine ("jsr asreax%ld", val);
+                   }
+                   return;
+               } else if (val == 8 && (flags & CF_UNSIGNED)) {
+                   AddCodeLine ("txa");
+                   AddCodeLine ("ldx sreg");
+                   AddCodeLine ("ldy sreg+1");
+                   AddCodeLine ("sty sreg");
+                   AddCodeLine ("ldy #$00");
                    AddCodeLine ("sty sreg+1");
-                   return;
+                   return;
                } else if (val == 16) {
-                   AddCodeLine ("ldy #$00");
-                   AddCodeLine ("ldx sreg+1");
-                   if ((flags & CF_UNSIGNED) == 0) {
-                       unsigned L = GetLocalLabel();
-                       AddCodeLine ("bpl %s", LocalLabelName (L));
-                       AddCodeLine ("dey");
-                       g_defcodelabel (L);
-                   }
+                   AddCodeLine ("ldy #$00");
+                   AddCodeLine ("ldx sreg+1");
+                   if ((flags & CF_UNSIGNED) == 0) {
+                       unsigned L = GetLocalLabel();
+                       AddCodeLine ("bpl %s", LocalLabelName (L));
+                       AddCodeLine ("dey");
+                       g_defcodelabel (L);
+                   }
                    AddCodeLine ("lda sreg");
-                   AddCodeLine ("sty sreg+1");
-                   AddCodeLine ("sty sreg");
-                   return;
-               }
-               break;
+                   AddCodeLine ("sty sreg+1");
+                   AddCodeLine ("sty sreg");
+                   return;
+               }
+               break;
 
-           default:
-               typeerror (flags);
-       }
+           default:
+               typeerror (flags);
+       }
 
-       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
         * into the normal, non-optimized stuff.
         */
        g_push (flags & ~CF_CONST, 0);
@@ -2962,6 +2967,15 @@ void g_asl (unsigned flags, unsigned long val)
 
            case CF_CHAR:
            case CF_INT:
+               if (val >= 8) {
+                   AddCodeLine ("tax");
+                   AddCodeLine ("lda #$00");
+                   val -= 8;
+                   if (val == 0) {
+                       /* Done */
+                       return;
+                   }
+               }
                if (val >= 1 && val <= 4) {
                    if (flags & CF_UNSIGNED) {
                        AddCodeLine ("jsr shlax%ld", val);
@@ -2969,11 +2983,7 @@ void g_asl (unsigned flags, unsigned long val)
                        AddCodeLine ("jsr aslax%ld", val);
                    }
                    return;
-               } else if (val == 8) {
-                   AddCodeLine ("tax");
-                   AddCodeLine ("lda #$00");
-                   return;
-               }
+               }
                break;
 
            case CF_LONG:
@@ -2985,7 +2995,7 @@ void g_asl (unsigned flags, unsigned long val)
                    }
                    return;
                } else if (val == 8) {
-                   AddCodeLine ("ldy sreg");
+                   AddCodeLine ("ldy sreg");
                    AddCodeLine ("sty sreg+1");
                    AddCodeLine ("stx sreg");
                    AddCodeLine ("tax");
@@ -3028,7 +3038,7 @@ void g_neg (unsigned flags)
            break;
 
        case CF_LONG:
-           AddCodeLine ("jsr negeax");
+           AddCodeLine ("jsr negeax");
            break;
 
        default:
index 231552d2e564c70696a1512564af9648ddba6c05..a9575022f0ecde28674bd6eac0fc87eb377d8fef 100644 (file)
@@ -161,45 +161,68 @@ static unsigned Opt_tosaddax (CodeSeg* S, unsigned Push, unsigned Add,
                              const char* ZPLo, const char* ZPHi)
 /* Optimize the tosaddax sequence if possible */
 {
+    CodeEntry* P;
     CodeEntry* N;
     CodeEntry* X;
     CodeEntry* PushEntry;
     CodeEntry* AddEntry;
+    int        DirectAdd;
+
 
     /* We need the entry behind the add */
     CHECK ((N = CS_GetNextEntry (S, Add)) != 0);
 
+    /* And the entry before the push */
+    CHECK ((P = CS_GetPrevEntry (S, Push)) != 0);
+
     /* Get the push entry */
     PushEntry = CS_GetEntry (S, Push);
 
+    /* Check the entry before the push, if it's a lda instruction with an
+     * addressing mode that does not use an additional index register. If
+     * so, we may use this location for the add and must not save the
+     * value in the zero page location.
+     */
+    DirectAdd = (P->OPC == OP65_LDA &&
+                (P->AM == AM65_IMM || P->AM == AM65_ZP || P->AM == AM65_ABS));
+
     /* Store the value into the zeropage instead of pushing it */
-    X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
-    CS_InsertEntry (S, X, Push+1);
     X = NewCodeEntry (OP65_STX, AM65_ZP, ZPHi, 0, PushEntry->LI);
-    CS_InsertEntry (S, X, Push+2);
+    CS_InsertEntry (S, X, Push+1);
+    ++Add;      /* Correct the index */
+    if (!DirectAdd) {
+       X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
+       CS_InsertEntry (S, X, Push+1);
+       ++Add;  /* Correct the index */
+    }
 
-    /* Correct the index of the add and get a pointer to the entry */
-    Add += 2;
+    /* Get a pointer to the add entry */
     AddEntry = CS_GetEntry (S, Add);
 
     /* Inline the add */
     X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, AddEntry->LI);
     CS_InsertEntry (S, X, Add+1);
-    X = NewCodeEntry (OP65_ADC, AM65_ZP, ZPLo, 0, AddEntry->LI);
+    if (DirectAdd) {
+       /* Add from variable location */
+       X = NewCodeEntry (OP65_ADC, P->AM, P->Arg, 0, AddEntry->LI);
+    } else {
+       /* Add from temp storage */
+       X = NewCodeEntry (OP65_ADC, AM65_ZP, ZPLo, 0, AddEntry->LI);
+    }
     CS_InsertEntry (S, X, Add+2);
     if (PushEntry->RI->In.RegX == 0) {
-       /* The high byte is the value in X plus the carry */
-       CodeLabel* L = CS_GenLabel (S, N);
-       X = NewCodeEntry (OP65_BCC, AM65_BRA, L->Name, L, AddEntry->LI);
-       CS_InsertEntry (S, X, Add+3);
-       X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, AddEntry->LI);
-       CS_InsertEntry (S, X, Add+4);
+       /* The high byte is the value in X plus the carry */
+       CodeLabel* L = CS_GenLabel (S, N);
+       X = NewCodeEntry (OP65_BCC, AM65_BRA, L->Name, L, AddEntry->LI);
+       CS_InsertEntry (S, X, Add+3);
+       X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, AddEntry->LI);
+       CS_InsertEntry (S, X, Add+4);
     } else if (AddEntry->RI->In.RegX == 0) {
-       /* The high byte is that of the first operand plus carry */
-       CodeLabel* L;
-       if (PushEntry->RI->In.RegX >= 0) {
-           /* Value of first op high byte is known */
-           char Buf [16];
+       /* The high byte is that of the first operand plus carry */
+       CodeLabel* L;
+       if (PushEntry->RI->In.RegX >= 0) {
+           /* Value of first op high byte is known */
+           char Buf [16];
            xsprintf (Buf, sizeof (Buf), "$%02X", PushEntry->RI->In.RegX);
            X = NewCodeEntry (OP65_LDX, AM65_IMM, Buf, 0, AddEntry->LI);
        } else {
@@ -237,28 +260,50 @@ static unsigned Opt_tosaddax (CodeSeg* S, unsigned Push, unsigned Add,
 
 
 static unsigned Opt_tosandax (CodeSeg* S, unsigned Push, unsigned And,
-                             const char* ZPLo, const char* ZPHi)
+                             const char* ZPLo, const char* ZPHi)
 /* Optimize the tosandax sequence if possible */
 {
+    CodeEntry* P;
     CodeEntry* X;
     CodeEntry* PushEntry;
     CodeEntry* AndEntry;
+    int        DirectAnd;
+
+    /* Get the entry before the push */
+    CHECK ((P = CS_GetPrevEntry (S, Push)) != 0);
 
     /* Get the push entry */
     PushEntry = CS_GetEntry (S, Push);
 
+    /* Check the entry before the push, if it's a lda instruction with an
+     * addressing mode that does not use an additional index register. If
+     * so, we may use this location for the and and must not save the
+     * value in the zero page location.
+     */
+    DirectAnd = (P->OPC == OP65_LDA &&
+                (P->AM == AM65_IMM || P->AM == AM65_ZP || P->AM == AM65_ABS));
+
     /* Store the value into the zeropage instead of pushing it */
-    X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
-    CS_InsertEntry (S, X, Push+1);
     X = NewCodeEntry (OP65_STX, AM65_ZP, ZPHi, 0, PushEntry->LI);
-    CS_InsertEntry (S, X, Push+2);
+    CS_InsertEntry (S, X, Push+1);
+    ++And;      /* Correct the index */
+    if (!DirectAnd) {
+       X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
+       CS_InsertEntry (S, X, Push+1);
+       ++And;  /* Correct the index */
+    }
 
-    /* Correct the index of the add and get a pointer to the entry */
-    And += 2;
+    /* Get a pointer to the and entry */
     AndEntry = CS_GetEntry (S, And);
 
     /* Inline the and */
-    X = NewCodeEntry (OP65_AND, AM65_ZP, ZPLo, 0, AndEntry->LI);
+    if (DirectAnd) {
+       /* And with variable location */
+       X = NewCodeEntry (OP65_AND, P->AM, P->Arg, 0, AndEntry->LI);
+    } else {
+       /* And with temp storage */
+       X = NewCodeEntry (OP65_AND, AM65_ZP, ZPLo, 0, AndEntry->LI);
+    }
     CS_InsertEntry (S, X, And+1);
     if (PushEntry->RI->In.RegX == 0 || AndEntry->RI->In.RegX == 0) {
        /* The high byte is zero */
@@ -289,28 +334,49 @@ static unsigned Opt_tosandax (CodeSeg* S, unsigned Push, unsigned And,
 
 
 static unsigned Opt_tosorax (CodeSeg* S, unsigned Push, unsigned Or,
-                            const char* ZPLo, const char* ZPHi)
+                            const char* ZPLo, const char* ZPHi)
 /* Optimize the tosorax sequence if possible */
 {
+    CodeEntry* P;
     CodeEntry* X;
     CodeEntry* PushEntry;
     CodeEntry* OrEntry;
+    int        DirectOr;
+
+    /* Get the entry before the push */
+    CHECK ((P = CS_GetPrevEntry (S, Push)) != 0);
 
     /* Get the push entry */
     PushEntry = CS_GetEntry (S, Push);
 
+    /* Check the entry before the push, if it's a lda instruction with an
+     * addressing mode that does not use an additional index register. If
+     * so, we may use this location for the or and must not save the
+     * value in the zero page location.
+     */
+    DirectOr = (P->OPC == OP65_LDA &&
+               (P->AM == AM65_IMM || P->AM == AM65_ZP || P->AM == AM65_ABS));
+
     /* Store the value into the zeropage instead of pushing it */
-    X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
-    CS_InsertEntry (S, X, Push+1);
     X = NewCodeEntry (OP65_STX, AM65_ZP, ZPHi, 0, PushEntry->LI);
-    CS_InsertEntry (S, X, Push+2);
+    CS_InsertEntry (S, X, Push+1);
+    ++Or;  /* Correct the index */
+    if (DirectOr) {
+       X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
+       CS_InsertEntry (S, X, Push+1);
+       ++Or;  /* Correct the index */
+    }
 
-    /* Correct the index of the add and get a pointer to the entry */
-    Or += 2;
+    /* Get a pointer to the or entry */
     OrEntry = CS_GetEntry (S, Or);
 
     /* Inline the or */
-    X = NewCodeEntry (OP65_ORA, AM65_ZP, ZPLo, 0, OrEntry->LI);
+    if (DirectOr) {
+       /* Or with variable location */
+       X = NewCodeEntry (OP65_ORA, P->AM, P->Arg, 0, OrEntry->LI);
+    } else {
+       X = NewCodeEntry (OP65_ORA, AM65_ZP, ZPLo, 0, OrEntry->LI);
+    }
     CS_InsertEntry (S, X, Or+1);
     if (PushEntry->RI->In.RegX >= 0 && OrEntry->RI->In.RegX >= 0) {
        /* Both values known, precalculate the result */
@@ -345,35 +411,57 @@ static unsigned Opt_tosorax (CodeSeg* S, unsigned Push, unsigned Or,
 
 static unsigned Opt_tosxorax (CodeSeg* S, unsigned Push, unsigned Xor,
                              const char* ZPLo, const char* ZPHi)
-/* Optimize the tosorax sequence if possible */
+/* Optimize the tosxorax sequence if possible */
 {
+    CodeEntry* P;
     CodeEntry* X;
     CodeEntry* PushEntry;
     CodeEntry* XorEntry;
+    int        DirectXor;
+
+    /* Get the entry before the push */
+    CHECK ((P = CS_GetPrevEntry (S, Push)) != 0);
 
     /* Get the push entry */
     PushEntry = CS_GetEntry (S, Push);
 
+    /* Check the entry before the push, if it's a lda instruction with an
+     * addressing mode that does not use an additional index register. If
+     * so, we may use this location for the xor and must not save the
+     * value in the zero page location.
+     */
+    DirectXor = (P->OPC == OP65_LDA &&
+                (P->AM == AM65_IMM || P->AM == AM65_ZP || P->AM == AM65_ABS));
+
     /* Store the value into the zeropage instead of pushing it */
-    X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
-    CS_InsertEntry (S, X, Push+1);
     X = NewCodeEntry (OP65_STX, AM65_ZP, ZPHi, 0, PushEntry->LI);
-    CS_InsertEntry (S, X, Push+2);
+    CS_InsertEntry (S, X, Push+1);
+    ++Xor;  /* Correct the index */
+    if (DirectXor) {
+       X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
+       CS_InsertEntry (S, X, Push+1);
+       ++Xor;  /* Correct the index */
+    }
 
-    /* Correct the index of the add and get a pointer to the entry */
-    Xor += 2;
+    /* Get a pointer to the entry */
     XorEntry = CS_GetEntry (S, Xor);
 
-    /* Inline the or */
-    X = NewCodeEntry (OP65_EOR, AM65_ZP, ZPLo, 0, XorEntry->LI);
+    /* Inline the xor */
+    if (DirectXor) {
+       /* Xor with variable location */
+       X = NewCodeEntry (OP65_EOR, P->AM, P->Arg, 0, XorEntry->LI);
+    } else {
+       /* Xor with temp storage */
+       X = NewCodeEntry (OP65_EOR, AM65_ZP, ZPLo, 0, XorEntry->LI);
+    }
     CS_InsertEntry (S, X, Xor+1);
     if (PushEntry->RI->In.RegX >= 0 && XorEntry->RI->In.RegX >= 0) {
        /* Both values known, precalculate the result */
-       char Buf [16];
-       int Val = (PushEntry->RI->In.RegX ^ XorEntry->RI->In.RegX);
-       xsprintf (Buf, sizeof (Buf), "$%02X", Val);
+       char Buf [16];
+       int Val = (PushEntry->RI->In.RegX ^ XorEntry->RI->In.RegX);
+       xsprintf (Buf, sizeof (Buf), "$%02X", Val);
                X = NewCodeEntry (OP65_LDX, AM65_IMM, Buf, 0, XorEntry->LI);
-       CS_InsertEntry (S, X, Xor+2);
+       CS_InsertEntry (S, X, Xor+2);
     } else if (PushEntry->RI->In.RegX != 0) {
        /* High byte is unknown */
                X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, XorEntry->LI);
@@ -399,13 +487,13 @@ static unsigned Opt_tosxorax (CodeSeg* S, unsigned Push, unsigned Xor,
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                  Code                                    */
 /*****************************************************************************/
 
 
 
 typedef unsigned (*OptFunc) (CodeSeg* S, unsigned Push, unsigned Store,
-                            const char* ZPLo, const char* ZPHi);
+                            const char* ZPLo, const char* ZPHi);
 typedef struct OptFuncDesc OptFuncDesc;
 struct OptFuncDesc {
     const char*         Name;   /* Name of the replaced runtime function */