]> git.sur5r.net Git - cc65/blobdiff - src/ca65/segment.c
If a debug symbol is an import, write out the import id.
[cc65] / src / ca65 / segment.c
index a089a5d88b1611a67d42cb9e09d97b346bb5780f..a0a7b96623b79caae09f74baa8c128fd1cab939c 100644 (file)
@@ -328,6 +328,13 @@ unsigned char GetSegAddrSize (unsigned SegNum)
 void SegCheck (void)
 /* Check the segments for range and other errors */
 {
+    static const unsigned long U_Hi[4] = {
+               0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
+    };
+    static const long S_Hi[4] = {
+               0x0000007FL, 0x00007FFFL, 0x007FFFFFL, 0x7FFFFFFFL
+    };
+
     unsigned I;
     for (I = 0; I < CollCount (&SegmentList); ++I) {
         Segment* S = CollAtUnchecked (&SegmentList, I);
@@ -346,44 +353,33 @@ void SegCheck (void)
                 /* Check if the expression is constant */
                 if (ED_IsConst (&ED)) {
 
+                   unsigned J;
+
                            /* The expression is constant. Check for range errors. */
-                   int Abs = (F->Type != FRAG_SEXPR);
-                    long Val = ED.Val;
-                   unsigned I;
-
-                   if (F->Len == 1) {
-                       if (Abs) {
-                           /* Absolute value */
-                           if (Val > 255) {
-                               LIError (&F->LI, "Range error (%ld not in [0..255])", Val);
-                           }
-                       } else {
-                           /* PC relative value */
-                           if (Val < -128 || Val > 127) {
-                               LIError (&F->LI, "Range error (%ld not in [-128..127])", Val);
-                           }
-                       }
-                   } else if (F->Len == 2) {
-                       if (Abs) {
-                           /* Absolute value */
-                           if (Val > 65535) {
-                               LIError (&F->LI, "Range error (%ld not in [0..65535])", Val);
-                           }
-                       } else {
-                           /* PC relative value */
-                           if (Val < -32768 || Val > 32767) {
-                               LIError (&F->LI, "Range error (%ld not in [-32768..32767])", Val);
-                           }
-                       }
-                   }
+                    CHECK (F->Len <= 4);
+                    if (F->Type == FRAG_SEXPR) {
+                        long Hi = S_Hi[F->Len-1];
+                        long Lo = ~Hi;
+                        if (ED.Val > Hi || ED.Val < Lo) {
+                            LIError (&F->LI,
+                                     "Range error (%ld not in [%ld..%ld])",
+                                     ED.Val, Lo, Hi);
+                        }
+                    } else {
+                        if (((unsigned long)ED.Val) > U_Hi[F->Len-1]) {
+                            LIError (&F->LI,
+                                     "Range error (%lu not in [0..%lu])",
+                                     (unsigned long)ED.Val, U_Hi[F->Len-1]);
+                        }
+                    }
 
                     /* We don't need the expression tree any longer */
                     FreeExpr (F->V.Expr);
 
                    /* Convert the fragment into a literal fragment */
-                   for (I = 0; I < F->Len; ++I) {
-                       F->V.Data [I] = Val & 0xFF;
-                       Val >>= 8;
+                   for (J = 0; J < F->Len; ++J) {
+                       F->V.Data[J] = ED.Val & 0xFF;
+                       ED.Val >>= 8;
                    }
                    F->Type = FRAG_LITERAL;
 
@@ -392,13 +388,13 @@ void SegCheck (void)
                    /* We cannot evaluate the expression now, leave the job for
                     * the linker. However, we can check if the address size
                      * matches the fragment size, and we will do so.
-                    */
+                    */
                     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)) {
                        LIError (&F->LI, "Range error");
                    }
-               }
+               }
 
                 /* Release memory allocated for the expression decriptor */
                 ED_Done (&ED);
@@ -457,6 +453,50 @@ void SegDump (void)
 
 
 
+void InitSegments (void)
+/* Initialize segments */
+{
+    /* Create the predefined segments. Code segment is active */
+    ActiveSeg = NewSegFromDef (&CodeSegDef);
+    NewSegFromDef (&RODataSegDef);
+    NewSegFromDef (&BssSegDef);
+    NewSegFromDef (&DataSegDef);
+    NewSegFromDef (&ZeropageSegDef);
+    NewSegFromDef (&NullSegDef);
+}
+
+
+
+void SetSegmentSizes (void)
+/* Set the default segment sizes according to the memory model */
+{
+    /* Initialize segment sizes. The segment definitions do already contain
+     * the correct values for the default case (near), so we must only change
+     * things that should be different.
+     */
+    switch (MemoryModel) {
+
+        case MMODEL_NEAR:
+            break;
+
+        case MMODEL_FAR:
+            CodeSegDef.AddrSize = ADDR_SIZE_FAR;
+            break;
+
+        case MMODEL_HUGE:
+            CodeSegDef.AddrSize   = ADDR_SIZE_FAR;
+            DataSegDef.AddrSize   = ADDR_SIZE_FAR;
+            BssSegDef.AddrSize    = ADDR_SIZE_FAR;
+            RODataSegDef.AddrSize = ADDR_SIZE_FAR;
+            break;
+
+        default:
+            Internal ("Invalid memory model: %d", MemoryModel);
+    }
+}
+
+
+
 static void WriteOneSeg (Segment* Seg)
 /* Write one segment to the object file */
 {
@@ -541,50 +581,6 @@ static void WriteOneSeg (Segment* Seg)
 
 
 
-void InitSegments (void)
-/* Initialize segments */
-{
-    /* Create the predefined segments. Code segment is active */
-    ActiveSeg = NewSegFromDef (&CodeSegDef);
-    NewSegFromDef (&RODataSegDef);
-    NewSegFromDef (&BssSegDef);
-    NewSegFromDef (&DataSegDef);
-    NewSegFromDef (&ZeropageSegDef);
-    NewSegFromDef (&NullSegDef);
-}
-
-
-
-void SetSegmentSizes (void)
-/* Set the default segment sizes according to the memory model */
-{
-    /* Initialize segment sizes. The segment definitions do already contain
-     * the correct values for the default case (near), so we must only change
-     * things that should be different.
-     */
-    switch (MemoryModel) {
-
-        case MMODEL_NEAR:
-            break;
-
-        case MMODEL_FAR:
-            CodeSegDef.AddrSize = ADDR_SIZE_FAR;
-            break;
-
-        case MMODEL_HUGE:
-            CodeSegDef.AddrSize   = ADDR_SIZE_FAR;
-            DataSegDef.AddrSize   = ADDR_SIZE_FAR;
-            BssSegDef.AddrSize    = ADDR_SIZE_FAR;
-            RODataSegDef.AddrSize = ADDR_SIZE_FAR;
-            break;
-
-        default:
-            Internal ("Invalid memory model: %d", MemoryModel);
-    }
-}
-
-
-
 void WriteSegments (void)
 /* Write the segment data to the object file */
 {