From c6fe12ef6bfd75b228d38d4b7639e399a9b98b49 Mon Sep 17 00:00:00 2001 From: cuz Date: Sat, 6 Apr 2002 14:51:27 +0000 Subject: [PATCH] Fixed a code generation bug git-svn-id: svn://svn.cc65.org/cc65/trunk@1215 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeent.c | 42 +++++++++++++++++++++++++- src/cc65/codeent.h | 5 ++++ src/cc65/codeinfo.c | 61 +++++++++++++++++++++++++++++++++++++ src/cc65/codeinfo.h | 28 +++++++++++++++++ src/cc65/coptcmp.c | 73 --------------------------------------------- src/cc65/coptind.c | 58 +++++++++++++++++------------------ src/cc65/expr.c | 67 +++++++++++++++++++++-------------------- 7 files changed, 198 insertions(+), 136 deletions(-) diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index 14bab0639..00a93a947 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -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 */ { diff --git a/src/cc65/codeent.h b/src/cc65/codeent.h index 154ceb470..a78d77e81 100644 --- a/src/cc65/codeent.h +++ b/src/cc65/codeent.h @@ -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 */ diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index a1fa65891..5014e71a4 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -56,6 +56,11 @@ +/* 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; + } +} + + + diff --git a/src/cc65/codeinfo.h b/src/cc65/codeinfo.h index d9e1036ed..7e4eddf98 100644 --- a/src/cc65/codeinfo.h +++ b/src/cc65/codeinfo.h @@ -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 */ diff --git a/src/cc65/coptcmp.c b/src/cc65/coptcmp.c index c185ecc27..049b3ef79 100644 --- a/src/cc65/coptcmp.c +++ b/src/cc65/coptcmp.c @@ -49,26 +49,6 @@ -/* 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 diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index 2291087d5..3c04f63a7 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -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; diff --git a/src/cc65/expr.c b/src/cc65/expr.c index dd2469387..c78d98cee 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -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; -- 2.39.5