diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index 5924ab6cf..a1af0bb8b 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -167,6 +167,17 @@ int ED_IsLocQuasiConst (const ExprDesc* Expr) +int ED_IsLocZP (const ExprDesc* Expr) +/* Return true if the expression is in a location on a zeropage */ +{ + return ED_IsLocRegister (Expr) || + (ED_IsLocConst (Expr) && + Expr->Sym != 0 && + (Expr->Sym->Flags & SC_ZEROPAGE) != 0); +} + + + #if !defined(HAVE_INLINE) int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) /* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ @@ -302,6 +313,23 @@ int ED_IsQuasiConstAddr (const ExprDesc* Expr) + +int ED_IsStackAddr (const ExprDesc* Expr) +/* Return true if the expression denotes a fixed address on stack */ +{ + return ED_IsAddrExpr (Expr) && ED_IsLocStack (Expr); +} + + + +int ED_IsZPInd (const ExprDesc* Expr) +/* Return true if the expression is located on the zeropage */ +{ + return ED_IsIndExpr (Expr) && ED_IsLocZP (Expr); +} + + + int ED_IsNullPtr (const ExprDesc* Expr) /* Return true if the given expression is a NULL pointer constant */ { diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index 2ef8b617f..93a8604c9 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -369,6 +369,9 @@ int ED_IsLocQuasiConst (const ExprDesc* Expr); */ #endif +int ED_IsLocZP (const ExprDesc* Expr); +/* Return true if the expression is in a location on a zeropage */ + #if defined(HAVE_INLINE) INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) /* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ @@ -572,6 +575,12 @@ int ED_IsQuasiConstAddr (const ExprDesc* Expr); ** This can be a constant address or a stack variable address. */ +int ED_IsStackAddr (const ExprDesc* Expr); +/* Return true if the expression denotes a fixed address on stack */ + +int ED_IsZPInd (const ExprDesc* Expr); +/* Return true if the expression is located on the zeropage */ + int ED_IsNullPtr (const ExprDesc* Expr); /* Return true if the given expression is a NULL pointer constant */ diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index e968aaf1f..246bce192 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -280,13 +280,11 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ** generated, and emit better code. */ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && - ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || - (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && - ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || - (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) { + (ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) && + (ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr))) { - int Reg1 = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr); - int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr); + int Reg1 = ED_IsZPInd (&Arg1.Expr); + int Reg2 = ED_IsZPInd (&Arg2.Expr); /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); @@ -342,9 +340,9 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && - ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) && - ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) && - (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) { + ED_IsConstAddr (&Arg2.Expr) && + ED_IsStackAddr (&Arg1.Expr) && + ED_GetStackOffs (&Arg1.Expr, Arg3.Expr.IVal) < 256) { /* It is possible to just use one index register even if the stack ** offset is not zero, by adjusting the offset to the constant @@ -353,7 +351,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ** than 256. Register space is zero page, which means that the ** address calculation could overflow in the linker. */ - int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && + int AllowOneIndex = !ED_IsLocZP (&Arg2.Expr) && !(ED_IsLocNone (&Arg2.Expr) && Arg2.Expr.IVal < 256); /* Calculate the real stack offset */ @@ -420,9 +418,9 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && - ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) && - (Arg2.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256 && - ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) { + ED_IsStackAddr (&Arg2.Expr) && + ED_GetStackOffs (&Arg2.Expr, Arg3.Expr.IVal) < 256 && + ED_IsConstAddr (&Arg1.Expr)) { /* It is possible to just use one index register even if the stack ** offset is not zero, by adjusting the offset to the constant @@ -431,7 +429,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ** than 256. Register space is zero page, which means that the ** address calculation could overflow in the linker. */ - int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && + int AllowOneIndex = !ED_IsLocZP (&Arg1.Expr) && !(ED_IsLocNone (&Arg1.Expr) && Arg1.Expr.IVal < 256); /* Calculate the real stack offset */ @@ -497,8 +495,8 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) goto ExitPoint; } - if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && - ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) && + if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && + ED_IsStackAddr (&Arg2.Expr) && (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) { /* Drop the generated code but leave the load of the first argument*/ @@ -637,10 +635,9 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) */ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ED_IsConstAbsInt (&Arg2.Expr) && - ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || - (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) { + (ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr))) { - int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr); + int Reg = ED_IsZPInd (&Arg1.Expr); /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); @@ -689,8 +686,8 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ED_IsConstAbsInt (&Arg2.Expr) && - ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) && - (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) { + ED_IsStackAddr (&Arg1.Expr) && + ED_GetStackOffs (&Arg1.Expr, Arg3.Expr.IVal) < 256) { /* Calculate the real stack offset */ int Offs = ED_GetStackOffs (&Arg1.Expr, 0); @@ -850,7 +847,7 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* We do now have Arg1 in the primary. Load the first character from ** this string and cast to int. This is the function result. */ - IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr); + IsArray = IsTypeArray (Arg1.Type) && ED_IsAddrExpr (&Arg1.Expr); if (IsArray && ED_IsLocStack (&Arg1.Expr) && (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) { /* Drop the generated code */ @@ -878,22 +875,20 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr) } } else if ((IS_Get (&CodeSizeFactor) >= 165) && - ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || - (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && - ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || - (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) && + (ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) && + (ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr)) && (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) { unsigned Entry, Loop, Fin; /* Labels */ const char* Load; const char* Compare; - if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) { + if (ED_IsZPInd (&Arg1.Expr)) { Load = "lda (%s),y"; } else { Load = "lda %s,y"; } - if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) { + if (ED_IsZPInd (&Arg2.Expr)) { Compare = "cmp (%s),y"; } else { Compare = "cmp %s,y"; @@ -924,14 +919,13 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr) g_defcodelabel (Fin); } else if ((IS_Get (&CodeSizeFactor) > 190) && - ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || - (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && + (ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) && (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) { unsigned Entry, Loop, Fin; /* Labels */ const char* Compare; - if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) { + if (ED_IsZPInd (&Arg2.Expr)) { Compare = "cmp (%s),y"; } else { Compare = "cmp %s,y"; @@ -1028,21 +1022,19 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ** be generated. If such a situation is detected, throw away the ** generated, and emit better code. */ - if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || - (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && - ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || - (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) && + if ((ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) && + (ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr)) && (IS_Get (&EagerlyInlineFuncs) || (ECount != UNSPECIFIED && ECount < 256))) { const char* Load; const char* Store; - if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) { + if (ED_IsZPInd (&Arg2.Expr)) { Load = "lda (%s),y"; } else { Load = "lda %s,y"; } - if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) { + if (ED_IsZPInd (&Arg1.Expr)) { Store = "sta (%s),y"; } else { Store = "sta %s,y"; @@ -1069,9 +1061,9 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) goto ExitPoint; } - if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) && + if (ED_IsStackAddr (&Arg2.Expr) && StackPtr >= -255 && - ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) { + ED_IsConstAddr (&Arg1.Expr)) { /* It is possible to just use one index register even if the stack ** offset is not zero, by adjusting the offset to the constant @@ -1080,7 +1072,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ** than 256. Register space is zero page, which means that the ** address calculation could overflow in the linker. */ - int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && + int AllowOneIndex = !ED_IsLocZP (&Arg1.Expr) && !(ED_IsLocNone (&Arg1.Expr) && Arg1.Expr.IVal < 256); /* Calculate the real stack offset */ @@ -1116,8 +1108,8 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) goto ExitPoint; } - if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) && - ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) && + if (ED_IsConstAddr (&Arg2.Expr) && + ED_IsStackAddr (&Arg1.Expr) && StackPtr >= -255) { /* It is possible to just use one index register even if the stack @@ -1127,7 +1119,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ** than 256. Register space is zero page, which means that the ** address calculation could overflow in the linker. */ - int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && + int AllowOneIndex = !ED_IsLocZP (&Arg2.Expr) && !(ED_IsLocNone (&Arg2.Expr) && Arg2.Expr.IVal < 256); /* Calculate the real stack offset */ @@ -1276,7 +1268,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ** completely within the reach of a byte sized index register. */ if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex && - (Arg.IVal - StackPtr) + ECount < 256) { + ED_GetStackOffs (&Arg, ECount) < 256) { /* Calculate the true stack offset */ int Offs = ED_GetStackOffs (&Arg, 0); @@ -1305,7 +1297,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) ** get inlined if requested on the command line, since we cannot know how ** big the buffer actually is, so inlining is not always safe. */ - if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsPtr && + if (ED_IsZPInd (&Arg) && IsPtr && IS_Get (&EagerlyInlineFuncs)) { /* Generate the strlen code */