mirror of
https://github.com/cc65/cc65.git
synced 2024-12-24 11:31:31 +00:00
General fixes for prerequisites for optimization on certain std functions.
Added utility functions for extracting expression info.
This commit is contained in:
parent
bb1b5c363e
commit
7b6f8249a0
@ -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 */
|
||||
{
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
@ -498,7 +496,7 @@ 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) &&
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user