mirror of
https://github.com/cc65/cc65.git
synced 2025-01-10 19:29:45 +00:00
Several improvements and a few bug fixes
git-svn-id: svn://svn.cc65.org/cc65/trunk@3339 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
218e722b91
commit
49d1a47269
@ -226,7 +226,7 @@ static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
|
|||||||
SymRef = ED->SymRef + ED->SymCount++;
|
SymRef = ED->SymRef + ED->SymCount++;
|
||||||
|
|
||||||
/* Initialize the new struct and return it */
|
/* Initialize the new struct and return it */
|
||||||
SymRef->Count = 1;
|
SymRef->Count = 0;
|
||||||
SymRef->Ref = Sym;
|
SymRef->Ref = Sym;
|
||||||
return SymRef;
|
return SymRef;
|
||||||
}
|
}
|
||||||
@ -335,6 +335,20 @@ static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void ED_NegRefs (ExprDesc* D)
|
||||||
|
/* Negate the references in ED */
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
for (I = 0; I < D->SymCount; ++I) {
|
||||||
|
D->SymRef[I].Count = -D->SymRef[I].Count;
|
||||||
|
}
|
||||||
|
for (I = 0; I < D->SecCount; ++I) {
|
||||||
|
D->SecRef[I].Count = -D->SecRef[I].Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
|
static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
|
||||||
/* Calculate ED = ED + Right, update address size in ED */
|
/* Calculate ED = ED + Right, update address size in ED */
|
||||||
{
|
{
|
||||||
@ -345,6 +359,19 @@ static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void ED_Sub (ExprDesc* ED, const ExprDesc* Right)
|
||||||
|
/* Calculate ED = ED - Right, update address size in ED */
|
||||||
|
{
|
||||||
|
ExprDesc D = *Right; /* Temporary */
|
||||||
|
ED_NegRefs (&D);
|
||||||
|
|
||||||
|
ED->Val -= Right->Val;
|
||||||
|
ED_MergeRefs (ED, &D); /* Merge negatives */
|
||||||
|
ED_MergeAddrSize (ED, Right);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
|
static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
|
||||||
/* Calculate ED = ED * Right, update address size in ED */
|
/* Calculate ED = ED * Right, update address size in ED */
|
||||||
{
|
{
|
||||||
@ -365,15 +392,8 @@ static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
|
|||||||
static void ED_Neg (ExprDesc* D)
|
static void ED_Neg (ExprDesc* D)
|
||||||
/* Negate an expression */
|
/* Negate an expression */
|
||||||
{
|
{
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
D->Val = -D->Val;
|
D->Val = -D->Val;
|
||||||
for (I = 0; I < D->SymCount; ++I) {
|
ED_NegRefs (D);
|
||||||
D->SymRef[I].Count = -D->SymRef[I].Count;
|
|
||||||
}
|
|
||||||
for (I = 0; I < D->SecCount; ++I) {
|
|
||||||
D->SecRef[I].Count = -D->SecRef[I].Count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -406,6 +426,22 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned char GetConstAddrSize (long Val)
|
||||||
|
/* Get the address size of a constant */
|
||||||
|
{
|
||||||
|
if ((Val & ~0xFFL) == 0) {
|
||||||
|
return ADDR_SIZE_ZP;
|
||||||
|
} else if ((Val & ~0xFFFFL) == 0) {
|
||||||
|
return ADDR_SIZE_ABS;
|
||||||
|
} else if ((Val & ~0xFFFFFFL) == 0) {
|
||||||
|
return ADDR_SIZE_FAR;
|
||||||
|
} else {
|
||||||
|
return ADDR_SIZE_LONG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
|
static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
|
||||||
/* Study a binary expression subtree. This is a helper function for StudyExpr
|
/* Study a binary expression subtree. This is a helper function for StudyExpr
|
||||||
* used for operations that succeed when both operands are known and constant.
|
* used for operations that succeed when both operands are known and constant.
|
||||||
@ -450,9 +486,9 @@ static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
|
|||||||
static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
|
static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
|
||||||
/* Study a literal expression node */
|
/* Study a literal expression node */
|
||||||
{
|
{
|
||||||
|
|
||||||
/* This one is easy */
|
/* This one is easy */
|
||||||
D->Val = Expr->V.Val;
|
D->Val = Expr->V.Val;
|
||||||
|
D->AddrSize = GetConstAddrSize (D->Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -621,8 +657,7 @@ static void StudyMinus (ExprNode* Expr, ExprDesc* D)
|
|||||||
if (ED_IsValid (D) || ED_IsValid (&Right)) {
|
if (ED_IsValid (D) || ED_IsValid (&Right)) {
|
||||||
|
|
||||||
/* Subtract both */
|
/* Subtract both */
|
||||||
ED_Neg (&Right);
|
ED_Sub (D, &Right);
|
||||||
ED_Add (D, &Right);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -1295,13 +1330,13 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
|
|||||||
void StudyExpr (ExprNode* Expr, ExprDesc* D)
|
void StudyExpr (ExprNode* Expr, ExprDesc* D)
|
||||||
/* Study an expression tree and place the contents into D */
|
/* Study an expression tree and place the contents into D */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I, J;
|
||||||
|
|
||||||
/* Call the internal function */
|
/* Call the internal function */
|
||||||
StudyExprInternal (Expr, D);
|
StudyExprInternal (Expr, D);
|
||||||
|
|
||||||
/* Remove symbol references with count zero */
|
/* Remove symbol references with count zero */
|
||||||
I = 0;
|
I = J = 0;
|
||||||
while (I < D->SymCount) {
|
while (I < D->SymCount) {
|
||||||
if (D->SymRef[I].Count == 0) {
|
if (D->SymRef[I].Count == 0) {
|
||||||
/* Delete the entry */
|
/* Delete the entry */
|
||||||
@ -1328,32 +1363,68 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we don't have an address size, assign one of the expression is a
|
/* If we don't have an address size, assign one if the expression is a
|
||||||
* constant.
|
* constant.
|
||||||
*/
|
*/
|
||||||
if (D->AddrSize == ADDR_SIZE_DEFAULT) {
|
if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
|
||||||
if (ED_IsConst (D)) {
|
D->AddrSize = GetConstAddrSize (D->Val);
|
||||||
if ((D->Val & ~0xFFL) == 0) {
|
}
|
||||||
D->AddrSize = ADDR_SIZE_ZP;
|
|
||||||
} else if ((D->Val & ~0xFFFFL) == 0) {
|
/* If the expression is valid, throw away the address size and recalculate
|
||||||
D->AddrSize = ADDR_SIZE_ABS;
|
* it using the data we have. This is more exact than the on-the-fly
|
||||||
} else if ((D->Val & 0xFFFFFFL) == 0) {
|
* calculation done when evaluating the tree, because symbols may have
|
||||||
D->AddrSize = ADDR_SIZE_FAR;
|
* been removed from the expression, and the final numeric value is now
|
||||||
|
* known.
|
||||||
|
*/
|
||||||
|
if (ED_IsValid (D)) {
|
||||||
|
unsigned char AddrSize;
|
||||||
|
if (D->SymCount == 1 && D->SecCount == 0) {
|
||||||
|
/* Exactly one symbol. Assume that the expression has the size of
|
||||||
|
* the symbol, provided that this size is known.
|
||||||
|
*/
|
||||||
|
const SymEntry* Sym = D->SymRef[0].Ref;
|
||||||
|
AddrSize = GetSymAddrSize (Sym);
|
||||||
|
if (AddrSize != ADDR_SIZE_DEFAULT) {
|
||||||
|
D->AddrSize = AddrSize;
|
||||||
} else {
|
} else {
|
||||||
D->AddrSize = ADDR_SIZE_LONG;
|
AddrSize = GetConstAddrSize (D->Val);
|
||||||
|
if (AddrSize > D->AddrSize) {
|
||||||
|
D->AddrSize = AddrSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (D->SymCount == 0 && D->SecCount == 1) {
|
||||||
|
/* Exactly one segment reference (segment+offset). In this case,
|
||||||
|
* the expression has the address size of the segment.
|
||||||
|
*/
|
||||||
|
unsigned SegNum = D->SecRef[0].Ref;
|
||||||
|
AddrSize = GetSegAddrSize (SegNum);
|
||||||
|
if (AddrSize != ADDR_SIZE_DEFAULT) {
|
||||||
|
D->AddrSize = AddrSize;
|
||||||
|
} else {
|
||||||
|
AddrSize = GetConstAddrSize (D->Val);
|
||||||
|
if (AddrSize > D->AddrSize) {
|
||||||
|
D->AddrSize = AddrSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AddrSize = GetConstAddrSize (D->Val);
|
||||||
|
if (AddrSize > D->AddrSize) {
|
||||||
|
D->AddrSize = AddrSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
/* Debug code */
|
||||||
printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
|
printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
|
||||||
|
printf ("Value: %08lX\n", D->Val);
|
||||||
if (!ED_IsValid (D)) {
|
if (!ED_IsValid (D)) {
|
||||||
printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
|
printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
|
||||||
} else {
|
} else {
|
||||||
printf ("Valid: %s\n", AddrSizeToStr (D->AddrSize));
|
printf ("Valid: %s\n", AddrSizeToStr (D->AddrSize));
|
||||||
|
}
|
||||||
printf ("%u symbols:\n", D->SymCount);
|
printf ("%u symbols:\n", D->SymCount);
|
||||||
printf ("%u sections:\n", D->SecCount);
|
printf ("%u sections:\n", D->SecCount);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user