struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / src / mos6502 / ralloc.c
blob94fb70d0a4206a4dd6781b65491a620891ce556c
1 /*------------------------------------------------------------------------
3 SDCCralloc.c - source file for register allocation. M6502 specific
5 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 -------------------------------------------------------------------------*/
22 #include "ralloc.h"
23 #include "gen.h"
24 #include "dbuf_string.h"
26 /* Flags to turn on debugging code.
28 enum
30 D_ALLOC = 0,
33 #if 1
34 #define D(_a, _s) if (_a) { printf _s; fflush(stdout); }
35 #else
36 #define D(_a, _s)
37 #endif
39 /** Local static variables */
40 static struct
42 bitVect *spiltSet;
43 set *stackSpil;
44 short blockSpil;
45 int slocNum;
46 int stackExtend;
47 int dataExtend;
48 } _G;
50 /* 6502 registers */
51 reg_info regsm6502[] =
53 {REG_GPR, A_IDX, "a", M6502MASK_A, NULL, 0, 1},
54 {REG_GPR, X_IDX, "x", M6502MASK_X, NULL, 0, 1},
55 {REG_GPR, Y_IDX, "y", M6502MASK_Y, NULL, 0, 1},
56 {REG_CND, CND_IDX, "C", 0, NULL, 0, 1},
57 {REG_GPR, XA_IDX, "xa", M6502MASK_XA, NULL, 0, 1},
58 // {REG_GPR, YA_IDX, "ya", M6502MASK_YA, NULL, 0, 1},
59 {REG_GPR, YX_IDX, "yx", M6502MASK_YX, NULL, 0, 1},
60 {0, SP_IDX, "sp", 0, NULL, 0, 1},
63 /* Shared with gen.c */
64 int m6502_ptrRegReq; /* one byte pointer register required */
66 int m6502_nRegs = sizeof(regsm6502)/sizeof(reg_info);
68 reg_info *m6502_reg_a;
69 reg_info *m6502_reg_x;
70 reg_info *m6502_reg_y;
71 reg_info *m6502_reg_xa;
72 //reg_info *m6502_reg_ya;
73 reg_info *m6502_reg_yx;
74 reg_info *m6502_reg_sp;
76 static void m6502SpillThis (symbol *);
77 static void updateRegUsage (iCode * ic);
78 extern void genm6502Code (iCode *);
81 /*-----------------------------------------------------------------*/
82 /* m6502_regWithIdx - returns pointer to register with index number */
83 /*-----------------------------------------------------------------*/
84 reg_info *
85 m6502_regWithIdx (int idx)
87 int i;
89 for (i = 0; i < m6502_nRegs; i++)
90 if (regsm6502[i].rIdx == idx)
91 return &regsm6502[i];
93 printf("error: regWithIdx %d not found\n",idx);
94 exit (1);
97 /*-----------------------------------------------------------------*/
98 /* m6502_freeReg - frees a register */
99 /*-----------------------------------------------------------------*/
100 void
101 m6502_freeReg (reg_info * reg)
103 if (!reg)
105 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
106 "m6502_freeReg - Freeing NULL register");
107 exit (1);
110 reg->isFree = 1;
112 switch (reg->rIdx)
114 case A_IDX:
115 if (m6502_reg_x->isFree)
116 m6502_reg_xa->isFree = 1;
117 break;
118 case X_IDX:
119 if (m6502_reg_a->isFree)
120 m6502_reg_xa->isFree = 1;
121 if (m6502_reg_y->isFree)
122 m6502_reg_yx->isFree = 1;
123 break;
124 case Y_IDX:
125 if (m6502_reg_x->isFree)
126 m6502_reg_yx->isFree = 1;
127 break;
128 case XA_IDX:
129 m6502_reg_x->isFree = 1;
130 m6502_reg_a->isFree = 1;
131 if (m6502_reg_y->isFree)
132 m6502_reg_yx->isFree = 1;
133 break;
134 // case YA_IDX:
135 // m6502_reg_y->isFree = 1;
136 // m6502_reg_a->isFree = 1;
137 // if (m6502_reg_x->isFree)
138 // m6502_reg_yx->isFree = 1;
139 // break;
140 case YX_IDX:
141 m6502_reg_y->isFree = 1;
142 m6502_reg_x->isFree = 1;
143 if (m6502_reg_a->isFree)
144 m6502_reg_xa->isFree = 1;
145 break;
146 default:
147 break;
151 /*-----------------------------------------------------------------*/
152 /* noOverLap - will iterate through the list looking for over lap */
153 /*-----------------------------------------------------------------*/
154 static int
155 noOverLap (set * itmpStack, symbol * fsym)
157 symbol *sym;
159 for (sym = setFirstItem (itmpStack); sym; sym = setNextItem (itmpStack))
161 if (bitVectBitValue(sym->clashes,fsym->key))
162 return 0;
164 return 1;
167 /*-----------------------------------------------------------------*/
168 /* isFree - will return 1 if the a free spil location is found */
169 /*-----------------------------------------------------------------*/
170 static
171 DEFSETFUNC (isFree)
173 symbol *sym = item;
174 V_ARG (symbol **, sloc);
175 V_ARG (symbol *, fsym);
177 /* if already found */
178 if (*sloc)
179 return 0;
181 /* if it is free && and the itmp assigned to
182 this does not have any overlapping live ranges
183 with the one currently being assigned and
184 the size can be accommodated */
185 if (sym->isFree
186 && noOverLap (sym->usl.itmpStack, fsym)
187 && getSize (sym->type) >= getSize (fsym->type))
189 *sloc = sym;
190 return 1;
193 return 0;
196 /*-----------------------------------------------------------------*/
197 /* createStackSpil - create a location somewhere to spill */
198 /*-----------------------------------------------------------------*/
199 static symbol *
200 createStackSpil (symbol * sym)
202 symbol *sloc = NULL;
203 struct dbuf_s dbuf;
205 /* first go try and find a free one that is already
206 existing on the stack */
207 if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
209 /* found a free one : just update & return */
210 sym->usl.spillLoc = sloc;
211 sym->stackSpil = 1;
212 sloc->isFree = 0;
213 addSetHead (&sloc->usl.itmpStack, sym);
214 return sym;
217 /* could not then have to create one , this is the hard part
218 we need to allocate this on the stack : this is really a
219 hack!! but cannot think of anything better at this time */
221 D (D_ALLOC, ("createStackSpil: for sym %p %s (old currFunc->stack %ld)\n", sym, sym->name, (long)(currFunc->stack)));
223 dbuf_init (&dbuf, 128);
224 dbuf_printf (&dbuf, "sloc%d", _G.slocNum++);
225 sloc = newiTemp (dbuf_c_str (&dbuf));
226 dbuf_destroy (&dbuf);
228 /* set the type to the spilling symbol */
229 sloc->type = copyLinkChain (sym->type);
230 sloc->etype = getSpec (sloc->type);
231 SPEC_SCLS (sloc->etype) = (options.xdata_spill)?S_XDATA:S_DATA;
232 SPEC_EXTR (sloc->etype) = 0;
233 SPEC_STAT (sloc->etype) = 0;
234 SPEC_VOLATILE(sloc->etype) = 0;
235 SPEC_ABSA(sloc->etype) = 0;
237 /* we don't allow it to be allocated
238 onto the external stack since : so we
239 temporarily turn it off ; we also
240 turn off memory model to prevent
241 the spil from going to the external storage
244 // useXstack = options.useXstack;
245 // model = options.model;
246 /* noOverlay = options.noOverlay; */
247 /* options.noOverlay = 1; */
248 // options.model = options.useXstack = 0;
250 allocLocal (sloc);
252 // options.useXstack = useXstack;
253 // options.model = model;
254 /* options.noOverlay = noOverlay; */
255 sloc->isref = 1; /* to prevent compiler warning */
257 /* if it is on the stack then update the stack */
258 if (IN_STACK (sloc->etype))
260 currFunc->stack += getSize (sloc->type);
261 _G.stackExtend += getSize (sloc->type);
263 else
265 _G.dataExtend += getSize (sloc->type);
268 /* add it to the stackSpil set */
269 addSetHead (&_G.stackSpil, sloc);
270 sym->usl.spillLoc = sloc;
271 sym->stackSpil = 1;
273 /* add it to the set of itempStack set
274 of the spill location */
275 addSetHead (&sloc->usl.itmpStack, sym);
277 D (D_ALLOC, ("createStackSpil: created new %s\n", sloc->name));
278 return sym;
281 /*-----------------------------------------------------------------*/
282 /* spillThis - spills a specific operand */
283 /*-----------------------------------------------------------------*/
284 static void
285 m6502SpillThis (symbol * sym)
287 int i;
288 /* if this is rematerializable or has a spillLocation
289 we are okay, else we need to create a spillLocation
290 for it */
291 if (!(sym->remat || sym->usl.spillLoc))
292 createStackSpil (sym);
294 /* mark it as spilt & put it in the spilt set */
295 sym->isspilt = sym->spillA = 1;
296 _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
298 for (i = 0; i < sym->nRegs; i++)
300 if (sym->regs[i])
302 m6502_freeReg (sym->regs[i]);
303 sym->regs[i] = NULL;
307 if (sym->usl.spillLoc && !sym->remat)
308 sym->usl.spillLoc->allocreq++;
309 return;
312 /*-----------------------------------------------------------------*/
313 /* deassignLRs - check the live to and if they have registers & */
314 /* are not spilt then free up the registers */
315 /*-----------------------------------------------------------------*/
316 static void
317 deassignLRs (iCode * ic, eBBlock * ebp)
319 symbol *sym;
320 int k;
322 for (sym = hTabFirstItem (liveRanges, &k); sym;
323 sym = hTabNextItem (liveRanges, &k))
325 /* if it does not end here */
326 if (sym->liveTo > ic->seq)
327 continue;
329 /* if it was spilt on stack then we can
330 mark the stack spil location as free */
331 if (sym->isspilt)
333 if (sym->stackSpil)
335 sym->usl.spillLoc->isFree = 1;
336 sym->stackSpil = 0;
338 continue;
343 /*------------------------------------------------------------------*/
344 /* verifyRegsAssigned - make sure an iTemp is properly initialized; */
345 /* it should either have registers or have been spilled. Otherwise, */
346 /* there was an uninitialized variable, so just spill this to get */
347 /* the operand in a valid state. */
348 /*------------------------------------------------------------------*/
349 static void
350 verifyRegsAssigned (operand *op, iCode * ic)
352 symbol * sym;
354 if (!op)
355 return;
356 if (!IS_ITEMP (op))
357 return;
359 sym = OP_SYMBOL (op);
360 if (sym->isspilt)
361 return;
362 if (!sym->nRegs)
363 return;
364 if (sym->regs[0])
365 return;
367 m6502SpillThis (sym);
370 /*-----------------------------------------------------------------*/
371 /* rUmaskForOp :- returns register mask for an operand */
372 /*-----------------------------------------------------------------*/
373 bitVect *
374 m6502_rUmaskForOp (operand * op)
376 bitVect *rumask;
377 symbol *sym;
378 int j;
380 /* only temporaries are assigned registers */
381 if (!IS_ITEMP (op))
382 return NULL;
384 sym = OP_SYMBOL (op);
386 /* if spilt or no registers assigned to it
387 then nothing */
388 if (sym->isspilt || !sym->nRegs)
389 return NULL;
391 rumask = newBitVect (m6502_nRegs);
393 for (j = 0; j < sym->nRegs; j++)
395 rumask = bitVectSetBit (rumask, sym->regs[j]->rIdx);
398 return rumask;
401 /*-----------------------------------------------------------------*/
402 /* regTypeNum - computes the type & number of registers required */
403 /*-----------------------------------------------------------------*/
404 static void
405 regTypeNum (void)
407 symbol *sym;
408 int k;
410 /* for each live range do */
411 for (sym = hTabFirstItem (liveRanges, &k); sym;
412 sym = hTabNextItem (liveRanges, &k))
414 /* if used zero times then no registers needed */
415 if ((sym->liveTo - sym->liveFrom) == 0)
416 continue;
418 D (D_ALLOC, ("regTypeNum: loop on sym %p\n", sym));
420 /* if the live range is a temporary */
421 if (sym->isitmp)
423 /* if the type is marked as a conditional */
424 if (sym->regType == REG_CND)
425 continue;
427 /* if used in return only then we don't
428 need registers */
429 if (sym->ruonly || sym->accuse)
431 if (IS_AGGREGATE (sym->type) || sym->isptr)
432 sym->type = aggrToPtr (sym->type, false);
433 continue;
436 /* if not then we require registers */
437 D (D_ALLOC,
438 ("regTypeNum: isagg %u nRegs %u type %p\n", IS_AGGREGATE (sym->type) || sym->isptr, sym->nRegs, sym->type));
439 sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr)
440 ? getSize (sym->type = aggrToPtr (sym->type, false))
441 : getSize (sym->type));
442 D (D_ALLOC, ("regTypeNum: setting nRegs of %s (%p) to %u\n", sym->name, sym, sym->nRegs));
444 D (D_ALLOC, ("regTypeNum: setup to assign regs sym %p\n", sym));
446 if (sym->nRegs > 8)
448 fprintf (stderr, "allocated more than 8 registers for type ");
449 printTypeChain (sym->type, stderr);
450 fprintf (stderr, "\n");
453 /* determine the type of register required */
454 if (sym->nRegs == 1 && IS_PTR (sym->type) && sym->uptr)
455 sym->regType = REG_PTR;
456 else
457 sym->regType = REG_GPR;
459 else
461 /* for the first run we don't provide */
462 /* registers for true symbols we will */
463 /* see how things go */
464 D (D_ALLOC, ("regTypeNum: #2 setting num of %p to 0\n", sym));
465 sym->nRegs = 0;
470 #if 0
471 /** Transform weird SDCC handling of writes via pointers
472 into something more sensible. */
473 static void
474 transformPointerSet (eBBlock **ebbs, int count)
476 /* for all blocks */
477 for (int i = 0; i < count; i++)
479 iCode *ic;
481 /* for all instructions do */
482 for (ic = ebbs[i]->sch; ic; ic = ic->next)
483 if (POINTER_SET (ic))
485 IC_LEFT (ic) = IC_RESULT (ic);
486 IC_RESULT (ic) = 0;
487 ic->op = SET_VALUE_AT_ADDRESS;
491 #endif
493 /*-----------------------------------------------------------------*/
494 /* deallocStackSpil - this will set the stack pointer back */
495 /*-----------------------------------------------------------------*/
496 static
497 DEFSETFUNC (deallocStackSpil)
499 symbol *sym = item;
501 deallocLocal (sym);
502 return 0;
505 /*-----------------------------------------------------------------*/
506 /* packRegsForAssign - register reduction for assignment */
507 /*-----------------------------------------------------------------*/
508 static int
509 packRegsForAssign (iCode * ic, eBBlock * ebp)
511 iCode *dic, *sic;
513 if (!IS_ITEMP (IC_RIGHT (ic))
514 || OP_SYMBOL (IC_RIGHT (ic))->isind
515 || OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
517 return 0;
520 /* if the true symbol is defined in far space or on stack
521 then we should not since this will increase register pressure */
522 #if 0
523 if (isOperandInFarSpace(IC_RESULT(ic)) && !farSpacePackable(ic))
525 return 0;
527 #endif
529 /* find the definition of iTempNN scanning backwards if we find
530 a use of the true symbol before we find the definition then
531 we cannot */
532 for (dic = ic->prev; dic; dic = dic->prev)
534 int crossedCall = 0;
536 /* We can pack across a function call only if it's a local */
537 /* variable or our parameter. Never pack global variables */
538 /* or parameters to a function we call. */
539 if ((dic->op == CALL || dic->op == PCALL))
541 if (!OP_SYMBOL (IC_RESULT (ic))->ismyparm
542 && !OP_SYMBOL (IC_RESULT (ic))->islocal)
544 crossedCall = 1;
548 /* Don't move an assignment out of a critical block */
549 if (dic->op == CRITICAL)
551 dic = NULL;
552 break;
555 if (SKIP_IC2 (dic))
556 continue;
558 if (dic->op == IFX)
560 if (IS_SYMOP (IC_COND (dic))
561 && (IC_COND (dic)->key == IC_RESULT (ic)->key
562 || IC_COND (dic)->key == IC_RIGHT (ic)->key))
564 dic = NULL;
565 break;
568 else
570 if (IS_TRUE_SYMOP (IC_RESULT (dic))
571 && IS_OP_VOLATILE (IC_RESULT (dic)))
573 dic = NULL;
574 break;
577 if (IS_SYMOP (IC_RESULT (dic))
578 && IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
580 if (POINTER_SET (dic))
581 dic = NULL;
582 break;
585 if (IS_SYMOP (IC_RIGHT (dic))
586 && (IC_RIGHT (dic)->key == IC_RESULT (ic)->key
587 || IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
589 dic = NULL;
590 break;
593 if (IS_SYMOP (IC_LEFT (dic))
594 && (IC_LEFT (dic)->key == IC_RESULT (ic)->key
595 || IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
597 dic = NULL;
598 break;
601 if (POINTER_SET (dic) &&
602 IC_RESULT (dic)->key == IC_RESULT (ic)->key)
604 dic = NULL;
605 break;
608 if (crossedCall)
610 dic = NULL;
611 break;
616 if (!dic)
617 return 0; /* did not find */
619 /* if assignment then check that right is not a bit */
620 if (ASSIGNMENT (ic) && !POINTER_SET (ic))
622 sym_link *etype = operandType (IC_RESULT (dic));
623 if (IS_BITFIELD (etype))
625 /* if result is a bit too then it's ok */
626 etype = operandType (IC_RESULT (ic));
627 if (!IS_BITFIELD (etype))
629 return 0;
634 /* found the definition */
636 /* delete from liverange table also
637 delete from all the points inbetween and the new
638 one */
639 for (sic = dic; sic != ic; sic = sic->next)
641 bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
642 if (IS_ITEMP (IC_RESULT (dic)))
643 bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
646 /* replace the result with the result of */
647 /* this assignment and remove this assignment */
648 bitVectUnSetBit (OP_SYMBOL (IC_RESULT (dic))->defs, dic->key);
649 ReplaceOpWithCheaperOp (&IC_RESULT (dic), IC_RESULT (ic));
651 if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
653 OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
655 // TODO: and the otherway around?
657 remiCodeFromeBBlock (ebp, ic);
658 bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
659 hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
660 OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
661 return 1;
664 /*------------------------------------------------------------------*/
665 /* findAssignToSym : scanning backwards looks for first assig found */
666 /*------------------------------------------------------------------*/
667 static iCode *
668 findAssignToSym (operand * op, iCode * ic)
670 iCode *dic;
672 /* This routine is used to find sequences like
673 iTempAA = FOO;
674 ...; (intervening ops don't use iTempAA or modify FOO)
675 blah = blah + iTempAA;
677 and eliminate the use of iTempAA, freeing up its register for
678 other uses.
680 for (dic = ic->prev; dic; dic = dic->prev)
682 if (dic->op == '=' &&
683 !POINTER_SET (dic) &&
684 IC_RESULT (dic)->key == op->key
685 && IS_TRUE_SYMOP(IC_RIGHT(dic))
687 break; /* found where this temp was defined */
689 /* if we find an usage then we cannot delete it */
690 if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
691 return NULL;
693 if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
694 return NULL;
696 if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
697 return NULL;
700 if (!dic)
701 return NULL; /* didn't find any assignment to op */
702 /* we are interested only if defined in far space */
703 /* or in stack space in case of + & - */
705 /* if assigned to a non-symbol then don't repack regs */
706 if (!IS_SYMOP (IC_RIGHT (dic)))
707 return NULL;
709 /* if the symbol's address has been taken, there might be a */
710 /* non-obvious assignment to it, and so we should not */
711 if (OP_SYMBOL (IC_RIGHT (dic))->addrtaken)
712 return NULL;
714 /* if the symbol is volatile then we should not */
715 if (isOperandVolatile (IC_RIGHT (dic), true))
716 return NULL;
717 /* XXX TODO --- should we be passing false to isOperandVolatile()?
718 What does it mean for an iTemp to be volatile, anyway? Passing
719 true is more cautious but may prevent possible optimizations */
721 /* if the symbol is in far space then we should not */
722 /* if (isOperandInFarSpace (IC_RIGHT (dic)))
723 return NULL; */
726 /* now make sure that the right side of dic
727 is not defined between ic & dic */
728 if (dic)
730 iCode *sic = dic->next;
732 for (; sic != ic; sic = sic->next)
733 if (IC_RESULT (sic) &&
734 IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
735 return NULL;
738 return dic;
741 /*-----------------------------------------------------------------*/
742 /* reassignAliasedSym - used by packRegsForSupport to replace */
743 /* redundant iTemp with equivalent symbol */
744 /*-----------------------------------------------------------------*/
745 static void
746 reassignAliasedSym (eBBlock *ebp, iCode *assignment, iCode *use, operand *op)
748 iCode *ic;
749 unsigned oldSymKey, newSymKey;
751 oldSymKey = op->key;
752 newSymKey = IC_RIGHT(assignment)->key;
754 /* only track live ranges of compiler-generated temporaries */
755 if (!IS_ITEMP(IC_RIGHT(assignment)))
756 newSymKey = 0;
758 /* update the live-value bitmaps */
759 for (ic = assignment; ic != use; ic = ic->next) {
760 bitVectUnSetBit (ic->rlive, oldSymKey);
761 if (newSymKey != 0)
762 ic->rlive = bitVectSetBit (ic->rlive, newSymKey);
765 /* update the sym of the used operand */
766 OP_SYMBOL(op) = OP_SYMBOL(IC_RIGHT(assignment));
767 op->key = OP_SYMBOL(op)->key;
769 /* update the sym's liverange */
770 if ( OP_LIVETO(op) < ic->seq )
771 setToRange(op, ic->seq, false);
773 /* remove the assignment iCode now that its result is unused */
774 remiCodeFromeBBlock (ebp, assignment);
775 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(assignment))->defs, assignment->key);
776 hTabDeleteItem (&iCodehTab, assignment->key, assignment, DELETE_ITEM, NULL);
780 /*-----------------------------------------------------------------*/
781 /* packRegsForSupport :- reduce some registers for support calls */
782 /*-----------------------------------------------------------------*/
783 static int
784 packRegsForSupport (iCode * ic, eBBlock * ebp)
786 iCode *dic;
787 int changes = 0;
789 /* for the left & right operand :- look to see if the
790 left was assigned a true symbol in far space in that
791 case replace them */
793 if (IS_ITEMP (IC_LEFT (ic)) &&
794 OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
796 dic = findAssignToSym (IC_LEFT (ic), ic);
798 if (dic)
800 /* found it we need to remove it from the block */
801 reassignAliasedSym (ebp, dic, ic, IC_LEFT(ic));
802 changes++;
806 /* do the same for the right operand */
807 if (IS_ITEMP (IC_RIGHT (ic)) &&
808 OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
810 iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
812 if (dic)
814 /* found it we need to remove it from the block */
815 reassignAliasedSym (ebp, dic, ic, IC_RIGHT(ic));
816 changes++;
820 return changes;
823 /*-----------------------------------------------------------------*/
824 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN */
825 /*-----------------------------------------------------------------*/
826 static bool
827 isBitwiseOptimizable (iCode * ic)
829 sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
830 sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
832 /* bitwise operations are considered optimizable
833 under the following conditions (Jean-Louis VERN)
835 x & lit
836 bit & bit
837 bit & x
838 bit ^ bit
839 bit ^ x
840 x ^ lit
841 x | lit
842 bit | bit
843 bit | x
845 if (IS_LITERAL(rtype) ||
846 (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
847 return true;
848 else
849 return false;
852 /*-----------------------------------------------------------------*/
853 /* packForPush - heuristics to reduce iCode for pushing */
854 /*-----------------------------------------------------------------*/
855 static void
856 packForPush (iCode * ic, eBBlock ** ebpp, int count)
858 iCode *dic, *lic;
859 bitVect *dbv;
860 int disallowHiddenAssignment = 0;
861 eBBlock * ebp = ebpp[ic->eBBlockNum];
863 if ((ic->op != IPUSH && ic->op != SEND) || !IS_ITEMP (IC_LEFT (ic)))
864 return;
866 /* must have only definition & one usage */
867 if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
868 bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
869 return;
871 /* find the definition */
872 if (!(dic = hTabItemWithKey (iCodehTab,
873 bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
874 return;
876 if (dic->op != '=' || POINTER_SET (dic))
877 return;
879 if (dic->seq < ebp->fSeq || dic->seq > ebp->lSeq) // Evelyn did this
881 int i;
882 for (i=0; i<count; i++)
884 if (dic->seq >= ebpp[i]->fSeq && dic->seq <= ebpp[i]->lSeq)
886 ebp=ebpp[i];
887 break;
890 if (i==count) // Abort if we can't find the definition's block
891 return;
894 if (IS_SYMOP(IC_RIGHT(dic)))
896 if (IC_RIGHT (dic)->isvolatile)
897 return;
899 if (OP_SYMBOL (IC_RIGHT (dic))->addrtaken || isOperandGlobal (IC_RIGHT (dic)))
900 disallowHiddenAssignment = 1;
902 /* make sure the right side does not have any definitions
903 inbetween */
904 dbv = OP_DEFS(IC_RIGHT(dic));
905 for (lic = ic; lic && lic != dic ; lic = lic->prev)
907 if (bitVectBitValue(dbv,lic->key))
908 return ;
909 if (disallowHiddenAssignment && (lic->op == CALL || lic->op == PCALL || POINTER_SET (lic)))
910 return;
912 /* make sure they have the same type */
913 if (IS_SPEC(operandType(IC_LEFT(ic))))
915 sym_link *itype=operandType(IC_LEFT(ic));
916 sym_link *ditype=operandType(IC_RIGHT(dic));
918 if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
919 SPEC_LONG(itype)!=SPEC_LONG(ditype))
920 return;
922 /* extend the live range of replaced operand if needed */
923 if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq)
925 OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
927 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
929 if (IS_ITEMP (IC_RIGHT (dic)))
930 OP_USES (IC_RIGHT (dic)) = bitVectSetBit (OP_USES (IC_RIGHT (dic)), ic->key);
932 /* we now we know that it has one & only one def & use
933 and the that the definition is an assignment */
934 ReplaceOpWithCheaperOp(&IC_LEFT (ic), IC_RIGHT (dic));
935 remiCodeFromeBBlock (ebp, dic);
936 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
939 /*------------------------------------------------------------------*/
940 /* moveSendToCall - move SEND to immediately precede its CALL/PCALL */
941 /*------------------------------------------------------------------*/
942 static iCode *
943 moveSendToCall (iCode *sic, eBBlock *ebp)
945 iCode * prev = sic->prev;
946 iCode * sic2 = NULL;
947 iCode * cic;
949 /* Go find the CALL/PCALL */
950 cic = sic;
951 while (cic && cic->op != CALL && cic->op != PCALL)
952 cic = cic->next;
953 if (!cic)
954 return sic;
956 /* Is there a second SEND? If so, we'll need to move it too. */
957 if (sic->next->op == SEND)
958 sic2 = sic->next;
960 /* relocate the SEND(s) */
961 remiCodeFromeBBlock (ebp, sic);
962 addiCodeToeBBlock (ebp, sic, cic);
963 if (sic2)
965 remiCodeFromeBBlock (ebp, sic2);
966 addiCodeToeBBlock (ebp, sic2, cic);
969 /* Return the iCode to continue processing at. */
970 if (prev)
971 return prev->next;
972 else
973 return ebp->sch;
977 /*---------------------------------------------------------------------*/
978 /* packPointerOp - see if we can move an offset from addition iCode */
979 /* to the pointer iCode to used indexed addr mode */
980 /* The z80-related ports do a similar thing in SDCCopt.c, offsetFold() */
981 /*---------------------------------------------------------------------*/
982 static void
983 packPointerOp (iCode * ic, eBBlock ** ebpp)
985 operand * pointer;
986 operand * offsetOp;
987 operand * nonOffsetOp;
988 iCode * dic;
989 iCode * uic;
990 int key;
992 if (POINTER_SET (ic))
994 pointer = IC_RESULT (ic);
995 offsetOp = IC_LEFT (ic);
997 else if (POINTER_GET (ic))
999 pointer = IC_LEFT (ic);
1000 offsetOp = IC_RIGHT (ic);
1002 else
1003 return;
1005 if (!IS_ITEMP (pointer))
1006 return;
1008 /* If the pointer is rematerializable, it's already fully optimized */
1009 if (OP_SYMBOL (pointer)->remat)
1010 return;
1012 if (offsetOp && IS_OP_LITERAL (offsetOp) && operandLitValue (offsetOp) != 0)
1013 return;
1014 if (offsetOp && IS_SYMOP (offsetOp))
1015 return;
1017 /* There must be only one definition */
1018 if (bitVectnBitsOn (OP_DEFS (pointer)) != 1)
1019 return;
1020 /* find the definition */
1021 if (!(dic = hTabItemWithKey (iCodehTab, bitVectFirstBit (OP_DEFS (pointer)))))
1022 return;
1024 if (dic->op == '+' && (IS_OP_LITERAL (IC_RIGHT (dic)) ||
1025 (IS_ITEMP (IC_RIGHT (dic)) && OP_SYMBOL (IC_RIGHT (dic))->remat)))
1027 nonOffsetOp = IC_LEFT (dic);
1028 offsetOp = IC_RIGHT (dic);
1030 else if (dic->op == '+' && IS_ITEMP (IC_LEFT (dic)) && OP_SYMBOL (IC_LEFT (dic))->remat)
1032 nonOffsetOp = IC_RIGHT (dic);
1033 offsetOp = IC_LEFT (dic);
1035 else
1036 return;
1039 /* Now check all of the uses to make sure they are all get/set pointer */
1040 /* and don't already have a non-zero offset operand */
1041 for (key=0; key<OP_USES (pointer)->size; key++)
1043 if (bitVectBitValue (OP_USES (pointer), key))
1045 uic = hTabItemWithKey (iCodehTab, key);
1046 if (POINTER_GET (uic))
1048 if (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic)) && operandLitValue (IC_RIGHT (uic)) != 0)
1049 return;
1050 if (IC_RIGHT (uic) && IS_SYMOP (IC_RIGHT (uic)))
1051 return;
1053 else if (POINTER_SET (uic))
1055 // FIXME: this code will make bug-3385.c fail
1056 // it seems there are some corner cases where this
1057 // optimization is unsafe.
1058 // Other cases might also be unsafe but no test triggers it.
1059 // HC08 is also affected by the same issue.
1060 // return;
1061 // remove the return above to trigger the failure.
1062 if (IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic)) && operandLitValue (IC_LEFT (uic)) != 0)
1063 return;
1064 if (IC_LEFT (uic) && IS_SYMOP (IC_LEFT (uic)))
1065 return;
1067 else
1068 return;
1072 /* Everything checks out. Move the literal or rematerializable offset */
1073 /* to the pointer get/set iCodes */
1074 for (key=0; key<OP_USES (pointer)->size; key++)
1076 if (bitVectBitValue (OP_USES (pointer), key))
1078 uic = hTabItemWithKey (iCodehTab, key);
1079 if (POINTER_GET (uic))
1081 IC_RIGHT (uic) = offsetOp;
1082 if (IS_SYMOP (offsetOp))
1083 OP_USES (offsetOp) = bitVectSetBit (OP_USES (offsetOp), key);
1085 else if (POINTER_SET (uic))
1087 IC_LEFT (uic) = offsetOp;
1088 if (IS_SYMOP (offsetOp))
1089 OP_USES (offsetOp) = bitVectSetBit (OP_USES (offsetOp), key);
1091 else
1092 return;
1096 /* Put the remaining operand on the right and convert to assignment */
1097 if (IS_SYMOP (offsetOp))
1098 bitVectUnSetBit (OP_USES (offsetOp), dic->key);
1099 IC_RIGHT (dic) = nonOffsetOp;
1100 IC_LEFT (dic) = NULL;
1101 SET_ISADDR (IC_RESULT (dic), 0);
1102 dic->op = '=';
1105 /*-----------------------------------------------------------------*/
1106 /* packRegisters - does some transformations to reduce register */
1107 /* pressure */
1108 /*-----------------------------------------------------------------*/
1109 static void
1110 packRegisters (eBBlock ** ebpp, int count)
1112 iCode *ic;
1113 int change = 0;
1114 int blockno;
1116 for (blockno=0; blockno<count; blockno++)
1118 eBBlock *ebp = ebpp[blockno];
1122 change = 0;
1123 /* look for assignments of the form */
1124 /* iTempNN = TrueSym (someoperation) SomeOperand */
1125 /* .... */
1126 /* TrueSym := iTempNN:1 */
1127 for (ic = ebp->sch; ic; ic = ic->next)
1129 /* find assignment of the form TrueSym := iTempNN:1 */
1130 if (ic->op == '=' && !POINTER_SET (ic))
1131 change += packRegsForAssign (ic, ebp);
1134 while (change);
1136 for (ic = ebp->sch; ic; ic = ic->next)
1138 //packRegsForLiteral (ic);
1140 /* move SEND to immediately precede its CALL/PCALL */
1141 if (ic->op == SEND && ic->next &&
1142 ic->next->op != CALL && ic->next->op != PCALL)
1144 ic = moveSendToCall (ic, ebp);
1147 /* if this is an itemp & result of an address of a true sym
1148 then mark this as rematerialisable */
1149 if (ic->op == ADDRESS_OF &&
1150 IS_ITEMP (IC_RESULT (ic)) &&
1151 IS_TRUE_SYMOP (IC_LEFT (ic)) &&
1152 bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
1153 !OP_SYMBOL (IC_LEFT (ic))->onStack)
1155 OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1156 OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1157 OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1160 /* Safe: just propagates the remat flag */
1161 /* if straight assignment then carry remat flag if this is the
1162 only definition */
1163 if (ic->op == '=' &&
1164 !POINTER_SET (ic) &&
1165 IS_SYMOP (IC_RIGHT (ic)) &&
1166 OP_SYMBOL (IC_RIGHT (ic))->remat &&
1167 bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1 &&
1168 !OP_SYMBOL (IC_RESULT (ic))->_isparm &&
1169 !OP_SYMBOL (IC_RESULT (ic))->addrtaken &&
1170 !isOperandGlobal (IC_RESULT (ic)))
1172 OP_SYMBOL (IC_RESULT (ic))->remat = OP_SYMBOL (IC_RIGHT (ic))->remat;
1173 OP_SYMBOL (IC_RESULT (ic))->rematiCode = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1176 /* if cast to a pointer & the pointer being
1177 cast is remat, then we can remat this cast as well */
1178 if (ic->op == CAST &&
1179 IS_SYMOP(IC_RIGHT(ic)) &&
1180 OP_SYMBOL(IC_RIGHT(ic))->remat &&
1181 bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
1182 !OP_SYMBOL (IC_RESULT (ic))->_isparm &&
1183 !OP_SYMBOL (IC_RESULT (ic))->addrtaken &&
1184 !isOperandGlobal (IC_RESULT (ic)))
1186 sym_link *to_type = operandType(IC_LEFT(ic));
1187 sym_link *from_type = operandType(IC_RIGHT(ic));
1188 if (IS_PTR(to_type) && IS_PTR(from_type))
1190 OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1191 OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1192 OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1196 /* if this is a +/- operation with a rematerializable
1197 then mark this as rematerializable as well */
1198 if ((ic->op == '+' || ic->op == '-') &&
1199 (IS_SYMOP (IC_LEFT (ic)) &&
1200 IS_ITEMP (IC_RESULT (ic)) &&
1201 IS_OP_LITERAL (IC_RIGHT (ic))) &&
1202 OP_SYMBOL (IC_LEFT (ic))->remat &&
1203 (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
1204 bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1)
1206 OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1207 OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1208 OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1210 /* mark the pointer usages */
1211 if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic)))
1212 OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
1214 if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic)))
1215 OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
1217 /* reduce for support function calls */
1218 if (ic->supportRtn || (ic->op != IFX && ic->op != JUMPTABLE))
1219 packRegsForSupport (ic, ebp);
1221 /* if the condition of an if instruction
1222 is defined in the previous instruction and
1223 this is the only usage then
1224 mark the itemp as a conditional */
1225 if ((IS_CONDITIONAL (ic) ||
1226 (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) &&
1227 ic->next && ic->next->op == IFX &&
1228 bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
1229 isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
1230 OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
1232 OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
1233 continue;
1236 /* pack for PUSH
1237 iTempNN := (some variable in farspace) V1
1238 push iTempNN ;
1239 -------------
1240 push V1
1242 if (ic->op == IPUSH || ic->op == SEND)
1244 packForPush (ic, ebpp, count);
1247 if (POINTER_SET (ic) || POINTER_GET (ic))
1248 packPointerOp (ic, ebpp);
1254 /*-----------------------------------------------------------------*/
1255 /* Mark variables for assignment by the register allocator. */
1256 /*-----------------------------------------------------------------*/
1257 static void
1258 serialRegMark (eBBlock ** ebbs, int count)
1260 int i;
1261 short int max_alloc_bytes = SHRT_MAX; // Byte limit. Set this to a low value to pass only few variables to the register allocator. This can be useful for debugging.
1263 D (D_ALLOC, ("serialRegMark for %s, currFunc->stack %d\n", currFunc->name, currFunc->stack));
1265 /* for all blocks */
1266 for (i = 0; i < count; i++)
1268 iCode *ic;
1270 if (ebbs[i]->noPath
1271 && (ebbs[i]->entryLabel != entryLabel
1272 && ebbs[i]->entryLabel != returnLabel))
1273 continue;
1275 /* for all instructions do */
1276 for (ic = ebbs[i]->sch; ic; ic = ic->next)
1278 updateRegUsage(ic);
1280 /* if result is present && is a true symbol */
1281 if (IC_RESULT (ic) && ic->op != IFX &&
1282 IS_TRUE_SYMOP (IC_RESULT (ic)))
1284 OP_SYMBOL (IC_RESULT (ic))->allocreq++;
1287 /* take away registers from live
1288 ranges that end at this instruction */
1289 deassignLRs (ic, ebbs[i]);
1291 /* some don't need registers */
1292 if (SKIP_IC2 (ic) ||
1293 ic->op == JUMPTABLE ||
1294 ic->op == IFX ||
1295 ic->op == IPUSH ||
1296 (IC_RESULT (ic) && POINTER_SET (ic)))
1297 continue;
1299 /* now we need to allocate registers only for the result */
1300 if (IC_RESULT (ic))
1302 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1304 /* Make sure any spill location is definitely allocated */
1305 if (sym->isspilt && !sym->remat && sym->usl.spillLoc &&
1306 !sym->usl.spillLoc->allocreq)
1308 sym->usl.spillLoc->allocreq++;
1311 /* if it does not need or is spilt
1312 or is already assigned to registers
1313 or will not live beyond this instructions */
1314 if (!sym->nRegs ||
1315 sym->isspilt ||
1316 sym->liveTo <= ic->seq)
1318 D (D_ALLOC, ("serialRegMark: won't live long enough.\n"));
1319 continue;
1322 /* if some liverange has been spilt at the block level
1323 and this one live beyond this block then spill this
1324 to be safe */
1325 if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
1327 m6502SpillThis (sym);
1328 continue;
1331 if (sym->remat)
1333 m6502SpillThis (sym);
1334 continue;
1337 if (max_alloc_bytes >= sym->nRegs)
1339 sym->for_newralloc = 1;
1340 max_alloc_bytes -= sym->nRegs;
1342 else if (!sym->for_newralloc)
1344 m6502SpillThis (sym);
1345 printf ("Spilt %s due to byte limit.\n", sym->name);
1352 /*-----------------------------------------------------------------*/
1353 /* RegFix */
1354 /*-----------------------------------------------------------------*/
1355 void
1356 m6502RegFix (eBBlock ** ebbs, int count)
1358 int i;
1360 /* Check for and fix any problems with uninitialized operands */
1361 for (i = 0; i < count; i++)
1363 iCode *ic;
1365 if (ebbs[i]->noPath && (ebbs[i]->entryLabel != entryLabel && ebbs[i]->entryLabel != returnLabel))
1366 continue;
1368 for (ic = ebbs[i]->sch; ic; ic = ic->next)
1370 deassignLRs (ic, ebbs[i]);
1372 if (SKIP_IC2 (ic))
1373 continue;
1375 if (ic->op == IFX)
1377 verifyRegsAssigned (IC_COND (ic), ic);
1378 continue;
1381 if (ic->op == JUMPTABLE)
1383 verifyRegsAssigned (IC_JTCOND (ic), ic);
1384 continue;
1387 verifyRegsAssigned (IC_RESULT (ic), ic);
1388 verifyRegsAssigned (IC_LEFT (ic), ic);
1389 verifyRegsAssigned (IC_RIGHT (ic), ic);
1394 /*-----------------------------------------------------------------*/
1395 /* assignRegisters - assigns registers to each live range as need */
1396 /*-----------------------------------------------------------------*/
1397 void
1398 m6502_assignRegisters (ebbIndex *ebbi)
1400 eBBlock ** ebbs = ebbi->bbOrder;
1401 int count = ebbi->count;
1402 iCode *ic;
1403 int i;
1405 m6502_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
1406 // TODO: add asserts to make sure IDX is correct
1407 m6502_reg_a = m6502_regWithIdx(A_IDX);
1408 m6502_reg_x = m6502_regWithIdx(X_IDX);
1409 m6502_reg_y = m6502_regWithIdx(Y_IDX);
1410 m6502_reg_xa = m6502_regWithIdx(XA_IDX);
1411 // m6502_reg_ya = m6502_regWithIdx(YA_IDX);
1412 m6502_reg_yx = m6502_regWithIdx(YX_IDX);
1413 m6502_reg_sp = m6502_regWithIdx(SP_IDX);
1415 // transformPointerSet (ebbs, count);
1417 /* change assignments this will remove some
1418 live ranges reducing some register pressure */
1420 packRegisters (ebbs, count);
1422 /* liveranges probably changed by register packing
1423 so we compute them again */
1424 recomputeLiveRanges (ebbs, count, false);
1426 if (options.dump_i_code)
1427 dumpEbbsToFileExt (DUMP_PACK, ebbi);
1429 /* first determine for each live range the number of
1430 registers & the type of registers required for each */
1431 regTypeNum ();
1433 /* Mark variables for assignment by the new allocator */
1434 serialRegMark (ebbs, count);
1436 /* Invoke optimal register allocator */
1437 ic = m6502_ralloc2_cc (ebbi);
1439 /* if stack was extended then tell the user */
1440 if (_G.stackExtend)
1442 // printf("Stack spills for %s: %d\n", currFunc->name, _G.stackExtend);
1443 _G.stackExtend = 0;
1446 if (_G.dataExtend)
1448 // printf("Data spills for %s: %d\n", currFunc->name, _G.dataExtend);
1449 _G.dataExtend = 0;
1452 /* redo that offsets for stacked automatic variables */
1453 if (currFunc)
1455 redoStackOffsets ();
1458 if (options.dump_i_code)
1460 dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
1461 dumpLiveRanges (DUMP_LRANGE, liveRanges);
1464 /* now get back the chain */
1465 ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
1467 genm6502Code (ic);
1469 /* free up any _G.stackSpil locations allocated */
1470 applyToSet (_G.stackSpil, deallocStackSpil);
1471 _G.slocNum = 0;
1472 setToNull ((void *) &_G.stackSpil);
1473 setToNull ((void *) &_G.spiltSet);
1475 /* mark all registers as free */
1476 for (i = 0; i < m6502_nRegs; i++) {
1477 reg_info *reg = m6502_regWithIdx (i);
1478 m6502_freeReg (reg);
1479 m6502_dirtyReg (reg);
1482 return;
1485 /*-----------------------------------------------------------------*/
1486 /* m6502_useReg - marks a register as used */
1487 /*-----------------------------------------------------------------*/
1488 void
1489 m6502_useReg (reg_info * reg)
1491 reg->isFree = 0;
1493 switch (reg->rIdx)
1495 case A_IDX:
1496 m6502_reg_xa->aop = NULL;
1497 m6502_reg_xa->isFree = 0;
1498 // m6502_reg_ya->aop = NULL;
1499 // m6502_reg_ya->isFree = 0;
1500 break;
1501 case X_IDX:
1502 m6502_reg_xa->aop = NULL;
1503 m6502_reg_xa->isFree = 0;
1504 m6502_reg_yx->aop = NULL;
1505 m6502_reg_yx->isFree = 0;
1506 break;
1507 case Y_IDX:
1508 // m6502_reg_ya->aop = NULL;
1509 // m6502_reg_ya->isFree = 0;
1510 m6502_reg_yx->aop = NULL;
1511 m6502_reg_yx->isFree = 0;
1512 break;
1513 case XA_IDX:
1514 m6502_reg_x->aop = NULL;
1515 m6502_reg_x->isFree = 0;
1516 m6502_reg_a->aop = NULL;
1517 m6502_reg_a->isFree = 0;
1518 break;
1519 // case YA_IDX:
1520 // m6502_reg_y->aop = NULL;
1521 // m6502_reg_y->isFree = 0;
1522 // m6502_reg_a->aop = NULL;
1523 // m6502_reg_a->isFree = 0;
1524 // break;
1525 case YX_IDX:
1526 m6502_reg_y->aop = NULL;
1527 m6502_reg_y->isFree = 0;
1528 m6502_reg_x->aop = NULL;
1529 m6502_reg_x->isFree = 0;
1530 break;
1531 default:
1532 break;
1536 /*-----------------------------------------------------------------*/
1537 /* m6502_dirtyReg - marks a register as dirty */
1538 /*-----------------------------------------------------------------*/
1539 void
1540 m6502_dirtyReg (reg_info * reg)
1542 reg->aop = NULL;
1543 reg->isLitConst=0;
1545 switch (reg->rIdx)
1547 case A_IDX:
1548 m6502_reg_xa->aop = NULL;
1549 m6502_reg_xa->isLitConst = 0;
1550 // m6502_reg_ya->aop = NULL;
1551 // m6502_reg_ya->isLitConst = 0;
1552 break;
1553 case X_IDX:
1554 m6502_reg_xa->aop = NULL;
1555 m6502_reg_xa->isLitConst = 0;
1556 m6502_reg_yx->aop = NULL;
1557 m6502_reg_yx->isLitConst = 0;
1558 break;
1559 case Y_IDX:
1560 // m6502_reg_ya->aop = NULL;
1561 // m6502_reg_ya->isLitConst = 0;
1562 m6502_reg_yx->aop = NULL;
1563 m6502_reg_yx->isLitConst = 0;
1564 break;
1565 case XA_IDX:
1566 m6502_reg_x->aop = NULL;
1567 m6502_reg_x->isLitConst = 0;
1568 m6502_reg_a->aop = NULL;
1569 m6502_reg_a->isLitConst = 0;
1570 break;
1571 // case YA_IDX:
1572 // m6502_reg_y->aop = NULL;
1573 // m6502_reg_y->isLitConst = 0;
1574 // m6502_reg_a->aop = NULL;
1575 // m6502_reg_a->isLitConst = 0;
1576 break;
1577 case YX_IDX:
1578 m6502_reg_y->aop = NULL;
1579 m6502_reg_y->isLitConst = 0;
1580 m6502_reg_x->aop = NULL;
1581 m6502_reg_x->isLitConst = 0;
1582 break;
1583 default:
1584 break;
1588 /*-----------------------------------------------------------------*/
1589 /* updateRegUsage - update the registers in use at the start of */
1590 /* this icode */
1591 /*-----------------------------------------------------------------*/
1592 static void
1593 updateRegUsage (iCode * ic)
1595 int reg;
1597 // update the registers in use at the start of this icode
1598 for (reg=0; reg<m6502_nRegs; reg++)
1600 if (regsm6502[reg].isFree)
1602 ic->riu &= ~(regsm6502[reg].mask);
1604 else
1606 ic->riu |= (regsm6502[reg].mask);