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