New segment attribute ALIGN_LOAD. Some cleanup.

git-svn-id: svn://svn.cc65.org/cc65/trunk@3353 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz
2005-01-08 13:44:11 +00:00
parent 1875825e78
commit 7774e57eae
4 changed files with 167 additions and 133 deletions

View File

@@ -6,9 +6,9 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1999-2001 Ullrich von Bassewitz */ /* (C) 1999-2005 Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* R<EFBFBD>merstrasse 52 */
/* D-70597 Stuttgart */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
@@ -161,18 +161,23 @@ static void BinWriteMem (BinDesc* D, Memory* M)
GetString (S->Name), GetObjFileName (S->Seg->AlignObj)); GetString (S->Name), GetObjFileName (S->Seg->AlignObj));
} }
/* If this is the run memory area, we must apply run alignment. If
* this is not the run memory area but the load memory area (which
* means that both are different), we must apply load alignment.
* Beware: DoWrite may be true even if this is the run memory area,
* because it may be also the load memory area.
*/
if (S->Run == M) {
/* Handle ALIGN and OFFSET/START */ /* Handle ALIGN and OFFSET/START */
if (S->Flags & SF_ALIGN) { if (S->Flags & SF_ALIGN) {
/* Align the address */ /* Align the address */
unsigned long Val, NewAddr; unsigned long Val = (0x01UL << S->Align) - 1;
Val = (0x01UL << S->Align) - 1; unsigned long NewAddr = (Addr + Val) & ~Val;
NewAddr = (Addr + Val) & ~Val;
if (DoWrite) { if (DoWrite) {
WriteMult (D->F, M->FillVal, NewAddr-Addr); WriteMult (D->F, M->FillVal, NewAddr-Addr);
} }
Addr = NewAddr; Addr = NewAddr;
/* Remember the fill value for the segment */
S->Seg->FillVal = M->FillVal;
} else if (S->Flags & (SF_OFFSET | SF_START)) { } else if (S->Flags & (SF_OFFSET | SF_START)) {
unsigned long NewAddr = S->Addr; unsigned long NewAddr = S->Addr;
if (S->Flags & SF_OFFSET) { if (S->Flags & SF_OFFSET) {
@@ -185,11 +190,27 @@ static void BinWriteMem (BinDesc* D, Memory* M)
Addr = NewAddr; Addr = NewAddr;
} }
} else if (S->Load == M) {
/* Handle ALIGN_LOAD */
if (S->Flags & SF_ALIGN_LOAD) {
/* Align the address */
unsigned long Val = (0x01UL << S->AlignLoad) - 1;
unsigned long NewAddr = (Addr + Val) & ~Val;
if (DoWrite) {
WriteMult (D->F, M->FillVal, NewAddr-Addr);
}
Addr = NewAddr;
}
}
/* Now write the segment to disk if it is not a BSS type segment and /* Now write the segment to disk if it is not a BSS type segment and
* if the memory area is the load area. * if the memory area is the load area.
*/ */
if (DoWrite) { if (DoWrite) {
RelocLineInfo (S->Seg); RelocLineInfo (S->Seg);
S->Seg->FillVal = M->FillVal;
SegWrite (D->F, S->Seg, BinWriteExpr, D); SegWrite (D->F, S->Seg, BinWriteExpr, D);
} else if (M->Flags & MF_FILL) { } else if (M->Flags & MF_FILL) {
WriteMult (D->F, M->FillVal, S->Seg->Size); WriteMult (D->F, M->FillVal, S->Seg->Size);
@@ -208,11 +229,9 @@ static void BinWriteMem (BinDesc* D, Memory* M)
} }
/* If a fill was requested, fill the remaining space */ /* If a fill was requested, fill the remaining space */
if (M->Flags & MF_FILL) { if ((M->Flags & MF_FILL) != 0 && M->FillLevel < M->Size) {
while (M->FillLevel < M->Size) { WriteMult (D->F, M->FillVal, M->Size - M->FillLevel);
Write8 (D->F, M->FillVal); M->FillLevel = M->Size;
++M->FillLevel;
}
} }
} }

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2004 Ullrich von Bassewitz */ /* (C) 1998-2005 Ullrich von Bassewitz */
/* R<>merstrasse 52 */ /* R<>merstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -96,10 +96,11 @@ unsigned SegDescCount; /* Number of entries in list */
#define SA_LOAD 0x0002 #define SA_LOAD 0x0002
#define SA_RUN 0x0004 #define SA_RUN 0x0004
#define SA_ALIGN 0x0008 #define SA_ALIGN 0x0008
#define SA_DEFINE 0x0010 #define SA_ALIGN_LOAD 0x0010
#define SA_OFFSET 0x0020 #define SA_DEFINE 0x0020
#define SA_START 0x0040 #define SA_OFFSET 0x0040
#define SA_OPTIONAL 0x0080 #define SA_START 0x0080
#define SA_OPTIONAL 0x0100
@@ -599,6 +600,7 @@ static void ParseSegments (void)
{ {
static const IdentTok Attributes [] = { static const IdentTok Attributes [] = {
{ "ALIGN", CFGTOK_ALIGN }, { "ALIGN", CFGTOK_ALIGN },
{ "ALIGN_LOAD", CFGTOK_ALIGN_LOAD },
{ "DEFINE", CFGTOK_DEFINE }, { "DEFINE", CFGTOK_DEFINE },
{ "LOAD", CFGTOK_LOAD }, { "LOAD", CFGTOK_LOAD },
{ "OFFSET", CFGTOK_OFFSET }, { "OFFSET", CFGTOK_OFFSET },
@@ -612,7 +614,6 @@ static void ParseSegments (void)
{ "RW", CFGTOK_RW }, { "RW", CFGTOK_RW },
{ "BSS", CFGTOK_BSS }, { "BSS", CFGTOK_BSS },
{ "ZP", CFGTOK_ZP }, { "ZP", CFGTOK_ZP },
{ "WPROT", CFGTOK_RO }, /* ### OBSOLETE */
}; };
unsigned Count; unsigned Count;
@@ -654,6 +655,17 @@ static void ParseSegments (void)
S->Flags |= SF_ALIGN; S->Flags |= SF_ALIGN;
break; break;
case CFGTOK_ALIGN_LOAD:
CfgAssureInt ();
FlagAttr (&S->Attr, SA_ALIGN_LOAD, "ALIGN_LOAD");
CfgRangeCheck (1, 0x10000);
S->AlignLoad = BitFind (CfgIVal);
if ((0x01UL << S->AlignLoad) != CfgIVal) {
CfgError ("Alignment must be a power of 2");
}
S->Flags |= SF_ALIGN_LOAD;
break;
case CFGTOK_DEFINE: case CFGTOK_DEFINE:
FlagAttr (&S->Attr, SA_DEFINE, "DEFINE"); FlagAttr (&S->Attr, SA_DEFINE, "DEFINE");
/* Map the token to a boolean */ /* Map the token to a boolean */
@@ -726,13 +738,6 @@ static void ParseSegments (void)
if ((S->Attr & SA_RUN) == 0) { if ((S->Attr & SA_RUN) == 0) {
S->Attr |= SA_RUN; S->Attr |= SA_RUN;
S->Run = S->Load; S->Run = S->Load;
} else {
/* Both attributes given */
S->Flags |= SF_LOAD_AND_RUN;
}
if ((S->Attr & SA_ALIGN) == 0) {
S->Attr |= SA_ALIGN;
S->Align = 0;
} }
/* 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
@@ -744,10 +749,21 @@ static void ParseSegments (void)
CfgGetName (), CfgErrorLine); CfgGetName (), CfgErrorLine);
} }
/* An attribute of ALIGN_LOAD doesn't make sense if there are no
* separate run and load memory areas.
*/
if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) {
Warning ("%s(%u): ALIGN_LOAD attribute specified, but no separate "
"LOAD and RUN memory areas assigned",
CfgGetName (), CfgErrorLine);
/* Remove the flag */
S->Flags &= ~SF_ALIGN_LOAD;
}
/* If the segment is marked as BSS style, it may not have separate /* If the segment is marked as BSS style, it may not have separate
* load and run memory areas, because it's is never written to disk. * load and run memory areas, because it's is never written to disk.
*/ */
if ((S->Flags & SF_BSS) != 0 && (S->Flags & SF_LOAD_AND_RUN) != 0) { if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) {
Warning ("%s(%u): Segment with type `bss' has both LOAD and RUN " Warning ("%s(%u): Segment with type `bss' has both LOAD and RUN "
"memory areas assigned", CfgGetName (), CfgErrorLine); "memory areas assigned", CfgGetName (), CfgErrorLine);
} }
@@ -778,8 +794,8 @@ static void ParseSegments (void)
SegDescInsert (S); SegDescInsert (S);
/* Insert the segment into the memory area list */ /* Insert the segment into the memory area list */
MemoryInsert (S->Run, S); MemoryInsert (S->Run, S);
if ((S->Flags & SF_LOAD_AND_RUN) != 0) { if (S->Load != S->Run) {
/* We have a separate RUN area given */ /* We have separate RUN and LOAD areas */
MemoryInsert (S->Load, S); MemoryInsert (S->Load, S);
} }
} else { } else {
@@ -1448,7 +1464,14 @@ void CfgAssignSegments (void)
/* Get the segment from the node */ /* Get the segment from the node */
SegDesc* S = N->Seg; SegDesc* S = N->Seg;
/* Handle ALIGN and OFFSET/START */ /* Some actions depend on wether this is the load or run memory
* area.
*/
if (S->Run == M) {
/* This is the run (and maybe load) memory area. Handle
* alignment and explict start address and offset.
*/
if (S->Flags & SF_ALIGN) { if (S->Flags & SF_ALIGN) {
/* Align the address */ /* Align the address */
unsigned long Val = (0x01UL << S->Align) - 1; unsigned long Val = (0x01UL << S->Align) - 1;
@@ -1473,14 +1496,25 @@ void CfgAssignSegments (void)
Addr = NewAddr; Addr = NewAddr;
} }
/* If this is the run area, set the start address of this segment, /* Set the start address of this segment, set the readonly flag
* set the readonly flag in the segment and and remember if the * in the segment and and remember if the segment is in a
* segment is in a relocatable file or not. * relocatable file or not.
*/ */
if (S->Run == M) {
S->Seg->PC = Addr; S->Seg->PC = Addr;
S->Seg->ReadOnly = (S->Flags & SF_RO) != 0; S->Seg->ReadOnly = (S->Flags & SF_RO) != 0;
S->Seg->Relocatable = M->Relocatable; S->Seg->Relocatable = M->Relocatable;
} else if (S->Load == M) {
/* This is the load memory area, *and* run and load are
* different (because of the "else" above). Handle alignment.
*/
if (S->Flags & SF_ALIGN_LOAD) {
/* Align the address */
unsigned long Val = (0x01UL << S->AlignLoad) - 1;
Addr = (Addr + Val) & ~Val;
}
} }
/* Increment the fill level of the memory area and check for an /* Increment the fill level of the memory area and check for an
@@ -1497,34 +1531,13 @@ void CfgAssignSegments (void)
* segment. * segment.
*/ */
if (S->Flags & SF_DEFINE) { if (S->Flags & SF_DEFINE) {
if ((S->Flags & SF_LOAD_AND_RUN) && S->Run == S->Load) { if (S->Run == M && (S->Flags & SF_RUN_DEF) == 0) {
/* RUN and LOAD given and in one memory area.
* Be careful: We will encounter this code twice, the
* first time when walking the RUN list, second time when
* walking the LOAD list. Be sure to define only the
* relevant symbols on each walk.
*/
if (S->Load == M) {
if ((S->Flags & SF_LOAD_DEF) == 0) {
CreateLoadDefines (S, Addr);
} else {
CHECK ((S->Flags & SF_RUN_DEF) == 0);
CreateRunDefines (S, Addr); CreateRunDefines (S, Addr);
} }
} if (S->Load == M && (S->Flags & SF_LOAD_DEF) == 0) {
} else {
/* RUN and LOAD in different memory areas, or RUN not
* given, so RUN defaults to LOAD. In the latter case, we
* have only one copy of the segment in the area.
*/
if (S->Run == M) {
CreateRunDefines (S, Addr);
}
if (S->Load == M) {
CreateLoadDefines (S, Addr); CreateLoadDefines (S, Addr);
} }
} }
}
/* Calculate the new address */ /* Calculate the new address */
Addr += S->Seg->Size; Addr += S->Seg->Size;

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2003 Ullrich von Bassewitz */ /* (C) 1998-2005 Ullrich von Bassewitz */
/* R<>merstrasse 52 */ /* R<>merstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -96,7 +96,8 @@ struct SegDesc {
Memory* Load; /* Load memory section */ Memory* Load; /* Load memory section */
Memory* Run; /* Run memory section */ Memory* Run; /* Run memory section */
unsigned long Addr; /* Start address or offset into segment */ unsigned long Addr; /* Start address or offset into segment */
unsigned char Align; /* Alignment if given */ unsigned char Align; /* Run area alignment if given */
unsigned char AlignLoad; /* Load area alignment if given */
}; };
/* Segment list */ /* Segment list */
@@ -113,13 +114,13 @@ extern unsigned SegDescCount; /* Number of entries in list */
#define SF_BSS 0x0002 /* Segment is BSS style segment */ #define SF_BSS 0x0002 /* Segment is BSS style segment */
#define SF_ZP 0x0004 /* Zeropage segment (o65 only) */ #define SF_ZP 0x0004 /* Zeropage segment (o65 only) */
#define SF_DEFINE 0x0008 /* Define start and size */ #define SF_DEFINE 0x0008 /* Define start and size */
#define SF_ALIGN 0x0010 /* Align the segment */ #define SF_ALIGN 0x0010 /* Align segment in run area */
#define SF_OFFSET 0x0020 /* Segment has offset in memory */ #define SF_ALIGN_LOAD 0x0020 /* Align segment in load area */
#define SF_START 0x0040 /* Segment has fixed start address */ #define SF_OFFSET 0x0040 /* Segment has offset in memory */
#define SF_OPTIONAL 0x0080 /* Segment is optional (must not exist) */ #define SF_START 0x0080 /* Segment has fixed start address */
#define SF_LOAD_AND_RUN 0x1000 /* LOAD and RUN given */ #define SF_OPTIONAL 0x0100 /* Segment is optional (must not exist) */
#define SF_RUN_DEF 0x2000 /* RUN symbols already defined */ #define SF_RUN_DEF 0x0200 /* RUN symbols already defined */
#define SF_LOAD_DEF 0x4000 /* LOAD symbols already defined */ #define SF_LOAD_DEF 0x0400 /* LOAD symbols already defined */

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2004 Ullrich von Bassewitz */ /* (C) 1998-2005 Ullrich von Bassewitz */
/* R<>merstrasse 52 */ /* R<>merstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -84,6 +84,7 @@ typedef enum {
CFGTOK_LOAD, CFGTOK_LOAD,
CFGTOK_RUN, CFGTOK_RUN,
CFGTOK_ALIGN, CFGTOK_ALIGN,
CFGTOK_ALIGN_LOAD,
CFGTOK_OFFSET, CFGTOK_OFFSET,
CFGTOK_OPTIONAL, CFGTOK_OPTIONAL,