]> git.sur5r.net Git - cc65/commitdiff
Allow arbitrary alignments, not just powers of two. Beware: This needs support
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 27 Dec 2011 22:54:52 +0000 (22:54 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 27 Dec 2011 22:54:52 +0000 (22:54 +0000)
in the linker which is currently missing.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5334 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/global.c
src/ca65/global.h
src/ca65/main.c
src/ca65/pseudo.c
src/ca65/segment.c
src/ca65/segment.h

index e934652ec2ed197ce5b308c5edf60422b7fc0824..ced950d6b52de17bf69c57dca79ed5858ceda1f4 100644 (file)
@@ -64,6 +64,7 @@ unsigned char AutoImport         = 0;   /* Mark unresolveds as import */
 unsigned char SmartMode                 = 0;   /* Smart mode */
 unsigned char DbgSyms           = 0;   /* Add debug symbols */
 unsigned char LineCont          = 0;   /* Allow line continuation */
+unsigned char LargeAlignment     = 0;   /* Don't warn about large alignments */
 
 /* Emulation features */
 unsigned char DollarIsPC         = 0;   /* Allow the $ symbol as current PC */
index 9cdd18e68d955027af21836544cda30c6d3a95d1..51b31725b5673d9b4652fa1dfa559db019da87c8 100644 (file)
@@ -66,6 +66,7 @@ extern unsigned char          AutoImport;         /* Mark unresolveds as import */
 extern unsigned char           SmartMode;          /* Smart mode */
 extern unsigned char           DbgSyms;            /* Add debug symbols */
 extern unsigned char           LineCont;           /* Allow line continuation */
+extern unsigned char    LargeAlignment;     /* Don't warn about large alignments */
 
 /* Emulation features */
 extern unsigned char           DollarIsPC;         /* Allow the $ symbol as current PC */
index 43da5ffd7be203a136edaa288ed6b11db202476a..6b16dd98be4ab2508cac1396112355fa52c6ac90 100644 (file)
@@ -119,6 +119,7 @@ static void Usage (void)
             "  --help\t\t\tHelp (this text)\n"
             "  --ignore-case\t\t\tIgnore case of symbols\n"
             "  --include-dir dir\t\tSet an include directory search path\n"
+            "  --large-alignment\t\tDon't warn about large alignments\n"
             "  --listing name\t\tCreate a listing file if assembly was ok\n"
             "  --list-bytes n\t\tMaximum number of bytes per listing line\n"
             "  --macpack-dir dir\t\tSet a macro package directory\n"
@@ -458,6 +459,15 @@ static void OptIncludeDir (const char* Opt attribute ((unused)), const char* Arg
 
 
 
+static void OptLargeAlignment (const char* Opt attribute ((unused)),
+                              const char* Arg attribute ((unused)))
+/* Don't warn about large alignments */
+{
+    LargeAlignment = 1;
+}
+
+
+
 static void OptListBytes (const char* Opt, const char* Arg)
 /* Set the maximum number of bytes per listing line */
 {
@@ -849,6 +859,7 @@ int main (int argc, char* argv [])
        { "--help",             0,      OptHelp                 },
        { "--ignore-case",      0,      OptIgnoreCase           },
        { "--include-dir",      1,      OptIncludeDir           },
+        { "--large-alignment",  0,      OptLargeAlignment       },
         { "--list-bytes",       1,      OptListBytes            },
        { "--listing",          1,      OptListing              },
         { "--macpack-dir",      1,      OptMacPackDir           },
index 477a6a6989b4fffa79146650396900d5cce26598..365fd5b79c0afc897019d3b001e5b81e46fc5c1c 100644 (file)
@@ -42,6 +42,7 @@
 #include <sys/stat.h>
 
 /* common */
+#include "alignment.h"
 #include "assertion.h"
 #include "bitops.h"
 #include "cddefs.h"
@@ -395,37 +396,31 @@ static void DoAddr (void)
 static void DoAlign (void)
 /* Align the PC to some boundary */
 {
-    long Val;
-    long Align;
-    unsigned Bit;
+    long FillVal;
+    long Alignment;
 
     /* Read the alignment value */
-    Align = ConstExpression ();
-    if (Align <= 0 || Align > 0x10000) {
-               ErrorSkip ("Range error");
-       return;
+    Alignment = ConstExpression ();
+    if (Alignment <= 0 || (unsigned long) Alignment > MAX_ALIGNMENT) {
+        ErrorSkip ("Range error");
+        return;
     }
 
     /* Optional value follows */
     if (CurTok.Tok == TOK_COMMA) {
-       NextTok ();
-       Val = ConstExpression ();
-       /* We need a byte value here */
-       if (!IsByteRange (Val)) {
-                   ErrorSkip ("Range error");
-           return;
-       }
+        NextTok ();
+        FillVal = ConstExpression ();
+        /* We need a byte value here */
+        if (!IsByteRange (FillVal)) {
+            ErrorSkip ("Range error");
+            return;
+        }
     } else {
-       Val = -1;
+        FillVal = -1;
     }
 
-    /* Check if the alignment is a power of two */
-    Bit = BitFind (Align);
-    if (Align != (0x01L << Bit)) {
-       Error ("Alignment value must be a power of 2");
-    } else {
-       SegAlign (Bit, (int) Val);
-    }
+    /* Generate the alignment */
+    SegAlign (Alignment, (int) FillVal);
 }
 
 
index 9a1532b26679b42aa553692eef326682b69dc5a1..a1c2aed27d9f26366ed23e7f5370121527503d07 100644 (file)
@@ -38,6 +38,7 @@
 
 /* common */
 #include "addrsize.h"
+#include "alignment.h"
 #include "coll.h"
 #include "mmodel.h"
 #include "segnames.h"
@@ -106,7 +107,7 @@ static Segment* NewSegFromDef (SegDef* Def)
     S->Last      = 0;
     S->FragCount = 0;
     S->Num       = CollCount (&SegmentList);
-    S->Align     = 0;
+    S->Align     = 1;
     S->RelocMode = 1;
     S->PC        = 0;
     S->AbsPC     = 0;
@@ -276,37 +277,53 @@ void EnterRelocMode (void)
 
 
 
-void SegAlign (unsigned Power, int Val)
-/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
- * actual fill value will be determined by the linker), otherwise use the
- * given value.
+void SegAlign (unsigned long Alignment, int FillVal)
+/* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments
+ * (the actual fill value will be determined by the linker), otherwise use
+ * the given value.
  */
 {
     unsigned char Data [4];
-    unsigned long Align = (1UL << Power) - 1;
-    unsigned long NewPC = (ActiveSeg->PC + Align) & ~Align;
-    unsigned long Count = NewPC - ActiveSeg->PC;
-
-    if (Val != -1) {
-       /* User defined fill value */
-       memset (Data, Val, sizeof (Data));
-       while (Count) {
-           if (Count > sizeof (Data)) {
-               EmitData (Data, sizeof (Data));
-               Count -= sizeof (Data);
-           } else {
-               EmitData (Data, Count);
-               Count = 0;
-           }
-       }
+    unsigned long CombinedAlignment;
+    unsigned long Count;
+
+    /* The segment must have the combined alignment of all separate alignments
+     * in the source. Calculate this alignment and check it for sanity.
+     */
+    CombinedAlignment = LeastCommonMultiple (ActiveSeg->Align, Alignment);
+    if (CombinedAlignment > MAX_ALIGNMENT) {
+        Error ("Combined alignment for active segment exceeds 0x10000");
     } else {
-       /* Linker defined fill value */
-       EmitFill (Count);
+        ActiveSeg->Align = CombinedAlignment;
+
+        /* Output a warning for larger alignments if not suppressed */
+        if (CombinedAlignment > LARGE_ALIGNMENT && !LargeAlignment) {
+            Warning (0, "Combined alignment is suspiciously large (%lu)",
+                     CombinedAlignment);
+        }
     }
 
-    /* Remember the alignment in the header */
-    if (ActiveSeg->Align < Power) {
-       ActiveSeg->Align = Power;
+
+
+    /* Calculate the number of fill bytes */
+    Count = AlignCount (ActiveSeg->PC, Alignment) - ActiveSeg->PC;
+
+    /* Emit the data or a fill fragment */
+    if (FillVal != -1) {
+               /* User defined fill value */
+               memset (Data, FillVal, sizeof (Data));
+               while (Count) {
+                   if (Count > sizeof (Data)) {
+                       EmitData (Data, sizeof (Data));
+                       Count -= sizeof (Data);
+                   } else {
+                       EmitData (Data, Count);
+                       Count = 0;
+                   }
+               }
+    } else {
+               /* Linker defined fill value */
+               EmitFill (Count);
     }
 }
 
@@ -513,8 +530,8 @@ static void WriteOneSeg (Segment* Seg)
 
     /* Write the segment data */
     ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */
-    ObjWriteVar (Seg->PC);                       /* Size */
-    ObjWrite8 (Seg->Align);                     /* Segment alignment */
+    ObjWriteVar (Seg->PC);                      /* Size */
+    ObjWriteVar (Seg->Align);                   /* Segment alignment */
     ObjWrite8 (Seg->Def->AddrSize);             /* Address size of the segment */
     ObjWriteVar (Seg->FragCount);               /* Number of fragments */
 
index c28c86be1e06e5a7c9a8d7dc54a6de5942c0b14a..0575bc7748f449b9213e772896e02bdbbd23d4fb 100644 (file)
@@ -62,7 +62,7 @@ struct Segment {
     Fragment*              Last;               /* Pointer to last fragment */
     unsigned long   FragCount;          /* Number of fragments */
     unsigned        Num;                       /* Segment number */
-    unsigned        Align;                     /* Segment alignment */
+    unsigned long   Align;                     /* Segment alignment */
     int             RelocMode;          /* Relocatable mode if OrgPerSeg */
     unsigned long   PC;                 /* PC if in relocatable mode */
     unsigned long   AbsPC;              /* PC if in local absolute mode */
@@ -128,10 +128,10 @@ INLINE unsigned char GetCurrentSegAddrSize (void)
 #  define GetCurrentSegAddrSize()    (ActiveSeg->Def->AddrSize)
 #endif
 
-void SegAlign (unsigned Power, int Val);
-/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
- * actual fill value will be determined by the linker), otherwise use the
- * given value.
+void SegAlign (unsigned long Alignment, int FillVal);
+/* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments
+ * (the actual fill value will be determined by the linker), otherwise use
+ * the given value.
  */
 
 unsigned char GetSegAddrSize (unsigned SegNum);