]> git.sur5r.net Git - cc65/blobdiff - src/ld65/config.c
Added support for arbitrary alignments.
[cc65] / src / ld65 / config.c
index f6e2ff0ed64ecb00b1a94aeef7445d6f416d51ee..ebafd0bd3b0996fb227881bf76798f3b43df1d03 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2010, Ullrich von Bassewitz                                      */
+/* (C) 1998-2011, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -47,6 +47,7 @@
 #include "xsprintf.h"
 
 /* ld65 */
+#include "alignment.h"
 #include "bin.h"
 #include "binfmt.h"
 #include "cfgexpr.h"
@@ -340,12 +341,13 @@ static SegDesc* NewSegDesc (unsigned Name)
     S = xmalloc (sizeof (SegDesc));
 
     /* Initialize the fields */
-    S->Name    = Name;
-    S->LI      = GenLineInfo (&CfgErrorPos);
-    S->Seg     = 0;
-    S->Attr    = 0;
-    S->Flags   = 0;
-    S->Align   = 0;
+    S->Name          = Name;
+    S->LI            = GenLineInfo (&CfgErrorPos);
+    S->Seg           = 0;
+    S->Attr          = 0;
+    S->Flags         = 0;
+    S->RunAlignment  = 1;
+    S->LoadAlignment = 1;
 
     /* Insert the struct into the list ... */
     CollAppend (&SegDescList, S);
@@ -359,6 +361,7 @@ static SegDesc* NewSegDesc (unsigned Name)
 static void FreeSegDesc (SegDesc* S)
 /* Free a segment descriptor */
 {
+    FreeLineInfo (S->LI);
     xfree (S);
 }
 
@@ -636,7 +639,6 @@ static void ParseSegments (void)
     };
 
     unsigned Count;
-    long     Val;
 
     /* The MEMORY section must preceed the SEGMENTS section */
     if ((SectionsEncountered & SE_MEMORY) == 0) {
@@ -671,21 +673,13 @@ static void ParseSegments (void)
 
                case CFGTOK_ALIGN:
                    FlagAttr (&S->Attr, SA_ALIGN, "ALIGN");
-                   Val = CfgCheckedConstExpr (1, 0x10000);
-                   S->Align = BitFind (Val);
-                   if ((0x01L << S->Align) != Val) {
-                       CfgError (&CfgErrorPos, "Alignment must be a power of 2");
-                   }
+                   S->RunAlignment = (unsigned) CfgCheckedConstExpr (1, MAX_ALIGNMENT);
                    S->Flags |= SF_ALIGN;
                    break;
 
                 case CFGTOK_ALIGN_LOAD:
                    FlagAttr (&S->Attr, SA_ALIGN_LOAD, "ALIGN_LOAD");
-                   Val = CfgCheckedConstExpr (1, 0x10000);
-                           S->AlignLoad = BitFind (Val);
-                   if ((0x01L << S->AlignLoad) != Val) {
-                       CfgError (&CfgErrorPos, "Alignment must be a power of 2");
-                   }
+                   S->LoadAlignment = (unsigned) CfgCheckedConstExpr (1, MAX_ALIGNMENT);
                    S->Flags |= SF_ALIGN_LOAD;
                    break;
 
@@ -1417,7 +1411,7 @@ static void ParseSymbols (void)
                 AttrCheck (AttrFlags, atType, "TYPE");
                 /* Create the export */
                 Exp = CreateExprExport (Name, Value, AddrSize);
-                CollAppend (&Exp->LineInfos, GenLineInfo (&CfgErrorPos));
+                CollAppend (&Exp->DefLines, GenLineInfo (&CfgErrorPos));
                 break;
 
             case CfgSymImport:
@@ -1428,7 +1422,7 @@ static void ParseSymbols (void)
                 /* Generate the import */
                 Imp = InsertImport (GenImport (Name, AddrSize));
                 /* Remember the file position */
-                CollAppend (&Imp->LineInfos, GenLineInfo (&CfgErrorPos));
+                CollAppend (&Imp->DefLines, GenLineInfo (&CfgErrorPos));
                 break;
 
             case CfgSymWeak:
@@ -1678,7 +1672,7 @@ static void ProcessSymbols (void)
                 if ((E = FindExport (Sym->Name)) == 0 || IsUnresolvedExport (E)) {
                     /* The symbol is undefined, generate an export */
                     E = CreateExprExport (Sym->Name, Sym->Value, Sym->AddrSize);
-                    CollAppend (&E->LineInfos, Sym->LI);
+                    CollAppend (&E->DefLines, Sym->LI);
                 }
                 break;
 
@@ -1701,12 +1695,12 @@ static void CreateRunDefines (SegDesc* S, unsigned long SegAddr)
     /* Define the run address of the segment */
     SB_Printf (&Buf, "__%s_RUN__", GetString (S->Name));
     E = CreateMemoryExport (GetStrBufId (&Buf), S->Run, SegAddr - S->Run->Start);
-    CollAppend (&E->LineInfos, S->LI);
+    CollAppend (&E->DefLines, S->LI);
 
     /* Define the size of the segment */
     SB_Printf (&Buf, "__%s_SIZE__", GetString (S->Name));
     E = CreateConstExport (GetStrBufId (&Buf), S->Seg->Size);
-    CollAppend (&E->LineInfos, S->LI);
+    CollAppend (&E->DefLines, S->LI);
 
     S->Flags |= SF_RUN_DEF;
     SB_Done (&Buf);
@@ -1723,7 +1717,7 @@ static void CreateLoadDefines (SegDesc* S, unsigned long SegAddr)
     /* Define the load address of the segment */
     SB_Printf (&Buf, "__%s_LOAD__", GetString (S->Name));
     E = CreateMemoryExport (GetStrBufId (&Buf), S->Load, SegAddr - S->Load->Start);
-    CollAppend (&E->LineInfos, S->LI);
+    CollAppend (&E->DefLines, S->LI);
 
     S->Flags |= SF_LOAD_DEF;
     SB_Done (&Buf);
@@ -1788,7 +1782,7 @@ unsigned CfgProcess (void)
             /* Define the start of the memory area */
            SB_Printf (&Buf, "__%s_START__", GetString (M->Name));
            E = CreateMemoryExport (GetStrBufId (&Buf), M, 0);
-            CollAppend (&E->LineInfos, M->LI);
+            CollAppend (&E->DefLines, M->LI);
 
             SB_Done (&Buf);
         }
@@ -1817,8 +1811,22 @@ unsigned CfgProcess (void)
                  */
                 if (S->Flags & SF_ALIGN) {
                     /* Align the address */
-                    unsigned long Val = (0x01UL << S->Align) - 1;
-                    Addr = (Addr + Val) & ~Val;
+                    unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment);
+
+                    /* If the first segment placed in the memory area needs
+                     * fill bytes for the alignment, emit a warning, since
+                     * this is somewhat suspicious.
+                     */
+                    if (M->FillLevel == 0 && NewAddr > Addr) {
+                        CfgWarning (GetSourcePos (S->LI),
+                                    "First segment in memory area `%s' does "
+                                    "already need fill bytes for alignment",
+                                    GetString (M->Name));
+                    }
+
+                    /* Use the aligned address */
+                    Addr = NewAddr;
+
                 } else if (S->Flags & (SF_OFFSET | SF_START)) {
                     /* Give the segment a fixed starting address */
                     unsigned long NewAddr = S->Addr;
@@ -1861,8 +1869,7 @@ unsigned CfgProcess (void)
                  */
                 if (S->Flags & SF_ALIGN_LOAD) {
                     /* Align the address */
-                    unsigned long Val = (0x01UL << S->AlignLoad) - 1;
-                    Addr = (Addr + Val) & ~Val;
+                    Addr = AlignAddr (Addr, S->LoadAlignment);
                 }
 
             }
@@ -1905,12 +1912,12 @@ unsigned CfgProcess (void)
             /* Define the size of the memory area */
            SB_Printf (&Buf, "__%s_SIZE__", GetString (M->Name));
            E = CreateConstExport (GetStrBufId (&Buf), M->Size);
-            CollAppend (&E->LineInfos, M->LI);
+            CollAppend (&E->DefLines, M->LI);
 
             /* Define the fill level of the memory area */
            SB_Printf (&Buf, "__%s_LAST__", GetString (M->Name));
            E = CreateMemoryExport (GetStrBufId (&Buf), M, M->FillLevel);
-            CollAppend (&E->LineInfos, M->LI);
+            CollAppend (&E->DefLines, M->LI);
 
             SB_Done (&Buf);
        }