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