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