]> git.sur5r.net Git - cc65/blob - src/ca65/studyexpr.c
Fixed a problem with evaluation of the address size
[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 = 0;
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_NegRefs (ExprDesc* D)
339 /* Negate the references in ED */
340 {
341     unsigned I;
342     for (I = 0; I < D->SymCount; ++I) {
343         D->SymRef[I].Count = -D->SymRef[I].Count;
344     }
345     for (I = 0; I < D->SecCount; ++I) {
346         D->SecRef[I].Count = -D->SecRef[I].Count;
347     }
348 }
349
350
351
352 static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
353 /* Calculate ED = ED + Right, update address size in ED */
354 {
355     ED->Val += Right->Val;
356     ED_MergeRefs (ED, Right);
357     ED_MergeAddrSize (ED, Right);
358 }
359
360
361
362 static void ED_Sub (ExprDesc* ED, const ExprDesc* Right)
363 /* Calculate ED = ED - Right, update address size in ED */
364 {
365     ExprDesc D = *Right;        /* Temporary */
366     ED_NegRefs (&D);
367
368     ED->Val -= Right->Val;
369     ED_MergeRefs (ED, &D);      /* Merge negatives */
370     ED_MergeAddrSize (ED, Right);
371 }
372
373
374
375 static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
376 /* Calculate ED = ED * Right, update address size in ED */
377 {
378     unsigned I;
379
380     ED->Val *= Right->Val;
381     for (I = 0; I < ED->SymCount; ++I) {
382         ED->SymRef[I].Count *= Right->Val;
383     }
384     for (I = 0; I < ED->SecCount; ++I) {
385         ED->SecRef[I].Count *= Right->Val;
386     }
387     ED_MergeAddrSize (ED, Right);
388 }
389
390
391
392 static void ED_Neg (ExprDesc* D)
393 /* Negate an expression */
394 {
395     D->Val = -D->Val;
396     ED_NegRefs (D);
397 }
398
399
400
401 static void ED_Move (ExprDesc* From, ExprDesc* To)
402 /* Move the data from one ExprDesc to another. Old data is freed, and From
403  * is prepared to that ED_Done may be called safely.
404  */
405 {
406     /* Delete old data */
407     ED_Done (To);
408
409     /* Move the data */
410     *To = *From;
411
412     /* Cleanup From */
413     ED_Init (From);
414 }
415
416
417
418 /*****************************************************************************/
419 /*                                   Code                                    */
420 /*****************************************************************************/
421
422
423
424 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
425 /* Study an expression tree and place the contents into D */
426
427
428
429 static unsigned char GetConstAddrSize (long Val)
430 /* Get the address size of a constant */
431 {
432     if ((Val & ~0xFFL) == 0) {
433         return ADDR_SIZE_ZP;
434     } else if ((Val & ~0xFFFFL) == 0) {
435         return ADDR_SIZE_ABS;
436     } else if ((Val & ~0xFFFFFFL) == 0) {
437         return ADDR_SIZE_FAR;
438     } else {
439         return ADDR_SIZE_LONG;
440     }
441 }
442
443
444
445 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
446 /* Study a binary expression subtree. This is a helper function for StudyExpr
447  * used for operations that succeed when both operands are known and constant.
448  * It evaluates the two subtrees and checks if they are constant. If they
449  * aren't constant, it will set the TOO_COMPLEX flag, and merge references.
450  * Otherwise the first value is returned in D->Val, the second one in D->Right,
451  * so the actual operation can be done by the caller.
452  */
453 {
454     ExprDesc Right;
455
456     /* Study the left side of the expression */
457     StudyExprInternal (Expr->Left, D);
458
459     /* Study the right side of the expression */
460     ED_Init (&Right);
461     StudyExprInternal (Expr->Right, &Right);
462
463     /* Check if we can handle the operation */
464     if (ED_IsConst (D) && ED_IsConst (&Right)) {
465
466         /* Remember the constant value from Right */
467         D->Right = Right.Val;
468
469     } else {
470
471         /* Cannot evaluate */
472         ED_Invalidate (D);
473
474         /* Merge references and update address size */
475         ED_MergeRefs (D, &Right);
476         ED_MergeAddrSize (D, &Right);
477
478     }
479
480     /* Cleanup Right */
481     ED_Done (&Right);
482 }
483
484
485
486 static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
487 /* Study a literal expression node */
488 {
489     /* This one is easy */
490     D->Val      = Expr->V.Val;
491     D->AddrSize = GetConstAddrSize (D->Val);
492 }
493
494
495
496 static void StudySymbol (ExprNode* Expr, ExprDesc* D)
497 /* Study a symbol expression node */
498 {
499     /* Get the symbol from the expression */
500     SymEntry* Sym = Expr->V.Sym;
501
502     /* If the symbol is defined somewhere, it has an expression associated.
503      * In this case, just study the expression associated with the symbol,
504      * but mark the symbol so if we encounter it twice, we know that we have
505      * a circular reference.
506      */
507     if (SymHasExpr (Sym)) {
508
509         if (SymHasUserMark (Sym)) {
510             if (Verbosity > 0) {
511                 DumpExpr (Expr, SymResolve);
512             }
513             PError (GetSymPos (Sym),
514                     "Circular reference in definition of symbol `%s'",
515                     GetSymName (Sym));
516             ED_Invalidate (D);
517         } else {
518
519             unsigned char AddrSize;
520
521             /* Mark the symbol and study its associated expression */
522             SymMarkUser (Sym);
523             StudyExprInternal (GetSymExpr (Sym), D);
524             SymUnmarkUser (Sym);
525
526             /* If the symbol has an explicit address size, use it. This may
527              * lead to range errors later (maybe even in the linker stage), if
528              * the user lied about the address size, but for now we trust him.
529              */
530             AddrSize = GetSymAddrSize (Sym);
531             if (AddrSize != ADDR_SIZE_DEFAULT) {
532                 D->AddrSize = AddrSize;
533             }
534         }
535
536     } else if (SymIsImport (Sym)) {
537
538         /* The symbol is an import. Track the symbols used and update the
539          * address size.
540          */
541         ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
542         ++SymRef->Count;
543         ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
544
545     } else {
546
547         unsigned char AddrSize;
548         SymTable* Parent;
549
550         /* The symbol is undefined. Track symbol usage but set the "too
551          * complex" flag, since we cannot evaluate the final result.
552          */
553         ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
554         ++SymRef->Count;
555         ED_Invalidate (D);
556
557         /* Since the symbol may be a forward, and we may need a statement
558          * about the address size, check higher lexical levels for a symbol
559          * with the same name and use its address size if we find such a
560          * symbol which is defined.
561          */
562         AddrSize = GetSymAddrSize (Sym);
563         Parent = GetSymParentScope (Sym);
564         if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
565             SymEntry* H = SymFindAny (Parent, GetSymName (Sym));
566             if (H) {
567                 AddrSize = GetSymAddrSize (H);
568                 if (AddrSize != ADDR_SIZE_DEFAULT) {
569                     D->AddrSize = AddrSize;
570                 }
571             }
572         } else {
573             D->AddrSize = AddrSize;
574         }
575     }
576 }
577
578
579
580 static void StudySection (ExprNode* Expr, ExprDesc* D)
581 /* Study a section expression node */
582 {
583     /* Get the section reference */
584     ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SegNum);
585
586     /* Update the data and the address size */
587     ++SecRef->Count;
588     ED_UpdateAddrSize (D, GetSegAddrSize (SecRef->Ref));
589 }
590
591
592
593 static void StudyULabel (ExprNode* Expr, ExprDesc* D)
594 /* Study an unnamed label expression node */
595 {
596     /* If we can resolve the label, study the expression associated with it,
597      * otherwise mark the expression as too complex to evaluate.
598      */
599     if (ULabCanResolve ()) {
600         /* We can resolve the label */
601         StudyExprInternal (ULabResolve (Expr->V.Val), D);
602     } else {
603         ED_Invalidate (D);
604     }
605 }
606
607
608
609 static void StudyPlus (ExprNode* Expr, ExprDesc* D)
610 /* Study an EXPR_PLUS binary expression node */
611 {
612     ExprDesc Right;
613
614     /* Study the left side of the expression */
615     StudyExprInternal (Expr->Left, D);
616
617     /* Study the right side of the expression */
618     ED_Init (&Right);
619     StudyExprInternal (Expr->Right, &Right);
620
621     /* Check if we can handle the operation */
622     if (ED_IsValid (D) && ED_IsValid (&Right)) {
623
624         /* Add both */
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 StudyMinus (ExprNode* Expr, ExprDesc* D)
645 /* Study an EXPR_MINUS 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     /* Check if we can handle the operation */
657     if (ED_IsValid (D) && ED_IsValid (&Right)) {
658
659         /* Subtract both */
660         ED_Sub (D, &Right);
661
662     } else {
663
664         /* Cannot evaluate */
665         ED_Invalidate (D);
666
667         /* Merge references and update address size */
668         ED_MergeRefs (D, &Right);
669         ED_MergeAddrSize (D, &Right);
670
671     }
672
673     /* Done */
674     ED_Done (&Right);
675 }
676
677
678
679 static void StudyMul (ExprNode* Expr, ExprDesc* D)
680 /* Study an EXPR_MUL binary expression node */
681 {
682     ExprDesc Right;
683
684     /* Study the left side of the expression */
685     StudyExprInternal (Expr->Left, D);
686
687     /* Study the right side of the expression */
688     ED_Init (&Right);
689     StudyExprInternal (Expr->Right, &Right);
690
691     /* We can handle the operation if at least one of both operands is const
692      * and the other one is valid.
693      */
694     if (ED_IsConst (D) && ED_IsValid (&Right)) {
695
696         /* Multiplicate both, result goes into Right */
697         ED_Mul (&Right, D);
698
699         /* Move result into D */
700         ED_Move (&Right, D);
701
702     } else if (ED_IsConst (&Right) && ED_IsValid (D)) {
703
704         /* Multiplicate both */
705         ED_Mul (D, &Right);
706
707     } else {
708
709         /* Cannot handle this operation */
710         ED_Invalidate (D);
711
712     }
713
714     /* If we could not handle the op, merge references and update address size */
715     if (!ED_IsValid (D)) {
716         ED_MergeRefs (D, &Right);
717         ED_MergeAddrSize (D, &Right);
718     }
719
720     /* Done */
721     ED_Done (&Right);
722 }
723
724
725
726 static void StudyDiv (ExprNode* Expr, ExprDesc* D)
727 /* Study an EXPR_DIV binary expression node */
728 {
729     /* Use helper function */
730     StudyBinaryExpr (Expr, D);
731
732     /* If the result is valid, apply the operation */
733     if (ED_IsValid (D)) {
734         if (D->Right == 0) {
735             Error ("Division by zero");
736             ED_Invalidate (D);
737         } else {
738             D->Val /= D->Right;
739         }
740     }
741 }
742
743
744
745 static void StudyMod (ExprNode* Expr, ExprDesc* D)
746 /* Study an EXPR_MOD binary expression node */
747 {
748     /* Use helper function */
749     StudyBinaryExpr (Expr, D);
750
751     /* If the result is valid, apply the operation */
752     if (ED_IsValid (D)) {
753         if (D->Right == 0) {
754             Error ("Modulo operation with zero");
755             ED_Invalidate (D);
756         } else {
757             D->Val %= D->Right;
758         }
759     }
760 }
761
762
763
764 static void StudyOr (ExprNode* Expr, ExprDesc* D)
765 /* Study an EXPR_OR binary expression node */
766 {
767     /* Use helper function */
768     StudyBinaryExpr (Expr, D);
769
770     /* If the result is valid, apply the operation */
771     if (ED_IsValid (D)) {
772         D->Val |= D->Right;
773     }
774 }
775
776
777
778 static void StudyXor (ExprNode* Expr, ExprDesc* D)
779 /* Study an EXPR_XOR binary expression node */
780 {
781     /* Use helper function */
782     StudyBinaryExpr (Expr, D);
783
784     /* If the result is valid, apply the operation */
785     if (ED_IsValid (D)) {
786         D->Val ^= D->Right;
787     }
788 }
789
790
791
792 static void StudyAnd (ExprNode* Expr, ExprDesc* D)
793 /* Study an EXPR_AND binary expression node */
794 {
795     /* Use helper function */
796     StudyBinaryExpr (Expr, D);
797
798     /* If the result is valid, apply the operation */
799     if (ED_IsValid (D)) {
800         D->Val &= D->Right;
801     }
802 }
803
804
805
806 static void StudyShl (ExprNode* Expr, ExprDesc* D)
807 /* Study an EXPR_SHL binary expression node */
808 {
809     /* Use helper function */
810     StudyBinaryExpr (Expr, D);
811
812     /* If the result is valid, apply the operation */
813     if (ED_IsValid (D)) {
814         D->Val = shl_l (D->Val, D->Right);
815     }
816 }
817
818
819
820 static void StudyShr (ExprNode* Expr, ExprDesc* D)
821 /* Study an EXPR_SHR binary expression node */
822 {
823     /* Use helper function */
824     StudyBinaryExpr (Expr, D);
825
826     /* If the result is valid, apply the operation */
827     if (ED_IsValid (D)) {
828         D->Val = shr_l (D->Val, D->Right);
829     }
830 }
831
832
833
834 static void StudyEQ (ExprNode* Expr, ExprDesc* D)
835 /* Study an EXPR_EQ binary expression node */
836 {
837     /* Use helper function */
838     StudyBinaryExpr (Expr, D);
839
840     /* If the result is valid, apply the operation */
841     if (ED_IsValid (D)) {
842         D->Val = (D->Val == D->Right);
843     }
844
845     /* In any case, the result is 0 or 1 */
846     D->AddrSize = ADDR_SIZE_ZP;
847 }
848
849
850
851 static void StudyNE (ExprNode* Expr, ExprDesc* D)
852 /* Study an EXPR_NE binary expression node */
853 {
854     /* Use helper function */
855     StudyBinaryExpr (Expr, D);
856
857     /* If the result is valid, apply the operation */
858     if (ED_IsValid (D)) {
859         D->Val = (D->Val != D->Right);
860     }
861
862     /* In any case, the result is 0 or 1 */
863     D->AddrSize = ADDR_SIZE_ZP;
864 }
865
866
867
868 static void StudyLT (ExprNode* Expr, ExprDesc* D)
869 /* Study an EXPR_LT binary expression node */
870 {
871     /* Use helper function */
872     StudyBinaryExpr (Expr, D);
873
874     /* If the result is valid, apply the operation */
875     if (ED_IsValid (D)) {
876         D->Val = (D->Val < D->Right);
877     }
878
879     /* In any case, the result is 0 or 1 */
880     D->AddrSize = ADDR_SIZE_ZP;
881 }
882
883
884
885 static void StudyGT (ExprNode* Expr, ExprDesc* D)
886 /* Study an EXPR_GT binary expression node */
887 {
888     /* Use helper function */
889     StudyBinaryExpr (Expr, D);
890
891     /* If the result is valid, apply the operation */
892     if (ED_IsValid (D)) {
893         D->Val = (D->Val > D->Right);
894     }
895
896     /* In any case, the result is 0 or 1 */
897     D->AddrSize = ADDR_SIZE_ZP;
898 }
899
900
901
902 static void StudyLE (ExprNode* Expr, ExprDesc* D)
903 /* Study an EXPR_LE binary expression node */
904 {
905     /* Use helper function */
906     StudyBinaryExpr (Expr, D);
907
908     /* If the result is valid, apply the operation */
909     if (ED_IsValid (D)) {
910         D->Val = (D->Val <= D->Right);
911     }
912
913     /* In any case, the result is 0 or 1 */
914     D->AddrSize = ADDR_SIZE_ZP;
915 }
916
917
918
919 static void StudyGE (ExprNode* Expr, ExprDesc* D)
920 /* Study an EXPR_GE binary expression node */
921 {
922     /* Use helper function */
923     StudyBinaryExpr (Expr, D);
924
925     /* If the result is valid, apply the operation */
926     if (ED_IsValid (D)) {
927         D->Val = (D->Val >= D->Right);
928     }
929
930     /* In any case, the result is 0 or 1 */
931     D->AddrSize = ADDR_SIZE_ZP;
932 }
933
934
935
936 static void StudyBoolAnd (ExprNode* Expr, ExprDesc* D)
937 /* Study an EXPR_BOOLAND binary expression node */
938 {
939     StudyExprInternal (Expr->Left, D);
940     if (ED_IsConst (D)) {
941         if (D->Val != 0) {   /* Shortcut op */
942             ED_Done (D);
943             ED_Init (D);
944             StudyExprInternal (Expr->Right, D);
945             if (ED_IsConst (D)) {
946                 D->Val = (D->Val != 0);
947             } else {
948                 ED_Invalidate (D);
949             }
950         }
951     } else {
952         ED_Invalidate (D);
953     }
954
955     /* In any case, the result is 0 or 1 */
956     D->AddrSize = ADDR_SIZE_ZP;
957 }
958
959
960
961 static void StudyBoolOr (ExprNode* Expr, ExprDesc* D)
962 /* Study an EXPR_BOOLOR binary expression node */
963 {
964     StudyExprInternal (Expr->Left, D);
965     if (ED_IsConst (D)) {
966         if (D->Val == 0) {   /* Shortcut op */
967             ED_Done (D);
968             ED_Init (D);
969             StudyExprInternal (Expr->Right, D);
970             if (ED_IsConst (D)) {
971                 D->Val = (D->Val != 0);
972             } else {
973                 ED_Invalidate (D);
974             }
975         } else {
976             D->Val = 1;
977         }
978     } else {
979         ED_Invalidate (D);
980     }
981
982     /* In any case, the result is 0 or 1 */
983     D->AddrSize = ADDR_SIZE_ZP;
984 }
985
986
987
988 static void StudyBoolXor (ExprNode* Expr, ExprDesc* D)
989 /* Study an EXPR_BOOLXOR binary expression node */
990 {
991     /* Use helper function */
992     StudyBinaryExpr (Expr, D);
993
994     /* If the result is valid, apply the operation */
995     if (ED_IsValid (D)) {
996         D->Val = (D->Val != 0) ^ (D->Right != 0);
997     }
998
999     /* In any case, the result is 0 or 1 */
1000     D->AddrSize = ADDR_SIZE_ZP;
1001 }
1002
1003
1004
1005 static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
1006 /* Study an EXPR_UNARY_MINUS expression node */
1007 {
1008     /* Study the expression */
1009     StudyExprInternal (Expr->Left, D);
1010
1011     /* If it is valid, negate it */
1012     if (ED_IsValid (D)) {
1013         ED_Neg (D);
1014     }
1015 }
1016
1017
1018
1019 static void StudyNot (ExprNode* Expr, ExprDesc* D)
1020 /* Study an EXPR_NOT expression node */
1021 {
1022     /* Study the expression */
1023     StudyExprInternal (Expr->Left, D);
1024
1025     /* We can handle only const expressions */
1026     if (ED_IsConst (D)) {
1027         D->Val = ~D->Val;
1028     } else {
1029         ED_Invalidate (D);
1030     }
1031 }
1032
1033
1034
1035 static void StudySwap (ExprNode* Expr, ExprDesc* D)
1036 /* Study an EXPR_SWAP 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 & ~0xFFFFUL) | ((D->Val >> 8) & 0xFF) | ((D->Val << 8) & 0xFF00);
1044     } else {
1045         ED_Invalidate (D);
1046     }
1047 }
1048
1049
1050
1051 static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
1052 /* Study an EXPR_BOOLNOT expression node */
1053 {
1054     /* Study the expression */
1055     StudyExprInternal (Expr->Left, D);
1056
1057     /* We can handle only const expressions */
1058     if (ED_IsConst (D)) {
1059         D->Val = (D->Val == 0);
1060     } else {
1061         ED_Invalidate (D);
1062     }
1063
1064     /* In any case, the result is 0 or 1 */
1065     D->AddrSize = ADDR_SIZE_ZP;
1066 }
1067
1068
1069
1070 static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
1071 /* Study an EXPR_BYTE0 expression node */
1072 {
1073     /* Study the expression */
1074     StudyExprInternal (Expr->Left, D);
1075
1076     /* We can handle only const expressions */
1077     if (ED_IsConst (D)) {
1078         D->Val = (D->Val & 0xFF);
1079     } else {
1080         ED_Invalidate (D);
1081     }
1082
1083     /* In any case, the result is a zero page expression */
1084     D->AddrSize = ADDR_SIZE_ZP;
1085 }
1086
1087
1088
1089 static void StudyByte1 (ExprNode* Expr, ExprDesc* D)
1090 /* Study an EXPR_BYTE1 expression node */
1091 {
1092     /* Study the expression */
1093     StudyExprInternal (Expr->Left, D);
1094
1095     /* We can handle only const expressions */
1096     if (ED_IsConst (D)) {
1097         D->Val = (D->Val >> 8) & 0xFF;
1098     } else {
1099         ED_Invalidate (D);
1100     }
1101
1102     /* In any case, the result is a zero page expression */
1103     D->AddrSize = ADDR_SIZE_ZP;
1104 }
1105
1106
1107
1108 static void StudyByte2 (ExprNode* Expr, ExprDesc* D)
1109 /* Study an EXPR_BYTE2 expression node */
1110 {
1111     /* Study the expression */
1112     StudyExprInternal (Expr->Left, D);
1113
1114     /* We can handle only const expressions */
1115     if (ED_IsConst (D)) {
1116         D->Val = (D->Val >> 16) & 0xFF;
1117     } else {
1118         ED_Invalidate (D);
1119     }
1120
1121     /* In any case, the result is a zero page expression */
1122     D->AddrSize = ADDR_SIZE_ZP;
1123 }
1124
1125
1126
1127 static void StudyByte3 (ExprNode* Expr, ExprDesc* D)
1128 /* Study an EXPR_BYTE3 expression node */
1129 {
1130     /* Study the expression */
1131     StudyExprInternal (Expr->Left, D);
1132
1133     /* We can handle only const expressions */
1134     if (ED_IsConst (D)) {
1135         D->Val = (D->Val >> 24) & 0xFF;
1136     } else {
1137         ED_Invalidate (D);
1138     }
1139
1140     /* In any case, the result is a zero page expression */
1141     D->AddrSize = ADDR_SIZE_ZP;
1142 }
1143
1144
1145
1146 static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
1147 /* Study an EXPR_WORD0 expression node */
1148 {
1149     /* Study the expression */
1150     StudyExprInternal (Expr->Left, D);
1151
1152     /* We can handle only const expressions */
1153     if (ED_IsConst (D)) {
1154         D->Val = (D->Val & 0xFFFFL);
1155     } else {
1156         ED_Invalidate (D);
1157     }
1158
1159     /* In any case, the result is an absolute expression */
1160     D->AddrSize = ADDR_SIZE_ABS;
1161 }
1162
1163
1164
1165 static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
1166 /* Study an EXPR_WORD1 expression node */
1167 {
1168     /* Study the expression */
1169     StudyExprInternal (Expr->Left, D);
1170
1171     /* We can handle only const expressions */
1172     if (ED_IsConst (D)) {
1173         D->Val = (D->Val >> 16) & 0xFFFFL;
1174     } else {
1175         ED_Invalidate (D);
1176     }
1177
1178     /* In any case, the result is an absolute expression */
1179     D->AddrSize = ADDR_SIZE_ABS;
1180 }
1181
1182
1183
1184 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
1185 /* Study an expression tree and place the contents into D */
1186 {
1187     /* Study this expression node */
1188     switch (Expr->Op) {
1189
1190         case EXPR_LITERAL:
1191             StudyLiteral (Expr, D);
1192             break;
1193
1194         case EXPR_SYMBOL:
1195             StudySymbol (Expr, D);
1196             break;
1197
1198         case EXPR_SECTION:
1199             StudySection (Expr, D);
1200             break;
1201
1202         case EXPR_ULABEL:
1203             StudyULabel (Expr, D);
1204             break;
1205
1206         case EXPR_PLUS:
1207             StudyPlus (Expr, D);
1208             break;
1209
1210         case EXPR_MINUS:
1211             StudyMinus (Expr, D);
1212             break;
1213
1214         case EXPR_MUL:
1215             StudyMul (Expr, D);
1216             break;
1217
1218         case EXPR_DIV:
1219             StudyDiv (Expr, D);
1220             break;
1221
1222         case EXPR_MOD:
1223             StudyMod (Expr, D);
1224             break;
1225
1226         case EXPR_OR:
1227             StudyOr (Expr, D);
1228             break;
1229
1230         case EXPR_XOR:
1231             StudyXor (Expr, D);
1232             break;
1233
1234         case EXPR_AND:
1235             StudyAnd (Expr, D);
1236             break;
1237
1238         case EXPR_SHL:
1239             StudyShl (Expr, D);
1240             break;
1241
1242         case EXPR_SHR:
1243             StudyShr (Expr, D);
1244             break;
1245
1246         case EXPR_EQ:
1247             StudyEQ (Expr, D);
1248             break;
1249
1250         case EXPR_NE:
1251             StudyNE (Expr, D);
1252             break;
1253
1254         case EXPR_LT:
1255             StudyLT (Expr, D);
1256             break;
1257
1258         case EXPR_GT:
1259             StudyGT (Expr, D);
1260             break;
1261
1262         case EXPR_LE:
1263             StudyLE (Expr, D);
1264             break;
1265
1266         case EXPR_GE:
1267             StudyGE (Expr, D);
1268             break;
1269
1270         case EXPR_BOOLAND:
1271             StudyBoolAnd (Expr, D);
1272             break;
1273
1274         case EXPR_BOOLOR:
1275             StudyBoolOr (Expr, D);
1276             break;
1277
1278         case EXPR_BOOLXOR:
1279             StudyBoolXor (Expr, D);
1280             break;
1281
1282         case EXPR_UNARY_MINUS:
1283             StudyUnaryMinus (Expr, D);
1284             break;
1285
1286         case EXPR_NOT:
1287             StudyNot (Expr, D);
1288             break;
1289
1290         case EXPR_SWAP:
1291             StudySwap (Expr, D);
1292             break;
1293
1294         case EXPR_BOOLNOT:
1295             StudyBoolNot (Expr, D);
1296             break;
1297
1298         case EXPR_BYTE0:
1299             StudyByte0 (Expr, D);
1300             break;
1301
1302         case EXPR_BYTE1:
1303             StudyByte1 (Expr, D);
1304             break;
1305
1306         case EXPR_BYTE2:
1307             StudyByte2 (Expr, D);
1308             break;
1309
1310         case EXPR_BYTE3:
1311             StudyByte3 (Expr, D);
1312             break;
1313
1314         case EXPR_WORD0:
1315             StudyWord0 (Expr, D);
1316             break;
1317
1318         case EXPR_WORD1:
1319             StudyWord1 (Expr, D);
1320             break;
1321
1322         default:
1323             Internal ("Unknown Op type: %u", Expr->Op);
1324             break;
1325     }
1326 }
1327
1328
1329
1330 void StudyExpr (ExprNode* Expr, ExprDesc* D)
1331 /* Study an expression tree and place the contents into D */
1332 {
1333     unsigned I, J;
1334
1335     /* Call the internal function */
1336     StudyExprInternal (Expr, D);
1337
1338     /* Remove symbol references with count zero */
1339     I = J = 0;
1340     while (I < D->SymCount) {
1341         if (D->SymRef[I].Count == 0) {
1342             /* Delete the entry */
1343             --D->SymCount;
1344             memmove (D->SymRef + I, D->SymRef + I + 1,
1345                      (D->SymCount - I) * sizeof (D->SymRef[0]));
1346         } else {
1347             /* Next entry */
1348             ++I;
1349         }
1350     }
1351
1352     /* Remove section references with count zero */
1353     I = 0;
1354     while (I < D->SecCount) {
1355         if (D->SecRef[I].Count == 0) {
1356             /* Delete the entry */
1357             --D->SecCount;
1358             memmove (D->SecRef + I, D->SecRef + I + 1,
1359                      (D->SecCount - I) * sizeof (D->SecRef[0]));
1360         } else {
1361             /* Next entry */
1362             ++I;
1363         }
1364     }
1365
1366     /* If we don't have an address size, assign one if the expression is a
1367      * constant.
1368      */
1369     if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
1370         D->AddrSize = GetConstAddrSize (D->Val);
1371     }
1372
1373     /* If the expression is valid, throw away the address size and recalculate
1374      * it using the data we have. This is more exact than the on-the-fly
1375      * calculation done when evaluating the tree, because symbols may have
1376      * been removed from the expression, and the final numeric value is now
1377      * known.
1378      */
1379     if (ED_IsValid (D)) {
1380         unsigned char AddrSize;
1381
1382         /* If there are symbols or sections, use the largest one. If the
1383          * expression resolves to a const, use the address size of the value.
1384          */
1385         if (D->SymCount > 0 || D->SecCount > 0) {
1386
1387             D->AddrSize = ADDR_SIZE_DEFAULT;
1388
1389             for (I = 0; I < D->SymCount; ++I) {
1390                 const SymEntry* Sym = D->SymRef[I].Ref;
1391                 AddrSize = GetSymAddrSize (Sym);
1392                 if (AddrSize > D->AddrSize) {
1393                     D->AddrSize = AddrSize;
1394                 }
1395             }
1396
1397             for (I = 0; I < D->SecCount; ++I) {
1398                 unsigned SegNum = D->SecRef[0].Ref;
1399                 AddrSize = GetSegAddrSize (SegNum);
1400                 if (AddrSize > D->AddrSize) {
1401                     D->AddrSize = AddrSize;
1402                 }
1403             }
1404
1405         } else {
1406             AddrSize = GetConstAddrSize (D->Val);
1407             if (AddrSize > D->AddrSize) {
1408                 D->AddrSize = AddrSize;
1409             }
1410         }
1411     }
1412
1413 #if 0
1414     /* Debug code */
1415     printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
1416     printf ("Value: %08lX\n", D->Val);
1417     if (!ED_IsValid (D)) {
1418         printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
1419     } else {
1420         printf ("Valid:   %s\n", AddrSizeToStr (D->AddrSize));
1421     }
1422     printf ("%u symbols:\n", D->SymCount);
1423     printf ("%u sections:\n", D->SecCount);
1424 #endif
1425 }
1426
1427
1428