X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fsegments.c;h=1474ebe5550f4cba2b108598d110c7b226737575;hb=35e1184901ca38bdb2e56d154ed3b71f6096eacc;hp=84c80d0850fad49cb9382d92f27e72e47fa81195;hpb=d3017665d2000e3664deb2029267ba3a6b9a565b;p=cc65 diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 84c80d085..1474ebe55 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.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 */ @@ -37,6 +37,8 @@ #include /* common */ +#include "addrsize.h" +#include "alignment.h" #include "check.h" #include "coll.h" #include "exprdefs.h" @@ -92,18 +94,17 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize) /* Initialize the fields */ S->Name = Name; S->Next = 0; + S->Flags = SEG_FLAG_NONE; S->Sections = EmptyCollection; + S->MemArea = 0; S->PC = 0; S->Size = 0; - S->AlignObj = 0; S->OutputName = 0; S->OutputOffs = 0; - S->Align = 0; + S->Alignment = 1; S->FillVal = 0; S->AddrSize = AddrSize; S->ReadOnly = 0; - S->Relocatable = 0; - S->Placed = 0; S->Dumped = 0; /* Insert the segment into the segment list and assign the segment id */ @@ -154,12 +155,9 @@ Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName) -Section* NewSection (Segment* Seg, unsigned char Align, unsigned char AddrSize) +Section* NewSection (Segment* Seg, unsigned long Alignment, unsigned char AddrSize) /* Create a new section for the given segment */ { - unsigned long V; - - /* Allocate memory */ Section* S = xmalloc (sizeof (Section)); @@ -170,12 +168,11 @@ Section* NewSection (Segment* Seg, unsigned char Align, unsigned char AddrSize) S->FragRoot = 0; S->FragLast = 0; S->Size = 0; - S->Align = Align; + S->Alignment= Alignment; S->AddrSize = AddrSize; /* Calculate the alignment bytes needed for the section */ - V = (0x01UL << S->Align) - 1; - S->Fill = (((Seg->Size + V) & ~V) - Seg->Size); + S->Fill = AlignCount (Seg->Size, S->Alignment); /* Adjust the segment size and set the section offset */ Seg->Size += S->Fill; @@ -194,40 +191,57 @@ Section* ReadSection (FILE* F, ObjData* O) /* Read a section from a file */ { unsigned Name; + unsigned Flags; unsigned Size; - unsigned char Align; + unsigned long Alignment; unsigned char Type; unsigned FragCount; Segment* S; Section* Sec; /* Read the segment data */ - (void) Read32 (F); /* File size of data */ + (void) Read32 (F); /* File size of data */ Name = MakeGlobalStringId (O, ReadVar (F)); /* Segment name */ - Size = Read32 (F); /* Size of data */ - Align = Read8 (F); /* Alignment */ - Type = Read8 (F); /* Segment type */ - FragCount = ReadVar (F); /* Number of fragments */ + Flags = ReadVar (F); /* Segment flags */ + Size = ReadVar (F); /* Size of data */ + Alignment = ReadVar (F); /* Alignment */ + Type = Read8 (F); /* Segment type */ + FragCount = ReadVar (F); /* Number of fragments */ /* Print some data */ - Print (stdout, 2, "Module `%s': Found segment `%s', size = %u, align = %u, type = %u\n", - GetObjFileName (O), GetString (Name), Size, Align, Type); + Print (stdout, 2, + "Module `%s': Found segment `%s', size = %u, alignment = %lu, type = %u\n", + GetObjFileName (O), GetString (Name), Size, Alignment, Type); /* Get the segment for this section */ S = GetSegment (Name, Type, GetObjFileName (O)); + + /* The only possible flag is currently SEG_FLAG_BANKREF, and it must be + * applied to the segment, not the section. + */ + S->Flags |= Flags; /* Allocate the section we will return later */ - Sec = NewSection (S, Align, Type); + Sec = NewSection (S, Alignment, Type); /* Remember the object file this section was from */ Sec->Obj = O; - /* Set up the minimum segment alignment */ - if (Sec->Align > S->Align) { - /* Section needs larger alignment, use this one */ - S->Align = Sec->Align; - S->AlignObj = O; + /* Set up the combined segment alignment */ + if (Sec->Alignment > 1) { + Alignment = LeastCommonMultiple (S->Alignment, Sec->Alignment); + if (Alignment > MAX_ALIGNMENT) { + Error ("Combined alignment for segment `%s' is %lu which exceeds " + "%lu. Last module requiring alignment was `%s'.", + GetString (Name), Alignment, MAX_ALIGNMENT, + GetObjFileName (O)); + } else if (Alignment >= LARGE_ALIGNMENT) { + Warning ("Combined alignment for segment `%s' is suspiciously " + "large (%lu). Last module requiring alignment was `%s'.", + GetString (Name), Alignment, GetObjFileName (O)); + } + S->Alignment = Alignment; } /* Start reading fragments from the file and insert them into the section . */ @@ -258,7 +272,7 @@ Section* ReadSection (FILE* F, ObjData* O) case FRAG_FILL: /* Will allocate memory, but we don't care... */ - Frag = NewFragment (Type, ReadVar (F), Sec); + Frag = NewFragment (Type, ReadVar (F), Sec); break; default: @@ -356,7 +370,7 @@ void SegDump (void) printf (" Literal (%u bytes):", F->Size); Count = F->Size; Data = F->LitBuf; - J = 100; + J = 100; while (Count--) { if (J > 75) { printf ("\n "); @@ -471,10 +485,6 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Frag = Sec->FragRoot; while (Frag) { - /* Do fragment alignment checks */ - - - /* Output fragment data */ switch (Frag->Type) { @@ -492,19 +502,19 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* break; case SEG_EXPR_RANGE_ERROR: - Error ("Range error in module `%s', line %lu", + Error ("Range error in module `%s', line %u", GetFragmentSourceName (Frag), GetFragmentSourceLine (Frag)); break; case SEG_EXPR_TOO_COMPLEX: - Error ("Expression too complex in module `%s', line %lu", + Error ("Expression too complex in module `%s', line %u", GetFragmentSourceName (Frag), GetFragmentSourceLine (Frag)); break; - case SEG_EXPR_INVALID: - Error ("Invalid expression in module `%s', line %lu", + case SEG_EXPR_INVALID: + Error ("Invalid expression in module `%s', line %u", GetFragmentSourceName (Frag), GetFragmentSourceLine (Frag)); break; @@ -552,7 +562,7 @@ static int CmpSegStart (const void* K1, const void* K2) /* Compare the start addresses */ if (S1->PC > S2->PC) { - return 1; + return 1; } else if (S1->PC < S2->PC) { return -1; } else { @@ -580,8 +590,8 @@ void PrintSegmentMap (FILE* F) qsort (SegPool, CollCount (&SegmentList), sizeof (Segment*), CmpSegStart); /* Print a header */ - fprintf (F, "Name Start End Size\n" - "--------------------------------------------\n"); + fprintf (F, "Name Start End Size Align\n" + "----------------------------------------------------\n"); /* Print the segments */ for (I = 0; I < CollCount (&SegmentList); ++I) { @@ -597,8 +607,8 @@ void PrintSegmentMap (FILE* F) /* Point to last element addressed */ --End; } - fprintf (F, "%-20s %06lX %06lX %06lX\n", - GetString (S->Name), S->PC, End, S->Size); + fprintf (F, "%-20s %06lX %06lX %06lX %05lX\n", + GetString (S->Name), S->PC, End, S->Size, S->Alignment); } }