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