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