1 /*****************************************************************************/
5 /* Study an expression tree */
9 /* (C) 2003-2007 Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
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_NegRefs (ExprDesc* D)
339 /* Negate the references in ED */
342 for (I = 0; I < D->SymCount; ++I) {
343 D->SymRef[I].Count = -D->SymRef[I].Count;
345 for (I = 0; I < D->SecCount; ++I) {
346 D->SecRef[I].Count = -D->SecRef[I].Count;
352 static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
353 /* Calculate ED = ED + Right, update address size in ED */
355 ED->Val += Right->Val;
356 ED_MergeRefs (ED, Right);
357 ED_MergeAddrSize (ED, Right);
362 static void ED_Sub (ExprDesc* ED, const ExprDesc* Right)
363 /* Calculate ED = ED - Right, update address size in ED */
365 ExprDesc D = *Right; /* Temporary */
368 ED->Val -= Right->Val;
369 ED_MergeRefs (ED, &D); /* Merge negatives */
370 ED_MergeAddrSize (ED, Right);
375 static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
376 /* Calculate ED = ED * Right, update address size in ED */
380 ED->Val *= Right->Val;
381 for (I = 0; I < ED->SymCount; ++I) {
382 ED->SymRef[I].Count *= Right->Val;
384 for (I = 0; I < ED->SecCount; ++I) {
385 ED->SecRef[I].Count *= Right->Val;
387 ED_MergeAddrSize (ED, Right);
392 static void ED_Neg (ExprDesc* D)
393 /* Negate an expression */
401 static void ED_Move (ExprDesc* From, ExprDesc* To)
402 /* Move the data from one ExprDesc to another. Old data is freed, and From
403 * is prepared to that ED_Done may be called safely.
406 /* Delete old data */
418 /*****************************************************************************/
420 /*****************************************************************************/
424 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
425 /* Study an expression tree and place the contents into D */
429 static unsigned char GetConstAddrSize (long Val)
430 /* Get the address size of a constant */
432 if ((Val & ~0xFFL) == 0) {
434 } else if ((Val & ~0xFFFFL) == 0) {
435 return ADDR_SIZE_ABS;
436 } else if ((Val & ~0xFFFFFFL) == 0) {
437 return ADDR_SIZE_FAR;
439 return ADDR_SIZE_LONG;
445 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
446 /* Study a binary expression subtree. This is a helper function for StudyExpr
447 * used for operations that succeed when both operands are known and constant.
448 * It evaluates the two subtrees and checks if they are constant. If they
449 * aren't constant, it will set the TOO_COMPLEX flag, and merge references.
450 * Otherwise the first value is returned in D->Val, the second one in D->Right,
451 * so the actual operation can be done by the caller.
456 /* Study the left side of the expression */
457 StudyExprInternal (Expr->Left, D);
459 /* Study the right side of the expression */
461 StudyExprInternal (Expr->Right, &Right);
463 /* Check if we can handle the operation */
464 if (ED_IsConst (D) && ED_IsConst (&Right)) {
466 /* Remember the constant value from Right */
467 D->Right = Right.Val;
471 /* Cannot evaluate */
474 /* Merge references and update address size */
475 ED_MergeRefs (D, &Right);
476 ED_MergeAddrSize (D, &Right);
486 static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
487 /* Study a literal expression node */
489 /* This one is easy */
490 D->Val = Expr->V.IVal;
491 D->AddrSize = GetConstAddrSize (D->Val);
496 static void StudySymbol (ExprNode* Expr, ExprDesc* D)
497 /* Study a symbol expression node */
499 /* Get the symbol from the expression */
500 SymEntry* Sym = Expr->V.Sym;
502 /* If the symbol is defined somewhere, it has an expression associated.
503 * In this case, just study the expression associated with the symbol,
504 * but mark the symbol so if we encounter it twice, we know that we have
505 * a circular reference.
507 if (SymHasExpr (Sym)) {
509 if (SymHasUserMark (Sym)) {
511 DumpExpr (Expr, SymResolve);
513 LIError (&Sym->LineInfos,
514 "Circular reference in definition of symbol `%m%p'",
519 unsigned char AddrSize;
521 /* Mark the symbol and study its associated expression */
523 StudyExprInternal (GetSymExpr (Sym), D);
526 /* If the symbol has an explicit address size, use it. This may
527 * lead to range errors later (maybe even in the linker stage), if
528 * the user lied about the address size, but for now we trust him.
530 AddrSize = GetSymAddrSize (Sym);
531 if (AddrSize != ADDR_SIZE_DEFAULT) {
532 D->AddrSize = AddrSize;
536 } else if (SymIsImport (Sym)) {
538 /* The symbol is an import. Track the symbols used and update the
541 ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
543 ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
547 unsigned char AddrSize;
550 /* The symbol is undefined. Track symbol usage but set the "too
551 * complex" flag, since we cannot evaluate the final result.
553 ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
557 /* Since the symbol may be a forward, and we may need a statement
558 * about the address size, check higher lexical levels for a symbol
559 * with the same name and use its address size if we find such a
560 * symbol which is defined.
562 AddrSize = GetSymAddrSize (Sym);
563 Parent = GetSymParentScope (Sym);
564 if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
565 SymEntry* H = SymFindAny (Parent, GetSymName (Sym));
567 AddrSize = GetSymAddrSize (H);
568 if (AddrSize != ADDR_SIZE_DEFAULT) {
569 D->AddrSize = AddrSize;
573 D->AddrSize = AddrSize;
580 static void StudySection (ExprNode* Expr, ExprDesc* D)
581 /* Study a section expression node */
583 /* Get the section reference */
584 ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SecNum);
586 /* Update the data and the address size */
588 ED_UpdateAddrSize (D, GetSegAddrSize (SecRef->Ref));
593 static void StudyULabel (ExprNode* Expr, ExprDesc* D)
594 /* Study an unnamed label expression node */
596 /* If we can resolve the label, study the expression associated with it,
597 * otherwise mark the expression as too complex to evaluate.
599 if (ULabCanResolve ()) {
600 /* We can resolve the label */
601 StudyExprInternal (ULabResolve (Expr->V.IVal), D);
609 static void StudyPlus (ExprNode* Expr, ExprDesc* D)
610 /* Study an EXPR_PLUS binary expression node */
614 /* Study the left side of the expression */
615 StudyExprInternal (Expr->Left, D);
617 /* Study the right side of the expression */
619 StudyExprInternal (Expr->Right, &Right);
621 /* Check if we can handle the operation */
622 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 StudyMinus (ExprNode* Expr, ExprDesc* D)
645 /* Study an EXPR_MINUS 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 /* Check if we can handle the operation */
657 if (ED_IsValid (D) && ED_IsValid (&Right)) {
664 /* Cannot evaluate */
667 /* Merge references and update address size */
668 ED_MergeRefs (D, &Right);
669 ED_MergeAddrSize (D, &Right);
679 static void StudyMul (ExprNode* Expr, ExprDesc* D)
680 /* Study an EXPR_MUL binary expression node */
684 /* Study the left side of the expression */
685 StudyExprInternal (Expr->Left, D);
687 /* Study the right side of the expression */
689 StudyExprInternal (Expr->Right, &Right);
691 /* We can handle the operation if at least one of both operands is const
692 * and the other one is valid.
694 if (ED_IsConst (D) && ED_IsValid (&Right)) {
696 /* Multiplicate both, result goes into Right */
699 /* Move result into D */
702 } else if (ED_IsConst (&Right) && ED_IsValid (D)) {
704 /* Multiplicate both */
709 /* Cannot handle this operation */
714 /* If we could not handle the op, merge references and update address size */
715 if (!ED_IsValid (D)) {
716 ED_MergeRefs (D, &Right);
717 ED_MergeAddrSize (D, &Right);
726 static void StudyDiv (ExprNode* Expr, ExprDesc* D)
727 /* Study an EXPR_DIV binary expression node */
729 /* Use helper function */
730 StudyBinaryExpr (Expr, D);
732 /* If the result is valid, apply the operation */
733 if (ED_IsValid (D)) {
735 Error ("Division by zero");
745 static void StudyMod (ExprNode* Expr, ExprDesc* D)
746 /* Study an EXPR_MOD binary expression node */
748 /* Use helper function */
749 StudyBinaryExpr (Expr, D);
751 /* If the result is valid, apply the operation */
752 if (ED_IsValid (D)) {
754 Error ("Modulo operation with zero");
764 static void StudyOr (ExprNode* Expr, ExprDesc* D)
765 /* Study an EXPR_OR binary expression node */
767 /* Use helper function */
768 StudyBinaryExpr (Expr, D);
770 /* If the result is valid, apply the operation */
771 if (ED_IsValid (D)) {
778 static void StudyXor (ExprNode* Expr, ExprDesc* D)
779 /* Study an EXPR_XOR binary expression node */
781 /* Use helper function */
782 StudyBinaryExpr (Expr, D);
784 /* If the result is valid, apply the operation */
785 if (ED_IsValid (D)) {
792 static void StudyAnd (ExprNode* Expr, ExprDesc* D)
793 /* Study an EXPR_AND binary expression node */
795 /* Use helper function */
796 StudyBinaryExpr (Expr, D);
798 /* If the result is valid, apply the operation */
799 if (ED_IsValid (D)) {
806 static void StudyShl (ExprNode* Expr, ExprDesc* D)
807 /* Study an EXPR_SHL binary expression node */
809 /* Use helper function */
810 StudyBinaryExpr (Expr, D);
812 /* If the result is valid, apply the operation */
813 if (ED_IsValid (D)) {
814 D->Val = shl_l (D->Val, D->Right);
820 static void StudyShr (ExprNode* Expr, ExprDesc* D)
821 /* Study an EXPR_SHR binary expression node */
823 /* Use helper function */
824 StudyBinaryExpr (Expr, D);
826 /* If the result is valid, apply the operation */
827 if (ED_IsValid (D)) {
828 D->Val = shr_l (D->Val, D->Right);
834 static void StudyEQ (ExprNode* Expr, ExprDesc* D)
835 /* Study an EXPR_EQ binary expression node */
837 /* Use helper function */
838 StudyBinaryExpr (Expr, D);
840 /* If the result is valid, apply the operation */
841 if (ED_IsValid (D)) {
842 D->Val = (D->Val == D->Right);
845 /* In any case, the result is 0 or 1 */
846 D->AddrSize = ADDR_SIZE_ZP;
851 static void StudyNE (ExprNode* Expr, ExprDesc* D)
852 /* Study an EXPR_NE binary expression node */
854 /* Use helper function */
855 StudyBinaryExpr (Expr, D);
857 /* If the result is valid, apply the operation */
858 if (ED_IsValid (D)) {
859 D->Val = (D->Val != D->Right);
862 /* In any case, the result is 0 or 1 */
863 D->AddrSize = ADDR_SIZE_ZP;
868 static void StudyLT (ExprNode* Expr, ExprDesc* D)
869 /* Study an EXPR_LT binary expression node */
871 /* Use helper function */
872 StudyBinaryExpr (Expr, D);
874 /* If the result is valid, apply the operation */
875 if (ED_IsValid (D)) {
876 D->Val = (D->Val < D->Right);
879 /* In any case, the result is 0 or 1 */
880 D->AddrSize = ADDR_SIZE_ZP;
885 static void StudyGT (ExprNode* Expr, ExprDesc* D)
886 /* Study an EXPR_GT binary expression node */
888 /* Use helper function */
889 StudyBinaryExpr (Expr, D);
891 /* If the result is valid, apply the operation */
892 if (ED_IsValid (D)) {
893 D->Val = (D->Val > D->Right);
896 /* In any case, the result is 0 or 1 */
897 D->AddrSize = ADDR_SIZE_ZP;
902 static void StudyLE (ExprNode* Expr, ExprDesc* D)
903 /* Study an EXPR_LE binary expression node */
905 /* Use helper function */
906 StudyBinaryExpr (Expr, D);
908 /* If the result is valid, apply the operation */
909 if (ED_IsValid (D)) {
910 D->Val = (D->Val <= D->Right);
913 /* In any case, the result is 0 or 1 */
914 D->AddrSize = ADDR_SIZE_ZP;
919 static void StudyGE (ExprNode* Expr, ExprDesc* D)
920 /* Study an EXPR_GE binary expression node */
922 /* Use helper function */
923 StudyBinaryExpr (Expr, D);
925 /* If the result is valid, apply the operation */
926 if (ED_IsValid (D)) {
927 D->Val = (D->Val >= D->Right);
930 /* In any case, the result is 0 or 1 */
931 D->AddrSize = ADDR_SIZE_ZP;
936 static void StudyBoolAnd (ExprNode* Expr, ExprDesc* D)
937 /* Study an EXPR_BOOLAND binary expression node */
939 StudyExprInternal (Expr->Left, D);
940 if (ED_IsConst (D)) {
941 if (D->Val != 0) { /* Shortcut op */
944 StudyExprInternal (Expr->Right, D);
945 if (ED_IsConst (D)) {
946 D->Val = (D->Val != 0);
955 /* In any case, the result is 0 or 1 */
956 D->AddrSize = ADDR_SIZE_ZP;
961 static void StudyBoolOr (ExprNode* Expr, ExprDesc* D)
962 /* Study an EXPR_BOOLOR binary expression node */
964 StudyExprInternal (Expr->Left, D);
965 if (ED_IsConst (D)) {
966 if (D->Val == 0) { /* Shortcut op */
969 StudyExprInternal (Expr->Right, D);
970 if (ED_IsConst (D)) {
971 D->Val = (D->Val != 0);
982 /* In any case, the result is 0 or 1 */
983 D->AddrSize = ADDR_SIZE_ZP;
988 static void StudyBoolXor (ExprNode* Expr, ExprDesc* D)
989 /* Study an EXPR_BOOLXOR binary expression node */
991 /* Use helper function */
992 StudyBinaryExpr (Expr, D);
994 /* If the result is valid, apply the operation */
995 if (ED_IsValid (D)) {
996 D->Val = (D->Val != 0) ^ (D->Right != 0);
999 /* In any case, the result is 0 or 1 */
1000 D->AddrSize = ADDR_SIZE_ZP;
1005 static void StudyMax (ExprNode* Expr, ExprDesc* D)
1006 /* Study an MAX binary expression node */
1008 /* Use helper function */
1009 StudyBinaryExpr (Expr, D);
1011 /* If the result is valid, apply the operation */
1012 if (ED_IsValid (D)) {
1013 D->Val = (D->Val > D->Right)? D->Val : D->Right;
1019 static void StudyMin (ExprNode* Expr, ExprDesc* D)
1020 /* Study an MIN binary expression node */
1022 /* Use helper function */
1023 StudyBinaryExpr (Expr, D);
1025 /* If the result is valid, apply the operation */
1026 if (ED_IsValid (D)) {
1027 D->Val = (D->Val < D->Right)? D->Val : D->Right;
1033 static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
1034 /* Study an EXPR_UNARY_MINUS expression node */
1036 /* Study the expression */
1037 StudyExprInternal (Expr->Left, D);
1039 /* If it is valid, negate it */
1040 if (ED_IsValid (D)) {
1047 static void StudyNot (ExprNode* Expr, ExprDesc* D)
1048 /* Study an EXPR_NOT expression node */
1050 /* Study the expression */
1051 StudyExprInternal (Expr->Left, D);
1053 /* We can handle only const expressions */
1054 if (ED_IsConst (D)) {
1063 static void StudySwap (ExprNode* Expr, ExprDesc* D)
1064 /* Study an EXPR_SWAP expression node */
1066 /* Study the expression */
1067 StudyExprInternal (Expr->Left, D);
1069 /* We can handle only const expressions */
1070 if (ED_IsConst (D)) {
1071 D->Val = (D->Val & ~0xFFFFUL) | ((D->Val >> 8) & 0xFF) | ((D->Val << 8) & 0xFF00);
1079 static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
1080 /* Study an EXPR_BOOLNOT expression node */
1082 /* Study the expression */
1083 StudyExprInternal (Expr->Left, D);
1085 /* We can handle only const expressions */
1086 if (ED_IsConst (D)) {
1087 D->Val = (D->Val == 0);
1092 /* In any case, the result is 0 or 1 */
1093 D->AddrSize = ADDR_SIZE_ZP;
1098 static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
1099 /* Study an EXPR_BYTE0 expression node */
1101 /* Study the expression */
1102 StudyExprInternal (Expr->Left, D);
1104 /* We can handle only const expressions */
1105 if (ED_IsConst (D)) {
1106 D->Val = (D->Val & 0xFF);
1111 /* In any case, the result is a zero page expression */
1112 D->AddrSize = ADDR_SIZE_ZP;
1117 static void StudyByte1 (ExprNode* Expr, ExprDesc* D)
1118 /* Study an EXPR_BYTE1 expression node */
1120 /* Study the expression */
1121 StudyExprInternal (Expr->Left, D);
1123 /* We can handle only const expressions */
1124 if (ED_IsConst (D)) {
1125 D->Val = (D->Val >> 8) & 0xFF;
1130 /* In any case, the result is a zero page expression */
1131 D->AddrSize = ADDR_SIZE_ZP;
1136 static void StudyByte2 (ExprNode* Expr, ExprDesc* D)
1137 /* Study an EXPR_BYTE2 expression node */
1139 /* Study the expression */
1140 StudyExprInternal (Expr->Left, D);
1142 /* We can handle only const expressions */
1143 if (ED_IsConst (D)) {
1144 D->Val = (D->Val >> 16) & 0xFF;
1149 /* In any case, the result is a zero page expression */
1150 D->AddrSize = ADDR_SIZE_ZP;
1155 static void StudyByte3 (ExprNode* Expr, ExprDesc* D)
1156 /* Study an EXPR_BYTE3 expression node */
1158 /* Study the expression */
1159 StudyExprInternal (Expr->Left, D);
1161 /* We can handle only const expressions */
1162 if (ED_IsConst (D)) {
1163 D->Val = (D->Val >> 24) & 0xFF;
1168 /* In any case, the result is a zero page expression */
1169 D->AddrSize = ADDR_SIZE_ZP;
1174 static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
1175 /* Study an EXPR_WORD0 expression node */
1177 /* Study the expression */
1178 StudyExprInternal (Expr->Left, D);
1180 /* We can handle only const expressions */
1181 if (ED_IsConst (D)) {
1182 D->Val = (D->Val & 0xFFFFL);
1187 /* In any case, the result is an absolute expression */
1188 D->AddrSize = ADDR_SIZE_ABS;
1193 static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
1194 /* Study an EXPR_WORD1 expression node */
1196 /* Study the expression */
1197 StudyExprInternal (Expr->Left, D);
1199 /* We can handle only const expressions */
1200 if (ED_IsConst (D)) {
1201 D->Val = (D->Val >> 16) & 0xFFFFL;
1206 /* In any case, the result is an absolute expression */
1207 D->AddrSize = ADDR_SIZE_ABS;
1212 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
1213 /* Study an expression tree and place the contents into D */
1215 /* Study this expression node */
1219 StudyLiteral (Expr, D);
1223 StudySymbol (Expr, D);
1227 StudySection (Expr, D);
1231 StudyULabel (Expr, D);
1235 StudyPlus (Expr, D);
1239 StudyMinus (Expr, D);
1299 StudyBoolAnd (Expr, D);
1303 StudyBoolOr (Expr, D);
1307 StudyBoolXor (Expr, D);
1318 case EXPR_UNARY_MINUS:
1319 StudyUnaryMinus (Expr, D);
1327 StudySwap (Expr, D);
1331 StudyBoolNot (Expr, D);
1335 StudyByte0 (Expr, D);
1339 StudyByte1 (Expr, D);
1343 StudyByte2 (Expr, D);
1347 StudyByte3 (Expr, D);
1351 StudyWord0 (Expr, D);
1355 StudyWord1 (Expr, D);
1359 Internal ("Unknown Op type: %u", Expr->Op);
1366 void StudyExpr (ExprNode* Expr, ExprDesc* D)
1367 /* Study an expression tree and place the contents into D */
1371 /* Call the internal function */
1372 StudyExprInternal (Expr, D);
1374 /* Remove symbol references with count zero */
1376 while (I < D->SymCount) {
1377 if (D->SymRef[I].Count == 0) {
1378 /* Delete the entry */
1380 memmove (D->SymRef + I, D->SymRef + I + 1,
1381 (D->SymCount - I) * sizeof (D->SymRef[0]));
1388 /* Remove section references with count zero */
1390 while (I < D->SecCount) {
1391 if (D->SecRef[I].Count == 0) {
1392 /* Delete the entry */
1394 memmove (D->SecRef + I, D->SecRef + I + 1,
1395 (D->SecCount - I) * sizeof (D->SecRef[0]));
1402 /* If we don't have an address size, assign one if the expression is a
1405 if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
1406 D->AddrSize = GetConstAddrSize (D->Val);
1409 /* If the expression is valid, throw away the address size and recalculate
1410 * it using the data we have. This is more exact than the on-the-fly
1411 * calculation done when evaluating the tree, because symbols may have
1412 * been removed from the expression, and the final numeric value is now
1415 if (ED_IsValid (D)) {
1416 unsigned char AddrSize;
1418 /* If there are symbols or sections, use the largest one. If the
1419 * expression resolves to a const, use the address size of the value.
1421 if (D->SymCount > 0 || D->SecCount > 0) {
1423 D->AddrSize = ADDR_SIZE_DEFAULT;
1425 for (I = 0; I < D->SymCount; ++I) {
1426 const SymEntry* Sym = D->SymRef[I].Ref;
1427 AddrSize = GetSymAddrSize (Sym);
1428 if (AddrSize > D->AddrSize) {
1429 D->AddrSize = AddrSize;
1433 for (I = 0; I < D->SecCount; ++I) {
1434 unsigned SegNum = D->SecRef[0].Ref;
1435 AddrSize = GetSegAddrSize (SegNum);
1436 if (AddrSize > D->AddrSize) {
1437 D->AddrSize = AddrSize;
1442 AddrSize = GetConstAddrSize (D->Val);
1443 if (AddrSize > D->AddrSize) {
1444 D->AddrSize = AddrSize;
1451 printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
1452 printf ("Value: %08lX\n", D->Val);
1453 if (!ED_IsValid (D)) {
1454 printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
1456 printf ("Valid: %s\n", AddrSizeToStr (D->AddrSize));
1458 printf ("%u symbols:\n", D->SymCount);
1459 printf ("%u sections:\n", D->SecCount);