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 /*****************************************************************************/
65 /*****************************************************************************/
67 /*****************************************************************************/
71 /* Since all expressions are first packed into expression trees, and each
72 * expression tree node is allocated on the heap, we add some type of special
73 * purpose memory allocation here: Instead of freeing the nodes, we save some
74 * number of freed nodes for later and remember them in a single linked list
75 * using the Left link.
77 #define MAX_FREE_NODES 64
78 static ExprNode* FreeExprNodes = 0;
79 static unsigned FreeNodeCount = 0;
81 /* Structure for parsing expression trees */
82 typedef struct ExprDesc ExprDesc;
84 long Val; /* The offset value */
85 long Left; /* Left value for StudyBinaryExpr */
86 int TooComplex; /* Expression is too complex to evaluate */
87 long SymCount; /* Symbol reference count */
88 long SecCount; /* Section reference count */
89 SymEntry* SymRef; /* Symbol reference if any */
90 unsigned SecRef; /* Section reference if any */
96 /*****************************************************************************/
98 /*****************************************************************************/
102 static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
103 /* Study an expression tree and place the contents into D */
107 /*****************************************************************************/
109 /*****************************************************************************/
113 static ExprDesc* InitExprDesc (ExprDesc* ED)
114 /* Initialize an ExprDesc structure for use with StudyExpr */
125 static int ExprDescIsConst (const ExprDesc* ED)
126 /* Return true if the expression is constant */
128 return (ED->TooComplex == 0 && ED->SymCount == 0 && ED->SecCount == 0);
133 static ExprNode* NewExprNode (unsigned Op)
134 /* Create a new expression node */
138 /* Do we have some nodes in the list already? */
140 /* Use first node from list */
142 FreeExprNodes = N->Left;
144 /* Allocate fresh memory */
145 N = xmalloc (sizeof (ExprNode));
148 N->Left = N->Right = 0;
156 static void FreeExprNode (ExprNode* E)
160 if (E->Op == EXPR_SYMBOL) {
161 /* Remove the symbol reference */
162 SymDelExprRef (E->V.Sym, E);
164 /* Place the symbol into the free nodes list if possible */
165 if (FreeNodeCount < MAX_FREE_NODES) {
166 /* Remember this node for later */
167 E->Left = FreeExprNodes;
170 /* Free the memory */
178 /*****************************************************************************/
180 /*****************************************************************************/
184 static ExprNode* Expr0 (void);
188 int IsByteRange (long Val)
189 /* Return true if this is a byte value */
191 return (Val & ~0xFFL) == 0;
196 int IsWordRange (long Val)
197 /* Return true if this is a word value */
199 return (Val & ~0xFFFF) == 0;
204 static int IsEasyConst (const ExprNode* E, long* Val)
205 /* Do some light checking if the given node is a constant. Don't care if E is
206 * a complex expression. If E is a constant, return true and place its value
207 * into Val, provided that Val is not NULL.
210 /* Resolve symbols, follow symbol chains */
211 while (E->Op == EXPR_SYMBOL) {
212 E = SymResolve (E->V.Sym);
214 /* Could not resolve */
219 /* Symbols resolved, check for a literal */
220 if (E->Op == EXPR_LITERAL) {
227 /* Not found to be a const according to our tests */
233 static ExprNode* FuncBlank (void)
234 /* Handle the .BLANK builtin function */
238 /* Assume no tokens if the closing brace follows (this is not correct in
239 * all cases, since the token may be the closing brace, but this will
240 * give a syntax error anyway and may not be handled by .BLANK.
242 if (Tok != TOK_RPAREN) {
243 /* Skip any tokens */
245 while (!TokIsSep (Tok)) {
246 if (Tok == TOK_LPAREN) {
248 } else if (Tok == TOK_RPAREN) {
260 return GenLiteralExpr (Result);
265 static ExprNode* FuncConst (void)
266 /* Handle the .CONST builtin function */
268 /* Read an expression */
269 ExprNode* Expr = Expression ();
271 /* Check the constness of the expression */
272 ExprNode* Result = GenLiteralExpr (IsConstExpr (Expr, 0));
274 /* Free the expression */
283 static ExprNode* FuncDefined (void)
284 /* Handle the .DEFINED builtin function */
286 /* Parse the symbol name and search for the symbol */
287 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
289 /* Check if the symbol is defined */
290 return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
295 static ExprNode* DoMatch (enum TC EqualityLevel)
296 /* Handle the .MATCH and .XMATCH builtin functions */
303 /* A list of tokens follows. Read this list and remember it building a
304 * single linked list of tokens including attributes. The list is
305 * terminated by a comma.
307 while (Tok != TOK_COMMA) {
309 /* We may not end-of-line of end-of-file here */
310 if (TokIsSep (Tok)) {
311 Error ("Unexpected end of line");
315 /* Get a node with this token */
316 Node = NewTokNode ();
318 /* Insert the node into the list */
333 /* Read the second list which is terminated by the right parenthesis and
334 * compare each token against the one in the first list.
338 while (Tok != TOK_RPAREN) {
340 /* We may not end-of-line of end-of-file here */
341 if (TokIsSep (Tok)) {
342 Error ("Unexpected end of line");
346 /* Compare the tokens if the result is not already known */
349 /* The second list is larger than the first one */
351 } else if (TokCmp (Node) < EqualityLevel) {
352 /* Tokens do not match */
357 /* Next token in first list */
362 /* Next token in current list */
366 /* Check if there are remaining tokens in the first list */
371 /* Free the token list */
378 /* Done, return the result */
379 return GenLiteralExpr (Result);
384 static ExprNode* FuncMatch (void)
385 /* Handle the .MATCH function */
387 return DoMatch (tcSameToken);
392 static ExprNode* FuncReferenced (void)
393 /* Handle the .REFERENCED builtin function */
395 /* Parse the symbol name and search for the symbol */
396 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
398 /* Check if the symbol is referenced */
399 return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
404 static ExprNode* FuncSizeOf (void)
405 /* Handle the .SIZEOF function */
409 /* Get the struct for the scoped struct name */
410 SymTable* Struct = ParseScopedSymTable (SYM_FIND_EXISTING);
412 /* Check if the given symbol is really a struct */
413 if (GetSymTabType (Struct) != ST_STRUCT) {
414 Error ("Argument to .SIZEOF is not a struct");
417 Size = GetStructSize (Struct);
420 /* Return the size */
421 return GenLiteralExpr (Size);
426 static ExprNode* FuncStrAt (void)
427 /* Handle the .STRAT function */
429 char Str [sizeof(SVal)];
433 /* String constant expected */
434 if (Tok != TOK_STRCON) {
435 Error ("String constant expected");
441 /* Remember the string and skip it */
445 /* Comma must follow */
448 /* Expression expected */
449 Index = ConstExpression ();
451 /* Must be a valid index */
452 if (Index >= (long) strlen (Str)) {
453 Error ("Range error");
457 /* Get the char, handle as unsigned. Be sure to translate it into
458 * the target character set.
460 C = TgtTranslateChar (Str [(size_t)Index]);
462 /* Return the char expression */
463 return GenLiteralExpr (C);
468 static ExprNode* FuncStrLen (void)
469 /* Handle the .STRLEN function */
473 /* String constant expected */
474 if (Tok != TOK_STRCON) {
476 Error ("String constant expected");
477 /* Smart error recovery */
478 if (Tok != TOK_RPAREN) {
485 /* Get the length of the string */
488 /* Skip the string */
492 /* Return the length */
493 return GenLiteralExpr (Len);
498 static ExprNode* FuncTCount (void)
499 /* Handle the .TCOUNT function */
501 /* We have a list of tokens that ends with the closing paren. Skip
502 * the tokens, handling nested braces and count them.
506 while (Parens != 0 || Tok != TOK_RPAREN) {
508 /* Check for end of line or end of input. Since the calling function
509 * will check for the closing paren, we don't need to print an error
510 * here, just bail out.
512 if (TokIsSep (Tok)) {
519 /* Keep track of the nesting level */
521 case TOK_LPAREN: ++Parens; break;
522 case TOK_RPAREN: --Parens; break;
530 /* Return the number of tokens */
531 return GenLiteralExpr (Count);
536 static ExprNode* FuncXMatch (void)
537 /* Handle the .XMATCH function */
539 return DoMatch (tcIdentical);
544 static ExprNode* Function (ExprNode* (*F) (void))
545 /* Handle builtin functions */
549 /* Skip the keyword */
552 /* Expression must be enclosed in braces */
553 if (Tok != TOK_LPAREN) {
554 Error ("'(' expected");
556 return GenLiteralExpr (0);
560 /* Call the function itself */
563 /* Closing brace must follow */
566 /* Return the result of the actual function */
572 static ExprNode* Factor (void)
582 N = GenLiteralExpr (IVal);
587 N = GenLiteralExpr (TgtTranslateChar (IVal));
593 /* Search for the symbol */
594 S = ParseScopedSymName (SYM_ALLOC_NEW);
596 /* Some weird error happened before */
597 N = GenLiteralExpr (0);
599 /* Mark the symbol as referenced */
601 /* Remove the symbol if possible */
602 if (SymHasExpr (S)) {
603 N = CloneExpr (GetSymExpr (S));
605 /* Create symbol node */
619 if (IsEasyConst (L, &Val)) {
621 N = GenLiteralExpr (-Val);
623 N = NewExprNode (EXPR_UNARY_MINUS);
631 if (IsEasyConst (L, &Val)) {
633 N = GenLiteralExpr (~Val);
635 N = NewExprNode (EXPR_NOT);
649 if (IsEasyConst (L, &Val)) {
651 N = GenLiteralExpr (Val & 0xFF);
653 N = NewExprNode (EXPR_BYTE0);
661 if (IsEasyConst (L, &Val)) {
663 N = GenLiteralExpr ((Val >> 8) & 0xFF);
665 N = NewExprNode (EXPR_BYTE1);
673 if (IsEasyConst (L, &Val)) {
675 N = GenLiteralExpr ((Val >> 16) & 0xFF);
677 N = NewExprNode (EXPR_BYTE2);
689 N = Function (FuncBlank);
693 N = Function (FuncConst);
697 N = GenLiteralExpr (CPUIsets[CPU]);
702 N = Function (FuncDefined);
706 N = Function (FuncMatch);
710 N = Function (FuncReferenced);
714 N = Function (FuncSizeOf);
718 N = Function (FuncStrAt);
722 N = Function (FuncStrLen);
726 N = Function (FuncTCount);
730 N = GenLiteralExpr (time (0));
735 N = GenLiteralExpr (VERSION);
740 N = Function (FuncXMatch);
744 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
745 /* A character constant */
746 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
748 N = GenLiteralExpr (0); /* Dummy */
749 Error ("Syntax error");
759 static ExprNode* Term (void)
761 /* Read left hand side */
762 ExprNode* Root = Factor ();
764 /* Handle multiplicative operations */
765 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
766 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
769 long LVal, RVal, Val;
773 /* Remember the token and skip it */
777 /* Move root to left side and read the right side */
781 /* If both expressions are constant, we can evaluate the term */
782 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
791 Error ("Division by zero");
800 Error ("Modulo operation with zero");
816 Val = shl_l (LVal, RVal);
820 Val = shr_l (LVal, RVal);
824 Internal ("Invalid token");
827 /* Generate a literal expression and delete the old left and
832 Root = GenLiteralExpr (Val);
836 /* Generate an expression tree */
839 case TOK_MUL: Op = EXPR_MUL; break;
840 case TOK_DIV: Op = EXPR_DIV; break;
841 case TOK_MOD: Op = EXPR_MOD; break;
842 case TOK_AND: Op = EXPR_AND; break;
843 case TOK_XOR: Op = EXPR_XOR; break;
844 case TOK_SHL: Op = EXPR_SHL; break;
845 case TOK_SHR: Op = EXPR_SHR; break;
846 default: Internal ("Invalid token");
848 Root = NewExprNode (Op);
856 /* Return the expression tree we've created */
862 static ExprNode* SimpleExpr (void)
864 /* Read left hand side */
865 ExprNode* Root = Term ();
867 /* Handle additive operations */
868 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
870 long LVal, RVal, Val;
874 /* Remember the token and skip it */
878 /* Move root to left side and read the right side */
882 /* If both expressions are constant, we can evaluate the term */
883 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
886 case TOK_PLUS: Val = LVal + RVal; break;
887 case TOK_MINUS: Val = LVal - RVal; break;
888 case TOK_OR: Val = LVal | RVal; break;
889 default: Internal ("Invalid token");
892 /* Generate a literal expression and delete the old left and
897 Root = GenLiteralExpr (Val);
901 /* Generate an expression tree */
904 case TOK_PLUS: Op = EXPR_PLUS; break;
905 case TOK_MINUS: Op = EXPR_MINUS; break;
906 case TOK_OR: Op = EXPR_OR; break;
907 default: Internal ("Invalid token");
909 Root = NewExprNode (Op);
916 /* Return the expression tree we've created */
922 static ExprNode* BoolExpr (void)
923 /* Evaluate a boolean expression */
925 /* Read left hand side */
926 ExprNode* Root = SimpleExpr ();
928 /* Handle booleans */
929 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
930 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
932 long LVal, RVal, Val;
936 /* Remember the token and skip it */
940 /* Move root to left side and read the right side */
942 Right = SimpleExpr ();
944 /* If both expressions are constant, we can evaluate the term */
945 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
948 case TOK_EQ: Val = (LVal == RVal); break;
949 case TOK_NE: Val = (LVal != RVal); break;
950 case TOK_LT: Val = (LVal < RVal); break;
951 case TOK_GT: Val = (LVal > RVal); break;
952 case TOK_LE: Val = (LVal <= RVal); break;
953 case TOK_GE: Val = (LVal >= RVal); break;
954 default: Internal ("Invalid token");
957 /* Generate a literal expression and delete the old left and
962 Root = GenLiteralExpr (Val);
966 /* Generate an expression tree */
969 case TOK_EQ: Op = EXPR_EQ; break;
970 case TOK_NE: Op = EXPR_NE; break;
971 case TOK_LT: Op = EXPR_LT; break;
972 case TOK_GT: Op = EXPR_GT; break;
973 case TOK_LE: Op = EXPR_LE; break;
974 case TOK_GE: Op = EXPR_GE; break;
975 default: Internal ("Invalid token");
977 Root = NewExprNode (Op);
984 /* Return the expression tree we've created */
990 static ExprNode* Expr2 (void)
991 /* Boolean operators: AND and XOR */
993 /* Read left hand side */
994 ExprNode* Root = BoolExpr ();
996 /* Handle booleans */
997 while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
999 long LVal, RVal, Val;
1003 /* Remember the token and skip it */
1007 /* Move root to left side and read the right side */
1009 Right = BoolExpr ();
1011 /* If both expressions are constant, we can evaluate the term */
1012 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1015 case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break;
1016 case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break;
1017 default: Internal ("Invalid token");
1020 /* Generate a literal expression and delete the old left and
1025 Root = GenLiteralExpr (Val);
1029 /* Generate an expression tree */
1032 case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
1033 case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
1034 default: Internal ("Invalid token");
1036 Root = NewExprNode (Op);
1038 Root->Right = Right;
1043 /* Return the expression tree we've created */
1049 static ExprNode* Expr1 (void)
1050 /* Boolean operators: OR */
1052 /* Read left hand side */
1053 ExprNode* Root = Expr2 ();
1055 /* Handle booleans */
1056 while (Tok == TOK_BOOLOR) {
1058 long LVal, RVal, Val;
1062 /* Remember the token and skip it */
1066 /* Move root to left side and read the right side */
1070 /* If both expressions are constant, we can evaluate the term */
1071 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1074 case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break;
1075 default: Internal ("Invalid token");
1078 /* Generate a literal expression and delete the old left and
1083 Root = GenLiteralExpr (Val);
1087 /* Generate an expression tree */
1090 case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
1091 default: Internal ("Invalid token");
1093 Root = NewExprNode (Op);
1095 Root->Right = Right;
1100 /* Return the expression tree we've created */
1106 static ExprNode* Expr0 (void)
1107 /* Boolean operators: NOT */
1111 /* Handle booleans */
1112 if (Tok == TOK_BOOLNOT) {
1117 /* Skip the operator token */
1120 /* Read the argument */
1123 /* If the argument is const, evaluate it directly */
1124 if (IsEasyConst (Left, &Val)) {
1126 Root = GenLiteralExpr (!Val);
1128 Root = NewExprNode (EXPR_BOOLNOT);
1134 /* Read left hand side */
1139 /* Return the expression tree we've created */
1145 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
1146 /* Study a binary expression subtree. Helper function for StudyExpr. */
1148 StudyExpr (Expr->Left, D, 1);
1149 if (ExprDescIsConst (D)) {
1152 StudyExpr (Expr->Right, D, 1);
1153 if (!ExprDescIsConst (D)) {
1163 static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign)
1164 /* Study an expression tree and place the contents into D */
1171 /* Initialize SD. This is not needed in all cases, but it's rather cheap
1172 * and simplifies the code below.
1176 /* Study this expression node */
1180 D->Val += (Sign * Expr->V.Val);
1185 if (SymIsImport (Sym)) {
1186 if (D->SymCount == 0) {
1187 D->SymCount += Sign;
1189 } else if (D->SymRef == Sym) {
1191 D->SymCount += Sign;
1193 /* More than one import */
1196 } else if (SymHasExpr (Sym)) {
1197 if (SymHasUserMark (Sym)) {
1198 if (Verbosity > 0) {
1199 DumpExpr (Expr, SymResolve);
1201 PError (GetSymPos (Sym),
1202 "Circular reference in definition of symbol `%s'",
1207 StudyExpr (GetSymExpr (Sym), D, Sign);
1208 SymUnmarkUser (Sym);
1216 Sec = Expr->V.SegNum;
1217 if (D->SecCount == 0) {
1218 D->SecCount += Sign;
1220 } else if (D->SecRef == Sec) {
1222 D->SecCount += Sign;
1224 /* More than one section */
1230 if (ULabCanResolve ()) {
1231 /* We can resolve the label */
1232 StudyExpr (ULabResolve (Expr->V.Val), D, Sign);
1239 StudyExpr (Expr->Left, D, Sign);
1240 StudyExpr (Expr->Right, D, Sign);
1244 StudyExpr (Expr->Left, D, Sign);
1245 StudyExpr (Expr->Right, D, -Sign);
1249 InitExprDesc (&SD1);
1250 StudyExpr (Expr->Left, &SD, 1);
1251 StudyExpr (Expr->Right, &SD1, 1);
1252 if (SD.TooComplex == 0 && SD1.TooComplex == 0) {
1253 /* First calculate SD = SD*SD1 if possible */
1254 if (ExprDescIsConst (&SD)) {
1255 /* Left is a constant */
1257 SD1.SymCount *= SD.Val;
1258 SD1.SecCount *= SD.Val;
1260 } else if (ExprDescIsConst (&SD1)) {
1261 /* Right is constant */
1263 SD.SymCount *= SD1.Val;
1264 SD.SecCount *= SD1.Val;
1268 /* Now calculate D * Sign * SD */
1269 if (!D->TooComplex) {
1270 if ((D->SymCount == 0 || SD.SymCount == 0 || D->SymRef == SD.SymRef) &&
1271 (D->SecCount == 0 || SD.SecCount == 0 || D->SecRef == SD.SecRef)) {
1272 D->Val += (Sign * SD.Val);
1273 if (D->SymCount == 0) {
1274 D->SymRef = SD.SymRef;
1276 D->SymCount += (Sign * SD.SymCount);
1277 if (D->SecCount == 0) {
1278 D->SecRef = SD.SecRef;
1280 D->SecCount += (Sign * SD.SecCount);
1291 StudyBinaryExpr (Expr, &SD);
1292 if (!SD.TooComplex) {
1294 Error ("Division by zero");
1297 D->Val += Sign * (SD.Left / SD.Val);
1305 StudyBinaryExpr (Expr, &SD);
1306 if (!SD.TooComplex) {
1308 Error ("Modulo operation with zero");
1311 D->Val += Sign * (SD.Left % SD.Val);
1319 StudyBinaryExpr (Expr, &SD);
1320 if (!SD.TooComplex) {
1321 D->Val += Sign * (SD.Left | SD.Val);
1328 StudyBinaryExpr (Expr, &SD);
1329 if (!SD.TooComplex) {
1330 D->Val += Sign * (SD.Left ^ SD.Val);
1337 StudyBinaryExpr (Expr, &SD);
1338 if (!SD.TooComplex) {
1339 D->Val += Sign * (SD.Left & SD.Val);
1346 StudyBinaryExpr (Expr, &SD);
1347 if (!SD.TooComplex) {
1348 D->Val += (Sign * shl_l (SD.Left, (unsigned) SD.Val));
1355 StudyBinaryExpr (Expr, &SD);
1356 if (!SD.TooComplex) {
1357 D->Val += (Sign * shr_l (SD.Left, (unsigned) SD.Val));
1364 StudyBinaryExpr (Expr, &SD);
1365 if (!SD.TooComplex) {
1366 D->Val += Sign * (SD.Left == SD.Val);
1373 StudyBinaryExpr (Expr, &SD);
1374 if (!SD.TooComplex) {
1375 D->Val += Sign * (SD.Left != SD.Val);
1382 StudyBinaryExpr (Expr, &SD);
1383 if (!SD.TooComplex) {
1384 D->Val += Sign * (SD.Left < SD.Val);
1391 StudyBinaryExpr (Expr, &SD);
1392 if (!SD.TooComplex) {
1393 D->Val += Sign * (SD.Left > SD.Val);
1400 StudyBinaryExpr (Expr, &SD);
1401 if (!SD.TooComplex) {
1402 D->Val += Sign * (SD.Left <= SD.Val);
1409 StudyBinaryExpr (Expr, &SD);
1410 if (!SD.TooComplex) {
1411 D->Val += Sign * (SD.Left >= SD.Val);
1418 StudyExpr (Expr->Left, &SD, 1);
1419 if (ExprDescIsConst (&SD)) {
1420 if (SD.Val != 0) { /* Shortcut op */
1422 StudyExpr (Expr->Right, &SD, 1);
1423 if (ExprDescIsConst (&SD)) {
1424 D->Val += Sign * (SD.Val != 0);
1435 StudyExpr (Expr->Left, &SD, 1);
1436 if (ExprDescIsConst (&SD)) {
1437 if (SD.Val == 0) { /* Shortcut op */
1438 StudyExpr (Expr->Right, &SD, 1);
1439 if (ExprDescIsConst (&SD)) {
1440 D->Val += Sign * (SD.Val != 0);
1453 StudyBinaryExpr (Expr, &SD);
1454 if (!SD.TooComplex) {
1455 D->Val += Sign * ((SD.Left != 0) ^ (SD.Val != 0));
1459 case EXPR_UNARY_MINUS:
1460 StudyExpr (Expr->Left, D, -Sign);
1464 StudyExpr (Expr->Left, &SD, 1);
1465 if (ExprDescIsConst (&SD)) {
1466 D->Val += (Sign * ~SD.Val);
1473 StudyExpr (Expr->Left, &SD, 1);
1474 if (ExprDescIsConst (&SD)) {
1475 D->Val += Sign * (((SD.Val >> 8) & 0x00FF) | ((SD.Val << 8) & 0xFF00));
1482 StudyExpr (Expr->Left, &SD, 1);
1483 if (ExprDescIsConst (&SD)) {
1484 D->Val += Sign * (SD.Val != 0);
1490 case EXPR_FORCEWORD:
1493 StudyExpr (Expr->Left, D, Sign);
1497 StudyExpr (Expr->Left, &SD, 1);
1498 if (ExprDescIsConst (&SD)) {
1499 D->Val += Sign * (SD.Val & 0xFF);
1506 StudyExpr (Expr->Left, &SD, 1);
1507 if (ExprDescIsConst (&SD)) {
1508 D->Val += Sign * ((SD.Val >> 8) & 0xFF);
1515 StudyExpr (Expr->Left, &SD, 1);
1516 if (ExprDescIsConst (&SD)) {
1517 D->Val += Sign * ((SD.Val >> 16) & 0xFF);
1524 StudyExpr (Expr->Left, &SD, 1);
1525 if (ExprDescIsConst (&SD)) {
1526 D->Val += Sign * ((SD.Val >> 24) & 0xFF);
1533 StudyExpr (Expr->Left, &SD, 1);
1534 if (ExprDescIsConst (&SD)) {
1535 D->Val += Sign * (SD.Val & 0xFFFF);
1542 StudyExpr (Expr->Left, &SD, 1);
1543 if (ExprDescIsConst (&SD)) {
1544 D->Val += Sign * ((SD.Val >> 16) & 0xFFFF);
1551 Internal ("Unknown Op type: %u", Expr->Op);
1558 ExprNode* Expression (void)
1559 /* Evaluate an expression, build the expression tree on the heap and return
1560 * a pointer to the root of the tree.
1564 return SimplifyExpr (Expr0 ());
1567 ExprNode* Expr = Expr0 ();
1568 printf ("Before: "); DumpExpr (Expr, SymResolve);
1569 Expr = SimplifyExpr (Expr);
1570 printf ("After: "); DumpExpr (Expr, SymResolve);
1577 long ConstExpression (void)
1578 /* Parse an expression. Check if the expression is const, and print an error
1579 * message if not. Return the value of the expression, or a dummy, if it is
1584 /* Read the expression */
1585 ExprNode* Expr = Expr0 ();
1588 ExprNode* Expr = Expression ();
1591 /* Study the expression */
1594 StudyExpr (Expr, &D, 1);
1596 /* Check if the expression is constant */
1597 if (!ExprDescIsConst (&D)) {
1598 Error ("Constant expression expected");
1602 /* Free the expression tree and return the value */
1609 void FreeExpr (ExprNode* Root)
1610 /* Free the expression, Root is pointing to. */
1613 FreeExpr (Root->Left);
1614 FreeExpr (Root->Right);
1615 FreeExprNode (Root);
1621 ExprNode* SimplifyExpr (ExprNode* Expr)
1622 /* Try to simplify the given expression tree */
1624 if (Expr && Expr->Op != EXPR_LITERAL) {
1626 /* Create an expression description and initialize it */
1630 /* Study the expression */
1631 StudyExpr (Expr, &D, 1);
1633 /* Now check if we can generate a literal value */
1634 if (ExprDescIsConst (&D)) {
1635 /* No external references */
1637 Expr = GenLiteralExpr (D.Val);
1645 ExprNode* GenLiteralExpr (long Val)
1646 /* Return an expression tree that encodes the given literal value */
1648 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1655 ExprNode* GenSymExpr (SymEntry* Sym)
1656 /* Return an expression node that encodes the given symbol */
1658 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1660 SymAddExprRef (Sym, Expr);
1666 static ExprNode* GenSectionExpr (unsigned SegNum)
1667 /* Return an expression node for the given section */
1669 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1670 Expr->V.SegNum = SegNum;
1676 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
1677 /* Generate an addition from the two operands */
1679 ExprNode* Root = NewExprNode (EXPR_PLUS);
1681 Root->Right = Right;
1687 ExprNode* GenCurrentPC (void)
1688 /* Return the current program counter as expression */
1693 /* Create SegmentBase + Offset */
1694 Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
1695 GenLiteralExpr (GetPC ()));
1697 /* Absolute mode, just return PC value */
1698 Root = GenLiteralExpr (GetPC ());
1706 ExprNode* GenSwapExpr (ExprNode* Expr)
1707 /* Return an extended expression with lo and hi bytes swapped */
1709 ExprNode* N = NewExprNode (EXPR_SWAP);
1716 ExprNode* GenBranchExpr (unsigned Offs)
1717 /* Return an expression that encodes the difference between current PC plus
1718 * offset and the target expression (that is, Expression() - (*+Offs) ).
1725 /* Read Expression() */
1728 /* If the expression is a cheap constant, generate a simpler tree */
1729 if (IsEasyConst (N, &Val)) {
1731 /* Free the constant expression tree */
1734 /* Generate the final expression:
1736 * Val - ((Seg + PC) + Offs)
1737 * Val - Seg - PC - Offs
1738 * (Val - PC - Offs) - Seg
1740 Root = GenLiteralExpr (Val - GetPC () - Offs);
1743 Root = NewExprNode (EXPR_MINUS);
1745 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1750 /* Generate the expression:
1752 * N - ((Seg + PC) + Offs)
1753 * N - Seg - PC - Offs
1754 * N - (PC + Offs) - Seg
1756 Root = NewExprNode (EXPR_MINUS);
1758 Root->Right = GenLiteralExpr (GetPC () + Offs);
1761 Root = NewExprNode (EXPR_MINUS);
1763 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1767 /* Return the result */
1773 ExprNode* GenULabelExpr (unsigned Num)
1774 /* Return an expression for an unnamed label with the given index */
1776 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1779 /* Return the new node */
1785 ExprNode* GenByteExpr (ExprNode* Expr)
1786 /* Force the given expression into a byte and return the result */
1788 /* Use the low byte operator to force the expression into byte size */
1789 ExprNode* Root = NewExprNode (EXPR_BYTE0);
1792 /* Return the result */
1798 ExprNode* GenWordExpr (ExprNode* Expr)
1799 /* Force the given expression into a word and return the result. */
1801 /* AND the expression by $FFFF to force it into word size */
1802 ExprNode* Root = NewExprNode (EXPR_AND);
1804 Root->Right = GenLiteralExpr (0xFFFF);
1806 /* Return the result */
1812 ExprNode* GenNE (ExprNode* Expr, long Val)
1813 /* Generate an expression that compares Expr and Val for inequality */
1815 /* Generate a compare node */
1816 ExprNode* Root = NewExprNode (EXPR_NE);
1818 Root->Right = GenLiteralExpr (Val);
1820 /* Return the result */
1826 int IsConstExpr (ExprNode* Expr, long* Val)
1827 /* Return true if the given expression is a constant expression, that is, one
1828 * with no references to external symbols. If Val is not NULL and the
1829 * expression is constant, the constant value is stored here.
1832 /* Study the expression */
1835 StudyExpr (Expr, &D, 1);
1837 /* Check if the expression is constant */
1838 if (ExprDescIsConst (&D)) {
1850 static void CheckAddrSize (const ExprNode* N, unsigned char* AddrSize)
1851 /* Internal routine that is recursively called to check for the address size
1852 * of the expression tree.
1856 unsigned char Left, Right;
1859 switch (N->Op & EXPR_TYPEMASK) {
1865 if (SymIsZP (N->V.Sym)) {
1866 if (*AddrSize < ADDR_SIZE_ZP) {
1867 *AddrSize = ADDR_SIZE_ZP;
1869 } else if (SymHasExpr (N->V.Sym)) {
1870 /* Check if this expression is a byte expression */
1871 CheckAddrSize (GetSymExpr (N->V.Sym), AddrSize);
1873 /* Undefined symbol, use absolute */
1874 if (*AddrSize < ADDR_SIZE_ABS) {
1875 *AddrSize = ADDR_SIZE_ABS;
1881 A = GetSegAddrSize (N->V.SegNum);
1882 if (A > *AddrSize) {
1890 case EXPR_UNARYNODE:
1897 /* No need to look at the expression */
1898 *AddrSize = ADDR_SIZE_ZP;
1903 case EXPR_FORCEWORD:
1904 /* No need to look at the expression */
1905 *AddrSize = ADDR_SIZE_ABS;
1909 /* No need to look at the expression */
1910 *AddrSize = ADDR_SIZE_FAR;
1914 CheckAddrSize (N->Left, AddrSize);
1919 case EXPR_BINARYNODE:
1920 Left = Right = ADDR_SIZE_DEFAULT;
1921 CheckAddrSize (N->Left, &Left);
1922 CheckAddrSize (N->Right, &Right);
1923 A = (Left > Right)? Left : Right;
1924 if (A > *AddrSize) {
1930 Internal ("Unknown expression op: %02X", N->Op);
1937 int IsByteExpr (ExprNode* Root)
1938 /* Return true if this is a byte expression */
1942 if (IsConstExpr (Root, &Val)) {
1943 return IsByteRange (Val);
1945 unsigned char AddrSize = ADDR_SIZE_DEFAULT;
1946 CheckAddrSize (Root, &AddrSize);
1947 return (AddrSize == ADDR_SIZE_ZP);
1953 ExprNode* CloneExpr (ExprNode* Expr)
1954 /* Clone the given expression tree. The function will simply clone symbol
1955 * nodes, it will not resolve them.
1960 /* Accept NULL pointers */
1965 /* Clone the node */
1969 Clone = GenLiteralExpr (Expr->V.Val);
1973 Clone = GenULabelExpr (Expr->V.Val);
1977 Clone = GenSymExpr (Expr->V.Sym);
1981 Clone = GenSectionExpr (Expr->V.SegNum);
1985 /* Generate a new node */
1986 Clone = NewExprNode (Expr->Op);
1987 /* Clone the tree nodes */
1988 Clone->Left = CloneExpr (Expr->Left);
1989 Clone->Right = CloneExpr (Expr->Right);
1999 void WriteExpr (ExprNode* Expr)
2000 /* Write the given expression to the object file */
2002 /* Null expressions are encoded by a type byte of zero */
2004 ObjWrite8 (EXPR_NULL);
2008 /* If the is a leafnode, write the expression attribute, otherwise
2009 * write the expression operands.
2014 ObjWrite8 (EXPR_LITERAL);
2015 ObjWrite32 (Expr->V.Val);
2019 if (SymIsImport (Expr->V.Sym)) {
2020 ObjWrite8 (EXPR_SYMBOL);
2021 ObjWriteVar (GetSymIndex (Expr->V.Sym));
2023 WriteExpr (GetSymExpr (Expr->V.Sym));
2028 ObjWrite8 (EXPR_SECTION);
2029 ObjWrite8 (Expr->V.SegNum);
2033 WriteExpr (ULabResolve (Expr->V.Val));
2037 /* Not a leaf node */
2038 ObjWrite8 (Expr->Op);
2039 WriteExpr (Expr->Left);
2040 WriteExpr (Expr->Right);