X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fsegments.c;h=1474ebe5550f4cba2b108598d110c7b226737575;hb=35e1184901ca38bdb2e56d154ed3b71f6096eacc;hp=10f23bbe24ad5c4bf782c7eef734e2df40622c29;hpb=6172979c1cb288411f34de1a4ac41d4b4dd37368;p=cc65 diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 10f23bbe2..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,11 +37,13 @@ #include /* common */ +#include "addrsize.h" +#include "alignment.h" #include "check.h" #include "coll.h" #include "exprdefs.h" #include "fragdefs.h" -#include "hashstr.h" +#include "hashfunc.h" #include "print.h" #include "segdefs.h" #include "symdefs.h" @@ -92,19 +94,17 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize) /* Initialize the fields */ S->Name = Name; S->Next = 0; - S->SecRoot = 0; - S->SecLast = 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 */ @@ -155,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)); @@ -171,25 +168,18 @@ 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; S->Offs = Seg->Size; /* Current size is offset */ /* Insert the section into the segment */ - if (Seg->SecRoot == 0) { - /* First section in this segment */ - Seg->SecRoot = S; - } else { - Seg->SecLast->Next = S; - } - Seg->SecLast = S; + CollAppend (&Seg->Sections, S); /* Return the struct */ return S; @@ -201,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 . */ @@ -265,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: @@ -278,9 +285,6 @@ Section* ReadSection (FILE* F, ObjData* O) /* Read the line infos into the list of the fragment */ ReadLineInfoList (F, O, &Frag->LineInfos); - /* Resolve the back pointers */ - FragResolveLineInfos (Frag); - /* Remember the module we had this fragment from */ Frag->Obj = O; } @@ -314,8 +318,12 @@ int IsBSSType (Segment* S) */ { /* Loop over all sections */ - Section* Sec = S->SecRoot; - while (Sec) { + unsigned I; + for (I = 0; I < CollCount (&S->Sections); ++I) { + + /* Get the next section */ + Section* Sec = CollAtUnchecked (&S->Sections, I); + /* Loop over all fragments */ Fragment* F = Sec->FragRoot; while (F) { @@ -334,7 +342,6 @@ int IsBSSType (Segment* S) } F = F->Next; } - Sec = Sec->Next; } return 1; } @@ -344,15 +351,15 @@ int IsBSSType (Segment* S) void SegDump (void) /* Dump the segments and it's contents */ { - unsigned I; + unsigned I, J; unsigned long Count; unsigned char* Data; - + for (I = 0; I < CollCount (&SegmentList); ++I) { - const Segment* Seg = CollConstAt (&SegmentList, I); - Section* S = Seg->SecRoot; + Segment* Seg = CollAtUnchecked (&SegmentList, I); printf ("Segment: %s (%lu)\n", GetString (Seg->Name), Seg->Size); - while (S) { + for (J = 0; J < CollCount (&Seg->Sections); ++J) { + Section* S = CollAtUnchecked (&Seg->Sections, J); unsigned J; Fragment* F = S->FragRoot; printf (" Section:\n"); @@ -363,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 "); @@ -396,7 +403,6 @@ void SegDump (void) } F = F->Next; } - S = S->Next; } } } @@ -408,14 +414,14 @@ unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size) * check and return one of the SEG_EXPR_xxx codes. */ { - static const unsigned long U_HighRange [4] = { - 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF + static const unsigned long U_Hi[4] = { + 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL }; - static const long S_HighRange [4] = { - 0x0000007F, 0x00007FFF, 0x007FFFFF, 0x7FFFFFFF + static const long S_Hi[4] = { + 0x0000007FL, 0x00007FFFL, 0x007FFFFFL, 0x7FFFFFFFL }; - static const long S_LowRange [4] = { - 0xFFFFFF80, 0xFFFF8000, 0xFF800000, 0x80000000 + static const long S_Lo[4] = { + ~0x0000007FL, ~0x00007FFFL, ~0x007FFFFFL, ~0x7FFFFFFFL }; @@ -427,12 +433,12 @@ unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size) /* Check for a range error */ if (Signed) { - if (Val > S_HighRange [Size-1] || Val < S_LowRange [Size-1]) { + if (Val > S_Hi[Size-1] || Val < S_Lo[Size-1]) { /* Range error */ return SEG_EXPR_RANGE_ERROR; } } else { - if (((unsigned long)Val) > U_HighRange [Size-1]) { + if (((unsigned long)Val) > U_Hi[Size-1]) { /* Range error */ return SEG_EXPR_RANGE_ERROR; } @@ -452,7 +458,7 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* * called (see description of SegWriteFunc above). */ { - Section* Sec; + unsigned I; int Sign; unsigned long Offs = 0; @@ -462,8 +468,8 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* S->OutputOffs = (unsigned long) ftell (Tgt); /* Loop over all sections in this segment */ - Sec = S->SecRoot; - while (Sec) { + for (I = 0; I < CollCount (&S->Sections); ++I) { + Section* Sec = CollAtUnchecked (&S->Sections, I); Fragment* Frag; /* Output were this section is from */ @@ -479,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) { @@ -500,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; @@ -538,14 +540,19 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* /* Next fragment */ Frag = Frag->Next; } - - /* Next section */ - Sec = Sec->Next; } } +unsigned SegmentCount (void) +/* Return the total number of segments */ +{ + return CollCount (&SegmentList); +} + + + static int CmpSegStart (const void* K1, const void* K2) /* Compare function for qsort */ { @@ -555,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 { @@ -583,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) { @@ -600,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); } } @@ -613,7 +620,7 @@ void PrintSegmentMap (FILE* F) void PrintDbgSegments (FILE* F) /* Output the segments to the debug file */ -{ +{ /* Walk over all segments */ unsigned I; for (I = 0; I < CollCount (&SegmentList); ++I) {