143e92b1b86c1c91ffc6fc710c3a04c4aa2782b3
[fw/sdcc] / src / pic16 / ralloc.c
1 /*------------------------------------------------------------------------
2
3   ralloc.c - source file for register allocation. PIC16 specific
4
5                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
6                 Added Pic Port T.scott Dattalo scott@dattalo.com (2000)
7                 Added Pic16 Port Martin Dubuc m.dubuc@rogers.com (2002)
8
9    This program is free software; you can redistribute it and/or modify it
10    under the terms of the GNU General Public License as published by the
11    Free Software Foundation; either version 2, or (at your option) any
12    later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22    
23    In other words, you are welcome to use, share and improve this program.
24    You are forbidden to forbid anyone else to use, share and improve
25    what you give them.   Help stamp out software-hoarding!  
26 -------------------------------------------------------------------------*/
27
28 #include "common.h"
29 #include "ralloc.h"
30 #include "pcode.h"
31 #include "gen.h"
32 #include "device.h"
33
34 #if defined(__BORLANDC__) || defined(_MSC_VER)
35 #define STRCASECMP stricmp
36 #else
37 #define STRCASECMP strcasecmp
38 #endif
39
40 #ifndef debugf
41 #define debugf(frm, rest)       _debugf(__FILE__, __LINE__, frm, rest)
42 #endif
43 void _debugf(char *f, int l, char *frm, ...);
44
45 #define NEWREG_DEBUG    0
46 //#define USE_ONSTACK
47
48
49 /*-----------------------------------------------------------------*/
50 /* At this point we start getting processor specific although      */
51 /* some routines are non-processor specific & can be reused when   */
52 /* targetting other processors. The decision for this will have    */
53 /* to be made on a routine by routine basis                        */
54 /* routines used to pack registers are most definitely not reusable */
55 /* since the pack the registers depending strictly on the MCU      */
56 /*-----------------------------------------------------------------*/
57
58 regs *pic16_typeRegWithIdx (int idx, int type, int fixed);
59 extern void genpic16Code (iCode *);
60
61 /* Global data */
62 static struct
63   {
64     bitVect *spiltSet;
65     set *stackSpil;
66     bitVect *regAssigned;
67     short blockSpil;
68     int slocNum;
69     bitVect *funcrUsed;         /* registers used in a function */
70     int stackExtend;
71     int dataExtend;
72   }
73 _G;
74
75 /* Shared with gen.c */
76 int pic16_ptrRegReq;            /* one byte pointer register required */
77
78
79 set *pic16_dynAllocRegs=NULL;
80 set *pic16_dynStackRegs=NULL;
81 set *pic16_dynProcessorRegs=NULL;
82 set *pic16_dynDirectRegs=NULL;
83 set *pic16_dynDirectBitRegs=NULL;
84 set *pic16_dynInternalRegs=NULL;
85 set *pic16_dynAccessRegs=NULL;
86
87 static hTab *dynDirectRegNames=NULL;
88 static hTab *dynAllocRegNames=NULL;
89 static hTab *dynProcRegNames=NULL;
90 static hTab *dynAccessRegNames=NULL;
91 //static hTab  *regHash = NULL;    /* a hash table containing ALL registers */
92
93 extern set *sectNames;
94
95 set *pic16_rel_udata=NULL;      /* relocatable uninitialized registers */
96 set *pic16_fix_udata=NULL;      /* absolute uninitialized registers */
97 set *pic16_equ_data=NULL;       /* registers used by equates */
98 set *pic16_int_regs=NULL;       /* internal registers placed in access bank 0 to 0x7f */
99 set *pic16_acs_udata=NULL;      /* access bank variables */
100
101 set *pic16_builtin_functions=NULL;
102
103 static int dynrIdx=0x00;                //0x20;         // starting temporary register rIdx
104 static int rDirectIdx=0;
105
106 int pic16_nRegs = 128;   // = sizeof (regspic16) / sizeof (regs);
107
108 int pic16_Gstack_base_addr=0; /* The starting address of registers that
109                          * are used to pass and return parameters */
110
111
112 int _inRegAllocator=0;  /* flag that marks whther allocReg happens while
113                          * inside the register allocator function */
114                          
115
116 static void spillThis (symbol *);
117 int pic16_ralloc_debug = 0;
118 static FILE *debugF = NULL;
119 /*-----------------------------------------------------------------*/
120 /* debugLog - open a file for debugging information                */
121 /*-----------------------------------------------------------------*/
122 //static void debugLog(char *inst,char *fmt, ...)
123 static void
124 debugLog (char *fmt,...)
125 {
126   static int append = 0;        // First time through, open the file without append.
127
128   char buffer[256];
129   //char *bufferP=buffer;
130   va_list ap;
131
132   if (!pic16_ralloc_debug || !dstFileName)
133     return;
134
135
136   if (!debugF)
137     {
138       /* create the file name */
139       strcpy (buffer, dstFileName);
140       strcat (buffer, ".d");
141
142       if (!(debugF = fopen (buffer, (append ? "a+" : "w"))))
143         {
144           werror (E_FILE_OPEN_ERR, buffer);
145           exit (1);
146         }
147       append = 1;               // Next time debubLog is called, we'll append the debug info
148
149     }
150
151   va_start (ap, fmt);
152
153   vsprintf (buffer, fmt, ap);
154
155   fprintf (debugF, "%s", buffer);
156   //fprintf (stderr, "%s", buffer);
157 /*
158    while (isspace((unsigned char)*bufferP)) bufferP++;
159
160    if (bufferP && *bufferP) 
161    lineCurr = (lineCurr ?
162    connectLine(lineCurr,newLineNode(lb)) :
163    (lineHead = newLineNode(lb)));
164    lineCurr->isInline = _G.inLine;
165    lineCurr->isDebug  = _G.debugLine;
166  */
167   va_end (ap);
168
169 }
170
171 static void
172 debugNewLine (void)
173 {
174   if(!pic16_ralloc_debug)return;
175
176   if (debugF)
177     fputc ('\n', debugF);
178 }
179 /*-----------------------------------------------------------------*/
180 /* debugLogClose - closes the debug log file (if opened)           */
181 /*-----------------------------------------------------------------*/
182 static void
183 debugLogClose (void)
184 {
185   if (debugF) {
186     fclose (debugF);
187     debugF = NULL;
188   }
189 }
190
191 #define AOP(op) op->aop
192
193 static char *
194 debugAopGet (char *str, operand * op)
195 {
196         if(!pic16_ralloc_debug)return NULL;
197
198         if (str)
199                 debugLog (str);
200
201         printOperand (op, debugF);
202         debugNewLine ();
203
204   return NULL;
205 }
206
207 char *
208 pic16_decodeOp (unsigned int op)
209 {
210         if (op < 128 && op > ' ') {
211                 buffer[0] = (op & 0xff);
212                 buffer[1] = 0;
213           return buffer;
214         }
215
216         switch (op) {
217                 case IDENTIFIER:        return "IDENTIFIER";
218                 case TYPE_NAME:         return "TYPE_NAME";
219                 case CONSTANT:          return "CONSTANT";
220                 case STRING_LITERAL:    return "STRING_LITERAL";
221                 case SIZEOF:            return "SIZEOF";
222                 case PTR_OP:            return "PTR_OP";
223                 case INC_OP:            return "INC_OP";
224                 case DEC_OP:            return "DEC_OP";
225                 case LEFT_OP:           return "LEFT_OP";
226                 case RIGHT_OP:          return "RIGHT_OP";
227                 case LE_OP:             return "LE_OP";
228                 case GE_OP:             return "GE_OP";
229                 case EQ_OP:             return "EQ_OP";
230                 case NE_OP:             return "NE_OP";
231                 case AND_OP:            return "AND_OP";
232                 case OR_OP:             return "OR_OP";
233                 case MUL_ASSIGN:        return "MUL_ASSIGN";
234                 case DIV_ASSIGN:        return "DIV_ASSIGN";
235                 case MOD_ASSIGN:        return "MOD_ASSIGN";
236                 case ADD_ASSIGN:        return "ADD_ASSIGN";
237                 case SUB_ASSIGN:        return "SUB_ASSIGN";
238                 case LEFT_ASSIGN:       return "LEFT_ASSIGN";
239                 case RIGHT_ASSIGN:      return "RIGHT_ASSIGN";
240                 case AND_ASSIGN:        return "AND_ASSIGN";
241                 case XOR_ASSIGN:        return "XOR_ASSIGN";
242                 case OR_ASSIGN:         return "OR_ASSIGN";
243                 case TYPEDEF:           return "TYPEDEF";
244                 case EXTERN:            return "EXTERN";
245                 case STATIC:            return "STATIC";
246                 case AUTO:              return "AUTO";
247                 case REGISTER:          return "REGISTER";
248                 case CODE:              return "CODE";
249                 case EEPROM:            return "EEPROM";
250                 case INTERRUPT:         return "INTERRUPT";
251                 case SFR:               return "SFR";
252                 case AT:                return "AT";
253                 case SBIT:              return "SBIT";
254                 case REENTRANT:         return "REENTRANT";
255                 case USING:             return "USING";
256                 case XDATA:             return "XDATA";
257                 case DATA:              return "DATA";
258                 case IDATA:             return "IDATA";
259                 case PDATA:             return "PDATA";
260                 case VAR_ARGS:          return "VAR_ARGS";
261                 case CRITICAL:          return "CRITICAL";
262                 case NONBANKED:         return "NONBANKED";
263                 case BANKED:            return "BANKED";
264                 case CHAR:              return "CHAR";
265                 case SHORT:             return "SHORT";
266                 case INT:               return "INT";
267                 case LONG:              return "LONG";
268                 case SIGNED:            return "SIGNED";
269                 case UNSIGNED:          return "UNSIGNED";
270                 case FLOAT:             return "FLOAT";
271                 case DOUBLE:            return "DOUBLE";
272                 case CONST:             return "CONST";
273                 case VOLATILE:          return "VOLATILE";
274                 case VOID:              return "VOID";
275                 case BIT:               return "BIT";
276                 case STRUCT:            return "STRUCT";
277                 case UNION:             return "UNION";
278                 case ENUM:              return "ENUM";
279                 case RANGE:             return "RANGE";
280                 case FAR:               return "FAR";
281                 case CASE:              return "CASE";
282                 case DEFAULT:           return "DEFAULT";
283                 case IF:                return "IF";
284                 case ELSE:              return "ELSE";
285                 case SWITCH:            return "SWITCH";
286                 case WHILE:             return "WHILE";
287                 case DO:                return "DO";
288                 case FOR:               return "FOR";
289                 case GOTO:              return "GOTO";
290                 case CONTINUE:          return "CONTINUE";
291                 case BREAK:             return "BREAK";
292                 case RETURN:            return "RETURN";
293                 case INLINEASM:         return "INLINEASM";
294                 case IFX:               return "IFX";
295                 case ADDRESS_OF:        return "ADDRESS_OF";
296                 case GET_VALUE_AT_ADDRESS:      return "GET_VALUE_AT_ADDRESS";
297                 case SPIL:              return "SPIL";
298                 case UNSPIL:            return "UNSPIL";
299                 case GETHBIT:           return "GETHBIT";
300                 case BITWISEAND:        return "BITWISEAND";
301                 case UNARYMINUS:        return "UNARYMINUS";
302                 case IPUSH:             return "IPUSH";
303                 case IPOP:              return "IPOP";
304                 case PCALL:             return "PCALL";
305                 case FUNCTION:          return "FUNCTION";
306                 case ENDFUNCTION:       return "ENDFUNCTION";
307                 case JUMPTABLE:         return "JUMPTABLE";
308                 case RRC:               return "RRC";
309                 case RLC:               return "RLC";
310                 case CAST:              return "CAST";
311                 case CALL:              return "CALL";
312                 case PARAM:             return "PARAM  ";
313                 case NULLOP:            return "NULLOP";
314                 case BLOCK:             return "BLOCK";
315                 case LABEL:             return "LABEL";
316                 case RECEIVE:           return "RECEIVE";
317                 case SEND:              return "SEND";
318                 case DUMMY_READ_VOLATILE:       return "DUMMY_READ_VOLATILE";
319         }
320         sprintf (buffer, "unkown op %d %c", op, op & 0xff);
321
322   return buffer;
323 }
324
325 #if 0
326 static char *decodeRegType(short type)
327 {
328         switch(type) {
329                 case REG_GPR: return "REG_GPR";
330                 case REG_PTR: return "REG_PTR";
331                 case REG_CND: return "REG_CNT";
332         
333         default:
334                 return "<unknown>";
335         }
336 }
337 #endif
338
339 /*-----------------------------------------------------------------*/
340 /*-----------------------------------------------------------------*/
341 static char *
342 debugLogRegType (short type)
343 {
344         if(!pic16_ralloc_debug)return NULL;
345         switch (type) {
346                 case REG_GPR: return "REG_GPR";
347                 case REG_PTR: return "REG_PTR";
348                 case REG_CND: return "REG_CND";
349         }
350         sprintf (buffer, "unknown reg type %d", type);
351
352   return buffer;
353 }
354
355 /*-----------------------------------------------------------------*/
356 /*-----------------------------------------------------------------*/
357 static int regname2key(char const *name)
358 {
359   int key = 0;
360
361   if(!name)
362     return 0;
363
364   while(*name) {
365
366     key += (*name++) + 1;
367
368   }
369
370   return ( (key + (key >> 4) + (key>>8)) & 0x3f);
371
372 }
373
374 /*-----------------------------------------------------------------*/
375 /* newReg - allocate and init memory for a new register            */
376 /*-----------------------------------------------------------------*/
377 regs* newReg(int type, short pc_type, int rIdx, char *name, unsigned size, int alias, operand *refop)
378 {
379
380   regs *dReg;
381
382         dReg = Safe_calloc(1,sizeof(regs));
383         dReg->type = type;
384         dReg->pc_type = pc_type;
385         dReg->rIdx = rIdx;
386         if(name) 
387                 dReg->name = Safe_strdup(name);
388         else {
389           if(xinst && pc_type == PO_GPR_TEMP) {
390             sprintf(buffer,"0x%02x", dReg->rIdx);
391           } else {
392             sprintf(buffer,"r0x%02x", dReg->rIdx);
393           }
394           
395           if(type == REG_STK) {
396             *buffer = 's';
397           }
398           dReg->name = Safe_strdup(buffer);
399         }
400
401
402         dReg->isFree = 0;
403         dReg->wasUsed = 1;
404         dReg->isEmitted = 0;
405
406         if(type == REG_SFR) {
407                 dReg->isFixed = 1;
408                 dReg->address = rIdx;
409                 dReg->accessBank = 1;
410         } else {
411                 dReg->isFixed = 0;
412                 dReg->address = 0;
413                 dReg->accessBank = 0;
414         }
415
416 #if NEWREG_DEBUG
417         fprintf(stderr,"newReg @ %p: %s, rIdx = 0x%02x\taccess= %d\tregop= %p\n",dReg, dReg->name,rIdx, dReg->accessBank, refop);
418 #endif
419         dReg->size = size;
420         dReg->alias = alias;
421         dReg->reg_alias = NULL;
422         dReg->reglives.usedpFlows = newSet();
423         dReg->reglives.assignedpFlows = newSet();
424         dReg->regop = refop;
425   
426         if(!(type == REG_SFR && alias == 0x80))
427                 hTabAddItem(&dynDirectRegNames, regname2key(dReg->name), dReg);
428
429   return dReg;
430 }
431
432 /*-----------------------------------------------------------------*/
433 /* regWithIdx - Search through a set of registers that matches idx */
434 /*-----------------------------------------------------------------*/
435 static regs *
436 regWithIdx (set *dRegs, int idx, unsigned fixed)
437 {
438   regs *dReg;
439
440 //#define D(text)       text
441 #define D(text)
442
443   for (dReg = setFirstItem(dRegs) ; dReg ; 
444        dReg = setNextItem(dRegs)) {
445
446         D(fprintf(stderr, "%s:%d testing reg w/rIdx = %d (%d f:%d)\t", __FUNCTION__, __LINE__, dReg->rIdx, idx, fixed));
447     if(idx == dReg->rIdx && (fixed == dReg->isFixed)) {
448           D(fprintf(stderr, "found!\n"));
449       return dReg;
450     } else
451           D(fprintf(stderr, "not found!\n"));
452   }
453
454   return NULL;
455 }
456
457 /*-----------------------------------------------------------------*/
458 /* regFindFree - Search for a free register in a set of registers  */
459 /*-----------------------------------------------------------------*/
460 static regs *
461 regFindFree (set *dRegs)
462 {
463   regs *dReg;
464
465   for (dReg = setFirstItem(dRegs) ; dReg ; 
466        dReg = setNextItem(dRegs)) {
467
468 //      fprintf(stderr, "%s:%d checking register %s (%p) [rIdx: 0x%02x] if free= %d\n",
469 //              __FILE__, __LINE__, dReg->name, dReg, dReg->rIdx, dReg->isFree);
470
471     if(dReg->isFree) {
472 //              fprintf(stderr, "%s:%d free register found, rIdx = %d\n", __FILE__, __LINE__, dReg->rIdx);
473                 
474       return dReg;
475     }
476   }
477
478   return NULL;
479 }
480
481 static regs *
482 regFindFreeNext(set *dRegs, regs *creg)
483 {
484   regs *dReg;
485
486     if(creg) {
487       /* position at current register */
488       for(dReg = setFirstItem(dRegs); dReg != creg; dReg = setNextItem(dRegs));
489     }
490     
491     for(dReg = setNextItem(dRegs); dReg; dReg = setNextItem(dRegs)) {
492       if(dReg->isFree) {
493         return dReg;
494       }
495     }
496   
497   return NULL;
498 }
499
500 /*-----------------------------------------------------------------*/
501 /* pic16_initStack - allocate registers for a pseudo stack               */
502 /*-----------------------------------------------------------------*/
503 void pic16_initStack(int base_address, int size)
504 {
505
506   int i;
507
508   pic16_Gstack_base_addr = base_address;
509   //fprintf(stderr,"initStack");
510
511   for(i = 0; i<size; i++)
512     addSet(&pic16_dynStackRegs,newReg(REG_STK, PO_GPR_TEMP,base_address++,NULL,1,0, NULL));
513 }
514
515 /*-----------------------------------------------------------------*
516  *-----------------------------------------------------------------*/
517 regs *
518 pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias)
519 {
520   regs *reg = newReg(REG_SFR, po_type, rIdx, name, 1, alias, NULL);
521
522 //      fprintf(stderr,"%s: %s addr =0x%x\n",__FUNCTION__, name,rIdx);
523
524         reg->wasUsed = 0;               // we do not know if they are going to be used at all
525         reg->accessBank = 1;            // implicit add access Bank
526
527         hTabAddItem(&dynProcRegNames, regname2key(reg->name), reg);
528
529   return addSet(&pic16_dynProcessorRegs, reg);
530 }
531
532 /*-----------------------------------------------------------------*
533  *-----------------------------------------------------------------*/
534
535 regs *
536 pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias)
537 {
538   regs * reg = newReg(REG_GPR, po_type, rIdx, name,1,alias, NULL);
539
540 //  fprintf(stderr,"%s:%d: %s   %s addr =0x%x\n",__FILE__, __LINE__, __FUNCTION__, name, rIdx);
541
542     if(reg) {
543       reg->wasUsed = 0;
544       return addSet(&pic16_dynInternalRegs,reg);
545     }
546
547   return NULL;
548 }
549
550
551 /*-----------------------------------------------------------------*/
552 /* allocReg - allocates register of given type                     */
553 /*-----------------------------------------------------------------*/
554 static regs *
555 allocReg (short type)
556 {
557   regs * reg=NULL;
558   
559 #define MAX_P16_NREGS   16
560
561
562 #if 0
563   if(dynrIdx > pic16_nRegs)
564         werror(W_POSSBUG2, __FILE__, __LINE__);
565         return NULL;
566 #endif
567
568         /* try to reuse some unused registers */
569         reg = regFindFree( pic16_dynAllocRegs );
570
571         if(reg) {
572 //              fprintf(stderr, "%s: [%s][cf:%p] found FREE register %s, rIdx: %d\n", __FILE__, (_inRegAllocator)?"ralloc":"", currFunc, reg->name, reg->rIdx);
573         }
574
575         if(!reg) {
576                 reg = newReg(REG_GPR, PO_GPR_TEMP, dynrIdx++, NULL, 1, 0, NULL);
577 //              fprintf(stderr, "%s [%s][cf:%p] allocating NEW register %s, rIdx: %d\n", __FILE__,
578 //                                      (_inRegAllocator)?"ralloc":"", currFunc, reg->name, reg->rIdx);
579
580 #if 1
581                 if(_inRegAllocator && (dynrIdx > MAX_P16_NREGS)) {
582                   //                  debugf("allocating more registers than available\n", 0);
583                   //                  return (NULL);
584                 }
585                 
586                 addSet(&pic16_dynAllocRegs, reg);
587                 hTabAddItem(&dynAllocRegNames, regname2key(reg->name), reg);
588 //              fprintf(stderr, "%s:%d added reg to pic16_dynAllocRegs = %p\n", __FUNCTION__, __LINE__, pic16_dynAllocRegs);
589 #endif
590         }
591         
592         debugLog ("%s of type %s for register rIdx: %d (0x%x)\n", __FUNCTION__, debugLogRegType (type), dynrIdx-1, dynrIdx-1);
593
594 #if 0
595         fprintf(stderr,"%s:%d: %s\t%s addr= 0x%x\trIdx= 0x%02x isFree: %d\n",
596                 __FILE__, __LINE__, __FUNCTION__, reg->name, reg->address, reg->rIdx, reg->isFree);
597 #endif
598         if(reg) {
599                 reg->isFree=0;
600                 reg->accessBank = 1;    /* this is a temporary register alloc in accessBank */
601                 reg->isLocal = 1;       /* this is a local frame register */
602 //              reg->wasUsed = 1;
603         }
604         
605         if (currFunc) {
606 //              fprintf(stderr, "%s:%d adding %s into function %s regsUsed\n", __FUNCTION__, __LINE__, reg->name, currFunc->name);
607                 currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, reg->rIdx);
608         }
609  
610   return (reg);         // addSet(&pic16_dynAllocRegs,reg);
611
612 }
613
614
615 /*-----------------------------------------------------------------*/
616 /* pic16_dirregWithName - search for register by name                    */
617 /*-----------------------------------------------------------------*/
618 regs *
619 pic16_dirregWithName (char *name)
620 {
621   int hkey;
622   regs *reg;
623
624   if(!name)
625     return NULL;
626
627   /* hash the name to get a key */
628
629   hkey = regname2key(name);
630
631 //      fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
632
633   reg = hTabFirstItemWK(dynDirectRegNames, hkey);
634
635   while(reg) {
636
637     if(STRCASECMP(reg->name, name) == 0) {
638 //              fprintf(stderr, "%s:%d: FOUND name = %s\thash = %d\n", __FUNCTION__, __LINE__, reg->name, hkey);
639       return(reg);
640     }
641
642     reg = hTabNextItemWK (dynDirectRegNames);
643   
644   }
645
646   return NULL; // name wasn't found in the hash table
647 }
648
649 /*-----------------------------------------------------------------*/
650 /* pic16_allocregWithName - search for register by name                    */
651 /*-----------------------------------------------------------------*/
652 regs *
653 pic16_allocregWithName (char *name)
654 {
655   int hkey;
656   regs *reg;
657
658   if(!name)
659     return NULL;
660
661   /* hash the name to get a key */
662
663   hkey = regname2key(name);
664
665   //fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
666
667   reg = hTabFirstItemWK(dynAllocRegNames, hkey);
668
669   while(reg) {
670
671     if(STRCASECMP(reg->name, name) == 0) {
672       return(reg);
673     }
674
675     reg = hTabNextItemWK (dynAllocRegNames);
676   
677   }
678
679   return NULL; // name wasn't found in the hash table
680
681 }
682
683
684 /*-----------------------------------------------------------------*/
685 /* pic16_procregWithName - search for register by name                    */
686 /*-----------------------------------------------------------------*/
687 regs *
688 pic16_procregWithName (char *name)
689 {
690   int hkey;
691   regs *reg;
692
693   if(!name)
694     return NULL;
695
696   /* hash the name to get a key */
697
698   hkey = regname2key(name);
699
700 //      fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
701
702   reg = hTabFirstItemWK(dynProcRegNames, hkey);
703
704   while(reg) {
705
706     if(STRCASECMP(reg->name, name) == 0) {
707       return(reg);
708     }
709
710     reg = hTabNextItemWK (dynProcRegNames);
711   
712   }
713
714   return NULL; // name wasn't found in the hash table
715
716 }
717
718 /*-----------------------------------------------------------------*/
719 /* pic16_accessregWithName - search for register by name           */
720 /*-----------------------------------------------------------------*/
721 regs *
722 pic16_accessregWithName (char *name)
723 {
724   int hkey;
725   regs *reg;
726
727   if(!name)
728     return NULL;
729
730   /* hash the name to get a key */
731
732   hkey = regname2key(name);
733
734 //      fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
735
736   reg = hTabFirstItemWK(dynAccessRegNames, hkey);
737
738   while(reg) {
739
740     if(STRCASECMP(reg->name, name) == 0) {
741       return(reg);
742     }
743
744     reg = hTabNextItemWK (dynAccessRegNames);
745   
746   }
747
748   return NULL; // name wasn't found in the hash table
749
750 }
751
752 regs *pic16_regWithName(char *name)
753 {
754   regs *reg;
755
756         reg = pic16_dirregWithName( name );
757         if(reg)return reg;
758         
759         reg = pic16_procregWithName( name );
760         if(reg)return reg;
761         
762         reg = pic16_allocregWithName( name );
763         if(reg)return reg;
764
765         reg = pic16_accessregWithName( name );
766         if(reg)return reg;
767         
768   return NULL;
769 }
770
771
772 /*-----------------------------------------------------------------*/
773 /* pic16_allocDirReg - allocates register of given type                  */
774 /*-----------------------------------------------------------------*/
775 regs *
776 pic16_allocDirReg (operand *op )
777 {
778   regs *reg;
779   char *name;
780
781         if(!IS_SYMOP(op)) {
782                 debugLog ("%s BAD, op is NULL\n", __FUNCTION__);
783 //              fprintf(stderr, "%s BAD, op is NULL\n", __FUNCTION__);
784           return NULL;
785         }
786
787         name = OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name;
788
789
790         if(!SPEC_OCLS( OP_SYM_ETYPE(op))) {
791 #if 0
792                 if(pic16_debug_verbose)
793                 {
794                         fprintf(stderr, "%s:%d symbol %s(r:%s) is not assigned to a memmap\n", __FILE__, __LINE__,
795                                 OP_SYMBOL(op)->name, OP_SYMBOL(op)->rname);
796                 }
797 #endif
798                 return NULL;
799         }
800
801         if(!IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
802                 || !IN_FARSPACE(SPEC_OCLS( OP_SYM_ETYPE(op))) ) {
803
804 #if 0
805                 if(pic16_debug_verbose) {
806                         fprintf(stderr, "dispace:%d farspace:%d codespace:%d regspace:%d stack:%d eeprom: %d regparm: %d isparm: %d\n",
807                                 IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
808                                 IN_FARSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
809                                 IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
810                                 IN_REGSP( SPEC_OCLS( OP_SYM_ETYPE(op))),
811                                 IN_STACK( OP_SYM_ETYPE(op)),
812                                 SPEC_OCLS(OP_SYM_ETYPE(op)) == eeprom,
813                                 IS_REGPARM(OP_SYM_ETYPE(op)),
814                                 IS_PARM(op));
815
816                         fprintf(stderr, "%s:%d symbol %s NOT in dirspace\n", __FILE__, __LINE__,
817                         OP_SYMBOL(op)->name);
818                 }
819 #endif
820
821         }
822
823
824
825         if (IS_CODE ( OP_SYM_ETYPE(op)) ) {
826 //              fprintf(stderr, "%s:%d sym: %s in codespace\n", __FUNCTION__, __LINE__, OP_SYMBOL(op)->name);
827                 return NULL;
828         }
829
830         if(IS_ITEMP(op))return NULL;
831         
832 //      if(IS_STATIC(OP_SYM_ETYPE(op)))return NULL;
833         
834         if(IN_STACK(OP_SYM_ETYPE(op)))return NULL;
835         
836         debugLog ("%s:%d symbol name %s\n", __FUNCTION__, __LINE__, name);
837 //      fprintf(stderr, "%s symbol name %s\tSTATIC:%d\n", __FUNCTION__,name, IS_STATIC(OP_SYM_ETYPE(op)));
838
839         {
840                 if(SPEC_CONST ( OP_SYM_ETYPE(op)) && (IS_CHAR ( OP_SYM_ETYPE(op)) )) {
841                         debugLog(" %d  const char\n",__LINE__);
842                         debugLog(" value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
843 //                      fprintf(stderr, " %d  const char\n",__LINE__);
844 //                      fprintf(stderr, " value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
845                 }
846
847         
848                 debugLog("  %d  storage class %d \n",__LINE__,SPEC_SCLS( OP_SYM_ETYPE(op)));
849                 if (IS_CODE ( OP_SYM_ETYPE(op)) )
850                         debugLog(" %d  code space\n",__LINE__);
851
852                 if (IS_INTEGRAL ( OP_SYM_ETYPE(op)) )
853                         debugLog(" %d  integral\n",__LINE__);
854
855                 if (IS_LITERAL ( OP_SYM_ETYPE(op)) )
856                         debugLog(" %d  literal\n",__LINE__);
857
858                 if (IS_SPEC ( OP_SYM_ETYPE(op)) )
859                         debugLog(" %d  specifier\n",__LINE__);
860
861                 debugAopGet(NULL, op);
862         }
863
864
865         reg = pic16_dirregWithName(name);
866
867         if(!reg) {
868           int address = 0;
869           int regtype = REG_GPR;
870     
871                 /* if this is at an absolute address, then get the address. */
872                 if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
873                         address = SPEC_ADDR ( OP_SYM_ETYPE(op));
874 //                      fprintf(stderr,"reg %s is at an absolute address: 0x%03x\n",name,address);
875                 }
876
877                 /* Register wasn't found in hash, so let's create
878                  * a new one and put it in the hash table AND in the 
879                  * dynDirectRegNames set */
880                 if(IS_CODE(OP_SYM_ETYPE(op)) || IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))) {
881                         debugLog("%s:%d sym: %s in codespace\n", __FUNCTION__, __LINE__, OP_SYMBOL(op)->name);
882                   return NULL;
883                 }
884
885
886 #if 0
887                 if(OP_SYMBOL(op)->onStack) {
888                         fprintf(stderr, "%s:%d onStack %s offset: %d\n", __FILE__, __LINE__,
889                                 OP_SYMBOL(op)->name, OP_SYMBOL(op)->stack);
890                 }
891 #endif
892
893                 if(!IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
894                         || !IN_FARSPACE(SPEC_OCLS( OP_SYM_ETYPE(op))) ) {
895
896 #if 0
897                         if(pic16_debug_verbose)
898                         {
899                                 fprintf(stderr, "dispace:%d farspace:%d codespace:%d regspace:%d stack:%d eeprom: %d\n",
900                                         IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
901                                         IN_FARSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
902                                         IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
903                                         IN_REGSP( SPEC_OCLS( OP_SYM_ETYPE(op))),
904                                         IN_STACK( OP_SYM_ETYPE(op)),
905                                         SPEC_OCLS(OP_SYM_ETYPE(op)) == eeprom);
906
907                                         fprintf(stderr, "%s:%d symbol %s NOT in dirspace\n", __FILE__, __LINE__,
908                                         OP_SYMBOL(op)->name);
909                         }
910 #endif
911                 }
912
913                 reg = newReg(regtype, PO_DIR, rDirectIdx++, name,getSize (OP_SYMBOL (op)->type),0, op);
914                 debugLog ("%d  -- added %s to hash, size = %d\n", __LINE__, name,reg->size);
915
916                 if( SPEC_SCLS( OP_SYM_ETYPE( op ) ) == S_REGISTER ) {
917                         fprintf(stderr, "%s:%d symbol %s is declared as register\n", __FILE__, __LINE__,
918                                 name);
919                                 
920                         reg->accessBank = 1;
921                         checkAddReg(&pic16_dynAccessRegs, reg);
922                         hTabAddItem(&dynAccessRegNames, regname2key(name), reg);
923                         
924                   return (reg);
925                 }
926
927
928 //              if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
929 //                      fprintf(stderr, " ralloc.c at fixed address: %s - changing to REG_SFR\n",name);
930 //                      reg->type = REG_SFR;
931 //              }
932
933                 if (IS_BITVAR (OP_SYM_ETYPE(op))) {
934 //                      fprintf(stderr, "%s:%d adding %s in bit registers\n", __FILE__, __LINE__, reg->name);
935                         addSet(&pic16_dynDirectBitRegs, reg);
936                         reg->isBitField = 1;
937                 } else {
938 //                      fprintf(stderr, "%s:%d adding %s in direct registers\n", __FILE__, __LINE__, reg->name);
939 //                      addSet(&pic16_dynDirectRegs, reg);
940
941 #if 1
942                   if(!(IS_STATIC(OP_SYM_ETYPE(op))
943                       && OP_SYMBOL(op)->ival
944                   ))
945 #endif
946                     checkAddReg(&pic16_dynDirectRegs, reg);
947                 }
948         
949         } else {
950 //              debugLog ("  -- %s is declared at address 0x30000x\n",name);
951           return (reg);                 /* This was NULL before, but since we found it
952                                          * why not just return it?! */
953         }
954
955         if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
956                 reg->isFixed = 1;
957                 reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
958
959                 /* work around for user defined registers in access bank */
960                 if((reg->address>= 0x00 && reg->address < pic16->acsSplitOfs)
961                         || (reg->address >= (0xf00 + pic16->acsSplitOfs) && reg->address <= 0xfff))
962                         reg->accessBank = 1;
963                 
964                 debugLog ("  -- and it is at a fixed address 0x%02x\n",reg->address);
965         }
966
967   return reg;
968 }
969
970 /*-----------------------------------------------------------------*/
971 /* pic16_allocRegByName - allocates register of given type                  */
972 /*-----------------------------------------------------------------*/
973 regs *
974 pic16_allocRegByName (char *name, int size, operand *op)
975 {
976
977   regs *reg;
978
979   if(!name) {
980     fprintf(stderr, "%s - allocating a NULL register\n",__FUNCTION__);
981     exit(1);
982   }
983
984   /* First, search the hash table to see if there is a register with this name */
985   reg = pic16_dirregWithName(name);
986
987   if(!reg) {
988
989     /* Register wasn't found in hash, so let's create
990      * a new one and put it in the hash table AND in the 
991      * dynDirectRegNames set */
992
993         //fprintf (stderr,"%s:%d symbol name %s\tregop= %p\n", __FUNCTION__, __LINE__, name, op);
994
995     reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,size,0, op);
996
997     debugLog ("%d  -- added %s to hash, size = %d\n", __LINE__, name,reg->size);
998         //fprintf(stderr, "  -- added %s to hash, size = %d\n", name,reg->size);
999
1000     //hTabAddItem(&dynDirectRegNames, regname2key(name), reg);  /* initially commented out */
1001     addSet(&pic16_dynDirectRegs, reg);
1002   }
1003
1004   return reg;
1005 }
1006
1007 /*-----------------------------------------------------------------*/
1008 /* RegWithIdx - returns pointer to register with index number       */
1009 /*-----------------------------------------------------------------*/
1010 regs *pic16_typeRegWithIdx (int idx, int type, int fixed)
1011 {
1012
1013   regs *dReg;
1014
1015   debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx);
1016 //  fprintf(stderr, "%s - requesting index = 0x%x (type = %d [%s])\n", __FUNCTION__, idx, type, decodeRegType(type));
1017
1018   switch (type) {
1019
1020   case REG_GPR:
1021     if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx, fixed)) != NULL) {
1022
1023       debugLog ("Found a Dynamic Register!\n");
1024       return dReg;
1025     }
1026     if( (dReg = regWithIdx ( pic16_dynDirectRegs, idx, fixed)) != NULL ) {
1027       debugLog ("Found a Direct Register!\n");
1028       return dReg;
1029     }
1030
1031         if( (dReg = regWithIdx ( pic16_dynInternalRegs, idx, fixed)) != NULL ) {
1032       debugLog ("Found an Internal Register!\n");
1033       return dReg;
1034     }
1035                 
1036     break;
1037   case REG_STK:
1038     if( (dReg = regWithIdx ( pic16_dynStackRegs, idx, fixed)) != NULL ) {
1039       debugLog ("Found a Stack Register!\n");
1040       return dReg;
1041     }
1042     break;
1043   case REG_SFR:
1044     if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx, 1)) != NULL ) {
1045       debugLog ("Found a Processor Register!\n");
1046       return dReg;
1047     }
1048
1049   case REG_CND:
1050   case REG_PTR:
1051   default:
1052     break;
1053   }
1054
1055
1056   return NULL;
1057 }
1058
1059 /*-----------------------------------------------------------------*/
1060 /* pic16_regWithIdx - returns pointer to register with index number*/
1061 /*-----------------------------------------------------------------*/
1062 regs *
1063 pic16_regWithIdx (int idx)
1064 {
1065   regs *dReg;
1066
1067   if( (dReg = pic16_typeRegWithIdx(idx,REG_GPR,0)) != NULL)
1068     return dReg;
1069
1070   if( (dReg = pic16_typeRegWithIdx(idx,REG_SFR,0)) != NULL)
1071     return dReg;
1072
1073 #if 0
1074   if( (dReg = pic16_typeRegWithIdx(idx,REG_STK,0)) != NULL)
1075     return dReg;
1076 #endif
1077
1078   return NULL;
1079 }
1080
1081 /*-----------------------------------------------------------------*/
1082 /* pic16_regWithIdx - returns pointer to register with index number       */
1083 /*-----------------------------------------------------------------*/
1084 regs *
1085 pic16_allocWithIdx (int idx)
1086 {
1087
1088   regs *dReg=NULL;
1089
1090   debugLog ("%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
1091 //  fprintf(stderr, "%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
1092
1093   if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx,0)) != NULL) {
1094
1095     debugLog ("Found a Dynamic Register!\n");
1096   } else if( (dReg = regWithIdx ( pic16_dynStackRegs, idx,0)) != NULL ) {
1097     debugLog ("Found a Stack Register!\n");
1098   } else if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx,1)) != NULL ) {
1099     debugLog ("Found a Processor Register!\n");
1100     fprintf(stderr, "Found a processor register! %s\n", dReg->name);
1101   } else if( (dReg = regWithIdx ( pic16_dynInternalRegs, idx,0)) != NULL ) {
1102     debugLog ("Found an Internal Register!\n");
1103   } else {
1104     
1105     debugLog ("Dynamic Register not found\n");
1106
1107 #if 1
1108         dReg = newReg(REG_GPR, PO_GPR_TEMP, idx, NULL, 1, 0, NULL);
1109         addSet(&pic16_dynAllocRegs, dReg);
1110         hTabAddItem(&dynAllocRegNames, regname2key(dReg->name), dReg);
1111 #endif
1112
1113         if(!dReg) {
1114 //      return (NULL);
1115     //fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx);
1116             werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1117                     "allocWithIdx not found");
1118             exit (1);
1119         }
1120   }
1121
1122   dReg->wasUsed = 1;
1123   dReg->isFree = 0;
1124
1125   return dReg;
1126 }
1127 /*-----------------------------------------------------------------*/
1128 /*-----------------------------------------------------------------*/
1129 regs *
1130 pic16_findFreeReg(short type)
1131 {
1132   //  int i;
1133   regs* dReg;
1134
1135   switch (type) {
1136   case REG_GPR:
1137     if((dReg = regFindFree(pic16_dynAllocRegs)) != NULL)
1138       return dReg;
1139 //      return (addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL)));
1140     return allocReg( REG_GPR );
1141
1142   case REG_STK:
1143
1144     if((dReg = regFindFree(pic16_dynStackRegs)) != NULL)
1145       return dReg;
1146
1147     return NULL;
1148
1149   case REG_PTR:
1150   case REG_CND:
1151   case REG_SFR:
1152   default:
1153     return NULL;
1154   }
1155 }
1156
1157 regs *
1158 pic16_findFreeRegNext(short type, regs *creg)
1159 {
1160   //  int i;
1161   regs* dReg;
1162
1163   switch (type) {
1164   case REG_GPR:
1165     if((dReg = regFindFreeNext(pic16_dynAllocRegs, creg)) != NULL)
1166       return dReg;
1167 //        return (addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL)));
1168     return (allocReg( REG_GPR ) );
1169
1170   case REG_STK:
1171
1172     if((dReg = regFindFreeNext(pic16_dynStackRegs, creg)) != NULL)
1173       return dReg;
1174
1175     return NULL;
1176
1177   case REG_PTR:
1178   case REG_CND:
1179   case REG_SFR:
1180   default:
1181     return NULL;
1182   }
1183 }
1184 /*-----------------------------------------------------------------*/
1185 /* freeReg - frees a register                                      */
1186 /*-----------------------------------------------------------------*/
1187 static void
1188 freeReg (regs * reg)
1189 {
1190         debugLog ("%s\n", __FUNCTION__);
1191 //      fprintf(stderr, "%s:%d register %s (%p) is freed\n", __FILE__, __LINE__, reg->name, reg);
1192         reg->isFree = 1;
1193 }
1194
1195
1196 /*-----------------------------------------------------------------*/
1197 /* nFreeRegs - returns number of free registers                    */
1198 /*-----------------------------------------------------------------*/
1199 static int
1200 nFreeRegs (int type)
1201 {
1202   regs *reg;
1203   int nfr=0;
1204
1205
1206                 /* although I fixed the register allocation/freeing scheme
1207                  * the for loop below doesn't give valid results. I do not
1208                  * know why yet. -- VR 10-Jan-2003 */
1209                  
1210         return 100;
1211
1212
1213   /* dynamically allocate as many as we need and worry about
1214    * fitting them into a PIC later */
1215
1216   debugLog ("%s\n", __FUNCTION__);
1217
1218         for(reg = setFirstItem(pic16_dynAllocRegs); reg; reg=setNextItem(pic16_dynAllocRegs))
1219                 if((reg->type == type) && reg->isFree)nfr++;
1220
1221         fprintf(stderr, "%s:%d # of free registers= %d\n", __FILE__, __LINE__, nfr);
1222   return nfr;
1223 }
1224
1225 /*-----------------------------------------------------------------*/
1226 /* nfreeRegsType - free registers with type                         */
1227 /*-----------------------------------------------------------------*/
1228 static int
1229 nfreeRegsType (int type)
1230 {
1231   int nfr;
1232   debugLog ("%s\n", __FUNCTION__);
1233   if (type == REG_PTR)
1234     {
1235       if ((nfr = nFreeRegs (type)) == 0)
1236         return nFreeRegs (REG_GPR);
1237     }
1238
1239   return nFreeRegs (type);
1240 }
1241 #if 0
1242 static void writeSetUsedRegs(FILE *of, set *dRegs)
1243 {
1244
1245   regs *dReg;
1246
1247   for (dReg = setFirstItem(dRegs) ; dReg ; 
1248        dReg = setNextItem(dRegs)) {
1249
1250     if(dReg->wasUsed)
1251       fprintf (of, "\t%s\n",dReg->name);
1252   }
1253
1254 }
1255 #endif
1256
1257 extern void pic16_groupRegistersInSection(set *regset);
1258
1259 extern void pic16_dump_equates(FILE *of, set *equs);
1260 extern void pic16_dump_access(FILE *of, set *section);
1261 //extern void pic16_dump_map(void);
1262 extern void pic16_dump_usection(FILE *of, set *section, int fix);
1263 extern void pic16_dump_isection(FILE *of, set *section, int fix);
1264 extern void pic16_dump_int_registers(FILE *of, set *section);
1265 extern void pic16_dump_idata(FILE *of, set *idataSymSet);
1266
1267 extern void pic16_dump_gsection(FILE *of, set *sections);
1268
1269 static void packBits(set *bregs)
1270 {
1271   set *regset;
1272   regs *breg;
1273   regs *bitfield=NULL;
1274   regs *relocbitfield=NULL;
1275   int bit_no=0;
1276   int byte_no=-1;
1277   char buffer[20];
1278
1279
1280   for (regset = bregs ; regset ;
1281        regset = regset->next) {
1282
1283     breg = regset->item;
1284     breg->isBitField = 1;
1285     //fprintf(stderr,"bit reg: %s\n",breg->name);
1286
1287     if(breg->isFixed) {
1288       //fprintf(stderr,"packing bit at fixed address = 0x%03x\n",breg->address);
1289
1290       bitfield = pic16_typeRegWithIdx (breg->address >> 3, -1 , 1);
1291       breg->rIdx = breg->address & 7;
1292       breg->address >>= 3;
1293
1294       if(!bitfield) {
1295         sprintf (buffer, "fbitfield%02x", breg->address);
1296         //fprintf(stderr,"new bit field\n");
1297         bitfield = newReg(REG_SFR, PO_GPR_BIT,breg->address,buffer,1,0, NULL);
1298         bitfield->isBitField = 1;
1299         bitfield->isFixed = 1;
1300         bitfield->address = breg->address;
1301         addSet(&pic16_dynDirectRegs,bitfield);
1302         //hTabAddItem(&dynDirectRegNames, regname2key(buffer), bitfield);
1303       } else {
1304         //fprintf(stderr,"  which is occupied by %s (addr = %d)\n",bitfield->name,bitfield->address);
1305         ;
1306       }
1307       breg->reg_alias = bitfield;
1308       bitfield = NULL;
1309
1310     } else {
1311       if(!relocbitfield || bit_no >7) {
1312         byte_no++;
1313         bit_no=0;
1314         sprintf (buffer, "bitfield%d", byte_no);
1315         //fprintf(stderr,"new relocatable bit field\n");
1316         relocbitfield = newReg(REG_GPR, PO_GPR_BIT,rDirectIdx++,buffer,1,0, NULL);
1317         relocbitfield->isBitField = 1;
1318         addSet(&pic16_dynDirectRegs,relocbitfield);
1319         //hTabAddItem(&dynDirectRegNames, regname2key(buffer), relocbitfield);
1320
1321       }
1322
1323       breg->reg_alias = relocbitfield;
1324       breg->address = rDirectIdx;   /* byte_no; */
1325       breg->rIdx = bit_no++;
1326     }
1327   }
1328       
1329 }
1330
1331 void pic16_writeUsedRegs(FILE *of) 
1332 {
1333   packBits(pic16_dynDirectBitRegs);
1334
1335   pic16_groupRegistersInSection(pic16_dynAllocRegs);
1336   pic16_groupRegistersInSection(pic16_dynInternalRegs);
1337   pic16_groupRegistersInSection(pic16_dynStackRegs);
1338   pic16_groupRegistersInSection(pic16_dynDirectRegs);
1339   pic16_groupRegistersInSection(pic16_dynDirectBitRegs);
1340   pic16_groupRegistersInSection(pic16_dynProcessorRegs);
1341   pic16_groupRegistersInSection(pic16_dynAccessRegs);
1342         
1343   /* dump equates */
1344   pic16_dump_equates(of, pic16_equ_data);
1345
1346 //      pic16_dump_esection(of, pic16_rel_eedata, 0);
1347 //      pic16_dump_esection(of, pic16_fix_eedata, 0);
1348
1349   /* dump access bank symbols */
1350   pic16_dump_access(of, pic16_acs_udata);
1351
1352   /* dump initialised data */
1353   pic16_dump_isection(of, rel_idataSymSet, 0);
1354   pic16_dump_isection(of, fix_idataSymSet, 1);
1355
1356   if(!xinst) {
1357     /* dump internal registers */
1358     pic16_dump_int_registers(of, pic16_int_regs);
1359   }
1360         
1361   /* dump generic section variables */
1362   pic16_dump_gsection(of, sectNames);
1363
1364   /* dump other variables */
1365   pic16_dump_usection(of, pic16_rel_udata, 0);
1366   pic16_dump_usection(of, pic16_fix_udata, 1);
1367 }
1368
1369
1370 /*-----------------------------------------------------------------*/
1371 /* computeSpillable - given a point find the spillable live ranges */
1372 /*-----------------------------------------------------------------*/
1373 static bitVect *
1374 computeSpillable (iCode * ic)
1375 {
1376   bitVect *spillable;
1377
1378   debugLog ("%s\n", __FUNCTION__);
1379   /* spillable live ranges are those that are live at this 
1380      point . the following categories need to be subtracted
1381      from this set. 
1382      a) - those that are already spilt
1383      b) - if being used by this one
1384      c) - defined by this one */
1385
1386   spillable = bitVectCopy (ic->rlive);
1387   spillable =
1388     bitVectCplAnd (spillable, _G.spiltSet);     /* those already spilt */
1389   spillable =
1390     bitVectCplAnd (spillable, ic->uses);        /* used in this one */
1391   bitVectUnSetBit (spillable, ic->defKey);
1392   spillable = bitVectIntersect (spillable, _G.regAssigned);
1393   return spillable;
1394
1395 }
1396
1397 /*-----------------------------------------------------------------*/
1398 /* noSpilLoc - return true if a variable has no spil location      */
1399 /*-----------------------------------------------------------------*/
1400 static int
1401 noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
1402 {
1403   debugLog ("%s\n", __FUNCTION__);
1404   return (sym->usl.spillLoc ? 0 : 1);
1405 }
1406
1407 /*-----------------------------------------------------------------*/
1408 /* hasSpilLoc - will return 1 if the symbol has spil location      */
1409 /*-----------------------------------------------------------------*/
1410 static int
1411 hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
1412 {
1413   debugLog ("%s\n", __FUNCTION__);
1414   return (sym->usl.spillLoc ? 1 : 0);
1415 }
1416
1417 /*-----------------------------------------------------------------*/
1418 /* directSpilLoc - will return 1 if the splilocation is in direct  */
1419 /*-----------------------------------------------------------------*/
1420 static int
1421 directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
1422 {
1423   debugLog ("%s\n", __FUNCTION__);
1424   if (sym->usl.spillLoc &&
1425       (IN_DIRSPACE (SPEC_OCLS (sym->usl.spillLoc->etype))))
1426     return 1;
1427   else
1428     return 0;
1429 }
1430
1431 /*-----------------------------------------------------------------*/
1432 /* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
1433 /*                    but is not used as a pointer                 */
1434 /*-----------------------------------------------------------------*/
1435 static int
1436 hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
1437 {
1438   debugLog ("%s\n", __FUNCTION__);
1439   return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
1440 }
1441
1442 /*-----------------------------------------------------------------*/
1443 /* rematable - will return 1 if the remat flag is set              */
1444 /*-----------------------------------------------------------------*/
1445 static int
1446 rematable (symbol * sym, eBBlock * ebp, iCode * ic)
1447 {
1448   debugLog ("%s\n", __FUNCTION__);
1449   return sym->remat;
1450 }
1451
1452 /*-----------------------------------------------------------------*/
1453 /* notUsedInRemaining - not used or defined in remain of the block */
1454 /*-----------------------------------------------------------------*/
1455 static int
1456 notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
1457 {
1458   debugLog ("%s\n", __FUNCTION__);
1459   return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
1460           allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
1461 }
1462
1463 /*-----------------------------------------------------------------*/
1464 /* allLRs - return true for all                                    */
1465 /*-----------------------------------------------------------------*/
1466 static int
1467 allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
1468 {
1469   debugLog ("%s\n", __FUNCTION__);
1470   return 1;
1471 }
1472
1473 /*-----------------------------------------------------------------*/
1474 /* liveRangesWith - applies function to a given set of live range  */
1475 /*-----------------------------------------------------------------*/
1476 static set *
1477 liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
1478                 eBBlock * ebp, iCode * ic)
1479 {
1480   set *rset = NULL;
1481   int i;
1482
1483   debugLog ("%s\n", __FUNCTION__);
1484   if (!lrs || !lrs->size)
1485     return NULL;
1486
1487   for (i = 1; i < lrs->size; i++)
1488     {
1489       symbol *sym;
1490       if (!bitVectBitValue (lrs, i))
1491         continue;
1492
1493       /* if we don't find it in the live range 
1494          hash table we are in serious trouble */
1495       if (!(sym = hTabItemWithKey (liveRanges, i)))
1496         {
1497           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1498                   "liveRangesWith could not find liveRange");
1499           exit (1);
1500         }
1501
1502       if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
1503         addSetHead (&rset, sym);
1504     }
1505
1506   return rset;
1507 }
1508
1509
1510 /*-----------------------------------------------------------------*/
1511 /* leastUsedLR - given a set determines which is the least used    */
1512 /*-----------------------------------------------------------------*/
1513 static symbol *
1514 leastUsedLR (set * sset)
1515 {
1516   symbol *sym = NULL, *lsym = NULL;
1517
1518   debugLog ("%s\n", __FUNCTION__);
1519   sym = lsym = setFirstItem (sset);
1520
1521   if (!lsym)
1522     return NULL;
1523
1524   for (; lsym; lsym = setNextItem (sset))
1525     {
1526
1527       /* if usage is the same then prefer
1528          the spill the smaller of the two */
1529       if (lsym->used == sym->used)
1530         if (getSize (lsym->type) < getSize (sym->type))
1531           sym = lsym;
1532
1533       /* if less usage */
1534       if (lsym->used < sym->used)
1535         sym = lsym;
1536
1537     }
1538
1539   setToNull ((void *) &sset);
1540   sym->blockSpil = 0;
1541   return sym;
1542 }
1543
1544 /*-----------------------------------------------------------------*/
1545 /* noOverLap - will iterate through the list looking for over lap  */
1546 /*-----------------------------------------------------------------*/
1547 static int
1548 noOverLap (set * itmpStack, symbol * fsym)
1549 {
1550   symbol *sym;
1551   debugLog ("%s\n", __FUNCTION__);
1552
1553
1554   for (sym = setFirstItem (itmpStack); sym;
1555        sym = setNextItem (itmpStack))
1556     {
1557       if (sym->liveTo > fsym->liveFrom)
1558         return 0;
1559
1560     }
1561
1562   return 1;
1563 }
1564
1565 /*-----------------------------------------------------------------*/
1566 /* isFree - will return 1 if the a free spil location is found     */
1567 /*-----------------------------------------------------------------*/
1568 static
1569 DEFSETFUNC (isFree)
1570 {
1571   symbol *sym = item;
1572   V_ARG (symbol **, sloc);
1573   V_ARG (symbol *, fsym);
1574
1575   debugLog ("%s\n", __FUNCTION__);
1576   /* if already found */
1577   if (*sloc)
1578     return 0;
1579
1580   /* if it is free && and the itmp assigned to
1581      this does not have any overlapping live ranges
1582      with the one currently being assigned and
1583      the size can be accomodated  */
1584   if (sym->isFree &&
1585       noOverLap (sym->usl.itmpStack, fsym) &&
1586       getSize (sym->type) >= getSize (fsym->type))
1587     {
1588       *sloc = sym;
1589       return 1;
1590     }
1591
1592   return 0;
1593 }
1594
1595 /*-----------------------------------------------------------------*/
1596 /* spillLRWithPtrReg :- will spil those live ranges which use PTR  */
1597 /*-----------------------------------------------------------------*/
1598 static void
1599 spillLRWithPtrReg (symbol * forSym)
1600 {
1601   symbol *lrsym;
1602   regs *r0, *r1;
1603   int k;
1604
1605   debugLog ("%s\n", __FUNCTION__);
1606   if (!_G.regAssigned ||
1607       bitVectIsZero (_G.regAssigned))
1608     return;
1609
1610   r0 = pic16_regWithIdx (R0_IDX);
1611   r1 = pic16_regWithIdx (R1_IDX);
1612
1613   /* for all live ranges */
1614   for (lrsym = hTabFirstItem (liveRanges, &k); lrsym;
1615        lrsym = hTabNextItem (liveRanges, &k))
1616     {
1617       int j;
1618
1619       /* if no registers assigned to it or
1620          spilt */
1621       /* if it does not overlap with this then 
1622          not need to spill it */
1623
1624       if (lrsym->isspilt || !lrsym->nRegs ||
1625           (lrsym->liveTo < forSym->liveFrom))
1626         continue;
1627
1628       /* go thru the registers : if it is either
1629          r0 or r1 then spil it */
1630       for (j = 0; j < lrsym->nRegs; j++)
1631         if (lrsym->regs[j] == r0 ||
1632             lrsym->regs[j] == r1)
1633           {
1634             spillThis (lrsym);
1635             break;
1636           }
1637     }
1638
1639 }
1640
1641 /*-----------------------------------------------------------------*/
1642 /* createStackSpil - create a location on the stack to spil        */
1643 /*-----------------------------------------------------------------*/
1644 static symbol *
1645 createStackSpil (symbol * sym)
1646 {
1647   symbol *sloc = NULL;
1648   int useXstack, model, noOverlay;
1649
1650   char slocBuffer[30];
1651   debugLog ("%s\n", __FUNCTION__);
1652
1653   /* first go try and find a free one that is already 
1654      existing on the stack */
1655   if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
1656     {
1657       /* found a free one : just update & return */
1658       sym->usl.spillLoc = sloc;
1659       sym->stackSpil = 1;
1660       sloc->isFree = 0;
1661       addSetHead (&sloc->usl.itmpStack, sym);
1662       return sym;
1663     }
1664
1665   /* could not then have to create one , this is the hard part
1666      we need to allocate this on the stack : this is really a
1667      hack!! but cannot think of anything better at this time */
1668
1669   if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
1670     {
1671       fprintf (stderr, "kkkInternal error: slocBuffer overflowed: %s:%d\n",
1672                __FILE__, __LINE__);
1673       exit (1);
1674     }
1675
1676   sloc = newiTemp (slocBuffer);
1677
1678   /* set the type to the spilling symbol */
1679   sloc->type = copyLinkChain (sym->type);
1680   sloc->etype = getSpec (sloc->type);
1681   SPEC_SCLS (sloc->etype) = S_DATA;
1682   SPEC_EXTR (sloc->etype) = 0;
1683   SPEC_STAT (sloc->etype) = 0;
1684
1685   /* we don't allow it to be allocated`
1686      onto the external stack since : so we
1687      temporarily turn it off ; we also
1688      turn off memory model to prevent
1689      the spil from going to the external storage
1690      and turn off overlaying 
1691    */
1692
1693   useXstack = options.useXstack;
1694   model = options.model;
1695   noOverlay = options.noOverlay;
1696   options.noOverlay = 1;
1697   options.model = options.useXstack = 0;
1698
1699   allocLocal (sloc);
1700
1701   options.useXstack = useXstack;
1702   options.model = model;
1703   options.noOverlay = noOverlay;
1704   sloc->isref = 1;              /* to prevent compiler warning */
1705
1706   /* if it is on the stack then update the stack */
1707   if (IN_STACK (sloc->etype))
1708     {
1709       currFunc->stack += getSize (sloc->type);
1710       _G.stackExtend += getSize (sloc->type);
1711     }
1712   else
1713     _G.dataExtend += getSize (sloc->type);
1714
1715   /* add it to the _G.stackSpil set */
1716   addSetHead (&_G.stackSpil, sloc);
1717   sym->usl.spillLoc = sloc;
1718   sym->stackSpil = 1;
1719
1720   /* add it to the set of itempStack set 
1721      of the spill location */
1722   addSetHead (&sloc->usl.itmpStack, sym);
1723   return sym;
1724 }
1725
1726 /*-----------------------------------------------------------------*/
1727 /* isSpiltOnStack - returns true if the spil location is on stack  */
1728 /*-----------------------------------------------------------------*/
1729 static bool
1730 isSpiltOnStack (symbol * sym)
1731 {
1732   sym_link *etype;
1733
1734   debugLog ("%s\n", __FUNCTION__);
1735   if (!sym)
1736     return FALSE;
1737
1738   if (!sym->isspilt)
1739     return FALSE;
1740
1741 /*     if (sym->_G.stackSpil) */
1742 /*      return TRUE; */
1743
1744   if (!sym->usl.spillLoc)
1745     return FALSE;
1746
1747   etype = getSpec (sym->usl.spillLoc->type);
1748   if (IN_STACK (etype))
1749     return TRUE;
1750
1751   return FALSE;
1752 }
1753
1754 /*-----------------------------------------------------------------*/
1755 /* spillThis - spils a specific operand                            */
1756 /*-----------------------------------------------------------------*/
1757 static void
1758 spillThis (symbol * sym)
1759 {
1760   int i;
1761   debugLog ("%s : %s\n", __FUNCTION__, sym->rname);
1762
1763   /* if this is rematerializable or has a spillLocation
1764      we are okay, else we need to create a spillLocation
1765      for it */
1766   if (!(sym->remat || sym->usl.spillLoc))
1767     createStackSpil (sym);
1768
1769
1770   /* mark it has spilt & put it in the spilt set */
1771   sym->isspilt = 1;
1772   _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
1773
1774   bitVectUnSetBit (_G.regAssigned, sym->key);
1775
1776   for (i = 0; i < sym->nRegs; i++)
1777
1778     if (sym->regs[i])
1779       {
1780         freeReg (sym->regs[i]);
1781         sym->regs[i] = NULL;
1782       }
1783
1784   /* if spilt on stack then free up r0 & r1 
1785      if they could have been assigned to some
1786      LIVE ranges */
1787   if (!pic16_ptrRegReq && isSpiltOnStack (sym))
1788     {
1789       pic16_ptrRegReq++;
1790       spillLRWithPtrReg (sym);
1791     }
1792
1793   if (sym->usl.spillLoc && !sym->remat)
1794     sym->usl.spillLoc->allocreq = 1;
1795   return;
1796 }
1797
1798 /*-----------------------------------------------------------------*/
1799 /* selectSpil - select a iTemp to spil : rather a simple procedure */
1800 /*-----------------------------------------------------------------*/
1801 static symbol *
1802 selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
1803 {
1804   bitVect *lrcs = NULL;
1805   set *selectS;
1806   symbol *sym;
1807
1808   debugLog ("%s\n", __FUNCTION__);
1809   /* get the spillable live ranges */
1810   lrcs = computeSpillable (ic);
1811
1812   /* get all live ranges that are rematerizable */
1813   if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
1814     {
1815
1816       /* return the least used of these */
1817       return leastUsedLR (selectS);
1818     }
1819
1820   /* get live ranges with spillLocations in direct space */
1821   if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
1822     {
1823       sym = leastUsedLR (selectS);
1824       strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ?
1825                            sym->usl.spillLoc->rname :
1826                            sym->usl.spillLoc->name));
1827       sym->spildir = 1;
1828       /* mark it as allocation required */
1829       sym->usl.spillLoc->allocreq = 1;
1830       return sym;
1831     }
1832
1833   /* if the symbol is local to the block then */
1834   if (forSym->liveTo < ebp->lSeq)
1835     {
1836
1837       /* check if there are any live ranges allocated
1838          to registers that are not used in this block */
1839       if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
1840         {
1841           sym = leastUsedLR (selectS);
1842           /* if this is not rematerializable */
1843           if (!sym->remat)
1844             {
1845               _G.blockSpil++;
1846               sym->blockSpil = 1;
1847             }
1848           return sym;
1849         }
1850
1851       /* check if there are any live ranges that not
1852          used in the remainder of the block */
1853       if (!_G.blockSpil &&
1854           !isiCodeInFunctionCall (ic) &&       
1855           (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
1856         {
1857           sym = leastUsedLR (selectS);
1858           if (!sym->remat)
1859             {
1860               sym->remainSpil = 1;
1861               _G.blockSpil++;
1862             }
1863           return sym;
1864         }
1865     }
1866
1867   /* find live ranges with spillocation && not used as pointers */
1868   if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
1869     {
1870
1871       sym = leastUsedLR (selectS);
1872       /* mark this as allocation required */
1873       sym->usl.spillLoc->allocreq = 1;
1874       return sym;
1875     }
1876
1877   /* find live ranges with spillocation */
1878   if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
1879     {
1880
1881       sym = leastUsedLR (selectS);
1882       sym->usl.spillLoc->allocreq = 1;
1883       return sym;
1884     }
1885
1886   /* couldn't find then we need to create a spil
1887      location on the stack , for which one? the least
1888      used ofcourse */
1889   if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
1890     {
1891
1892       /* return a created spil location */
1893       sym = createStackSpil (leastUsedLR (selectS));
1894       sym->usl.spillLoc->allocreq = 1;
1895       return sym;
1896     }
1897
1898   /* this is an extreme situation we will spill
1899      this one : happens very rarely but it does happen */
1900   spillThis (forSym);
1901   return forSym;
1902
1903 }
1904
1905 /*-----------------------------------------------------------------*/
1906 /* spilSomething - spil some variable & mark registers as free     */
1907 /*-----------------------------------------------------------------*/
1908 static bool
1909 spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
1910 {
1911   symbol *ssym;
1912   int i;
1913
1914   debugLog ("%s\n", __FUNCTION__);
1915   /* get something we can spil */
1916   ssym = selectSpil (ic, ebp, forSym);
1917
1918   /* mark it as spilt */
1919   ssym->isspilt = 1;
1920   _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
1921
1922   /* mark it as not register assigned &
1923      take it away from the set */
1924   bitVectUnSetBit (_G.regAssigned, ssym->key);
1925
1926   /* mark the registers as free */
1927   for (i = 0; i < ssym->nRegs; i++)
1928     if (ssym->regs[i])
1929       freeReg (ssym->regs[i]);
1930
1931   /* if spilt on stack then free up r0 & r1 
1932      if they could have been assigned to as gprs */
1933   if (!pic16_ptrRegReq && isSpiltOnStack (ssym))
1934     {
1935       pic16_ptrRegReq++;
1936       spillLRWithPtrReg (ssym);
1937     }
1938
1939   /* if this was a block level spil then insert push & pop 
1940      at the start & end of block respectively */
1941   if (ssym->blockSpil)
1942     {
1943       iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
1944       /* add push to the start of the block */
1945       addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
1946                                     ebp->sch->next : ebp->sch));
1947       nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
1948       /* add pop to the end of the block */
1949       addiCodeToeBBlock (ebp, nic, NULL);
1950     }
1951
1952   /* if spilt because not used in the remainder of the
1953      block then add a push before this instruction and
1954      a pop at the end of the block */
1955   if (ssym->remainSpil)
1956     {
1957
1958       iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
1959       /* add push just before this instruction */
1960       addiCodeToeBBlock (ebp, nic, ic);
1961
1962       nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
1963       /* add pop to the end of the block */
1964       addiCodeToeBBlock (ebp, nic, NULL);
1965     }
1966
1967   if (ssym == forSym)
1968     return FALSE;
1969   else
1970     return TRUE;
1971 }
1972
1973 /*-----------------------------------------------------------------*/
1974 /* getRegPtr - will try for PTR if not a GPR type if not spil      */
1975 /*-----------------------------------------------------------------*/
1976 static regs *
1977 getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
1978 {
1979   regs *reg;
1980   int j;
1981
1982   debugLog ("%s\n", __FUNCTION__);
1983 tryAgain:
1984   /* try for a ptr type */
1985   if ((reg = allocReg (REG_PTR)))
1986     return reg;
1987
1988   /* try for gpr type */
1989   if ((reg = allocReg (REG_GPR)))
1990     return reg;
1991
1992   /* we have to spil */
1993   if (!spilSomething (ic, ebp, sym))
1994     return NULL;
1995
1996   /* make sure partially assigned registers aren't reused */
1997   for (j=0; j<=sym->nRegs; j++)
1998     if (sym->regs[j])
1999       sym->regs[j]->isFree = 0;
2000       
2001   /* this looks like an infinite loop but 
2002      in really selectSpil will abort  */
2003   goto tryAgain;
2004 }
2005
2006 /*-----------------------------------------------------------------*/
2007 /* getRegGpr - will try for GPR if not spil                        */
2008 /*-----------------------------------------------------------------*/
2009 static regs *
2010 getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
2011 {
2012   regs *reg;
2013   int j;
2014
2015   debugLog ("%s\n", __FUNCTION__);
2016 tryAgain:
2017   /* try for gpr type */
2018   if ((reg = allocReg (REG_GPR)))
2019     return reg;
2020
2021   if (!pic16_ptrRegReq)
2022     if ((reg = allocReg (REG_PTR)))
2023       return reg;
2024
2025   /* we have to spil */
2026   if (!spilSomething (ic, ebp, sym))
2027     return NULL;
2028
2029   /* make sure partially assigned registers aren't reused */
2030   for (j=0; j<=sym->nRegs; j++)
2031     if (sym->regs[j])
2032       sym->regs[j]->isFree = 0;
2033       
2034   /* this looks like an infinite loop but 
2035      in really selectSpil will abort  */
2036   goto tryAgain;
2037 }
2038
2039 /*-----------------------------------------------------------------*/
2040 /* symHasReg - symbol has a given register                         */
2041 /*-----------------------------------------------------------------*/
2042 static bool
2043 symHasReg (symbol * sym, regs * reg)
2044 {
2045   int i;
2046
2047   debugLog ("%s\n", __FUNCTION__);
2048   for (i = 0; i < sym->nRegs; i++)
2049     if (sym->regs[i] == reg)
2050       return TRUE;
2051
2052   return FALSE;
2053 }
2054
2055 /*-----------------------------------------------------------------*/
2056 /* deassignLRs - check the live to and if they have registers & are */
2057 /*               not spilt then free up the registers              */
2058 /*-----------------------------------------------------------------*/
2059 static void
2060 deassignLRs (iCode * ic, eBBlock * ebp)
2061 {
2062   symbol *sym;
2063   int k;
2064   symbol *result;
2065
2066   debugLog ("%s\n", __FUNCTION__);
2067   for (sym = hTabFirstItem (liveRanges, &k); sym;
2068        sym = hTabNextItem (liveRanges, &k))
2069     {
2070
2071       symbol *psym = NULL;
2072       /* if it does not end here */
2073       if (sym->liveTo > ic->seq)
2074         continue;
2075
2076       /* if it was spilt on stack then we can 
2077          mark the stack spil location as free */
2078       if (sym->isspilt)
2079         {
2080           if (sym->stackSpil)
2081             {
2082               sym->usl.spillLoc->isFree = 1;
2083               sym->stackSpil = 0;
2084             }
2085           continue;
2086         }
2087
2088       if (!bitVectBitValue (_G.regAssigned, sym->key))
2089         continue;
2090
2091       /* special case for shifting: there is a case where shift count
2092        * can be allocated in the same register as the result, so do not
2093        * free right registers if same as result registers, cause genShiftLeft
2094        * will fail -- VR */
2095        if(ic->op == LEFT_OP)
2096          continue;
2097
2098       /* special case check if this is an IFX &
2099          the privious one was a pop and the 
2100          previous one was not spilt then keep track
2101          of the symbol */
2102       if (ic->op == IFX && ic->prev &&
2103           ic->prev->op == IPOP &&
2104           !ic->prev->parmPush &&
2105           !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
2106         psym = OP_SYMBOL (IC_LEFT (ic->prev));
2107
2108       if (sym->nRegs)
2109         {
2110           int i = 0;
2111
2112           bitVectUnSetBit (_G.regAssigned, sym->key);
2113
2114           /* if the result of this one needs registers
2115              and does not have it then assign it right
2116              away */
2117           if (IC_RESULT (ic) &&
2118               !(SKIP_IC2 (ic) ||        /* not a special icode */
2119                 ic->op == JUMPTABLE ||
2120                 ic->op == IFX ||
2121                 ic->op == IPUSH ||
2122                 ic->op == IPOP ||
2123                 ic->op == RETURN ||
2124                 POINTER_SET (ic)) &&
2125               (result = OP_SYMBOL (IC_RESULT (ic))) &&  /* has a result */
2126               result->liveTo > ic->seq &&       /* and will live beyond this */
2127               result->liveTo <= ebp->lSeq &&    /* does not go beyond this block */
2128               result->liveFrom == ic->seq &&    /* does not start before here */
2129               result->regType == sym->regType &&        /* same register types */
2130               result->nRegs &&  /* which needs registers */
2131               !result->isspilt &&       /* and does not already have them */
2132               !result->remat &&
2133               !bitVectBitValue (_G.regAssigned, result->key) &&
2134           /* the number of free regs + number of regs in this LR
2135              can accomodate the what result Needs */
2136               ((nfreeRegsType (result->regType) +
2137                 sym->nRegs) >= result->nRegs)
2138             )
2139             {
2140               
2141
2142 //            for (i = 0; i < max (sym->nRegs, result->nRegs); i++)
2143               /* the above does not free the unsued registers in sym,
2144                * leaving them marked as used, and increasing register usage
2145                * until the end of the function - VR 23/11/05 */
2146
2147               for (i = 0; i < result->nRegs; i++)
2148                 if (i < sym->nRegs)
2149                   result->regs[i] = sym->regs[i];
2150                 else
2151                   result->regs[i] = getRegGpr (ic, ebp, result);
2152
2153               _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
2154             }
2155
2156           /* free the remaining */
2157           for (; i < sym->nRegs; i++)
2158             {
2159               if (psym)
2160                 {
2161                   if (!symHasReg (psym, sym->regs[i]))
2162                     freeReg (sym->regs[i]);
2163                 }
2164               else
2165                 freeReg (sym->regs[i]);
2166             }
2167         }
2168     }
2169 }
2170
2171
2172 /*-----------------------------------------------------------------*/
2173 /* reassignLR - reassign this to registers                         */
2174 /*-----------------------------------------------------------------*/
2175 static void
2176 reassignLR (operand * op)
2177 {
2178   symbol *sym = OP_SYMBOL (op);
2179   int i;
2180
2181   debugLog ("%s\n", __FUNCTION__);
2182   /* not spilt any more */
2183   sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
2184   bitVectUnSetBit (_G.spiltSet, sym->key);
2185
2186   _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
2187
2188   _G.blockSpil--;
2189
2190   for (i = 0; i < sym->nRegs; i++)
2191     sym->regs[i]->isFree = 0;
2192 }
2193
2194 /*-----------------------------------------------------------------*/
2195 /* willCauseSpill - determines if allocating will cause a spill    */
2196 /*-----------------------------------------------------------------*/
2197 static int
2198 willCauseSpill (int nr, int rt)
2199 {
2200   debugLog ("%s\n", __FUNCTION__);
2201   /* first check if there are any avlb registers
2202      of te type required */
2203   if (rt == REG_PTR)
2204     {
2205       /* special case for pointer type 
2206          if pointer type not avlb then 
2207          check for type gpr */
2208       if (nFreeRegs (rt) >= nr)
2209         return 0;
2210       if (nFreeRegs (REG_GPR) >= nr)
2211         return 0;
2212     }
2213   else
2214     {
2215       if (pic16_ptrRegReq)
2216         {
2217           if (nFreeRegs (rt) >= nr)
2218             return 0;
2219         }
2220       else
2221         {
2222           if (nFreeRegs (REG_PTR) +
2223               nFreeRegs (REG_GPR) >= nr)
2224             return 0;
2225         }
2226     }
2227
2228   debugLog (" ... yep it will (cause a spill)\n");
2229   /* it will cause a spil */
2230   return 1;
2231 }
2232
2233 /*-----------------------------------------------------------------*/
2234 /* positionRegs - the allocator can allocate same registers to res- */
2235 /* ult and operand, if this happens make sure they are in the same */
2236 /* position as the operand otherwise chaos results                 */
2237 /*-----------------------------------------------------------------*/
2238 static void
2239 positionRegs (symbol * result, symbol * opsym, int lineno)
2240 {
2241   int count = min (result->nRegs, opsym->nRegs);
2242   int i, j = 0, shared = 0;
2243
2244   debugLog ("%s\n", __FUNCTION__);
2245   /* if the result has been spilt then cannot share */
2246   if (opsym->isspilt)
2247     return;
2248 again:
2249   shared = 0;
2250   /* first make sure that they actually share */
2251   for (i = 0; i < count; i++)
2252     {
2253       for (j = 0; j < count; j++)
2254         {
2255           if (result->regs[i] == opsym->regs[j] && i != j)
2256             {
2257               shared = 1;
2258               goto xchgPositions;
2259             }
2260         }
2261     }
2262 xchgPositions:
2263   if (shared)
2264     {
2265       regs *tmp = result->regs[i];
2266       result->regs[i] = result->regs[j];
2267       result->regs[j] = tmp;
2268       goto again;
2269     }
2270 }
2271
2272 /*------------------------------------------------------------------*/
2273 /* verifyRegsAssigned - make sure an iTemp is properly initialized; */
2274 /* it should either have registers or have beed spilled. Otherwise, */
2275 /* there was an uninitialized variable, so just spill this to get   */
2276 /* the operand in a valid state.                                    */
2277 /*------------------------------------------------------------------*/
2278 static void
2279 verifyRegsAssigned (operand *op, iCode * ic)
2280 {
2281   symbol * sym;
2282   
2283   if (!op) return;
2284   if (!IS_ITEMP (op)) return;
2285   
2286   sym = OP_SYMBOL (op);
2287   if (sym->isspilt) return;
2288   if (!sym->nRegs) return;
2289   if (sym->regs[0]) return;
2290   
2291   werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT, 
2292             sym->prereqv ? sym->prereqv->name : sym->name);
2293   spillThis (sym);
2294 }
2295
2296
2297 /*-----------------------------------------------------------------*/
2298 /* serialRegAssign - serially allocate registers to the variables  */
2299 /*-----------------------------------------------------------------*/
2300 static void
2301 serialRegAssign (eBBlock ** ebbs, int count)
2302 {
2303   int i;
2304   iCode *ic;
2305   
2306   debugLog ("%s\n", __FUNCTION__);
2307   /* for all blocks */
2308   for (i = 0; i < count; i++)
2309     {
2310       if (ebbs[i]->noPath &&
2311           (ebbs[i]->entryLabel != entryLabel &&
2312            ebbs[i]->entryLabel != returnLabel))
2313         continue;
2314
2315       /* of all instructions do */
2316       for (ic = ebbs[i]->sch; ic; ic = ic->next)
2317         {
2318
2319           debugLog ("  op: %s\n", pic16_decodeOp (ic->op));
2320
2321                 if(IC_RESULT(ic) && !IS_ITEMP( IC_RESULT(ic)))
2322                         pic16_allocDirReg(IC_RESULT(ic));
2323
2324                 if(IC_LEFT(ic) && !IS_ITEMP( IC_LEFT(ic)))
2325                         pic16_allocDirReg(IC_LEFT(ic));
2326
2327                 if(IC_RIGHT(ic) && !IS_ITEMP( IC_RIGHT(ic)))
2328                         pic16_allocDirReg(IC_RIGHT(ic));
2329
2330           /* if this is an ipop that means some live
2331              range will have to be assigned again */
2332           if (ic->op == IPOP)
2333             reassignLR (IC_LEFT (ic));
2334
2335           /* if result is present && is a true symbol */
2336           if (IC_RESULT (ic) && ic->op != IFX &&
2337               IS_TRUE_SYMOP (IC_RESULT (ic)))
2338             OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
2339
2340           /* take away registers from live
2341              ranges that end at this instruction */
2342           deassignLRs (ic, ebbs[i]);
2343
2344           /* some don't need registers */
2345           if (SKIP_IC2 (ic) ||
2346               ic->op == JUMPTABLE ||
2347               ic->op == IFX ||
2348               ic->op == IPUSH ||
2349               ic->op == IPOP ||
2350               (IC_RESULT (ic) && POINTER_SET (ic)))
2351             continue;
2352
2353           /* now we need to allocate registers
2354              only for the result */
2355           if (IC_RESULT (ic))
2356             {
2357               symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2358               bitVect *spillable;
2359               int willCS;
2360               int j;
2361               int ptrRegSet = 0;
2362
2363               /* Make sure any spill location is definately allocated */
2364               if (sym->isspilt && !sym->remat && sym->usl.spillLoc &&
2365                   !sym->usl.spillLoc->allocreq)
2366                 {
2367                   sym->usl.spillLoc->allocreq++;
2368                 }
2369
2370               /* if it does not need or is spilt 
2371                  or is already assigned to registers
2372                  or will not live beyond this instructions */
2373               if (!sym->nRegs ||
2374                   sym->isspilt ||
2375                   bitVectBitValue (_G.regAssigned, sym->key) ||
2376                   sym->liveTo <= ic->seq)
2377                 continue;
2378
2379               /* if some liverange has been spilt at the block level
2380                  and this one live beyond this block then spil this
2381                  to be safe */
2382               if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
2383                 {
2384                   spillThis (sym);
2385                   continue;
2386                 }
2387               /* if trying to allocate this will cause
2388                  a spill and there is nothing to spill 
2389                  or this one is rematerializable then
2390                  spill this one */
2391               willCS = willCauseSpill (sym->nRegs, sym->regType);
2392
2393               /* explicit turn off register spilling */
2394               willCS = 0;
2395               
2396               spillable = computeSpillable (ic);
2397               if (sym->remat ||
2398                   (willCS && bitVectIsZero (spillable)))
2399                 {
2400
2401                   spillThis (sym);
2402                   continue;
2403
2404                 }
2405
2406               /* If the live range preceeds the point of definition 
2407                  then ideally we must take into account registers that 
2408                  have been allocated after sym->liveFrom but freed
2409                  before ic->seq. This is complicated, so spill this
2410                  symbol instead and let fillGaps handle the allocation. */
2411 #if 0
2412               if (sym->liveFrom < ic->seq)
2413                 {
2414                     spillThis (sym);
2415                     continue;                 
2416                 }
2417 #endif
2418               /* if it has a spillocation & is used less than
2419                  all other live ranges then spill this */
2420                 if (willCS) {
2421                     if (sym->usl.spillLoc) {
2422                         symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
2423                                                                          allLRs, ebbs[i], ic));
2424                         if (leastUsed && leastUsed->used > sym->used) {
2425                             spillThis (sym);
2426                             continue;
2427                         }
2428                     } else {
2429                         /* if none of the liveRanges have a spillLocation then better
2430                            to spill this one than anything else already assigned to registers */
2431                         if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
2432                             /* if this is local to this block then we might find a block spil */
2433                             if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
2434                                 spillThis (sym);
2435                                 continue;
2436                             }
2437                         }
2438                     }
2439                 }
2440
2441               if (ic->op == RECEIVE)
2442                 debugLog ("When I get clever, I'll optimize the receive logic\n");
2443
2444               if(POINTER_GET(ic) && IS_BITFIELD(getSpec(operandType(IC_RESULT(ic))))
2445                 && (SPEC_BLEN(getSpec(operandType(IC_RESULT(ic))))==1)
2446                 && (ic->next->op == IFX)
2447                 && (OP_LIVETO(IC_RESULT(ic)) == ic->next->seq)) {
2448
2449                 /* skip register allocation since none will be used */
2450                 for(j=0;j<sym->nRegs;j++)
2451                   sym->regs[j] = newReg(REG_TMP, PO_GPR_TEMP, 0, "bad", 1, 0, NULL);
2452 //                OP_SYMBOL(IC_RESULT(ic))->nRegs = 0;
2453                 
2454                 continue;
2455               }
2456
2457               /* if we need ptr regs for the right side
2458                  then mark it */
2459               if (POINTER_GET (ic) && IS_SYMOP( IC_LEFT(ic) ) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
2460                   <= (unsigned) PTRSIZE)
2461                 {
2462                   pic16_ptrRegReq++;
2463                   ptrRegSet = 1;
2464                 }
2465               /* else we assign registers to it */
2466               _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
2467
2468               if(debugF) 
2469                 bitVectDebugOn(_G.regAssigned, debugF);
2470
2471               for (j = 0; j < sym->nRegs; j++)
2472                 {
2473                   if (sym->regType == REG_PTR)
2474                     sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
2475                   else
2476                     sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
2477
2478                   /* if the allocation falied which means
2479                      this was spilt then break */
2480                   if (!sym->regs[j])
2481                     break;
2482                 }
2483               debugLog ("  %d - \n", __LINE__);
2484
2485               /* if it shares registers with operands make sure
2486                  that they are in the same position */
2487               if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
2488                   OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
2489                 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2490                               OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
2491               /* do the same for the right operand */
2492               if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
2493                   OP_SYMBOL (IC_RIGHT (ic))->nRegs && ic->op != '=')
2494                 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2495                               OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
2496
2497               debugLog ("  %d - \n", __LINE__);
2498               if (ptrRegSet)
2499                 {
2500                   debugLog ("  %d - \n", __LINE__);
2501                   pic16_ptrRegReq--;
2502                   ptrRegSet = 0;
2503                 }
2504
2505             }
2506         }
2507     }
2508
2509     /* Check for and fix any problems with uninitialized operands */
2510     for (i = 0; i < count; i++)
2511       {
2512         iCode *ic;
2513
2514         if (ebbs[i]->noPath &&
2515             (ebbs[i]->entryLabel != entryLabel &&
2516              ebbs[i]->entryLabel != returnLabel))
2517             continue;
2518
2519         for (ic = ebbs[i]->sch; ic; ic = ic->next)
2520           {
2521             if (SKIP_IC2 (ic))
2522               continue;
2523
2524             if (ic->op == IFX)
2525               {
2526                 verifyRegsAssigned (IC_COND (ic), ic);
2527                 continue;
2528               }
2529
2530             if (ic->op == JUMPTABLE)
2531               {
2532                 verifyRegsAssigned (IC_JTCOND (ic), ic);
2533                 continue;
2534               }
2535
2536             verifyRegsAssigned (IC_RESULT (ic), ic);
2537             verifyRegsAssigned (IC_LEFT (ic), ic);
2538             verifyRegsAssigned (IC_RIGHT (ic), ic);
2539           }
2540       }    
2541     
2542 }
2543
2544 /*-----------------------------------------------------------------*/
2545 /* rUmaskForOp :- returns register mask for an operand             */
2546 /*-----------------------------------------------------------------*/
2547 static bitVect *
2548 rUmaskForOp (operand * op)
2549 {
2550   bitVect *rumask;
2551   symbol *sym;
2552   int j;
2553
2554   debugLog ("%s\n", __FUNCTION__);
2555   /* only temporaries are assigned registers */
2556   if (!IS_ITEMP (op))
2557     return NULL;
2558
2559   sym = OP_SYMBOL (op);
2560
2561   /* if spilt or no registers assigned to it
2562      then nothing */
2563   if (sym->isspilt || !sym->nRegs)
2564     return NULL;
2565
2566   rumask = newBitVect (pic16_nRegs);
2567
2568   for (j = 0; j < sym->nRegs; j++)
2569     {
2570       rumask = bitVectSetBit (rumask,
2571                               sym->regs[j]->rIdx);
2572     }
2573
2574   return rumask;
2575 }
2576
2577 /*-----------------------------------------------------------------*/
2578 /* regsUsedIniCode :- returns bit vector of registers used in iCode */
2579 /*-----------------------------------------------------------------*/
2580 static bitVect *
2581 regsUsedIniCode (iCode * ic)
2582 {
2583   bitVect *rmask = newBitVect (pic16_nRegs);
2584
2585   debugLog ("%s\n", __FUNCTION__);
2586   /* do the special cases first */
2587   if (ic->op == IFX)
2588     {
2589       rmask = bitVectUnion (rmask,
2590                             rUmaskForOp (IC_COND (ic)));
2591       goto ret;
2592     }
2593
2594   /* for the jumptable */
2595   if (ic->op == JUMPTABLE)
2596     {
2597       rmask = bitVectUnion (rmask,
2598                             rUmaskForOp (IC_JTCOND (ic)));
2599
2600       goto ret;
2601     }
2602
2603   /* of all other cases */
2604   if (IC_LEFT (ic))
2605     rmask = bitVectUnion (rmask,
2606                           rUmaskForOp (IC_LEFT (ic)));
2607
2608
2609   if (IC_RIGHT (ic))
2610     rmask = bitVectUnion (rmask,
2611                           rUmaskForOp (IC_RIGHT (ic)));
2612
2613   if (IC_RESULT (ic))
2614     rmask = bitVectUnion (rmask,
2615                           rUmaskForOp (IC_RESULT (ic)));
2616
2617 ret:
2618   return rmask;
2619 }
2620
2621 /*-----------------------------------------------------------------*/
2622 /* createRegMask - for each instruction will determine the regsUsed */
2623 /*-----------------------------------------------------------------*/
2624 static void
2625 createRegMask (eBBlock ** ebbs, int count)
2626 {
2627   int i;
2628
2629   debugLog ("%s\n", __FUNCTION__);
2630   /* for all blocks */
2631   for (i = 0; i < count; i++)
2632     {
2633       iCode *ic;
2634
2635       if (ebbs[i]->noPath &&
2636           (ebbs[i]->entryLabel != entryLabel &&
2637            ebbs[i]->entryLabel != returnLabel))
2638         continue;
2639
2640       /* for all instructions */
2641       for (ic = ebbs[i]->sch; ic; ic = ic->next)
2642         {
2643
2644           int j;
2645
2646           if (SKIP_IC2 (ic) || !ic->rlive)
2647             continue;
2648
2649           /* first mark the registers used in this
2650              instruction */
2651           ic->rUsed = regsUsedIniCode (ic);
2652           _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
2653
2654           /* now create the register mask for those 
2655              registers that are in use : this is a
2656              super set of ic->rUsed */
2657           ic->rMask = newBitVect (pic16_nRegs + 1);
2658
2659           /* for all live Ranges alive at this point */
2660           for (j = 1; j < ic->rlive->size; j++)
2661             {
2662               symbol *sym;
2663               int k;
2664
2665               /* if not alive then continue */
2666               if (!bitVectBitValue (ic->rlive, j))
2667                 continue;
2668
2669               /* find the live range we are interested in */
2670               if (!(sym = hTabItemWithKey (liveRanges, j)))
2671                 {
2672                   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2673                           "createRegMask cannot find live range");
2674                   exit (0);
2675                 }
2676
2677               /* if no register assigned to it */
2678               if (!sym->nRegs || sym->isspilt)
2679                 continue;
2680
2681               /* for all the registers allocated to it */
2682               for (k = 0; k < sym->nRegs; k++)
2683                 if (sym->regs[k])
2684                   ic->rMask =
2685                     bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
2686             }
2687         }
2688     }
2689 }
2690
2691 /*-----------------------------------------------------------------*/
2692 /* rematStr - returns the rematerialized string for a remat var    */
2693 /*-----------------------------------------------------------------*/
2694 static symbol *
2695 rematStr (symbol * sym)
2696 {
2697   char *s = buffer;
2698   iCode *ic = sym->rematiCode;
2699   symbol *psym = NULL;
2700
2701   debugLog ("%s\n", __FUNCTION__);
2702
2703   //printf ("%s\n", s);
2704
2705   /* if plus or minus print the right hand side */
2706
2707   if (ic->op == '+' || ic->op == '-') {
2708         
2709     iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2710
2711     sprintf (s, "(%s %c 0x%04x)",
2712              OP_SYMBOL (IC_LEFT (ric))->rname,
2713              ic->op,
2714              (int) operandLitValue (IC_RIGHT (ic)));
2715
2716
2717     //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
2718
2719     psym = newSymbol (OP_SYMBOL (IC_LEFT (ric))->rname, 1);
2720     psym->offset = (int) operandLitValue (IC_RIGHT (ic));
2721
2722     return psym;
2723   }
2724
2725   sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
2726   psym = newSymbol (OP_SYMBOL (IC_LEFT (ic))->rname, 1);
2727
2728   //printf ("ralloc.c:%d %s\n", __LINE__,buffer);
2729   return psym;
2730 }
2731
2732 #if 0
2733 /*-----------------------------------------------------------------*/
2734 /* rematStr - returns the rematerialized string for a remat var    */
2735 /*-----------------------------------------------------------------*/
2736 static char *
2737 rematStr (symbol * sym)
2738 {
2739   char *s = buffer;
2740   iCode *ic = sym->rematiCode;
2741
2742   debugLog ("%s\n", __FUNCTION__);
2743   while (1)
2744     {
2745
2746       printf ("%s\n", s);
2747       /* if plus or minus print the right hand side */
2748 /*
2749    if (ic->op == '+' || ic->op == '-') {
2750    sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
2751    ic->op );
2752    s += strlen(s);
2753    ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2754    continue ;
2755    }
2756  */
2757       if (ic->op == '+' || ic->op == '-')
2758         {
2759           iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2760           sprintf (s, "(%s %c 0x%04x)",
2761                    OP_SYMBOL (IC_LEFT (ric))->rname,
2762                    ic->op,
2763                    (int) operandLitValue (IC_RIGHT (ic)));
2764
2765           //s += strlen(s);
2766           //ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2767           //continue ;
2768           //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
2769           return buffer;
2770         }
2771
2772       /* we reached the end */
2773       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
2774       break;
2775     }
2776
2777   printf ("%s\n", buffer);
2778   return buffer;
2779 }
2780 #endif
2781
2782 /*-----------------------------------------------------------------*/
2783 /* regTypeNum - computes the type & number of registers required   */
2784 /*-----------------------------------------------------------------*/
2785 static void
2786 regTypeNum ()
2787 {
2788   symbol *sym;
2789   int k;
2790   iCode *ic;
2791
2792   debugLog ("%s\n", __FUNCTION__);
2793   /* for each live range do */
2794   for (sym = hTabFirstItem (liveRanges, &k); sym;
2795        sym = hTabNextItem (liveRanges, &k)) {
2796
2797     debugLog ("  %d - %s\n", __LINE__, sym->rname);
2798     //fprintf(stderr,"  %d - %s\n", __LINE__, sym->rname);
2799
2800     /* if used zero times then no registers needed */
2801     if ((sym->liveTo - sym->liveFrom) == 0)
2802       continue;
2803
2804
2805     /* if the live range is a temporary */
2806     if (sym->isitmp) {
2807
2808       debugLog ("  %d - itemp register\n", __LINE__);
2809
2810       /* if the type is marked as a conditional */
2811       if (sym->regType == REG_CND)
2812         continue;
2813
2814       /* if used in return only then we don't 
2815          need registers */
2816       if (sym->ruonly || sym->accuse) {
2817         if (IS_AGGREGATE (sym->type) || sym->isptr)
2818           sym->type = aggrToPtr (sym->type, FALSE);
2819         debugLog ("  %d - no reg needed - used as a return\n", __LINE__);
2820         continue;
2821       }
2822
2823       /* if the symbol has only one definition &
2824          that definition is a get_pointer and the
2825          pointer we are getting is rematerializable and
2826          in "data" space */
2827
2828       if (bitVectnBitsOn (sym->defs) == 1 &&
2829           (ic = hTabItemWithKey (iCodehTab,
2830                                  bitVectFirstBit (sym->defs))) &&
2831           POINTER_GET (ic) &&
2832           !IS_BITVAR (sym->etype) &&
2833           (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) {
2834
2835 //        continue;       /* FIXME -- VR */
2836         if (ptrPseudoSymSafe (sym, ic)) {
2837           
2838           symbol *psym;
2839           
2840           debugLog ("  %d - \n", __LINE__);
2841               
2842           /* create a psuedo symbol & force a spil */
2843           //X symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
2844           psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
2845           psym->type = sym->type;
2846           psym->etype = sym->etype;
2847           psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (ic)));
2848           strcpy (psym->rname, psym->name);
2849           sym->isspilt = 1;
2850           sym->usl.spillLoc = psym;
2851           continue;
2852         }
2853
2854         /* if in data space or idata space then try to
2855            allocate pointer register */
2856
2857       }
2858
2859       /* if not then we require registers */
2860       sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
2861                     getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
2862                     getSize (sym->type));
2863
2864
2865 #if 0
2866     if(IS_PTR_CONST (sym->type)) {
2867 #else
2868     if(IS_CODEPTR (sym->type)) {
2869 #endif
2870       // what IS this ???? (HJD)
2871       debugLog ("  %d const pointer type requires %d registers, changing to 3\n",__LINE__,sym->nRegs); // patch 14
2872       sym->nRegs = 3; // patch 14
2873     }
2874
2875       if (sym->nRegs > 4) {
2876         fprintf (stderr, "allocated more than 4 or 0 registers for type ");
2877         printTypeChain (sym->type, stderr);
2878         fprintf (stderr, "\n");
2879       }
2880
2881       /* determine the type of register required */
2882       if (sym->nRegs == 1 &&
2883           IS_PTR (sym->type) &&
2884           sym->uptr)
2885         sym->regType = REG_PTR;
2886       else
2887         sym->regType = REG_GPR;
2888
2889
2890       debugLog ("  reg name %s,  reg type %s\n", sym->rname, debugLogRegType (sym->regType));
2891
2892     }
2893     else
2894       /* for the first run we don't provide */
2895       /* registers for true symbols we will */
2896       /* see how things go                  */
2897       sym->nRegs = 0;
2898       
2899   }
2900
2901 }
2902 static DEFSETFUNC (markRegFree)
2903 {
2904   ((regs *)item)->isFree = 1;
2905 //  ((regs *)item)->wasUsed = 0;
2906
2907   return 0;
2908 }
2909
2910 DEFSETFUNC (pic16_deallocReg)
2911 {
2912   fprintf(stderr,"deallocting register %s\n",((regs *)item)->name);
2913   ((regs *)item)->isFree = 1;
2914   ((regs *)item)->wasUsed = 0;
2915
2916   return 0;
2917 }
2918 /*-----------------------------------------------------------------*/
2919 /* freeAllRegs - mark all registers as free                        */
2920 /*-----------------------------------------------------------------*/
2921 void
2922 pic16_freeAllRegs ()
2923 {
2924   debugLog ("%s\n", __FUNCTION__);
2925
2926   applyToSet(pic16_dynAllocRegs,markRegFree);
2927   applyToSet(pic16_dynStackRegs,markRegFree);
2928 }
2929
2930 /*-----------------------------------------------------------------*/
2931 /*-----------------------------------------------------------------*/
2932 void
2933 pic16_deallocateAllRegs ()
2934 {
2935   debugLog ("%s\n", __FUNCTION__);
2936
2937   applyToSet(pic16_dynAllocRegs,pic16_deallocReg);
2938 }
2939
2940
2941 /*-----------------------------------------------------------------*/
2942 /* deallocStackSpil - this will set the stack pointer back         */
2943 /*-----------------------------------------------------------------*/
2944 static
2945 DEFSETFUNC (deallocStackSpil)
2946 {
2947   symbol *sym = item;
2948
2949   debugLog ("%s\n", __FUNCTION__);
2950   deallocLocal (sym);
2951   return 0;
2952 }
2953
2954 /*-----------------------------------------------------------------*/
2955 /* farSpacePackable - returns the packable icode for far variables */
2956 /*-----------------------------------------------------------------*/
2957 static iCode *
2958 farSpacePackable (iCode * ic)
2959 {
2960   iCode *dic;
2961
2962   debugLog ("%s\n", __FUNCTION__);
2963   /* go thru till we find a definition for the
2964      symbol on the right */
2965   for (dic = ic->prev; dic; dic = dic->prev)
2966     {
2967
2968       /* if the definition is a call then no */
2969       if ((dic->op == CALL || dic->op == PCALL) &&
2970           IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2971         {
2972           return NULL;
2973         }
2974
2975       /* if shift by unknown amount then not */
2976       if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
2977           IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2978         return NULL;
2979
2980       /* if pointer get and size > 1 */
2981       if (POINTER_GET (dic) &&
2982           getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
2983         return NULL;
2984
2985       if (POINTER_SET (dic) &&
2986           getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
2987         return NULL;
2988
2989       /* if any three is a true symbol in far space */
2990       if (IC_RESULT (dic) &&
2991           IS_TRUE_SYMOP (IC_RESULT (dic)) &&
2992           isOperandInFarSpace (IC_RESULT (dic)))
2993         return NULL;
2994
2995       if (IC_RIGHT (dic) &&
2996           IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
2997           isOperandInFarSpace (IC_RIGHT (dic)) &&
2998           !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
2999         return NULL;
3000
3001       if (IC_LEFT (dic) &&
3002           IS_TRUE_SYMOP (IC_LEFT (dic)) &&
3003           isOperandInFarSpace (IC_LEFT (dic)) &&
3004           !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
3005         return NULL;
3006
3007       if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
3008         {
3009           if ((dic->op == LEFT_OP ||
3010                dic->op == RIGHT_OP ||
3011                dic->op == '-') &&
3012               IS_OP_LITERAL (IC_RIGHT (dic)))
3013             return NULL;
3014           else
3015             return dic;
3016         }
3017     }
3018
3019   return NULL;
3020 }
3021
3022 #if 0
3023 static int packRegsForPointerGet(iCode *ic, eBBlock *ebp)
3024 {
3025   iCode *dic, *sic;
3026
3027     debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
3028     debugLog ("ic->op = %s\n", pic16_decodeOp( ic->op ) );
3029     debugAopGet ("  result:", IC_RESULT (ic));
3030     debugAopGet ("  left:", IC_LEFT (ic));
3031     debugAopGet ("  right:", IC_RIGHT (ic));
3032
3033     dic = ic->prev;
3034     if((dic->op == '=')
3035       && (
3036 }
3037 #endif
3038
3039
3040 void replaceOperandWithOperand(eBBlock *ebp, iCode *ic, operand *src, iCode *dic, operand *dst);
3041
3042 /*-----------------------------------------------------------------*/
3043 /* packRegsForAssign - register reduction for assignment           */
3044 /*-----------------------------------------------------------------*/
3045 static int
3046 packRegsForAssign (iCode * ic, eBBlock * ebp)
3047 {
3048   iCode *dic, *sic;
3049
3050   debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
3051   debugLog ("ic->op = %s\n", pic16_decodeOp( ic->op ) );
3052   debugAopGet ("  result:", IC_RESULT (ic));
3053   debugAopGet ("  left:", IC_LEFT (ic));
3054   debugAopGet ("  right:", IC_RIGHT (ic));
3055
3056 //      fprintf(stderr, "%s:%d symbol = %s\n", __FILE__, __LINE__, OP_SYMBOL( IC_RESULT(ic))->name);
3057
3058         debugLog(" %d - actuall processing\n", __LINE__ );
3059
3060   if (!IS_ITEMP (IC_RESULT (ic))) {
3061     pic16_allocDirReg(IC_RESULT (ic));
3062     debugLog ("  %d - result is not temp\n", __LINE__);
3063   }
3064
3065 //  if(IS_VALOP(IC_RIGHT(ic)))return 0;
3066
3067 /* See BUGLOG0001 - VR */
3068 #if 1
3069   if (!IS_ITEMP (IC_RIGHT (ic)) /*&& (!IS_PARM(IC_RESULT(ic)))*/) {
3070     debugLog ("  %d - not packing - right is not temp\n", __LINE__);
3071     pic16_allocDirReg(IC_RIGHT (ic));
3072     return 0;
3073   }
3074 #endif
3075
3076   if (OP_SYMBOL (IC_RIGHT (ic))->isind ||
3077       OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
3078     {
3079       debugLog ("  %d - not packing - right side fails \n", __LINE__);
3080       return 0;
3081     }
3082
3083   /* if the true symbol is defined in far space or on stack
3084      then we should not since this will increase register pressure */
3085   if (isOperandInFarSpace (IC_RESULT (ic)))
3086     {
3087       if ((dic = farSpacePackable (ic)))
3088         goto pack;
3089       else
3090         return 0;
3091
3092     }
3093
3094   /* find the definition of iTempNN scanning backwards if we find a 
3095      a use of the true symbol before we find the definition then 
3096      we cannot pack */
3097   for (dic = ic->prev; dic; dic = dic->prev)
3098     {
3099
3100       /* if there is a function call and this is
3101          a parameter & not my parameter then don't pack it */
3102       if ((dic->op == CALL || dic->op == PCALL) &&
3103           (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
3104            !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
3105         {
3106           debugLog ("  %d - \n", __LINE__);
3107           dic = NULL;
3108           break;
3109         }
3110
3111
3112       if (SKIP_IC2 (dic))
3113         continue;
3114
3115         debugLog("%d\tSearching for iTempNN\n", __LINE__);
3116
3117       if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
3118           IS_OP_VOLATILE (IC_RESULT (dic)))
3119         {
3120           debugLog ("  %d - dic is VOLATILE \n", __LINE__);
3121           dic = NULL;
3122           break;
3123         }
3124
3125 #if 1
3126       if( IS_SYMOP( IC_RESULT(dic)) &&
3127         IS_BITFIELD( OP_SYMBOL(IC_RESULT(dic))->etype ) ) {
3128
3129           debugLog (" %d - result is bitfield\n", __LINE__);
3130           dic = NULL;
3131           break;
3132         }
3133 #endif
3134
3135       if (IS_SYMOP (IC_RESULT (dic)) &&
3136           IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
3137         {
3138           /* A previous result was assigned to the same register - we'll our definition */
3139           debugLog ("  %d - dic result key == ic right key -- pointer set=%c\n",
3140                     __LINE__, ((POINTER_SET (dic)) ? 'Y' : 'N'));
3141           if (POINTER_SET (dic))
3142             dic = NULL;
3143
3144           break;
3145         }
3146
3147       if (IS_SYMOP (IC_RIGHT (dic)) &&
3148           (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
3149            IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
3150         {
3151           debugLog ("  %d - dic right key == ic rightor result key\n", __LINE__);
3152           dic = NULL;
3153           break;
3154         }
3155
3156       if (IS_SYMOP (IC_LEFT (dic)) &&
3157           (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
3158            IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
3159         {
3160           debugLog ("  %d - dic left key == ic rightor result key\n", __LINE__);
3161           dic = NULL;
3162           break;
3163         }
3164
3165       if (POINTER_SET (dic) &&
3166           IC_RESULT (dic)->key == IC_RESULT (ic)->key)
3167         {
3168           debugLog ("  %d - dic result key == ic result key -- pointer set=Y\n",
3169                     __LINE__);
3170           dic = NULL;
3171           break;
3172         }
3173     }
3174
3175   if (!dic)
3176     return 0;                   /* did not find */
3177
3178 #if 1
3179         /* This code is taken from the hc08 port. Do not know
3180          * if it fits for pic16, but I leave it here just in case */
3181
3182         /* if assignment then check that right is not a bit */
3183         if (ASSIGNMENT (ic) && !POINTER_SET (ic)) {
3184           sym_link *etype = operandType (IC_RESULT (dic));
3185
3186                 if (IS_BITFIELD (etype)) {
3187                         /* if result is a bit too then it's ok */
3188                         etype = operandType (IC_RESULT (ic));
3189                         if (!IS_BITFIELD (etype)) {
3190                                 debugLog(" %d bitfields\n");
3191                           return 0;
3192                         }
3193                 }
3194         }
3195 #endif
3196
3197   /* if the result is on stack or iaccess then it must be
3198      the same atleast one of the operands */
3199   if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
3200       OP_SYMBOL (IC_RESULT (ic))->iaccess)
3201     {
3202       /* the operation has only one symbol
3203          operator then we can pack */
3204       if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
3205           (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
3206         goto pack;
3207
3208       if (!((IC_LEFT (dic) &&
3209              IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
3210             (IC_RIGHT (dic) &&
3211              IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
3212         return 0;
3213     }
3214 pack:
3215   debugLog ("  packing. removing %s\n", OP_SYMBOL (IC_RIGHT (ic))->rname);
3216   debugLog ("  replacing with %s\n", OP_SYMBOL (IC_RESULT (dic))->rname);
3217   /* found the definition */
3218   /* replace the result with the result of */
3219   /* this assignment and remove this assignment */
3220
3221   
3222     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3223     IC_RESULT (dic) = IC_RESULT (ic);
3224
3225     if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
3226       {
3227         OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
3228       }
3229     /* delete from liverange table also 
3230        delete from all the points inbetween and the new
3231        one */
3232     for (sic = dic; sic != ic; sic = sic->next)
3233       {
3234         bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
3235         if (IS_ITEMP (IC_RESULT (dic)))
3236           bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
3237       }
3238
3239     remiCodeFromeBBlock (ebp, ic);
3240     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
3241
3242     debugLog("  %d\n", __LINE__ );
3243     hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
3244     OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
3245     return 1;
3246 }
3247
3248
3249 #if 1
3250
3251 #define NO_packRegsForAccUse
3252 #define NO_packRegsForSupport
3253 #define NO_packRegsForOneuse
3254 #define NO_cast_peep
3255
3256 #endif
3257
3258
3259 #ifndef NO_packRegsForSupport
3260 /*-----------------------------------------------------------------*/
3261 /* findAssignToSym : scanning backwards looks for first assig found */
3262 /*-----------------------------------------------------------------*/
3263 static iCode *
3264 findAssignToSym (operand * op, iCode * ic)
3265 {
3266   iCode *dic;
3267
3268   debugLog ("%s\n", __FUNCTION__);
3269   for (dic = ic->prev; dic; dic = dic->prev)
3270     {
3271
3272       /* if definition by assignment */
3273       if (dic->op == '=' &&
3274           !POINTER_SET (dic) &&
3275           IC_RESULT (dic)->key == op->key
3276 /*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
3277         )
3278         {
3279
3280           /* we are interested only if defined in far space */
3281           /* or in stack space in case of + & - */
3282
3283           /* if assigned to a non-symbol then return
3284              true */
3285           if (!IS_SYMOP (IC_RIGHT (dic)))
3286             break;
3287
3288           /* if the symbol is in far space then
3289              we should not */
3290           if (isOperandInFarSpace (IC_RIGHT (dic)))
3291             return NULL;
3292
3293           /* for + & - operations make sure that
3294              if it is on the stack it is the same
3295              as one of the three operands */
3296           if ((ic->op == '+' || ic->op == '-') &&
3297               OP_SYMBOL (IC_RIGHT (dic))->onStack)
3298             {
3299               if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
3300                   IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
3301                   IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
3302                 return NULL;
3303             }
3304
3305           break;
3306
3307         }
3308
3309       /* if we find an usage then we cannot delete it */
3310       if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
3311         return NULL;
3312
3313       if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
3314         return NULL;
3315
3316       if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
3317         return NULL;
3318     }
3319
3320   /* now make sure that the right side of dic
3321      is not defined between ic & dic */
3322   if (dic)
3323     {
3324       iCode *sic = dic->next;
3325
3326       for (; sic != ic; sic = sic->next)
3327         if (IC_RESULT (sic) &&
3328             IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
3329           return NULL;
3330     }
3331
3332   return dic;
3333
3334
3335 }
3336 #endif
3337
3338
3339 #ifndef NO_packRegsForSupport
3340 /*-----------------------------------------------------------------*/
3341 /* packRegsForSupport :- reduce some registers for support calls   */
3342 /*-----------------------------------------------------------------*/
3343 static int
3344 packRegsForSupport (iCode * ic, eBBlock * ebp)
3345 {
3346   int change = 0;
3347
3348   debugLog ("%s\n", __FUNCTION__);
3349   /* for the left & right operand :- look to see if the
3350      left was assigned a true symbol in far space in that
3351      case replace them */
3352   if (IS_ITEMP (IC_LEFT (ic)) &&
3353       OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
3354     {
3355       iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
3356       iCode *sic;
3357
3358       if (!dic)
3359         goto right;
3360
3361       debugAopGet ("removing left:", IC_LEFT (ic));
3362
3363       /* found it we need to remove it from the
3364          block */
3365       for (sic = dic; sic != ic; sic = sic->next)
3366         bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
3367
3368       IC_LEFT (ic)->operand.symOperand =
3369         IC_RIGHT (dic)->operand.symOperand;
3370       IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3371       remiCodeFromeBBlock (ebp, dic);
3372       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3373       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3374       change++;
3375     }
3376
3377   /* do the same for the right operand */
3378 right:
3379   if (!change &&
3380       IS_ITEMP (IC_RIGHT (ic)) &&
3381       OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
3382     {
3383       iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
3384       iCode *sic;
3385
3386       if (!dic)
3387         return change;
3388
3389       /* if this is a subtraction & the result
3390          is a true symbol in far space then don't pack */
3391       if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
3392         {
3393           sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
3394           if (IN_FARSPACE (SPEC_OCLS (etype)))
3395             return change;
3396         }
3397
3398       debugAopGet ("removing right:", IC_RIGHT (ic));
3399
3400       /* found it we need to remove it from the
3401          block */
3402       for (sic = dic; sic != ic; sic = sic->next)
3403         bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
3404
3405       IC_RIGHT (ic)->operand.symOperand =
3406         IC_RIGHT (dic)->operand.symOperand;
3407       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3408
3409       remiCodeFromeBBlock (ebp, dic);
3410       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3411       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3412       change++;
3413     }
3414
3415   return change;
3416 }
3417 #endif
3418
3419
3420 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
3421
3422 #ifndef NO_packRegsForOneuse
3423 /*-----------------------------------------------------------------*/
3424 /* packRegsForOneuse : - will reduce some registers for single Use */
3425 /*-----------------------------------------------------------------*/
3426 static iCode *
3427 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
3428 {
3429   bitVect *uses;
3430   iCode *dic, *sic;
3431
3432   return NULL;
3433
3434   debugLog ("%s\n", __FUNCTION__);
3435   /* if returning a literal then do nothing */
3436   if (!IS_SYMOP (op))
3437     return NULL;
3438
3439   if(OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly)
3440     return NULL;
3441
3442   /* only upto 2 bytes since we cannot predict
3443      the usage of b, & acc */
3444   if (getSize (operandType (op)) > (pic16_fReturnSizePic - 1)
3445       && ic->op != RETURN
3446       && ic->op != SEND
3447       && !POINTER_SET(ic)
3448       && !POINTER_GET(ic)
3449       )
3450     return NULL;
3451
3452   /* this routine will mark the a symbol as used in one 
3453      instruction use only && if the definition is local 
3454      (ie. within the basic block) && has only one definition &&
3455      that definition is either a return value from a 
3456      function or does not contain any variables in
3457      far space */
3458
3459 #if 0
3460   uses = bitVectCopy (OP_USES (op));
3461   bitVectUnSetBit (uses, ic->key);      /* take away this iCode */
3462   if (!bitVectIsZero (uses))    /* has other uses */
3463     return NULL;
3464 #endif
3465
3466 #if 1
3467   if (bitVectnBitsOn (OP_USES (op)) > 1)
3468     return NULL;
3469 #endif
3470
3471   /* if it has only one defintion */
3472   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
3473     return NULL;                /* has more than one definition */
3474
3475   /* get that definition */
3476   if (!(dic =
3477         hTabItemWithKey (iCodehTab,
3478                          bitVectFirstBit (OP_DEFS (op)))))
3479     return NULL;
3480
3481   /* found the definition now check if it is local */
3482   if (dic->seq < ebp->fSeq ||
3483       dic->seq > ebp->lSeq)
3484     return NULL;                /* non-local */
3485
3486   /* now check if it is the return from
3487      a function call */
3488   if (dic->op == CALL || dic->op == PCALL)
3489     {
3490       if (ic->op != SEND && ic->op != RETURN &&
3491           !POINTER_SET(ic) && !POINTER_GET(ic))
3492         {
3493           OP_SYMBOL (op)->ruonly = 1;
3494           return dic;
3495         }
3496       dic = dic->next;
3497     }
3498   else
3499     {
3500
3501
3502   /* otherwise check that the definition does
3503      not contain any symbols in far space */
3504   if (isOperandInFarSpace (IC_LEFT (dic)) ||
3505       isOperandInFarSpace (IC_RIGHT (dic)) ||
3506       IS_OP_RUONLY (IC_LEFT (ic)) ||
3507       IS_OP_RUONLY (IC_RIGHT (ic)))
3508     {
3509       return NULL;
3510     }
3511
3512   /* if pointer set then make sure the pointer
3513      is one byte */
3514   if (POINTER_SET (dic) &&
3515       !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3516     return NULL;
3517
3518   if (POINTER_GET (dic) &&
3519       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3520     return NULL;
3521     }
3522
3523   sic = dic;
3524
3525   /* also make sure the intervenening instructions
3526      don't have any thing in far space */
3527   for (dic = dic->next; dic && dic != ic; dic = dic->next)
3528     {
3529
3530       /* if there is an intervening function call then no */
3531       if (dic->op == CALL || dic->op == PCALL)
3532         return NULL;
3533       /* if pointer set then make sure the pointer
3534          is one byte */
3535       if (POINTER_SET (dic) &&
3536           !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3537         return NULL;
3538
3539       if (POINTER_GET (dic) &&
3540           !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3541         return NULL;
3542
3543       /* if address of & the result is remat then okay */
3544       if (dic->op == ADDRESS_OF &&
3545           OP_SYMBOL (IC_RESULT (dic))->remat)
3546         continue;
3547
3548       /* if operand has size of three or more & this
3549          operation is a '*','/' or '%' then 'b' may
3550          cause a problem */
3551       if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
3552           getSize (operandType (op)) >= 2)
3553         return NULL;
3554
3555       /* if left or right or result is in far space */
3556       if (isOperandInFarSpace (IC_LEFT (dic)) ||
3557           isOperandInFarSpace (IC_RIGHT (dic)) ||
3558           isOperandInFarSpace (IC_RESULT (dic)) ||
3559           IS_OP_RUONLY (IC_LEFT (dic)) ||
3560           IS_OP_RUONLY (IC_RIGHT (dic)) ||
3561           IS_OP_RUONLY (IC_RESULT (dic)))
3562         {
3563           return NULL;
3564         }
3565     }
3566
3567   OP_SYMBOL (op)->ruonly = 1;
3568   return sic;
3569
3570 }
3571 #endif
3572
3573
3574 /*-----------------------------------------------------------------*/
3575 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
3576 /*-----------------------------------------------------------------*/
3577 static bool
3578 isBitwiseOptimizable (iCode * ic)
3579 {
3580   sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
3581   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
3582
3583   debugLog ("%s\n", __FUNCTION__);
3584   /* bitwise operations are considered optimizable
3585      under the following conditions (Jean-Louis VERN) 
3586
3587      x & lit
3588      bit & bit
3589      bit & x
3590      bit ^ bit
3591      bit ^ x
3592      x   ^ lit
3593      x   | lit
3594      bit | bit
3595      bit | x
3596    */
3597   if (IS_LITERAL (rtype) ||
3598       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
3599     return TRUE;
3600   else
3601     return FALSE;
3602 }
3603
3604
3605 #ifndef NO_packRegsForAccUse
3606
3607 /*-----------------------------------------------------------------*/
3608 /* packRegsForAccUse - pack registers for acc use                  */
3609 /*-----------------------------------------------------------------*/
3610 static void
3611 packRegsForAccUse (iCode * ic)
3612 {
3613   iCode *uic;
3614
3615   debugLog ("%s\n", __FUNCTION__);
3616
3617   /* if this is an aggregate, e.g. a one byte char array */
3618   if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
3619     return;
3620   }
3621   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3622
3623   /* if + or - then it has to be one byte result */
3624   if ((ic->op == '+' || ic->op == '-')
3625       && getSize (operandType (IC_RESULT (ic))) > 1)
3626     return;
3627
3628   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3629   /* if shift operation make sure right side is not a literal */
3630   if (ic->op == RIGHT_OP &&
3631       (isOperandLiteral (IC_RIGHT (ic)) ||
3632        getSize (operandType (IC_RESULT (ic))) > 1))
3633     return;
3634
3635   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3636   if (ic->op == LEFT_OP &&
3637       (isOperandLiteral (IC_RIGHT (ic)) ||
3638        getSize (operandType (IC_RESULT (ic))) > 1))
3639     return;
3640
3641   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3642   if (IS_BITWISE_OP (ic) &&
3643       getSize (operandType (IC_RESULT (ic))) > 1)
3644     return;
3645
3646
3647   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3648   /* has only one definition */
3649   if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
3650     return;
3651
3652   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3653   /* has only one use */
3654   if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
3655     return;
3656
3657   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3658   /* and the usage immediately follows this iCode */
3659   if (!(uic = hTabItemWithKey (iCodehTab,
3660                                bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
3661     return;
3662
3663   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3664   if (ic->next != uic)
3665     return;
3666
3667   /* if it is a conditional branch then we definitely can */
3668   if (uic->op == IFX)
3669     goto accuse;
3670
3671   if (uic->op == JUMPTABLE)
3672     return;
3673
3674   /* if the usage is not is an assignment
3675      or an arithmetic / bitwise / shift operation then not */
3676   if (POINTER_SET (uic) &&
3677       getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
3678     return;
3679
3680   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3681   if (uic->op != '=' &&
3682       !IS_ARITHMETIC_OP (uic) &&
3683       !IS_BITWISE_OP (uic) &&
3684       uic->op != LEFT_OP &&
3685       uic->op != RIGHT_OP)
3686     return;
3687
3688   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3689   /* if used in ^ operation then make sure right is not a 
3690      literl */
3691   if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
3692     return;
3693
3694   /* if shift operation make sure right side is not a literal */
3695   if (uic->op == RIGHT_OP &&
3696       (isOperandLiteral (IC_RIGHT (uic)) ||
3697        getSize (operandType (IC_RESULT (uic))) > 1))
3698     return;
3699
3700   if (uic->op == LEFT_OP &&
3701       (isOperandLiteral (IC_RIGHT (uic)) ||
3702        getSize (operandType (IC_RESULT (uic))) > 1))
3703     return;
3704
3705   /* make sure that the result of this icode is not on the
3706      stack, since acc is used to compute stack offset */
3707   if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
3708       OP_SYMBOL (IC_RESULT (uic))->onStack)
3709     return;
3710
3711   /* if either one of them in far space then we cannot */
3712   if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3713        isOperandInFarSpace (IC_LEFT (uic))) ||
3714       (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3715        isOperandInFarSpace (IC_RIGHT (uic))))
3716     return;
3717
3718   /* if the usage has only one operand then we can */
3719   if (IC_LEFT (uic) == NULL ||
3720       IC_RIGHT (uic) == NULL)
3721     goto accuse;
3722
3723   /* make sure this is on the left side if not
3724      a '+' since '+' is commutative */
3725   if (ic->op != '+' &&
3726       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
3727     return;
3728
3729 #if 1
3730   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3731   /* if one of them is a literal then we can */
3732   if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
3733         (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))  &&
3734        (getSize (operandType (IC_RESULT (uic))) <= 1))
3735     {
3736       OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3737       return;
3738     }
3739 #endif
3740
3741   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3742   /* if the other one is not on stack then we can */
3743   if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
3744       (IS_ITEMP (IC_RIGHT (uic)) ||
3745        (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3746         !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
3747     goto accuse;
3748
3749   if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
3750       (IS_ITEMP (IC_LEFT (uic)) ||
3751        (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3752         !OP_SYMBOL (IC_LEFT (uic))->onStack)))
3753     goto accuse;
3754
3755   return;
3756
3757 accuse:
3758   debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
3759   OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3760
3761
3762 }
3763 #endif
3764
3765
3766 /*-----------------------------------------------------------------*/
3767 /* packForPush - hueristics to reduce iCode for pushing            */
3768 /*-----------------------------------------------------------------*/
3769 static void
3770 packForReceive (iCode * ic, eBBlock * ebp)
3771 {
3772   iCode *dic;
3773
3774   debugLog ("%s\n", __FUNCTION__);
3775   debugAopGet ("  result:", IC_RESULT (ic));
3776   debugAopGet ("  left:", IC_LEFT (ic));
3777   debugAopGet ("  right:", IC_RIGHT (ic));
3778
3779   if (!ic->next)
3780     return;
3781
3782   for (dic = ic->next; dic; dic = dic->next)
3783     {
3784       if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
3785         debugLog ("    used on left\n");
3786       if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
3787         debugLog ("    used on right\n");
3788       if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
3789         debugLog ("    used on result\n");
3790
3791       if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
3792         (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
3793         return;
3794     }
3795
3796   debugLog ("  hey we can remove this unnecessary assign\n");
3797 }
3798 /*-----------------------------------------------------------------*/
3799 /* packForPush - hueristics to reduce iCode for pushing            */
3800 /*-----------------------------------------------------------------*/
3801 static void
3802 packForPush (iCode * ic, eBBlock * ebp)
3803 {
3804   iCode *dic;
3805   char *iLine;
3806   
3807   debugLog ("%s\n", __FUNCTION__);
3808   if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
3809     return;
3810
3811 #if 0
3812   {
3813     int n1, n2;
3814     char *iLine;
3815
3816       n1 = bitVectnBitsOn( OP_DEFS(IC_LEFT(ic)));
3817       n2 = bitVectnBitsOn( OP_USES(IC_LEFT(ic)));
3818       iLine = printILine(ic);
3819       debugf3("defs: %d\tuses: %d\t%s\n", n1, n2, printILine(ic));
3820       dbuf_free(iLine);
3821       debugf2("IC_LEFT(ic): from %d to %d\n", OP_LIVEFROM(IC_LEFT(ic)), OP_LIVETO(IC_LEFT(ic)));
3822   }
3823 #endif
3824
3825   /* must have only definition & one usage */
3826   if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
3827       bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
3828     return;
3829
3830   /* find the definition */
3831   if (!(dic = hTabItemWithKey (iCodehTab,
3832                                bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
3833     return;
3834
3835   /* if definition is not assignment,
3836    * or is not pointer (because pointer might have changed) */
3837   if (dic->op != '=' || POINTER_SET (dic))
3838     return;
3839
3840   /* we must ensure that we can use the delete the assignment,
3841    * because the source might have been modified in between.
3842    * Until I know how to fix this, I'll use the adhoc fix
3843    * to check the liveranges */
3844   if((OP_LIVEFROM(IC_RIGHT(dic))==0) || (OP_LIVETO(IC_RIGHT(dic))==0))
3845     return;
3846 //  debugf2("IC_RIGHT(dic): from %d to %d\n", OP_LIVEFROM(IC_RIGHT(dic)), OP_LIVETO(IC_RIGHT(dic)));
3847   
3848
3849
3850   /* we now we know that it has one & only one def & use
3851      and the that the definition is an assignment */
3852   IC_LEFT (ic) = IC_RIGHT (dic);
3853   
3854   iLine = printILine(dic);
3855   debugf("remiCodeFromeBBlock: %s\n", iLine);
3856   dbuf_free(iLine);
3857
3858   remiCodeFromeBBlock (ebp, dic);
3859   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3860   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3861 }
3862
3863 static void printSymType(char * str, sym_link *sl)
3864 {
3865         if(!pic16_ralloc_debug)return;
3866         
3867         debugLog ("    %s Symbol type: ",str);
3868         printTypeChain (sl, debugF);
3869         debugLog ("\n");
3870 }
3871
3872 /*-----------------------------------------------------------------*/
3873 /* some debug code to print the symbol S_TYPE. Note that
3874  * the function checkSClass in src/SDCCsymt.c dinks with
3875  * the S_TYPE in ways the PIC port doesn't fully like...*/
3876 /*-----------------------------------------------------------------*/
3877 static void isData(sym_link *sl)
3878 {
3879   FILE *of = stderr;
3880
3881     if(!pic16_ralloc_debug)return;
3882     
3883     if(!sl)return;
3884     
3885     if(debugF)
3886       of = debugF;
3887
3888     for ( ; sl; sl=sl->next) {
3889       if(!IS_DECL(sl) ) {
3890         switch (SPEC_SCLS(sl)) {
3891           case S_DATA: fprintf (of, "data "); break;
3892           case S_XDATA: fprintf (of, "xdata "); break;
3893           case S_SFR: fprintf (of, "sfr "); break;
3894           case S_SBIT: fprintf (of, "sbit "); break;
3895           case S_CODE: fprintf (of, "code "); break;
3896           case S_IDATA: fprintf (of, "idata "); break;
3897           case S_PDATA: fprintf (of, "pdata "); break;
3898           case S_LITERAL: fprintf (of, "literal "); break;
3899           case S_STACK: fprintf (of, "stack "); break;
3900           case S_XSTACK: fprintf (of, "xstack "); break;
3901           case S_BIT: fprintf (of, "bit "); break;
3902           case S_EEPROM: fprintf (of, "eeprom "); break;
3903           default: break;
3904         }
3905       }
3906     }
3907 }
3908
3909
3910 /*--------------------------------------------------------------------*/
3911 /* pic16_packRegisters - does some transformations to reduce          */
3912 /*                   register pressure                                */
3913 /*                                                                    */
3914 /*--------------------------------------------------------------------*/
3915 static void
3916 pic16_packRegisters (eBBlock * ebp)
3917 {
3918   iCode *ic;
3919   int change = 0;
3920
3921   debugLog ("%s\n", __FUNCTION__);
3922
3923   while (1) {
3924
3925     change = 0;
3926
3927     /* look for assignments of the form */
3928     /* iTempNN = TRueSym (someoperation) SomeOperand */
3929     /*       ....                       */
3930     /* TrueSym := iTempNN:1             */
3931     for (ic = ebp->sch; ic; ic = ic->next)
3932       {
3933 //              debugLog("%d\n", __LINE__);
3934         /* find assignment of the form TrueSym := iTempNN:1 */
3935         if ( (ic->op == '=') && !POINTER_SET (ic) ) // patch 11
3936           change += packRegsForAssign (ic, ebp);
3937         /* debug stuff */
3938         if (ic->op == '=')
3939           {
3940             if (POINTER_SET (ic))
3941               debugLog ("pointer is set\n");
3942             debugAopGet ("  result:", IC_RESULT (ic));
3943             debugAopGet ("  left:", IC_LEFT (ic));
3944             debugAopGet ("  right:", IC_RIGHT (ic));
3945           }
3946
3947       }
3948
3949     if (!change)
3950       break;
3951   }
3952
3953   for (ic = ebp->sch; ic; ic = ic->next) {
3954
3955     if(IS_SYMOP ( IC_LEFT(ic))) {
3956       sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
3957
3958       debugAopGet ("x  left:", IC_LEFT (ic));
3959 #if 0
3960       if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
3961 #else
3962       if(IS_CODEPTR(OP_SYMBOL(IC_LEFT(ic))->type))
3963 #endif
3964         debugLog ("    is a pointer\n");
3965
3966       if(IS_PTR(OP_SYMBOL(IC_LEFT(ic))->type))
3967         debugLog ("    is a ptr\n");
3968
3969       if(IS_OP_VOLATILE(IC_LEFT(ic)))
3970         debugLog ("    is volatile\n");
3971
3972       isData(etype);
3973
3974         if(IS_OP_VOLATILE(IC_LEFT(ic))) {
3975             debugLog ("  %d - left is not temp, allocating\n", __LINE__);
3976             pic16_allocDirReg(IC_LEFT (ic));
3977         }
3978
3979       printSymType("c  ", OP_SYMBOL(IC_LEFT(ic))->type);
3980     }
3981
3982     if(IS_SYMOP ( IC_RIGHT(ic))) {
3983       debugAopGet ("  right:", IC_RIGHT (ic));
3984       printSymType("    ", OP_SYMBOL(IC_RIGHT(ic))->type);
3985     }
3986
3987     if(IS_SYMOP ( IC_RESULT(ic))) {
3988       debugAopGet ("  result:", IC_RESULT (ic));
3989       printSymType("     ", OP_SYMBOL(IC_RESULT(ic))->type);
3990     }
3991
3992     if(IS_TRUE_SYMOP ( IC_RIGHT(ic))) {
3993       debugAopGet ("  right:", IC_RIGHT (ic));
3994       printSymType("    ", OP_SYMBOL(IC_RIGHT(ic))->type);
3995 //      pic16_allocDirReg(IC_RIGHT(ic));
3996     }
3997
3998     if(IS_TRUE_SYMOP ( IC_RESULT(ic))) {
3999       debugAopGet ("  result:", IC_RESULT (ic));
4000       printSymType("     ", OP_SYMBOL(IC_RESULT(ic))->type);
4001 //      pic16_allocDirReg(IC_RESULT(ic));
4002     }
4003
4004
4005     if (POINTER_SET (ic))
4006       debugLog ("  %d - Pointer set\n", __LINE__);
4007       
4008       /* Look for two subsequent iCodes with */
4009       /*   iTemp := _c;         */
4010       /*   _c = iTemp & op;     */
4011       /* and replace them by    */
4012       /*   iTemp := _c;         */
4013       /*   _c = _c & op;        */
4014       if ((ic->op == BITWISEAND || ic->op == '|' || ic->op == '^')
4015         && ic->prev
4016         && ic->prev->op == '='
4017         && IS_ITEMP (IC_LEFT (ic))
4018         && IC_LEFT (ic) == IC_RESULT (ic->prev)
4019         && isOperandEqual (IC_RESULT(ic), IC_RIGHT(ic->prev)))
4020         {
4021           iCode* ic_prev = ic->prev;
4022           symbol* prev_result_sym = OP_SYMBOL (IC_RESULT (ic_prev));
4023                         
4024           ReplaceOpWithCheaperOp (&IC_LEFT (ic), IC_RESULT (ic));
4025           if (IC_RESULT (ic_prev) != IC_RIGHT (ic)) {
4026             bitVectUnSetBit (OP_USES (IC_RESULT (ic_prev)), ic->key);
4027             if (/*IS_ITEMP (IC_RESULT (ic_prev)) && */
4028               prev_result_sym->liveTo == ic->seq)
4029             {
4030               prev_result_sym->liveTo = ic_prev->seq;
4031             }
4032           }
4033           bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
4034           
4035           bitVectSetBit (ic->rlive, IC_RESULT (ic)->key);
4036
4037           if (bitVectIsZero (OP_USES (IC_RESULT (ic_prev)))) {
4038             bitVectUnSetBit (ic->rlive, IC_RESULT (ic)->key);
4039             bitVectUnSetBit (OP_DEFS (IC_RESULT (ic_prev)), ic_prev->key);
4040             remiCodeFromeBBlock (ebp, ic_prev);
4041             hTabDeleteItem (&iCodehTab, ic_prev->key, ic_prev, DELETE_ITEM, NULL);
4042           }
4043         }
4044                 
4045     /* if this is an itemp & result of a address of a true sym 
4046        then mark this as rematerialisable   */
4047     if (ic->op == ADDRESS_OF &&
4048         IS_ITEMP (IC_RESULT (ic)) &&
4049         IS_TRUE_SYMOP (IC_LEFT (ic)) &&
4050         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
4051         !OP_SYMBOL (IC_LEFT (ic))->onStack)
4052       {
4053
4054         debugLog ("  %d - %s. result is rematerializable\n", __LINE__,__FUNCTION__);
4055
4056         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
4057         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
4058         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
4059
4060       }
4061
4062     /* if straight assignment then carry remat flag if
4063        this is the only definition */
4064     if (ic->op == '=' &&
4065         !POINTER_SET (ic) &&
4066         IS_SYMOP (IC_RIGHT (ic)) &&
4067         OP_SYMBOL (IC_RIGHT (ic))->remat &&
4068         bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
4069       {
4070         debugLog ("  %d - %s. straight rematerializable\n", __LINE__,__FUNCTION__);
4071
4072         OP_SYMBOL (IC_RESULT (ic))->remat =
4073           OP_SYMBOL (IC_RIGHT (ic))->remat;
4074         OP_SYMBOL (IC_RESULT (ic))->rematiCode =
4075           OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
4076       }
4077
4078     /* if this is a +/- operation with a rematerizable 
4079        then mark this as rematerializable as well */
4080     if ((ic->op == '+' || ic->op == '-') &&
4081         (IS_SYMOP (IC_LEFT (ic)) &&
4082          IS_ITEMP (IC_RESULT (ic)) &&
4083          OP_SYMBOL (IC_LEFT (ic))->remat &&
4084          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
4085          IS_OP_LITERAL (IC_RIGHT (ic))))
4086       {
4087         debugLog ("  %d - %s. rematerializable because op is +/-\n", __LINE__,__FUNCTION__);
4088         //int i = 
4089         operandLitValue (IC_RIGHT (ic));
4090         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
4091         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
4092         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
4093       }
4094
4095
4096 #if 0
4097     /* try to optimize FSR0 usage when reading data memory pointers */
4098      
4099     if(getenv("OPTIMIZE_NEAR_POINTER_GET")) {
4100           static int fsr0usage=0;
4101           static iCode *usic;
4102
4103                 if(POINTER_GET(ic)                              /* this is a memory read */
4104                         && ic->loop                                     /* this is in a loop */
4105                 ) {
4106                         fprintf(stderr, "might optimize FSR0 usage\n");
4107                 }
4108     }
4109 #endif
4110           
4111     /* mark the pointer usages */
4112     if (POINTER_SET (ic))
4113       {
4114         OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
4115         debugLog ("  marking as a pointer (set) =>");
4116         debugAopGet ("  result:", IC_RESULT (ic));
4117
4118       }
4119
4120     if (POINTER_GET (ic))
4121       {
4122         if(IS_SYMOP(IC_LEFT(ic))) {
4123           OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
4124           debugLog ("  marking as a pointer (get) =>");
4125           debugAopGet ("  left:", IC_LEFT (ic));
4126         }
4127         
4128         if(getenv("OPTIMIZE_BITFIELD_POINTER_GET")) {
4129           if(IS_ITEMP(IC_LEFT(ic)) && IS_BITFIELD(OP_SYM_ETYPE(IC_LEFT(ic)))) {
4130             iCode *dic = ic->prev;
4131
4132             fprintf(stderr, "%s:%d might give opt POINTER_GET && IS_BITFIELD(IC_LEFT)\n", __FILE__, __LINE__);
4133           
4134             if(dic && dic->op == '='
4135               && isOperandEqual(IC_RESULT(dic), IC_LEFT(ic))) {
4136               
4137                 fprintf(stderr, "%s:%d && prev is '=' && prev->result == ic->left\n", __FILE__, __LINE__);
4138
4139
4140                 /* replace prev->left with ic->left */
4141                 IC_LEFT(ic) = IC_RIGHT(dic);
4142                 IC_RIGHT(ic->prev) = NULL;
4143                 
4144                 /* remove ic->prev iCode (assignment) */
4145                 remiCodeFromeBBlock (ebp, dic);
4146                 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,ic->key);
4147
4148
4149                 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
4150             }
4151           }
4152         }
4153       }
4154
4155         //debugLog("  %d   %s\n", __LINE__, __FUNCTION__);
4156
4157     if (!SKIP_IC2 (ic))
4158       {
4159         //debugLog("  %d   %s\n", __LINE__, __FUNCTION__ );
4160         /* if we are using a symbol on the stack
4161            then we should say pic16_ptrRegReq */
4162         if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
4163           pic16_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
4164                                OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
4165         else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
4166           pic16_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
4167                                OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
4168         else
4169           {
4170
4171                 //debugLog("   %d   %s\n", __LINE__, __FUNCTION__ );
4172             if (IS_SYMOP (IC_LEFT (ic)))
4173               pic16_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
4174                                    OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
4175             if (IS_SYMOP (IC_RIGHT (ic)))
4176               pic16_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
4177                                    OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
4178             if (IS_SYMOP (IC_RESULT (ic)))
4179               pic16_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
4180                                    OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
4181           }
4182
4183         debugLog ("  %d - pointer reg req = %d\n", __LINE__,pic16_ptrRegReq);
4184
4185       }
4186
4187     /* if the condition of an if instruction
4188        is defined in the previous instruction then
4189        mark the itemp as a conditional */
4190     if ((IS_CONDITIONAL (ic) ||
4191          ((ic->op == BITWISEAND ||
4192            ic->op == '|' ||
4193            ic->op == '^') &&
4194           isBitwiseOptimizable (ic))) &&
4195         ic->next && ic->next->op == IFX &&
4196         isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
4197         OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
4198       {
4199
4200         debugLog ("  %d\n", __LINE__);
4201         OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
4202         continue;
4203       }
4204
4205         debugLog(" %d\n", __LINE__);
4206
4207 #ifndef NO_packRegsForSupport
4208     /* reduce for support function calls */
4209     if (ic->supportRtn || ic->op == '+' || ic->op == '-')
4210       packRegsForSupport (ic, ebp);
4211 #endif
4212
4213     /* if a parameter is passed, it's in W, so we may not
4214        need to place a copy in a register */
4215     if (ic->op == RECEIVE)
4216       packForReceive (ic, ebp);
4217
4218 #ifndef NO_packRegsForOneuse
4219     /* some cases the redundant moves can
4220        can be eliminated for return statements */
4221     if ((ic->op == RETURN || ic->op == SEND) &&
4222         !isOperandInFarSpace (IC_LEFT (ic)) &&
4223         !options.model)
4224       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
4225 #endif
4226
4227 #ifndef NO_packRegsForOneuse
4228     /* if pointer set & left has a size more than
4229        one and right is not in far space */
4230     if (POINTER_SET (ic) &&
4231         !isOperandInFarSpace (IC_RIGHT (ic)) &&
4232         !OP_SYMBOL (IC_RESULT (ic))->remat &&
4233         !IS_OP_RUONLY (IC_RIGHT (ic)) &&
4234         getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
4235
4236       packRegsForOneuse (ic, IC_RESULT (ic), ebp);
4237 #endif
4238
4239 #ifndef NO_packRegsForOneuse
4240     /* if pointer get */
4241     if (POINTER_GET (ic) &&
4242         !isOperandInFarSpace (IC_RESULT (ic)) &&
4243         !OP_SYMBOL (IC_LEFT (ic))->remat &&
4244         !IS_OP_RUONLY (IC_RESULT (ic)) &&
4245         getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
4246
4247       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
4248       debugLog("%d - return from packRegsForOneuse\n", __LINE__);
4249 #endif
4250
4251 #ifndef NO_cast_peep
4252     /* if this is cast for intergral promotion then
4253        check if only use of  the definition of the 
4254        operand being casted/ if yes then replace
4255        the result of that arithmetic operation with 
4256        this result and get rid of the cast */
4257     if (ic->op == CAST) {
4258         
4259       sym_link *fromType = operandType (IC_RIGHT (ic));
4260       sym_link *toType = operandType (IC_LEFT (ic));
4261
4262       debugLog ("  %d - casting\n", __LINE__);
4263
4264       if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
4265           getSize (fromType) != getSize (toType)) {
4266             
4267
4268         iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
4269         if (dic) {
4270                 
4271           if (IS_ARITHMETIC_OP (dic)) {
4272                     debugLog("   %d   %s\n", __LINE__, __FUNCTION__ );
4273                     
4274             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
4275             IC_RESULT (dic) = IC_RESULT (ic);
4276             remiCodeFromeBBlock (ebp, ic);
4277             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
4278             hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
4279             OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
4280             ic = ic->prev;
4281           }  else
4282                 
4283             OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
4284         }
4285       } else {
4286
4287         /* if the type from and type to are the same
4288            then if this is the only use then packit */
4289         if (compareType (operandType (IC_RIGHT (ic)),
4290                          operandType (IC_LEFT (ic))) == 1) {
4291                 
4292           iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
4293           if (dic) {
4294
4295                    debugLog(" %d\n", __LINE__);
4296
4297             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
4298             IC_RESULT (dic) = IC_RESULT (ic);
4299             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
4300             remiCodeFromeBBlock (ebp, ic);
4301             hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
4302             OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
4303             ic = ic->prev;
4304           }
4305         }
4306       }
4307     }
4308 #endif
4309
4310 #if 1
4311     /* there are some problems with packing variables
4312      * it seems that the live range estimator doesn't
4313      * estimate correctly the liveranges of some symbols */
4314      
4315     /* pack for PUSH 
4316        iTempNN := (some variable in farspace) V1
4317        push iTempNN ;
4318        -------------
4319        push V1
4320     */
4321     if (ic->op == IPUSH)
4322       {
4323         packForPush (ic, ebp);
4324       }
4325 #endif
4326
4327 #ifndef NO_packRegsForAccUse
4328     /* pack registers for accumulator use, when the
4329        result of an arithmetic or bit wise operation
4330        has only one use, that use is immediately following
4331        the defintion and the using iCode has only one
4332        operand or has two operands but one is literal &
4333        the result of that operation is not on stack then
4334        we can leave the result of this operation in acc:b
4335        combination */
4336     if ((IS_ARITHMETIC_OP (ic)
4337
4338          || IS_BITWISE_OP (ic)
4339
4340          || ic->op == LEFT_OP || ic->op == RIGHT_OP
4341
4342          ) &&
4343         IS_ITEMP (IC_RESULT (ic)) &&
4344         getSize (operandType (IC_RESULT (ic))) <= 1)
4345
4346       packRegsForAccUse (ic);
4347 #endif
4348
4349   }
4350 }
4351
4352 static void
4353 dumpEbbsToDebug (eBBlock ** ebbs, int count)
4354 {
4355   int i;
4356
4357   if (!pic16_ralloc_debug || !debugF)
4358     return;
4359
4360   for (i = 0; i < count; i++)
4361     {
4362       fprintf (debugF, "\n----------------------------------------------------------------\n");
4363       fprintf (debugF, "Basic Block %s : loop Depth = %d noPath = %d , lastinLoop = %d\n",
4364                ebbs[i]->entryLabel->name,
4365                ebbs[i]->depth,
4366                ebbs[i]->noPath,
4367                ebbs[i]->isLastInLoop);
4368       fprintf (debugF, "depth 1st num %d : bbnum = %d 1st iCode = %d , last iCode = %d\n",
4369                ebbs[i]->dfnum,
4370                ebbs[i]->bbnum,
4371                ebbs[i]->fSeq,
4372                ebbs[i]->lSeq);
4373       fprintf (debugF, "visited %d : hasFcall = %d\n",
4374                ebbs[i]->visited,
4375                ebbs[i]->hasFcall);
4376
4377       fprintf (debugF, "\ndefines bitVector :");
4378       bitVectDebugOn (ebbs[i]->defSet, debugF);
4379       fprintf (debugF, "\nlocal defines bitVector :");
4380       bitVectDebugOn (ebbs[i]->ldefs, debugF);
4381       fprintf (debugF, "\npointers Set bitvector :");
4382       bitVectDebugOn (ebbs[i]->ptrsSet, debugF);
4383       fprintf (debugF, "\nin pointers Set bitvector :");
4384       bitVectDebugOn (ebbs[i]->inPtrsSet, debugF);
4385       fprintf (debugF, "\ninDefs Set bitvector :");
4386       bitVectDebugOn (ebbs[i]->inDefs, debugF);
4387       fprintf (debugF, "\noutDefs Set bitvector :");
4388       bitVectDebugOn (ebbs[i]->outDefs, debugF);
4389       fprintf (debugF, "\nusesDefs Set bitvector :");
4390       bitVectDebugOn (ebbs[i]->usesDefs, debugF);
4391       fprintf (debugF, "\n----------------------------------------------------------------\n");
4392       printiCChain (ebbs[i]->sch, debugF);
4393     }
4394 }
4395
4396 void dbg_dumpregusage(void);
4397
4398 /*-----------------------------------------------------------------*/
4399 /* pic16_assignRegisters - assigns registers to each live range as need  */
4400 /*-----------------------------------------------------------------*/
4401 void
4402 pic16_assignRegisters (ebbIndex * ebbi)
4403 {
4404   eBBlock ** ebbs = ebbi->bbOrder;
4405   int count = ebbi->count;
4406   iCode *ic;
4407   int i;
4408
4409   debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s", __FILE__, __FUNCTION__);
4410   debugLog ("\nebbs before optimizing:\n");
4411   dumpEbbsToDebug (ebbs, count);
4412
4413   _inRegAllocator = 1;
4414
4415   pic16_freeAllRegs();
4416 #if 0
4417         dbg_dumpregusage();
4418         /* clear whats left over from peephole parser */
4419         pic16_dynAllocRegs= newSet();   //NULL;
4420 //      pic16_dynStackRegs= newSet();   //NULL;
4421 //      pic16_dynProcessorRegs=newSet();        //NULL;
4422 //      pic16_dynDirectRegs=newSet();           //NULL;
4423 //      pic16_dynDirectBitRegs=newSet();        //NULL;
4424 //      pic16_dynInternalRegs=newSet();         //NULL;
4425 //      pic16_dynAccessRegs=newSet();           //NULL;
4426
4427 //      dynDirectRegNames=NULL;
4428         dynAllocRegNames=NULL;
4429 //      dynProcRegNames=NULL;
4430 //      dynAccessRegNames=NULL;
4431 #endif
4432
4433   setToNull ((void *) &_G.funcrUsed);
4434   pic16_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
4435
4436
4437   /* change assignments this will remove some
4438      live ranges reducing some register pressure */
4439   for (i = 0; i < count; i++)
4440     pic16_packRegisters (ebbs[i]);
4441
4442
4443   {
4444     regs *reg;
4445     int hkey;
4446
4447     debugLog("dir registers allocated so far:\n");
4448     reg = hTabFirstItem(dynDirectRegNames, &hkey);
4449
4450 #if 0
4451     while(reg) {
4452       debugLog("  -- #%d reg = %s  key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4453 //      fprintf(stderr, "  -- #%d reg = %s  key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4454       reg = hTabNextItem(dynDirectRegNames, &hkey);
4455     }
4456 #endif
4457
4458   }
4459
4460   /* liveranges probably changed by register packing
4461      so we compute them again */
4462   recomputeLiveRanges (ebbs, count);
4463
4464   if (options.dump_pack)
4465     dumpEbbsToFileExt (DUMP_PACK, ebbi);
4466
4467   /* first determine for each live range the number of 
4468      registers & the type of registers required for each */
4469   regTypeNum ();
4470
4471   /* start counting function temporary registers from zero */
4472   /* XXX: Resetting dynrIdx breaks register allocation,
4473    *      see #1489055, #1483693 (?), and #1445850! */
4474   //dynrIdx = 0;
4475
4476   /* and serially allocate registers */
4477   serialRegAssign (ebbs, count);
4478
4479 #if 0
4480   debugLog ("ebbs after serialRegAssign:\n");
4481   dumpEbbsToDebug (ebbs, count);
4482 #endif
4483
4484   //pic16_freeAllRegs();
4485
4486   /* if stack was extended then tell the user */
4487   if (_G.stackExtend)
4488     {
4489 /*      werror(W_TOOMANY_SPILS,"stack", */
4490 /*             _G.stackExtend,currFunc->name,""); */
4491       _G.stackExtend = 0;
4492     }
4493
4494   if (_G.dataExtend)
4495     {
4496 /*      werror(W_TOOMANY_SPILS,"data space", */
4497 /*             _G.dataExtend,currFunc->name,""); */
4498       _G.dataExtend = 0;
4499     }
4500
4501   /* after that create the register mask
4502      for each of the instruction */
4503   createRegMask (ebbs, count);
4504
4505   /* redo that offsets for stacked automatic variables */
4506   redoStackOffsets ();
4507
4508   if (options.dump_rassgn)
4509     dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
4510
4511 //  dumpLR(ebbs, count);
4512
4513   /* now get back the chain */
4514   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
4515
4516   debugLog ("ebbs after optimizing:\n");
4517   dumpEbbsToDebug (ebbs, count);
4518
4519
4520   _inRegAllocator = 0;
4521
4522   genpic16Code (ic);
4523
4524   /* free up any _G.stackSpil locations allocated */
4525   applyToSet (_G.stackSpil, deallocStackSpil);
4526   _G.slocNum = 0;
4527   setToNull ((void *) &_G.stackSpil);
4528   setToNull ((void *) &_G.spiltSet);
4529   /* mark all registers as free */
4530   pic16_freeAllRegs ();
4531
4532
4533   debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
4534   debugLogClose ();
4535   return;
4536 }