/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#include "bitops.h"
#include "check.h"
#include "print.h"
+#include "segdefs.h"
+#include "target.h"
#include "xmalloc.h"
#include "xsprintf.h"
#define MA_DEFINE 0x0010
#define MA_FILL 0x0020
#define MA_FILLVAL 0x0040
+#define MA_BANK 0x0080
/* Segment list */
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 {
S->Seg = 0;
S->Attr = 0;
S->Flags = 0;
+ S->FillVal = 0;
S->RunAlignment = 1;
S->LoadAlignment = 1;
/* 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 },
/* 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;
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 */
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");
{ "ALIGN", CFGTOK_ALIGN },
{ "ALIGN_LOAD", CFGTOK_ALIGN_LOAD },
{ "DEFINE", CFGTOK_DEFINE },
+ { "FILLVAL", CFGTOK_FILLVAL },
{ "LOAD", CFGTOK_LOAD },
{ "OFFSET", CFGTOK_OFFSET },
{ "OPTIONAL", CFGTOK_OPTIONAL },
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));
/* 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 [] = {
};
/* 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;
/* 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;
/* 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 */
}
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");
if (AttrFlags & atCount) {
ConDesSetCountSym (Type, Count);
}
+ if (AttrFlags & atImport) {
+ ConDesSetImport (Type, &Import);
+ }
if (AttrFlags & atOrder) {
ConDesSetOrder (Type, Order);
}
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
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;
/* 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.
*/
*/
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) {
}
+ /* 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.
*/
/* 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
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);
}
}