1 /*****************************************************************************/
5 /* Study an expression tree */
9 /* (C) 2003-2012, 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, neither the ERROR nor the
110 * TOO_COMPLEX flags are set.
113 return ((D->Flags & (ED_ERROR | ED_TOO_COMPLEX)) == 0);
118 static int ED_HasError (const ExprDesc* D)
119 /* Return true if the expression has an error. */
121 return ((D->Flags & ED_ERROR) != 0);
126 static void ED_Invalidate (ExprDesc* D)
127 /* Set the TOO_COMPLEX flag for D */
129 D->Flags |= ED_TOO_COMPLEX;
134 static void ED_SetError (ExprDesc* D)
135 /* Set the TOO_COMPLEX and ERROR flags for D */
137 D->Flags |= (ED_ERROR | ED_TOO_COMPLEX);
142 static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
143 /* Update the address size of the expression */
145 if (ED_IsValid (ED)) {
146 /* ADDR_SIZE_DEFAULT may get overridden */
147 if (ED->AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) {
148 ED->AddrSize = AddrSize;
151 /* ADDR_SIZE_DEFAULT takes precedence */
152 if (ED->AddrSize != ADDR_SIZE_DEFAULT) {
153 if (AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) {
154 ED->AddrSize = AddrSize;
162 static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
163 /* Merge the address sizes of two expressions into ED */
165 if (ED->AddrSize == ADDR_SIZE_DEFAULT) {
166 /* If ED is valid, ADDR_SIZE_DEFAULT gets always overridden, otherwise
167 * it takes precedence over anything else.
169 if (ED_IsValid (ED)) {
170 ED->AddrSize = Right->AddrSize;
172 } else if (Right->AddrSize == ADDR_SIZE_DEFAULT) {
173 /* If Right is valid, ADDR_SIZE_DEFAULT gets always overridden,
174 * otherwise it takes precedence over anything else.
176 if (!ED_IsValid (Right)) {
177 ED->AddrSize = Right->AddrSize;
180 /* Neither ED nor Right has a default address size, use the larger of
183 if (Right->AddrSize > ED->AddrSize) {
184 ED->AddrSize = Right->AddrSize;
191 static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
192 /* Find a symbol reference and return it. Return NULL if the reference does
198 for (I = 0, SymRef = ED->SymRef; I < ED->SymCount; ++I, ++SymRef) {
199 if (SymRef->Ref == Sym) {
208 static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
209 /* Find a section reference and return it. Return NULL if the reference does
215 for (I = 0, SecRef = ED->SecRef; I < ED->SecCount; ++I, ++SecRef) {
216 if (SecRef->Ref == Sec) {
225 static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
226 /* Allocate a new symbol reference and return it. The count of the new
227 * reference will be set to zero, and the reference itself to Sym.
232 /* Make sure we have enough SymRef slots */
233 if (ED->SymCount >= ED->SymLimit) {
235 if (ED->SymLimit == 0) {
238 ED->SymRef = xrealloc (ED->SymRef, ED->SymLimit * sizeof (ED->SymRef[0]));
241 /* Allocate a new slot */
242 SymRef = ED->SymRef + ED->SymCount++;
244 /* Initialize the new struct and return it */
252 static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
253 /* Allocate a new section reference and return it. The count of the new
254 * reference will be set to zero, and the reference itself to Sec.
259 /* Make sure we have enough SecRef slots */
260 if (ED->SecCount >= ED->SecLimit) {
262 if (ED->SecLimit == 0) {
265 ED->SecRef = xrealloc (ED->SecRef, ED->SecLimit * sizeof (ED->SecRef[0]));
268 /* Allocate a new slot */
269 SecRef = ED->SecRef + ED->SecCount++;
271 /* Initialize the new struct and return it */
279 static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
280 /* Get a symbol reference and return it. If the symbol reference does not
281 * exist, a new one is created and returned.
284 ED_SymRef* SymRef = ED_FindSymRef (ED, Sym);
286 SymRef = ED_AllocSymRef (ED, Sym);
293 static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec)
294 /* Get a section reference and return it. If the section reference does not
295 * exist, a new one is created and returned.
298 ED_SecRef* SecRef = ED_FindSecRef (ED, Sec);
300 SecRef = ED_AllocSecRef (ED, Sec);
307 static void ED_MergeSymRefs (ExprDesc* ED, const ExprDesc* New)
308 /* Merge the symbol references from New into ED */
311 for (I = 0; I < New->SymCount; ++I) {
313 /* Get a pointer to the SymRef entry */
314 const ED_SymRef* NewRef = New->SymRef + I;
316 /* Get the corresponding entry in ED */
317 ED_SymRef* SymRef = ED_GetSymRef (ED, NewRef->Ref);
319 /* Sum up the references */
320 SymRef->Count += NewRef->Count;
326 static void ED_MergeSecRefs (ExprDesc* ED, const ExprDesc* New)
327 /* Merge the section references from New into ED */
330 for (I = 0; I < New->SecCount; ++I) {
332 /* Get a pointer to the SymRef entry */
333 const ED_SecRef* NewRef = New->SecRef + I;
335 /* Get the corresponding entry in ED */
336 ED_SecRef* SecRef = ED_GetSecRef (ED, NewRef->Ref);
338 /* Sum up the references */
339 SecRef->Count += NewRef->Count;
345 static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New)
346 /* Merge all references from New into ED */
348 ED_MergeSymRefs (ED, New);
349 ED_MergeSecRefs (ED, New);
354 static void ED_NegRefs (ExprDesc* D)
355 /* Negate the references in ED */
358 for (I = 0; I < D->SymCount; ++I) {
359 D->SymRef[I].Count = -D->SymRef[I].Count;
361 for (I = 0; I < D->SecCount; ++I) {
362 D->SecRef[I].Count = -D->SecRef[I].Count;
368 static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
369 /* Calculate ED = ED + Right, update address size in ED */
371 ED->Val += Right->Val;
372 ED_MergeRefs (ED, Right);
373 ED_MergeAddrSize (ED, Right);
378 static void ED_Sub (ExprDesc* ED, const ExprDesc* Right)
379 /* Calculate ED = ED - Right, update address size in ED */
381 ExprDesc D = *Right; /* Temporary */
384 ED->Val -= Right->Val;
385 ED_MergeRefs (ED, &D); /* Merge negatives */
386 ED_MergeAddrSize (ED, Right);
391 static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
392 /* Calculate ED = ED * Right, update address size in ED */
396 ED->Val *= Right->Val;
397 for (I = 0; I < ED->SymCount; ++I) {
398 ED->SymRef[I].Count *= Right->Val;
400 for (I = 0; I < ED->SecCount; ++I) {
401 ED->SecRef[I].Count *= Right->Val;
403 ED_MergeAddrSize (ED, Right);
408 static void ED_Neg (ExprDesc* D)
409 /* Negate an expression */
417 static void ED_Move (ExprDesc* From, ExprDesc* To)
418 /* Move the data from one ExprDesc to another. Old data is freed, and From
419 * is prepared to that ED_Done may be called safely.
422 /* Delete old data */
434 /*****************************************************************************/
436 /*****************************************************************************/
440 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
441 /* Study an expression tree and place the contents into D */
445 static unsigned char GetConstAddrSize (long Val)
446 /* Get the address size of a constant */
448 if ((Val & ~0xFFL) == 0) {
450 } else if ((Val & ~0xFFFFL) == 0) {
451 return ADDR_SIZE_ABS;
452 } else if ((Val & ~0xFFFFFFL) == 0) {
453 return ADDR_SIZE_FAR;
455 return ADDR_SIZE_LONG;
461 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
462 /* Study a binary expression subtree. This is a helper function for StudyExpr
463 * used for operations that succeed when both operands are known and constant.
464 * It evaluates the two subtrees and checks if they are constant. If they
465 * aren't constant, it will set the TOO_COMPLEX flag, and merge references.
466 * Otherwise the first value is returned in D->Val, the second one in D->Right,
467 * so the actual operation can be done by the caller.
472 /* Study the left side of the expression */
473 StudyExprInternal (Expr->Left, D);
475 /* Study the right side of the expression */
477 StudyExprInternal (Expr->Right, &Right);
479 /* Check if we can handle the operation */
480 if (ED_IsConst (D) && ED_IsConst (&Right)) {
482 /* Remember the constant value from Right */
483 D->Right = Right.Val;
487 /* Cannot evaluate */
490 /* Merge references and update address size */
491 ED_MergeRefs (D, &Right);
492 ED_MergeAddrSize (D, &Right);
502 static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
503 /* Study a literal expression node */
505 /* This one is easy */
506 D->Val = Expr->V.IVal;
507 D->AddrSize = GetConstAddrSize (D->Val);
512 static void StudySymbol (ExprNode* Expr, ExprDesc* D)
513 /* Study a symbol expression node */
515 /* Get the symbol from the expression */
516 SymEntry* Sym = Expr->V.Sym;
518 /* If the symbol is defined somewhere, it has an expression associated.
519 * In this case, just study the expression associated with the symbol,
520 * but mark the symbol so if we encounter it twice, we know that we have
521 * a circular reference.
523 if (SymHasExpr (Sym)) {
525 if (SymHasUserMark (Sym)) {
526 LIError (&Sym->DefLines,
527 "Circular reference in definition of symbol `%m%p'",
532 unsigned char AddrSize;
534 /* Mark the symbol and study its associated expression */
536 StudyExprInternal (GetSymExpr (Sym), D);
539 /* If requested and if the expression is valid, dump it */
540 if (Verbosity > 0 && !ED_HasError (D)) {
541 DumpExpr (Expr, SymResolve);
544 /* If the symbol has an explicit address size, use it. This may
545 * lead to range errors later (maybe even in the linker stage), if
546 * the user lied about the address size, but for now we trust him.
548 AddrSize = GetSymAddrSize (Sym);
549 if (AddrSize != ADDR_SIZE_DEFAULT) {
550 D->AddrSize = AddrSize;
554 } else if (SymIsImport (Sym)) {
556 /* The symbol is an import. Track the symbols used and update the
559 ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
561 ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
565 unsigned char AddrSize;
568 /* The symbol is undefined. Track symbol usage but set the "too
569 * complex" flag, since we cannot evaluate the final result.
571 ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
575 /* Since the symbol may be a forward, and we may need a statement
576 * about the address size, check higher lexical levels for a symbol
577 * with the same name and use its address size if we find such a
578 * symbol which is defined.
580 AddrSize = GetSymAddrSize (Sym);
581 Parent = GetSymParentScope (Sym);
582 if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
583 SymEntry* H = SymFindAny (Parent, GetSymName (Sym));
585 AddrSize = GetSymAddrSize (H);
586 if (AddrSize != ADDR_SIZE_DEFAULT) {
587 D->AddrSize = AddrSize;
591 D->AddrSize = AddrSize;
598 static void StudySection (ExprNode* Expr, ExprDesc* D)
599 /* Study a section expression node */
601 /* Get the section reference */
602 ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SecNum);
604 /* Update the data and the address size */
606 ED_UpdateAddrSize (D, GetSegAddrSize (SecRef->Ref));
611 static void StudyULabel (ExprNode* Expr, ExprDesc* D)
612 /* Study an unnamed label expression node */
614 /* If we can resolve the label, study the expression associated with it,
615 * otherwise mark the expression as too complex to evaluate.
617 if (ULabCanResolve ()) {
618 /* We can resolve the label */
619 StudyExprInternal (ULabResolve (Expr->V.IVal), D);
627 static void StudyPlus (ExprNode* Expr, ExprDesc* D)
628 /* Study an EXPR_PLUS binary expression node */
632 /* Study the left side of the expression */
633 StudyExprInternal (Expr->Left, D);
635 /* Study the right side of the expression */
637 StudyExprInternal (Expr->Right, &Right);
639 /* Check if we can handle the operation */
640 if (ED_IsValid (D) && ED_IsValid (&Right)) {
647 /* Cannot evaluate */
650 /* Merge references and update address size */
651 ED_MergeRefs (D, &Right);
652 ED_MergeAddrSize (D, &Right);
662 static void StudyMinus (ExprNode* Expr, ExprDesc* D)
663 /* Study an EXPR_MINUS binary expression node */
667 /* Study the left side of the expression */
668 StudyExprInternal (Expr->Left, D);
670 /* Study the right side of the expression */
672 StudyExprInternal (Expr->Right, &Right);
674 /* Check if we can handle the operation */
675 if (ED_IsValid (D) && ED_IsValid (&Right)) {
682 /* Cannot evaluate */
685 /* Merge references and update address size */
686 ED_MergeRefs (D, &Right);
687 ED_MergeAddrSize (D, &Right);
697 static void StudyMul (ExprNode* Expr, ExprDesc* D)
698 /* Study an EXPR_MUL binary expression node */
702 /* Study the left side of the expression */
703 StudyExprInternal (Expr->Left, D);
705 /* Study the right side of the expression */
707 StudyExprInternal (Expr->Right, &Right);
709 /* We can handle the operation if at least one of both operands is const
710 * and the other one is valid.
712 if (ED_IsConst (D) && ED_IsValid (&Right)) {
714 /* Multiplicate both, result goes into Right */
717 /* Move result into D */
720 } else if (ED_IsConst (&Right) && ED_IsValid (D)) {
722 /* Multiplicate both */
727 /* Cannot handle this operation */
732 /* If we could not handle the op, merge references and update address size */
733 if (!ED_IsValid (D)) {
734 ED_MergeRefs (D, &Right);
735 ED_MergeAddrSize (D, &Right);
744 static void StudyDiv (ExprNode* Expr, ExprDesc* D)
745 /* Study an EXPR_DIV binary expression node */
747 /* Use helper function */
748 StudyBinaryExpr (Expr, D);
750 /* If the result is valid, apply the operation */
751 if (ED_IsValid (D)) {
753 Error ("Division by zero");
763 static void StudyMod (ExprNode* Expr, ExprDesc* D)
764 /* Study an EXPR_MOD binary expression node */
766 /* Use helper function */
767 StudyBinaryExpr (Expr, D);
769 /* If the result is valid, apply the operation */
770 if (ED_IsValid (D)) {
772 Error ("Modulo operation with zero");
782 static void StudyOr (ExprNode* Expr, ExprDesc* D)
783 /* Study an EXPR_OR binary expression node */
785 /* Use helper function */
786 StudyBinaryExpr (Expr, D);
788 /* If the result is valid, apply the operation */
789 if (ED_IsValid (D)) {
796 static void StudyXor (ExprNode* Expr, ExprDesc* D)
797 /* Study an EXPR_XOR binary expression node */
799 /* Use helper function */
800 StudyBinaryExpr (Expr, D);
802 /* If the result is valid, apply the operation */
803 if (ED_IsValid (D)) {
810 static void StudyAnd (ExprNode* Expr, ExprDesc* D)
811 /* Study an EXPR_AND binary expression node */
813 /* Use helper function */
814 StudyBinaryExpr (Expr, D);
816 /* If the result is valid, apply the operation */
817 if (ED_IsValid (D)) {
824 static void StudyShl (ExprNode* Expr, ExprDesc* D)
825 /* Study an EXPR_SHL binary expression node */
827 /* Use helper function */
828 StudyBinaryExpr (Expr, D);
830 /* If the result is valid, apply the operation */
831 if (ED_IsValid (D)) {
832 D->Val = shl_l (D->Val, D->Right);
838 static void StudyShr (ExprNode* Expr, ExprDesc* D)
839 /* Study an EXPR_SHR binary expression node */
841 /* Use helper function */
842 StudyBinaryExpr (Expr, D);
844 /* If the result is valid, apply the operation */
845 if (ED_IsValid (D)) {
846 D->Val = shr_l (D->Val, D->Right);
852 static void StudyEQ (ExprNode* Expr, ExprDesc* D)
853 /* Study an EXPR_EQ binary expression node */
855 /* Use helper function */
856 StudyBinaryExpr (Expr, D);
858 /* If the result is valid, apply the operation */
859 if (ED_IsValid (D)) {
860 D->Val = (D->Val == D->Right);
863 /* In any case, the result is 0 or 1 */
864 D->AddrSize = ADDR_SIZE_ZP;
869 static void StudyNE (ExprNode* Expr, ExprDesc* D)
870 /* Study an EXPR_NE binary expression node */
872 /* Use helper function */
873 StudyBinaryExpr (Expr, D);
875 /* If the result is valid, apply the operation */
876 if (ED_IsValid (D)) {
877 D->Val = (D->Val != D->Right);
880 /* In any case, the result is 0 or 1 */
881 D->AddrSize = ADDR_SIZE_ZP;
886 static void StudyLT (ExprNode* Expr, ExprDesc* D)
887 /* Study an EXPR_LT binary expression node */
889 /* Use helper function */
890 StudyBinaryExpr (Expr, D);
892 /* If the result is valid, apply the operation */
893 if (ED_IsValid (D)) {
894 D->Val = (D->Val < D->Right);
897 /* In any case, the result is 0 or 1 */
898 D->AddrSize = ADDR_SIZE_ZP;
903 static void StudyGT (ExprNode* Expr, ExprDesc* D)
904 /* Study an EXPR_GT binary expression node */
906 /* Use helper function */
907 StudyBinaryExpr (Expr, D);
909 /* If the result is valid, apply the operation */
910 if (ED_IsValid (D)) {
911 D->Val = (D->Val > D->Right);
914 /* In any case, the result is 0 or 1 */
915 D->AddrSize = ADDR_SIZE_ZP;
920 static void StudyLE (ExprNode* Expr, ExprDesc* D)
921 /* Study an EXPR_LE binary expression node */
923 /* Use helper function */
924 StudyBinaryExpr (Expr, D);
926 /* If the result is valid, apply the operation */
927 if (ED_IsValid (D)) {
928 D->Val = (D->Val <= D->Right);
931 /* In any case, the result is 0 or 1 */
932 D->AddrSize = ADDR_SIZE_ZP;
937 static void StudyGE (ExprNode* Expr, ExprDesc* D)
938 /* Study an EXPR_GE binary expression node */
940 /* Use helper function */
941 StudyBinaryExpr (Expr, D);
943 /* If the result is valid, apply the operation */
944 if (ED_IsValid (D)) {
945 D->Val = (D->Val >= D->Right);
948 /* In any case, the result is 0 or 1 */
949 D->AddrSize = ADDR_SIZE_ZP;
954 static void StudyBoolAnd (ExprNode* Expr, ExprDesc* D)
955 /* Study an EXPR_BOOLAND binary expression node */
957 StudyExprInternal (Expr->Left, D);
958 if (ED_IsConst (D)) {
959 if (D->Val != 0) { /* Shortcut op */
962 StudyExprInternal (Expr->Right, D);
963 if (ED_IsConst (D)) {
964 D->Val = (D->Val != 0);
973 /* In any case, the result is 0 or 1 */
974 D->AddrSize = ADDR_SIZE_ZP;
979 static void StudyBoolOr (ExprNode* Expr, ExprDesc* D)
980 /* Study an EXPR_BOOLOR binary expression node */
982 StudyExprInternal (Expr->Left, D);
983 if (ED_IsConst (D)) {
984 if (D->Val == 0) { /* Shortcut op */
987 StudyExprInternal (Expr->Right, D);
988 if (ED_IsConst (D)) {
989 D->Val = (D->Val != 0);
1000 /* In any case, the result is 0 or 1 */
1001 D->AddrSize = ADDR_SIZE_ZP;
1006 static void StudyBoolXor (ExprNode* Expr, ExprDesc* D)
1007 /* Study an EXPR_BOOLXOR binary expression node */
1009 /* Use helper function */
1010 StudyBinaryExpr (Expr, D);
1012 /* If the result is valid, apply the operation */
1013 if (ED_IsValid (D)) {
1014 D->Val = (D->Val != 0) ^ (D->Right != 0);
1017 /* In any case, the result is 0 or 1 */
1018 D->AddrSize = ADDR_SIZE_ZP;
1023 static void StudyMax (ExprNode* Expr, ExprDesc* D)
1024 /* Study an MAX binary expression node */
1026 /* Use helper function */
1027 StudyBinaryExpr (Expr, D);
1029 /* If the result is valid, apply the operation */
1030 if (ED_IsValid (D)) {
1031 D->Val = (D->Val > D->Right)? D->Val : D->Right;
1037 static void StudyMin (ExprNode* Expr, ExprDesc* D)
1038 /* Study an MIN binary expression node */
1040 /* Use helper function */
1041 StudyBinaryExpr (Expr, D);
1043 /* If the result is valid, apply the operation */
1044 if (ED_IsValid (D)) {
1045 D->Val = (D->Val < D->Right)? D->Val : D->Right;
1051 static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
1052 /* Study an EXPR_UNARY_MINUS expression node */
1054 /* Study the expression */
1055 StudyExprInternal (Expr->Left, D);
1057 /* If it is valid, negate it */
1058 if (ED_IsValid (D)) {
1065 static void StudyNot (ExprNode* Expr, ExprDesc* D)
1066 /* Study an EXPR_NOT expression node */
1068 /* Study the expression */
1069 StudyExprInternal (Expr->Left, D);
1071 /* We can handle only const expressions */
1072 if (ED_IsConst (D)) {
1081 static void StudySwap (ExprNode* Expr, ExprDesc* D)
1082 /* Study an EXPR_SWAP expression node */
1084 /* Study the expression */
1085 StudyExprInternal (Expr->Left, D);
1087 /* We can handle only const expressions */
1088 if (ED_IsConst (D)) {
1089 D->Val = (D->Val & ~0xFFFFUL) | ((D->Val >> 8) & 0xFF) | ((D->Val << 8) & 0xFF00);
1097 static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
1098 /* Study an EXPR_BOOLNOT expression node */
1100 /* Study the expression */
1101 StudyExprInternal (Expr->Left, D);
1103 /* We can handle only const expressions */
1104 if (ED_IsConst (D)) {
1105 D->Val = (D->Val == 0);
1110 /* In any case, the result is 0 or 1 */
1111 D->AddrSize = ADDR_SIZE_ZP;
1116 static void StudyBank (ExprNode* Expr, ExprDesc* D)
1117 /* Study an EXPR_BANK expression node */
1119 /* Study the expression extracting section references */
1120 StudyExprInternal (Expr->Left, D);
1122 /* The expression is always linker evaluated, so invalidate it */
1128 static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
1129 /* Study an EXPR_BYTE0 expression node */
1131 /* Study the expression */
1132 StudyExprInternal (Expr->Left, D);
1134 /* We can handle only const expressions */
1135 if (ED_IsConst (D)) {
1136 D->Val = (D->Val & 0xFF);
1141 /* In any case, the result is a zero page expression */
1142 D->AddrSize = ADDR_SIZE_ZP;
1147 static void StudyByte1 (ExprNode* Expr, ExprDesc* D)
1148 /* Study an EXPR_BYTE1 expression node */
1150 /* Study the expression */
1151 StudyExprInternal (Expr->Left, D);
1153 /* We can handle only const expressions */
1154 if (ED_IsConst (D)) {
1155 D->Val = (D->Val >> 8) & 0xFF;
1160 /* In any case, the result is a zero page expression */
1161 D->AddrSize = ADDR_SIZE_ZP;
1166 static void StudyByte2 (ExprNode* Expr, ExprDesc* D)
1167 /* Study an EXPR_BYTE2 expression node */
1169 /* Study the expression */
1170 StudyExprInternal (Expr->Left, D);
1172 /* We can handle only const expressions */
1173 if (ED_IsConst (D)) {
1174 D->Val = (D->Val >> 16) & 0xFF;
1179 /* In any case, the result is a zero page expression */
1180 D->AddrSize = ADDR_SIZE_ZP;
1185 static void StudyByte3 (ExprNode* Expr, ExprDesc* D)
1186 /* Study an EXPR_BYTE3 expression node */
1188 /* Study the expression */
1189 StudyExprInternal (Expr->Left, D);
1191 /* We can handle only const expressions */
1192 if (ED_IsConst (D)) {
1193 D->Val = (D->Val >> 24) & 0xFF;
1198 /* In any case, the result is a zero page expression */
1199 D->AddrSize = ADDR_SIZE_ZP;
1204 static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
1205 /* Study an EXPR_WORD0 expression node */
1207 /* Study the expression */
1208 StudyExprInternal (Expr->Left, D);
1210 /* We can handle only const expressions */
1211 if (ED_IsConst (D)) {
1217 /* In any case, the result is an absolute expression */
1218 D->AddrSize = ADDR_SIZE_ABS;
1223 static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
1224 /* Study an EXPR_WORD1 expression node */
1226 /* Study the expression */
1227 StudyExprInternal (Expr->Left, D);
1229 /* We can handle only const expressions */
1230 if (ED_IsConst (D)) {
1231 D->Val = (D->Val >> 16) & 0xFFFFL;
1236 /* In any case, the result is an absolute expression */
1237 D->AddrSize = ADDR_SIZE_ABS;
1242 static void StudyFarAddr (ExprNode* Expr, ExprDesc* D)
1243 /* Study an EXPR_FARADDR expression node */
1245 /* Study the expression */
1246 StudyExprInternal (Expr->Left, D);
1248 /* We can handle only const expressions */
1249 if (ED_IsConst (D)) {
1250 D->Val &= 0xFFFFFFL;
1255 /* In any case, the result is a far address */
1256 D->AddrSize = ADDR_SIZE_FAR;
1261 static void StudyDWord (ExprNode* Expr, ExprDesc* D)
1262 /* Study an EXPR_DWORD expression node */
1264 /* Study the expression */
1265 StudyExprInternal (Expr->Left, D);
1267 /* We can handle only const expressions */
1268 if (ED_IsConst (D)) {
1269 D->Val &= 0xFFFFFFFFL;
1274 /* In any case, the result is a long expression */
1275 D->AddrSize = ADDR_SIZE_LONG;
1280 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
1281 /* Study an expression tree and place the contents into D */
1283 /* Study this expression node */
1287 StudyLiteral (Expr, D);
1291 StudySymbol (Expr, D);
1295 StudySection (Expr, D);
1299 StudyULabel (Expr, D);
1303 StudyPlus (Expr, D);
1307 StudyMinus (Expr, D);
1367 StudyBoolAnd (Expr, D);
1371 StudyBoolOr (Expr, D);
1375 StudyBoolXor (Expr, D);
1386 case EXPR_UNARY_MINUS:
1387 StudyUnaryMinus (Expr, D);
1395 StudySwap (Expr, D);
1399 StudyBoolNot (Expr, D);
1403 StudyBank (Expr, D);
1407 StudyByte0 (Expr, D);
1411 StudyByte1 (Expr, D);
1415 StudyByte2 (Expr, D);
1419 StudyByte3 (Expr, D);
1423 StudyWord0 (Expr, D);
1427 StudyWord1 (Expr, D);
1431 StudyFarAddr (Expr, D);
1435 StudyDWord (Expr, D);
1439 Internal ("Unknown Op type: %u", Expr->Op);
1446 void StudyExpr (ExprNode* Expr, ExprDesc* D)
1447 /* Study an expression tree and place the contents into D */
1451 /* Call the internal function */
1452 StudyExprInternal (Expr, D);
1454 /* Remove symbol references with count zero */
1456 while (I < D->SymCount) {
1457 if (D->SymRef[I].Count == 0) {
1458 /* Delete the entry */
1460 memmove (D->SymRef + I, D->SymRef + I + 1,
1461 (D->SymCount - I) * sizeof (D->SymRef[0]));
1468 /* Remove section references with count zero */
1470 while (I < D->SecCount) {
1471 if (D->SecRef[I].Count == 0) {
1472 /* Delete the entry */
1474 memmove (D->SecRef + I, D->SecRef + I + 1,
1475 (D->SecCount - I) * sizeof (D->SecRef[0]));
1482 /* If we don't have an address size, assign one if the expression is a
1485 if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
1486 D->AddrSize = GetConstAddrSize (D->Val);
1489 /* If the expression is valid, throw away the address size and recalculate
1490 * it using the data we have. This is more exact than the on-the-fly
1491 * calculation done when evaluating the tree, because symbols may have
1492 * been removed from the expression, and the final numeric value is now
1495 if (ED_IsValid (D)) {
1496 unsigned char AddrSize;
1498 /* If there are symbols or sections, use the largest one. If the
1499 * expression resolves to a const, use the address size of the value.
1501 if (D->SymCount > 0 || D->SecCount > 0) {
1503 D->AddrSize = ADDR_SIZE_DEFAULT;
1505 for (I = 0; I < D->SymCount; ++I) {
1506 const SymEntry* Sym = D->SymRef[I].Ref;
1507 AddrSize = GetSymAddrSize (Sym);
1508 if (AddrSize > D->AddrSize) {
1509 D->AddrSize = AddrSize;
1513 for (I = 0; I < D->SecCount; ++I) {
1514 unsigned SegNum = D->SecRef[0].Ref;
1515 AddrSize = GetSegAddrSize (SegNum);
1516 if (AddrSize > D->AddrSize) {
1517 D->AddrSize = AddrSize;
1522 AddrSize = GetConstAddrSize (D->Val);
1523 if (AddrSize > D->AddrSize) {
1524 D->AddrSize = AddrSize;
1531 printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
1532 printf ("Value: %08lX\n", D->Val);
1533 if (!ED_IsValid (D)) {
1534 printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
1536 printf ("Valid: %s\n", AddrSizeToStr (D->AddrSize));
1538 printf ("%u symbols:\n", D->SymCount);
1539 printf ("%u sections:\n", D->SecCount);