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