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 /*****************************************************************************/
64 /*****************************************************************************/
66 /*****************************************************************************/
70 /* Since all expressions are first packed into expression trees, and each
71 * expression tree node is allocated on the heap, we add some type of special
72 * purpose memory allocation here: Instead of freeing the nodes, we save some
73 * number of freed nodes for later and remember them in a single linked list
74 * using the Left link.
76 #define MAX_FREE_NODES 64
77 static ExprNode* FreeExprNodes = 0;
78 static unsigned FreeNodeCount = 0;
80 /* Structure for parsing expression trees */
81 typedef struct ExprDesc ExprDesc;
83 long Val; /* The offset value */
84 long Left; /* Left value for StudyBinaryExpr */
85 int TooComplex; /* Expression is too complex to evaluate */
86 long SymCount; /* Symbol reference count */
87 long SecCount; /* Section reference count */
88 SymEntry* SymRef; /* Symbol reference if any */
89 unsigned SecRef; /* Section reference if any */
95 /*****************************************************************************/
97 /*****************************************************************************/
101 static ExprDesc* InitExprDesc (ExprDesc* ED)
102 /* Initialize an ExprDesc structure for use with StudyExpr */
113 static int ExprDescIsConst (const ExprDesc* ED)
114 /* Return true if the expression is constant */
116 return (ED->TooComplex == 0 && ED->SymCount == 0 && ED->SecCount == 0);
121 static ExprNode* NewExprNode (unsigned Op)
122 /* Create a new expression node */
126 /* Do we have some nodes in the list already? */
128 /* Use first node from list */
130 FreeExprNodes = N->Left;
132 /* Allocate fresh memory */
133 N = xmalloc (sizeof (ExprNode));
136 N->Left = N->Right = 0;
144 static void FreeExprNode (ExprNode* E)
148 if (E->Op == EXPR_SYMBOL) {
149 /* Remove the symbol reference */
150 SymDelExprRef (E->V.Sym, E);
152 /* Place the symbol into the free nodes list if possible */
153 if (FreeNodeCount < MAX_FREE_NODES) {
154 /* Remember this node for later */
155 E->Left = FreeExprNodes;
158 /* Free the memory */
166 /*****************************************************************************/
168 /*****************************************************************************/
172 static ExprNode* Expr0 (void);
176 int IsByteRange (long Val)
177 /* Return true if this is a byte value */
179 return (Val & ~0xFFL) == 0;
184 int IsWordRange (long Val)
185 /* Return true if this is a word value */
187 return (Val & ~0xFFFF) == 0;
192 static int FuncBlank (void)
193 /* Handle the .BLANK builtin function */
195 /* Assume no tokens if the closing brace follows (this is not correct in
196 * all cases, since the token may be the closing brace, but this will
197 * give a syntax error anyway and may not be handled by .BLANK.
199 if (Tok == TOK_RPAREN) {
203 /* Skip any tokens */
205 while (!TokIsSep (Tok)) {
206 if (Tok == TOK_LPAREN) {
208 } else if (Tok == TOK_RPAREN) {
224 static int FuncConst (void)
225 /* Handle the .CONST builtin function */
227 /* Read an expression */
228 ExprNode* Expr = Expression ();
230 /* Check the constness of the expression */
231 int Result = IsConstExpr (Expr, 0);
233 /* Free the expression */
242 static int FuncDefined (void)
243 /* Handle the .DEFINED builtin function */
245 /* Parse the symbol name and search for the symbol */
246 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
248 /* Check if the symbol is defined */
249 return (Sym != 0 && SymIsDef (Sym));
254 static int DoMatch (enum TC EqualityLevel)
255 /* Handle the .MATCH and .XMATCH builtin functions */
262 /* A list of tokens follows. Read this list and remember it building a
263 * single linked list of tokens including attributes. The list is
264 * terminated by a comma.
266 while (Tok != TOK_COMMA) {
268 /* We may not end-of-line of end-of-file here */
269 if (TokIsSep (Tok)) {
270 Error ("Unexpected end of line");
274 /* Get a node with this token */
275 Node = NewTokNode ();
277 /* Insert the node into the list */
292 /* Read the second list which is terminated by the right parenthesis and
293 * compare each token against the one in the first list.
297 while (Tok != TOK_RPAREN) {
299 /* We may not end-of-line of end-of-file here */
300 if (TokIsSep (Tok)) {
301 Error ("Unexpected end of line");
305 /* Compare the tokens if the result is not already known */
308 /* The second list is larger than the first one */
310 } else if (TokCmp (Node) < EqualityLevel) {
311 /* Tokens do not match */
316 /* Next token in first list */
321 /* Next token in current list */
325 /* Check if there are remaining tokens in the first list */
330 /* Free the token list */
337 /* Done, return the result */
343 static int FuncMatch (void)
344 /* Handle the .MATCH function */
346 return DoMatch (tcSameToken);
351 static int FuncReferenced (void)
352 /* Handle the .REFERENCED builtin function */
354 /* Parse the symbol name and search for the symbol */
355 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
357 /* Check if the symbol is referenced */
358 return (Sym != 0 && SymIsRef (Sym));
363 static int FuncStrAt (void)
364 /* Handle the .STRAT function */
366 char Str [sizeof(SVal)];
369 /* String constant expected */
370 if (Tok != TOK_STRCON) {
371 Error ("String constant expected");
377 /* Remember the string and skip it */
381 /* Comma must follow */
384 /* Expression expected */
385 Index = ConstExpression ();
387 /* Must be a valid index */
388 if (Index >= (long) strlen (Str)) {
389 Error ("Range error");
393 /* Return the char, handle as unsigned. Be sure to translate it into
394 * the target character set.
396 return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
401 static int FuncStrLen (void)
402 /* Handle the .STRLEN function */
404 /* String constant expected */
405 if (Tok != TOK_STRCON) {
407 Error ("String constant expected");
408 /* Smart error recovery */
409 if (Tok != TOK_RPAREN) {
416 /* Get the length of the string */
417 int Len = strlen (SVal);
419 /* Skip the string */
422 /* Return the length */
430 static int FuncTCount (void)
431 /* Handle the .TCOUNT function */
433 /* We have a list of tokens that ends with the closing paren. Skip
434 * the tokens, handling nested braces and count them.
438 while (Parens != 0 || Tok != TOK_RPAREN) {
440 /* Check for end of line or end of input. Since the calling function
441 * will check for the closing paren, we don't need to print an error
442 * here, just bail out.
444 if (TokIsSep (Tok)) {
451 /* Keep track of the nesting level */
453 case TOK_LPAREN: ++Parens; break;
454 case TOK_RPAREN: --Parens; break;
462 /* Return the number of tokens */
468 static int FuncXMatch (void)
469 /* Handle the .XMATCH function */
471 return DoMatch (tcIdentical);
476 static ExprNode* Function (int (*F) (void))
477 /* Handle builtin functions */
481 /* Skip the keyword */
484 /* Expression must be enclosed in braces */
485 if (Tok != TOK_LPAREN) {
486 Error ("'(' expected");
488 return GenLiteralExpr (0);
492 /* Call the function itself */
495 /* Closing brace must follow */
498 /* Return an expression node with the boolean code */
499 return GenLiteralExpr (Result);
504 static ExprNode* Factor (void)
512 N = GenLiteralExpr (IVal);
517 N = GenLiteralExpr (TgtTranslateChar (IVal));
523 /* Search for the symbol */
524 S = ParseScopedSymName (SYM_ALLOC_NEW);
526 /* Some weird error happened before */
527 N = GenLiteralExpr (0);
529 /* Mark the symbol as referenced */
531 /* Create symbol node */
543 N = NewExprNode (EXPR_UNARY_MINUS);
549 N = NewExprNode (EXPR_NOT);
561 N = NewExprNode (EXPR_BYTE0);
567 N = NewExprNode (EXPR_BYTE1);
573 N = NewExprNode (EXPR_BYTE2);
584 N = Function (FuncBlank);
588 N = Function (FuncConst);
592 N = GenLiteralExpr (CPUIsets[CPU]);
597 N = Function (FuncDefined);
601 N = Function (FuncMatch);
605 N = Function (FuncReferenced);
609 N = Function (FuncStrAt);
613 N = Function (FuncStrLen);
617 N = Function (FuncTCount);
621 N = GenLiteralExpr (time (0));
626 N = GenLiteralExpr (VERSION);
632 N = Function (FuncXMatch);
636 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
637 /* A character constant */
638 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
640 N = GenLiteralExpr (0); /* Dummy */
641 Error ("Syntax error");
651 static ExprNode* Term (void)
653 /* Read left hand side */
654 ExprNode* Root = Factor ();
656 /* Handle multiplicative operations */
657 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
658 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
661 /* Create the new node */
662 ExprNode* Left = Root;
664 case TOK_MUL: Root = NewExprNode (EXPR_MUL); break;
665 case TOK_DIV: Root = NewExprNode (EXPR_DIV); break;
666 case TOK_MOD: Root = NewExprNode (EXPR_MOD); break;
667 case TOK_AND: Root = NewExprNode (EXPR_AND); break;
668 case TOK_XOR: Root = NewExprNode (EXPR_XOR); break;
669 case TOK_SHL: Root = NewExprNode (EXPR_SHL); break;
670 case TOK_SHR: Root = NewExprNode (EXPR_SHR); break;
671 default: Internal ("Invalid token");
675 /* Skip the operator token */
678 /* Parse the right hand side */
679 Root->Right = Factor ();
683 /* Return the expression tree we've created */
689 static ExprNode* SimpleExpr (void)
691 /* Read left hand side */
692 ExprNode* Root = Term ();
694 /* Handle additive operations */
695 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
697 /* Create the new node */
698 ExprNode* Left = Root;
700 case TOK_PLUS: Root = NewExprNode (EXPR_PLUS); break;
701 case TOK_MINUS: Root = NewExprNode (EXPR_MINUS); break;
702 case TOK_OR: Root = NewExprNode (EXPR_OR); break;
703 default: Internal ("Invalid token");
707 /* Skip the operator token */
710 /* Parse the right hand side */
711 Root->Right = Term ();
715 /* Return the expression tree we've created */
721 static ExprNode* BoolExpr (void)
722 /* Evaluate a boolean expression */
724 /* Read left hand side */
725 ExprNode* Root = SimpleExpr ();
727 /* Handle booleans */
728 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
729 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
731 /* Create the new node */
732 ExprNode* Left = Root;
734 case TOK_EQ: Root = NewExprNode (EXPR_EQ); break;
735 case TOK_NE: Root = NewExprNode (EXPR_NE); break;
736 case TOK_LT: Root = NewExprNode (EXPR_LT); break;
737 case TOK_GT: Root = NewExprNode (EXPR_GT); break;
738 case TOK_LE: Root = NewExprNode (EXPR_LE); break;
739 case TOK_GE: Root = NewExprNode (EXPR_GE); break;
740 default: Internal ("Invalid token");
744 /* Skip the operator token */
747 /* Parse the right hand side */
748 Root->Right = SimpleExpr ();
752 /* Return the expression tree we've created */
758 static ExprNode* Expr2 (void)
759 /* Boolean operators: AND and XOR */
761 /* Read left hand side */
762 ExprNode* Root = BoolExpr ();
764 /* Handle booleans */
765 while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
767 /* Create the new node */
768 ExprNode* Left = Root;
770 case TOK_BOOLAND: Root = NewExprNode (EXPR_BOOLAND); break;
771 case TOK_BOOLXOR: Root = NewExprNode (EXPR_BOOLXOR); break;
772 default: Internal ("Invalid token");
776 /* Skip the operator token */
779 /* Parse the right hand side */
780 Root->Right = BoolExpr ();
784 /* Return the expression tree we've created */
790 static ExprNode* Expr1 (void)
791 /* Boolean operators: OR */
793 /* Read left hand side */
794 ExprNode* Root = Expr2 ();
796 /* Handle booleans */
797 while (Tok == TOK_BOOLOR) {
799 /* Create the new node */
800 ExprNode* Left = Root;
802 case TOK_BOOLOR: Root = NewExprNode (EXPR_BOOLOR); break;
803 default: Internal ("Invalid token");
807 /* Skip the operator token */
810 /* Parse the right hand side */
811 Root->Right = Expr2 ();
815 /* Return the expression tree we've created */
821 static ExprNode* Expr0 (void)
822 /* Boolean operators: NOT */
826 /* Handle booleans */
827 if (Tok == TOK_BOOLNOT) {
829 /* Create the new node */
830 Root = NewExprNode (EXPR_BOOLNOT);
832 /* Skip the operator token */
835 /* Parse the left hand side, allow more BNOTs */
836 Root->Left = Expr0 ();
840 /* Read left hand side */
845 /* Return the expression tree we've created */
851 static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
852 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
853 /* Study a binary expression subtree */
855 StudyExpr (Expr->Left, D, 1);
856 if (ExprDescIsConst (D)) {
859 StudyExpr (Expr->Right, D, 1);
860 if (!ExprDescIsConst (D)) {
870 static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign)
871 /* Study an expression tree and place the contents into D */
878 /* Initialize SD. This is not needed in all cases, but it's rather cheap
879 * and simplifies the code below.
883 /* Study this expression node */
887 D->Val += (Sign * Expr->V.Val);
892 if (SymIsImport (Sym)) {
893 if (D->SymCount == 0) {
896 } else if (D->SymRef == Sym) {
900 /* More than one import */
903 } else if (SymHasExpr (Sym)) {
904 if (SymHasUserMark (Sym)) {
906 DumpExpr (Expr, SymResolve);
908 PError (GetSymPos (Sym),
909 "Circular reference in definition of symbol `%s'",
914 StudyExpr (GetSymExpr (Sym), D, Sign);
923 Sec = Expr->V.SegNum;
924 if (D->SecCount == 0) {
927 } else if (D->SecRef == Sec) {
931 /* More than one section */
937 if (ULabCanResolve ()) {
938 /* We can resolve the label */
939 StudyExpr (ULabResolve (Expr->V.Val), D, Sign);
946 StudyExpr (Expr->Left, D, Sign);
947 StudyExpr (Expr->Right, D, Sign);
951 StudyExpr (Expr->Left, D, Sign);
952 StudyExpr (Expr->Right, D, -Sign);
957 StudyExpr (Expr->Left, &SD, 1);
958 StudyExpr (Expr->Right, &SD1, 1);
959 if (SD.TooComplex == 0 && SD1.TooComplex == 0) {
960 /* First calculate SD = SD*SD1 if possible */
961 if (ExprDescIsConst (&SD)) {
962 /* Left is a constant */
964 SD1.SymCount *= SD.Val;
965 SD1.SecCount *= SD.Val;
967 } else if (ExprDescIsConst (&SD1)) {
968 /* Right is constant */
970 SD.SymCount *= SD1.Val;
971 SD.SecCount *= SD1.Val;
975 /* Now calculate D * Sign * SD */
976 if (!D->TooComplex) {
977 if ((D->SymCount == 0 || SD.SymCount == 0 || D->SymRef == SD.SymRef) &&
978 (D->SecCount == 0 || SD.SecCount == 0 || D->SecRef == SD.SecRef)) {
979 D->Val += (Sign * SD.Val);
980 if (D->SymCount == 0) {
981 D->SymRef = SD.SymRef;
983 D->SymCount += (Sign * SD.SymCount);
984 if (D->SecCount == 0) {
985 D->SecRef = SD.SecRef;
987 D->SecCount += (Sign * SD.SecCount);
998 StudyBinaryExpr (Expr, &SD);
999 if (!SD.TooComplex) {
1001 Error ("Division by zero");
1004 D->Val += Sign * (SD.Left / SD.Val);
1012 StudyBinaryExpr (Expr, &SD);
1013 if (!SD.TooComplex) {
1015 Error ("Modulo operation with zero");
1018 D->Val += Sign * (SD.Left % SD.Val);
1026 StudyBinaryExpr (Expr, &SD);
1027 if (!SD.TooComplex) {
1028 D->Val += Sign * (SD.Left | SD.Val);
1035 StudyBinaryExpr (Expr, &SD);
1036 if (!SD.TooComplex) {
1037 D->Val += Sign * (SD.Left ^ SD.Val);
1044 StudyBinaryExpr (Expr, &SD);
1045 if (!SD.TooComplex) {
1046 D->Val += Sign * (SD.Left & SD.Val);
1053 StudyBinaryExpr (Expr, &SD);
1054 if (!SD.TooComplex) {
1055 D->Val += (Sign * shl_l (SD.Left, (unsigned) SD.Val));
1062 StudyBinaryExpr (Expr, &SD);
1063 if (!SD.TooComplex) {
1064 D->Val += (Sign * shr_l (SD.Left, (unsigned) SD.Val));
1071 StudyBinaryExpr (Expr, &SD);
1072 if (!SD.TooComplex) {
1073 D->Val += Sign * (SD.Left == SD.Val);
1080 StudyBinaryExpr (Expr, &SD);
1081 if (!SD.TooComplex) {
1082 D->Val += Sign * (SD.Left != SD.Val);
1089 StudyBinaryExpr (Expr, &SD);
1090 if (!SD.TooComplex) {
1091 D->Val += Sign * (SD.Left < SD.Val);
1098 StudyBinaryExpr (Expr, &SD);
1099 if (!SD.TooComplex) {
1100 D->Val += Sign * (SD.Left > SD.Val);
1107 StudyBinaryExpr (Expr, &SD);
1108 if (!SD.TooComplex) {
1109 D->Val += Sign * (SD.Left <= SD.Val);
1116 StudyBinaryExpr (Expr, &SD);
1117 if (!SD.TooComplex) {
1118 D->Val += Sign * (SD.Left >= SD.Val);
1125 StudyExpr (Expr->Left, &SD, 1);
1126 if (ExprDescIsConst (&SD)) {
1127 if (SD.Val != 0) { /* Shortcut op */
1129 StudyExpr (Expr->Right, &SD, 1);
1130 if (ExprDescIsConst (&SD)) {
1131 D->Val += Sign * (SD.Val != 0);
1142 StudyExpr (Expr->Left, &SD, 1);
1143 if (ExprDescIsConst (&SD)) {
1144 if (SD.Val == 0) { /* Shortcut op */
1145 StudyExpr (Expr->Right, &SD, 1);
1146 if (ExprDescIsConst (&SD)) {
1147 D->Val += Sign * (SD.Val != 0);
1160 StudyBinaryExpr (Expr, &SD);
1161 if (!SD.TooComplex) {
1162 D->Val += Sign * ((SD.Left != 0) ^ (SD.Val != 0));
1166 case EXPR_UNARY_MINUS:
1167 StudyExpr (Expr->Left, D, -Sign);
1171 StudyExpr (Expr->Left, &SD, 1);
1172 if (ExprDescIsConst (&SD)) {
1173 D->Val += (Sign * ~SD.Val);
1180 StudyExpr (Expr->Left, &SD, 1);
1181 if (ExprDescIsConst (&SD)) {
1182 D->Val += Sign * (((SD.Val >> 8) & 0x00FF) | ((SD.Val << 8) & 0xFF00));
1189 StudyExpr (Expr->Left, &SD, 1);
1190 if (ExprDescIsConst (&SD)) {
1191 D->Val += Sign * (SD.Val != 0);
1197 case EXPR_FORCEWORD:
1200 StudyExpr (Expr->Left, D, Sign);
1204 StudyExpr (Expr->Left, &SD, 1);
1205 if (ExprDescIsConst (&SD)) {
1206 D->Val += Sign * (SD.Val & 0xFF);
1213 StudyExpr (Expr->Left, &SD, 1);
1214 if (ExprDescIsConst (&SD)) {
1215 D->Val += Sign * ((SD.Val >> 8) & 0xFF);
1222 StudyExpr (Expr->Left, &SD, 1);
1223 if (ExprDescIsConst (&SD)) {
1224 D->Val += Sign * ((SD.Val >> 16) & 0xFF);
1231 StudyExpr (Expr->Left, &SD, 1);
1232 if (ExprDescIsConst (&SD)) {
1233 D->Val += Sign * ((SD.Val >> 24) & 0xFF);
1240 StudyExpr (Expr->Left, &SD, 1);
1241 if (ExprDescIsConst (&SD)) {
1242 D->Val += Sign * (SD.Val & 0xFFFF);
1249 StudyExpr (Expr->Left, &SD, 1);
1250 if (ExprDescIsConst (&SD)) {
1251 D->Val += Sign * ((SD.Val >> 16) & 0xFFFF);
1258 Internal ("Unknown Op type: %u", Expr->Op);
1265 static ExprNode* SimplifyExpr (ExprNode* Expr)
1266 /* Try to simplify the given expression tree */
1268 if (Expr && Expr->Op != EXPR_LITERAL) {
1270 /* Create an expression description and initialize it */
1274 /* Study the expression */
1275 StudyExpr (Expr, &D, 1);
1277 /* Now check if we can generate a literal value */
1278 if (ExprDescIsConst (&D)) {
1279 /* No external references */
1281 Expr = GenLiteralExpr (D.Val);
1289 ExprNode* Expression (void)
1290 /* Evaluate an expression, build the expression tree on the heap and return
1291 * a pointer to the root of the tree.
1295 return SimplifyExpr (Expr0 ());
1298 ExprNode* Expr = Expr0 ();
1299 printf ("Before: "); DumpExpr (Expr, SymResolve);
1300 Expr = SimplifyExpr (Expr);
1301 printf ("After: "); DumpExpr (Expr, SymResolve);
1308 long ConstExpression (void)
1309 /* Parse an expression. Check if the expression is const, and print an error
1310 * message if not. Return the value of the expression, or a dummy, if it is
1315 /* Read the expression */
1316 ExprNode* Expr = Expr0 ();
1319 ExprNode* Expr = Expression ();
1322 /* Study the expression */
1325 StudyExpr (Expr, &D, 1);
1327 /* Check if the expression is constant */
1328 if (!ExprDescIsConst (&D)) {
1329 Error ("Constant expression expected");
1333 /* Free the expression tree and return the value */
1340 void FreeExpr (ExprNode* Root)
1341 /* Free the expression, Root is pointing to. */
1344 FreeExpr (Root->Left);
1345 FreeExpr (Root->Right);
1346 FreeExprNode (Root);
1352 ExprNode* GenLiteralExpr (long Val)
1353 /* Return an expression tree that encodes the given literal value */
1355 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1362 ExprNode* GenSymExpr (SymEntry* Sym)
1363 /* Return an expression node that encodes the given symbol */
1365 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1367 SymAddExprRef (Sym, Expr);
1373 static ExprNode* GenSectionExpr (unsigned SegNum)
1374 /* Return an expression node for the given section */
1376 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1377 Expr->V.SegNum = SegNum;
1383 ExprNode* GenCurrentPC (void)
1384 /* Return the current program counter as expression */
1389 /* Create SegmentBase + Offset */
1390 Root = NewExprNode (EXPR_PLUS);
1391 Root->Left = GenSectionExpr (GetCurrentSegNum ());
1392 Root->Right = GenLiteralExpr (GetPC ());
1394 /* Absolute mode, just return PC value */
1395 Root = GenLiteralExpr (GetPC ());
1403 ExprNode* GenSwapExpr (ExprNode* Expr)
1404 /* Return an extended expression with lo and hi bytes swapped */
1406 ExprNode* N = NewExprNode (EXPR_SWAP);
1413 ExprNode* GenBranchExpr (unsigned Offs)
1414 /* Return an expression that encodes the difference between current PC plus
1415 * offset and the target expression (that is, Expression() - (*+Offs) ).
1423 N = NewExprNode (EXPR_PLUS);
1424 N->Left = GenSectionExpr (GetCurrentSegNum ());
1425 N->Right = GenLiteralExpr (GetPC () + Offs);
1427 N = GenLiteralExpr (GetPC () + Offs);
1430 /* Create the root node */
1431 Root = NewExprNode (EXPR_MINUS);
1432 Root->Left = Expression ();
1435 /* Return the result */
1436 return SimplifyExpr (Root);
1441 ExprNode* GenULabelExpr (unsigned Num)
1442 /* Return an expression for an unnamed label with the given index */
1444 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1447 /* Return the new node */
1453 ExprNode* GenByteExpr (ExprNode* Expr)
1454 /* Force the given expression into a byte and return the result */
1456 /* Use the low byte operator to force the expression into byte size */
1457 ExprNode* Root = NewExprNode (EXPR_BYTE0);
1460 /* Return the result */
1466 ExprNode* GenWordExpr (ExprNode* Expr)
1467 /* Force the given expression into a word and return the result. */
1469 /* AND the expression by $FFFF to force it into word size */
1470 ExprNode* Root = NewExprNode (EXPR_AND);
1472 Root->Right = GenLiteralExpr (0xFFFF);
1474 /* Return the result */
1480 ExprNode* GenNE (ExprNode* Expr, long Val)
1481 /* Generate an expression that compares Expr and Val for inequality */
1483 /* Generate a compare node */
1484 ExprNode* Root = NewExprNode (EXPR_NE);
1486 Root->Right = GenLiteralExpr (Val);
1488 /* Return the result */
1494 int IsConstExpr (ExprNode* Expr, long* Val)
1495 /* Return true if the given expression is a constant expression, that is, one
1496 * with no references to external symbols. If Val is not NULL and the
1497 * expression is constant, the constant value is stored here.
1500 /* Study the expression */
1503 StudyExpr (Expr, &D, 1);
1505 /* Check if the expression is constant */
1506 if (ExprDescIsConst (&D)) {
1518 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1519 /* Internal routine that is recursively called to check if there is a zeropage
1520 * symbol in the expression tree.
1524 switch (N->Op & EXPR_TYPEMASK) {
1530 if (SymIsZP (N->V.Sym)) {
1532 } else if (SymHasExpr (N->V.Sym)) {
1533 /* Check if this expression is a byte expression */
1534 *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
1539 if (GetSegAddrSize (N->V.SegNum) == ADDR_SIZE_ZP) {
1547 case EXPR_UNARYNODE:
1548 CheckByteExpr (N->Left, IsByte);
1551 case EXPR_BINARYNODE:
1552 CheckByteExpr (N->Left, IsByte);
1553 CheckByteExpr (N->Right, IsByte);
1557 Internal ("Unknown expression op: %02X", N->Op);
1564 int IsByteExpr (ExprNode* Root)
1565 /* Return true if this is a byte expression */
1570 if (IsConstExpr (Root, &Val)) {
1571 IsByte = IsByteRange (Val);
1572 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1573 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1574 /* Symbol forced to have byte range */
1577 /* We have undefined symbols in the expression. Assume that the
1578 * expression is a byte expression if there is at least one symbol
1579 * declared as zeropage in it. Being wrong here is not a very big
1580 * problem since the linker knows about all symbols and detects
1581 * error like mixing absolute and zeropage labels.
1584 CheckByteExpr (Root, &IsByte);
1591 ExprNode* CloneExpr (ExprNode* Expr)
1592 /* Clone the given expression tree. The function will simply clone symbol
1593 * nodes, it will not resolve them.
1598 /* Accept NULL pointers */
1603 /* Clone the node */
1607 Clone = GenLiteralExpr (Expr->V.Val);
1611 Clone = GenULabelExpr (Expr->V.Val);
1615 Clone = GenSymExpr (Expr->V.Sym);
1619 Clone = GenSectionExpr (Expr->V.SegNum);
1623 /* Generate a new node */
1624 Clone = NewExprNode (Expr->Op);
1625 /* Clone the tree nodes */
1626 Clone->Left = CloneExpr (Expr->Left);
1627 Clone->Right = CloneExpr (Expr->Right);
1637 void WriteExpr (ExprNode* Expr)
1638 /* Write the given expression to the object file */
1640 /* Null expressions are encoded by a type byte of zero */
1642 ObjWrite8 (EXPR_NULL);
1646 /* If the is a leafnode, write the expression attribute, otherwise
1647 * write the expression operands.
1652 ObjWrite8 (EXPR_LITERAL);
1653 ObjWrite32 (Expr->V.Val);
1657 if (SymIsImport (Expr->V.Sym)) {
1658 ObjWrite8 (EXPR_SYMBOL);
1659 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1661 WriteExpr (GetSymExpr (Expr->V.Sym));
1666 ObjWrite8 (EXPR_SECTION);
1667 ObjWrite8 (Expr->V.SegNum);
1671 WriteExpr (ULabResolve (Expr->V.Val));
1675 /* Not a leaf node */
1676 ObjWrite8 (Expr->Op);
1677 WriteExpr (Expr->Left);
1678 WriteExpr (Expr->Right);