]> git.sur5r.net Git - cc65/commitdiff
Did some renaming and cleanup: Renamed EXPR_SEGMENT to EXPR_SECTION, since
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 14 Dec 2002 22:57:00 +0000 (22:57 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 14 Dec 2002 22:57:00 +0000 (22:57 +0000)
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
src/ca65/expr.c
src/common/exprdefs.h
src/ld65/condes.c
src/ld65/config.c
src/ld65/exports.c
src/ld65/exports.h
src/ld65/expr.c
src/ld65/expr.h
src/ld65/o65.c

index 94ae219c3652c4a7c85fb95399bc120b3e32628e..1925d6818907d5af1161c1d1485c2baeb13c6ad2 100644 (file)
@@ -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;
index 0c394b26b8ecaf77b4ed22faf53529bd4aa51c62..634836bde21287b7110cf32556cfec6367fbb1d0 100644 (file)
@@ -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;
 
index 4bf38bf7fd6f8de0d151788a17fe438fd9919cde..d0f9cd50badc93790f49ab6db12508dba3477b09 100644 (file)
 /* 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;
 };
 
index 68beb6f780fa63780163c292ab5201dc48996c60..cbe03f4cf5e6e3150b46a09dd0270c53d3849ccd 100644 (file)
@@ -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.
index 0faeb8e18e836c4124a17c5b81696966aaac3a94..cd9da9952187be9f22345b8f61130be6b58f51d1 100644 (file)
@@ -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);
index 6518bcaf917ab2a0d67a651fc6f3921544af73fa..7761a078a6b5bcf8d9b8f368559090044e9ce678 100644 (file)
@@ -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);
index 1a0e1a008f612756f828657fc41aa3458e6441f2..cad0313c09f7671759d5581aa792a112a951e4d8 100644 (file)
@@ -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);
index 57092d9f1613e8962fe58f18754f40e810bd812c..a59e1f2becd2696b76af6f6aa47616f68cca4637 100644 (file)
@@ -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 */
index a810d0228f55204a3d8b660c6ffd83c493889ad3..03b9a47861bfbccd30649cd968eb8b33688d684d 100644 (file)
@@ -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 */
 
index f6fe27b6187a4fb2214865062421fe8d6831155f..137784350a03eff05f93ce888c5e026620e2da86 100644 (file)
@@ -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 */