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