1 /*------------------------------------------------------------------------
3 ralloc.c - source file for register allocation. PIC16 specific
5 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 Added Pic Port T.scott Dattalo scott@dattalo.com (2000)
7 Added Pic16 Port Martin Dubuc m.dubuc@rogers.com (2002)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
34 #if defined(__BORLANDC__) || defined(_MSC_VER)
35 #define STRCASECMP stricmp
37 #define STRCASECMP strcasecmp
41 #define debugf(frm, rest) _debugf(__FILE__, __LINE__, frm, rest)
43 void _debugf(char *f, int l, char *frm, ...);
45 #define NEWREG_DEBUG 0
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 /*-----------------------------------------------------------------*/
58 regs *pic16_typeRegWithIdx (int idx, int type, int fixed);
59 extern void genpic16Code (iCode *);
69 bitVect *funcrUsed; /* registers used in a function */
75 /* Shared with gen.c */
76 int pic16_ptrRegReq; /* one byte pointer register required */
79 set *pic16_dynAllocRegs=NULL;
80 set *pic16_dynStackRegs=NULL;
81 set *pic16_dynProcessorRegs=NULL;
82 set *pic16_dynDirectRegs=NULL;
83 set *pic16_dynDirectBitRegs=NULL;
84 set *pic16_dynInternalRegs=NULL;
85 set *pic16_dynAccessRegs=NULL;
87 static hTab *dynDirectRegNames=NULL;
88 static hTab *dynAllocRegNames=NULL;
89 static hTab *dynProcRegNames=NULL;
90 static hTab *dynAccessRegNames=NULL;
91 //static hTab *regHash = NULL; /* a hash table containing ALL registers */
93 extern set *sectNames;
95 set *pic16_rel_udata=NULL; /* relocatable uninitialized registers */
96 set *pic16_fix_udata=NULL; /* absolute uninitialized registers */
97 set *pic16_equ_data=NULL; /* registers used by equates */
98 set *pic16_int_regs=NULL; /* internal registers placed in access bank 0 to 0x7f */
99 set *pic16_acs_udata=NULL; /* access bank variables */
101 set *pic16_builtin_functions=NULL;
103 static int dynrIdx=0x00; //0x20; // starting temporary register rIdx
104 static int rDirectIdx=0;
106 int pic16_nRegs = 128; // = sizeof (regspic16) / sizeof (regs);
108 int pic16_Gstack_base_addr=0; /* The starting address of registers that
109 * are used to pass and return parameters */
112 int _inRegAllocator=0; /* flag that marks whther allocReg happens while
113 * inside the register allocator function */
116 static void spillThis (symbol *);
117 int pic16_ralloc_debug = 0;
118 static FILE *debugF = NULL;
119 /*-----------------------------------------------------------------*/
120 /* debugLog - open a file for debugging information */
121 /*-----------------------------------------------------------------*/
122 //static void debugLog(char *inst,char *fmt, ...)
124 debugLog (char *fmt,...)
126 static int append = 0; // First time through, open the file without append.
129 //char *bufferP=buffer;
132 if (!pic16_ralloc_debug || !dstFileName)
138 /* create the file name */
139 strcpy (buffer, dstFileName);
140 strcat (buffer, ".d");
142 if (!(debugF = fopen (buffer, (append ? "a+" : "w"))))
144 werror (E_FILE_OPEN_ERR, buffer);
147 append = 1; // Next time debubLog is called, we'll append the debug info
153 vsprintf (buffer, fmt, ap);
155 fprintf (debugF, "%s", buffer);
157 while (isspace(*bufferP)) bufferP++;
159 if (bufferP && *bufferP)
160 lineCurr = (lineCurr ?
161 connectLine(lineCurr,newLineNode(lb)) :
162 (lineHead = newLineNode(lb)));
163 lineCurr->isInline = _G.inLine;
164 lineCurr->isDebug = _G.debugLine;
173 if(!pic16_ralloc_debug)return;
176 fputc ('\n', debugF);
178 /*-----------------------------------------------------------------*/
179 /* debugLogClose - closes the debug log file (if opened) */
180 /*-----------------------------------------------------------------*/
190 #define AOP(op) op->aop
193 debugAopGet (char *str, operand * op)
195 if(!pic16_ralloc_debug)return NULL;
200 printOperand (op, debugF);
207 pic16_decodeOp (unsigned int op)
209 if (op < 128 && op > ' ') {
210 buffer[0] = (op & 0xff);
216 case IDENTIFIER: return "IDENTIFIER";
217 case TYPE_NAME: return "TYPE_NAME";
218 case CONSTANT: return "CONSTANT";
219 case STRING_LITERAL: return "STRING_LITERAL";
220 case SIZEOF: return "SIZEOF";
221 case PTR_OP: return "PTR_OP";
222 case INC_OP: return "INC_OP";
223 case DEC_OP: return "DEC_OP";
224 case LEFT_OP: return "LEFT_OP";
225 case RIGHT_OP: return "RIGHT_OP";
226 case LE_OP: return "LE_OP";
227 case GE_OP: return "GE_OP";
228 case EQ_OP: return "EQ_OP";
229 case NE_OP: return "NE_OP";
230 case AND_OP: return "AND_OP";
231 case OR_OP: return "OR_OP";
232 case MUL_ASSIGN: return "MUL_ASSIGN";
233 case DIV_ASSIGN: return "DIV_ASSIGN";
234 case MOD_ASSIGN: return "MOD_ASSIGN";
235 case ADD_ASSIGN: return "ADD_ASSIGN";
236 case SUB_ASSIGN: return "SUB_ASSIGN";
237 case LEFT_ASSIGN: return "LEFT_ASSIGN";
238 case RIGHT_ASSIGN: return "RIGHT_ASSIGN";
239 case AND_ASSIGN: return "AND_ASSIGN";
240 case XOR_ASSIGN: return "XOR_ASSIGN";
241 case OR_ASSIGN: return "OR_ASSIGN";
242 case TYPEDEF: return "TYPEDEF";
243 case EXTERN: return "EXTERN";
244 case STATIC: return "STATIC";
245 case AUTO: return "AUTO";
246 case REGISTER: return "REGISTER";
247 case CODE: return "CODE";
248 case EEPROM: return "EEPROM";
249 case INTERRUPT: return "INTERRUPT";
250 case SFR: return "SFR";
251 case AT: return "AT";
252 case SBIT: return "SBIT";
253 case REENTRANT: return "REENTRANT";
254 case USING: return "USING";
255 case XDATA: return "XDATA";
256 case DATA: return "DATA";
257 case IDATA: return "IDATA";
258 case PDATA: return "PDATA";
259 case VAR_ARGS: return "VAR_ARGS";
260 case CRITICAL: return "CRITICAL";
261 case NONBANKED: return "NONBANKED";
262 case BANKED: return "BANKED";
263 case CHAR: return "CHAR";
264 case SHORT: return "SHORT";
265 case INT: return "INT";
266 case LONG: return "LONG";
267 case SIGNED: return "SIGNED";
268 case UNSIGNED: return "UNSIGNED";
269 case FLOAT: return "FLOAT";
270 case DOUBLE: return "DOUBLE";
271 case CONST: return "CONST";
272 case VOLATILE: return "VOLATILE";
273 case VOID: return "VOID";
274 case BIT: return "BIT";
275 case STRUCT: return "STRUCT";
276 case UNION: return "UNION";
277 case ENUM: return "ENUM";
278 case ELIPSIS: return "ELIPSIS";
279 case RANGE: return "RANGE";
280 case FAR: return "FAR";
281 case CASE: return "CASE";
282 case DEFAULT: return "DEFAULT";
283 case IF: return "IF";
284 case ELSE: return "ELSE";
285 case SWITCH: return "SWITCH";
286 case WHILE: return "WHILE";
287 case DO: return "DO";
288 case FOR: return "FOR";
289 case GOTO: return "GOTO";
290 case CONTINUE: return "CONTINUE";
291 case BREAK: return "BREAK";
292 case RETURN: return "RETURN";
293 case INLINEASM: return "INLINEASM";
294 case IFX: return "IFX";
295 case ADDRESS_OF: return "ADDRESS_OF";
296 case GET_VALUE_AT_ADDRESS: return "GET_VALUE_AT_ADDRESS";
297 case SPIL: return "SPIL";
298 case UNSPIL: return "UNSPIL";
299 case GETHBIT: return "GETHBIT";
300 case BITWISEAND: return "BITWISEAND";
301 case UNARYMINUS: return "UNARYMINUS";
302 case IPUSH: return "IPUSH";
303 case IPOP: return "IPOP";
304 case PCALL: return "PCALL";
305 case ENDFUNCTION: return "ENDFUNCTION";
306 case JUMPTABLE: return "JUMPTABLE";
307 case RRC: return "RRC";
308 case RLC: return "RLC";
309 case CAST: return "CAST";
310 case CALL: return "CALL";
311 case PARAM: return "PARAM ";
312 case NULLOP: return "NULLOP";
313 case BLOCK: return "BLOCK";
314 case LABEL: return "LABEL";
315 case RECEIVE: return "RECEIVE";
316 case SEND: return "SEND";
317 case DUMMY_READ_VOLATILE: return "DUMMY_READ_VOLATILE";
319 sprintf (buffer, "unkown op %d %c", op, op & 0xff);
323 /*-----------------------------------------------------------------*/
324 /*-----------------------------------------------------------------*/
326 debugLogRegType (short type)
328 if(!pic16_ralloc_debug)return NULL;
330 case REG_GPR: return "REG_GPR";
331 case REG_PTR: return "REG_PTR";
332 case REG_CND: return "REG_CND";
334 sprintf (buffer, "unknown reg type %d", type);
339 /*-----------------------------------------------------------------*/
340 /*-----------------------------------------------------------------*/
341 static int regname2key(char const *name)
350 key += (*name++) + 1;
354 return ( (key + (key >> 4) + (key>>8)) & 0x3f);
358 /*-----------------------------------------------------------------*/
359 /* newReg - allocate and init memory for a new register */
360 /*-----------------------------------------------------------------*/
361 regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias, operand *refop)
366 dReg = Safe_calloc(1,sizeof(regs));
368 dReg->pc_type = pc_type;
371 dReg->name = Safe_strdup(name);
373 sprintf(buffer,"r0x%02X", dReg->rIdx);
376 dReg->name = Safe_strdup(buffer);
384 if(type == REG_SFR) {
386 dReg->address = rIdx;
387 dReg->accessBank = 1;
391 dReg->accessBank = 0;
395 fprintf(stderr,"newReg: %s, rIdx = 0x%02x\taccess= %d\tregop= %p\n",dReg->name,rIdx, dReg->accessBank, refop);
399 dReg->reg_alias = NULL;
400 dReg->reglives.usedpFlows = newSet();
401 dReg->reglives.assignedpFlows = newSet();
404 if(!(type == REG_SFR && alias == 0x80))
405 hTabAddItem(&dynDirectRegNames, regname2key(name), dReg);
410 /*-----------------------------------------------------------------*/
411 /* regWithIdx - Search through a set of registers that matches idx */
412 /*-----------------------------------------------------------------*/
414 regWithIdx (set *dRegs, int idx, unsigned fixed)
418 for (dReg = setFirstItem(dRegs) ; dReg ;
419 dReg = setNextItem(dRegs)) {
421 if(idx == dReg->rIdx && (fixed == dReg->isFixed)) {
429 /*-----------------------------------------------------------------*/
430 /* regFindFree - Search for a free register in a set of registers */
431 /*-----------------------------------------------------------------*/
433 regFindFree (set *dRegs)
437 for (dReg = setFirstItem(dRegs) ; dReg ;
438 dReg = setNextItem(dRegs)) {
440 // fprintf(stderr, "%s:%d checking register %s (%p) [rIdx: 0x%02x] if free= %d\n",
441 // __FILE__, __LINE__, dReg->name, dReg, dReg->rIdx, dReg->isFree);
452 regFindFreeNext(set *dRegs, regs *creg)
457 /* position at current register */
458 for(dReg = setFirstItem(dRegs); dReg != creg; dReg = setNextItem(dRegs));
461 for(dReg = setNextItem(dRegs); dReg; dReg = setNextItem(dRegs)) {
470 /*-----------------------------------------------------------------*/
471 /* pic16_initStack - allocate registers for a pseudo stack */
472 /*-----------------------------------------------------------------*/
473 void pic16_initStack(int base_address, int size)
478 pic16_Gstack_base_addr = base_address;
479 //fprintf(stderr,"initStack");
481 for(i = 0; i<size; i++)
482 addSet(&pic16_dynStackRegs,newReg(REG_STK, PO_GPR_TEMP,base_address++,NULL,1,0, NULL));
485 /*-----------------------------------------------------------------*
486 *-----------------------------------------------------------------*/
488 pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias)
490 regs *reg = newReg(REG_SFR, po_type, rIdx, name, 1, alias, NULL);
492 // fprintf(stderr,"%s: %s addr =0x%x\n",__FUNCTION__, name,rIdx);
494 reg->wasUsed = 0; // we do not know if they are going to be used at all
495 reg->accessBank = 1; // implicit add access Bank
497 hTabAddItem(&dynProcRegNames, regname2key(reg->name), reg);
499 return addSet(&pic16_dynProcessorRegs, reg);
502 /*-----------------------------------------------------------------*
503 *-----------------------------------------------------------------*/
506 pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias)
508 regs * reg = newReg(REG_GPR, po_type, rIdx, name,1,alias, NULL);
510 // fprintf(stderr,"%s:%d: %s %s addr =0x%x\n",__FILE__, __LINE__, __FUNCTION__, name, rIdx);
514 return addSet(&pic16_dynInternalRegs,reg);
521 /*-----------------------------------------------------------------*/
522 /* allocReg - allocates register of given type */
523 /*-----------------------------------------------------------------*/
525 allocReg (short type)
529 #define MAX_P16_NREGS 6
533 if(dynrIdx > pic16_nRegs)
537 /* try to reuse some unused registers */
538 reg = regFindFree( pic16_dynAllocRegs );
541 // fprintf(stderr, "%s: [%s] found FREE register %s, rIdx: %d\n", __FILE__, (_inRegAllocator)?"ralloc":"", reg->name, reg->rIdx);
545 reg = newReg(REG_GPR, PO_GPR_TEMP, dynrIdx++, NULL, 1, 0, NULL);
546 // fprintf(stderr, "%s: [%s] allocating NEW register %s, rIdx: %d\n", __FILE__, (_inRegAllocator)?"ralloc":"", reg->name, reg->rIdx);
549 if(_inRegAllocator && (dynrIdx > MAX_P16_NREGS)) {
550 // debugf("allocating more registers than available\n", 0);
555 // addSet(&pic16_dynAllocRegs, reg);
558 addSet(&pic16_dynAllocRegs, reg);
559 hTabAddItem(&dynAllocRegNames, regname2key(reg->name), reg);
563 debugLog ("%s of type %s for register rIdx: %d (0x%x)\n", __FUNCTION__, debugLogRegType (type), dynrIdx-1, dynrIdx-1);
566 fprintf(stderr,"%s:%d: %s\t%s addr= 0x%x\trIdx= 0x%02x isFree: %d\n",
567 __FILE__, __LINE__, __FUNCTION__, reg->name, reg->address, reg->rIdx, reg->isFree);
570 reg->accessBank = 1; /* this is a temporary register alloc in accessBank */
571 reg->isLocal = 1; /* this is a local frame register */
576 // fprintf(stderr, "%s:%d adding %s into function %s regsUsed\n", __FUNCTION__, __LINE__, reg->name, currFunc->name);
577 currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, reg->rIdx);
580 return (reg); // addSet(&pic16_dynAllocRegs,reg);
585 /*-----------------------------------------------------------------*/
586 /* pic16_dirregWithName - search for register by name */
587 /*-----------------------------------------------------------------*/
589 pic16_dirregWithName (char *name)
597 /* hash the name to get a key */
599 hkey = regname2key(name);
601 // fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
603 reg = hTabFirstItemWK(dynDirectRegNames, hkey);
607 if(STRCASECMP(reg->name, name) == 0) {
608 // fprintf(stderr, "%s:%d: FOUND name = %s\thash = %d\n", __FUNCTION__, __LINE__, reg->name, hkey);
612 reg = hTabNextItemWK (dynDirectRegNames);
616 return NULL; // name wasn't found in the hash table
619 /*-----------------------------------------------------------------*/
620 /* pic16_allocregWithName - search for register by name */
621 /*-----------------------------------------------------------------*/
623 pic16_allocregWithName (char *name)
631 /* hash the name to get a key */
633 hkey = regname2key(name);
635 // fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
637 reg = hTabFirstItemWK(dynAllocRegNames, hkey);
641 if(STRCASECMP(reg->name, name) == 0) {
645 reg = hTabNextItemWK (dynAllocRegNames);
649 return NULL; // name wasn't found in the hash table
654 /*-----------------------------------------------------------------*/
655 /* pic16_procregWithName - search for register by name */
656 /*-----------------------------------------------------------------*/
658 pic16_procregWithName (char *name)
666 /* hash the name to get a key */
668 hkey = regname2key(name);
670 // fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
672 reg = hTabFirstItemWK(dynProcRegNames, hkey);
676 if(STRCASECMP(reg->name, name) == 0) {
680 reg = hTabNextItemWK (dynProcRegNames);
684 return NULL; // name wasn't found in the hash table
688 /*-----------------------------------------------------------------*/
689 /* pic16_accessregWithName - search for register by name */
690 /*-----------------------------------------------------------------*/
692 pic16_accessregWithName (char *name)
700 /* hash the name to get a key */
702 hkey = regname2key(name);
704 // fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
706 reg = hTabFirstItemWK(dynAccessRegNames, hkey);
710 if(STRCASECMP(reg->name, name) == 0) {
714 reg = hTabNextItemWK (dynAccessRegNames);
718 return NULL; // name wasn't found in the hash table
722 regs *pic16_regWithName(char *name)
726 reg = pic16_dirregWithName( name );
729 reg = pic16_procregWithName( name );
732 reg = pic16_allocregWithName( name );
735 reg = pic16_accessregWithName( name );
742 /*-----------------------------------------------------------------*/
743 /* pic16_allocDirReg - allocates register of given type */
744 /*-----------------------------------------------------------------*/
746 pic16_allocDirReg (operand *op )
752 debugLog ("%s BAD, op is NULL\n", __FUNCTION__);
753 // fprintf(stderr, "%s BAD, op is NULL\n", __FUNCTION__);
757 name = OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name;
760 if(!SPEC_OCLS( OP_SYM_ETYPE(op))) {
762 if(pic16_debug_verbose)
764 fprintf(stderr, "%s:%d symbol %s(r:%s) is not assigned to a memmap\n", __FILE__, __LINE__,
765 OP_SYMBOL(op)->name, OP_SYMBOL(op)->rname);
771 if(!IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
772 || !IN_FARSPACE(SPEC_OCLS( OP_SYM_ETYPE(op))) ) {
775 if(pic16_debug_verbose) {
776 fprintf(stderr, "dispace:%d farspace:%d codespace:%d regspace:%d stack:%d eeprom: %d regparm: %d isparm: %d\n",
777 IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
778 IN_FARSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
779 IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
780 IN_REGSP( SPEC_OCLS( OP_SYM_ETYPE(op))),
781 IN_STACK( OP_SYM_ETYPE(op)),
782 SPEC_OCLS(OP_SYM_ETYPE(op)) == eeprom,
783 IS_REGPARM(OP_SYM_ETYPE(op)),
786 fprintf(stderr, "%s:%d symbol %s NOT in dirspace\n", __FILE__, __LINE__,
787 OP_SYMBOL(op)->name);
795 if (IS_CODE ( OP_SYM_ETYPE(op)) ) {
796 // fprintf(stderr, "%s:%d sym: %s in codespace\n", __FUNCTION__, __LINE__, OP_SYMBOL(op)->name);
800 if(IS_ITEMP(op))return NULL;
802 // if(IS_STATIC(OP_SYM_ETYPE(op)))return NULL;
804 if(IN_STACK(OP_SYM_ETYPE(op)))return NULL;
806 debugLog ("%s:%d symbol name %s\n", __FUNCTION__, __LINE__, name);
807 // fprintf(stderr, "%s symbol name %s\tSTATIC:%d\n", __FUNCTION__,name, IS_STATIC(OP_SYM_ETYPE(op)));
810 if(SPEC_CONST ( OP_SYM_ETYPE(op)) && (IS_CHAR ( OP_SYM_ETYPE(op)) )) {
811 debugLog(" %d const char\n",__LINE__);
812 debugLog(" value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
813 // fprintf(stderr, " %d const char\n",__LINE__);
814 // fprintf(stderr, " value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
818 debugLog(" %d storage class %d \n",__LINE__,SPEC_SCLS( OP_SYM_ETYPE(op)));
819 if (IS_CODE ( OP_SYM_ETYPE(op)) )
820 debugLog(" %d code space\n",__LINE__);
822 if (IS_INTEGRAL ( OP_SYM_ETYPE(op)) )
823 debugLog(" %d integral\n",__LINE__);
825 if (IS_LITERAL ( OP_SYM_ETYPE(op)) )
826 debugLog(" %d literal\n",__LINE__);
828 if (IS_SPEC ( OP_SYM_ETYPE(op)) )
829 debugLog(" %d specifier\n",__LINE__);
831 debugAopGet(NULL, op);
835 reg = pic16_dirregWithName(name);
839 int regtype = REG_GPR;
841 /* if this is at an absolute address, then get the address. */
842 if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
843 address = SPEC_ADDR ( OP_SYM_ETYPE(op));
844 // fprintf(stderr,"reg %s is at an absolute address: 0x%03x\n",name,address);
847 /* Register wasn't found in hash, so let's create
848 * a new one and put it in the hash table AND in the
849 * dynDirectRegNames set */
850 if(IS_CODE(OP_SYM_ETYPE(op)) || IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))) {
851 debugLog("%s:%d sym: %s in codespace\n", __FUNCTION__, __LINE__, OP_SYMBOL(op)->name);
857 if(OP_SYMBOL(op)->onStack) {
858 fprintf(stderr, "%s:%d onStack %s offset: %d\n", __FILE__, __LINE__,
859 OP_SYMBOL(op)->name, OP_SYMBOL(op)->stack);
863 if(!IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
864 || !IN_FARSPACE(SPEC_OCLS( OP_SYM_ETYPE(op))) ) {
867 if(pic16_debug_verbose)
869 fprintf(stderr, "dispace:%d farspace:%d codespace:%d regspace:%d stack:%d eeprom: %d\n",
870 IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
871 IN_FARSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
872 IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
873 IN_REGSP( SPEC_OCLS( OP_SYM_ETYPE(op))),
874 IN_STACK( OP_SYM_ETYPE(op)),
875 SPEC_OCLS(OP_SYM_ETYPE(op)) == eeprom);
877 fprintf(stderr, "%s:%d symbol %s NOT in dirspace\n", __FILE__, __LINE__,
878 OP_SYMBOL(op)->name);
883 reg = newReg(regtype, PO_DIR, rDirectIdx++, name,getSize (OP_SYMBOL (op)->type),0, op);
884 debugLog ("%d -- added %s to hash, size = %d\n", __LINE__, name,reg->size);
886 if( SPEC_SCLS( OP_SYM_ETYPE( op ) ) == S_REGISTER ) {
887 fprintf(stderr, "%s:%d symbol %s is declared as register\n", __FILE__, __LINE__,
891 checkAddReg(&pic16_dynAccessRegs, reg);
892 hTabAddItem(&dynAccessRegNames, regname2key(name), reg);
898 // if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
899 // fprintf(stderr, " ralloc.c at fixed address: %s - changing to REG_SFR\n",name);
900 // reg->type = REG_SFR;
903 if (IS_BITVAR (OP_SYM_ETYPE(op))) {
904 // fprintf(stderr, "%s:%d adding %s in bit registers\n", __FILE__, __LINE__, reg->name);
905 addSet(&pic16_dynDirectBitRegs, reg);
908 // fprintf(stderr, "%s:%d adding %s in direct registers\n", __FILE__, __LINE__, reg->name);
909 // addSet(&pic16_dynDirectRegs, reg);
912 if(!(IS_STATIC(OP_SYM_ETYPE(op))
913 && OP_SYMBOL(op)->ival
916 checkAddReg(&pic16_dynDirectRegs, reg);
920 // debugLog (" -- %s is declared at address 0x30000x\n",name);
921 return (reg); /* This was NULL before, but since we found it
922 * why not just return it?! */
925 if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
927 reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
929 /* work around for user defined registers in access bank */
930 if((reg->address>= 0x00 && reg->address < 0x80)
931 || (reg->address >= 0xf80 && reg->address <= 0xfff))
934 debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address);
940 /*-----------------------------------------------------------------*/
941 /* pic16_allocRegByName - allocates register of given type */
942 /*-----------------------------------------------------------------*/
944 pic16_allocRegByName (char *name, int size, operand *op)
950 fprintf(stderr, "%s - allocating a NULL register\n",__FUNCTION__);
954 /* First, search the hash table to see if there is a register with this name */
955 reg = pic16_dirregWithName(name);
959 /* Register wasn't found in hash, so let's create
960 * a new one and put it in the hash table AND in the
961 * dynDirectRegNames set */
963 fprintf (stderr,"%s:%d symbol name %s\tregop= %p\n", __FUNCTION__, __LINE__, name, op);
965 reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,size,0, op);
967 debugLog ("%d -- added %s to hash, size = %d\n", __LINE__, name,reg->size);
968 //fprintf(stderr, " -- added %s to hash, size = %d\n", name,reg->size);
970 //hTabAddItem(&dynDirectRegNames, regname2key(name), reg); /* initially commented out */
971 addSet(&pic16_dynDirectRegs, reg);
977 /*-----------------------------------------------------------------*/
978 /* RegWithIdx - returns pointer to register with index number */
979 /*-----------------------------------------------------------------*/
980 regs *pic16_typeRegWithIdx (int idx, int type, int fixed)
985 debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx);
986 // fprintf(stderr, "%s - requesting index = 0x%x\n", __FUNCTION__, idx);
991 if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx, fixed)) != NULL) {
993 debugLog ("Found a Dynamic Register!\n");
996 if( (dReg = regWithIdx ( pic16_dynDirectRegs, idx, fixed)) != NULL ) {
997 debugLog ("Found a Direct Register!\n");
1003 if( (dReg = regWithIdx ( pic16_dynStackRegs, idx, fixed)) != NULL ) {
1004 debugLog ("Found a Stack Register!\n");
1009 if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx, 1)) != NULL ) {
1010 debugLog ("Found a Processor Register!\n");
1024 /*-----------------------------------------------------------------*/
1025 /* pic16_regWithIdx - returns pointer to register with index number*/
1026 /*-----------------------------------------------------------------*/
1028 pic16_regWithIdx (int idx)
1032 if( (dReg = pic16_typeRegWithIdx(idx,REG_GPR,0)) != NULL)
1035 if( (dReg = pic16_typeRegWithIdx(idx,REG_SFR,0)) != NULL)
1039 if( (dReg = pic16_typeRegWithIdx(idx,REG_STK,0)) != NULL)
1046 /*-----------------------------------------------------------------*/
1047 /* pic16_regWithIdx - returns pointer to register with index number */
1048 /*-----------------------------------------------------------------*/
1050 pic16_allocWithIdx (int idx)
1055 debugLog ("%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
1056 // fprintf(stderr, "%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
1058 if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx,0)) != NULL) {
1060 debugLog ("Found a Dynamic Register!\n");
1061 } else if( (dReg = regWithIdx ( pic16_dynStackRegs, idx,0)) != NULL ) {
1062 debugLog ("Found a Stack Register!\n");
1063 } else if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx,1)) != NULL ) {
1064 debugLog ("Found a Processor Register!\n");
1065 fprintf(stderr, "Found a processor register! %s\n", dReg->name);
1066 } else if( (dReg = regWithIdx ( pic16_dynInternalRegs, idx,0)) != NULL ) {
1067 debugLog ("Found an Internal Register!\n");
1070 debugLog ("Dynamic Register not found\n");
1073 //fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx);
1074 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1075 "regWithIdx not found");
1085 /*-----------------------------------------------------------------*/
1086 /*-----------------------------------------------------------------*/
1088 pic16_findFreeReg(short type)
1095 if((dReg = regFindFree(pic16_dynAllocRegs)) != NULL)
1097 return allocReg( REG_GPR ); //addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL));
1101 if((dReg = regFindFree(pic16_dynStackRegs)) != NULL)
1115 pic16_findFreeRegNext(short type, regs *creg)
1122 if((dReg = regFindFreeNext(pic16_dynAllocRegs, creg)) != NULL)
1124 return (addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL)));
1128 if((dReg = regFindFreeNext(pic16_dynStackRegs, creg)) != NULL)
1140 /*-----------------------------------------------------------------*/
1141 /* freeReg - frees a register */
1142 /*-----------------------------------------------------------------*/
1144 freeReg (regs * reg)
1146 debugLog ("%s\n", __FUNCTION__);
1147 // fprintf(stderr, "%s:%d register %s (%p) is freed\n", __FILE__, __LINE__, reg->name, reg);
1152 /*-----------------------------------------------------------------*/
1153 /* nFreeRegs - returns number of free registers */
1154 /*-----------------------------------------------------------------*/
1156 nFreeRegs (int type)
1162 /* although I fixed the register allocation/freeing scheme
1163 * the for loop below doesn't give valid results. I do not
1164 * know why yet. -- VR 10-Jan-2003 */
1169 /* dynamically allocate as many as we need and worry about
1170 * fitting them into a PIC later */
1172 debugLog ("%s\n", __FUNCTION__);
1174 for(reg = setFirstItem(pic16_dynAllocRegs); reg; reg=setNextItem(pic16_dynAllocRegs))
1175 if((reg->type == type) && reg->isFree)nfr++;
1177 fprintf(stderr, "%s:%d # of free registers= %d\n", __FILE__, __LINE__, nfr);
1181 /*-----------------------------------------------------------------*/
1182 /* nfreeRegsType - free registers with type */
1183 /*-----------------------------------------------------------------*/
1185 nfreeRegsType (int type)
1188 debugLog ("%s\n", __FUNCTION__);
1189 if (type == REG_PTR)
1191 if ((nfr = nFreeRegs (type)) == 0)
1192 return nFreeRegs (REG_GPR);
1195 return nFreeRegs (type);
1198 static void writeSetUsedRegs(FILE *of, set *dRegs)
1203 for (dReg = setFirstItem(dRegs) ; dReg ;
1204 dReg = setNextItem(dRegs)) {
1207 fprintf (of, "\t%s\n",dReg->name);
1213 extern void pic16_groupRegistersInSection(set *regset);
1215 extern void pic16_dump_equates(FILE *of, set *equs);
1216 extern void pic16_dump_access(FILE *of, set *section);
1217 //extern void pic16_dump_map(void);
1218 extern void pic16_dump_usection(FILE *of, set *section, int fix);
1219 extern void pic16_dump_isection(FILE *of, set *section, int fix);
1220 extern void pic16_dump_int_registers(FILE *of, set *section);
1221 extern void pic16_dump_idata(FILE *of, set *idataSymSet);
1223 extern void pic16_dump_gsection(FILE *of, set *sections);
1225 static void packBits(set *bregs)
1229 regs *bitfield=NULL;
1230 regs *relocbitfield=NULL;
1236 for (regset = bregs ; regset ;
1237 regset = regset->next) {
1239 breg = regset->item;
1240 breg->isBitField = 1;
1241 //fprintf(stderr,"bit reg: %s\n",breg->name);
1244 //fprintf(stderr,"packing bit at fixed address = 0x%03x\n",breg->address);
1246 bitfield = pic16_typeRegWithIdx (breg->address >> 3, -1 , 1);
1247 breg->rIdx = breg->address & 7;
1248 breg->address >>= 3;
1251 sprintf (buffer, "fbitfield%02x", breg->address);
1252 //fprintf(stderr,"new bit field\n");
1253 bitfield = newReg(REG_SFR, PO_GPR_BIT,breg->address,buffer,1,0, NULL);
1254 bitfield->isBitField = 1;
1255 bitfield->isFixed = 1;
1256 bitfield->address = breg->address;
1257 addSet(&pic16_dynDirectRegs,bitfield);
1258 //hTabAddItem(&dynDirectRegNames, regname2key(buffer), bitfield);
1260 //fprintf(stderr," which is occupied by %s (addr = %d)\n",bitfield->name,bitfield->address);
1263 breg->reg_alias = bitfield;
1267 if(!relocbitfield || bit_no >7) {
1270 sprintf (buffer, "bitfield%d", byte_no);
1271 //fprintf(stderr,"new relocatable bit field\n");
1272 relocbitfield = newReg(REG_GPR, PO_GPR_BIT,rDirectIdx++,buffer,1,0, NULL);
1273 relocbitfield->isBitField = 1;
1274 addSet(&pic16_dynDirectRegs,relocbitfield);
1275 //hTabAddItem(&dynDirectRegNames, regname2key(buffer), relocbitfield);
1279 breg->reg_alias = relocbitfield;
1280 breg->address = rDirectIdx; /* byte_no; */
1281 breg->rIdx = bit_no++;
1287 void pic16_writeUsedRegs(FILE *of)
1289 packBits(pic16_dynDirectBitRegs);
1291 // fprintf(stderr, "%s: pic16_dynAllocRegs\n", __FUNCTION__);
1292 pic16_groupRegistersInSection(pic16_dynAllocRegs);
1294 // fprintf(stderr, "%s: pic16_dynInternalRegs\n", __FUNCTION__);
1295 pic16_groupRegistersInSection(pic16_dynInternalRegs);
1297 // fprintf(stderr, "%s: pic16_dynStackRegs\n", __FUNCTION__);
1298 pic16_groupRegistersInSection(pic16_dynStackRegs);
1300 // fprintf(stderr, "%s: pic16_dynDirectRegs\n", __FUNCTION__);
1301 pic16_groupRegistersInSection(pic16_dynDirectRegs);
1303 // fprintf(stderr, "%s: pic16_dynDirectBitsRegs\n", __FUNCTION__);
1304 pic16_groupRegistersInSection(pic16_dynDirectBitRegs);
1306 // fprintf(stderr, "%s: pic16_dynProcessorRegs\n", __FUNCTION__);
1307 pic16_groupRegistersInSection(pic16_dynProcessorRegs);
1309 // fprintf(stderr, "%s: pic16_dynAccessRegs\n", __FUNCTION__);
1310 pic16_groupRegistersInSection(pic16_dynAccessRegs);
1313 pic16_dump_equates(of, pic16_equ_data);
1315 // pic16_dump_esection(of, pic16_rel_eedata, 0);
1316 // pic16_dump_esection(of, pic16_fix_eedata, 0);
1318 /* dump access bank symbols */
1319 pic16_dump_access(of, pic16_acs_udata);
1321 /* dump initialised data */
1322 pic16_dump_isection(of, rel_idataSymSet, 0);
1323 pic16_dump_isection(of, fix_idataSymSet, 1);
1325 /* dump internal registers */
1326 pic16_dump_int_registers(of, pic16_int_regs);
1328 /* dump generic section variables */
1329 pic16_dump_gsection(of, sectNames);
1331 /* dump other variables */
1332 pic16_dump_usection(of, pic16_rel_udata, 0);
1333 pic16_dump_usection(of, pic16_fix_udata, 1);
1338 /*-----------------------------------------------------------------*/
1339 /* computeSpillable - given a point find the spillable live ranges */
1340 /*-----------------------------------------------------------------*/
1342 computeSpillable (iCode * ic)
1346 debugLog ("%s\n", __FUNCTION__);
1347 /* spillable live ranges are those that are live at this
1348 point . the following categories need to be subtracted
1350 a) - those that are already spilt
1351 b) - if being used by this one
1352 c) - defined by this one */
1354 spillable = bitVectCopy (ic->rlive);
1356 bitVectCplAnd (spillable, _G.spiltSet); /* those already spilt */
1358 bitVectCplAnd (spillable, ic->uses); /* used in this one */
1359 bitVectUnSetBit (spillable, ic->defKey);
1360 spillable = bitVectIntersect (spillable, _G.regAssigned);
1365 /*-----------------------------------------------------------------*/
1366 /* noSpilLoc - return true if a variable has no spil location */
1367 /*-----------------------------------------------------------------*/
1369 noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
1371 debugLog ("%s\n", __FUNCTION__);
1372 return (sym->usl.spillLoc ? 0 : 1);
1375 /*-----------------------------------------------------------------*/
1376 /* hasSpilLoc - will return 1 if the symbol has spil location */
1377 /*-----------------------------------------------------------------*/
1379 hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
1381 debugLog ("%s\n", __FUNCTION__);
1382 return (sym->usl.spillLoc ? 1 : 0);
1385 /*-----------------------------------------------------------------*/
1386 /* directSpilLoc - will return 1 if the splilocation is in direct */
1387 /*-----------------------------------------------------------------*/
1389 directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
1391 debugLog ("%s\n", __FUNCTION__);
1392 if (sym->usl.spillLoc &&
1393 (IN_DIRSPACE (SPEC_OCLS (sym->usl.spillLoc->etype))))
1399 /*-----------------------------------------------------------------*/
1400 /* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
1401 /* but is not used as a pointer */
1402 /*-----------------------------------------------------------------*/
1404 hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
1406 debugLog ("%s\n", __FUNCTION__);
1407 return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
1410 /*-----------------------------------------------------------------*/
1411 /* rematable - will return 1 if the remat flag is set */
1412 /*-----------------------------------------------------------------*/
1414 rematable (symbol * sym, eBBlock * ebp, iCode * ic)
1416 debugLog ("%s\n", __FUNCTION__);
1420 /*-----------------------------------------------------------------*/
1421 /* notUsedInRemaining - not used or defined in remain of the block */
1422 /*-----------------------------------------------------------------*/
1424 notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
1426 debugLog ("%s\n", __FUNCTION__);
1427 return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
1428 allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
1431 /*-----------------------------------------------------------------*/
1432 /* allLRs - return true for all */
1433 /*-----------------------------------------------------------------*/
1435 allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
1437 debugLog ("%s\n", __FUNCTION__);
1441 /*-----------------------------------------------------------------*/
1442 /* liveRangesWith - applies function to a given set of live range */
1443 /*-----------------------------------------------------------------*/
1445 liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
1446 eBBlock * ebp, iCode * ic)
1451 debugLog ("%s\n", __FUNCTION__);
1452 if (!lrs || !lrs->size)
1455 for (i = 1; i < lrs->size; i++)
1458 if (!bitVectBitValue (lrs, i))
1461 /* if we don't find it in the live range
1462 hash table we are in serious trouble */
1463 if (!(sym = hTabItemWithKey (liveRanges, i)))
1465 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1466 "liveRangesWith could not find liveRange");
1470 if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
1471 addSetHead (&rset, sym);
1478 /*-----------------------------------------------------------------*/
1479 /* leastUsedLR - given a set determines which is the least used */
1480 /*-----------------------------------------------------------------*/
1482 leastUsedLR (set * sset)
1484 symbol *sym = NULL, *lsym = NULL;
1486 debugLog ("%s\n", __FUNCTION__);
1487 sym = lsym = setFirstItem (sset);
1492 for (; lsym; lsym = setNextItem (sset))
1495 /* if usage is the same then prefer
1496 the spill the smaller of the two */
1497 if (lsym->used == sym->used)
1498 if (getSize (lsym->type) < getSize (sym->type))
1502 if (lsym->used < sym->used)
1507 setToNull ((void *) &sset);
1512 /*-----------------------------------------------------------------*/
1513 /* noOverLap - will iterate through the list looking for over lap */
1514 /*-----------------------------------------------------------------*/
1516 noOverLap (set * itmpStack, symbol * fsym)
1519 debugLog ("%s\n", __FUNCTION__);
1522 for (sym = setFirstItem (itmpStack); sym;
1523 sym = setNextItem (itmpStack))
1525 if (sym->liveTo > fsym->liveFrom)
1533 /*-----------------------------------------------------------------*/
1534 /* isFree - will return 1 if the a free spil location is found */
1535 /*-----------------------------------------------------------------*/
1540 V_ARG (symbol **, sloc);
1541 V_ARG (symbol *, fsym);
1543 debugLog ("%s\n", __FUNCTION__);
1544 /* if already found */
1548 /* if it is free && and the itmp assigned to
1549 this does not have any overlapping live ranges
1550 with the one currently being assigned and
1551 the size can be accomodated */
1553 noOverLap (sym->usl.itmpStack, fsym) &&
1554 getSize (sym->type) >= getSize (fsym->type))
1563 /*-----------------------------------------------------------------*/
1564 /* spillLRWithPtrReg :- will spil those live ranges which use PTR */
1565 /*-----------------------------------------------------------------*/
1567 spillLRWithPtrReg (symbol * forSym)
1573 debugLog ("%s\n", __FUNCTION__);
1574 if (!_G.regAssigned ||
1575 bitVectIsZero (_G.regAssigned))
1578 r0 = pic16_regWithIdx (R0_IDX);
1579 r1 = pic16_regWithIdx (R1_IDX);
1581 /* for all live ranges */
1582 for (lrsym = hTabFirstItem (liveRanges, &k); lrsym;
1583 lrsym = hTabNextItem (liveRanges, &k))
1587 /* if no registers assigned to it or
1589 /* if it does not overlap with this then
1590 not need to spill it */
1592 if (lrsym->isspilt || !lrsym->nRegs ||
1593 (lrsym->liveTo < forSym->liveFrom))
1596 /* go thru the registers : if it is either
1597 r0 or r1 then spil it */
1598 for (j = 0; j < lrsym->nRegs; j++)
1599 if (lrsym->regs[j] == r0 ||
1600 lrsym->regs[j] == r1)
1609 /*-----------------------------------------------------------------*/
1610 /* createStackSpil - create a location on the stack to spil */
1611 /*-----------------------------------------------------------------*/
1613 createStackSpil (symbol * sym)
1615 symbol *sloc = NULL;
1616 int useXstack, model, noOverlay;
1618 char slocBuffer[30];
1619 debugLog ("%s\n", __FUNCTION__);
1621 /* first go try and find a free one that is already
1622 existing on the stack */
1623 if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
1625 /* found a free one : just update & return */
1626 sym->usl.spillLoc = sloc;
1629 addSetHead (&sloc->usl.itmpStack, sym);
1633 /* could not then have to create one , this is the hard part
1634 we need to allocate this on the stack : this is really a
1635 hack!! but cannot think of anything better at this time */
1637 if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
1639 fprintf (stderr, "kkkInternal error: slocBuffer overflowed: %s:%d\n",
1640 __FILE__, __LINE__);
1644 sloc = newiTemp (slocBuffer);
1646 /* set the type to the spilling symbol */
1647 sloc->type = copyLinkChain (sym->type);
1648 sloc->etype = getSpec (sloc->type);
1649 SPEC_SCLS (sloc->etype) = S_DATA;
1650 SPEC_EXTR (sloc->etype) = 0;
1651 SPEC_STAT (sloc->etype) = 0;
1653 /* we don't allow it to be allocated`
1654 onto the external stack since : so we
1655 temporarily turn it off ; we also
1656 turn off memory model to prevent
1657 the spil from going to the external storage
1658 and turn off overlaying
1661 useXstack = options.useXstack;
1662 model = options.model;
1663 noOverlay = options.noOverlay;
1664 options.noOverlay = 1;
1665 options.model = options.useXstack = 0;
1669 options.useXstack = useXstack;
1670 options.model = model;
1671 options.noOverlay = noOverlay;
1672 sloc->isref = 1; /* to prevent compiler warning */
1674 /* if it is on the stack then update the stack */
1675 if (IN_STACK (sloc->etype))
1677 currFunc->stack += getSize (sloc->type);
1678 _G.stackExtend += getSize (sloc->type);
1681 _G.dataExtend += getSize (sloc->type);
1683 /* add it to the _G.stackSpil set */
1684 addSetHead (&_G.stackSpil, sloc);
1685 sym->usl.spillLoc = sloc;
1688 /* add it to the set of itempStack set
1689 of the spill location */
1690 addSetHead (&sloc->usl.itmpStack, sym);
1694 /*-----------------------------------------------------------------*/
1695 /* isSpiltOnStack - returns true if the spil location is on stack */
1696 /*-----------------------------------------------------------------*/
1698 isSpiltOnStack (symbol * sym)
1702 debugLog ("%s\n", __FUNCTION__);
1709 /* if (sym->_G.stackSpil) */
1712 if (!sym->usl.spillLoc)
1715 etype = getSpec (sym->usl.spillLoc->type);
1716 if (IN_STACK (etype))
1722 /*-----------------------------------------------------------------*/
1723 /* spillThis - spils a specific operand */
1724 /*-----------------------------------------------------------------*/
1726 spillThis (symbol * sym)
1729 debugLog ("%s : %s\n", __FUNCTION__, sym->rname);
1731 /* if this is rematerializable or has a spillLocation
1732 we are okay, else we need to create a spillLocation
1734 if (!(sym->remat || sym->usl.spillLoc))
1735 createStackSpil (sym);
1738 /* mark it has spilt & put it in the spilt set */
1740 _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
1742 bitVectUnSetBit (_G.regAssigned, sym->key);
1744 for (i = 0; i < sym->nRegs; i++)
1748 freeReg (sym->regs[i]);
1749 sym->regs[i] = NULL;
1752 /* if spilt on stack then free up r0 & r1
1753 if they could have been assigned to some
1755 if (!pic16_ptrRegReq && isSpiltOnStack (sym))
1758 spillLRWithPtrReg (sym);
1761 if (sym->usl.spillLoc && !sym->remat)
1762 sym->usl.spillLoc->allocreq = 1;
1766 /*-----------------------------------------------------------------*/
1767 /* selectSpil - select a iTemp to spil : rather a simple procedure */
1768 /*-----------------------------------------------------------------*/
1770 selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
1772 bitVect *lrcs = NULL;
1776 debugLog ("%s\n", __FUNCTION__);
1777 /* get the spillable live ranges */
1778 lrcs = computeSpillable (ic);
1780 /* get all live ranges that are rematerizable */
1781 if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
1784 /* return the least used of these */
1785 return leastUsedLR (selectS);
1788 /* get live ranges with spillLocations in direct space */
1789 if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
1791 sym = leastUsedLR (selectS);
1792 strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ?
1793 sym->usl.spillLoc->rname :
1794 sym->usl.spillLoc->name));
1796 /* mark it as allocation required */
1797 sym->usl.spillLoc->allocreq = 1;
1801 /* if the symbol is local to the block then */
1802 if (forSym->liveTo < ebp->lSeq)
1805 /* check if there are any live ranges allocated
1806 to registers that are not used in this block */
1807 if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
1809 sym = leastUsedLR (selectS);
1810 /* if this is not rematerializable */
1819 /* check if there are any live ranges that not
1820 used in the remainder of the block */
1821 if (!_G.blockSpil &&
1822 !isiCodeInFunctionCall (ic) &&
1823 (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
1825 sym = leastUsedLR (selectS);
1828 sym->remainSpil = 1;
1835 /* find live ranges with spillocation && not used as pointers */
1836 if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
1839 sym = leastUsedLR (selectS);
1840 /* mark this as allocation required */
1841 sym->usl.spillLoc->allocreq = 1;
1845 /* find live ranges with spillocation */
1846 if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
1849 sym = leastUsedLR (selectS);
1850 sym->usl.spillLoc->allocreq = 1;
1854 /* couldn't find then we need to create a spil
1855 location on the stack , for which one? the least
1857 if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
1860 /* return a created spil location */
1861 sym = createStackSpil (leastUsedLR (selectS));
1862 sym->usl.spillLoc->allocreq = 1;
1866 /* this is an extreme situation we will spill
1867 this one : happens very rarely but it does happen */
1873 /*-----------------------------------------------------------------*/
1874 /* spilSomething - spil some variable & mark registers as free */
1875 /*-----------------------------------------------------------------*/
1877 spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
1882 debugLog ("%s\n", __FUNCTION__);
1883 /* get something we can spil */
1884 ssym = selectSpil (ic, ebp, forSym);
1886 /* mark it as spilt */
1888 _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
1890 /* mark it as not register assigned &
1891 take it away from the set */
1892 bitVectUnSetBit (_G.regAssigned, ssym->key);
1894 /* mark the registers as free */
1895 for (i = 0; i < ssym->nRegs; i++)
1897 freeReg (ssym->regs[i]);
1899 /* if spilt on stack then free up r0 & r1
1900 if they could have been assigned to as gprs */
1901 if (!pic16_ptrRegReq && isSpiltOnStack (ssym))
1904 spillLRWithPtrReg (ssym);
1907 /* if this was a block level spil then insert push & pop
1908 at the start & end of block respectively */
1909 if (ssym->blockSpil)
1911 iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
1912 /* add push to the start of the block */
1913 addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
1914 ebp->sch->next : ebp->sch));
1915 nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
1916 /* add pop to the end of the block */
1917 addiCodeToeBBlock (ebp, nic, NULL);
1920 /* if spilt because not used in the remainder of the
1921 block then add a push before this instruction and
1922 a pop at the end of the block */
1923 if (ssym->remainSpil)
1926 iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
1927 /* add push just before this instruction */
1928 addiCodeToeBBlock (ebp, nic, ic);
1930 nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
1931 /* add pop to the end of the block */
1932 addiCodeToeBBlock (ebp, nic, NULL);
1941 /*-----------------------------------------------------------------*/
1942 /* getRegPtr - will try for PTR if not a GPR type if not spil */
1943 /*-----------------------------------------------------------------*/
1945 getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
1950 debugLog ("%s\n", __FUNCTION__);
1952 /* try for a ptr type */
1953 if ((reg = allocReg (REG_PTR)))
1956 /* try for gpr type */
1957 if ((reg = allocReg (REG_GPR)))
1960 /* we have to spil */
1961 if (!spilSomething (ic, ebp, sym))
1964 /* make sure partially assigned registers aren't reused */
1965 for (j=0; j<=sym->nRegs; j++)
1967 sym->regs[j]->isFree = 0;
1969 /* this looks like an infinite loop but
1970 in really selectSpil will abort */
1974 /*-----------------------------------------------------------------*/
1975 /* getRegGpr - will try for GPR if not spil */
1976 /*-----------------------------------------------------------------*/
1978 getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
1983 debugLog ("%s\n", __FUNCTION__);
1985 /* try for gpr type */
1986 if ((reg = allocReg (REG_GPR)))
1989 if (!pic16_ptrRegReq)
1990 if ((reg = allocReg (REG_PTR)))
1993 /* we have to spil */
1994 if (!spilSomething (ic, ebp, sym))
1997 /* make sure partially assigned registers aren't reused */
1998 for (j=0; j<=sym->nRegs; j++)
2000 sym->regs[j]->isFree = 0;
2002 /* this looks like an infinite loop but
2003 in really selectSpil will abort */
2007 /*-----------------------------------------------------------------*/
2008 /* symHasReg - symbol has a given register */
2009 /*-----------------------------------------------------------------*/
2011 symHasReg (symbol * sym, regs * reg)
2015 debugLog ("%s\n", __FUNCTION__);
2016 for (i = 0; i < sym->nRegs; i++)
2017 if (sym->regs[i] == reg)
2023 /*-----------------------------------------------------------------*/
2024 /* deassignLRs - check the live to and if they have registers & are */
2025 /* not spilt then free up the registers */
2026 /*-----------------------------------------------------------------*/
2028 deassignLRs (iCode * ic, eBBlock * ebp)
2034 debugLog ("%s\n", __FUNCTION__);
2035 for (sym = hTabFirstItem (liveRanges, &k); sym;
2036 sym = hTabNextItem (liveRanges, &k))
2039 symbol *psym = NULL;
2040 /* if it does not end here */
2041 if (sym->liveTo > ic->seq)
2044 /* if it was spilt on stack then we can
2045 mark the stack spil location as free */
2050 sym->usl.spillLoc->isFree = 1;
2056 if (!bitVectBitValue (_G.regAssigned, sym->key))
2059 /* special case for shifting: there is a case where shift count
2060 * can be allocated in the same register as the result, so do not
2061 * free right registers if same as result registers, cause genShiftLeft
2062 * will fail -- VR */
2063 if(ic->op == LEFT_OP)
2066 /* special case check if this is an IFX &
2067 the privious one was a pop and the
2068 previous one was not spilt then keep track
2070 if (ic->op == IFX && ic->prev &&
2071 ic->prev->op == IPOP &&
2072 !ic->prev->parmPush &&
2073 !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
2074 psym = OP_SYMBOL (IC_LEFT (ic->prev));
2080 bitVectUnSetBit (_G.regAssigned, sym->key);
2082 /* if the result of this one needs registers
2083 and does not have it then assign it right
2085 if (IC_RESULT (ic) &&
2086 !(SKIP_IC2 (ic) || /* not a special icode */
2087 ic->op == JUMPTABLE ||
2092 POINTER_SET (ic)) &&
2093 (result = OP_SYMBOL (IC_RESULT (ic))) && /* has a result */
2094 result->liveTo > ic->seq && /* and will live beyond this */
2095 result->liveTo <= ebp->lSeq && /* does not go beyond this block */
2096 result->liveFrom == ic->seq && /* does not start before here */
2097 result->regType == sym->regType && /* same register types */
2098 result->nRegs && /* which needs registers */
2099 !result->isspilt && /* and does not already have them */
2101 !bitVectBitValue (_G.regAssigned, result->key) &&
2102 /* the number of free regs + number of regs in this LR
2103 can accomodate the what result Needs */
2104 ((nfreeRegsType (result->regType) +
2105 sym->nRegs) >= result->nRegs)
2109 for (i = 0; i < max (sym->nRegs, result->nRegs); i++)
2111 result->regs[i] = sym->regs[i];
2113 result->regs[i] = getRegGpr (ic, ebp, result);
2115 _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
2119 /* free the remaining */
2120 for (; i < sym->nRegs; i++)
2124 if (!symHasReg (psym, sym->regs[i]))
2125 freeReg (sym->regs[i]);
2128 freeReg (sym->regs[i]);
2135 /*-----------------------------------------------------------------*/
2136 /* reassignLR - reassign this to registers */
2137 /*-----------------------------------------------------------------*/
2139 reassignLR (operand * op)
2141 symbol *sym = OP_SYMBOL (op);
2144 debugLog ("%s\n", __FUNCTION__);
2145 /* not spilt any more */
2146 sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
2147 bitVectUnSetBit (_G.spiltSet, sym->key);
2149 _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
2153 for (i = 0; i < sym->nRegs; i++)
2154 sym->regs[i]->isFree = 0;
2157 /*-----------------------------------------------------------------*/
2158 /* willCauseSpill - determines if allocating will cause a spill */
2159 /*-----------------------------------------------------------------*/
2161 willCauseSpill (int nr, int rt)
2163 debugLog ("%s\n", __FUNCTION__);
2164 /* first check if there are any avlb registers
2165 of te type required */
2168 /* special case for pointer type
2169 if pointer type not avlb then
2170 check for type gpr */
2171 if (nFreeRegs (rt) >= nr)
2173 if (nFreeRegs (REG_GPR) >= nr)
2178 if (pic16_ptrRegReq)
2180 if (nFreeRegs (rt) >= nr)
2185 if (nFreeRegs (REG_PTR) +
2186 nFreeRegs (REG_GPR) >= nr)
2191 debugLog (" ... yep it will (cause a spill)\n");
2192 /* it will cause a spil */
2196 /*-----------------------------------------------------------------*/
2197 /* positionRegs - the allocator can allocate same registers to res- */
2198 /* ult and operand, if this happens make sure they are in the same */
2199 /* position as the operand otherwise chaos results */
2200 /*-----------------------------------------------------------------*/
2202 positionRegs (symbol * result, symbol * opsym, int lineno)
2204 int count = min (result->nRegs, opsym->nRegs);
2205 int i, j = 0, shared = 0;
2207 debugLog ("%s\n", __FUNCTION__);
2208 /* if the result has been spilt then cannot share */
2213 /* first make sure that they actually share */
2214 for (i = 0; i < count; i++)
2216 for (j = 0; j < count; j++)
2218 if (result->regs[i] == opsym->regs[j] && i != j)
2228 regs *tmp = result->regs[i];
2229 result->regs[i] = result->regs[j];
2230 result->regs[j] = tmp;
2235 /*------------------------------------------------------------------*/
2236 /* verifyRegsAssigned - make sure an iTemp is properly initialized; */
2237 /* it should either have registers or have beed spilled. Otherwise, */
2238 /* there was an uninitialized variable, so just spill this to get */
2239 /* the operand in a valid state. */
2240 /*------------------------------------------------------------------*/
2242 verifyRegsAssigned (operand *op, iCode * ic)
2247 if (!IS_ITEMP (op)) return;
2249 sym = OP_SYMBOL (op);
2250 if (sym->isspilt) return;
2251 if (!sym->nRegs) return;
2252 if (sym->regs[0]) return;
2254 werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT,
2255 sym->prereqv ? sym->prereqv->name : sym->name);
2260 /*-----------------------------------------------------------------*/
2261 /* serialRegAssign - serially allocate registers to the variables */
2262 /*-----------------------------------------------------------------*/
2264 serialRegAssign (eBBlock ** ebbs, int count)
2269 debugLog ("%s\n", __FUNCTION__);
2270 /* for all blocks */
2271 for (i = 0; i < count; i++)
2273 if (ebbs[i]->noPath &&
2274 (ebbs[i]->entryLabel != entryLabel &&
2275 ebbs[i]->entryLabel != returnLabel))
2278 /* of all instructions do */
2279 for (ic = ebbs[i]->sch; ic; ic = ic->next)
2282 debugLog (" op: %s\n", pic16_decodeOp (ic->op));
2284 if(IC_RESULT(ic) && !IS_ITEMP( IC_RESULT(ic)))
2285 pic16_allocDirReg(IC_RESULT(ic));
2287 if(IC_LEFT(ic) && !IS_ITEMP( IC_LEFT(ic)))
2288 pic16_allocDirReg(IC_LEFT(ic));
2290 if(IC_RIGHT(ic) && !IS_ITEMP( IC_RIGHT(ic)))
2291 pic16_allocDirReg(IC_RIGHT(ic));
2293 /* if this is an ipop that means some live
2294 range will have to be assigned again */
2296 reassignLR (IC_LEFT (ic));
2298 /* if result is present && is a true symbol */
2299 if (IC_RESULT (ic) && ic->op != IFX &&
2300 IS_TRUE_SYMOP (IC_RESULT (ic)))
2301 OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
2303 /* take away registers from live
2304 ranges that end at this instruction */
2305 deassignLRs (ic, ebbs[i]);
2307 /* some don't need registers */
2308 if (SKIP_IC2 (ic) ||
2309 ic->op == JUMPTABLE ||
2313 (IC_RESULT (ic) && POINTER_SET (ic)))
2316 /* now we need to allocate registers
2317 only for the result */
2320 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2326 /* Make sure any spill location is definately allocated */
2327 if (sym->isspilt && !sym->remat && sym->usl.spillLoc &&
2328 !sym->usl.spillLoc->allocreq)
2330 sym->usl.spillLoc->allocreq++;
2333 /* if it does not need or is spilt
2334 or is already assigned to registers
2335 or will not live beyond this instructions */
2338 bitVectBitValue (_G.regAssigned, sym->key) ||
2339 sym->liveTo <= ic->seq)
2342 /* if some liverange has been spilt at the block level
2343 and this one live beyond this block then spil this
2345 if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
2350 /* if trying to allocate this will cause
2351 a spill and there is nothing to spill
2352 or this one is rematerializable then
2354 willCS = willCauseSpill (sym->nRegs, sym->regType);
2356 /* explicit turn off register spilling */
2359 spillable = computeSpillable (ic);
2361 (willCS && bitVectIsZero (spillable)))
2369 /* If the live range preceeds the point of definition
2370 then ideally we must take into account registers that
2371 have been allocated after sym->liveFrom but freed
2372 before ic->seq. This is complicated, so spill this
2373 symbol instead and let fillGaps handle the allocation. */
2375 if (sym->liveFrom < ic->seq)
2381 /* if it has a spillocation & is used less than
2382 all other live ranges then spill this */
2384 if (sym->usl.spillLoc) {
2385 symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
2386 allLRs, ebbs[i], ic));
2387 if (leastUsed && leastUsed->used > sym->used) {
2392 /* if none of the liveRanges have a spillLocation then better
2393 to spill this one than anything else already assigned to registers */
2394 if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
2395 /* if this is local to this block then we might find a block spil */
2396 if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
2404 if (ic->op == RECEIVE)
2405 debugLog ("When I get clever, I'll optimize the receive logic\n");
2407 if(POINTER_GET(ic) && IS_BITFIELD(getSpec(operandType(IC_RESULT(ic))))
2408 && (SPEC_BLEN(getSpec(operandType(IC_RESULT(ic))))==1)
2409 && (ic->next->op == IFX)
2410 && (OP_LIVETO(IC_RESULT(ic)) == ic->next->seq)) {
2412 /* skip register allocation since none will be used */
2413 for(j=0;j<sym->nRegs;j++)
2414 sym->regs[j] = newReg(REG_TMP, PO_GPR_TEMP, 0, "bad", 1, 0, NULL);
2415 // OP_SYMBOL(IC_RESULT(ic))->nRegs = 0;
2420 /* if we need ptr regs for the right side
2422 if (POINTER_GET (ic) && IS_SYMOP( IC_LEFT(ic) ) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
2423 <= (unsigned) PTRSIZE)
2428 /* else we assign registers to it */
2429 _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
2432 bitVectDebugOn(_G.regAssigned, debugF);
2434 for (j = 0; j < sym->nRegs; j++)
2436 if (sym->regType == REG_PTR)
2437 sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
2439 sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
2441 /* if the allocation falied which means
2442 this was spilt then break */
2446 debugLog (" %d - \n", __LINE__);
2448 /* if it shares registers with operands make sure
2449 that they are in the same position */
2450 if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
2451 OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
2452 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2453 OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
2454 /* do the same for the right operand */
2455 if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
2456 OP_SYMBOL (IC_RIGHT (ic))->nRegs && ic->op != '=')
2457 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2458 OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
2460 debugLog (" %d - \n", __LINE__);
2463 debugLog (" %d - \n", __LINE__);
2472 /* Check for and fix any problems with uninitialized operands */
2473 for (i = 0; i < count; i++)
2477 if (ebbs[i]->noPath &&
2478 (ebbs[i]->entryLabel != entryLabel &&
2479 ebbs[i]->entryLabel != returnLabel))
2482 for (ic = ebbs[i]->sch; ic; ic = ic->next)
2489 verifyRegsAssigned (IC_COND (ic), ic);
2493 if (ic->op == JUMPTABLE)
2495 verifyRegsAssigned (IC_JTCOND (ic), ic);
2499 verifyRegsAssigned (IC_RESULT (ic), ic);
2500 verifyRegsAssigned (IC_LEFT (ic), ic);
2501 verifyRegsAssigned (IC_RIGHT (ic), ic);
2507 /*-----------------------------------------------------------------*/
2508 /* rUmaskForOp :- returns register mask for an operand */
2509 /*-----------------------------------------------------------------*/
2511 rUmaskForOp (operand * op)
2517 debugLog ("%s\n", __FUNCTION__);
2518 /* only temporaries are assigned registers */
2522 sym = OP_SYMBOL (op);
2524 /* if spilt or no registers assigned to it
2526 if (sym->isspilt || !sym->nRegs)
2529 rumask = newBitVect (pic16_nRegs);
2531 for (j = 0; j < sym->nRegs; j++)
2533 rumask = bitVectSetBit (rumask,
2534 sym->regs[j]->rIdx);
2540 /*-----------------------------------------------------------------*/
2541 /* regsUsedIniCode :- returns bit vector of registers used in iCode */
2542 /*-----------------------------------------------------------------*/
2544 regsUsedIniCode (iCode * ic)
2546 bitVect *rmask = newBitVect (pic16_nRegs);
2548 debugLog ("%s\n", __FUNCTION__);
2549 /* do the special cases first */
2552 rmask = bitVectUnion (rmask,
2553 rUmaskForOp (IC_COND (ic)));
2557 /* for the jumptable */
2558 if (ic->op == JUMPTABLE)
2560 rmask = bitVectUnion (rmask,
2561 rUmaskForOp (IC_JTCOND (ic)));
2566 /* of all other cases */
2568 rmask = bitVectUnion (rmask,
2569 rUmaskForOp (IC_LEFT (ic)));
2573 rmask = bitVectUnion (rmask,
2574 rUmaskForOp (IC_RIGHT (ic)));
2577 rmask = bitVectUnion (rmask,
2578 rUmaskForOp (IC_RESULT (ic)));
2584 /*-----------------------------------------------------------------*/
2585 /* createRegMask - for each instruction will determine the regsUsed */
2586 /*-----------------------------------------------------------------*/
2588 createRegMask (eBBlock ** ebbs, int count)
2592 debugLog ("%s\n", __FUNCTION__);
2593 /* for all blocks */
2594 for (i = 0; i < count; i++)
2598 if (ebbs[i]->noPath &&
2599 (ebbs[i]->entryLabel != entryLabel &&
2600 ebbs[i]->entryLabel != returnLabel))
2603 /* for all instructions */
2604 for (ic = ebbs[i]->sch; ic; ic = ic->next)
2609 if (SKIP_IC2 (ic) || !ic->rlive)
2612 /* first mark the registers used in this
2614 ic->rUsed = regsUsedIniCode (ic);
2615 _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
2617 /* now create the register mask for those
2618 registers that are in use : this is a
2619 super set of ic->rUsed */
2620 ic->rMask = newBitVect (pic16_nRegs + 1);
2622 /* for all live Ranges alive at this point */
2623 for (j = 1; j < ic->rlive->size; j++)
2628 /* if not alive then continue */
2629 if (!bitVectBitValue (ic->rlive, j))
2632 /* find the live range we are interested in */
2633 if (!(sym = hTabItemWithKey (liveRanges, j)))
2635 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2636 "createRegMask cannot find live range");
2640 /* if no register assigned to it */
2641 if (!sym->nRegs || sym->isspilt)
2644 /* for all the registers allocated to it */
2645 for (k = 0; k < sym->nRegs; k++)
2648 bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
2654 /*-----------------------------------------------------------------*/
2655 /* rematStr - returns the rematerialized string for a remat var */
2656 /*-----------------------------------------------------------------*/
2658 rematStr (symbol * sym)
2661 iCode *ic = sym->rematiCode;
2662 symbol *psym = NULL;
2664 debugLog ("%s\n", __FUNCTION__);
2666 //printf ("%s\n", s);
2668 /* if plus or minus print the right hand side */
2670 if (ic->op == '+' || ic->op == '-') {
2672 iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2674 sprintf (s, "(%s %c 0x%04x)",
2675 OP_SYMBOL (IC_LEFT (ric))->rname,
2677 (int) operandLitValue (IC_RIGHT (ic)));
2680 //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
2682 psym = newSymbol (OP_SYMBOL (IC_LEFT (ric))->rname, 1);
2683 psym->offset = (int) operandLitValue (IC_RIGHT (ic));
2688 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
2689 psym = newSymbol (OP_SYMBOL (IC_LEFT (ic))->rname, 1);
2691 //printf ("ralloc.c:%d %s\n", __LINE__,buffer);
2696 /*-----------------------------------------------------------------*/
2697 /* rematStr - returns the rematerialized string for a remat var */
2698 /*-----------------------------------------------------------------*/
2700 rematStr (symbol * sym)
2703 iCode *ic = sym->rematiCode;
2705 debugLog ("%s\n", __FUNCTION__);
2710 /* if plus or minus print the right hand side */
2712 if (ic->op == '+' || ic->op == '-') {
2713 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
2716 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2720 if (ic->op == '+' || ic->op == '-')
2722 iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2723 sprintf (s, "(%s %c 0x%04x)",
2724 OP_SYMBOL (IC_LEFT (ric))->rname,
2726 (int) operandLitValue (IC_RIGHT (ic)));
2729 //ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2731 //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
2735 /* we reached the end */
2736 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
2740 printf ("%s\n", buffer);
2745 /*-----------------------------------------------------------------*/
2746 /* regTypeNum - computes the type & number of registers required */
2747 /*-----------------------------------------------------------------*/
2755 debugLog ("%s\n", __FUNCTION__);
2756 /* for each live range do */
2757 for (sym = hTabFirstItem (liveRanges, &k); sym;
2758 sym = hTabNextItem (liveRanges, &k)) {
2760 debugLog (" %d - %s\n", __LINE__, sym->rname);
2761 //fprintf(stderr," %d - %s\n", __LINE__, sym->rname);
2763 /* if used zero times then no registers needed */
2764 if ((sym->liveTo - sym->liveFrom) == 0)
2768 /* if the live range is a temporary */
2771 debugLog (" %d - itemp register\n", __LINE__);
2773 /* if the type is marked as a conditional */
2774 if (sym->regType == REG_CND)
2777 /* if used in return only then we don't
2779 if (sym->ruonly || sym->accuse) {
2780 if (IS_AGGREGATE (sym->type) || sym->isptr)
2781 sym->type = aggrToPtr (sym->type, FALSE);
2782 debugLog (" %d - no reg needed - used as a return\n", __LINE__);
2786 /* if the symbol has only one definition &
2787 that definition is a get_pointer and the
2788 pointer we are getting is rematerializable and
2791 if (bitVectnBitsOn (sym->defs) == 1 &&
2792 (ic = hTabItemWithKey (iCodehTab,
2793 bitVectFirstBit (sym->defs))) &&
2795 !IS_BITVAR (sym->etype) &&
2796 (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) {
2798 if (ptrPseudoSymSafe (sym, ic)) {
2802 debugLog (" %d - \n", __LINE__);
2804 /* create a psuedo symbol & force a spil */
2805 //X symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
2806 psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
2807 psym->type = sym->type;
2808 psym->etype = sym->etype;
2809 psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (ic)));
2810 strcpy (psym->rname, psym->name);
2812 sym->usl.spillLoc = psym;
2816 /* if in data space or idata space then try to
2817 allocate pointer register */
2821 /* if not then we require registers */
2822 sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
2823 getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
2824 getSize (sym->type));
2828 if(IS_PTR_CONST (sym->type)) {
2830 if(IS_CODEPTR (sym->type)) {
2832 // what IS this ???? (HJD)
2833 debugLog (" %d const pointer type requires %d registers, changing to 3\n",__LINE__,sym->nRegs); // patch 14
2834 sym->nRegs = 3; // patch 14
2837 if (sym->nRegs > 4) {
2838 fprintf (stderr, "allocated more than 4 or 0 registers for type ");
2839 printTypeChain (sym->type, stderr);
2840 fprintf (stderr, "\n");
2843 /* determine the type of register required */
2844 if (sym->nRegs == 1 &&
2845 IS_PTR (sym->type) &&
2847 sym->regType = REG_PTR;
2849 sym->regType = REG_GPR;
2852 debugLog (" reg name %s, reg type %s\n", sym->rname, debugLogRegType (sym->regType));
2856 /* for the first run we don't provide */
2857 /* registers for true symbols we will */
2858 /* see how things go */
2864 static DEFSETFUNC (markRegFree)
2866 ((regs *)item)->isFree = 1;
2871 DEFSETFUNC (pic16_deallocReg)
2873 fprintf(stderr,"deallocting register %s\n",((regs *)item)->name);
2874 ((regs *)item)->isFree = 1;
2875 ((regs *)item)->wasUsed = 0;
2879 /*-----------------------------------------------------------------*/
2880 /* freeAllRegs - mark all registers as free */
2881 /*-----------------------------------------------------------------*/
2883 pic16_freeAllRegs ()
2885 debugLog ("%s\n", __FUNCTION__);
2887 applyToSet(pic16_dynAllocRegs,markRegFree);
2888 applyToSet(pic16_dynStackRegs,markRegFree);
2891 /*-----------------------------------------------------------------*/
2892 /*-----------------------------------------------------------------*/
2894 pic16_deallocateAllRegs ()
2896 debugLog ("%s\n", __FUNCTION__);
2898 applyToSet(pic16_dynAllocRegs,pic16_deallocReg);
2902 /*-----------------------------------------------------------------*/
2903 /* deallocStackSpil - this will set the stack pointer back */
2904 /*-----------------------------------------------------------------*/
2906 DEFSETFUNC (deallocStackSpil)
2910 debugLog ("%s\n", __FUNCTION__);
2915 /*-----------------------------------------------------------------*/
2916 /* farSpacePackable - returns the packable icode for far variables */
2917 /*-----------------------------------------------------------------*/
2919 farSpacePackable (iCode * ic)
2923 debugLog ("%s\n", __FUNCTION__);
2924 /* go thru till we find a definition for the
2925 symbol on the right */
2926 for (dic = ic->prev; dic; dic = dic->prev)
2929 /* if the definition is a call then no */
2930 if ((dic->op == CALL || dic->op == PCALL) &&
2931 IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2936 /* if shift by unknown amount then not */
2937 if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
2938 IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2941 /* if pointer get and size > 1 */
2942 if (POINTER_GET (dic) &&
2943 getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
2946 if (POINTER_SET (dic) &&
2947 getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
2950 /* if any three is a true symbol in far space */
2951 if (IC_RESULT (dic) &&
2952 IS_TRUE_SYMOP (IC_RESULT (dic)) &&
2953 isOperandInFarSpace (IC_RESULT (dic)))
2956 if (IC_RIGHT (dic) &&
2957 IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
2958 isOperandInFarSpace (IC_RIGHT (dic)) &&
2959 !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
2962 if (IC_LEFT (dic) &&
2963 IS_TRUE_SYMOP (IC_LEFT (dic)) &&
2964 isOperandInFarSpace (IC_LEFT (dic)) &&
2965 !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
2968 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
2970 if ((dic->op == LEFT_OP ||
2971 dic->op == RIGHT_OP ||
2973 IS_OP_LITERAL (IC_RIGHT (dic)))
2984 static int packRegsForPointerGet(iCode *ic, eBBlock *ebp)
2988 debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
2989 debugLog ("ic->op = %s\n", pic16_decodeOp( ic->op ) );
2990 debugAopGet (" result:", IC_RESULT (ic));
2991 debugAopGet (" left:", IC_LEFT (ic));
2992 debugAopGet (" right:", IC_RIGHT (ic));
3001 void replaceOperandWithOperand(eBBlock *ebp, iCode *ic, operand *src, iCode *dic, operand *dst);
3003 /*-----------------------------------------------------------------*/
3004 /* packRegsForAssign - register reduction for assignment */
3005 /*-----------------------------------------------------------------*/
3007 packRegsForAssign (iCode * ic, eBBlock * ebp)
3011 debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
3012 debugLog ("ic->op = %s\n", pic16_decodeOp( ic->op ) );
3013 debugAopGet (" result:", IC_RESULT (ic));
3014 debugAopGet (" left:", IC_LEFT (ic));
3015 debugAopGet (" right:", IC_RIGHT (ic));
3017 // fprintf(stderr, "%s:%d symbol = %s\n", __FILE__, __LINE__, OP_SYMBOL( IC_RESULT(ic))->name);
3019 debugLog(" %d - actuall processing\n", __LINE__ );
3021 if (!IS_ITEMP (IC_RESULT (ic))) {
3022 pic16_allocDirReg(IC_RESULT (ic));
3023 debugLog (" %d - result is not temp\n", __LINE__);
3026 // if(IS_VALOP(IC_RIGHT(ic)))return 0;
3028 /* See BUGLOG0001 - VR */
3030 if (!IS_ITEMP (IC_RIGHT (ic)) /*&& (!IS_PARM(IC_RESULT(ic)))*/) {
3031 debugLog (" %d - not packing - right is not temp\n", __LINE__);
3032 pic16_allocDirReg(IC_RIGHT (ic));
3037 if (OP_SYMBOL (IC_RIGHT (ic))->isind ||
3038 OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
3040 debugLog (" %d - not packing - right side fails \n", __LINE__);
3044 /* if the true symbol is defined in far space or on stack
3045 then we should not since this will increase register pressure */
3046 if (isOperandInFarSpace (IC_RESULT (ic)))
3048 if ((dic = farSpacePackable (ic)))
3055 /* find the definition of iTempNN scanning backwards if we find a
3056 a use of the true symbol before we find the definition then
3058 for (dic = ic->prev; dic; dic = dic->prev)
3061 /* if there is a function call and this is
3062 a parameter & not my parameter then don't pack it */
3063 if ((dic->op == CALL || dic->op == PCALL) &&
3064 (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
3065 !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
3067 debugLog (" %d - \n", __LINE__);
3076 debugLog("%d\tSearching for iTempNN\n", __LINE__);
3078 if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
3079 IS_OP_VOLATILE (IC_RESULT (dic)))
3081 debugLog (" %d - dic is VOLATILE \n", __LINE__);
3087 if( IS_SYMOP( IC_RESULT(dic)) &&
3088 IS_BITFIELD( OP_SYMBOL(IC_RESULT(dic))->etype ) ) {
3090 debugLog (" %d - result is bitfield\n", __LINE__);
3096 if (IS_SYMOP (IC_RESULT (dic)) &&
3097 IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
3099 /* A previous result was assigned to the same register - we'll our definition */
3100 debugLog (" %d - dic result key == ic right key -- pointer set=%c\n",
3101 __LINE__, ((POINTER_SET (dic)) ? 'Y' : 'N'));
3102 if (POINTER_SET (dic))
3108 if (IS_SYMOP (IC_RIGHT (dic)) &&
3109 (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
3110 IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
3112 debugLog (" %d - dic right key == ic rightor result key\n", __LINE__);
3117 if (IS_SYMOP (IC_LEFT (dic)) &&
3118 (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
3119 IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
3121 debugLog (" %d - dic left key == ic rightor result key\n", __LINE__);
3126 if (POINTER_SET (dic) &&
3127 IC_RESULT (dic)->key == IC_RESULT (ic)->key)
3129 debugLog (" %d - dic result key == ic result key -- pointer set=Y\n",
3137 return 0; /* did not find */
3140 /* This code is taken from the hc08 port. Do not know
3141 * if it fits for pic16, but I leave it here just in case */
3143 /* if assignment then check that right is not a bit */
3144 if (ASSIGNMENT (dic) && !POINTER_SET (dic)) {
3145 sym_link *etype = operandType (IC_RIGHT (dic));
3147 if (IS_BITFIELD (etype)) {
3148 /* if result is a bit too then it's ok */
3149 etype = operandType (IC_RESULT (dic));
3150 if (!IS_BITFIELD (etype)) {
3151 debugLog(" %d bitfields\n");
3158 /* if the result is on stack or iaccess then it must be
3159 the same atleast one of the operands */
3160 if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
3161 OP_SYMBOL (IC_RESULT (ic))->iaccess)
3163 /* the operation has only one symbol
3164 operator then we can pack */
3165 if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
3166 (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
3169 if (!((IC_LEFT (dic) &&
3170 IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
3172 IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
3176 debugLog (" packing. removing %s\n", OP_SYMBOL (IC_RIGHT (ic))->rname);
3177 debugLog (" replacing with %s\n", OP_SYMBOL (IC_RESULT (dic))->rname);
3178 /* found the definition */
3179 /* replace the result with the result of */
3180 /* this assignment and remove this assignment */
3183 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3184 IC_RESULT (dic) = IC_RESULT (ic);
3186 if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
3188 OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
3190 /* delete from liverange table also
3191 delete from all the points inbetween and the new
3193 for (sic = dic; sic != ic; sic = sic->next)
3195 bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
3196 if (IS_ITEMP (IC_RESULT (dic)))
3197 bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
3200 remiCodeFromeBBlock (ebp, ic);
3201 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
3203 debugLog(" %d\n", __LINE__ );
3204 hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
3205 OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
3211 #define NO_packRegsForAccUse
3212 #define NO_packRegsForSupport
3213 #define NO_packRegsForOneuse
3214 #define NO_cast_peep
3219 #ifndef NO_packRegsForSupport
3220 /*-----------------------------------------------------------------*/
3221 /* findAssignToSym : scanning backwards looks for first assig found */
3222 /*-----------------------------------------------------------------*/
3224 findAssignToSym (operand * op, iCode * ic)
3228 debugLog ("%s\n", __FUNCTION__);
3229 for (dic = ic->prev; dic; dic = dic->prev)
3232 /* if definition by assignment */
3233 if (dic->op == '=' &&
3234 !POINTER_SET (dic) &&
3235 IC_RESULT (dic)->key == op->key
3236 /* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */
3240 /* we are interested only if defined in far space */
3241 /* or in stack space in case of + & - */
3243 /* if assigned to a non-symbol then return
3245 if (!IS_SYMOP (IC_RIGHT (dic)))
3248 /* if the symbol is in far space then
3250 if (isOperandInFarSpace (IC_RIGHT (dic)))
3253 /* for + & - operations make sure that
3254 if it is on the stack it is the same
3255 as one of the three operands */
3256 if ((ic->op == '+' || ic->op == '-') &&
3257 OP_SYMBOL (IC_RIGHT (dic))->onStack)
3259 if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
3260 IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
3261 IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
3269 /* if we find an usage then we cannot delete it */
3270 if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
3273 if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
3276 if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
3280 /* now make sure that the right side of dic
3281 is not defined between ic & dic */
3284 iCode *sic = dic->next;
3286 for (; sic != ic; sic = sic->next)
3287 if (IC_RESULT (sic) &&
3288 IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
3299 #ifndef NO_packRegsForSupport
3300 /*-----------------------------------------------------------------*/
3301 /* packRegsForSupport :- reduce some registers for support calls */
3302 /*-----------------------------------------------------------------*/
3304 packRegsForSupport (iCode * ic, eBBlock * ebp)
3308 debugLog ("%s\n", __FUNCTION__);
3309 /* for the left & right operand :- look to see if the
3310 left was assigned a true symbol in far space in that
3311 case replace them */
3312 if (IS_ITEMP (IC_LEFT (ic)) &&
3313 OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
3315 iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
3321 debugAopGet ("removing left:", IC_LEFT (ic));
3323 /* found it we need to remove it from the
3325 for (sic = dic; sic != ic; sic = sic->next)
3326 bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
3328 IC_LEFT (ic)->operand.symOperand =
3329 IC_RIGHT (dic)->operand.symOperand;
3330 IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3331 remiCodeFromeBBlock (ebp, dic);
3332 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3333 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3337 /* do the same for the right operand */
3340 IS_ITEMP (IC_RIGHT (ic)) &&
3341 OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
3343 iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
3349 /* if this is a subtraction & the result
3350 is a true symbol in far space then don't pack */
3351 if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
3353 sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
3354 if (IN_FARSPACE (SPEC_OCLS (etype)))
3358 debugAopGet ("removing right:", IC_RIGHT (ic));
3360 /* found it we need to remove it from the
3362 for (sic = dic; sic != ic; sic = sic->next)
3363 bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
3365 IC_RIGHT (ic)->operand.symOperand =
3366 IC_RIGHT (dic)->operand.symOperand;
3367 IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3369 remiCodeFromeBBlock (ebp, dic);
3370 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3371 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3380 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
3382 #ifndef NO_packRegsForOneuse
3383 /*-----------------------------------------------------------------*/
3384 /* packRegsForOneuse : - will reduce some registers for single Use */
3385 /*-----------------------------------------------------------------*/
3387 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
3392 debugLog ("%s\n", __FUNCTION__);
3393 /* if returning a literal then do nothing */
3397 if(OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly)
3400 /* only upto 2 bytes since we cannot predict
3401 the usage of b, & acc */
3402 if (getSize (operandType (op)) > (pic16_fReturnSizePic - 1)
3410 /* this routine will mark the a symbol as used in one
3411 instruction use only && if the definition is local
3412 (ie. within the basic block) && has only one definition &&
3413 that definition is either a return value from a
3414 function or does not contain any variables in
3418 uses = bitVectCopy (OP_USES (op));
3419 bitVectUnSetBit (uses, ic->key); /* take away this iCode */
3420 if (!bitVectIsZero (uses)) /* has other uses */
3425 if (bitVectnBitsOn (OP_USES (op)) > 1)
3429 /* if it has only one defintion */
3430 if (bitVectnBitsOn (OP_DEFS (op)) > 1)
3431 return NULL; /* has more than one definition */
3433 /* get that definition */
3435 hTabItemWithKey (iCodehTab,
3436 bitVectFirstBit (OP_DEFS (op)))))
3439 /* found the definition now check if it is local */
3440 if (dic->seq < ebp->fSeq ||
3441 dic->seq > ebp->lSeq)
3442 return NULL; /* non-local */
3444 /* now check if it is the return from
3446 if (dic->op == CALL || dic->op == PCALL)
3448 if (ic->op != SEND && ic->op != RETURN &&
3449 !POINTER_SET(ic) && !POINTER_GET(ic))
3451 OP_SYMBOL (op)->ruonly = 1;
3460 /* otherwise check that the definition does
3461 not contain any symbols in far space */
3462 if (isOperandInFarSpace (IC_LEFT (dic)) ||
3463 isOperandInFarSpace (IC_RIGHT (dic)) ||
3464 IS_OP_RUONLY (IC_LEFT (ic)) ||
3465 IS_OP_RUONLY (IC_RIGHT (ic)))
3470 /* if pointer set then make sure the pointer
3472 if (POINTER_SET (dic) &&
3473 !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3476 if (POINTER_GET (dic) &&
3477 !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3483 /* also make sure the intervenening instructions
3484 don't have any thing in far space */
3485 for (dic = dic->next; dic && dic != ic; dic = dic->next)
3488 /* if there is an intervening function call then no */
3489 if (dic->op == CALL || dic->op == PCALL)
3491 /* if pointer set then make sure the pointer
3493 if (POINTER_SET (dic) &&
3494 !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3497 if (POINTER_GET (dic) &&
3498 !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3501 /* if address of & the result is remat then okay */
3502 if (dic->op == ADDRESS_OF &&
3503 OP_SYMBOL (IC_RESULT (dic))->remat)
3506 /* if operand has size of three or more & this
3507 operation is a '*','/' or '%' then 'b' may
3509 if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
3510 getSize (operandType (op)) >= 2)
3513 /* if left or right or result is in far space */
3514 if (isOperandInFarSpace (IC_LEFT (dic)) ||
3515 isOperandInFarSpace (IC_RIGHT (dic)) ||
3516 isOperandInFarSpace (IC_RESULT (dic)) ||
3517 IS_OP_RUONLY (IC_LEFT (dic)) ||
3518 IS_OP_RUONLY (IC_RIGHT (dic)) ||
3519 IS_OP_RUONLY (IC_RESULT (dic)))
3525 OP_SYMBOL (op)->ruonly = 1;
3532 /*-----------------------------------------------------------------*/
3533 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN */
3534 /*-----------------------------------------------------------------*/
3536 isBitwiseOptimizable (iCode * ic)
3538 sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
3539 sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
3541 debugLog ("%s\n", __FUNCTION__);
3542 /* bitwise operations are considered optimizable
3543 under the following conditions (Jean-Louis VERN)
3555 if (IS_LITERAL (rtype) ||
3556 (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
3563 #ifndef NO_packRegsForAccUse
3565 /*-----------------------------------------------------------------*/
3566 /* packRegsForAccUse - pack registers for acc use */
3567 /*-----------------------------------------------------------------*/
3569 packRegsForAccUse (iCode * ic)
3573 debugLog ("%s\n", __FUNCTION__);
3575 /* if this is an aggregate, e.g. a one byte char array */
3576 if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
3579 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3581 /* if + or - then it has to be one byte result */
3582 if ((ic->op == '+' || ic->op == '-')
3583 && getSize (operandType (IC_RESULT (ic))) > 1)
3586 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3587 /* if shift operation make sure right side is not a literal */
3588 if (ic->op == RIGHT_OP &&
3589 (isOperandLiteral (IC_RIGHT (ic)) ||
3590 getSize (operandType (IC_RESULT (ic))) > 1))
3593 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3594 if (ic->op == LEFT_OP &&
3595 (isOperandLiteral (IC_RIGHT (ic)) ||
3596 getSize (operandType (IC_RESULT (ic))) > 1))
3599 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3600 if (IS_BITWISE_OP (ic) &&
3601 getSize (operandType (IC_RESULT (ic))) > 1)
3605 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3606 /* has only one definition */
3607 if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
3610 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3611 /* has only one use */
3612 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
3615 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3616 /* and the usage immediately follows this iCode */
3617 if (!(uic = hTabItemWithKey (iCodehTab,
3618 bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
3621 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3622 if (ic->next != uic)
3625 /* if it is a conditional branch then we definitely can */
3629 if (uic->op == JUMPTABLE)
3632 /* if the usage is not is an assignment
3633 or an arithmetic / bitwise / shift operation then not */
3634 if (POINTER_SET (uic) &&
3635 getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
3638 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3639 if (uic->op != '=' &&
3640 !IS_ARITHMETIC_OP (uic) &&
3641 !IS_BITWISE_OP (uic) &&
3642 uic->op != LEFT_OP &&
3643 uic->op != RIGHT_OP)
3646 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3647 /* if used in ^ operation then make sure right is not a
3649 if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
3652 /* if shift operation make sure right side is not a literal */
3653 if (uic->op == RIGHT_OP &&
3654 (isOperandLiteral (IC_RIGHT (uic)) ||
3655 getSize (operandType (IC_RESULT (uic))) > 1))
3658 if (uic->op == LEFT_OP &&
3659 (isOperandLiteral (IC_RIGHT (uic)) ||
3660 getSize (operandType (IC_RESULT (uic))) > 1))
3663 /* make sure that the result of this icode is not on the
3664 stack, since acc is used to compute stack offset */
3665 if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
3666 OP_SYMBOL (IC_RESULT (uic))->onStack)
3669 /* if either one of them in far space then we cannot */
3670 if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3671 isOperandInFarSpace (IC_LEFT (uic))) ||
3672 (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3673 isOperandInFarSpace (IC_RIGHT (uic))))
3676 /* if the usage has only one operand then we can */
3677 if (IC_LEFT (uic) == NULL ||
3678 IC_RIGHT (uic) == NULL)
3681 /* make sure this is on the left side if not
3682 a '+' since '+' is commutative */
3683 if (ic->op != '+' &&
3684 IC_LEFT (uic)->key != IC_RESULT (ic)->key)
3688 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3689 /* if one of them is a literal then we can */
3690 if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
3691 (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic)))) &&
3692 (getSize (operandType (IC_RESULT (uic))) <= 1))
3694 OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3699 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3700 /* if the other one is not on stack then we can */
3701 if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
3702 (IS_ITEMP (IC_RIGHT (uic)) ||
3703 (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3704 !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
3707 if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
3708 (IS_ITEMP (IC_LEFT (uic)) ||
3709 (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3710 !OP_SYMBOL (IC_LEFT (uic))->onStack)))
3716 debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
3717 OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3724 /*-----------------------------------------------------------------*/
3725 /* packForPush - hueristics to reduce iCode for pushing */
3726 /*-----------------------------------------------------------------*/
3728 packForReceive (iCode * ic, eBBlock * ebp)
3732 debugLog ("%s\n", __FUNCTION__);
3733 debugAopGet (" result:", IC_RESULT (ic));
3734 debugAopGet (" left:", IC_LEFT (ic));
3735 debugAopGet (" right:", IC_RIGHT (ic));
3740 for (dic = ic->next; dic; dic = dic->next)
3742 if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
3743 debugLog (" used on left\n");
3744 if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
3745 debugLog (" used on right\n");
3746 if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
3747 debugLog (" used on result\n");
3749 if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
3750 (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
3754 debugLog (" hey we can remove this unnecessary assign\n");
3756 /*-----------------------------------------------------------------*/
3757 /* packForPush - hueristics to reduce iCode for pushing */
3758 /*-----------------------------------------------------------------*/
3760 packForPush (iCode * ic, eBBlock * ebp)
3764 debugLog ("%s\n", __FUNCTION__);
3765 if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
3772 n1 = bitVectnBitsOn( OP_DEFS(IC_LEFT(ic)));
3773 n2 = bitVectnBitsOn( OP_USES(IC_LEFT(ic)));
3774 debugf3("defs: %d\tuses: %d\t%s\n", n1, n2, printILine(ic));
3775 debugf2("IC_LEFT(ic): from %d to %d\n", OP_LIVEFROM(IC_LEFT(ic)), OP_LIVETO(IC_LEFT(ic)));
3779 /* must have only definition & one usage */
3780 if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
3781 bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
3784 /* find the definition */
3785 if (!(dic = hTabItemWithKey (iCodehTab,
3786 bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
3789 /* if definition is not assignment,
3790 * or is not pointer (because pointer might have changed) */
3791 if (dic->op != '=' || POINTER_SET (dic))
3794 /* we must ensure that we can use the delete the assignment,
3795 * because the source might have been modified in between.
3796 * Until I know how to fix this, I'll use the adhoc fix
3797 * to check the liveranges */
3798 if((OP_LIVEFROM(IC_RIGHT(dic))==0) || (OP_LIVETO(IC_RIGHT(dic))==0))
3800 // debugf2("IC_RIGHT(dic): from %d to %d\n", OP_LIVEFROM(IC_RIGHT(dic)), OP_LIVETO(IC_RIGHT(dic)));
3804 /* we now we know that it has one & only one def & use
3805 and the that the definition is an assignment */
3806 IC_LEFT (ic) = IC_RIGHT (dic);
3808 debugf("remiCodeFromeBBlock: %s\n", printILine(dic));
3810 remiCodeFromeBBlock (ebp, dic);
3811 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3812 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3815 static void printSymType(char * str, sym_link *sl)
3817 if(!pic16_ralloc_debug)return;
3819 debugLog (" %s Symbol type: ",str);
3820 printTypeChain( sl, debugF);
3824 /*-----------------------------------------------------------------*/
3825 /* some debug code to print the symbol S_TYPE. Note that
3826 * the function checkSClass in src/SDCCsymt.c dinks with
3827 * the S_TYPE in ways the PIC port doesn't fully like...*/
3828 /*-----------------------------------------------------------------*/
3829 static void isData(sym_link *sl)
3833 if(!pic16_ralloc_debug)return;
3840 for ( ; sl; sl=sl->next) {
3842 switch (SPEC_SCLS(sl)) {
3843 case S_DATA: fprintf (of, "data "); break;
3844 case S_XDATA: fprintf (of, "xdata "); break;
3845 case S_SFR: fprintf (of, "sfr "); break;
3846 case S_SBIT: fprintf (of, "sbit "); break;
3847 case S_CODE: fprintf (of, "code "); break;
3848 case S_IDATA: fprintf (of, "idata "); break;
3849 case S_PDATA: fprintf (of, "pdata "); break;
3850 case S_LITERAL: fprintf (of, "literal "); break;
3851 case S_STACK: fprintf (of, "stack "); break;
3852 case S_XSTACK: fprintf (of, "xstack "); break;
3853 case S_BIT: fprintf (of, "bit "); break;
3854 case S_EEPROM: fprintf (of, "eeprom "); break;
3862 /*--------------------------------------------------------------------*/
3863 /* pic16_packRegisters - does some transformations to reduce */
3864 /* register pressure */
3866 /*--------------------------------------------------------------------*/
3868 pic16_packRegisters (eBBlock * ebp)
3873 debugLog ("%s\n", __FUNCTION__);
3879 /* look for assignments of the form */
3880 /* iTempNN = TRueSym (someoperation) SomeOperand */
3882 /* TrueSym := iTempNN:1 */
3883 for (ic = ebp->sch; ic; ic = ic->next)
3885 // debugLog("%d\n", __LINE__);
3886 /* find assignment of the form TrueSym := iTempNN:1 */
3887 if ( (ic->op == '=') && !POINTER_SET (ic) ) // patch 11
3888 change += packRegsForAssign (ic, ebp);
3892 if (POINTER_SET (ic))
3893 debugLog ("pointer is set\n");
3894 debugAopGet (" result:", IC_RESULT (ic));
3895 debugAopGet (" left:", IC_LEFT (ic));
3896 debugAopGet (" right:", IC_RIGHT (ic));
3905 for (ic = ebp->sch; ic; ic = ic->next) {
3907 if(IS_SYMOP ( IC_LEFT(ic))) {
3908 sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
3910 debugAopGet ("x left:", IC_LEFT (ic));
3912 if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
3914 if(IS_CODEPTR(OP_SYMBOL(IC_LEFT(ic))->type))
3916 debugLog (" is a pointer\n");
3918 if(IS_PTR(OP_SYMBOL(IC_LEFT(ic))->type))
3919 debugLog (" is a ptr\n");
3921 if(IS_OP_VOLATILE(IC_LEFT(ic)))
3922 debugLog (" is volatile\n");
3926 if(IS_OP_VOLATILE(IC_LEFT(ic))) {
3927 debugLog (" %d - left is not temp, allocating\n", __LINE__);
3928 pic16_allocDirReg(IC_LEFT (ic));
3931 printSymType("c ", OP_SYMBOL(IC_LEFT(ic))->type);
3934 if(IS_SYMOP ( IC_RIGHT(ic))) {
3935 debugAopGet (" right:", IC_RIGHT (ic));
3936 printSymType(" ", OP_SYMBOL(IC_RIGHT(ic))->type);
3939 if(IS_SYMOP ( IC_RESULT(ic))) {
3940 debugAopGet (" result:", IC_RESULT (ic));
3941 printSymType(" ", OP_SYMBOL(IC_RESULT(ic))->type);
3944 if(IS_TRUE_SYMOP ( IC_RIGHT(ic))) {
3945 debugAopGet (" right:", IC_RIGHT (ic));
3946 printSymType(" ", OP_SYMBOL(IC_RIGHT(ic))->type);
3947 // pic16_allocDirReg(IC_RIGHT(ic));
3950 if(IS_TRUE_SYMOP ( IC_RESULT(ic))) {
3951 debugAopGet (" result:", IC_RESULT (ic));
3952 printSymType(" ", OP_SYMBOL(IC_RESULT(ic))->type);
3953 // pic16_allocDirReg(IC_RESULT(ic));
3957 if (POINTER_SET (ic))
3958 debugLog (" %d - Pointer set\n", __LINE__);
3960 /* Look for two subsequent iCodes with */
3962 /* _c = iTemp & op; */
3963 /* and replace them by */
3966 if ((ic->op == BITWISEAND || ic->op == '|' || ic->op == '^')
3968 && ic->prev->op == '='
3969 && IS_ITEMP (IC_LEFT (ic))
3970 && IC_LEFT (ic) == IC_RESULT (ic->prev)
3971 && isOperandEqual (IC_RESULT(ic), IC_RIGHT(ic->prev)))
3973 iCode* ic_prev = ic->prev;
3974 symbol* prev_result_sym = OP_SYMBOL (IC_RESULT (ic_prev));
3976 ReplaceOpWithCheaperOp (&IC_LEFT (ic), IC_RESULT (ic));
3977 if (IC_RESULT (ic_prev) != IC_RIGHT (ic)) {
3978 bitVectUnSetBit (OP_USES (IC_RESULT (ic_prev)), ic->key);
3979 if (/*IS_ITEMP (IC_RESULT (ic_prev)) && */
3980 prev_result_sym->liveTo == ic->seq)
3982 prev_result_sym->liveTo = ic_prev->seq;
3985 bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
3987 bitVectSetBit (ic->rlive, IC_RESULT (ic)->key);
3989 if (bitVectIsZero (OP_USES (IC_RESULT (ic_prev)))) {
3990 bitVectUnSetBit (ic->rlive, IC_RESULT (ic)->key);
3991 bitVectUnSetBit (OP_DEFS (IC_RESULT (ic_prev)), ic_prev->key);
3992 remiCodeFromeBBlock (ebp, ic_prev);
3993 hTabDeleteItem (&iCodehTab, ic_prev->key, ic_prev, DELETE_ITEM, NULL);
3997 /* if this is an itemp & result of a address of a true sym
3998 then mark this as rematerialisable */
3999 if (ic->op == ADDRESS_OF &&
4000 IS_ITEMP (IC_RESULT (ic)) &&
4001 IS_TRUE_SYMOP (IC_LEFT (ic)) &&
4002 bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
4003 !OP_SYMBOL (IC_LEFT (ic))->onStack)
4006 debugLog (" %d - %s. result is rematerializable\n", __LINE__,__FUNCTION__);
4008 OP_SYMBOL (IC_RESULT (ic))->remat = 1;
4009 OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
4010 OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
4014 /* if straight assignment then carry remat flag if
4015 this is the only definition */
4016 if (ic->op == '=' &&
4017 !POINTER_SET (ic) &&
4018 IS_SYMOP (IC_RIGHT (ic)) &&
4019 OP_SYMBOL (IC_RIGHT (ic))->remat &&
4020 bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
4022 debugLog (" %d - %s. straight rematerializable\n", __LINE__,__FUNCTION__);
4024 OP_SYMBOL (IC_RESULT (ic))->remat =
4025 OP_SYMBOL (IC_RIGHT (ic))->remat;
4026 OP_SYMBOL (IC_RESULT (ic))->rematiCode =
4027 OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
4030 /* if this is a +/- operation with a rematerizable
4031 then mark this as rematerializable as well */
4032 if ((ic->op == '+' || ic->op == '-') &&
4033 (IS_SYMOP (IC_LEFT (ic)) &&
4034 IS_ITEMP (IC_RESULT (ic)) &&
4035 OP_SYMBOL (IC_LEFT (ic))->remat &&
4036 bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
4037 IS_OP_LITERAL (IC_RIGHT (ic))))
4039 debugLog (" %d - %s. rematerializable because op is +/-\n", __LINE__,__FUNCTION__);
4041 operandLitValue (IC_RIGHT (ic));
4042 OP_SYMBOL (IC_RESULT (ic))->remat = 1;
4043 OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
4044 OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
4049 /* if this is an arithmetic operation
4050 * && result or left is not rematerializable (so it is a plain arithmetic op)
4051 * && and left is not used after this iCode */
4053 if(getenv("OPTIMIZE_NEAR_POINTER_GET"))
4055 if (IS_ARITHMETIC_OP(ic)
4056 && !IS_OP_LITERAL (IC_LEFT (ic))
4057 && !OP_SYMBOL (IC_RESULT(ic))->rematiCode
4058 && !OP_SYMBOL (IC_LEFT(ic))->rematiCode
4059 && (OP_LIVETO (IC_LEFT(ic) ) <= ic->seq)
4061 iCode *dic = ic->prev;
4063 /* search backwards to find assignment from a remat pointer */
4064 while(dic && dic->seq >= OP_LIVEFROM( IC_LEFT(ic) )) {
4066 /* is it a pointer_get? */
4068 && IS_DATA_PTR(OP_SYM_TYPE (IC_LEFT (dic)))) {
4069 fprintf(stderr, "%s:%d `%s' is a data pointer (ic seq: %d)\n", __FILE__, __LINE__,
4070 OP_SYMBOL(IC_LEFT(dic))->rname, dic->seq);
4072 /* so we can replace ic->left with dic->left, & remove assignment */
4073 ReplaceOpWithCheaperOp( &IC_LEFT(ic), IC_LEFT(dic) );
4075 bitVectUnSetBit(OP_USES( IC_LEFT(ic) ), ic->key);
4076 bitVectUnSetBit(OP_DEFS( IC_RESULT(dic) ), dic->key );
4078 // dic->op = DUMMY_READ_VOLATILE;
4080 remiCodeFromeBBlock(ebp, dic);
4081 hTabDeleteItem(&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
4090 /* mark the pointer usages */
4091 if (POINTER_SET (ic))
4093 OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
4094 debugLog (" marking as a pointer (set) =>");
4095 debugAopGet (" result:", IC_RESULT (ic));
4099 if (POINTER_GET (ic))
4101 if(IS_SYMOP(IC_LEFT(ic))) {
4102 OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
4103 debugLog (" marking as a pointer (get) =>");
4104 debugAopGet (" left:", IC_LEFT (ic));
4107 if(getenv("OPTIMIZE_BITFIELD_POINTER_GET")) {
4108 if(IS_ITEMP(IC_LEFT(ic)) && IS_BITFIELD(OP_SYM_ETYPE(IC_LEFT(ic)))) {
4109 iCode *dic = ic->prev;
4111 fprintf(stderr, "%s:%d might give opt POINTER_GET && IS_BITFIELD(IC_LEFT)\n", __FILE__, __LINE__);
4113 if(dic && dic->op == '='
4114 && isOperandEqual(IC_RESULT(dic), IC_LEFT(ic))) {
4116 fprintf(stderr, "%s:%d && prev is '=' && prev->result == ic->left\n", __FILE__, __LINE__);
4119 /* replace prev->left with ic->left */
4120 IC_LEFT(ic) = IC_RIGHT(dic);
4121 IC_RIGHT(ic->prev) = NULL;
4123 /* remove ic->prev iCode (assignment) */
4124 remiCodeFromeBBlock (ebp, dic);
4125 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,ic->key);
4128 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
4134 //debugLog(" %d %s\n", __LINE__, __FUNCTION__);
4138 //debugLog(" %d %s\n", __LINE__, __FUNCTION__ );
4139 /* if we are using a symbol on the stack
4140 then we should say pic16_ptrRegReq */
4141 if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
4142 pic16_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
4143 OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
4144 else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
4145 pic16_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
4146 OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
4150 //debugLog(" %d %s\n", __LINE__, __FUNCTION__ );
4151 if (IS_SYMOP (IC_LEFT (ic)))
4152 pic16_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
4153 OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
4154 if (IS_SYMOP (IC_RIGHT (ic)))
4155 pic16_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
4156 OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
4157 if (IS_SYMOP (IC_RESULT (ic)))
4158 pic16_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
4159 OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
4162 debugLog (" %d - pointer reg req = %d\n", __LINE__,pic16_ptrRegReq);
4166 /* if the condition of an if instruction
4167 is defined in the previous instruction then
4168 mark the itemp as a conditional */
4169 if ((IS_CONDITIONAL (ic) ||
4170 ((ic->op == BITWISEAND ||
4173 isBitwiseOptimizable (ic))) &&
4174 ic->next && ic->next->op == IFX &&
4175 isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
4176 OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
4179 debugLog (" %d\n", __LINE__);
4180 OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
4184 debugLog(" %d\n", __LINE__);
4186 #ifndef NO_packRegsForSupport
4187 /* reduce for support function calls */
4188 if (ic->supportRtn || ic->op == '+' || ic->op == '-')
4189 packRegsForSupport (ic, ebp);
4192 /* if a parameter is passed, it's in W, so we may not
4193 need to place a copy in a register */
4194 if (ic->op == RECEIVE)
4195 packForReceive (ic, ebp);
4197 #ifndef NO_packRegsForOneuse
4198 /* some cases the redundant moves can
4199 can be eliminated for return statements */
4200 if ((ic->op == RETURN || ic->op == SEND) &&
4201 !isOperandInFarSpace (IC_LEFT (ic)) &&
4203 packRegsForOneuse (ic, IC_LEFT (ic), ebp);
4206 #ifndef NO_packRegsForOneuse
4207 /* if pointer set & left has a size more than
4208 one and right is not in far space */
4209 if (POINTER_SET (ic) &&
4210 !isOperandInFarSpace (IC_RIGHT (ic)) &&
4211 !OP_SYMBOL (IC_RESULT (ic))->remat &&
4212 !IS_OP_RUONLY (IC_RIGHT (ic)) &&
4213 getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
4215 packRegsForOneuse (ic, IC_RESULT (ic), ebp);
4218 #ifndef NO_packRegsForOneuse
4219 /* if pointer get */
4220 if (POINTER_GET (ic) &&
4221 !isOperandInFarSpace (IC_RESULT (ic)) &&
4222 !OP_SYMBOL (IC_LEFT (ic))->remat &&
4223 !IS_OP_RUONLY (IC_RESULT (ic)) &&
4224 getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
4226 packRegsForOneuse (ic, IC_LEFT (ic), ebp);
4227 debugLog("%d - return from packRegsForOneuse\n", __LINE__);
4230 #ifndef NO_cast_peep
4231 /* if this is cast for intergral promotion then
4232 check if only use of the definition of the
4233 operand being casted/ if yes then replace
4234 the result of that arithmetic operation with
4235 this result and get rid of the cast */
4236 if (ic->op == CAST) {
4238 sym_link *fromType = operandType (IC_RIGHT (ic));
4239 sym_link *toType = operandType (IC_LEFT (ic));
4241 debugLog (" %d - casting\n", __LINE__);
4243 if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
4244 getSize (fromType) != getSize (toType)) {
4247 iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
4250 if (IS_ARITHMETIC_OP (dic)) {
4251 debugLog(" %d %s\n", __LINE__, __FUNCTION__ );
4253 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
4254 IC_RESULT (dic) = IC_RESULT (ic);
4255 remiCodeFromeBBlock (ebp, ic);
4256 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
4257 hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
4258 OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
4262 OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
4266 /* if the type from and type to are the same
4267 then if this is the only use then packit */
4268 if (compareType (operandType (IC_RIGHT (ic)),
4269 operandType (IC_LEFT (ic))) == 1) {
4271 iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
4274 debugLog(" %d\n", __LINE__);
4276 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
4277 IC_RESULT (dic) = IC_RESULT (ic);
4278 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
4279 remiCodeFromeBBlock (ebp, ic);
4280 hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
4281 OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
4290 /* there are some problems with packing variables
4291 * it seems that the live range estimator doesn't
4292 * estimate correctly the liveranges of some symbols */
4295 iTempNN := (some variable in farspace) V1
4300 if (ic->op == IPUSH)
4302 packForPush (ic, ebp);
4306 #ifndef NO_packRegsForAccUse
4307 /* pack registers for accumulator use, when the
4308 result of an arithmetic or bit wise operation
4309 has only one use, that use is immediately following
4310 the defintion and the using iCode has only one
4311 operand or has two operands but one is literal &
4312 the result of that operation is not on stack then
4313 we can leave the result of this operation in acc:b
4315 if ((IS_ARITHMETIC_OP (ic)
4317 || IS_BITWISE_OP (ic)
4319 || ic->op == LEFT_OP || ic->op == RIGHT_OP
4322 IS_ITEMP (IC_RESULT (ic)) &&
4323 getSize (operandType (IC_RESULT (ic))) <= 1)
4325 packRegsForAccUse (ic);
4332 dumpEbbsToDebug (eBBlock ** ebbs, int count)
4336 if (!pic16_ralloc_debug || !debugF)
4339 for (i = 0; i < count; i++)
4341 fprintf (debugF, "\n----------------------------------------------------------------\n");
4342 fprintf (debugF, "Basic Block %s : loop Depth = %d noPath = %d , lastinLoop = %d\n",
4343 ebbs[i]->entryLabel->name,
4346 ebbs[i]->isLastInLoop);
4347 fprintf (debugF, "depth 1st num %d : bbnum = %d 1st iCode = %d , last iCode = %d\n",
4352 fprintf (debugF, "visited %d : hasFcall = %d\n",
4356 fprintf (debugF, "\ndefines bitVector :");
4357 bitVectDebugOn (ebbs[i]->defSet, debugF);
4358 fprintf (debugF, "\nlocal defines bitVector :");
4359 bitVectDebugOn (ebbs[i]->ldefs, debugF);
4360 fprintf (debugF, "\npointers Set bitvector :");
4361 bitVectDebugOn (ebbs[i]->ptrsSet, debugF);
4362 fprintf (debugF, "\nin pointers Set bitvector :");
4363 bitVectDebugOn (ebbs[i]->inPtrsSet, debugF);
4364 fprintf (debugF, "\ninDefs Set bitvector :");
4365 bitVectDebugOn (ebbs[i]->inDefs, debugF);
4366 fprintf (debugF, "\noutDefs Set bitvector :");
4367 bitVectDebugOn (ebbs[i]->outDefs, debugF);
4368 fprintf (debugF, "\nusesDefs Set bitvector :");
4369 bitVectDebugOn (ebbs[i]->usesDefs, debugF);
4370 fprintf (debugF, "\n----------------------------------------------------------------\n");
4371 printiCChain (ebbs[i]->sch, debugF);
4374 /*-----------------------------------------------------------------*/
4375 /* pic16_assignRegisters - assigns registers to each live range as need */
4376 /*-----------------------------------------------------------------*/
4378 pic16_assignRegisters (ebbIndex * ebbi)
4380 eBBlock ** ebbs = ebbi->bbOrder;
4381 int count = ebbi->count;
4385 debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s", __FILE__, __FUNCTION__);
4386 debugLog ("\nebbs before optimizing:\n");
4387 dumpEbbsToDebug (ebbs, count);
4389 _inRegAllocator = 1;
4391 setToNull ((void *) &_G.funcrUsed);
4392 pic16_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
4395 /* change assignments this will remove some
4396 live ranges reducing some register pressure */
4397 for (i = 0; i < count; i++)
4398 pic16_packRegisters (ebbs[i]);
4405 debugLog("dir registers allocated so far:\n");
4406 reg = hTabFirstItem(dynDirectRegNames, &hkey);
4409 debugLog(" -- #%d reg = %s key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4410 // fprintf(stderr, " -- #%d reg = %s key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4411 reg = hTabNextItem(dynDirectRegNames, &hkey);
4416 /* liveranges probably changed by register packing
4417 so we compute them again */
4418 recomputeLiveRanges (ebbs, count);
4420 if (options.dump_pack)
4421 dumpEbbsToFileExt (DUMP_PACK, ebbi);
4423 /* first determine for each live range the number of
4424 registers & the type of registers required for each */
4427 /* start counting function temporary registers from zero */
4430 /* and serially allocate registers */
4431 serialRegAssign (ebbs, count);
4434 debugLog ("ebbs after serialRegAssign:\n");
4435 dumpEbbsToDebug (ebbs, count);
4438 //pic16_freeAllRegs();
4440 /* if stack was extended then tell the user */
4443 /* werror(W_TOOMANY_SPILS,"stack", */
4444 /* _G.stackExtend,currFunc->name,""); */
4450 /* werror(W_TOOMANY_SPILS,"data space", */
4451 /* _G.dataExtend,currFunc->name,""); */
4455 /* after that create the register mask
4456 for each of the instruction */
4457 createRegMask (ebbs, count);
4459 /* redo that offsets for stacked automatic variables */
4460 redoStackOffsets ();
4462 if (options.dump_rassgn)
4463 dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
4465 /* now get back the chain */
4466 ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
4468 debugLog ("ebbs after optimizing:\n");
4469 dumpEbbsToDebug (ebbs, count);
4471 _inRegAllocator = 0;
4475 /* free up any _G.stackSpil locations allocated */
4476 applyToSet (_G.stackSpil, deallocStackSpil);
4478 setToNull ((void *) &_G.stackSpil);
4479 setToNull ((void *) &_G.spiltSet);
4480 /* mark all registers as free */
4481 pic16_freeAllRegs ();
4484 debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");