*Buf += 2;
return;
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
/* 8 bit segment number */
*Buf += 1;
return;
if (RelocMode) {
/* Create SegmentBase + Offset */
Left = NewExprNode ();
- Left->Op = EXPR_SEGMENT;
+ Left->Op = EXPR_SECTION;
Left->V.SegNum = GetSegNum ();
Root = NewExprNode ();
/* Create *+Offs */
if (RelocMode) {
Left = NewExprNode ();
- Left->Op = EXPR_SEGMENT;
+ Left->Op = EXPR_SECTION;
Left->V.SegNum = GetSegNum ();
N = NewExprNode ();
}
break;
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
*IsByte = 1;
}
Clone->V.Sym = Expr->V.Sym;
break;
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
Clone->V.SegNum = Expr->V.SegNum;
break;
return Left;
} else {
/* Check for SEG - SEG which is now possible */
- if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
+ if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION &&
Left->V.SegNum == Right->V.SegNum) {
/* SEG - SEG, remove it completely */
FreeExprNode (Left);
Clone->V.Sym = Expr->V.Sym;
break;
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
Clone->V.SegNum = Expr->V.SegNum;
break;
ObjWrite16 (GetSymIndex (Expr->V.Sym));
break;
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
ObjWrite8 (Expr->V.SegNum);
break;
/* Leaf node codes */
#define EXPR_LITERAL (EXPR_LEAFNODE | 0x01)
#define EXPR_SYMBOL (EXPR_LEAFNODE | 0x02)
-#define EXPR_SEGMENT (EXPR_LEAFNODE | 0x03)
-#define EXPR_MEMAREA (EXPR_LEAFNODE | 0x04) /* Linker only */
-#define EXPR_ULABEL (EXPR_LEAFNODE | 0x05) /* Assembler only */
+#define EXPR_SECTION (EXPR_LEAFNODE | 0x03)
+#define EXPR_SEGMENT (EXPR_LEAFNODE | 0x04) /* Linker only */
+#define EXPR_MEMAREA (EXPR_LEAFNODE | 0x05) /* Linker only */
+#define EXPR_ULABEL (EXPR_LEAFNODE | 0x06) /* Assembler only */
/* Binary operations, left and right hand sides are valid */
#define EXPR_PLUS (EXPR_BINARYNODE | 0x01)
/* The expression node itself */
typedef struct ExprNode ExprNode;
-struct ExprNode {
+struct ExprNode {
unsigned char Op; /* Operand/Type */
ExprNode* Left; /* Left leaf */
ExprNode* Right; /* Right leaf */
- struct ObjData* Obj; /* Object file reference (linker) */
+ struct ObjData* Obj; /* Object file reference (linker) */
union {
long Val; /* If this is a value */
struct SymEntry* Sym; /* If this is a symbol */
unsigned SegNum; /* If this is a segment */
- unsigned ImpNum; /* If this is an import */
- struct Memory* MemArea; /* If this is a memory area */
- struct Section* Sec; /* If segment and Obj is NULL */
+ unsigned ImpNum; /* If this is an import */
+ struct Memory* Mem; /* If this is a memory area */
+ struct Segment* Seg; /* If this is a segment */
+ struct Section* Sec; /* If section and Obj is NULL */
} V;
};
/* Define the table start as an export, offset into section is zero
* (the section only contains the table).
*/
- CreateSegExport (CD->Label, Sec, 0);
+ CreateSectionExport (CD->Label, Sec, 0);
/* If we have a CountSym name given AND if it is referenced, define it
* with the number of elements in the table.
#include "bitops.h"
#include "print.h"
#include "xmalloc.h"
+#include "xsprintf.h"
/* ld65 */
#include "bin.h"
break;
case CFGTOK_SIZE:
- FlagAttr (&M->Attr, MA_SIZE, "SIZE");
+ FlagAttr (&M->Attr, MA_SIZE, "SIZE");
CfgAssureInt ();
M->Size = CfgIVal;
break;
case CFGTOK_FILLVAL:
FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL");
- CfgAssureInt ();
+ CfgAssureInt ();
CfgRangeCheck (0, 0xFF);
M->FillVal = (unsigned char) CfgIVal;
break;
-static void CreateRunDefines (Memory* M, SegDesc* S, unsigned long Addr)
+static void CreateRunDefines (SegDesc* S)
/* Create the defines for a RUN segment */
{
char Buf [256];
- sprintf (Buf, "__%s_RUN__", S->Name);
- CreateMemExport (Buf, M, Addr - M->Start);
- sprintf (Buf, "__%s_SIZE__", S->Name);
+ xsprintf (Buf, sizeof (Buf), "__%s_RUN__", S->Name);
+ CreateSegmentExport (Buf, S->Seg, 0);
+ xsprintf (Buf, sizeof (Buf), "__%s_SIZE__", S->Name);
CreateConstExport (Buf, S->Seg->Size);
S->Flags |= SF_RUN_DEF;
}
-static void CreateLoadDefines (Memory* M, SegDesc* S, unsigned long Addr)
+static void CreateLoadDefines (Memory* M, SegDesc* S)
/* Create the defines for a LOAD segment */
{
char Buf [256];
- sprintf (Buf, "__%s_LOAD__", S->Name);
- CreateMemExport (Buf, M, Addr - M->Start);
+ xsprintf (Buf, sizeof (Buf), "__%s_LOAD__", S->Name);
+ CreateMemoryExport (Buf, M, S->Seg->PC - M->Start);
S->Flags |= SF_LOAD_DEF;
}
*/
if (S->Load == M) {
if ((S->Flags & SF_LOAD_DEF) == 0) {
- CreateLoadDefines (M, S, Addr);
+ CreateLoadDefines (M, S);
} else {
CHECK ((S->Flags & SF_RUN_DEF) == 0);
- CreateRunDefines (M, S, Addr);
+ CreateRunDefines (S);
}
}
} else {
/* RUN and LOAD in different memory areas, or RUN not
- * given, so RUN defaults to LOAD. In the latter case, we
+ * given, so RUN defaults to LOAD. In the latter case, we
* have only one copy of the segment in the area.
*/
if (S->Run == M) {
- CreateRunDefines (M, S, Addr);
+ CreateRunDefines (S);
}
if (S->Load == M) {
- CreateLoadDefines (M, S, Addr);
+ CreateLoadDefines (M, S);
}
}
}
if (M->Flags & MF_DEFINE) {
char Buf [256];
sprintf (Buf, "__%s_START__", M->Name);
- CreateMemExport (Buf, M, 0);
+ CreateMemoryExport (Buf, M, 0);
sprintf (Buf, "__%s_SIZE__", M->Name);
CreateConstExport (Buf, M->Size);
sprintf (Buf, "__%s_LAST__", M->Name);
-Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs)
+Export* CreateMemoryExport (const char* Name, Memory* Mem, unsigned long Offs)
/* Create an relative export for a memory area offset */
{
/* Create a new export */
Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
/* Assign the value */
- E->Expr = MemExpr (Mem, Offs, 0);
+ E->Expr = MemoryExpr (Mem, Offs, 0);
/* Insert the export */
InsertExport (E);
-Export* CreateSegExport (const char* Name, Section* Sec, unsigned long Offs)
-/* Create a relative export to a segment (section) */
+Export* CreateSegmentExport (const char* Name, Segment* Seg, unsigned long Offs)
+/* Create a relative export to a segment */
{
/* Create a new export */
Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
/* Assign the value */
- E->Expr = SegExpr (Sec, Offs, 0);
+ E->Expr = SegmentExpr (Seg, Offs, 0);
+
+ /* Insert the export */
+ InsertExport (E);
+
+ /* Return the new export */
+ return E;
+}
+
+
+
+Export* CreateSectionExport (const char* Name, Section* Sec, unsigned long Offs)
+/* Create a relative export to a section */
+{
+ /* Create a new export */
+ Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
+
+ /* Assign the value */
+ E->Expr = SectionExpr (Sec, Offs, 0);
/* Insert the export */
InsertExport (E);
Export* CreateConstExport (const char* Name, long Value);
/* Create an export for a literal date */
-Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs);
+Export* CreateMemoryExport (const char* Name, Memory* Mem, unsigned long Offs);
/* Create an relative export for a memory area offset */
-Export* CreateSegExport (const char* Name, Section* S, unsigned long Offs);
-/* Create a relative export to a segment (section) */
+Export* CreateSegmentExport (const char* Name, Segment* Seg, unsigned long Offs);
+/* Create a relative export to a segment */
+
+Export* CreateSectionExport (const char* Name, Section* S, unsigned long Offs);
+/* Create a relative export to a section */
Export* FindExport (const char* Name);
/* Check for an identifier in the list. Return 0 if not found, otherwise
int IsUnresolvedExport (const Export* E);
/* Return true if the given export is unresolved */
-int IsConstExport (const Export* E);
+int IsConstExport (const Export* E);
/* Return true if the expression associated with this export is const */
long GetExportVal (const Export* E);
Section* GetExprSection (ExprNode* Expr)
-/* Get the segment for a segment expression node */
+/* Get the segment for a section expression node */
{
- /* Check that this is really a segment node */
- PRECONDITION (Expr->Op == EXPR_SEGMENT);
+ /* Check that this is really a section node */
+ PRECONDITION (Expr->Op == EXPR_SECTION);
/* If we have an object file, get the section from it, otherwise
* (internally generated expressions), get the section from the
* which in turn means, that we have a circular reference.
*/
if (ExportHasMark (E)) {
- CircularRefError (E);
- Val = 0;
+ CircularRefError (E);
+ Val = 0;
} else {
- MarkExport (E);
+ MarkExport (E);
Val = GetExportVal (E);
- UnmarkExport (E);
+ UnmarkExport (E);
}
return Val;
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
S = GetExprSection (Expr);
return S->Offs + S->Seg->PC;
- case EXPR_MEMAREA:
- return Expr->V.MemArea->Start;
+ case EXPR_SEGMENT:
+ return Expr->V.Seg->PC;
+
+ case EXPR_MEMAREA:
+ return Expr->V.Mem->Start;
case EXPR_PLUS:
return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
-ExprNode* MemExpr (Memory* Mem, long Offs, ObjData* O)
-/* Return an expression tree that encodes an offset into the memory area */
+ExprNode* MemoryExpr (Memory* Mem, long Offs, ObjData* O)
+/* Return an expression tree that encodes an offset into a memory area */
{
ExprNode* Root;
ExprNode* Expr = NewExprNode (O);
Expr->Op = EXPR_MEMAREA;
- Expr->V.MemArea = Mem;
+ Expr->V.Mem = Mem;
- Root = NewExprNode (O);
- Root->Op = EXPR_PLUS;
- Root->Left = Expr;
- Root->Right = LiteralExpr (Offs, O);
+ if (Offs != 0) {
+ Root = NewExprNode (O);
+ Root->Op = EXPR_PLUS;
+ Root->Left = Expr;
+ Root->Right = LiteralExpr (Offs, O);
+ } else {
+ Root = Expr;
+ }
return Root;
}
-ExprNode* SegExpr (Section* Sec, long Offs, ObjData* O)
+ExprNode* SegmentExpr (Segment* Seg, long Offs, ObjData* O)
/* Return an expression tree that encodes an offset into a segment */
{
ExprNode* Root;
ExprNode* Expr = NewExprNode (O);
Expr->Op = EXPR_SEGMENT;
+ Expr->V.Seg = Seg;
+
+ if (Offs != 0) {
+ Root = NewExprNode (O);
+ Root->Op = EXPR_PLUS;
+ Root->Left = Expr;
+ Root->Right = LiteralExpr (Offs, O);
+ } else {
+ Root = Expr;
+ }
+
+ return Root;
+}
+
+
+
+ExprNode* SectionExpr (Section* Sec, long Offs, ObjData* O)
+/* Return an expression tree that encodes an offset into a section */
+{
+ ExprNode* Root;
+
+ ExprNode* Expr = NewExprNode (O);
+ Expr->Op = EXPR_SECTION;
Expr->V.Sec = Sec;
- Root = NewExprNode (O);
- Root->Op = EXPR_PLUS;
- Root->Left = Expr;
- Root->Right = LiteralExpr (Offs, O);
+ if (Offs != 0) {
+ Root = NewExprNode (O);
+ Root->Op = EXPR_PLUS;
+ Root->Left = Expr;
+ Root->Right = LiteralExpr (Offs, O);
+ } else {
+ Root = Expr;
+ }
return Root;
}
Expr->V.ImpNum = Read16 (F);
break;
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
/* Read the segment number */
Expr->V.SegNum = Read8 (F);
break;
/* Import number must be identical */
return (E1->V.ImpNum == E2->V.ImpNum);
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
/* Section must be identical */
return (GetExprSection (E1) == GetExprSection (E2));
+ case EXPR_SEGMENT:
+ /* Segment must be identical */
+ return (E1->V.Seg == E2->V.Seg);
+
case EXPR_MEMAREA:
/* Memory area must be identical */
- return (E1->V.MemArea == E2->V.MemArea);
+ return (E1->V.Mem == E2->V.Mem );
default:
/* Not a leaf node */
/* Get the exported symbol for a symbol expression node */
Section* GetExprSection (ExprNode* Expr);
-/* Get the segment for a segment expression node */
+/* Get the segment for a section expression node */
long GetExprVal (ExprNode* Expr);
/* Get the value of a constant expression */
ExprNode* LiteralExpr (long Val, ObjData* O);
/* Return an expression tree that encodes the given literal value */
-ExprNode* MemExpr (Memory* Mem, long Offs, ObjData* O);
+ExprNode* MemoryExpr (Memory* Mem, long Offs, ObjData* O);
/* Return an expression tree that encodes an offset into the memory area */
-ExprNode* SegExpr (Section* Sec, long Offs, ObjData* O);
+ExprNode* SegmentExpr (Segment* Seg, long Offs, ObjData* O);
/* Return an expression tree that encodes an offset into a segment */
+ExprNode* SectionExpr (Section* Sec, long Offs, ObjData* O);
+/* Return an expression tree that encodes an offset into a section */
+
void DumpExpr (const ExprNode* Expr);
/* Dump an expression tree to stdout */
O65Desc* D; /* File format descriptor */
long Val; /* The offset value */
int TooComplex; /* Expression too complex */
- Section* SegRef; /* Section referenced if any */
+ Segment* SegRef; /* Segment reference if any */
+ Section* SecRef; /* Section reference if any */
ExtSym* ExtRef; /* External reference if any */
};
ED->Val = 0;
ED->TooComplex = 0;
ED->SegRef = 0;
+ ED->SecRef = 0;
ED->ExtRef = 0;
return ED;
}
/*****************************************************************************/
-/* Expression handling */
+/* Expression handling */
/*****************************************************************************/
}
break;
- case EXPR_SEGMENT:
- if (D->SegRef) {
+ case EXPR_SECTION:
+ if (D->SecRef) {
/* We cannot handle more than one segment reference in o65 */
D->TooComplex = 1;
} else {
/* Remember the segment reference */
- D->SegRef = GetExprSection (Expr);
+ D->SecRef = GetExprSection (Expr);
/* Add the offset of the section to the constant value */
- Val = D->SegRef->Offs + D->SegRef->Seg->PC;
+ Val = D->SecRef->Offs + D->SecRef->Seg->PC;
+ if (Sign < 0) {
+ D->Val -= Val;
+ } else {
+ D->Val += Val;
+ }
+ }
+ break;
+
+ case EXPR_SEGMENT:
+ if (D->SegRef) {
+ /* We cannot handle more than one segment reference in o65 */
+ D->TooComplex = 1;
+ } else {
+ /* Remember the segment reference */
+ D->SegRef = Expr->V.Seg;
+ /* Add the offset of the segment to the constant value */
+ Val = D->SegRef->PC;
if (Sign < 0) {
D->Val -= Val;
} else {
* table.
*/
{
- long Diff;
- long BinVal;
- ExprNode* Expr;
- ExprDesc ED;
+ long Diff;
+ unsigned RefCount;
+ long BinVal;
+ ExprNode* Expr;
+ ExprDesc ED;
unsigned char RelocType;
/* Cast the Data pointer to its real type, an O65Desc */
/* Recursively collect information about this expression */
O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
- /* We cannot handle both, an imported symbol and a segment ref */
- if (ED.SegRef != 0 && ED.ExtRef != 0) {
+ /* We cannot handle more than one external reference */
+ RefCount = (ED.SegRef != 0) + (ED.SecRef != 0) + (ED.ExtRef != 0);
+ if (RefCount > 1) {
ED.TooComplex = 1;
}
return SEG_EXPR_TOO_COMPLEX;
}
- /* Safety: Check that we are really referencing a symbol or a segment */
- CHECK (ED.SegRef != 0 || ED.ExtRef != 0);
+ /* Safety: Check that we have exactly one reference */
+ CHECK (RefCount == 1);
/* Write out the offset that goes into the segment. */
BinVal = ED.Val;
switch (Size) {
case 1:
- RelocType = O65RELOC_LOW;
- break;
+ RelocType = O65RELOC_LOW;
+ break;
case 2:
RelocType = O65RELOC_WORD;
- break;
+ break;
case 3:
- RelocType = O65RELOC_SEGADR;
- break;
+ RelocType = O65RELOC_SEGADR;
+ break;
case 4:
- /* 4 byte expression not supported by o65 */
- return SEG_EXPR_TOO_COMPLEX;
+ /* 4 byte expression not supported by o65 */
+ return SEG_EXPR_TOO_COMPLEX;
default:
- Internal ("O65WriteExpr: Invalid expression size: %u", Size);
- RelocType = 0; /* Avoid gcc warnings */
+ Internal ("O65WriteExpr: Invalid expression size: %u", Size);
+ RelocType = 0; /* Avoid gcc warnings */
}
}
/* Determine which segment we're referencing */
- if (ED.ExtRef) {
+ if (ED.SegRef || ED.SecRef) {
+
+ const SegDesc* Seg;
+
+ /* Segment or section reference. */
+ if (ED.SecRef) {
+ /* Get segment from section */
+ ED.SegRef = ED.SecRef->Seg;
+ }
+
+ /* Search for the segment and map it to it's o65 segmentID */
+ Seg = O65FindSeg (D, ED.SegRef);
+ if (Seg == 0) {
+ /* For some reason, we didn't find this segment in the list of
+ * segments written to the o65 file.
+ */
+ return SEG_EXPR_INVALID;
+ }
+ RelocType |= O65SegType (Seg);
+ O65RelocPutByte (D->CurReloc, RelocType);
+
+ /* Output additional data if needed */
+ switch (RelocType & O65RELOC_MASK) {
+ case O65RELOC_HIGH:
+ O65RelocPutByte (D->CurReloc, ED.Val & 0xFF);
+ break;
+ case O65RELOC_SEG:
+ O65RelocPutWord (D->CurReloc, ED.Val & 0xFFFF);
+ break;
+ }
+
+ } else if (ED.ExtRef) {
/* Imported symbol */
RelocType |= O65SEG_UNDEF;
O65RelocPutByte (D->CurReloc, RelocType);
/* Put the number of the imported symbol into the table */
O65RelocPutWord (D->CurReloc, ExtSymNum (ED.ExtRef));
+
} else {
- /* Segment reference. Search for the segment and map it to it's
- * o65 segmentID
- */
- const SegDesc* Seg = O65FindSeg (D, ED.SegRef->Seg);
- if (Seg == 0) {
- /* For some reason, we didn't find this segment in the list of
- * segments written to the o65 file.
- */
- return SEG_EXPR_INVALID;
- }
- RelocType |= O65SegType (Seg);
- O65RelocPutByte (D->CurReloc, RelocType);
-
- /* Output additional data if needed */
- switch (RelocType & O65RELOC_MASK) {
- case O65RELOC_HIGH:
- O65RelocPutByte (D->CurReloc, ED.Val & 0xFF);
- break;
- case O65RELOC_SEG:
- O65RelocPutWord (D->CurReloc, ED.Val & 0xFFFF);
- break;
- }
+
+ /* OOPS - something bad happened */
+ Internal ("External reference not handled");
+
}
/* Success */
/* Recursively collect information about this expression */
O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
- /* We cannot handle expressions with imported symbols here */
- if (ED.ExtRef != 0) {
+ /* We cannot handle expressions with imported symbols, or expressions
+ * with more than one segment reference here
+ */
+ if (ED.ExtRef != 0 || (ED.SegRef != 0 && ED.SecRef != 0)) {
ED.TooComplex = 1;
}
}
/* Determine the segment id for the expression */
- if (ED.SegRef == 0) {
- /* Absolute value */
- SegmentID = O65SEG_ABS;
- } else {
- /* Segment reference. Search for the segment and map it to it's
- * o65 segmentID
- */
- const SegDesc* Seg = O65FindSeg (D, ED.SegRef->Seg);
+ if (ED.SegRef != 0 || ED.SecRef != 0) {
+
+ const SegDesc* Seg;
+
+ /* Segment or section reference */
+ if (ED.SecRef != 0) {
+ ED.SegRef = ED.SecRef->Seg; /* Get segment from section */
+ }
+
+ /* Search for the segment and map it to it's o65 segmentID */
+ Seg = O65FindSeg (D, ED.SegRef);
if (Seg == 0) {
/* For some reason, we didn't find this segment in the list of
* segments written to the o65 file.
Error ("Segment for symbol `%s' is undefined", Name);
}
SegmentID = O65SegType (Seg);
+
+ } else {
+
+ /* Absolute value */
+ SegmentID = O65SEG_ABS;
+
}
/* Write the name to the output file */