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