1/*****************************************************************************/
2/* */
3/* studyexpr.c */
4/* */
5/* Study an expression tree */
6/* */
7/* */
8/* */
9/* (C) 2003-2012, Ullrich von Bassewitz */
10/* Roemerstrasse 52 */
11/* D-70794 Filderstadt */
12/* EMail: uz@cc65.org */
13/* */
14/* */
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. */
18/* */
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: */
22/* */
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 */
30/* distribution. */
31/* */
32/*****************************************************************************/
33
34
35
36#include <string.h>
37
38/* common */
39#include "check.h"
40#include "debugflag.h"
41#include "shift.h"
42#include "xmalloc.h"
43
44/* ca65 */
45#include "error.h"
46#include "segment.h"
47#include "studyexpr.h"
48#include "symtab.h"
49#include "ulabel.h"
50
51
52
53/*****************************************************************************/
54/* struct ExprDesc */
55/*****************************************************************************/
56
57
58
59ExprDesc* ED_Init (ExprDesc* ED)
60/* Initialize an ExprDesc structure for use with StudyExpr */
61{
62 ED->Flags = ED_OK;
63 ED->AddrSize = ADDR_SIZE_DEFAULT;
64 ED->Val = 0;
65 ED->SymCount = 0;
66 ED->SymLimit = 0;
67 ED->SymRef = 0;
68 ED->SecCount = 0;
69 ED->SecLimit = 0;
70 ED->SecRef = 0;
71 return ED;
72}
73
74
75
76void ED_Done (ExprDesc* ED)
77/* Delete allocated memory for an ExprDesc. */
78{
79 xfree (ED->SymRef);
80 xfree (ED->SecRef);
81}
82
83
84
85int ED_IsConst (const ExprDesc* D)
86/* Return true if the expression is constant */
87{
88 unsigned I;
89
90 if (D->Flags & ED_TOO_COMPLEX) {
91 return 0;
92 }
93 for (I = 0; I < D->SymCount; ++I) {
94 if (D->SymRef[I].Count != 0) {
95 return 0;
96 }
97 }
98 for (I = 0; I < D->SecCount; ++I) {
99 if (D->SecRef[I].Count != 0) {
100 return 0;
101 }
102 }
103 return 1;
104}
105
106
107
108static 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.
111*/
112{
113 return ((D->Flags & (ED_ERROR | ED_TOO_COMPLEX)) == 0);
114}
115
116
117
118static int ED_HasError (const ExprDesc* D)
119/* Return true if the expression has an error. */
120{
121 return ((D->Flags & ED_ERROR) != 0);
122}
123
124
125
126static void ED_Invalidate (ExprDesc* D)
127/* Set the TOO_COMPLEX flag for D */
128{
129 D->Flags |= ED_TOO_COMPLEX;
130}
131
132
133
134static void ED_SetError (ExprDesc* D)
135/* Set the TOO_COMPLEX and ERROR flags for D */
136{
137 D->Flags |= (ED_ERROR | ED_TOO_COMPLEX);
138}
139
140
141
142static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
143/* Update the address size of the expression */
144{
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;
149 }
150 } else {
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;
155 }
156 }
157 }
158}
159
160
161
162static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
163/* Merge the address sizes of two expressions into ED */
164{
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.
168 */
169 if (ED_IsValid (ED)) {
170 ED->AddrSize = Right->AddrSize;
171 }
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.
175 */
176 if (!ED_IsValid (Right)) {
177 ED->AddrSize = Right->AddrSize;
178 }
179 } else {
180 /* Neither ED nor Right has a default address size, use the larger of
181 ** the two.
182 */
183 if (Right->AddrSize > ED->AddrSize) {
184 ED->AddrSize = Right->AddrSize;
185 }
186 }
187}
188
189
190
191static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
192/* Find a symbol reference and return it. Return NULL if the reference does
193** not exist.
194*/
195{
196 unsigned I;
197 ED_SymRef* SymRef;
198 for (I = 0, SymRef = ED->SymRef; I < ED->SymCount; ++I, ++SymRef) {
199 if (SymRef->Ref == Sym) {
200 return SymRef;
201 }
202 }
203 return 0;
204}
205
206
207
208static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
209/* Find a section reference and return it. Return NULL if the reference does
210** not exist.
211*/
212{
213 unsigned I;
214 ED_SecRef* SecRef;
215 for (I = 0, SecRef = ED->SecRef; I < ED->SecCount; ++I, ++SecRef) {
216 if (SecRef->Ref == Sec) {
217 return SecRef;
218 }
219 }
220 return 0;
221}
222
223
224
225static 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.
228*/
229{
230 ED_SymRef* SymRef;
231
232 /* Make sure we have enough SymRef slots */
233 if (ED->SymCount >= ED->SymLimit) {
234 ED->SymLimit *= 2;
235 if (ED->SymLimit == 0) {
236 ED->SymLimit = 2;
237 }
238 ED->SymRef = xrealloc (ED->SymRef, ED->SymLimit * sizeof (ED->SymRef[0]));
239 }
240
241 /* Allocate a new slot */
242 SymRef = ED->SymRef + ED->SymCount++;
243
244 /* Initialize the new struct and return it */
245 SymRef->Count = 0;
246 SymRef->Ref = Sym;
247 return SymRef;
248}
249
250
251
252static 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.
255*/
256{
257 ED_SecRef* SecRef;
258
259 /* Make sure we have enough SecRef slots */
260 if (ED->SecCount >= ED->SecLimit) {
261 ED->SecLimit *= 2;
262 if (ED->SecLimit == 0) {
263 ED->SecLimit = 2;
264 }
265 ED->SecRef = xrealloc (ED->SecRef, ED->SecLimit * sizeof (ED->SecRef[0]));
266 }
267
268 /* Allocate a new slot */
269 SecRef = ED->SecRef + ED->SecCount++;
270
271 /* Initialize the new struct and return it */
272 SecRef->Count = 0;
273 SecRef->Ref = Sec;
274 return SecRef;
275}
276
277
278
279static 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.
282*/
283{
284 ED_SymRef* SymRef = ED_FindSymRef (ED, Sym);
285 if (SymRef == 0) {
286 SymRef = ED_AllocSymRef (ED, Sym);
287 }
288 return SymRef;
289}
290
291
292
293static 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.
296*/
297{
298 ED_SecRef* SecRef = ED_FindSecRef (ED, Sec);
299 if (SecRef == 0) {
300 SecRef = ED_AllocSecRef (ED, Sec);
301 }
302 return SecRef;
303}
304
305
306
307static void ED_MergeSymRefs (ExprDesc* ED, const ExprDesc* New)
308/* Merge the symbol references from New into ED */
309{
310 unsigned I;
311 for (I = 0; I < New->SymCount; ++I) {
312
313 /* Get a pointer to the SymRef entry */
314 const ED_SymRef* NewRef = New->SymRef + I;
315
316 /* Get the corresponding entry in ED */
317 ED_SymRef* SymRef = ED_GetSymRef (ED, NewRef->Ref);
318
319 /* Sum up the references */
320 SymRef->Count += NewRef->Count;
321 }
322}
323
324
325
326static void ED_MergeSecRefs (ExprDesc* ED, const ExprDesc* New)
327/* Merge the section references from New into ED */
328{
329 unsigned I;
330 for (I = 0; I < New->SecCount; ++I) {
331
332 /* Get a pointer to the SymRef entry */
333 const ED_SecRef* NewRef = New->SecRef + I;
334
335 /* Get the corresponding entry in ED */
336 ED_SecRef* SecRef = ED_GetSecRef (ED, NewRef->Ref);
337
338 /* Sum up the references */
339 SecRef->Count += NewRef->Count;
340 }
341}
342
343
344
345static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New)
346/* Merge all references from New into ED */
347{
348 ED_MergeSymRefs (ED, New);
349 ED_MergeSecRefs (ED, New);
350}
351
352
353
354static void ED_NegRefs (ExprDesc* D)
355/* Negate the references in ED */
356{
357 unsigned I;
358 for (I = 0; I < D->SymCount; ++I) {
359 D->SymRef[I].Count = -D->SymRef[I].Count;
360 }
361 for (I = 0; I < D->SecCount; ++I) {
362 D->SecRef[I].Count = -D->SecRef[I].Count;
363 }
364}
365
366
367
368static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
369/* Calculate ED = ED + Right, update address size in ED */
370{
371 ED->Val += Right->Val;
372 ED_MergeRefs (ED, Right);
373 ED_MergeAddrSize (ED, Right);
374}
375
376
377
378static void ED_Sub (ExprDesc* ED, const ExprDesc* Right)
379/* Calculate ED = ED - Right, update address size in ED */
380{
381 ExprDesc D = *Right; /* Temporary */
382 ED_NegRefs (&D);
383
384 ED->Val -= Right->Val;
385 ED_MergeRefs (ED, &D); /* Merge negatives */
386 ED_MergeAddrSize (ED, Right);
387}
388
389
390
391static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
392/* Calculate ED = ED * Right, update address size in ED */
393{
394 unsigned I;
395
396 ED->Val *= Right->Val;
397 for (I = 0; I < ED->SymCount; ++I) {
398 ED->SymRef[I].Count *= Right->Val;
399 }
400 for (I = 0; I < ED->SecCount; ++I) {
401 ED->SecRef[I].Count *= Right->Val;
402 }
403 ED_MergeAddrSize (ED, Right);
404}
405
406
407
408static void ED_Neg (ExprDesc* D)
409/* Negate an expression */
410{
411 D->Val = -D->Val;
412 ED_NegRefs (D);
413}
414
415
416
417static 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.
420*/
421{
422 /* Delete old data */
423 ED_Done (To);
424
425 /* Move the data */
426 *To = *From;
427
428 /* Cleanup From */
429 ED_Init (From);
430}
431
432
433
434/*****************************************************************************/
435/* Code */
436/*****************************************************************************/
437
438
439
440static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
441/* Study an expression tree and place the contents into D */
442
443
444
445static unsigned char GetConstAddrSize (long Val)
446/* Get the address size of a constant */
447{
448 if ((Val & ~0xFFL) == 0) {
449 return ADDR_SIZE_ZP;
450 } else if ((Val & ~0xFFFFL) == 0) {
451 return ADDR_SIZE_ABS;
452 } else if ((Val & ~0xFFFFFFL) == 0) {
453 return ADDR_SIZE_FAR;
454 } else {
455 return ADDR_SIZE_LONG;
456 }
457}
458
459
460
461static 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.
468*/
469{
470 ExprDesc Right;
471
472 /* Study the left side of the expression */
473 StudyExprInternal (Expr->Left, D);
474
475 /* Study the right side of the expression */
476 ED_Init (&Right);
477 StudyExprInternal (Expr->Right, &Right);
478
479 /* Check if we can handle the operation */
480 if (ED_IsConst (D) && ED_IsConst (&Right)) {
481
482 /* Remember the constant value from Right */
483 D->Right = Right.Val;
484
485 } else {
486
487 /* Cannot evaluate */
488 ED_Invalidate (D);
489
490 /* Merge references and update address size */
491 ED_MergeRefs (D, &Right);
492 ED_MergeAddrSize (D, &Right);
493
494 }
495
496 /* Cleanup Right */
497 ED_Done (&Right);
498}
499
500
501
502static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
503/* Study a literal expression node */
504{
505 /* This one is easy */
506 D->Val = Expr->V.IVal;
507 D->AddrSize = GetConstAddrSize (D->Val);
508}
509
510
511
512static void StudySymbol (ExprNode* Expr, ExprDesc* D)
513/* Study a symbol expression node */
514{
515 /* Get the symbol from the expression */
516 SymEntry* Sym = Expr->V.Sym;
517
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.
522 */
523 if (SymHasExpr (Sym)) {
524
525 if (SymHasUserMark (Sym)) {
526 LIError (&Sym->DefLines,
527 "Circular reference in definition of symbol '%m%p'",
528 GetSymName (Sym));
529 ED_SetError (D);
530 } else {
531
532 unsigned char AddrSize;
533
534 /* Mark the symbol and study its associated expression */
535 SymMarkUser (Sym);
536 StudyExprInternal (GetSymExpr (Sym), D);
537 SymUnmarkUser (Sym);
538
539 /* If requested and if the expression is valid, dump it */
540 if (Debug > 0 && !ED_HasError (D)) {
541 DumpExpr (Expr, SymResolve);
542 }
543
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.
547 */
548 AddrSize = GetSymAddrSize (Sym);
549 if (AddrSize != ADDR_SIZE_DEFAULT) {
550 D->AddrSize = AddrSize;
551 }
552 }
553
554 } else if (SymIsImport (Sym)) {
555
556 /* The symbol is an import. Track the symbols used and update the
557 ** address size.
558 */
559 ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
560 ++SymRef->Count;
561 ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
562
563 } else {
564
565 unsigned char AddrSize;
566 SymTable* Parent;
567
568 /* The symbol is undefined. Track symbol usage but set the "too
569 ** complex" flag, since we cannot evaluate the final result.
570 */
571 ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
572 ++SymRef->Count;
573 ED_Invalidate (D);
574
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.
579 */
580 AddrSize = GetSymAddrSize (Sym);
581 Parent = GetSymParentScope (Sym);
582 if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
583 SymEntry* H = SymFindAny (Parent, GetSymName (Sym));
584 if (H) {
585 AddrSize = GetSymAddrSize (H);
586 if (AddrSize != ADDR_SIZE_DEFAULT) {
587 D->AddrSize = AddrSize;
588 }
589 }
590 } else {
591 D->AddrSize = AddrSize;
592 }
593 }
594}
595
596
597
598static void StudySection (ExprNode* Expr, ExprDesc* D)
599/* Study a section expression node */
600{
601 /* Get the section reference */
602 ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SecNum);
603
604 /* Update the data and the address size */
605 ++SecRef->Count;
606 ED_UpdateAddrSize (D, GetSegAddrSize (SecRef->Ref));
607}
608
609
610
611static void StudyULabel (ExprNode* Expr, ExprDesc* D)
612/* Study an unnamed label expression node */
613{
614 /* If we can resolve the label, study the expression associated with it,
615 ** otherwise mark the expression as too complex to evaluate.
616 */
617 if (ULabCanResolve ()) {
618 /* We can resolve the label */
619 StudyExprInternal (ULabResolve (Expr->V.IVal), D);
620 } else {
621 ED_Invalidate (D);
622 }
623}
624
625
626
627static void StudyPlus (ExprNode* Expr, ExprDesc* D)
628/* Study an EXPR_PLUS binary expression node */
629{
630 ExprDesc Right;
631
632 /* Study the left side of the expression */
633 StudyExprInternal (Expr->Left, D);
634
635 /* Study the right side of the expression */
636 ED_Init (&Right);
637 StudyExprInternal (Expr->Right, &Right);
638
639 /* Check if we can handle the operation */
640 if (ED_IsValid (D) && ED_IsValid (&Right)) {
641
642 /* Add both */
643 ED_Add (D, &Right);
644
645 } else {
646
647 /* Cannot evaluate */
648 ED_Invalidate (D);
649
650 /* Merge references and update address size */
651 ED_MergeRefs (D, &Right);
652 ED_MergeAddrSize (D, &Right);
653
654 }
655
656 /* Done */
657 ED_Done (&Right);
658}
659
660
661
662static void StudyMinus (ExprNode* Expr, ExprDesc* D)
663/* Study an EXPR_MINUS binary expression node */
664{
665 ExprDesc Right;
666
667 /* Study the left side of the expression */
668 StudyExprInternal (Expr->Left, D);
669
670 /* Study the right side of the expression */
671 ED_Init (&Right);
672 StudyExprInternal (Expr->Right, &Right);
673
674 /* Check if we can handle the operation */
675 if (ED_IsValid (D) && ED_IsValid (&Right)) {
676
677 /* Subtract both */
678 ED_Sub (D, &Right);
679
680 } else {
681
682 /* Cannot evaluate */
683 ED_Invalidate (D);
684
685 /* Merge references and update address size */
686 ED_MergeRefs (D, &Right);
687 ED_MergeAddrSize (D, &Right);
688
689 }
690
691 /* Done */
692 ED_Done (&Right);
693}
694
695
696
697static void StudyMul (ExprNode* Expr, ExprDesc* D)
698/* Study an EXPR_MUL binary expression node */
699{
700 ExprDesc Right;
701
702 /* Study the left side of the expression */
703 StudyExprInternal (Expr->Left, D);
704
705 /* Study the right side of the expression */
706 ED_Init (&Right);
707 StudyExprInternal (Expr->Right, &Right);
708
709 /* We can handle the operation if at least one of both operands is const
710 ** and the other one is valid.
711 */
712 if (ED_IsConst (D) && ED_IsValid (&Right)) {
713
714 /* Multiplicate both, result goes into Right */
715 ED_Mul (&Right, D);
716
717 /* Move result into D */
718 ED_Move (&Right, D);
719
720 } else if (ED_IsConst (&Right) && ED_IsValid (D)) {
721
722 /* Multiplicate both */
723 ED_Mul (D, &Right);
724
725 } else {
726
727 /* Cannot handle this operation */
728 ED_Invalidate (D);
729
730 }
731
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);
736 }
737
738 /* Done */
739 ED_Done (&Right);
740}
741
742
743
744static void StudyDiv (ExprNode* Expr, ExprDesc* D)
745/* Study an EXPR_DIV binary expression node */
746{
747 /* Use helper function */
748 StudyBinaryExpr (Expr, D);
749
750 /* If the result is valid, apply the operation */
751 if (ED_IsValid (D)) {
752 if (D->Right == 0) {
753 Error ("Division by zero");
754 ED_SetError (D);
755 } else {
756 D->Val /= D->Right;
757 }
758 }
759}
760
761
762
763static void StudyMod (ExprNode* Expr, ExprDesc* D)
764/* Study an EXPR_MOD binary expression node */
765{
766 /* Use helper function */
767 StudyBinaryExpr (Expr, D);
768
769 /* If the result is valid, apply the operation */
770 if (ED_IsValid (D)) {
771 if (D->Right == 0) {
772 Error ("Modulo operation with zero");
773 ED_SetError (D);
774 } else {
775 D->Val %= D->Right;
776 }
777 }
778}
779
780
781
782static void StudyOr (ExprNode* Expr, ExprDesc* D)
783/* Study an EXPR_OR binary expression node */
784{
785 /* Use helper function */
786 StudyBinaryExpr (Expr, D);
787
788 /* If the result is valid, apply the operation */
789 if (ED_IsValid (D)) {
790 D->Val |= D->Right;
791 }
792}
793
794
795
796static void StudyXor (ExprNode* Expr, ExprDesc* D)
797/* Study an EXPR_XOR binary expression node */
798{
799 /* Use helper function */
800 StudyBinaryExpr (Expr, D);
801
802 /* If the result is valid, apply the operation */
803 if (ED_IsValid (D)) {
804 D->Val ^= D->Right;
805 }
806}
807
808
809
810static void StudyAnd (ExprNode* Expr, ExprDesc* D)
811/* Study an EXPR_AND binary expression node */
812{
813 /* Use helper function */
814 StudyBinaryExpr (Expr, D);
815
816 /* If the result is valid, apply the operation */
817 if (ED_IsValid (D)) {
818 D->Val &= D->Right;
819 }
820}
821
822
823
824static void StudyShl (ExprNode* Expr, ExprDesc* D)
825/* Study an EXPR_SHL binary expression node */
826{
827 /* Use helper function */
828 StudyBinaryExpr (Expr, D);
829
830 /* If the result is valid, apply the operation */
831 if (ED_IsValid (D)) {
832 D->Val = shl_l (D->Val, D->Right);
833 }
834}
835
836
837
838static void StudyShr (ExprNode* Expr, ExprDesc* D)
839/* Study an EXPR_SHR binary expression node */
840{
841 /* Use helper function */
842 StudyBinaryExpr (Expr, D);
843
844 /* If the result is valid, apply the operation */
845 if (ED_IsValid (D)) {
846 D->Val = shr_l (D->Val, D->Right);
847 }
848}
849
850
851
852static void StudyEQ (ExprNode* Expr, ExprDesc* D)
853/* Study an EXPR_EQ binary expression node */
854{
855 /* Use helper function */
856 StudyBinaryExpr (Expr, D);
857
858 /* If the result is valid, apply the operation */
859 if (ED_IsValid (D)) {
860 D->Val = (D->Val == D->Right);
861 }
862
863 /* In any case, the result is 0 or 1 */
864 D->AddrSize = ADDR_SIZE_ZP;
865}
866
867
868
869static void StudyNE (ExprNode* Expr, ExprDesc* D)
870/* Study an EXPR_NE binary expression node */
871{
872 /* Use helper function */
873 StudyBinaryExpr (Expr, D);
874
875 /* If the result is valid, apply the operation */
876 if (ED_IsValid (D)) {
877 D->Val = (D->Val != D->Right);
878 }
879
880 /* In any case, the result is 0 or 1 */
881 D->AddrSize = ADDR_SIZE_ZP;
882}
883
884
885
886static void StudyLT (ExprNode* Expr, ExprDesc* D)
887/* Study an EXPR_LT binary expression node */
888{
889 /* Use helper function */
890 StudyBinaryExpr (Expr, D);
891
892 /* If the result is valid, apply the operation */
893 if (ED_IsValid (D)) {
894 D->Val = (D->Val < D->Right);
895 }
896
897 /* In any case, the result is 0 or 1 */
898 D->AddrSize = ADDR_SIZE_ZP;
899}
900
901
902
903static void StudyGT (ExprNode* Expr, ExprDesc* D)
904/* Study an EXPR_GT binary expression node */
905{
906 /* Use helper function */
907 StudyBinaryExpr (Expr, D);
908
909 /* If the result is valid, apply the operation */
910 if (ED_IsValid (D)) {
911 D->Val = (D->Val > D->Right);
912 }
913
914 /* In any case, the result is 0 or 1 */
915 D->AddrSize = ADDR_SIZE_ZP;
916}
917
918
919
920static void StudyLE (ExprNode* Expr, ExprDesc* D)
921/* Study an EXPR_LE binary expression node */
922{
923 /* Use helper function */
924 StudyBinaryExpr (Expr, D);
925
926 /* If the result is valid, apply the operation */
927 if (ED_IsValid (D)) {
928 D->Val = (D->Val <= D->Right);
929 }
930
931 /* In any case, the result is 0 or 1 */
932 D->AddrSize = ADDR_SIZE_ZP;
933}
934
935
936
937static void StudyGE (ExprNode* Expr, ExprDesc* D)
938/* Study an EXPR_GE binary expression node */
939{
940 /* Use helper function */
941 StudyBinaryExpr (Expr, D);
942
943 /* If the result is valid, apply the operation */
944 if (ED_IsValid (D)) {
945 D->Val = (D->Val >= D->Right);
946 }
947
948 /* In any case, the result is 0 or 1 */
949 D->AddrSize = ADDR_SIZE_ZP;
950}
951
952
953
954static void StudyBoolAnd (ExprNode* Expr, ExprDesc* D)
955/* Study an EXPR_BOOLAND binary expression node */
956{
957 StudyExprInternal (Expr->Left, D);
958 if (ED_IsConst (D)) {
959 if (D->Val != 0) { /* Shortcut op */
960 ED_Done (D);
961 ED_Init (D);
962 StudyExprInternal (Expr->Right, D);
963 if (ED_IsConst (D)) {
964 D->Val = (D->Val != 0);
965 } else {
966 ED_Invalidate (D);
967 }
968 }
969 } else {
970 ED_Invalidate (D);
971 }
972
973 /* In any case, the result is 0 or 1 */
974 D->AddrSize = ADDR_SIZE_ZP;
975}
976
977
978
979static void StudyBoolOr (ExprNode* Expr, ExprDesc* D)
980/* Study an EXPR_BOOLOR binary expression node */
981{
982 StudyExprInternal (Expr->Left, D);
983 if (ED_IsConst (D)) {
984 if (D->Val == 0) { /* Shortcut op */
985 ED_Done (D);
986 ED_Init (D);
987 StudyExprInternal (Expr->Right, D);
988 if (ED_IsConst (D)) {
989 D->Val = (D->Val != 0);
990 } else {
991 ED_Invalidate (D);
992 }
993 } else {
994 D->Val = 1;
995 }
996 } else {
997 ED_Invalidate (D);
998 }
999
1000 /* In any case, the result is 0 or 1 */
1001 D->AddrSize = ADDR_SIZE_ZP;
1002}
1003
1004
1005
1006static void StudyBoolXor (ExprNode* Expr, ExprDesc* D)
1007/* Study an EXPR_BOOLXOR binary expression node */
1008{
1009 /* Use helper function */
1010 StudyBinaryExpr (Expr, D);
1011
1012 /* If the result is valid, apply the operation */
1013 if (ED_IsValid (D)) {
1014 D->Val = (D->Val != 0) ^ (D->Right != 0);
1015 }
1016
1017 /* In any case, the result is 0 or 1 */
1018 D->AddrSize = ADDR_SIZE_ZP;
1019}
1020
1021
1022
1023static void StudyMax (ExprNode* Expr, ExprDesc* D)
1024/* Study an MAX binary expression node */
1025{
1026 /* Use helper function */
1027 StudyBinaryExpr (Expr, D);
1028
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;
1032 }
1033}
1034
1035
1036
1037static void StudyMin (ExprNode* Expr, ExprDesc* D)
1038/* Study an MIN binary expression node */
1039{
1040 /* Use helper function */
1041 StudyBinaryExpr (Expr, D);
1042
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;
1046 }
1047}
1048
1049
1050
1051static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
1052/* Study an EXPR_UNARY_MINUS expression node */
1053{
1054 /* Study the expression */
1055 StudyExprInternal (Expr->Left, D);
1056
1057 /* If it is valid, negate it */
1058 if (ED_IsValid (D)) {
1059 ED_Neg (D);
1060 }
1061}
1062
1063
1064
1065static void StudyNot (ExprNode* Expr, ExprDesc* D)
1066/* Study an EXPR_NOT expression node */
1067{
1068 /* Study the expression */
1069 StudyExprInternal (Expr->Left, D);
1070
1071 /* We can handle only const expressions */
1072 if (ED_IsConst (D)) {
1073 D->Val = ~D->Val;
1074 } else {
1075 ED_Invalidate (D);
1076 }
1077}
1078
1079
1080
1081static void StudySwap (ExprNode* Expr, ExprDesc* D)
1082/* Study an EXPR_SWAP expression node */
1083{
1084 /* Study the expression */
1085 StudyExprInternal (Expr->Left, D);
1086
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);
1090 } else {
1091 ED_Invalidate (D);
1092 }
1093}
1094
1095
1096
1097static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
1098/* Study an EXPR_BOOLNOT expression node */
1099{
1100 /* Study the expression */
1101 StudyExprInternal (Expr->Left, D);
1102
1103 /* We can handle only const expressions */
1104 if (ED_IsConst (D)) {
1105 D->Val = (D->Val == 0);
1106 } else {
1107 ED_Invalidate (D);
1108 }
1109
1110 /* In any case, the result is 0 or 1 */
1111 D->AddrSize = ADDR_SIZE_ZP;
1112}
1113
1114
1115
1116static void StudyBank (ExprNode* Expr, ExprDesc* D)
1117/* Study an EXPR_BANK expression node */
1118{
1119 /* Study the expression extracting section references */
1120 StudyExprInternal (Expr->Left, D);
1121
1122 /* The expression is always linker evaluated, so invalidate it */
1123 ED_Invalidate (D);
1124}
1125
1126
1127
1128static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
1129/* Study an EXPR_BYTE0 expression node */
1130{
1131 /* Study the expression */
1132 StudyExprInternal (Expr->Left, D);
1133
1134 /* We can handle only const expressions */
1135 if (ED_IsConst (D)) {
1136 D->Val = (D->Val & 0xFF);
1137 } else {
1138 ED_Invalidate (D);
1139 }
1140
1141 /* In any case, the result is a zero page expression */
1142 D->AddrSize = ADDR_SIZE_ZP;
1143}
1144
1145
1146
1147static void StudyByte1 (ExprNode* Expr, ExprDesc* D)
1148/* Study an EXPR_BYTE1 expression node */
1149{
1150 /* Study the expression */
1151 StudyExprInternal (Expr->Left, D);
1152
1153 /* We can handle only const expressions */
1154 if (ED_IsConst (D)) {
1155 D->Val = (D->Val >> 8) & 0xFF;
1156 } else {
1157 ED_Invalidate (D);
1158 }
1159
1160 /* In any case, the result is a zero page expression */
1161 D->AddrSize = ADDR_SIZE_ZP;
1162}
1163
1164
1165
1166static void StudyByte2 (ExprNode* Expr, ExprDesc* D)
1167/* Study an EXPR_BYTE2 expression node */
1168{
1169 /* Study the expression */
1170 StudyExprInternal (Expr->Left, D);
1171
1172 /* We can handle only const expressions */
1173 if (ED_IsConst (D)) {
1174 D->Val = (D->Val >> 16) & 0xFF;
1175 } else {
1176 ED_Invalidate (D);
1177 }
1178
1179 /* In any case, the result is a zero page expression */
1180 D->AddrSize = ADDR_SIZE_ZP;
1181}
1182
1183
1184
1185static void StudyByte3 (ExprNode* Expr, ExprDesc* D)
1186/* Study an EXPR_BYTE3 expression node */
1187{
1188 /* Study the expression */
1189 StudyExprInternal (Expr->Left, D);
1190
1191 /* We can handle only const expressions */
1192 if (ED_IsConst (D)) {
1193 D->Val = (D->Val >> 24) & 0xFF;
1194 } else {
1195 ED_Invalidate (D);
1196 }
1197
1198 /* In any case, the result is a zero page expression */
1199 D->AddrSize = ADDR_SIZE_ZP;
1200}
1201
1202
1203
1204static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
1205/* Study an EXPR_WORD0 expression node */
1206{
1207 /* Study the expression */
1208 StudyExprInternal (Expr->Left, D);
1209
1210 /* We can handle only const expressions */
1211 if (ED_IsConst (D)) {
1212 D->Val &= 0xFFFFL;
1213 } else {
1214 ED_Invalidate (D);
1215 }
1216
1217 /* In any case, the result is an absolute expression */
1218 D->AddrSize = ADDR_SIZE_ABS;
1219}
1220
1221
1222
1223static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
1224/* Study an EXPR_WORD1 expression node */
1225{
1226 /* Study the expression */
1227 StudyExprInternal (Expr->Left, D);
1228
1229 /* We can handle only const expressions */
1230 if (ED_IsConst (D)) {
1231 D->Val = (D->Val >> 16) & 0xFFFFL;
1232 } else {
1233 ED_Invalidate (D);
1234 }
1235
1236 /* In any case, the result is an absolute expression */
1237 D->AddrSize = ADDR_SIZE_ABS;
1238}
1239
1240
1241
1242static void StudyFarAddr (ExprNode* Expr, ExprDesc* D)
1243/* Study an EXPR_FARADDR expression node */
1244{
1245 /* Study the expression */
1246 StudyExprInternal (Expr->Left, D);
1247
1248 /* We can handle only const expressions */
1249 if (ED_IsConst (D)) {
1250 D->Val &= 0xFFFFFFL;
1251 } else {
1252 ED_Invalidate (D);
1253 }
1254
1255 /* In any case, the result is a far address */
1256 D->AddrSize = ADDR_SIZE_FAR;
1257}
1258
1259
1260
1261static void StudyDWord (ExprNode* Expr, ExprDesc* D)
1262/* Study an EXPR_DWORD expression node */
1263{
1264 /* Study the expression */
1265 StudyExprInternal (Expr->Left, D);
1266
1267 /* We can handle only const expressions */
1268 if (ED_IsConst (D)) {
1269 D->Val &= 0xFFFFFFFFL;
1270 } else {
1271 ED_Invalidate (D);
1272 }
1273
1274 /* In any case, the result is a long expression */
1275 D->AddrSize = ADDR_SIZE_LONG;
1276}
1277
1278
1279
1280static void StudyNearAddr (ExprNode* Expr, ExprDesc* D)
1281/* Study an EXPR_NEARADDR expression node */
1282{
1283 /* Study the expression */
1284 StudyExprInternal (Expr->Left, D);
1285
1286 /* We can handle only const expressions */
1287 if (!ED_IsConst (D)) {
1288 ED_Invalidate (D);
1289 }
1290
1291 /* Promote to absolute if smaller. */
1292 if (D->AddrSize < ADDR_SIZE_ABS)
1293 {
1294 D->AddrSize = ADDR_SIZE_ABS;
1295 }
1296}
1297
1298
1299
1300static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
1301/* Study an expression tree and place the contents into D */
1302{
1303 /* Study this expression node */
1304 switch (Expr->Op) {
1305
1306 case EXPR_LITERAL:
1307 StudyLiteral (Expr, D);
1308 break;
1309
1310 case EXPR_SYMBOL:
1311 StudySymbol (Expr, D);
1312 break;
1313
1314 case EXPR_SECTION:
1315 StudySection (Expr, D);
1316 break;
1317
1318 case EXPR_ULABEL:
1319 StudyULabel (Expr, D);
1320 break;
1321
1322 case EXPR_PLUS:
1323 StudyPlus (Expr, D);
1324 break;
1325
1326 case EXPR_MINUS:
1327 StudyMinus (Expr, D);
1328 break;
1329
1330 case EXPR_MUL:
1331 StudyMul (Expr, D);
1332 break;
1333
1334 case EXPR_DIV:
1335 StudyDiv (Expr, D);
1336 break;
1337
1338 case EXPR_MOD:
1339 StudyMod (Expr, D);
1340 break;
1341
1342 case EXPR_OR:
1343 StudyOr (Expr, D);
1344 break;
1345
1346 case EXPR_XOR:
1347 StudyXor (Expr, D);
1348 break;
1349
1350 case EXPR_AND:
1351 StudyAnd (Expr, D);
1352 break;
1353
1354 case EXPR_SHL:
1355 StudyShl (Expr, D);
1356 break;
1357
1358 case EXPR_SHR:
1359 StudyShr (Expr, D);
1360 break;
1361
1362 case EXPR_EQ:
1363 StudyEQ (Expr, D);
1364 break;
1365
1366 case EXPR_NE:
1367 StudyNE (Expr, D);
1368 break;
1369
1370 case EXPR_LT:
1371 StudyLT (Expr, D);
1372 break;
1373
1374 case EXPR_GT:
1375 StudyGT (Expr, D);
1376 break;
1377
1378 case EXPR_LE:
1379 StudyLE (Expr, D);
1380 break;
1381
1382 case EXPR_GE:
1383 StudyGE (Expr, D);
1384 break;
1385
1386 case EXPR_BOOLAND:
1387 StudyBoolAnd (Expr, D);
1388 break;
1389
1390 case EXPR_BOOLOR:
1391 StudyBoolOr (Expr, D);
1392 break;
1393
1394 case EXPR_BOOLXOR:
1395 StudyBoolXor (Expr, D);
1396 break;
1397
1398 case EXPR_MAX:
1399 StudyMax (Expr, D);
1400 break;
1401
1402 case EXPR_MIN:
1403 StudyMin (Expr, D);
1404 break;
1405
1406 case EXPR_UNARY_MINUS:
1407 StudyUnaryMinus (Expr, D);
1408 break;
1409
1410 case EXPR_NOT:
1411 StudyNot (Expr, D);
1412 break;
1413
1414 case EXPR_SWAP:
1415 StudySwap (Expr, D);
1416 break;
1417
1418 case EXPR_BOOLNOT:
1419 StudyBoolNot (Expr, D);
1420 break;
1421
1422 case EXPR_BANK:
1423 StudyBank (Expr, D);
1424 break;
1425
1426 case EXPR_BYTE0:
1427 StudyByte0 (Expr, D);
1428 break;
1429
1430 case EXPR_BYTE1:
1431 StudyByte1 (Expr, D);
1432 break;
1433
1434 case EXPR_BYTE2:
1435 StudyByte2 (Expr, D);
1436 break;
1437
1438 case EXPR_BYTE3:
1439 StudyByte3 (Expr, D);
1440 break;
1441
1442 case EXPR_WORD0:
1443 StudyWord0 (Expr, D);
1444 break;
1445
1446 case EXPR_WORD1:
1447 StudyWord1 (Expr, D);
1448 break;
1449
1450 case EXPR_FARADDR:
1451 StudyFarAddr (Expr, D);
1452 break;
1453
1454 case EXPR_DWORD:
1455 StudyDWord (Expr, D);
1456 break;
1457
1458 case EXPR_NEARADDR:
1459 StudyNearAddr (Expr, D);
1460 break;
1461
1462 default:
1463 Internal ("Unknown Op type: %u", Expr->Op);
1464 break;
1465 }
1466}
1467
1468
1469
1470void StudyExpr (ExprNode* Expr, ExprDesc* D)
1471/* Study an expression tree and place the contents into D */
1472{
1473 unsigned I, J;
1474
1475 /* Call the internal function */
1476 StudyExprInternal (Expr, D);
1477
1478 /* Remove symbol references with count zero */
1479 I = J = 0;
1480 while (I < D->SymCount) {
1481 if (D->SymRef[I].Count == 0) {
1482 /* Delete the entry */
1483 --D->SymCount;
1484 memmove (D->SymRef + I, D->SymRef + I + 1,
1485 (D->SymCount - I) * sizeof (D->SymRef[0]));
1486 } else {
1487 /* Next entry */
1488 ++I;
1489 }
1490 }
1491
1492 /* Remove section references with count zero */
1493 I = 0;
1494 while (I < D->SecCount) {
1495 if (D->SecRef[I].Count == 0) {
1496 /* Delete the entry */
1497 --D->SecCount;
1498 memmove (D->SecRef + I, D->SecRef + I + 1,
1499 (D->SecCount - I) * sizeof (D->SecRef[0]));
1500 } else {
1501 /* Next entry */
1502 ++I;
1503 }
1504 }
1505
1506 /* If we don't have an address size, assign one if the expression is a
1507 ** constant.
1508 */
1509 if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
1510 D->AddrSize = GetConstAddrSize (D->Val);
1511 }
1512
1513 /* If the expression is valid, throw away the address size and recalculate
1514 ** it using the data we have. This is more exact than the on-the-fly
1515 ** calculation done when evaluating the tree, because symbols may have
1516 ** been removed from the expression, and the final numeric value is now
1517 ** known.
1518 */
1519 if (ED_IsValid (D)) {
1520 unsigned char AddrSize;
1521
1522 /* If there are symbols or sections, use the largest one. If the
1523 ** expression resolves to a const, use the address size of the value.
1524 */
1525 if (D->SymCount > 0 || D->SecCount > 0) {
1526
1527 D->AddrSize = ADDR_SIZE_DEFAULT;
1528
1529 for (I = 0; I < D->SymCount; ++I) {
1530 const SymEntry* Sym = D->SymRef[I].Ref;
1531 AddrSize = GetSymAddrSize (Sym);
1532 if (AddrSize > D->AddrSize) {
1533 D->AddrSize = AddrSize;
1534 }
1535 }
1536
1537 for (I = 0; I < D->SecCount; ++I) {
1538 unsigned SegNum = D->SecRef[0].Ref;
1539 AddrSize = GetSegAddrSize (SegNum);
1540 if (AddrSize > D->AddrSize) {
1541 D->AddrSize = AddrSize;
1542 }
1543 }
1544
1545 } else {
1546 AddrSize = GetConstAddrSize (D->Val);
1547 if (AddrSize > D->AddrSize) {
1548 D->AddrSize = AddrSize;
1549 }
1550 }
1551 }
1552
1553#if 0
1554 /* Debug code */
1555 printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
1556 printf ("Value: %08lX\n", D->Val);
1557 if (!ED_IsValid (D)) {
1558 printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
1559 } else {
1560 printf ("Valid: %s\n", AddrSizeToStr (D->AddrSize));
1561 }
1562 printf ("%u symbols:\n", D->SymCount);
1563 printf ("%u sections:\n", D->SecCount);
1564#endif
1565}
1566