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