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