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