/* */
/* */
/* */
-/* (C) 1998-2007 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* common */
#include "addrsize.h"
+#include "coll.h"
#include "mmodel.h"
#include "segnames.h"
#include "xmalloc.h"
static int RelocMode = 1;
static unsigned long AbsPC = 0; /* PC if in absolute mode */
-/* Segment initializer macro */
-#define SEG(segdef, num, prev) \
- { prev, 0, 0, 0, num, 0, 1, 0, 0, segdef }
-
/* Definitions for predefined segments */
SegDef NullSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_NULL, ADDR_SIZE_ABS);
SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_ZEROPAGE, ADDR_SIZE_ZP);
SegDef RODataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_RODATA, ADDR_SIZE_ABS);
SegDef CodeSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_CODE, ADDR_SIZE_ABS);
-/* Predefined segments */
-static Segment NullSeg = SEG (&NullSegDef, 5, NULL);
-static Segment ZeropageSeg = SEG (&ZeropageSegDef, 4, &NullSeg);
-static Segment DataSeg = SEG (&DataSegDef, 3, &ZeropageSeg);
-static Segment BssSeg = SEG (&BssSegDef, 2, &DataSeg);
-static Segment RODataSeg = SEG (&RODataSegDef, 1, &BssSeg);
-static Segment CodeSeg = SEG (&CodeSegDef, 0, &RODataSeg);
-
-/* Number of segments */
-static unsigned SegmentCount = 6;
-
-/* List of all segments */
-Segment* SegmentList = &CodeSeg;
-static Segment* SegmentLast = &NullSeg;
+/* Collection containing all segments */
+Collection SegmentList = STATIC_COLLECTION_INITIALIZER;
/* Currently active segment */
-Segment* ActiveSeg = &CodeSeg;
+Segment* ActiveSeg;
-static Segment* NewSegment (const char* Name, unsigned char AddrSize)
-/* Create a new segment, insert it into the global list and return it */
+static Segment* NewSegFromDef (SegDef* Def)
+/* Create a new segment from a segment definition. Used only internally, no
+ * checks.
+ */
{
- Segment* S;
-
- /* Check for too many segments */
- if (SegmentCount >= 256) {
- Fatal ("Too many segments");
- }
-
- /* Check the segment name for invalid names */
- if (!ValidSegName (Name)) {
- Error ("Illegal segment name: `%s'", Name);
- }
-
/* Create a new segment */
- S = xmalloc (sizeof (*S));
+ Segment* S = xmalloc (sizeof (*S));
/* Initialize it */
- S->List = 0;
S->Root = 0;
S->Last = 0;
S->FragCount = 0;
- S->Num = SegmentCount++;
+ S->Num = CollCount (&SegmentList);
S->Align = 0;
S->RelocMode = 1;
S->PC = 0;
S->AbsPC = 0;
- S->Def = NewSegDef (Name, AddrSize);
+ S->Def = Def;
/* Insert it into the segment list */
- SegmentLast->List = S;
- SegmentLast = S;
+ CollAppend (&SegmentList, S);
/* And return it... */
return S;
+static Segment* NewSegment (const char* Name, unsigned char AddrSize)
+/* Create a new segment, insert it into the global list and return it */
+{
+ /* Check for too many segments */
+ if (CollCount (&SegmentList) >= 256) {
+ Fatal ("Too many segments");
+ }
+
+ /* Check the segment name for invalid names */
+ if (!ValidSegName (Name)) {
+ Error ("Illegal segment name: `%s'", Name);
+ }
+
+ /* Create a new segment and return it */
+ return NewSegFromDef (NewSegDef (Name, AddrSize));
+}
+
+
+
Fragment* GenFragment (unsigned char Type, unsigned short Len)
/* Generate a new fragment, add it to the current segment and return it. */
{
void UseSeg (const SegDef* D)
/* Use the segment with the given name */
{
- Segment* Seg = SegmentList;
- while (Seg) {
+ unsigned I;
+ for (I = 0; I < CollCount (&SegmentList); ++I) {
+ Segment* Seg = CollAtUnchecked (&SegmentList, I);
if (strcmp (Seg->Def->Name, D->Name) == 0) {
/* We found this segment. Check if the type is identical */
if (D->AddrSize != ADDR_SIZE_DEFAULT &&
Seg->Def->AddrSize != D->AddrSize) {
- Error ("Segment attribute mismatch");
- /* Use the new attribute to avoid errors */
+ Error ("Segment attribute mismatch");
+ /* Use the new attribute to avoid errors */
Seg->Def->AddrSize = D->AddrSize;
}
ActiveSeg = Seg;
return;
}
- /* Check next segment */
- Seg = Seg->List;
}
/* Segment is not in list, create a new one */
if (D->AddrSize == ADDR_SIZE_DEFAULT) {
- Seg = NewSegment (D->Name, ADDR_SIZE_ABS);
+ ActiveSeg = NewSegment (D->Name, ADDR_SIZE_ABS);
} else {
- Seg = NewSegment (D->Name, D->AddrSize);
+ ActiveSeg = NewSegment (D->Name, D->AddrSize);
}
- ActiveSeg = Seg;
}
unsigned char GetSegAddrSize (unsigned SegNum)
/* Return the address size of the segment with the given number */
{
- /* Search for the segment */
- Segment* S = SegmentList;
- while (S && SegNum) {
- --SegNum;
- S = S->List;
- }
-
- /* Did we find it? */
- if (S == 0) {
+ /* Is there such a segment? */
+ if (SegNum >= CollCount (&SegmentList)) {
FAIL ("Invalid segment number");
}
/* Return the address size */
- return S->Def->AddrSize;
+ return ((Segment*) CollAtUnchecked (&SegmentList, SegNum))->Def->AddrSize;
}
void SegCheck (void)
/* Check the segments for range and other errors */
{
- Segment* S = SegmentList;
- while (S) {
+ unsigned I;
+ for (I = 0; I < CollCount (&SegmentList); ++I) {
+ Segment* S = CollAtUnchecked (&SegmentList, I);
Fragment* F = S->Root;
while (F) {
if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
}
F = F->Next;
}
- S = S->List;
}
}
void SegDump (void)
/* Dump the contents of all segments */
{
+ unsigned I;
unsigned X = 0;
- Segment* S = SegmentList;
+
printf ("\n");
- while (S) {
+ for (I = 0; I < CollCount (&SegmentList); ++I) {
+ Segment* S = CollAtUnchecked (&SegmentList, I);
unsigned I;
Fragment* F;
int State = -1;
F = F->Next;
}
printf ("\n End PC = $%04X\n", (unsigned)(S->PC & 0xFFFF));
- S = S->List;
}
printf ("\n");
}
void InitSegments (void)
/* Initialize segments */
+{
+ /* Create the predefined segments. Code segment is active */
+ ActiveSeg = NewSegFromDef (&CodeSegDef);
+ NewSegFromDef (&RODataSegDef);
+ NewSegFromDef (&BssSegDef);
+ NewSegFromDef (&DataSegDef);
+ NewSegFromDef (&ZeropageSegDef);
+ NewSegFromDef (&NullSegDef);
+}
+
+
+
+void SetSegmentSizes (void)
+/* Set the default segment sizes according to the memory model */
{
/* Initialize segment sizes. The segment definitions do already contain
* the correct values for the default case (near), so we must only change
void WriteSegments (void)
/* Write the segment data to the object file */
{
- Segment* Seg;
+ unsigned I;
/* Tell the object file module that we're about to start the seg list */
ObjStartSegments ();
/* First thing is segment count */
- ObjWriteVar (SegmentCount);
+ ObjWriteVar (CollCount (&SegmentList));
/* Now walk through all segments and write them to the object file */
- Seg = SegmentList;
- while (Seg) {
+ for (I = 0; I < CollCount (&SegmentList); ++I) {
/* Write one segment */
- WriteOneSeg (Seg);
- /* Next segment */
- Seg = Seg->List;
+ WriteOneSeg (CollAtUnchecked (&SegmentList, I));
}
/* Done writing segments */