mirror of
https://github.com/cc65/cc65.git
synced 2024-12-26 08:32:00 +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:
parent
b069a6ae70
commit
8949233151
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -175,6 +176,7 @@ 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 */
|
||||||
|
Memory* MemRef; /* Memory reference if any */
|
||||||
Segment* SegRef; /* Segment reference if any */
|
Segment* SegRef; /* Segment reference if any */
|
||||||
Section* SecRef; /* Section reference if any */
|
Section* SecRef; /* Section reference if any */
|
||||||
ExtSym* ExtRef; /* External reference if any */
|
ExtSym* ExtRef; /* External reference if any */
|
||||||
@ -194,6 +196,7 @@ static ExprDesc* InitExprDesc (ExprDesc* ED, O65Desc* D)
|
|||||||
ED->D = D;
|
ED->D = D;
|
||||||
ED->Val = 0;
|
ED->Val = 0;
|
||||||
ED->TooComplex = 0;
|
ED->TooComplex = 0;
|
||||||
|
ED->MemRef = 0;
|
||||||
ED->SegRef = 0;
|
ED->SegRef = 0;
|
||||||
ED->SecRef = 0;
|
ED->SecRef = 0;
|
||||||
ED->ExtRef = 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)
|
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
|
/* 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.
|
* 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;
|
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:
|
case EXPR_PLUS:
|
||||||
O65ParseExpr (Expr->Left, D, Sign);
|
O65ParseExpr (Expr->Left, D, Sign);
|
||||||
O65ParseExpr (Expr->Right, 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);
|
O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
|
||||||
|
|
||||||
/* We cannot handle more than one external reference */
|
/* 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) {
|
if (RefCount > 1) {
|
||||||
ED.TooComplex = 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 */
|
/* Bail out if we cannot handle the expression */
|
||||||
if (ED.TooComplex) {
|
if (ED.TooComplex) {
|
||||||
return SEG_EXPR_TOO_COMPLEX;
|
return SEG_EXPR_TOO_COMPLEX;
|
||||||
|
Loading…
Reference in New Issue
Block a user