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