]> git.sur5r.net Git - cc65/blobdiff - src/ld65/segments.c
Removed unneeded include files.
[cc65] / src / ld65 / segments.c
index 84c80d0850fad49cb9382d92f27e72e47fa81195..1474ebe5550f4cba2b108598d110c7b226737575 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -37,6 +37,8 @@
 #include <string.h>
 
 /* common */
+#include "addrsize.h"
+#include "alignment.h"
 #include "check.h"
 #include "coll.h"
 #include "exprdefs.h"
@@ -92,18 +94,17 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize)
     /* Initialize the fields */
     S->Name        = Name;
     S->Next       = 0;
+    S->Flags       = SEG_FLAG_NONE;
     S->Sections    = EmptyCollection;
+    S->MemArea     = 0;
     S->PC         = 0;
     S->Size               = 0;
-    S->AlignObj           = 0;
     S->OutputName  = 0;
     S->OutputOffs  = 0;
-    S->Align       = 0;
+    S->Alignment   = 1;
     S->FillVal    = 0;
     S->AddrSize    = AddrSize;
     S->ReadOnly    = 0;
-    S->Relocatable = 0;
-    S->Placed      = 0;
     S->Dumped      = 0;
 
     /* Insert the segment into the segment list and assign the segment id */
@@ -154,12 +155,9 @@ Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName)
 
 
 
-Section* NewSection (Segment* Seg, unsigned char Align, unsigned char AddrSize)
+Section* NewSection (Segment* Seg, unsigned long Alignment, unsigned char AddrSize)
 /* Create a new section for the given segment */
 {
-    unsigned long V;
-
-
     /* Allocate memory */
     Section* S = xmalloc (sizeof (Section));
 
@@ -170,12 +168,11 @@ Section* NewSection (Segment* Seg, unsigned char Align, unsigned char AddrSize)
     S->FragRoot = 0;
     S->FragLast = 0;
     S->Size    = 0;
-    S->Align    = Align;
+    S->Alignment= Alignment;
     S->AddrSize = AddrSize;
 
     /* Calculate the alignment bytes needed for the section */
-    V = (0x01UL << S->Align) - 1;
-    S->Fill = (((Seg->Size + V) & ~V) - Seg->Size);
+    S->Fill = AlignCount (Seg->Size, S->Alignment);
 
     /* Adjust the segment size and set the section offset */
     Seg->Size  += S->Fill;
@@ -194,40 +191,57 @@ Section* ReadSection (FILE* F, ObjData* O)
 /* Read a section from a file */
 {
     unsigned      Name;
+    unsigned      Flags;
     unsigned      Size;
-    unsigned char Align;
+    unsigned long Alignment;
     unsigned char Type;
     unsigned      FragCount;
     Segment*      S;
     Section*      Sec;
 
     /* Read the segment data */
-    (void) Read32 (F);            /* File size of data */
+    (void) Read32 (F);          /* File size of data */
     Name      = MakeGlobalStringId (O, ReadVar (F));    /* Segment name */
-    Size      = Read32 (F);       /* Size of data */
-    Align     = Read8 (F);        /* Alignment */
-    Type      = Read8 (F);        /* Segment type */
-    FragCount = ReadVar (F);      /* Number of fragments */
+    Flags     = ReadVar (F);    /* Segment flags */
+    Size      = ReadVar (F);    /* Size of data */
+    Alignment = ReadVar (F);    /* Alignment */
+    Type      = Read8 (F);      /* Segment type */
+    FragCount = ReadVar (F);    /* Number of fragments */
 
 
     /* Print some data */
-    Print (stdout, 2, "Module `%s': Found segment `%s', size = %u, align = %u, type = %u\n",
-          GetObjFileName (O), GetString (Name), Size, Align, Type);
+    Print (stdout, 2,
+           "Module `%s': Found segment `%s', size = %u, alignment = %lu, type = %u\n",
+          GetObjFileName (O), GetString (Name), Size, Alignment, Type);
 
     /* Get the segment for this section */
     S = GetSegment (Name, Type, GetObjFileName (O));
+                                        
+    /* The only possible flag is currently SEG_FLAG_BANKREF, and it must be
+     * applied to the segment, not the section.
+     */
+    S->Flags |= Flags;
 
     /* Allocate the section we will return later */
-    Sec = NewSection (S, Align, Type);
+    Sec = NewSection (S, Alignment, Type);
 
     /* Remember the object file this section was from */
     Sec->Obj = O;
 
-    /* Set up the minimum segment alignment */
-    if (Sec->Align > S->Align) {
-       /* Section needs larger alignment, use this one */
-       S->Align    = Sec->Align;
-       S->AlignObj = O;
+    /* Set up the combined segment alignment */
+    if (Sec->Alignment > 1) {
+        Alignment = LeastCommonMultiple (S->Alignment, Sec->Alignment);
+        if (Alignment > MAX_ALIGNMENT) {
+            Error ("Combined alignment for segment `%s' is %lu which exceeds "
+                   "%lu. Last module requiring alignment was `%s'.",
+                   GetString (Name), Alignment, MAX_ALIGNMENT,
+                   GetObjFileName (O));
+        } else if (Alignment >= LARGE_ALIGNMENT) {
+            Warning ("Combined alignment for segment `%s' is suspiciously "
+                     "large (%lu). Last module requiring alignment was `%s'.",
+                     GetString (Name), Alignment, GetObjFileName (O));
+        }
+        S->Alignment = Alignment;
     }
 
     /* Start reading fragments from the file and insert them into the section . */
@@ -258,7 +272,7 @@ Section* ReadSection (FILE* F, ObjData* O)
 
            case FRAG_FILL:
                /* Will allocate memory, but we don't care... */
-               Frag = NewFragment (Type, ReadVar (F), Sec);
+               Frag = NewFragment (Type, ReadVar (F), Sec);
                break;
 
            default:
@@ -356,7 +370,7 @@ void SegDump (void)
                        printf ("    Literal (%u bytes):", F->Size);
                        Count = F->Size;
                        Data  = F->LitBuf;
-                       J = 100;
+                       J = 100;
                        while (Count--) {
                            if (J > 75) {
                                printf ("\n   ");
@@ -471,10 +485,6 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void*
        Frag = Sec->FragRoot;
        while (Frag) {
 
-            /* Do fragment alignment checks */
-
-
-
             /* Output fragment data */
            switch (Frag->Type) {
 
@@ -492,19 +502,19 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void*
                            break;
 
                        case SEG_EXPR_RANGE_ERROR:
-                           Error ("Range error in module `%s', line %lu",
+                           Error ("Range error in module `%s', line %u",
                                   GetFragmentSourceName (Frag),
                                   GetFragmentSourceLine (Frag));
                            break;
 
                        case SEG_EXPR_TOO_COMPLEX:
-                           Error ("Expression too complex in module `%s', line %lu",
+                           Error ("Expression too complex in module `%s', line %u",
                                   GetFragmentSourceName (Frag),
                                   GetFragmentSourceLine (Frag));
                            break;
 
-                       case SEG_EXPR_INVALID:
-                           Error ("Invalid expression in module `%s', line %lu",
+                       case SEG_EXPR_INVALID:
+                           Error ("Invalid expression in module `%s', line %u",
                                   GetFragmentSourceName (Frag),
                                   GetFragmentSourceLine (Frag));
                            break;
@@ -552,7 +562,7 @@ static int CmpSegStart (const void* K1, const void* K2)
 
     /* Compare the start addresses */
     if (S1->PC > S2->PC) {
-       return 1;
+       return 1;
     } else if (S1->PC < S2->PC) {
        return -1;
     } else {
@@ -580,8 +590,8 @@ void PrintSegmentMap (FILE* F)
     qsort (SegPool, CollCount (&SegmentList), sizeof (Segment*), CmpSegStart);
 
     /* Print a header */
-    fprintf (F, "Name                  Start   End     Size\n"
-               "--------------------------------------------\n");
+    fprintf (F, "Name                   Start     End    Size  Align\n"
+               "----------------------------------------------------\n");
 
     /* Print the segments */
     for (I = 0; I < CollCount (&SegmentList); ++I) {
@@ -597,8 +607,8 @@ void PrintSegmentMap (FILE* F)
                /* Point to last element addressed */
                --End;
            }
-           fprintf (F, "%-20s  %06lX  %06lX  %06lX\n",
-                            GetString (S->Name), S->PC, End, S->Size);
+           fprintf (F, "%-20s  %06lX  %06lX  %06lX  %05lX\n",
+                            GetString (S->Name), S->PC, End, S->Size, S->Alignment);
        }
     }