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