mirror of
https://github.com/cc65/cc65.git
synced 2025-01-13 09:31:53 +00:00
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
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
158
src/ld65/o65.c
158
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:
|
||||
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:
|
||||
if (D->SegRef) {
|
||||
/* We cannot handle more than one segment reference in o65 */
|
||||
D->TooComplex = 1;
|
||||
} else {
|
||||
/* Remember the segment reference */
|
||||
D->SegRef = GetExprSection (Expr);
|
||||
/* Add the offset of the section to the constant value */
|
||||
Val = D->SegRef->Offs + D->SegRef->Seg->PC;
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* 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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user