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