/* */
/* */
/* */
-/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2003-2012, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* common */
#include "check.h"
-#include "print.h"
+#include "debugflag.h"
#include "shift.h"
#include "xmalloc.h"
{
ED->Flags = ED_OK;
ED->AddrSize = ADDR_SIZE_DEFAULT;
- ED->Val = 0;
+ ED->Val = 0;
ED->SymCount = 0;
ED->SymLimit = 0;
ED->SymRef = 0;
static int ED_IsValid (const ExprDesc* D)
-/* Return true if the expression is valid, that is, the TOO_COMPLEX flag is
- * not set
+/* Return true if the expression is valid, that is, neither the ERROR nor the
+ * TOO_COMPLEX flags are set.
*/
{
- return ((D->Flags & ED_TOO_COMPLEX) == 0);
+ return ((D->Flags & (ED_ERROR | ED_TOO_COMPLEX)) == 0);
+}
+
+
+
+static int ED_HasError (const ExprDesc* D)
+/* Return true if the expression has an error. */
+{
+ return ((D->Flags & ED_ERROR) != 0);
}
+static void ED_SetError (ExprDesc* D)
+/* Set the TOO_COMPLEX and ERROR flags for D */
+{
+ D->Flags |= (ED_ERROR | ED_TOO_COMPLEX);
+}
+
+
+
static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
/* Update the address size of the expression */
{
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
/* Study a literal expression node */
{
/* This one is easy */
- D->Val = Expr->V.Val;
+ D->Val = Expr->V.IVal;
D->AddrSize = GetConstAddrSize (D->Val);
}
if (SymHasExpr (Sym)) {
if (SymHasUserMark (Sym)) {
- if (Verbosity > 0) {
- DumpExpr (Expr, SymResolve);
- }
- PError (GetSymPos (Sym),
- "Circular reference in definition of symbol `%s'",
- GetSymName (Sym));
- ED_Invalidate (D);
+ LIError (&Sym->DefLines,
+ "Circular reference in definition of symbol `%m%p'",
+ GetSymName (Sym));
+ ED_SetError (D);
} else {
unsigned char AddrSize;
StudyExprInternal (GetSymExpr (Sym), D);
SymUnmarkUser (Sym);
+ /* If requested and if the expression is valid, dump it */
+ if (Debug > 0 && !ED_HasError (D)) {
+ DumpExpr (Expr, SymResolve);
+ }
+
/* If the symbol has an explicit address size, use it. This may
* lead to range errors later (maybe even in the linker stage), if
* the user lied about the address size, but for now we trust him.
/* Study a section expression node */
{
/* Get the section reference */
- ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SegNum);
+ ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SecNum);
/* Update the data and the address size */
++SecRef->Count;
*/
if (ULabCanResolve ()) {
/* We can resolve the label */
- StudyExprInternal (ULabResolve (Expr->V.Val), D);
+ StudyExprInternal (ULabResolve (Expr->V.IVal), D);
} else {
ED_Invalidate (D);
}
StudyExprInternal (Expr->Right, &Right);
/* Check if we can handle the operation */
- if (ED_IsValid (D) || ED_IsValid (&Right)) {
+ if (ED_IsValid (D) && ED_IsValid (&Right)) {
/* Add both */
ED_Add (D, &Right);
StudyExprInternal (Expr->Right, &Right);
/* Check if we can handle the operation */
- if (ED_IsValid (D) || ED_IsValid (&Right)) {
+ if (ED_IsValid (D) && ED_IsValid (&Right)) {
/* Subtract both */
ED_Sub (D, &Right);
if (ED_IsValid (D)) {
if (D->Right == 0) {
Error ("Division by zero");
- ED_Invalidate (D);
+ ED_SetError (D);
} else {
D->Val /= D->Right;
}
if (ED_IsValid (D)) {
if (D->Right == 0) {
Error ("Modulo operation with zero");
- ED_Invalidate (D);
+ ED_SetError (D);
} else {
D->Val %= D->Right;
}
+static void StudyMax (ExprNode* Expr, ExprDesc* D)
+/* Study an MAX binary expression node */
+{
+ /* Use helper function */
+ StudyBinaryExpr (Expr, D);
+
+ /* If the result is valid, apply the operation */
+ if (ED_IsValid (D)) {
+ D->Val = (D->Val > D->Right)? D->Val : D->Right;
+ }
+}
+
+
+
+static void StudyMin (ExprNode* Expr, ExprDesc* D)
+/* Study an MIN binary expression node */
+{
+ /* Use helper function */
+ StudyBinaryExpr (Expr, D);
+
+ /* If the result is valid, apply the operation */
+ if (ED_IsValid (D)) {
+ D->Val = (D->Val < D->Right)? D->Val : D->Right;
+ }
+}
+
+
+
static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
/* Study an EXPR_UNARY_MINUS expression node */
{
+static void StudyBank (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BANK expression node */
+{
+ /* Study the expression extracting section references */
+ StudyExprInternal (Expr->Left, D);
+
+ /* The expression is always linker evaluated, so invalidate it */
+ ED_Invalidate (D);
+}
+
+
+
static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
/* Study an EXPR_BYTE0 expression node */
{
/* We can handle only const expressions */
if (ED_IsConst (D)) {
- D->Val = (D->Val & 0xFFFFL);
+ D->Val &= 0xFFFFL;
} else {
ED_Invalidate (D);
}
+static void StudyFarAddr (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_FARADDR expression node */
+{
+ /* Study the expression */
+ StudyExprInternal (Expr->Left, D);
+
+ /* We can handle only const expressions */
+ if (ED_IsConst (D)) {
+ D->Val &= 0xFFFFFFL;
+ } else {
+ ED_Invalidate (D);
+ }
+
+ /* In any case, the result is a far address */
+ D->AddrSize = ADDR_SIZE_FAR;
+}
+
+
+
+static void StudyDWord (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_DWORD expression node */
+{
+ /* Study the expression */
+ StudyExprInternal (Expr->Left, D);
+
+ /* We can handle only const expressions */
+ if (ED_IsConst (D)) {
+ D->Val &= 0xFFFFFFFFL;
+ } else {
+ ED_Invalidate (D);
+ }
+
+ /* In any case, the result is a long expression */
+ D->AddrSize = ADDR_SIZE_LONG;
+}
+
+
+
static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
/* Study an expression tree and place the contents into D */
{
/* Study this expression node */
switch (Expr->Op) {
- case EXPR_LITERAL:
+ case EXPR_LITERAL:
StudyLiteral (Expr, D);
- break;
+ break;
- case EXPR_SYMBOL:
+ case EXPR_SYMBOL:
StudySymbol (Expr, D);
break;
- case EXPR_SECTION:
+ case EXPR_SECTION:
StudySection (Expr, D);
- break;
+ break;
- case EXPR_ULABEL:
+ case EXPR_ULABEL:
StudyULabel (Expr, D);
break;
- case EXPR_PLUS:
+ case EXPR_PLUS:
StudyPlus (Expr, D);
- break;
+ break;
- case EXPR_MINUS:
- StudyMinus (Expr, D);
- break;
+ case EXPR_MINUS:
+ StudyMinus (Expr, D);
+ break;
case EXPR_MUL:
StudyMul (Expr, D);
StudyBoolXor (Expr, D);
break;
+ case EXPR_MAX:
+ StudyMax (Expr, D);
+ break;
+
+ case EXPR_MIN:
+ StudyMin (Expr, D);
+ break;
+
case EXPR_UNARY_MINUS:
StudyUnaryMinus (Expr, D);
break;
StudyBoolNot (Expr, D);
break;
+ case EXPR_BANK:
+ StudyBank (Expr, D);
+ break;
+
case EXPR_BYTE0:
StudyByte0 (Expr, D);
break;
StudyWord1 (Expr, D);
break;
+ case EXPR_FARADDR:
+ StudyFarAddr (Expr, D);
+ break;
+
+ case EXPR_DWORD:
+ StudyDWord (Expr, D);
+ break;
+
default:
- Internal ("Unknown Op type: %u", Expr->Op);
- break;
+ Internal ("Unknown Op type: %u", Expr->Op);
+ break;
}
}
*/
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 {
- AddrSize = GetConstAddrSize (D->Val);
+
+ /* If there are symbols or sections, use the largest one. If the
+ * expression resolves to a const, use the address size of the value.
+ */
+ if (D->SymCount > 0 || D->SecCount > 0) {
+
+ D->AddrSize = ADDR_SIZE_DEFAULT;
+
+ for (I = 0; I < D->SymCount; ++I) {
+ const SymEntry* Sym = D->SymRef[I].Ref;
+ AddrSize = GetSymAddrSize (Sym);
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);
+
+ for (I = 0; I < D->SecCount; ++I) {
+ unsigned SegNum = D->SecRef[0].Ref;
+ AddrSize = GetSegAddrSize (SegNum);
if (AddrSize > D->AddrSize) {
D->AddrSize = AddrSize;
}
}
+
} else {
AddrSize = GetConstAddrSize (D->Val);
if (AddrSize > D->AddrSize) {
printf ("%u sections:\n", D->SecCount);
#endif
}
-
-
-