fixed bug #510826
[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
987             /* take away registers from live
988                ranges that end at this instruction */
989             deassignLRs (ic, ebbs[i]);
990
991             /* some don't need registers */
992             if (SKIP_IC2 (ic) ||
993                 ic->op == JUMPTABLE ||
994                 ic->op == IFX ||
995                 ic->op == IPUSH ||
996                 ic->op == IPOP ||
997                 (IC_RESULT (ic) && POINTER_SET (ic)))
998                 continue;
999
1000 #if 0
1001             /* xa51 has advance compare instructions */
1002             if (ic->op == '<' || ic->op == '>' || 
1003                 ic->op == LE_OP || ic->op == GE_OP ||
1004                 ic->op == NE_OP || ic->op == EQ_OP) {
1005               /* if this result is only used for an ifx, we don't
1006                  need registers nor the ifx */
1007               int used=bitVectnBitsOn(OP_SYMBOL(IC_RESULT(ic))->uses);
1008               iCode *nic;
1009               if (used!=1) {
1010                 fprintf (stderr, "unexpected \"used\" for cmp:%d\n", ic->op);
1011                 exit (1);
1012               }
1013               // find the ifx
1014               for (nic=ic->next; nic; nic=nic->next) {
1015                 if (nic->op == IFX) {
1016                   break;
1017                 }
1018               }
1019               if (!nic) {
1020                 // we are in big trouble
1021                 fprintf (stderr, "No ifx found for %d\n",
1022                          ic->op);
1023                 exit (1);
1024               }
1025               // remove the ifx
1026               nic->prev->next=nic->next;
1027               if (nic->next) {
1028                 nic->next->prev=nic->prev;
1029               }
1030             }
1031 #endif
1032
1033             /* now we need to allocate registers
1034                only for the result */
1035             if (IC_RESULT (ic)) {
1036                 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1037                 bitVect *spillable;
1038                 int willCS;
1039
1040                 /* if it does not need or is spilt 
1041                    or is already assigned to registers
1042                    or will not live beyond this instructions */
1043                 if (!sym->nRegs ||
1044                     sym->isspilt ||
1045                     bitVectBitValue (_G.regAssigned, sym->key) ||
1046                     sym->liveTo <= ic->seq)
1047                     continue;
1048
1049                 /* if some liverange has been spilt at the block level
1050                    and this one live beyond this block then spil this
1051                    to be safe */
1052                 if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) {
1053                     spillThis (sym);
1054                     continue;
1055                 }
1056                 /* if trying to allocate this will cause
1057                    a spill and there is nothing to spill 
1058                    or this one is rematerializable then
1059                    spill this one */
1060                 willCS = willCauseSpill (sym);
1061                 spillable = computeSpillable (ic);
1062                 if (sym->remat || (willCS && bitVectIsZero (spillable))) {                    
1063                     spillThis (sym);
1064                     continue;                 
1065                 }
1066
1067                 /* if it has a spillocation & is used less than
1068                    all other live ranges then spill this */
1069                 if (willCS) {
1070                   if (sym->usl.spillLoc) {
1071                     symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
1072                                                                      allLRs, ebbs[i], ic));
1073                     if (leastUsed && leastUsed->used > sym->used) {
1074                       spillThis (sym);
1075                       continue;
1076                     }
1077                   } else {
1078                     /* if none of the liveRanges have a spillLocation then better
1079                        to spill this one than anything else already assigned to registers */
1080                     if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
1081                       /* if this is local to this block then we might find a block spil */
1082                       if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
1083                         spillThis (sym);
1084                         continue;
1085                       }
1086                     }
1087                   }
1088                 }
1089
1090                 /* else we assign registers to it */
1091                 _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
1092                 _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
1093
1094                 if (sym->regType == REG_PTR)
1095                   getRegPtr (ic, ebbs[i], sym, 0);
1096                 else
1097                   getRegGpr (ic, ebbs[i], sym, 0);
1098                 
1099                 /* if it shares registers with operands make sure
1100                    that they are in the same position */
1101                 if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
1102                     OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') {
1103                     positionRegs (OP_SYMBOL (IC_RESULT (ic)),
1104                                   OP_SYMBOL (IC_LEFT (ic)));
1105                 }
1106                 /* do the same for the right operand */
1107                 if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
1108                     OP_SYMBOL (IC_RIGHT (ic))->nRegs) {
1109                     positionRegs (OP_SYMBOL (IC_RESULT (ic)),
1110                                   OP_SYMBOL (IC_RIGHT (ic)));
1111                 }
1112             }
1113         }
1114     }
1115 }
1116
1117 /*-----------------------------------------------------------------*/
1118 /* rUmaskForOp :- returns register mask for an operand             */
1119 /*-----------------------------------------------------------------*/
1120 bitVect *xa51_rUmaskForOp (operand * op) {
1121   bitVect *rumask;
1122   symbol *sym;
1123   int j;
1124   
1125   /* only temporaries are assigned registers */
1126   if (!IS_ITEMP (op))
1127     return NULL;
1128   
1129   sym = OP_SYMBOL (op);
1130   
1131   /* if spilt or no registers assigned to it 
1132      then nothing */
1133   if (sym->isspilt || !sym->nRegs || !sym->regs[0])
1134     return NULL;
1135   
1136   rumask = newBitVect (xa51_nRegs);
1137   
1138   for (j = 0; j < sym->nRegs; j++) {
1139     rumask = bitVectSetBit (rumask,
1140                             sym->regs[j]->rIdx);
1141   }
1142   return rumask;
1143 }
1144
1145 /*-----------------------------------------------------------------*/
1146 /* regsUsedIniCode :- returns bit vector of registers used in iCode */
1147 /*-----------------------------------------------------------------*/
1148 static bitVect *
1149 regsUsedIniCode (iCode * ic)
1150 {
1151   bitVect *rmask = newBitVect (xa51_nRegs);
1152
1153   /* do the special cases first */
1154   if (ic->op == IFX)
1155     {
1156       rmask = bitVectUnion (rmask,
1157                             xa51_rUmaskForOp (IC_COND (ic)));
1158       goto ret;
1159     }
1160
1161   /* for the jumptable */
1162   if (ic->op == JUMPTABLE)
1163     {
1164       rmask = bitVectUnion (rmask,
1165                             xa51_rUmaskForOp (IC_JTCOND (ic)));
1166
1167       goto ret;
1168     }
1169
1170   /* of all other cases */
1171   if (IC_LEFT (ic))
1172     rmask = bitVectUnion (rmask,
1173                           xa51_rUmaskForOp (IC_LEFT (ic)));
1174
1175
1176   if (IC_RIGHT (ic))
1177     rmask = bitVectUnion (rmask,
1178                           xa51_rUmaskForOp (IC_RIGHT (ic)));
1179
1180   if (IC_RESULT (ic))
1181     rmask = bitVectUnion (rmask,
1182                           xa51_rUmaskForOp (IC_RESULT (ic)));
1183
1184 ret:
1185   return rmask;
1186 }
1187
1188 /*-----------------------------------------------------------------*/
1189 /* createRegMask - for each instruction will determine the regsUsed */
1190 /*-----------------------------------------------------------------*/
1191 static void
1192 createRegMask (eBBlock ** ebbs, int count)
1193 {
1194   int i;
1195
1196   /* for all blocks */
1197   for (i = 0; i < count; i++)
1198     {
1199       iCode *ic;
1200
1201       if (ebbs[i]->noPath &&
1202           (ebbs[i]->entryLabel != entryLabel &&
1203            ebbs[i]->entryLabel != returnLabel))
1204         continue;
1205
1206       /* for all instructions */
1207       for (ic = ebbs[i]->sch; ic; ic = ic->next)
1208         {
1209
1210           int j;
1211
1212           if (SKIP_IC2 (ic) || !ic->rlive)
1213             continue;
1214
1215           /* first mark the registers used in this
1216              instruction */
1217           ic->rUsed = regsUsedIniCode (ic);
1218           _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
1219
1220           /* now create the register mask for those 
1221              registers that are in use : this is a
1222              super set of ic->rUsed */
1223           ic->rMask = newBitVect (xa51_nRegs + 1);
1224
1225           /* for all live Ranges alive at this point */
1226           for (j = 1; j < ic->rlive->size; j++)
1227             {
1228               symbol *sym;
1229               int k;
1230
1231               /* if not alive then continue */
1232               if (!bitVectBitValue (ic->rlive, j))
1233                 continue;
1234
1235               /* find the live range we are interested in */
1236               if (!(sym = hTabItemWithKey (liveRanges, j)))
1237                 {
1238                   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1239                           "createRegMask cannot find live range");
1240                   exit (0);
1241                 }
1242
1243               /* if no register assigned to it */
1244               if (!sym->nRegs || sym->isspilt)
1245                 continue;
1246
1247               /* for all the registers allocated to it */
1248               for (k = 0; k < sym->nRegs; k++)
1249                 if (sym->regs[k])
1250                   ic->rMask =
1251                     bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
1252             }
1253         }
1254     }
1255 }
1256
1257 /*-----------------------------------------------------------------*/
1258 /* rematStr - returns the rematerialized string for a remat var    */
1259 /*-----------------------------------------------------------------*/
1260 static char *
1261 rematStr (symbol * sym)
1262 {
1263   char *s = buffer;
1264   iCode *ic = sym->rematiCode;
1265
1266   while (1)
1267     {
1268
1269       /* if plus or minus print the right hand side */
1270       if (ic->op == '+' || ic->op == '-')
1271         {
1272           sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
1273                    ic->op);
1274           s += strlen (s);
1275           ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1276           continue;
1277         }
1278
1279       /* cast then continue */
1280       if (IS_CAST_ICODE(ic)) {
1281           ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1282           continue;
1283       }
1284       /* we reached the end */
1285       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
1286       break;
1287     }
1288
1289   return buffer;
1290 }
1291
1292 /*-----------------------------------------------------------------*/
1293 /* regTypeNum - computes the type & number of registers required   */
1294 /*-----------------------------------------------------------------*/
1295 static void
1296 regTypeNum (eBBlock *ebbs)
1297 {
1298   symbol *sym;
1299   int k;
1300   iCode *ic;
1301
1302   /* for each live range do */
1303   for (sym = hTabFirstItem (liveRanges, &k); sym;
1304        sym = hTabNextItem (liveRanges, &k))
1305     {
1306
1307       /* if used zero times then no registers needed */
1308       if ((sym->liveTo - sym->liveFrom) == 0)
1309         continue;
1310
1311
1312       /* if the live range is a temporary */
1313       if (sym->isitmp)
1314         {
1315
1316           /* if the type is marked as a conditional */
1317           if (sym->regType == REG_CND)
1318             continue;
1319
1320           /* if used in return only then we don't 
1321              need registers */
1322 #if 0 // not yet
1323           if (sym->ruonly || sym->accuse)
1324             {
1325               if (IS_AGGREGATE (sym->type) || sym->isptr)
1326                 sym->type = aggrToPtr (sym->type, FALSE);
1327               continue;
1328             }
1329 #endif
1330
1331           /* if the symbol has only one definition &
1332              that definition is a get_pointer */
1333           if (bitVectnBitsOn (sym->defs) == 1 &&
1334               (ic = hTabItemWithKey (iCodehTab,
1335                                      bitVectFirstBit (sym->defs))) &&
1336               POINTER_GET (ic) &&
1337               !sym->noSpilLoc &&
1338               !IS_BITVAR (sym->etype))
1339             {
1340               /* and that pointer is remat in data space */
1341               if (OP_SYMBOL (IC_LEFT (ic))->remat &&
1342                   !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
1343                   DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER)
1344                 {
1345                   /* create a psuedo symbol & force a spil */
1346                   symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
1347                   psym->type = sym->type;
1348                   psym->etype = sym->etype;
1349                   strcpy (psym->rname, psym->name);
1350                   sym->isspilt = 1;
1351                   sym->usl.spillLoc = psym;
1352 #if 0 // an alternative fix for bug #480076
1353                   /* now this is a useless assignment to itself */
1354                   remiCodeFromeBBlock (ebbs, ic);
1355 #else
1356                   /* now this really is an assignment to itself, make it so;
1357                      it will be optimized out later */
1358                   ic->op='=';
1359                   IC_RIGHT(ic)=IC_RESULT(ic);
1360                   IC_LEFT(ic)=NULL;
1361 #endif
1362                   continue;
1363                 }
1364
1365               /* if in data space or idata space then try to
1366                  allocate pointer register */
1367
1368             }
1369
1370           /* if not then we require registers */
1371 #if 0
1372           sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
1373                         getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
1374                         getSize (sym->type));
1375 #else
1376           {
1377             int size=((IS_AGGREGATE (sym->type) || sym->isptr) ?
1378                       getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
1379                       getSize (sym->type));
1380             switch (size) 
1381               {
1382               case 1: // byte
1383               case 2: // word or pointer
1384                 sym->nRegs=1;
1385                 break;
1386               case 3: // generic pointer
1387                 sym->nRegs=2;
1388                 break;
1389               case 4: // dword or float
1390                 sym->nRegs=2;
1391                 break;
1392               default: 
1393                 fprintf (stderr, "regTypeNum: unknown size\n");
1394                 exit (1);
1395               }
1396           }
1397 #endif
1398
1399           if (sym->nRegs > 4)
1400             {
1401               fprintf (stderr, "allocated more than 4 or 0 registers for type ");
1402               printTypeChain (sym->type, stderr);
1403               fprintf (stderr, "\n");
1404               exit (1);
1405             }
1406
1407           /* determine the type of register required */
1408           if (IS_PTR (sym->type))
1409             sym->regType = REG_PTR;
1410           else
1411             sym->regType = REG_GPR;
1412
1413         }
1414       else
1415         /* for the first run we don't provide */
1416         /* registers for true symbols we will */
1417         /* see how things go                  */
1418         sym->nRegs = 0;
1419     }
1420
1421 }
1422
1423 /*-----------------------------------------------------------------*/
1424 /* deallocStackSpil - this will set the stack pointer back         */
1425 /*-----------------------------------------------------------------*/
1426 static
1427 DEFSETFUNC (deallocStackSpil)
1428 {
1429   symbol *sym = item;
1430
1431   deallocLocal (sym);
1432   return 0;
1433 }
1434
1435 /*-----------------------------------------------------------------*/
1436 /* packRegsForAssign - register reduction for assignment           */
1437 /*-----------------------------------------------------------------*/
1438 static int
1439 packRegsForAssign (iCode * ic, eBBlock * ebp)
1440 {
1441   iCode *dic, *sic;
1442
1443   if (!IS_ITEMP (IC_RIGHT (ic)) ||
1444       OP_LIVETO (IC_RIGHT (ic)) > ic->seq) {
1445     return 0;
1446   }
1447
1448   /* find the definition of iTempNN scanning backwards */
1449   for (dic = ic->prev; dic; dic = dic->prev) {
1450
1451     /* if there is a function call then don't pack it */
1452     if ((dic->op == CALL || dic->op == PCALL)) {
1453       dic = NULL;
1454       break;
1455     }
1456     
1457     if (SKIP_IC2 (dic))
1458       continue;
1459
1460     if (IS_SYMOP (IC_RESULT (dic)) &&
1461         IC_RESULT (dic)->key == IC_RIGHT (ic)->key) {
1462       break;
1463     }
1464
1465   }
1466
1467   if (!dic)
1468     return 0;                   /* did not find */
1469
1470   /* found the definition */
1471   /* replace the result with the result of */
1472   /* this assignment and remove this assignment */
1473   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1474   IC_RESULT (dic) = IC_RESULT (ic);
1475
1476   if (IS_ITEMP (IC_RESULT (dic)) && 
1477       OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
1478     {
1479       OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
1480     }
1481   /* delete from liverange table also 
1482      delete from all the points inbetween and the new
1483      one */
1484   for (sic = dic; sic != ic; sic = sic->next)
1485     {
1486       bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
1487       if (IS_ITEMP (IC_RESULT (dic)))
1488         bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
1489     }
1490
1491   remiCodeFromeBBlock (ebp, ic);
1492   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
1493   hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
1494   OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
1495   return 1;
1496
1497 }
1498
1499 /*-----------------------------------------------------------------*/
1500 /* findAssignToSym : scanning backwards looks for first assig found */
1501 /*-----------------------------------------------------------------*/
1502 static iCode *
1503 findAssignToSym (operand * op, iCode * ic)
1504 {
1505   iCode *dic;
1506
1507   for (dic = ic->prev; dic; dic = dic->prev)
1508     {
1509
1510       /* if definition by assignment */
1511       if (dic->op == '=' &&
1512           !POINTER_SET (dic) &&
1513           IC_RESULT (dic)->key == op->key
1514 /*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
1515         )
1516         {
1517
1518           /* we are interested only if defined in far space */
1519           /* or in stack space in case of + & - */
1520
1521           /* if assigned to a non-symbol then return
1522              FALSE */
1523           if (!IS_SYMOP (IC_RIGHT (dic)))
1524             return NULL;
1525
1526           /* if the symbol is in far space then
1527              we should not */
1528           if (isOperandInFarSpace (IC_RIGHT (dic)))
1529             return NULL;
1530
1531           /* for + & - operations make sure that
1532              if it is on the stack it is the same
1533              as one of the three operands */
1534           if ((ic->op == '+' || ic->op == '-') &&
1535               OP_SYMBOL (IC_RIGHT (dic))->onStack)
1536             {
1537
1538               if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
1539                   IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
1540                   IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
1541                 return NULL;
1542             }
1543
1544           break;
1545
1546         }
1547
1548       /* if we find an usage then we cannot delete it */
1549       if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
1550         return NULL;
1551
1552       if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
1553         return NULL;
1554
1555       if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
1556         return NULL;
1557     }
1558
1559   /* now make sure that the right side of dic
1560      is not defined between ic & dic */
1561   if (dic)
1562     {
1563       iCode *sic = dic->next;
1564
1565       for (; sic != ic; sic = sic->next)
1566         if (IC_RESULT (sic) &&
1567             IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
1568           return NULL;
1569     }
1570
1571   return dic;
1572
1573
1574 }
1575
1576 /*-----------------------------------------------------------------*/
1577 /* packRegsForSupport :- reduce some registers for support calls   */
1578 /*-----------------------------------------------------------------*/
1579 static int
1580 packRegsForSupport (iCode * ic, eBBlock * ebp)
1581 {
1582   int change = 0;
1583   iCode *dic, *sic;
1584
1585   /* for the left & right operand :- look to see if the
1586      left was assigned a true symbol in far space in that
1587      case replace them */
1588
1589   if (IS_ITEMP (IC_LEFT (ic)) &&
1590       OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
1591     {
1592       dic = findAssignToSym (IC_LEFT (ic), ic);
1593
1594       if (!dic)
1595         goto right;
1596
1597       /* found it we need to remove it from the
1598          block */
1599       for (sic = dic; sic != ic; sic = sic->next)
1600         bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
1601
1602       OP_SYMBOL(IC_LEFT (ic))=OP_SYMBOL(IC_RIGHT (dic));
1603       IC_LEFT (ic)->key = OP_SYMBOL(IC_RIGHT (dic))->key;
1604       remiCodeFromeBBlock (ebp, dic);
1605       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1606       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1607       change++;
1608     }
1609
1610   /* do the same for the right operand */
1611  right:
1612   if (!change &&
1613       IS_ITEMP (IC_RIGHT (ic)) &&
1614       OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
1615     {
1616       iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
1617       iCode *sic;
1618
1619       if (!dic)
1620         return change;
1621
1622       /* if this is a subtraction & the result
1623          is a true symbol in far space then don't pack */
1624       if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
1625         {
1626           sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
1627           if (IN_FARSPACE (SPEC_OCLS (etype)))
1628             return change;
1629         }
1630       /* found it we need to remove it from the
1631          block */
1632       for (sic = dic; sic != ic; sic = sic->next)
1633         bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
1634
1635       IC_RIGHT (ic)->operand.symOperand =
1636         IC_RIGHT (dic)->operand.symOperand;
1637       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
1638
1639       remiCodeFromeBBlock (ebp, dic);
1640       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1641       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1642       change++;
1643     }
1644
1645   return change;
1646 }
1647
1648 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1649
1650
1651 /*-----------------------------------------------------------------*/
1652 /* packRegsForOneuse : - will reduce some registers for single Use */
1653 /*-----------------------------------------------------------------*/
1654 static iCode *
1655 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
1656 {
1657   bitVect *uses;
1658   iCode *dic, *sic;
1659
1660   /* if returning a literal then do nothing */
1661   if (!IS_SYMOP (op))
1662     return NULL;
1663
1664   if (ic->op != RETURN &&
1665       ic->op != SEND &&
1666       !POINTER_SET (ic) &&
1667       !POINTER_GET (ic))
1668     return NULL;
1669   
1670   /* this routine will mark the a symbol as used in one 
1671      instruction use only && if the defintion is local 
1672      (ie. within the basic block) && has only one definition &&
1673      that definiion is either a return value from a 
1674      function or does not contain any variables in
1675      far space */
1676   uses = bitVectCopy (OP_USES (op));
1677   bitVectUnSetBit (uses, ic->key);      /* take away this iCode */
1678   if (!bitVectIsZero (uses))    /* has other uses */
1679     return NULL;
1680
1681   /* if it has only one defintion */
1682   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
1683     return NULL;                /* has more than one definition */
1684
1685   /* get that definition */
1686   if (!(dic =
1687         hTabItemWithKey (iCodehTab,
1688                          bitVectFirstBit (OP_DEFS (op)))))
1689     return NULL;
1690
1691   /* if that only usage is a cast */
1692   if (dic->op == CAST) {
1693     /* to a bigger type */
1694     if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > 
1695         getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
1696       /* than we can not, since we cannot predict the usage of b & acc */
1697       return NULL;
1698     }
1699   }
1700
1701   /* found the definition now check if it is local */
1702   if (dic->seq < ebp->fSeq ||
1703       dic->seq > ebp->lSeq)
1704     return NULL;                /* non-local */
1705
1706   /* now check if it is the return from
1707      a function call */
1708   if (dic->op == CALL || dic->op == PCALL)
1709     {
1710       if (ic->op != SEND && ic->op != RETURN &&
1711           !POINTER_SET(ic) && !POINTER_GET(ic))
1712         {
1713           OP_SYMBOL (op)->ruonly = 1;
1714           return dic;
1715         }
1716       dic = dic->next;
1717     }
1718
1719
1720   /* otherwise check that the definition does
1721      not contain any symbols in far space */
1722   if (isOperandInFarSpace (IC_LEFT (dic)) ||
1723       isOperandInFarSpace (IC_RIGHT (dic)) ||
1724       IS_OP_RUONLY (IC_LEFT (ic)) ||
1725       IS_OP_RUONLY (IC_RIGHT (ic)))
1726     {
1727       return NULL;
1728     }
1729
1730   /* if pointer set then make sure the pointer
1731      is one byte */
1732   if (POINTER_SET (dic) &&
1733       !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
1734     return NULL;
1735
1736   if (POINTER_GET (dic) &&
1737       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
1738     return NULL;
1739
1740   sic = dic;
1741
1742   /* also make sure the intervenening instructions
1743      don't have any thing in far space */
1744   for (dic = dic->next; dic && dic != ic && sic != ic; dic = dic->next)
1745     {
1746
1747       /* if there is an intervening function call then no */
1748       if (dic->op == CALL || dic->op == PCALL)
1749         return NULL;
1750       /* if pointer set then make sure the pointer
1751          is one byte */
1752       if (POINTER_SET (dic) &&
1753           !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
1754         return NULL;
1755
1756       if (POINTER_GET (dic) &&
1757           !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
1758         return NULL;
1759
1760       /* if address of & the result is remat the okay */
1761       if (dic->op == ADDRESS_OF &&
1762           OP_SYMBOL (IC_RESULT (dic))->remat)
1763         continue;
1764
1765       /* if operand has size of three or more & this
1766          operation is a '*','/' or '%' then 'b' may
1767          cause a problem */
1768       if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
1769           getSize (operandType (op)) >= 3)
1770         return NULL;
1771
1772       /* if left or right or result is in far space */
1773       if (isOperandInFarSpace (IC_LEFT (dic)) ||
1774           isOperandInFarSpace (IC_RIGHT (dic)) ||
1775           isOperandInFarSpace (IC_RESULT (dic)) ||
1776           IS_OP_RUONLY (IC_LEFT (dic)) ||
1777           IS_OP_RUONLY (IC_RIGHT (dic)) ||
1778           IS_OP_RUONLY (IC_RESULT (dic)))
1779         {
1780           return NULL;
1781         }
1782       /* if left or right or result is on stack */
1783       if (isOperandOnStack(IC_LEFT(dic)) ||
1784           isOperandOnStack(IC_RIGHT(dic)) ||
1785           isOperandOnStack(IC_RESULT(dic))) {
1786         return NULL;
1787       }
1788     }
1789
1790   OP_SYMBOL (op)->ruonly = 1;
1791   return sic;
1792
1793 }
1794
1795 /*-----------------------------------------------------------------*/
1796 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
1797 /*-----------------------------------------------------------------*/
1798 static bool
1799 isBitwiseOptimizable (iCode * ic)
1800 {
1801   sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
1802   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
1803
1804   /* bitwise operations are considered optimizable
1805      under the following conditions (Jean-Louis VERN) 
1806
1807      x & lit
1808      bit & bit
1809      bit & x
1810      bit ^ bit
1811      bit ^ x
1812      x   ^ lit
1813      x   | lit
1814      bit | bit
1815      bit | x
1816   */
1817   if (IS_LITERAL(rtype) ||
1818       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
1819     return TRUE;
1820   else
1821     return FALSE;
1822 }
1823
1824 /*-----------------------------------------------------------------*/
1825 /* packForPush - hueristics to reduce iCode for pushing            */
1826 /*-----------------------------------------------------------------*/
1827 static void
1828 packForPush (iCode * ic, eBBlock * ebp)
1829 {
1830   iCode *dic, *lic;
1831   bitVect *dbv;
1832
1833   if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
1834     return;
1835
1836   /* must have only definition & one usage */
1837   if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
1838       bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
1839     return;
1840
1841   /* find the definition */
1842   if (!(dic = hTabItemWithKey (iCodehTab,
1843                                bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
1844     return;
1845
1846   if (dic->op != '=' || POINTER_SET (dic))
1847     return;
1848
1849   /* make sure the right side does not have any definitions
1850      inbetween */
1851   dbv = OP_DEFS(IC_RIGHT(dic));
1852   for (lic = ic; lic && lic != dic ; lic = lic->prev) {
1853     if (bitVectBitValue(dbv,lic->key)) 
1854       return ;
1855   }
1856   /* make sure they have the same type */
1857   {
1858     sym_link *itype=operandType(IC_LEFT(ic));
1859     sym_link *ditype=operandType(IC_RIGHT(dic));
1860
1861     if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
1862         SPEC_LONG(itype)!=SPEC_LONG(ditype))
1863       return;
1864   }
1865   /* extend the live range of replaced operand if needed */
1866   if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) {
1867           OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
1868   }
1869   /* we now know that it has one & only one def & use
1870      and the that the definition is an assignment */
1871   IC_LEFT (ic) = IC_RIGHT (dic);
1872    
1873   remiCodeFromeBBlock (ebp, dic);
1874   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1875   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1876 }
1877
1878 /*-----------------------------------------------------------------*/
1879 /* packRegisters - does some transformations to reduce register    */
1880 /*                   pressure                                      */
1881 /*-----------------------------------------------------------------*/
1882 static void packRegisters (eBBlock * ebp) {
1883   iCode *ic;
1884   int change = 0;
1885   
1886   return; // that's it for now
1887
1888   while (1) {
1889     change = 0;
1890     
1891     for (ic = ebp->sch; ic; ic = ic->next) {
1892       if (ic->op == '=')
1893         change += packRegsForAssign (ic, ebp);
1894     }
1895     
1896     if (!change)
1897       break;
1898   }
1899
1900   for (ic = ebp->sch; ic; ic = ic->next)
1901     {
1902       /* if this is an itemp & result of an address of a true sym 
1903          then mark this as rematerialisable   */
1904       if (ic->op == ADDRESS_OF &&
1905           IS_ITEMP (IC_RESULT (ic)) &&
1906           IS_TRUE_SYMOP (IC_LEFT (ic)) &&
1907           bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
1908           !OP_SYMBOL (IC_LEFT (ic))->onStack)
1909         {
1910
1911           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1912           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1913           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1914
1915         }
1916
1917       /* if straight assignment then carry remat flag if
1918          this is the only definition */
1919       if (ic->op == '=' &&
1920           !POINTER_SET (ic) &&
1921           IS_SYMOP (IC_RIGHT (ic)) &&
1922           OP_SYMBOL (IC_RIGHT (ic))->remat &&
1923           !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
1924           bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
1925         {
1926
1927           OP_SYMBOL (IC_RESULT (ic))->remat =
1928             OP_SYMBOL (IC_RIGHT (ic))->remat;
1929           OP_SYMBOL (IC_RESULT (ic))->rematiCode =
1930             OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1931         }
1932
1933       /* if cast to a generic pointer & the pointer being
1934          cast is remat, then we can remat this cast as well */
1935       if (ic->op == CAST && 
1936           IS_SYMOP(IC_RIGHT(ic)) &&
1937           OP_SYMBOL(IC_RIGHT(ic))->remat ) {
1938               sym_link *to_type = operandType(IC_LEFT(ic));
1939               sym_link *from_type = operandType(IC_RIGHT(ic));
1940               if (IS_GENPTR(to_type) && IS_PTR(from_type)) {                  
1941                       OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1942                       OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1943                       OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1944               }
1945       }
1946
1947       /* if this is a +/- operation with a rematerizable 
1948          then mark this as rematerializable as well */
1949       if ((ic->op == '+' || ic->op == '-') &&
1950           (IS_SYMOP (IC_LEFT (ic)) &&
1951            IS_ITEMP (IC_RESULT (ic)) &&
1952            IS_OP_LITERAL (IC_RIGHT (ic))) &&
1953            OP_SYMBOL (IC_LEFT (ic))->remat &&
1954           (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
1955            bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1)
1956         {
1957           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1958           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1959           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1960         }
1961
1962       /* mark the pointer usages */
1963       if (POINTER_SET (ic))
1964         OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
1965
1966       if (POINTER_GET (ic))
1967         OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
1968
1969       /* if the condition of an if instruction
1970          is defined in the previous instruction and
1971          this is the only usage then
1972          mark the itemp as a conditional */
1973       if ((IS_CONDITIONAL (ic) ||
1974            (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) &&
1975           ic->next && ic->next->op == IFX &&
1976           bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
1977           isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
1978           OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
1979         {
1980           OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
1981           continue;
1982         }
1983
1984       /* reduce for support function calls */
1985       if (ic->supportRtn || ic->op == '+' || ic->op == '-')
1986         packRegsForSupport (ic, ebp);
1987
1988       /* some cases the redundant moves can
1989          can be eliminated for return statements */
1990       if ((ic->op == RETURN || ic->op == SEND) &&
1991           !isOperandInFarSpace (IC_LEFT (ic)) &&
1992           options.model == MODEL_SMALL) {
1993         if (0 && options.stackAuto) {
1994           /* we should check here if acc will be clobbered for stack
1995              offset calculations */
1996         } else {
1997           packRegsForOneuse (ic, IC_LEFT (ic), ebp);
1998         }
1999       }
2000
2001       /* if pointer set & left has a size more than
2002          one and right is not in far space */
2003       if (POINTER_SET (ic) &&
2004           !isOperandInFarSpace (IC_RIGHT (ic)) &&
2005           !OP_SYMBOL (IC_RESULT (ic))->remat &&
2006           !IS_OP_RUONLY (IC_RIGHT (ic)) &&
2007           getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
2008
2009         packRegsForOneuse (ic, IC_RESULT (ic), ebp);
2010
2011       /* if pointer get */
2012       if (POINTER_GET (ic) &&
2013           !isOperandInFarSpace (IC_RESULT (ic)) &&
2014           !OP_SYMBOL (IC_LEFT (ic))->remat &&
2015           !IS_OP_RUONLY (IC_RESULT (ic)) &&
2016           getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
2017
2018         packRegsForOneuse (ic, IC_LEFT (ic), ebp);
2019
2020
2021       /* if this is cast for intergral promotion then
2022          check if only use of  the definition of the 
2023          operand being casted/ if yes then replace
2024          the result of that arithmetic operation with 
2025          this result and get rid of the cast */
2026       if (ic->op == CAST)
2027         {
2028           sym_link *fromType = operandType (IC_RIGHT (ic));
2029           sym_link *toType = operandType (IC_LEFT (ic));
2030
2031           if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
2032               getSize (fromType) != getSize (toType) &&
2033               SPEC_USIGN (fromType) == SPEC_USIGN (toType))
2034             {
2035
2036               iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
2037               if (dic)
2038                 {
2039                   if (IS_ARITHMETIC_OP (dic))
2040                     {                  
2041                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
2042                       IC_RESULT (dic) = IC_RESULT (ic);
2043                       remiCodeFromeBBlock (ebp, ic);
2044                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
2045                       hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
2046                       OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
2047                       ic = ic->prev;
2048                     }
2049                   else
2050                     OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
2051                 }
2052             }
2053           else
2054             {
2055
2056               /* if the type from and type to are the same
2057                  then if this is the only use then packit */
2058               if (compareType (operandType (IC_RIGHT (ic)),
2059                              operandType (IC_LEFT (ic))) == 1)
2060                 {
2061                   iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
2062                   if (dic)
2063                     {
2064                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
2065                       IC_RESULT (dic) = IC_RESULT (ic);
2066                       remiCodeFromeBBlock (ebp, ic);
2067                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
2068                       hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
2069                       OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
2070                       ic = ic->prev;
2071                     }
2072                 }
2073             }
2074         }
2075
2076       /* pack for PUSH 
2077          iTempNN := (some variable in farspace) V1
2078          push iTempNN ;
2079          -------------
2080          push V1
2081        */
2082       if (ic->op == IPUSH)
2083         {
2084           packForPush (ic, ebp);
2085         }
2086     }
2087 }
2088
2089 /*-----------------------------------------------------------------*/
2090 /* assignRegisters - assigns registers to each live range as need  */
2091 /*-----------------------------------------------------------------*/
2092 void
2093 xa51_assignRegisters (eBBlock ** ebbs, int count)
2094 {
2095   iCode *ic;
2096   int i;
2097
2098   setToNull ((void *) &_G.funcrUsed);
2099   setToNull ((void *) &_G.totRegAssigned);
2100   _G.stackExtend = _G.dataExtend = 0;
2101
2102   /* change assignments this will remove some
2103      live ranges reducing some register pressure */
2104   for (i = 0; i < count; i++)
2105     packRegisters (ebbs[i]);
2106
2107   if (options.dump_pack)
2108     dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
2109
2110   /* first determine for each live range the number of 
2111      registers & the type of registers required for each */
2112   regTypeNum (*ebbs);
2113
2114   /* and serially allocate registers */
2115   serialRegAssign (ebbs, count);
2116
2117   freeAllRegs ();
2118
2119   /* if stack was extended then tell the user */
2120   if (_G.stackExtend)
2121     {
2122 /*      werror(W_TOOMANY_SPILS,"stack", */
2123 /*             _G.stackExtend,currFunc->name,""); */
2124       _G.stackExtend = 0;
2125     }
2126
2127   if (_G.dataExtend)
2128     {
2129 /*      werror(W_TOOMANY_SPILS,"data space", */
2130 /*             _G.dataExtend,currFunc->name,""); */
2131       _G.dataExtend = 0;
2132     }
2133
2134   /* after that create the register mask
2135      for each of the instruction */
2136   createRegMask (ebbs, count);
2137
2138   /* redo that offsets for stacked automatic variables */
2139   redoStackOffsets ();
2140
2141   if (options.dump_rassgn)
2142     {
2143       dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
2144       dumpLiveRanges (DUMP_LRANGE, liveRanges);
2145     }
2146
2147   /* do the overlaysegment stuff SDCCmem.c */
2148   doOverlays (ebbs, count);
2149
2150   /* now get back the chain */
2151   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
2152
2153   genXA51Code (ic);
2154
2155   /* free up any _G.stackSpil locations allocated */
2156   applyToSet (_G.stackSpil, deallocStackSpil);
2157   _G.slocNum = 0;
2158   setToNull ((void **) &_G.stackSpil);
2159   setToNull ((void **) &_G.spiltSet);
2160   /* mark all registers as free */
2161   freeAllRegs ();
2162
2163   return;
2164 }