X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fconfig.c;h=4aaa7d99dcc71d022e84bf18f08756615f164abe;hb=77bd3169f6df69b8f62ca52008fb4a999b5b035e;hp=9a05bdd798d0abbb4bb9bb8d0dab14b8e34b2111;hpb=e935c8fead24e26c55ff0306437efad194c99398;p=cc65 diff --git a/src/ld65/config.c b/src/ld65/config.c index 9a05bdd79..4aaa7d99d 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -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 */ @@ -47,6 +47,7 @@ #include "bitops.h" #include "check.h" #include "print.h" +#include "segdefs.h" #include "xmalloc.h" #include "xsprintf.h" @@ -102,6 +103,7 @@ static Collection MemoryAreas = STATIC_COLLECTION_INITIALIZER; #define MA_DEFINE 0x0010 #define MA_FILL 0x0020 #define MA_FILLVAL 0x0040 +#define MA_BANK 0x0080 /* Segment list */ static Collection SegDescList = STATIC_COLLECTION_INITIALIZER; @@ -116,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 { @@ -351,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; @@ -405,13 +409,14 @@ static void ParseMemory (void) /* Parse a MEMORY section */ { static const IdentTok Attributes [] = { - { "START", CFGTOK_START }, - { "SIZE", CFGTOK_SIZE }, - { "TYPE", CFGTOK_TYPE }, - { "FILE", CFGTOK_FILE }, + { "BANK", CFGTOK_BANK }, { "DEFINE", CFGTOK_DEFINE }, + { "FILE", CFGTOK_FILE }, { "FILL", CFGTOK_FILL }, { "FILLVAL", CFGTOK_FILLVAL }, + { "SIZE", CFGTOK_SIZE }, + { "START", CFGTOK_START }, + { "TYPE", CFGTOK_TYPE }, }; static const IdentTok Types [] = { { "RO", CFGTOK_RO }, @@ -442,21 +447,17 @@ static void ParseMemory (void) /* Check which attribute was given */ switch (AttrTok) { - case CFGTOK_START: - FlagAttr (&M->Attr, MA_START, "START"); - M->StartExpr = CfgExpr (); - break; - - case CFGTOK_SIZE: - FlagAttr (&M->Attr, MA_SIZE, "SIZE"); - M->SizeExpr = CfgExpr (); + case CFGTOK_BANK: + FlagAttr (&M->Attr, MA_BANK, "BANK"); + M->BankExpr = CfgExpr (); break; - case CFGTOK_TYPE: - FlagAttr (&M->Attr, MA_TYPE, "TYPE"); - CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); - if (CfgTok == CFGTOK_RO) { - M->Flags |= MF_RO; + case CFGTOK_DEFINE: + FlagAttr (&M->Attr, MA_DEFINE, "DEFINE"); + /* Map the token to a boolean */ + CfgBoolToken (); + if (CfgTok == CFGTOK_TRUE) { + M->Flags |= MF_DEFINE; } CfgNextTok (); break; @@ -469,16 +470,6 @@ static void ParseMemory (void) CfgNextTok (); break; - case CFGTOK_DEFINE: - FlagAttr (&M->Attr, MA_DEFINE, "DEFINE"); - /* Map the token to a boolean */ - CfgBoolToken (); - if (CfgTok == CFGTOK_TRUE) { - M->Flags |= MF_DEFINE; - } - CfgNextTok (); - break; - case CFGTOK_FILL: FlagAttr (&M->Attr, MA_FILL, "FILL"); /* Map the token to a boolean */ @@ -494,6 +485,25 @@ static void ParseMemory (void) M->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF); break; + case CFGTOK_SIZE: + FlagAttr (&M->Attr, MA_SIZE, "SIZE"); + M->SizeExpr = CfgExpr (); + break; + + case CFGTOK_START: + FlagAttr (&M->Attr, MA_START, "START"); + M->StartExpr = CfgExpr (); + break; + + case CFGTOK_TYPE: + FlagAttr (&M->Attr, MA_TYPE, "TYPE"); + CfgSpecialToken (Types, ENTRY_COUNT (Types), "TYPE"); + if (CfgTok == CFGTOK_RO) { + M->Flags |= MF_RO; + } + CfgNextTok (); + break; + default: FAIL ("Unexpected attribute token"); @@ -629,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 }, @@ -698,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)); @@ -1025,11 +1042,12 @@ static void ParseConDes (void) /* Parse the CONDES feature */ { static const IdentTok Attributes [] = { - { "SEGMENT", CFGTOK_SEGMENT }, - { "LABEL", CFGTOK_LABEL }, { "COUNT", CFGTOK_COUNT }, - { "TYPE", CFGTOK_TYPE }, + { "IMPORT", CFGTOK_IMPORT }, + { "LABEL", CFGTOK_LABEL }, { "ORDER", CFGTOK_ORDER }, + { "SEGMENT", CFGTOK_SEGMENT }, + { "TYPE", CFGTOK_TYPE }, }; static const IdentTok Types [] = { @@ -1044,9 +1062,10 @@ static void ParseConDes (void) }; /* Attribute values. */ - unsigned SegName = INVALID_STRING_ID; - unsigned Label = INVALID_STRING_ID; unsigned Count = INVALID_STRING_ID; + unsigned Label = INVALID_STRING_ID; + unsigned SegName = INVALID_STRING_ID; + ConDesImport Import; /* Initialize to avoid gcc warnings: */ int Type = -1; ConDesOrder Order = cdIncreasing; @@ -1054,11 +1073,12 @@ static void ParseConDes (void) /* Bitmask to remember the attributes we got already */ enum { atNone = 0x0000, - atSegName = 0x0001, - atLabel = 0x0002, - atCount = 0x0004, - atType = 0x0008, - atOrder = 0x0010 + atCount = 0x0001, + atImport = 0x0002, + atLabel = 0x0004, + atOrder = 0x0008, + atSegName = 0x0010, + atType = 0x0020, }; unsigned AttrFlags = atNone; @@ -1077,50 +1097,34 @@ static void ParseConDes (void) /* Check which attribute was given */ switch (AttrTok) { - case CFGTOK_SEGMENT: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atSegName, "SEGMENT"); + case CFGTOK_COUNT: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atCount, "COUNT"); /* We expect an identifier */ - CfgAssureIdent (); - /* Remember the value for later */ - SegName = GetStrBufId (&CfgSVal); + CfgAssureIdent (); + /* Remember the value for later */ + Count = GetStrBufId (&CfgSVal); break; - case CFGTOK_LABEL: + case CFGTOK_IMPORT: /* Don't allow this twice */ - FlagAttr (&AttrFlags, atLabel, "LABEL"); + FlagAttr (&AttrFlags, atImport, "IMPORT"); /* We expect an identifier */ - CfgAssureIdent (); - /* Remember the value for later */ - Label = GetStrBufId (&CfgSVal); - break; + CfgAssureIdent (); + /* Remember value and position for later */ + Import.Name = GetStrBufId (&CfgSVal); + Import.Pos = CfgErrorPos; + Import.AddrSize = ADDR_SIZE_ABS; + break; - case CFGTOK_COUNT: + case CFGTOK_LABEL: /* Don't allow this twice */ - FlagAttr (&AttrFlags, atCount, "COUNT"); + FlagAttr (&AttrFlags, atLabel, "LABEL"); /* We expect an identifier */ - CfgAssureIdent (); - /* Remember the value for later */ - Count = GetStrBufId (&CfgSVal); - break; - - case CFGTOK_TYPE: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atType, "TYPE"); - /* The type may be given as id or numerical */ - if (CfgTok == CFGTOK_INTCON) { - CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX); - Type = (int) CfgIVal; - } else { - CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); - switch (CfgTok) { - case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break; - case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break; - case CFGTOK_INTERRUPTOR: Type = CD_TYPE_INT; break; - default: FAIL ("Unexpected type token"); - } - } - break; + CfgAssureIdent (); + /* Remember the value for later */ + Label = GetStrBufId (&CfgSVal); + break; case CFGTOK_ORDER: /* Don't allow this twice */ @@ -1133,6 +1137,33 @@ static void ParseConDes (void) } break; + case CFGTOK_SEGMENT: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atSegName, "SEGMENT"); + /* We expect an identifier */ + CfgAssureIdent (); + /* Remember the value for later */ + SegName = GetStrBufId (&CfgSVal); + break; + + case CFGTOK_TYPE: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atType, "TYPE"); + /* The type may be given as id or numerical */ + if (CfgTok == CFGTOK_INTCON) { + CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX); + Type = (int) CfgIVal; + } else { + CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); + switch (CfgTok) { + case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break; + case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break; + case CFGTOK_INTERRUPTOR: Type = CD_TYPE_INT; break; + default: FAIL ("Unexpected type token"); + } + } + break; + default: FAIL ("Unexpected attribute token"); @@ -1167,6 +1198,9 @@ static void ParseConDes (void) if (AttrFlags & atCount) { ConDesSetCountSym (Type, Count); } + if (AttrFlags & atImport) { + ConDesSetImport (Type, &Import); + } if (AttrFlags & atOrder) { ConDesSetOrder (Type, Order); } @@ -1427,7 +1461,7 @@ static void ParseSymbols (void) /* Generate the import */ Imp = InsertImport (GenImport (Name, AddrSize)); /* Remember the file position */ - CollAppend (&Imp->DefLines, GenLineInfo (&CfgErrorPos)); + CollAppend (&Imp->RefLines, GenLineInfo (&CfgErrorPos)); break; case CfgSymWeak: @@ -1553,22 +1587,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 @@ -1584,6 +1618,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; @@ -1809,6 +1846,9 @@ unsigned CfgProcess (void) /* Get the segment */ SegDesc* S = CollAtUnchecked (&M->SegList, J); + /* Remember the start address before handling this segment */ + unsigned long StartAddr = Addr; + /* Some actions depend on wether this is the load or run memory * area. */ @@ -1865,10 +1905,11 @@ unsigned CfgProcess (void) */ S->Seg->PC = Addr; S->Seg->ReadOnly = (S->Flags & SF_RO) != 0; - S->Seg->Relocatable = M->Relocatable; - /* Remember that this segment is placed */ - S->Seg->Placed = 1; + /* Remember the run memory for this segment, which is also a + * flag that the segment has been placed. + */ + S->Seg->MemArea = M; } else if (S->Load == M) { @@ -1882,6 +1923,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. */ @@ -1910,6 +1958,11 @@ unsigned CfgProcess (void) /* Calculate the new address */ Addr += S->Seg->Size; + /* If this segment goes out to the file, increase the file size */ + if ((S->Flags & SF_BSS) == 0 && S->Load == M) { + M->F->Size += Addr - StartAddr; + } + } /* If requested, define symbols for start, size and offset of the @@ -1942,11 +1995,11 @@ unsigned CfgProcess (void) SB_Done (&Buf); } - /* Grow the file by the size of the memory area */ - if (M->Flags & MF_FILL) { - M->F->Size += M->Size; - } else { - M->F->Size += M->FillLevel; + /* If we didn't have an overflow and are requested to fill the memory + * area, acount for that in the file size. + */ + if ((M->Flags & MF_OVERFLOW) == 0 && (M->Flags & MF_FILL) != 0) { + M->F->Size += (M->Size - M->FillLevel); } }