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