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