mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 04:30:10 +00:00
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
This commit is contained in:
parent
1c77d3a6f0
commit
574c8fa273
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user