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