From f58b068ff2c3cfa28e025cdbd4833b5ac650da44 Mon Sep 17 00:00:00 2001 From: bernhardheld Date: Tue, 20 Jan 2004 21:08:53 +0000 Subject: [PATCH] * src/pic/device.c, * src/pic/gen.c, * src/pic/gen.h, * src/pic/glue.c, * src/pic/main.c, * src/pic/pcode.c, * src/pic/pcode.h, * src/pic/pcodepeep.c, * src/pic/pcoderegs.c, * src/pic/ralloc.c, * src/pic/ralloc.h: applied patch from Slade Rich; added support for multiple code pages and multiple RAM banks on the PIC 14 port. The ASM files now no longer simply assume all the code / RAM are in the same page / bank. This means the linker can safely allocate code/RAM of separate ASM files to different pages/banks. * doc/sdccman.lyx: added Slade's tips git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3146 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- src/pic/device.c | 4 - src/pic/gen.c | 212 ++----- src/pic/gen.h | 2 +- src/pic/glue.c | 54 +- src/pic/main.c | 8 +- src/pic/pcode.c | 1458 +++++++++++++++++++++++++++---------------- src/pic/pcode.h | 50 +- src/pic/pcodepeep.c | 358 +++-------- src/pic/pcoderegs.c | 265 ++++---- src/pic/ralloc.c | 224 ++++++- src/pic/ralloc.h | 4 + 11 files changed, 1524 insertions(+), 1115 deletions(-) diff --git a/src/pic/device.c b/src/pic/device.c index ab3e15a1..ad4bf78e 100644 --- a/src/pic/device.c +++ b/src/pic/device.c @@ -563,9 +563,6 @@ void assignRelocatableRegisters(set *regset, int used) if((!reg->isFixed) && ( used || reg->wasUsed)) { /* If register have been reused then shall not print it a second time. */ -// Undefine REUSE_GPR in files pcode.c & device.c to prevent local function registers being reused. -#define REUSE_GPR -#ifdef REUSE_GPR set *s; int done = 0; for (s = regset; s; s = s->next) { @@ -582,7 +579,6 @@ void assignRelocatableRegisters(set *regset, int used) } } if (!done) -#endif // REUSE_GPR address = assignRegister(reg,address); } } diff --git a/src/pic/gen.c b/src/pic/gen.c index 5eb4d55c..ac1dff89 100644 --- a/src/pic/gen.c +++ b/src/pic/gen.c @@ -229,15 +229,6 @@ void emitpcodeNULLop(PIC_OPCODE poc) } -void emitpcodePagesel(const char *label) -{ - - char code[81]; - strcpy(code,"\tpagesel "); - strcat(code,label); - addpCode2pBlock(pb,newpCodeInlineP(code)); - -} /*-----------------------------------------------------------------*/ /* pic14_emitcode - writes the code into a file : for now it is simple */ @@ -610,11 +601,7 @@ static asmop *aopForRemat (operand *op) // x symbol *sym) offset = OP_SYMBOL(IC_LEFT(ic))->offset; aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0); -#if 0 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op)); -#else - PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op)); -#endif PCOI(aop->aopu.pcop)->index = val; DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d", @@ -767,11 +754,7 @@ void aopOp (operand *op, iCode *ic, bool result) { sym_link *type = operandType(op); -#if 0 if(IS_PTR_CONST(type)) -#else - if(IS_CODEPTR(type)) -#endif DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__); } @@ -890,11 +873,7 @@ void aopOp (operand *op, iCode *ic, bool result) { sym_link *type = operandType(op); -#if 0 if(IS_PTR_CONST(type)) -#else - if(IS_CODEPTR(type)) -#endif DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__); } @@ -1210,44 +1189,16 @@ pCodeOp *popGetLabel(unsigned int key) } /*-------------------------------------------------------------------*/ -/* popGetLabel - create a new pCodeOp of type PO_LABEL with offset=1 */ +/* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */ /*-------------------------------------------------------------------*/ pCodeOp *popGetHighLabel(unsigned int key) { pCodeOp *pcop; - DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset); - - if(key>(unsigned int)max_key) - max_key = key; - - pcop = newpCodeOpLabel(NULL,key+100+labelOffset); + pcop = popGetLabel(key); PCOLAB(pcop)->offset = 1; return pcop; } -/*-----------------------------------------------------------------*/ -/* popCopyReg - copy a pcode operator */ -/*-----------------------------------------------------------------*/ -pCodeOp *popCopyReg(pCodeOpReg *pc) -{ - pCodeOpReg *pcor; - - pcor = Safe_calloc(1,sizeof(pCodeOpReg) ); - pcor->pcop.type = pc->pcop.type; - if(pc->pcop.name) { - if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name))) - fprintf(stderr,"oops %s %d",__FILE__,__LINE__); - } else - pcor->pcop.name = NULL; - - pcor->r = pc->r; - pcor->rIdx = pc->rIdx; - pcor->r->wasUsed=1; - - //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx); - - return PCOP(pcor); -} /*-----------------------------------------------------------------*/ /* popGet - asm operator to pcode operator conversion */ /*-----------------------------------------------------------------*/ @@ -1271,7 +1222,7 @@ pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func) /*-----------------------------------------------------------------*/ /* popGet - asm operator to pcode operator conversion */ /*-----------------------------------------------------------------*/ -pCodeOp *popGetWithString(char *str) +pCodeOp *popGetWithString(char *str, int isExtern) { pCodeOp *pcop; @@ -1282,6 +1233,7 @@ pCodeOp *popGetWithString(char *str) } pcop = newpCodeOp(str,PO_STR); + PCOS(pcop)->isPublic = isExtern ? 1 : 0; return pcop; } @@ -1318,6 +1270,8 @@ pCodeOp *popRegFromString(char *str, int size, int offset) return pcop; } +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ pCodeOp *popRegFromIdx(int rIdx) { pCodeOp *pcop; @@ -1328,7 +1282,7 @@ pCodeOp *popRegFromIdx(int rIdx) pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); PCOR(pcop)->rIdx = rIdx; - PCOR(pcop)->r = pic14_regWithIdx(rIdx); + PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1); PCOR(pcop)->r->isFree = 0; PCOR(pcop)->r->wasUsed = 1; @@ -1337,6 +1291,7 @@ pCodeOp *popRegFromIdx(int rIdx) return pcop; } + /*-----------------------------------------------------------------*/ /* popGet - asm operator to pcode operator conversion */ /*-----------------------------------------------------------------*/ @@ -2164,17 +2119,9 @@ static void assignResultValue(operand * oper) DEBUGpic14_AopType(__LINE__,oper,NULL,NULL); - if(!GpsuedoStkPtr) { - /* The last byte in the assignment is in W */ - size--; - emitpcode(POC_MOVWF, popGet(AOP(oper),size)); - GpsuedoStkPtr++; - DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - } - while (size--) { - emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr)); - GpsuedoStkPtr++; + if (GpsuedoStkPtr++) + emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr)); emitpcode(POC_MOVWF, popGet(AOP(oper),size)); } } @@ -2368,6 +2315,9 @@ static void saverbank (int bank, iCode *ic, bool pushPsw) static void genCall (iCode *ic) { sym_link *dtype; + symbol *sym; + unsigned char *name; + int isExtern; DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); @@ -2394,14 +2344,14 @@ static void genCall (iCode *ic) * in registers. (The pCode optimizer will get * rid of most of these :). */ - int psuedoStkPtr=-1; + int psuedoStkPtr=-1; int firstTimeThruLoop = 1; _G.sendSet = reverseSet(_G.sendSet); /* First figure how many parameters are getting passed */ for (sic = setFirstItem(_G.sendSet) ; sic ; - sic = setNextItem(_G.sendSet)) { + sic = setNextItem(_G.sendSet)) { aopOp(IC_LEFT(sic),sic,FALSE); psuedoStkPtr += AOP_SIZE(IC_LEFT(sic)); @@ -2409,47 +2359,44 @@ static void genCall (iCode *ic) } for (sic = setFirstItem(_G.sendSet) ; sic ; - sic = setNextItem(_G.sendSet)) { + sic = setNextItem(_G.sendSet)) { int size, offset = 0; aopOp(IC_LEFT(sic),sic,FALSE); size = AOP_SIZE(IC_LEFT(sic)); while (size--) { - DEBUGpic14_emitcode ("; ","%d left %s",__LINE__, - AopType(AOP_TYPE(IC_LEFT(sic)))); + DEBUGpic14_emitcode ("; ","%d left %s",__LINE__, + AopType(AOP_TYPE(IC_LEFT(sic)))); - if(!firstTimeThruLoop) { - /* If this is not the first time we've been through the loop - * then we need to save the parameter in a temporary - * register. The last byte of the last parameter is - * passed in W. */ - emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr)); + if(!firstTimeThruLoop) { + /* If this is not the first time we've been through the loop + * then we need to save the parameter in a temporary + * register. The last byte of the last parameter is + * passed in W. */ + emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr)); - } - firstTimeThruLoop=0; + } + firstTimeThruLoop=0; - //if (strcmp(l,fReturn[offset])) { - mov2w (AOP(IC_LEFT(sic)), offset); -/* - if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) || - ((AOP(IC_LEFT(sic))->type) == AOP_LIT) ) - emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset)); - else - emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset)); -*/ - //} - offset++; + mov2w (AOP(IC_LEFT(sic)), offset); + offset++; } freeAsmop (IC_LEFT(sic),NULL,sic,TRUE); } _G.sendSet = NULL; } /* make the call */ - emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ? - OP_SYMBOL(IC_LEFT(ic))->rname : - OP_SYMBOL(IC_LEFT(ic))->name)); - + sym = OP_SYMBOL(IC_LEFT(ic)); + name = sym->rname[0] ? sym->rname : sym->name; + isExtern = IS_EXTERN(sym->etype); + if (isExtern) { + emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */ + } + emitpcode(POC_CALL,popGetWithString(name,isExtern)); + if (isExtern) { + emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel */ + } GpsuedoStkPtr=0; /* if we need assign a result value */ if ((IS_ITEMP(IC_RESULT(ic)) && @@ -2503,6 +2450,7 @@ static void genPcall (iCode *ic) symbol *albl = newiTempLabel(NULL); symbol *blbl = newiTempLabel(NULL); PIC_OPCODE poc; + pCodeOp *pcop; operand *left; DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); @@ -2546,8 +2494,9 @@ static void genPcall (iCode *ic) } */ emitpcode(POC_CALL,popGetLabel(albl->key)); - emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */ - emitpcode(POC_GOTO,popGetLabel(blbl->key)); + pcop = popGetLabel(blbl->key); + emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */ + emitpcode(POC_GOTO,pcop); emitpLabel(albl->key); poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW); @@ -2655,7 +2604,7 @@ static void genFunction (iCode *ic) pic14_emitcode(";","-----------------------------------------"); pic14_emitcode("","%s:",sym->rname); - addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname)); + addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype))); ftype = operandType(IC_LEFT(ic)); @@ -2698,7 +2647,7 @@ static void genFunction (iCode *ic) emitpcode(POC_MOVWF, popCopyReg(&pc_ssave)); emitpcode(POC_MOVFW, popCopyReg(&pc_pclath)); emitpcode(POC_MOVWF, popCopyReg(&pc_psave)); - emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* durring an interrupt PCLATH must be cleared before a goto or call statement */ + emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */ pBlockConvert2ISR(pb); #if 0 @@ -2981,7 +2930,7 @@ static void genEndFunction (iCode *ic) emitpcodeNULLop(POC_RETURN); /* Mark the end of a function */ - addpCode2pBlock(pb,newpCodeFunction(NULL,NULL)); + addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0)); } } @@ -3025,7 +2974,7 @@ static void genRet (iCode *ic) emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset)); } if(size) { - emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr)); + emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size)); } offset++; } @@ -3958,21 +3907,6 @@ static void genCmp (operand *left,operand *right, } - /* - This works, but is only good for ints. - It also requires a "known zero" register. - emitpcode(POC_MOVLW, popGetLit(mlit & 0xff)); - emitpcode(POC_ADDFW, popGet(AOP(left),0)); - emitpcode(POC_RLFW, popCopyReg(&pc_kzero)); - emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff))); - emitpcode(POC_ADDFW, popGet(AOP(left),1)); - genSkipc(&rFalseIfx); - - emitpLabel(truelbl->key); - if(ifx) ifx->generated = 1; - return; - **/ - /* There are no more special cases, so perform a general compare */ emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff)); @@ -5337,26 +5271,22 @@ static void genAnd (iCode *ic, iCode *ifx) //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE)); // bit = left & 2^n if(size) - pic14_emitcode("mov","c,acc.%d",posbit&0x07); - // if(left & 2^n) + pic14_emitcode("mov","c,acc.%d",posbit&0x07); + // if(left & 2^n) else{ - if(ifx){ -/* - if(IC_TRUE(ifx)) { - emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0)); - emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key)); - } else { - emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0)); - emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key)); - } -*/ - emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS), - newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0)); - emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key)); - - ifx->generated = 1; - } - goto release; + if(ifx){ + int offset = 0; + while (posbit > 7) { + posbit -= 8; + offset++; + } + emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS), + newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0)); + emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key)); + + ifx->generated = 1; + } + goto release; } } else { symbol *tlbl = newiTempLabel(NULL); @@ -8355,6 +8285,7 @@ static void genConstPointerGet (operand *left, symbol *albl = newiTempLabel(NULL); symbol *blbl = newiTempLabel(NULL); PIC_OPCODE poc; + pCodeOp *pcop; DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); aopOp(left,ic,FALSE); @@ -8366,8 +8297,9 @@ static void genConstPointerGet (operand *left, DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__); emitpcode(POC_CALL,popGetLabel(albl->key)); - emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */ - emitpcode(POC_GOTO,popGetLabel(blbl->key)); + pcop = popGetLabel(blbl->key); + emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */ + emitpcode(POC_GOTO,pcop); emitpLabel(albl->key); poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW); @@ -8405,11 +8337,7 @@ static void genPointerGet (iCode *ic) type = operandType(left); etype = getSpec(type); -#if 0 if (IS_PTR_CONST(type)) -#else - if (IS_CODEPTR(type)) -#endif DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__); /* if left is of type of pointer then it is simple */ @@ -8465,11 +8393,9 @@ static void genPointerGet (iCode *ic) break; case GPOINTER: -#if 0 if (IS_PTR_CONST(type)) genConstPointerGet (left,result,ic); else -#endif genGenPointerGet (left,result,ic); break; } @@ -9633,17 +9559,9 @@ static void genCast (iCode *ic) goto release; DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__); -#if 0 if (IS_PTR_CONST(rtype)) -#else - if (IS_CODEPTR(rtype)) -#endif DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__); -#if 0 if (IS_PTR_CONST(operandType(IC_RESULT(ic)))) -#else - if (IS_CODEPTR(operandType(IC_RESULT(ic)))) -#endif DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__); if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) { diff --git a/src/pic/gen.h b/src/pic/gen.h index 36c5d157..03a4639a 100644 --- a/src/pic/gen.h +++ b/src/pic/gen.h @@ -162,7 +162,7 @@ pCodeOp *popGetLabel(unsigned int key); pCodeOp *popCopyReg(pCodeOpReg *pc); pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval); pCodeOp *popGetLit(unsigned int lit); -pCodeOp *popGetWithString(char *str); +pCodeOp *popGetWithString(char *str, int isExtern); pCodeOp *popRegFromString(char *str, int size, int offset); pCodeOp *popGet (asmop *aop, int offset);//, bool bit16, bool dname); pCodeOp *popGetTempReg(void); diff --git a/src/pic/glue.c b/src/pic/glue.c index c0077533..654d9c33 100644 --- a/src/pic/glue.c +++ b/src/pic/glue.c @@ -58,6 +58,7 @@ extern DEFSETFUNC (rmTmpFiles); extern void AnalyzeBanking (void); extern void copyFile (FILE * dest, FILE * src); +extern void ReuseReg(void); extern void InlinepCode(void); extern void writeUsedRegs(FILE *); @@ -68,7 +69,7 @@ extern void printChar (FILE * ofile, char *s, int plen); void pCodeInitRegisters(void); int getConfigWord(int address); -char *udata_section_name="udata"; // FIXME Temporary fix to change udata section name -- VR +char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR /*-----------------------------------------------------------------*/ /* aopLiteral - string from a literal value */ @@ -139,6 +140,9 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag) !IS_STATIC (sym->etype)) addSetHead (&publics, sym); + // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs() + if (sym->_isparm) + continue; /* if extern then do nothing or is a function then do nothing */ if (IS_FUNC (sym->type)) @@ -445,9 +449,11 @@ pic14emitStaticSeg (memmap * map) for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) { - /* if it is "extern" then do nothing */ - if (IS_EXTERN (sym->etype)) - continue; + /* if extern then add it into the extern list */ + if (IS_EXTERN (sym->etype)) { + addSetHead (&externs, sym); + continue; + } /* if it is not static add it to the public table */ @@ -555,7 +561,8 @@ pic14createInterruptVect (FILE * vFile) if (!(mainf = findSymWithLevel (SymbolTab, mainf))) { if (!options.cc_only) - werror (E_NO_MAIN); +// werror (E_NO_MAIN); + fprintf(stderr,"WARNING: function 'main' undefined\n"); return; } @@ -564,7 +571,8 @@ pic14createInterruptVect (FILE * vFile) { /* if ! compile only then main function should be present */ if (!options.cc_only) - werror (E_NO_MAIN); +// werror (E_NO_MAIN); + fprintf(stderr,"WARNING: function 'main' undefined\n"); return; } @@ -576,13 +584,9 @@ pic14createInterruptVect (FILE * vFile) fprintf (vFile, "%s", iComments2); fprintf (vFile, "; reset vector \n"); fprintf (vFile, "%s", iComments2); - fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); - fprintf (vFile, "\tnop\n"); /* first location used by incircuit debugger */ + fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0 + fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */ fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n"); -/* during an interrupt PCLATH must be cleared before a goto - delete me - fprintf (vFile, "\tnop\n"); - fprintf (vFile, "\tgoto\t__sdcc_interrupt\n"); -*/ } @@ -629,11 +633,15 @@ pic14printPublics (FILE * afile) for (sym = setFirstItem (publics); sym; sym = setNextItem (publics)) { + if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) { if (!IS_BITVAR(sym->type)) fprintf (afile, "\tglobal %s\n", sym->rname); - } else - fprintf (afile, ";\tglobal %s\n", sym->rname); + } else { + /* Absolute variables are defines in the asm file as equates and thus can not be made global. */ + if (!SPEC_ABSA (sym->etype)) + fprintf (afile, "\tglobal %s\n", sym->rname); + } } } @@ -751,7 +759,7 @@ pic14emitOverlay (FILE * afile) void picglue () { - + char udata_name[80]; FILE *vFile; FILE *asmFile; FILE *ovrFile = tempfile(); @@ -814,9 +822,7 @@ picglue () AnalyzepCode('*'); - //#ifdef PCODE_DEBUG - //printCallTree(stderr); - //#endif + ReuseReg(); // ReuseReg where call tree permits InlinepCode(); @@ -867,10 +873,16 @@ picglue () fprintf (asmFile, "%s", iComments2); copyFile (asmFile, sfr->oFile); + + if (udata_section_name) { + sprintf(udata_name,"%s",udata_section_name); + } else { + sprintf(udata_name,"data_%s",moduleName); + } fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; %s\n", udata_section_name); + fprintf (asmFile, "; udata\n"); fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "\t%s\n", udata_section_name); + fprintf (asmFile, "%s\tudata\n", udata_name); copyFile (asmFile, data->oFile); /* Put all variables into a cblock */ @@ -930,7 +942,7 @@ picglue () fprintf (asmFile, "%s", iComments2); fprintf (asmFile, "; interrupt and initialization code\n"); fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME); + fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file /* interrupt service routine */ fprintf (asmFile, "__sdcc_interrupt:\n"); diff --git a/src/pic/main.c b/src/pic/main.c index dcb0aca0..5aec2e9c 100644 --- a/src/pic/main.c +++ b/src/pic/main.c @@ -16,6 +16,7 @@ static char _defaultRules[] = { #include "peeph.rul" + "" }; /* list of key words used by msc51 */ @@ -260,8 +261,8 @@ _pic14_genAssemblerPreamble (FILE * of) } fprintf (of, "\tlist\tp=%s\n",&name[1]); - fprintf (of, "\tradix dec"); - fprintf (of, "\ninclude \"%s.inc\"\n",name); + fprintf (of, "\tradix dec\n"); + fprintf (of, "\tinclude \"%s.inc\"\n",name); } /* Generate interrupt vector table. */ @@ -473,7 +474,8 @@ PORT pic_port = hasExtBitOp, /* hasExtBitOp */ oclsExpense, /* oclsExpense */ FALSE, - TRUE, /* little endian */ +// TRUE, /* little endian */ + FALSE, /* little endian - PIC code enumlates big endian */ 0, /* leave lt */ 0, /* leave gt */ 1, /* transform <= to ! > */ diff --git a/src/pic/pcode.c b/src/pic/pcode.c index 295ff336..daa0a9f3 100644 --- a/src/pic/pcode.c +++ b/src/pic/pcode.c @@ -29,6 +29,10 @@ #include "ralloc.h" #include "device.h" +pCode *findFunction(char *fname); + +static void FixRegisterBanking(pBlock *pb,int cur_bank); + #if defined(__BORLANDC__) || defined(_MSC_VER) #define STRCASECMP stricmp #else @@ -57,19 +61,16 @@ pCodeOpReg pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL}; pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL}; pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL}; -pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL}; pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL}; pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL}; pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL}; static int mnemonics_initialized = 0; - static hTab *pic14MnemonicsHash = NULL; static hTab *pic14pCodePeepCommandsHash = NULL; - static pFile *the_pFile = NULL; static pBlock *pb_dead_pcodes = NULL; @@ -81,6 +82,9 @@ int debug_verbose = 0; /* Set true to inundate .asm file */ // static int GpCodeSequenceNumber = 1; int GpcFlowSeq = 1; +unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */ +unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */ + extern void RemoveUnusedRegisters(void); extern void RegsUnMapLiveRanges(void); extern void BuildFlowTree(pBlock *pb); @@ -111,8 +115,6 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd); int pCodePeepMatchRule(pCode *pc); void pBlockStats(FILE *of, pBlock *pb); pBlock *newpBlock(void); -extern void pCodeInsertAfter(pCode *pc1, pCode *pc2); -extern pCodeOp *popCopyReg(pCodeOpReg *pc); pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval); void pCodeRegMapLiveRanges(pBlock *pb); @@ -122,7 +124,7 @@ void pCodeRegMapLiveRanges(pBlock *pb); /****************************************************************/ pCodeInstruction pciADDWF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -144,7 +146,7 @@ pCodeInstruction pciADDWF = { }; pCodeInstruction pciADDFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -166,7 +168,7 @@ pCodeInstruction pciADDFW = { }; pCodeInstruction pciADDLW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -188,7 +190,7 @@ pCodeInstruction pciADDLW = { }; pCodeInstruction pciANDLW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -210,7 +212,7 @@ pCodeInstruction pciANDLW = { }; pCodeInstruction pciANDWF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -232,7 +234,7 @@ pCodeInstruction pciANDWF = { }; pCodeInstruction pciANDFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -254,7 +256,7 @@ pCodeInstruction pciANDFW = { }; pCodeInstruction pciBCF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -276,7 +278,7 @@ pCodeInstruction pciBCF = { }; pCodeInstruction pciBSF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -298,7 +300,7 @@ pCodeInstruction pciBSF = { }; pCodeInstruction pciBTFSC = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeSKIP, genericDestruct, genericPrint}, @@ -320,7 +322,7 @@ pCodeInstruction pciBTFSC = { }; pCodeInstruction pciBTFSS = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeSKIP, genericDestruct, genericPrint}, @@ -342,7 +344,7 @@ pCodeInstruction pciBTFSS = { }; pCodeInstruction pciCALL = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -364,7 +366,7 @@ pCodeInstruction pciCALL = { }; pCodeInstruction pciCOMF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -386,7 +388,7 @@ pCodeInstruction pciCOMF = { }; pCodeInstruction pciCOMFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -408,7 +410,7 @@ pCodeInstruction pciCOMFW = { }; pCodeInstruction pciCLRF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -430,7 +432,7 @@ pCodeInstruction pciCLRF = { }; pCodeInstruction pciCLRW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -452,7 +454,7 @@ pCodeInstruction pciCLRW = { }; pCodeInstruction pciCLRWDT = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -474,7 +476,7 @@ pCodeInstruction pciCLRWDT = { }; pCodeInstruction pciDECF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -496,7 +498,7 @@ pCodeInstruction pciDECF = { }; pCodeInstruction pciDECFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -518,7 +520,7 @@ pCodeInstruction pciDECFW = { }; pCodeInstruction pciDECFSZ = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeSKIP, genericDestruct, genericPrint}, @@ -540,7 +542,7 @@ pCodeInstruction pciDECFSZ = { }; pCodeInstruction pciDECFSZW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeSKIP, genericDestruct, genericPrint}, @@ -562,7 +564,7 @@ pCodeInstruction pciDECFSZW = { }; pCodeInstruction pciGOTO = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeGOTO, genericDestruct, genericPrint}, @@ -584,7 +586,7 @@ pCodeInstruction pciGOTO = { }; pCodeInstruction pciINCF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -606,7 +608,7 @@ pCodeInstruction pciINCF = { }; pCodeInstruction pciINCFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -628,7 +630,7 @@ pCodeInstruction pciINCFW = { }; pCodeInstruction pciINCFSZ = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeSKIP, genericDestruct, genericPrint}, @@ -650,7 +652,7 @@ pCodeInstruction pciINCFSZ = { }; pCodeInstruction pciINCFSZW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeSKIP, genericDestruct, genericPrint}, @@ -672,7 +674,7 @@ pCodeInstruction pciINCFSZW = { }; pCodeInstruction pciIORWF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -694,7 +696,7 @@ pCodeInstruction pciIORWF = { }; pCodeInstruction pciIORFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -716,7 +718,7 @@ pCodeInstruction pciIORFW = { }; pCodeInstruction pciIORLW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -738,7 +740,7 @@ pCodeInstruction pciIORLW = { }; pCodeInstruction pciMOVF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -760,7 +762,7 @@ pCodeInstruction pciMOVF = { }; pCodeInstruction pciMOVFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -782,7 +784,7 @@ pCodeInstruction pciMOVFW = { }; pCodeInstruction pciMOVWF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -804,7 +806,7 @@ pCodeInstruction pciMOVWF = { }; pCodeInstruction pciMOVLW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, genericDestruct, genericPrint}, POC_MOVLW, @@ -825,7 +827,7 @@ pCodeInstruction pciMOVLW = { }; pCodeInstruction pciNOP = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, genericDestruct, genericPrint}, POC_NOP, @@ -846,7 +848,7 @@ pCodeInstruction pciNOP = { }; pCodeInstruction pciRETFIE = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeRETURN, genericDestruct, genericPrint}, @@ -868,7 +870,7 @@ pCodeInstruction pciRETFIE = { }; pCodeInstruction pciRETLW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeRETURN, genericDestruct, genericPrint}, @@ -890,7 +892,7 @@ pCodeInstruction pciRETLW = { }; pCodeInstruction pciRETURN = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // AnalyzeRETURN, genericDestruct, genericPrint}, @@ -912,7 +914,7 @@ pCodeInstruction pciRETURN = { }; pCodeInstruction pciRLF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -934,7 +936,7 @@ pCodeInstruction pciRLF = { }; pCodeInstruction pciRLFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -956,7 +958,7 @@ pCodeInstruction pciRLFW = { }; pCodeInstruction pciRRF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -978,7 +980,7 @@ pCodeInstruction pciRRF = { }; pCodeInstruction pciRRFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1000,7 +1002,7 @@ pCodeInstruction pciRRFW = { }; pCodeInstruction pciSUBWF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1022,7 +1024,7 @@ pCodeInstruction pciSUBWF = { }; pCodeInstruction pciSUBFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1044,7 +1046,7 @@ pCodeInstruction pciSUBFW = { }; pCodeInstruction pciSUBLW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1066,7 +1068,7 @@ pCodeInstruction pciSUBLW = { }; pCodeInstruction pciSWAPF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1088,7 +1090,7 @@ pCodeInstruction pciSWAPF = { }; pCodeInstruction pciSWAPFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1110,7 +1112,7 @@ pCodeInstruction pciSWAPFW = { }; pCodeInstruction pciTRIS = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1132,7 +1134,7 @@ pCodeInstruction pciTRIS = { }; pCodeInstruction pciXORWF = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1154,7 +1156,7 @@ pCodeInstruction pciXORWF = { }; pCodeInstruction pciXORFW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1176,7 +1178,7 @@ pCodeInstruction pciXORFW = { }; pCodeInstruction pciXORLW = { - {PC_OPCODE, NULL, NULL, 0, NULL, + {PC_OPCODE, NULL, NULL, 0, 0, NULL, // genericAnalyze, genericDestruct, genericPrint}, @@ -1198,10 +1200,68 @@ pCodeInstruction pciXORLW = { }; -#define MAX_PIC14MNEMONICS 100 +pCodeInstruction pciBANKSEL = { + {PC_OPCODE, NULL, NULL, 0, 0, NULL, + // genericAnalyze, + genericDestruct, + genericPrint}, + POC_BANKSEL, + "BANKSEL", + NULL, // from branch + NULL, // to branch + NULL, // label + NULL, // operand + NULL, // flow block + NULL, // C source + 1, // num ops + 0,0, // dest, bit instruction + 0,0, // branch, skip + 0, // literal operand + POC_NOP, + PCC_NONE, // inCond + PCC_REGISTER // outCond +}; + +pCodeInstruction pciPAGESEL = { + {PC_OPCODE, NULL, NULL, 0, 0, NULL, + // genericAnalyze, + genericDestruct, + genericPrint}, + POC_PAGESEL, + "PAGESEL", + NULL, // from branch + NULL, // to branch + NULL, // label + NULL, // operand + NULL, // flow block + NULL, // C source + 1, // num ops + 0,0, // dest, bit instruction + 0,0, // branch, skip + 0, // literal operand + POC_NOP, + PCC_NONE, // inCond + PCC_REGISTER // outCond +}; + pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS]; +/*-----------------------------------------------------------------*/ +/* return a unique ID number to assist pCodes debuging */ +/*-----------------------------------------------------------------*/ +unsigned PCodeID(void) { + static unsigned int pcodeId = 1; // unique ID number to be assigned to all pCodes +/**/ + static unsigned int stop; + if (pcodeId == 5801) + stop++; + if ((pcodeId >= 855)&&(pcodeId <= 856)) + stop++; +/**/ + return pcodeId++; +} + #ifdef HAVE_VSNPRINTF // Alas, vsnprintf is not ANSI standard, and does not exist // on Solaris (and probably other non-Gnu flavored Unixes). @@ -1278,21 +1338,23 @@ extern void init_pic(char *); void pCodeInitRegisters(void) { static int initialized=0; - int shareBankAddress; + int shareBankAddress,stkSize; if(initialized) return; initialized = 1; - initStack(0xfff, 8); + shareBankAddress = 0x7f; /* FIXME - some PIC ICs like 16C7X which do not have a shared bank need a different approach. */ + stkSize = 8; // Set pseudo stack size to 8 + initStack(shareBankAddress, stkSize); // Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters init_pic(port->processor); - pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80); + pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180); pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80); - pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80); - pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80); + pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180); + pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180); pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80); - pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80); + pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180); pc_status.rIdx = IDX_STATUS; pc_fsr.rIdx = IDX_FSR; @@ -1301,19 +1363,20 @@ void pCodeInitRegisters(void) pc_pcl.rIdx = IDX_PCL; pc_pclath.rIdx = IDX_PCLATH; - pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0); /* Known Zero - actually just a general purpose reg. */ - pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0x80); /* Interupt storage for working register - must be same address in all banks ie section SHAREBANK. */ - pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interupt storage for status register. */ - pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interupt storage for pclath register. */ + pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0x180); /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */ + pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for status register. */ + pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for pclath register. */ - pc_kzero.rIdx = pc_kzero.r->rIdx; pc_wsave.rIdx = pc_wsave.r->rIdx; pc_ssave.rIdx = pc_ssave.r->rIdx; pc_psave.rIdx = pc_psave.r->rIdx; - shareBankAddress = 0x7f; /* FIXME - this is different for some PICs ICs if the sharebank does not exist then this address needs to be reserved across all banks. */ - pc_wsave.r->isFixed = 1; - pc_wsave.r->address = shareBankAddress; + pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */ + pc_wsave.r->address = shareBankAddress-stkSize; + pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */ + pc_ssave.r->address = shareBankAddress-stkSize-1; + pc_psave.r->isFixed = 1; /* This register must be in the first bank. */ + pc_psave.r->address = shareBankAddress-stkSize-2; /* probably should put this in a separate initialization routine */ pb_dead_pcodes = newpBlock(); @@ -1405,6 +1468,8 @@ void pic14initMnemonics(void) pic14Mnemonics[POC_XORLW] = &pciXORLW; pic14Mnemonics[POC_XORWF] = &pciXORWF; pic14Mnemonics[POC_XORFW] = &pciXORFW; + pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL; + pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL; for(i=0; i=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) { memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction)); + pci->pc.id = PCodeID(); pci->pcop = pcop; if(pci->inCond & PCC_EXAMINE_PCOP) @@ -1724,6 +1790,7 @@ pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_la pcw->pci.pc.type = PC_WILD; pcw->pci.pc.prev = pcw->pci.pc.next = NULL; + pcw->id = PCodeID(); pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL; pcw->pci.pc.pb = NULL; @@ -1757,6 +1824,7 @@ pCode *newpCodeInlineP(char *cP) pcc->pc.type = PC_INLINE; pcc->pc.prev = pcc->pc.next = NULL; + pcc->pc.id = PCodeID(); //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL; pcc->pc.pb = NULL; @@ -1786,6 +1854,7 @@ pCode *newpCodeCharP(char *cP) pcc->pc.type = PC_COMMENT; pcc->pc.prev = pcc->pc.next = NULL; + pcc->pc.id = PCodeID(); //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL; pcc->pc.pb = NULL; @@ -1807,7 +1876,7 @@ pCode *newpCodeCharP(char *cP) /*-----------------------------------------------------------------*/ -pCode *newpCodeFunction(char *mod,char *f) +pCode *newpCodeFunction(char *mod,char *f,int isPublic) { pCodeFunction *pcf; @@ -1816,6 +1885,7 @@ pCode *newpCodeFunction(char *mod,char *f) pcf->pc.type = PC_FUNCTION; pcf->pc.prev = pcf->pc.next = NULL; + pcf->pc.id = PCodeID(); //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL; pcf->pc.pb = NULL; @@ -1839,6 +1909,8 @@ pCode *newpCodeFunction(char *mod,char *f) } else pcf->fname = NULL; + pcf->isPublic = (unsigned)isPublic; + return ( (pCode *)pcf); } @@ -1886,8 +1958,8 @@ pCode *newpCodeFlow(void ) pcflow->inCond = PCC_NONE; pcflow->outCond = PCC_NONE; - pcflow->firstBank = -1; - pcflow->lastBank = -1; + pcflow->firstBank = 'U'; /* Undetermined */ + pcflow->lastBank = 'U'; /* Undetermined */ pcflow->FromConflicts = 0; pcflow->ToConflicts = 0; @@ -1927,6 +1999,7 @@ pCode *newpCodeCSource(int ln, char *f, char *l) pccs->pc.type = PC_CSOURCE; pccs->pc.prev = pccs->pc.next = NULL; + pccs->pc.id = PCodeID(); pccs->pc.pb = NULL; pccs->pc.destruct = genericDestruct; @@ -1972,6 +2045,7 @@ pCode *newpCodeLabel(char *name, int key) pcl->pc.type = PC_LABEL; pcl->pc.prev = pcl->pc.next = NULL; + pcl->pc.id = PCodeID(); //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL; pcl->pc.pb = NULL; @@ -2155,10 +2229,23 @@ pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype) return pcop; } +/*-----------------------------------------------------------------*/ +/* Find a symbol with matching name */ +/*-----------------------------------------------------------------*/ +static symbol *symFindWithName(memmap * map, const char *name) +{ + symbol *sym; + + for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) { + if (sym->rname && (strcmp(sym->rname,name)==0)) + return sym; + } + return 0; +} /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ -pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace) +pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace) { pCodeOp *pcop; struct regs *r = 0; @@ -2166,15 +2253,18 @@ pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace) pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) ); pcop->type = PO_GPR_BIT; - PCORB(pcop)->bit = bit; + PCORB(pcop)->bit = ibit; PCORB(pcop)->inBitSpace = inBitSpace; - /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */ - if (s && !inBitSpace) { - r = dirregWithName(s); - if (!r) { - unsigned char idx = ((s[3] - (((s[3]>='0')&&(s[3]<='9'))?'0':'A'-10))<<4)|(s[4] - (((s[4]>='0')&&(s[4]<='9'))?'0':'A'-10)); - r = pic14_regWithIdx(idx); + if (name) r = regFindWithName(name); + if (!r) { + // Register has not been allocated - check for symbol information + symbol *sym; + sym = symFindWithName(bit, name); + if (!sym) sym = symFindWithName(sfrbit, name); + if (!sym) sym = symFindWithName(sfr, name); + if (sym) { + r = allocNewDirReg(sym->etype,name); } } if (r) { @@ -2182,7 +2272,7 @@ pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace) PCOR(pcop)->r = r; PCOR(pcop)->rIdx = r->rIdx; } else { - pcop->name = Safe_strdup(s); + pcop->name = Safe_strdup(name); PCOR(pcop)->r = NULL; PCOR(pcop)->rIdx = 0; } @@ -2215,7 +2305,8 @@ pCodeOp *newpCodeOpReg(int rIdx) PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx; } - pcop->type = PCOR(pcop)->r->pc_type; + if(PCOR(pcop)->r) + pcop->type = PCOR(pcop)->r->pc_type; return pcop; } @@ -2233,6 +2324,20 @@ pCodeOp *newpCodeOpRegFromStr(char *name) return pcop; } +pCodeOp *newpCodeOpStr(char *name) +{ + pCodeOp *pcop; + + pcop = Safe_calloc(1,sizeof(pCodeOpStr)); + pcop->type = PO_STR; + pcop->name = Safe_strdup(name); + + PCOS(pcop)->isPublic = 0; + + return pcop; +} + + /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ @@ -2253,6 +2358,7 @@ pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type) case PO_LABEL: pcop = newpCodeOpLabel(NULL,-1); break; + case PO_GPR_TEMP: pcop = newpCodeOpReg(-1); break; @@ -2265,6 +2371,10 @@ pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type) pcop = newpCodeOpReg(-1); break; + case PO_STR: + pcop = newpCodeOpStr(name); + break; + default: pcop = Safe_calloc(1,sizeof(pCodeOp) ); pcop->type = type; @@ -2505,6 +2615,240 @@ static void genericDestruct(pCode *pc) } +/*-----------------------------------------------------------------*/ +/* Copies the pCodeInstruction flow pointer from source pCode */ +/*-----------------------------------------------------------------*/ +static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) { + pCode *p; + pCodeFlow *pcflow = 0; + for (p=pcs; p; p=p->prev) { + if (isPCI(p)) { + pcflow = PCI(p)->pcflow; + break; + } + if (isPCF(p)) { + pcflow = (pCodeFlow*)p; + break; + } + } + PCI(pcd)->pcflow = pcflow; +} + +/*-----------------------------------------------------------------*/ +/* pCodeInsertAfter - splice in the pCode chain starting with pc2 */ +/* into the pCode chain containing pc1 */ +/*-----------------------------------------------------------------*/ +void pCodeInsertAfter(pCode *pc1, pCode *pc2) +{ + + if(!pc1 || !pc2) + return; + + pc2->next = pc1->next; + if(pc1->next) + pc1->next->prev = pc2; + + pc2->pb = pc1->pb; + pc2->prev = pc1; + pc1->next = pc2; + + /* If this is an instrution type propogate the flow */ + if (isPCI(pc2)) + CopyFlow(PCI(pc2),pc1); +} + +/*------------------------------------------------------------------*/ +/* pCodeInsertBefore - splice in the pCode chain starting with pc2 */ +/* into the pCode chain containing pc1 */ +/*------------------------------------------------------------------*/ +void pCodeInsertBefore(pCode *pc1, pCode *pc2) +{ + + if(!pc1 || !pc2) + return; + + pc2->prev = pc1->prev; + if(pc1->prev) + pc1->prev->next = pc2; + + pc2->pb = pc1->pb; + pc2->next = pc1; + pc1->prev = pc2; + + /* If this is an instrution type propogate the flow */ + if (isPCI(pc2)) + CopyFlow(PCI(pc2),pc1); +} + +/*-----------------------------------------------------------------*/ +/* pCodeOpCopy - copy a pcode operator */ +/*-----------------------------------------------------------------*/ +pCodeOp *pCodeOpCopy(pCodeOp *pcop) +{ + pCodeOp *pcopnew=NULL; + + if(!pcop) + return NULL; + + switch(pcop->type) { + case PO_CRY: + case PO_BIT: + //DFPRINTF((stderr,"pCodeOpCopy bit\n")); + pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) ); + PCORB(pcopnew)->bit = PCORB(pcop)->bit; + PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace; + + break; + + case PO_WILD: + /* Here we expand the wild card into the appropriate type: */ + /* By recursively calling pCodeOpCopy */ + //DFPRINTF((stderr,"pCodeOpCopy wild\n")); + if(PCOW(pcop)->matched) + pcopnew = pCodeOpCopy(PCOW(pcop)->matched); + else { + // Probably a label + pcopnew = pCodeOpCopy(PCOW(pcop)->subtype); + pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]); + //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name)); + } + + return pcopnew; + break; + + case PO_LABEL: + //DFPRINTF((stderr,"pCodeOpCopy label\n")); + pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) ); + PCOLAB(pcopnew)->key = PCOLAB(pcop)->key; + break; + + case PO_IMMEDIATE: + pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) ); + PCOI(pcopnew)->index = PCOI(pcop)->index; + PCOI(pcopnew)->offset = PCOI(pcop)->offset; + PCOI(pcopnew)->_const = PCOI(pcop)->_const; + PCOI(pcopnew)->_function = PCOI(pcop)->_function; + break; + + case PO_LITERAL: + //DFPRINTF((stderr,"pCodeOpCopy lit\n")); + pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) ); + PCOL(pcopnew)->lit = PCOL(pcop)->lit; + break; + + case PO_GPR_BIT: + + pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace); + PCOR(pcopnew)->r = PCOR(pcop)->r; + PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx; + DFPRINTF((stderr," pCodeOpCopy Bit -register index\n")); + return pcopnew; + break; + + case PO_GPR_POINTER: + case PO_GPR_REGISTER: + case PO_GPR_TEMP: + case PO_FSR: + case PO_INDF: + //DFPRINTF((stderr,"pCodeOpCopy GPR register\n")); + pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) ); + PCOR(pcopnew)->r = PCOR(pcop)->r; + PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx; + PCOR(pcopnew)->instance = PCOR(pcop)->instance; + DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx)); + break; + + case PO_DIR: + //fprintf(stderr,"pCodeOpCopy PO_DIR\n"); + pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) ); + PCOR(pcopnew)->r = PCOR(pcop)->r; + PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx; + PCOR(pcopnew)->instance = PCOR(pcop)->instance; + break; + case PO_STATUS: + DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n")); + case PO_SFR_REGISTER: + case PO_STR: + case PO_NONE: + case PO_W: + case PO_INTCON: + case PO_PCL: + case PO_PCLATH: + + //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type)); + pcopnew = Safe_calloc(1,sizeof(pCodeOp) ); + + } + + pcopnew->type = pcop->type; + if(pcop->name) + pcopnew->name = Safe_strdup(pcop->name); + else + pcopnew->name = NULL; + + return pcopnew; +} + +/*-----------------------------------------------------------------*/ +/* popCopyReg - copy a pcode operator */ +/*-----------------------------------------------------------------*/ +pCodeOp *popCopyReg(pCodeOpReg *pc) +{ + pCodeOpReg *pcor; + + pcor = Safe_calloc(1,sizeof(pCodeOpReg) ); + pcor->pcop.type = pc->pcop.type; + if(pc->pcop.name) { + if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name))) + fprintf(stderr,"oops %s %d",__FILE__,__LINE__); + } else + pcor->pcop.name = NULL; + + pcor->r = pc->r; + pcor->rIdx = pc->rIdx; + pcor->r->wasUsed=1; + + //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx); + + return PCOP(pcor); +} + +/*-----------------------------------------------------------------*/ +/* pCodeInstructionCopy - copy a pCodeInstructionCopy */ +/*-----------------------------------------------------------------*/ +pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert) +{ + pCodeInstruction *new_pci; + + if(invert) + new_pci = PCI(newpCode(pci->inverted_op,pci->pcop)); + else + new_pci = PCI(newpCode(pci->op,pci->pcop)); + + new_pci->pc.pb = pci->pc.pb; + new_pci->from = pci->from; + new_pci->to = pci->to; + new_pci->label = pci->label; + new_pci->pcflow = pci->pcflow; + + return PCODE(new_pci); +} + +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +void pCodeDeleteChain(pCode *f,pCode *t) +{ + pCode *pc; + + while(f && f!=t) { + DFPRINTF((stderr,"delete pCode:\n")); + pc = f->next; + //f->print(stderr,f); + //f->delete(f); this dumps core... + f = pc; + } +} + /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ void pBlockRegs(FILE *of, pBlock *pb) @@ -2546,7 +2890,10 @@ char *get_op(pCodeOp *pcop,char *buffer, size_t size) return pcop->name; break; case PO_GPR_TEMP: - r = pic14_regWithIdx(PCOR(pcop)->r->rIdx); + if (PCOR(pcop)->r->type == REG_STK) + r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1); + else + r = pic14_regWithIdx(PCOR(pcop)->r->rIdx); if(use_buffer) { SAFE_snprintf(&buffer,&size,"%s",r->name); @@ -2783,7 +3130,7 @@ static void genericPrint(FILE *of, pCode *pc) /* Debug */ if(debug_verbose) { - fprintf(of, "\t;key=%03x",pc->seq); + fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq); if(PCI(pc)->pcflow) fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq); } @@ -3088,7 +3435,7 @@ static void genericAnalyze(pCode *pc) return; case PC_BAD: - fprintf(stderr,,";A bad pCode is being used\n"); + fprintf(stderr,";A bad pCode is being used\n"); } } @@ -3329,6 +3676,7 @@ regs * getRegFromInstruction(pCode *pc) case PO_GPR_BIT: return PCOR(PCI(pc)->pcop)->r; + case PO_GPR_REGISTER: case PO_DIR: //fprintf(stderr, "getRegFromInstruction - dir\n"); return PCOR(PCI(pc)->pcop)->r; @@ -3374,7 +3722,7 @@ void AnalyzepBlock(pBlock *pb) regs *r = setFirstItem(pb->tregisters); while(r) { - if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) { + if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) { PCOR(PCI(pc)->pcop)->r = r; break; } @@ -3413,8 +3761,6 @@ void AnalyzepBlock(pBlock *pb) /*-----------------------------------------------------------------*/ /* */ /*-----------------------------------------------------------------*/ -#define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL)) - void InsertpFlow(pCode *pc, pCode **pflow) { if(*pflow) @@ -3631,10 +3977,11 @@ void FlowStats(pCodeFlow *pcflow) * to whether they're set or cleared. * *-----------------------------------------------------------------*/ +/* #define SET_BANK_BIT (1 << 16) #define CLR_BANK_BIT 0 -int isBankInstruction(pCode *pc) +static int isBankInstruction(pCode *pc) { regs *reg; int bank = -1; @@ -3644,7 +3991,7 @@ int isBankInstruction(pCode *pc) if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) { - /* Check to see if the register banks are changing */ + // Check to see if the register banks are changing if(PCI(pc)->isModReg) { pCodeOp *pcop = PCI(pc)->pcop; @@ -3683,13 +4030,13 @@ int isBankInstruction(pCode *pc) return bank; } - +*/ /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ -void FillFlow(pCodeFlow *pcflow) +/* +static void FillFlow(pCodeFlow *pcflow) { - pCode *pc; int cur_bank; @@ -3711,8 +4058,7 @@ void FillFlow(pCodeFlow *pcflow) isBankInstruction(pc); pc = pc->next; } while (pc && (pc != pcflow->end) && !isPCFL(pc)); - -/* +/ * if(!pc ) { fprintf(stderr, " FillFlow - Bad end of flow\n"); } else { @@ -3724,8 +4070,9 @@ void FillFlow(pCodeFlow *pcflow) dumpCond(pcflow->inCond); fprintf(stderr, " FillFlow outCond: "); dumpCond(pcflow->outCond); -*/ +* / } +*/ /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ @@ -3851,7 +4198,8 @@ int isPCinFlow(pCode *pc, pCode *pcflow) /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ -void BanksUsedFlow2(pCode *pcflow) +/* +static void BanksUsedFlow2(pCode *pcflow) { pCode *pc=NULL; @@ -3879,7 +4227,7 @@ void BanksUsedFlow2(pCode *pcflow) if(bank_selected > 0) { //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected); - /* This instruction is modifying banking bits before accessing registers */ + // This instruction is modifying banking bits before accessing registers if(!RegUsed) PCFL(pcflow)->firstBank = -1; @@ -3911,13 +4259,12 @@ void BanksUsedFlow2(pCode *pcflow) // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n", // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank); - - - } +*/ /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ -void BanksUsedFlow(pBlock *pb) +/* +static void BanksUsedFlow(pBlock *pb) { pCode *pcflow; @@ -3935,134 +4282,289 @@ void BanksUsedFlow(pBlock *pb) } } - +*/ /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ -void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit) +static void pCodeInstructionInsertAfter(pCodeInstruction *pci, pCodeInstruction *new_pci) { - pCode *new_pc; - - if(!pc) - return; - if(RP_BankBit < 0) - new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status)); - else - new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF), - popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit)); + pCodeInsertAfter(pci->pc.prev, &new_pci->pc); - if(position) { - /* insert the bank switch after this pc instruction */ - pCode *pcnext = findNextInstruction(pc); - pCodeInsertAfter(pc, new_pc); - if(pcnext) - pc = pcnext; + /* Move the label, if there is one */ - } else - pCodeInsertAfter(pc->prev, new_pc); + if(pci->label) { + new_pci->label = pci->label; + pci->label = NULL; + } - /* Move the label, if there is one */ + /* Move the C code comment, if there is one */ - if(PCI(pc)->label) { - PCI(new_pc)->label = PCI(pc)->label; - PCI(pc)->label = NULL; + if(pci->cline) { + new_pci->cline = pci->cline; + pci->cline = NULL; } /* The new instruction has the same pcflow block */ - PCI(new_pc)->pcflow = PCI(pc)->pcflow; + new_pci->pcflow = pci->pcflow; } + /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ -void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank) +static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit) { - pCode *pc=NULL; - pCode *pcprev=NULL; pCode *new_pc; - regs *reg; + new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit)); - if(!pcfl) - return; + pCodeInstructionInsertAfter(pci, PCI(new_pc)); +} - pc = findNextInstruction(pcfl->pc.next); +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +static void insertBankSel(pCodeInstruction *pci, const char *name) +{ + pCode *new_pc; - while(isPCinFlow(pc,PCODE(pcfl))) { + pCodeOp *pcop = popCopyReg(PCOR(pci->pcop)); + pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it + if (pcop->name == 0) + pcop->name = strdup(name); + new_pc = newpCode(POC_BANKSEL, pcop); - reg = getRegFromInstruction(pc); -#if 0 - if(reg) { - fprintf(stderr, " %s ",reg->name); - fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg)); + pCodeInstructionInsertAfter(pci, PCI(new_pc)); +} +/*-----------------------------------------------------------------*/ +/* If the register is a fixed known addess then we can assign the */ +/* bank selection bits. Otherwise the linker is going to assign */ +/* the register location and thus has to set bank selection bits */ +/* through the banksel directive. */ +/* One critical assumption here is that within this C module all */ +/* the locally allocated registers are in the same udata sector. */ +/* Therefore banksel is only called for external registers or the */ +/* first time a local register is encountered. */ +/*-----------------------------------------------------------------*/ +static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */ +static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg) +{ + int bank; + int a = reg->alias>>7; + if ((a&3) == 3) { + return cur_bank; // This register is available in all banks + } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) { + return cur_bank; // This register is available in banks 0 & 1 + } else if (a&2) { + if (reg->address&0x80) { + if ((cur_bank==1)||(cur_bank==3)) { + return cur_bank; // This register is available in banks 1 & 3 + } + } else { + if ((cur_bank==0)||(cur_bank==1)) { + return cur_bank; // This register is available in banks 0 & 2 + } } -#endif + } + + if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank + return cur_bank; + LastRegIdx = reg->rIdx; + + if (reg->isFixed) { + bank = REG_BANK(reg); + } else if (reg->isExtern) { + bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown + } else { + bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown + } + if ((cur_bank == 'L')&&(bank == 'L')) { // If current bank and new bank are both allocated locally by the linker, then assume it is in same bank. + return 'L'; // Local registers are presumed to be in same linker assigned bank + } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank + insertBankSel(pci, reg->name); // Let linker choose the bank selection + } else if (bank == 'E') { // Reg is now extern and linker to assign bank + insertBankSel(pci, reg->name); // Let linker choose the bank selection + } else if ((cur_bank == -1)||(cur_bank == 'L')||(cur_bank == 'E')) { // Current bank unknown and new register bank is known then can set bank bits + insertBankSwitch(pci, bank&1, PIC_RP0_BIT); + insertBankSwitch(pci, bank&2, PIC_RP1_BIT); + } else { // Current bank and new register banks known - can set bank bits + switch((cur_bank^bank) & 3) { + case 0: + break; + case 1: + insertBankSwitch(pci, bank&1, PIC_RP0_BIT); + break; + case 2: + insertBankSwitch(pci, bank&2, PIC_RP1_BIT); + break; + case 3: + insertBankSwitch(pci, bank&1, PIC_RP0_BIT); + insertBankSwitch(pci, bank&2, PIC_RP1_BIT); + break; + } + } + + return bank; +} + +/*-----------------------------------------------------------------*/ +/* Check for bank selection pcodes instructions and modify */ +/* cur_bank to match. */ +/*-----------------------------------------------------------------*/ +static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) { + + if (isSTATUS_REG(reg)) { + + if (PCI(pc)->op == POC_BCF) { + int old_bank = *cur_bank; + if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) { + /* If current bank is unknown or linker assigned then set to 0 else just change the bit */ + if (*cur_bank & ~(0x3)) + *cur_bank = 0; + else + *cur_bank = *cur_bank&0x2; + LastRegIdx = reg->rIdx; + } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) { + /* If current bank is unknown or linker assigned then set to 0 else just change the bit */ + if (*cur_bank & ~(0x3)) + *cur_bank = 0; + else + *cur_bank = *cur_bank&0x1; + LastRegIdx = reg->rIdx; + } + return old_bank != *cur_bank; + } + + if (PCI(pc)->op == POC_BSF) { + int old_bank = *cur_bank; + if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) { + /* If current bank is unknown or linker assigned then set to bit else just change the bit */ + if (*cur_bank & ~(0x3)) + *cur_bank = 0x1; + else + *cur_bank = (*cur_bank&0x2) | 0x1; + LastRegIdx = reg->rIdx; + } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) { + /* If current bank is unknown or linker assigned then set to bit else just change the bit */ + if (*cur_bank & ~(0x3)) + *cur_bank = 0x2; + else + *cur_bank = (*cur_bank&0x1) | 0x2; + LastRegIdx = reg->rIdx; + } + return old_bank != *cur_bank; + } + + } else if (PCI(pc)->op == POC_BANKSEL) { + int old_bank = *cur_bank; + *cur_bank = (PCOR(PCI(pc)->pcop)->r->isExtern) ? 'E' : 'L'; + LastRegIdx = reg->rIdx; + return old_bank != *cur_bank; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* Set bank selection if necessary */ +/*-----------------------------------------------------------------*/ +static int DoBankSelect(pCode *pc, int cur_bank) { + pCode *pcprev; + regs *reg; + + if(!isPCI(pc)) + return cur_bank; + + if (isCALL(pc)) { + pCode *pcf = findFunction(get_op_from_instruction(PCI(pc))); + if (pcf && isPCF(pcf)) { + pCode *pcfr; + int rbank = 'U'; // Undetermined + FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done + // Check all the returns to work out what bank is selected + for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) { + if (isPCI(pcfr)) { + if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) { + if (rbank == 'U') + rbank = PCFL(pcfr)->lastBank; + else + if (rbank != PCFL(pcfr)->lastBank) + return -1; // Unknown bank - multiple returns with different banks + } + } + } + if (rbank == 'U') + return -1; // Unknown bank + return rbank; + } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) { + /* Extern functions may use registers in different bank - must call banksel */ + return -1; /* Unknown bank */ + } + } + + if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) { + return -1; /* New bank unknown - linkers choice. */ + } + + reg = getRegFromInstruction(pc); + if (reg) { - if( ( (reg && REG_BANK(reg)!=cur_bank) || - ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) && - (!isPCI_LIT(pc)) ){ + if (IsBankChange(pc,reg,&cur_bank)) + return cur_bank; + + if (!isPCI_LIT(pc)) { /* Examine the instruction before this one to make sure it is * not a skip type instruction */ pcprev = findPrevpCode(pc->prev, PC_OPCODE); if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) { - int b; - int reg_bank; + cur_bank = BankSelect(PCI(pc),cur_bank,reg); + } else { + cur_bank = BankSelect(PCI(pcprev),cur_bank,reg); + } + if (!PCI(pc)->pcflow) + fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id); + else + PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */ + } + } + return cur_bank; +} - reg_bank = (reg) ? REG_BANK(reg) : 0; - - b = cur_bank ^ reg_bank; +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +/* +static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank) +{ + pCode *pc=NULL; + pCode *pcprev=NULL; - //fprintf(stderr, "Cool! can switch banks\n"); - cur_bank = reg_bank; - switch(b & 3) { - case 0: - break; - case 1: - insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT); - break; - case 2: - insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT); - insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT); - break; - case 3: - if(cur_bank & 3) { - insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT); - insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT); - } else - insertBankSwitch(0, pc, -1, -1); - break; + if(!pcfl) + return; - } + pc = findNextInstruction(pcfl->pc.next); - } else { - //fprintf(stderr, "Bummer can't switch banks\n"); - ; - } - } + while(isPCinFlow(pc,PCODE(pcfl))) { + cur_bank = DoBankSelect(pc,cur_bank); pcprev = pc; pc = findNextInstruction(pc->next); } if(pcprev && cur_bank) { - /* Brute force - make sure that we point to bank 0 at the - * end of each flow block */ - new_pc = newpCode(POC_BCF, - popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT)); - pCodeInsertAfter(pcprev, new_pc); - cur_bank = 0; + // Set bank state to unknown at the end of each flow block + cur_bank = -1; } } - +*/ /*-----------------------------------------------------------------*/ /*int compareBankFlow - compare the banking requirements between */ /* flow objects. */ /*-----------------------------------------------------------------*/ +/* int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom) { @@ -4100,17 +4602,19 @@ int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom) pcflow->FromConflicts++; } - /* + / * fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n", pcflowLink->pcflow->pc.seq, pcflowLink->pcflow->FromConflicts, pcflowLink->pcflow->ToConflicts); - */ + * / return 1; } +*/ /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ +/* void FixBankFlow(pBlock *pb) { pCode *pc=NULL; @@ -4126,11 +4630,11 @@ void FixBankFlow(pBlock *pb) pcflow = findNextpCode(pb->pcHead, PC_FLOW); - /* + / * First loop through all of the flow objects in this pcode block and fix the ones that have banking conflicts between the entry and exit. - */ + * / //fprintf(stderr, "FixBankFlow - Phase 1\n"); @@ -4196,10 +4700,10 @@ void FixBankFlow(pBlock *pb) if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) { //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts); - FixRegisterBankingInFlow(PCFL(pcflow),0); + FixRegisterBankingInFlow(PCFL(pcflow),-1); BanksUsedFlow2(pcflow); - continue; /* Don't need to check the flow from here - it's already been fixed */ + continue; / * Don't need to check the flow from here - it's already been fixed * / } @@ -4224,15 +4728,15 @@ void FixBankFlow(pBlock *pb) if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) { //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts); - FixRegisterBankingInFlow(PCFL(pcflow),0); + FixRegisterBankingInFlow(PCFL(pcflow),-1); BanksUsedFlow2(pcflow); } } - /* + / * Loop through the flow objects again and find the ones with the maximum conflicts - */ + * / for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); pcflow != NULL; @@ -4244,7 +4748,7 @@ void FixBankFlow(pBlock *pb) if(PCFL(pcflow)->FromConflicts > max_FromConflicts) pcflow_max_From = pcflow; } -/* +/ * if(pcflow_max_To) fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n", PCFL(pcflow_max_To)->pc.seq, @@ -4254,8 +4758,9 @@ void FixBankFlow(pBlock *pb) fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n", PCFL(pcflow_max_From)->pc.seq, PCFL(pcflow_max_From)->FromConflicts); -*/ +* / } +*/ /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ @@ -4450,9 +4955,9 @@ void pBlockRemoveUnusedLabels(pBlock *pb) for(pc = pb->pcHead; pc; pc = pc->next) { - if(isPCL(pc)) // pc->type == PC_LABEL) + if(isPCL(pc)) // Label pcode pcl = PCL(pc); - else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label) + else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label pcl = PCL(PCI(pc)->label->pc); else continue; @@ -4601,200 +5106,93 @@ pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval) } - -#if 0 -/*-----------------------------------------------------------------*/ -/*-----------------------------------------------------------------*/ -int InstructionRegBank(pCode *pc) -{ - regs *reg; - - if( (reg = getRegFromInstruction(pc)) == NULL) - return -1; - - return REG_BANK(reg); - -} -#endif - /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ -void FixRegisterBanking(pBlock *pb) +static void FixRegisterBanking(pBlock *pb,int cur_bank) { - pCode *pc=NULL; - pCode *pcprev=NULL; - - int cur_bank; - regs *reg; + pCode *pc; + int firstBank = 'U'; if(!pb) return; - //pc = findNextpCode(pb->pcHead, PC_FLOW); - pc = findNextpCode(pb->pcHead, PC_OPCODE); - if(!pc) + for (pc=pb->pcHead; pc; pc=pc->next) { + if (isPCFL(pc)) { + firstBank = PCFL(pc)->firstBank; + break; + } + } + if (firstBank != 'U') { + /* This block has already been done */ + if (firstBank != cur_bank) { + /* This block has started with a different bank - must adjust it */ + if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */ + while (pc) { + if (isPCI(pc)) { + regs *reg = getRegFromInstruction(pc); + if (reg) { + DoBankSelect(pc,cur_bank); + } + } + pc = pc->next; + } + } + } return; - /* loop through all of the flow blocks with in one pblock */ - - //fprintf(stderr,"Register banking\n"); - cur_bank = 0; - do { - /* at this point, pc should point to a PC_FLOW object */ - - - /* for each flow block, determine the register banking - requirements */ - - // do { - if(isPCI(pc)) { - //genericPrint(stderr, pc); - - reg = getRegFromInstruction(pc); -#if 0 - if(reg) { - fprintf(stderr, " %s ",reg->name); - fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n", - reg->address,REG_BANK(reg),reg->isBitField); - - } -#endif - - if( ( (reg && REG_BANK(reg)!=cur_bank) || - ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) && - (!isPCI_LIT(pc)) ){ - - - /* Examine the instruction before this one to make sure it is - * not a skip type instruction */ - pcprev = findPrevpCode(pc->prev, PC_OPCODE); - - if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) { - int b; - int reg_bank; - - reg_bank = (reg) ? REG_BANK(reg) : 0; - - b = cur_bank ^ reg_bank; - - cur_bank = reg_bank; - switch(b & 3) { - case 0: - break; - case 1: - insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT); - break; - case 2: - insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT); - insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT); - break; - case 3: - if(cur_bank & 3) { - insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT); - insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT); - } else - insertBankSwitch(0, pc, -1, -1); - break; - - } - - }else { - //fprintf(stderr, "Bummer can't switch banks\n"); - ; - } - } + } - pcprev = pc; + /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */ + LastRegIdx = -1; + cur_bank = -1; + for (pc=pb->pcHead; pc; pc=pc->next) { + if (isPCFL(pc)) { + PCFL(pc)->firstBank = cur_bank; + continue; + } + cur_bank = DoBankSelect(pc,cur_bank); + } + /* Trace through branches and set the bank selection as required. */ + LastRegIdx = -1; + cur_bank = -1; + for (pc=pb->pcHead; pc; pc=pc->next) { + if (isPCFL(pc)) { + PCFL(pc)->firstBank = cur_bank; + continue; + } + if (isPCI(pc)) { + if (PCI(pc)->op == POC_GOTO) { + int lastRegIdx = LastRegIdx; + pCode *pcb = pc; + /* Trace through branch */ + pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop)); + while (pcl) { + if (isPCI(pcl)) { + regs *reg = getRegFromInstruction(pcl); + if (reg) { + int bankUnknown = -1; + if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */ + break; + if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */ + break; + } + } + pcl = pcl->next; + } + LastRegIdx = lastRegIdx; + } else { + /* Keep track out current bank */ + regs *reg = getRegFromInstruction(pc); + if (reg) + IsBankChange(pc,reg,&cur_bank); } - - pc = pc->next; - // } while(pc && !(isPCFL(pc))); - - - }while (pc); - - if(pcprev && cur_bank) { - - int pos = 1; /* Assume that the bank swithc instruction(s) - * are inserted after this instruction */ - - if((PCI(pcprev)->op == POC_RETLW) || - (PCI(pcprev)->op == POC_RETURN) || - (PCI(pcprev)->op == POC_RETFIE)) { - - /* oops, a RETURN - we need to switch banks *before* the RETURN */ - - pos = 0; - - } - - /* Brute force - make sure that we point to bank 0 at the - * end of each flow block */ - - switch(cur_bank & 3) { - case 0: - break; - case 1: - insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT); - break; - case 2: - insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT); - insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT); - break; - case 3: - insertBankSwitch(pos, pcprev, -1, -1); - break; - } -/* - new_pc = newpCode(POC_BCF, - popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT)); - pCodeInsertAfter(pcprev, new_pc); -*/ - cur_bank = 0; - //fprintf(stderr, "Brute force switch\n"); } - } - - -#if 0 - if(reg && REG_BANK(reg)!=cur_bank) { - //fprintf(stderr,"need to switch banks\n"); - /* Examine the instruction before this one to make sure it is - * not a skip type instruction */ - pcprev = findPrevpCode(pc->prev, PC_OPCODE); - if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) { - int b = cur_bank ^ REG_BANK(reg); - - cur_bank = REG_BANK(reg); - - switch(b & 3) { - case 0: - break; - case 1: - insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT); - break; - case 2: - insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT); - insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT); - break; - case 3: - if(cur_bank & 3) { - insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT); - insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT); - } else - insertBankSwitch(0, pc, -1, -1); - break; - - } -#endif - - - - +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ void pBlockDestruct(pBlock *pb) { @@ -4926,8 +5324,8 @@ void AnalyzeFlow(int level) * to determine the Register Banks they use */ - for(pb = the_pFile->pbHead; pb; pb = pb->next) - FixBankFlow(pb); +// for(pb = the_pFile->pbHead; pb; pb = pb->next) +// FixBankFlow(pb); for(pb = the_pFile->pbHead; pb; pb = pb->next) @@ -4945,7 +5343,8 @@ void AnalyzeFlow(int level) for(pb = the_pFile->pbHead; pb; pb = pb->next) DumpFlow(pb); */ - /* debug stuff */ + /* debug stuff */ +/* for(pb = the_pFile->pbHead; pb; pb = pb->next) { pCode *pcflow; for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); @@ -4955,7 +5354,7 @@ void AnalyzeFlow(int level) FillFlow(PCFL(pcflow)); } } - +*/ /* for(pb = the_pFile->pbHead; pb; pb = pb->next) { pCode *pcflow; @@ -4997,16 +5396,13 @@ void AnalyzeBanking(void) AnalyzeFlow(0); AnalyzeFlow(1); +// for(pb = the_pFile->pbHead; pb; pb = pb->next) +// BanksUsedFlow(pb); for(pb = the_pFile->pbHead; pb; pb = pb->next) - BanksUsedFlow(pb); - for(pb = the_pFile->pbHead; pb; pb = pb->next) - FixRegisterBanking(pb); + FixRegisterBanking(pb,-1); // cur_bank is unknown } -// Undefine REUSE_GPR in files pcode.c & device.c to prevent local function registers being reused. -#define REUSE_GPR -#ifdef REUSE_GPR /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ DEFSETFUNC (resetrIdx) @@ -5017,11 +5413,27 @@ DEFSETFUNC (resetrIdx) return 0; } -pCode *findFunction(char *fname); +/*-----------------------------------------------------------------*/ +/* InitRegReuse - Initialises variables for code analyzer */ +/*-----------------------------------------------------------------*/ + +void InitReuseReg(void) +{ + /* Find end of statically allocated variables for start idx */ + unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */ + regs *r; + for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) { + if (r->type != REG_SFR) { + maxIdx += r->size; /* Increment for all statically allocated variables */ + } + } + peakIdx = maxIdx; + applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */ +} /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ -unsigned register_reassign(pBlock *pb, unsigned idx) +static unsigned register_reassign(pBlock *pb, unsigned idx) { pCode *pc; @@ -5030,6 +5442,8 @@ unsigned register_reassign(pBlock *pb, unsigned idx) if(!pc) return idx; + pb->visited = 1; + DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname)); if (pb->tregisters) { @@ -5040,6 +5454,7 @@ unsigned register_reassign(pBlock *pb, unsigned idx) if (r->rIdx < (int)idx) { char s[20]; r->rIdx = idx++; + if (peakIdx < idx) peakIdx = idx; sprintf(s,"r0x%02X", r->rIdx); DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s)); free(r->name); @@ -5065,56 +5480,47 @@ unsigned register_reassign(pBlock *pb, unsigned idx) return idx; } -/*-----------------------------------------------------------------*/ -/* Re-allocate the GPR for optimum reuse for a given pblock */ -/* eg if a function m() calls function f1() and f2(), where f1 */ -/* allocates a local variable vf1 and f2 allocates a local */ -/* variable vf2. Then providing f1 and f2 do not call each other */ -/* they may share the same general purpose registers for vf1 and */ -/* vf2. */ -/* This is done by first setting the the regs rIdx to start after */ -/* all the global variables, then walking through the call tree */ -/* renaming the registers to match their new idx and incrementng */ -/* it as it goes. If a function has already been called it will */ -/* only rename the registers if it has already used up those */ -/* registers ie rIdx of the function's registers is lower than the */ -/* current rIdx. That way the register will not be reused while */ -/* still being used by an eariler function call. */ -/*-----------------------------------------------------------------*/ -void register_reusage(pBlock *mainPb) -{ - static int exercised = 0; - if (!exercised) { /* Only do this once */ - /* Find end of statically allocated variables for start idx */ - unsigned idx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */ - regs *r; - for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) { - if (r->type != REG_SFR) { - idx += r->size; /* Increment for all statically allocated variables */ - } - } - - applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */ - - if (mainPb) - idx = register_reassign(mainPb,idx); /* Do main and all the functions that are called from it. */ - idx = register_reassign(the_pFile->pbHead,idx); /* Do the other functions such as interrupts. */ +/*------------------------------------------------------------------*/ +/* ReuseReg were call tree permits */ +/* */ +/* Re-allocate the GPR for optimum reuse for a given pblock */ +/* eg if a function m() calls function f1() and f2(), where f1 */ +/* allocates a local variable vf1 and f2 allocates a local */ +/* variable vf2. Then providing f1 and f2 do not call each other */ +/* they may share the same general purpose registers for vf1 and */ +/* vf2. */ +/* This is done by first setting the the regs rIdx to start after */ +/* all the global variables, then walking through the call tree */ +/* renaming the registers to match their new idx and incrementng */ +/* it as it goes. If a function has already been called it will */ +/* only rename the registers if it has already used up those */ +/* registers ie rIdx of the function's registers is lower than the */ +/* current rIdx. That way the register will not be reused while */ +/* still being used by an eariler function call. */ +/* */ +/* Note for this to work the fucntions need to be declared static. */ +/* */ +/*------------------------------------------------------------------*/ +void ReuseReg(void) +{ + pBlock *pb; + InitReuseReg(); + for(pb = the_pFile->pbHead; pb; pb = pb->next) { + /* Non static functions can be called from other modules so their registers must reassign */ + if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited)) + register_reassign(pb,peakIdx); } - exercised++; } -#endif // REUSE_GPR /*-----------------------------------------------------------------*/ /* buildCallTree - look at the flow and extract all of the calls */ /* */ /*-----------------------------------------------------------------*/ -set *register_usage(pBlock *pb); - void buildCallTree(void ) { pBranch *pbr; - pBlock *pb, *mainPb = 0; + pBlock *pb; pCode *pc; if(!the_pFile) @@ -5157,7 +5563,6 @@ void buildCallTree(void ) //fprintf(stderr," found main \n"); pb->cmemmap = NULL; /* FIXME do we need to free ? */ pb->dbName = 'M'; - mainPb = pb; } pbr = Safe_calloc(1,sizeof(pBranch)); @@ -5182,22 +5587,6 @@ void buildCallTree(void ) } } } - -#ifdef REUSE_GPR - register_reusage(mainPb); /* Comment out this line to prevent local function registers being reused. Note from this point onwards finding a GPR by its rIdx value will no longer work.*/ -#endif // REUSE_GPR - - /* Re-allocate the registers so that there are no collisions - * between local variables when one function call another */ - - // this is weird... - // pic14_deallocateAllRegs(); - - for(pb = the_pFile->pbHead; pb; pb = pb->next) { - if(!pb->visited) - register_usage(pb); - } - } /*-----------------------------------------------------------------*/ @@ -5234,14 +5623,12 @@ void AnalyzepCode(char dbName) do { DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1)); - //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1); /* First, merge the labels with the instructions */ for(pb = the_pFile->pbHead; pb; pb = pb->next) { if('*' == dbName || getpBlock_dbName(pb) == dbName) { DFPRINTF((stderr," analyze and merging block %c\n",dbName)); - //fprintf(stderr," analyze and merging block %c\n",dbName); pBlockMergeLabels(pb); AnalyzepBlock(pb); } else { @@ -5307,8 +5694,10 @@ void MarkUsedRegisters(set *regset) for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) { r2 = pic14_regWithIdx(r1->rIdx); - r2->isFree = 0; - r2->wasUsed = 1; + if (r2) { + r2->isFree = 0; + r2->wasUsed = 1; + } } } @@ -5379,13 +5768,14 @@ static void sequencepCode(void) /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ +/* set *register_usage(pBlock *pb) { pCode *pc,*pcn; set *registers=NULL; set *registersInCallPath = NULL; - /* check recursion */ + / * check recursion * / pc = setFirstItem(pb->function_entries); @@ -5419,9 +5809,9 @@ set *register_usage(pBlock *pb) MarkUsedRegisters(pb->tregisters); if(registersInCallPath) { - /* registers were used in the functions this pBlock has called */ - /* so now, we need to see if these collide with the ones we are */ - /* using here */ + / * registers were used in the functions this pBlock has called * / + / * so now, we need to see if these collide with the ones we are * / + / * using here * / regs *r1,*r2, *newreg; @@ -5429,44 +5819,42 @@ set *register_usage(pBlock *pb) r1 = setFirstItem(registersInCallPath); while(r1) { + if (r1->type != REG_STK) { + r2 = setFirstItem(pb->tregisters); - r2 = setFirstItem(pb->tregisters); - - while(r2 && (r1->type != REG_STK)) { + while(r2 && (r2->type != REG_STK)) { - if(r2->rIdx == r1->rIdx) { - newreg = pic14_findFreeReg(REG_GPR); + if(r2->rIdx == r1->rIdx) { + newreg = pic14_findFreeReg(REG_GPR); - if(!newreg) { - DFPRINTF((stderr,"Bummer, no more registers.\n")); - exit(1); - } + if(!newreg) { + DFPRINTF((stderr,"Bummer, no more registers.\n")); + exit(1); + } - DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n", - r1->rIdx, newreg->rIdx)); - r2->rIdx = newreg->rIdx; - //if(r2->name) free(r2->name); - if(newreg->name) - r2->name = Safe_strdup(newreg->name); - else - r2->name = NULL; - newreg->isFree = 0; - newreg->wasUsed = 1; - } - r2 = setNextItem(pb->tregisters); + DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n", + r1->rIdx, newreg->rIdx)); + r2->rIdx = newreg->rIdx; + if(newreg->name) + r2->name = Safe_strdup(newreg->name); + else + r2->name = NULL; + newreg->isFree = 0; + newreg->wasUsed = 1; + } + r2 = setNextItem(pb->tregisters); + } } r1 = setNextItem(registersInCallPath); } - /* Collisions have been resolved. Now free the registers in the call path */ + / * Collisions have been resolved. Now free the registers in the call path * / r1 = setFirstItem(registersInCallPath); while(r1) { - if(r1->type != REG_STK) { newreg = pic14_regWithIdx(r1->rIdx); - newreg->isFree = 1; - } + if (newreg) newreg->isFree = 1; r1 = setNextItem(registersInCallPath); } @@ -5486,6 +5874,7 @@ set *register_usage(pBlock *pb) return registers; } +*/ /*-----------------------------------------------------------------*/ /* printCallTree - writes the call tree to a file */ @@ -5613,80 +6002,89 @@ void InlineFunction(pBlock *pb) if(isCALL(pc)) { pCode *pcn = findFunction(get_op_from_instruction(PCI(pc))); + pCode *pcp = pc->prev; pCode *pct; pCode *pce; pBranch *pbr; - if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) { - - //fprintf(stderr,"Cool can inline:\n"); - //pcn->print(stderr,pcn); + if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1) && !PCF(pcn)->isPublic && (pcp && (isPCI_BITSKIP(pcp)||!isPCI_SKIP(pcp)))) { /* Bit skips can be inverted other skips can not */ - //fprintf(stderr,"recursive call Inline\n"); - InlineFunction(pcn->pb); - //fprintf(stderr,"return from recursive call Inline\n"); + InlineFunction(pcn->pb); - /* - At this point, *pc points to a CALL mnemonic, and - *pcn points to the function that is being called. + /* + At this point, *pc points to a CALL mnemonic, and + *pcn points to the function that is being called. - To in-line this call, we need to remove the CALL - and RETURN(s), and link the function pCode in with - the CALLee pCode. + To in-line this call, we need to remove the CALL + and RETURN(s), and link the function pCode in with + the CALLee pCode. - */ + */ + pc_call = pc; - /* Remove the CALL */ - pc_call = pc; - pc = pc->prev; + /* Check if previous instruction was a bit skip */ + if (isPCI_BITSKIP(pcp)) { + pCodeLabel *pcl; + /* Invert skip instruction and add a goto */ + PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS; - /* remove callee pBlock from the pBlock linked list */ - removepBlock(pcn->pb); - - pce = pcn; - while(pce) { - pce->pb = pb; - pce = pce->next; - } - - /* Remove the Function pCode */ - pct = findNextInstruction(pcn->next); + if(isPCL(pc_call->next)) { // Label pcode + pcl = PCL(pc_call->next); + } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label + pcl = PCL(PCI(pc_call->next)->label->pc); + } else { + pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100)); + PCI(pc_call->next)->label->pc = (struct pCode*)pcl; + } + pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR))); + } - /* Link the function with the callee */ - pc->next = pcn->next; - pcn->next->prev = pc; - - /* Convert the function name into a label */ + /* remove callee pBlock from the pBlock linked list */ + removepBlock(pcn->pb); - pbr = Safe_calloc(1,sizeof(pBranch)); - pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1); - pbr->next = NULL; - PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr); - PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label); - - /* turn all of the return's except the last into goto's */ - /* check case for 2 instruction pBlocks */ - pce = findNextInstruction(pcn->next); - while(pce) { - pCode *pce_next = findNextInstruction(pce->next); - - if(pce_next == NULL) { - /* found the last return */ - pCode *pc_call_next = findNextInstruction(pc_call->next); - - //fprintf(stderr,"found last return\n"); - //pce->print(stderr,pce); - pce->prev->next = pc_call->next; - pc_call->next->prev = pce->prev; - PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label, - PCI(pce)->label); - } + pce = pcn; + while(pce) { + pce->pb = pb; + pce = pce->next; + } - pce = pce_next; - } + /* Remove the Function pCode */ + pct = findNextInstruction(pcn->next); + + /* Link the function with the callee */ + if (pcp) pcp->next = pcn->next; + pcn->next->prev = pcp; + + /* Convert the function name into a label */ + + pbr = Safe_calloc(1,sizeof(pBranch)); + pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1); + pbr->next = NULL; + PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr); + PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label); + + /* turn all of the return's except the last into goto's */ + /* check case for 2 instruction pBlocks */ + pce = findNextInstruction(pcn->next); + while(pce) { + pCode *pce_next = findNextInstruction(pce->next); + + if(pce_next == NULL) { + /* found the last return */ + pCode *pc_call_next = findNextInstruction(pc_call->next); + + //fprintf(stderr,"found last return\n"); + //pce->print(stderr,pce); + pce->prev->next = pc_call->next; + pc_call->next->prev = pce->prev; + PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label, + PCI(pce)->label); + } + pce = pce_next; + } } } else diff --git a/src/pic/pcode.h b/src/pic/pcode.h index 1c3a024f..063437ca 100644 --- a/src/pic/pcode.h +++ b/src/pic/pcode.h @@ -219,7 +219,11 @@ typedef enum POC_TRIS, POC_XORLW, POC_XORWF, - POC_XORFW + POC_XORFW, + POC_BANKSEL, + POC_PAGESEL, + + MAX_PIC14MNEMONICS } PIC_OPCODE; @@ -357,6 +361,12 @@ typedef struct pCodeOpRegPtr } pCodeOpRegPtr; +typedef struct pCodeOpStr /* Only used here for the name of fn being called or jumped to */ +{ + pCodeOp pcop; + unsigned isPublic: 1; /* True if not static ie extern */ +} pCodeOpStr; + typedef struct pCodeOpWild { pCodeOp pcop; @@ -389,6 +399,7 @@ typedef struct pCode struct pCode *prev; // The pCode objects are linked together struct pCode *next; // in doubly linked lists. + unsigned id; // unique ID number for all pCodes to assist in debugging int seq; // sequence number struct pBlock *pb; // The pBlock that contains this pCode. @@ -572,7 +583,8 @@ typedef struct pCodeFunction pBranch *to; // pCodes that execute after pBranch *label; // pCode instructions that have labels - int ncalled; /* Number of times function is called */ + int ncalled; /* Number of times function is called */ + unsigned isPublic:1; /* True if the fn is not static and can be called from another module (ie a another c or asm file) */ } pCodeFunction; @@ -758,31 +770,38 @@ typedef struct peepCommand { #define PCOLAB(x) ((pCodeOpLabel *)(x)) #define PCOR(x) ((pCodeOpReg *)(x)) #define PCORB(x) ((pCodeOpRegBit *)(x)) +#define PCOS(x) ((pCodeOpStr *)(x)) #define PCOW(x) ((pCodeOpWild *)(x)) #define PBR(x) ((pBranch *)(x)) #define PCWB(x) ((pCodeWildBlock *)(x)) +#define isPCOLAB(x) ((PCOP(x)->type) == PO_LABEL) +#define isPCOS(x) ((PCOP(x)->type) == PO_STR) + /* macros for checking pCode types */ #define isPCI(x) ((PCODE(x)->type == PC_OPCODE)) -#define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isBranch) -#define isPCI_SKIP(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip) -#define isPCI_LIT(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isLit) -#define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip && PCI(x)->isBitInst) #define isPCFL(x) ((PCODE(x)->type == PC_FLOW)) #define isPCF(x) ((PCODE(x)->type == PC_FUNCTION)) #define isPCL(x) ((PCODE(x)->type == PC_LABEL)) #define isPCW(x) ((PCODE(x)->type == PC_WILD)) #define isPCCS(x) ((PCODE(x)->type == PC_CSOURCE)) -#define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL)) -#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS) +/* + macros for checking pCodeInstruction types +*/ +#define isCALL(x) (isPCI(x) && (PCI(x)->op == POC_CALL)) +#define isPCI_BRANCH(x) (isPCI(x) && PCI(x)->isBranch) +#define isPCI_SKIP(x) (isPCI(x) && PCI(x)->isSkip) +#define isPCI_LIT(x) (isPCI(x) && PCI(x)->isLit) +#define isPCI_BITSKIP(x)(isPCI_SKIP(x) && PCI(x)->isBitInst) -#define isPCOLAB(x) ((PCOP(x)->type) == PO_LABEL) + +#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS) /*-----------------------------------------------------------------* * pCode functions. @@ -791,9 +810,13 @@ typedef struct peepCommand { pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop); // Create a new pCode given an operand pCode *newpCodeCharP(char *cP); // Create a new pCode given a char * pCode *newpCodeInlineP(char *cP); // Create a new pCode given a char * -pCode *newpCodeFunction(char *g, char *f); // Create a new function +pCode *newpCodeFunction(char *g, char *f,int); // Create a new function pCode *newpCodeLabel(char *name,int key); // Create a new label given a key pCode *newpCodeCSource(int ln, char *f, char *l); // Create a new symbol line +pCode *findNextInstruction(pCode *pci); +pCode *findNextpCode(pCode *pc, PC_TYPE pct); +pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert); + pBlock *newpCodeChain(memmap *cm,char c, pCode *pc); // Create a new pBlock void printpBlock(FILE *of, pBlock *pb); // Write a pBlock to a file void printpCode(FILE *of, pCode *pc); // Write a pCode to a file @@ -806,6 +829,9 @@ int OptimizepCode(char dbName); void printCallTree(FILE *of); void pCodePeepInit(void); void pBlockConvert2ISR(pBlock *pb); +void pCodeInsertAfter(pCode *pc1, pCode *pc2); +void pCodeInsertBefore(pCode *pc1, pCode *pc2); +void pCodeDeleteChain(pCode *f,pCode *t); pCodeOp *newpCodeOpLabel(char *name, int key); pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space,int is_func); @@ -814,9 +840,8 @@ pCodeOp *newpCodeOpBit(char *name, int bit,int inBitSpace); pCodeOp *newpCodeOpRegFromStr(char *name); pCodeOp *newpCodeOp(char *name, PIC_OPTYPE p); pCodeOp *pCodeOpCopy(pCodeOp *pcop); +pCodeOp *popCopyReg(pCodeOpReg *pc); -pCode * findNextInstruction(pCode *pci); -pCode * findNextpCode(pCode *pc, PC_TYPE pct); int isPCinFlow(pCode *pc, pCode *pcflow); struct regs * getRegFromInstruction(pCode *pc); @@ -832,7 +857,6 @@ extern pCodeOpReg pc_indf; extern pCodeOpReg pc_fsr; extern pCodeOpReg pc_pcl; extern pCodeOpReg pc_pclath; -extern pCodeOpReg pc_kzero; extern pCodeOpReg pc_wsave; /* wsave, ssave and psave are used to save W, the Status and PCLATH*/ extern pCodeOpReg pc_ssave; /* registers during an interrupt */ extern pCodeOpReg pc_psave; /* registers during an interrupt */ diff --git a/src/pic/pcodepeep.c b/src/pic/pcodepeep.c index 4330c03f..4a37e7d1 100644 --- a/src/pic/pcodepeep.c +++ b/src/pic/pcodepeep.c @@ -1663,7 +1663,7 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd) /* If the opcodes don't match then the line doesn't match */ if(PCI(pcs)->op != PCI(pcd)->op) - return 0; + return 0; #ifdef PCODE_DEBUG DFPRINTF((stderr,"%s comparing\n",__FUNCTION__)); @@ -1672,39 +1672,78 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd) #endif if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) - return 0; + return 0; /* Compare the operands */ if(PCI(pcd)->pcop) { - if (PCI(pcd)->pcop->type == PO_WILD) { - index = PCOW(PCI(pcd)->pcop)->id; - //DFPRINTF((stderr,"destination is wild\n")); + // Volatile types should not be deleted or modified, these include SFR, externs and publics + // They can be used as a matched, however if a match is found then the optimiser intends + // to change some aspect of a block of code, which is most likely a critcal one. As this + // method of optimisation does not allow a means to distiguishing what may change, it is + // best to just negate any match. + if (PCI(pcs)->pcop) { + struct regs *r; + pCodeOp *pcop = PCI(pcs)->pcop; + switch(pcop->type) { + case PO_W: + case PO_STATUS: + case PO_FSR: + case PO_INDF: + case PO_INTCON: + case PO_PCL: + case PO_PCLATH: + case PO_SFR_REGISTER: + return 0; // SFR - do not modify + case PO_DIR: + case PO_GPR_REGISTER: + case PO_GPR_BIT: + case PO_GPR_TEMP: + case PO_GPR_POINTER: + r = PCOR(pcop)->r; + if (r->isPublic||r->isExtern||r->isFixed) // Changes to these types of registers should not be changed as they may be used else where + return 0; + default: + break; + } + } + if (PCI(pcd)->pcop->type == PO_WILD) { + char *n; + index = PCOW(PCI(pcd)->pcop)->id; + //DFPRINTF((stderr,"destination is wild\n")); #ifdef DEBUG_PCODEPEEP - if (index > peepBlock->nops) { - DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__)); - exit(1); - } + if (index > peepBlock->nops) { + DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__)); + exit(1); + } #endif - - PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop; - if(!peepBlock->target.wildpCodeOps[index]) { - peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop; - - //fprintf(stderr, "first time for wild opcode #%d\n",index); - return 1; - - } else { - /* - pcs->print(stderr,pcs); - pcd->print(stderr,pcd); - fprintf(stderr, "comparing operands of these instructions, result %d\n", - pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]) - ); - */ - - return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]); - } - + n = PCI(pcs)->pcop->name; + if(peepBlock->target.vars[index]) { + if ((!n)||(strcmp(peepBlock->target.vars[index],n) != 0)) + return 0; // variable is different + } else { + DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n)); + peepBlock->target.vars[index] = n; + } + + PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop; + if(!peepBlock->target.wildpCodeOps[index]) { + peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop; + + //fprintf(stderr, "first time for wild opcode #%d\n",index); + return 1; + + } else { + /* + pcs->print(stderr,pcs); + pcd->print(stderr,pcd); + fprintf(stderr, "comparing operands of these instructions, result %d\n", + pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]) + ); + */ + + return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]); + } +/* { char *n; @@ -1728,30 +1767,30 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd) return 1; } } - - } else if (PCI(pcd)->pcop->type == PO_LITERAL) { - /* - pcs->print(stderr,pcs); - pcd->print(stderr,pcd); - - fprintf(stderr, "comparing literal operands of these instructions, result %d\n", - pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop)); - */ - return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop); - - } else { - /* FIXME - need an else to check the case when the destination - * isn't a wild card */ - /* - fprintf(stderr, "Destination is not wild: operand compare =%d\n", - pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop)); - */ - return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop); - - } +*/ + } else if (PCI(pcd)->pcop->type == PO_LITERAL) { + /* + pcs->print(stderr,pcs); + pcd->print(stderr,pcd); + + fprintf(stderr, "comparing literal operands of these instructions, result %d\n", + pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop)); + */ + return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop); + + } else { + /* FIXME - need an else to check the case when the destination + * isn't a wild card */ + /* + fprintf(stderr, "Destination is not wild: operand compare =%d\n", + pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop)); + */ + return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop); + + } } else - /* The pcd has no operand. Lines match if pcs has no operand either*/ - return (PCI(pcs)->pcop == NULL); + /* The pcd has no operand. Lines match if pcs has no operand either*/ + return (PCI(pcs)->pcop == NULL); } } @@ -1791,23 +1830,23 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd) if(PCW(pcd)->operand) { PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop; if(peepBlock->target.vars[index]) { - int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0); + int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0); #ifdef PCODE_DEBUG - if(i) - DFPRINTF((stderr," (matched)\n")); - else { - DFPRINTF((stderr," (no match: wild card operand mismatch\n")); - DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n", - peepBlock->target.vars[index], - PCI(pcs)->pcop->name)); - } + if(i) + DFPRINTF((stderr," (matched)\n")); + else { + DFPRINTF((stderr," (no match: wild card operand mismatch\n")); + DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n", + peepBlock->target.vars[index], + PCI(pcs)->pcop->name)); + } #endif - return i; + return i; } else { - DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name)); - peepBlock->target.vars[index] = PCI(pcs)->pcop->name; - return 1; + DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name)); + peepBlock->target.vars[index] = PCI(pcs)->pcop->name; + return 1; } } @@ -1858,195 +1897,6 @@ void pCodePeepClrVars(pCodePeep *pcp) } -/*-----------------------------------------------------------------*/ -/* pCodeInsertAfter - splice in the pCode chain starting with pc2 */ -/* into the pCode chain containing pc1 */ -/*-----------------------------------------------------------------*/ -void pCodeInsertAfter(pCode *pc1, pCode *pc2) -{ - - if(!pc1 || !pc2) - return; - - pc2->next = pc1->next; - if(pc1->next) - pc1->next->prev = pc2; - - pc2->pb = pc1->pb; - pc2->prev = pc1; - pc1->next = pc2; - -} - -/*------------------------------------------------------------------*/ -/* pCodeInsertBefore - splice in the pCode chain starting with pc2 */ -/* into the pCode chain containing pc1 */ -/*------------------------------------------------------------------*/ -void pCodeInsertBefore(pCode *pc1, pCode *pc2) -{ - - if(!pc1 || !pc2) - return; - - pc2->prev = pc1->prev; - if(pc1->prev) - pc1->prev->next = pc2; - - pc2->pb = pc1->pb; - pc2->next = pc1; - pc1->prev = pc2; - -} - -/*-----------------------------------------------------------------*/ -/* pCodeOpCopy - copy a pcode operator */ -/*-----------------------------------------------------------------*/ -pCodeOp *pCodeOpCopy(pCodeOp *pcop) -{ - pCodeOp *pcopnew=NULL; - - if(!pcop) - return NULL; - - switch(pcop->type) { - case PO_CRY: - case PO_BIT: - //DFPRINTF((stderr,"pCodeOpCopy bit\n")); - pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) ); - PCORB(pcopnew)->bit = PCORB(pcop)->bit; - PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace; - - break; - - case PO_WILD: - /* Here we expand the wild card into the appropriate type: */ - /* By recursively calling pCodeOpCopy */ - //DFPRINTF((stderr,"pCodeOpCopy wild\n")); - if(PCOW(pcop)->matched) - pcopnew = pCodeOpCopy(PCOW(pcop)->matched); - else { - // Probably a label - pcopnew = pCodeOpCopy(PCOW(pcop)->subtype); - pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]); - //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name)); - } - - return pcopnew; - break; - - case PO_LABEL: - //DFPRINTF((stderr,"pCodeOpCopy label\n")); - pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) ); - PCOLAB(pcopnew)->key = PCOLAB(pcop)->key; - break; - - case PO_IMMEDIATE: - pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) ); - PCOI(pcopnew)->index = PCOI(pcop)->index; - PCOI(pcopnew)->offset = PCOI(pcop)->offset; - PCOI(pcopnew)->_const = PCOI(pcop)->_const; - PCOI(pcopnew)->_function = PCOI(pcop)->_function; - break; - - case PO_LITERAL: - //DFPRINTF((stderr,"pCodeOpCopy lit\n")); - pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) ); - PCOL(pcopnew)->lit = PCOL(pcop)->lit; - break; - - case PO_GPR_BIT: - - pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace); - PCOR(pcopnew)->r = PCOR(pcop)->r; - PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx; - DFPRINTF((stderr," pCodeOpCopy Bit -register index\n")); - return pcopnew; - break; - - case PO_GPR_POINTER: - case PO_GPR_REGISTER: - case PO_GPR_TEMP: - case PO_FSR: - case PO_INDF: - //DFPRINTF((stderr,"pCodeOpCopy GPR register\n")); - pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) ); - PCOR(pcopnew)->r = PCOR(pcop)->r; - PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx; - PCOR(pcopnew)->instance = PCOR(pcop)->instance; - DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx)); - break; - - case PO_DIR: - //fprintf(stderr,"pCodeOpCopy PO_DIR\n"); - pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) ); - PCOR(pcopnew)->r = PCOR(pcop)->r; - PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx; - PCOR(pcopnew)->instance = PCOR(pcop)->instance; - break; - case PO_STATUS: - DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n")); - case PO_SFR_REGISTER: - case PO_STR: - case PO_NONE: - case PO_W: - case PO_INTCON: - case PO_PCL: - case PO_PCLATH: - - //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type)); - pcopnew = Safe_calloc(1,sizeof(pCodeOp) ); - - } - - pcopnew->type = pcop->type; - if(pcop->name) - pcopnew->name = Safe_strdup(pcop->name); - else - pcopnew->name = NULL; - - return pcopnew; -} - - -/*-----------------------------------------------------------------*/ -/* pCodeCopy - copy a pcode */ -/*-----------------------------------------------------------------*/ -static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert) -{ - pCodeInstruction *new_pci; - - if(invert) - new_pci = PCI(newpCode(pci->inverted_op,pci->pcop)); - else - new_pci = PCI(newpCode(pci->op,pci->pcop)); - - new_pci->pc.pb = pci->pc.pb; - new_pci->from = pci->from; - new_pci->to = pci->to; - new_pci->label = pci->label; - new_pci->pcflow = pci->pcflow; - - return PCODE(new_pci); -} - -/*-----------------------------------------------------------------*/ -/*-----------------------------------------------------------------*/ -void pCodeDeleteChain(pCode *f,pCode *t) -{ - pCode *pc; - - - while(f && f!=t) { - DFPRINTF((stderr,"delete pCode:\n")); - pc = f->next; - //f->print(stderr,f); - //f->delete(f); this dumps core... - - f = pc; - - } - -} /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ int pCodePeepMatchRule(pCode *pc) diff --git a/src/pic/pcoderegs.c b/src/pic/pcoderegs.c index 633e8df5..0ead86a2 100644 --- a/src/pic/pcoderegs.c +++ b/src/pic/pcoderegs.c @@ -36,8 +36,6 @@ #include "pcoderegs.h" #include "pcodeflow.h" -extern void pCodeInsertAfter(pCode *pc1, pCode *pc2); -extern void pCodeInsertBefore(pCode *pc1, pCode *pc2); extern void dbg_dumpregusage(void); extern pCode * findPrevInstruction(pCode *pci); extern pBranch * pBranchAppend(pBranch *h, pBranch *n); @@ -317,7 +315,7 @@ void RemoveRegsFromSet(set *regset) pc = setFirstItem(reg->reglives.usedpCodes); - if(reg->type == REG_SFR || reg->type == REG_STK) { + if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern) { //fprintf(stderr, "not removing SFR reg %s even though used only once\n",reg->name); continue; } @@ -376,7 +374,7 @@ void RemoveUnusedRegisters(void) */ RemoveRegsFromSet(dynDirectBitRegs); - if(total_registers_saved) fprintf(stderr, " *** Saved %d registers ***\n", total_registers_saved); + if(total_registers_saved) DFPRINTF((stderr, " *** Saved %d registers ***\n", total_registers_saved)); } @@ -454,44 +452,83 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int pc2 = pc1; pc1 = pct1; } -/* - fprintf(stderr,"pCodeOptime2pCodes\n"); - pc1->print(stderr,pc1); - pc2->print(stderr,pc2); -*/ + + //fprintf(stderr,"pCodeOptime2pCodes\n"); + //pc1->print(stderr,pc1); + //pc2->print(stderr,pc2); + if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){ + pCode *pc; + int regUsed = 0; + int wUsed = 0; + int wSaved = 0; + int wChgd = 0; /* clrf reg stuff... movf reg,w - can be replaced with + can be replaced with (only if next instructions are not going to use W and reg is not used again later) stuff... - movlw 0 + movlw 0 or clrf reg */ pCode *newpc; - fprintf(stderr, " CLRF/MOVFW. instruction after MOVFW is:\n"); - pct1 = findNextInstruction(pc2->next); + DFPRINTF((stderr, " optimising CLRF reg ... MOVF reg,W to ... MOVLW 0\n")); + pct1 = pc = findNextInstruction(pc2->next); if(PCI(pct1)->op == POC_MOVWF) { - newpc = newpCode(POC_CLRF, PCI(pct1)->pcop); - pct1->destruct(pct1); - } else { - newpc = newpCode(POC_MOVLW, newpCodeOpLit(0)); + wSaved = wUsed = 1; /* Maybe able to replace with clrf pc2->next->reg. */ + pc = findNextInstruction(pc->next); } + for (; pc; pc = findNextInstruction(pc->next)) { + if (isPCI(pc)) { + regs *r; + if (!wChgd) { + if (PCI(pc)->inCond & PCC_W) + wUsed = 1; + if (PCI(pc)->outCond & PCC_W) { + pCode *pcp = findPrevInstruction(pc); + if (pcp && !isPCI_SKIP(pcp)) { + wChgd = 1; /* W has changed so we no longer care if it is used, however if there is a preceding skip instruction then maybe current W is still going to be used */ + if (regUsed) + break; + } + } + } + r = getRegFromInstruction(pc); /* Check if reg is used later. */ + if (r && (r->rIdx==reg->rIdx)) { + if (!(PCI(pc)->outCond & PCC_REGISTER)) + regUsed = 1; + if (wChgd) + break; + } + } + } + if(regUsed&&wUsed) { + /* Do not optimise as exisiting code is required. */ + } else { + /* Can optimise. */ + if(regUsed) { + newpc = newpCode(POC_CLRF, PCI(pc1)->pcop); + } else if(wSaved && !wUsed) { + newpc = newpCode(POC_CLRF, PCI(pct1)->pcop); + pct1->destruct(pct1); + } else { + newpc = newpCode(POC_MOVLW, newpCodeOpLit(0)); + } - pCodeInsertAfter(pc2, newpc); - PCI(newpc)->pcflow = PCFL(pcfl_used); - newpc->seq = pc2->seq; - - Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); - total_registers_saved++; // debugging stats. + pCodeInsertAfter(pc2, newpc); + PCI(newpc)->pcflow = PCFL(pcfl_used); + newpc->seq = pc2->seq; + Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); + total_registers_saved++; // debugging stats. + } } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){ - fprintf(stderr, " CLRF/IORFW.\n"); + DFPRINTF((stderr, " optimising CLRF/IORFW\n")); pct2 = findNextInstruction(pc2->next); @@ -505,60 +542,57 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int total_registers_saved++; // debugging stats. } else if(PCI(pc1)->op == POC_MOVWF) { + // Optimising MOVWF reg ... pct2 = findNextInstruction(pc2->next); if(PCI(pc2)->op == POC_MOVFW) { - /* - fprintf(stderr, " MOVWF/MOVFW. instruction after MOVFW is:\n"); - pct2->print(stderr,pct2); - */ + // Optimising MOVWF reg ... MOVF reg,W if(PCI(pct2)->op == POC_MOVWF) { - /* - Change: + /* + Change: - movwf reg + movwf reg - stuff... + stuff... - movf reg,w - movwf reg2 + movf reg,w + movwf reg2 - To: + To: - - */ - reg2 = getRegFromInstruction(pct2); - //if(reg2 && !regUsedinRange(pc1,pc2,reg2) && (reg2->type != REG_SFR)) { - if(reg2 && !regUsedinRange(pc1,pc2,reg2)) { - if(pCodeSearchCondition(pct2, PCC_Z) < 1) { - pCode *pct3 = findNextInstruction(pct2->next); - fprintf(stderr,"ABCD\n"); - pct2->seq = pc1->seq; - unlinkpCode(pct2); - pCodeInsertAfter(findPrevInstruction(pc1->prev),pct2); + */ + reg2 = getRegFromInstruction(pct2); + if(reg2 && !regUsedinRange(pc1,pc2,reg2)) { -#define usesW(x) ((x) && (isPCI(x)) && ( (PCI(x)->inCond & PCC_W) != 0)) + if(pCodeSearchCondition(pct2, PCC_Z) < 1) { + pCode *pct3 = findNextInstruction(pct2->next); + DFPRINTF((stderr, " optimising MOVF reg ... MOVF reg,W MOVWF reg2\n")); + pct2->seq = pc1->seq; + unlinkpCode(pct2); + pCodeInsertAfter(findPrevInstruction(pc1->prev),pct2); - if(usesW(pct3)) - ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free); - else - Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); +#define usesW(x) ((x) && (isPCI(x)) && ( (PCI(x)->inCond & PCC_W) != 0)) - total_registers_saved++; // debugging stats. - return 1; - } else { - //fprintf(stderr,"didn't optimize because Z bit is used\n"); - } - } + if(usesW(pct3)) + ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free); + else + Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); + + total_registers_saved++; // debugging stats. + return 1; + } else { + //fprintf(stderr,"didn't optimize because Z bit is used\n"); + } + } /* - fprintf(stderr, " couldn't optimize\n"); - if(reg2) - fprintf(stderr, " %s is used in range\n",reg2->name); - else - fprintf(stderr, " reg2 is NULL\n"); + fprintf(stderr, " couldn't optimize\n"); + if(reg2) + fprintf(stderr, " %s is used in range\n",reg2->name); + else + fprintf(stderr, " reg2 is NULL\n"); */ } } @@ -567,73 +601,66 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) { if ( (PCI(pct1)->op == POC_MOVFW) && - (PCI(pc2)->op == POC_MOVFW)) { + (PCI(pc2)->op == POC_MOVFW)) { - reg1 = getRegFromInstruction(pct1); - if(reg1 && !regUsedinRange(pc1,pc2,reg1)) { - /* - fprintf(stderr, " MOVF/MOVFW. \n"); - fprintf(stderr, " ...optimizing\n"); - */ + reg1 = getRegFromInstruction(pct1); + if(reg1 && !regUsedinRange(pc1,pc2,reg1)) { + DFPRINTF((stderr, " optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n")); + /* + Change: - /* - Change: + movf reg1,w + movwf reg - movf reg1,w - movwf reg + stuff... + movf reg,w - stuff... - movf reg,w + To: - To: + stuff... - stuff... + movf reg1,w - movf reg1,w + Or, if we're not deleting the register then the "To" is: - Or, if we're not deleting the register then the "To" is: + stuff... - stuff... + movf reg1,w + movwf reg + */ + pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop); + pCodeInsertAfter(pc2, pct2); + PCI(pct2)->pcflow = PCFL(pcfl_used); + pct2->seq = pc2->seq; - movf reg1,w - movwf reg + if(can_free) { + Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); + } else { + /* If we're not freeing the register then that means (probably) + * the register is needed somewhere else.*/ + unlinkpCode(pc1); + pCodeInsertAfter(pct2, pc1); + Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free); + } - */ - pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop); - pCodeInsertAfter(pc2, pct2); - PCI(pct2)->pcflow = PCFL(pcfl_used); - pct2->seq = pc2->seq; - - if(can_free) { - Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); - } else { - /* If we're not freeing the register then that means (probably) - * the register is needed somewhere else.*/ - unlinkpCode(pc1); - pCodeInsertAfter(pct2, pc1); - - Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free); - } - - Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0); - total_registers_saved++; // debugging stats. + Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0); + total_registers_saved++; // debugging stats. - } + } +/* Note this else if is same conditional as the if - DELETE ME } else if ( (PCI(pct1)->op == POC_MOVWF) && - (PCI(pc2)->op == POC_MOVFW)) { - //fprintf(stderr,"movwf MOVWF/MOVFW\n"); - if(optimize_level > 1 && can_free) { - pct2 = newpCode(POC_MOVFW, PCI(pc1)->pcop); - pCodeInsertAfter(pc2, pct2); - Remove2pcodes(pcfl_used, pc1, pc2, reg, 1); - total_registers_saved++; // debugging stats. - } + (PCI(pc2)->op == POC_MOVFW)) { + DFPRINTF(stderr, " optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n"); + if(optimize_level > 1 && can_free) { + pct2 = newpCode(POC_MOVFW, PCI(pc1)->pcop); + pCodeInsertAfter(pc2, pct2); + Remove2pcodes(pcfl_used, pc1, pc2, reg, 1); + total_registers_saved++; // debugging stats. + } +*/ } - - } - } return (total_registers_saved != t); @@ -659,8 +686,12 @@ void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level) reg = fregs->item; fregs = fregs->next; +/* +if (strcmp(reg->name,"_SubState")==0) + fprintf(stderr,"Reg: %s\n",reg->name); +*/ - if(reg->type == REG_SFR || reg->type == REG_STK) { + if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern|| reg->isFixed) { //fprintf(stderr,"skipping SFR: %s\n",reg->name); continue; } @@ -810,15 +841,15 @@ void pCodeRegOptimizeRegUsage(int level) OptimizeRegUsage(dynDirectRegs,0, (OPT_PASSES-passes)); if(total_registers_saved != saved) - fprintf(stderr, " *** pass %d, Saved %d registers, total saved %d ***\n", - (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved); + DFPRINTF((stderr, " *** pass %d, Saved %d registers, total saved %d ***\n", + (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved)); passes--; } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) ); if(total_registers_saved == t) - fprintf(stderr, "No registers saved on this pass\n"); + DFPRINTF((stderr, "No registers saved on this pass\n")); /* diff --git a/src/pic/ralloc.c b/src/pic/ralloc.c index f191dd51..809c6dbe 100644 --- a/src/pic/ralloc.c +++ b/src/pic/ralloc.c @@ -392,7 +392,7 @@ decodeOp (unsigned int op) case SEND: return "SEND"; } - sprintf (buffer, "unkown op %d %c", op, op & 0xff); + sprintf (buffer, "unknown op %d %c", op, op & 0xff); return buffer; } /*-----------------------------------------------------------------*/ @@ -446,24 +446,24 @@ static regs* newReg(short type, short pc_type, int rIdx, char *name, int size, i dReg->type = type; dReg->pc_type = pc_type; dReg->rIdx = rIdx; - if(name) + if(name) { dReg->name = Safe_strdup(name); - else { + } else { sprintf(buffer,"r0x%02X", dReg->rIdx); - if(type == REG_STK) - *buffer = 's'; dReg->name = Safe_strdup(buffer); } //fprintf(stderr,"newReg: %s, rIdx = 0x%02x\n",dReg->name,rIdx); dReg->isFree = 0; dReg->wasUsed = 1; - if(type == REG_SFR) + if (type == REG_SFR) dReg->isFixed = 1; else dReg->isFixed = 0; dReg->isMapped = 0; dReg->isEmitted = 0; + dReg->isPublic = 0; + dReg->isExtern = 0; dReg->address = 0; dReg->size = size; dReg->alias = alias; @@ -495,6 +495,64 @@ regWithIdx (set *dRegs, int idx, int fixed) return NULL; } +/*-----------------------------------------------------------------*/ +/* regWithName - Search through a set of registers that matches name */ +/*-----------------------------------------------------------------*/ +static regs * +regWithName (set *dRegs, const char *name) +{ + regs *dReg; + + for (dReg = setFirstItem(dRegs) ; dReg ; + dReg = setNextItem(dRegs)) { + + if((strcmp(name,dReg->name)==0)) { + return dReg; + } + } + + return NULL; +} + +/*-----------------------------------------------------------------*/ +/* regWithName - Search for a registers that matches name */ +/*-----------------------------------------------------------------*/ +regs * +regFindWithName (const char *name) +{ + regs *dReg; + + if( (dReg = regWithName ( dynDirectRegs, name)) != NULL ) { + debugLog ("Found a Direct Register!\n"); + return dReg; + } + if( (dReg = regWithName ( dynDirectBitRegs, name)) != NULL) { + debugLog ("Found a Direct Bit Register!\n"); + return dReg; + } + + if (*name=='_') name++; // Step passed '_' + + if( (dReg = regWithName ( dynAllocRegs, name)) != NULL) { + debugLog ("Found a Dynamic Register!\n"); + return dReg; + } + if( (dReg = regWithName ( dynProcessorRegs, name)) != NULL) { + debugLog ("Found a Processor Register!\n"); + return dReg; + } + if( (dReg = regWithName ( dynInternalRegs, name)) != NULL) { + debugLog ("Found an Internal Register!\n"); + return dReg; + } + if( (dReg = regWithName ( dynStackRegs, name)) != NULL) { + debugLog ("Found an Stack Register!\n"); + return dReg; + } + + return NULL; +} + /*-----------------------------------------------------------------*/ /* regFindFree - Search for a free register in a set of registers */ /*-----------------------------------------------------------------*/ @@ -523,8 +581,15 @@ void initStack(int base_address, int size) Gstack_base_addr = base_address; //fprintf(stderr,"initStack"); - for(i = 0; iaddress = base_address; // Pseudo stack needs a fixed location that can be known by all modules + r->isFixed = 1; + r->name[0] = 's'; + r->alias = 0x180; // Using shared memory for pseudo stack + addSet(&dynStackRegs,r); + base_address--; + } } /*-----------------------------------------------------------------* @@ -606,6 +671,68 @@ int IS_CONFIG_ADDRESS(int address) return address == 0x2007; } +/*-----------------------------------------------------------------*/ +/* allocNewDirReg - allocates a new register of given type */ +/*-----------------------------------------------------------------*/ +regs * +allocNewDirReg (sym_link *symlnk,const char *name) +{ + regs *reg; + int address = 0; + + /* if this is at an absolute address, then get the address. */ + if (SPEC_ABSA (symlnk) ) { + address = SPEC_ADDR (symlnk); + //fprintf(stderr,"reg %s is at an absolute address: 0x%03x\n",name,address); + } + + /* Register wasn't found in hash, so let's create + * a new one and put it in the hash table AND in the + * dynDirectRegNames set */ + if (IS_CONFIG_ADDRESS(address)) { + debugLog (" -- %s is declared at address 0x2007\n",name); + reg = 0; + } else { + int idx; + if (address) { + if (IS_BITVAR (symlnk)) + idx = address >> 3; + else + idx = address; + } else { + idx = rDirectIdx++; + } + reg = newReg(REG_GPR, PO_DIR, idx, (char*)name,getSize (symlnk),0 ); + debugLog (" -- added %s to hash, size = %d\n", (char*)name,reg->size); + + if (SPEC_ABSA (symlnk) ) { + reg->type = REG_SFR; + } + + if (IS_BITVAR (symlnk)) { + addSet(&dynDirectBitRegs, reg); + reg->isBitField = 1; + } else + addSet(&dynDirectRegs, reg); + + if (!IS_STATIC (symlnk)) { + reg->isPublic = 1; + } + if (IS_EXTERN (symlnk)) { + reg->isExtern = 1; + } + + } + + if (address && reg) { + reg->isFixed = 1; + reg->address = address; + debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address); + } + + return reg; +} + /*-----------------------------------------------------------------*/ /* allocDirReg - allocates register of given type */ /*-----------------------------------------------------------------*/ @@ -670,6 +797,7 @@ allocDirReg (operand *op ) reg = dirregWithName(name); } +#if 0 if(!reg) { int address = 0; @@ -702,6 +830,14 @@ allocDirReg (operand *op ) } else addSet(&dynDirectRegs, reg); + if (!IS_STATIC (OP_SYM_ETYPE(op))) { + reg->isPublic = 1; + } + if (IS_EXTERN (OP_SYM_ETYPE(op))) { + reg->isExtern = 1; + } + + } else { debugLog (" -- %s is declared at address 0x2007\n",name); @@ -713,12 +849,24 @@ allocDirReg (operand *op ) reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op)); debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address); } +#endif + + if(reg) { + if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) { + reg->isFixed = 1; + reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op)); + debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address); + } + } else { + allocNewDirReg (OP_SYM_ETYPE(op),name); + } return reg; } + /*-----------------------------------------------------------------*/ -/* allocDirReg - allocates register of given type */ +/* allocRegByName - allocates register with given name */ /*-----------------------------------------------------------------*/ regs * allocRegByName (char *name, int size) @@ -734,17 +882,58 @@ allocRegByName (char *name, int size) /* First, search the hash table to see if there is a register with this name */ reg = dirregWithName(name); - if(!reg) { + if(!reg) { + int found = 0; + symbol *sym; /* Register wasn't found in hash, so let's create * a new one and put it in the hash table AND in the * dynDirectRegNames set */ //fprintf (stderr,"%s symbol name %s\n", __FUNCTION__,name); reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,size,0 ); + for (sym = setFirstItem(sfr->syms); sym; sym = setNextItem(sfr->syms)) { + if (strcmp(reg->name+1,sym->name)==0) { + unsigned a = SPEC_ADDR(sym->etype); + reg->address = a; + reg->isFixed = 1; + reg->type = REG_SFR; + if (!IS_STATIC (sym->etype)) { + reg->isPublic = 1; + } + if (IS_EXTERN (sym->etype)) { + reg->isExtern = 1; + } + if (IS_BITVAR (sym->etype)) + reg->isBitField = 1; + found = 1; + break; + } + } + if (!found) { + for (sym = setFirstItem(data->syms); sym; sym = setNextItem(data->syms)) { + if (strcmp(reg->name+1,sym->name)==0) { + unsigned a = SPEC_ADDR(sym->etype); + reg->address = a; + if (!IS_STATIC (sym->etype)) { + reg->isPublic = 1; + } + if (IS_EXTERN (sym->etype)) { + reg->isExtern = 1; + } + if (IS_BITVAR (sym->etype)) + reg->isBitField = 1; + found = 1; + break; + } + } + } debugLog (" -- added %s to hash, size = %d\n", name,reg->size); //hTabAddItem(&dynDirectRegNames, regname2key(name), reg); + if (reg->isBitField) { + addSet(&dynDirectBitRegs, reg); + } else addSet(&dynDirectRegs, reg); } @@ -812,9 +1001,6 @@ pic14_regWithIdx (int idx) if( (dReg = typeRegWithIdx(idx,REG_SFR,0)) != NULL) return dReg; - if( (dReg = typeRegWithIdx(idx,REG_STK,0)) != NULL) - return dReg; - return NULL; } @@ -2504,11 +2690,7 @@ regTypeNum () getSize (sym->type)); -#if 0 if(IS_PTR_CONST (sym->type)) { -#else - if(IS_CODEPTR (sym->type)) { -#endif debugLog (" %d const pointer type requires %d registers, changing to 2\n",__LINE__,sym->nRegs); sym->nRegs = 2; } @@ -3505,11 +3687,7 @@ packRegisters (eBBlock * ebp) sym_link *etype = getSpec (operandType (IC_LEFT (ic))); debugAopGet (" left:", IC_LEFT (ic)); -#if 0 if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type)) -#else - if(IS_CODEPTR(OP_SYMBOL(IC_LEFT(ic))->type)) -#endif debugLog (" is a pointer\n"); if(IS_OP_VOLATILE(IC_LEFT(ic))) @@ -3848,10 +4026,6 @@ pic14_assignRegisters (eBBlock ** ebbs, int count) } - /* liveranges probably changed by register packing - so we compute them again */ - recomputeLiveRanges (ebbs, count); - if (options.dump_pack) dumpEbbsToFileExt (DUMP_PACK, ebbs, count); diff --git a/src/pic/ralloc.h b/src/pic/ralloc.h index 5c6d77b8..08ddfa2e 100644 --- a/src/pic/ralloc.h +++ b/src/pic/ralloc.h @@ -72,6 +72,8 @@ typedef struct regs unsigned isMapped:1; /* The Register's address has been mapped to physical RAM */ unsigned isBitField:1; /* True if reg is type bit OR is holder for several bits */ unsigned isEmitted:1; /* True if the reg has been written to a .asm file */ + unsigned isPublic:1; /* True if the reg is not static and can be modified in another module (ie a another c or asm file) */ + unsigned isExtern:1; /* True if the reg is in another module */ unsigned address; /* reg's address if isFixed | isMapped is true */ unsigned size; /* 0 for byte, 1 for int, 4 for long */ unsigned alias; /* Alias mask if register appears in multiple banks */ @@ -104,9 +106,11 @@ void pic14_deallocateAllRegs (); regs *pic14_findFreeReg(short type); regs *pic14_allocWithIdx (int idx); regs *typeRegWithIdx (int idx, int type, int fixed); +regs *regFindWithName (const char *name); regs *allocDirReg (operand *op ); regs *allocRegByName (char *name, int size ); +regs *allocNewDirReg (sym_link *symlnk,const char *name); /* Define register address that are constant across PIC family */ #define IDX_INDF 0 -- 2.47.2