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
This commit is contained in:
parent
f47648ecfb
commit
0774fe273a
10 changed files with 236 additions and 125 deletions
|
@ -352,7 +352,7 @@ static void SkipExpr (unsigned char** Buf)
|
||||||
*Buf += 2;
|
*Buf += 2;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SECTION:
|
||||||
/* 8 bit segment number */
|
/* 8 bit segment number */
|
||||||
*Buf += 1;
|
*Buf += 1;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -971,7 +971,7 @@ ExprNode* CurrentPC (void)
|
||||||
if (RelocMode) {
|
if (RelocMode) {
|
||||||
/* Create SegmentBase + Offset */
|
/* Create SegmentBase + Offset */
|
||||||
Left = NewExprNode ();
|
Left = NewExprNode ();
|
||||||
Left->Op = EXPR_SEGMENT;
|
Left->Op = EXPR_SECTION;
|
||||||
Left->V.SegNum = GetSegNum ();
|
Left->V.SegNum = GetSegNum ();
|
||||||
|
|
||||||
Root = NewExprNode ();
|
Root = NewExprNode ();
|
||||||
|
@ -1011,7 +1011,7 @@ ExprNode* BranchExpr (unsigned Offs)
|
||||||
/* Create *+Offs */
|
/* Create *+Offs */
|
||||||
if (RelocMode) {
|
if (RelocMode) {
|
||||||
Left = NewExprNode ();
|
Left = NewExprNode ();
|
||||||
Left->Op = EXPR_SEGMENT;
|
Left->Op = EXPR_SECTION;
|
||||||
Left->V.SegNum = GetSegNum ();
|
Left->V.SegNum = GetSegNum ();
|
||||||
|
|
||||||
N = NewExprNode ();
|
N = NewExprNode ();
|
||||||
|
@ -1176,7 +1176,7 @@ static void CheckByteExpr (const ExprNode* N, int* IsByte)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SECTION:
|
||||||
if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
|
if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
|
||||||
*IsByte = 1;
|
*IsByte = 1;
|
||||||
}
|
}
|
||||||
|
@ -1416,7 +1416,7 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
|
||||||
Clone->V.Sym = Expr->V.Sym;
|
Clone->V.Sym = Expr->V.Sym;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SECTION:
|
||||||
Clone->V.SegNum = Expr->V.SegNum;
|
Clone->V.SegNum = Expr->V.SegNum;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1477,7 +1477,7 @@ static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
|
||||||
return Left;
|
return Left;
|
||||||
} else {
|
} else {
|
||||||
/* Check for SEG - SEG which is now possible */
|
/* 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) {
|
Left->V.SegNum == Right->V.SegNum) {
|
||||||
/* SEG - SEG, remove it completely */
|
/* SEG - SEG, remove it completely */
|
||||||
FreeExprNode (Left);
|
FreeExprNode (Left);
|
||||||
|
@ -1563,7 +1563,7 @@ ExprNode* CloneExpr (ExprNode* Expr)
|
||||||
Clone->V.Sym = Expr->V.Sym;
|
Clone->V.Sym = Expr->V.Sym;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SECTION:
|
||||||
Clone->V.SegNum = Expr->V.SegNum;
|
Clone->V.SegNum = Expr->V.SegNum;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1606,7 +1606,7 @@ void WriteExpr (ExprNode* Expr)
|
||||||
ObjWrite16 (GetSymIndex (Expr->V.Sym));
|
ObjWrite16 (GetSymIndex (Expr->V.Sym));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SECTION:
|
||||||
ObjWrite8 (Expr->V.SegNum);
|
ObjWrite8 (Expr->V.SegNum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -56,9 +56,10 @@
|
||||||
/* Leaf node codes */
|
/* Leaf node codes */
|
||||||
#define EXPR_LITERAL (EXPR_LEAFNODE | 0x01)
|
#define EXPR_LITERAL (EXPR_LEAFNODE | 0x01)
|
||||||
#define EXPR_SYMBOL (EXPR_LEAFNODE | 0x02)
|
#define EXPR_SYMBOL (EXPR_LEAFNODE | 0x02)
|
||||||
#define EXPR_SEGMENT (EXPR_LEAFNODE | 0x03)
|
#define EXPR_SECTION (EXPR_LEAFNODE | 0x03)
|
||||||
#define EXPR_MEMAREA (EXPR_LEAFNODE | 0x04) /* Linker only */
|
#define EXPR_SEGMENT (EXPR_LEAFNODE | 0x04) /* Linker only */
|
||||||
#define EXPR_ULABEL (EXPR_LEAFNODE | 0x05) /* Assembler 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 */
|
/* Binary operations, left and right hand sides are valid */
|
||||||
#define EXPR_PLUS (EXPR_BINARYNODE | 0x01)
|
#define EXPR_PLUS (EXPR_BINARYNODE | 0x01)
|
||||||
|
@ -110,8 +111,9 @@ struct ExprNode {
|
||||||
struct SymEntry* Sym; /* If this is a symbol */
|
struct SymEntry* Sym; /* If this is a symbol */
|
||||||
unsigned SegNum; /* If this is a segment */
|
unsigned SegNum; /* If this is a segment */
|
||||||
unsigned ImpNum; /* If this is an import */
|
unsigned ImpNum; /* If this is an import */
|
||||||
struct Memory* MemArea; /* If this is a memory area */
|
struct Memory* Mem; /* If this is a memory area */
|
||||||
struct Section* Sec; /* If segment and Obj is NULL */
|
struct Segment* Seg; /* If this is a segment */
|
||||||
|
struct Section* Sec; /* If section and Obj is NULL */
|
||||||
} V;
|
} V;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ static void ConDesCreateOne (ConDesDesc* CD)
|
||||||
/* Define the table start as an export, offset into section is zero
|
/* Define the table start as an export, offset into section is zero
|
||||||
* (the section only contains the table).
|
* (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
|
/* If we have a CountSym name given AND if it is referenced, define it
|
||||||
* with the number of elements in the table.
|
* with the number of elements in the table.
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "bitops.h"
|
#include "bitops.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
#include "xsprintf.h"
|
||||||
|
|
||||||
/* ld65 */
|
/* ld65 */
|
||||||
#include "bin.h"
|
#include "bin.h"
|
||||||
|
@ -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 */
|
/* Create the defines for a RUN segment */
|
||||||
{
|
{
|
||||||
char Buf [256];
|
char Buf [256];
|
||||||
|
|
||||||
sprintf (Buf, "__%s_RUN__", S->Name);
|
xsprintf (Buf, sizeof (Buf), "__%s_RUN__", S->Name);
|
||||||
CreateMemExport (Buf, M, Addr - M->Start);
|
CreateSegmentExport (Buf, S->Seg, 0);
|
||||||
sprintf (Buf, "__%s_SIZE__", S->Name);
|
xsprintf (Buf, sizeof (Buf), "__%s_SIZE__", S->Name);
|
||||||
CreateConstExport (Buf, S->Seg->Size);
|
CreateConstExport (Buf, S->Seg->Size);
|
||||||
S->Flags |= SF_RUN_DEF;
|
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 */
|
/* Create the defines for a LOAD segment */
|
||||||
{
|
{
|
||||||
char Buf [256];
|
char Buf [256];
|
||||||
|
|
||||||
sprintf (Buf, "__%s_LOAD__", S->Name);
|
xsprintf (Buf, sizeof (Buf), "__%s_LOAD__", S->Name);
|
||||||
CreateMemExport (Buf, M, Addr - M->Start);
|
CreateMemoryExport (Buf, M, S->Seg->PC - M->Start);
|
||||||
S->Flags |= SF_LOAD_DEF;
|
S->Flags |= SF_LOAD_DEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1486,10 +1487,10 @@ void CfgAssignSegments (void)
|
||||||
*/
|
*/
|
||||||
if (S->Load == M) {
|
if (S->Load == M) {
|
||||||
if ((S->Flags & SF_LOAD_DEF) == 0) {
|
if ((S->Flags & SF_LOAD_DEF) == 0) {
|
||||||
CreateLoadDefines (M, S, Addr);
|
CreateLoadDefines (M, S);
|
||||||
} else {
|
} else {
|
||||||
CHECK ((S->Flags & SF_RUN_DEF) == 0);
|
CHECK ((S->Flags & SF_RUN_DEF) == 0);
|
||||||
CreateRunDefines (M, S, Addr);
|
CreateRunDefines (S);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1498,10 +1499,10 @@ void CfgAssignSegments (void)
|
||||||
* have only one copy of the segment in the area.
|
* have only one copy of the segment in the area.
|
||||||
*/
|
*/
|
||||||
if (S->Run == M) {
|
if (S->Run == M) {
|
||||||
CreateRunDefines (M, S, Addr);
|
CreateRunDefines (S);
|
||||||
}
|
}
|
||||||
if (S->Load == M) {
|
if (S->Load == M) {
|
||||||
CreateLoadDefines (M, S, Addr);
|
CreateLoadDefines (M, S);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1517,7 +1518,7 @@ void CfgAssignSegments (void)
|
||||||
if (M->Flags & MF_DEFINE) {
|
if (M->Flags & MF_DEFINE) {
|
||||||
char Buf [256];
|
char Buf [256];
|
||||||
sprintf (Buf, "__%s_START__", M->Name);
|
sprintf (Buf, "__%s_START__", M->Name);
|
||||||
CreateMemExport (Buf, M, 0);
|
CreateMemoryExport (Buf, M, 0);
|
||||||
sprintf (Buf, "__%s_SIZE__", M->Name);
|
sprintf (Buf, "__%s_SIZE__", M->Name);
|
||||||
CreateConstExport (Buf, M->Size);
|
CreateConstExport (Buf, M->Size);
|
||||||
sprintf (Buf, "__%s_LAST__", M->Name);
|
sprintf (Buf, "__%s_LAST__", M->Name);
|
||||||
|
|
|
@ -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 an relative export for a memory area offset */
|
||||||
{
|
{
|
||||||
/* Create a new export */
|
/* Create a new export */
|
||||||
Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
|
Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
|
||||||
|
|
||||||
/* Assign the value */
|
/* Assign the value */
|
||||||
E->Expr = MemExpr (Mem, Offs, 0);
|
E->Expr = MemoryExpr (Mem, Offs, 0);
|
||||||
|
|
||||||
/* Insert the export */
|
/* Insert the export */
|
||||||
InsertExport (E);
|
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)
|
Export* CreateSegmentExport (const char* Name, Segment* Seg, unsigned long Offs)
|
||||||
/* Create a relative export to a segment (section) */
|
/* Create a relative export to a segment */
|
||||||
{
|
{
|
||||||
/* Create a new export */
|
/* Create a new export */
|
||||||
Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
|
Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
|
||||||
|
|
||||||
/* Assign the value */
|
/* 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 */
|
/* Insert the export */
|
||||||
InsertExport (E);
|
InsertExport (E);
|
||||||
|
|
|
@ -120,11 +120,14 @@ void InsertExport (Export* E);
|
||||||
Export* CreateConstExport (const char* Name, long Value);
|
Export* CreateConstExport (const char* Name, long Value);
|
||||||
/* Create an export for a literal date */
|
/* 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 */
|
/* Create an relative export for a memory area offset */
|
||||||
|
|
||||||
Export* CreateSegExport (const char* Name, Section* S, unsigned long Offs);
|
Export* CreateSegmentExport (const char* Name, Segment* Seg, unsigned long Offs);
|
||||||
/* Create a relative export to a segment (section) */
|
/* 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);
|
Export* FindExport (const char* Name);
|
||||||
/* Check for an identifier in the list. Return 0 if not found, otherwise
|
/* Check for an identifier in the list. Return 0 if not found, otherwise
|
||||||
|
|
|
@ -204,10 +204,10 @@ Export* GetExprExport (ExprNode* Expr)
|
||||||
|
|
||||||
|
|
||||||
Section* GetExprSection (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 */
|
/* Check that this is really a section node */
|
||||||
PRECONDITION (Expr->Op == EXPR_SEGMENT);
|
PRECONDITION (Expr->Op == EXPR_SECTION);
|
||||||
|
|
||||||
/* If we have an object file, get the section from it, otherwise
|
/* If we have an object file, get the section from it, otherwise
|
||||||
* (internally generated expressions), get the section from the
|
* (internally generated expressions), get the section from the
|
||||||
|
@ -252,12 +252,15 @@ long GetExprVal (ExprNode* Expr)
|
||||||
}
|
}
|
||||||
return Val;
|
return Val;
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SECTION:
|
||||||
S = GetExprSection (Expr);
|
S = GetExprSection (Expr);
|
||||||
return S->Offs + S->Seg->PC;
|
return S->Offs + S->Seg->PC;
|
||||||
|
|
||||||
|
case EXPR_SEGMENT:
|
||||||
|
return Expr->V.Seg->PC;
|
||||||
|
|
||||||
case EXPR_MEMAREA:
|
case EXPR_MEMAREA:
|
||||||
return Expr->V.MemArea->Start;
|
return Expr->V.Mem->Start;
|
||||||
|
|
||||||
case EXPR_PLUS:
|
case EXPR_PLUS:
|
||||||
return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
|
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)
|
ExprNode* MemoryExpr (Memory* Mem, long Offs, ObjData* O)
|
||||||
/* Return an expression tree that encodes an offset into the memory area */
|
/* Return an expression tree that encodes an offset into a memory area */
|
||||||
{
|
{
|
||||||
ExprNode* Root;
|
ExprNode* Root;
|
||||||
|
|
||||||
ExprNode* Expr = NewExprNode (O);
|
ExprNode* Expr = NewExprNode (O);
|
||||||
Expr->Op = EXPR_MEMAREA;
|
Expr->Op = EXPR_MEMAREA;
|
||||||
Expr->V.MemArea = Mem;
|
Expr->V.Mem = Mem;
|
||||||
|
|
||||||
|
if (Offs != 0) {
|
||||||
Root = NewExprNode (O);
|
Root = NewExprNode (O);
|
||||||
Root->Op = EXPR_PLUS;
|
Root->Op = EXPR_PLUS;
|
||||||
Root->Left = Expr;
|
Root->Left = Expr;
|
||||||
Root->Right = LiteralExpr (Offs, O);
|
Root->Right = LiteralExpr (Offs, O);
|
||||||
|
} else {
|
||||||
|
Root = Expr;
|
||||||
|
}
|
||||||
|
|
||||||
return Root;
|
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 */
|
/* Return an expression tree that encodes an offset into a segment */
|
||||||
{
|
{
|
||||||
ExprNode* Root;
|
ExprNode* Root;
|
||||||
|
|
||||||
ExprNode* Expr = NewExprNode (O);
|
ExprNode* Expr = NewExprNode (O);
|
||||||
Expr->Op = EXPR_SEGMENT;
|
Expr->Op = EXPR_SEGMENT;
|
||||||
Expr->V.Sec = Sec;
|
Expr->V.Seg = Seg;
|
||||||
|
|
||||||
|
if (Offs != 0) {
|
||||||
Root = NewExprNode (O);
|
Root = NewExprNode (O);
|
||||||
Root->Op = EXPR_PLUS;
|
Root->Op = EXPR_PLUS;
|
||||||
Root->Left = Expr;
|
Root->Left = Expr;
|
||||||
Root->Right = LiteralExpr (Offs, O);
|
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;
|
||||||
|
|
||||||
|
if (Offs != 0) {
|
||||||
|
Root = NewExprNode (O);
|
||||||
|
Root->Op = EXPR_PLUS;
|
||||||
|
Root->Left = Expr;
|
||||||
|
Root->Right = LiteralExpr (Offs, O);
|
||||||
|
} else {
|
||||||
|
Root = Expr;
|
||||||
|
}
|
||||||
|
|
||||||
return Root;
|
return Root;
|
||||||
}
|
}
|
||||||
|
@ -437,7 +471,7 @@ ExprNode* ReadExpr (FILE* F, ObjData* O)
|
||||||
Expr->V.ImpNum = Read16 (F);
|
Expr->V.ImpNum = Read16 (F);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SECTION:
|
||||||
/* Read the segment number */
|
/* Read the segment number */
|
||||||
Expr->V.SegNum = Read8 (F);
|
Expr->V.SegNum = Read8 (F);
|
||||||
break;
|
break;
|
||||||
|
@ -488,13 +522,17 @@ int EqualExpr (ExprNode* E1, ExprNode* E2)
|
||||||
/* Import number must be identical */
|
/* Import number must be identical */
|
||||||
return (E1->V.ImpNum == E2->V.ImpNum);
|
return (E1->V.ImpNum == E2->V.ImpNum);
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SECTION:
|
||||||
/* Section must be identical */
|
/* Section must be identical */
|
||||||
return (GetExprSection (E1) == GetExprSection (E2));
|
return (GetExprSection (E1) == GetExprSection (E2));
|
||||||
|
|
||||||
|
case EXPR_SEGMENT:
|
||||||
|
/* Segment must be identical */
|
||||||
|
return (E1->V.Seg == E2->V.Seg);
|
||||||
|
|
||||||
case EXPR_MEMAREA:
|
case EXPR_MEMAREA:
|
||||||
/* Memory area must be identical */
|
/* Memory area must be identical */
|
||||||
return (E1->V.MemArea == E2->V.MemArea);
|
return (E1->V.Mem == E2->V.Mem );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Not a leaf node */
|
/* Not a leaf node */
|
||||||
|
|
|
@ -69,7 +69,7 @@ Export* GetExprExport (ExprNode* Expr);
|
||||||
/* Get the exported symbol for a symbol expression node */
|
/* Get the exported symbol for a symbol expression node */
|
||||||
|
|
||||||
Section* GetExprSection (ExprNode* Expr);
|
Section* GetExprSection (ExprNode* Expr);
|
||||||
/* Get the segment for a segment expression node */
|
/* Get the segment for a section expression node */
|
||||||
|
|
||||||
long GetExprVal (ExprNode* Expr);
|
long GetExprVal (ExprNode* Expr);
|
||||||
/* Get the value of a constant expression */
|
/* Get the value of a constant expression */
|
||||||
|
@ -77,12 +77,15 @@ long GetExprVal (ExprNode* Expr);
|
||||||
ExprNode* LiteralExpr (long Val, ObjData* O);
|
ExprNode* LiteralExpr (long Val, ObjData* O);
|
||||||
/* Return an expression tree that encodes the given literal value */
|
/* 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 */
|
/* 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 */
|
/* 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);
|
void DumpExpr (const ExprNode* Expr);
|
||||||
/* Dump an expression tree to stdout */
|
/* Dump an expression tree to stdout */
|
||||||
|
|
||||||
|
|
104
src/ld65/o65.c
104
src/ld65/o65.c
|
@ -173,7 +173,8 @@ struct ExprDesc {
|
||||||
O65Desc* D; /* File format descriptor */
|
O65Desc* D; /* File format descriptor */
|
||||||
long Val; /* The offset value */
|
long Val; /* The offset value */
|
||||||
int TooComplex; /* Expression too complex */
|
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 */
|
ExtSym* ExtRef; /* External reference if any */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,6 +193,7 @@ static ExprDesc* InitExprDesc (ExprDesc* ED, O65Desc* D)
|
||||||
ED->Val = 0;
|
ED->Val = 0;
|
||||||
ED->TooComplex = 0;
|
ED->TooComplex = 0;
|
||||||
ED->SegRef = 0;
|
ED->SegRef = 0;
|
||||||
|
ED->SecRef = 0;
|
||||||
ED->ExtRef = 0;
|
ED->ExtRef = 0;
|
||||||
return ED;
|
return ED;
|
||||||
}
|
}
|
||||||
|
@ -328,15 +330,32 @@ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
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->SecRef = GetExprSection (Expr);
|
||||||
|
/* Add the offset of the section to the constant value */
|
||||||
|
Val = D->SecRef->Offs + D->SecRef->Seg->PC;
|
||||||
|
if (Sign < 0) {
|
||||||
|
D->Val -= Val;
|
||||||
|
} else {
|
||||||
|
D->Val += Val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SEGMENT:
|
||||||
if (D->SegRef) {
|
if (D->SegRef) {
|
||||||
/* We cannot handle more than one segment reference in o65 */
|
/* We cannot handle more than one segment reference in o65 */
|
||||||
D->TooComplex = 1;
|
D->TooComplex = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Remember the segment reference */
|
/* Remember the segment reference */
|
||||||
D->SegRef = GetExprSection (Expr);
|
D->SegRef = Expr->V.Seg;
|
||||||
/* Add the offset of the section to the constant value */
|
/* Add the offset of the segment to the constant value */
|
||||||
Val = D->SegRef->Offs + D->SegRef->Seg->PC;
|
Val = D->SegRef->PC;
|
||||||
if (Sign < 0) {
|
if (Sign < 0) {
|
||||||
D->Val -= Val;
|
D->Val -= Val;
|
||||||
} else {
|
} else {
|
||||||
|
@ -523,6 +542,7 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size,
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
long Diff;
|
long Diff;
|
||||||
|
unsigned RefCount;
|
||||||
long BinVal;
|
long BinVal;
|
||||||
ExprNode* Expr;
|
ExprNode* Expr;
|
||||||
ExprDesc ED;
|
ExprDesc ED;
|
||||||
|
@ -564,8 +584,9 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size,
|
||||||
/* Recursively collect information about this expression */
|
/* Recursively collect information about this expression */
|
||||||
O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
|
O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
|
||||||
|
|
||||||
/* We cannot handle both, an imported symbol and a segment ref */
|
/* We cannot handle more than one external reference */
|
||||||
if (ED.SegRef != 0 && ED.ExtRef != 0) {
|
RefCount = (ED.SegRef != 0) + (ED.SecRef != 0) + (ED.ExtRef != 0);
|
||||||
|
if (RefCount > 1) {
|
||||||
ED.TooComplex = 1;
|
ED.TooComplex = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,8 +595,8 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size,
|
||||||
return SEG_EXPR_TOO_COMPLEX;
|
return SEG_EXPR_TOO_COMPLEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Safety: Check that we are really referencing a symbol or a segment */
|
/* Safety: Check that we have exactly one reference */
|
||||||
CHECK (ED.SegRef != 0 || ED.ExtRef != 0);
|
CHECK (RefCount == 1);
|
||||||
|
|
||||||
/* Write out the offset that goes into the segment. */
|
/* Write out the offset that goes into the segment. */
|
||||||
BinVal = ED.Val;
|
BinVal = ED.Val;
|
||||||
|
@ -624,17 +645,18 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine which segment we're referencing */
|
/* Determine which segment we're referencing */
|
||||||
if (ED.ExtRef) {
|
if (ED.SegRef || ED.SecRef) {
|
||||||
/* Imported symbol */
|
|
||||||
RelocType |= O65SEG_UNDEF;
|
const SegDesc* Seg;
|
||||||
O65RelocPutByte (D->CurReloc, RelocType);
|
|
||||||
/* Put the number of the imported symbol into the table */
|
/* Segment or section reference. */
|
||||||
O65RelocPutWord (D->CurReloc, ExtSymNum (ED.ExtRef));
|
if (ED.SecRef) {
|
||||||
} else {
|
/* Get segment from section */
|
||||||
/* Segment reference. Search for the segment and map it to it's
|
ED.SegRef = ED.SecRef->Seg;
|
||||||
* o65 segmentID
|
}
|
||||||
*/
|
|
||||||
const SegDesc* Seg = O65FindSeg (D, ED.SegRef->Seg);
|
/* Search for the segment and map it to it's o65 segmentID */
|
||||||
|
Seg = O65FindSeg (D, ED.SegRef);
|
||||||
if (Seg == 0) {
|
if (Seg == 0) {
|
||||||
/* For some reason, we didn't find this segment in the list of
|
/* For some reason, we didn't find this segment in the list of
|
||||||
* segments written to the o65 file.
|
* segments written to the o65 file.
|
||||||
|
@ -653,6 +675,19 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size,
|
||||||
O65RelocPutWord (D->CurReloc, ED.Val & 0xFFFF);
|
O65RelocPutWord (D->CurReloc, ED.Val & 0xFFFF);
|
||||||
break;
|
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 {
|
||||||
|
|
||||||
|
/* OOPS - something bad happened */
|
||||||
|
Internal ("External reference not handled");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
|
@ -843,8 +878,10 @@ static void O65WriteExports (O65Desc* D)
|
||||||
/* Recursively collect information about this expression */
|
/* Recursively collect information about this expression */
|
||||||
O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
|
O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
|
||||||
|
|
||||||
/* We cannot handle expressions with imported symbols here */
|
/* We cannot handle expressions with imported symbols, or expressions
|
||||||
if (ED.ExtRef != 0) {
|
* with more than one segment reference here
|
||||||
|
*/
|
||||||
|
if (ED.ExtRef != 0 || (ED.SegRef != 0 && ED.SecRef != 0)) {
|
||||||
ED.TooComplex = 1;
|
ED.TooComplex = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,14 +891,17 @@ static void O65WriteExports (O65Desc* D)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine the segment id for the expression */
|
/* Determine the segment id for the expression */
|
||||||
if (ED.SegRef == 0) {
|
if (ED.SegRef != 0 || ED.SecRef != 0) {
|
||||||
/* Absolute value */
|
|
||||||
SegmentID = O65SEG_ABS;
|
const SegDesc* Seg;
|
||||||
} else {
|
|
||||||
/* Segment reference. Search for the segment and map it to it's
|
/* Segment or section reference */
|
||||||
* o65 segmentID
|
if (ED.SecRef != 0) {
|
||||||
*/
|
ED.SegRef = ED.SecRef->Seg; /* Get segment from section */
|
||||||
const SegDesc* Seg = O65FindSeg (D, ED.SegRef->Seg);
|
}
|
||||||
|
|
||||||
|
/* Search for the segment and map it to it's o65 segmentID */
|
||||||
|
Seg = O65FindSeg (D, ED.SegRef);
|
||||||
if (Seg == 0) {
|
if (Seg == 0) {
|
||||||
/* For some reason, we didn't find this segment in the list of
|
/* For some reason, we didn't find this segment in the list of
|
||||||
* segments written to the o65 file.
|
* segments written to the o65 file.
|
||||||
|
@ -869,6 +909,12 @@ static void O65WriteExports (O65Desc* D)
|
||||||
Error ("Segment for symbol `%s' is undefined", Name);
|
Error ("Segment for symbol `%s' is undefined", Name);
|
||||||
}
|
}
|
||||||
SegmentID = O65SegType (Seg);
|
SegmentID = O65SegType (Seg);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Absolute value */
|
||||||
|
SegmentID = O65SEG_ABS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the name to the output file */
|
/* Write the name to the output file */
|
||||||
|
|
Loading…
Add table
Reference in a new issue