* src/pic16/glue.c,
[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 extern void pic16_assignConfigWordValue(int address, int value);
52
53 /* Global data */
54 static struct
55   {
56     bitVect *spiltSet;
57     set *stackSpil;
58     bitVect *regAssigned;
59     short blockSpil;
60     int slocNum;
61     bitVect *funcrUsed;         /* registers used in a function */
62     int stackExtend;
63     int dataExtend;
64   }
65 _G;
66
67 /* Shared with gen.c */
68 int pic16_ptrRegReq;            /* one byte pointer register required */
69
70
71 set *pic16_dynAllocRegs=NULL;
72 set *pic16_dynStackRegs=NULL;
73 set *pic16_dynProcessorRegs=NULL;
74 set *pic16_dynDirectRegs=NULL;
75 set *pic16_dynDirectBitRegs=NULL;
76 set *pic16_dynInternalRegs=NULL;
77
78 static hTab  *dynDirectRegNames= NULL;
79 //static hTab  *regHash = NULL;    /* a hash table containing ALL registers */
80
81 set *pic16_rel_udata=NULL;      /* relocatable uninitialized registers */
82 set *pic16_fix_udata=NULL;      /* absolute uninitialized registers */
83 set *pic16_equ_data=NULL;       /* registers used by equates */
84 set *pic16_int_regs=NULL;       /* internal registers placed in access bank 0 to 0x7f */
85
86 set *pic16_builtin_functions=NULL;
87
88 static int dynrIdx=0x10;                //0x20;         // starting temporary register rIdx
89 static int rDirectIdx=0;
90
91 int pic16_nRegs = 128;   // = sizeof (regspic16) / sizeof (regs);
92
93 int pic16_Gstack_base_addr=0; /* The starting address of registers that
94                          * are used to pass and return parameters */
95
96
97
98
99 static void spillThis (symbol *);
100 int pic16_ralloc_debug = 0;
101 static FILE *debugF = NULL;
102 /*-----------------------------------------------------------------*/
103 /* debugLog - open a file for debugging information                */
104 /*-----------------------------------------------------------------*/
105 //static void debugLog(char *inst,char *fmt, ...)
106 static void
107 debugLog (char *fmt,...)
108 {
109   static int append = 0;        // First time through, open the file without append.
110
111   char buffer[256];
112   //char *bufferP=buffer;
113   va_list ap;
114
115   if (!pic16_ralloc_debug || !dstFileName)
116     return;
117
118
119   if (!debugF)
120     {
121       /* create the file name */
122       strcpy (buffer, dstFileName);
123       strcat (buffer, ".d");
124
125       if (!(debugF = fopen (buffer, (append ? "a+" : "w"))))
126         {
127           werror (E_FILE_OPEN_ERR, buffer);
128           exit (1);
129         }
130       append = 1;               // Next time debubLog is called, we'll append the debug info
131
132     }
133
134   va_start (ap, fmt);
135
136   vsprintf (buffer, fmt, ap);
137
138   fprintf (debugF, "%s", buffer);
139 /*
140    while (isspace(*bufferP)) bufferP++;
141
142    if (bufferP && *bufferP) 
143    lineCurr = (lineCurr ?
144    connectLine(lineCurr,newLineNode(lb)) :
145    (lineHead = newLineNode(lb)));
146    lineCurr->isInline = _G.inLine;
147    lineCurr->isDebug  = _G.debugLine;
148  */
149   va_end (ap);
150
151 }
152
153 static void
154 debugNewLine (void)
155 {
156         if(!pic16_ralloc_debug)return;
157         
158         if (debugF)
159                 fputc ('\n', debugF);
160 }
161 /*-----------------------------------------------------------------*/
162 /* debugLogClose - closes the debug log file (if opened)           */
163 /*-----------------------------------------------------------------*/
164 static void
165 debugLogClose (void)
166 {
167         if (debugF) {
168                 fclose (debugF);
169                 debugF = NULL;
170         }
171 }
172
173 #define AOP(op) op->aop
174
175 static char *
176 debugAopGet (char *str, operand * op)
177 {
178         if(!pic16_ralloc_debug)return NULL;
179
180         if (str)
181                 debugLog (str);
182
183         printOperand (op, debugF);
184         debugNewLine ();
185
186   return NULL;
187 }
188
189 static char *
190 decodeOp (unsigned int op)
191 {
192         if (op < 128 && op > ' ') {
193                 buffer[0] = (op & 0xff);
194                 buffer[1] = 0;
195           return buffer;
196         }
197
198         switch (op) {
199                 case IDENTIFIER:        return "IDENTIFIER";
200                 case TYPE_NAME:         return "TYPE_NAME";
201                 case CONSTANT:          return "CONSTANT";
202                 case STRING_LITERAL:    return "STRING_LITERAL";
203                 case SIZEOF:            return "SIZEOF";
204                 case PTR_OP:            return "PTR_OP";
205                 case INC_OP:            return "INC_OP";
206                 case DEC_OP:            return "DEC_OP";
207                 case LEFT_OP:           return "LEFT_OP";
208                 case RIGHT_OP:          return "RIGHT_OP";
209                 case LE_OP:             return "LE_OP";
210                 case GE_OP:             return "GE_OP";
211                 case EQ_OP:             return "EQ_OP";
212                 case NE_OP:             return "NE_OP";
213                 case AND_OP:            return "AND_OP";
214                 case OR_OP:             return "OR_OP";
215                 case MUL_ASSIGN:        return "MUL_ASSIGN";
216                 case DIV_ASSIGN:        return "DIV_ASSIGN";
217                 case MOD_ASSIGN:        return "MOD_ASSIGN";
218                 case ADD_ASSIGN:        return "ADD_ASSIGN";
219                 case SUB_ASSIGN:        return "SUB_ASSIGN";
220                 case LEFT_ASSIGN:       return "LEFT_ASSIGN";
221                 case RIGHT_ASSIGN:      return "RIGHT_ASSIGN";
222                 case AND_ASSIGN:        return "AND_ASSIGN";
223                 case XOR_ASSIGN:        return "XOR_ASSIGN";
224                 case OR_ASSIGN:         return "OR_ASSIGN";
225                 case TYPEDEF:           return "TYPEDEF";
226                 case EXTERN:            return "EXTERN";
227                 case STATIC:            return "STATIC";
228                 case AUTO:              return "AUTO";
229                 case REGISTER:          return "REGISTER";
230                 case CODE:              return "CODE";
231                 case EEPROM:            return "EEPROM";
232                 case INTERRUPT:         return "INTERRUPT";
233                 case SFR:               return "SFR";
234                 case AT:                return "AT";
235                 case SBIT:              return "SBIT";
236                 case REENTRANT:         return "REENTRANT";
237                 case USING:             return "USING";
238                 case XDATA:             return "XDATA";
239                 case DATA:              return "DATA";
240                 case IDATA:             return "IDATA";
241                 case PDATA:             return "PDATA";
242                 case VAR_ARGS:          return "VAR_ARGS";
243                 case CRITICAL:          return "CRITICAL";
244                 case NONBANKED:         return "NONBANKED";
245                 case BANKED:            return "BANKED";
246                 case CHAR:              return "CHAR";
247                 case SHORT:             return "SHORT";
248                 case INT:               return "INT";
249                 case LONG:              return "LONG";
250                 case SIGNED:            return "SIGNED";
251                 case UNSIGNED:          return "UNSIGNED";
252                 case FLOAT:             return "FLOAT";
253                 case DOUBLE:            return "DOUBLE";
254                 case CONST:             return "CONST";
255                 case VOLATILE:          return "VOLATILE";
256                 case VOID:              return "VOID";
257                 case BIT:               return "BIT";
258                 case STRUCT:            return "STRUCT";
259                 case UNION:             return "UNION";
260                 case ENUM:              return "ENUM";
261                 case ELIPSIS:           return "ELIPSIS";
262                 case RANGE:             return "RANGE";
263                 case FAR:               return "FAR";
264                 case CASE:              return "CASE";
265                 case DEFAULT:           return "DEFAULT";
266                 case IF:                return "IF";
267                 case ELSE:              return "ELSE";
268                 case SWITCH:            return "SWITCH";
269                 case WHILE:             return "WHILE";
270                 case DO:                return "DO";
271                 case FOR:               return "FOR";
272                 case GOTO:              return "GOTO";
273                 case CONTINUE:          return "CONTINUE";
274                 case BREAK:             return "BREAK";
275                 case RETURN:            return "RETURN";
276                 case INLINEASM:         return "INLINEASM";
277                 case IFX:               return "IFX";
278                 case ADDRESS_OF:        return "ADDRESS_OF";
279                 case GET_VALUE_AT_ADDRESS:      return "GET_VALUE_AT_ADDRESS";
280                 case SPIL:              return "SPIL";
281                 case UNSPIL:            return "UNSPIL";
282                 case GETHBIT:           return "GETHBIT";
283                 case BITWISEAND:        return "BITWISEAND";
284                 case UNARYMINUS:        return "UNARYMINUS";
285                 case IPUSH:             return "IPUSH";
286                 case IPOP:              return "IPOP";
287                 case PCALL:             return "PCALL";
288                 case ENDFUNCTION:       return "ENDFUNCTION";
289                 case JUMPTABLE:         return "JUMPTABLE";
290                 case RRC:               return "RRC";
291                 case RLC:               return "RLC";
292                 case CAST:              return "CAST";
293                 case CALL:              return "CALL";
294                 case PARAM:             return "PARAM  ";
295                 case NULLOP:            return "NULLOP";
296                 case BLOCK:             return "BLOCK";
297                 case LABEL:             return "LABEL";
298                 case RECEIVE:           return "RECEIVE";
299                 case SEND:              return "SEND";
300         }
301         sprintf (buffer, "unkown op %d %c", op, op & 0xff);
302
303   return buffer;
304 }
305 /*-----------------------------------------------------------------*/
306 /*-----------------------------------------------------------------*/
307 static char *
308 debugLogRegType (short type)
309 {
310         if(!pic16_ralloc_debug)return NULL;
311         switch (type) {
312                 case REG_GPR: return "REG_GPR";
313                 case REG_PTR: return "REG_PTR";
314                 case REG_CND: return "REG_CND";
315         }
316         sprintf (buffer, "unknown reg type %d", type);
317
318   return buffer;
319 }
320
321 /*-----------------------------------------------------------------*/
322 /*-----------------------------------------------------------------*/
323 static int regname2key(char const *name)
324 {
325   int key = 0;
326
327   if(!name)
328     return 0;
329
330   while(*name) {
331
332     key += (*name++) + 1;
333
334   }
335
336   return ( (key + (key >> 4) + (key>>8)) & 0x3f);
337
338 }
339
340 /*-----------------------------------------------------------------*/
341 /* newReg - allocate and init memory for a new register            */
342 /*-----------------------------------------------------------------*/
343 regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias, operand *refop)
344 {
345
346   regs *dReg;
347
348         dReg = Safe_calloc(1,sizeof(regs));
349         dReg->type = type;
350         dReg->pc_type = pc_type;
351         dReg->rIdx = rIdx;
352         if(name) 
353                 dReg->name = Safe_strdup(name);
354         else {
355                 sprintf(buffer,"r0x%02X", dReg->rIdx);
356                 if(type == REG_STK)
357                         *buffer = 's';
358                         dReg->name = Safe_strdup(buffer);
359         }
360
361
362         dReg->isFree = 0;
363         dReg->wasUsed = 1;
364         dReg->isEmitted = 0;
365
366         if(type == REG_SFR) {
367                 dReg->isFixed = 1;
368                 dReg->address = rIdx;
369                 dReg->accessBank = 1;
370         } else {
371                 dReg->isFixed = 0;
372                 dReg->address = 0;
373                 dReg->accessBank = 0;
374         }
375
376 //      fprintf(stderr,"newReg: %s, rIdx = 0x%02x\taccess= %d\n",dReg->name,rIdx, dReg->accessBank);
377         
378         dReg->size = size;
379         dReg->alias = alias;
380         dReg->reg_alias = NULL;
381         dReg->reglives.usedpFlows = newSet();
382         dReg->reglives.assignedpFlows = newSet();
383         dReg->regop = refop;
384   
385         if(!(type == REG_SFR && alias == 0x80))
386                 hTabAddItem(&dynDirectRegNames, regname2key(name), dReg);
387
388   return dReg;
389 }
390
391 /*-----------------------------------------------------------------*/
392 /* regWithIdx - Search through a set of registers that matches idx */
393 /*-----------------------------------------------------------------*/
394 static regs *
395 regWithIdx (set *dRegs, int idx, int fixed)
396 {
397   regs *dReg;
398
399   for (dReg = setFirstItem(dRegs) ; dReg ; 
400        dReg = setNextItem(dRegs)) {
401
402     if(idx == dReg->rIdx && (fixed == dReg->isFixed)) {
403       return dReg;
404     }
405   }
406
407   return NULL;
408 }
409
410 /*-----------------------------------------------------------------*/
411 /* regFindFree - Search for a free register in a set of registers  */
412 /*-----------------------------------------------------------------*/
413 static regs *
414 regFindFree (set *dRegs)
415 {
416   regs *dReg;
417
418   for (dReg = setFirstItem(dRegs) ; dReg ; 
419        dReg = setNextItem(dRegs)) {
420
421 //      fprintf(stderr, "%s:%d checking register %s (%p) [rIdx: 0x%02x] if free= %d\n",
422 //              __FILE__, __LINE__, dReg->name, dReg, dReg->rIdx, dReg->isFree);
423
424     if(dReg->isFree) {
425       return dReg;
426     }
427   }
428
429   return NULL;
430 }
431 /*-----------------------------------------------------------------*/
432 /* pic16_initStack - allocate registers for a pseudo stack               */
433 /*-----------------------------------------------------------------*/
434 void pic16_initStack(int base_address, int size)
435 {
436
437   int i;
438
439   pic16_Gstack_base_addr = base_address;
440   //fprintf(stderr,"initStack");
441
442   for(i = 0; i<size; i++)
443     addSet(&pic16_dynStackRegs,newReg(REG_STK, PO_GPR_TEMP,base_address++,NULL,1,0, NULL));
444 }
445
446 /*-----------------------------------------------------------------*
447  *-----------------------------------------------------------------*/
448 regs *
449 pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias)
450 {
451   regs *reg = newReg(REG_SFR, po_type, rIdx, name, 1, alias, NULL);
452
453 //      fprintf(stderr,"%s: %s addr =0x%x\n",__FUNCTION__, name,rIdx);
454
455         reg->wasUsed = 0;               // we do not know if they are going to be used at all
456         reg->accessBank = 1;            // implicit add access Bank
457
458   return addSet(&pic16_dynProcessorRegs, reg);
459 }
460
461 /*-----------------------------------------------------------------*
462  *-----------------------------------------------------------------*/
463
464 regs *
465 pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias)
466 {
467   regs * reg = newReg(REG_GPR, po_type, rIdx, name,1,alias, NULL);
468
469 //  fprintf(stderr,"%s:%d: %s   %s addr =0x%x\n",__FILE__, __LINE__, __FUNCTION__, name, rIdx);
470
471     if(reg) {
472       reg->wasUsed = 0;
473       return addSet(&pic16_dynInternalRegs,reg);
474     }
475
476   return NULL;
477 }
478 /*-----------------------------------------------------------------*/
479 /* allocReg - allocates register of given type                     */
480 /*-----------------------------------------------------------------*/
481 static regs *
482 allocReg (short type)
483 {
484   regs * reg=NULL;
485   
486 #if 0
487   if(dynrIdx > pic16_nRegs)
488         return NULL;
489 #endif
490
491         /* try to reuse some unused registers */
492         reg = regFindFree( pic16_dynAllocRegs );
493
494         if(reg) {
495 //              fprintf(stderr, "%s: found FREE register %s\n", __FILE__, reg->name);
496         }
497
498         if(!reg) {
499                 reg = newReg(REG_GPR, PO_GPR_TEMP, dynrIdx++, NULL, 1, 0, NULL);
500 //              addSet(&pic16_dynAllocRegs, reg);
501         }
502
503         addSet(&pic16_dynAllocRegs, reg);
504
505         reg->isFree=0;
506
507 //      debugLog ("%s of type %s\n", __FUNCTION__, debugLogRegType (type));
508
509 //      fprintf(stderr,"%s:%d: %s\t%s addr= 0x%x\trIdx= 0x%02x isFree: %d\n",
510 //              __FILE__, __LINE__, __FUNCTION__, reg->name, reg->address, reg->rIdx, reg->isFree);
511
512         if(reg) {
513                 reg->accessBank = 1;    /* this is a temporary register alloc in accessBank */
514                 reg->isLocal = 1;       /* this is a local frame register */
515         }
516         
517         if (currFunc) {
518 //              fprintf(stderr, "%s:%d adding %s into function %s regsUsed\n", __FUNCTION__, __LINE__, reg->name, currFunc->name);
519                 currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, reg->rIdx);
520         }
521  
522   return (reg);         // addSet(&pic16_dynAllocRegs,reg);
523
524 }
525
526
527 /*-----------------------------------------------------------------*/
528 /* pic16_dirregWithName - search for register by name                    */
529 /*-----------------------------------------------------------------*/
530 regs *
531 pic16_dirregWithName (char *name)
532 {
533   int hkey;
534   regs *reg;
535
536   if(!name)
537     return NULL;
538
539   /* hash the name to get a key */
540
541   hkey = regname2key(name);
542
543 //      fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
544
545   reg = hTabFirstItemWK(dynDirectRegNames, hkey);
546
547   while(reg) {
548
549     if(STRCASECMP(reg->name, name) == 0) {
550       return(reg);
551     }
552
553     reg = hTabNextItemWK (dynDirectRegNames);
554   
555   }
556
557   return NULL; // name wasn't found in the hash table
558 }
559
560 int PIC16_IS_CONFIG_ADDRESS(int address)
561 {
562
563   return address >= 0x300000 && address <= 0x300000d;
564 }
565
566 /*-----------------------------------------------------------------*/
567 /* pic16_allocDirReg - allocates register of given type                  */
568 /*-----------------------------------------------------------------*/
569 regs *
570 pic16_allocDirReg (operand *op )
571 {
572   regs *reg;
573   char *name;
574
575         if(!IS_SYMOP(op)) {
576                 debugLog ("%s BAD, op is NULL\n", __FUNCTION__);
577 //              fprintf(stderr, "%s BAD, op is NULL\n", __FUNCTION__);
578           return NULL;
579         }
580
581         name = OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name;
582
583         if(!SPEC_OCLS( OP_SYM_ETYPE(op))) {                                                                     // patch 13
584                 if(pic16_debug_verbose)                                                                         //
585                 {                                                                                               //
586                         fprintf(stderr, "%s:%d symbol %s(r:%s) is not assigned to a memmap\n", __FILE__, __LINE__,      //
587                                 OP_SYMBOL(op)->name, OP_SYMBOL(op)->rname);                                                             //
588                 }                                                                                               //
589                 return NULL;                                                                                    //
590         }                                                                                                       // patch 13
591
592         debugLog ("%s:%d symbol name %s\n", __FUNCTION__, __LINE__, name);
593 //      fprintf(stderr, "%s symbol name %s\n", __FUNCTION__,name);
594
595         {
596                 if(SPEC_CONST ( OP_SYM_ETYPE(op)) && (IS_CHAR ( OP_SYM_ETYPE(op)) )) {
597                         debugLog(" %d  const char\n",__LINE__);
598                         debugLog(" value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
599 //                      fprintf(stderr, " %d  const char\n",__LINE__);
600 //                      fprintf(stderr, " value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
601                 }
602
603         
604                 debugLog("  %d  storage class %d \n",__LINE__,SPEC_SCLS( OP_SYM_ETYPE(op)));
605                 if (IS_CODE ( OP_SYM_ETYPE(op)) )
606                         debugLog(" %d  code space\n",__LINE__);
607
608                 if (IS_INTEGRAL ( OP_SYM_ETYPE(op)) )
609                         debugLog(" %d  integral\n",__LINE__);
610
611                 if (IS_LITERAL ( OP_SYM_ETYPE(op)) )
612                         debugLog(" %d  literal\n",__LINE__);
613
614                 if (IS_SPEC ( OP_SYM_ETYPE(op)) )
615                         debugLog(" %d  specifier\n",__LINE__);
616
617                 debugAopGet(NULL, op);
618         }
619
620         if (IS_CODE ( OP_SYM_ETYPE(op)) )
621                 return NULL;
622
623         /* First, search the hash table to see if there is a register with this name */
624         if (SPEC_ABSA ( OP_SYM_ETYPE(op)) && !(IS_BITVAR (OP_SYM_ETYPE(op))) ) {
625                 reg=NULL;
626 //              reg = regWithIdx (pic16_dynProcessorRegs, SPEC_ADDR ( OP_SYM_ETYPE(op)), 1);
627
628 #if 0
629                 if(!reg) 
630                         fprintf(stderr,"%s:%d: ralloc %s is at fixed address but not a processor reg, addr=0x%x\n",
631                                         __FUNCTION__, __LINE__, name, SPEC_ADDR ( OP_SYM_ETYPE(op)));
632                 else
633                         fprintf(stderr,"%s:%d: ralloc %s at fixed address has already been declared, addr=0x%x\n",
634                                         __FUNCTION__, __LINE__, name, SPEC_ADDR ( OP_SYM_ETYPE(op)));
635 #endif
636         } else {
637 //              fprintf(stderr,"ralloc:%d %s \n", __LINE__,name);
638     
639                 reg = pic16_dirregWithName(name);
640         }
641
642         if(!reg) {
643           int address = 0;
644           int regtype = REG_GPR;
645     
646                 /* if this is at an absolute address, then get the address. */
647                 if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
648                         address = SPEC_ADDR ( OP_SYM_ETYPE(op));
649 //                      fprintf(stderr,"reg %s is at an absolute address: 0x%03x\n",name,address);
650                 }
651
652                 /* Register wasn't found in hash, so let's create
653                  * a new one and put it in the hash table AND in the 
654                  * dynDirectRegNames set */
655                 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))) {
656                         if(pic16_debug_verbose)
657                                 fprintf(stderr, "%s:%d symbol %s in codespace\n", __FILE__, __LINE__,
658                                         OP_SYMBOL(op)->name);
659                         debugLog("%s:%d sym: %s in codespace\n", __FUNCTION__, __LINE__, OP_SYMBOL(op)->name);
660                   return NULL;
661                 }
662
663                 if(!PIC16_IS_CONFIG_ADDRESS(address)) {
664 //                      fprintf(stderr,"%s:allocating new reg %s\n",__FUNCTION__, name);
665
666                         /* this is an error, why added? -- VR */
667 //                      if(SPEC_SCLS(OP_SYM_ETYPE(op)))regtype = REG_SFR;
668
669                         if(OP_SYMBOL(op)->onStack) {
670 //                              fprintf(stderr, "%s:%d onStack %s\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
671                                 OP_SYMBOL(op)->onStack = 0;
672                                 SPEC_OCLS(OP_SYM_ETYPE(op)) = data;
673                                 regtype = REG_GPR;
674                         }
675
676                         if(!IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))) {                                               // patch 13
677                                 if(pic16_debug_verbose)                                                                 //
678                                 {                                                                                       //
679                                         fprintf(stderr, "dispace:%d farspace:%d codespace:%d regspace:%d stack:%d\n",
680                                                 IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
681                                                 IN_FARSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
682                                                 IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
683                                                 IN_REGSP( SPEC_OCLS( OP_SYM_ETYPE(op))),
684                                                 IN_STACK( OP_SYM_ETYPE(op)));
685
686                                         fprintf(stderr, "%s:%d symbol %s NOT in dirspace\n", __FILE__, __LINE__,        //
687                                                 OP_SYMBOL(op)->name);                                                   //
688                                 }                                                                                       //
689 //                              return NULL;                                                                            //
690                         }                                                                                               // patch 13
691
692                         reg = newReg(regtype, PO_DIR, rDirectIdx++, name,getSize (OP_SYMBOL (op)->type),0, op);
693                         debugLog ("%d  -- added %s to hash, size = %d\n", __LINE__, name,reg->size);
694
695 //                      hTabAddItem(&dynDirectRegNames, regname2key(name), reg);        /* commented out */
696
697 //                      if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
698 //                              fprintf(stderr, " ralloc.c at fixed address: %s - changing to REG_SFR\n",name);
699 //                              reg->type = REG_SFR;
700 //                      }
701
702                         if (IS_BITVAR (OP_SYM_ETYPE(op))) {
703 //                              fprintf(stderr, "%s:%d adding %s in bit registers\n", __FILE__, __LINE__, reg->name);
704                                 addSet(&pic16_dynDirectBitRegs, reg);
705                                 reg->isBitField = 1;
706                         } else {
707 //                              fprintf(stderr, "%s:%d adding %s in direct registers\n", __FILE__, __LINE__, reg->name);
708 //                              addSet(&pic16_dynDirectRegs, reg);
709                                 checkAddReg(&pic16_dynDirectRegs, reg);
710                         }
711         
712                 } else {
713                         debugLog ("  -- %s is declared at address 0x30000x\n",name);
714 //                      fprintf(stderr, "  -- %s is declared at address 0x30000x\n",name);
715         
716                   return NULL;
717                 }
718         }
719
720         if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
721                 reg->isFixed = 1;
722                 reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
723
724                 /* work around for user defined registers in access bank */
725                 if((reg->address>= 0x00 && reg->address < 0x80)
726                         || (reg->address >= 0xf80 && reg->address <= 0xfff))
727                         reg->accessBank = 1;
728                 
729                 debugLog ("  -- and it is at a fixed address 0x%02x\n",reg->address);
730         }
731
732   return reg;
733 }
734
735 /*-----------------------------------------------------------------*/
736 /* pic16_allocRegByName - allocates register of given type                  */
737 /*-----------------------------------------------------------------*/
738 regs *
739 pic16_allocRegByName (char *name, int size)
740 {
741
742   regs *reg;
743
744   if(!name) {
745     fprintf(stderr, "%s - allocating a NULL register\n",__FUNCTION__);
746     exit(1);
747   }
748
749   /* First, search the hash table to see if there is a register with this name */
750   reg = pic16_dirregWithName(name);
751
752   if(!reg) {
753
754     /* Register wasn't found in hash, so let's create
755      * a new one and put it in the hash table AND in the 
756      * dynDirectRegNames set */
757     //fprintf (stderr,"%s symbol name %s\n", __FUNCTION__,name);
758     reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,size,0, NULL);
759
760     debugLog ("%d  -- added %s to hash, size = %d\n", __LINE__, name,reg->size);
761         //fprintf(stderr, "  -- added %s to hash, size = %d\n", name,reg->size);
762
763     //hTabAddItem(&dynDirectRegNames, regname2key(name), reg);  /* initially commented out */
764     addSet(&pic16_dynDirectRegs, reg);
765   }
766
767   return reg;
768 }
769
770 /*-----------------------------------------------------------------*/
771 /* RegWithIdx - returns pointer to register with index number       */
772 /*-----------------------------------------------------------------*/
773 regs *pic16_typeRegWithIdx (int idx, int type, int fixed)
774 {
775
776   regs *dReg;
777
778   debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx);
779 //  fprintf(stderr, "%s - requesting index = 0x%x\n", __FUNCTION__, idx);
780
781   switch (type) {
782
783   case REG_GPR:
784     if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx, fixed)) != NULL) {
785
786       debugLog ("Found a Dynamic Register!\n");
787       return dReg;
788     }
789     if( (dReg = regWithIdx ( pic16_dynDirectRegs, idx, fixed)) != NULL ) {
790       debugLog ("Found a Direct Register!\n");
791       return dReg;
792     }
793
794     break;
795   case REG_STK:
796     if( (dReg = regWithIdx ( pic16_dynStackRegs, idx, fixed)) != NULL ) {
797       debugLog ("Found a Stack Register!\n");
798       return dReg;
799     }
800     break;
801   case REG_SFR:
802     if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx, fixed)) != NULL ) {
803       debugLog ("Found a Processor Register!\n");
804       return dReg;
805     }
806
807   case REG_CND:
808   case REG_PTR:
809   default:
810     break;
811   }
812
813
814   return NULL;
815 }
816
817 /*-----------------------------------------------------------------*/
818 /* pic16_regWithIdx - returns pointer to register with index number*/
819 /*-----------------------------------------------------------------*/
820 regs *
821 pic16_regWithIdx (int idx)
822 {
823   regs *dReg;
824
825   if( (dReg = pic16_typeRegWithIdx(idx,REG_GPR,0)) != NULL)
826     return dReg;
827
828   if( (dReg = pic16_typeRegWithIdx(idx,REG_SFR,0)) != NULL)
829     return dReg;
830
831   if( (dReg = pic16_typeRegWithIdx(idx,REG_STK,0)) != NULL)
832     return dReg;
833
834   return NULL;
835 }
836
837 /*-----------------------------------------------------------------*/
838 /* pic16_regWithIdx - returns pointer to register with index number       */
839 /*-----------------------------------------------------------------*/
840 regs *
841 pic16_allocWithIdx (int idx)
842 {
843
844   regs *dReg;
845
846   debugLog ("%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
847 //  fprintf(stderr, "%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
848
849   if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx,0)) != NULL) {
850
851     debugLog ("Found a Dynamic Register!\n");
852   } else if( (dReg = regWithIdx ( pic16_dynStackRegs, idx,0)) != NULL ) {
853     debugLog ("Found a Stack Register!\n");
854   } else if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx,0)) != NULL ) {
855     debugLog ("Found a Processor Register!\n");
856     fprintf(stderr, "Found a processor register! %s\n", dReg->name);
857   } else if( (dReg = regWithIdx ( pic16_dynInternalRegs, idx,0)) != NULL ) {
858     debugLog ("Found an Internal Register!\n");
859   } else {
860     
861     debugLog ("Dynamic Register not found\n");
862
863
864     //fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx);
865     werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
866             "regWithIdx not found");
867     exit (1);
868
869   }
870
871   dReg->wasUsed = 1;
872   dReg->isFree = 0;
873
874   return dReg;
875 }
876 /*-----------------------------------------------------------------*/
877 /*-----------------------------------------------------------------*/
878 regs *
879 pic16_findFreeReg(short type)
880 {
881   //  int i;
882   regs* dReg;
883
884   switch (type) {
885   case REG_GPR:
886     if((dReg = regFindFree(pic16_dynAllocRegs)) != NULL)
887       return dReg;
888     return allocReg( REG_GPR );         //addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL));
889
890   case REG_STK:
891
892     if((dReg = regFindFree(pic16_dynStackRegs)) != NULL)
893       return dReg;
894
895     return NULL;
896
897   case REG_PTR:
898   case REG_CND:
899   case REG_SFR:
900   default:
901     return NULL;
902   }
903 }
904 /*-----------------------------------------------------------------*/
905 /* freeReg - frees a register                                      */
906 /*-----------------------------------------------------------------*/
907 static void
908 freeReg (regs * reg)
909 {
910         debugLog ("%s\n", __FUNCTION__);
911 //      fprintf(stderr, "%s:%d register %s (%p) is freed\n", __FILE__, __LINE__, reg->name, reg);
912         reg->isFree = 1;
913 }
914
915
916 /*-----------------------------------------------------------------*/
917 /* nFreeRegs - returns number of free registers                    */
918 /*-----------------------------------------------------------------*/
919 static int
920 nFreeRegs (int type)
921 {
922   regs *reg;
923   int nfr=0;
924
925
926                 /* although I fixed the register allocation/freeing scheme
927                  * the for loop below doesn't give valid results. I do not
928                  * know why yet. -- VR 10-Jan-2003 */
929                  
930         return 100;
931
932
933   /* dynamically allocate as many as we need and worry about
934    * fitting them into a PIC later */
935
936   debugLog ("%s\n", __FUNCTION__);
937
938         for(reg = setFirstItem(pic16_dynAllocRegs); reg; reg=setNextItem(pic16_dynAllocRegs))
939                 if((reg->type == type) && reg->isFree)nfr++;
940
941         fprintf(stderr, "%s:%d # of free registers= %d\n", __FILE__, __LINE__, nfr);
942   return nfr;
943 }
944
945 /*-----------------------------------------------------------------*/
946 /* nfreeRegsType - free registers with type                         */
947 /*-----------------------------------------------------------------*/
948 static int
949 nfreeRegsType (int type)
950 {
951   int nfr;
952   debugLog ("%s\n", __FUNCTION__);
953   if (type == REG_PTR)
954     {
955       if ((nfr = nFreeRegs (type)) == 0)
956         return nFreeRegs (REG_GPR);
957     }
958
959   return nFreeRegs (type);
960 }
961 #if 0
962 static void writeSetUsedRegs(FILE *of, set *dRegs)
963 {
964
965   regs *dReg;
966
967   for (dReg = setFirstItem(dRegs) ; dReg ; 
968        dReg = setNextItem(dRegs)) {
969
970     if(dReg->wasUsed)
971       fprintf (of, "\t%s\n",dReg->name);
972   }
973
974 }
975 #endif
976
977 extern void pic16_groupRegistersInSection(set *regset);
978
979 extern void pic16_dump_equates(FILE *of, set *equs);
980 //extern void pic16_dump_map(void);
981 extern void pic16_dump_section(FILE *of, set *section, int fix);
982 extern void pic16_dump_int_registers(FILE *of, set *section);
983 extern void pic16_dump_idata(FILE *of, set *idataSymSet);
984
985 static void packBits(set *bregs)
986 {
987   set *regset;
988   regs *breg;
989   regs *bitfield=NULL;
990   regs *relocbitfield=NULL;
991   int bit_no=0;
992   int byte_no=-1;
993   char buffer[20];
994
995
996   for (regset = bregs ; regset ;
997        regset = regset->next) {
998
999     breg = regset->item;
1000     breg->isBitField = 1;
1001     //fprintf(stderr,"bit reg: %s\n",breg->name);
1002
1003     if(breg->isFixed) {
1004       //fprintf(stderr,"packing bit at fixed address = 0x%03x\n",breg->address);
1005
1006       bitfield = pic16_typeRegWithIdx (breg->address >> 3, -1 , 1);
1007       breg->rIdx = breg->address & 7;
1008       breg->address >>= 3;
1009
1010       if(!bitfield) {
1011         sprintf (buffer, "fbitfield%02x", breg->address);
1012         //fprintf(stderr,"new bit field\n");
1013         bitfield = newReg(REG_SFR, PO_GPR_BIT,breg->address,buffer,1,0, NULL);
1014         bitfield->isBitField = 1;
1015         bitfield->isFixed = 1;
1016         bitfield->address = breg->address;
1017         addSet(&pic16_dynDirectRegs,bitfield);
1018         //hTabAddItem(&dynDirectRegNames, regname2key(buffer), bitfield);
1019       } else {
1020         //fprintf(stderr,"  which is occupied by %s (addr = %d)\n",bitfield->name,bitfield->address);
1021         ;
1022       }
1023       breg->reg_alias = bitfield;
1024       bitfield = NULL;
1025
1026     } else {
1027       if(!relocbitfield || bit_no >7) {
1028         byte_no++;
1029         bit_no=0;
1030         sprintf (buffer, "bitfield%d", byte_no);
1031         //fprintf(stderr,"new relocatable bit field\n");
1032         relocbitfield = newReg(REG_GPR, PO_GPR_BIT,rDirectIdx++,buffer,1,0, NULL);
1033         relocbitfield->isBitField = 1;
1034         addSet(&pic16_dynDirectRegs,relocbitfield);
1035         //hTabAddItem(&dynDirectRegNames, regname2key(buffer), relocbitfield);
1036
1037       }
1038
1039       breg->reg_alias = relocbitfield;
1040       breg->address = rDirectIdx;   /* byte_no; */
1041       breg->rIdx = bit_no++;
1042     }
1043   }
1044       
1045 }
1046
1047
1048
1049 #if 0
1050 static void bitEQUs(FILE *of, set *bregs)
1051 {
1052   regs *breg,*bytereg;
1053   int bit_no=0;
1054
1055   //fprintf(stderr," %s\n",__FUNCTION__);
1056   for (breg = setFirstItem(bregs) ; breg ;
1057        breg = setNextItem(bregs)) {
1058
1059     //fprintf(stderr,"bit reg: %s\n",breg->name);
1060
1061     bytereg = breg->reg_alias;
1062     if(bytereg)
1063       fprintf (of, "%s\tEQU\t( (%s<<3)+%d)\n",
1064                breg->name,
1065                bytereg->name,
1066                breg->rIdx & 0x0007);
1067
1068     else {
1069       fprintf(stderr, "bit field is not assigned to a register\n");
1070       fprintf (of, "%s\tEQU\t( (bitfield%d<<3)+%d)\n",
1071                breg->name,
1072                bit_no>>3,
1073                bit_no & 0x0007);
1074
1075       bit_no++;
1076     }
1077   }
1078       
1079 }
1080
1081 static void aliasEQUs(FILE *of, set *fregs, int use_rIdx)
1082 {
1083   regs *reg;
1084
1085
1086   for (reg = setFirstItem(fregs) ; reg ;
1087        reg = setNextItem(fregs)) {
1088
1089     if(!reg->isEmitted && reg->wasUsed) {
1090       if(use_rIdx) {
1091         if (reg->type != REG_SFR) {
1092           fprintf (of, "%s\tEQU\t0x%03x\n",
1093                    reg->name,
1094                    reg->rIdx);
1095         }
1096       }
1097       else
1098         fprintf (of, "%s\tEQU\t0x%03x\n",
1099                  reg->name,
1100                  reg->address);
1101     }
1102   }
1103       
1104 }
1105 #endif
1106
1107 void pic16_writeUsedRegs(FILE *of) 
1108 {
1109         packBits(pic16_dynDirectBitRegs);
1110
1111         pic16_groupRegistersInSection(pic16_dynAllocRegs);
1112         pic16_groupRegistersInSection(pic16_dynInternalRegs);
1113         pic16_groupRegistersInSection(pic16_dynStackRegs);
1114         pic16_groupRegistersInSection(pic16_dynDirectRegs);
1115         pic16_groupRegistersInSection(pic16_dynDirectBitRegs);
1116         pic16_groupRegistersInSection(pic16_dynProcessorRegs);
1117         
1118         
1119 #if 0
1120         pic16_assignFixedRegisters(pic16_dynAllocRegs);
1121         pic16_assignFixedRegisters(pic16_dynStackRegs);
1122         pic16_assignFixedRegisters(pic16_dynDirectRegs);
1123         pic16_assignFixedRegisters(pic16_dynProcessorRegs);
1124
1125         pic16_assignRelocatableRegisters(pic16_dynDirectBitRegs, 0);
1126         pic16_assignRelocatableRegisters(pic16_dynInternalRegs,0);
1127         pic16_assignRelocatableRegisters(pic16_dynAllocRegs,0);
1128         pic16_assignRelocatableRegisters(pic16_dynStackRegs,0);
1129         pic16_assignRelocatableRegisters(pic16_dynDirectRegs,0);
1130 #endif
1131
1132 //      pic16_dump_map();
1133 //      pic16_dump_cblock(of);
1134
1135         /* dump equates */
1136         pic16_dump_equates(of, pic16_equ_data);
1137
1138         /* dump initialised data */
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_section(of, pic16_rel_udata, 0);
1146         pic16_dump_section(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 this is an ipop that means some live
2118              range will have to be assigned again */
2119           if (ic->op == IPOP)
2120             reassignLR (IC_LEFT (ic));
2121
2122           /* if result is present && is a true symbol */
2123           if (IC_RESULT (ic) && ic->op != IFX &&
2124               IS_TRUE_SYMOP (IC_RESULT (ic)))
2125             OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
2126
2127           /* take away registers from live
2128              ranges that end at this instruction */
2129           deassignLRs (ic, ebbs[i]);
2130
2131           /* some don't need registers */
2132           if (SKIP_IC2 (ic) ||
2133               ic->op == JUMPTABLE ||
2134               ic->op == IFX ||
2135               ic->op == IPUSH ||
2136               ic->op == IPOP ||
2137               (IC_RESULT (ic) && POINTER_SET (ic)))
2138             continue;
2139
2140           /* now we need to allocate registers
2141              only for the result */
2142           if (IC_RESULT (ic))
2143             {
2144               symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2145               bitVect *spillable;
2146               int willCS;
2147               int j;
2148               int ptrRegSet = 0;
2149
2150               /* if it does not need or is spilt 
2151                  or is already assigned to registers
2152                  or will not live beyond this instructions */
2153               if (!sym->nRegs ||
2154                   sym->isspilt ||
2155                   bitVectBitValue (_G.regAssigned, sym->key) ||
2156                   sym->liveTo <= ic->seq)
2157                 continue;
2158
2159               /* if some liverange has been spilt at the block level
2160                  and this one live beyond this block then spil this
2161                  to be safe */
2162               if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
2163                 {
2164                   spillThis (sym);
2165                   continue;
2166                 }
2167               /* if trying to allocate this will cause
2168                  a spill and there is nothing to spill 
2169                  or this one is rematerializable then
2170                  spill this one */
2171               willCS = willCauseSpill (sym->nRegs, sym->regType);
2172               spillable = computeSpillable (ic);
2173               if (sym->remat ||
2174                   (willCS && bitVectIsZero (spillable)))
2175                 {
2176
2177                   spillThis (sym);
2178                   continue;
2179
2180                 }
2181
2182               /* if it has a spillocation & is used less than
2183                  all other live ranges then spill this */
2184                 if (willCS) {
2185                     if (sym->usl.spillLoc) {
2186                         symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
2187                                                                          allLRs, ebbs[i], ic));
2188                         if (leastUsed && leastUsed->used > sym->used) {
2189                             spillThis (sym);
2190                             continue;
2191                         }
2192                     } else {
2193                         /* if none of the liveRanges have a spillLocation then better
2194                            to spill this one than anything else already assigned to registers */
2195                         if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
2196                             /* if this is local to this block then we might find a block spil */
2197                             if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
2198                                 spillThis (sym);
2199                                 continue;
2200                             }
2201                         }
2202                     }
2203                 }
2204
2205               if (ic->op == RECEIVE)
2206                 debugLog ("When I get clever, I'll optimize the receive logic\n");
2207
2208               /* if we need ptr regs for the right side
2209                  then mark it */
2210               if (POINTER_GET (ic) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
2211                   <= (unsigned) PTRSIZE)
2212                 {
2213                   pic16_ptrRegReq++;
2214                   ptrRegSet = 1;
2215                 }
2216               /* else we assign registers to it */
2217               _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
2218
2219               debugLog ("  %d - \n", __LINE__);
2220               if(debugF) 
2221                 bitVectDebugOn(_G.regAssigned, debugF);
2222
2223               for (j = 0; j < sym->nRegs; j++)
2224                 {
2225                   if (sym->regType == REG_PTR)
2226                     sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
2227                   else
2228                     sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
2229
2230                   /* if the allocation falied which means
2231                      this was spilt then break */
2232                   if (!sym->regs[j])
2233                     break;
2234                 }
2235               debugLog ("  %d - \n", __LINE__);
2236
2237               /* if it shares registers with operands make sure
2238                  that they are in the same position */
2239               if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
2240                   OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
2241                 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2242                               OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
2243               /* do the same for the right operand */
2244               if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
2245                   OP_SYMBOL (IC_RIGHT (ic))->nRegs && ic->op != '=')
2246                 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2247                               OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
2248
2249               debugLog ("  %d - \n", __LINE__);
2250               if (ptrRegSet)
2251                 {
2252                   debugLog ("  %d - \n", __LINE__);
2253                   pic16_ptrRegReq--;
2254                   ptrRegSet = 0;
2255                 }
2256
2257             }
2258         }
2259     }
2260
2261     /* Check for and fix any problems with uninitialized operands */
2262     for (i = 0; i < count; i++)
2263       {
2264         iCode *ic;
2265
2266         if (ebbs[i]->noPath &&
2267             (ebbs[i]->entryLabel != entryLabel &&
2268              ebbs[i]->entryLabel != returnLabel))
2269             continue;
2270
2271         for (ic = ebbs[i]->sch; ic; ic = ic->next)
2272           {
2273             if (SKIP_IC2 (ic))
2274               continue;
2275
2276             if (ic->op == IFX)
2277               {
2278                 verifyRegsAssigned (IC_COND (ic), ic);
2279                 continue;
2280               }
2281
2282             if (ic->op == JUMPTABLE)
2283               {
2284                 verifyRegsAssigned (IC_JTCOND (ic), ic);
2285                 continue;
2286               }
2287
2288             verifyRegsAssigned (IC_RESULT (ic), ic);
2289             verifyRegsAssigned (IC_LEFT (ic), ic);
2290             verifyRegsAssigned (IC_RIGHT (ic), ic);
2291           }
2292       }    
2293     
2294 }
2295
2296 /*-----------------------------------------------------------------*/
2297 /* rUmaskForOp :- returns register mask for an operand             */
2298 /*-----------------------------------------------------------------*/
2299 static bitVect *
2300 rUmaskForOp (operand * op)
2301 {
2302   bitVect *rumask;
2303   symbol *sym;
2304   int j;
2305
2306   debugLog ("%s\n", __FUNCTION__);
2307   /* only temporaries are assigned registers */
2308   if (!IS_ITEMP (op))
2309     return NULL;
2310
2311   sym = OP_SYMBOL (op);
2312
2313   /* if spilt or no registers assigned to it
2314      then nothing */
2315   if (sym->isspilt || !sym->nRegs)
2316     return NULL;
2317
2318   rumask = newBitVect (pic16_nRegs);
2319
2320   for (j = 0; j < sym->nRegs; j++)
2321     {
2322       rumask = bitVectSetBit (rumask,
2323                               sym->regs[j]->rIdx);
2324     }
2325
2326   return rumask;
2327 }
2328
2329 /*-----------------------------------------------------------------*/
2330 /* regsUsedIniCode :- returns bit vector of registers used in iCode */
2331 /*-----------------------------------------------------------------*/
2332 static bitVect *
2333 regsUsedIniCode (iCode * ic)
2334 {
2335   bitVect *rmask = newBitVect (pic16_nRegs);
2336
2337   debugLog ("%s\n", __FUNCTION__);
2338   /* do the special cases first */
2339   if (ic->op == IFX)
2340     {
2341       rmask = bitVectUnion (rmask,
2342                             rUmaskForOp (IC_COND (ic)));
2343       goto ret;
2344     }
2345
2346   /* for the jumptable */
2347   if (ic->op == JUMPTABLE)
2348     {
2349       rmask = bitVectUnion (rmask,
2350                             rUmaskForOp (IC_JTCOND (ic)));
2351
2352       goto ret;
2353     }
2354
2355   /* of all other cases */
2356   if (IC_LEFT (ic))
2357     rmask = bitVectUnion (rmask,
2358                           rUmaskForOp (IC_LEFT (ic)));
2359
2360
2361   if (IC_RIGHT (ic))
2362     rmask = bitVectUnion (rmask,
2363                           rUmaskForOp (IC_RIGHT (ic)));
2364
2365   if (IC_RESULT (ic))
2366     rmask = bitVectUnion (rmask,
2367                           rUmaskForOp (IC_RESULT (ic)));
2368
2369 ret:
2370   return rmask;
2371 }
2372
2373 /*-----------------------------------------------------------------*/
2374 /* createRegMask - for each instruction will determine the regsUsed */
2375 /*-----------------------------------------------------------------*/
2376 static void
2377 createRegMask (eBBlock ** ebbs, int count)
2378 {
2379   int i;
2380
2381   debugLog ("%s\n", __FUNCTION__);
2382   /* for all blocks */
2383   for (i = 0; i < count; i++)
2384     {
2385       iCode *ic;
2386
2387       if (ebbs[i]->noPath &&
2388           (ebbs[i]->entryLabel != entryLabel &&
2389            ebbs[i]->entryLabel != returnLabel))
2390         continue;
2391
2392       /* for all instructions */
2393       for (ic = ebbs[i]->sch; ic; ic = ic->next)
2394         {
2395
2396           int j;
2397
2398           if (SKIP_IC2 (ic) || !ic->rlive)
2399             continue;
2400
2401           /* first mark the registers used in this
2402              instruction */
2403           ic->rUsed = regsUsedIniCode (ic);
2404           _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
2405
2406           /* now create the register mask for those 
2407              registers that are in use : this is a
2408              super set of ic->rUsed */
2409           ic->rMask = newBitVect (pic16_nRegs + 1);
2410
2411           /* for all live Ranges alive at this point */
2412           for (j = 1; j < ic->rlive->size; j++)
2413             {
2414               symbol *sym;
2415               int k;
2416
2417               /* if not alive then continue */
2418               if (!bitVectBitValue (ic->rlive, j))
2419                 continue;
2420
2421               /* find the live range we are interested in */
2422               if (!(sym = hTabItemWithKey (liveRanges, j)))
2423                 {
2424                   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2425                           "createRegMask cannot find live range");
2426                   exit (0);
2427                 }
2428
2429               /* if no register assigned to it */
2430               if (!sym->nRegs || sym->isspilt)
2431                 continue;
2432
2433               /* for all the registers allocated to it */
2434               for (k = 0; k < sym->nRegs; k++)
2435                 if (sym->regs[k])
2436                   ic->rMask =
2437                     bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
2438             }
2439         }
2440     }
2441 }
2442
2443 /*-----------------------------------------------------------------*/
2444 /* rematStr - returns the rematerialized string for a remat var    */
2445 /*-----------------------------------------------------------------*/
2446 static symbol *
2447 rematStr (symbol * sym)
2448 {
2449   char *s = buffer;
2450   iCode *ic = sym->rematiCode;
2451   symbol *psym = NULL;
2452
2453   debugLog ("%s\n", __FUNCTION__);
2454
2455   //printf ("%s\n", s);
2456
2457   /* if plus or minus print the right hand side */
2458
2459   if (ic->op == '+' || ic->op == '-') {
2460         
2461     iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2462
2463     sprintf (s, "(%s %c 0x%04x)",
2464              OP_SYMBOL (IC_LEFT (ric))->rname,
2465              ic->op,
2466              (int) operandLitValue (IC_RIGHT (ic)));
2467
2468
2469     //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
2470
2471     psym = newSymbol (OP_SYMBOL (IC_LEFT (ric))->rname, 1);
2472     psym->offset = (int) operandLitValue (IC_RIGHT (ic));
2473
2474     return psym;
2475   }
2476
2477   sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
2478   psym = newSymbol (OP_SYMBOL (IC_LEFT (ic))->rname, 1);
2479
2480   //printf ("ralloc.c:%d %s\n", __LINE__,buffer);
2481   return psym;
2482 }
2483
2484 #if 0
2485 /*-----------------------------------------------------------------*/
2486 /* rematStr - returns the rematerialized string for a remat var    */
2487 /*-----------------------------------------------------------------*/
2488 static char *
2489 rematStr (symbol * sym)
2490 {
2491   char *s = buffer;
2492   iCode *ic = sym->rematiCode;
2493
2494   debugLog ("%s\n", __FUNCTION__);
2495   while (1)
2496     {
2497
2498       printf ("%s\n", s);
2499       /* if plus or minus print the right hand side */
2500 /*
2501    if (ic->op == '+' || ic->op == '-') {
2502    sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
2503    ic->op );
2504    s += strlen(s);
2505    ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2506    continue ;
2507    }
2508  */
2509       if (ic->op == '+' || ic->op == '-')
2510         {
2511           iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2512           sprintf (s, "(%s %c 0x%04x)",
2513                    OP_SYMBOL (IC_LEFT (ric))->rname,
2514                    ic->op,
2515                    (int) operandLitValue (IC_RIGHT (ic)));
2516
2517           //s += strlen(s);
2518           //ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2519           //continue ;
2520           //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
2521           return buffer;
2522         }
2523
2524       /* we reached the end */
2525       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
2526       break;
2527     }
2528
2529   printf ("%s\n", buffer);
2530   return buffer;
2531 }
2532 #endif
2533
2534 /*-----------------------------------------------------------------*/
2535 /* regTypeNum - computes the type & number of registers required   */
2536 /*-----------------------------------------------------------------*/
2537 static void
2538 regTypeNum ()
2539 {
2540   symbol *sym;
2541   int k;
2542   iCode *ic;
2543
2544   debugLog ("%s\n", __FUNCTION__);
2545   /* for each live range do */
2546   for (sym = hTabFirstItem (liveRanges, &k); sym;
2547        sym = hTabNextItem (liveRanges, &k)) {
2548
2549     debugLog ("  %d - %s\n", __LINE__, sym->rname);
2550     //fprintf(stderr,"  %d - %s\n", __LINE__, sym->rname);
2551
2552     /* if used zero times then no registers needed */
2553     if ((sym->liveTo - sym->liveFrom) == 0)
2554       continue;
2555
2556
2557     /* if the live range is a temporary */
2558     if (sym->isitmp) {
2559
2560       debugLog ("  %d - itemp register\n", __LINE__);
2561
2562       /* if the type is marked as a conditional */
2563       if (sym->regType == REG_CND)
2564         continue;
2565
2566       /* if used in return only then we don't 
2567          need registers */
2568       if (sym->ruonly || sym->accuse) {
2569         if (IS_AGGREGATE (sym->type) || sym->isptr)
2570           sym->type = aggrToPtr (sym->type, FALSE);
2571         debugLog ("  %d - no reg needed - used as a return\n", __LINE__);
2572
2573         continue;
2574       }
2575
2576       /* if the symbol has only one definition &
2577          that definition is a get_pointer and the
2578          pointer we are getting is rematerializable and
2579          in "data" space */
2580
2581       if (bitVectnBitsOn (sym->defs) == 1 &&
2582           (ic = hTabItemWithKey (iCodehTab,
2583                                  bitVectFirstBit (sym->defs))) &&
2584           POINTER_GET (ic) &&
2585           !IS_BITVAR (sym->etype) &&
2586           (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) {
2587
2588         if (ptrPseudoSymSafe (sym, ic)) {
2589           
2590           symbol *psym;
2591           
2592           debugLog ("  %d - \n", __LINE__);
2593               
2594           /* create a psuedo symbol & force a spil */
2595           //X symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
2596           psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
2597           psym->type = sym->type;
2598           psym->etype = sym->etype;
2599           psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (ic)));
2600           strcpy (psym->rname, psym->name);
2601           sym->isspilt = 1;
2602           sym->usl.spillLoc = psym;
2603           continue;
2604         }
2605
2606         /* if in data space or idata space then try to
2607            allocate pointer register */
2608
2609       }
2610
2611       /* if not then we require registers */
2612       sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
2613                     getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
2614                     getSize (sym->type));
2615
2616
2617 #if 0
2618     if(IS_PTR_CONST (sym->type)) {
2619 #else
2620     if(IS_CODEPTR (sym->type)) {
2621 #endif
2622       // what IS this ???? (HJD)
2623       debugLog ("  %d const pointer type requires %d registers, changing to 3\n",__LINE__,sym->nRegs); // patch 14
2624       sym->nRegs = 3; // patch 14
2625     }
2626
2627       if (sym->nRegs > 4) {
2628         fprintf (stderr, "allocated more than 4 or 0 registers for type ");
2629         printTypeChain (sym->type, stderr);
2630         fprintf (stderr, "\n");
2631       }
2632
2633       /* determine the type of register required */
2634       if (sym->nRegs == 1 &&
2635           IS_PTR (sym->type) &&
2636           sym->uptr)
2637         sym->regType = REG_PTR;
2638       else
2639         sym->regType = REG_GPR;
2640
2641
2642       debugLog ("  reg name %s,  reg type %s\n", sym->rname, debugLogRegType (sym->regType));
2643
2644     }
2645     else
2646       /* for the first run we don't provide */
2647       /* registers for true symbols we will */
2648       /* see how things go                  */
2649       sym->nRegs = 0;
2650   }
2651
2652 }
2653 static DEFSETFUNC (markRegFree)
2654 {
2655   ((regs *)item)->isFree = 1;
2656
2657   return 0;
2658 }
2659
2660 DEFSETFUNC (pic16_deallocReg)
2661 {
2662   fprintf(stderr,"deallocting register %s\n",((regs *)item)->name);
2663   ((regs *)item)->isFree = 1;
2664   ((regs *)item)->wasUsed = 0;
2665
2666   return 0;
2667 }
2668 /*-----------------------------------------------------------------*/
2669 /* freeAllRegs - mark all registers as free                        */
2670 /*-----------------------------------------------------------------*/
2671 void
2672 pic16_freeAllRegs ()
2673 {
2674   debugLog ("%s\n", __FUNCTION__);
2675
2676   applyToSet(pic16_dynAllocRegs,markRegFree);
2677   applyToSet(pic16_dynStackRegs,markRegFree);
2678 }
2679
2680 /*-----------------------------------------------------------------*/
2681 /*-----------------------------------------------------------------*/
2682 void
2683 pic16_deallocateAllRegs ()
2684 {
2685   debugLog ("%s\n", __FUNCTION__);
2686
2687   applyToSet(pic16_dynAllocRegs,pic16_deallocReg);
2688 }
2689
2690
2691 /*-----------------------------------------------------------------*/
2692 /* deallocStackSpil - this will set the stack pointer back         */
2693 /*-----------------------------------------------------------------*/
2694 static
2695 DEFSETFUNC (deallocStackSpil)
2696 {
2697   symbol *sym = item;
2698
2699   debugLog ("%s\n", __FUNCTION__);
2700   deallocLocal (sym);
2701   return 0;
2702 }
2703
2704 /*-----------------------------------------------------------------*/
2705 /* farSpacePackable - returns the packable icode for far variables */
2706 /*-----------------------------------------------------------------*/
2707 static iCode *
2708 farSpacePackable (iCode * ic)
2709 {
2710   iCode *dic;
2711
2712   debugLog ("%s\n", __FUNCTION__);
2713   /* go thru till we find a definition for the
2714      symbol on the right */
2715   for (dic = ic->prev; dic; dic = dic->prev)
2716     {
2717
2718       /* if the definition is a call then no */
2719       if ((dic->op == CALL || dic->op == PCALL) &&
2720           IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2721         {
2722           return NULL;
2723         }
2724
2725       /* if shift by unknown amount then not */
2726       if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
2727           IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2728         return NULL;
2729
2730       /* if pointer get and size > 1 */
2731       if (POINTER_GET (dic) &&
2732           getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
2733         return NULL;
2734
2735       if (POINTER_SET (dic) &&
2736           getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
2737         return NULL;
2738
2739       /* if any three is a true symbol in far space */
2740       if (IC_RESULT (dic) &&
2741           IS_TRUE_SYMOP (IC_RESULT (dic)) &&
2742           isOperandInFarSpace (IC_RESULT (dic)))
2743         return NULL;
2744
2745       if (IC_RIGHT (dic) &&
2746           IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
2747           isOperandInFarSpace (IC_RIGHT (dic)) &&
2748           !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
2749         return NULL;
2750
2751       if (IC_LEFT (dic) &&
2752           IS_TRUE_SYMOP (IC_LEFT (dic)) &&
2753           isOperandInFarSpace (IC_LEFT (dic)) &&
2754           !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
2755         return NULL;
2756
2757       if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
2758         {
2759           if ((dic->op == LEFT_OP ||
2760                dic->op == RIGHT_OP ||
2761                dic->op == '-') &&
2762               IS_OP_LITERAL (IC_RIGHT (dic)))
2763             return NULL;
2764           else
2765             return dic;
2766         }
2767     }
2768
2769   return NULL;
2770 }
2771
2772 /*-----------------------------------------------------------------*/
2773 /* packRegsForAssign - register reduction for assignment           */
2774 /*-----------------------------------------------------------------*/
2775 static int
2776 packRegsForAssign (iCode * ic, eBBlock * ebp)
2777 {
2778
2779   iCode *dic, *sic;
2780
2781   debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
2782   debugLog ("ic->op = %s\n", decodeOp( ic->op ) );
2783   debugAopGet ("  result:", IC_RESULT (ic));
2784   debugAopGet ("  left:", IC_LEFT (ic));
2785   debugAopGet ("  right:", IC_RIGHT (ic));
2786
2787 //      fprintf(stderr, "%s:%d symbol = %s\n", __FILE__, __LINE__, OP_SYMBOL( IC_RESULT(ic))->name);
2788
2789   /* if this is at an absolute address, then get the address. */
2790   if (SPEC_ABSA ( OP_SYM_ETYPE(IC_RESULT(ic))) ) {
2791     if(PIC16_IS_CONFIG_ADDRESS( SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))))) {
2792       debugLog ("  %d - found config word declaration\n", __LINE__);
2793       if(IS_VALOP(IC_RIGHT(ic))) {
2794         debugLog ("  setting config word to %x\n", 
2795                   (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
2796 //      fprintf(stderr, "  setting config word to %x\n", 
2797 //                (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
2798         pic16_assignConfigWordValue(  SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))),
2799                                 (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
2800       }
2801
2802
2803         debugLog(" %d\n", __LINE__);
2804
2805       /* remove the assignment from the iCode chain. */
2806
2807       remiCodeFromeBBlock (ebp, ic);
2808       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
2809       hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
2810
2811       return 1;
2812
2813     }
2814   }
2815         debugLog(" %d - actuall processing\n", __LINE__ );
2816
2817   if (!IS_ITEMP (IC_RESULT (ic))) {
2818     pic16_allocDirReg(IC_RESULT (ic));
2819     debugLog ("  %d - result is not temp\n", __LINE__);
2820   }
2821
2822 #if 0
2823   if (IC_LEFT (ic) && !IS_ITEMP (IC_LEFT (ic))) {
2824     debugLog ("  %d - left is not temp, allocating\n", __LINE__);
2825     pic16_allocDirReg(IC_LEFT (ic));
2826   }
2827 #endif
2828
2829 /* See BUGLOG0001 - VR */
2830 #if 1
2831   if (!IS_ITEMP (IC_RIGHT (ic))) {
2832     debugLog ("  %d - not packing - right is not temp\n", __LINE__);
2833     pic16_allocDirReg(IC_RIGHT (ic));
2834     return 0;
2835   }
2836 #endif
2837
2838   if (OP_SYMBOL (IC_RIGHT (ic))->isind ||
2839       OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
2840     {
2841       debugLog ("  %d - not packing - right side fails \n", __LINE__);
2842       return 0;
2843     }
2844
2845   /* if the true symbol is defined in far space or on stack
2846      then we should not since this will increase register pressure */
2847   if (isOperandInFarSpace (IC_RESULT (ic)))
2848     {
2849       if ((dic = farSpacePackable (ic)))
2850         goto pack;
2851       else
2852         return 0;
2853
2854     }
2855
2856   /* find the definition of iTempNN scanning backwards if we find a 
2857      a use of the true symbol before we find the definition then 
2858      we cannot pack */
2859   for (dic = ic->prev; dic; dic = dic->prev)
2860     {
2861
2862       /* if there is a function call and this is
2863          a parameter & not my parameter then don't pack it */
2864       if ((dic->op == CALL || dic->op == PCALL) &&
2865           (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
2866            !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
2867         {
2868           debugLog ("  %d - \n", __LINE__);
2869           dic = NULL;
2870           break;
2871         }
2872
2873
2874       if (SKIP_IC2 (dic))
2875         continue;
2876
2877         debugLog("%d\tSearching for iTempNN\n", __LINE__);
2878
2879 #if 0
2880         if(IS_TRUE_SYMOP( IC_RESULT(dic))) {
2881                 debugLog("%d - dic result is a TRUE_SYMOP\n", __LINE__);
2882                 debugAopGet(" result is ", IC_RESULT(dic));
2883         }
2884         if(IS_TRUE_SYMOP( IC_LEFT(dic))) {
2885                 debugLog("%d - dic left is a SYMOP\n", __LINE__);
2886                 debugAopGet("   left is ", IC_LEFT(dic));
2887         }
2888         if(IS_TRUE_SYMOP( IC_RIGHT(dic))) {
2889                 debugLog("%d - dic right is a SYMOP\n", __LINE__);
2890                 debugAopGet("  right is ", IC_RIGHT(dic));
2891         }
2892 #endif
2893
2894       if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
2895           IS_OP_VOLATILE (IC_RESULT (dic)))
2896         {
2897           debugLog ("  %d - dic is VOLATILE \n", __LINE__);
2898           dic = NULL;
2899           break;
2900         }
2901
2902 #if 0
2903       if (IS_TRUE_SYMOP( IC_RIGHT (dic)) &&
2904                 IS_OP_VOLATILE (IC_RIGHT(dic)))
2905         {
2906           debugLog ("  %d - dic right is VOLATILE\n", __LINE__);
2907           dic = NULL;
2908           break;
2909         }
2910 #endif
2911
2912 #if 0
2913       if (IS_TRUE_SYMOP( IC_LEFT (dic)) &&
2914                 IS_OP_VOLATILE (IC_LEFT(dic)))
2915         {
2916           debugLog ("  %d - dic left is VOLATILE\n", __LINE__);
2917           dic = NULL;
2918           break;
2919         }
2920 #endif
2921
2922
2923 #if 1
2924       if( IS_SYMOP( IC_RESULT(dic)) &&
2925         IS_BITFIELD( OP_SYMBOL(IC_RESULT(dic))->etype ) ) {
2926
2927           debugLog (" %d - result is bitfield\n", __LINE__);
2928           dic = NULL;
2929           break;
2930         }
2931 #endif
2932
2933       if (IS_SYMOP (IC_RESULT (dic)) &&
2934           IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2935         {
2936           /* A previous result was assigned to the same register - we'll our definition */
2937           debugLog ("  %d - dic result key == ic right key -- pointer set=%c\n",
2938                     __LINE__, ((POINTER_SET (dic)) ? 'Y' : 'N'));
2939           if (POINTER_SET (dic))
2940             dic = NULL;
2941
2942           break;
2943         }
2944
2945       if (IS_SYMOP (IC_RIGHT (dic)) &&
2946           (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
2947            IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
2948         {
2949           debugLog ("  %d - dic right key == ic rightor result key\n", __LINE__);
2950           dic = NULL;
2951           break;
2952         }
2953
2954       if (IS_SYMOP (IC_LEFT (dic)) &&
2955           (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
2956            IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
2957         {
2958           debugLog ("  %d - dic left key == ic rightor result key\n", __LINE__);
2959           dic = NULL;
2960           break;
2961         }
2962
2963       if (POINTER_SET (dic) &&
2964           IC_RESULT (dic)->key == IC_RESULT (ic)->key)
2965         {
2966           debugLog ("  %d - dic result key == ic result key -- pointer set=Y\n",
2967                     __LINE__);
2968           dic = NULL;
2969           break;
2970         }
2971     }
2972
2973   if (!dic)
2974     return 0;                   /* did not find */
2975
2976 #if 1
2977         /* This code is taken from the hc08 port. Do not know
2978          * if it fits for pic16, but I leave it here just in case */
2979
2980         /* if assignment then check that right is not a bit */
2981         if (ASSIGNMENT (dic) && !POINTER_SET (dic)) {
2982           sym_link *etype = operandType (IC_RIGHT (dic));
2983
2984                 if (IS_BITFIELD (etype)) {
2985                         /* if result is a bit too then it's ok */
2986                         etype = operandType (IC_RESULT (dic));
2987                         if (!IS_BITFIELD (etype)) {
2988                                 debugLog(" %d bitfields\n");
2989                           return 0;
2990                         }
2991                 }
2992         }
2993 #endif
2994
2995   /* if the result is on stack or iaccess then it must be
2996      the same atleast one of the operands */
2997   if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
2998       OP_SYMBOL (IC_RESULT (ic))->iaccess)
2999     {
3000
3001 #if 0
3002         /* clear the onStack flag, the port doesn't support it yet! FIXME */
3003         if(OP_SYMBOL(IC_RESULT(ic))->onStack)
3004                 OP_SYMBOL(IC_RESULT(ic))->onStack = 0;
3005 #endif
3006         
3007
3008       /* the operation has only one symbol
3009          operator then we can pack */
3010       if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
3011           (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
3012         goto pack;
3013
3014       if (!((IC_LEFT (dic) &&
3015              IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
3016             (IC_RIGHT (dic) &&
3017              IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
3018         return 0;
3019     }
3020 pack:
3021   debugLog ("  packing. removing %s\n", OP_SYMBOL (IC_RIGHT (ic))->rname);
3022   debugLog ("  replacing with %s\n", OP_SYMBOL (IC_RESULT (dic))->rname);
3023   /* found the definition */
3024   /* replace the result with the result of */
3025   /* this assignment and remove this assignment */
3026   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3027   IC_RESULT (dic) = IC_RESULT (ic);
3028
3029   if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
3030     {
3031       OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
3032     }
3033   /* delete from liverange table also 
3034      delete from all the points inbetween and the new
3035      one */
3036   for (sic = dic; sic != ic; sic = sic->next)
3037     {
3038       bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
3039       if (IS_ITEMP (IC_RESULT (dic)))
3040         bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
3041     }
3042
3043   remiCodeFromeBBlock (ebp, ic);
3044   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
3045
3046         debugLog("  %d\n", __LINE__ );
3047   hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
3048   OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
3049   return 1;
3050
3051
3052 }
3053
3054 #if 1
3055
3056 #define NO_packRegsForAccUse
3057 #define NO_packRegsForSupport
3058 #define NO_packRegsForOneuse
3059 #define NO_cast_peep
3060
3061 #endif
3062
3063
3064 #ifndef NO_packRegsForSupport
3065 /*-----------------------------------------------------------------*/
3066 /* findAssignToSym : scanning backwards looks for first assig found */
3067 /*-----------------------------------------------------------------*/
3068 static iCode *
3069 findAssignToSym (operand * op, iCode * ic)
3070 {
3071   iCode *dic;
3072
3073   debugLog ("%s\n", __FUNCTION__);
3074   for (dic = ic->prev; dic; dic = dic->prev)
3075     {
3076
3077       /* if definition by assignment */
3078       if (dic->op == '=' &&
3079           !POINTER_SET (dic) &&
3080           IC_RESULT (dic)->key == op->key
3081 /*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
3082         )
3083         {
3084
3085           /* we are interested only if defined in far space */
3086           /* or in stack space in case of + & - */
3087
3088           /* if assigned to a non-symbol then return
3089              true */
3090           if (!IS_SYMOP (IC_RIGHT (dic)))
3091             break;
3092
3093           /* if the symbol is in far space then
3094              we should not */
3095           if (isOperandInFarSpace (IC_RIGHT (dic)))
3096             return NULL;
3097
3098           /* for + & - operations make sure that
3099              if it is on the stack it is the same
3100              as one of the three operands */
3101           if ((ic->op == '+' || ic->op == '-') &&
3102               OP_SYMBOL (IC_RIGHT (dic))->onStack)
3103             {
3104
3105 #if 0
3106                 if(OP_SYMBOL(IC_RESULT(ic))->onStack)
3107                         OP_SYMBOL(IC_RESULT(ic))->onStack = 0;
3108 #endif
3109
3110               if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
3111                   IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
3112                   IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
3113                 return NULL;
3114             }
3115
3116           break;
3117
3118         }
3119
3120       /* if we find an usage then we cannot delete it */
3121       if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
3122         return NULL;
3123
3124       if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
3125         return NULL;
3126
3127       if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
3128         return NULL;
3129     }
3130
3131   /* now make sure that the right side of dic
3132      is not defined between ic & dic */
3133   if (dic)
3134     {
3135       iCode *sic = dic->next;
3136
3137       for (; sic != ic; sic = sic->next)
3138         if (IC_RESULT (sic) &&
3139             IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
3140           return NULL;
3141     }
3142
3143   return dic;
3144
3145
3146 }
3147 #endif
3148
3149
3150 #ifndef NO_packRegsForSupport
3151 /*-----------------------------------------------------------------*/
3152 /* packRegsForSupport :- reduce some registers for support calls   */
3153 /*-----------------------------------------------------------------*/
3154 static int
3155 packRegsForSupport (iCode * ic, eBBlock * ebp)
3156 {
3157   int change = 0;
3158
3159   debugLog ("%s\n", __FUNCTION__);
3160   /* for the left & right operand :- look to see if the
3161      left was assigned a true symbol in far space in that
3162      case replace them */
3163   if (IS_ITEMP (IC_LEFT (ic)) &&
3164       OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
3165     {
3166       iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
3167       iCode *sic;
3168
3169       if (!dic)
3170         goto right;
3171
3172       debugAopGet ("removing left:", IC_LEFT (ic));
3173
3174       /* found it we need to remove it from the
3175          block */
3176       for (sic = dic; sic != ic; sic = sic->next)
3177         bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
3178
3179       IC_LEFT (ic)->operand.symOperand =
3180         IC_RIGHT (dic)->operand.symOperand;
3181       IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3182       remiCodeFromeBBlock (ebp, dic);
3183       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3184       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3185       change++;
3186     }
3187
3188   /* do the same for the right operand */
3189 right:
3190   if (!change &&
3191       IS_ITEMP (IC_RIGHT (ic)) &&
3192       OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
3193     {
3194       iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
3195       iCode *sic;
3196
3197       if (!dic)
3198         return change;
3199
3200       /* if this is a subtraction & the result
3201          is a true symbol in far space then don't pack */
3202       if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
3203         {
3204           sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
3205           if (IN_FARSPACE (SPEC_OCLS (etype)))
3206             return change;
3207         }
3208
3209       debugAopGet ("removing right:", IC_RIGHT (ic));
3210
3211       /* found it we need to remove it from the
3212          block */
3213       for (sic = dic; sic != ic; sic = sic->next)
3214         bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
3215
3216       IC_RIGHT (ic)->operand.symOperand =
3217         IC_RIGHT (dic)->operand.symOperand;
3218       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3219
3220       remiCodeFromeBBlock (ebp, dic);
3221       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3222       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3223       change++;
3224     }
3225
3226   return change;
3227 }
3228 #endif
3229
3230
3231 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
3232
3233 #ifndef NO_packRegsForOneuse
3234 /*-----------------------------------------------------------------*/
3235 /* packRegsForOneuse : - will reduce some registers for single Use */
3236 /*-----------------------------------------------------------------*/
3237 static iCode *
3238 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
3239 {
3240   bitVect *uses;
3241   iCode *dic, *sic;
3242
3243   debugLog ("%s\n", __FUNCTION__);
3244   /* if returning a literal then do nothing */
3245   if (!IS_SYMOP (op))
3246     return NULL;
3247
3248   /* only upto 2 bytes since we cannot predict
3249      the usage of b, & acc */
3250   if (getSize (operandType (op)) > (pic16_fReturnSizePic - 3) &&        /* was 2, changed to 3 -- VR */
3251       ic->op != RETURN &&
3252       ic->op != SEND)
3253     return NULL;
3254
3255   /* this routine will mark the a symbol as used in one 
3256      instruction use only && if the definition is local 
3257      (ie. within the basic block) && has only one definition &&
3258      that definition is either a return value from a 
3259      function or does not contain any variables in
3260      far space */
3261   uses = bitVectCopy (OP_USES (op));
3262   bitVectUnSetBit (uses, ic->key);      /* take away this iCode */
3263   if (!bitVectIsZero (uses))    /* has other uses */
3264     return NULL;
3265
3266   /* if it has only one defintion */
3267   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
3268     return NULL;                /* has more than one definition */
3269
3270   /* get that definition */
3271   if (!(dic =
3272         hTabItemWithKey (iCodehTab,
3273                          bitVectFirstBit (OP_DEFS (op)))))
3274     return NULL;
3275
3276   /* found the definition now check if it is local */
3277   if (dic->seq < ebp->fSeq ||
3278       dic->seq > ebp->lSeq)
3279     return NULL;                /* non-local */
3280
3281   /* now check if it is the return from
3282      a function call */
3283   if (dic->op == CALL || dic->op == PCALL)
3284     {
3285       if (ic->op != SEND && ic->op != RETURN &&
3286           !POINTER_SET(ic) && !POINTER_GET(ic))
3287         {
3288           OP_SYMBOL (op)->ruonly = 1;
3289           return dic;
3290         }
3291       dic = dic->next;
3292     }
3293
3294
3295   /* otherwise check that the definition does
3296      not contain any symbols in far space */
3297   if (isOperandInFarSpace (IC_LEFT (dic)) ||
3298       isOperandInFarSpace (IC_RIGHT (dic)) ||
3299       IS_OP_RUONLY (IC_LEFT (ic)) ||
3300       IS_OP_RUONLY (IC_RIGHT (ic)))
3301     {
3302       return NULL;
3303     }
3304
3305   /* if pointer set then make sure the pointer
3306      is one byte */
3307   if (POINTER_SET (dic) &&
3308       !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3309     return NULL;
3310
3311   if (POINTER_GET (dic) &&
3312       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3313     return NULL;
3314
3315   sic = dic;
3316
3317   /* also make sure the intervenening instructions
3318      don't have any thing in far space */
3319   for (dic = dic->next; dic && dic != ic; dic = dic->next)
3320     {
3321
3322       /* if there is an intervening function call then no */
3323       if (dic->op == CALL || dic->op == PCALL)
3324         return NULL;
3325       /* if pointer set then make sure the pointer
3326          is one byte */
3327       if (POINTER_SET (dic) &&
3328           !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3329         return NULL;
3330
3331       if (POINTER_GET (dic) &&
3332           !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3333         return NULL;
3334
3335       /* if address of & the result is remat then okay */
3336       if (dic->op == ADDRESS_OF &&
3337           OP_SYMBOL (IC_RESULT (dic))->remat)
3338         continue;
3339
3340       /* if operand has size of three or more & this
3341          operation is a '*','/' or '%' then 'b' may
3342          cause a problem */
3343       if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
3344           getSize (operandType (op)) >= 3)
3345         return NULL;
3346
3347       /* if left or right or result is in far space */
3348       if (isOperandInFarSpace (IC_LEFT (dic)) ||
3349           isOperandInFarSpace (IC_RIGHT (dic)) ||
3350           isOperandInFarSpace (IC_RESULT (dic)) ||
3351           IS_OP_RUONLY (IC_LEFT (dic)) ||
3352           IS_OP_RUONLY (IC_RIGHT (dic)) ||
3353           IS_OP_RUONLY (IC_RESULT (dic)))
3354         {
3355           return NULL;
3356         }
3357     }
3358
3359   OP_SYMBOL (op)->ruonly = 1;
3360   return sic;
3361
3362 }
3363 #endif
3364
3365
3366 /*-----------------------------------------------------------------*/
3367 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
3368 /*-----------------------------------------------------------------*/
3369 static bool
3370 isBitwiseOptimizable (iCode * ic)
3371 {
3372   sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
3373   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
3374
3375   debugLog ("%s\n", __FUNCTION__);
3376   /* bitwise operations are considered optimizable
3377      under the following conditions (Jean-Louis VERN) 
3378
3379      x & lit
3380      bit & bit
3381      bit & x
3382      bit ^ bit
3383      bit ^ x
3384      x   ^ lit
3385      x   | lit
3386      bit | bit
3387      bit | x
3388    */
3389   if (IS_LITERAL (rtype) ||
3390       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
3391     return TRUE;
3392   else
3393     return FALSE;
3394 }
3395
3396
3397 #ifndef NO_packRegsForAccUse
3398
3399 /*-----------------------------------------------------------------*/
3400 /* packRegsForAccUse - pack registers for acc use                  */
3401 /*-----------------------------------------------------------------*/
3402 static void
3403 packRegsForAccUse (iCode * ic)
3404 {
3405   iCode *uic;
3406
3407   debugLog ("%s\n", __FUNCTION__);
3408
3409   /* if this is an aggregate, e.g. a one byte char array */
3410   if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
3411     return;
3412   }
3413   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3414
3415   /* if + or - then it has to be one byte result */
3416   if ((ic->op == '+' || ic->op == '-')
3417       && getSize (operandType (IC_RESULT (ic))) > 1)
3418     return;
3419
3420   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3421   /* if shift operation make sure right side is not a literal */
3422   if (ic->op == RIGHT_OP &&
3423       (isOperandLiteral (IC_RIGHT (ic)) ||
3424        getSize (operandType (IC_RESULT (ic))) > 1))
3425     return;
3426
3427   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3428   if (ic->op == LEFT_OP &&
3429       (isOperandLiteral (IC_RIGHT (ic)) ||
3430        getSize (operandType (IC_RESULT (ic))) > 1))
3431     return;
3432
3433   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3434   if (IS_BITWISE_OP (ic) &&
3435       getSize (operandType (IC_RESULT (ic))) > 1)
3436     return;
3437
3438
3439   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3440   /* has only one definition */
3441   if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
3442     return;
3443
3444   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3445   /* has only one use */
3446   if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
3447     return;
3448
3449   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3450   /* and the usage immediately follows this iCode */
3451   if (!(uic = hTabItemWithKey (iCodehTab,
3452                                bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
3453     return;
3454
3455   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3456   if (ic->next != uic)
3457     return;
3458
3459   /* if it is a conditional branch then we definitely can */
3460   if (uic->op == IFX)
3461     goto accuse;
3462
3463   if (uic->op == JUMPTABLE)
3464     return;
3465
3466   /* if the usage is not is an assignment
3467      or an arithmetic / bitwise / shift operation then not */
3468   if (POINTER_SET (uic) &&
3469       getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
3470     return;
3471
3472   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3473   if (uic->op != '=' &&
3474       !IS_ARITHMETIC_OP (uic) &&
3475       !IS_BITWISE_OP (uic) &&
3476       uic->op != LEFT_OP &&
3477       uic->op != RIGHT_OP)
3478     return;
3479
3480   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3481   /* if used in ^ operation then make sure right is not a 
3482      literl */
3483   if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
3484     return;
3485
3486   /* if shift operation make sure right side is not a literal */
3487   if (uic->op == RIGHT_OP &&
3488       (isOperandLiteral (IC_RIGHT (uic)) ||
3489        getSize (operandType (IC_RESULT (uic))) > 1))
3490     return;
3491
3492   if (uic->op == LEFT_OP &&
3493       (isOperandLiteral (IC_RIGHT (uic)) ||
3494        getSize (operandType (IC_RESULT (uic))) > 1))
3495     return;
3496
3497   /* make sure that the result of this icode is not on the
3498      stack, since acc is used to compute stack offset */
3499   if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
3500       OP_SYMBOL (IC_RESULT (uic))->onStack)
3501     return;
3502
3503   /* if either one of them in far space then we cannot */
3504   if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3505        isOperandInFarSpace (IC_LEFT (uic))) ||
3506       (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3507        isOperandInFarSpace (IC_RIGHT (uic))))
3508     return;
3509
3510   /* if the usage has only one operand then we can */
3511   if (IC_LEFT (uic) == NULL ||
3512       IC_RIGHT (uic) == NULL)
3513     goto accuse;
3514
3515   /* make sure this is on the left side if not
3516      a '+' since '+' is commutative */
3517   if (ic->op != '+' &&
3518       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
3519     return;
3520
3521 #if 1
3522   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3523   /* if one of them is a literal then we can */
3524   if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
3525         (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))  &&
3526        (getSize (operandType (IC_RESULT (uic))) <= 1))
3527     {
3528       OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3529       return;
3530     }
3531 #endif
3532
3533   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3534   /* if the other one is not on stack then we can */
3535   if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
3536       (IS_ITEMP (IC_RIGHT (uic)) ||
3537        (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3538         !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
3539     goto accuse;
3540
3541   if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
3542       (IS_ITEMP (IC_LEFT (uic)) ||
3543        (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3544         !OP_SYMBOL (IC_LEFT (uic))->onStack)))
3545     goto accuse;
3546
3547   return;
3548
3549 accuse:
3550   debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
3551   OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3552
3553
3554 }
3555 #endif
3556
3557
3558 /*-----------------------------------------------------------------*/
3559 /* packForPush - hueristics to reduce iCode for pushing            */
3560 /*-----------------------------------------------------------------*/
3561 static void
3562 packForReceive (iCode * ic, eBBlock * ebp)
3563 {
3564   iCode *dic;
3565
3566   debugLog ("%s\n", __FUNCTION__);
3567   debugAopGet ("  result:", IC_RESULT (ic));
3568   debugAopGet ("  left:", IC_LEFT (ic));
3569   debugAopGet ("  right:", IC_RIGHT (ic));
3570
3571   if (!ic->next)
3572     return;
3573
3574   for (dic = ic->next; dic; dic = dic->next)
3575     {
3576
3577
3578
3579       if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
3580         debugLog ("    used on left\n");
3581       if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
3582         debugLog ("    used on right\n");
3583       if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
3584         debugLog ("    used on result\n");
3585
3586       if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
3587           (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
3588         return;
3589
3590     }
3591
3592   debugLog ("  hey we can remove this unnecessary assign\n");
3593 }
3594 /*-----------------------------------------------------------------*/
3595 /* packForPush - hueristics to reduce iCode for pushing            */
3596 /*-----------------------------------------------------------------*/
3597 static void
3598 packForPush (iCode * ic, eBBlock * ebp)
3599 {
3600   iCode *dic;
3601
3602   debugLog ("%s\n", __FUNCTION__);
3603   if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
3604     return;
3605
3606   /* must have only definition & one usage */
3607   if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
3608       bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
3609     return;
3610
3611   /* find the definition */
3612   if (!(dic = hTabItemWithKey (iCodehTab,
3613                                bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
3614     return;
3615
3616   if (dic->op != '=' || POINTER_SET (dic))
3617     return;
3618
3619   /* we now we know that it has one & only one def & use
3620      and the that the definition is an assignment */
3621   IC_LEFT (ic) = IC_RIGHT (dic);
3622
3623   remiCodeFromeBBlock (ebp, dic);
3624   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3625   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3626 }
3627
3628 static void printSymType(char * str, sym_link *sl)
3629 {
3630         if(!pic16_ralloc_debug)return;
3631         
3632         debugLog ("    %s Symbol type: ",str);
3633         printTypeChain( sl, debugF);
3634         debugLog ("\n");
3635 }
3636
3637 /*-----------------------------------------------------------------*/
3638 /* some debug code to print the symbol S_TYPE. Note that
3639  * the function checkSClass in src/SDCCsymt.c dinks with
3640  * the S_TYPE in ways the PIC port doesn't fully like...*/
3641 /*-----------------------------------------------------------------*/
3642 static void isData(sym_link *sl)
3643 {
3644   FILE *of = stderr;
3645
3646         if(!pic16_ralloc_debug)return;
3647         
3648         if(!sl)return;
3649
3650         if(debugF)
3651                 of = debugF;
3652
3653         for ( ; sl; sl=sl->next) {
3654                 if(!IS_DECL(sl) ) {
3655                         switch (SPEC_SCLS(sl)) {
3656                                 case S_DATA: fprintf (of, "data "); break;
3657                                 case S_XDATA: fprintf (of, "xdata "); break;
3658                                 case S_SFR: fprintf (of, "sfr "); break;
3659                                 case S_SBIT: fprintf (of, "sbit "); break;
3660                                 case S_CODE: fprintf (of, "code "); break;
3661                                 case S_IDATA: fprintf (of, "idata "); break;
3662                                 case S_PDATA: fprintf (of, "pdata "); break;
3663                                 case S_LITERAL: fprintf (of, "literal "); break;
3664                                 case S_STACK: fprintf (of, "stack "); break;
3665                                 case S_XSTACK: fprintf (of, "xstack "); break;
3666                                 case S_BIT: fprintf (of, "bit "); break;
3667                                 case S_EEPROM: fprintf (of, "eeprom "); break;
3668                                 default: break;
3669                         }
3670
3671                 }
3672         }
3673 }
3674
3675
3676 /*--------------------------------------------------------------------*/
3677 /* pic16_packRegisters - does some transformations to reduce          */
3678 /*                   register pressure                                */
3679 /*                                                                    */
3680 /*--------------------------------------------------------------------*/
3681 static void
3682 pic16_packRegisters (eBBlock * ebp)
3683 {
3684   iCode *ic;
3685   int change = 0;
3686
3687   debugLog ("%s\n", __FUNCTION__);
3688
3689   while (1) {
3690
3691     change = 0;
3692
3693     /* look for assignments of the form */
3694     /* iTempNN = TRueSym (someoperation) SomeOperand */
3695     /*       ....                       */
3696     /* TrueSym := iTempNN:1             */
3697     for (ic = ebp->sch; ic; ic = ic->next)
3698       {
3699 //              debugLog("%d\n", __LINE__);
3700         /* find assignment of the form TrueSym := iTempNN:1 */
3701         /* see BUGLOG0001 for workaround with the CAST - VR */
3702 //      if ( (ic->op == '=' || ic->op == CAST) && !POINTER_SET (ic) ) // patch 11
3703         if ( (ic->op == '=') && !POINTER_SET (ic) ) // patch 11
3704           change += packRegsForAssign (ic, ebp);
3705         /* debug stuff */
3706         if (ic->op == '=')
3707           {
3708             if (POINTER_SET (ic))
3709               debugLog ("pointer is set\n");
3710             debugAopGet ("  result:", IC_RESULT (ic));
3711             debugAopGet ("  left:", IC_LEFT (ic));
3712             debugAopGet ("  right:", IC_RIGHT (ic));
3713           }
3714
3715       }
3716
3717     if (!change)
3718       break;
3719   }
3720
3721   for (ic = ebp->sch; ic; ic = ic->next) {
3722
3723     if(IS_SYMOP ( IC_LEFT(ic))) {
3724       sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
3725
3726       debugAopGet ("x  left:", IC_LEFT (ic));
3727 #if 0
3728       if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
3729 #else
3730       if(IS_CODEPTR(OP_SYMBOL(IC_LEFT(ic))->type))
3731 #endif
3732         debugLog ("    is a pointer\n");
3733
3734       if(IS_PTR(OP_SYMBOL(IC_LEFT(ic))->type))
3735         debugLog ("    is a ptr\n");
3736
3737       if(IS_OP_VOLATILE(IC_LEFT(ic)))
3738         debugLog ("    is volatile\n");
3739
3740       isData(etype);
3741
3742         if(IS_OP_VOLATILE(IC_LEFT(ic))) {
3743             debugLog ("  %d - left is not temp, allocating\n", __LINE__);
3744             pic16_allocDirReg(IC_LEFT (ic));
3745         }
3746
3747       printSymType("c  ", OP_SYMBOL(IC_LEFT(ic))->type);
3748     }
3749
3750     if(IS_SYMOP ( IC_RIGHT(ic))) {
3751       debugAopGet ("  right:", IC_RIGHT (ic));
3752       printSymType("    ", OP_SYMBOL(IC_RIGHT(ic))->type);
3753     }
3754
3755     if(IS_SYMOP ( IC_RESULT(ic))) {
3756       debugAopGet ("  result:", IC_RESULT (ic));
3757       printSymType("     ", OP_SYMBOL(IC_RESULT(ic))->type);
3758     }
3759
3760     if(IS_TRUE_SYMOP ( IC_RIGHT(ic))) {
3761       debugAopGet ("  right:", IC_RIGHT (ic));
3762       printSymType("    ", OP_SYMBOL(IC_RIGHT(ic))->type);
3763 //      pic16_allocDirReg(IC_RIGHT(ic));
3764     }
3765
3766     if(IS_TRUE_SYMOP ( IC_RESULT(ic))) {
3767       debugAopGet ("  result:", IC_RESULT (ic));
3768       printSymType("     ", OP_SYMBOL(IC_RESULT(ic))->type);
3769 //      pic16_allocDirReg(IC_RESULT(ic));
3770     }
3771
3772
3773     if (POINTER_SET (ic))
3774         debugLog ("  %d - Pointer set\n", __LINE__);
3775
3776
3777     /* if this is an itemp & result of a address of a true sym 
3778        then mark this as rematerialisable   */
3779     if (ic->op == ADDRESS_OF &&
3780         IS_ITEMP (IC_RESULT (ic)) &&
3781         IS_TRUE_SYMOP (IC_LEFT (ic)) &&
3782         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
3783         !OP_SYMBOL (IC_LEFT (ic))->onStack)
3784       {
3785
3786         debugLog ("  %d - %s. result is rematerializable\n", __LINE__,__FUNCTION__);
3787
3788         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
3789         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
3790         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
3791
3792       }
3793
3794     /* if straight assignment then carry remat flag if
3795        this is the only definition */
3796     if (ic->op == '=' &&
3797         !POINTER_SET (ic) &&
3798         IS_SYMOP (IC_RIGHT (ic)) &&
3799         OP_SYMBOL (IC_RIGHT (ic))->remat &&
3800         bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
3801       {
3802         debugLog ("  %d - %s. straight rematerializable\n", __LINE__,__FUNCTION__);
3803
3804         OP_SYMBOL (IC_RESULT (ic))->remat =
3805           OP_SYMBOL (IC_RIGHT (ic))->remat;
3806         OP_SYMBOL (IC_RESULT (ic))->rematiCode =
3807           OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
3808       }
3809
3810     /* if this is a +/- operation with a rematerizable 
3811        then mark this as rematerializable as well */
3812     if ((ic->op == '+' || ic->op == '-') &&
3813         (IS_SYMOP (IC_LEFT (ic)) &&
3814          IS_ITEMP (IC_RESULT (ic)) &&
3815          OP_SYMBOL (IC_LEFT (ic))->remat &&
3816          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
3817          IS_OP_LITERAL (IC_RIGHT (ic))))
3818       {
3819         debugLog ("  %d - %s. rematerializable because op is +/-\n", __LINE__,__FUNCTION__);
3820         //int i = 
3821         operandLitValue (IC_RIGHT (ic));
3822         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
3823         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
3824         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
3825       }
3826
3827     /* mark the pointer usages */
3828     if (POINTER_SET (ic))
3829       {
3830         OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
3831         debugLog ("  marking as a pointer (set) =>");
3832         debugAopGet ("  result:", IC_RESULT (ic));
3833       }
3834     if (POINTER_GET (ic))
3835       {
3836         OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
3837         debugLog ("  marking as a pointer (get) =>");
3838         debugAopGet ("  left:", IC_LEFT (ic));
3839       }
3840
3841         //debugLog("  %d   %s\n", __LINE__, __FUNCTION__);
3842
3843     if (!SKIP_IC2 (ic))
3844       {
3845         //debugLog("  %d   %s\n", __LINE__, __FUNCTION__ );
3846         /* if we are using a symbol on the stack
3847            then we should say pic16_ptrRegReq */
3848         if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
3849           pic16_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
3850                                OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
3851         else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
3852           pic16_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
3853                                OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
3854         else
3855           {
3856
3857                 //debugLog("   %d   %s\n", __LINE__, __FUNCTION__ );
3858             if (IS_SYMOP (IC_LEFT (ic)))
3859               pic16_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
3860                                    OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
3861             if (IS_SYMOP (IC_RIGHT (ic)))
3862               pic16_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
3863                                    OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
3864             if (IS_SYMOP (IC_RESULT (ic)))
3865               pic16_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
3866                                    OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
3867           }
3868
3869         debugLog ("  %d - pointer reg req = %d\n", __LINE__,pic16_ptrRegReq);
3870
3871       }
3872
3873     /* if the condition of an if instruction
3874        is defined in the previous instruction then
3875        mark the itemp as a conditional */
3876     if ((IS_CONDITIONAL (ic) ||
3877          ((ic->op == BITWISEAND ||
3878            ic->op == '|' ||
3879            ic->op == '^') &&
3880           isBitwiseOptimizable (ic))) &&
3881         ic->next && ic->next->op == IFX &&
3882         isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
3883         OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
3884       {
3885
3886         debugLog ("  %d\n", __LINE__);
3887         OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
3888         continue;
3889       }
3890
3891         debugLog(" %d\n", __LINE__);
3892
3893 #ifndef NO_packRegsForSupport
3894     /* reduce for support function calls */
3895     if (ic->supportRtn || ic->op == '+' || ic->op == '-')
3896       packRegsForSupport (ic, ebp);
3897 #endif
3898
3899     /* if a parameter is passed, it's in W, so we may not
3900        need to place a copy in a register */
3901     if (ic->op == RECEIVE)
3902       packForReceive (ic, ebp);
3903
3904 #ifndef NO_packRegsForOneuse
3905     /* some cases the redundant moves can
3906        can be eliminated for return statements */
3907     if ((ic->op == RETURN || ic->op == SEND) &&
3908         !isOperandInFarSpace (IC_LEFT (ic)) &&
3909         !options.model)
3910       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
3911 #endif
3912
3913 #ifndef NO_packRegsForOneuse
3914     /* if pointer set & left has a size more than
3915        one and right is not in far space */
3916     if (POINTER_SET (ic) &&
3917         !isOperandInFarSpace (IC_RIGHT (ic)) &&
3918         !OP_SYMBOL (IC_RESULT (ic))->remat &&
3919         !IS_OP_RUONLY (IC_RIGHT (ic)) &&
3920         getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
3921
3922       packRegsForOneuse (ic, IC_RESULT (ic), ebp);
3923 #endif
3924
3925 #ifndef NO_packRegsForOneuse
3926     /* if pointer get */
3927     if (POINTER_GET (ic) &&
3928         !isOperandInFarSpace (IC_RESULT (ic)) &&
3929         !OP_SYMBOL (IC_LEFT (ic))->remat &&
3930         !IS_OP_RUONLY (IC_RESULT (ic)) &&
3931         getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
3932
3933       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
3934       debugLog("%d - return from packRegsForOneuse\n", __LINE__);
3935 #endif
3936
3937 #ifndef NO_cast_peep
3938     /* if this is cast for intergral promotion then
3939        check if only use of  the definition of the 
3940        operand being casted/ if yes then replace
3941        the result of that arithmetic operation with 
3942        this result and get rid of the cast */
3943     if (ic->op == CAST) {
3944         
3945       sym_link *fromType = operandType (IC_RIGHT (ic));
3946       sym_link *toType = operandType (IC_LEFT (ic));
3947
3948       debugLog ("  %d - casting\n", __LINE__);
3949
3950       if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
3951           getSize (fromType) != getSize (toType)) {
3952             
3953
3954         iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
3955         if (dic) {
3956                 
3957           if (IS_ARITHMETIC_OP (dic)) {
3958                     debugLog("   %d   %s\n", __LINE__, __FUNCTION__ );
3959                     
3960             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3961             IC_RESULT (dic) = IC_RESULT (ic);
3962             remiCodeFromeBBlock (ebp, ic);
3963             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
3964             hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
3965             OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
3966             ic = ic->prev;
3967           }  else
3968                 
3969             OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
3970         }
3971       } else {
3972
3973         /* if the type from and type to are the same
3974            then if this is the only use then packit */
3975         if (compareType (operandType (IC_RIGHT (ic)),
3976                          operandType (IC_LEFT (ic))) == 1) {
3977                 
3978           iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
3979           if (dic) {
3980
3981                    debugLog(" %d\n", __LINE__);
3982
3983             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3984             IC_RESULT (dic) = IC_RESULT (ic);
3985             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
3986             remiCodeFromeBBlock (ebp, ic);
3987             hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
3988             OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
3989             ic = ic->prev;
3990           }
3991         }
3992       }
3993     }
3994 #endif
3995     /* pack for PUSH 
3996        iTempNN := (some variable in farspace) V1
3997        push iTempNN ;
3998        -------------
3999        push V1
4000     */
4001     if (ic->op == IPUSH)
4002       {
4003         packForPush (ic, ebp);
4004       }
4005
4006
4007 #ifndef NO_packRegsForAccUse
4008     /* pack registers for accumulator use, when the
4009        result of an arithmetic or bit wise operation
4010        has only one use, that use is immediately following
4011        the defintion and the using iCode has only one
4012        operand or has two operands but one is literal &
4013        the result of that operation is not on stack then
4014        we can leave the result of this operation in acc:b
4015        combination */
4016     if ((IS_ARITHMETIC_OP (ic)
4017
4018          || IS_BITWISE_OP (ic)
4019
4020          || ic->op == LEFT_OP || ic->op == RIGHT_OP
4021
4022          ) &&
4023         IS_ITEMP (IC_RESULT (ic)) &&
4024         getSize (operandType (IC_RESULT (ic))) <= 1)
4025
4026       packRegsForAccUse (ic);
4027 #endif
4028
4029   }
4030 }
4031
4032 static void
4033 dumpEbbsToDebug (eBBlock ** ebbs, int count)
4034 {
4035   int i;
4036
4037   if (!pic16_ralloc_debug || !debugF)
4038     return;
4039
4040   for (i = 0; i < count; i++)
4041     {
4042       fprintf (debugF, "\n----------------------------------------------------------------\n");
4043       fprintf (debugF, "Basic Block %s : loop Depth = %d noPath = %d , lastinLoop = %d\n",
4044                ebbs[i]->entryLabel->name,
4045                ebbs[i]->depth,
4046                ebbs[i]->noPath,
4047                ebbs[i]->isLastInLoop);
4048       fprintf (debugF, "depth 1st num %d : bbnum = %d 1st iCode = %d , last iCode = %d\n",
4049                ebbs[i]->dfnum,
4050                ebbs[i]->bbnum,
4051                ebbs[i]->fSeq,
4052                ebbs[i]->lSeq);
4053       fprintf (debugF, "visited %d : hasFcall = %d\n",
4054                ebbs[i]->visited,
4055                ebbs[i]->hasFcall);
4056
4057       fprintf (debugF, "\ndefines bitVector :");
4058       bitVectDebugOn (ebbs[i]->defSet, debugF);
4059       fprintf (debugF, "\nlocal defines bitVector :");
4060       bitVectDebugOn (ebbs[i]->ldefs, debugF);
4061       fprintf (debugF, "\npointers Set bitvector :");
4062       bitVectDebugOn (ebbs[i]->ptrsSet, debugF);
4063       fprintf (debugF, "\nin pointers Set bitvector :");
4064       bitVectDebugOn (ebbs[i]->inPtrsSet, debugF);
4065       fprintf (debugF, "\ninDefs Set bitvector :");
4066       bitVectDebugOn (ebbs[i]->inDefs, debugF);
4067       fprintf (debugF, "\noutDefs Set bitvector :");
4068       bitVectDebugOn (ebbs[i]->outDefs, debugF);
4069       fprintf (debugF, "\nusesDefs Set bitvector :");
4070       bitVectDebugOn (ebbs[i]->usesDefs, debugF);
4071       fprintf (debugF, "\n----------------------------------------------------------------\n");
4072       printiCChain (ebbs[i]->sch, debugF);
4073     }
4074 }
4075 /*-----------------------------------------------------------------*/
4076 /* pic16_assignRegisters - assigns registers to each live range as need  */
4077 /*-----------------------------------------------------------------*/
4078 void
4079 pic16_assignRegisters (eBBlock ** ebbs, int count)
4080 {
4081   iCode *ic;
4082   int i;
4083
4084   debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s", __FILE__, __FUNCTION__);
4085   debugLog ("\nebbs before optimizing:\n");
4086   dumpEbbsToDebug (ebbs, count);
4087
4088   setToNull ((void *) &_G.funcrUsed);
4089   pic16_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
4090
4091
4092   /* change assignments this will remove some
4093      live ranges reducing some register pressure */
4094   for (i = 0; i < count; i++)
4095     pic16_packRegisters (ebbs[i]);
4096
4097   {
4098     regs *reg;
4099     int hkey;
4100     int i=0;
4101
4102     debugLog("dir registers allocated so far:\n");
4103     reg = hTabFirstItem(dynDirectRegNames, &hkey);
4104
4105     while(reg) {
4106       debugLog("  -- #%d reg = %s  key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4107 //      fprintf(stderr, "  -- #%d reg = %s  key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4108       reg = hTabNextItem(dynDirectRegNames, &hkey);
4109     }
4110
4111   }
4112
4113   /* liveranges probably changed by register packing
4114      so we compute them again */
4115   recomputeLiveRanges (ebbs, count);
4116
4117   if (options.dump_pack)
4118     dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
4119
4120   /* first determine for each live range the number of 
4121      registers & the type of registers required for each */
4122   regTypeNum ();
4123
4124   /* and serially allocate registers */
4125   serialRegAssign (ebbs, count);
4126
4127 //  debugLog ("ebbs after serialRegAssign:\n");
4128 //  dumpEbbsToDebug (ebbs, count);
4129
4130
4131   //pic16_freeAllRegs();
4132
4133   /* if stack was extended then tell the user */
4134   if (_G.stackExtend)
4135     {
4136 /*      werror(W_TOOMANY_SPILS,"stack", */
4137 /*             _G.stackExtend,currFunc->name,""); */
4138       _G.stackExtend = 0;
4139     }
4140
4141   if (_G.dataExtend)
4142     {
4143 /*      werror(W_TOOMANY_SPILS,"data space", */
4144 /*             _G.dataExtend,currFunc->name,""); */
4145       _G.dataExtend = 0;
4146     }
4147
4148   /* after that create the register mask
4149      for each of the instruction */
4150   createRegMask (ebbs, count);
4151
4152   /* redo that offsets for stacked automatic variables */
4153   redoStackOffsets ();
4154
4155   if (options.dump_rassgn)
4156     dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
4157
4158   /* now get back the chain */
4159   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
4160
4161   debugLog ("ebbs after optimizing:\n");
4162   dumpEbbsToDebug (ebbs, count);
4163
4164
4165   genpic16Code (ic);
4166
4167   /* free up any _G.stackSpil locations allocated */
4168   applyToSet (_G.stackSpil, deallocStackSpil);
4169   _G.slocNum = 0;
4170   setToNull ((void *) &_G.stackSpil);
4171   setToNull ((void *) &_G.spiltSet);
4172   /* mark all registers as free */
4173   pic16_freeAllRegs ();
4174
4175   debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
4176   debugLogClose ();
4177   return;
4178 }