From 574c8fa27300483b0c2f3623d8203f0d5ef95f1e Mon Sep 17 00:00:00 2001 From: uz Date: Sun, 9 Sep 2012 19:00:43 +0000 Subject: [PATCH] Added a "fillval" attribute to the segment definition. When given, it 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 | 14 ++++++++++++-- src/ld65/bin.c | 9 ++++----- src/ld65/config.c | 31 +++++++++++++++++++++++++------ src/ld65/config.h | 4 +++- src/ld65/segments.c | 16 +++++++++++----- 5 files changed, 55 insertions(+), 19 deletions(-) diff --git a/doc/ld65.sgml b/doc/ld65.sgml index 457893ffc..89b3f3d67 100644 --- a/doc/ld65.sgml +++ b/doc/ld65.sgml @@ -728,8 +728,11 @@ into a memory area that is marked as readonly. Unused memory in a memory area may be filled. Use the " 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 "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); } diff --git a/src/ld65/config.c b/src/ld65/config.c index bb2691407..12d875321 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -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. */ diff --git a/src/ld65/config.h b/src/ld65/config.h index 6dc4a7b6b..da3a6478d 100644 --- a/src/ld65/config.h +++ b/src/ld65/config.h @@ -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 */ diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 156fd8100..fe6c78dd7 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -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 */