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