]> git.sur5r.net Git - cc65/blob - src/ca65/studyexpr.c
Removed (pretty inconsistently used) tab chars from source code base.
[cc65] / src / ca65 / studyexpr.c
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
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, 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
118 static 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
126 static void ED_Invalidate (ExprDesc* D)
127 /* Set the TOO_COMPLEX flag for D */
128 {
129     D->Flags |= ED_TOO_COMPLEX;
130 }
131
132
133
134 static 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
142 static 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
162 static 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
191 static 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
208 static 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
225 static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
226 /* Allocate a new symbol reference and return it. The count of the new
227  * reference will be set to zero, and the reference itself to Sym.
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
252 static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
253 /* Allocate a new section reference and return it. The count of the new
254  * reference will be set to zero, and the reference itself to Sec.
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
279 static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
280 /* Get a symbol reference and return it. If the symbol reference does not
281  * exist, a new one is created and returned.
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
293 static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec)
294 /* Get a section reference and return it. If the section reference does not
295  * exist, a new one is created and returned.
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
307 static 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
326 static 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
345 static 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
354 static 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
368 static 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
378 static 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
391 static 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
408 static void ED_Neg (ExprDesc* D)
409 /* Negate an expression */
410 {
411     D->Val = -D->Val;
412     ED_NegRefs (D);
413 }
414
415
416
417 static void ED_Move (ExprDesc* From, ExprDesc* To)
418 /* Move the data from one ExprDesc to another. Old data is freed, and From
419  * is prepared to that ED_Done may be called safely.
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
440 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
441 /* Study an expression tree and place the contents into D */
442
443
444
445 static 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
461 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
462 /* Study a binary expression subtree. This is a helper function for StudyExpr
463  * used for operations that succeed when both operands are known and constant.
464  * It evaluates the two subtrees and checks if they are constant. If they
465  * aren't constant, it will set the TOO_COMPLEX flag, and merge references.
466  * Otherwise the first value is returned in D->Val, the second one in D->Right,
467  * so the actual operation can be done by the caller.
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
502 static 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
512 static 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
598 static 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
611 static 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
627 static 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
662 static 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
697 static 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
744 static 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
763 static 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
782 static 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
796 static 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
810 static 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
824 static 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
838 static 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
852 static 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
869 static 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
886 static 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
903 static 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
920 static 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
937 static 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
954 static 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
979 static 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
1006 static 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
1023 static 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
1037 static 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
1051 static 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
1065 static 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
1081 static 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
1097 static 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
1116 static 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
1128 static 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
1147 static 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
1166 static 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
1185 static 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
1204 static 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
1223 static 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
1242 static 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
1261 static 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
1280 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
1281 /* Study an expression tree and place the contents into D */
1282 {
1283     /* Study this expression node */
1284     switch (Expr->Op) {
1285
1286         case EXPR_LITERAL:
1287             StudyLiteral (Expr, D);
1288             break;
1289
1290         case EXPR_SYMBOL:
1291             StudySymbol (Expr, D);
1292             break;
1293
1294         case EXPR_SECTION:
1295             StudySection (Expr, D);
1296             break;
1297
1298         case EXPR_ULABEL:
1299             StudyULabel (Expr, D);
1300             break;
1301
1302         case EXPR_PLUS:
1303             StudyPlus (Expr, D);
1304             break;
1305
1306         case EXPR_MINUS:
1307             StudyMinus (Expr, D);
1308             break;
1309
1310         case EXPR_MUL:
1311             StudyMul (Expr, D);
1312             break;
1313
1314         case EXPR_DIV:
1315             StudyDiv (Expr, D);
1316             break;
1317
1318         case EXPR_MOD:
1319             StudyMod (Expr, D);
1320             break;
1321
1322         case EXPR_OR:
1323             StudyOr (Expr, D);
1324             break;
1325
1326         case EXPR_XOR:
1327             StudyXor (Expr, D);
1328             break;
1329
1330         case EXPR_AND:
1331             StudyAnd (Expr, D);
1332             break;
1333
1334         case EXPR_SHL:
1335             StudyShl (Expr, D);
1336             break;
1337
1338         case EXPR_SHR:
1339             StudyShr (Expr, D);
1340             break;
1341
1342         case EXPR_EQ:
1343             StudyEQ (Expr, D);
1344             break;
1345
1346         case EXPR_NE:
1347             StudyNE (Expr, D);
1348             break;
1349
1350         case EXPR_LT:
1351             StudyLT (Expr, D);
1352             break;
1353
1354         case EXPR_GT:
1355             StudyGT (Expr, D);
1356             break;
1357
1358         case EXPR_LE:
1359             StudyLE (Expr, D);
1360             break;
1361
1362         case EXPR_GE:
1363             StudyGE (Expr, D);
1364             break;
1365
1366         case EXPR_BOOLAND:
1367             StudyBoolAnd (Expr, D);
1368             break;
1369
1370         case EXPR_BOOLOR:
1371             StudyBoolOr (Expr, D);
1372             break;
1373
1374         case EXPR_BOOLXOR:
1375             StudyBoolXor (Expr, D);
1376             break;
1377
1378         case EXPR_MAX:
1379             StudyMax (Expr, D);
1380             break;
1381
1382         case EXPR_MIN:
1383             StudyMin (Expr, D);
1384             break;
1385
1386         case EXPR_UNARY_MINUS:
1387             StudyUnaryMinus (Expr, D);
1388             break;
1389
1390         case EXPR_NOT:
1391             StudyNot (Expr, D);
1392             break;
1393
1394         case EXPR_SWAP:
1395             StudySwap (Expr, D);
1396             break;
1397
1398         case EXPR_BOOLNOT:
1399             StudyBoolNot (Expr, D);
1400             break;
1401
1402         case EXPR_BANK:
1403             StudyBank (Expr, D);
1404             break;
1405
1406         case EXPR_BYTE0:
1407             StudyByte0 (Expr, D);
1408             break;
1409
1410         case EXPR_BYTE1:
1411             StudyByte1 (Expr, D);
1412             break;
1413
1414         case EXPR_BYTE2:
1415             StudyByte2 (Expr, D);
1416             break;
1417
1418         case EXPR_BYTE3:
1419             StudyByte3 (Expr, D);
1420             break;
1421
1422         case EXPR_WORD0:
1423             StudyWord0 (Expr, D);
1424             break;
1425
1426         case EXPR_WORD1:
1427             StudyWord1 (Expr, D);
1428             break;
1429
1430         case EXPR_FARADDR:
1431             StudyFarAddr (Expr, D);
1432             break;
1433
1434         case EXPR_DWORD:
1435             StudyDWord (Expr, D);
1436             break;
1437
1438         default:
1439             Internal ("Unknown Op type: %u", Expr->Op);
1440             break;
1441     }
1442 }
1443
1444
1445
1446 void StudyExpr (ExprNode* Expr, ExprDesc* D)
1447 /* Study an expression tree and place the contents into D */
1448 {
1449     unsigned I, J;
1450
1451     /* Call the internal function */
1452     StudyExprInternal (Expr, D);
1453
1454     /* Remove symbol references with count zero */
1455     I = J = 0;
1456     while (I < D->SymCount) {
1457         if (D->SymRef[I].Count == 0) {
1458             /* Delete the entry */
1459             --D->SymCount;
1460             memmove (D->SymRef + I, D->SymRef + I + 1,
1461                      (D->SymCount - I) * sizeof (D->SymRef[0]));
1462         } else {
1463             /* Next entry */
1464             ++I;
1465         }
1466     }
1467
1468     /* Remove section references with count zero */
1469     I = 0;
1470     while (I < D->SecCount) {
1471         if (D->SecRef[I].Count == 0) {
1472             /* Delete the entry */
1473             --D->SecCount;
1474             memmove (D->SecRef + I, D->SecRef + I + 1,
1475                      (D->SecCount - I) * sizeof (D->SecRef[0]));
1476         } else {
1477             /* Next entry */
1478             ++I;
1479         }
1480     }
1481
1482     /* If we don't have an address size, assign one if the expression is a
1483      * constant.
1484      */
1485     if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
1486         D->AddrSize = GetConstAddrSize (D->Val);
1487     }
1488
1489     /* If the expression is valid, throw away the address size and recalculate
1490      * it using the data we have. This is more exact than the on-the-fly
1491      * calculation done when evaluating the tree, because symbols may have
1492      * been removed from the expression, and the final numeric value is now
1493      * known.
1494      */
1495     if (ED_IsValid (D)) {
1496         unsigned char AddrSize;
1497
1498         /* If there are symbols or sections, use the largest one. If the
1499          * expression resolves to a const, use the address size of the value.
1500          */
1501         if (D->SymCount > 0 || D->SecCount > 0) {
1502
1503             D->AddrSize = ADDR_SIZE_DEFAULT;
1504
1505             for (I = 0; I < D->SymCount; ++I) {
1506                 const SymEntry* Sym = D->SymRef[I].Ref;
1507                 AddrSize = GetSymAddrSize (Sym);
1508                 if (AddrSize > D->AddrSize) {
1509                     D->AddrSize = AddrSize;
1510                 }
1511             }
1512
1513             for (I = 0; I < D->SecCount; ++I) {
1514                 unsigned SegNum = D->SecRef[0].Ref;
1515                 AddrSize = GetSegAddrSize (SegNum);
1516                 if (AddrSize > D->AddrSize) {
1517                     D->AddrSize = AddrSize;
1518                 }
1519             }
1520
1521         } else {
1522             AddrSize = GetConstAddrSize (D->Val);
1523             if (AddrSize > D->AddrSize) {
1524                 D->AddrSize = AddrSize;
1525             }
1526         }
1527     }
1528
1529 #if 0
1530     /* Debug code */
1531     printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
1532     printf ("Value: %08lX\n", D->Val);
1533     if (!ED_IsValid (D)) {
1534         printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
1535     } else {
1536         printf ("Valid:   %s\n", AddrSizeToStr (D->AddrSize));
1537     }
1538     printf ("%u symbols:\n", D->SymCount);
1539     printf ("%u sections:\n", D->SecCount);
1540 #endif
1541 }
1542
1543
1544