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