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 */
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 */
" --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"
+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 */
{
{ "--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 },
#include <sys/stat.h>
/* common */
+#include "alignment.h"
#include "assertion.h"
#include "bitops.h"
#include "cddefs.h"
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);
}
/* common */
#include "addrsize.h"
+#include "alignment.h"
#include "coll.h"
#include "mmodel.h"
#include "segnames.h"
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;
-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);
}
}
/* 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 */
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 */
# 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);