]> git.sur5r.net Git - cc65/commitdiff
Fixed several address size issues
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 12 Dec 2003 15:40:08 +0000 (15:40 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 12 Dec 2003 15:40:08 +0000 (15:40 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2729 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/instr.c
src/ca65/segment.c
src/ca65/studyexpr.c
src/ca65/symentry.c
src/ca65/symentry.h

index d0bb0ab14f3460e14070e82eb26262e577db25f4..b6fc51f01df4459c333ff050b76743ad159e1336 100644 (file)
@@ -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;
         }
index 27066844f529e0d37b100eb2d2a105d393f38f0a..2f67c6ed04a8555abb2d1789044047a8ff31ea09 100644 (file)
@@ -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");
                    }
                }
index 6cc44fb3d1c5eb184cceb6f04164a250277401ad..56821b90cd3fd10a47cdd68325f7f632c0141855 100644 (file)
@@ -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 */
index 124ad7d9ef2721adcd1b92c38f00bdd0159594a2..6163bf02a59e9cd64f557660bb33cbb8ee0bcda1 100644 (file)
@@ -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 */
 {
index 2f5324edecc61e9004590f68024c6ad621fb0ce2..f72e3bf17e5200e0c52b34f2f322ec2280990d33 100644 (file)
@@ -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 */