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