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