From 0774fe273affa9156915c81e6e892fd3565d5d93 Mon Sep 17 00:00:00 2001 From: cuz Date: Sat, 14 Dec 2002 22:57:00 +0000 Subject: [PATCH] Did some renaming and cleanup: Renamed EXPR_SEGMENT to EXPR_SECTION, since this is what it really is. Added a real EXPR_SECTION which is now used in the linker to represent the run address of a segment, provided that it is requested to be defined. Changed some named in use of EXPR_MEMAREA. Added handling of the new EXPR_SEGMENT to both, the binary and o65 output format. git-svn-id: svn://svn.cc65.org/cc65/trunk@1769 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ar65/library.c | 2 +- src/ca65/expr.c | 14 ++-- src/common/exprdefs.h | 18 ++--- src/ld65/condes.c | 2 +- src/ld65/config.c | 31 +++++---- src/ld65/exports.c | 28 ++++++-- src/ld65/exports.h | 11 +-- src/ld65/expr.c | 88 ++++++++++++++++------- src/ld65/expr.h | 9 ++- src/ld65/o65.c | 158 +++++++++++++++++++++++++++--------------- 10 files changed, 236 insertions(+), 125 deletions(-) diff --git a/src/ar65/library.c b/src/ar65/library.c index 94ae219c3..1925d6818 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -352,7 +352,7 @@ static void SkipExpr (unsigned char** Buf) *Buf += 2; return; - case EXPR_SEGMENT: + case EXPR_SECTION: /* 8 bit segment number */ *Buf += 1; return; diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 0c394b26b..634836bde 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -971,7 +971,7 @@ ExprNode* CurrentPC (void) if (RelocMode) { /* Create SegmentBase + Offset */ Left = NewExprNode (); - Left->Op = EXPR_SEGMENT; + Left->Op = EXPR_SECTION; Left->V.SegNum = GetSegNum (); Root = NewExprNode (); @@ -1011,7 +1011,7 @@ ExprNode* BranchExpr (unsigned Offs) /* Create *+Offs */ if (RelocMode) { Left = NewExprNode (); - Left->Op = EXPR_SEGMENT; + Left->Op = EXPR_SECTION; Left->V.SegNum = GetSegNum (); N = NewExprNode (); @@ -1176,7 +1176,7 @@ static void CheckByteExpr (const ExprNode* N, int* IsByte) } break; - case EXPR_SEGMENT: + case EXPR_SECTION: if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) { *IsByte = 1; } @@ -1416,7 +1416,7 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone) Clone->V.Sym = Expr->V.Sym; break; - case EXPR_SEGMENT: + case EXPR_SECTION: Clone->V.SegNum = Expr->V.SegNum; break; @@ -1477,7 +1477,7 @@ static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign) 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); @@ -1563,7 +1563,7 @@ ExprNode* CloneExpr (ExprNode* Expr) Clone->V.Sym = Expr->V.Sym; break; - case EXPR_SEGMENT: + case EXPR_SECTION: Clone->V.SegNum = Expr->V.SegNum; break; @@ -1606,7 +1606,7 @@ void WriteExpr (ExprNode* Expr) ObjWrite16 (GetSymIndex (Expr->V.Sym)); break; - case EXPR_SEGMENT: + case EXPR_SECTION: ObjWrite8 (Expr->V.SegNum); break; diff --git a/src/common/exprdefs.h b/src/common/exprdefs.h index 4bf38bf7f..d0f9cd50b 100644 --- a/src/common/exprdefs.h +++ b/src/common/exprdefs.h @@ -56,9 +56,10 @@ /* 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) @@ -100,18 +101,19 @@ /* 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; }; diff --git a/src/ld65/condes.c b/src/ld65/condes.c index 68beb6f78..cbe03f4cf 100644 --- a/src/ld65/condes.c +++ b/src/ld65/condes.c @@ -175,7 +175,7 @@ static void ConDesCreateOne (ConDesDesc* CD) /* 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. diff --git a/src/ld65/config.c b/src/ld65/config.c index 0faeb8e18..cd9da9952 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -43,6 +43,7 @@ #include "bitops.h" #include "print.h" #include "xmalloc.h" +#include "xsprintf.h" /* ld65 */ #include "bin.h" @@ -444,7 +445,7 @@ static void ParseMemory (void) break; case CFGTOK_SIZE: - FlagAttr (&M->Attr, MA_SIZE, "SIZE"); + FlagAttr (&M->Attr, MA_SIZE, "SIZE"); CfgAssureInt (); M->Size = CfgIVal; break; @@ -484,7 +485,7 @@ static void ParseMemory (void) case CFGTOK_FILLVAL: FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL"); - CfgAssureInt (); + CfgAssureInt (); CfgRangeCheck (0, 0xFF); M->FillVal = (unsigned char) CfgIVal; break; @@ -1388,27 +1389,27 @@ void CfgRead (void) -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; } @@ -1486,22 +1487,22 @@ void CfgAssignSegments (void) */ 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); } } } @@ -1517,7 +1518,7 @@ void CfgAssignSegments (void) 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); diff --git a/src/ld65/exports.c b/src/ld65/exports.c index 6518bcaf9..7761a078a 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -364,14 +364,14 @@ Export* CreateConstExport (const char* Name, long Value) -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); @@ -382,14 +382,32 @@ Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs) -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); diff --git a/src/ld65/exports.h b/src/ld65/exports.h index 1a0e1a008..cad0313c0 100644 --- a/src/ld65/exports.h +++ b/src/ld65/exports.h @@ -120,11 +120,14 @@ void InsertExport (Export* 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 @@ -137,7 +140,7 @@ int IsUnresolved (const char* Name); 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); diff --git a/src/ld65/expr.c b/src/ld65/expr.c index 57092d9f1..a59e1f2be 100644 --- a/src/ld65/expr.c +++ b/src/ld65/expr.c @@ -204,10 +204,10 @@ Export* GetExprExport (ExprNode* Expr) 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 @@ -243,21 +243,24 @@ long GetExprVal (ExprNode* Expr) * 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); @@ -371,38 +374,69 @@ ExprNode* LiteralExpr (long Val, ObjData* O) -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; } @@ -437,7 +471,7 @@ ExprNode* ReadExpr (FILE* F, ObjData* O) Expr->V.ImpNum = Read16 (F); break; - case EXPR_SEGMENT: + case EXPR_SECTION: /* Read the segment number */ Expr->V.SegNum = Read8 (F); break; @@ -488,13 +522,17 @@ int EqualExpr (ExprNode* E1, ExprNode* E2) /* 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 */ diff --git a/src/ld65/expr.h b/src/ld65/expr.h index a810d0228..03b9a4786 100644 --- a/src/ld65/expr.h +++ b/src/ld65/expr.h @@ -69,7 +69,7 @@ Export* GetExprExport (ExprNode* Expr); /* 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 */ @@ -77,12 +77,15 @@ long GetExprVal (ExprNode* Expr); 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 */ diff --git a/src/ld65/o65.c b/src/ld65/o65.c index f6fe27b61..137784350 100644 --- a/src/ld65/o65.c +++ b/src/ld65/o65.c @@ -173,7 +173,8 @@ struct ExprDesc { 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 */ }; @@ -192,6 +193,7 @@ static ExprDesc* InitExprDesc (ExprDesc* ED, O65Desc* D) ED->Val = 0; ED->TooComplex = 0; ED->SegRef = 0; + ED->SecRef = 0; ED->ExtRef = 0; return ED; } @@ -277,7 +279,7 @@ static const SegDesc* O65FindSeg (const O65Desc* D, const Segment* S) /*****************************************************************************/ -/* Expression handling */ +/* Expression handling */ /*****************************************************************************/ @@ -328,15 +330,32 @@ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign) } 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 { @@ -522,10 +541,11 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, * 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 */ @@ -564,8 +584,9 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, /* 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; } @@ -574,8 +595,8 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, 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; @@ -602,57 +623,71 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, 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 */ @@ -843,8 +878,10 @@ static void O65WriteExports (O65Desc* D) /* 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; } @@ -854,14 +891,17 @@ static void O65WriteExports (O65Desc* D) } /* 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. @@ -869,6 +909,12 @@ static void O65WriteExports (O65Desc* D) Error ("Segment for symbol `%s' is undefined", Name); } SegmentID = O65SegType (Seg); + + } else { + + /* Absolute value */ + SegmentID = O65SEG_ABS; + } /* Write the name to the output file */ -- 2.39.5