1 /*****************************************************************************/
5 /* Study an expression tree */
9 /* (C) 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 /*****************************************************************************/
47 #include "studyexpr.h"
53 /*****************************************************************************/
55 /*****************************************************************************/
59 ExprDesc* ED_Init (ExprDesc* ED)
60 /* Initialize an ExprDesc structure for use with StudyExpr */
63 ED->AddrSize = ADDR_SIZE_DEFAULT;
76 void ED_Done (ExprDesc* ED)
77 /* Delete allocated memory for an ExprDesc. */
85 int ED_IsConst (const ExprDesc* D)
86 /* Return true if the expression is constant */
90 if (D->Flags & ED_TOO_COMPLEX) {
93 for (I = 0; I < D->SymCount; ++I) {
94 if (D->SymRef[I].Count != 0) {
98 for (I = 0; I < D->SecCount; ++I) {
99 if (D->SecRef[I].Count != 0) {
108 static int ED_IsValid (const ExprDesc* D)
109 /* Return true if the expression is valid, that is, the TOO_COMPLEX flag is
113 return ((D->Flags & ED_TOO_COMPLEX) == 0);
118 static void ED_Invalidate (ExprDesc* D)
119 /* Set the TOO_COMPLEX flag for D */
121 D->Flags |= ED_TOO_COMPLEX;
126 static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
127 /* Update the address size of the expression */
129 if (ED_IsValid (ED)) {
130 /* ADDR_SIZE_DEFAULT may get overridden */
131 if (ED->AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) {
132 ED->AddrSize = AddrSize;
135 /* ADDR_SIZE_DEFAULT takes precedence */
136 if (ED->AddrSize != ADDR_SIZE_DEFAULT) {
137 if (AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) {
138 ED->AddrSize = AddrSize;
146 static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
147 /* Merge the address sizes of two expressions into ED */
149 if (ED->AddrSize == ADDR_SIZE_DEFAULT) {
150 /* If ED is valid, ADDR_SIZE_DEFAULT gets always overridden, otherwise
151 * it takes precedence over anything else.
153 if (ED_IsValid (ED)) {
154 ED->AddrSize = Right->AddrSize;
156 } else if (Right->AddrSize == ADDR_SIZE_DEFAULT) {
157 /* If Right is valid, ADDR_SIZE_DEFAULT gets always overridden,
158 * otherwise it takes precedence over anything else.
160 if (!ED_IsValid (Right)) {
161 ED->AddrSize = Right->AddrSize;
164 /* Neither ED nor Right has a default address size, use the larger of
167 if (Right->AddrSize > ED->AddrSize) {
168 ED->AddrSize = Right->AddrSize;
175 static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
176 /* Find a symbol reference and return it. Return NULL if the reference does
182 for (I = 0, SymRef = ED->SymRef; I < ED->SymCount; ++I, ++SymRef) {
183 if (SymRef->Ref == Sym) {
192 static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
193 /* Find a section reference and return it. Return NULL if the reference does
199 for (I = 0, SecRef = ED->SecRef; I < ED->SecCount; ++I, ++SecRef) {
200 if (SecRef->Ref == Sec) {
209 static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
210 /* Allocate a new symbol reference and return it. The count of the new
211 * reference will be set to zero, and the reference itself to Sym.
216 /* Make sure we have enough SymRef slots */
217 if (ED->SymCount >= ED->SymLimit) {
219 if (ED->SymLimit == 0) {
222 ED->SymRef = xrealloc (ED->SymRef, ED->SymLimit * sizeof (ED->SymRef[0]));
225 /* Allocate a new slot */
226 SymRef = ED->SymRef + ED->SymCount++;
228 /* Initialize the new struct and return it */
236 static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
237 /* Allocate a new section reference and return it. The count of the new
238 * reference will be set to zero, and the reference itself to Sec.
243 /* Make sure we have enough SecRef slots */
244 if (ED->SecCount >= ED->SecLimit) {
246 if (ED->SecLimit == 0) {
249 ED->SecRef = xrealloc (ED->SecRef, ED->SecLimit * sizeof (ED->SecRef[0]));
252 /* Allocate a new slot */
253 SecRef = ED->SecRef + ED->SecCount++;
255 /* Initialize the new struct and return it */
263 static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
264 /* Get a symbol reference and return it. If the symbol reference does not
265 * exist, a new one is created and returned.
268 ED_SymRef* SymRef = ED_FindSymRef (ED, Sym);
270 SymRef = ED_AllocSymRef (ED, Sym);
277 static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec)
278 /* Get a section reference and return it. If the section reference does not
279 * exist, a new one is created and returned.
282 ED_SecRef* SecRef = ED_FindSecRef (ED, Sec);
284 SecRef = ED_AllocSecRef (ED, Sec);
291 static void ED_MergeSymRefs (ExprDesc* ED, const ExprDesc* New)
292 /* Merge the symbol references from New into ED */
295 for (I = 0; I < New->SymCount; ++I) {
297 /* Get a pointer to the SymRef entry */
298 const ED_SymRef* NewRef = New->SymRef + I;
300 /* Get the corresponding entry in ED */
301 ED_SymRef* SymRef = ED_GetSymRef (ED, NewRef->Ref);
303 /* Sum up the references */
304 SymRef->Count += NewRef->Count;
310 static void ED_MergeSecRefs (ExprDesc* ED, const ExprDesc* New)
311 /* Merge the section references from New into ED */
314 for (I = 0; I < New->SecCount; ++I) {
316 /* Get a pointer to the SymRef entry */
317 const ED_SecRef* NewRef = New->SecRef + I;
319 /* Get the corresponding entry in ED */
320 ED_SecRef* SecRef = ED_GetSecRef (ED, NewRef->Ref);
322 /* Sum up the references */
323 SecRef->Count += NewRef->Count;
329 static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New)
330 /* Merge all references from New into ED */
332 ED_MergeSymRefs (ED, New);
333 ED_MergeSecRefs (ED, New);
338 static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
339 /* Calculate ED = ED + Right, update address size in ED */
341 ED->Val += Right->Val;
342 ED_MergeRefs (ED, Right);
343 ED_MergeAddrSize (ED, Right);
348 static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
349 /* Calculate ED = ED * Right, update address size in ED */
353 ED->Val *= Right->Val;
354 for (I = 0; I < ED->SymCount; ++I) {
355 ED->SymRef[I].Count *= Right->Val;
357 for (I = 0; I < ED->SecCount; ++I) {
358 ED->SecRef[I].Count *= Right->Val;
360 ED_MergeAddrSize (ED, Right);
365 static void ED_Neg (ExprDesc* D)
366 /* Negate an expression */
371 for (I = 0; I < D->SymCount; ++I) {
372 D->SymRef[I].Count = -D->SymRef[I].Count;
374 for (I = 0; I < D->SecCount; ++I) {
375 D->SecRef[I].Count = -D->SecRef[I].Count;
381 static void ED_Move (ExprDesc* From, ExprDesc* To)
382 /* Move the data from one ExprDesc to another. Old data is freed, and From
383 * is prepared to that ED_Done may be called safely.
386 /* Delete old data */
398 /*****************************************************************************/
400 /*****************************************************************************/
404 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
405 /* Study an expression tree and place the contents into D */
409 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
410 /* Study a binary expression subtree. This is a helper function for StudyExpr
411 * used for operations that succeed when both operands are known and constant.
412 * It evaluates the two subtrees and checks if they are constant. If they
413 * aren't constant, it will set the TOO_COMPLEX flag, and merge references.
414 * Otherwise the first value is returned in D->Val, the second one in D->Right,
415 * so the actual operation can be done by the caller.
420 /* Study the left side of the expression */
421 StudyExprInternal (Expr->Left, D);
423 /* Study the right side of the expression */
425 StudyExprInternal (Expr->Right, &Right);
427 /* Check if we can handle the operation */
428 if (ED_IsConst (D) && ED_IsConst (&Right)) {
430 /* Remember the constant value from Right */
431 D->Right = Right.Val;
435 /* Cannot evaluate */
438 /* Merge references and update address size */
439 ED_MergeRefs (D, &Right);
440 ED_MergeAddrSize (D, &Right);
450 static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
451 /* Study a literal expression node */
454 /* This one is easy */
455 D->Val = Expr->V.Val;
460 static void StudySymbol (ExprNode* Expr, ExprDesc* D)
461 /* Study a symbol expression node */
463 /* Get the symbol from the expression */
464 SymEntry* Sym = Expr->V.Sym;
466 /* If the symbol is defined somewhere, it has an expression associated.
467 * In this case, just study the expression associated with the symbol,
468 * but mark the symbol so if we encounter it twice, we know that we have
469 * a circular reference.
471 if (SymHasExpr (Sym)) {
473 if (SymHasUserMark (Sym)) {
475 DumpExpr (Expr, SymResolve);
477 PError (GetSymPos (Sym),
478 "Circular reference in definition of symbol `%s'",
483 unsigned char AddrSize;
485 /* Mark the symbol and study its associated expression */
487 StudyExprInternal (GetSymExpr (Sym), D);
490 /* If the symbol has an explicit address size, use it. This may
491 * lead to range errors later (maybe even in the linker stage), if
492 * the user lied about the address size, but for now we trust him.
494 AddrSize = GetSymAddrSize (Sym);
495 if (AddrSize != ADDR_SIZE_DEFAULT) {
496 D->AddrSize = AddrSize;
500 } else if (SymIsImport (Sym)) {
502 /* The symbol is an import. Track the symbols used and update the
505 ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
507 ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
511 unsigned char AddrSize;
514 /* The symbol is undefined. Track symbol usage but set the "too
515 * complex" flag, since we cannot evaluate the final result.
517 ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
521 /* Since the symbol may be a forward, and we may need a statement
522 * about the address size, check higher lexical levels for a symbol
523 * with the same name and use its address size if we find such a
524 * symbol which is defined.
526 AddrSize = GetSymAddrSize (Sym);
527 Parent = GetSymParentScope (Sym);
528 if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
529 SymEntry* H = SymFindAny (Parent, GetSymName (Sym));
531 AddrSize = GetSymAddrSize (H);
532 if (AddrSize != ADDR_SIZE_DEFAULT) {
533 D->AddrSize = AddrSize;
537 D->AddrSize = AddrSize;
544 static void StudySection (ExprNode* Expr, ExprDesc* D)
545 /* Study a section expression node */
547 /* Get the section reference */
548 ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SegNum);
550 /* Update the data and the address size */
552 ED_UpdateAddrSize (D, GetSegAddrSize (SecRef->Ref));
557 static void StudyULabel (ExprNode* Expr, ExprDesc* D)
558 /* Study an unnamed label expression node */
560 /* If we can resolve the label, study the expression associated with it,
561 * otherwise mark the expression as too complex to evaluate.
563 if (ULabCanResolve ()) {
564 /* We can resolve the label */
565 StudyExprInternal (ULabResolve (Expr->V.Val), D);
573 static void StudyPlus (ExprNode* Expr, ExprDesc* D)
574 /* Study an EXPR_PLUS binary expression node */
578 /* Study the left side of the expression */
579 StudyExprInternal (Expr->Left, D);
581 /* Study the right side of the expression */
583 StudyExprInternal (Expr->Right, &Right);
585 /* Check if we can handle the operation */
586 if (ED_IsValid (D) || ED_IsValid (&Right)) {
593 /* Cannot evaluate */
596 /* Merge references and update address size */
597 ED_MergeRefs (D, &Right);
598 ED_MergeAddrSize (D, &Right);
608 static void StudyMinus (ExprNode* Expr, ExprDesc* D)
609 /* Study an EXPR_MINUS binary expression node */
613 /* Study the left side of the expression */
614 StudyExprInternal (Expr->Left, D);
616 /* Study the right side of the expression */
618 StudyExprInternal (Expr->Right, &Right);
620 /* Check if we can handle the operation */
621 if (ED_IsValid (D) || ED_IsValid (&Right)) {
629 /* Cannot evaluate */
632 /* Merge references and update address size */
633 ED_MergeRefs (D, &Right);
634 ED_MergeAddrSize (D, &Right);
644 static void StudyMul (ExprNode* Expr, ExprDesc* D)
645 /* Study an EXPR_MUL binary expression node */
649 /* Study the left side of the expression */
650 StudyExprInternal (Expr->Left, D);
652 /* Study the right side of the expression */
654 StudyExprInternal (Expr->Right, &Right);
656 /* We can handle the operation if at least one of both operands is const
657 * and the other one is valid.
659 if (ED_IsConst (D) && ED_IsValid (&Right)) {
661 /* Multiplicate both, result goes into Right */
664 /* Move result into D */
667 } else if (ED_IsConst (&Right) && ED_IsValid (D)) {
669 /* Multiplicate both */
674 /* Cannot handle this operation */
679 /* If we could not handle the op, merge references and update address size */
680 if (!ED_IsValid (D)) {
681 ED_MergeRefs (D, &Right);
682 ED_MergeAddrSize (D, &Right);
691 static void StudyDiv (ExprNode* Expr, ExprDesc* D)
692 /* Study an EXPR_DIV binary expression node */
694 /* Use helper function */
695 StudyBinaryExpr (Expr, D);
697 /* If the result is valid, apply the operation */
698 if (ED_IsValid (D)) {
700 Error ("Division by zero");
710 static void StudyMod (ExprNode* Expr, ExprDesc* D)
711 /* Study an EXPR_MOD binary expression node */
713 /* Use helper function */
714 StudyBinaryExpr (Expr, D);
716 /* If the result is valid, apply the operation */
717 if (ED_IsValid (D)) {
719 Error ("Modulo operation with zero");
729 static void StudyOr (ExprNode* Expr, ExprDesc* D)
730 /* Study an EXPR_OR binary expression node */
732 /* Use helper function */
733 StudyBinaryExpr (Expr, D);
735 /* If the result is valid, apply the operation */
736 if (ED_IsValid (D)) {
743 static void StudyXor (ExprNode* Expr, ExprDesc* D)
744 /* Study an EXPR_XOR binary expression node */
746 /* Use helper function */
747 StudyBinaryExpr (Expr, D);
749 /* If the result is valid, apply the operation */
750 if (ED_IsValid (D)) {
757 static void StudyAnd (ExprNode* Expr, ExprDesc* D)
758 /* Study an EXPR_AND binary expression node */
760 /* Use helper function */
761 StudyBinaryExpr (Expr, D);
763 /* If the result is valid, apply the operation */
764 if (ED_IsValid (D)) {
771 static void StudyShl (ExprNode* Expr, ExprDesc* D)
772 /* Study an EXPR_SHL binary expression node */
774 /* Use helper function */
775 StudyBinaryExpr (Expr, D);
777 /* If the result is valid, apply the operation */
778 if (ED_IsValid (D)) {
779 D->Val = shl_l (D->Val, D->Right);
785 static void StudyShr (ExprNode* Expr, ExprDesc* D)
786 /* Study an EXPR_SHR binary expression node */
788 /* Use helper function */
789 StudyBinaryExpr (Expr, D);
791 /* If the result is valid, apply the operation */
792 if (ED_IsValid (D)) {
793 D->Val = shr_l (D->Val, D->Right);
799 static void StudyEQ (ExprNode* Expr, ExprDesc* D)
800 /* Study an EXPR_EQ binary expression node */
802 /* Use helper function */
803 StudyBinaryExpr (Expr, D);
805 /* If the result is valid, apply the operation */
806 if (ED_IsValid (D)) {
807 D->Val = (D->Val == D->Right);
810 /* In any case, the result is 0 or 1 */
811 D->AddrSize = ADDR_SIZE_ZP;
816 static void StudyNE (ExprNode* Expr, ExprDesc* D)
817 /* Study an EXPR_NE binary expression node */
819 /* Use helper function */
820 StudyBinaryExpr (Expr, D);
822 /* If the result is valid, apply the operation */
823 if (ED_IsValid (D)) {
824 D->Val = (D->Val != D->Right);
827 /* In any case, the result is 0 or 1 */
828 D->AddrSize = ADDR_SIZE_ZP;
833 static void StudyLT (ExprNode* Expr, ExprDesc* D)
834 /* Study an EXPR_LT binary expression node */
836 /* Use helper function */
837 StudyBinaryExpr (Expr, D);
839 /* If the result is valid, apply the operation */
840 if (ED_IsValid (D)) {
841 D->Val = (D->Val < D->Right);
844 /* In any case, the result is 0 or 1 */
845 D->AddrSize = ADDR_SIZE_ZP;
850 static void StudyGT (ExprNode* Expr, ExprDesc* D)
851 /* Study an EXPR_GT binary expression node */
853 /* Use helper function */
854 StudyBinaryExpr (Expr, D);
856 /* If the result is valid, apply the operation */
857 if (ED_IsValid (D)) {
858 D->Val = (D->Val > D->Right);
861 /* In any case, the result is 0 or 1 */
862 D->AddrSize = ADDR_SIZE_ZP;
867 static void StudyLE (ExprNode* Expr, ExprDesc* D)
868 /* Study an EXPR_LE binary expression node */
870 /* Use helper function */
871 StudyBinaryExpr (Expr, D);
873 /* If the result is valid, apply the operation */
874 if (ED_IsValid (D)) {
875 D->Val = (D->Val <= D->Right);
878 /* In any case, the result is 0 or 1 */
879 D->AddrSize = ADDR_SIZE_ZP;
884 static void StudyGE (ExprNode* Expr, ExprDesc* D)
885 /* Study an EXPR_GE binary expression node */
887 /* Use helper function */
888 StudyBinaryExpr (Expr, D);
890 /* If the result is valid, apply the operation */
891 if (ED_IsValid (D)) {
892 D->Val = (D->Val >= D->Right);
895 /* In any case, the result is 0 or 1 */
896 D->AddrSize = ADDR_SIZE_ZP;
901 static void StudyBoolAnd (ExprNode* Expr, ExprDesc* D)
902 /* Study an EXPR_BOOLAND binary expression node */
904 StudyExprInternal (Expr->Left, D);
905 if (ED_IsConst (D)) {
906 if (D->Val != 0) { /* Shortcut op */
909 StudyExprInternal (Expr->Right, D);
910 if (ED_IsConst (D)) {
911 D->Val = (D->Val != 0);
920 /* In any case, the result is 0 or 1 */
921 D->AddrSize = ADDR_SIZE_ZP;
926 static void StudyBoolOr (ExprNode* Expr, ExprDesc* D)
927 /* Study an EXPR_BOOLOR binary expression node */
929 StudyExprInternal (Expr->Left, D);
930 if (ED_IsConst (D)) {
931 if (D->Val == 0) { /* Shortcut op */
934 StudyExprInternal (Expr->Right, D);
935 if (ED_IsConst (D)) {
936 D->Val = (D->Val != 0);
947 /* In any case, the result is 0 or 1 */
948 D->AddrSize = ADDR_SIZE_ZP;
953 static void StudyBoolXor (ExprNode* Expr, ExprDesc* D)
954 /* Study an EXPR_BOOLXOR binary expression node */
956 /* Use helper function */
957 StudyBinaryExpr (Expr, D);
959 /* If the result is valid, apply the operation */
960 if (ED_IsValid (D)) {
961 D->Val = (D->Val != 0) ^ (D->Right != 0);
964 /* In any case, the result is 0 or 1 */
965 D->AddrSize = ADDR_SIZE_ZP;
970 static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
971 /* Study an EXPR_UNARY_MINUS expression node */
973 /* Study the expression */
974 StudyExprInternal (Expr->Left, D);
976 /* If it is valid, negate it */
977 if (ED_IsValid (D)) {
984 static void StudyNot (ExprNode* Expr, ExprDesc* D)
985 /* Study an EXPR_NOT expression node */
987 /* Study the expression */
988 StudyExprInternal (Expr->Left, D);
990 /* We can handle only const expressions */
991 if (ED_IsConst (D)) {
1000 static void StudySwap (ExprNode* Expr, ExprDesc* D)
1001 /* Study an EXPR_SWAP expression node */
1003 /* Study the expression */
1004 StudyExprInternal (Expr->Left, D);
1006 /* We can handle only const expressions */
1007 if (ED_IsConst (D)) {
1008 D->Val = (D->Val & ~0xFFFFUL) | ((D->Val >> 8) & 0xFF) | ((D->Val << 8) & 0xFF00);
1016 static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
1017 /* Study an EXPR_BOOLNOT expression node */
1019 /* Study the expression */
1020 StudyExprInternal (Expr->Left, D);
1022 /* We can handle only const expressions */
1023 if (ED_IsConst (D)) {
1024 D->Val = (D->Val == 0);
1029 /* In any case, the result is 0 or 1 */
1030 D->AddrSize = ADDR_SIZE_ZP;
1035 static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
1036 /* Study an EXPR_BYTE0 expression node */
1038 /* Study the expression */
1039 StudyExprInternal (Expr->Left, D);
1041 /* We can handle only const expressions */
1042 if (ED_IsConst (D)) {
1043 D->Val = (D->Val & 0xFF);
1048 /* In any case, the result is a zero page expression */
1049 D->AddrSize = ADDR_SIZE_ZP;
1054 static void StudyByte1 (ExprNode* Expr, ExprDesc* D)
1055 /* Study an EXPR_BYTE1 expression node */
1057 /* Study the expression */
1058 StudyExprInternal (Expr->Left, D);
1060 /* We can handle only const expressions */
1061 if (ED_IsConst (D)) {
1062 D->Val = (D->Val >> 8) & 0xFF;
1067 /* In any case, the result is a zero page expression */
1068 D->AddrSize = ADDR_SIZE_ZP;
1073 static void StudyByte2 (ExprNode* Expr, ExprDesc* D)
1074 /* Study an EXPR_BYTE2 expression node */
1076 /* Study the expression */
1077 StudyExprInternal (Expr->Left, D);
1079 /* We can handle only const expressions */
1080 if (ED_IsConst (D)) {
1081 D->Val = (D->Val >> 16) & 0xFF;
1086 /* In any case, the result is a zero page expression */
1087 D->AddrSize = ADDR_SIZE_ZP;
1092 static void StudyByte3 (ExprNode* Expr, ExprDesc* D)
1093 /* Study an EXPR_BYTE3 expression node */
1095 /* Study the expression */
1096 StudyExprInternal (Expr->Left, D);
1098 /* We can handle only const expressions */
1099 if (ED_IsConst (D)) {
1100 D->Val = (D->Val >> 24) & 0xFF;
1105 /* In any case, the result is a zero page expression */
1106 D->AddrSize = ADDR_SIZE_ZP;
1111 static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
1112 /* Study an EXPR_WORD0 expression node */
1114 /* Study the expression */
1115 StudyExprInternal (Expr->Left, D);
1117 /* We can handle only const expressions */
1118 if (ED_IsConst (D)) {
1119 D->Val = (D->Val & 0xFFFFL);
1124 /* In any case, the result is an absolute expression */
1125 D->AddrSize = ADDR_SIZE_ABS;
1130 static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
1131 /* Study an EXPR_WORD1 expression node */
1133 /* Study the expression */
1134 StudyExprInternal (Expr->Left, D);
1136 /* We can handle only const expressions */
1137 if (ED_IsConst (D)) {
1138 D->Val = (D->Val >> 16) & 0xFFFFL;
1143 /* In any case, the result is an absolute expression */
1144 D->AddrSize = ADDR_SIZE_ABS;
1149 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
1150 /* Study an expression tree and place the contents into D */
1152 /* Study this expression node */
1156 StudyLiteral (Expr, D);
1160 StudySymbol (Expr, D);
1164 StudySection (Expr, D);
1168 StudyULabel (Expr, D);
1172 StudyPlus (Expr, D);
1176 StudyMinus (Expr, D);
1236 StudyBoolAnd (Expr, D);
1240 StudyBoolOr (Expr, D);
1244 StudyBoolXor (Expr, D);
1247 case EXPR_UNARY_MINUS:
1248 StudyUnaryMinus (Expr, D);
1256 StudySwap (Expr, D);
1260 StudyBoolNot (Expr, D);
1264 StudyByte0 (Expr, D);
1268 StudyByte1 (Expr, D);
1272 StudyByte2 (Expr, D);
1276 StudyByte3 (Expr, D);
1280 StudyWord0 (Expr, D);
1284 StudyWord1 (Expr, D);
1288 Internal ("Unknown Op type: %u", Expr->Op);
1295 void StudyExpr (ExprNode* Expr, ExprDesc* D)
1296 /* Study an expression tree and place the contents into D */
1300 /* Call the internal function */
1301 StudyExprInternal (Expr, D);
1303 /* Remove symbol references with count zero */
1305 while (I < D->SymCount) {
1306 if (D->SymRef[I].Count == 0) {
1307 /* Delete the entry */
1309 memmove (D->SymRef + I, D->SymRef + I + 1,
1310 (D->SymCount - I) * sizeof (D->SymRef[0]));
1317 /* Remove section references with count zero */
1319 while (I < D->SecCount) {
1320 if (D->SecRef[I].Count == 0) {
1321 /* Delete the entry */
1323 memmove (D->SecRef + I, D->SecRef + I + 1,
1324 (D->SecCount - I) * sizeof (D->SecRef[0]));
1331 /* If we don't have an address size, assign one of the expression is a
1334 if (D->AddrSize == ADDR_SIZE_DEFAULT) {
1335 if (ED_IsConst (D)) {
1336 if ((D->Val & ~0xFFL) == 0) {
1337 D->AddrSize = ADDR_SIZE_ZP;
1338 } else if ((D->Val & ~0xFFFFL) == 0) {
1339 D->AddrSize = ADDR_SIZE_ABS;
1340 } else if ((D->Val & 0xFFFFFFL) == 0) {
1341 D->AddrSize = ADDR_SIZE_FAR;
1343 D->AddrSize = ADDR_SIZE_LONG;
1349 printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
1350 if (!ED_IsValid (D)) {
1351 printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
1353 printf ("Valid: %s\n", AddrSizeToStr (D->AddrSize));
1354 printf ("%u symbols:\n", D->SymCount);
1355 printf ("%u sections:\n", D->SecCount);