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