/* */
/* */
/* */
-/* (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 "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;
/* 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");
/* 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.
*/
Addr = NewAddr;
}
+ /* If the segment has .BANK expressions referring to it, it
+ * must be placed into a memory area that has the bank
+ * attribute.
+ */
+ if ((S->Seg->Flags & SEG_FLAG_BANKREF) != 0 && M->BankExpr == 0) {
+ CfgError (GetSourcePos (S->LI),
+ "Segment `%s' is refered to by .BANK, but the "
+ "memory area `%s' it is placed into has no BANK "
+ "attribute",
+ GetString (S->Name),
+ GetString (M->Name));
+ }
+
/* Set the start address of this segment, set the readonly flag
* in the segment and and remember if the segment is in a
* relocatable file or not.
*/
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) {
/* 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);
}
}