From: cuz Date: Fri, 12 Dec 2003 15:40:08 +0000 (+0000) Subject: Fixed several address size issues X-Git-Tag: V2.12.0~1075 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=841c5f814b25460d97779a8b787d41ae8c9626c5;p=cc65 Fixed several address size issues git-svn-id: svn://svn.cc65.org/cc65/trunk@2729 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/ca65/instr.c b/src/ca65/instr.c index d0bb0ab14..b6fc51f01 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -43,6 +43,7 @@ #include "attrib.h" #include "bitops.h" #include "check.h" +#include "mmodel.h" /* ca65 */ #include "asserts.h" @@ -586,16 +587,21 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A) /* Simplify it if possible */ A->Expr = SimplifyExpr (A->Expr, &ED); + /* If we don't know how big the expression is, assume the default + * address size for data. + */ + if (ED.AddrSize == ADDR_SIZE_DEFAULT) { + ED.AddrSize = DataAddrSize; + } + /* Check the size */ switch (ED.AddrSize) { case ADDR_SIZE_ABS: - printf ("abs\n"); A->AddrModeSet &= ~AM_SET_ZP; break; case ADDR_SIZE_FAR: - printf ("far\n"); A->AddrModeSet &= ~(AM_SET_ZP | AM_SET_ABS); break; } diff --git a/src/ca65/segment.c b/src/ca65/segment.c index 27066844f..2f67c6ed0 100644 --- a/src/ca65/segment.c +++ b/src/ca65/segment.c @@ -355,6 +355,11 @@ void SegCheck (void) if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) || (F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) || (F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) { + printf ("Range error\n"); + printf ("F->Len = %u, ED.AddrSize = %s\n", + F->Len, AddrSizeToStr (ED.AddrSize)); + DumpExpr (F->V.Expr, SymResolve); + printf ("-------------------------------------------\n"); PError (&F->Pos, "Range error"); } } diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c index 6cc44fb3d..56821b90c 100644 --- a/src/ca65/studyexpr.c +++ b/src/ca65/studyexpr.c @@ -126,8 +126,47 @@ static void ED_Invalidate (ExprDesc* D) static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize) /* Update the address size of the expression */ { - if (ED->AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) { - ED->AddrSize = AddrSize; + if (ED_IsValid (ED)) { + /* ADDR_SIZE_DEFAULT may get overridden */ + if (ED->AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) { + ED->AddrSize = AddrSize; + } + } else { + /* ADDR_SIZE_DEFAULT takes precedence */ + if (ED->AddrSize != ADDR_SIZE_DEFAULT) { + if (AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) { + ED->AddrSize = AddrSize; + } + } + } +} + + + +static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right) +/* Merge the address sizes of two expressions into ED */ +{ + if (ED->AddrSize == ADDR_SIZE_DEFAULT) { + /* If ED is valid, ADDR_SIZE_DEFAULT gets always overridden, otherwise + * it takes precedence over anything else. + */ + if (ED_IsValid (ED)) { + ED->AddrSize = Right->AddrSize; + } + } else if (Right->AddrSize == ADDR_SIZE_DEFAULT) { + /* If Right is valid, ADDR_SIZE_DEFAULT gets always overridden, + * otherwise it takes precedence over anything else. + */ + if (!ED_IsValid (Right)) { + ED->AddrSize = Right->AddrSize; + } + } else { + /* Neither ED nor Right has a default address size, use the larger of + * the two. + */ + if (Right->AddrSize > ED->AddrSize) { + ED->AddrSize = Right->AddrSize; + } } } @@ -301,7 +340,7 @@ static void ED_Add (ExprDesc* ED, const ExprDesc* Right) { ED->Val += Right->Val; ED_MergeRefs (ED, Right); - ED_UpdateAddrSize (ED, Right->AddrSize); + ED_MergeAddrSize (ED, Right); } @@ -318,7 +357,7 @@ static void ED_Mul (ExprDesc* ED, const ExprDesc* Right) for (I = 0; I < ED->SecCount; ++I) { ED->SecRef[I].Count *= Right->Val; } - ED_UpdateAddrSize (ED, Right->AddrSize); + ED_MergeAddrSize (ED, Right); } @@ -398,7 +437,7 @@ static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D) /* Merge references and update address size */ ED_MergeRefs (D, &Right); - ED_UpdateAddrSize (D, Right.AddrSize); + ED_MergeAddrSize (D, &Right); } @@ -411,6 +450,7 @@ 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; } @@ -429,6 +469,7 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D) * a circular reference. */ if (SymHasExpr (Sym)) { + if (SymHasUserMark (Sym)) { if (Verbosity > 0) { DumpExpr (Expr, SymResolve); @@ -448,26 +489,52 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D) /* If the symbol has an explicit address size, use it. This may * lead to range errors later (maybe even in the linker stage), if - * the user lied about the address size, but for now we trust the - * user. + * the user lied about the address size, but for now we trust him. */ AddrSize = GetSymAddrSize (Sym); if (AddrSize != ADDR_SIZE_DEFAULT) { D->AddrSize = AddrSize; } } - } else { - /* The symbol is either undefined or an import. In both cases, track - * the symbols used and update the address size, but in case of an - * undefined symbol also set the "too complex" flag, since we cannot - * evaluate the final result. + + } else if (SymIsImport (Sym)) { + + /* The symbol is an import. Track the symbols used and update the + * address size. */ ED_SymRef* SymRef = ED_GetSymRef (D, Sym); ++SymRef->Count; ED_UpdateAddrSize (D, GetSymAddrSize (Sym)); - if (!SymIsImport (Sym)) { - /* Cannot handle */ - ED_Invalidate (D); + + } else { + + unsigned char AddrSize; + SymTable* Parent; + + /* The symbol is undefined. Track symbol usage but set the "too + * complex" flag, since we cannot evaluate the final result. + */ + ED_SymRef* SymRef = ED_GetSymRef (D, Sym); + ++SymRef->Count; + ED_Invalidate (D); + + /* Since the symbol may be a forward, and we may need a statement + * about the address size, check higher lexical levels for a symbol + * with the same name and use its address size if we find such a + * symbol which is defined. + */ + AddrSize = GetSymAddrSize (Sym); + Parent = GetSymParentScope (Sym); + if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) { + SymEntry* H = SymFindAny (Parent, GetSymName (Sym)); + if (H) { + AddrSize = GetSymAddrSize (H); + if (AddrSize != ADDR_SIZE_DEFAULT) { + D->AddrSize = AddrSize; + } + } + } else { + D->AddrSize = AddrSize; } } } @@ -528,7 +595,7 @@ static void StudyPlus (ExprNode* Expr, ExprDesc* D) /* Merge references and update address size */ ED_MergeRefs (D, &Right); - ED_UpdateAddrSize (D, Right.AddrSize); + ED_MergeAddrSize (D, &Right); } @@ -564,7 +631,7 @@ static void StudyMinus (ExprNode* Expr, ExprDesc* D) /* Merge references and update address size */ ED_MergeRefs (D, &Right); - ED_UpdateAddrSize (D, Right.AddrSize); + ED_MergeAddrSize (D, &Right); } @@ -612,7 +679,7 @@ static void StudyMul (ExprNode* Expr, ExprDesc* D) /* If we could not handle the op, merge references and update address size */ if (!ED_IsValid (D)) { ED_MergeRefs (D, &Right); - ED_UpdateAddrSize (D, Right.AddrSize); + ED_MergeAddrSize (D, &Right); } /* Done */ diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index 124ad7d9e..6163bf02a 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -485,6 +485,16 @@ int SymIsConst (SymEntry* S, long* Val) +SymTable* GetSymParentScope (SymEntry* S) +/* Get the parent scope of the symbol (not the one it is defined in). Return + * NULL if the symbol is a cheap local, or defined on global level. + */ +{ + return (S->SymTab && S->SymTab->Parent)? S->SymTab->Parent : 0; +} + + + struct ExprNode* GetSymExpr (SymEntry* S) /* Get the expression for a non-const symbol */ { diff --git a/src/ca65/symentry.h b/src/ca65/symentry.h index 2f5324ede..f72e3bf17 100644 --- a/src/ca65/symentry.h +++ b/src/ca65/symentry.h @@ -247,6 +247,11 @@ INLINE int SymHasUserMark (SymEntry* S) #else # define SymHasUserMark(S) (((S)->Flags & SF_USER) != 0) #endif + +struct SymTable* GetSymParentScope (SymEntry* S); +/* Get the parent scope of the symbol (not the one it is defined in). Return + * NULL if the symbol is a cheap local, or defined on global level. + */ struct ExprNode* GetSymExpr (SymEntry* Sym); /* Get the expression for a non-const symbol */