From 49d1a47269d3829b453166c1d3c4648175b3896d Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 19 Dec 2004 22:15:43 +0000 Subject: [PATCH] Several improvements and a few bug fixes git-svn-id: svn://svn.cc65.org/cc65/trunk@3339 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/studyexpr.c | 125 +++++++++++++++++++++++++++++++++---------- 1 file changed, 98 insertions(+), 27 deletions(-) diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c index 56821b90c..2fafda934 100644 --- a/src/ca65/studyexpr.c +++ b/src/ca65/studyexpr.c @@ -226,7 +226,7 @@ static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym) SymRef = ED->SymRef + ED->SymCount++; /* Initialize the new struct and return it */ - SymRef->Count = 1; + SymRef->Count = 0; SymRef->Ref = Sym; return SymRef; } @@ -335,6 +335,20 @@ static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New) +static void ED_NegRefs (ExprDesc* D) +/* Negate the references in ED */ +{ + unsigned I; + for (I = 0; I < D->SymCount; ++I) { + D->SymRef[I].Count = -D->SymRef[I].Count; + } + for (I = 0; I < D->SecCount; ++I) { + D->SecRef[I].Count = -D->SecRef[I].Count; + } +} + + + static void ED_Add (ExprDesc* ED, const ExprDesc* Right) /* Calculate ED = ED + Right, update address size in ED */ { @@ -345,6 +359,19 @@ static void ED_Add (ExprDesc* ED, const ExprDesc* Right) +static void ED_Sub (ExprDesc* ED, const ExprDesc* Right) +/* Calculate ED = ED - Right, update address size in ED */ +{ + ExprDesc D = *Right; /* Temporary */ + ED_NegRefs (&D); + + ED->Val -= Right->Val; + ED_MergeRefs (ED, &D); /* Merge negatives */ + ED_MergeAddrSize (ED, Right); +} + + + static void ED_Mul (ExprDesc* ED, const ExprDesc* Right) /* Calculate ED = ED * Right, update address size in ED */ { @@ -365,15 +392,8 @@ static void ED_Mul (ExprDesc* ED, const ExprDesc* Right) static void ED_Neg (ExprDesc* D) /* Negate an expression */ { - unsigned I; - D->Val = -D->Val; - for (I = 0; I < D->SymCount; ++I) { - D->SymRef[I].Count = -D->SymRef[I].Count; - } - for (I = 0; I < D->SecCount; ++I) { - D->SecRef[I].Count = -D->SecRef[I].Count; - } + ED_NegRefs (D); } @@ -406,6 +426,22 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D); +static unsigned char GetConstAddrSize (long Val) +/* Get the address size of a constant */ +{ + if ((Val & ~0xFFL) == 0) { + return ADDR_SIZE_ZP; + } else if ((Val & ~0xFFFFL) == 0) { + return ADDR_SIZE_ABS; + } else if ((Val & ~0xFFFFFFL) == 0) { + return ADDR_SIZE_FAR; + } else { + return ADDR_SIZE_LONG; + } +} + + + static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D) /* Study a binary expression subtree. This is a helper function for StudyExpr * used for operations that succeed when both operands are known and constant. @@ -450,9 +486,9 @@ static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D) static void StudyLiteral (ExprNode* Expr, ExprDesc* D) /* Study a literal expression node */ { - /* This one is easy */ - D->Val = Expr->V.Val; + D->Val = Expr->V.Val; + D->AddrSize = GetConstAddrSize (D->Val); } @@ -621,8 +657,7 @@ static void StudyMinus (ExprNode* Expr, ExprDesc* D) if (ED_IsValid (D) || ED_IsValid (&Right)) { /* Subtract both */ - ED_Neg (&Right); - ED_Add (D, &Right); + ED_Sub (D, &Right); } else { @@ -1295,13 +1330,13 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D) void StudyExpr (ExprNode* Expr, ExprDesc* D) /* Study an expression tree and place the contents into D */ { - unsigned I; + unsigned I, J; /* Call the internal function */ StudyExprInternal (Expr, D); /* Remove symbol references with count zero */ - I = 0; + I = J = 0; while (I < D->SymCount) { if (D->SymRef[I].Count == 0) { /* Delete the entry */ @@ -1328,32 +1363,68 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D) } } - /* If we don't have an address size, assign one of the expression is a + /* If we don't have an address size, assign one if the expression is a * constant. */ - if (D->AddrSize == ADDR_SIZE_DEFAULT) { - if (ED_IsConst (D)) { - if ((D->Val & ~0xFFL) == 0) { - D->AddrSize = ADDR_SIZE_ZP; - } else if ((D->Val & ~0xFFFFL) == 0) { - D->AddrSize = ADDR_SIZE_ABS; - } else if ((D->Val & 0xFFFFFFL) == 0) { - D->AddrSize = ADDR_SIZE_FAR; + if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) { + D->AddrSize = GetConstAddrSize (D->Val); + } + + /* If the expression is valid, throw away the address size and recalculate + * it using the data we have. This is more exact than the on-the-fly + * calculation done when evaluating the tree, because symbols may have + * been removed from the expression, and the final numeric value is now + * known. + */ + if (ED_IsValid (D)) { + unsigned char AddrSize; + if (D->SymCount == 1 && D->SecCount == 0) { + /* Exactly one symbol. Assume that the expression has the size of + * the symbol, provided that this size is known. + */ + const SymEntry* Sym = D->SymRef[0].Ref; + AddrSize = GetSymAddrSize (Sym); + if (AddrSize != ADDR_SIZE_DEFAULT) { + D->AddrSize = AddrSize; + } else { + AddrSize = GetConstAddrSize (D->Val); + if (AddrSize > D->AddrSize) { + D->AddrSize = AddrSize; + } + } + } else if (D->SymCount == 0 && D->SecCount == 1) { + /* Exactly one segment reference (segment+offset). In this case, + * the expression has the address size of the segment. + */ + unsigned SegNum = D->SecRef[0].Ref; + AddrSize = GetSegAddrSize (SegNum); + if (AddrSize != ADDR_SIZE_DEFAULT) { + D->AddrSize = AddrSize; } else { - D->AddrSize = ADDR_SIZE_LONG; + AddrSize = GetConstAddrSize (D->Val); + if (AddrSize > D->AddrSize) { + D->AddrSize = AddrSize; + } + } + } else { + AddrSize = GetConstAddrSize (D->Val); + if (AddrSize > D->AddrSize) { + D->AddrSize = AddrSize; } } } #if 0 + /* Debug code */ printf ("StudyExpr: "); DumpExpr (Expr, SymResolve); + printf ("Value: %08lX\n", D->Val); if (!ED_IsValid (D)) { printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize)); } else { printf ("Valid: %s\n", AddrSizeToStr (D->AddrSize)); - printf ("%u symbols:\n", D->SymCount); - printf ("%u sections:\n", D->SecCount); } + printf ("%u symbols:\n", D->SymCount); + printf ("%u sections:\n", D->SecCount); #endif } -- 2.39.5