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