xa51 backup
[fw/sdcc] / src / xa51 / ralloc.c
1 /* This port is in development, UNSTABLE, DEVELOPERS ONLY! */
2
3 /* idea:
4    R0-^-R2(R0L-R2H) used for scratch (byte, word, pointer)
5    R3L-^-R6H used for bytes
6    R6-v-R4 used for ptr
7    R15/R6-v-R4 used for words
8    
9    R7 used for stack
10 */
11
12 /*------------------------------------------------------------------------
13   
14   SDCCralloc.c - source file for register allocation. (xa51) specific
15   
16   Written By -  
17   
18   This program is free software; you can redistribute it and/or modify it
19   under the terms of the GNU General Public License as published by the
20   Free Software Foundation; either version 2, or (at your option) any
21   later version.
22   
23   This program is distributed in the hope that it will be useful,
24   but WITHOUT ANY WARRANTY; without even the implied warranty of
25   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26   GNU General Public License for more details.
27   
28   You should have received a copy of the GNU General Public License
29   along with this program; if not, write to the Free Software
30   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31   
32   In other words, you are welcome to use, share and improve this program.
33   You are forbidden to forbid anyone else to use, share and improve
34   what you give them.   Help stamp out software-hoarding!  
35   -------------------------------------------------------------------------*/
36
37 #include "common.h"
38 #include "ralloc.h"
39 #include "gen.h"
40
41 extern void genXA51Code (iCode *);
42
43 #define D0(x) 
44 #define D1(x) x
45 #define D2(x) x
46
47 /* Global data */
48 static struct
49 {
50   bitVect *spiltSet;
51   set *stackSpil;
52   bitVect *regAssigned;
53   bitVect *totRegAssigned;    /* final set of LRs that got into registers */
54   short blockSpil;
55   int slocNum;
56   bitVect *funcrUsed;           /* registers used in a function */
57   int stackExtend;
58 }
59 _G;
60
61 /* xa51 registers */
62 regs regsXA51[]={
63   // index size type name regMask isFree symbol
64   {R0L_ID, 1, REG_SCR, "r0l", 0x0001, 1, NULL}, // r0l used for scratch
65   {R0H_ID, 1, REG_SCR, "r0h", 0x0002, 1, NULL}, // r0h used for scratch
66   {R1L_ID, 1, REG_SCR, "r1l", 0x0004, 1, NULL}, // r1l used for scratch
67   {R1H_ID, 1, REG_SCR, "r1h", 0x0008, 1, NULL}, // r1h used for scratch
68   {R2L_ID, 1, REG_PTR, "r2l", 0x0010, 1, NULL},
69   {R2H_ID, 1, REG_PTR, "r2h", 0x0020, 1, NULL},
70   {R3L_ID, 1, REG_PTR, "r3l", 0x0040, 1, NULL},
71   {R3H_ID, 1, REG_PTR, "r3h", 0x0080, 1, NULL},
72   {R4L_ID, 1, REG_PTR, "r4l", 0x0100, 1, NULL},
73   {R4H_ID, 1, REG_PTR, "r4h", 0x0200, 1, NULL},
74   {R5L_ID, 1, REG_PTR, "r5l", 0x0400, 1, NULL},
75   {R5H_ID, 1, REG_PTR, "r5h", 0x0800, 1, NULL},
76   {R6L_ID, 1, REG_PTR, "r6l", 0x1000, 1, NULL},
77   {R6H_ID, 1, REG_PTR, "r6h", 0x2000, 1, NULL},
78   {R7L_ID, 1, REG_STK, "r7l", 0x4000, 1, NULL}, // r7=SP
79   {R7H_ID, 1, REG_STK, "r7h", 0x8000, 1, NULL}, // r7=SP
80
81   {R0_ID, 2, REG_SCR, "r0",  0x0003, 1, NULL}, // r0 used for scratch
82   {R1_ID, 2, REG_SCR, "r1",  0x000c, 1, NULL}, // r1 used for scratch
83   {R2_ID, 2, REG_PTR, "r2",  0x0030, 1, NULL}, 
84   {R3_ID, 2, REG_PTR, "r3",  0x00c0, 1, NULL},
85   {R4_ID, 2, REG_PTR, "r4",  0x0300, 1, NULL}, 
86   {R5_ID, 2, REG_PTR, "r5",  0x0c00, 1, NULL}, 
87   {R6_ID, 2, REG_PTR, "r6",  0x3000, 1, NULL}, 
88   {R7_ID, 2, REG_STK, "r7",  0xc000, 1, NULL}, // r7=SP
89 #if 0 // some derivates have even more! (only bit/word access no ptr use)
90   {R8_ID, 2, REG_GPR, "r8",  0x010000, 1, NULL},
91   {R9_ID, 2, REG_GPR, "r9",  0x020000, 1, NULL},
92   {R10_ID, 2, REG_GPR, "r10", 0x040000, 1, NULL},
93   {R11_ID, 2, REG_GPR, "r11", 0x080000, 1, NULL},
94   {R12_ID, 2, REG_GPR, "r12", 0x100000, 1, NULL},
95   {R13_ID, 2, REG_GPR, "r13", 0x200000, 1, NULL},
96   {R14_ID, 2, REG_GPR, "r14", 0x400000, 1, NULL},
97   {R15_ID, 2, REG_GPR, "r15", 0x800000, 1, NULL},
98 #endif
99   {R0R1_ID, 4, REG_GPR, "(r0,r1)", 0x000f, 1, NULL},
100   {R2R3_ID, 4, REG_GPR, "(r2,r3)", 0x00f0, 1, NULL},
101   {R4R5_ID, 4, REG_GPR, "(r4,r5)", 0x0f00, 1, NULL},
102   {R6R7_ID, 4, REG_GPR, "(r6,r7)", 0xf000, 1, NULL},
103 };
104
105 int xa51_nRegs=sizeof(regsXA51)/sizeof(regs);
106
107 // the currently in use registers
108 unsigned long xa51RegsInUse=0;
109
110 // this should be set with a command line switch
111 bool xa51HasGprRegs=0;
112
113 /*-----------------------------------------------------------------*/
114 /* xa51_regWithMask - returns pointer to register with mask        */
115 /*-----------------------------------------------------------------*/
116 regs *xa51_regWithMask (unsigned long mask) {
117   int i;
118   for (i=0; i<xa51_nRegs; i++) {
119     if (regsXA51[i].regMask==mask) {
120       return &regsXA51[i];
121     }
122   }
123   return NULL;
124 }
125
126 /*-----------------------------------------------------------------*/
127 /* checkRegsMask - check the consistancy of the regMask redundancy */
128 /*-----------------------------------------------------------------*/
129
130 void checkRegMask(char *f) { // for debugging purposes only
131   int i;
132   unsigned long regMask=0;
133   
134   // rebuild the regmask
135   for (i=0; i<xa51_nRegs; i++) {
136     if (!regsXA51[i].isFree) {
137       regMask |= regsXA51[i].regMask;
138     }
139   }
140   
141   // check it
142   if (regMask != xa51RegsInUse) {
143     fprintf (stderr, "error(%s): regMask inconsistent 0x%08lx != 0x%08lx\n",
144              f, regMask, xa51RegsInUse);
145     regMask=regMask^xa51RegsInUse;
146     fprintf (stderr, "%s used by %s\n", 
147              xa51_regWithMask(regMask)->name, 
148              xa51_regWithMask(regMask)->sym->name);
149     
150     exit(1);
151     return;
152   }
153 }
154
155 char *regTypeToStr(short type) {
156   switch (type) 
157     {
158     case REG_PTR: return "ptr"; break; // pointer
159     case REG_GPR: return "gpr"; break; // general purpose
160     case REG_CND: return "cnd"; break; // condition (bit)
161     case REG_STK: return "stk"; break; // stack
162     case REG_SCR: return "scr"; break; // scratch
163     default: return "???";
164     }
165 }
166
167 /*-----------------------------------------------------------------*/
168 /* freeReg - frees a previous allocated register                   */
169 /*-----------------------------------------------------------------*/
170 static void freeReg (regs * reg, bool silent) {
171   
172   checkRegMask(__FUNCTION__);
173   
174   if (!reg) {
175     werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
176             "freeReg - freeing NULL register");
177     return;
178   }
179   
180   if (!silent) {
181     D0(fprintf (stderr, "freeReg: (%08lx) %s (%s) ", xa51RegsInUse, 
182                 reg->name, reg->sym->name));
183   }
184   
185   if (reg->isFree || ((xa51RegsInUse&reg->regMask)!=reg->regMask)) {
186     werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
187             "freeReg - freeing unused register(s)");
188     exit (1);
189   }
190   xa51RegsInUse &= ~reg->regMask;
191   reg->isFree = 1;
192   reg->sym = NULL;
193   if (!silent) D0(fprintf (stderr, "(%08lx)\n", xa51RegsInUse));
194   
195   checkRegMask(__FUNCTION__);
196 }
197
198 /*-----------------------------------------------------------------*/
199 /* allocReg - allocates register of given size (byte, word, dword) */
200 /*            and type (ptr, gpr, cnd)                             */
201 /*-----------------------------------------------------------------*/
202 static bool allocReg (short size, short type, symbol *sym, 
203                       short offset, bool silent) {
204   int i;
205   
206   checkRegMask(__FUNCTION__);
207   
208   if (!silent) {
209     D0(fprintf (stderr, "allocReg (%08lx) for %s size:%d, type:%s ", 
210                 xa51RegsInUse,
211                 sym->name,
212                 size, regTypeToStr(type)));
213   }
214   
215   switch (size) 
216     {
217       // TODO: gaps could be filled for dwords too
218     case 1:
219       // let's see if we can fill a gap
220       for (i=0; i<xa51_nRegs; i++) {
221         if (regsXA51[i].size==2 && regsXA51[i].type==type) {
222           unsigned long mask=regsXA51[i].regMask & ~xa51RegsInUse;
223           if (mask && mask!=regsXA51[i].regMask) {
224             regs *reg=xa51_regWithMask(mask);
225             // found a gap
226             sym->regs[offset]=reg;
227             xa51RegsInUse |= mask;
228             reg->isFree=0; // redundant
229             reg->sym = sym;
230             if (!silent) {
231               D0(fprintf (stderr, "(using gap) %s\n", reg->name));
232             }
233             checkRegMask(__FUNCTION__);
234             return TRUE;
235           }
236         }
237       }
238       // no we can't, fall through
239     case 2:
240       for (i=0; i<xa51_nRegs; i++) {
241         if (regsXA51[i].size==size &&
242             regsXA51[i].type==type &&
243             (regsXA51[i].regMask & xa51RegsInUse)==0) {
244           xa51RegsInUse |= regsXA51[i].regMask;
245           regsXA51[i].isFree = 0; // redundant
246           regsXA51[i].sym = sym;
247           if (!silent) {
248             D0(fprintf (stderr, "%s\n", regsXA51[i].name));
249           }
250           sym->regs[offset]=&regsXA51[i];
251           checkRegMask(__FUNCTION__);
252           return TRUE;
253         }
254       }
255       if (!silent) {
256         D0(fprintf (stderr, "failed (%08lx)\n", xa51RegsInUse));
257       }
258       checkRegMask(__FUNCTION__);
259       return FALSE;
260       break;
261     case 3:
262       // this must be a generic pointer
263       if (!silent) {
264         D0(fprintf (stderr, "trying 1+2\n"));
265       }
266       // get the generic part (gpr regs can't be byte)
267       if (allocReg (1, REG_PTR, sym, offset+1, silent)) {
268         // get the pointer part
269         if (allocReg (2, REG_PTR, sym, offset, silent)) {
270           checkRegMask(__FUNCTION__);
271           return TRUE;
272         }
273         freeReg(sym->regs[offset+1], silent);
274         sym->regs[offset+1]=NULL;
275       }
276       checkRegMask(__FUNCTION__);
277       return FALSE;
278       break;
279     case 4: // this is a dword
280       if (!silent) {
281         D0(fprintf (stderr, "trying 2+2\n"));
282       }
283       if ((xa51HasGprRegs && allocReg (2, REG_GPR, sym, offset, silent)) ||
284           allocReg (2, REG_PTR, sym, offset, silent)) {
285         if ((xa51HasGprRegs && allocReg (2, REG_GPR, sym, offset+1, silent)) ||
286             allocReg (2, REG_PTR, sym, offset+1, silent)) {
287           checkRegMask(__FUNCTION__);
288           return TRUE;
289         }
290       }
291       if (sym->regs[offset]) {
292         freeReg(sym->regs[offset], FALSE);
293         sym->regs[offset]=NULL;
294       }
295       checkRegMask(__FUNCTION__);
296       return FALSE;
297       break;
298     }
299   fprintf (stderr, "\nallocReg: cannot allocate reg of size %d\n", size);
300   exit (1);
301   return FALSE;
302 }
303
304 /*-------------------------------------------------------------------*/
305 /* freeAllRegs - frees all registers                                 */
306 /*-------------------------------------------------------------------*/
307 // just to be sure, this should not be needed
308 static void freeAllRegs (void) {
309   char regsFreed[132];
310   int i;
311   int nfr = 0;
312   
313   checkRegMask(__FUNCTION__);
314   
315   regsFreed[0]=0;
316   for (i=0; i<xa51_nRegs; i++) {
317     if (!regsXA51[i].isFree) {
318       strcat (regsFreed, regsXA51[i].name);
319       strcat (regsFreed, " ");
320       regsXA51[i].isFree=1;
321       regsXA51[i].sym=NULL;
322       nfr++;
323     }
324   }
325   xa51RegsInUse=0;
326   if (nfr) {
327     fprintf (stderr, "freeAllRegisters: %d regs freed (%s)\n", nfr, regsFreed);
328     exit (1);
329   }
330 }
331
332 /*-----------------------------------------------------------------*/
333 /* allDefsOutOfRange - all definitions are out of a range          */
334 /*-----------------------------------------------------------------*/
335 static bool allDefsOutOfRange (bitVect * defs, int fseq, int toseq) {
336   int i;
337   
338   if (!defs)
339     return TRUE;
340   
341   for (i = 0; i < defs->size; i++)
342     {
343       iCode *ic;
344       
345       if (bitVectBitValue (defs, i) &&
346           (ic = hTabItemWithKey (iCodehTab, i)) &&
347           (ic->seq >= fseq && ic->seq <= toseq))
348         return FALSE;
349     }
350   return TRUE;
351 }
352
353 /*-----------------------------------------------------------------*/
354 /* computeSpillable - given a point find the spillable live ranges */
355 /*-----------------------------------------------------------------*/
356 static bitVect *computeSpillable (iCode * ic) {
357   bitVect *spillable;
358   
359   /* spillable live ranges are those that are live at this 
360      point . the following categories need to be subtracted
361      from this set. 
362      a) - those that are already spilt
363      b) - if being used by this one
364      c) - defined by this one */
365   
366   spillable = bitVectCopy (ic->rlive);
367   spillable =
368     bitVectCplAnd (spillable, _G.spiltSet);     /* those already spilt */
369   spillable =
370     bitVectCplAnd (spillable, ic->uses);        /* used in this one */
371   bitVectUnSetBit (spillable, ic->defKey);      /* defined by this one */
372   spillable = bitVectIntersect (spillable, _G.regAssigned);
373   return spillable;
374   
375 }
376
377 /*-----------------------------------------------------------------*/
378 /* noSpilLoc - return true if a variable has no spil location      */
379 /*-----------------------------------------------------------------*/
380 static int
381 noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
382 {
383   return (sym->usl.spillLoc ? 0 : 1);
384 }
385
386 /*-----------------------------------------------------------------*/
387 /* hasSpilLoc - will return 1 if the symbol has spil location      */
388 /*-----------------------------------------------------------------*/
389 static int
390 hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
391 {
392   return (sym->usl.spillLoc ? 1 : 0);
393 }
394
395 /*-----------------------------------------------------------------*/
396 /* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
397 /*                    but is not used as a pointer                 */
398 /*-----------------------------------------------------------------*/
399 static int
400 hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
401 {
402   return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
403 }
404
405 /*-----------------------------------------------------------------*/
406 /* rematable - will return 1 if the remat flag is set              */
407 /*-----------------------------------------------------------------*/
408 static int
409 rematable (symbol * sym, eBBlock * ebp, iCode * ic)
410 {
411   return sym->remat;
412 }
413
414 /*-----------------------------------------------------------------*/
415 /* notUsedInBlock - not used in this block                         */
416 /*-----------------------------------------------------------------*/
417 static int
418 notUsedInBlock (symbol * sym, eBBlock * ebp, iCode * ic)
419 {
420   return (!bitVectBitsInCommon (sym->defs, ebp->usesDefs) &&
421           allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
422   /*     return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */
423 }
424
425 /*-----------------------------------------------------------------*/
426 /* notUsedInRemaining - not used or defined in remain of the block */
427 /*-----------------------------------------------------------------*/
428 static int
429 notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
430 {
431   return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
432           allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
433 }
434
435 /*-----------------------------------------------------------------*/
436 /* allLRs - return true for all                                    */
437 /*-----------------------------------------------------------------*/
438 static int
439 allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
440 {
441   return 1;
442 }
443
444 /*-----------------------------------------------------------------*/
445 /* liveRangesWith - applies function to a given set of live range  */
446 /*-----------------------------------------------------------------*/
447 static set *
448 liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
449                 eBBlock * ebp, iCode * ic)
450 {
451   set *rset = NULL;
452   int i;
453   
454   if (!lrs || !lrs->size)
455     return NULL;
456   
457   for (i = 1; i < lrs->size; i++)
458     {
459       symbol *sym;
460       if (!bitVectBitValue (lrs, i))
461         continue;
462       
463       /* if we don't find it in the live range 
464          hash table we are in serious trouble */
465       if (!(sym = hTabItemWithKey (liveRanges, i)))
466         {
467           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
468                   "liveRangesWith could not find liveRange");
469           exit (1);
470         }
471       
472       if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
473         addSetHead (&rset, sym);
474     }
475   
476   return rset;
477 }
478
479
480 /*-----------------------------------------------------------------*/
481 /* leastUsedLR - given a set determines which is the least used    */
482 /*-----------------------------------------------------------------*/
483 static symbol *
484 leastUsedLR (set * sset)
485 {
486   symbol *sym = NULL, *lsym = NULL;
487   
488   sym = lsym = setFirstItem (sset);
489   
490   if (!lsym)
491     return NULL;
492   
493   for (; lsym; lsym = setNextItem (sset))
494     {
495       
496       /* if usage is the same then prefer
497          the spill the smaller of the two */
498       if (lsym->used == sym->used)
499         if (getSize (lsym->type) < getSize (sym->type))
500           sym = lsym;
501       
502       /* if less usage */
503       if (lsym->used < sym->used)
504         sym = lsym;
505       
506     }
507   
508   setToNull ((void **) &sset);
509   sym->blockSpil = 0;
510   return sym;
511 }
512
513 /*-----------------------------------------------------------------*/
514 /* noOverLap - will iterate through the list looking for over lap  */
515 /*-----------------------------------------------------------------*/
516 static int
517 noOverLap (set * itmpStack, symbol * fsym)
518 {
519   symbol *sym;
520   
521   
522   for (sym = setFirstItem (itmpStack); sym;
523        sym = setNextItem (itmpStack))
524     {
525       if (bitVectBitValue(sym->clashes,fsym->key)) return 0;
526     }
527   
528   return 1;
529 }
530
531 /*-----------------------------------------------------------------*/
532 /* isFree - will return 1 if the a free spil location is found     */
533 /*-----------------------------------------------------------------*/
534 static DEFSETFUNC (isFree) {
535   symbol *sym = item;
536   V_ARG (symbol **, sloc);
537   V_ARG (symbol *, fsym);
538   
539   /* if already found */
540   if (*sloc)
541     return 0;
542   
543   /* if it is free && and the itmp assigned to
544      this does not have any overlapping live ranges
545      with the one currently being assigned and
546      the size can be accomodated  */
547   if (sym->isFree &&
548       noOverLap (sym->usl.itmpStack, fsym) &&
549       /* TODO: this is a waste but causes to many problems 
550          getSize (sym->type) >= getSize (fsym->type)) {
551       */
552       getSize (sym->type) == getSize (fsym->type)) {
553     *sloc = sym;
554     return 1;
555   }
556   
557   return 0;
558 }
559
560 /*-----------------------------------------------------------------*/
561 /* createStackSpil - create a location on the stack to spil        */
562 /*-----------------------------------------------------------------*/
563 static symbol *
564 createStackSpil (symbol * sym)
565 {
566   symbol *sloc = NULL;
567   char slocBuffer[30];
568   
569   D1(fprintf (stderr, "  createStackSpil for %s\n", sym->name));
570   
571   /* first go try and find a free one that is already 
572      existing on the stack */
573   if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
574     {
575       /* found a free one : just update & return */
576       sym->usl.spillLoc = sloc;
577       sym->stackSpil = 1;
578       sloc->isFree = 0;
579       addSetHead (&sloc->usl.itmpStack, sym);
580       D1(fprintf (stderr, "    using existing %s\n", sloc->name));
581       return sym;
582     }
583   
584   sprintf (slocBuffer, "sloc%d", _G.slocNum++);
585   sloc = newiTemp (slocBuffer);
586   
587   /* set the type to the spilling symbol */
588   sloc->type = copyLinkChain (sym->type);
589   sloc->etype = getSpec (sloc->type);
590   SPEC_SCLS (sloc->etype) = S_STACK;
591   SPEC_EXTR (sloc->etype) = 0;
592   SPEC_STAT (sloc->etype) = 0;
593   SPEC_VOLATILE(sloc->etype) = 0;
594   SPEC_ABSA(sloc->etype) = 0;
595   
596   allocLocal (sloc);
597   
598   sloc->isref = 1;              /* to prevent compiler warning */
599   
600   currFunc->stack += getSize (sloc->type);
601   _G.stackExtend += getSize (sloc->type);
602   
603   /* add it to the _G.stackSpil set */
604   addSetHead (&_G.stackSpil, sloc);
605   sym->usl.spillLoc = sloc;
606   sym->stackSpil = 1;
607   
608   /* add it to the set of itempStack set 
609      of the spill location */
610   addSetHead (&sloc->usl.itmpStack, sym);
611   return sym;
612 }
613
614 /*-----------------------------------------------------------------*/
615 /* spillThis - spils a specific operand                            */
616 /*-----------------------------------------------------------------*/
617 static void
618 spillThis (symbol * sym)
619 {
620   int i;
621   
622   D1(fprintf (stderr, "  spillThis: %s\n", sym->name));
623   
624   /* if this is rematerializable or has a spillLocation
625      we are okay, else we need to create a spillLocation
626      for it */
627   if (!(sym->remat || sym->usl.spillLoc))
628     createStackSpil (sym);
629   
630   
631   /* mark it has spilt & put it in the spilt set */
632   sym->isspilt = sym->spillA = 1;
633   _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
634   
635   bitVectUnSetBit (_G.regAssigned, sym->key);
636   bitVectUnSetBit (_G.totRegAssigned, sym->key);
637   
638   for (i = 0; i < sym->nRegs; i++)
639     
640     if (sym->regs[i])
641       {
642         freeReg (sym->regs[i], FALSE);
643       }
644   
645   if (sym->usl.spillLoc && !sym->remat)
646     sym->usl.spillLoc->allocreq++;
647   return;
648 }
649
650 /*-----------------------------------------------------------------*/
651 /* selectSpil - select a iTemp to spil : rather a simple procedure */
652 /*-----------------------------------------------------------------*/
653 static symbol *
654 selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
655 {
656   bitVect *lrcs = NULL;
657   set *selectS;
658   symbol *sym;
659   
660   /* get the spillable live ranges */
661   lrcs = computeSpillable (ic);
662   
663   /* get all live ranges that are rematerizable */
664   if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
665     {
666       /* return the least used of these */
667       return leastUsedLR (selectS);
668     }
669   
670   /* if the symbol is local to the block then */
671   if (forSym->liveTo < ebp->lSeq)
672     {
673       
674       /* check if there are any live ranges allocated
675          to registers that are not used in this block */
676       if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
677         {
678           sym = leastUsedLR (selectS);
679           /* if this is not rematerializable */
680           if (!sym->remat)
681             {
682               _G.blockSpil++;
683               sym->blockSpil = 1;
684             }
685           return sym;
686         }
687       
688       /* check if there are any live ranges that not
689          used in the remainder of the block */
690       if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
691         {
692           sym = leastUsedLR (selectS);
693           if (sym != forSym)
694             {
695               if (!sym->remat)
696                 {
697                   sym->remainSpil = 1;
698                   _G.blockSpil++;
699                 }
700               return sym;
701             }
702         }
703     }
704   
705   /* find live ranges with spillocation && not used as pointers */
706   if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
707     {
708       
709       sym = leastUsedLR (selectS);
710       /* mark this as allocation required */
711       sym->usl.spillLoc->allocreq++;
712       return sym;
713     }
714   
715   /* find live ranges with spillocation */
716   if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
717     {
718       
719       sym = leastUsedLR (selectS);
720       sym->usl.spillLoc->allocreq++;
721       return sym;
722     }
723   
724   /* couldn't find then we need to create a spil
725      location on the stack , for which one? the least
726      used ofcourse */
727   if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
728     {
729       
730       /* return a created spil location */
731       sym = createStackSpil (leastUsedLR (selectS));
732       sym->usl.spillLoc->allocreq++;
733       return sym;
734     }
735   
736   /* this is an extreme situation we will spill
737      this one : happens very rarely but it does happen */
738   spillThis (forSym);
739   return forSym;
740 }
741
742 /*-----------------------------------------------------------------*/
743 /* spillSomething - spil some variable & mark registers as free    */
744 /*-----------------------------------------------------------------*/
745 static bool
746 spillSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
747 {
748   symbol *ssym;
749   int i;
750   
751   /* get something we can spil */
752   ssym = selectSpil (ic, ebp, forSym);
753   
754   D1(fprintf (stderr, "  spillSomething: spilling %s\n", ssym->name));
755   
756   /* mark it as spilt */
757   ssym->isspilt = ssym->spillA = 1;
758   _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
759   
760   /* mark it as not register assigned &
761      take it away from the set */
762   //bitVectUnSetBit (_G.regAssigned, ssym->key);
763   //bitVectUnSetBit (_G.totRegAssigned, ssym->key);
764   
765   /* mark the registers as free */
766   for (i = 0; i < ssym->nRegs; i++) {
767     if (ssym->regs[i]) {
768       freeReg (ssym->regs[i], FALSE);
769       // dont NULL ssym->regs[i], it might be used later
770     }
771   }
772   
773   /* if this was a block level spil then insert push & pop 
774      at the start & end of block respectively */
775   if (ssym->blockSpil)
776     {
777       iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
778       /* add push to the start of the block */
779       addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
780                                     ebp->sch->next : ebp->sch));
781       nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
782       /* add pop to the end of the block */
783       addiCodeToeBBlock (ebp, nic, NULL);
784     }
785   
786   /* if spilt because not used in the remainder of the
787      block then add a push before this instruction and
788      a pop at the end of the block */
789   if (ssym->remainSpil)
790     {
791       
792       iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
793       /* add push just before this instruction */
794       addiCodeToeBBlock (ebp, nic, ic);
795       
796       nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
797       /* add pop to the end of the block */
798       addiCodeToeBBlock (ebp, nic, NULL);
799     }
800   
801   if (ssym == forSym)
802     return FALSE;
803   else
804     return TRUE;
805 }
806
807 /*-----------------------------------------------------------------*/
808 /* getRegPtr - will try for PTR if not a GPR type if not spil      */
809 /*-----------------------------------------------------------------*/
810 static bool getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym, short offset) {
811   
812   D0(fprintf (stderr, "getRegPtr: %s ", sym->name));
813   D0(printTypeChain(sym->type, stderr));
814   D0(fprintf (stderr, "\n"));
815   
816   while (1) {
817     /* this looks like an infinite loop but 
818        in really selectSpil will abort  */
819     
820     /* try for a ptr type */
821     if (allocReg (getSize(sym->type), REG_PTR, sym, offset, FALSE))
822       return TRUE;
823     
824     /* try for gpr type */
825     if (xa51HasGprRegs && allocReg (getSize(sym->type), 
826                                     REG_GPR, sym, offset, FALSE))
827       return TRUE;
828     
829     /* we have to spil */
830     if (!spillSomething (ic, ebp, sym))
831       return FALSE;
832     
833   }
834 }
835
836 /*-----------------------------------------------------------------*/
837 /* getRegGpr - will try for GPR if not spil                        */
838 /*-----------------------------------------------------------------*/
839 static bool getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym, short offset) {
840   
841   D0(fprintf (stderr, "getRegGpr: %s ", sym->name));
842   D0(printTypeChain(sym->type, stderr));
843   D0(fprintf (stderr, "\n"));
844   
845   while(1) {
846     /* this looks like an infinite loop but 
847        in really selectSpil will abort  */
848     
849     /* try for gpr type */
850     if (xa51HasGprRegs && allocReg (getSize(sym->type), 
851                                     REG_GPR, sym, offset, FALSE))
852       return TRUE;
853     
854     if (allocReg (getSize(sym->type), REG_PTR, sym, offset, FALSE))
855       return TRUE;
856     
857     /* we have to spil */
858     if (!spillSomething (ic, ebp, sym))
859       return FALSE;
860   }
861 }
862
863 /*-----------------------------------------------------------------*/
864 /* deassignLRs - check the live to and if they have registers & are */
865 /*               not spilt then free up the registers              */
866 /*-----------------------------------------------------------------*/
867 static void
868 deassignLRs (iCode * ic, eBBlock * ebp)
869 {
870   symbol *sym;
871   int k;
872   
873   for (sym = hTabFirstItem (liveRanges, &k); sym;
874        sym = hTabNextItem (liveRanges, &k))
875     {
876       /* if it does not end here */
877       if (sym->liveTo > ic->seq)
878         continue;
879       
880       /* if it was spilt on stack then we can 
881          mark the stack spil location as free */
882       if (sym->isspilt)
883         {
884           if (sym->stackSpil)
885             {
886               sym->usl.spillLoc->isFree = 1;
887               sym->stackSpil = 0;
888             }
889           continue;
890         }
891       
892       if (!bitVectBitValue (_G.regAssigned, sym->key))
893         continue;
894       
895       if (sym->nRegs) {
896         int i;
897         
898         bitVectUnSetBit (_G.regAssigned, sym->key);
899         
900         /* free the regs */
901         for (i=0; i < sym->nRegs; i++) {
902           freeReg (sym->regs[i], FALSE);
903         }
904       }
905     }
906 }
907
908 /*-----------------------------------------------------------------*/
909 /* willCauseSpill - determines if allocating will cause a spill    */
910 /*-----------------------------------------------------------------*/
911 static bool willCauseSpill (symbol *sym) {
912   int i;
913   // do it the rude way
914   if (allocReg (getSize(sym->type), sym->regType, sym, 0, TRUE) ||
915       allocReg (getSize(sym->type), sym->regType==REG_PTR?REG_GPR:REG_PTR, 
916                 sym, 0, TRUE)) {
917     // so we can, but we won't
918     for (i=0; i<sym->nRegs; i++) {
919       freeReg (sym->regs[i], TRUE);
920       sym->regs[i]=NULL;
921     }
922     return FALSE;
923   }
924   D1(fprintf (stderr, "  %s will cause a spill\n", sym->name));
925   return TRUE;
926 }
927
928 /*-----------------------------------------------------------------*/
929 /* positionRegs - the allocator can allocate same registers to res- */
930 /* ult and operand, if this happens make sure they are in the same */
931 /* position as the operand otherwise chaos results                 */
932 /*-----------------------------------------------------------------*/
933 static int
934 positionRegs (symbol * result, symbol * opsym)
935 {
936   int count = min (result->nRegs, opsym->nRegs);
937   int i, j = 0, shared = 0;
938   int changed = 0;
939   
940   /* if the result has been spilt then cannot share */
941   if (opsym->isspilt)
942     return 0;
943  again:
944   shared = 0;
945   /* first make sure that they actually share */
946   for (i = 0; i < count; i++)
947     {
948       for (j = 0; j < count; j++)
949         {
950           if (result->regs[i] == opsym->regs[j] && i != j)
951             {
952               shared = 1;
953               goto xchgPositions;
954             }
955         }
956     }
957  xchgPositions:
958   if (shared)
959     {
960       regs *tmp = result->regs[i];
961       result->regs[i] = result->regs[j];
962       result->regs[j] = tmp;
963       changed ++;
964       D2(fprintf (stderr, "positionRegs: rearranged regs for %s and %s\n",
965                   result->name, opsym->name));
966       goto again;
967     }
968   return changed;
969 }
970
971 /*-----------------------------------------------------------------*/
972 /* serialRegAssign - serially allocate registers to the variables  */
973 /*-----------------------------------------------------------------*/
974 static void
975 serialRegAssign (eBBlock ** ebbs, int count)
976 {
977   int i;
978   
979   /* for all blocks */
980   for (i = 0; i < count; i++) {
981     
982     iCode *ic;
983     
984     if (ebbs[i]->noPath &&
985         (ebbs[i]->entryLabel != entryLabel &&
986          ebbs[i]->entryLabel != returnLabel))
987       continue;
988     
989     /* of all instructions do */
990     for (ic = ebbs[i]->sch; ic; ic = ic->next) {
991       
992       /* if result is present && is a true symbol */
993       if (IC_RESULT (ic) && ic->op != IFX &&
994           IS_TRUE_SYMOP (IC_RESULT (ic))) {
995         OP_SYMBOL (IC_RESULT (ic))->allocreq++;
996       }
997       
998       /* take away registers from live
999          ranges that end at this instruction */
1000       deassignLRs (ic, ebbs[i]);
1001       
1002       /* some don't need registers */
1003       if (SKIP_IC2 (ic) ||
1004           ic->op == JUMPTABLE ||
1005           ic->op == IFX ||
1006           ic->op == IPUSH ||
1007           ic->op == IPOP ||
1008           (IC_RESULT (ic) && POINTER_SET (ic)))
1009         continue;
1010       
1011       /* now we need to allocate registers
1012          only for the result */
1013       if (IC_RESULT (ic)) {
1014         symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1015         bitVect *spillable;
1016         int willCS;
1017         
1018         /* if it does not need or is spilt 
1019            or is already assigned to registers
1020            or will not live beyond this instructions */
1021         if (!sym->nRegs ||
1022             sym->isspilt ||
1023             bitVectBitValue (_G.regAssigned, sym->key) ||
1024             sym->liveTo <= ic->seq)
1025           continue;
1026         
1027         /* if some liverange has been spilt at the block level
1028            and this one live beyond this block then spil this
1029            to be safe */
1030         if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) {
1031           spillThis (sym);
1032           continue;
1033         }
1034         /* if trying to allocate this will cause
1035            a spill and there is nothing to spill 
1036            or this one is rematerializable then
1037            spill this one */
1038         willCS = willCauseSpill (sym);
1039         spillable = computeSpillable (ic);
1040         if (sym->remat || (willCS && bitVectIsZero (spillable))) {                    
1041           spillThis (sym);
1042           continue;                   
1043         }
1044         
1045         /* if it has a spillocation & is used less than
1046            all other live ranges then spill this */
1047         if (willCS) {
1048           if (sym->usl.spillLoc) {
1049             symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
1050                                                              allLRs, ebbs[i], ic));
1051             if (leastUsed && leastUsed->used > sym->used) {
1052               spillThis (sym);
1053               continue;
1054             }
1055           } else {
1056             /* if none of the liveRanges have a spillLocation then better
1057                to spill this one than anything else already assigned to registers */
1058             if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
1059               /* if this is local to this block then we might find a block spil */
1060               if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
1061                 spillThis (sym);
1062                 continue;
1063               }
1064             }
1065           }
1066         }
1067         
1068         /* else we assign registers to it */
1069         _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
1070         _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
1071         
1072         if (sym->regType == REG_PTR)
1073           getRegPtr (ic, ebbs[i], sym, 0);
1074         else
1075           getRegGpr (ic, ebbs[i], sym, 0);
1076         
1077         /* if it shares registers with operands make sure
1078            that they are in the same position */
1079         if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
1080             OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') {
1081           positionRegs (OP_SYMBOL (IC_RESULT (ic)),
1082                         OP_SYMBOL (IC_LEFT (ic)));
1083         }
1084         /* do the same for the right operand */
1085         if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
1086             OP_SYMBOL (IC_RIGHT (ic))->nRegs) {
1087           positionRegs (OP_SYMBOL (IC_RESULT (ic)),
1088                         OP_SYMBOL (IC_RIGHT (ic)));
1089         }
1090       }
1091     }
1092   }
1093 }
1094
1095 /*-----------------------------------------------------------------*/
1096 /* rUmaskForOp :- returns register mask for an operand             */
1097 /*-----------------------------------------------------------------*/
1098 bitVect *xa51_rUmaskForOp (operand * op) {
1099   bitVect *rumask;
1100   symbol *sym;
1101   int j;
1102   
1103   /* only temporaries are assigned registers */
1104   if (!IS_ITEMP (op))
1105     return NULL;
1106   
1107   sym = OP_SYMBOL (op);
1108   
1109   /* if spilt or no registers assigned to it 
1110      then nothing */
1111   if (sym->isspilt || !sym->nRegs || !sym->regs[0])
1112     return NULL;
1113   
1114   rumask = newBitVect (xa51_nRegs);
1115   
1116   for (j = 0; j < sym->nRegs; j++) {
1117     rumask = bitVectSetBit (rumask,
1118                             sym->regs[j]->rIdx);
1119   }
1120   return rumask;
1121 }
1122
1123 /*-----------------------------------------------------------------*/
1124 /* regsUsedIniCode :- returns bit vector of registers used in iCode */
1125 /*-----------------------------------------------------------------*/
1126 static bitVect *
1127 regsUsedIniCode (iCode * ic)
1128 {
1129   bitVect *rmask = newBitVect (xa51_nRegs);
1130   
1131   /* do the special cases first */
1132   if (ic->op == IFX)
1133     {
1134       rmask = bitVectUnion (rmask,
1135                             xa51_rUmaskForOp (IC_COND (ic)));
1136       goto ret;
1137     }
1138   
1139   /* for the jumptable */
1140   if (ic->op == JUMPTABLE)
1141     {
1142       rmask = bitVectUnion (rmask,
1143                             xa51_rUmaskForOp (IC_JTCOND (ic)));
1144       
1145       goto ret;
1146     }
1147   
1148   /* of all other cases */
1149   if (IC_LEFT (ic))
1150     rmask = bitVectUnion (rmask,
1151                           xa51_rUmaskForOp (IC_LEFT (ic)));
1152   
1153   
1154   if (IC_RIGHT (ic))
1155     rmask = bitVectUnion (rmask,
1156                           xa51_rUmaskForOp (IC_RIGHT (ic)));
1157   
1158   if (IC_RESULT (ic))
1159     rmask = bitVectUnion (rmask,
1160                           xa51_rUmaskForOp (IC_RESULT (ic)));
1161   
1162  ret:
1163   return rmask;
1164 }
1165
1166 /*-----------------------------------------------------------------*/
1167 /* createRegMask - for each instruction will determine the regsUsed */
1168 /*-----------------------------------------------------------------*/
1169 static void
1170 createRegMask (eBBlock ** ebbs, int count)
1171 {
1172   int i;
1173   
1174   /* for all blocks */
1175   for (i = 0; i < count; i++)
1176     {
1177       iCode *ic;
1178       
1179       if (ebbs[i]->noPath &&
1180           (ebbs[i]->entryLabel != entryLabel &&
1181            ebbs[i]->entryLabel != returnLabel))
1182         continue;
1183       
1184       /* for all instructions */
1185       for (ic = ebbs[i]->sch; ic; ic = ic->next)
1186         {
1187           
1188           int j;
1189           
1190           if (SKIP_IC2 (ic) || !ic->rlive)
1191             continue;
1192           
1193           /* first mark the registers used in this
1194              instruction */
1195           ic->rUsed = regsUsedIniCode (ic);
1196           _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
1197           
1198           /* now create the register mask for those 
1199              registers that are in use : this is a
1200              super set of ic->rUsed */
1201           ic->rMask = newBitVect (xa51_nRegs + 1);
1202           
1203           /* for all live Ranges alive at this point */
1204           for (j = 1; j < ic->rlive->size; j++)
1205             {
1206               symbol *sym;
1207               int k;
1208               
1209               /* if not alive then continue */
1210               if (!bitVectBitValue (ic->rlive, j))
1211                 continue;
1212               
1213               /* find the live range we are interested in */
1214               if (!(sym = hTabItemWithKey (liveRanges, j)))
1215                 {
1216                   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1217                           "createRegMask cannot find live range");
1218                   exit (0);
1219                 }
1220               
1221               /* if no register assigned to it */
1222               if (!sym->nRegs || sym->isspilt)
1223                 continue;
1224               
1225               /* for all the registers allocated to it */
1226               for (k = 0; k < sym->nRegs; k++)
1227                 if (sym->regs[k])
1228                   ic->rMask =
1229                     bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
1230             }
1231         }
1232     }
1233 }
1234
1235 /*-----------------------------------------------------------------*/
1236 /* rematStr - returns the rematerialized string for a remat var    */
1237 /*-----------------------------------------------------------------*/
1238 static char *
1239 rematStr (symbol * sym)
1240 {
1241   char *s = buffer;
1242   iCode *ic = sym->rematiCode;
1243   
1244   while (1)
1245     {
1246       
1247       /* if plus or minus print the right hand side */
1248       if (ic->op == '+' || ic->op == '-')
1249         {
1250           sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
1251                    ic->op);
1252           s += strlen (s);
1253           ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1254           continue;
1255         }
1256       
1257       /* cast then continue */
1258       if (IS_CAST_ICODE(ic)) {
1259         ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1260         continue;
1261       }
1262       /* we reached the end */
1263       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
1264       break;
1265     }
1266   
1267   return buffer;
1268 }
1269
1270 /*-----------------------------------------------------------------*/
1271 /* regTypeNum - computes the type & number of registers required   */
1272 /*-----------------------------------------------------------------*/
1273 static void
1274 regTypeNum (eBBlock *ebbs)
1275 {
1276   symbol *sym;
1277   int k;
1278   iCode *ic;
1279   
1280   /* for each live range do */
1281   for (sym = hTabFirstItem (liveRanges, &k); sym;
1282        sym = hTabNextItem (liveRanges, &k))
1283     {
1284       
1285       /* if used zero times then no registers needed */
1286       if ((sym->liveTo - sym->liveFrom) == 0)
1287         continue;
1288       
1289       
1290       /* if the live range is a temporary */
1291       if (sym->isitmp)
1292         {
1293           
1294           /* if the type is marked as a conditional */
1295           if (sym->regType == REG_CND)
1296             continue;
1297           
1298           /* if used in return only then we don't 
1299              need registers */
1300 #if 0 // not yet
1301           if (sym->ruonly || sym->accuse)
1302             {
1303               if (IS_AGGREGATE (sym->type) || sym->isptr)
1304                 sym->type = aggrToPtr (sym->type, FALSE);
1305               continue;
1306             }
1307 #endif
1308           
1309           /* if the symbol has only one definition &
1310              that definition is a get_pointer */
1311           if (bitVectnBitsOn (sym->defs) == 1 &&
1312               (ic = hTabItemWithKey (iCodehTab,
1313                                      bitVectFirstBit (sym->defs))) &&
1314               POINTER_GET (ic) &&
1315               !sym->noSpilLoc &&
1316               !IS_BITVAR (sym->etype))
1317             {
1318               /* and that pointer is remat in data space */
1319               if (OP_SYMBOL (IC_LEFT (ic))->remat &&
1320                   !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
1321                   DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER)
1322                 {
1323                   /* create a psuedo symbol & force a spil */
1324                   symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
1325                   psym->type = sym->type;
1326                   psym->etype = sym->etype;
1327                   strcpy (psym->rname, psym->name);
1328                   sym->isspilt = 1;
1329                   sym->usl.spillLoc = psym;
1330 #if 0 // an alternative fix for bug #480076
1331                   /* now this is a useless assignment to itself */
1332                   remiCodeFromeBBlock (ebbs, ic);
1333 #else
1334                   /* now this really is an assignment to itself, make it so;
1335                      it will be optimized out later */
1336                   ic->op='=';
1337                   IC_RIGHT(ic)=IC_RESULT(ic);
1338                   IC_LEFT(ic)=NULL;
1339 #endif
1340                   continue;
1341                 }
1342               
1343               /* if in data space or idata space then try to
1344                  allocate pointer register */
1345               
1346             }
1347           
1348           /* if not then we require registers */
1349 #if 0
1350           sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
1351                         getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
1352                         getSize (sym->type));
1353 #else
1354           {
1355             int size=((IS_AGGREGATE (sym->type) || sym->isptr) ?
1356                       getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
1357                       getSize (sym->type));
1358             switch (size) 
1359               {
1360               case 1: // byte
1361               case 2: // word or pointer
1362                 sym->nRegs=1;
1363                 break;
1364               case 3: // generic pointer
1365                 sym->nRegs=2;
1366                 break;
1367               case 4: // dword or float
1368                 sym->nRegs=2;
1369                 break;
1370               default: 
1371                 fprintf (stderr, "regTypeNum: unknown size\n");
1372                 exit (1);
1373               }
1374           }
1375 #endif
1376           
1377           if (sym->nRegs > 4)
1378             {
1379               fprintf (stderr, "allocated more than 4 or 0 registers for type ");
1380               printTypeChain (sym->type, stderr);
1381               fprintf (stderr, "\n");
1382               exit (1);
1383             }
1384           
1385           /* determine the type of register required */
1386           if (IS_PTR (sym->type))
1387             sym->regType = REG_PTR;
1388           else
1389             sym->regType = REG_GPR;
1390           
1391         }
1392       else
1393         /* for the first run we don't provide */
1394         /* registers for true symbols we will */
1395         /* see how things go                  */
1396         sym->nRegs = 0;
1397     }
1398   
1399 }
1400
1401 /*-----------------------------------------------------------------*/
1402 /* deallocStackSpil - this will set the stack pointer back         */
1403 /*-----------------------------------------------------------------*/
1404 static
1405 DEFSETFUNC (deallocStackSpil)
1406 {
1407   symbol *sym = item;
1408   
1409   deallocLocal (sym);
1410   return 0;
1411 }
1412
1413 /*-----------------------------------------------------------------*/
1414 /* packRegsForAssign - register reduction for assignment           */
1415 /*-----------------------------------------------------------------*/
1416 static int
1417 packRegsForAssign (iCode * ic, eBBlock * ebp)
1418 {
1419   iCode *dic, *sic;
1420   
1421   if (!IS_ITEMP (IC_RIGHT (ic)) ||
1422       OP_LIVETO (IC_RIGHT (ic)) > ic->seq) {
1423     return 0;
1424   }
1425
1426   /* find the definition of iTempNN scanning backwards */
1427   for (dic = ic->prev; dic; dic = dic->prev) {
1428     
1429     /* if there is a function call then don't pack it */
1430     if ((dic->op == CALL || dic->op == PCALL)) {
1431       dic = NULL;
1432       break;
1433     }
1434     
1435     if (SKIP_IC2 (dic))
1436       continue;
1437     
1438     if (IS_SYMOP (IC_RESULT (dic)) &&
1439         IC_RESULT (dic)->key == IC_RIGHT (ic)->key) {
1440       break;
1441     }
1442     
1443   }
1444   
1445   if (!dic)
1446     return 0;                   /* did not find */
1447
1448   /* found the definition */
1449   /* replace the result with the result of */
1450   /* this assignment and remove this assignment */
1451   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1452   IC_RESULT (dic) = IC_RESULT (ic);
1453   
1454   if (IS_ITEMP (IC_RESULT (dic)) && 
1455       OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
1456     {
1457       OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
1458     }
1459   /* delete from liverange table also 
1460      delete from all the points inbetween and the new
1461      one */
1462   for (sic = dic; sic != ic; sic = sic->next)
1463     {
1464       bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
1465       if (IS_ITEMP (IC_RESULT (dic)))
1466         bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
1467     }
1468   
1469   remiCodeFromeBBlock (ebp, ic);
1470   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
1471   hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
1472   OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
1473   return 1;
1474   
1475 }
1476
1477 /*-----------------------------------------------------------------*/
1478 /* findAssignToSym : scanning backwards looks for first assig found */
1479 /*-----------------------------------------------------------------*/
1480 static iCode *
1481 findAssignToSym (operand * op, iCode * ic)
1482 {
1483   iCode *dic;
1484   
1485   for (dic = ic->prev; dic; dic = dic->prev)
1486     {
1487       
1488       /* if definition by assignment */
1489       if (dic->op == '=' &&
1490           !POINTER_SET (dic) &&
1491           IC_RESULT (dic)->key == op->key
1492           /*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
1493           )
1494         {
1495           
1496           /* we are interested only if defined in far space */
1497           /* or in stack space in case of + & - */
1498           
1499           /* if assigned to a non-symbol then return
1500              FALSE */
1501           if (!IS_SYMOP (IC_RIGHT (dic)))
1502             return NULL;
1503           
1504           /* if the symbol is in far space then
1505              we should not */
1506           if (isOperandInFarSpace (IC_RIGHT (dic)))
1507             return NULL;
1508           
1509           /* for + & - operations make sure that
1510              if it is on the stack it is the same
1511              as one of the three operands */
1512           if ((ic->op == '+' || ic->op == '-') &&
1513               OP_SYMBOL (IC_RIGHT (dic))->onStack)
1514             {
1515               
1516               if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
1517                   IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
1518                   IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
1519                 return NULL;
1520             }
1521           
1522           break;
1523           
1524         }
1525       
1526       /* if we find an usage then we cannot delete it */
1527       if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
1528         return NULL;
1529       
1530       if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
1531         return NULL;
1532       
1533       if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
1534         return NULL;
1535     }
1536   
1537   /* now make sure that the right side of dic
1538      is not defined between ic & dic */
1539   if (dic)
1540     {
1541       iCode *sic = dic->next;
1542       
1543       for (; sic != ic; sic = sic->next)
1544         if (IC_RESULT (sic) &&
1545             IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
1546           return NULL;
1547     }
1548   
1549   return dic;
1550   
1551   
1552 }
1553
1554 /*-----------------------------------------------------------------*/
1555 /* packRegsForSupport :- reduce some registers for support calls   */
1556 /*-----------------------------------------------------------------*/
1557 static int
1558 packRegsForSupport (iCode * ic, eBBlock * ebp)
1559 {
1560   int change = 0;
1561   iCode *dic, *sic;
1562   
1563   /* for the left & right operand :- look to see if the
1564      left was assigned a true symbol in far space in that
1565      case replace them */
1566
1567   if (IS_ITEMP (IC_LEFT (ic)) &&
1568       OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
1569     {
1570       dic = findAssignToSym (IC_LEFT (ic), ic);
1571       
1572       if (!dic)
1573         goto right;
1574       
1575       /* found it we need to remove it from the
1576          block */
1577       for (sic = dic; sic != ic; sic = sic->next)
1578         bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
1579       
1580       OP_SYMBOL(IC_LEFT (ic))=OP_SYMBOL(IC_RIGHT (dic));
1581       IC_LEFT (ic)->key = OP_SYMBOL(IC_RIGHT (dic))->key;
1582       remiCodeFromeBBlock (ebp, dic);
1583       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1584       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1585       change++;
1586     }
1587   
1588   /* do the same for the right operand */
1589  right:
1590   if (!change &&
1591       IS_ITEMP (IC_RIGHT (ic)) &&
1592       OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
1593     {
1594       iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
1595       iCode *sic;
1596       
1597       if (!dic)
1598         return change;
1599       
1600       /* if this is a subtraction & the result
1601          is a true symbol in far space then don't pack */
1602       if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
1603         {
1604           sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
1605           if (IN_FARSPACE (SPEC_OCLS (etype)))
1606             return change;
1607         }
1608       /* found it we need to remove it from the
1609          block */
1610       for (sic = dic; sic != ic; sic = sic->next)
1611         bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
1612       
1613       IC_RIGHT (ic)->operand.symOperand =
1614         IC_RIGHT (dic)->operand.symOperand;
1615       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
1616       
1617       remiCodeFromeBBlock (ebp, dic);
1618       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1619       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1620       change++;
1621     }
1622   
1623   return change;
1624 }
1625
1626 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1627
1628
1629 /*-----------------------------------------------------------------*/
1630 /* packRegsForOneuse : - will reduce some registers for single Use */
1631 /*-----------------------------------------------------------------*/
1632 static iCode *
1633 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
1634 {
1635   bitVect *uses;
1636   iCode *dic, *sic;
1637
1638   /* if returning a literal then do nothing */
1639   if (!IS_SYMOP (op))
1640     return NULL;
1641   
1642   if (ic->op != RETURN &&
1643       ic->op != SEND &&
1644       !POINTER_SET (ic) &&
1645       !POINTER_GET (ic))
1646     return NULL;
1647   
1648   /* this routine will mark the a symbol as used in one 
1649      instruction use only && if the defintion is local 
1650      (ie. within the basic block) && has only one definition &&
1651      that definiion is either a return value from a 
1652      function or does not contain any variables in
1653      far space */
1654   uses = bitVectCopy (OP_USES (op));
1655   bitVectUnSetBit (uses, ic->key);      /* take away this iCode */
1656   if (!bitVectIsZero (uses))    /* has other uses */
1657     return NULL;
1658   
1659   /* if it has only one defintion */
1660   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
1661     return NULL;                /* has more than one definition */
1662   
1663   /* get that definition */
1664   if (!(dic =
1665         hTabItemWithKey (iCodehTab,
1666                          bitVectFirstBit (OP_DEFS (op)))))
1667     return NULL;
1668   
1669 #if 0
1670   /* if that only usage is a cast */
1671   if (dic->op == CAST) {
1672     /* to a bigger type */
1673     if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > 
1674         getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
1675       /* than we can not, since we cannot predict the usage of b & acc */
1676       return NULL;
1677     }
1678   }
1679 #endif
1680   
1681   /* found the definition now check if it is local */
1682   if (dic->seq < ebp->fSeq ||
1683       dic->seq > ebp->lSeq)
1684     return NULL;                /* non-local */
1685   
1686   /* now check if it is the return from
1687      a function call */
1688   if (dic->op == CALL || dic->op == PCALL)
1689     {
1690       if (ic->op != SEND && ic->op != RETURN &&
1691           !POINTER_SET(ic) && !POINTER_GET(ic))
1692         {
1693           OP_SYMBOL (op)->ruonly = 1;
1694           return dic;
1695         }
1696       dic = dic->next;
1697     }
1698   
1699 #if 0  
1700   /* otherwise check that the definition does
1701      not contain any symbols in far space */
1702   if (isOperandInFarSpace (IC_LEFT (dic)) ||
1703       isOperandInFarSpace (IC_RIGHT (dic)) ||
1704       IS_OP_RUONLY (IC_LEFT (ic)) ||
1705       IS_OP_RUONLY (IC_RIGHT (ic)))
1706     {
1707       return NULL;
1708     }
1709 #endif
1710
1711 #if 0  
1712   /* if pointer set then make sure the pointer
1713      is one byte */
1714   if (POINTER_SET (dic) &&
1715       !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
1716     return NULL;
1717   
1718   if (POINTER_GET (dic) &&
1719       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
1720     return NULL;
1721 #endif
1722   
1723   sic = dic;
1724   
1725   /* also make sure the intervenening instructions
1726      don't have any thing in far space */
1727   for (dic = dic->next; dic && dic != ic && sic != ic; dic = dic->next)
1728     {
1729       
1730       /* if there is an intervening function call then no */
1731       if (dic->op == CALL || dic->op == PCALL)
1732         return NULL;
1733
1734 #if 0
1735       /* if pointer set then make sure the pointer
1736          is one byte */
1737       if (POINTER_SET (dic) &&
1738           !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
1739         return NULL;
1740       
1741       if (POINTER_GET (dic) &&
1742           !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
1743         return NULL;
1744 #endif
1745       
1746       /* if address of & the result is remat the okay */
1747       if (dic->op == ADDRESS_OF &&
1748           OP_SYMBOL (IC_RESULT (dic))->remat)
1749         continue;
1750
1751 #if 0      
1752       /* if operand has size of three or more & this
1753          operation is a '*','/' or '%' then 'b' may
1754          cause a problem */
1755       if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
1756           getSize (operandType (op)) >= 3)
1757         return NULL;
1758 #endif
1759       
1760 #if 0
1761       /* if left or right or result is in far space */
1762       if (isOperandInFarSpace (IC_LEFT (dic)) ||
1763           isOperandInFarSpace (IC_RIGHT (dic)) ||
1764           isOperandInFarSpace (IC_RESULT (dic)) ||
1765           IS_OP_RUONLY (IC_LEFT (dic)) ||
1766           IS_OP_RUONLY (IC_RIGHT (dic)) ||
1767           IS_OP_RUONLY (IC_RESULT (dic)))
1768         {
1769           return NULL;
1770         }
1771       /* if left or right or result is on stack */
1772       if (isOperandOnStack(IC_LEFT(dic)) ||
1773           isOperandOnStack(IC_RIGHT(dic)) ||
1774           isOperandOnStack(IC_RESULT(dic))) {
1775         return NULL;
1776       }
1777 #endif
1778     }
1779   
1780   OP_SYMBOL (op)->ruonly = 1;
1781   fprintf (stderr, "%s is used only once in line %d.\n", 
1782            OP_SYMBOL(op)->name, ic->lineno);
1783   return sic;
1784   
1785 }
1786
1787 /*-----------------------------------------------------------------*/
1788 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
1789 /*-----------------------------------------------------------------*/
1790 static bool
1791 isBitwiseOptimizable (iCode * ic)
1792 {
1793   sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
1794   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
1795   
1796   /* bitwise operations are considered optimizable
1797      under the following conditions (Jean-Louis VERN) 
1798      
1799      x & lit
1800      bit & bit
1801      bit & x
1802      bit ^ bit
1803      bit ^ x
1804      x   ^ lit
1805      x   | lit
1806      bit | bit
1807      bit | x
1808   */
1809   if (IS_LITERAL(rtype) ||
1810       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
1811     return TRUE;
1812   else
1813     return FALSE;
1814 }
1815
1816 /*-----------------------------------------------------------------*/
1817 /* packForPush - hueristics to reduce iCode for pushing            */
1818 /*-----------------------------------------------------------------*/
1819 static void
1820 packForPush (iCode * ic, eBBlock * ebp)
1821 {
1822   iCode *dic, *lic;
1823   bitVect *dbv;
1824
1825   if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
1826     return;
1827   
1828   /* must have only definition & one usage */
1829   if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
1830       bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
1831     return;
1832   
1833   /* find the definition */
1834   if (!(dic = hTabItemWithKey (iCodehTab,
1835                                bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
1836     return;
1837   
1838   if (dic->op != '=' || POINTER_SET (dic))
1839     return;
1840   
1841   /* make sure the right side does not have any definitions
1842      inbetween */
1843   dbv = OP_DEFS(IC_RIGHT(dic));
1844   for (lic = ic; lic && lic != dic ; lic = lic->prev) {
1845     if (bitVectBitValue(dbv,lic->key)) 
1846       return ;
1847   }
1848   /* make sure they have the same type */
1849   {
1850     sym_link *itype=operandType(IC_LEFT(ic));
1851     sym_link *ditype=operandType(IC_RIGHT(dic));
1852     
1853     if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
1854         SPEC_LONG(itype)!=SPEC_LONG(ditype))
1855       return;
1856   }
1857   /* extend the live range of replaced operand if needed */
1858   if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) {
1859     OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
1860   }
1861   /* we now know that it has one & only one def & use
1862      and the that the definition is an assignment */
1863   IC_LEFT (ic) = IC_RIGHT (dic);
1864   
1865   remiCodeFromeBBlock (ebp, dic);
1866   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1867   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1868 }
1869
1870 /*-----------------------------------------------------------------*/
1871 /* packRegisters - does some transformations to reduce register    */
1872 /*                   pressure                                      */
1873 /*-----------------------------------------------------------------*/
1874 static void packRegisters (eBBlock * ebp) {
1875   iCode *ic;
1876   int change = 0;
1877   
1878   while (1) {
1879     change = 0;
1880     
1881     for (ic = ebp->sch; ic; ic = ic->next) {
1882       if (ic->op == '=')
1883         change += packRegsForAssign (ic, ebp);
1884     }
1885     
1886     if (!change)
1887       break;
1888   }
1889   
1890   for (ic = ebp->sch; ic; ic = ic->next)
1891     {
1892       /* if the condition of an if instruction
1893          is defined in the previous instruction and
1894          this is the only usage then
1895          mark the itemp as a conditional */
1896       if ((IS_CONDITIONAL (ic) ||
1897            (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic)))) {
1898         if (ic->next && ic->next->op == IFX &&
1899             bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
1900             isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
1901             OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq) {
1902           OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
1903           continue;
1904         }
1905       }
1906
1907 #if 0
1908       /* if this is an itemp & result of an address of a true sym 
1909          then mark this as rematerialisable   */
1910       if (ic->op == ADDRESS_OF &&
1911           IS_ITEMP (IC_RESULT (ic)) &&
1912           IS_TRUE_SYMOP (IC_LEFT (ic)) &&
1913           bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
1914           !OP_SYMBOL (IC_LEFT (ic))->onStack)
1915         {
1916           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1917           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1918           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1919         }
1920
1921       /* if straight assignment then carry remat flag if
1922          this is the only definition */
1923       if (ic->op == '=' &&
1924           !POINTER_SET (ic) &&
1925           IS_SYMOP (IC_RIGHT (ic)) &&
1926           OP_SYMBOL (IC_RIGHT (ic))->remat &&
1927           !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
1928           bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
1929         {
1930           
1931           OP_SYMBOL (IC_RESULT (ic))->remat =
1932             OP_SYMBOL (IC_RIGHT (ic))->remat;
1933           OP_SYMBOL (IC_RESULT (ic))->rematiCode =
1934             OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1935         }
1936       
1937       /* if cast to a generic pointer & the pointer being
1938          cast is remat, then we can remat this cast as well */
1939       if (ic->op == CAST && 
1940           IS_SYMOP(IC_RIGHT(ic)) &&
1941           OP_SYMBOL(IC_RIGHT(ic))->remat ) {
1942         sym_link *to_type = operandType(IC_LEFT(ic));
1943         sym_link *from_type = operandType(IC_RIGHT(ic));
1944         if (IS_GENPTR(to_type) && IS_PTR(from_type)) {                
1945           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1946           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1947           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1948         }
1949       }
1950       
1951       /* if this is a +/- operation with a rematerizable 
1952          then mark this as rematerializable as well */
1953       if ((ic->op == '+' || ic->op == '-') &&
1954           (IS_SYMOP (IC_LEFT (ic)) &&
1955            IS_ITEMP (IC_RESULT (ic)) &&
1956            IS_OP_LITERAL (IC_RIGHT (ic))) &&
1957           OP_SYMBOL (IC_LEFT (ic))->remat &&
1958           (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
1959           bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1)
1960         {
1961           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1962           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1963           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1964         }
1965 #endif
1966       
1967       /* mark the pointer usages */
1968       if (POINTER_SET (ic))
1969         OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
1970       
1971       if (POINTER_GET (ic))
1972         OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
1973       
1974       /* reduce for support function calls */
1975       if (ic->supportRtn || ic->op == '+' || ic->op == '-')
1976         packRegsForSupport (ic, ebp);
1977       
1978       /* some cases the redundant moves can
1979          can be eliminated for return statements */
1980       if (ic->op == RETURN || ic->op == SEND) {
1981           packRegsForOneuse (ic, IC_LEFT (ic), ebp);
1982         }
1983       
1984       /* if pointer set & left has a size more than
1985          one and right is not in far space */
1986       if (POINTER_SET (ic) &&
1987           !isOperandInFarSpace (IC_RIGHT (ic)) &&
1988           !OP_SYMBOL (IC_RESULT (ic))->remat &&
1989           !IS_OP_RUONLY (IC_RIGHT (ic)) &&
1990           getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
1991         
1992         packRegsForOneuse (ic, IC_RESULT (ic), ebp);
1993       
1994       /* if pointer get */
1995       if (POINTER_GET (ic) &&
1996           !isOperandInFarSpace (IC_RESULT (ic)) &&
1997           !OP_SYMBOL (IC_LEFT (ic))->remat &&
1998           !IS_OP_RUONLY (IC_RESULT (ic)) &&
1999           getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
2000         
2001         packRegsForOneuse (ic, IC_LEFT (ic), ebp);
2002       
2003       
2004       /* if this is cast for intergral promotion then
2005          check if only use of  the definition of the 
2006          operand being casted/ if yes then replace
2007          the result of that arithmetic operation with 
2008          this result and get rid of the cast */
2009       if (ic->op == CAST)
2010         {
2011           sym_link *fromType = operandType (IC_RIGHT (ic));
2012           sym_link *toType = operandType (IC_LEFT (ic));
2013           
2014           if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
2015               getSize (fromType) != getSize (toType) &&
2016               SPEC_USIGN (fromType) == SPEC_USIGN (toType))
2017             {
2018               
2019               iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
2020               if (dic)
2021                 {
2022                   if (IS_ARITHMETIC_OP (dic))
2023                     {                  
2024                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
2025                       IC_RESULT (dic) = IC_RESULT (ic);
2026                       remiCodeFromeBBlock (ebp, ic);
2027                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
2028                       hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
2029                       OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
2030                       ic = ic->prev;
2031                     }
2032                   else
2033                     OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
2034                 }
2035             }
2036           else
2037             {
2038               
2039               /* if the type from and type to are the same
2040                  then if this is the only use then packit */
2041               if (compareType (operandType (IC_RIGHT (ic)),
2042                                operandType (IC_LEFT (ic))) == 1)
2043                 {
2044                   iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
2045                   if (dic)
2046                     {
2047                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
2048                       IC_RESULT (dic) = IC_RESULT (ic);
2049                       remiCodeFromeBBlock (ebp, ic);
2050                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
2051                       hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
2052                       OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
2053                       ic = ic->prev;
2054                     }
2055                 }
2056             }
2057         }
2058       
2059       /* pack for PUSH 
2060          iTempNN := (some variable in farspace) V1
2061          push iTempNN ;
2062          -------------
2063          push V1
2064       */
2065       if (ic->op == IPUSH)
2066         {
2067           packForPush (ic, ebp);
2068         }
2069     }
2070 }
2071
2072 /*-----------------------------------------------------------------*/
2073 /* assignRegisters - assigns registers to each live range as need  */
2074 /*-----------------------------------------------------------------*/
2075 void
2076 xa51_assignRegisters (eBBlock ** ebbs, int count)
2077 {
2078   iCode *ic;
2079   int i;
2080   
2081   setToNull ((void *) &_G.funcrUsed);
2082   setToNull ((void *) &_G.totRegAssigned);
2083   _G.stackExtend = 0;
2084   
2085   /* change assignments this will remove some
2086      live ranges reducing some register pressure */
2087   for (i = 0; i < count; i++)
2088     packRegisters (ebbs[i]);
2089   
2090   if (options.dump_pack)
2091     dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
2092   
2093   /* first determine for each live range the number of 
2094      registers & the type of registers required for each */
2095   regTypeNum (*ebbs);
2096   
2097   /* and serially allocate registers */
2098   serialRegAssign (ebbs, count);
2099   
2100   freeAllRegs ();
2101   
2102   /* if stack was extended then tell the user */
2103   if (_G.stackExtend)
2104     {
2105       werror(I_EXTENDED_STACK_SPILS,
2106              _G.stackExtend,currFunc->name,"");
2107       _G.stackExtend = 0;
2108     }
2109   
2110   /* after that create the register mask
2111      for each of the instruction */
2112   createRegMask (ebbs, count);
2113   
2114   /* redo that offsets for stacked automatic variables */
2115   redoStackOffsets ();
2116   
2117   if (options.dump_rassgn)
2118     {
2119       dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
2120       dumpLiveRanges (DUMP_LRANGE, liveRanges);
2121     }
2122   
2123   /* do the overlaysegment stuff SDCCmem.c */
2124   doOverlays (ebbs, count);
2125   
2126   /* now get back the chain */
2127   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
2128   
2129   genXA51Code (ic);
2130   
2131   /* free up any _G.stackSpil locations allocated */
2132   applyToSet (_G.stackSpil, deallocStackSpil);
2133   _G.slocNum = 0;
2134   setToNull ((void **) &_G.stackSpil);
2135   setToNull ((void **) &_G.spiltSet);
2136   /* mark all registers as free */
2137   freeAllRegs ();
2138   
2139   return;
2140 }