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