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