1
0
mirror of https://github.com/cc65/cc65.git synced 2024-07-06 13:29:01 +00:00

Added handling of memory areas references in expressions for o65

git-svn-id: svn://svn.cc65.org/cc65/trunk@2453 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2003-09-27 19:53:09 +00:00
parent b069a6ae70
commit 8949233151

View File

@ -35,6 +35,7 @@
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <time.h>
@ -175,6 +176,7 @@ struct ExprDesc {
O65Desc* D; /* File format descriptor */
long Val; /* The offset value */
int TooComplex; /* Expression too complex */
Memory* MemRef; /* Memory reference if any */
Segment* SegRef; /* Segment reference if any */
Section* SecRef; /* Section reference if any */
ExtSym* ExtRef; /* External reference if any */
@ -194,6 +196,7 @@ static ExprDesc* InitExprDesc (ExprDesc* ED, O65Desc* D)
ED->D = D;
ED->Val = 0;
ED->TooComplex = 0;
ED->MemRef = 0;
ED->SegRef = 0;
ED->SecRef = 0;
ED->ExtRef = 0;
@ -236,6 +239,60 @@ static unsigned O65SegType (const SegDesc* S)
static void CvtMemoryToSegment (ExprDesc* ED)
/* Convert a memory area into a segment by searching the list of run segments
* in this memory area and assigning the nearest one.
*/
{
/* Get the memory area from the expression */
Memory* M = ED->MemRef;
/* Get the list of segments in this memory area */
MemListNode* N = M->SegList;
/* Remember the "nearest" segment and its offset */
Segment* Nearest = 0;
unsigned long Offs = ULONG_MAX;
/* Walk over all segments */
while (N != 0) {
/* Get the segment from this node and check if it's a run segment */
SegDesc* S = N->Seg;
if (S->Run == M) {
unsigned long O;
/* Get the segment from the segment descriptor */
Segment* Seg = S->Seg;
/* Check the PC. */
if ((long) Seg->PC <= ED->Val && (O = (ED->Val - Seg->PC)) < Offs) {
/* This is the nearest segment for now */
Offs = O;
Nearest = Seg;
/* If we found an exact match, don't look further */
if (Offs == 0) {
break;
}
}
}
/* Next segment */
N = N->Next;
}
/* If we found a segment, use it and adjust the offset */
if (Nearest) {
ED->SegRef = Nearest;
ED->MemRef = 0;
ED->Val -= Nearest->PC;
}
}
static const SegDesc* FindSeg (SegDesc** const List, unsigned Count, const Segment* S)
/* Search for a segment in the given list of segment descriptors and return
* the descriptor for a segment if we found it, and NULL if not.
@ -366,6 +423,25 @@ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign)
}
break;
case EXPR_MEMAREA:
if (D->MemRef) {
/* We cannot handle more than one memory reference in o65 */
D->TooComplex = 1;
} else {
/* Remember the memory area reference */
D->MemRef = Expr->V.Mem;
/* Add the start address of the memory area to the constant
* value
*/
Val = D->MemRef->Start;
if (Sign < 0) {
D->Val -= Val;
} else {
D->Val += Val;
}
}
break;
case EXPR_PLUS:
O65ParseExpr (Expr->Left, D, Sign);
O65ParseExpr (Expr->Right, D, Sign);
@ -587,11 +663,23 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size,
O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
/* We cannot handle more than one external reference */
RefCount = (ED.SegRef != 0) + (ED.SecRef != 0) + (ED.ExtRef != 0);
RefCount = (ED.MemRef != 0) + (ED.SegRef != 0) +
(ED.SecRef != 0) + (ED.ExtRef != 0);
if (RefCount > 1) {
ED.TooComplex = 1;
}
/* If we have a memory area reference, we need to convert it into a
* segment reference. If we cannot do that, we cannot handle the
* expression.
*/
if (ED.MemRef) {
CvtMemoryToSegment (&ED);
if (ED.SegRef == 0) {
return SEG_EXPR_TOO_COMPLEX;
}
}
/* Bail out if we cannot handle the expression */
if (ED.TooComplex) {
return SEG_EXPR_TOO_COMPLEX;