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