]> git.sur5r.net Git - cc65/blob - src/ca65/studyexpr.c
New module strstack
[cc65] / src / ca65 / studyexpr.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                studyexpr.c                                */
4 /*                                                                           */
5 /*                         Study an expression tree                          */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2003      Ullrich von Bassewitz                                       */
10 /*               Römerstraße 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 "print.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
59 ExprDesc* 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
76 void ED_Done (ExprDesc* ED)
77 /* Delete allocated memory for an ExprDesc. */
78 {
79     xfree (ED->SymRef);
80     xfree (ED->SecRef);
81 }
82
83
84
85 int 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
108 static int ED_IsValid (const ExprDesc* D)
109 /* Return true if the expression is valid, that is, the TOO_COMPLEX flag is
110  * not set
111  */
112 {
113     return ((D->Flags & ED_TOO_COMPLEX) == 0);
114 }
115
116
117
118 static void ED_Invalidate (ExprDesc* D)
119 /* Set the TOO_COMPLEX flag for D */
120 {
121     D->Flags |= ED_TOO_COMPLEX;
122 }
123
124
125
126 static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
127 /* Update the address size of the expression */
128 {
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;
133         }
134     } else {
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;
139             }
140         }
141     }
142 }
143
144
145
146 static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
147 /* Merge the address sizes of two expressions into ED */
148 {
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.
152          */
153         if (ED_IsValid (ED)) {
154             ED->AddrSize = Right->AddrSize;
155         }
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.
159          */
160         if (!ED_IsValid (Right)) {
161             ED->AddrSize = Right->AddrSize;
162         }
163     } else {
164         /* Neither ED nor Right has a default address size, use the larger of
165          * the two.
166          */
167         if (Right->AddrSize > ED->AddrSize) {
168             ED->AddrSize = Right->AddrSize;
169         }
170     }
171 }
172
173
174
175 static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
176 /* Find a symbol reference and return it. Return NULL if the reference does
177  * not exist.
178  */
179 {
180     unsigned I;
181     ED_SymRef* SymRef;
182     for (I = 0, SymRef = ED->SymRef; I < ED->SymCount; ++I, ++SymRef) {
183         if (SymRef->Ref == Sym) {
184             return SymRef;
185         }
186     }
187     return 0;
188 }
189
190
191
192 static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
193 /* Find a section reference and return it. Return NULL if the reference does
194  * not exist.
195  */
196 {
197     unsigned I;
198     ED_SecRef* SecRef;
199     for (I = 0, SecRef = ED->SecRef; I < ED->SecCount; ++I, ++SecRef) {
200         if (SecRef->Ref == Sec) {
201             return SecRef;
202         }
203     }
204     return 0;
205 }
206
207
208
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.
212  */
213 {
214     ED_SymRef* SymRef;
215
216     /* Make sure we have enough SymRef slots */
217     if (ED->SymCount >= ED->SymLimit) {
218         ED->SymLimit *= 2;
219         if (ED->SymLimit == 0) {
220             ED->SymLimit = 2;
221         }
222         ED->SymRef = xrealloc (ED->SymRef, ED->SymLimit * sizeof (ED->SymRef[0]));
223     }
224
225     /* Allocate a new slot */
226     SymRef = ED->SymRef + ED->SymCount++;
227
228     /* Initialize the new struct and return it */
229     SymRef->Count = 1;
230     SymRef->Ref   = Sym;
231     return SymRef;
232 }
233
234
235
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.
239  */
240 {
241     ED_SecRef* SecRef;
242
243     /* Make sure we have enough SecRef slots */
244     if (ED->SecCount >= ED->SecLimit) {
245         ED->SecLimit *= 2;
246         if (ED->SecLimit == 0) {
247             ED->SecLimit = 2;
248         }
249         ED->SecRef = xrealloc (ED->SecRef, ED->SecLimit * sizeof (ED->SecRef[0]));
250     }
251
252     /* Allocate a new slot */
253     SecRef = ED->SecRef + ED->SecCount++;
254
255     /* Initialize the new struct and return it */
256     SecRef->Count = 0;
257     SecRef->Ref   = Sec;
258     return SecRef;
259 }
260
261
262
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.
266  */
267 {
268     ED_SymRef* SymRef = ED_FindSymRef (ED, Sym);
269     if (SymRef == 0) {
270         SymRef = ED_AllocSymRef (ED, Sym);
271     }
272     return SymRef;
273 }
274
275
276
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.
280  */
281 {
282     ED_SecRef* SecRef = ED_FindSecRef (ED, Sec);
283     if (SecRef == 0) {
284         SecRef = ED_AllocSecRef (ED, Sec);
285     }
286     return SecRef;
287 }
288
289
290
291 static void ED_MergeSymRefs (ExprDesc* ED, const ExprDesc* New)
292 /* Merge the symbol references from New into ED */
293 {
294     unsigned I;
295     for (I = 0; I < New->SymCount; ++I) {
296
297         /* Get a pointer to the SymRef entry */
298         const ED_SymRef* NewRef = New->SymRef + I;
299
300         /* Get the corresponding entry in ED */
301         ED_SymRef* SymRef = ED_GetSymRef (ED, NewRef->Ref);
302
303         /* Sum up the references */
304         SymRef->Count += NewRef->Count;
305     }
306 }
307
308
309
310 static void ED_MergeSecRefs (ExprDesc* ED, const ExprDesc* New)
311 /* Merge the section references from New into ED */
312 {
313     unsigned I;
314     for (I = 0; I < New->SecCount; ++I) {
315
316         /* Get a pointer to the SymRef entry */
317         const ED_SecRef* NewRef = New->SecRef + I;
318
319         /* Get the corresponding entry in ED */
320         ED_SecRef* SecRef = ED_GetSecRef (ED, NewRef->Ref);
321
322         /* Sum up the references */
323         SecRef->Count += NewRef->Count;
324     }
325 }
326
327
328
329 static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New)
330 /* Merge all references from New into ED */
331 {
332     ED_MergeSymRefs (ED, New);
333     ED_MergeSecRefs (ED, New);
334 }
335
336
337
338 static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
339 /* Calculate ED = ED + Right, update address size in ED */
340 {
341     ED->Val += Right->Val;
342     ED_MergeRefs (ED, Right);
343     ED_MergeAddrSize (ED, Right);
344 }
345
346
347
348 static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
349 /* Calculate ED = ED * Right, update address size in ED */
350 {
351     unsigned I;
352
353     ED->Val *= Right->Val;
354     for (I = 0; I < ED->SymCount; ++I) {
355         ED->SymRef[I].Count *= Right->Val;
356     }
357     for (I = 0; I < ED->SecCount; ++I) {
358         ED->SecRef[I].Count *= Right->Val;
359     }
360     ED_MergeAddrSize (ED, Right);
361 }
362
363
364
365 static void ED_Neg (ExprDesc* D)
366 /* Negate an expression */
367 {
368     unsigned I;
369
370     D->Val = -D->Val;
371     for (I = 0; I < D->SymCount; ++I) {
372         D->SymRef[I].Count = -D->SymRef[I].Count;
373     }
374     for (I = 0; I < D->SecCount; ++I) {
375         D->SecRef[I].Count = -D->SecRef[I].Count;
376     }
377 }
378
379
380
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.
384  */
385 {
386     /* Delete old data */
387     ED_Done (To);
388
389     /* Move the data */
390     *To = *From;
391
392     /* Cleanup From */
393     ED_Init (From);
394 }
395
396
397
398 /*****************************************************************************/
399 /*                                   Code                                    */
400 /*****************************************************************************/
401
402
403
404 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
405 /* Study an expression tree and place the contents into D */
406
407
408
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.
416  */
417 {
418     ExprDesc Right;
419
420     /* Study the left side of the expression */
421     StudyExprInternal (Expr->Left, D);
422
423     /* Study the right side of the expression */
424     ED_Init (&Right);
425     StudyExprInternal (Expr->Right, &Right);
426
427     /* Check if we can handle the operation */
428     if (ED_IsConst (D) && ED_IsConst (&Right)) {
429
430         /* Remember the constant value from Right */
431         D->Right = Right.Val;
432
433     } else {
434
435         /* Cannot evaluate */
436         ED_Invalidate (D);
437
438         /* Merge references and update address size */
439         ED_MergeRefs (D, &Right);
440         ED_MergeAddrSize (D, &Right);
441
442     }
443
444     /* Cleanup Right */
445     ED_Done (&Right);
446 }
447
448
449
450 static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
451 /* Study a literal expression node */
452 {
453
454     /* This one is easy */
455     D->Val = Expr->V.Val;
456 }
457
458
459
460 static void StudySymbol (ExprNode* Expr, ExprDesc* D)
461 /* Study a symbol expression node */
462 {
463     /* Get the symbol from the expression */
464     SymEntry* Sym = Expr->V.Sym;
465
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.
470      */
471     if (SymHasExpr (Sym)) {
472
473         if (SymHasUserMark (Sym)) {
474             if (Verbosity > 0) {
475                 DumpExpr (Expr, SymResolve);
476             }
477             PError (GetSymPos (Sym),
478                     "Circular reference in definition of symbol `%s'",
479                     GetSymName (Sym));
480             ED_Invalidate (D);
481         } else {
482
483             unsigned char AddrSize;
484
485             /* Mark the symbol and study its associated expression */
486             SymMarkUser (Sym);
487             StudyExprInternal (GetSymExpr (Sym), D);
488             SymUnmarkUser (Sym);
489
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.
493              */
494             AddrSize = GetSymAddrSize (Sym);
495             if (AddrSize != ADDR_SIZE_DEFAULT) {
496                 D->AddrSize = AddrSize;
497             }
498         }
499
500     } else if (SymIsImport (Sym)) {
501
502         /* The symbol is an import. Track the symbols used and update the
503          * address size.
504          */
505         ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
506         ++SymRef->Count;
507         ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
508
509     } else {
510
511         unsigned char AddrSize;
512         SymTable* Parent;
513
514         /* The symbol is undefined. Track symbol usage but set the "too
515          * complex" flag, since we cannot evaluate the final result.
516          */
517         ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
518         ++SymRef->Count;
519         ED_Invalidate (D);
520
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.
525          */
526         AddrSize = GetSymAddrSize (Sym);
527         Parent = GetSymParentScope (Sym);
528         if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
529             SymEntry* H = SymFindAny (Parent, GetSymName (Sym));
530             if (H) {
531                 AddrSize = GetSymAddrSize (H);
532                 if (AddrSize != ADDR_SIZE_DEFAULT) {
533                     D->AddrSize = AddrSize;
534                 }
535             }
536         } else {
537             D->AddrSize = AddrSize;
538         }
539     }
540 }
541
542
543
544 static void StudySection (ExprNode* Expr, ExprDesc* D)
545 /* Study a section expression node */
546 {
547     /* Get the section reference */
548     ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SegNum);
549
550     /* Update the data and the address size */
551     ++SecRef->Count;
552     ED_UpdateAddrSize (D, GetSegAddrSize (SecRef->Ref));
553 }
554
555
556
557 static void StudyULabel (ExprNode* Expr, ExprDesc* D)
558 /* Study an unnamed label expression node */
559 {
560     /* If we can resolve the label, study the expression associated with it,
561      * otherwise mark the expression as too complex to evaluate.
562      */
563     if (ULabCanResolve ()) {
564         /* We can resolve the label */
565         StudyExprInternal (ULabResolve (Expr->V.Val), D);
566     } else {
567         ED_Invalidate (D);
568     }
569 }
570
571
572
573 static void StudyPlus (ExprNode* Expr, ExprDesc* D)
574 /* Study an EXPR_PLUS binary expression node */
575 {
576     ExprDesc Right;
577
578     /* Study the left side of the expression */
579     StudyExprInternal (Expr->Left, D);
580
581     /* Study the right side of the expression */
582     ED_Init (&Right);
583     StudyExprInternal (Expr->Right, &Right);
584
585     /* Check if we can handle the operation */
586     if (ED_IsValid (D) || ED_IsValid (&Right)) {
587
588         /* Add both */
589         ED_Add (D, &Right);
590
591     } else {
592
593         /* Cannot evaluate */
594         ED_Invalidate (D);
595
596         /* Merge references and update address size */
597         ED_MergeRefs (D, &Right);
598         ED_MergeAddrSize (D, &Right);
599
600     }
601
602     /* Done */
603     ED_Done (&Right);
604 }
605
606
607
608 static void StudyMinus (ExprNode* Expr, ExprDesc* D)
609 /* Study an EXPR_MINUS binary expression node */
610 {
611     ExprDesc Right;
612
613     /* Study the left side of the expression */
614     StudyExprInternal (Expr->Left, D);
615
616     /* Study the right side of the expression */
617     ED_Init (&Right);
618     StudyExprInternal (Expr->Right, &Right);
619
620     /* Check if we can handle the operation */
621     if (ED_IsValid (D) || ED_IsValid (&Right)) {
622
623         /* Subtract both */
624         ED_Neg (&Right);
625         ED_Add (D, &Right);
626
627     } else {
628
629         /* Cannot evaluate */
630         ED_Invalidate (D);
631
632         /* Merge references and update address size */
633         ED_MergeRefs (D, &Right);
634         ED_MergeAddrSize (D, &Right);
635
636     }
637
638     /* Done */
639     ED_Done (&Right);
640 }
641
642
643
644 static void StudyMul (ExprNode* Expr, ExprDesc* D)
645 /* Study an EXPR_MUL binary expression node */
646 {
647     ExprDesc Right;
648
649     /* Study the left side of the expression */
650     StudyExprInternal (Expr->Left, D);
651
652     /* Study the right side of the expression */
653     ED_Init (&Right);
654     StudyExprInternal (Expr->Right, &Right);
655
656     /* We can handle the operation if at least one of both operands is const
657      * and the other one is valid.
658      */
659     if (ED_IsConst (D) && ED_IsValid (&Right)) {
660
661         /* Multiplicate both, result goes into Right */
662         ED_Mul (&Right, D);
663
664         /* Move result into D */
665         ED_Move (&Right, D);
666
667     } else if (ED_IsConst (&Right) && ED_IsValid (D)) {
668
669         /* Multiplicate both */
670         ED_Mul (D, &Right);
671
672     } else {
673
674         /* Cannot handle this operation */
675         ED_Invalidate (D);
676
677     }
678
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);
683     }
684
685     /* Done */
686     ED_Done (&Right);
687 }
688
689
690
691 static void StudyDiv (ExprNode* Expr, ExprDesc* D)
692 /* Study an EXPR_DIV binary expression node */
693 {
694     /* Use helper function */
695     StudyBinaryExpr (Expr, D);
696
697     /* If the result is valid, apply the operation */
698     if (ED_IsValid (D)) {
699         if (D->Right == 0) {
700             Error ("Division by zero");
701             ED_Invalidate (D);
702         } else {
703             D->Val /= D->Right;
704         }
705     }
706 }
707
708
709
710 static void StudyMod (ExprNode* Expr, ExprDesc* D)
711 /* Study an EXPR_MOD binary expression node */
712 {
713     /* Use helper function */
714     StudyBinaryExpr (Expr, D);
715
716     /* If the result is valid, apply the operation */
717     if (ED_IsValid (D)) {
718         if (D->Right == 0) {
719             Error ("Modulo operation with zero");
720             ED_Invalidate (D);
721         } else {
722             D->Val %= D->Right;
723         }
724     }
725 }
726
727
728
729 static void StudyOr (ExprNode* Expr, ExprDesc* D)
730 /* Study an EXPR_OR binary expression node */
731 {
732     /* Use helper function */
733     StudyBinaryExpr (Expr, D);
734
735     /* If the result is valid, apply the operation */
736     if (ED_IsValid (D)) {
737         D->Val |= D->Right;
738     }
739 }
740
741
742
743 static void StudyXor (ExprNode* Expr, ExprDesc* D)
744 /* Study an EXPR_XOR binary expression node */
745 {
746     /* Use helper function */
747     StudyBinaryExpr (Expr, D);
748
749     /* If the result is valid, apply the operation */
750     if (ED_IsValid (D)) {
751         D->Val ^= D->Right;
752     }
753 }
754
755
756
757 static void StudyAnd (ExprNode* Expr, ExprDesc* D)
758 /* Study an EXPR_AND binary expression node */
759 {
760     /* Use helper function */
761     StudyBinaryExpr (Expr, D);
762
763     /* If the result is valid, apply the operation */
764     if (ED_IsValid (D)) {
765         D->Val &= D->Right;
766     }
767 }
768
769
770
771 static void StudyShl (ExprNode* Expr, ExprDesc* D)
772 /* Study an EXPR_SHL binary expression node */
773 {
774     /* Use helper function */
775     StudyBinaryExpr (Expr, D);
776
777     /* If the result is valid, apply the operation */
778     if (ED_IsValid (D)) {
779         D->Val = shl_l (D->Val, D->Right);
780     }
781 }
782
783
784
785 static void StudyShr (ExprNode* Expr, ExprDesc* D)
786 /* Study an EXPR_SHR binary expression node */
787 {
788     /* Use helper function */
789     StudyBinaryExpr (Expr, D);
790
791     /* If the result is valid, apply the operation */
792     if (ED_IsValid (D)) {
793         D->Val = shr_l (D->Val, D->Right);
794     }
795 }
796
797
798
799 static void StudyEQ (ExprNode* Expr, ExprDesc* D)
800 /* Study an EXPR_EQ binary expression node */
801 {
802     /* Use helper function */
803     StudyBinaryExpr (Expr, D);
804
805     /* If the result is valid, apply the operation */
806     if (ED_IsValid (D)) {
807         D->Val = (D->Val == D->Right);
808     }
809
810     /* In any case, the result is 0 or 1 */
811     D->AddrSize = ADDR_SIZE_ZP;
812 }
813
814
815
816 static void StudyNE (ExprNode* Expr, ExprDesc* D)
817 /* Study an EXPR_NE binary expression node */
818 {
819     /* Use helper function */
820     StudyBinaryExpr (Expr, D);
821
822     /* If the result is valid, apply the operation */
823     if (ED_IsValid (D)) {
824         D->Val = (D->Val != D->Right);
825     }
826
827     /* In any case, the result is 0 or 1 */
828     D->AddrSize = ADDR_SIZE_ZP;
829 }
830
831
832
833 static void StudyLT (ExprNode* Expr, ExprDesc* D)
834 /* Study an EXPR_LT binary expression node */
835 {
836     /* Use helper function */
837     StudyBinaryExpr (Expr, D);
838
839     /* If the result is valid, apply the operation */
840     if (ED_IsValid (D)) {
841         D->Val = (D->Val < D->Right);
842     }
843
844     /* In any case, the result is 0 or 1 */
845     D->AddrSize = ADDR_SIZE_ZP;
846 }
847
848
849
850 static void StudyGT (ExprNode* Expr, ExprDesc* D)
851 /* Study an EXPR_GT binary expression node */
852 {
853     /* Use helper function */
854     StudyBinaryExpr (Expr, D);
855
856     /* If the result is valid, apply the operation */
857     if (ED_IsValid (D)) {
858         D->Val = (D->Val > D->Right);
859     }
860
861     /* In any case, the result is 0 or 1 */
862     D->AddrSize = ADDR_SIZE_ZP;
863 }
864
865
866
867 static void StudyLE (ExprNode* Expr, ExprDesc* D)
868 /* Study an EXPR_LE binary expression node */
869 {
870     /* Use helper function */
871     StudyBinaryExpr (Expr, D);
872
873     /* If the result is valid, apply the operation */
874     if (ED_IsValid (D)) {
875         D->Val = (D->Val <= D->Right);
876     }
877
878     /* In any case, the result is 0 or 1 */
879     D->AddrSize = ADDR_SIZE_ZP;
880 }
881
882
883
884 static void StudyGE (ExprNode* Expr, ExprDesc* D)
885 /* Study an EXPR_GE binary expression node */
886 {
887     /* Use helper function */
888     StudyBinaryExpr (Expr, D);
889
890     /* If the result is valid, apply the operation */
891     if (ED_IsValid (D)) {
892         D->Val = (D->Val >= D->Right);
893     }
894
895     /* In any case, the result is 0 or 1 */
896     D->AddrSize = ADDR_SIZE_ZP;
897 }
898
899
900
901 static void StudyBoolAnd (ExprNode* Expr, ExprDesc* D)
902 /* Study an EXPR_BOOLAND binary expression node */
903 {
904     StudyExprInternal (Expr->Left, D);
905     if (ED_IsConst (D)) {
906         if (D->Val != 0) {   /* Shortcut op */
907             ED_Done (D);
908             ED_Init (D);
909             StudyExprInternal (Expr->Right, D);
910             if (ED_IsConst (D)) {
911                 D->Val = (D->Val != 0);
912             } else {
913                 ED_Invalidate (D);
914             }
915         }
916     } else {
917         ED_Invalidate (D);
918     }
919
920     /* In any case, the result is 0 or 1 */
921     D->AddrSize = ADDR_SIZE_ZP;
922 }
923
924
925
926 static void StudyBoolOr (ExprNode* Expr, ExprDesc* D)
927 /* Study an EXPR_BOOLOR binary expression node */
928 {
929     StudyExprInternal (Expr->Left, D);
930     if (ED_IsConst (D)) {
931         if (D->Val == 0) {   /* Shortcut op */
932             ED_Done (D);
933             ED_Init (D);
934             StudyExprInternal (Expr->Right, D);
935             if (ED_IsConst (D)) {
936                 D->Val = (D->Val != 0);
937             } else {
938                 ED_Invalidate (D);
939             }
940         } else {
941             D->Val = 1;
942         }
943     } else {
944         ED_Invalidate (D);
945     }
946
947     /* In any case, the result is 0 or 1 */
948     D->AddrSize = ADDR_SIZE_ZP;
949 }
950
951
952
953 static void StudyBoolXor (ExprNode* Expr, ExprDesc* D)
954 /* Study an EXPR_BOOLXOR binary expression node */
955 {
956     /* Use helper function */
957     StudyBinaryExpr (Expr, D);
958
959     /* If the result is valid, apply the operation */
960     if (ED_IsValid (D)) {
961         D->Val = (D->Val != 0) ^ (D->Right != 0);
962     }
963
964     /* In any case, the result is 0 or 1 */
965     D->AddrSize = ADDR_SIZE_ZP;
966 }
967
968
969
970 static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
971 /* Study an EXPR_UNARY_MINUS expression node */
972 {
973     /* Study the expression */
974     StudyExprInternal (Expr->Left, D);
975
976     /* If it is valid, negate it */
977     if (ED_IsValid (D)) {
978         ED_Neg (D);
979     }
980 }
981
982
983
984 static void StudyNot (ExprNode* Expr, ExprDesc* D)
985 /* Study an EXPR_NOT expression node */
986 {
987     /* Study the expression */
988     StudyExprInternal (Expr->Left, D);
989
990     /* We can handle only const expressions */
991     if (ED_IsConst (D)) {
992         D->Val = ~D->Val;
993     } else {
994         ED_Invalidate (D);
995     }
996 }
997
998
999
1000 static void StudySwap (ExprNode* Expr, ExprDesc* D)
1001 /* Study an EXPR_SWAP expression node */
1002 {
1003     /* Study the expression */
1004     StudyExprInternal (Expr->Left, D);
1005
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);
1009     } else {
1010         ED_Invalidate (D);
1011     }
1012 }
1013
1014
1015
1016 static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
1017 /* Study an EXPR_BOOLNOT expression node */
1018 {
1019     /* Study the expression */
1020     StudyExprInternal (Expr->Left, D);
1021
1022     /* We can handle only const expressions */
1023     if (ED_IsConst (D)) {
1024         D->Val = (D->Val == 0);
1025     } else {
1026         ED_Invalidate (D);
1027     }
1028
1029     /* In any case, the result is 0 or 1 */
1030     D->AddrSize = ADDR_SIZE_ZP;
1031 }
1032
1033
1034
1035 static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
1036 /* Study an EXPR_BYTE0 expression node */
1037 {
1038     /* Study the expression */
1039     StudyExprInternal (Expr->Left, D);
1040
1041     /* We can handle only const expressions */
1042     if (ED_IsConst (D)) {
1043         D->Val = (D->Val & 0xFF);
1044     } else {
1045         ED_Invalidate (D);
1046     }
1047
1048     /* In any case, the result is a zero page expression */
1049     D->AddrSize = ADDR_SIZE_ZP;
1050 }
1051
1052
1053
1054 static void StudyByte1 (ExprNode* Expr, ExprDesc* D)
1055 /* Study an EXPR_BYTE1 expression node */
1056 {
1057     /* Study the expression */
1058     StudyExprInternal (Expr->Left, D);
1059
1060     /* We can handle only const expressions */
1061     if (ED_IsConst (D)) {
1062         D->Val = (D->Val >> 8) & 0xFF;
1063     } else {
1064         ED_Invalidate (D);
1065     }
1066
1067     /* In any case, the result is a zero page expression */
1068     D->AddrSize = ADDR_SIZE_ZP;
1069 }
1070
1071
1072
1073 static void StudyByte2 (ExprNode* Expr, ExprDesc* D)
1074 /* Study an EXPR_BYTE2 expression node */
1075 {
1076     /* Study the expression */
1077     StudyExprInternal (Expr->Left, D);
1078
1079     /* We can handle only const expressions */
1080     if (ED_IsConst (D)) {
1081         D->Val = (D->Val >> 16) & 0xFF;
1082     } else {
1083         ED_Invalidate (D);
1084     }
1085
1086     /* In any case, the result is a zero page expression */
1087     D->AddrSize = ADDR_SIZE_ZP;
1088 }
1089
1090
1091
1092 static void StudyByte3 (ExprNode* Expr, ExprDesc* D)
1093 /* Study an EXPR_BYTE3 expression node */
1094 {
1095     /* Study the expression */
1096     StudyExprInternal (Expr->Left, D);
1097
1098     /* We can handle only const expressions */
1099     if (ED_IsConst (D)) {
1100         D->Val = (D->Val >> 24) & 0xFF;
1101     } else {
1102         ED_Invalidate (D);
1103     }
1104
1105     /* In any case, the result is a zero page expression */
1106     D->AddrSize = ADDR_SIZE_ZP;
1107 }
1108
1109
1110
1111 static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
1112 /* Study an EXPR_WORD0 expression node */
1113 {
1114     /* Study the expression */
1115     StudyExprInternal (Expr->Left, D);
1116
1117     /* We can handle only const expressions */
1118     if (ED_IsConst (D)) {
1119         D->Val = (D->Val & 0xFFFFL);
1120     } else {
1121         ED_Invalidate (D);
1122     }
1123
1124     /* In any case, the result is an absolute expression */
1125     D->AddrSize = ADDR_SIZE_ABS;
1126 }
1127
1128
1129
1130 static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
1131 /* Study an EXPR_WORD1 expression node */
1132 {
1133     /* Study the expression */
1134     StudyExprInternal (Expr->Left, D);
1135
1136     /* We can handle only const expressions */
1137     if (ED_IsConst (D)) {
1138         D->Val = (D->Val >> 16) & 0xFFFFL;
1139     } else {
1140         ED_Invalidate (D);
1141     }
1142
1143     /* In any case, the result is an absolute expression */
1144     D->AddrSize = ADDR_SIZE_ABS;
1145 }
1146
1147
1148
1149 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
1150 /* Study an expression tree and place the contents into D */
1151 {
1152     /* Study this expression node */
1153     switch (Expr->Op) {
1154
1155         case EXPR_LITERAL:
1156             StudyLiteral (Expr, D);
1157             break;
1158
1159         case EXPR_SYMBOL:
1160             StudySymbol (Expr, D);
1161             break;
1162
1163         case EXPR_SECTION:
1164             StudySection (Expr, D);
1165             break;
1166
1167         case EXPR_ULABEL:
1168             StudyULabel (Expr, D);
1169             break;
1170
1171         case EXPR_PLUS:
1172             StudyPlus (Expr, D);
1173             break;
1174
1175         case EXPR_MINUS:
1176             StudyMinus (Expr, D);
1177             break;
1178
1179         case EXPR_MUL:
1180             StudyMul (Expr, D);
1181             break;
1182
1183         case EXPR_DIV:
1184             StudyDiv (Expr, D);
1185             break;
1186
1187         case EXPR_MOD:
1188             StudyMod (Expr, D);
1189             break;
1190
1191         case EXPR_OR:
1192             StudyOr (Expr, D);
1193             break;
1194
1195         case EXPR_XOR:
1196             StudyXor (Expr, D);
1197             break;
1198
1199         case EXPR_AND:
1200             StudyAnd (Expr, D);
1201             break;
1202
1203         case EXPR_SHL:
1204             StudyShl (Expr, D);
1205             break;
1206
1207         case EXPR_SHR:
1208             StudyShr (Expr, D);
1209             break;
1210
1211         case EXPR_EQ:
1212             StudyEQ (Expr, D);
1213             break;
1214
1215         case EXPR_NE:
1216             StudyNE (Expr, D);
1217             break;
1218
1219         case EXPR_LT:
1220             StudyLT (Expr, D);
1221             break;
1222
1223         case EXPR_GT:
1224             StudyGT (Expr, D);
1225             break;
1226
1227         case EXPR_LE:
1228             StudyLE (Expr, D);
1229             break;
1230
1231         case EXPR_GE:
1232             StudyGE (Expr, D);
1233             break;
1234
1235         case EXPR_BOOLAND:
1236             StudyBoolAnd (Expr, D);
1237             break;
1238
1239         case EXPR_BOOLOR:
1240             StudyBoolOr (Expr, D);
1241             break;
1242
1243         case EXPR_BOOLXOR:
1244             StudyBoolXor (Expr, D);
1245             break;
1246
1247         case EXPR_UNARY_MINUS:
1248             StudyUnaryMinus (Expr, D);
1249             break;
1250
1251         case EXPR_NOT:
1252             StudyNot (Expr, D);
1253             break;
1254
1255         case EXPR_SWAP:
1256             StudySwap (Expr, D);
1257             break;
1258
1259         case EXPR_BOOLNOT:
1260             StudyBoolNot (Expr, D);
1261             break;
1262
1263         case EXPR_BYTE0:
1264             StudyByte0 (Expr, D);
1265             break;
1266
1267         case EXPR_BYTE1:
1268             StudyByte1 (Expr, D);
1269             break;
1270
1271         case EXPR_BYTE2:
1272             StudyByte2 (Expr, D);
1273             break;
1274
1275         case EXPR_BYTE3:
1276             StudyByte3 (Expr, D);
1277             break;
1278
1279         case EXPR_WORD0:
1280             StudyWord0 (Expr, D);
1281             break;
1282
1283         case EXPR_WORD1:
1284             StudyWord1 (Expr, D);
1285             break;
1286
1287         default:
1288             Internal ("Unknown Op type: %u", Expr->Op);
1289             break;
1290     }
1291 }
1292
1293
1294
1295 void StudyExpr (ExprNode* Expr, ExprDesc* D)
1296 /* Study an expression tree and place the contents into D */
1297 {
1298     unsigned I;
1299
1300     /* Call the internal function */
1301     StudyExprInternal (Expr, D);
1302
1303     /* Remove symbol references with count zero */
1304     I = 0;
1305     while (I < D->SymCount) {
1306         if (D->SymRef[I].Count == 0) {
1307             /* Delete the entry */
1308             --D->SymCount;
1309             memmove (D->SymRef + I, D->SymRef + I + 1,
1310                      (D->SymCount - I) * sizeof (D->SymRef[0]));
1311         } else {
1312             /* Next entry */
1313             ++I;
1314         }
1315     }
1316
1317     /* Remove section references with count zero */
1318     I = 0;
1319     while (I < D->SecCount) {
1320         if (D->SecRef[I].Count == 0) {
1321             /* Delete the entry */
1322             --D->SecCount;
1323             memmove (D->SecRef + I, D->SecRef + I + 1,
1324                      (D->SecCount - I) * sizeof (D->SecRef[0]));
1325         } else {
1326             /* Next entry */
1327             ++I;
1328         }
1329     }
1330
1331     /* If we don't have an address size, assign one of the expression is a
1332      * constant.
1333      */
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;
1342             } else {
1343                 D->AddrSize = ADDR_SIZE_LONG;
1344             }
1345         }
1346     }
1347
1348 #if 0
1349     printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
1350     if (!ED_IsValid (D)) {
1351         printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
1352     } else {
1353         printf ("Valid:   %s\n", AddrSizeToStr (D->AddrSize));
1354         printf ("%u symbols:\n", D->SymCount);
1355         printf ("%u sections:\n", D->SecCount);
1356     }
1357 #endif
1358 }
1359
1360
1361