* src/pic16/device.c (Pics16[]): added devices 18F2550, 18F4331,
[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 < 0x80)
931                         || (reg->address >= 0xf80 && 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 }
3207
3208
3209 #if 1
3210
3211 #define NO_packRegsForAccUse
3212 #define NO_packRegsForSupport
3213 #define NO_packRegsForOneuse
3214 #define NO_cast_peep
3215
3216 #endif
3217
3218
3219 #ifndef NO_packRegsForSupport
3220 /*-----------------------------------------------------------------*/
3221 /* findAssignToSym : scanning backwards looks for first assig found */
3222 /*-----------------------------------------------------------------*/
3223 static iCode *
3224 findAssignToSym (operand * op, iCode * ic)
3225 {
3226   iCode *dic;
3227
3228   debugLog ("%s\n", __FUNCTION__);
3229   for (dic = ic->prev; dic; dic = dic->prev)
3230     {
3231
3232       /* if definition by assignment */
3233       if (dic->op == '=' &&
3234           !POINTER_SET (dic) &&
3235           IC_RESULT (dic)->key == op->key
3236 /*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
3237         )
3238         {
3239
3240           /* we are interested only if defined in far space */
3241           /* or in stack space in case of + & - */
3242
3243           /* if assigned to a non-symbol then return
3244              true */
3245           if (!IS_SYMOP (IC_RIGHT (dic)))
3246             break;
3247
3248           /* if the symbol is in far space then
3249              we should not */
3250           if (isOperandInFarSpace (IC_RIGHT (dic)))
3251             return NULL;
3252
3253           /* for + & - operations make sure that
3254              if it is on the stack it is the same
3255              as one of the three operands */
3256           if ((ic->op == '+' || ic->op == '-') &&
3257               OP_SYMBOL (IC_RIGHT (dic))->onStack)
3258             {
3259               if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
3260                   IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
3261                   IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
3262                 return NULL;
3263             }
3264
3265           break;
3266
3267         }
3268
3269       /* if we find an usage then we cannot delete it */
3270       if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
3271         return NULL;
3272
3273       if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
3274         return NULL;
3275
3276       if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
3277         return NULL;
3278     }
3279
3280   /* now make sure that the right side of dic
3281      is not defined between ic & dic */
3282   if (dic)
3283     {
3284       iCode *sic = dic->next;
3285
3286       for (; sic != ic; sic = sic->next)
3287         if (IC_RESULT (sic) &&
3288             IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
3289           return NULL;
3290     }
3291
3292   return dic;
3293
3294
3295 }
3296 #endif
3297
3298
3299 #ifndef NO_packRegsForSupport
3300 /*-----------------------------------------------------------------*/
3301 /* packRegsForSupport :- reduce some registers for support calls   */
3302 /*-----------------------------------------------------------------*/
3303 static int
3304 packRegsForSupport (iCode * ic, eBBlock * ebp)
3305 {
3306   int change = 0;
3307
3308   debugLog ("%s\n", __FUNCTION__);
3309   /* for the left & right operand :- look to see if the
3310      left was assigned a true symbol in far space in that
3311      case replace them */
3312   if (IS_ITEMP (IC_LEFT (ic)) &&
3313       OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
3314     {
3315       iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
3316       iCode *sic;
3317
3318       if (!dic)
3319         goto right;
3320
3321       debugAopGet ("removing left:", IC_LEFT (ic));
3322
3323       /* found it we need to remove it from the
3324          block */
3325       for (sic = dic; sic != ic; sic = sic->next)
3326         bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
3327
3328       IC_LEFT (ic)->operand.symOperand =
3329         IC_RIGHT (dic)->operand.symOperand;
3330       IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3331       remiCodeFromeBBlock (ebp, dic);
3332       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3333       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3334       change++;
3335     }
3336
3337   /* do the same for the right operand */
3338 right:
3339   if (!change &&
3340       IS_ITEMP (IC_RIGHT (ic)) &&
3341       OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
3342     {
3343       iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
3344       iCode *sic;
3345
3346       if (!dic)
3347         return change;
3348
3349       /* if this is a subtraction & the result
3350          is a true symbol in far space then don't pack */
3351       if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
3352         {
3353           sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
3354           if (IN_FARSPACE (SPEC_OCLS (etype)))
3355             return change;
3356         }
3357
3358       debugAopGet ("removing right:", IC_RIGHT (ic));
3359
3360       /* found it we need to remove it from the
3361          block */
3362       for (sic = dic; sic != ic; sic = sic->next)
3363         bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
3364
3365       IC_RIGHT (ic)->operand.symOperand =
3366         IC_RIGHT (dic)->operand.symOperand;
3367       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3368
3369       remiCodeFromeBBlock (ebp, dic);
3370       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3371       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3372       change++;
3373     }
3374
3375   return change;
3376 }
3377 #endif
3378
3379
3380 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
3381
3382 #ifndef NO_packRegsForOneuse
3383 /*-----------------------------------------------------------------*/
3384 /* packRegsForOneuse : - will reduce some registers for single Use */
3385 /*-----------------------------------------------------------------*/
3386 static iCode *
3387 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
3388 {
3389   bitVect *uses;
3390   iCode *dic, *sic;
3391
3392   debugLog ("%s\n", __FUNCTION__);
3393   /* if returning a literal then do nothing */
3394   if (!IS_SYMOP (op))
3395     return NULL;
3396
3397   if(OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly)
3398     return NULL;
3399
3400   /* only upto 2 bytes since we cannot predict
3401      the usage of b, & acc */
3402   if (getSize (operandType (op)) > (pic16_fReturnSizePic - 1)
3403       && ic->op != RETURN
3404       && ic->op != SEND
3405       && !POINTER_SET(ic)
3406       && !POINTER_GET(ic)
3407       )
3408     return NULL;
3409
3410   /* this routine will mark the a symbol as used in one 
3411      instruction use only && if the definition is local 
3412      (ie. within the basic block) && has only one definition &&
3413      that definition is either a return value from a 
3414      function or does not contain any variables in
3415      far space */
3416
3417 #if 0
3418   uses = bitVectCopy (OP_USES (op));
3419   bitVectUnSetBit (uses, ic->key);      /* take away this iCode */
3420   if (!bitVectIsZero (uses))    /* has other uses */
3421     return NULL;
3422 #endif
3423
3424 #if 1
3425   if (bitVectnBitsOn (OP_USES (op)) > 1)
3426     return NULL;
3427 #endif
3428
3429   /* if it has only one defintion */
3430   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
3431     return NULL;                /* has more than one definition */
3432
3433   /* get that definition */
3434   if (!(dic =
3435         hTabItemWithKey (iCodehTab,
3436                          bitVectFirstBit (OP_DEFS (op)))))
3437     return NULL;
3438
3439   /* found the definition now check if it is local */
3440   if (dic->seq < ebp->fSeq ||
3441       dic->seq > ebp->lSeq)
3442     return NULL;                /* non-local */
3443
3444   /* now check if it is the return from
3445      a function call */
3446   if (dic->op == CALL || dic->op == PCALL)
3447     {
3448       if (ic->op != SEND && ic->op != RETURN &&
3449           !POINTER_SET(ic) && !POINTER_GET(ic))
3450         {
3451           OP_SYMBOL (op)->ruonly = 1;
3452           return dic;
3453         }
3454       dic = dic->next;
3455     }
3456   else
3457     {
3458
3459
3460   /* otherwise check that the definition does
3461      not contain any symbols in far space */
3462   if (isOperandInFarSpace (IC_LEFT (dic)) ||
3463       isOperandInFarSpace (IC_RIGHT (dic)) ||
3464       IS_OP_RUONLY (IC_LEFT (ic)) ||
3465       IS_OP_RUONLY (IC_RIGHT (ic)))
3466     {
3467       return NULL;
3468     }
3469
3470   /* if pointer set then make sure the pointer
3471      is one byte */
3472   if (POINTER_SET (dic) &&
3473       !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3474     return NULL;
3475
3476   if (POINTER_GET (dic) &&
3477       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3478     return NULL;
3479     }
3480
3481   sic = dic;
3482
3483   /* also make sure the intervenening instructions
3484      don't have any thing in far space */
3485   for (dic = dic->next; dic && dic != ic; dic = dic->next)
3486     {
3487
3488       /* if there is an intervening function call then no */
3489       if (dic->op == CALL || dic->op == PCALL)
3490         return NULL;
3491       /* if pointer set then make sure the pointer
3492          is one byte */
3493       if (POINTER_SET (dic) &&
3494           !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3495         return NULL;
3496
3497       if (POINTER_GET (dic) &&
3498           !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3499         return NULL;
3500
3501       /* if address of & the result is remat then okay */
3502       if (dic->op == ADDRESS_OF &&
3503           OP_SYMBOL (IC_RESULT (dic))->remat)
3504         continue;
3505
3506       /* if operand has size of three or more & this
3507          operation is a '*','/' or '%' then 'b' may
3508          cause a problem */
3509       if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
3510           getSize (operandType (op)) >= 2)
3511         return NULL;
3512
3513       /* if left or right or result is in far space */
3514       if (isOperandInFarSpace (IC_LEFT (dic)) ||
3515           isOperandInFarSpace (IC_RIGHT (dic)) ||
3516           isOperandInFarSpace (IC_RESULT (dic)) ||
3517           IS_OP_RUONLY (IC_LEFT (dic)) ||
3518           IS_OP_RUONLY (IC_RIGHT (dic)) ||
3519           IS_OP_RUONLY (IC_RESULT (dic)))
3520         {
3521           return NULL;
3522         }
3523     }
3524
3525   OP_SYMBOL (op)->ruonly = 1;
3526   return sic;
3527
3528 }
3529 #endif
3530
3531
3532 /*-----------------------------------------------------------------*/
3533 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
3534 /*-----------------------------------------------------------------*/
3535 static bool
3536 isBitwiseOptimizable (iCode * ic)
3537 {
3538   sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
3539   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
3540
3541   debugLog ("%s\n", __FUNCTION__);
3542   /* bitwise operations are considered optimizable
3543      under the following conditions (Jean-Louis VERN) 
3544
3545      x & lit
3546      bit & bit
3547      bit & x
3548      bit ^ bit
3549      bit ^ x
3550      x   ^ lit
3551      x   | lit
3552      bit | bit
3553      bit | x
3554    */
3555   if (IS_LITERAL (rtype) ||
3556       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
3557     return TRUE;
3558   else
3559     return FALSE;
3560 }
3561
3562
3563 #ifndef NO_packRegsForAccUse
3564
3565 /*-----------------------------------------------------------------*/
3566 /* packRegsForAccUse - pack registers for acc use                  */
3567 /*-----------------------------------------------------------------*/
3568 static void
3569 packRegsForAccUse (iCode * ic)
3570 {
3571   iCode *uic;
3572
3573   debugLog ("%s\n", __FUNCTION__);
3574
3575   /* if this is an aggregate, e.g. a one byte char array */
3576   if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
3577     return;
3578   }
3579   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3580
3581   /* if + or - then it has to be one byte result */
3582   if ((ic->op == '+' || ic->op == '-')
3583       && getSize (operandType (IC_RESULT (ic))) > 1)
3584     return;
3585
3586   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3587   /* if shift operation make sure right side is not a literal */
3588   if (ic->op == RIGHT_OP &&
3589       (isOperandLiteral (IC_RIGHT (ic)) ||
3590        getSize (operandType (IC_RESULT (ic))) > 1))
3591     return;
3592
3593   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3594   if (ic->op == LEFT_OP &&
3595       (isOperandLiteral (IC_RIGHT (ic)) ||
3596        getSize (operandType (IC_RESULT (ic))) > 1))
3597     return;
3598
3599   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3600   if (IS_BITWISE_OP (ic) &&
3601       getSize (operandType (IC_RESULT (ic))) > 1)
3602     return;
3603
3604
3605   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3606   /* has only one definition */
3607   if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
3608     return;
3609
3610   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3611   /* has only one use */
3612   if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
3613     return;
3614
3615   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3616   /* and the usage immediately follows this iCode */
3617   if (!(uic = hTabItemWithKey (iCodehTab,
3618                                bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
3619     return;
3620
3621   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3622   if (ic->next != uic)
3623     return;
3624
3625   /* if it is a conditional branch then we definitely can */
3626   if (uic->op == IFX)
3627     goto accuse;
3628
3629   if (uic->op == JUMPTABLE)
3630     return;
3631
3632   /* if the usage is not is an assignment
3633      or an arithmetic / bitwise / shift operation then not */
3634   if (POINTER_SET (uic) &&
3635       getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
3636     return;
3637
3638   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3639   if (uic->op != '=' &&
3640       !IS_ARITHMETIC_OP (uic) &&
3641       !IS_BITWISE_OP (uic) &&
3642       uic->op != LEFT_OP &&
3643       uic->op != RIGHT_OP)
3644     return;
3645
3646   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3647   /* if used in ^ operation then make sure right is not a 
3648      literl */
3649   if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
3650     return;
3651
3652   /* if shift operation make sure right side is not a literal */
3653   if (uic->op == RIGHT_OP &&
3654       (isOperandLiteral (IC_RIGHT (uic)) ||
3655        getSize (operandType (IC_RESULT (uic))) > 1))
3656     return;
3657
3658   if (uic->op == LEFT_OP &&
3659       (isOperandLiteral (IC_RIGHT (uic)) ||
3660        getSize (operandType (IC_RESULT (uic))) > 1))
3661     return;
3662
3663   /* make sure that the result of this icode is not on the
3664      stack, since acc is used to compute stack offset */
3665   if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
3666       OP_SYMBOL (IC_RESULT (uic))->onStack)
3667     return;
3668
3669   /* if either one of them in far space then we cannot */
3670   if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3671        isOperandInFarSpace (IC_LEFT (uic))) ||
3672       (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3673        isOperandInFarSpace (IC_RIGHT (uic))))
3674     return;
3675
3676   /* if the usage has only one operand then we can */
3677   if (IC_LEFT (uic) == NULL ||
3678       IC_RIGHT (uic) == NULL)
3679     goto accuse;
3680
3681   /* make sure this is on the left side if not
3682      a '+' since '+' is commutative */
3683   if (ic->op != '+' &&
3684       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
3685     return;
3686
3687 #if 1
3688   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3689   /* if one of them is a literal then we can */
3690   if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
3691         (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))  &&
3692        (getSize (operandType (IC_RESULT (uic))) <= 1))
3693     {
3694       OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3695       return;
3696     }
3697 #endif
3698
3699   debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
3700   /* if the other one is not on stack then we can */
3701   if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
3702       (IS_ITEMP (IC_RIGHT (uic)) ||
3703        (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3704         !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
3705     goto accuse;
3706
3707   if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
3708       (IS_ITEMP (IC_LEFT (uic)) ||
3709        (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3710         !OP_SYMBOL (IC_LEFT (uic))->onStack)))
3711     goto accuse;
3712
3713   return;
3714
3715 accuse:
3716   debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
3717   OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3718
3719
3720 }
3721 #endif
3722
3723
3724 /*-----------------------------------------------------------------*/
3725 /* packForPush - hueristics to reduce iCode for pushing            */
3726 /*-----------------------------------------------------------------*/
3727 static void
3728 packForReceive (iCode * ic, eBBlock * ebp)
3729 {
3730   iCode *dic;
3731
3732   debugLog ("%s\n", __FUNCTION__);
3733   debugAopGet ("  result:", IC_RESULT (ic));
3734   debugAopGet ("  left:", IC_LEFT (ic));
3735   debugAopGet ("  right:", IC_RIGHT (ic));
3736
3737   if (!ic->next)
3738     return;
3739
3740   for (dic = ic->next; dic; dic = dic->next)
3741     {
3742       if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
3743         debugLog ("    used on left\n");
3744       if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
3745         debugLog ("    used on right\n");
3746       if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
3747         debugLog ("    used on result\n");
3748
3749       if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
3750         (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
3751         return;
3752     }
3753
3754   debugLog ("  hey we can remove this unnecessary assign\n");
3755 }
3756 /*-----------------------------------------------------------------*/
3757 /* packForPush - hueristics to reduce iCode for pushing            */
3758 /*-----------------------------------------------------------------*/
3759 static void
3760 packForPush (iCode * ic, eBBlock * ebp)
3761 {
3762   iCode *dic;
3763   
3764   debugLog ("%s\n", __FUNCTION__);
3765   if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
3766     return;
3767
3768 #if 0
3769   {
3770     int n1, n2;
3771
3772       n1 = bitVectnBitsOn( OP_DEFS(IC_LEFT(ic)));
3773       n2 = bitVectnBitsOn( OP_USES(IC_LEFT(ic)));
3774       debugf3("defs: %d\tuses: %d\t%s\n", n1, n2, printILine(ic));
3775       debugf2("IC_LEFT(ic): from %d to %d\n", OP_LIVEFROM(IC_LEFT(ic)), OP_LIVETO(IC_LEFT(ic)));
3776   }
3777 #endif
3778
3779   /* must have only definition & one usage */
3780   if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
3781       bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
3782     return;
3783
3784   /* find the definition */
3785   if (!(dic = hTabItemWithKey (iCodehTab,
3786                                bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
3787     return;
3788
3789   /* if definition is not assignment,
3790    * or is not pointer (because pointer might have changed) */
3791   if (dic->op != '=' || POINTER_SET (dic))
3792     return;
3793
3794   /* we must ensure that we can use the delete the assignment,
3795    * because the source might have been modified in between.
3796    * Until I know how to fix this, I'll use the adhoc fix
3797    * to check the liveranges */
3798   if((OP_LIVEFROM(IC_RIGHT(dic))==0) || (OP_LIVETO(IC_RIGHT(dic))==0))
3799     return;
3800 //  debugf2("IC_RIGHT(dic): from %d to %d\n", OP_LIVEFROM(IC_RIGHT(dic)), OP_LIVETO(IC_RIGHT(dic)));
3801   
3802
3803
3804   /* we now we know that it has one & only one def & use
3805      and the that the definition is an assignment */
3806   IC_LEFT (ic) = IC_RIGHT (dic);
3807   
3808   debugf("remiCodeFromeBBlock: %s\n", printILine(dic));
3809
3810   remiCodeFromeBBlock (ebp, dic);
3811   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3812   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3813 }
3814
3815 static void printSymType(char * str, sym_link *sl)
3816 {
3817         if(!pic16_ralloc_debug)return;
3818         
3819         debugLog ("    %s Symbol type: ",str);
3820         printTypeChain( sl, debugF);
3821         debugLog ("\n");
3822 }
3823
3824 /*-----------------------------------------------------------------*/
3825 /* some debug code to print the symbol S_TYPE. Note that
3826  * the function checkSClass in src/SDCCsymt.c dinks with
3827  * the S_TYPE in ways the PIC port doesn't fully like...*/
3828 /*-----------------------------------------------------------------*/
3829 static void isData(sym_link *sl)
3830 {
3831   FILE *of = stderr;
3832
3833     if(!pic16_ralloc_debug)return;
3834     
3835     if(!sl)return;
3836     
3837     if(debugF)
3838       of = debugF;
3839
3840     for ( ; sl; sl=sl->next) {
3841       if(!IS_DECL(sl) ) {
3842         switch (SPEC_SCLS(sl)) {
3843           case S_DATA: fprintf (of, "data "); break;
3844           case S_XDATA: fprintf (of, "xdata "); break;
3845           case S_SFR: fprintf (of, "sfr "); break;
3846           case S_SBIT: fprintf (of, "sbit "); break;
3847           case S_CODE: fprintf (of, "code "); break;
3848           case S_IDATA: fprintf (of, "idata "); break;
3849           case S_PDATA: fprintf (of, "pdata "); break;
3850           case S_LITERAL: fprintf (of, "literal "); break;
3851           case S_STACK: fprintf (of, "stack "); break;
3852           case S_XSTACK: fprintf (of, "xstack "); break;
3853           case S_BIT: fprintf (of, "bit "); break;
3854           case S_EEPROM: fprintf (of, "eeprom "); break;
3855           default: break;
3856         }
3857       }
3858     }
3859 }
3860
3861
3862 /*--------------------------------------------------------------------*/
3863 /* pic16_packRegisters - does some transformations to reduce          */
3864 /*                   register pressure                                */
3865 /*                                                                    */
3866 /*--------------------------------------------------------------------*/
3867 static void
3868 pic16_packRegisters (eBBlock * ebp)
3869 {
3870   iCode *ic;
3871   int change = 0;
3872
3873   debugLog ("%s\n", __FUNCTION__);
3874
3875   while (1) {
3876
3877     change = 0;
3878
3879     /* look for assignments of the form */
3880     /* iTempNN = TRueSym (someoperation) SomeOperand */
3881     /*       ....                       */
3882     /* TrueSym := iTempNN:1             */
3883     for (ic = ebp->sch; ic; ic = ic->next)
3884       {
3885 //              debugLog("%d\n", __LINE__);
3886         /* find assignment of the form TrueSym := iTempNN:1 */
3887         if ( (ic->op == '=') && !POINTER_SET (ic) ) // patch 11
3888           change += packRegsForAssign (ic, ebp);
3889         /* debug stuff */
3890         if (ic->op == '=')
3891           {
3892             if (POINTER_SET (ic))
3893               debugLog ("pointer is set\n");
3894             debugAopGet ("  result:", IC_RESULT (ic));
3895             debugAopGet ("  left:", IC_LEFT (ic));
3896             debugAopGet ("  right:", IC_RIGHT (ic));
3897           }
3898
3899       }
3900
3901     if (!change)
3902       break;
3903   }
3904
3905   for (ic = ebp->sch; ic; ic = ic->next) {
3906
3907     if(IS_SYMOP ( IC_LEFT(ic))) {
3908       sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
3909
3910       debugAopGet ("x  left:", IC_LEFT (ic));
3911 #if 0
3912       if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
3913 #else
3914       if(IS_CODEPTR(OP_SYMBOL(IC_LEFT(ic))->type))
3915 #endif
3916         debugLog ("    is a pointer\n");
3917
3918       if(IS_PTR(OP_SYMBOL(IC_LEFT(ic))->type))
3919         debugLog ("    is a ptr\n");
3920
3921       if(IS_OP_VOLATILE(IC_LEFT(ic)))
3922         debugLog ("    is volatile\n");
3923
3924       isData(etype);
3925
3926         if(IS_OP_VOLATILE(IC_LEFT(ic))) {
3927             debugLog ("  %d - left is not temp, allocating\n", __LINE__);
3928             pic16_allocDirReg(IC_LEFT (ic));
3929         }
3930
3931       printSymType("c  ", OP_SYMBOL(IC_LEFT(ic))->type);
3932     }
3933
3934     if(IS_SYMOP ( IC_RIGHT(ic))) {
3935       debugAopGet ("  right:", IC_RIGHT (ic));
3936       printSymType("    ", OP_SYMBOL(IC_RIGHT(ic))->type);
3937     }
3938
3939     if(IS_SYMOP ( IC_RESULT(ic))) {
3940       debugAopGet ("  result:", IC_RESULT (ic));
3941       printSymType("     ", OP_SYMBOL(IC_RESULT(ic))->type);
3942     }
3943
3944     if(IS_TRUE_SYMOP ( IC_RIGHT(ic))) {
3945       debugAopGet ("  right:", IC_RIGHT (ic));
3946       printSymType("    ", OP_SYMBOL(IC_RIGHT(ic))->type);
3947 //      pic16_allocDirReg(IC_RIGHT(ic));
3948     }
3949
3950     if(IS_TRUE_SYMOP ( IC_RESULT(ic))) {
3951       debugAopGet ("  result:", IC_RESULT (ic));
3952       printSymType("     ", OP_SYMBOL(IC_RESULT(ic))->type);
3953 //      pic16_allocDirReg(IC_RESULT(ic));
3954     }
3955
3956
3957     if (POINTER_SET (ic))
3958       debugLog ("  %d - Pointer set\n", __LINE__);
3959       
3960       /* Look for two subsequent iCodes with */
3961       /*   iTemp := _c;         */
3962       /*   _c = iTemp & op;     */
3963       /* and replace them by    */
3964       /*   iTemp := _c;         */
3965       /*   _c = _c & op;        */
3966       if ((ic->op == BITWISEAND || ic->op == '|' || ic->op == '^')
3967         && ic->prev
3968         && ic->prev->op == '='
3969         && IS_ITEMP (IC_LEFT (ic))
3970         && IC_LEFT (ic) == IC_RESULT (ic->prev)
3971         && isOperandEqual (IC_RESULT(ic), IC_RIGHT(ic->prev)))
3972         {
3973           iCode* ic_prev = ic->prev;
3974           symbol* prev_result_sym = OP_SYMBOL (IC_RESULT (ic_prev));
3975                         
3976           ReplaceOpWithCheaperOp (&IC_LEFT (ic), IC_RESULT (ic));
3977           if (IC_RESULT (ic_prev) != IC_RIGHT (ic)) {
3978             bitVectUnSetBit (OP_USES (IC_RESULT (ic_prev)), ic->key);
3979             if (/*IS_ITEMP (IC_RESULT (ic_prev)) && */
3980               prev_result_sym->liveTo == ic->seq)
3981             {
3982               prev_result_sym->liveTo = ic_prev->seq;
3983             }
3984           }
3985           bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
3986           
3987           bitVectSetBit (ic->rlive, IC_RESULT (ic)->key);
3988
3989           if (bitVectIsZero (OP_USES (IC_RESULT (ic_prev)))) {
3990             bitVectUnSetBit (ic->rlive, IC_RESULT (ic)->key);
3991             bitVectUnSetBit (OP_DEFS (IC_RESULT (ic_prev)), ic_prev->key);
3992             remiCodeFromeBBlock (ebp, ic_prev);
3993             hTabDeleteItem (&iCodehTab, ic_prev->key, ic_prev, DELETE_ITEM, NULL);
3994           }
3995         }
3996                 
3997     /* if this is an itemp & result of a address of a true sym 
3998        then mark this as rematerialisable   */
3999     if (ic->op == ADDRESS_OF &&
4000         IS_ITEMP (IC_RESULT (ic)) &&
4001         IS_TRUE_SYMOP (IC_LEFT (ic)) &&
4002         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
4003         !OP_SYMBOL (IC_LEFT (ic))->onStack)
4004       {
4005
4006         debugLog ("  %d - %s. result is rematerializable\n", __LINE__,__FUNCTION__);
4007
4008         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
4009         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
4010         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
4011
4012       }
4013
4014     /* if straight assignment then carry remat flag if
4015        this is the only definition */
4016     if (ic->op == '=' &&
4017         !POINTER_SET (ic) &&
4018         IS_SYMOP (IC_RIGHT (ic)) &&
4019         OP_SYMBOL (IC_RIGHT (ic))->remat &&
4020         bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
4021       {
4022         debugLog ("  %d - %s. straight rematerializable\n", __LINE__,__FUNCTION__);
4023
4024         OP_SYMBOL (IC_RESULT (ic))->remat =
4025           OP_SYMBOL (IC_RIGHT (ic))->remat;
4026         OP_SYMBOL (IC_RESULT (ic))->rematiCode =
4027           OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
4028       }
4029
4030     /* if this is a +/- operation with a rematerizable 
4031        then mark this as rematerializable as well */
4032     if ((ic->op == '+' || ic->op == '-') &&
4033         (IS_SYMOP (IC_LEFT (ic)) &&
4034          IS_ITEMP (IC_RESULT (ic)) &&
4035          OP_SYMBOL (IC_LEFT (ic))->remat &&
4036          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
4037          IS_OP_LITERAL (IC_RIGHT (ic))))
4038       {
4039         debugLog ("  %d - %s. rematerializable because op is +/-\n", __LINE__,__FUNCTION__);
4040         //int i = 
4041         operandLitValue (IC_RIGHT (ic));
4042         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
4043         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
4044         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
4045       }
4046
4047
4048 #if 0
4049     /* if this is an arithmetic operation
4050      *   && result or left is not rematerializable (so it is a plain arithmetic op)
4051      *   && and left is not used after this iCode */
4052      
4053     if(getenv("OPTIMIZE_NEAR_POINTER_GET"))
4054
4055     if (IS_ARITHMETIC_OP(ic)
4056       && !IS_OP_LITERAL (IC_LEFT (ic))
4057       && !OP_SYMBOL (IC_RESULT(ic))->rematiCode
4058       && !OP_SYMBOL (IC_LEFT(ic))->rematiCode
4059       && (OP_LIVETO (IC_LEFT(ic) ) <= ic->seq)
4060       ) {
4061         iCode *dic = ic->prev;
4062         
4063           /* search backwards to find assignment from a remat pointer */
4064           while(dic && dic->seq >= OP_LIVEFROM( IC_LEFT(ic) )) {
4065
4066             /* is it a pointer_get? */
4067             if(POINTER_GET(dic)
4068               && IS_DATA_PTR(OP_SYM_TYPE (IC_LEFT (dic)))) {
4069                 fprintf(stderr, "%s:%d `%s' is a data pointer (ic seq: %d)\n", __FILE__, __LINE__,
4070                           OP_SYMBOL(IC_LEFT(dic))->rname, dic->seq);
4071                           
4072                 /* so we can replace ic->left with dic->left, & remove assignment */
4073                 ReplaceOpWithCheaperOp( &IC_LEFT(ic), IC_LEFT(dic) );
4074                 
4075                 bitVectUnSetBit(OP_USES( IC_LEFT(ic) ), ic->key);
4076                 bitVectUnSetBit(OP_DEFS( IC_RESULT(dic) ), dic->key );
4077                 
4078 //                dic->op = DUMMY_READ_VOLATILE;
4079 #if 1
4080                 remiCodeFromeBBlock(ebp, dic);
4081                 hTabDeleteItem(&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
4082 #endif
4083                 break;
4084             }
4085             dic = dic->prev;
4086           }
4087     }
4088 #endif
4089           
4090     /* mark the pointer usages */
4091     if (POINTER_SET (ic))
4092       {
4093         OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
4094         debugLog ("  marking as a pointer (set) =>");
4095         debugAopGet ("  result:", IC_RESULT (ic));
4096
4097       }
4098
4099     if (POINTER_GET (ic))
4100       {
4101         if(IS_SYMOP(IC_LEFT(ic))) {
4102           OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
4103           debugLog ("  marking as a pointer (get) =>");
4104           debugAopGet ("  left:", IC_LEFT (ic));
4105         }
4106         
4107         if(getenv("OPTIMIZE_BITFIELD_POINTER_GET")) {
4108           if(IS_ITEMP(IC_LEFT(ic)) && IS_BITFIELD(OP_SYM_ETYPE(IC_LEFT(ic)))) {
4109             iCode *dic = ic->prev;
4110
4111             fprintf(stderr, "%s:%d might give opt POINTER_GET && IS_BITFIELD(IC_LEFT)\n", __FILE__, __LINE__);
4112           
4113             if(dic && dic->op == '='
4114               && isOperandEqual(IC_RESULT(dic), IC_LEFT(ic))) {
4115               
4116                 fprintf(stderr, "%s:%d && prev is '=' && prev->result == ic->left\n", __FILE__, __LINE__);
4117
4118
4119                 /* replace prev->left with ic->left */
4120                 IC_LEFT(ic) = IC_RIGHT(dic);
4121                 IC_RIGHT(ic->prev) = NULL;
4122                 
4123                 /* remove ic->prev iCode (assignment) */
4124                 remiCodeFromeBBlock (ebp, dic);
4125                 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,ic->key);
4126
4127
4128                 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
4129             }
4130           }
4131         }
4132       }
4133
4134         //debugLog("  %d   %s\n", __LINE__, __FUNCTION__);
4135
4136     if (!SKIP_IC2 (ic))
4137       {
4138         //debugLog("  %d   %s\n", __LINE__, __FUNCTION__ );
4139         /* if we are using a symbol on the stack
4140            then we should say pic16_ptrRegReq */
4141         if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
4142           pic16_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
4143                                OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
4144         else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
4145           pic16_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
4146                                OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
4147         else
4148           {
4149
4150                 //debugLog("   %d   %s\n", __LINE__, __FUNCTION__ );
4151             if (IS_SYMOP (IC_LEFT (ic)))
4152               pic16_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
4153                                    OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
4154             if (IS_SYMOP (IC_RIGHT (ic)))
4155               pic16_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
4156                                    OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
4157             if (IS_SYMOP (IC_RESULT (ic)))
4158               pic16_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
4159                                    OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
4160           }
4161
4162         debugLog ("  %d - pointer reg req = %d\n", __LINE__,pic16_ptrRegReq);
4163
4164       }
4165
4166     /* if the condition of an if instruction
4167        is defined in the previous instruction then
4168        mark the itemp as a conditional */
4169     if ((IS_CONDITIONAL (ic) ||
4170          ((ic->op == BITWISEAND ||
4171            ic->op == '|' ||
4172            ic->op == '^') &&
4173           isBitwiseOptimizable (ic))) &&
4174         ic->next && ic->next->op == IFX &&
4175         isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
4176         OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
4177       {
4178
4179         debugLog ("  %d\n", __LINE__);
4180         OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
4181         continue;
4182       }
4183
4184         debugLog(" %d\n", __LINE__);
4185
4186 #ifndef NO_packRegsForSupport
4187     /* reduce for support function calls */
4188     if (ic->supportRtn || ic->op == '+' || ic->op == '-')
4189       packRegsForSupport (ic, ebp);
4190 #endif
4191
4192     /* if a parameter is passed, it's in W, so we may not
4193        need to place a copy in a register */
4194     if (ic->op == RECEIVE)
4195       packForReceive (ic, ebp);
4196
4197 #ifndef NO_packRegsForOneuse
4198     /* some cases the redundant moves can
4199        can be eliminated for return statements */
4200     if ((ic->op == RETURN || ic->op == SEND) &&
4201         !isOperandInFarSpace (IC_LEFT (ic)) &&
4202         !options.model)
4203       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
4204 #endif
4205
4206 #ifndef NO_packRegsForOneuse
4207     /* if pointer set & left has a size more than
4208        one and right is not in far space */
4209     if (POINTER_SET (ic) &&
4210         !isOperandInFarSpace (IC_RIGHT (ic)) &&
4211         !OP_SYMBOL (IC_RESULT (ic))->remat &&
4212         !IS_OP_RUONLY (IC_RIGHT (ic)) &&
4213         getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
4214
4215       packRegsForOneuse (ic, IC_RESULT (ic), ebp);
4216 #endif
4217
4218 #ifndef NO_packRegsForOneuse
4219     /* if pointer get */
4220     if (POINTER_GET (ic) &&
4221         !isOperandInFarSpace (IC_RESULT (ic)) &&
4222         !OP_SYMBOL (IC_LEFT (ic))->remat &&
4223         !IS_OP_RUONLY (IC_RESULT (ic)) &&
4224         getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
4225
4226       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
4227       debugLog("%d - return from packRegsForOneuse\n", __LINE__);
4228 #endif
4229
4230 #ifndef NO_cast_peep
4231     /* if this is cast for intergral promotion then
4232        check if only use of  the definition of the 
4233        operand being casted/ if yes then replace
4234        the result of that arithmetic operation with 
4235        this result and get rid of the cast */
4236     if (ic->op == CAST) {
4237         
4238       sym_link *fromType = operandType (IC_RIGHT (ic));
4239       sym_link *toType = operandType (IC_LEFT (ic));
4240
4241       debugLog ("  %d - casting\n", __LINE__);
4242
4243       if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
4244           getSize (fromType) != getSize (toType)) {
4245             
4246
4247         iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
4248         if (dic) {
4249                 
4250           if (IS_ARITHMETIC_OP (dic)) {
4251                     debugLog("   %d   %s\n", __LINE__, __FUNCTION__ );
4252                     
4253             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
4254             IC_RESULT (dic) = IC_RESULT (ic);
4255             remiCodeFromeBBlock (ebp, ic);
4256             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
4257             hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
4258             OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
4259             ic = ic->prev;
4260           }  else
4261                 
4262             OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
4263         }
4264       } else {
4265
4266         /* if the type from and type to are the same
4267            then if this is the only use then packit */
4268         if (compareType (operandType (IC_RIGHT (ic)),
4269                          operandType (IC_LEFT (ic))) == 1) {
4270                 
4271           iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
4272           if (dic) {
4273
4274                    debugLog(" %d\n", __LINE__);
4275
4276             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
4277             IC_RESULT (dic) = IC_RESULT (ic);
4278             bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
4279             remiCodeFromeBBlock (ebp, ic);
4280             hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
4281             OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
4282             ic = ic->prev;
4283           }
4284         }
4285       }
4286     }
4287 #endif
4288
4289 #if 1
4290     /* there are some problems with packing variables
4291      * it seems that the live range estimator doesn't
4292      * estimate correctly the liveranges of some symbols */
4293      
4294     /* pack for PUSH 
4295        iTempNN := (some variable in farspace) V1
4296        push iTempNN ;
4297        -------------
4298        push V1
4299     */
4300     if (ic->op == IPUSH)
4301       {
4302         packForPush (ic, ebp);
4303       }
4304 #endif
4305
4306 #ifndef NO_packRegsForAccUse
4307     /* pack registers for accumulator use, when the
4308        result of an arithmetic or bit wise operation
4309        has only one use, that use is immediately following
4310        the defintion and the using iCode has only one
4311        operand or has two operands but one is literal &
4312        the result of that operation is not on stack then
4313        we can leave the result of this operation in acc:b
4314        combination */
4315     if ((IS_ARITHMETIC_OP (ic)
4316
4317          || IS_BITWISE_OP (ic)
4318
4319          || ic->op == LEFT_OP || ic->op == RIGHT_OP
4320
4321          ) &&
4322         IS_ITEMP (IC_RESULT (ic)) &&
4323         getSize (operandType (IC_RESULT (ic))) <= 1)
4324
4325       packRegsForAccUse (ic);
4326 #endif
4327
4328   }
4329 }
4330
4331 static void
4332 dumpEbbsToDebug (eBBlock ** ebbs, int count)
4333 {
4334   int i;
4335
4336   if (!pic16_ralloc_debug || !debugF)
4337     return;
4338
4339   for (i = 0; i < count; i++)
4340     {
4341       fprintf (debugF, "\n----------------------------------------------------------------\n");
4342       fprintf (debugF, "Basic Block %s : loop Depth = %d noPath = %d , lastinLoop = %d\n",
4343                ebbs[i]->entryLabel->name,
4344                ebbs[i]->depth,
4345                ebbs[i]->noPath,
4346                ebbs[i]->isLastInLoop);
4347       fprintf (debugF, "depth 1st num %d : bbnum = %d 1st iCode = %d , last iCode = %d\n",
4348                ebbs[i]->dfnum,
4349                ebbs[i]->bbnum,
4350                ebbs[i]->fSeq,
4351                ebbs[i]->lSeq);
4352       fprintf (debugF, "visited %d : hasFcall = %d\n",
4353                ebbs[i]->visited,
4354                ebbs[i]->hasFcall);
4355
4356       fprintf (debugF, "\ndefines bitVector :");
4357       bitVectDebugOn (ebbs[i]->defSet, debugF);
4358       fprintf (debugF, "\nlocal defines bitVector :");
4359       bitVectDebugOn (ebbs[i]->ldefs, debugF);
4360       fprintf (debugF, "\npointers Set bitvector :");
4361       bitVectDebugOn (ebbs[i]->ptrsSet, debugF);
4362       fprintf (debugF, "\nin pointers Set bitvector :");
4363       bitVectDebugOn (ebbs[i]->inPtrsSet, debugF);
4364       fprintf (debugF, "\ninDefs Set bitvector :");
4365       bitVectDebugOn (ebbs[i]->inDefs, debugF);
4366       fprintf (debugF, "\noutDefs Set bitvector :");
4367       bitVectDebugOn (ebbs[i]->outDefs, debugF);
4368       fprintf (debugF, "\nusesDefs Set bitvector :");
4369       bitVectDebugOn (ebbs[i]->usesDefs, debugF);
4370       fprintf (debugF, "\n----------------------------------------------------------------\n");
4371       printiCChain (ebbs[i]->sch, debugF);
4372     }
4373 }
4374 /*-----------------------------------------------------------------*/
4375 /* pic16_assignRegisters - assigns registers to each live range as need  */
4376 /*-----------------------------------------------------------------*/
4377 void
4378 pic16_assignRegisters (ebbIndex * ebbi)
4379 {
4380   eBBlock ** ebbs = ebbi->bbOrder;
4381   int count = ebbi->count;
4382   iCode *ic;
4383   int i;
4384
4385   debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s", __FILE__, __FUNCTION__);
4386   debugLog ("\nebbs before optimizing:\n");
4387   dumpEbbsToDebug (ebbs, count);
4388
4389   _inRegAllocator = 1;
4390
4391   setToNull ((void *) &_G.funcrUsed);
4392   pic16_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
4393
4394
4395   /* change assignments this will remove some
4396      live ranges reducing some register pressure */
4397   for (i = 0; i < count; i++)
4398     pic16_packRegisters (ebbs[i]);
4399
4400   {
4401     regs *reg;
4402     int hkey;
4403     int i=0;
4404
4405     debugLog("dir registers allocated so far:\n");
4406     reg = hTabFirstItem(dynDirectRegNames, &hkey);
4407
4408     while(reg) {
4409       debugLog("  -- #%d reg = %s  key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4410 //      fprintf(stderr, "  -- #%d reg = %s  key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4411       reg = hTabNextItem(dynDirectRegNames, &hkey);
4412     }
4413
4414   }
4415
4416   /* liveranges probably changed by register packing
4417      so we compute them again */
4418   recomputeLiveRanges (ebbs, count);
4419
4420   if (options.dump_pack)
4421     dumpEbbsToFileExt (DUMP_PACK, ebbi);
4422
4423   /* first determine for each live range the number of 
4424      registers & the type of registers required for each */
4425   regTypeNum ();
4426
4427   /* start counting function temporary registers from zero */
4428   dynrIdx = 0;
4429
4430   /* and serially allocate registers */
4431   serialRegAssign (ebbs, count);
4432
4433 #if 0
4434   debugLog ("ebbs after serialRegAssign:\n");
4435   dumpEbbsToDebug (ebbs, count);
4436 #endif
4437
4438   //pic16_freeAllRegs();
4439
4440   /* if stack was extended then tell the user */
4441   if (_G.stackExtend)
4442     {
4443 /*      werror(W_TOOMANY_SPILS,"stack", */
4444 /*             _G.stackExtend,currFunc->name,""); */
4445       _G.stackExtend = 0;
4446     }
4447
4448   if (_G.dataExtend)
4449     {
4450 /*      werror(W_TOOMANY_SPILS,"data space", */
4451 /*             _G.dataExtend,currFunc->name,""); */
4452       _G.dataExtend = 0;
4453     }
4454
4455   /* after that create the register mask
4456      for each of the instruction */
4457   createRegMask (ebbs, count);
4458
4459   /* redo that offsets for stacked automatic variables */
4460   redoStackOffsets ();
4461
4462   if (options.dump_rassgn)
4463     dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
4464
4465   /* now get back the chain */
4466   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
4467
4468   debugLog ("ebbs after optimizing:\n");
4469   dumpEbbsToDebug (ebbs, count);
4470
4471   _inRegAllocator = 0;
4472
4473   genpic16Code (ic);
4474
4475   /* free up any _G.stackSpil locations allocated */
4476   applyToSet (_G.stackSpil, deallocStackSpil);
4477   _G.slocNum = 0;
4478   setToNull ((void *) &_G.stackSpil);
4479   setToNull ((void *) &_G.spiltSet);
4480   /* mark all registers as free */
4481   pic16_freeAllRegs ();
4482
4483
4484   debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
4485   debugLogClose ();
4486   return;
4487 }