]> git.sur5r.net Git - cc65/commitdiff
Added a "fillval" attribute to the segment definition. When given, it
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 9 Sep 2012 19:00:43 +0000 (19:00 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 9 Sep 2012 19:00:43 +0000 (19:00 +0000)
overrides the value from the memory area for all space that lies within the
segment itself.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5823 b7a2c559-68d2-44c3-8de9-860c34a00d81

doc/ld65.sgml
src/ld65/bin.c
src/ld65/config.c
src/ld65/config.h
src/ld65/segments.c

index 457893ffc33a467ff9e8828827f118b0f76777b0..89b3f3d670377f384c3630ab791f4fb7f6162341 100644 (file)
@@ -728,8 +728,11 @@ into a memory area that is marked as readonly.
 Unused memory in a memory area may be filled. Use the "<tt/fill = yes/"
 attribute to request this. The default value to fill unused space is zero. If
 you don't like this, you may specify a byte value that is used to fill these
-areas with the "<tt/fillval/" attribute. This value is also used to fill unfilled
-areas generated by the assemblers <tt/.ALIGN/ and <tt/.RES/ directives.
+areas with the "<tt/fillval/" attribute. If there is no "<tt/fillval/"
+attribute for the segment, the "<tt/fillval/" attribute of the memory area (or
+its default) is used instead. This means that the value may also be used to
+fill unfilled areas generated by the assemblers <tt/.ALIGN/ and <tt/.RES/
+directives.
 
 The symbol <tt/%S/ may be used to access the default start address (that is,
 the one defined in the <ref id="FEATURES" name="FEATURES"> section, or the
@@ -804,6 +807,13 @@ segment in the load memory area, in case different load and run areas have
 been specified. There are no special attributes to set start or offset for
 just the load memory area.
 
+A "<tt/fillval/" attribute may not only be specified for a memory area, but
+also for a segment. The value must be an integer between 0 and 255. It is used
+as fill value for space reserved by the assemblers <tt/.ALIGN/ and <tt/.RES/
+commands. It is also used as fill value for space between sections (part of a
+segment that comes from one object file) caused by alignment, but not for
+space that preceeds the first section.
+
 To suppress the warning, the linker issues if it encounters a segment that is
 not found in any of the input files, use "<tt/optional=yes/" as additional
 segment attribute. Be careful when using this attribute, because a missing
index 17cb8d56f72313654feef76fbe95fc1b34f4ca5b..1a2ef4e82082b270507a29e9a43616c7d2483b6d 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1999-2011, Ullrich von Bassewitz                                      */
+/* (C) 1999-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -142,7 +142,7 @@ static void BinWriteMem (BinDesc* D, MemoryArea* M)
     /* Debugging: Check that the file offset is correct */
     if (ftell (D->F) != (long)M->FileOffs) {
         Internal ("Invalid file offset for memory area %s: %ld/%lu",
-                  GetString (M->Name), ftell (D->F), M->FileOffs);            
+                  GetString (M->Name), ftell (D->F), M->FileOffs);
     }
 
     /* Walk over all segments in this memory area */
@@ -231,11 +231,10 @@ static void BinWriteMem (BinDesc* D, MemoryArea* M)
         */
                if (DoWrite) {
             unsigned long P = ftell (D->F);
-            S->Seg->FillVal = M->FillVal;
            SegWrite (D->Filename, D->F, S->Seg, BinWriteExpr, D);
             PrintNumVal ("Wrote", (unsigned long) (ftell (D->F) - P));
-       } else if (M->Flags & MF_FILL) {
-           WriteMult (D->F, M->FillVal, S->Seg->Size);
+               } else if (M->Flags & MF_FILL) {
+           WriteMult (D->F, S->Seg->FillVal, S->Seg->Size);
             PrintNumVal ("Filled", (unsigned long) S->Seg->Size);
        }
 
index bb2691407d339c4ca6b35d00aff0e9e5fd4f95b2..12d8753219f656b0e701a0f23b656194f9d1e049 100644 (file)
@@ -118,6 +118,7 @@ static Collection       SegDescList = STATIC_COLLECTION_INITIALIZER;
 #define SA_OFFSET      0x0040
 #define SA_START       0x0080
 #define SA_OPTIONAL     0x0100
+#define SA_FILLVAL      0x0200
 
 /* Symbol types used in the CfgSymbol structure */
 typedef enum {
@@ -353,6 +354,7 @@ static SegDesc* NewSegDesc (unsigned Name)
     S->Seg           = 0;
     S->Attr          = 0;
     S->Flags         = 0;
+    S->FillVal       = 0;
     S->RunAlignment  = 1;
     S->LoadAlignment = 1;
 
@@ -637,6 +639,7 @@ static void ParseSegments (void)
         {   "ALIGN",            CFGTOK_ALIGN            },
         {   "ALIGN_LOAD",       CFGTOK_ALIGN_LOAD       },
         {   "DEFINE",           CFGTOK_DEFINE           },
+        {   "FILLVAL",          CFGTOK_FILLVAL          },
                {   "LOAD",             CFGTOK_LOAD             },
        {   "OFFSET",           CFGTOK_OFFSET           },
         {   "OPTIONAL",         CFGTOK_OPTIONAL         },
@@ -706,6 +709,12 @@ static void ParseSegments (void)
                     CfgNextTok ();
                    break;
 
+                case CFGTOK_FILLVAL:
+                   FlagAttr (&S->Attr, SA_FILLVAL, "FILLVAL");
+                   S->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF);
+                    S->Flags |= SF_FILLVAL;
+                   break;
+
                case CFGTOK_LOAD:
                    FlagAttr (&S->Attr, SA_LOAD, "LOAD");
                    S->Load = CfgGetMemory (GetStrBufId (&CfgSVal));
@@ -1561,22 +1570,22 @@ static void ProcessSegments (void)
     while (I < CollCount (&SegDescList)) {
 
         /* Get the next segment descriptor */
-       SegDesc* S = CollAtUnchecked (&SegDescList, I);
+       SegDesc* S = CollAtUnchecked (&SegDescList, I);
 
         /* Search for the actual segment in the input files. The function may
          * return NULL (no such segment), this is checked later.
          */
         S->Seg = SegFind (S->Name);
 
-       /* If the segment is marked as BSS style, and if the segment exists
+       /* If the segment is marked as BSS style, and if the segment exists
          * in any of the object file, check that there's no initialized data
          * in the segment.
-        */
-       if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) {
+        */
+       if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) {
                    CfgWarning (GetSourcePos (S->LI),
                         "Segment `%s' with type `bss' contains initialized data",
-                       GetString (S->Name));
-       }
+                       GetString (S->Name));
+       }
 
        /* If this segment does exist in any of the object files, insert the
                 * segment into the load/run memory areas. Otherwise print a warning
@@ -1592,6 +1601,9 @@ static void ProcessSegments (void)
                MemoryInsert (S->Load, S);
            }
 
+            /* Use the fill value from the config */
+            S->Seg->FillVal = S->FillVal;
+
             /* Process the next segment descriptor in the next run */
             ++I;
 
@@ -1894,6 +1906,13 @@ unsigned CfgProcess (void)
 
             }
 
+            /* If this is the load memory area and the segment doesn't have a
+             * fill value defined, use the one from the memory area.
+             */
+            if (S->Load == M && (S->Flags & SF_FILLVAL) == 0) {
+                S->Seg->FillVal = M->FillVal;
+            }
+
            /* Increment the fill level of the memory area and check for an
             * overflow.
             */
index 6dc4a7b6b9f1d2533f3221a9c8373063adda4283..da3a6478d43733080f362589320fea796cbf3ffa 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                                                */
@@ -75,6 +75,7 @@ struct SegDesc {
     Segment*                   Seg;            /* Pointer to segment structure */
     unsigned                   Attr;           /* Attributes for segment */
     unsigned                   Flags;          /* Set of bitmapped flags */
+    unsigned char       FillVal;        /* Fill value for this segment */
     struct MemoryArea*  Load;           /* Load memory section */
     struct MemoryArea*  Run;            /* Run memory section */
     unsigned long              Addr;           /* Start address or offset into segment */
@@ -94,6 +95,7 @@ struct SegDesc {
 #define SF_OPTIONAL     0x0100          /* Segment is optional (must not exist) */
 #define SF_RUN_DEF             0x0200          /* RUN symbols already defined */
 #define SF_LOAD_DEF    0x0400          /* LOAD symbols already defined */
+#define SF_FILLVAL      0x0800          /* Segment has separate fill value */
 
 
 
index 156fd8100a877fac12d44e032d98327f23b8f12f..fe6c78dd74c1e7b8224d27c6887c9b73827b42b6 100644 (file)
@@ -464,16 +464,22 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void*
 
     /* Loop over all sections in this segment */
     for (I = 0; I < CollCount (&S->Sections); ++I) {
-        Section* Sec = CollAtUnchecked (&S->Sections, I);
-       Fragment* Frag;
+
+        Section*        Sec = CollAtUnchecked (&S->Sections, I);
+       Fragment*       Frag;
+        unsigned char   FillVal;
 
         /* Output were this section is from */
         Print (stdout, 2, "      Section from \"%s\"\n", GetObjFileName (Sec->Obj));
 
-       /* If we have fill bytes, write them now */
+       /* If we have fill bytes, write them now. Beware: If this is the
+         * first section, the fill value is not considered part of the segment
+         * and therefore taken from the memory area.
+         */
+        FillVal = (I == 0)? S->MemArea->FillVal : S->FillVal;
                Print (stdout, 2, "        Filling 0x%lx bytes with 0x%02x\n",
-               Sec->Fill, S->FillVal);
-       WriteMult (Tgt, S->FillVal, Sec->Fill);
+               Sec->Fill, FillVal);
+       WriteMult (Tgt, FillVal, Sec->Fill);
        Offs += Sec->Fill;
 
        /* Loop over all fragments in this section */