]> git.sur5r.net Git - cc65/blob - src/ca65/studyexpr.c
Started to add a new .BANK instruction that allows access to a memory area
[cc65] / src / ca65 / studyexpr.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                studyexpr.c                                */
4 /*                                                                           */
5 /*                         Study an expression tree                          */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2003-2007 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 "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.IVal;
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             LIError (&Sym->DefLines,
514                      "Circular reference in definition of symbol `%m%p'",
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.SecNum);
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.IVal), 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 StudyMax (ExprNode* Expr, ExprDesc* D)
1006 /* Study an MAX binary expression node */
1007 {
1008     /* Use helper function */
1009     StudyBinaryExpr (Expr, D);
1010
1011     /* If the result is valid, apply the operation */
1012     if (ED_IsValid (D)) {
1013         D->Val = (D->Val > D->Right)? D->Val : D->Right;
1014     }
1015 }
1016
1017
1018
1019 static void StudyMin (ExprNode* Expr, ExprDesc* D)
1020 /* Study an MIN binary expression node */
1021 {
1022     /* Use helper function */
1023     StudyBinaryExpr (Expr, D);
1024
1025     /* If the result is valid, apply the operation */
1026     if (ED_IsValid (D)) {
1027         D->Val = (D->Val < D->Right)? D->Val : D->Right;
1028     }
1029 }
1030
1031
1032
1033 static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
1034 /* Study an EXPR_UNARY_MINUS expression node */
1035 {
1036     /* Study the expression */
1037     StudyExprInternal (Expr->Left, D);
1038
1039     /* If it is valid, negate it */
1040     if (ED_IsValid (D)) {
1041         ED_Neg (D);
1042     }
1043 }
1044
1045
1046
1047 static void StudyNot (ExprNode* Expr, ExprDesc* D)
1048 /* Study an EXPR_NOT expression node */
1049 {
1050     /* Study the expression */
1051     StudyExprInternal (Expr->Left, D);
1052
1053     /* We can handle only const expressions */
1054     if (ED_IsConst (D)) {
1055         D->Val = ~D->Val;
1056     } else {
1057         ED_Invalidate (D);
1058     }
1059 }
1060
1061
1062
1063 static void StudySwap (ExprNode* Expr, ExprDesc* D)
1064 /* Study an EXPR_SWAP expression node */
1065 {
1066     /* Study the expression */
1067     StudyExprInternal (Expr->Left, D);
1068
1069     /* We can handle only const expressions */
1070     if (ED_IsConst (D)) {
1071         D->Val = (D->Val & ~0xFFFFUL) | ((D->Val >> 8) & 0xFF) | ((D->Val << 8) & 0xFF00);
1072     } else {
1073         ED_Invalidate (D);
1074     }
1075 }
1076
1077
1078
1079 static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
1080 /* Study an EXPR_BOOLNOT expression node */
1081 {
1082     /* Study the expression */
1083     StudyExprInternal (Expr->Left, D);
1084
1085     /* We can handle only const expressions */
1086     if (ED_IsConst (D)) {
1087         D->Val = (D->Val == 0);
1088     } else {
1089         ED_Invalidate (D);
1090     }
1091
1092     /* In any case, the result is 0 or 1 */
1093     D->AddrSize = ADDR_SIZE_ZP;
1094 }
1095
1096
1097
1098 static void StudyBank (ExprNode* Expr, ExprDesc* D)
1099 /* Study an EXPR_BANK expression node */
1100 {
1101     /* Get the section reference */
1102     ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SecNum);
1103
1104     /* Update the data and the address size */
1105     ++SecRef->Count;
1106
1107     /* The expression is always linker evaluated, so invalidate it */
1108     ED_Invalidate (D);
1109 }
1110
1111
1112
1113 static void StudyBankRaw (ExprNode* Expr, ExprDesc* D)
1114 /* Study an EXPR_BANKRAW expression node */
1115 {
1116     /* Study the expression extracting section references */
1117     StudyExprInternal (Expr->Left, D);
1118
1119     /* The expression is always linker evaluated, so invalidate it */
1120     ED_Invalidate (D);
1121 }
1122
1123
1124
1125 static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
1126 /* Study an EXPR_BYTE0 expression node */
1127 {
1128     /* Study the expression */
1129     StudyExprInternal (Expr->Left, D);
1130
1131     /* We can handle only const expressions */
1132     if (ED_IsConst (D)) {
1133         D->Val = (D->Val & 0xFF);
1134     } else {
1135         ED_Invalidate (D);
1136     }
1137
1138     /* In any case, the result is a zero page expression */
1139     D->AddrSize = ADDR_SIZE_ZP;
1140 }
1141
1142
1143
1144 static void StudyByte1 (ExprNode* Expr, ExprDesc* D)
1145 /* Study an EXPR_BYTE1 expression node */
1146 {
1147     /* Study the expression */
1148     StudyExprInternal (Expr->Left, D);
1149
1150     /* We can handle only const expressions */
1151     if (ED_IsConst (D)) {
1152         D->Val = (D->Val >> 8) & 0xFF;
1153     } else {
1154         ED_Invalidate (D);
1155     }
1156
1157     /* In any case, the result is a zero page expression */
1158     D->AddrSize = ADDR_SIZE_ZP;
1159 }
1160
1161
1162
1163 static void StudyByte2 (ExprNode* Expr, ExprDesc* D)
1164 /* Study an EXPR_BYTE2 expression node */
1165 {
1166     /* Study the expression */
1167     StudyExprInternal (Expr->Left, D);
1168
1169     /* We can handle only const expressions */
1170     if (ED_IsConst (D)) {
1171         D->Val = (D->Val >> 16) & 0xFF;
1172     } else {
1173         ED_Invalidate (D);
1174     }
1175
1176     /* In any case, the result is a zero page expression */
1177     D->AddrSize = ADDR_SIZE_ZP;
1178 }
1179
1180
1181
1182 static void StudyByte3 (ExprNode* Expr, ExprDesc* D)
1183 /* Study an EXPR_BYTE3 expression node */
1184 {
1185     /* Study the expression */
1186     StudyExprInternal (Expr->Left, D);
1187
1188     /* We can handle only const expressions */
1189     if (ED_IsConst (D)) {
1190         D->Val = (D->Val >> 24) & 0xFF;
1191     } else {
1192         ED_Invalidate (D);
1193     }
1194
1195     /* In any case, the result is a zero page expression */
1196     D->AddrSize = ADDR_SIZE_ZP;
1197 }
1198
1199
1200
1201 static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
1202 /* Study an EXPR_WORD0 expression node */
1203 {
1204     /* Study the expression */
1205     StudyExprInternal (Expr->Left, D);
1206
1207     /* We can handle only const expressions */
1208     if (ED_IsConst (D)) {
1209         D->Val = (D->Val & 0xFFFFL);
1210     } else {
1211         ED_Invalidate (D);
1212     }
1213
1214     /* In any case, the result is an absolute expression */
1215     D->AddrSize = ADDR_SIZE_ABS;
1216 }
1217
1218
1219
1220 static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
1221 /* Study an EXPR_WORD1 expression node */
1222 {
1223     /* Study the expression */
1224     StudyExprInternal (Expr->Left, D);
1225
1226     /* We can handle only const expressions */
1227     if (ED_IsConst (D)) {
1228         D->Val = (D->Val >> 16) & 0xFFFFL;
1229     } else {
1230         ED_Invalidate (D);
1231     }
1232
1233     /* In any case, the result is an absolute expression */
1234     D->AddrSize = ADDR_SIZE_ABS;
1235 }
1236
1237
1238
1239 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
1240 /* Study an expression tree and place the contents into D */
1241 {
1242     /* Study this expression node */
1243     switch (Expr->Op) {
1244
1245         case EXPR_LITERAL:
1246             StudyLiteral (Expr, D);
1247             break;
1248
1249         case EXPR_SYMBOL:
1250             StudySymbol (Expr, D);
1251             break;
1252
1253         case EXPR_SECTION:
1254             StudySection (Expr, D);
1255             break;
1256
1257         case EXPR_ULABEL:
1258             StudyULabel (Expr, D);
1259             break;
1260
1261         case EXPR_BANK:
1262             StudyBank (Expr, D);
1263             break;
1264
1265         case EXPR_PLUS:
1266             StudyPlus (Expr, D);
1267             break;
1268
1269         case EXPR_MINUS:
1270             StudyMinus (Expr, D);
1271             break;
1272
1273         case EXPR_MUL:
1274             StudyMul (Expr, D);
1275             break;
1276
1277         case EXPR_DIV:
1278             StudyDiv (Expr, D);
1279             break;
1280
1281         case EXPR_MOD:
1282             StudyMod (Expr, D);
1283             break;
1284
1285         case EXPR_OR:
1286             StudyOr (Expr, D);
1287             break;
1288
1289         case EXPR_XOR:
1290             StudyXor (Expr, D);
1291             break;
1292
1293         case EXPR_AND:
1294             StudyAnd (Expr, D);
1295             break;
1296
1297         case EXPR_SHL:
1298             StudyShl (Expr, D);
1299             break;
1300
1301         case EXPR_SHR:
1302             StudyShr (Expr, D);
1303             break;
1304
1305         case EXPR_EQ:
1306             StudyEQ (Expr, D);
1307             break;
1308
1309         case EXPR_NE:
1310             StudyNE (Expr, D);
1311             break;
1312
1313         case EXPR_LT:
1314             StudyLT (Expr, D);
1315             break;
1316
1317         case EXPR_GT:
1318             StudyGT (Expr, D);
1319             break;
1320
1321         case EXPR_LE:
1322             StudyLE (Expr, D);
1323             break;
1324
1325         case EXPR_GE:
1326             StudyGE (Expr, D);
1327             break;
1328
1329         case EXPR_BOOLAND:
1330             StudyBoolAnd (Expr, D);
1331             break;
1332
1333         case EXPR_BOOLOR:
1334             StudyBoolOr (Expr, D);
1335             break;
1336
1337         case EXPR_BOOLXOR:
1338             StudyBoolXor (Expr, D);
1339             break;
1340
1341         case EXPR_MAX:
1342             StudyMax (Expr, D);
1343             break;
1344
1345         case EXPR_MIN:
1346             StudyMin (Expr, D);
1347             break;
1348
1349         case EXPR_UNARY_MINUS:
1350             StudyUnaryMinus (Expr, D);
1351             break;
1352
1353         case EXPR_NOT:
1354             StudyNot (Expr, D);
1355             break;
1356
1357         case EXPR_SWAP:
1358             StudySwap (Expr, D);
1359             break;
1360
1361         case EXPR_BOOLNOT:
1362             StudyBoolNot (Expr, D);
1363             break;
1364
1365         case EXPR_BANKRAW:
1366             StudyBankRaw (Expr, D);
1367             break;
1368
1369         case EXPR_BYTE0:
1370             StudyByte0 (Expr, D);
1371             break;
1372
1373         case EXPR_BYTE1:
1374             StudyByte1 (Expr, D);
1375             break;
1376
1377         case EXPR_BYTE2:
1378             StudyByte2 (Expr, D);
1379             break;
1380
1381         case EXPR_BYTE3:
1382             StudyByte3 (Expr, D);
1383             break;
1384
1385         case EXPR_WORD0:
1386             StudyWord0 (Expr, D);
1387             break;
1388
1389         case EXPR_WORD1:
1390             StudyWord1 (Expr, D);
1391             break;
1392
1393         default:
1394             Internal ("Unknown Op type: %u", Expr->Op);
1395             break;
1396     }
1397 }
1398
1399
1400
1401 void StudyExpr (ExprNode* Expr, ExprDesc* D)
1402 /* Study an expression tree and place the contents into D */
1403 {
1404     unsigned I, J;
1405
1406     /* Call the internal function */
1407     StudyExprInternal (Expr, D);
1408
1409     /* Remove symbol references with count zero */
1410     I = J = 0;
1411     while (I < D->SymCount) {
1412         if (D->SymRef[I].Count == 0) {
1413             /* Delete the entry */
1414             --D->SymCount;
1415             memmove (D->SymRef + I, D->SymRef + I + 1,
1416                      (D->SymCount - I) * sizeof (D->SymRef[0]));
1417         } else {
1418             /* Next entry */
1419             ++I;
1420         }
1421     }
1422
1423     /* Remove section references with count zero */
1424     I = 0;
1425     while (I < D->SecCount) {
1426         if (D->SecRef[I].Count == 0) {
1427             /* Delete the entry */
1428             --D->SecCount;
1429             memmove (D->SecRef + I, D->SecRef + I + 1,
1430                      (D->SecCount - I) * sizeof (D->SecRef[0]));
1431         } else {
1432             /* Next entry */
1433             ++I;
1434         }
1435     }
1436
1437     /* If we don't have an address size, assign one if the expression is a
1438      * constant.
1439      */
1440     if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
1441         D->AddrSize = GetConstAddrSize (D->Val);
1442     }
1443
1444     /* If the expression is valid, throw away the address size and recalculate
1445      * it using the data we have. This is more exact than the on-the-fly
1446      * calculation done when evaluating the tree, because symbols may have
1447      * been removed from the expression, and the final numeric value is now
1448      * known.
1449      */
1450     if (ED_IsValid (D)) {
1451         unsigned char AddrSize;
1452
1453         /* If there are symbols or sections, use the largest one. If the
1454          * expression resolves to a const, use the address size of the value.
1455          */
1456         if (D->SymCount > 0 || D->SecCount > 0) {
1457
1458             D->AddrSize = ADDR_SIZE_DEFAULT;
1459
1460             for (I = 0; I < D->SymCount; ++I) {
1461                 const SymEntry* Sym = D->SymRef[I].Ref;
1462                 AddrSize = GetSymAddrSize (Sym);
1463                 if (AddrSize > D->AddrSize) {
1464                     D->AddrSize = AddrSize;
1465                 }
1466             }
1467
1468             for (I = 0; I < D->SecCount; ++I) {
1469                 unsigned SegNum = D->SecRef[0].Ref;
1470                 AddrSize = GetSegAddrSize (SegNum);
1471                 if (AddrSize > D->AddrSize) {
1472                     D->AddrSize = AddrSize;
1473                 }
1474             }
1475
1476         } else {
1477             AddrSize = GetConstAddrSize (D->Val);
1478             if (AddrSize > D->AddrSize) {
1479                 D->AddrSize = AddrSize;
1480             }
1481         }
1482     }
1483
1484 #if 0
1485     /* Debug code */
1486     printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
1487     printf ("Value: %08lX\n", D->Val);
1488     if (!ED_IsValid (D)) {
1489         printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
1490     } else {
1491         printf ("Valid:   %s\n", AddrSizeToStr (D->AddrSize));
1492     }
1493     printf ("%u symbols:\n", D->SymCount);
1494     printf ("%u sections:\n", D->SecCount);
1495 #endif
1496 }
1497
1498
1499