]> git.gag.com Git - fw/sdcc/blob - src/xa51/ralloc.c
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
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 and the
1333              pointer we are getting is rematerializable and
1334              in "data" space */
1335
1336           if (bitVectnBitsOn (sym->defs) == 1 &&
1337               (ic = hTabItemWithKey (iCodehTab,
1338                                      bitVectFirstBit (sym->defs))) &&
1339               POINTER_GET (ic) &&
1340               !sym->noSpilLoc &&
1341               !IS_BITVAR (sym->etype))
1342             {
1343
1344
1345               /* if remat in data space */
1346               if (OP_SYMBOL (IC_LEFT (ic))->remat &&
1347                   !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
1348                   DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER)
1349                 {
1350                   /* create a psuedo symbol & force a spil */
1351                   symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
1352                   psym->type = sym->type;
1353                   psym->etype = sym->etype;
1354                   strcpy (psym->rname, psym->name);
1355                   sym->isspilt = 1;
1356                   sym->usl.spillLoc = psym;
1357 #if 0 // an alternative fix for bug #480076
1358                   /* now this is a useless assignment to itself */
1359                   remiCodeFromeBBlock (ebbs, ic);
1360 #else
1361                   /* now this really is an assignment to itself, make it so;
1362                      it will be optimized out later */
1363                   ic->op='=';
1364                   IC_RIGHT(ic)=IC_RESULT(ic);
1365                   IC_LEFT(ic)=NULL;
1366 #endif
1367                   continue;
1368                 }
1369
1370               /* if in data space or idata space then try to
1371                  allocate pointer register */
1372
1373             }
1374
1375           /* if not then we require registers */
1376 #if 0
1377           sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
1378                         getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
1379                         getSize (sym->type));
1380 #else
1381           {
1382             int size=((IS_AGGREGATE (sym->type) || sym->isptr) ?
1383                       getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
1384                       getSize (sym->type));
1385             switch (size) 
1386               {
1387               case 1: // byte
1388               case 2: // word or pointer
1389                 sym->nRegs=1;
1390                 break;
1391               case 3: // generic pointer
1392                 sym->nRegs=2;
1393                 break;
1394               case 4: // dword or float
1395                 sym->nRegs=2;
1396                 break;
1397               default: 
1398                 fprintf (stderr, "regTypeNum: unknown size\n");
1399                 exit (1);
1400               }
1401           }
1402 #endif
1403
1404           if (sym->nRegs > 4)
1405             {
1406               fprintf (stderr, "allocated more than 4 or 0 registers for type ");
1407               printTypeChain (sym->type, stderr);
1408               fprintf (stderr, "\n");
1409               exit (1);
1410             }
1411
1412           /* determine the type of register required */
1413           if (IS_PTR (sym->type))
1414             sym->regType = REG_PTR;
1415           else
1416             sym->regType = REG_GPR;
1417
1418         }
1419       else
1420         /* for the first run we don't provide */
1421         /* registers for true symbols we will */
1422         /* see how things go                  */
1423         sym->nRegs = 0;
1424     }
1425
1426 }
1427
1428 /*-----------------------------------------------------------------*/
1429 /* deallocStackSpil - this will set the stack pointer back         */
1430 /*-----------------------------------------------------------------*/
1431 static
1432 DEFSETFUNC (deallocStackSpil)
1433 {
1434   symbol *sym = item;
1435
1436   deallocLocal (sym);
1437   return 0;
1438 }
1439
1440 /*-----------------------------------------------------------------*/
1441 /* packRegsForAssign - register reduction for assignment           */
1442 /*-----------------------------------------------------------------*/
1443 static int
1444 packRegsForAssign (iCode * ic, eBBlock * ebp)
1445 {
1446   iCode *dic, *sic;
1447
1448   if (!IS_ITEMP (IC_RIGHT (ic)) ||
1449       OP_LIVETO (IC_RIGHT (ic)) > ic->seq) {
1450     return 0;
1451   }
1452
1453   /* find the definition of iTempNN scanning backwards */
1454   for (dic = ic->prev; dic; dic = dic->prev) {
1455
1456     /* if there is a function call then don't pack it */
1457     if ((dic->op == CALL || dic->op == PCALL)) {
1458       dic = NULL;
1459       break;
1460     }
1461     
1462     if (SKIP_IC2 (dic))
1463       continue;
1464
1465     if (IS_SYMOP (IC_RESULT (dic)) &&
1466         IC_RESULT (dic)->key == IC_RIGHT (ic)->key) {
1467       break;
1468     }
1469
1470   }
1471
1472   if (!dic)
1473     return 0;                   /* did not find */
1474
1475   /* found the definition */
1476   /* replace the result with the result of */
1477   /* this assignment and remove this assignment */
1478   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1479   IC_RESULT (dic) = IC_RESULT (ic);
1480
1481   if (IS_ITEMP (IC_RESULT (dic)) && 
1482       OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
1483     {
1484       OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
1485     }
1486   /* delete from liverange table also 
1487      delete from all the points inbetween and the new
1488      one */
1489   for (sic = dic; sic != ic; sic = sic->next)
1490     {
1491       bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
1492       if (IS_ITEMP (IC_RESULT (dic)))
1493         bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
1494     }
1495
1496   remiCodeFromeBBlock (ebp, ic);
1497   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
1498   hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
1499   OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
1500   return 1;
1501
1502 }
1503
1504 /*-----------------------------------------------------------------*/
1505 /* findAssignToSym : scanning backwards looks for first assig found */
1506 /*-----------------------------------------------------------------*/
1507 static iCode *
1508 findAssignToSym (operand * op, iCode * ic)
1509 {
1510   iCode *dic;
1511
1512   for (dic = ic->prev; dic; dic = dic->prev)
1513     {
1514
1515       /* if definition by assignment */
1516       if (dic->op == '=' &&
1517           !POINTER_SET (dic) &&
1518           IC_RESULT (dic)->key == op->key
1519 /*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
1520         )
1521         {
1522
1523           /* we are interested only if defined in far space */
1524           /* or in stack space in case of + & - */
1525
1526           /* if assigned to a non-symbol then return
1527              FALSE */
1528           if (!IS_SYMOP (IC_RIGHT (dic)))
1529             return NULL;
1530
1531           /* if the symbol is in far space then
1532              we should not */
1533           if (isOperandInFarSpace (IC_RIGHT (dic)))
1534             return NULL;
1535
1536           /* for + & - operations make sure that
1537              if it is on the stack it is the same
1538              as one of the three operands */
1539           if ((ic->op == '+' || ic->op == '-') &&
1540               OP_SYMBOL (IC_RIGHT (dic))->onStack)
1541             {
1542
1543               if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
1544                   IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
1545                   IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
1546                 return NULL;
1547             }
1548
1549           break;
1550
1551         }
1552
1553       /* if we find an usage then we cannot delete it */
1554       if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
1555         return NULL;
1556
1557       if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
1558         return NULL;
1559
1560       if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
1561         return NULL;
1562     }
1563
1564   /* now make sure that the right side of dic
1565      is not defined between ic & dic */
1566   if (dic)
1567     {
1568       iCode *sic = dic->next;
1569
1570       for (; sic != ic; sic = sic->next)
1571         if (IC_RESULT (sic) &&
1572             IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
1573           return NULL;
1574     }
1575
1576   return dic;
1577
1578
1579 }
1580
1581 /*-----------------------------------------------------------------*/
1582 /* packRegsForSupport :- reduce some registers for support calls   */
1583 /*-----------------------------------------------------------------*/
1584 static int
1585 packRegsForSupport (iCode * ic, eBBlock * ebp)
1586 {
1587   int change = 0;
1588   iCode *dic, *sic;
1589
1590   /* for the left & right operand :- look to see if the
1591      left was assigned a true symbol in far space in that
1592      case replace them */
1593
1594   if (IS_ITEMP (IC_LEFT (ic)) &&
1595       OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
1596     {
1597       dic = findAssignToSym (IC_LEFT (ic), ic);
1598
1599       if (!dic)
1600         goto right;
1601
1602       /* found it we need to remove it from the
1603          block */
1604       for (sic = dic; sic != ic; sic = sic->next)
1605         bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
1606
1607       OP_SYMBOL(IC_LEFT (ic))=OP_SYMBOL(IC_RIGHT (dic));
1608       IC_LEFT (ic)->key = OP_SYMBOL(IC_RIGHT (dic))->key;
1609       remiCodeFromeBBlock (ebp, dic);
1610       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1611       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1612       change++;
1613     }
1614
1615   /* do the same for the right operand */
1616  right:
1617   if (!change &&
1618       IS_ITEMP (IC_RIGHT (ic)) &&
1619       OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
1620     {
1621       iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
1622       iCode *sic;
1623
1624       if (!dic)
1625         return change;
1626
1627       /* if this is a subtraction & the result
1628          is a true symbol in far space then don't pack */
1629       if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
1630         {
1631           sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
1632           if (IN_FARSPACE (SPEC_OCLS (etype)))
1633             return change;
1634         }
1635       /* found it we need to remove it from the
1636          block */
1637       for (sic = dic; sic != ic; sic = sic->next)
1638         bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
1639
1640       IC_RIGHT (ic)->operand.symOperand =
1641         IC_RIGHT (dic)->operand.symOperand;
1642       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
1643
1644       remiCodeFromeBBlock (ebp, dic);
1645       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1646       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1647       change++;
1648     }
1649
1650   return change;
1651 }
1652
1653 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1654
1655
1656 /*-----------------------------------------------------------------*/
1657 /* packRegsForOneuse : - will reduce some registers for single Use */
1658 /*-----------------------------------------------------------------*/
1659 static iCode *
1660 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
1661 {
1662   bitVect *uses;
1663   iCode *dic, *sic;
1664
1665   /* if returning a literal then do nothing */
1666   if (!IS_SYMOP (op))
1667     return NULL;
1668
1669   if (ic->op != RETURN &&
1670       ic->op != SEND &&
1671       !POINTER_SET (ic) &&
1672       !POINTER_GET (ic))
1673     return NULL;
1674   
1675   /* this routine will mark the a symbol as used in one 
1676      instruction use only && if the defintion is local 
1677      (ie. within the basic block) && has only one definition &&
1678      that definiion is either a return value from a 
1679      function or does not contain any variables in
1680      far space */
1681   uses = bitVectCopy (OP_USES (op));
1682   bitVectUnSetBit (uses, ic->key);      /* take away this iCode */
1683   if (!bitVectIsZero (uses))    /* has other uses */
1684     return NULL;
1685
1686   /* if it has only one defintion */
1687   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
1688     return NULL;                /* has more than one definition */
1689
1690   /* get that definition */
1691   if (!(dic =
1692         hTabItemWithKey (iCodehTab,
1693                          bitVectFirstBit (OP_DEFS (op)))))
1694     return NULL;
1695
1696   /* if that only usage is a cast */
1697   if (dic->op == CAST) {
1698     /* to a bigger type */
1699     if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > 
1700         getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
1701       /* than we can not, since we cannot predict the usage of b & acc */
1702       return NULL;
1703     }
1704   }
1705
1706   /* found the definition now check if it is local */
1707   if (dic->seq < ebp->fSeq ||
1708       dic->seq > ebp->lSeq)
1709     return NULL;                /* non-local */
1710
1711   /* now check if it is the return from
1712      a function call */
1713   if (dic->op == CALL || dic->op == PCALL)
1714     {
1715       if (ic->op != SEND && ic->op != RETURN &&
1716           !POINTER_SET(ic) && !POINTER_GET(ic))
1717         {
1718           OP_SYMBOL (op)->ruonly = 1;
1719           return dic;
1720         }
1721       dic = dic->next;
1722     }
1723
1724
1725   /* otherwise check that the definition does
1726      not contain any symbols in far space */
1727   if (isOperandInFarSpace (IC_LEFT (dic)) ||
1728       isOperandInFarSpace (IC_RIGHT (dic)) ||
1729       IS_OP_RUONLY (IC_LEFT (ic)) ||
1730       IS_OP_RUONLY (IC_RIGHT (ic)))
1731     {
1732       return NULL;
1733     }
1734
1735   /* if pointer set then make sure the pointer
1736      is one byte */
1737   if (POINTER_SET (dic) &&
1738       !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
1739     return NULL;
1740
1741   if (POINTER_GET (dic) &&
1742       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
1743     return NULL;
1744
1745   sic = dic;
1746
1747   /* also make sure the intervenening instructions
1748      don't have any thing in far space */
1749   for (dic = dic->next; dic && dic != ic && sic != ic; dic = dic->next)
1750     {
1751
1752       /* if there is an intervening function call then no */
1753       if (dic->op == CALL || dic->op == PCALL)
1754         return NULL;
1755       /* if pointer set then make sure the pointer
1756          is one byte */
1757       if (POINTER_SET (dic) &&
1758           !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
1759         return NULL;
1760
1761       if (POINTER_GET (dic) &&
1762           !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
1763         return NULL;
1764
1765       /* if address of & the result is remat the okay */
1766       if (dic->op == ADDRESS_OF &&
1767           OP_SYMBOL (IC_RESULT (dic))->remat)
1768         continue;
1769
1770       /* if operand has size of three or more & this
1771          operation is a '*','/' or '%' then 'b' may
1772          cause a problem */
1773       if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
1774           getSize (operandType (op)) >= 3)
1775         return NULL;
1776
1777       /* if left or right or result is in far space */
1778       if (isOperandInFarSpace (IC_LEFT (dic)) ||
1779           isOperandInFarSpace (IC_RIGHT (dic)) ||
1780           isOperandInFarSpace (IC_RESULT (dic)) ||
1781           IS_OP_RUONLY (IC_LEFT (dic)) ||
1782           IS_OP_RUONLY (IC_RIGHT (dic)) ||
1783           IS_OP_RUONLY (IC_RESULT (dic)))
1784         {
1785           return NULL;
1786         }
1787       /* if left or right or result is on stack */
1788       if (isOperandOnStack(IC_LEFT(dic)) ||
1789           isOperandOnStack(IC_RIGHT(dic)) ||
1790           isOperandOnStack(IC_RESULT(dic))) {
1791         return NULL;
1792       }
1793     }
1794
1795   OP_SYMBOL (op)->ruonly = 1;
1796   return sic;
1797
1798 }
1799
1800 /*-----------------------------------------------------------------*/
1801 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
1802 /*-----------------------------------------------------------------*/
1803 static bool
1804 isBitwiseOptimizable (iCode * ic)
1805 {
1806   sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
1807   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
1808
1809   /* bitwise operations are considered optimizable
1810      under the following conditions (Jean-Louis VERN) 
1811
1812      x & lit
1813      bit & bit
1814      bit & x
1815      bit ^ bit
1816      bit ^ x
1817      x   ^ lit
1818      x   | lit
1819      bit | bit
1820      bit | x
1821   */
1822   if (IS_LITERAL(rtype) ||
1823       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
1824     return TRUE;
1825   else
1826     return FALSE;
1827 }
1828
1829 /*-----------------------------------------------------------------*/
1830 /* packForPush - hueristics to reduce iCode for pushing            */
1831 /*-----------------------------------------------------------------*/
1832 static void
1833 packForPush (iCode * ic, eBBlock * ebp)
1834 {
1835   iCode *dic, *lic;
1836   bitVect *dbv;
1837
1838   if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
1839     return;
1840
1841   /* must have only definition & one usage */
1842   if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
1843       bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
1844     return;
1845
1846   /* find the definition */
1847   if (!(dic = hTabItemWithKey (iCodehTab,
1848                                bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
1849     return;
1850
1851   if (dic->op != '=' || POINTER_SET (dic))
1852     return;
1853
1854   /* make sure the right side does not have any definitions
1855      inbetween */
1856   dbv = OP_DEFS(IC_RIGHT(dic));
1857   for (lic = ic; lic && lic != dic ; lic = lic->prev) {
1858     if (bitVectBitValue(dbv,lic->key)) 
1859       return ;
1860   }
1861   /* make sure they have the same type */
1862   {
1863     sym_link *itype=operandType(IC_LEFT(ic));
1864     sym_link *ditype=operandType(IC_RIGHT(dic));
1865
1866     if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
1867         SPEC_LONG(itype)!=SPEC_LONG(ditype))
1868       return;
1869   }
1870   /* extend the live range of replaced operand if needed */
1871   if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) {
1872           OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
1873   }
1874   /* we now know that it has one & only one def & use
1875      and the that the definition is an assignment */
1876   IC_LEFT (ic) = IC_RIGHT (dic);
1877    
1878   remiCodeFromeBBlock (ebp, dic);
1879   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1880   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1881 }
1882
1883 /*-----------------------------------------------------------------*/
1884 /* packRegisters - does some transformations to reduce register    */
1885 /*                   pressure                                      */
1886 /*-----------------------------------------------------------------*/
1887 static void packRegisters (eBBlock * ebp) {
1888   iCode *ic;
1889   int change = 0;
1890   
1891   return; // that's it for now
1892
1893   while (1) {
1894     change = 0;
1895     
1896     for (ic = ebp->sch; ic; ic = ic->next) {
1897       if (ic->op == '=')
1898         change += packRegsForAssign (ic, ebp);
1899     }
1900     
1901     if (!change)
1902       break;
1903   }
1904
1905   for (ic = ebp->sch; ic; ic = ic->next)
1906     {
1907       /* if this is an itemp & result of an address of a true sym 
1908          then mark this as rematerialisable   */
1909       if (ic->op == ADDRESS_OF &&
1910           IS_ITEMP (IC_RESULT (ic)) &&
1911           IS_TRUE_SYMOP (IC_LEFT (ic)) &&
1912           bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
1913           !OP_SYMBOL (IC_LEFT (ic))->onStack)
1914         {
1915
1916           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1917           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1918           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1919
1920         }
1921
1922       /* if straight assignment then carry remat flag if
1923          this is the only definition */
1924       if (ic->op == '=' &&
1925           !POINTER_SET (ic) &&
1926           IS_SYMOP (IC_RIGHT (ic)) &&
1927           OP_SYMBOL (IC_RIGHT (ic))->remat &&
1928           !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
1929           bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
1930         {
1931
1932           OP_SYMBOL (IC_RESULT (ic))->remat =
1933             OP_SYMBOL (IC_RIGHT (ic))->remat;
1934           OP_SYMBOL (IC_RESULT (ic))->rematiCode =
1935             OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1936         }
1937
1938       /* if cast to a generic pointer & the pointer being
1939          cast is remat, then we can remat this cast as well */
1940       if (ic->op == CAST && 
1941           IS_SYMOP(IC_RIGHT(ic)) &&
1942           OP_SYMBOL(IC_RIGHT(ic))->remat ) {
1943               sym_link *to_type = operandType(IC_LEFT(ic));
1944               sym_link *from_type = operandType(IC_RIGHT(ic));
1945               if (IS_GENPTR(to_type) && IS_PTR(from_type)) {                  
1946                       OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1947                       OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1948                       OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1949               }
1950       }
1951
1952       /* if this is a +/- operation with a rematerizable 
1953          then mark this as rematerializable as well */
1954       if ((ic->op == '+' || ic->op == '-') &&
1955           (IS_SYMOP (IC_LEFT (ic)) &&
1956            IS_ITEMP (IC_RESULT (ic)) &&
1957            IS_OP_LITERAL (IC_RIGHT (ic))) &&
1958            OP_SYMBOL (IC_LEFT (ic))->remat &&
1959           (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
1960            bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1)
1961         {
1962           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1963           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1964           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1965         }
1966
1967       /* mark the pointer usages */
1968       if (POINTER_SET (ic))
1969         OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
1970
1971       if (POINTER_GET (ic))
1972         OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
1973
1974       /* if the condition of an if instruction
1975          is defined in the previous instruction and
1976          this is the only usage then
1977          mark the itemp as a conditional */
1978       if ((IS_CONDITIONAL (ic) ||
1979            (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) &&
1980           ic->next && ic->next->op == IFX &&
1981           bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
1982           isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
1983           OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
1984         {
1985           OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
1986           continue;
1987         }
1988
1989       /* reduce for support function calls */
1990       if (ic->supportRtn || ic->op == '+' || ic->op == '-')
1991         packRegsForSupport (ic, ebp);
1992
1993       /* some cases the redundant moves can
1994          can be eliminated for return statements */
1995       if ((ic->op == RETURN || ic->op == SEND) &&
1996           !isOperandInFarSpace (IC_LEFT (ic)) &&
1997           options.model == MODEL_SMALL) {
1998         if (0 && options.stackAuto) {
1999           /* we should check here if acc will be clobbered for stack
2000              offset calculations */
2001         } else {
2002           packRegsForOneuse (ic, IC_LEFT (ic), ebp);
2003         }
2004       }
2005
2006       /* if pointer set & left has a size more than
2007          one and right is not in far space */
2008       if (POINTER_SET (ic) &&
2009           !isOperandInFarSpace (IC_RIGHT (ic)) &&
2010           !OP_SYMBOL (IC_RESULT (ic))->remat &&
2011           !IS_OP_RUONLY (IC_RIGHT (ic)) &&
2012           getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
2013
2014         packRegsForOneuse (ic, IC_RESULT (ic), ebp);
2015
2016       /* if pointer get */
2017       if (POINTER_GET (ic) &&
2018           !isOperandInFarSpace (IC_RESULT (ic)) &&
2019           !OP_SYMBOL (IC_LEFT (ic))->remat &&
2020           !IS_OP_RUONLY (IC_RESULT (ic)) &&
2021           getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
2022
2023         packRegsForOneuse (ic, IC_LEFT (ic), ebp);
2024
2025
2026       /* if this is cast for intergral promotion then
2027          check if only use of  the definition of the 
2028          operand being casted/ if yes then replace
2029          the result of that arithmetic operation with 
2030          this result and get rid of the cast */
2031       if (ic->op == CAST)
2032         {
2033           sym_link *fromType = operandType (IC_RIGHT (ic));
2034           sym_link *toType = operandType (IC_LEFT (ic));
2035
2036           if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
2037               getSize (fromType) != getSize (toType) &&
2038               SPEC_USIGN (fromType) == SPEC_USIGN (toType))
2039             {
2040
2041               iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
2042               if (dic)
2043                 {
2044                   if (IS_ARITHMETIC_OP (dic))
2045                     {                  
2046                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
2047                       IC_RESULT (dic) = IC_RESULT (ic);
2048                       remiCodeFromeBBlock (ebp, ic);
2049                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
2050                       hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
2051                       OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
2052                       ic = ic->prev;
2053                     }
2054                   else
2055                     OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
2056                 }
2057             }
2058           else
2059             {
2060
2061               /* if the type from and type to are the same
2062                  then if this is the only use then packit */
2063               if (compareType (operandType (IC_RIGHT (ic)),
2064                              operandType (IC_LEFT (ic))) == 1)
2065                 {
2066                   iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
2067                   if (dic)
2068                     {
2069                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
2070                       IC_RESULT (dic) = IC_RESULT (ic);
2071                       remiCodeFromeBBlock (ebp, ic);
2072                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
2073                       hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
2074                       OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
2075                       ic = ic->prev;
2076                     }
2077                 }
2078             }
2079         }
2080
2081       /* pack for PUSH 
2082          iTempNN := (some variable in farspace) V1
2083          push iTempNN ;
2084          -------------
2085          push V1
2086        */
2087       if (ic->op == IPUSH)
2088         {
2089           packForPush (ic, ebp);
2090         }
2091     }
2092 }
2093
2094 /*-----------------------------------------------------------------*/
2095 /* assignRegisters - assigns registers to each live range as need  */
2096 /*-----------------------------------------------------------------*/
2097 void
2098 xa51_assignRegisters (eBBlock ** ebbs, int count)
2099 {
2100   iCode *ic;
2101   int i;
2102
2103   setToNull ((void *) &_G.funcrUsed);
2104   setToNull ((void *) &_G.totRegAssigned);
2105   _G.stackExtend = _G.dataExtend = 0;
2106
2107   /* change assignments this will remove some
2108      live ranges reducing some register pressure */
2109   for (i = 0; i < count; i++)
2110     packRegisters (ebbs[i]);
2111
2112   if (options.dump_pack)
2113     dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
2114
2115   /* first determine for each live range the number of 
2116      registers & the type of registers required for each */
2117   regTypeNum (*ebbs);
2118
2119   /* and serially allocate registers */
2120   serialRegAssign (ebbs, count);
2121
2122   freeAllRegs ();
2123
2124   /* if stack was extended then tell the user */
2125   if (_G.stackExtend)
2126     {
2127 /*      werror(W_TOOMANY_SPILS,"stack", */
2128 /*             _G.stackExtend,currFunc->name,""); */
2129       _G.stackExtend = 0;
2130     }
2131
2132   if (_G.dataExtend)
2133     {
2134 /*      werror(W_TOOMANY_SPILS,"data space", */
2135 /*             _G.dataExtend,currFunc->name,""); */
2136       _G.dataExtend = 0;
2137     }
2138
2139   /* after that create the register mask
2140      for each of the instruction */
2141   createRegMask (ebbs, count);
2142
2143   /* redo that offsets for stacked automatic variables */
2144   redoStackOffsets ();
2145
2146   if (options.dump_rassgn)
2147     {
2148       dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
2149       dumpLiveRanges (DUMP_LRANGE, liveRanges);
2150     }
2151
2152   /* do the overlaysegment stuff SDCCmem.c */
2153   doOverlays (ebbs, count);
2154
2155   /* now get back the chain */
2156   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
2157
2158   genXA51Code (ic);
2159
2160   /* free up any _G.stackSpil locations allocated */
2161   applyToSet (_G.stackSpil, deallocStackSpil);
2162   _G.slocNum = 0;
2163   setToNull ((void **) &_G.stackSpil);
2164   setToNull ((void **) &_G.spiltSet);
2165   /* mark all registers as free */
2166   freeAllRegs ();
2167
2168   return;
2169 }