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