/*****************************************************************************/
/* */
-/* expr.c */
+/* expr.c */
/* */
-/* Expression evaluation for the ca65 macroassembler */
+/* Expression evaluation for the ca65 macroassembler */
/* */
/* */
/* */
-/* (C) 1998-2010, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#include "exprdefs.h"
#include "print.h"
#include "shift.h"
+#include "segdefs.h"
#include "strbuf.h"
#include "tgttrans.h"
#include "version.h"
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
* number of freed nodes for later and remember them in a single linked list
* using the Left link.
*/
-#define MAX_FREE_NODES 64
-static ExprNode* FreeExprNodes = 0;
-static unsigned FreeNodeCount = 0;
+#define MAX_FREE_NODES 64
+static ExprNode* FreeExprNodes = 0;
+static unsigned FreeNodeCount = 0;
/*****************************************************************************/
-/* Helpers */
+/* Helpers */
/*****************************************************************************/
ExprNode* N;
/* Do we have some nodes in the list already? */
- if (FreeExprNodes) {
- /* Use first node from list */
- N = FreeExprNodes;
- FreeExprNodes = N->Left;
+ if (FreeNodeCount) {
+ /* Use first node from list */
+ N = FreeExprNodes;
+ FreeExprNodes = N->Left;
+ --FreeNodeCount;
} else {
- /* Allocate fresh memory */
+ /* Allocate fresh memory */
N = xmalloc (sizeof (ExprNode));
}
N->Op = Op;
SymDelExprRef (E->V.Sym, E);
}
/* Place the symbol into the free nodes list if possible */
- if (FreeNodeCount < MAX_FREE_NODES) {
- /* Remember this node for later */
- E->Left = FreeExprNodes;
- FreeExprNodes = E;
- } else {
- /* Free the memory */
- xfree (E);
- }
+ if (FreeNodeCount < MAX_FREE_NODES) {
+ /* Remember this node for later */
+ E->Left = FreeExprNodes;
+ FreeExprNodes = E;
+ ++FreeNodeCount;
+ } else {
+ /* Free the memory */
+ xfree (E);
+ }
}
}
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
-static int IsEasyConst (const ExprNode* E, long* Val)
+int IsEasyConst (const ExprNode* E, long* Val)
/* Do some light checking if the given node is a constant. Don't care if E is
* a complex expression. If E is a constant, return true and place its value
* into Val, provided that Val is not NULL.
+static ExprNode* Bank (ExprNode* Operand)
+/* Return the bank of the given segmented expression */
+{
+ /* Generate the bank expression */
+ ExprNode* Expr = NewExprNode (EXPR_BANK);
+ Expr->Left = Operand;
+
+ /* Return the result */
+ return Expr;
+}
+
+
+
static ExprNode* BankByte (ExprNode* Operand)
/* Return the bank byte of the given expression */
{
+ExprNode* FuncBank (void)
+/* Handle the .BANK builtin function */
+{
+ return Bank (Expression ());
+}
+
+
+
ExprNode* FuncBankByte (void)
/* Handle the .BANKBYTE builtin function */
{
/* We have a list of tokens that ends with the closing paren. Skip
* the tokens, and count them. Allow optionally curly braces.
*/
- Token Term = GetTokListTerm (TOK_RPAREN);
+ token_t Term = GetTokListTerm (TOK_RPAREN);
unsigned Count = 0;
- while (Tok != Term) {
+ while (CurTok.Tok != Term) {
- /* Check for end of line or end of input. Since the calling function
- * will check for the closing paren, we don't need to print an error
- * here, just bail out.
- */
- if (TokIsSep (Tok)) {
- break;
- }
+ /* Check for end of line or end of input. Since the calling function
+ * will check for the closing paren, we don't need to print an error
+ * here, just bail out.
+ */
+ if (TokIsSep (CurTok.Tok)) {
+ break;
+ }
- /* One more token */
- ++Count;
+ /* One more token */
+ ++Count;
- /* Skip the token */
- NextTok ();
+ /* Skip the token */
+ NextTok ();
}
/* If the list was enclosed in curly braces, skip the closing brace */
- if (Term == TOK_RCURLY && Tok == TOK_RCURLY) {
+ if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
NextTok ();
}
/* Handle the .DEFINED builtin function */
{
/* Parse the symbol name and search for the symbol */
- SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+ SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
/* Check if the symbol is defined */
return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
* single linked list of tokens including attributes. The list is
* either enclosed in curly braces, or terminated by a comma.
*/
- Token Term = GetTokListTerm (TOK_COMMA);
- while (Tok != Term) {
-
- /* We may not end-of-line of end-of-file here */
- if (TokIsSep (Tok)) {
- Error ("Unexpected end of line");
- return GenLiteral0 ();
- }
-
- /* Get a node with this token */
- Node = NewTokNode ();
-
- /* Insert the node into the list */
- if (Last == 0) {
- Root = Node;
- } else {
- Last->Next = Node;
- }
- Last = Node;
-
- /* Skip the token */
- NextTok ();
+ token_t Term = GetTokListTerm (TOK_COMMA);
+ while (CurTok.Tok != Term) {
+
+ /* We may not end-of-line of end-of-file here */
+ if (TokIsSep (CurTok.Tok)) {
+ Error ("Unexpected end of line");
+ return GenLiteral0 ();
+ }
+
+ /* Get a node with this token */
+ Node = NewTokNode ();
+
+ /* Insert the node into the list */
+ if (Last == 0) {
+ Root = Node;
+ } else {
+ Last->Next = Node;
+ }
+ Last = Node;
+
+ /* Skip the token */
+ NextTok ();
}
/* Skip the terminator token*/
Term = GetTokListTerm (TOK_RPAREN);
Result = 1;
Node = Root;
- while (Tok != Term) {
-
- /* We may not end-of-line of end-of-file here */
- if (TokIsSep (Tok)) {
- Error ("Unexpected end of line");
- return GenLiteral0 ();
- }
-
- /* Compare the tokens if the result is not already known */
- if (Result != 0) {
- if (Node == 0) {
- /* The second list is larger than the first one */
- Result = 0;
- } else if (TokCmp (Node) < EqualityLevel) {
- /* Tokens do not match */
- Result = 0;
- }
- }
-
- /* Next token in first list */
- if (Node) {
- Node = Node->Next;
- }
-
- /* Next token in current list */
- NextTok ();
+ while (CurTok.Tok != Term) {
+
+ /* We may not end-of-line of end-of-file here */
+ if (TokIsSep (CurTok.Tok)) {
+ Error ("Unexpected end of line");
+ return GenLiteral0 ();
+ }
+
+ /* Compare the tokens if the result is not already known */
+ if (Result != 0) {
+ if (Node == 0) {
+ /* The second list is larger than the first one */
+ Result = 0;
+ } else if (TokCmp (Node) < EqualityLevel) {
+ /* Tokens do not match */
+ Result = 0;
+ }
+ }
+
+ /* Next token in first list */
+ if (Node) {
+ Node = Node->Next;
+ }
+
+ /* Next token in current list */
+ NextTok ();
}
/* If the token list was enclosed in curly braces, eat the closing brace */
/* Check if there are remaining tokens in the first list */
if (Node != 0) {
- Result = 0;
+ Result = 0;
}
/* Free the token list */
while (Root) {
- Node = Root;
- Root = Root->Next;
- FreeTokNode (Node);
+ Node = Root;
+ Root = Root->Next;
+ FreeTokNode (Node);
}
/* Done, return the result */
/* Handle the .REFERENCED builtin function */
{
/* Parse the symbol name and search for the symbol */
- SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+ SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
/* Check if the symbol is referenced */
return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
SizeSym = 0;
/* Check for a cheap local which needs special handling */
- if (Tok == TOK_LOCAL_IDENT) {
+ if (CurTok.Tok == TOK_LOCAL_IDENT) {
/* Cheap local symbol */
- Sym = SymFindLocal (SymLast, &SVal, SYM_FIND_EXISTING);
+ Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
if (Sym == 0) {
- Error ("Unknown symbol or scope: `%m%p'", &SVal);
+ Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
} else {
SizeSym = GetSizeOfSymbol (Sym);
}
/* Remember and skip SVal, terminate ScopeName so it is empty */
- SB_Copy (&Name, &SVal);
+ SB_Copy (&Name, &CurTok.SVal);
NextTok ();
SB_Terminate (&ScopeName);
unsigned char C = 0;
/* String constant expected */
- if (Tok != TOK_STRCON) {
- Error ("String constant expected");
- NextTok ();
- goto ExitPoint;
+ if (CurTok.Tok != TOK_STRCON) {
+ Error ("String constant expected");
+ NextTok ();
+ goto ExitPoint;
}
/* Remember the string and skip it */
- SB_Copy (&Str, &SVal);
+ SB_Copy (&Str, &CurTok.SVal);
NextTok ();
/* Comma must follow */
/* Must be a valid index */
if (Index >= (long) SB_GetLen (&Str)) {
- Error ("Range error");
+ Error ("Range error");
goto ExitPoint;
}
int Len;
/* String constant expected */
- if (Tok != TOK_STRCON) {
+ if (CurTok.Tok != TOK_STRCON) {
- Error ("String constant expected");
- /* Smart error recovery */
- if (Tok != TOK_RPAREN) {
- NextTok ();
- }
- Len = 0;
+ Error ("String constant expected");
+ /* Smart error recovery */
+ if (CurTok.Tok != TOK_RPAREN) {
+ NextTok ();
+ }
+ Len = 0;
} else {
/* Get the length of the string */
- Len = SB_GetLen (&SVal);
+ Len = SB_GetLen (&CurTok.SVal);
- /* Skip the string */
- NextTok ();
+ /* Skip the string */
+ NextTok ();
}
/* Return the length */
/* We have a list of tokens that ends with the closing paren. Skip
* the tokens, and count them. Allow optionally curly braces.
*/
- Token Term = GetTokListTerm (TOK_RPAREN);
+ token_t Term = GetTokListTerm (TOK_RPAREN);
int Count = 0;
- while (Tok != Term) {
+ while (CurTok.Tok != Term) {
- /* Check for end of line or end of input. Since the calling function
- * will check for the closing paren, we don't need to print an error
- * here, just bail out.
- */
- if (TokIsSep (Tok)) {
- break;
- }
+ /* Check for end of line or end of input. Since the calling function
+ * will check for the closing paren, we don't need to print an error
+ * here, just bail out.
+ */
+ if (TokIsSep (CurTok.Tok)) {
+ break;
+ }
- /* One more token */
- ++Count;
+ /* One more token */
+ ++Count;
- /* Skip the token */
- NextTok ();
+ /* Skip the token */
+ NextTok ();
}
/* If the list was enclosed in curly braces, skip the closing brace */
- if (Term == TOK_RCURLY && Tok == TOK_RCURLY) {
+ if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
NextTok ();
}
NextTok ();
/* Expression must be enclosed in braces */
- if (Tok != TOK_LPAREN) {
- Error ("'(' expected");
- SkipUntilSep ();
- return GenLiteral0 ();
+ if (CurTok.Tok != TOK_LPAREN) {
+ Error ("'(' expected");
+ SkipUntilSep ();
+ return GenLiteral0 ();
}
NextTok ();
ExprNode* N;
long Val;
- switch (Tok) {
+ switch (CurTok.Tok) {
- case TOK_INTCON:
- N = GenLiteralExpr (IVal);
- NextTok ();
- break;
-
- case TOK_CHARCON:
- N = GenLiteralExpr (TgtTranslateChar (IVal));
- NextTok ();
- break;
+ case TOK_INTCON:
+ N = GenLiteralExpr (CurTok.IVal);
+ NextTok ();
+ break;
- case TOK_NAMESPACE:
- case TOK_IDENT:
- N = Symbol (ParseScopedSymName (SYM_ALLOC_NEW));
- break;
+ case TOK_CHARCON:
+ N = GenLiteralExpr (TgtTranslateChar (CurTok.IVal));
+ NextTok ();
+ break;
+ case TOK_NAMESPACE:
+ case TOK_IDENT:
case TOK_LOCAL_IDENT:
- N = Symbol (SymFindLocal (SymLast, &SVal, SYM_ALLOC_NEW));
- NextTok ();
+ N = Symbol (ParseAnySymName (SYM_ALLOC_NEW));
break;
- case TOK_ULABEL:
- N = ULabRef (IVal);
- NextTok ();
- break;
+ case TOK_ULABEL:
+ N = ULabRef (CurTok.IVal);
+ NextTok ();
+ break;
case TOK_PLUS:
NextTok ();
N = Factor ();
break;
- case TOK_MINUS:
- NextTok ();
+ case TOK_MINUS:
+ NextTok ();
L = Factor ();
if (IsEasyConst (L, &Val)) {
FreeExpr (L);
N = GenLiteralExpr (-Val);
} else {
N = NewExprNode (EXPR_UNARY_MINUS);
- N->Left = L;
+ N->Left = L;
}
- break;
+ break;
- case TOK_NOT:
- NextTok ();
+ case TOK_NOT:
+ NextTok ();
L = Factor ();
if (IsEasyConst (L, &Val)) {
FreeExpr (L);
N = NewExprNode (EXPR_NOT);
N->Left = L;
}
- break;
+ break;
- case TOK_STAR:
- case TOK_PC:
- NextTok ();
- N = GenCurrentPC ();
- break;
+ case TOK_STAR:
+ case TOK_PC:
+ NextTok ();
+ N = GenCurrentPC ();
+ break;
- case TOK_LT:
- NextTok ();
+ case TOK_LT:
+ NextTok ();
N = LoByte (Factor ());
- break;
+ break;
- case TOK_GT:
- NextTok ();
+ case TOK_GT:
+ NextTok ();
N = HiByte (Factor ());
- break;
+ break;
- case TOK_BANK:
+ case TOK_XOR:
+ /* ^ means the bank byte of an expression */
NextTok ();
N = BankByte (Factor ());
break;
- case TOK_LPAREN:
- NextTok ();
- N = Expr0 ();
- ConsumeRParen ();
- break;
+ case TOK_LPAREN:
+ NextTok ();
+ N = Expr0 ();
+ ConsumeRParen ();
+ break;
+
+ case TOK_BANK:
+ N = Function (FuncBank);
+ break;
case TOK_BANKBYTE:
N = Function (FuncBankByte);
break;
case TOK_BLANK:
- N = Function (FuncBlank);
- break;
+ N = Function (FuncBlank);
+ break;
- case TOK_CONST:
- N = Function (FuncConst);
- break;
+ case TOK_CONST:
+ N = Function (FuncConst);
+ break;
- case TOK_CPU:
- N = GenLiteralExpr (CPUIsets[CPU]);
- NextTok ();
- break;
+ case TOK_CPU:
+ N = GenLiteralExpr (CPUIsets[CPU]);
+ NextTok ();
+ break;
case TOK_DEFINED:
- N = Function (FuncDefined);
- break;
+ N = Function (FuncDefined);
+ break;
case TOK_HIBYTE:
N = Function (FuncHiByte);
N = Function (FuncLoWord);
break;
- case TOK_MATCH:
- N = Function (FuncMatch);
- break;
+ case TOK_MATCH:
+ N = Function (FuncMatch);
+ break;
case TOK_MAX:
N = Function (FuncMax);
break;
case TOK_REFERENCED:
- N = Function (FuncReferenced);
- break;
+ N = Function (FuncReferenced);
+ break;
case TOK_SIZEOF:
N = Function (FuncSizeOf);
break;
- case TOK_STRAT:
- N = Function (FuncStrAt);
- break;
+ case TOK_STRAT:
+ N = Function (FuncStrAt);
+ break;
- case TOK_STRLEN:
- N = Function (FuncStrLen);
- break;
+ case TOK_STRLEN:
+ N = Function (FuncStrLen);
+ break;
- case TOK_TCOUNT:
- N = Function (FuncTCount);
- break;
+ case TOK_TCOUNT:
+ N = Function (FuncTCount);
+ break;
- case TOK_TIME:
- N = GenLiteralExpr (time (0));
- NextTok ();
- break;
+ case TOK_TIME:
+ N = GenLiteralExpr ((long) time (0));
+ NextTok ();
+ break;
case TOK_VERSION:
N = GenLiteralExpr (GetVersionAsNumber ());
NextTok ();
break;
- case TOK_XMATCH:
- N = Function (FuncXMatch);
- break;
-
- default:
- if (LooseCharTerm && Tok == TOK_STRCON && SB_GetLen (&SVal) == 1) {
- /* A character constant */
- N = GenLiteralExpr (TgtTranslateChar (SB_At (&SVal, 0)));
- } else {
- N = GenLiteral0 (); /* Dummy */
- Error ("Syntax error");
- }
- NextTok ();
- break;
+ case TOK_XMATCH:
+ N = Function (FuncXMatch);
+ break;
+
+ default:
+ if (LooseCharTerm && CurTok.Tok == TOK_STRCON &&
+ SB_GetLen (&CurTok.SVal) == 1) {
+ /* A character constant */
+ N = GenLiteralExpr (TgtTranslateChar (SB_At (&CurTok.SVal, 0)));
+ } else {
+ N = GenLiteral0 (); /* Dummy */
+ Error ("Syntax error");
+ }
+ NextTok ();
+ break;
}
return N;
}
ExprNode* Root = Factor ();
/* Handle multiplicative operations */
- while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
- Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
- Tok == TOK_SHR) {
+ while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV ||
+ CurTok.Tok == TOK_MOD || CurTok.Tok == TOK_AND ||
+ CurTok.Tok == TOK_XOR || CurTok.Tok == TOK_SHL ||
+ CurTok.Tok == TOK_SHR) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
/* Generate an expression tree */
unsigned char Op;
switch (T) {
- case TOK_MUL: Op = EXPR_MUL; break;
+ case TOK_MUL: Op = EXPR_MUL; break;
case TOK_DIV: Op = EXPR_DIV; break;
case TOK_MOD: Op = EXPR_MOD; break;
case TOK_AND: Op = EXPR_AND; break;
case TOK_XOR: Op = EXPR_XOR; break;
case TOK_SHL: Op = EXPR_SHL; break;
case TOK_SHR: Op = EXPR_SHR; break;
- default: Internal ("Invalid token");
+ default: Internal ("Invalid token");
}
Root = NewExprNode (Op);
Root->Left = Left;
ExprNode* Root = Term ();
/* Handle additive operations */
- while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
+ while (CurTok.Tok == TOK_PLUS ||
+ CurTok.Tok == TOK_MINUS ||
+ CurTok.Tok == TOK_OR) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
case TOK_PLUS: Op = EXPR_PLUS; break;
case TOK_MINUS: Op = EXPR_MINUS; break;
case TOK_OR: Op = EXPR_OR; break;
- default: Internal ("Invalid token");
+ default: Internal ("Invalid token");
}
Root = NewExprNode (Op);
Root->Left = Left;
ExprNode* Root = SimpleExpr ();
/* Handle booleans */
- while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
- Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
+ while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE ||
+ CurTok.Tok == TOK_LT || CurTok.Tok == TOK_GT ||
+ CurTok.Tok == TOK_LE || CurTok.Tok == TOK_GE) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
case TOK_GT: Op = EXPR_GT; break;
case TOK_LE: Op = EXPR_LE; break;
case TOK_GE: Op = EXPR_GE; break;
- default: Internal ("Invalid token");
+ default: Internal ("Invalid token");
}
Root = NewExprNode (Op);
Root->Left = Left;
ExprNode* Root = BoolExpr ();
/* Handle booleans */
- while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
+ while (CurTok.Tok == TOK_BOOLAND || CurTok.Tok == TOK_BOOLXOR) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
switch (T) {
case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
- default: Internal ("Invalid token");
+ default: Internal ("Invalid token");
}
Root = NewExprNode (Op);
Root->Left = Left;
ExprNode* Root = Expr2 ();
/* Handle booleans */
- while (Tok == TOK_BOOLOR) {
+ while (CurTok.Tok == TOK_BOOLOR) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
unsigned char Op;
switch (T) {
case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
- default: Internal ("Invalid token");
+ default: Internal ("Invalid token");
}
Root = NewExprNode (Op);
Root->Left = Left;
ExprNode* Root;
/* Handle booleans */
- if (Tok == TOK_BOOLNOT) {
+ if (CurTok.Tok == TOK_BOOLNOT) {
long Val;
ExprNode* Left;
/* Skip the operator token */
- NextTok ();
+ NextTok ();
/* Read the argument */
Left = Expr0 ();
} else {
- /* Read left hand side */
- Root = Expr1 ();
+ /* Read left hand side */
+ Root = Expr1 ();
}
if (ED_IsConst (&D)) {
Val = D.Val;
} else {
- Error ("Constant expression expected");
- Val = 0;
+ Error ("Constant expression expected");
+ Val = 0;
}
/* Free the expression tree and allocated memory for D */
/* Free the expression, Root is pointing to. */
{
if (Root) {
- FreeExpr (Root->Left);
- FreeExpr (Root->Right);
- FreeExprNode (Root);
+ FreeExpr (Root->Left);
+ FreeExpr (Root->Right);
+ FreeExprNode (Root);
}
}
-static ExprNode* GenSectionExpr (unsigned SegNum)
+static ExprNode* GenSectionExpr (unsigned SecNum)
/* Return an expression node for the given section */
{
ExprNode* Expr = NewExprNode (EXPR_SECTION);
- Expr->V.SegNum = SegNum;
+ Expr->V.SecNum = SecNum;
+ return Expr;
+}
+
+
+
+static ExprNode* GenBankExpr (unsigned SecNum)
+/* Return an expression node for the given bank */
+{
+ ExprNode* Expr = NewExprNode (EXPR_BANK);
+ Expr->V.SecNum = SecNum;
return Expr;
}
ExprNode* Root;
if (GetRelocMode ()) {
- /* Create SegmentBase + Offset */
- Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
+ /* Create SegmentBase + Offset */
+ Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
GenLiteralExpr (GetPC ()));
} else {
- /* Absolute mode, just return PC value */
- Root = GenLiteralExpr (GetPC ());
+ /* Absolute mode, just return PC value */
+ Root = GenLiteralExpr (GetPC ());
}
return Root;
/* Return an expression for an unnamed label with the given index */
{
ExprNode* Node = NewExprNode (EXPR_ULABEL);
- Node->V.IVal = Num;
+ Node->V.IVal = Num;
/* Return the new node */
return Node;
+ExprNode* GenFarAddrExpr (ExprNode* Expr)
+/* Force the given expression into a far address and return the result. */
+{
+ long Val;
+
+ /* Special handling for const expressions */
+ if (IsEasyConst (Expr, &Val)) {
+ FreeExpr (Expr);
+ Expr = GenLiteralExpr (Val & 0xFFFFFF);
+ } else {
+ ExprNode* Operand = Expr;
+ Expr = NewExprNode (EXPR_FARADDR);
+ Expr->Left = Operand;
+ }
+ return Expr;
+}
+
+
+
+ExprNode* GenDWordExpr (ExprNode* Expr)
+/* Force the given expression into a dword and return the result. */
+{
+ long Val;
+
+ /* Special handling for const expressions */
+ if (IsEasyConst (Expr, &Val)) {
+ FreeExpr (Expr);
+ Expr = GenLiteralExpr (Val & 0xFFFFFFFF);
+ } else {
+ ExprNode* Operand = Expr;
+ Expr = NewExprNode (EXPR_DWORD);
+ Expr->Left = Operand;
+ }
+ return Expr;
+}
+
+
+
ExprNode* GenNE (ExprNode* Expr, long Val)
/* Generate an expression that compares Expr and Val for inequality */
{
/* Generate a compare node */
ExprNode* Root = NewExprNode (EXPR_NE);
Root->Left = Expr;
- Root->Right = GenLiteralExpr (Val);
+ Root->Right = GenLiteralExpr (Val);
/* Return the result */
return Root;
/* Clone the node */
switch (Expr->Op) {
- case EXPR_LITERAL:
+ case EXPR_LITERAL:
Clone = GenLiteralExpr (Expr->V.IVal);
break;
- case EXPR_ULABEL:
- Clone = GenULabelExpr (Expr->V.IVal);
- break;
+ case EXPR_ULABEL:
+ Clone = GenULabelExpr (Expr->V.IVal);
+ break;
- case EXPR_SYMBOL:
- Clone = GenSymExpr (Expr->V.Sym);
- break;
+ case EXPR_SYMBOL:
+ Clone = GenSymExpr (Expr->V.Sym);
+ break;
- case EXPR_SECTION:
- Clone = GenSectionExpr (Expr->V.SegNum);
- break;
+ case EXPR_SECTION:
+ Clone = GenSectionExpr (Expr->V.SecNum);
+ break;
+
+ case EXPR_BANK:
+ Clone = GenBankExpr (Expr->V.SecNum);
+ break;
default:
/* Generate a new node */
{
/* Null expressions are encoded by a type byte of zero */
if (Expr == 0) {
- ObjWrite8 (EXPR_NULL);
- return;
+ ObjWrite8 (EXPR_NULL);
+ return;
}
/* If the is a leafnode, write the expression attribute, otherwise
case EXPR_LITERAL:
ObjWrite8 (EXPR_LITERAL);
- ObjWrite32 (Expr->V.IVal);
- break;
+ ObjWrite32 (Expr->V.IVal);
+ break;
case EXPR_SYMBOL:
- if (SymIsImport (Expr->V.Sym)) {
+ if (SymIsImport (Expr->V.Sym)) {
ObjWrite8 (EXPR_SYMBOL);
- ObjWriteVar (GetSymIndex (Expr->V.Sym));
+ ObjWriteVar (GetSymImportId (Expr->V.Sym));
} else {
WriteExpr (GetSymExpr (Expr->V.Sym));
}
- break;
+ break;
case EXPR_SECTION:
ObjWrite8 (EXPR_SECTION);
- ObjWrite8 (Expr->V.SegNum);
- break;
+ ObjWriteVar (Expr->V.SecNum);
+ break;
- case EXPR_ULABEL:
+ case EXPR_ULABEL:
WriteExpr (ULabResolve (Expr->V.IVal));
- break;
+ break;
default:
- /* Not a leaf node */
+ /* Not a leaf node */
ObjWrite8 (Expr->Op);
- WriteExpr (Expr->Left);
- WriteExpr (Expr->Right);
- break;
+ WriteExpr (Expr->Left);
+ WriteExpr (Expr->Right);
+ break;
}
}
}
/* Check the type code */
- switch (Expr->Op & EXPR_TYPEMASK) {
+ switch (EXPR_NODETYPE (Expr->Op)) {
case EXPR_LEAFNODE:
if (Expr->Op == EXPR_SYMBOL) {
+ExprNode* MakeBoundedExpr (ExprNode* Expr, unsigned Size)
+/* Force the given expression into a specific size of ForceRange is true */
+{
+ if (ForceRange) {
+ switch (Size) {
+ case 1: Expr = GenByteExpr (Expr); break;
+ case 2: Expr = GenWordExpr (Expr); break;
+ case 3: Expr = GenFarAddrExpr (Expr); break;
+ case 4: Expr = GenDWordExpr (Expr); break;
+ default: Internal ("Invalid size in BoundedExpr: %u", Size);
+ }
+ }
+ return Expr;
+}
+
+
+
+ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size)
+/* Parse an expression and force it within a given size if ForceRange is true */
+{
+ return MakeBoundedExpr (ExprFunc (), Size);
+}
+
+
+