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 StudyNearAddr (ExprNode* Expr, ExprDesc* D) |
1281 | /* Study an EXPR_NEARADDR expression node */ |
1282 | { |
1283 | /* Study the expression */ |
1284 | StudyExprInternal (Expr->Left, D); |
1285 | |
1286 | /* We can handle only const expressions */ |
1287 | if (!ED_IsConst (D)) { |
1288 | ED_Invalidate (D); |
1289 | } |
1290 | |
1291 | /* Promote to absolute if smaller. */ |
1292 | if (D->AddrSize < ADDR_SIZE_ABS) |
1293 | { |
1294 | D->AddrSize = ADDR_SIZE_ABS; |
1295 | } |
1296 | } |
1297 | |
1298 | |
1299 | |
1300 | static void StudyExprInternal (ExprNode* Expr, ExprDesc* D) |
1301 | /* Study an expression tree and place the contents into D */ |
1302 | { |
1303 | /* Study this expression node */ |
1304 | switch (Expr->Op) { |
1305 | |
1306 | case EXPR_LITERAL: |
1307 | StudyLiteral (Expr, D); |
1308 | break; |
1309 | |
1310 | case EXPR_SYMBOL: |
1311 | StudySymbol (Expr, D); |
1312 | break; |
1313 | |
1314 | case EXPR_SECTION: |
1315 | StudySection (Expr, D); |
1316 | break; |
1317 | |
1318 | case EXPR_ULABEL: |
1319 | StudyULabel (Expr, D); |
1320 | break; |
1321 | |
1322 | case EXPR_PLUS: |
1323 | StudyPlus (Expr, D); |
1324 | break; |
1325 | |
1326 | case EXPR_MINUS: |
1327 | StudyMinus (Expr, D); |
1328 | break; |
1329 | |
1330 | case EXPR_MUL: |
1331 | StudyMul (Expr, D); |
1332 | break; |
1333 | |
1334 | case EXPR_DIV: |
1335 | StudyDiv (Expr, D); |
1336 | break; |
1337 | |
1338 | case EXPR_MOD: |
1339 | StudyMod (Expr, D); |
1340 | break; |
1341 | |
1342 | case EXPR_OR: |
1343 | StudyOr (Expr, D); |
1344 | break; |
1345 | |
1346 | case EXPR_XOR: |
1347 | StudyXor (Expr, D); |
1348 | break; |
1349 | |
1350 | case EXPR_AND: |
1351 | StudyAnd (Expr, D); |
1352 | break; |
1353 | |
1354 | case EXPR_SHL: |
1355 | StudyShl (Expr, D); |
1356 | break; |
1357 | |
1358 | case EXPR_SHR: |
1359 | StudyShr (Expr, D); |
1360 | break; |
1361 | |
1362 | case EXPR_EQ: |
1363 | StudyEQ (Expr, D); |
1364 | break; |
1365 | |
1366 | case EXPR_NE: |
1367 | StudyNE (Expr, D); |
1368 | break; |
1369 | |
1370 | case EXPR_LT: |
1371 | StudyLT (Expr, D); |
1372 | break; |
1373 | |
1374 | case EXPR_GT: |
1375 | StudyGT (Expr, D); |
1376 | break; |
1377 | |
1378 | case EXPR_LE: |
1379 | StudyLE (Expr, D); |
1380 | break; |
1381 | |
1382 | case EXPR_GE: |
1383 | StudyGE (Expr, D); |
1384 | break; |
1385 | |
1386 | case EXPR_BOOLAND: |
1387 | StudyBoolAnd (Expr, D); |
1388 | break; |
1389 | |
1390 | case EXPR_BOOLOR: |
1391 | StudyBoolOr (Expr, D); |
1392 | break; |
1393 | |
1394 | case EXPR_BOOLXOR: |
1395 | StudyBoolXor (Expr, D); |
1396 | break; |
1397 | |
1398 | case EXPR_MAX: |
1399 | StudyMax (Expr, D); |
1400 | break; |
1401 | |
1402 | case EXPR_MIN: |
1403 | StudyMin (Expr, D); |
1404 | break; |
1405 | |
1406 | case EXPR_UNARY_MINUS: |
1407 | StudyUnaryMinus (Expr, D); |
1408 | break; |
1409 | |
1410 | case EXPR_NOT: |
1411 | StudyNot (Expr, D); |
1412 | break; |
1413 | |
1414 | case EXPR_SWAP: |
1415 | StudySwap (Expr, D); |
1416 | break; |
1417 | |
1418 | case EXPR_BOOLNOT: |
1419 | StudyBoolNot (Expr, D); |
1420 | break; |
1421 | |
1422 | case EXPR_BANK: |
1423 | StudyBank (Expr, D); |
1424 | break; |
1425 | |
1426 | case EXPR_BYTE0: |
1427 | StudyByte0 (Expr, D); |
1428 | break; |
1429 | |
1430 | case EXPR_BYTE1: |
1431 | StudyByte1 (Expr, D); |
1432 | break; |
1433 | |
1434 | case EXPR_BYTE2: |
1435 | StudyByte2 (Expr, D); |
1436 | break; |
1437 | |
1438 | case EXPR_BYTE3: |
1439 | StudyByte3 (Expr, D); |
1440 | break; |
1441 | |
1442 | case EXPR_WORD0: |
1443 | StudyWord0 (Expr, D); |
1444 | break; |
1445 | |
1446 | case EXPR_WORD1: |
1447 | StudyWord1 (Expr, D); |
1448 | break; |
1449 | |
1450 | case EXPR_FARADDR: |
1451 | StudyFarAddr (Expr, D); |
1452 | break; |
1453 | |
1454 | case EXPR_DWORD: |
1455 | StudyDWord (Expr, D); |
1456 | break; |
1457 | |
1458 | case EXPR_NEARADDR: |
1459 | StudyNearAddr (Expr, D); |
1460 | break; |
1461 | |
1462 | default: |
1463 | Internal ("Unknown Op type: %u" , Expr->Op); |
1464 | break; |
1465 | } |
1466 | } |
1467 | |
1468 | |
1469 | |
1470 | void StudyExpr (ExprNode* Expr, ExprDesc* D) |
1471 | /* Study an expression tree and place the contents into D */ |
1472 | { |
1473 | unsigned I, J; |
1474 | |
1475 | /* Call the internal function */ |
1476 | StudyExprInternal (Expr, D); |
1477 | |
1478 | /* Remove symbol references with count zero */ |
1479 | I = J = 0; |
1480 | while (I < D->SymCount) { |
1481 | if (D->SymRef[I].Count == 0) { |
1482 | /* Delete the entry */ |
1483 | --D->SymCount; |
1484 | memmove (D->SymRef + I, D->SymRef + I + 1, |
1485 | (D->SymCount - I) * sizeof (D->SymRef[0])); |
1486 | } else { |
1487 | /* Next entry */ |
1488 | ++I; |
1489 | } |
1490 | } |
1491 | |
1492 | /* Remove section references with count zero */ |
1493 | I = 0; |
1494 | while (I < D->SecCount) { |
1495 | if (D->SecRef[I].Count == 0) { |
1496 | /* Delete the entry */ |
1497 | --D->SecCount; |
1498 | memmove (D->SecRef + I, D->SecRef + I + 1, |
1499 | (D->SecCount - I) * sizeof (D->SecRef[0])); |
1500 | } else { |
1501 | /* Next entry */ |
1502 | ++I; |
1503 | } |
1504 | } |
1505 | |
1506 | /* If we don't have an address size, assign one if the expression is a |
1507 | ** constant. |
1508 | */ |
1509 | if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) { |
1510 | D->AddrSize = GetConstAddrSize (D->Val); |
1511 | } |
1512 | |
1513 | /* If the expression is valid, throw away the address size and recalculate |
1514 | ** it using the data we have. This is more exact than the on-the-fly |
1515 | ** calculation done when evaluating the tree, because symbols may have |
1516 | ** been removed from the expression, and the final numeric value is now |
1517 | ** known. |
1518 | */ |
1519 | if (ED_IsValid (D)) { |
1520 | unsigned char AddrSize; |
1521 | |
1522 | /* If there are symbols or sections, use the largest one. If the |
1523 | ** expression resolves to a const, use the address size of the value. |
1524 | */ |
1525 | if (D->SymCount > 0 || D->SecCount > 0) { |
1526 | |
1527 | D->AddrSize = ADDR_SIZE_DEFAULT; |
1528 | |
1529 | for (I = 0; I < D->SymCount; ++I) { |
1530 | const SymEntry* Sym = D->SymRef[I].Ref; |
1531 | AddrSize = GetSymAddrSize (Sym); |
1532 | if (AddrSize > D->AddrSize) { |
1533 | D->AddrSize = AddrSize; |
1534 | } |
1535 | } |
1536 | |
1537 | for (I = 0; I < D->SecCount; ++I) { |
1538 | unsigned SegNum = D->SecRef[0].Ref; |
1539 | AddrSize = GetSegAddrSize (SegNum); |
1540 | if (AddrSize > D->AddrSize) { |
1541 | D->AddrSize = AddrSize; |
1542 | } |
1543 | } |
1544 | |
1545 | } else { |
1546 | AddrSize = GetConstAddrSize (D->Val); |
1547 | if (AddrSize > D->AddrSize) { |
1548 | D->AddrSize = AddrSize; |
1549 | } |
1550 | } |
1551 | } |
1552 | |
1553 | #if 0 |
1554 | /* Debug code */ |
1555 | printf ("StudyExpr: " ); DumpExpr (Expr, SymResolve); |
1556 | printf ("Value: %08lX\n" , D->Val); |
1557 | if (!ED_IsValid (D)) { |
1558 | printf ("Invalid: %s\n" , AddrSizeToStr (D->AddrSize)); |
1559 | } else { |
1560 | printf ("Valid: %s\n" , AddrSizeToStr (D->AddrSize)); |
1561 | } |
1562 | printf ("%u symbols:\n" , D->SymCount); |
1563 | printf ("%u sections:\n" , D->SecCount); |
1564 | #endif |
1565 | } |
1566 | |