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