]> git.sur5r.net Git - cc65/commitdiff
Fixed a code generation bug
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 6 Apr 2002 14:51:27 +0000 (14:51 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 6 Apr 2002 14:51:27 +0000 (14:51 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1215 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeent.c
src/cc65/codeent.h
src/cc65/codeinfo.c
src/cc65/codeinfo.h
src/cc65/coptcmp.c
src/cc65/coptind.c
src/cc65/expr.c

index 14bab06393a42336caabc71ffa88a3b8d289de30..00a93a947a6146c437b97bec709de7e31f138621 100644 (file)
@@ -224,7 +224,7 @@ const char* MakeHexArg (unsigned Num)
  */
 {
     static char Buf[16];
-    xsprintf (Buf, sizeof (Buf), "$%02X", (char) Num);
+    xsprintf (Buf, sizeof (Buf), "$%02X", (unsigned char) Num);
     return Buf;
 }
 
@@ -376,6 +376,46 @@ int CE_KnownImm (const CodeEntry* E)
 
 
 
+int CE_UseLoadFlags (const CodeEntry* E)
+/* Return true if the instruction uses any flags that are set by a load of
+ * a register (N and Z).
+ */
+{
+    /* A branch will use the flags */
+    if (E->Info & OF_FBRA) {
+        return 1;
+    }
+
+    /* Call of a boolean transformer routine will also use the flags */
+    if (E->OPC == OP65_JSR) {
+        /* Get the condition that is evaluated and check it */
+        switch (FindBoolCmpCond (E->Arg)) {
+            case CMP_EQ:
+            case CMP_NE:
+            case CMP_GT:
+            case CMP_GE:
+            case CMP_LT:
+            case CMP_LE:
+            case CMP_UGT:
+            case CMP_ULE:
+            case CMP_INV:
+                /* Will use the N or Z flags */
+                return 1;
+
+
+            case CMP_UGE:       /* Uses only carry */
+            case CMP_ULT:       /* Dito */
+            default:            /* No bool transformer subroutine */
+                return 0;
+        }
+    }
+
+    /* Anything else */
+    return 0;
+}
+
+
+
 void CE_FreeRegInfo (CodeEntry* E)
 /* Free an existing register info struct */
 {
index 154ceb470879ea23bef7155c361c4f3a08c72627..a78d77e8107f949fad7250add5835feddceeccf4 100644 (file)
@@ -196,6 +196,11 @@ INLINE int CE_IsCall (const CodeEntry* E, const char* Name)
 #  define CE_IsCall(E, Name) ((E)->OPC == OP65_JSR && strcmp ((E)->Arg, (Name)) == 0)
 #endif
 
+int CE_UseLoadFlags (const CodeEntry* E);
+/* Return true if the instruction uses any flags that are set by a load of
+ * a register (N and Z).
+ */
+
 void CE_FreeRegInfo (CodeEntry* E);
 /* Free an existing register info struct */
 
index a1fa65891a9eaf3bfc67550c6df8736f6c638dea..5014e71a4f1c8e179c848a2871d16633b8c194ec 100644 (file)
 
 
 
+/* Table with the compare suffixes */
+static const char CmpSuffixTab [][4] = {
+    "eq", "ne", "gt", "ge", "lt", "le", "ugt", "uge", "ult", "ule"
+};
+
 /* Table listing the function names and code info values for known internally
  * used functions. This table should get auto-generated in the future.
  */
@@ -584,3 +589,59 @@ unsigned GetKnownReg (unsigned Use, const RegContents* RC)
 
 
 
+static cmp_t FindCmpCond (const char* Code, unsigned CodeLen)
+/* Search for a compare condition by the given code using the given length */
+{
+    unsigned I;
+
+    /* Linear search */
+    for (I = 0; I < sizeof (CmpSuffixTab) / sizeof (CmpSuffixTab [0]); ++I) {
+       if (strncmp (Code, CmpSuffixTab [I], CodeLen) == 0) {
+           /* Found */
+           return I;
+       }
+    }
+
+    /* Not found */
+    return CMP_INV;
+}
+
+
+
+cmp_t FindBoolCmpCond (const char* Name)
+/* Check if the given string is the name of one of the boolean transformer
+ * subroutine, and if so, return the condition that is evaluated by this
+ * routine. Return CMP_INV if the condition is not recognised.
+ */
+{
+    /* Check for the correct subroutine name */
+    if (strncmp (Name, "bool", 4) == 0) {
+       /* Name is ok, search for the code in the table */
+       return FindCmpCond (Name+4, strlen(Name)-4);
+    } else {
+       /* Not found */
+       return CMP_INV;
+    }
+}
+
+
+
+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.
+ */
+{
+    unsigned Len = strlen (Name);
+
+    /* Check for the correct subroutine name */
+    if (strncmp (Name, "tos", 3) == 0 && strcmp (Name+Len-2, "ax") == 0) {
+       /* Name is ok, search for the code in the table */
+       return FindCmpCond (Name+3, Len-3-2);
+    } else {
+       /* Not found */
+       return CMP_INV;
+    }
+}
+
+
+
index d9e1036ed8515089aa01c5e2de45ed35d3477f98..7e4eddf983c99c699093e92bc8862fe3f6d0c4bd 100644 (file)
@@ -103,6 +103,23 @@ struct ZPInfo {
 
 
 
+/* Defines for the conditions in a compare */
+typedef enum {
+    CMP_INV = -1,
+    CMP_EQ,
+    CMP_NE,
+    CMP_GT,
+    CMP_GE,
+    CMP_LT,
+    CMP_LE,
+    CMP_UGT,
+    CMP_UGE,
+    CMP_ULT,
+    CMP_ULE
+} cmp_t;
+
+
+
 /*****************************************************************************/
 /*                                          Code                                    */
 /*****************************************************************************/
@@ -143,6 +160,17 @@ unsigned GetKnownReg (unsigned Use, const struct RegContents* RC);
  * register in question does not have a known value, return REG_NONE.
  */
 
+cmp_t FindBoolCmpCond (const char* Name);
+/* Check if the given string is the name of one of the boolean transformer
+ * subroutine, and if so, return the condition that is evaluated by this
+ * routine. Return CMP_INV if the condition is not recognised.
+ */
+
+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.
+ */
+
 
 
 /* End of codeinfo.h */
index c185ecc27ad9432bf3b5afb1b8374723ed661190..049b3ef7970c492bad7364549cfae7531db9dc75 100644 (file)
 
 
 
-/* Defines for the conditions in a compare */
-typedef enum {
-    CMP_INV = -1,
-    CMP_EQ,
-    CMP_NE,
-    CMP_GT,
-    CMP_GE,
-    CMP_LT,
-    CMP_LE,
-    CMP_UGT,
-    CMP_UGE,
-    CMP_ULT,
-    CMP_ULE
-} cmp_t;
-
-/* Table with the compare suffixes */
-static const char CmpSuffixTab [][4] = {
-    "eq", "ne", "gt", "ge", "lt", "le", "ugt", "uge", "ult", "ule"
-};
-
 /* Table used to invert a condition, indexed by condition */
 static const unsigned char CmpInvertTab [] = {
     CMP_NE, CMP_EQ,
@@ -89,59 +69,6 @@ static const char CmpSignedTab [] = {
 
 
 
-static cmp_t FindCmpCond (const char* Code, unsigned CodeLen)
-/* Search for a compare condition by the given code using the given length */
-{
-    unsigned I;
-
-    /* Linear search */
-    for (I = 0; I < sizeof (CmpSuffixTab) / sizeof (CmpSuffixTab [0]); ++I) {
-       if (strncmp (Code, CmpSuffixTab [I], CodeLen) == 0) {
-           /* Found */
-           return I;
-       }
-    }
-
-    /* Not found */
-    return CMP_INV;
-}
-
-
-
-static cmp_t FindBoolCmpCond (const char* Name)
-/* Map a condition suffix to a code. Return the code or CMP_INV on failure */
-{
-    /* Check for the correct subroutine name */
-    if (strncmp (Name, "bool", 4) == 0) {
-       /* Name is ok, search for the code in the table */
-       return FindCmpCond (Name+4, strlen(Name)-4);
-    } else {
-       /* Not found */
-       return CMP_INV;
-    }
-}
-
-
-
-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.
- */
-{
-    unsigned Len = strlen (Name);
-
-    /* Check for the correct subroutine name */
-    if (strncmp (Name, "tos", 3) == 0 && strcmp (Name+Len-2, "ax") == 0) {
-       /* Name is ok, search for the code in the table */
-       return FindCmpCond (Name+3, Len-3-2);
-    } else {
-       /* Not found */
-       return CMP_INV;
-    }
-}
-
-
-
 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
index 2291087d501aa222be9e6687ec99d90449d5abb5..3c04f63a7c5523be9a583f2f93ade565bc8d250b 100644 (file)
@@ -655,7 +655,7 @@ unsigned OptCondBranches (CodeSeg* S)
 
 
 /*****************************************************************************/
-/*                     Remove unused loads and stores                       */
+/*                     Remove unused loads and stores                       */
 /*****************************************************************************/
 
 
@@ -675,24 +675,24 @@ unsigned OptUnusedLoads (CodeSeg* S)
                CodeEntry* E = CS_GetEntry (S, I);
 
        /* Check if it's a register load or transfer insn */
-       if ((E->Info & (OF_LOAD | OF_XFR | OF_REG_INCDEC)) != 0  &&
-           (N = CS_GetNextEntry (S, I)) != 0                    &&
-           (N->Info & OF_FBRA) == 0) {
+       if ((E->Info & (OF_LOAD | OF_XFR | OF_REG_INCDEC)) != 0         &&
+           (N = CS_GetNextEntry (S, I)) != 0                           &&
+           !CE_UseLoadFlags (N)) {
 
            /* Check which sort of load or transfer it is */
            unsigned R;
            switch (E->OPC) {
-               case OP65_DEA:
-               case OP65_INA:
-               case OP65_LDA:
+               case OP65_DEA:
+               case OP65_INA:
+               case OP65_LDA:
                case OP65_TXA:
                case OP65_TYA:  R = REG_A;      break;
-               case OP65_DEX:
-               case OP65_INX:
-               case OP65_LDX:
+               case OP65_DEX:
+               case OP65_INX:
+               case OP65_LDX:
                case OP65_TAX:  R = REG_X;      break;
-               case OP65_DEY:
-               case OP65_INY:
+               case OP65_DEY:
+               case OP65_INY:
                        case OP65_LDY:
                case OP65_TAY:  R = REG_Y;      break;
                default:        goto NextEntry;         /* OOPS */
@@ -799,7 +799,7 @@ unsigned OptDupLoads (CodeSeg* S)
                            CE_KnownImm (E)                   && /* Value to be loaded is known */
                            In->RegA == (long) E->Num         && /* Both are equal */
                            (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
-                   (N->Info & OF_FBRA) == 0) {          /* Which is not a cond branch */
+                   !CE_UseLoadFlags (N)) {              /* Which does not use the flags */
                    Delete = 1;
                }
                break;
@@ -809,7 +809,7 @@ unsigned OptDupLoads (CodeSeg* S)
                    CE_KnownImm (E)                   && /* Value to be loaded is known */
                    In->RegX == (long) E->Num         && /* Both are equal */
                            (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
-                   (N->Info & OF_FBRA) == 0) {          /* Which is not a cond branch */
+                   !CE_UseLoadFlags (N)) {              /* Which does not use the flags */
                    Delete = 1;
                }
                break;
@@ -819,7 +819,7 @@ unsigned OptDupLoads (CodeSeg* S)
                    CE_KnownImm (E)                   && /* Value to be loaded is known */
                    In->RegY == (long) E->Num         && /* Both are equal */
                            (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
-                   (N->Info & OF_FBRA) == 0) {          /* Which is not a cond branch */
+                   !CE_UseLoadFlags (N)) {              /* Which does not use the flags */
                    Delete = 1;
                }
                break;
@@ -908,37 +908,37 @@ unsigned OptDupLoads (CodeSeg* S)
                 if (In->RegA >= 0                     &&
                    In->RegA == In->RegX              &&
                    (N = CS_GetNextEntry (S, I)) != 0 &&
-                   (N->Info & OF_FBRA) == 0) {
+                           !CE_UseLoadFlags (N)) {        
                    /* Value is identical and not followed by a branch */
                    Delete = 1;
                }
                break;
 
            case OP65_TAY:
-                if (In->RegA >= 0                 &&
-                   In->RegA == In->RegY    &&
+                if (In->RegA >= 0                       &&
+                   In->RegA == In->RegY                &&
                    (N = CS_GetNextEntry (S, I)) != 0   &&
-                   (N->Info & OF_FBRA) == 0) {
+                           !CE_UseLoadFlags (N)) {
                    /* Value is identical and not followed by a branch */
                    Delete = 1;
                }
                break;
 
                    case OP65_TXA:
-                if (In->RegX >= 0                 &&
-                   In->RegX == In->RegA    &&
+                if (In->RegX >= 0                       &&
+                   In->RegX == In->RegA                &&
                    (N = CS_GetNextEntry (S, I)) != 0   &&
-                   (N->Info & OF_FBRA) == 0) {
+                           !CE_UseLoadFlags (N)) {
                    /* Value is identical and not followed by a branch */
                    Delete = 1;
                }
                break;
 
            case OP65_TYA:
-                if (In->RegY >= 0                 &&
-                   In->RegY == In->RegA    &&
+                if (In->RegY >= 0                       &&
+                   In->RegY == In->RegA                &&
                    (N = CS_GetNextEntry (S, I)) != 0   &&
-                   (N->Info & OF_FBRA) == 0) {
+                           !CE_UseLoadFlags (N)) {
                    /* Value is identical and not followed by a branch */
                    Delete = 1;
                }
@@ -967,7 +967,7 @@ unsigned OptDupLoads (CodeSeg* S)
 
     }
 
-    /* Free register info */
+    /* Free register info */                            
     CS_FreeRegInfo (S);
 
     /* Return the number of changes made */
@@ -1003,7 +1003,7 @@ unsigned OptStoreLoad (CodeSeg* S)
             (E->OPC == OP65_STY && N->OPC == OP65_LDY))    &&
            strcmp (E->Arg, N->Arg) == 0                    &&
            (X = CS_GetNextEntry (S, I+1)) != 0             &&
-                   (X->Info & OF_FBRA) == 0) {
+            !CE_UseLoadFlags (X)) {
 
                    /* Register has already the correct value, remove the load */
            CS_DelEntry (S, I+1);
@@ -1060,8 +1060,8 @@ unsigned OptTransfers (CodeSeg* S)
                 */
                if ((X = CS_GetNextEntry (S, I+1)) == 0) {
                    goto NextEntry;
-               }
-               if ((X->Info & OF_FBRA) != 0) {
+               }              
+                if (CE_UseLoadFlags (X)) {
                    if (I == 0) {
                        /* No preceeding entry */
                        goto NextEntry;
index dd2469387b9668c8a26c67c928f4bd0e5ba9f39d..c78d98cee6b5fef424e3372e5355a2899abfd0e5 100644 (file)
@@ -281,16 +281,16 @@ unsigned assignadjust (type* lhst, ExprDesc* rhs)
 
 
 
-void DefineData (ExprDesc* lval)
+void DefineData (ExprDesc* Expr)
 /* Output a data definition for the given expression */
 {
-    unsigned flags = lval->Flags;
+    unsigned Flags = Expr->Flags;
 
-    switch (flags & E_MCTYPE) {
+    switch (Flags & E_MCTYPE) {
 
                case E_TCONST:
            /* Number */
-           g_defdata (TypeOf (lval->Type) | CF_CONST, lval->ConstVal, 0);
+           g_defdata (TypeOf (Expr->Type) | CF_CONST, Expr->ConstVal, 0);
                    break;
 
        case E_TREGISTER:
@@ -305,33 +305,33 @@ void DefineData (ExprDesc* lval)
                case E_TGLAB:
         case E_TLLAB:
                    /* Local or global symbol */
-           g_defdata (GlobalModeFlags (flags), lval->Name, lval->ConstVal);
+           g_defdata (GlobalModeFlags (Flags), Expr->Name, Expr->ConstVal);
            break;
 
                case E_TLIT:
            /* a literal of some kind */
-                   g_defdata (CF_STATIC, LiteralPoolLabel, lval->ConstVal);
+                   g_defdata (CF_STATIC, LiteralPoolLabel, Expr->ConstVal);
                    break;
 
                default:
-           Internal ("Unknown constant type: %04X", flags);
+           Internal ("Unknown constant type: %04X", Flags);
     }
 }
 
 
 
-static void lconst (unsigned flags, ExprDesc* lval)
-/* Load primary reg with some constant value. */
+static void lconst (unsigned Flags, ExprDesc* Expr)
+/* Load the primary register with some constant value. */
 {
-    switch (lval->Flags & E_MCTYPE) {
+    switch (Expr->Flags & E_MCTYPE) {
 
        case E_TLOFFS:
-                   g_leasp (lval->ConstVal);
+                   g_leasp (Expr->ConstVal);
            break;
 
                case E_TCONST:
            /* Number constant */
-                   g_getimmed (flags | TypeOf (lval->Type) | CF_CONST, lval->ConstVal, 0);
+                   g_getimmed (Flags | TypeOf (Expr->Type) | CF_CONST, Expr->ConstVal, 0);
                    break;
 
        case E_TREGISTER:
@@ -346,18 +346,18 @@ static void lconst (unsigned flags, ExprDesc* lval)
                case E_TGLAB:
         case E_TLLAB:
                    /* Local or global symbol, load address */
-           flags |= GlobalModeFlags (lval->Flags);
-           flags &= ~CF_CONST;
-           g_getimmed (flags, lval->Name, lval->ConstVal);
+           Flags |= GlobalModeFlags (Expr->Flags);
+           Flags &= ~CF_CONST;
+           g_getimmed (Flags, Expr->Name, Expr->ConstVal);
                    break;
 
                case E_TLIT:
            /* Literal string */
-           g_getimmed (CF_STATIC, LiteralPoolLabel, lval->ConstVal);
+           g_getimmed (CF_STATIC, LiteralPoolLabel, Expr->ConstVal);
                    break;
 
                default:
-           Internal ("Unknown constant type: %04X", lval->Flags);
+           Internal ("Unknown constant type: %04X", Expr->Flags);
     }
 }
 
@@ -411,9 +411,10 @@ static int kcalc (int tok, long val1, long val2)
 
 
 
-static GenDesc* FindGen (token_t Tok, GenDesc** Table)
+static const GenDesc* FindGen (token_t Tok, const GenDesc** Table)
+/* Find a token in a generator table */
 {
-    GenDesc* G;
+    const GenDesc* G;
     while ((G = *Table) != 0) {
        if (G->Tok == Tok) {
            return G;
@@ -1760,7 +1761,7 @@ static int hie10 (ExprDesc* lval)
 
 
 
-static int hie_internal (GenDesc** ops,                /* List of generators */
+static int hie_internal (const GenDesc** ops,          /* List of generators */
                                 ExprDesc* lval,        /* parent expr's lval */
                                 int (*hienext) (ExprDesc*),
                         int* UsedGen)          /* next higher level */
@@ -1770,7 +1771,7 @@ static int hie_internal (GenDesc** ops,           /* List of generators */
     ExprDesc lval2;
     CodeMark Mark1;
     CodeMark Mark2;
-    GenDesc* Gen;
+    const GenDesc* Gen;
     token_t tok;                               /* The operator token */
     unsigned ltype, type;
     int rconst;                                /* Operand is a constant */
@@ -1870,8 +1871,8 @@ static int hie_internal (GenDesc** ops,           /* List of generators */
 
 
 
-static int hie_compare (GenDesc** ops,         /* List of generators */
-                               ExprDesc* lval, /* parent expr's lval */
+static int hie_compare (const GenDesc** ops,   /* List of generators */
+                               ExprDesc* lval,         /* parent expr's lval */
                                int (*hienext) (ExprDesc*))
 /* Helper function for the compare operators */
 {
@@ -1879,7 +1880,7 @@ static int hie_compare (GenDesc** ops,            /* List of generators */
     ExprDesc lval2;
     CodeMark Mark1;
     CodeMark Mark2;
-    GenDesc* Gen;
+    const GenDesc* Gen;
     token_t tok;                       /* The operator token */
     unsigned ltype;
     int rconst;                                /* Operand is a constant */
@@ -1997,7 +1998,7 @@ static int hie_compare (GenDesc** ops,            /* List of generators */
 static int hie9 (ExprDesc *lval)
 /* Process * and / operators. */
 {
-    static GenDesc* hie9_ops [] = {
+    static const GenDesc* hie9_ops [] = {
        &GenMUL, &GenDIV, &GenMOD, 0
     };
     int UsedGen;
@@ -2421,7 +2422,7 @@ static int hie8 (ExprDesc* lval)
 static int hie7 (ExprDesc *lval)
 /* Parse << and >>. */
 {
-    static GenDesc* hie7_ops [] = {
+    static const GenDesc* hie7_ops [] = {
                &GenASL, &GenASR, 0
     };
     int UsedGen;
@@ -2434,7 +2435,7 @@ static int hie7 (ExprDesc *lval)
 static int hie6 (ExprDesc *lval)
 /* process greater-than type comparators */
 {
-    static GenDesc* hie6_ops [] = {
+    static const GenDesc* hie6_ops [] = {
        &GenLT, &GenLE, &GenGE, &GenGT, 0
     };
     return hie_compare (hie6_ops, lval, hie7);
@@ -2444,7 +2445,7 @@ static int hie6 (ExprDesc *lval)
 
 static int hie5 (ExprDesc *lval)
 {
-    static GenDesc* hie5_ops[] = {
+    static const GenDesc* hie5_ops[] = {
                &GenEQ, &GenNE, 0
     };
     return hie_compare (hie5_ops, lval, hie6);
@@ -2455,7 +2456,7 @@ static int hie5 (ExprDesc *lval)
 static int hie4 (ExprDesc* lval)
 /* Handle & (bitwise and) */
 {
-    static GenDesc* hie4_ops [] = {
+    static const GenDesc* hie4_ops [] = {
                &GenAND, 0
     };
     int UsedGen;
@@ -2468,7 +2469,7 @@ static int hie4 (ExprDesc* lval)
 static int hie3 (ExprDesc *lval)
 /* Handle ^ (bitwise exclusive or) */
 {
-    static GenDesc* hie3_ops [] = {
+    static const GenDesc* hie3_ops [] = {
                &GenXOR, 0
     };
     int UsedGen;
@@ -2481,7 +2482,7 @@ static int hie3 (ExprDesc *lval)
 static int hie2 (ExprDesc *lval)
 /* Handle | (bitwise or) */
 {
-    static GenDesc* hie2_ops [] = {
+    static const GenDesc* hie2_ops [] = {
                &GenOR, 0
     };
     int UsedGen;
@@ -2810,7 +2811,7 @@ static int hieQuest (ExprDesc *lval)
 
 
 
-static void opeq (GenDesc* Gen, ExprDesc *lval, int k)
+static void opeq (const GenDesc* Gen, ExprDesc *lval, int k)
 /* Process "op=" operators. */
 {
     ExprDesc lval2;
@@ -2891,7 +2892,7 @@ static void opeq (GenDesc* Gen, ExprDesc *lval, int k)
 
 
 
-static void addsubeq (GenDesc* Gen, ExprDesc *lval, int k)
+static void addsubeq (const GenDesc* Gen, ExprDesc *lval, int k)
 /* Process the += and -= operators */
 {
     ExprDesc lval2;