1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
59 #include "studyexpr.h"
67 /*****************************************************************************/
69 /*****************************************************************************/
73 /* Since all expressions are first packed into expression trees, and each
74 * expression tree node is allocated on the heap, we add some type of special
75 * purpose memory allocation here: Instead of freeing the nodes, we save some
76 * number of freed nodes for later and remember them in a single linked list
77 * using the Left link.
79 #define MAX_FREE_NODES 64
80 static ExprNode* FreeExprNodes = 0;
81 static unsigned FreeNodeCount = 0;
85 /*****************************************************************************/
87 /*****************************************************************************/
91 static ExprNode* NewExprNode (unsigned Op)
92 /* Create a new expression node */
96 /* Do we have some nodes in the list already? */
98 /* Use first node from list */
100 FreeExprNodes = N->Left;
102 /* Allocate fresh memory */
103 N = xmalloc (sizeof (ExprNode));
106 N->Left = N->Right = 0;
114 static void FreeExprNode (ExprNode* E)
118 if (E->Op == EXPR_SYMBOL) {
119 /* Remove the symbol reference */
120 SymDelExprRef (E->V.Sym, E);
122 /* Place the symbol into the free nodes list if possible */
123 if (FreeNodeCount < MAX_FREE_NODES) {
124 /* Remember this node for later */
125 E->Left = FreeExprNodes;
128 /* Free the memory */
136 /*****************************************************************************/
138 /*****************************************************************************/
142 static ExprNode* Expr0 (void);
146 int IsByteRange (long Val)
147 /* Return true if this is a byte value */
149 return (Val & ~0xFFL) == 0;
154 int IsWordRange (long Val)
155 /* Return true if this is a word value */
157 return (Val & ~0xFFFFL) == 0;
162 int IsFarRange (long Val)
163 /* Return true if this is a far (24 bit) value */
165 return (Val & ~0xFFFFFFL) == 0;
170 static int IsEasyConst (const ExprNode* E, long* Val)
171 /* Do some light checking if the given node is a constant. Don't care if E is
172 * a complex expression. If E is a constant, return true and place its value
173 * into Val, provided that Val is not NULL.
176 /* Resolve symbols, follow symbol chains */
177 while (E->Op == EXPR_SYMBOL) {
178 E = SymResolve (E->V.Sym);
180 /* Could not resolve */
185 /* Symbols resolved, check for a literal */
186 if (E->Op == EXPR_LITERAL) {
193 /* Not found to be a const according to our tests */
199 static ExprNode* Symbol (SymEntry* S)
200 /* Reference a symbol and return an expression for it */
203 /* Some weird error happened before */
204 return GenLiteralExpr (0);
206 /* Mark the symbol as referenced */
208 /* Create symbol node */
209 return GenSymExpr (S);
215 static ExprNode* FuncBlank (void)
216 /* Handle the .BLANK builtin function */
220 /* Assume no tokens if the closing brace follows (this is not correct in
221 * all cases, since the token may be the closing brace, but this will
222 * give a syntax error anyway and may not be handled by .BLANK.
224 if (Tok != TOK_RPAREN) {
225 /* Skip any tokens */
227 while (!TokIsSep (Tok)) {
228 if (Tok == TOK_LPAREN) {
230 } else if (Tok == TOK_RPAREN) {
242 return GenLiteralExpr (Result);
247 static ExprNode* FuncConst (void)
248 /* Handle the .CONST builtin function */
250 /* Read an expression */
251 ExprNode* Expr = Expression ();
253 /* Check the constness of the expression */
254 ExprNode* Result = GenLiteralExpr (IsConstExpr (Expr, 0));
256 /* Free the expression */
265 static ExprNode* FuncDefined (void)
266 /* Handle the .DEFINED builtin function */
268 /* Parse the symbol name and search for the symbol */
269 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
271 /* Check if the symbol is defined */
272 return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
277 static ExprNode* DoMatch (enum TC EqualityLevel)
278 /* Handle the .MATCH and .XMATCH builtin functions */
285 /* A list of tokens follows. Read this list and remember it building a
286 * single linked list of tokens including attributes. The list is
287 * terminated by a comma.
289 while (Tok != TOK_COMMA) {
291 /* We may not end-of-line of end-of-file here */
292 if (TokIsSep (Tok)) {
293 Error ("Unexpected end of line");
297 /* Get a node with this token */
298 Node = NewTokNode ();
300 /* Insert the node into the list */
315 /* Read the second list which is terminated by the right parenthesis and
316 * compare each token against the one in the first list.
320 while (Tok != TOK_RPAREN) {
322 /* We may not end-of-line of end-of-file here */
323 if (TokIsSep (Tok)) {
324 Error ("Unexpected end of line");
328 /* Compare the tokens if the result is not already known */
331 /* The second list is larger than the first one */
333 } else if (TokCmp (Node) < EqualityLevel) {
334 /* Tokens do not match */
339 /* Next token in first list */
344 /* Next token in current list */
348 /* Check if there are remaining tokens in the first list */
353 /* Free the token list */
360 /* Done, return the result */
361 return GenLiteralExpr (Result);
366 static ExprNode* FuncMatch (void)
367 /* Handle the .MATCH function */
369 return DoMatch (tcSameToken);
374 static ExprNode* FuncReferenced (void)
375 /* Handle the .REFERENCED builtin function */
377 /* Parse the symbol name and search for the symbol */
378 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
380 /* Check if the symbol is referenced */
381 return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
386 static ExprNode* FuncSizeOf (void)
387 /* Handle the .SIZEOF function */
389 StrBuf ScopeName = AUTO_STRBUF_INITIALIZER;
390 char Name[sizeof (SVal)];
398 /* Assume an error */
401 /* Check for a cheap local which needs special handling */
402 if (Tok == TOK_LOCAL_IDENT) {
404 /* Cheap local symbol */
405 Sym = SymFindLocal (SymLast, SVal, SYM_FIND_EXISTING);
407 Error ("Unknown symbol or scope: `%s%s'",
408 SB_GetConstBuf (&ScopeName), Name);
410 SizeSym = GetSizeOfSymbol (Sym);
415 /* Parse the scope and the name */
416 SymTable* ParentScope = ParseScopedIdent (Name, &ScopeName);
418 /* Check if the parent scope is valid */
419 if (ParentScope == 0) {
421 DoneStrBuf (&ScopeName);
422 return GenLiteralExpr (0);
425 /* If ScopeName is empty, no explicit scope was specified. We have to
426 * search upper scope levels in this case.
428 NoScope = SB_IsEmpty (&ScopeName);
430 /* First search for a scope with the given name */
432 Scope = SymFindAnyScope (ParentScope, Name);
434 Scope = SymFindScope (ParentScope, Name, SYM_FIND_EXISTING);
437 /* If we did find a scope with the name, read the symbol defining the
438 * size, otherwise search for a symbol entry with the name and scope.
441 /* Yep, it's a scope */
442 SizeSym = GetSizeOfScope (Scope);
445 Sym = SymFindAny (ParentScope, Name);
447 Sym = SymFind (ParentScope, Name, SYM_FIND_EXISTING);
450 /* If we found the symbol retrieve the size, otherwise complain */
452 SizeSym = GetSizeOfSymbol (Sym);
454 Error ("Unknown symbol or scope: `%s%s'",
455 SB_GetConstBuf (&ScopeName), Name);
460 /* Check if we have a size */
461 if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) {
462 Error ("Size of `%s%s' is unknown", SB_GetConstBuf (&ScopeName), Name);
466 /* Free the scope name */
467 DoneStrBuf (&ScopeName);
469 /* Return the size */
470 return GenLiteralExpr (Size);
475 static ExprNode* FuncStrAt (void)
476 /* Handle the .STRAT function */
478 char Str [sizeof(SVal)];
482 /* String constant expected */
483 if (Tok != TOK_STRCON) {
484 Error ("String constant expected");
490 /* Remember the string and skip it */
494 /* Comma must follow */
497 /* Expression expected */
498 Index = ConstExpression ();
500 /* Must be a valid index */
501 if (Index >= (long) strlen (Str)) {
502 Error ("Range error");
506 /* Get the char, handle as unsigned. Be sure to translate it into
507 * the target character set.
509 C = TgtTranslateChar (Str [(size_t)Index]);
511 /* Return the char expression */
512 return GenLiteralExpr (C);
517 static ExprNode* FuncStrLen (void)
518 /* Handle the .STRLEN function */
522 /* String constant expected */
523 if (Tok != TOK_STRCON) {
525 Error ("String constant expected");
526 /* Smart error recovery */
527 if (Tok != TOK_RPAREN) {
534 /* Get the length of the string */
537 /* Skip the string */
541 /* Return the length */
542 return GenLiteralExpr (Len);
547 static ExprNode* FuncTCount (void)
548 /* Handle the .TCOUNT function */
550 /* We have a list of tokens that ends with the closing paren. Skip
551 * the tokens, handling nested braces and count them.
555 while (Parens != 0 || Tok != TOK_RPAREN) {
557 /* Check for end of line or end of input. Since the calling function
558 * will check for the closing paren, we don't need to print an error
559 * here, just bail out.
561 if (TokIsSep (Tok)) {
568 /* Keep track of the nesting level */
570 case TOK_LPAREN: ++Parens; break;
571 case TOK_RPAREN: --Parens; break;
579 /* Return the number of tokens */
580 return GenLiteralExpr (Count);
585 static ExprNode* FuncXMatch (void)
586 /* Handle the .XMATCH function */
588 return DoMatch (tcIdentical);
593 static ExprNode* Function (ExprNode* (*F) (void))
594 /* Handle builtin functions */
598 /* Skip the keyword */
601 /* Expression must be enclosed in braces */
602 if (Tok != TOK_LPAREN) {
603 Error ("'(' expected");
605 return GenLiteralExpr (0);
609 /* Call the function itself */
612 /* Closing brace must follow */
615 /* Return the result of the actual function */
621 static ExprNode* Factor (void)
630 N = GenLiteralExpr (IVal);
635 N = GenLiteralExpr (TgtTranslateChar (IVal));
641 N = Symbol (ParseScopedSymName (SYM_ALLOC_NEW));
644 case TOK_LOCAL_IDENT:
645 N = Symbol (SymFindLocal (SymLast, SVal, SYM_ALLOC_NEW));
657 if (IsEasyConst (L, &Val)) {
659 N = GenLiteralExpr (-Val);
661 N = NewExprNode (EXPR_UNARY_MINUS);
669 if (IsEasyConst (L, &Val)) {
671 N = GenLiteralExpr (~Val);
673 N = NewExprNode (EXPR_NOT);
687 if (IsEasyConst (L, &Val)) {
689 N = GenLiteralExpr (Val & 0xFF);
691 N = NewExprNode (EXPR_BYTE0);
699 if (IsEasyConst (L, &Val)) {
701 N = GenLiteralExpr ((Val >> 8) & 0xFF);
703 N = NewExprNode (EXPR_BYTE1);
711 if (IsEasyConst (L, &Val)) {
713 N = GenLiteralExpr ((Val >> 16) & 0xFF);
715 N = NewExprNode (EXPR_BYTE2);
727 N = Function (FuncBlank);
731 N = Function (FuncConst);
735 N = GenLiteralExpr (CPUIsets[CPU]);
740 N = Function (FuncDefined);
744 N = Function (FuncMatch);
748 N = Function (FuncReferenced);
752 N = Function (FuncSizeOf);
756 N = Function (FuncStrAt);
760 N = Function (FuncStrLen);
764 N = Function (FuncTCount);
768 N = GenLiteralExpr (time (0));
773 N = GenLiteralExpr (VERSION);
778 N = Function (FuncXMatch);
782 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
783 /* A character constant */
784 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
786 N = GenLiteralExpr (0); /* Dummy */
787 Error ("Syntax error");
797 static ExprNode* Term (void)
799 /* Read left hand side */
800 ExprNode* Root = Factor ();
802 /* Handle multiplicative operations */
803 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
804 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
807 long LVal, RVal, Val;
811 /* Remember the token and skip it */
815 /* Move root to left side and read the right side */
819 /* If both expressions are constant, we can evaluate the term */
820 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
829 Error ("Division by zero");
838 Error ("Modulo operation with zero");
854 Val = shl_l (LVal, RVal);
858 Val = shr_l (LVal, RVal);
862 Internal ("Invalid token");
865 /* Generate a literal expression and delete the old left and
870 Root = GenLiteralExpr (Val);
874 /* Generate an expression tree */
877 case TOK_MUL: Op = EXPR_MUL; break;
878 case TOK_DIV: Op = EXPR_DIV; break;
879 case TOK_MOD: Op = EXPR_MOD; break;
880 case TOK_AND: Op = EXPR_AND; break;
881 case TOK_XOR: Op = EXPR_XOR; break;
882 case TOK_SHL: Op = EXPR_SHL; break;
883 case TOK_SHR: Op = EXPR_SHR; break;
884 default: Internal ("Invalid token");
886 Root = NewExprNode (Op);
894 /* Return the expression tree we've created */
900 static ExprNode* SimpleExpr (void)
902 /* Read left hand side */
903 ExprNode* Root = Term ();
905 /* Handle additive operations */
906 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
908 long LVal, RVal, Val;
912 /* Remember the token and skip it */
916 /* Move root to left side and read the right side */
920 /* If both expressions are constant, we can evaluate the term */
921 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
924 case TOK_PLUS: Val = LVal + RVal; break;
925 case TOK_MINUS: Val = LVal - RVal; break;
926 case TOK_OR: Val = LVal | RVal; break;
927 default: Internal ("Invalid token");
930 /* Generate a literal expression and delete the old left and
935 Root = GenLiteralExpr (Val);
939 /* Generate an expression tree */
942 case TOK_PLUS: Op = EXPR_PLUS; break;
943 case TOK_MINUS: Op = EXPR_MINUS; break;
944 case TOK_OR: Op = EXPR_OR; break;
945 default: Internal ("Invalid token");
947 Root = NewExprNode (Op);
954 /* Return the expression tree we've created */
960 static ExprNode* BoolExpr (void)
961 /* Evaluate a boolean expression */
963 /* Read left hand side */
964 ExprNode* Root = SimpleExpr ();
966 /* Handle booleans */
967 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
968 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
970 long LVal, RVal, Val;
974 /* Remember the token and skip it */
978 /* Move root to left side and read the right side */
980 Right = SimpleExpr ();
982 /* If both expressions are constant, we can evaluate the term */
983 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
986 case TOK_EQ: Val = (LVal == RVal); break;
987 case TOK_NE: Val = (LVal != RVal); break;
988 case TOK_LT: Val = (LVal < RVal); break;
989 case TOK_GT: Val = (LVal > RVal); break;
990 case TOK_LE: Val = (LVal <= RVal); break;
991 case TOK_GE: Val = (LVal >= RVal); break;
992 default: Internal ("Invalid token");
995 /* Generate a literal expression and delete the old left and
1000 Root = GenLiteralExpr (Val);
1004 /* Generate an expression tree */
1007 case TOK_EQ: Op = EXPR_EQ; break;
1008 case TOK_NE: Op = EXPR_NE; break;
1009 case TOK_LT: Op = EXPR_LT; break;
1010 case TOK_GT: Op = EXPR_GT; break;
1011 case TOK_LE: Op = EXPR_LE; break;
1012 case TOK_GE: Op = EXPR_GE; break;
1013 default: Internal ("Invalid token");
1015 Root = NewExprNode (Op);
1017 Root->Right = Right;
1022 /* Return the expression tree we've created */
1028 static ExprNode* Expr2 (void)
1029 /* Boolean operators: AND and XOR */
1031 /* Read left hand side */
1032 ExprNode* Root = BoolExpr ();
1034 /* Handle booleans */
1035 while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
1037 long LVal, RVal, Val;
1041 /* Remember the token and skip it */
1045 /* Move root to left side and read the right side */
1047 Right = BoolExpr ();
1049 /* If both expressions are constant, we can evaluate the term */
1050 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1053 case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break;
1054 case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break;
1055 default: Internal ("Invalid token");
1058 /* Generate a literal expression and delete the old left and
1063 Root = GenLiteralExpr (Val);
1067 /* Generate an expression tree */
1070 case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
1071 case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
1072 default: Internal ("Invalid token");
1074 Root = NewExprNode (Op);
1076 Root->Right = Right;
1081 /* Return the expression tree we've created */
1087 static ExprNode* Expr1 (void)
1088 /* Boolean operators: OR */
1090 /* Read left hand side */
1091 ExprNode* Root = Expr2 ();
1093 /* Handle booleans */
1094 while (Tok == TOK_BOOLOR) {
1096 long LVal, RVal, Val;
1100 /* Remember the token and skip it */
1104 /* Move root to left side and read the right side */
1108 /* If both expressions are constant, we can evaluate the term */
1109 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1112 case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break;
1113 default: Internal ("Invalid token");
1116 /* Generate a literal expression and delete the old left and
1121 Root = GenLiteralExpr (Val);
1125 /* Generate an expression tree */
1128 case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
1129 default: Internal ("Invalid token");
1131 Root = NewExprNode (Op);
1133 Root->Right = Right;
1138 /* Return the expression tree we've created */
1144 static ExprNode* Expr0 (void)
1145 /* Boolean operators: NOT */
1149 /* Handle booleans */
1150 if (Tok == TOK_BOOLNOT) {
1155 /* Skip the operator token */
1158 /* Read the argument */
1161 /* If the argument is const, evaluate it directly */
1162 if (IsEasyConst (Left, &Val)) {
1164 Root = GenLiteralExpr (!Val);
1166 Root = NewExprNode (EXPR_BOOLNOT);
1172 /* Read left hand side */
1177 /* Return the expression tree we've created */
1183 ExprNode* Expression (void)
1184 /* Evaluate an expression, build the expression tree on the heap and return
1185 * a pointer to the root of the tree.
1193 long ConstExpression (void)
1194 /* Parse an expression. Check if the expression is const, and print an error
1195 * message if not. Return the value of the expression, or a dummy, if it is
1201 /* Read the expression */
1202 ExprNode* Expr = Expression ();
1204 /* Study the expression */
1207 StudyExpr (Expr, &D);
1209 /* Check if the expression is constant */
1210 if (ED_IsConst (&D)) {
1213 Error ("Constant expression expected");
1217 /* Free the expression tree and allocated memory for D */
1221 /* Return the value */
1227 void FreeExpr (ExprNode* Root)
1228 /* Free the expression, Root is pointing to. */
1231 FreeExpr (Root->Left);
1232 FreeExpr (Root->Right);
1233 FreeExprNode (Root);
1239 ExprNode* SimplifyExpr (ExprNode* Expr, const ExprDesc* D)
1240 /* Try to simplify the given expression tree */
1242 if (Expr->Op != EXPR_LITERAL && ED_IsConst (D)) {
1243 /* No external references */
1245 Expr = GenLiteralExpr (D->Val);
1252 ExprNode* GenLiteralExpr (long Val)
1253 /* Return an expression tree that encodes the given literal value */
1255 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1262 ExprNode* GenSymExpr (SymEntry* Sym)
1263 /* Return an expression node that encodes the given symbol */
1265 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1267 SymAddExprRef (Sym, Expr);
1273 static ExprNode* GenSectionExpr (unsigned SegNum)
1274 /* Return an expression node for the given section */
1276 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1277 Expr->V.SegNum = SegNum;
1283 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
1284 /* Generate an addition from the two operands */
1287 if (IsEasyConst (Left, &Val) && Val == 0) {
1290 } else if (IsEasyConst (Right, &Val) && Val == 0) {
1294 ExprNode* Root = NewExprNode (EXPR_PLUS);
1296 Root->Right = Right;
1303 ExprNode* GenCurrentPC (void)
1304 /* Return the current program counter as expression */
1309 /* Create SegmentBase + Offset */
1310 Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
1311 GenLiteralExpr (GetPC ()));
1313 /* Absolute mode, just return PC value */
1314 Root = GenLiteralExpr (GetPC ());
1322 ExprNode* GenSwapExpr (ExprNode* Expr)
1323 /* Return an extended expression with lo and hi bytes swapped */
1325 ExprNode* N = NewExprNode (EXPR_SWAP);
1332 ExprNode* GenBranchExpr (unsigned Offs)
1333 /* Return an expression that encodes the difference between current PC plus
1334 * offset and the target expression (that is, Expression() - (*+Offs) ).
1341 /* Read Expression() */
1344 /* If the expression is a cheap constant, generate a simpler tree */
1345 if (IsEasyConst (N, &Val)) {
1347 /* Free the constant expression tree */
1350 /* Generate the final expression:
1352 * Val - ((Seg + PC) + Offs)
1353 * Val - Seg - PC - Offs
1354 * (Val - PC - Offs) - Seg
1356 Root = GenLiteralExpr (Val - GetPC () - Offs);
1359 Root = NewExprNode (EXPR_MINUS);
1361 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1366 /* Generate the expression:
1368 * N - ((Seg + PC) + Offs)
1369 * N - Seg - PC - Offs
1370 * N - (PC + Offs) - Seg
1372 Root = NewExprNode (EXPR_MINUS);
1374 Root->Right = GenLiteralExpr (GetPC () + Offs);
1377 Root = NewExprNode (EXPR_MINUS);
1379 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1383 /* Return the result */
1389 ExprNode* GenULabelExpr (unsigned Num)
1390 /* Return an expression for an unnamed label with the given index */
1392 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1395 /* Return the new node */
1401 ExprNode* GenByteExpr (ExprNode* Expr)
1402 /* Force the given expression into a byte and return the result */
1404 /* Use the low byte operator to force the expression into byte size */
1405 ExprNode* Root = NewExprNode (EXPR_BYTE0);
1408 /* Return the result */
1414 ExprNode* GenWordExpr (ExprNode* Expr)
1415 /* Force the given expression into a word and return the result. */
1417 /* AND the expression by $FFFF to force it into word size */
1418 ExprNode* Root = NewExprNode (EXPR_AND);
1420 Root->Right = GenLiteralExpr (0xFFFF);
1422 /* Return the result */
1428 ExprNode* GenNE (ExprNode* Expr, long Val)
1429 /* Generate an expression that compares Expr and Val for inequality */
1431 /* Generate a compare node */
1432 ExprNode* Root = NewExprNode (EXPR_NE);
1434 Root->Right = GenLiteralExpr (Val);
1436 /* Return the result */
1442 int IsConstExpr (ExprNode* Expr, long* Val)
1443 /* Return true if the given expression is a constant expression, that is, one
1444 * with no references to external symbols. If Val is not NULL and the
1445 * expression is constant, the constant value is stored here.
1450 /* Study the expression */
1453 StudyExpr (Expr, &D);
1455 /* Check if the expression is constant */
1456 IsConst = ED_IsConst (&D);
1457 if (IsConst && Val != 0) {
1461 /* Delete allocated memory and return the result */
1468 static void CheckAddrSize (const ExprNode* N, unsigned char* AddrSize)
1469 /* Internal routine that is recursively called to check for the address size
1470 * of the expression tree.
1474 unsigned char Left, Right;
1477 switch (N->Op & EXPR_TYPEMASK) {
1483 if (SymIsZP (N->V.Sym)) {
1484 if (*AddrSize < ADDR_SIZE_ZP) {
1485 *AddrSize = ADDR_SIZE_ZP;
1487 } else if (SymHasExpr (N->V.Sym)) {
1488 /* Check if this expression is a byte expression */
1489 CheckAddrSize (GetSymExpr (N->V.Sym), AddrSize);
1491 /* Undefined symbol, use absolute */
1492 if (*AddrSize < ADDR_SIZE_ABS) {
1493 *AddrSize = ADDR_SIZE_ABS;
1499 A = GetSegAddrSize (N->V.SegNum);
1500 if (A > *AddrSize) {
1508 case EXPR_UNARYNODE:
1515 /* No need to look at the expression */
1516 *AddrSize = ADDR_SIZE_ZP;
1521 /* No need to look at the expression */
1522 *AddrSize = ADDR_SIZE_ABS;
1526 CheckAddrSize (N->Left, AddrSize);
1531 case EXPR_BINARYNODE:
1532 Left = Right = ADDR_SIZE_DEFAULT;
1533 CheckAddrSize (N->Left, &Left);
1534 CheckAddrSize (N->Right, &Right);
1535 A = (Left > Right)? Left : Right;
1536 if (A > *AddrSize) {
1542 Internal ("Unknown expression op: %02X", N->Op);
1549 int IsByteExpr (ExprNode* Root)
1550 /* Return true if this is a byte expression */
1554 if (IsConstExpr (Root, &Val)) {
1555 return IsByteRange (Val);
1557 unsigned char AddrSize = ADDR_SIZE_DEFAULT;
1558 CheckAddrSize (Root, &AddrSize);
1559 return (AddrSize == ADDR_SIZE_ZP);
1565 ExprNode* CloneExpr (ExprNode* Expr)
1566 /* Clone the given expression tree. The function will simply clone symbol
1567 * nodes, it will not resolve them.
1572 /* Accept NULL pointers */
1577 /* Clone the node */
1581 Clone = GenLiteralExpr (Expr->V.Val);
1585 Clone = GenULabelExpr (Expr->V.Val);
1589 Clone = GenSymExpr (Expr->V.Sym);
1593 Clone = GenSectionExpr (Expr->V.SegNum);
1597 /* Generate a new node */
1598 Clone = NewExprNode (Expr->Op);
1599 /* Clone the tree nodes */
1600 Clone->Left = CloneExpr (Expr->Left);
1601 Clone->Right = CloneExpr (Expr->Right);
1611 void WriteExpr (ExprNode* Expr)
1612 /* Write the given expression to the object file */
1614 /* Null expressions are encoded by a type byte of zero */
1616 ObjWrite8 (EXPR_NULL);
1620 /* If the is a leafnode, write the expression attribute, otherwise
1621 * write the expression operands.
1626 ObjWrite8 (EXPR_LITERAL);
1627 ObjWrite32 (Expr->V.Val);
1631 if (SymIsImport (Expr->V.Sym)) {
1632 ObjWrite8 (EXPR_SYMBOL);
1633 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1635 WriteExpr (GetSymExpr (Expr->V.Sym));
1640 ObjWrite8 (EXPR_SECTION);
1641 ObjWrite8 (Expr->V.SegNum);
1645 WriteExpr (ULabResolve (Expr->V.Val));
1649 /* Not a leaf node */
1650 ObjWrite8 (Expr->Op);
1651 WriteExpr (Expr->Left);
1652 WriteExpr (Expr->Right);