* device/lib/_gptrget.c,
[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 && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
1738         {
1739           sym = leastUsedLR (selectS);
1740           if (!sym->remat)
1741             {
1742               sym->remainSpil = 1;
1743               _G.blockSpil++;
1744             }
1745           return sym;
1746         }
1747     }
1748
1749   /* find live ranges with spillocation && not used as pointers */
1750   if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
1751     {
1752
1753       sym = leastUsedLR (selectS);
1754       /* mark this as allocation required */
1755       sym->usl.spillLoc->allocreq = 1;
1756       return sym;
1757     }
1758
1759   /* find live ranges with spillocation */
1760   if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
1761     {
1762
1763       sym = leastUsedLR (selectS);
1764       sym->usl.spillLoc->allocreq = 1;
1765       return sym;
1766     }
1767
1768   /* couldn't find then we need to create a spil
1769      location on the stack , for which one? the least
1770      used ofcourse */
1771   if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
1772     {
1773
1774       /* return a created spil location */
1775       sym = createStackSpil (leastUsedLR (selectS));
1776       sym->usl.spillLoc->allocreq = 1;
1777       return sym;
1778     }
1779
1780   /* this is an extreme situation we will spill
1781      this one : happens very rarely but it does happen */
1782   spillThis (forSym);
1783   return forSym;
1784
1785 }
1786
1787 /*-----------------------------------------------------------------*/
1788 /* spilSomething - spil some variable & mark registers as free     */
1789 /*-----------------------------------------------------------------*/
1790 static bool
1791 spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
1792 {
1793   symbol *ssym;
1794   int i;
1795
1796   debugLog ("%s\n", __FUNCTION__);
1797   /* get something we can spil */
1798   ssym = selectSpil (ic, ebp, forSym);
1799
1800   /* mark it as spilt */
1801   ssym->isspilt = 1;
1802   _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
1803
1804   /* mark it as not register assigned &
1805      take it away from the set */
1806   bitVectUnSetBit (_G.regAssigned, ssym->key);
1807
1808   /* mark the registers as free */
1809   for (i = 0; i < ssym->nRegs; i++)
1810     if (ssym->regs[i])
1811       freeReg (ssym->regs[i]);
1812
1813   /* if spilt on stack then free up r0 & r1 
1814      if they could have been assigned to as gprs */
1815   if (!pic16_ptrRegReq && isSpiltOnStack (ssym))
1816     {
1817       pic16_ptrRegReq++;
1818       spillLRWithPtrReg (ssym);
1819     }
1820
1821   /* if this was a block level spil then insert push & pop 
1822      at the start & end of block respectively */
1823   if (ssym->blockSpil)
1824     {
1825       iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
1826       /* add push to the start of the block */
1827       addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
1828                                     ebp->sch->next : ebp->sch));
1829       nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
1830       /* add pop to the end of the block */
1831       addiCodeToeBBlock (ebp, nic, NULL);
1832     }
1833
1834   /* if spilt because not used in the remainder of the
1835      block then add a push before this instruction and
1836      a pop at the end of the block */
1837   if (ssym->remainSpil)
1838     {
1839
1840       iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
1841       /* add push just before this instruction */
1842       addiCodeToeBBlock (ebp, nic, ic);
1843
1844       nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
1845       /* add pop to the end of the block */
1846       addiCodeToeBBlock (ebp, nic, NULL);
1847     }
1848
1849   if (ssym == forSym)
1850     return FALSE;
1851   else
1852     return TRUE;
1853 }
1854
1855 /*-----------------------------------------------------------------*/
1856 /* getRegPtr - will try for PTR if not a GPR type if not spil      */
1857 /*-----------------------------------------------------------------*/
1858 static regs *
1859 getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
1860 {
1861   regs *reg;
1862   int j;
1863
1864   debugLog ("%s\n", __FUNCTION__);
1865 tryAgain:
1866   /* try for a ptr type */
1867   if ((reg = allocReg (REG_PTR)))
1868     return reg;
1869
1870   /* try for gpr type */
1871   if ((reg = allocReg (REG_GPR)))
1872     return reg;
1873
1874   /* we have to spil */
1875   if (!spilSomething (ic, ebp, sym))
1876     return NULL;
1877
1878   /* make sure partially assigned registers aren't reused */
1879   for (j=0; j<=sym->nRegs; j++)
1880     if (sym->regs[j])
1881       sym->regs[j]->isFree = 0;
1882       
1883   /* this looks like an infinite loop but 
1884      in really selectSpil will abort  */
1885   goto tryAgain;
1886 }
1887
1888 /*-----------------------------------------------------------------*/
1889 /* getRegGpr - will try for GPR if not spil                        */
1890 /*-----------------------------------------------------------------*/
1891 static regs *
1892 getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
1893 {
1894   regs *reg;
1895   int j;
1896
1897   debugLog ("%s\n", __FUNCTION__);
1898 tryAgain:
1899   /* try for gpr type */
1900   if ((reg = allocReg (REG_GPR)))
1901     return reg;
1902
1903   if (!pic16_ptrRegReq)
1904     if ((reg = allocReg (REG_PTR)))
1905       return reg;
1906
1907   /* we have to spil */
1908   if (!spilSomething (ic, ebp, sym))
1909     return NULL;
1910
1911   /* make sure partially assigned registers aren't reused */
1912   for (j=0; j<=sym->nRegs; j++)
1913     if (sym->regs[j])
1914       sym->regs[j]->isFree = 0;
1915       
1916   /* this looks like an infinite loop but 
1917      in really selectSpil will abort  */
1918   goto tryAgain;
1919 }
1920
1921 /*-----------------------------------------------------------------*/
1922 /* symHasReg - symbol has a given register                         */
1923 /*-----------------------------------------------------------------*/
1924 static bool
1925 symHasReg (symbol * sym, regs * reg)
1926 {
1927   int i;
1928
1929   debugLog ("%s\n", __FUNCTION__);
1930   for (i = 0; i < sym->nRegs; i++)
1931     if (sym->regs[i] == reg)
1932       return TRUE;
1933
1934   return FALSE;
1935 }
1936
1937 /*-----------------------------------------------------------------*/
1938 /* deassignLRs - check the live to and if they have registers & are */
1939 /*               not spilt then free up the registers              */
1940 /*-----------------------------------------------------------------*/
1941 static void
1942 deassignLRs (iCode * ic, eBBlock * ebp)
1943 {
1944   symbol *sym;
1945   int k;
1946   symbol *result;
1947
1948   debugLog ("%s\n", __FUNCTION__);
1949   for (sym = hTabFirstItem (liveRanges, &k); sym;
1950        sym = hTabNextItem (liveRanges, &k))
1951     {
1952
1953       symbol *psym = NULL;
1954       /* if it does not end here */
1955       if (sym->liveTo > ic->seq)
1956         continue;
1957
1958       /* if it was spilt on stack then we can 
1959          mark the stack spil location as free */
1960       if (sym->isspilt)
1961         {
1962           if (sym->stackSpil)
1963             {
1964               sym->usl.spillLoc->isFree = 1;
1965               sym->stackSpil = 0;
1966             }
1967           continue;
1968         }
1969
1970       if (!bitVectBitValue (_G.regAssigned, sym->key))
1971         continue;
1972
1973       /* special case check if this is an IFX &
1974          the privious one was a pop and the 
1975          previous one was not spilt then keep track
1976          of the symbol */
1977       if (ic->op == IFX && ic->prev &&
1978           ic->prev->op == IPOP &&
1979           !ic->prev->parmPush &&
1980           !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
1981         psym = OP_SYMBOL (IC_LEFT (ic->prev));
1982
1983       if (sym->nRegs)
1984         {
1985           int i = 0;
1986
1987           bitVectUnSetBit (_G.regAssigned, sym->key);
1988
1989           /* if the result of this one needs registers
1990              and does not have it then assign it right
1991              away */
1992           if (IC_RESULT (ic) &&
1993               !(SKIP_IC2 (ic) ||        /* not a special icode */
1994                 ic->op == JUMPTABLE ||
1995                 ic->op == IFX ||
1996                 ic->op == IPUSH ||
1997                 ic->op == IPOP ||
1998                 ic->op == RETURN ||
1999                 POINTER_SET (ic)) &&
2000               (result = OP_SYMBOL (IC_RESULT (ic))) &&  /* has a result */
2001               result->liveTo > ic->seq &&       /* and will live beyond this */
2002               result->liveTo <= ebp->lSeq &&    /* does not go beyond this block */
2003               result->liveFrom == ic->seq &&    /* does not start before here */
2004               result->regType == sym->regType &&        /* same register types */
2005               result->nRegs &&  /* which needs registers */
2006               !result->isspilt &&       /* and does not already have them */
2007               !result->remat &&
2008               !bitVectBitValue (_G.regAssigned, result->key) &&
2009           /* the number of free regs + number of regs in this LR
2010              can accomodate the what result Needs */
2011               ((nfreeRegsType (result->regType) +
2012                 sym->nRegs) >= result->nRegs)
2013             )
2014             {
2015
2016               for (i = 0; i < max (sym->nRegs, result->nRegs); i++)
2017                 if (i < sym->nRegs)
2018                   result->regs[i] = sym->regs[i];
2019                 else
2020                   result->regs[i] = getRegGpr (ic, ebp, result);
2021
2022               _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
2023
2024             }
2025
2026           /* free the remaining */
2027           for (; i < sym->nRegs; i++)
2028             {
2029               if (psym)
2030                 {
2031                   if (!symHasReg (psym, sym->regs[i]))
2032                     freeReg (sym->regs[i]);
2033                 }
2034               else
2035                 freeReg (sym->regs[i]);
2036             }
2037         }
2038     }
2039 }
2040
2041
2042 /*-----------------------------------------------------------------*/
2043 /* reassignLR - reassign this to registers                         */
2044 /*-----------------------------------------------------------------*/
2045 static void
2046 reassignLR (operand * op)
2047 {
2048   symbol *sym = OP_SYMBOL (op);
2049   int i;
2050
2051   debugLog ("%s\n", __FUNCTION__);
2052   /* not spilt any more */
2053   sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
2054   bitVectUnSetBit (_G.spiltSet, sym->key);
2055
2056   _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
2057
2058   _G.blockSpil--;
2059
2060   for (i = 0; i < sym->nRegs; i++)
2061     sym->regs[i]->isFree = 0;
2062 }
2063
2064 /*-----------------------------------------------------------------*/
2065 /* willCauseSpill - determines if allocating will cause a spill    */
2066 /*-----------------------------------------------------------------*/
2067 static int
2068 willCauseSpill (int nr, int rt)
2069 {
2070   debugLog ("%s\n", __FUNCTION__);
2071   /* first check if there are any avlb registers
2072      of te type required */
2073   if (rt == REG_PTR)
2074     {
2075       /* special case for pointer type 
2076          if pointer type not avlb then 
2077          check for type gpr */
2078       if (nFreeRegs (rt) >= nr)
2079         return 0;
2080       if (nFreeRegs (REG_GPR) >= nr)
2081         return 0;
2082     }
2083   else
2084     {
2085       if (pic16_ptrRegReq)
2086         {
2087           if (nFreeRegs (rt) >= nr)
2088             return 0;
2089         }
2090       else
2091         {
2092           if (nFreeRegs (REG_PTR) +
2093               nFreeRegs (REG_GPR) >= nr)
2094             return 0;
2095         }
2096     }
2097
2098   debugLog (" ... yep it will (cause a spill)\n");
2099   /* it will cause a spil */
2100   return 1;
2101 }
2102
2103 /*-----------------------------------------------------------------*/
2104 /* positionRegs - the allocator can allocate same registers to res- */
2105 /* ult and operand, if this happens make sure they are in the same */
2106 /* position as the operand otherwise chaos results                 */
2107 /*-----------------------------------------------------------------*/
2108 static void
2109 positionRegs (symbol * result, symbol * opsym, int lineno)
2110 {
2111   int count = min (result->nRegs, opsym->nRegs);
2112   int i, j = 0, shared = 0;
2113
2114   debugLog ("%s\n", __FUNCTION__);
2115   /* if the result has been spilt then cannot share */
2116   if (opsym->isspilt)
2117     return;
2118 again:
2119   shared = 0;
2120   /* first make sure that they actually share */
2121   for (i = 0; i < count; i++)
2122     {
2123       for (j = 0; j < count; j++)
2124         {
2125           if (result->regs[i] == opsym->regs[j] && i != j)
2126             {
2127               shared = 1;
2128               goto xchgPositions;
2129             }
2130         }
2131     }
2132 xchgPositions:
2133   if (shared)
2134     {
2135       regs *tmp = result->regs[i];
2136       result->regs[i] = result->regs[j];
2137       result->regs[j] = tmp;
2138       goto again;
2139     }
2140 }
2141
2142 /*------------------------------------------------------------------*/
2143 /* verifyRegsAssigned - make sure an iTemp is properly initialized; */
2144 /* it should either have registers or have beed spilled. Otherwise, */
2145 /* there was an uninitialized variable, so just spill this to get   */
2146 /* the operand in a valid state.                                    */
2147 /*------------------------------------------------------------------*/
2148 static void
2149 verifyRegsAssigned (operand *op, iCode * ic)
2150 {
2151   symbol * sym;
2152   
2153   if (!op) return;
2154   if (!IS_ITEMP (op)) return;
2155   
2156   sym = OP_SYMBOL (op);
2157   if (sym->isspilt) return;
2158   if (!sym->nRegs) return;
2159   if (sym->regs[0]) return;
2160   
2161   werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT, 
2162             sym->prereqv ? sym->prereqv->name : sym->name);
2163   spillThis (sym);
2164 }
2165
2166
2167 /*-----------------------------------------------------------------*/
2168 /* serialRegAssign - serially allocate registers to the variables  */
2169 /*-----------------------------------------------------------------*/
2170 static void
2171 serialRegAssign (eBBlock ** ebbs, int count)
2172 {
2173   int i;
2174
2175   debugLog ("%s\n", __FUNCTION__);
2176   /* for all blocks */
2177   for (i = 0; i < count; i++)
2178     {
2179
2180       iCode *ic;
2181
2182       if (ebbs[i]->noPath &&
2183           (ebbs[i]->entryLabel != entryLabel &&
2184            ebbs[i]->entryLabel != returnLabel))
2185         continue;
2186
2187       /* of all instructions do */
2188       for (ic = ebbs[i]->sch; ic; ic = ic->next)
2189         {
2190
2191           debugLog ("  op: %s\n", decodeOp (ic->op));
2192
2193                 if(IC_RESULT(ic) && !IS_ITEMP( IC_RESULT(ic)))
2194                         pic16_allocDirReg(IC_RESULT(ic));
2195
2196                 if(IC_LEFT(ic) && !IS_ITEMP( IC_LEFT(ic)))
2197                         pic16_allocDirReg(IC_LEFT(ic));
2198
2199                 if(IC_RIGHT(ic) && !IS_ITEMP( IC_RIGHT(ic)))
2200                         pic16_allocDirReg(IC_RIGHT(ic));
2201
2202           /* if this is an ipop that means some live
2203              range will have to be assigned again */
2204           if (ic->op == IPOP)
2205             reassignLR (IC_LEFT (ic));
2206
2207           /* if result is present && is a true symbol */
2208           if (IC_RESULT (ic) && ic->op != IFX &&
2209               IS_TRUE_SYMOP (IC_RESULT (ic)))
2210             OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
2211
2212           /* take away registers from live
2213              ranges that end at this instruction */
2214           deassignLRs (ic, ebbs[i]);
2215
2216           /* some don't need registers */
2217           if (SKIP_IC2 (ic) ||
2218               ic->op == JUMPTABLE ||
2219               ic->op == IFX ||
2220               ic->op == IPUSH ||
2221               ic->op == IPOP ||
2222               (IC_RESULT (ic) && POINTER_SET (ic)))
2223             continue;
2224
2225           /* now we need to allocate registers
2226              only for the result */
2227           if (IC_RESULT (ic))
2228             {
2229               symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2230               bitVect *spillable;
2231               int willCS;
2232               int j;
2233               int ptrRegSet = 0;
2234
2235               /* if it does not need or is spilt 
2236                  or is already assigned to registers
2237                  or will not live beyond this instructions */
2238               if (!sym->nRegs ||
2239                   sym->isspilt ||
2240                   bitVectBitValue (_G.regAssigned, sym->key) ||
2241                   sym->liveTo <= ic->seq)
2242                 continue;
2243
2244               /* if some liverange has been spilt at the block level
2245                  and this one live beyond this block then spil this
2246                  to be safe */
2247               if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
2248                 {
2249                   spillThis (sym);
2250                   continue;
2251                 }
2252               /* if trying to allocate this will cause
2253                  a spill and there is nothing to spill 
2254                  or this one is rematerializable then
2255                  spill this one */
2256               willCS = willCauseSpill (sym->nRegs, sym->regType);
2257               spillable = computeSpillable (ic);
2258               if (sym->remat ||
2259                   (willCS && bitVectIsZero (spillable)))
2260                 {
2261
2262                   spillThis (sym);
2263                   continue;
2264
2265                 }
2266
2267               /* If the live range preceeds the point of definition 
2268                  then ideally we must take into account registers that 
2269                  have been allocated after sym->liveFrom but freed
2270                  before ic->seq. This is complicated, so spill this
2271                  symbol instead and let fillGaps handle the allocation. */
2272               if (sym->liveFrom < ic->seq)
2273                 {
2274                     spillThis (sym);
2275                     continue;                 
2276                 }
2277
2278               /* if it has a spillocation & is used less than
2279                  all other live ranges then spill this */
2280                 if (willCS) {
2281                     if (sym->usl.spillLoc) {
2282                         symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
2283                                                                          allLRs, ebbs[i], ic));
2284                         if (leastUsed && leastUsed->used > sym->used) {
2285                             spillThis (sym);
2286                             continue;
2287                         }
2288                     } else {
2289                         /* if none of the liveRanges have a spillLocation then better
2290                            to spill this one than anything else already assigned to registers */
2291                         if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
2292                             /* if this is local to this block then we might find a block spil */
2293                             if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
2294                                 spillThis (sym);
2295                                 continue;
2296                             }
2297                         }
2298                     }
2299                 }
2300
2301               if (ic->op == RECEIVE)
2302                 debugLog ("When I get clever, I'll optimize the receive logic\n");
2303
2304               /* if we need ptr regs for the right side
2305                  then mark it */
2306               if (POINTER_GET (ic) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
2307                   <= (unsigned) PTRSIZE)
2308                 {
2309                   pic16_ptrRegReq++;
2310                   ptrRegSet = 1;
2311                 }
2312               /* else we assign registers to it */
2313               _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
2314
2315               debugLog ("  %d - nRegs: %d\n", __LINE__, sym->nRegs);
2316               if(debugF) 
2317                 bitVectDebugOn(_G.regAssigned, debugF);
2318
2319               for (j = 0; j < sym->nRegs; j++)
2320                 {
2321                   if (sym->regType == REG_PTR)
2322                     sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
2323                   else
2324                     sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
2325
2326                   /* if the allocation falied which means
2327                      this was spilt then break */
2328                   if (!sym->regs[j])
2329                     break;
2330                 }
2331               debugLog ("  %d - \n", __LINE__);
2332
2333               /* if it shares registers with operands make sure
2334                  that they are in the same position */
2335               if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
2336                   OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
2337                 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2338                               OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
2339               /* do the same for the right operand */
2340               if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
2341                   OP_SYMBOL (IC_RIGHT (ic))->nRegs && ic->op != '=')
2342                 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2343                               OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
2344
2345               debugLog ("  %d - \n", __LINE__);
2346               if (ptrRegSet)
2347                 {
2348                   debugLog ("  %d - \n", __LINE__);
2349                   pic16_ptrRegReq--;
2350                   ptrRegSet = 0;
2351                 }
2352
2353             }
2354         }
2355     }
2356
2357     /* Check for and fix any problems with uninitialized operands */
2358     for (i = 0; i < count; i++)
2359       {
2360         iCode *ic;
2361
2362         if (ebbs[i]->noPath &&
2363             (ebbs[i]->entryLabel != entryLabel &&
2364              ebbs[i]->entryLabel != returnLabel))
2365             continue;
2366
2367         for (ic = ebbs[i]->sch; ic; ic = ic->next)
2368           {
2369             if (SKIP_IC2 (ic))
2370               continue;
2371
2372             if (ic->op == IFX)
2373               {
2374                 verifyRegsAssigned (IC_COND (ic), ic);
2375                 continue;
2376               }
2377
2378             if (ic->op == JUMPTABLE)
2379               {
2380                 verifyRegsAssigned (IC_JTCOND (ic), ic);
2381                 continue;
2382               }
2383
2384             verifyRegsAssigned (IC_RESULT (ic), ic);
2385             verifyRegsAssigned (IC_LEFT (ic), ic);
2386             verifyRegsAssigned (IC_RIGHT (ic), ic);
2387           }
2388       }    
2389     
2390 }
2391
2392 /*-----------------------------------------------------------------*/
2393 /* rUmaskForOp :- returns register mask for an operand             */
2394 /*-----------------------------------------------------------------*/
2395 static bitVect *
2396 rUmaskForOp (operand * op)
2397 {
2398   bitVect *rumask;
2399   symbol *sym;
2400   int j;
2401
2402   debugLog ("%s\n", __FUNCTION__);
2403   /* only temporaries are assigned registers */
2404   if (!IS_ITEMP (op))
2405     return NULL;
2406
2407   sym = OP_SYMBOL (op);
2408
2409   /* if spilt or no registers assigned to it
2410      then nothing */
2411   if (sym->isspilt || !sym->nRegs)
2412     return NULL;
2413
2414   rumask = newBitVect (pic16_nRegs);
2415
2416   for (j = 0; j < sym->nRegs; j++)
2417     {
2418       rumask = bitVectSetBit (rumask,
2419                               sym->regs[j]->rIdx);
2420     }
2421
2422   return rumask;
2423 }
2424
2425 /*-----------------------------------------------------------------*/
2426 /* regsUsedIniCode :- returns bit vector of registers used in iCode */
2427 /*-----------------------------------------------------------------*/
2428 static bitVect *
2429 regsUsedIniCode (iCode * ic)
2430 {
2431   bitVect *rmask = newBitVect (pic16_nRegs);
2432
2433   debugLog ("%s\n", __FUNCTION__);
2434   /* do the special cases first */
2435   if (ic->op == IFX)
2436     {
2437       rmask = bitVectUnion (rmask,
2438                             rUmaskForOp (IC_COND (ic)));
2439       goto ret;
2440     }
2441
2442   /* for the jumptable */
2443   if (ic->op == JUMPTABLE)
2444     {
2445       rmask = bitVectUnion (rmask,
2446                             rUmaskForOp (IC_JTCOND (ic)));
2447
2448       goto ret;
2449     }
2450
2451   /* of all other cases */
2452   if (IC_LEFT (ic))
2453     rmask = bitVectUnion (rmask,
2454                           rUmaskForOp (IC_LEFT (ic)));
2455
2456
2457   if (IC_RIGHT (ic))
2458     rmask = bitVectUnion (rmask,
2459                           rUmaskForOp (IC_RIGHT (ic)));
2460
2461   if (IC_RESULT (ic))
2462     rmask = bitVectUnion (rmask,
2463                           rUmaskForOp (IC_RESULT (ic)));
2464
2465 ret:
2466   return rmask;
2467 }
2468
2469 /*-----------------------------------------------------------------*/
2470 /* createRegMask - for each instruction will determine the regsUsed */
2471 /*-----------------------------------------------------------------*/
2472 static void
2473 createRegMask (eBBlock ** ebbs, int count)
2474 {
2475   int i;
2476
2477   debugLog ("%s\n", __FUNCTION__);
2478   /* for all blocks */
2479   for (i = 0; i < count; i++)
2480     {
2481       iCode *ic;
2482
2483       if (ebbs[i]->noPath &&
2484           (ebbs[i]->entryLabel != entryLabel &&
2485            ebbs[i]->entryLabel != returnLabel))
2486         continue;
2487
2488       /* for all instructions */
2489       for (ic = ebbs[i]->sch; ic; ic = ic->next)
2490         {
2491
2492           int j;
2493
2494           if (SKIP_IC2 (ic) || !ic->rlive)
2495             continue;
2496
2497           /* first mark the registers used in this
2498              instruction */
2499           ic->rUsed = regsUsedIniCode (ic);
2500           _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
2501
2502           /* now create the register mask for those 
2503              registers that are in use : this is a
2504              super set of ic->rUsed */
2505           ic->rMask = newBitVect (pic16_nRegs + 1);
2506
2507           /* for all live Ranges alive at this point */
2508           for (j = 1; j < ic->rlive->size; j++)
2509             {
2510               symbol *sym;
2511               int k;
2512
2513               /* if not alive then continue */
2514               if (!bitVectBitValue (ic->rlive, j))
2515                 continue;
2516
2517               /* find the live range we are interested in */
2518               if (!(sym = hTabItemWithKey (liveRanges, j)))
2519                 {
2520                   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2521                           "createRegMask cannot find live range");
2522                   exit (0);
2523                 }
2524
2525               /* if no register assigned to it */
2526               if (!sym->nRegs || sym->isspilt)
2527                 continue;
2528
2529               /* for all the registers allocated to it */
2530               for (k = 0; k < sym->nRegs; k++)
2531                 if (sym->regs[k])
2532                   ic->rMask =
2533                     bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
2534             }
2535         }
2536     }
2537 }
2538
2539 /*-----------------------------------------------------------------*/
2540 /* rematStr - returns the rematerialized string for a remat var    */
2541 /*-----------------------------------------------------------------*/
2542 static symbol *
2543 rematStr (symbol * sym)
2544 {
2545   char *s = buffer;
2546   iCode *ic = sym->rematiCode;
2547   symbol *psym = NULL;
2548
2549   debugLog ("%s\n", __FUNCTION__);
2550
2551   //printf ("%s\n", s);
2552
2553   /* if plus or minus print the right hand side */
2554
2555   if (ic->op == '+' || ic->op == '-') {
2556         
2557     iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2558
2559     sprintf (s, "(%s %c 0x%04x)",
2560              OP_SYMBOL (IC_LEFT (ric))->rname,
2561              ic->op,
2562              (int) operandLitValue (IC_RIGHT (ic)));
2563
2564
2565     //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
2566
2567     psym = newSymbol (OP_SYMBOL (IC_LEFT (ric))->rname, 1);
2568     psym->offset = (int) operandLitValue (IC_RIGHT (ic));
2569
2570     return psym;
2571   }
2572
2573   sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
2574   psym = newSymbol (OP_SYMBOL (IC_LEFT (ic))->rname, 1);
2575
2576   //printf ("ralloc.c:%d %s\n", __LINE__,buffer);
2577   return psym;
2578 }
2579
2580 #if 0
2581 /*-----------------------------------------------------------------*/
2582 /* rematStr - returns the rematerialized string for a remat var    */
2583 /*-----------------------------------------------------------------*/
2584 static char *
2585 rematStr (symbol * sym)
2586 {
2587   char *s = buffer;
2588   iCode *ic = sym->rematiCode;
2589
2590   debugLog ("%s\n", __FUNCTION__);
2591   while (1)
2592     {
2593
2594       printf ("%s\n", s);
2595       /* if plus or minus print the right hand side */
2596 /*
2597    if (ic->op == '+' || ic->op == '-') {
2598    sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
2599    ic->op );
2600    s += strlen(s);
2601    ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2602    continue ;
2603    }
2604  */
2605       if (ic->op == '+' || ic->op == '-')
2606         {
2607           iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2608           sprintf (s, "(%s %c 0x%04x)",
2609                    OP_SYMBOL (IC_LEFT (ric))->rname,
2610                    ic->op,
2611                    (int) operandLitValue (IC_RIGHT (ic)));
2612
2613           //s += strlen(s);
2614           //ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2615           //continue ;
2616           //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
2617           return buffer;
2618         }
2619
2620       /* we reached the end */
2621       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
2622       break;
2623     }
2624
2625   printf ("%s\n", buffer);
2626   return buffer;
2627 }
2628 #endif
2629
2630 /*-----------------------------------------------------------------*/
2631 /* regTypeNum - computes the type & number of registers required   */
2632 /*-----------------------------------------------------------------*/
2633 static void
2634 regTypeNum ()
2635 {
2636   symbol *sym;
2637   int k;
2638   iCode *ic;
2639
2640   debugLog ("%s\n", __FUNCTION__);
2641   /* for each live range do */
2642   for (sym = hTabFirstItem (liveRanges, &k); sym;
2643        sym = hTabNextItem (liveRanges, &k)) {
2644
2645     debugLog ("  %d - %s\n", __LINE__, sym->rname);
2646     //fprintf(stderr,"  %d - %s\n", __LINE__, sym->rname);
2647
2648     /* if used zero times then no registers needed */
2649     if ((sym->liveTo - sym->liveFrom) == 0)
2650       continue;
2651
2652
2653     /* if the live range is a temporary */
2654     if (sym->isitmp) {
2655
2656       debugLog ("  %d - itemp register\n", __LINE__);
2657
2658       /* if the type is marked as a conditional */
2659       if (sym->regType == REG_CND)
2660         continue;
2661
2662       /* if used in return only then we don't 
2663          need registers */
2664       if (sym->ruonly || sym->accuse) {
2665         if (IS_AGGREGATE (sym->type) || sym->isptr)
2666           sym->type = aggrToPtr (sym->type, FALSE);
2667         debugLog ("  %d - no reg needed - used as a return\n", __LINE__);
2668
2669         continue;
2670       }
2671
2672       /* if the symbol has only one definition &
2673          that definition is a get_pointer and the
2674          pointer we are getting is rematerializable and
2675          in "data" space */
2676
2677       if (bitVectnBitsOn (sym->defs) == 1 &&
2678           (ic = hTabItemWithKey (iCodehTab,
2679                                  bitVectFirstBit (sym->defs))) &&
2680           POINTER_GET (ic) &&
2681           !IS_BITVAR (sym->etype) &&
2682           (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) {
2683
2684         if (ptrPseudoSymSafe (sym, ic)) {
2685           
2686           symbol *psym;
2687           
2688           debugLog ("  %d - \n", __LINE__);
2689               
2690           /* create a psuedo symbol & force a spil */
2691           //X symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
2692           psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
2693           psym->type = sym->type;
2694           psym->etype = sym->etype;
2695           psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (ic)));
2696           strcpy (psym->rname, psym->name);
2697           sym->isspilt = 1;
2698           sym->usl.spillLoc = psym;
2699           continue;
2700         }
2701
2702         /* if in data space or idata space then try to
2703            allocate pointer register */
2704
2705       }
2706
2707       /* if not then we require registers */
2708       sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
2709                     getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
2710                     getSize (sym->type));
2711
2712
2713 #if 0
2714     if(IS_PTR_CONST (sym->type)) {
2715 #else
2716     if(IS_CODEPTR (sym->type)) {
2717 #endif
2718       // what IS this ???? (HJD)
2719       debugLog ("  %d const pointer type requires %d registers, changing to 3\n",__LINE__,sym->nRegs); // patch 14
2720       sym->nRegs = 3; // patch 14
2721     }
2722
2723       if (sym->nRegs > 4) {
2724         fprintf (stderr, "allocated more than 4 or 0 registers for type ");
2725         printTypeChain (sym->type, stderr);
2726         fprintf (stderr, "\n");
2727       }
2728
2729       /* determine the type of register required */
2730       if (sym->nRegs == 1 &&
2731           IS_PTR (sym->type) &&
2732           sym->uptr)
2733         sym->regType = REG_PTR;
2734       else
2735         sym->regType = REG_GPR;
2736
2737
2738       debugLog ("  reg name %s,  reg type %s\n", sym->rname, debugLogRegType (sym->regType));
2739
2740     }
2741     else
2742       /* for the first run we don't provide */
2743       /* registers for true symbols we will */
2744       /* see how things go                  */
2745       sym->nRegs = 0;
2746   }
2747
2748 }
2749 static DEFSETFUNC (markRegFree)
2750 {
2751   ((regs *)item)->isFree = 1;
2752
2753   return 0;
2754 }
2755
2756 DEFSETFUNC (pic16_deallocReg)
2757 {
2758   fprintf(stderr,"deallocting register %s\n",((regs *)item)->name);
2759   ((regs *)item)->isFree = 1;
2760   ((regs *)item)->wasUsed = 0;
2761
2762   return 0;
2763 }
2764 /*-----------------------------------------------------------------*/
2765 /* freeAllRegs - mark all registers as free                        */
2766 /*-----------------------------------------------------------------*/
2767 void
2768 pic16_freeAllRegs ()
2769 {
2770   debugLog ("%s\n", __FUNCTION__);
2771
2772   applyToSet(pic16_dynAllocRegs,markRegFree);
2773   applyToSet(pic16_dynStackRegs,markRegFree);
2774 }
2775
2776 /*-----------------------------------------------------------------*/
2777 /*-----------------------------------------------------------------*/
2778 void
2779 pic16_deallocateAllRegs ()
2780 {
2781   debugLog ("%s\n", __FUNCTION__);
2782
2783   applyToSet(pic16_dynAllocRegs,pic16_deallocReg);
2784 }
2785
2786
2787 /*-----------------------------------------------------------------*/
2788 /* deallocStackSpil - this will set the stack pointer back         */
2789 /*-----------------------------------------------------------------*/
2790 static
2791 DEFSETFUNC (deallocStackSpil)
2792 {
2793   symbol *sym = item;
2794
2795   debugLog ("%s\n", __FUNCTION__);
2796   deallocLocal (sym);
2797   return 0;
2798 }
2799
2800 /*-----------------------------------------------------------------*/
2801 /* farSpacePackable - returns the packable icode for far variables */
2802 /*-----------------------------------------------------------------*/
2803 static iCode *
2804 farSpacePackable (iCode * ic)
2805 {
2806   iCode *dic;
2807
2808   debugLog ("%s\n", __FUNCTION__);
2809   /* go thru till we find a definition for the
2810      symbol on the right */
2811   for (dic = ic->prev; dic; dic = dic->prev)
2812     {
2813
2814       /* if the definition is a call then no */
2815       if ((dic->op == CALL || dic->op == PCALL) &&
2816           IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2817         {
2818           return NULL;
2819         }
2820
2821       /* if shift by unknown amount then not */
2822       if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
2823           IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2824         return NULL;
2825
2826       /* if pointer get and size > 1 */
2827       if (POINTER_GET (dic) &&
2828           getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
2829         return NULL;
2830
2831       if (POINTER_SET (dic) &&
2832           getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
2833         return NULL;
2834
2835       /* if any three is a true symbol in far space */
2836       if (IC_RESULT (dic) &&
2837           IS_TRUE_SYMOP (IC_RESULT (dic)) &&
2838           isOperandInFarSpace (IC_RESULT (dic)))
2839         return NULL;
2840
2841       if (IC_RIGHT (dic) &&
2842           IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
2843           isOperandInFarSpace (IC_RIGHT (dic)) &&
2844           !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
2845         return NULL;
2846
2847       if (IC_LEFT (dic) &&
2848           IS_TRUE_SYMOP (IC_LEFT (dic)) &&
2849           isOperandInFarSpace (IC_LEFT (dic)) &&
2850           !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
2851         return NULL;
2852
2853       if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
2854         {
2855           if ((dic->op == LEFT_OP ||
2856                dic->op == RIGHT_OP ||
2857                dic->op == '-') &&
2858               IS_OP_LITERAL (IC_RIGHT (dic)))
2859             return NULL;
2860           else
2861             return dic;
2862         }
2863     }
2864
2865   return NULL;
2866 }
2867
2868 /*-----------------------------------------------------------------*/
2869 /* packRegsForAssign - register reduction for assignment           */
2870 /*-----------------------------------------------------------------*/
2871 static int
2872 packRegsForAssign (iCode * ic, eBBlock * ebp)
2873 {
2874
2875   iCode *dic, *sic;
2876
2877   debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
2878   debugLog ("ic->op = %s\n", decodeOp( ic->op ) );
2879   debugAopGet ("  result:", IC_RESULT (ic));
2880   debugAopGet ("  left:", IC_LEFT (ic));
2881   debugAopGet ("  right:", IC_RIGHT (ic));
2882
2883 //      fprintf(stderr, "%s:%d symbol = %s\n", __FILE__, __LINE__, OP_SYMBOL( IC_RESULT(ic))->name);
2884
2885         debugLog(" %d - actuall processing\n", __LINE__ );
2886
2887   if (!IS_ITEMP (IC_RESULT (ic))) {
2888     pic16_allocDirReg(IC_RESULT (ic));
2889     debugLog ("  %d - result is not temp\n", __LINE__);
2890   }
2891
2892
2893 /* See BUGLOG0001 - VR */
2894 #if 1
2895   if (!IS_ITEMP (IC_RIGHT (ic))) {
2896     debugLog ("  %d - not packing - right is not temp\n", __LINE__);
2897     pic16_allocDirReg(IC_RIGHT (ic));
2898     return 0;
2899   }
2900 #endif
2901
2902   if (OP_SYMBOL (IC_RIGHT (ic))->isind ||
2903       OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
2904     {
2905       debugLog ("  %d - not packing - right side fails \n", __LINE__);
2906       return 0;
2907     }
2908
2909   /* if the true symbol is defined in far space or on stack
2910      then we should not since this will increase register pressure */
2911   if (isOperandInFarSpace (IC_RESULT (ic)))
2912     {
2913       if ((dic = farSpacePackable (ic)))
2914         goto pack;
2915       else
2916         return 0;
2917
2918     }
2919
2920   /* find the definition of iTempNN scanning backwards if we find a 
2921      a use of the true symbol before we find the definition then 
2922      we cannot pack */
2923   for (dic = ic->prev; dic; dic = dic->prev)
2924     {
2925
2926       /* if there is a function call and this is
2927          a parameter & not my parameter then don't pack it */
2928       if ((dic->op == CALL || dic->op == PCALL) &&
2929           (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
2930            !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
2931         {
2932           debugLog ("  %d - \n", __LINE__);
2933           dic = NULL;
2934           break;
2935         }
2936
2937
2938       if (SKIP_IC2 (dic))
2939         continue;
2940
2941         debugLog("%d\tSearching for iTempNN\n", __LINE__);
2942
2943       if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
2944           IS_OP_VOLATILE (IC_RESULT (dic)))
2945         {
2946           debugLog ("  %d - dic is VOLATILE \n", __LINE__);
2947           dic = NULL;
2948           break;
2949         }
2950
2951 #if 1
2952       if( IS_SYMOP( IC_RESULT(dic)) &&
2953         IS_BITFIELD( OP_SYMBOL(IC_RESULT(dic))->etype ) ) {
2954
2955           debugLog (" %d - result is bitfield\n", __LINE__);
2956           dic = NULL;
2957           break;
2958         }
2959 #endif
2960
2961       if (IS_SYMOP (IC_RESULT (dic)) &&
2962           IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2963         {
2964           /* A previous result was assigned to the same register - we'll our definition */
2965           debugLog ("  %d - dic result key == ic right key -- pointer set=%c\n",
2966                     __LINE__, ((POINTER_SET (dic)) ? 'Y' : 'N'));
2967           if (POINTER_SET (dic))
2968             dic = NULL;
2969
2970           break;
2971         }
2972
2973       if (IS_SYMOP (IC_RIGHT (dic)) &&
2974           (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
2975            IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
2976         {
2977           debugLog ("  %d - dic right key == ic rightor result key\n", __LINE__);
2978           dic = NULL;
2979           break;
2980         }
2981
2982       if (IS_SYMOP (IC_LEFT (dic)) &&
2983           (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
2984            IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
2985         {
2986           debugLog ("  %d - dic left key == ic rightor result key\n", __LINE__);
2987           dic = NULL;
2988           break;
2989         }
2990
2991       if (POINTER_SET (dic) &&
2992           IC_RESULT (dic)->key == IC_RESULT (ic)->key)
2993         {
2994           debugLog ("  %d - dic result key == ic result key -- pointer set=Y\n",
2995                     __LINE__);
2996           dic = NULL;
2997           break;
2998         }
2999     }
3000
3001   if (!dic)
3002     return 0;                   /* did not find */
3003
3004 #if 1
3005         /* This code is taken from the hc08 port. Do not know
3006          * if it fits for pic16, but I leave it here just in case */
3007
3008         /* if assignment then check that right is not a bit */
3009         if (ASSIGNMENT (dic) && !POINTER_SET (dic)) {
3010           sym_link *etype = operandType (IC_RIGHT (dic));
3011
3012                 if (IS_BITFIELD (etype)) {
3013                         /* if result is a bit too then it's ok */
3014                         etype = operandType (IC_RESULT (dic));
3015                         if (!IS_BITFIELD (etype)) {
3016                                 debugLog(" %d bitfields\n");
3017                           return 0;
3018                         }
3019                 }
3020         }
3021 #endif
3022
3023   /* if the result is on stack or iaccess then it must be
3024      the same atleast one of the operands */
3025   if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
3026       OP_SYMBOL (IC_RESULT (ic))->iaccess)
3027     {
3028       /* the operation has only one symbol
3029          operator then we can pack */
3030       if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
3031           (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
3032         goto pack;
3033
3034       if (!((IC_LEFT (dic) &&
3035              IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
3036             (IC_RIGHT (dic) &&
3037              IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
3038         return 0;
3039     }
3040 pack:
3041   debugLog ("  packing. removing %s\n", OP_SYMBOL (IC_RIGHT (ic))->rname);
3042   debugLog ("  replacing with %s\n", OP_SYMBOL (IC_RESULT (dic))->rname);
3043   /* found the definition */
3044   /* replace the result with the result of */
3045   /* this assignment and remove this assignment */
3046   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3047   IC_RESULT (dic) = IC_RESULT (ic);
3048
3049   if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
3050     {
3051       OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
3052     }
3053   /* delete from liverange table also 
3054      delete from all the points inbetween and the new
3055      one */
3056   for (sic = dic; sic != ic; sic = sic->next)
3057     {
3058       bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
3059       if (IS_ITEMP (IC_RESULT (dic)))
3060         bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
3061     }
3062
3063   remiCodeFromeBBlock (ebp, ic);
3064   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
3065
3066         debugLog("  %d\n", __LINE__ );
3067   hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
3068   OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
3069   return 1;
3070
3071
3072 }
3073
3074 #if 1
3075
3076 #define NO_packRegsForAccUse
3077 #define NO_packRegsForSupport
3078 #define NO_packRegsForOneuse
3079 #define NO_cast_peep
3080
3081 #endif
3082
3083
3084 #ifndef NO_packRegsForSupport
3085 /*-----------------------------------------------------------------*/
3086 /* findAssignToSym : scanning backwards looks for first assig found */
3087 /*-----------------------------------------------------------------*/
3088 static iCode *
3089 findAssignToSym (operand * op, iCode * ic)
3090 {
3091   iCode *dic;
3092
3093   debugLog ("%s\n", __FUNCTION__);
3094   for (dic = ic->prev; dic; dic = dic->prev)
3095     {
3096
3097       /* if definition by assignment */
3098       if (dic->op == '=' &&
3099           !POINTER_SET (dic) &&
3100           IC_RESULT (dic)->key == op->key
3101 /*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
3102         )
3103         {
3104
3105           /* we are interested only if defined in far space */
3106           /* or in stack space in case of + & - */
3107
3108           /* if assigned to a non-symbol then return
3109              true */
3110           if (!IS_SYMOP (IC_RIGHT (dic)))
3111             break;
3112
3113           /* if the symbol is in far space then
3114              we should not */
3115           if (isOperandInFarSpace (IC_RIGHT (dic)))
3116             return NULL;
3117
3118           /* for + & - operations make sure that
3119              if it is on the stack it is the same
3120              as one of the three operands */
3121           if ((ic->op == '+' || ic->op == '-') &&
3122               OP_SYMBOL (IC_RIGHT (dic))->onStack)
3123             {
3124               if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
3125                   IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
3126                   IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
3127                 return NULL;
3128             }
3129
3130           break;
3131
3132         }
3133
3134       /* if we find an usage then we cannot delete it */
3135       if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
3136         return NULL;
3137
3138       if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
3139         return NULL;
3140
3141       if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
3142         return NULL;
3143     }
3144
3145   /* now make sure that the right side of dic
3146      is not defined between ic & dic */
3147   if (dic)
3148     {
3149       iCode *sic = dic->next;
3150
3151       for (; sic != ic; sic = sic->next)
3152         if (IC_RESULT (sic) &&
3153             IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
3154           return NULL;
3155     }
3156
3157   return dic;
3158
3159
3160 }
3161 #endif
3162
3163
3164 #ifndef NO_packRegsForSupport
3165 /*-----------------------------------------------------------------*/
3166 /* packRegsForSupport :- reduce some registers for support calls   */
3167 /*-----------------------------------------------------------------*/
3168 static int
3169 packRegsForSupport (iCode * ic, eBBlock * ebp)
3170 {
3171   int change = 0;
3172
3173   debugLog ("%s\n", __FUNCTION__);
3174   /* for the left & right operand :- look to see if the
3175      left was assigned a true symbol in far space in that
3176      case replace them */
3177   if (IS_ITEMP (IC_LEFT (ic)) &&
3178       OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
3179     {
3180       iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
3181       iCode *sic;
3182
3183       if (!dic)
3184         goto right;
3185
3186       debugAopGet ("removing left:", IC_LEFT (ic));
3187
3188       /* found it we need to remove it from the
3189          block */
3190       for (sic = dic; sic != ic; sic = sic->next)
3191         bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
3192
3193       IC_LEFT (ic)->operand.symOperand =
3194         IC_RIGHT (dic)->operand.symOperand;
3195       IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3196       remiCodeFromeBBlock (ebp, dic);
3197       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3198       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3199       change++;
3200     }
3201
3202   /* do the same for the right operand */
3203 right:
3204   if (!change &&
3205       IS_ITEMP (IC_RIGHT (ic)) &&
3206       OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
3207     {
3208       iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
3209       iCode *sic;
3210
3211       if (!dic)
3212         return change;
3213
3214       /* if this is a subtraction & the result
3215          is a true symbol in far space then don't pack */
3216       if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
3217         {
3218           sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
3219           if (IN_FARSPACE (SPEC_OCLS (etype)))
3220             return change;
3221         }
3222
3223       debugAopGet ("removing right:", IC_RIGHT (ic));
3224
3225       /* found it we need to remove it from the
3226          block */
3227       for (sic = dic; sic != ic; sic = sic->next)
3228         bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
3229
3230       IC_RIGHT (ic)->operand.symOperand =
3231         IC_RIGHT (dic)->operand.symOperand;
3232       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3233
3234       remiCodeFromeBBlock (ebp, dic);
3235       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3236       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3237       change++;
3238     }
3239
3240   return change;
3241 }
3242 #endif
3243
3244
3245 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
3246
3247 #ifndef NO_packRegsForOneuse
3248 /*-----------------------------------------------------------------*/
3249 /* packRegsForOneuse : - will reduce some registers for single Use */
3250 /*-----------------------------------------------------------------*/
3251 static iCode *
3252 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
3253 {
3254   bitVect *uses;
3255   iCode *dic, *sic;
3256
3257   debugLog ("%s\n", __FUNCTION__);
3258   /* if returning a literal then do nothing */
3259   if (!IS_SYMOP (op))
3260     return NULL;
3261
3262   /* only upto 2 bytes since we cannot predict
3263      the usage of b, & acc */
3264   if (getSize (operandType (op)) > (pic16_fReturnSizePic - 3) &&        /* was 2, changed to 3 -- VR */
3265       ic->op != RETURN &&
3266       ic->op != SEND)
3267     return NULL;
3268
3269   /* this routine will mark the a symbol as used in one 
3270      instruction use only && if the definition is local 
3271      (ie. within the basic block) && has only one definition &&
3272      that definition is either a return value from a 
3273      function or does not contain any variables in
3274      far space */
3275   uses = bitVectCopy (OP_USES (op));
3276   bitVectUnSetBit (uses, ic->key);      /* take away this iCode */
3277   if (!bitVectIsZero (uses))    /* has other uses */
3278     return NULL;
3279
3280   /* if it has only one defintion */
3281   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
3282     return NULL;                /* has more than one definition */
3283
3284   /* get that definition */
3285   if (!(dic =
3286         hTabItemWithKey (iCodehTab,
3287                          bitVectFirstBit (OP_DEFS (op)))))
3288     return NULL;
3289
3290   /* found the definition now check if it is local */
3291   if (dic->seq < ebp->fSeq ||
3292       dic->seq > ebp->lSeq)
3293     return NULL;                /* non-local */
3294
3295   /* now check if it is the return from
3296      a function call */
3297   if (dic->op == CALL || dic->op == PCALL)
3298     {
3299       if (ic->op != SEND && ic->op != RETURN &&
3300           !POINTER_SET(ic) && !POINTER_GET(ic))
3301         {
3302           OP_SYMBOL (op)->ruonly = 1;
3303           return dic;
3304         }
3305       dic = dic->next;
3306     }
3307
3308
3309   /* otherwise check that the definition does
3310      not contain any symbols in far space */
3311   if (isOperandInFarSpace (IC_LEFT (dic)) ||
3312       isOperandInFarSpace (IC_RIGHT (dic)) ||
3313       IS_OP_RUONLY (IC_LEFT (ic)) ||
3314       IS_OP_RUONLY (IC_RIGHT (ic)))
3315     {
3316       return NULL;
3317     }
3318
3319   /* if pointer set then make sure the pointer
3320      is one byte */
3321   if (POINTER_SET (dic) &&
3322       !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3323     return NULL;
3324
3325   if (POINTER_GET (dic) &&
3326       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3327     return NULL;
3328
3329   sic = dic;
3330
3331   /* also make sure the intervenening instructions
3332      don't have any thing in far space */
3333   for (dic = dic->next; dic && dic != ic; dic = dic->next)
3334     {
3335
3336       /* if there is an intervening function call then no */
3337       if (dic->op == CALL || dic->op == PCALL)
3338         return NULL;
3339       /* if pointer set then make sure the pointer
3340          is one byte */
3341       if (POINTER_SET (dic) &&
3342           !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3343         return NULL;
3344
3345       if (POINTER_GET (dic) &&
3346           !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3347         return NULL;
3348
3349       /* if address of & the result is remat then okay */
3350       if (dic->op == ADDRESS_OF &&
3351           OP_SYMBOL (IC_RESULT (dic))->remat)
3352         continue;
3353
3354       /* if operand has size of three or more & this
3355          operation is a '*','/' or '%' then 'b' may
3356          cause a problem */
3357       if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
3358           getSize (operandType (op)) >= 3)
3359         return NULL;
3360
3361       /* if left or right or result is in far space */
3362       if (isOperandInFarSpace (IC_LEFT (dic)) ||
3363           isOperandInFarSpace (IC_RIGHT (dic)) ||
3364           isOperandInFarSpace (IC_RESULT (dic)) ||
3365           IS_OP_RUONLY (IC_LEFT (dic)) ||
3366           IS_OP_RUONLY (IC_RIGHT (dic)) ||
3367           IS_OP_RUONLY (IC_RESULT (dic)))
3368         {
3369           return NULL;
3370         }
3371     }
3372
3373   OP_SYMBOL (op)->ruonly = 1;
3374   return sic;
3375
3376 }
3377 #endif
3378
3379
3380 /*-----------------------------------------------------------------*/
3381 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
3382 /*-----------------------------------------------------------------*/
3383 static bool
3384 isBitwiseOptimizable (iCode * ic)
3385 {
3386   sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
3387   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
3388
3389   debugLog ("%s\n", __FUNCTION__);
3390   /* bitwise operations are considered optimizable
3391      under the following conditions (Jean-Louis VERN) 
3392
3393      x & lit
3394      bit & bit
3395      bit & x
3396      bit ^ bit
3397      bit ^ x
3398      x   ^ lit
3399      x   | lit
3400      bit | bit
3401      bit | x
3402    */
3403   if (IS_LITERAL (rtype) ||
3404       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
3405     return TRUE;
3406   else
3407     return FALSE;
3408 }
3409
3410
3411 #ifndef NO_packRegsForAccUse
3412
3413 /*-----------------------------------------------------------------*/
3414 /* packRegsForAccUse - pack registers for acc use                  */
3415 /*-----------------------------------------------------------------*/
3416 static void
3417 packRegsForAccUse (iCode * ic)
3418 {
3419   iCode *uic;
3420
3421   debugLog ("%s\n", __FUNCTION__);
3422
3423   /* if this is an aggregate, e.g. a one byte char array */
3424   if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
3425     return;
3426   }
3427   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3428
3429   /* if + or - then it has to be one byte result */
3430   if ((ic->op == '+' || ic->op == '-')
3431       && getSize (operandType (IC_RESULT (ic))) > 1)
3432     return;
3433
3434   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3435   /* if shift operation make sure right side is not a literal */
3436   if (ic->op == RIGHT_OP &&
3437       (isOperandLiteral (IC_RIGHT (ic)) ||
3438        getSize (operandType (IC_RESULT (ic))) > 1))
3439     return;
3440
3441   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3442   if (ic->op == LEFT_OP &&
3443       (isOperandLiteral (IC_RIGHT (ic)) ||
3444        getSize (operandType (IC_RESULT (ic))) > 1))
3445     return;
3446
3447   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3448   if (IS_BITWISE_OP (ic) &&
3449       getSize (operandType (IC_RESULT (ic))) > 1)
3450     return;
3451
3452
3453   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3454   /* has only one definition */
3455   if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
3456     return;
3457
3458   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3459   /* has only one use */
3460   if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
3461     return;
3462
3463   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3464   /* and the usage immediately follows this iCode */
3465   if (!(uic = hTabItemWithKey (iCodehTab,
3466                                bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
3467     return;
3468
3469   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3470   if (ic->next != uic)
3471     return;
3472
3473   /* if it is a conditional branch then we definitely can */
3474   if (uic->op == IFX)
3475     goto accuse;
3476
3477   if (uic->op == JUMPTABLE)
3478     return;
3479
3480   /* if the usage is not is an assignment
3481      or an arithmetic / bitwise / shift operation then not */
3482   if (POINTER_SET (uic) &&
3483       getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
3484     return;
3485
3486   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3487   if (uic->op != '=' &&
3488       !IS_ARITHMETIC_OP (uic) &&
3489       !IS_BITWISE_OP (uic) &&
3490       uic->op != LEFT_OP &&
3491       uic->op != RIGHT_OP)
3492     return;
3493
3494   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3495   /* if used in ^ operation then make sure right is not a 
3496      literl */
3497   if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
3498     return;
3499
3500   /* if shift operation make sure right side is not a literal */
3501   if (uic->op == RIGHT_OP &&
3502       (isOperandLiteral (IC_RIGHT (uic)) ||
3503        getSize (operandType (IC_RESULT (uic))) > 1))
3504     return;
3505
3506   if (uic->op == LEFT_OP &&
3507       (isOperandLiteral (IC_RIGHT (uic)) ||
3508        getSize (operandType (IC_RESULT (uic))) > 1))
3509     return;
3510
3511   /* make sure that the result of this icode is not on the
3512      stack, since acc is used to compute stack offset */
3513   if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
3514       OP_SYMBOL (IC_RESULT (uic))->onStack)
3515     return;
3516
3517   /* if either one of them in far space then we cannot */
3518   if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3519        isOperandInFarSpace (IC_LEFT (uic))) ||
3520       (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3521        isOperandInFarSpace (IC_RIGHT (uic))))
3522     return;
3523
3524   /* if the usage has only one operand then we can */
3525   if (IC_LEFT (uic) == NULL ||
3526       IC_RIGHT (uic) == NULL)
3527     goto accuse;
3528
3529   /* make sure this is on the left side if not
3530      a '+' since '+' is commutative */
3531   if (ic->op != '+' &&
3532       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
3533     return;
3534
3535 #if 1
3536   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3537   /* if one of them is a literal then we can */
3538   if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
3539         (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))  &&
3540        (getSize (operandType (IC_RESULT (uic))) <= 1))
3541     {
3542       OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3543       return;
3544     }
3545 #endif
3546
3547   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3548   /* if the other one is not on stack then we can */
3549   if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
3550       (IS_ITEMP (IC_RIGHT (uic)) ||
3551        (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3552         !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
3553     goto accuse;
3554
3555   if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
3556       (IS_ITEMP (IC_LEFT (uic)) ||
3557        (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3558         !OP_SYMBOL (IC_LEFT (uic))->onStack)))
3559     goto accuse;
3560
3561   return;
3562
3563 accuse:
3564   debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
3565   OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3566
3567
3568 }
3569 #endif
3570
3571
3572 /*-----------------------------------------------------------------*/
3573 /* packForPush - hueristics to reduce iCode for pushing            */
3574 /*-----------------------------------------------------------------*/
3575 static void
3576 packForReceive (iCode * ic, eBBlock * ebp)
3577 {
3578   iCode *dic;
3579
3580   debugLog ("%s\n", __FUNCTION__);
3581   debugAopGet ("  result:", IC_RESULT (ic));
3582   debugAopGet ("  left:", IC_LEFT (ic));
3583   debugAopGet ("  right:", IC_RIGHT (ic));
3584
3585   if (!ic->next)
3586     return;
3587
3588   for (dic = ic->next; dic; dic = dic->next)
3589     {
3590
3591
3592
3593       if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
3594         debugLog ("    used on left\n");
3595       if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
3596         debugLog ("    used on right\n");
3597       if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
3598         debugLog ("    used on result\n");
3599
3600       if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
3601           (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
3602         return;
3603
3604     }
3605
3606   debugLog ("  hey we can remove this unnecessary assign\n");
3607 }
3608 /*-----------------------------------------------------------------*/
3609 /* packForPush - hueristics to reduce iCode for pushing            */
3610 /*-----------------------------------------------------------------*/
3611 static void
3612 packForPush (iCode * ic, eBBlock * ebp)
3613 {
3614   iCode *dic;
3615
3616   debugLog ("%s\n", __FUNCTION__);
3617   if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
3618     return;
3619
3620   /* must have only definition & one usage */
3621   if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
3622       bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
3623     return;
3624
3625   /* find the definition */
3626   if (!(dic = hTabItemWithKey (iCodehTab,
3627                                bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
3628     return;
3629
3630   if (dic->op != '=' || POINTER_SET (dic))
3631     return;
3632
3633   /* we now we know that it has one & only one def & use
3634      and the that the definition is an assignment */
3635   IC_LEFT (ic) = IC_RIGHT (dic);
3636
3637   remiCodeFromeBBlock (ebp, dic);
3638   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3639   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3640 }
3641
3642 static void printSymType(char * str, sym_link *sl)
3643 {
3644         if(!pic16_ralloc_debug)return;
3645         
3646         debugLog ("    %s Symbol type: ",str);
3647         printTypeChain( sl, debugF);
3648         debugLog ("\n");
3649 }
3650
3651 /*-----------------------------------------------------------------*/
3652 /* some debug code to print the symbol S_TYPE. Note that
3653  * the function checkSClass in src/SDCCsymt.c dinks with
3654  * the S_TYPE in ways the PIC port doesn't fully like...*/
3655 /*-----------------------------------------------------------------*/
3656 static void isData(sym_link *sl)
3657 {
3658   FILE *of = stderr;
3659
3660         if(!pic16_ralloc_debug)return;
3661         
3662         if(!sl)return;
3663
3664         if(debugF)
3665                 of = debugF;
3666
3667         for ( ; sl; sl=sl->next) {
3668                 if(!IS_DECL(sl) ) {
3669                         switch (SPEC_SCLS(sl)) {
3670                                 case S_DATA: fprintf (of, "data "); break;
3671                                 case S_XDATA: fprintf (of, "xdata "); break;
3672                                 case S_SFR: fprintf (of, "sfr "); break;
3673                                 case S_SBIT: fprintf (of, "sbit "); break;
3674                                 case S_CODE: fprintf (of, "code "); break;
3675                                 case S_IDATA: fprintf (of, "idata "); break;
3676                                 case S_PDATA: fprintf (of, "pdata "); break;
3677                                 case S_LITERAL: fprintf (of, "literal "); break;
3678                                 case S_STACK: fprintf (of, "stack "); break;
3679                                 case S_XSTACK: fprintf (of, "xstack "); break;
3680                                 case S_BIT: fprintf (of, "bit "); break;
3681                                 case S_EEPROM: fprintf (of, "eeprom "); break;
3682                                 default: break;
3683                         }
3684
3685                 }
3686         }
3687 }
3688
3689
3690 /*--------------------------------------------------------------------*/
3691 /* pic16_packRegisters - does some transformations to reduce          */
3692 /*                   register pressure                                */
3693 /*                                                                    */
3694 /*--------------------------------------------------------------------*/
3695 static void
3696 pic16_packRegisters (eBBlock * ebp)
3697 {
3698   iCode *ic;
3699   int change = 0;
3700
3701   debugLog ("%s\n", __FUNCTION__);
3702
3703   while (1) {
3704
3705     change = 0;
3706
3707     /* look for assignments of the form */
3708     /* iTempNN = TRueSym (someoperation) SomeOperand */
3709     /*       ....                       */
3710     /* TrueSym := iTempNN:1             */
3711     for (ic = ebp->sch; ic; ic = ic->next)
3712       {
3713 //              debugLog("%d\n", __LINE__);
3714         /* find assignment of the form TrueSym := iTempNN:1 */
3715         /* see BUGLOG0001 for workaround with the CAST - VR */
3716 //      if ( (ic->op == '=' || ic->op == CAST) && !POINTER_SET (ic) ) // patch 11
3717         if ( (ic->op == '=') && !POINTER_SET (ic) ) // patch 11
3718           change += packRegsForAssign (ic, ebp);
3719         /* debug stuff */
3720         if (ic->op == '=')
3721           {
3722             if (POINTER_SET (ic))
3723               debugLog ("pointer is set\n");
3724             debugAopGet ("  result:", IC_RESULT (ic));
3725             debugAopGet ("  left:", IC_LEFT (ic));
3726             debugAopGet ("  right:", IC_RIGHT (ic));
3727           }
3728
3729       }
3730
3731     if (!change)
3732       break;
3733   }
3734
3735   for (ic = ebp->sch; ic; ic = ic->next) {
3736
3737     if(IS_SYMOP ( IC_LEFT(ic))) {
3738       sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
3739
3740       debugAopGet ("x  left:", IC_LEFT (ic));
3741 #if 0
3742       if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
3743 #else
3744       if(IS_CODEPTR(OP_SYMBOL(IC_LEFT(ic))->type))
3745 #endif
3746         debugLog ("    is a pointer\n");
3747
3748       if(IS_PTR(OP_SYMBOL(IC_LEFT(ic))->type))
3749         debugLog ("    is a ptr\n");
3750
3751       if(IS_OP_VOLATILE(IC_LEFT(ic)))
3752         debugLog ("    is volatile\n");
3753
3754       isData(etype);
3755
3756         if(IS_OP_VOLATILE(IC_LEFT(ic))) {
3757             debugLog ("  %d - left is not temp, allocating\n", __LINE__);
3758             pic16_allocDirReg(IC_LEFT (ic));
3759         }
3760
3761       printSymType("c  ", OP_SYMBOL(IC_LEFT(ic))->type);
3762     }
3763
3764     if(IS_SYMOP ( IC_RIGHT(ic))) {
3765       debugAopGet ("  right:", IC_RIGHT (ic));
3766       printSymType("    ", OP_SYMBOL(IC_RIGHT(ic))->type);
3767     }
3768
3769     if(IS_SYMOP ( IC_RESULT(ic))) {
3770       debugAopGet ("  result:", IC_RESULT (ic));
3771       printSymType("     ", OP_SYMBOL(IC_RESULT(ic))->type);
3772     }
3773
3774     if(IS_TRUE_SYMOP ( IC_RIGHT(ic))) {
3775       debugAopGet ("  right:", IC_RIGHT (ic));
3776       printSymType("    ", OP_SYMBOL(IC_RIGHT(ic))->type);
3777 //      pic16_allocDirReg(IC_RIGHT(ic));
3778     }
3779
3780     if(IS_TRUE_SYMOP ( IC_RESULT(ic))) {
3781       debugAopGet ("  result:", IC_RESULT (ic));
3782       printSymType("     ", OP_SYMBOL(IC_RESULT(ic))->type);
3783 //      pic16_allocDirReg(IC_RESULT(ic));
3784     }
3785
3786
3787     if (POINTER_SET (ic))
3788         debugLog ("  %d - Pointer set\n", __LINE__);
3789
3790
3791     /* if this is an itemp & result of a address of a true sym 
3792        then mark this as rematerialisable   */
3793     if (ic->op == ADDRESS_OF &&
3794         IS_ITEMP (IC_RESULT (ic)) &&
3795         IS_TRUE_SYMOP (IC_LEFT (ic)) &&
3796         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
3797         !OP_SYMBOL (IC_LEFT (ic))->onStack)
3798       {
3799
3800         debugLog ("  %d - %s. result is rematerializable\n", __LINE__,__FUNCTION__);
3801
3802         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
3803         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
3804         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
3805
3806       }
3807
3808     /* if straight assignment then carry remat flag if
3809        this is the only definition */
3810     if (ic->op == '=' &&
3811         !POINTER_SET (ic) &&
3812         IS_SYMOP (IC_RIGHT (ic)) &&
3813         OP_SYMBOL (IC_RIGHT (ic))->remat &&
3814         bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
3815       {
3816         debugLog ("  %d - %s. straight rematerializable\n", __LINE__,__FUNCTION__);
3817
3818         OP_SYMBOL (IC_RESULT (ic))->remat =
3819           OP_SYMBOL (IC_RIGHT (ic))->remat;
3820         OP_SYMBOL (IC_RESULT (ic))->rematiCode =
3821           OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
3822       }
3823
3824     /* if this is a +/- operation with a rematerizable 
3825        then mark this as rematerializable as well */
3826     if ((ic->op == '+' || ic->op == '-') &&
3827         (IS_SYMOP (IC_LEFT (ic)) &&
3828          IS_ITEMP (IC_RESULT (ic)) &&
3829          OP_SYMBOL (IC_LEFT (ic))->remat &&
3830          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
3831          IS_OP_LITERAL (IC_RIGHT (ic))))
3832       {
3833         debugLog ("  %d - %s. rematerializable because op is +/-\n", __LINE__,__FUNCTION__);
3834         //int i = 
3835         operandLitValue (IC_RIGHT (ic));
3836         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
3837         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
3838         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
3839       }
3840
3841     /* mark the pointer usages */
3842     if (POINTER_SET (ic))
3843       {
3844         OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
3845         debugLog ("  marking as a pointer (set) =>");
3846         debugAopGet ("  result:", IC_RESULT (ic));
3847       }
3848     if (POINTER_GET (ic))
3849       {
3850         OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
3851         debugLog ("  marking as a pointer (get) =>");
3852         debugAopGet ("  left:", IC_LEFT (ic));
3853       }
3854
3855         //debugLog("  %d   %s\n", __LINE__, __FUNCTION__);
3856
3857     if (!SKIP_IC2 (ic))
3858       {
3859         //debugLog("  %d   %s\n", __LINE__, __FUNCTION__ );
3860         /* if we are using a symbol on the stack
3861            then we should say pic16_ptrRegReq */
3862         if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
3863           pic16_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
3864                                OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
3865         else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
3866           pic16_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
3867                                OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
3868         else
3869           {
3870
3871                 //debugLog("   %d   %s\n", __LINE__, __FUNCTION__ );
3872             if (IS_SYMOP (IC_LEFT (ic)))
3873               pic16_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
3874                                    OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
3875             if (IS_SYMOP (IC_RIGHT (ic)))
3876               pic16_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
3877                                    OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
3878             if (IS_SYMOP (IC_RESULT (ic)))
3879               pic16_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
3880                                    OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
3881           }
3882
3883         debugLog ("  %d - pointer reg req = %d\n", __LINE__,pic16_ptrRegReq);
3884
3885       }
3886
3887     /* if the condition of an if instruction
3888        is defined in the previous instruction then
3889        mark the itemp as a conditional */
3890     if ((IS_CONDITIONAL (ic) ||
3891          ((ic->op == BITWISEAND ||
3892            ic->op == '|' ||
3893            ic->op == '^') &&
3894           isBitwiseOptimizable (ic))) &&
3895         ic->next && ic->next->op == IFX &&
3896         isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
3897         OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
3898       {
3899
3900         debugLog ("  %d\n", __LINE__);
3901         OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
3902         continue;
3903       }
3904
3905         debugLog(" %d\n", __LINE__);
3906
3907 #ifndef NO_packRegsForSupport
3908     /* reduce for support function calls */
3909     if (ic->supportRtn || ic->op == '+' || ic->op == '-')
3910       packRegsForSupport (ic, ebp);
3911 #endif
3912
3913     /* if a parameter is passed, it's in W, so we may not
3914        need to place a copy in a register */
3915     if (ic->op == RECEIVE)
3916       packForReceive (ic, ebp);
3917
3918 #ifndef NO_packRegsForOneuse
3919     /* some cases the redundant moves can
3920        can be eliminated for return statements */
3921     if ((ic->op == RETURN || ic->op == SEND) &&
3922         !isOperandInFarSpace (IC_LEFT (ic)) &&
3923         !options.model)
3924       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
3925 #endif
3926
3927 #ifndef NO_packRegsForOneuse
3928     /* if pointer set & left has a size more than
3929        one and right is not in far space */
3930     if (POINTER_SET (ic) &&
3931         !isOperandInFarSpace (IC_RIGHT (ic)) &&
3932         !OP_SYMBOL (IC_RESULT (ic))->remat &&
3933         !IS_OP_RUONLY (IC_RIGHT (ic)) &&
3934         getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
3935
3936       packRegsForOneuse (ic, IC_RESULT (ic), ebp);
3937 #endif
3938
3939 #ifndef NO_packRegsForOneuse
3940     /* if pointer get */
3941     if (POINTER_GET (ic) &&
3942         !isOperandInFarSpace (IC_RESULT (ic)) &&
3943         !OP_SYMBOL (IC_LEFT (ic))->remat &&
3944         !IS_OP_RUONLY (IC_RESULT (ic)) &&
3945         getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
3946
3947       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
3948       debugLog("%d - return from packRegsForOneuse\n", __LINE__);
3949 #endif
3950
3951 #ifndef NO_cast_peep
3952     /* if this is cast for intergral promotion then
3953        check if only use of  the definition of the 
3954        operand being casted/ if yes then replace
3955        the result of that arithmetic operation with 
3956        this result and get rid of the cast */
3957     if (ic->op == CAST) {
3958         
3959       sym_link *fromType = operandType (IC_RIGHT (ic));
3960       sym_link *toType = operandType (IC_LEFT (ic));
3961
3962       debugLog ("  %d - casting\n", __LINE__);
3963
3964       if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
3965           getSize (fromType) != getSize (toType)) {
3966             
3967
3968         iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
3969         if (dic) {
3970                 
3971           if (IS_ARITHMETIC_OP (dic)) {
3972                     debugLog("   %d   %s\n", __LINE__, __FUNCTION__ );
3973                     
3974             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3975             IC_RESULT (dic) = IC_RESULT (ic);
3976             remiCodeFromeBBlock (ebp, ic);
3977             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
3978             hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
3979             OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
3980             ic = ic->prev;
3981           }  else
3982                 
3983             OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
3984         }
3985       } else {
3986
3987         /* if the type from and type to are the same
3988            then if this is the only use then packit */
3989         if (compareType (operandType (IC_RIGHT (ic)),
3990                          operandType (IC_LEFT (ic))) == 1) {
3991                 
3992           iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
3993           if (dic) {
3994
3995                    debugLog(" %d\n", __LINE__);
3996
3997             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3998             IC_RESULT (dic) = IC_RESULT (ic);
3999             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
4000             remiCodeFromeBBlock (ebp, ic);
4001             hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
4002             OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
4003             ic = ic->prev;
4004           }
4005         }
4006       }
4007     }
4008 #endif
4009     /* pack for PUSH 
4010        iTempNN := (some variable in farspace) V1
4011        push iTempNN ;
4012        -------------
4013        push V1
4014     */
4015     if (ic->op == IPUSH)
4016       {
4017         packForPush (ic, ebp);
4018       }
4019
4020
4021 #ifndef NO_packRegsForAccUse
4022     /* pack registers for accumulator use, when the
4023        result of an arithmetic or bit wise operation
4024        has only one use, that use is immediately following
4025        the defintion and the using iCode has only one
4026        operand or has two operands but one is literal &
4027        the result of that operation is not on stack then
4028        we can leave the result of this operation in acc:b
4029        combination */
4030     if ((IS_ARITHMETIC_OP (ic)
4031
4032          || IS_BITWISE_OP (ic)
4033
4034          || ic->op == LEFT_OP || ic->op == RIGHT_OP
4035
4036          ) &&
4037         IS_ITEMP (IC_RESULT (ic)) &&
4038         getSize (operandType (IC_RESULT (ic))) <= 1)
4039
4040       packRegsForAccUse (ic);
4041 #endif
4042
4043   }
4044 }
4045
4046 static void
4047 dumpEbbsToDebug (eBBlock ** ebbs, int count)
4048 {
4049   int i;
4050
4051   if (!pic16_ralloc_debug || !debugF)
4052     return;
4053
4054   for (i = 0; i < count; i++)
4055     {
4056       fprintf (debugF, "\n----------------------------------------------------------------\n");
4057       fprintf (debugF, "Basic Block %s : loop Depth = %d noPath = %d , lastinLoop = %d\n",
4058                ebbs[i]->entryLabel->name,
4059                ebbs[i]->depth,
4060                ebbs[i]->noPath,
4061                ebbs[i]->isLastInLoop);
4062       fprintf (debugF, "depth 1st num %d : bbnum = %d 1st iCode = %d , last iCode = %d\n",
4063                ebbs[i]->dfnum,
4064                ebbs[i]->bbnum,
4065                ebbs[i]->fSeq,
4066                ebbs[i]->lSeq);
4067       fprintf (debugF, "visited %d : hasFcall = %d\n",
4068                ebbs[i]->visited,
4069                ebbs[i]->hasFcall);
4070
4071       fprintf (debugF, "\ndefines bitVector :");
4072       bitVectDebugOn (ebbs[i]->defSet, debugF);
4073       fprintf (debugF, "\nlocal defines bitVector :");
4074       bitVectDebugOn (ebbs[i]->ldefs, debugF);
4075       fprintf (debugF, "\npointers Set bitvector :");
4076       bitVectDebugOn (ebbs[i]->ptrsSet, debugF);
4077       fprintf (debugF, "\nin pointers Set bitvector :");
4078       bitVectDebugOn (ebbs[i]->inPtrsSet, debugF);
4079       fprintf (debugF, "\ninDefs Set bitvector :");
4080       bitVectDebugOn (ebbs[i]->inDefs, debugF);
4081       fprintf (debugF, "\noutDefs Set bitvector :");
4082       bitVectDebugOn (ebbs[i]->outDefs, debugF);
4083       fprintf (debugF, "\nusesDefs Set bitvector :");
4084       bitVectDebugOn (ebbs[i]->usesDefs, debugF);
4085       fprintf (debugF, "\n----------------------------------------------------------------\n");
4086       printiCChain (ebbs[i]->sch, debugF);
4087     }
4088 }
4089 /*-----------------------------------------------------------------*/
4090 /* pic16_assignRegisters - assigns registers to each live range as need  */
4091 /*-----------------------------------------------------------------*/
4092 void
4093 pic16_assignRegisters (eBBlock ** ebbs, int count)
4094 {
4095   iCode *ic;
4096   int i;
4097
4098   debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s", __FILE__, __FUNCTION__);
4099   debugLog ("\nebbs before optimizing:\n");
4100   dumpEbbsToDebug (ebbs, count);
4101
4102   setToNull ((void *) &_G.funcrUsed);
4103   pic16_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
4104
4105
4106   /* change assignments this will remove some
4107      live ranges reducing some register pressure */
4108   for (i = 0; i < count; i++)
4109     pic16_packRegisters (ebbs[i]);
4110
4111   {
4112     regs *reg;
4113     int hkey;
4114     int i=0;
4115
4116     debugLog("dir registers allocated so far:\n");
4117     reg = hTabFirstItem(dynDirectRegNames, &hkey);
4118
4119     while(reg) {
4120       debugLog("  -- #%d reg = %s  key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4121 //      fprintf(stderr, "  -- #%d reg = %s  key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4122       reg = hTabNextItem(dynDirectRegNames, &hkey);
4123     }
4124
4125   }
4126
4127   /* liveranges probably changed by register packing
4128      so we compute them again */
4129   recomputeLiveRanges (ebbs, count);
4130
4131   if (options.dump_pack)
4132     dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
4133
4134   /* first determine for each live range the number of 
4135      registers & the type of registers required for each */
4136   regTypeNum ();
4137
4138   /* and serially allocate registers */
4139   serialRegAssign (ebbs, count);
4140
4141 //  debugLog ("ebbs after serialRegAssign:\n");
4142 //  dumpEbbsToDebug (ebbs, count);
4143
4144
4145   //pic16_freeAllRegs();
4146
4147   /* if stack was extended then tell the user */
4148   if (_G.stackExtend)
4149     {
4150 /*      werror(W_TOOMANY_SPILS,"stack", */
4151 /*             _G.stackExtend,currFunc->name,""); */
4152       _G.stackExtend = 0;
4153     }
4154
4155   if (_G.dataExtend)
4156     {
4157 /*      werror(W_TOOMANY_SPILS,"data space", */
4158 /*             _G.dataExtend,currFunc->name,""); */
4159       _G.dataExtend = 0;
4160     }
4161
4162   /* after that create the register mask
4163      for each of the instruction */
4164   createRegMask (ebbs, count);
4165
4166   /* redo that offsets for stacked automatic variables */
4167   redoStackOffsets ();
4168
4169   if (options.dump_rassgn)
4170     dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
4171
4172   /* now get back the chain */
4173   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
4174
4175   debugLog ("ebbs after optimizing:\n");
4176   dumpEbbsToDebug (ebbs, count);
4177
4178
4179   genpic16Code (ic);
4180
4181   /* free up any _G.stackSpil locations allocated */
4182   applyToSet (_G.stackSpil, deallocStackSpil);
4183   _G.slocNum = 0;
4184   setToNull ((void *) &_G.stackSpil);
4185   setToNull ((void *) &_G.spiltSet);
4186   /* mark all registers as free */
4187   pic16_freeAllRegs ();
4188
4189   debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
4190   debugLogClose ();
4191   return;
4192 }