From: vrokas Date: Mon, 20 Dec 2004 21:48:32 +0000 (+0000) Subject: * src/SDCCast.c (gatherAutoInit): allow pic16 to emit static X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=35dd84251b9d153bb48ad98be9c5eae77799cb42;p=fw%2Fsdcc * src/SDCCast.c (gatherAutoInit): allow pic16 to emit static variables initial values to idata section, * src/SDCCicode.c (geniCodeCall): patch from ### to fix unreferenced variables in some functions. This utilizes parmBytes field of iCode structure to hold the offset of the variable in stack. (might be able to use the stack field too?) * applied patch from Raphael Neider # ### , # ### * src/pic16/glue.c (pic16emitRegularMap): fix to print static variable initial values in idata section, * src/pic16/ralloc.c (pic16_allocDirReg): don't allocate register for static variables with initial value * src/device/lib/pic16/libsdcc/float/ulong2fs.c (__ulong2fs): applied fix in while loop from Raphael Neider. git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3607 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/ChangeLog b/ChangeLog index 059d1cb5..0ac92a39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2004-12-20 Vangelis Rokas + + * src/SDCCast.c (gatherAutoInit): allow pic16 to emit static + variables initial values to idata section, + * src/SDCCicode.c (geniCodeCall): patch from ### to fix unreferenced + variables in some functions. This utilizes parmBytes field of iCode + structure to hold the offset of the variable in stack. (might be + able to use the stack field too?) + * applied patch from Raphael Neider # ### , # ### + * src/pic16/glue.c (pic16emitRegularMap): fix to print static + variable initial values in idata section, + * src/pic16/ralloc.c (pic16_allocDirReg): don't allocate register + for static variables with initial value + * src/device/lib/pic16/libsdcc/float/ulong2fs.c (__ulong2fs): + applied fix in while loop from Raphael Neider. + 2004-12-19 Maarten Brock * src/ds390/gen.c (genCpl): fixed bit=~(char/bit) bugs, added warning diff --git a/device/lib/pic16/libsdcc/float/ulong2fs.c b/device/lib/pic16/libsdcc/float/ulong2fs.c index 90322f28..7f673c2b 100644 --- a/device/lib/pic16/libsdcc/float/ulong2fs.c +++ b/device/lib/pic16/libsdcc/float/ulong2fs.c @@ -50,7 +50,7 @@ float __ulong2fs (unsigned long a ) _FS_REENTRANT do { a<<=1; exp--; - } while (a > HIDDEN); + } while (a < HIDDEN); } #if 0 diff --git a/src/SDCCBBlock.c b/src/SDCCBBlock.c index 5c757bca..931fefcd 100644 --- a/src/SDCCBBlock.c +++ b/src/SDCCBBlock.c @@ -88,7 +88,9 @@ newEdge (eBBlock * from, eBBlock * to) /*-----------------------------------------------------------------*/ FILE *createDumpFile (int id) { struct _dumpFiles *dumpFilesPtr=dumpFiles; - + static int dumpIndex=0; + static char dumpIndexStr[32]; + while (dumpFilesPtr->id) { if (dumpFilesPtr->id==id) break; @@ -100,15 +102,26 @@ FILE *createDumpFile (int id) { exit (1); } + sprintf(dumpIndexStr, ".%d", dumpIndex); + dumpIndex++; + if (!dumpFilesPtr->filePtr) { // not used before, create it strncpyz (scratchFileName, dstFileName, PATH_MAX); +#if 0 + strncatz (scratchFileName, dumpIndexStr, PATH_MAX); +#endif strncatz (scratchFileName, dumpFilesPtr->ext, PATH_MAX); if (!(dumpFilesPtr->filePtr = fopen (scratchFileName, "w"))) { werror (E_FILE_OPEN_ERR, scratchFileName); exit (1); } } + +#if 0 + fprintf(dumpFilesPtr->filePtr, "Dump file index: %d\n", dumpIndex); +#endif + return dumpFilesPtr->filePtr; } diff --git a/src/SDCCast.c b/src/SDCCast.c index b3e14fe4..206e5bfe 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -1130,6 +1130,21 @@ gatherAutoInit (symbol * autoChain) if (sym->ival) resolveIvalSym (sym->ival, sym->type); +#if 1 + /* if we are PIC16 port, + * and this is a static, + * and have initial value, + * and not S_CODE, don't emit in gs segment, + * but allow glue.c:pic16emitRegularMap to put symbol + * in idata section */ + if(TARGET_IS_PIC16 && + IS_STATIC (sym->etype) && sym->ival + && SPEC_SCLS(sym->etype) != S_CODE) { + SPEC_SCLS (sym->etype) = S_DATA; + continue; + } +#endif + /* if this is a static variable & has an */ /* initial value the code needs to be lifted */ /* here to the main portion since they can be */ diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 8a1d0504..b989c88d 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -3379,6 +3379,8 @@ geniCodeCall (operand * left, ast * parms,int lvl) static void geniCodeReceive (value * args) { + unsigned char paramByteCounter = 0; + /* for all arguments that are passed in registers */ while (args) { @@ -3419,6 +3421,17 @@ geniCodeReceive (value * args) first = 0; } IC_RESULT (ic) = opr; + + /* misuse of parmBytes (normally used for functions) + * to save estimated stack position of this argument. + * Normally this should be zero for RECEIVE iCodes. + * No idea if this causes side effects on other ports. - dw + */ + ic->parmBytes = paramByteCounter; + + /* what stack position do we have? */ + paramByteCounter += getSize (sym->type); + ADDTOCHAIN (ic); } diff --git a/src/SDCClrange.c b/src/SDCClrange.c index d99df74c..194d37a2 100644 --- a/src/SDCClrange.c +++ b/src/SDCClrange.c @@ -531,6 +531,8 @@ rlivePoint (eBBlock ** ebbs, int count) } } } +// fprintf(stderr, "%s:%d IS_SYMOP left\t", __FILE__, __LINE__);printOperand(IC_LEFT(ic), stderr); +// fprintf(stderr, "\n"); } if (IS_SYMOP(IC_RIGHT(ic))) @@ -543,6 +545,8 @@ rlivePoint (eBBlock ** ebbs, int count) ic->rlive = bitVectSetBit (ic->rlive, IC_RIGHT(ic)->key); findNextUse (ebbs[i], ic->next, IC_RIGHT(ic)); } +// fprintf(stderr, "%s:%d IS_SYMOP right\t", __FILE__, __LINE__);printOperand(IC_RIGHT(ic), stderr); +// fprintf(stderr, "\n"); } if (POINTER_SET(ic) && IS_SYMOP(IC_RESULT(ic))) diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index e6ab1b76..7ccca8c3 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -1485,8 +1485,9 @@ checkSClass (symbol * sym, int isProto) /* if parameter or local variable then change */ /* the storage class to reflect where the var will go */ - if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED && - !IS_STATIC(sym->etype)) + if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED + && !IS_STATIC(sym->etype) + ) { if (options.stackAuto || (currFunc && IFFUNC_ISREENT (currFunc->type))) { diff --git a/src/pic16/gen.c b/src/pic16/gen.c index fed12d12..e474f6c0 100644 --- a/src/pic16/gen.c +++ b/src/pic16/gen.c @@ -57,7 +57,6 @@ extern void pic16_printpBlock(FILE *of, pBlock *pb); static asmop *newAsmop (short type); static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op); extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...); -static void mov2w (asmop *aop, int offset); static void mov2f(asmop *dst, asmop *src, int offset); static void mov2fp(pCodeOp *dst, asmop *src, int offset); static pCodeOp *pic16_popRegFromIdx(int rIdx); @@ -681,8 +680,8 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) for(i=0;isize;i++) { /* initialise for stack access via frame pointer */ - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat)); - + // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand + pic16_emitpcode(POC_MOVLW, pic16_popGetLit((sym->stack + 1 + i /*+ _G.stack_lat*/))); pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_plusw2), pcop[i])); } @@ -1304,8 +1303,8 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) ); for(i=0;isize;i++) { /* initialise for stack access via frame pointer */ - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat)); - + // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand + pic16_emitpcode(POC_MOVLW, pic16_popGetLit((OP_SYMBOL(IC_RESULT(ic))->stack + 1 + i /*+ _G.stack_lat*/))); pic16_emitpcode(POC_MOVFF, pic16_popGet2p( aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2))); } @@ -1910,7 +1909,9 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) case AOP_REG: { - int rIdx = aop->aopu.aop_reg[offset]->rIdx; + int rIdx; + assert (aop && aop->aopu.aop_reg[offset] != NULL); + rIdx = aop->aopu.aop_reg[offset]->rIdx; DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__); @@ -2217,7 +2218,7 @@ void pic16_aopPut (asmop *aop, char *s, int offset) /*-----------------------------------------------------------------*/ /* mov2w - generate either a MOVLW or MOVFW based operand type */ /*-----------------------------------------------------------------*/ -static void mov2w (asmop *aop, int offset) +void mov2w (asmop *aop, int offset) { DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset); @@ -2903,6 +2904,9 @@ static void assignResultValue(operand * oper, int rescall) /* its called from genReceive (probably) -- VR */ + /* I hope this code will not be called from somewhere else in the future! + * We manually set the pseudo stack pointer in genReceive. - dw + */ if(!GpsuedoStkPtr && _G.useWreg) { // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr); @@ -2913,6 +2917,7 @@ static void assignResultValue(operand * oper, int rescall) offset++; // debugf("receive from WREG\n", 0); } + GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */ } // GpsuedoStkPtr++; _G.stack_lat = AOP_SIZE(oper)-1; @@ -2920,7 +2925,7 @@ static void assignResultValue(operand * oper, int rescall) while (size) { size--; GpsuedoStkPtr++; - popaopidx(AOP(oper), offset, GpsuedoStkPtr); + popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg); // debugf("receive from STACK\n", 0); offset++; } @@ -3604,7 +3609,7 @@ static void genFunction (iCode *ic) pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack)); pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l)); - emitSKPNC; + emitSKPC; pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h)); } @@ -3672,10 +3677,19 @@ static void genEndFunction (iCode *ic) if ((IFFUNC_ISREENT(sym->type) || options.stackAuto) && sym->stack) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l)); - emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h)); + if (sym->stack == 1) { + pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg(&pic16_pc_fsr1l)); + pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h)); + } else { + // we have to add more than one... + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc1)); // this holds a return value! + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1)); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l)); + emitSKPNC; + pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h)); + pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)! + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_plusw1)); // this holds a retrun value! + } } // sym->regsUsed = _G.fregsUsed; @@ -7507,9 +7521,9 @@ static void genAnd (iCode *ic, iCode *ifx) else { if(ifx) { pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key)); - pic16_emitpLabel(tlbl->key); ifx->generated = 1; } + pic16_emitpLabel(tlbl->key); goto release; } } @@ -10293,12 +10307,7 @@ static void genUnpackBits (operand *result, operand *left, char *rname, int ptyp /* it is a single bit, so use the appropriate bit instructions */ DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__); - if(IS_BITFIELD(etype)/* && !IS_ITEMP(left)*/) { - pic16_emitpcode(POC_MOVFW, pic16_popGet( AOP(result), 0 )); - pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); - } else { - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); - } + pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); if((ptype == POINTER) && (result)) { /* workaround to reduce the extra lfsr instruction */ @@ -10309,12 +10318,7 @@ static void genUnpackBits (operand *result, operand *left, char *rname, int ptyp pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); } - - if(IS_BITFIELD(etype)) { - pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); - } else { - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg)); - } + pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg)); pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 )); return; @@ -12029,11 +12033,12 @@ static void genAddrOf (iCode *ic) pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2h), pic16_popGet(AOP(result), 1))); - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0)); - emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1)); + + // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( - (OP_SYMBOL( IC_LEFT(ic))->stack + 1 ) /*+ _G.stack_lat*/)); + pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result), 0)); + emitSKPC; + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result), 1)); goto release; } @@ -12207,6 +12212,16 @@ static void genAssign (iCode *ic) // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit, // sizeof(unsigned long int), sizeof(float)); + + if (AOP_TYPE(right) == AOP_REG) { + DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__); + while (size--) { + + pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++)); + } // while + goto release; + } + if(AOP_TYPE(right) != AOP_LIT && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype)) && !IS_FUNC(OP_SYM_TYPE(right)) @@ -12288,8 +12303,8 @@ static void genAssign (iCode *ic) } else if (AOP_TYPE(right) == AOP_CRY) { pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); if(offset == 0) { -// debugf("%s: BTFSS offset == 0\n", __FUNCTION__); - pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0)); + //debugf("%s: BTFSS offset == 0\n", __FUNCTION__); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); } } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) { @@ -12387,6 +12402,7 @@ static void genJumpTab (iCode *ic) #endif pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE); + pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, "")); /* now generate the jump labels */ for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab; jtab = setNextItem(IC_JTLABELS(ic))) { @@ -12394,6 +12410,7 @@ static void genJumpTab (iCode *ic) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key)); } + pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, "")); } @@ -12951,10 +12968,14 @@ static void genReceive (iCode *ic) } } else { DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) )); - _G.accInUse++; pic16_aopOp(IC_RESULT(ic),ic,FALSE); _G.accInUse--; + + /* set pseudo stack pointer to where it should be - dw*/ + GpsuedoStkPtr = ic->parmBytes; + + /* setting GpsuedoStkPtr has side effects here: */ assignResultValue(IC_RESULT(ic), 0); } diff --git a/src/pic16/gen.h b/src/pic16/gen.h index dd649f37..84af5945 100644 --- a/src/pic16/gen.h +++ b/src/pic16/gen.h @@ -202,6 +202,7 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop); const char *pic16_pCodeOpType( pCodeOp *pcop); int pic16_my_powof2 (unsigned long num); +void mov2w (asmop *aop, int offset); void dumpiCode(iCode *lic); diff --git a/src/pic16/genarith.c b/src/pic16/genarith.c index b5b707a8..8221433f 100644 --- a/src/pic16/genarith.c +++ b/src/pic16/genarith.c @@ -48,10 +48,6 @@ #include "pcode.h" #include "gen.h" -//#define D_POS(txt) DEBUGpic16_emitcode ("; TECODEV::: " txt, " (%s:%d (%s))", __FILE__, __LINE__, __FUNCTION__) - -#define D_POS(msg) DEBUGpic16_emitcode("; ", msg, "%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__) - #if 1 #define pic16_emitcode DEBUGpic16_emitcode #endif @@ -533,7 +529,6 @@ static void genAddLit (iCode *ic, int lit) pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); break; default: /* 0x01LL */ - D_POS("FIXED: added default case for adding 0x01??"); pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0)); emitSKPNC; @@ -578,11 +573,9 @@ static void genAddLit (iCode *ic, int lit) genAddLit2byte (result, MSB16, hi); break; case 1: /* 0xHH01 */ - D_POS(">>> IMPROVED"); pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi)); pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16)); - D_POS("<<< IMPROVED"); break; /* case 0xff: * 0xHHff * pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE)); @@ -594,9 +587,7 @@ static void genAddLit (iCode *ic, int lit) pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi)); - D_POS(">>> IMPROVED"); pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16)); - D_POS("<<< IMPROVED"); break; } @@ -613,22 +604,17 @@ static void genAddLit (iCode *ic, int lit) if(carry_info) { switch(lo) { case 0: - D_POS(">>> IMPROVED and compacted 0"); emitSKPNC; pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset)); - D_POS("<<< IMPROVED and compacted"); break; case 0xff: pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); - D_POS(">>> Changed from SKPZ/SKPC to always SKPC"); emitSKPC; pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset)); break; default: - D_POS(">>> IMPROVED and compacted - default"); pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset)); - D_POS("<<< IMPROVED and compacted"); break; } }else { @@ -702,9 +688,8 @@ static void genAddLit (iCode *ic, int lit) /* left addend is in a register */ switch(lit & 0xff) { case 0: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); + mov2w(AOP(left),0); emitMOVWF(result, 0); - D_POS(">>> REMOVED double assignment"); break; case 1: pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0)); @@ -732,7 +717,7 @@ static void genAddLit (iCode *ic, int lit) pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); + mov2w(AOP(left),0); /* We don't know the state of the carry bit at this point */ clear_carry = 1; } @@ -748,26 +733,20 @@ static void genAddLit (iCode *ic, int lit) pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offset)); - D_POS(">>> FIXED from left to result"); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - D_POS("<<< FIXED from left to result"); clear_carry = 0; } else { - D_POS(">>> FIXED"); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - D_POS("<<< FIXED"); } } else { - D_POS(">>> IMPROVED"); pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); + mov2w(AOP(left),offset); pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset)); - D_POS("<<< IMPROVED"); } offset++; } @@ -881,7 +860,7 @@ void pic16_genPlus (iCode *ic) AOP(IC_RIGHT(ic))->aopu.aop_dir); pic16_emitcode(" xorlw","1"); } else { - pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0)); + mov2w(AOP(IC_LEFT(ic)),0); pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(IC_LEFT(ic)),0)); @@ -923,7 +902,7 @@ void pic16_genPlus (iCode *ic) } else { emitCLRZ; // needed here as well: INCFW is not always executed, Z is undefined then - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0)); + mov2w(AOP(IC_LEFT(ic)),0); pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_LEFT(ic)),0)); //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE)); @@ -1014,9 +993,7 @@ void pic16_genPlus (iCode *ic) // right is signed, oh dear ... for(i=size; i< AOP_SIZE(result); i++) { pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i)); - D_POS(">>> FIXED sign test from result to right"); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - D_POS("<<< FIXED sign test from result to right"); pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result),i)); pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i)); pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i)); @@ -1031,7 +1008,7 @@ void pic16_genPlus (iCode *ic) // add first bytes for(i=0; i>> FIXED added to uninitialized result"); pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i)); - D_POS ("<<< FIXED"); } } } else { @@ -1423,7 +1398,6 @@ void pic16_genMinus (iCode *ic) if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) { if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) { if(lit & 1) { - D_POS(">>> FIXED from MOVLW right(=result) to MOVLW left(=literal,left&1==1)"); pic16_emitpcode(POC_MOVLW , pic16_popGetLit(1)); pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0)); } @@ -1440,13 +1414,12 @@ void pic16_genMinus (iCode *ic) pic16_emitpcode(POC_MOVLW , pic16_popGetLit(lit & 0xff)); pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_MOVLW , pic16_popGetLit((lit-1) & 0xff)); - D_POS(">>> IMPROVED removed following assignment W-->result"); //pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0)); } } else { - pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0)); + mov2w(AOP(IC_LEFT(ic)),0); pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_DECFW , pic16_popGet(AOP(IC_LEFT(ic)),0)); } @@ -1481,9 +1454,7 @@ void pic16_genMinus (iCode *ic) if( (size == 1) && ((lit & 0xff) == 0) ) { /* res = 0 - right */ if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) { - D_POS(">>> IMPROVED changed comf,incf to negf"); pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(IC_RIGHT(ic)),0)); - D_POS("<<< IMPROVED changed comf,incf to negf"); } else { pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0)); @@ -1492,7 +1463,7 @@ void pic16_genMinus (iCode *ic) goto release; } - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),0)); + mov2w(AOP(IC_RIGHT(ic)),0); pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff)); pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); @@ -1501,7 +1472,6 @@ void pic16_genMinus (iCode *ic) while(--size) { lit >>= 8; offset++; - D_POS(">>> FIXED and compacted"); if(same) { // here we have x = lit - x for sizeof(x)>1 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); @@ -1511,7 +1481,6 @@ void pic16_genMinus (iCode *ic) pic16_emitpcode(POC_SUBFWB_D0, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); } - D_POS("<<< FIXED and compacted"); } @@ -1532,7 +1501,7 @@ void pic16_genMinus (iCode *ic) DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC) - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_RIGHT(ic)),0)); + mov2w(AOP(IC_RIGHT(ic)),0); if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_LEFT(ic)),0)); @@ -1569,13 +1538,10 @@ void pic16_genMinus (iCode *ic) while(size--){ if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - D_POS(">>> IMPROVED by replacing emitSKPC, incfszw by subwfb"); + mov2w(AOP(IC_RIGHT(ic)),offset); pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - D_POS("<<< IMPROVED by replacing emitSKPC, incfszw by subwfb"); } else { - D_POS(">>> FIXED for same regs right and result"); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); + mov2w(AOP(IC_RIGHT(ic)),offset); pic16_emitpcode(POC_SUBWFB_D0, pic16_popGet(AOP(IC_LEFT(ic)),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); } @@ -1841,7 +1807,7 @@ void pic16_genUMult8X8_8 (operand *left, if(AOP_TYPE(left) != AOP_ACC) { // left is not WREG if(AOP_TYPE(right) != AOP_ACC) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); + mov2w(AOP(left), 0); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); } else { pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); @@ -1909,7 +1875,7 @@ void pic16_genUMult16X16_16 (operand *left, pct3 = pic16_popGetTempReg(1); pct4 = pic16_popGetTempReg(1); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); + mov2w(AOP(left), 0); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1))); @@ -1921,7 +1887,7 @@ void pic16_genUMult16X16_16 (operand *left, pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3))); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1)); + mov2w(AOP(left), 1); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4))); @@ -1941,7 +1907,7 @@ void pic16_genUMult16X16_16 (operand *left, } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); + mov2w(AOP(left), 0); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0))); @@ -1953,7 +1919,7 @@ void pic16_genUMult16X16_16 (operand *left, pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1)); + mov2w(AOP(left), 1); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1)); @@ -1994,7 +1960,7 @@ void pic16_genSMult8X8_8 (operand *left, #if 0 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),7,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(result_hi)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); + mov2w(AOP(left),0); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),7,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result),1)); #endif @@ -2186,7 +2152,7 @@ void pic16_genUMult32X32_32 (operand *left, pct3 = pic16_popGetTempReg(1); pct4 = pic16_popGetTempReg(1); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); + mov2w(AOP(left), 0); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1))); @@ -2198,7 +2164,7 @@ void pic16_genUMult32X32_32 (operand *left, pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3))); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1)); + mov2w(AOP(left), 1); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4))); @@ -2218,7 +2184,7 @@ void pic16_genUMult32X32_32 (operand *left, } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); + mov2w(AOP(left), 0); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0))); @@ -2230,7 +2196,7 @@ void pic16_genUMult32X32_32 (operand *left, pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1)); + mov2w(AOP(left), 1); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1)); diff --git a/src/pic16/glue.c b/src/pic16/glue.c index 9b672423..573f83c5 100644 --- a/src/pic16/glue.c +++ b/src/pic16/glue.c @@ -175,12 +175,20 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag) checkAddSym(&publics, sym); } else +#if 1 + /* new version */ if(IS_STATIC(sym->etype) - && !(sym->ival && !sym->level) - ) { + && !sym->ival) /* && !sym->level*/ { +#else + /* old version */ + if(IS_STATIC(sym->etype) + && !(sym->ival && !sym->level)) { +#endif regs *reg; sectSym *ssym; int found=0; + +// debugf("adding symbol %s\n", sym->name); #define SET_IMPLICIT 1 #if SET_IMPLICIT @@ -191,15 +199,15 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag) reg = pic16_allocDirReg( operandFromSymbol( sym )); if(reg) { -#if 1 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) { if(!strcmp(ssym->name, reg->name))found=1; } -#endif + if(!found) checkAddReg(&pic16_rel_udata, reg); else - checkAddSym(&publics, sym); + debugf("Coudld not find %s in pic16_rel_udata. Check!\n", reg->name); +// checkAddSym(&publics, sym); } } @@ -214,28 +222,9 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag) continue; } -#if 0 - /* print extra debug info if required */ - if (options.debug || sym->level == 0) { - cdbWriteSymbol (sym); //, cdbFile, FALSE, FALSE); - - if (!sym->level) /* global */ - if (IS_STATIC (sym->etype)) - fprintf (map->oFile, "F%s_", moduleName); /* scope is file */ - else - fprintf (map->oFile, "G_"); /* scope is global */ - else - /* symbol is local */ - fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-")); - fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block); - } -#endif - - /* if is has an absolute address then generate an equate for this no need to allocate space */ if (SPEC_ABSA (sym->etype)) { -// if (options.debug || sym->level == 0) // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n", // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType); @@ -343,7 +332,9 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag) /* if it has an initial value then do it only if it is a global variable */ - if (sym->ival && sym->level == 0) { + if (sym->ival + && ((sym->level == 0) + || IS_STATIC(sym->etype)) ) { ast *ival = NULL; #if 0 @@ -1460,6 +1451,8 @@ pic16printPublics (FILE *afile) fprintf (afile, "%s", iComments2); for(sym = setFirstItem (publics); sym; sym = setNextItem (publics)) + /* sanity check */ + if(!IS_STATIC(sym->etype)) fprintf(afile, "\tglobal %s\n", sym->rname); } @@ -1545,27 +1538,6 @@ pic16emitOverlay (FILE * afile) if (IS_FUNC (sym->type)) continue; -#if 0 - /* print extra debug info if required */ - if (options.debug || sym->level == 0) - { - - cdbSymbol (sym, cdbFile, FALSE, FALSE); - - if (!sym->level) - { /* global */ - if (IS_STATIC (sym->etype)) - fprintf (afile, "F%s_", moduleName); /* scope is file */ - else - fprintf (afile, "G_"); /* scope is global */ - } - else - /* symbol is local */ - fprintf (afile, "L%s_", - (sym->localof ? sym->localof->name : "-null-")); - fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block); - } -#endif /* if is has an absolute address then generate an equate for this no need to allocate space */ diff --git a/src/pic16/pcode.c b/src/pic16/pcode.c index 8eba5102..9f5522b2 100644 --- a/src/pic16/pcode.c +++ b/src/pic16/pcode.c @@ -6907,10 +6907,12 @@ int instrSize (pCode *pc) */ int isLabel (pCode *pc, char *label) { - if (isPCI(pc) || isPCAD(pc)) { + if (!pc) return 0; + + // label attached to the pCode? + if (isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO) { pBranch *lab = NULL; - if (isPCI(pc)) lab = PCI(pc)->label; - else if (isPCAD(pc)) lab = PCAD(pc)->pci.label; + lab = PCI(pc)->label; while (lab) { if (isPCL(lab->pc) && strcmp(PCL(lab->pc)->label, label) == 0) { @@ -6918,12 +6920,23 @@ int isLabel (pCode *pc, char *label) } lab = lab->next; } // while - } + } // if + + // is inline assembly label? + if (isPCAD(pc) && PCAD(pc)->directive == NULL && PCAD(pc)->arg) { + // do not compare trailing ':' + if (strncmp (PCAD(pc)->arg, label, strlen (label)) == 0) { + return 1; + } + } // if + + // is pCodeLabel? if (isPCL(pc)) { if (strcmp(PCL(pc)->label,label) == 0) { return 1; } - } + } // if + // no label/no label attached/wrong label(s) return 0; } @@ -6933,7 +6946,7 @@ int isLabel (pCode *pc, char *label) * Returns max if the label could not be found or * its distance from pc in (-max..+max). */ -int findpCodeLabel (pCode *pc, char *label, int max) { +int findpCodeLabel (pCode *pc, char *label, int max, pCode **target) { int dist = instrSize(pc); pCode *curr = pc; @@ -6942,7 +6955,10 @@ int findpCodeLabel (pCode *pc, char *label, int max) { curr = curr->prev; dist += instrSize(curr); // sizeof (instruction) } // while - if (curr && dist < max) return -dist; + if (curr && dist < max) { + if (target != NULL) *target = curr; + return -dist; + } dist = 0; curr = pic16_findNextInstruction (pc->next); @@ -6951,33 +6967,15 @@ int findpCodeLabel (pCode *pc, char *label, int max) { dist += instrSize(curr); // sizeof (instruction) curr = curr->next; } // while - if (curr && dist < max) return dist; + if (curr && dist < max) { + if (target != NULL) *target = curr; + return dist; + } + if (target != NULL) *target = NULL; return max; } -/* Returns 0 if the pCode pc is known to NOT be in a jumptable. - * If in doubt (or sure that pc is part of a jumptable), 1 is returned. - */ -int isJumptable (pCode *pc, pCode *prev, pCode *next) -{ - // we might be the last item in a jump table or not in - // jumptable at all -- then we don't care - if (!next || !isPCI(next) || PCI(next)->op != POC_GOTO) - return 0; - - // preceding instruction is a skip instruction (cannot be jumptable) - if (prev && isPCI(prev) && (isPCI_SKIP(prev))) - return 0; - - // GOTOs within a jumptable are unlabelled... - if (next && isPCI(next) && PCI(next)->op == POC_GOTO && PCI(next)->label) - return 0; - - // if in doubt: assume we are in a jumptable - return 1; -} - /* Returns -1 if pc does NOT denote an instruction like * BTFS[SC] STATUS,i * Otherwise we return @@ -7036,15 +7034,21 @@ int hasNoLabel (pCode *pc) pCode *prev; if (!pc) return 1; - // has labels attached? - if (isPCI(pc) && PCI(pc)->label) return 0; - // are there any label pCodes between pc and the previous instruction? prev = pic16_findPrevInstruction (pc->prev); - pc = pc->prev; while (pc && pc != prev) { + // pCode with attached label? + if ((isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO) + && PCI(pc)->label) { + return 0; + } + // is inline assembly label? + if (isPCAD(pc) && PCAD(pc)->directive == NULL) return 0; if (isPCW(pc) && PCW(pc)->label) return 0; + + // pCodeLabel? if (isPCL(pc)) return 0; + pc = pc->prev; } // if @@ -7052,9 +7056,112 @@ int hasNoLabel (pCode *pc) return 1; } +/* Replaces the old pCode with the new one, moving the labels, + * C source line and probably flow information to the new pCode. + */ +void pic16_pCodeReplace (pCode *oldPC, pCode *newPC) { + if (!oldPC || !newPC || !isPCI(oldPC) || !isPCI(newPC)) + return; + + /* first move all labels from old to new */ + PCI(newPC)->label = pic16_pBranchAppend (PCI(oldPC)->label, PCI(newPC)->label); + PCI(oldPC)->label = NULL; + + /* move C source line (if possible) */ + if (PCI(oldPC)->cline && !PCI(newPC)->cline) + PCI(newPC)->cline = PCI(oldPC)->cline; + + /* insert new pCode into pBlock */ + pic16_pCodeInsertAfter (oldPC, newPC); + pic16_unlinkpCode (oldPC); + + /* TODO: update flow (newPC->from, newPC->to) */ + PCI(newPC)->pcflow = PCI(oldPC)->pcflow; + + /* destruct replaced pCode */ + oldPC->destruct (oldPC); +} + +/* Returns the inverted conditional branch (if any) or NULL. + * pcop must be set to the new jump target. + */ +pCode *getNegatedBcc (pCode *bcc, pCodeOp *pcop) +{ + pCode *newBcc; + + if (!bcc || !isPCI(bcc)) return NULL; + + switch (PCI(bcc)->op) { + case POC_BC: newBcc = pic16_newpCode (POC_BNC , pcop); break; + case POC_BZ: newBcc = pic16_newpCode (POC_BNZ , pcop); break; + case POC_BOV: newBcc = pic16_newpCode (POC_BNOV, pcop); break; + case POC_BN: newBcc = pic16_newpCode (POC_BNN , pcop); break; + case POC_BNC: newBcc = pic16_newpCode (POC_BC , pcop); break; + case POC_BNZ: newBcc = pic16_newpCode (POC_BZ , pcop); break; + case POC_BNOV: newBcc = pic16_newpCode (POC_BOV , pcop); break; + case POC_BNN: newBcc = pic16_newpCode (POC_BN , pcop); break; + default: + newBcc = NULL; + } + return newBcc; +} + +#define MAX_DIST_GOTO 0x7FFFFFFF #define MAX_DIST_BRA 1020 #define MAX_DIST_BCC 120 -#define IS_GOTO(arg) ((arg) && isPCI(arg) && (PCI(arg)->op == POC_GOTO)) +#define IS_GOTO(arg) ((arg) && isPCI(arg) && (PCI(arg)->op == POC_GOTO || PCI(arg)->op == POC_BRA)) + +/* Follows GOTO/BRA instructions to their target instructions, stores the + * final destination (not a GOTO or BRA instruction) in target and returns + * the distance from the original pc to *target. + */ +int resolveJumpChain (pCode *pc, pCode **target, pCodeOp **pcop) { + pCode *curr = pc; + pCode *last = NULL; + pCodeOp *lastPCOP = NULL; + int dist = 0; + + /* only follow unconditional branches, except for the initial pCode (which may be a conditional branch) */ + while (curr && isPCI(curr) && (PCI(curr)->op == POC_GOTO || PCI(curr)->op == POC_BRA + || (curr == pc && isConditionalBranch(curr)))) { + last = curr; + lastPCOP = PCI(curr)->pcop; + dist = findpCodeLabel (pc, PCI(curr)->pcop->name, MAX_DIST_GOTO, &curr); + } // while + + if (target) *target = last; + if (pcop) *pcop = lastPCOP; + return dist; +} + +/* Returns pc if it is not a OPT_JUMPTABLE_BEGIN INFO pCode. + * Otherwise the first pCode after the jumptable (after + * the OPT_JUMPTABLE_END tag) is returned. + */ +pCode *skipJumptables (pCode *pc) +{ + if (!pc) return NULL; + + while (pc->type == PC_INFO && PCINF(pc)->type == INF_OPTIMIZATION && PCOO(PCINF(pc)->oper1)->type == OPT_JUMPTABLE_BEGIN) { + do { + pc = pc->next; + } while (pc && (pc->type != PC_INFO || PCINF(pc)->type != INF_OPTIMIZATION + || PCOO(PCINF(pc)->oper1)->type != OPT_JUMPTABLE_END)); + // skip OPT_END as well + if (pc) pc = pc->next; + } // while + + return pc; +} + +pCode *pic16_findNextInstructionSkipJumptables (pCode *pc) +{ + while (pc && !isPCI(pc) && !isPCAD(pc) && !isPCW(pc)) { + pc = skipJumptables (pc->next); + } // while + + return pc; +} /* Turn GOTOs into BRAs if distance between GOTO and label * is less than 1024 bytes. @@ -7069,156 +7176,204 @@ void pic16_OptimizeJumps () pCode *pc_prev = NULL; pCode *pc_next = NULL; pBlock *pb; + pCode *target; + int change, iteration; int isHandled = 0; - int opt=0, toofar=0, jumptabs=0, opt_cond = 0, cond_toofar=0, opt_reorder = 0; + char *label; + int opt=0, toofar=0, opt_cond = 0, cond_toofar=0, opt_reorder = 0, opt_gotonext = 0, opt_gotochain = 0; if (!the_pFile) return; + //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__); + for (pb = the_pFile->pbHead; pb != NULL; pb = pb->next) { - pc = pic16_findNextInstruction (pb->pcHead); + iteration = 1; + int matchedInvertRule = 1; + do { + //fprintf (stderr, "%s:%d: iterating over pBlock %p\n", __FUNCTION__, __LINE__, pb); + change = 0; + pc = pic16_findNextInstruction (pb->pcHead); - while (pc) { - pc_next = pic16_findNextInstruction (pc->next); - // turn GOTOs into BRAs (if absolute distance to label < 1024) - if (IS_GOTO(pc)) { - char *label = PCI(pc)->pcop->name; - int condBraType = isSkipOnStatus(pc_prev); - int dist = findpCodeLabel(pc, label, MAX_DIST_BRA); - if (dist < 0) dist = -dist; - //fprintf (stderr, "distance: %d (", dist); pc->print(stderr, pc);fprintf (stderr, ")\n"); - isHandled = 0; - - if (condBraType != -1 && hasNoLabel(pc)) { - if (dist < MAX_DIST_BCC) { - pCode *bcc = NULL; - switch (condBraType) { - case 0x00: bcc = pic16_newpCode (POC_BC, PCI(pc)->pcop);break; - // no BDC on DIGIT CARRY available - case 0x02: bcc = pic16_newpCode (POC_BZ, PCI(pc)->pcop);break; - case 0x03: bcc = pic16_newpCode (POC_BOV, PCI(pc)->pcop);break; - case 0x04: bcc = pic16_newpCode (POC_BN, PCI(pc)->pcop);break; - case 0x10: bcc = pic16_newpCode (POC_BNC, PCI(pc)->pcop);break; - // no BNDC on DIGIT CARRY available - case 0x12: bcc = pic16_newpCode (POC_BNZ, PCI(pc)->pcop);break; - case 0x13: bcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop);break; - case 0x14: bcc = pic16_newpCode (POC_BNN, PCI(pc)->pcop);break; - default: - // no replacement possible - bcc = NULL; - break; - } // switch - if (bcc) { - // ATTENTION: keep labels attached to BTFSx! - // HINT: GOTO is label free (checked above) - isHandled = 1; - PCI(bcc)->label = PCI(pc_prev)->label; + while (pc) { + pc_next = pic16_findNextInstructionSkipJumptables (pc->next); + + + /* (1) resolve chained jumps + * Do not perform this until pattern (4) is no longer present! Otherwise we will + * (a) leave dead code in and + * (b) skip over the dead code with an (unneccessary) jump. + */ + if (!matchedInvertRule && (IS_GOTO(pc) || isConditionalBranch(pc))) { + pCodeOp *lastTargetOp = NULL; + int newDist = resolveJumpChain (pc, &target, &lastTargetOp); + int maxDist = MAX_DIST_BCC; + if (PCI(pc)->op == POC_BRA) maxDist = MAX_DIST_BRA; + if (PCI(pc)->op == POC_GOTO) maxDist = MAX_DIST_GOTO; + + /* be careful NOT to make the jump instruction longer (might break previously shortened jumps!) */ + if (lastTargetOp && newDist <= maxDist && lastTargetOp != PCI(pc)->pcop + && strcmp (lastTargetOp->name, PCI(pc)->pcop->name) != 0) { + //fprintf (stderr, "(1) ");pc->print(stderr, pc); fprintf (stderr, " --> %s\n", lastTargetOp->name); + if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(1) jump chain resolved")); } + PCI(pc)->pcop->name = lastTargetOp->name; + change++; + opt_gotochain++; + } // if + } // if + + + if (IS_GOTO(pc)) { + label = PCI(pc)->pcop->name; + int condBraType = isSkipOnStatus(pc_prev); + int dist = findpCodeLabel(pc, label, MAX_DIST_BRA, &target); + if (dist < 0) dist = -dist; + //fprintf (stderr, "distance: %d (", dist); pc->print(stderr, pc);fprintf (stderr, ")\n"); + isHandled = 0; + + + /* (2) remove "GOTO label; label:" */ + if (isLabel (pc_next, label)) { + //fprintf (stderr, "(2) GOTO next instruction: ");pc->print(stderr, pc);fprintf (stderr, " --> ");pc_next->print(stderr, pc_next); fprintf(stderr, "\n"); + // first remove all preceeding SKIP instructions + while (pc_prev && isPCI_SKIP(pc_prev)) { + // attach labels on this instruction to pc_next + //fprintf (stderr, "(2) preceeding SKIP removed: ");pc_prev->print(stderr, pc_prev);fprintf(stderr, "\n"); + PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc_prev)->label, PCI(pc_next)->label); PCI(pc_prev)->label = NULL; - pic16_pCodeInsertAfter (pc, bcc); - pic16_pCodeInsertAfter(pc_prev, pic16_newpCodeCharP("goto-optimization 1")); - pc_prev->destruct(pc_prev); - pc->destruct(pc); - pc = bcc; - opt_cond++; + if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(2) SKIP removed")); } + pic16_unlinkpCode (pc_prev); + pc_prev = pic16_findPrevInstruction (pc); + } // while + // now remove the redundant goto itself + PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc)->label, PCI(pc_next)->label); + if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP("(2) GOTO next instruction removed")); } + pic16_unlinkpCode (pc); + pc = pic16_findPrevInstruction(pc_next->prev); + isHandled = 1; // do not perform further optimizations + opt_gotonext++; + change++; + } // if + + + /* (3) turn BTFSx STATUS,i; GOTO label into Bcc label if possible */ + if (!isHandled && condBraType != -1 && hasNoLabel(pc)) { + if (dist < MAX_DIST_BCC) { + pCode *bcc = NULL; + switch (condBraType) { + case 0x00: bcc = pic16_newpCode (POC_BC, PCI(pc)->pcop);break; + // no BDC on DIGIT CARRY available + case 0x02: bcc = pic16_newpCode (POC_BZ, PCI(pc)->pcop);break; + case 0x03: bcc = pic16_newpCode (POC_BOV, PCI(pc)->pcop);break; + case 0x04: bcc = pic16_newpCode (POC_BN, PCI(pc)->pcop);break; + case 0x10: bcc = pic16_newpCode (POC_BNC, PCI(pc)->pcop);break; + // no BNDC on DIGIT CARRY available + case 0x12: bcc = pic16_newpCode (POC_BNZ, PCI(pc)->pcop);break; + case 0x13: bcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop);break; + case 0x14: bcc = pic16_newpCode (POC_BNN, PCI(pc)->pcop);break; + default: + // no replacement possible + bcc = NULL; + break; + } // switch + if (bcc) { + // ATTENTION: keep labels attached to BTFSx! + // HINT: GOTO is label free (checked above) + //fprintf (stderr, "%s:%d: (3) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(bcc)->mnemonic, label); + isHandled = 1; // do not perform further optimizations + if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(3) conditional branch introduced")); } + pic16_pCodeReplace (pc_prev, bcc); + pc->destruct(pc); + pc = bcc; + opt_cond++; + change++; + } // if + } else { + //fprintf (stderr, "(%d, too far for Bcc)\n", dist); + cond_toofar++; } // if - } else { - //fprintf (stderr, "(%d, too far for Bcc)\n", dist); - cond_toofar++; } // if - } // if - if (!isHandled) { - // eliminate the following (common) tripel: - // ; - // labels1: Bcc label2; - // GOTO somewhere; ; <-- instruction referenced by pc - // label2: - // and replace it by - // labels1: B#(cc) somewhere; ; #(cc) is the negated condition cc - // label2: - // ATTENTION: all labels pointing to "Bcc label2" must be attached - // to instead - // ATTENTION: This optimization is only valid if is - // not a skip operation! - // ATTENTION: somewhere must be within MAX_DIST_BCC bytes! - // ATTENTION: no label may be attached to the GOTO instruction! - if (isConditionalBranch(pc_prev) - && (!isPCI_SKIP(pic16_findPrevInstruction(pc_prev->prev))) - && (dist < MAX_DIST_BCC) - && isLabel(pc_next,PCI(pc_prev)->pcop->name) - && hasNoLabel(pc)) { - pCode *newBcc = NULL; - switch (PCI(pc_prev)->op) { - case POC_BC: newBcc = pic16_newpCode (POC_BNC , PCI(pc)->pcop); break; - case POC_BZ: newBcc = pic16_newpCode (POC_BNZ , PCI(pc)->pcop); break; - case POC_BOV: newBcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop); break; - case POC_BN: newBcc = pic16_newpCode (POC_BNN , PCI(pc)->pcop); break; - case POC_BNC: newBcc = pic16_newpCode (POC_BC , PCI(pc)->pcop); break; - case POC_BNZ: newBcc = pic16_newpCode (POC_BZ , PCI(pc)->pcop); break; - case POC_BNOV: newBcc = pic16_newpCode (POC_BOV , PCI(pc)->pcop); break; - case POC_BNN: newBcc = pic16_newpCode (POC_BN , PCI(pc)->pcop); break; - default: - newBcc = NULL; - } + if (!isHandled) { + // (4) eliminate the following (common) tripel: + // ; + // labels1: Bcc label2; + // GOTO somewhere; ; <-- instruction referenced by pc + // label2: + // and replace it by + // labels1: B#(cc) somewhere; ; #(cc) is the negated condition cc + // label2: + // ATTENTION: all labels pointing to "Bcc label2" must be attached + // to instead + // ATTENTION: This optimization is only valid if is + // not a skip operation! + // ATTENTION: somewhere must be within MAX_DIST_BCC bytes! + // ATTENTION: no label may be attached to the GOTO instruction! + if (isConditionalBranch(pc_prev) + && (!isPCI_SKIP(pic16_findPrevInstruction(pc_prev->prev))) + && (dist < MAX_DIST_BCC) + && isLabel(pc_next,PCI(pc_prev)->pcop->name) + && hasNoLabel(pc)) { + pCode *newBcc = getNegatedBcc (pc_prev, PCI(pc)->pcop); - if (newBcc) { - PCI(newBcc)->label = PCI(pc_prev)->label; - PCI(pc_prev)->label = NULL; - - pic16_pCodeInsertAfter(pc_prev, newBcc); - pic16_pCodeInsertAfter(pc_prev, pic16_newpCodeCharP("goto-optimization 2")); - pc->destruct(pc); - pc->destruct(pc_prev); - pc = newBcc; - isHandled = 1; - opt_reorder++; + if (newBcc) { + //fprintf (stderr, "%s:%d: (4) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBcc)->mnemonic, label); + isHandled = 1; // do not perform further optimizations + if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(4) conditional skipping branch inverted")); } + pic16_pCodeReplace (pc_prev, newBcc); + pc->destruct(pc); + pc = newBcc; + opt_reorder++; + change++; + matchedInvertRule++; + } } } - } - - if (!isHandled) { - // now just turn GOTO into BRA - if (!isJumptable(pc, pc_prev, pc_next)) { + + /* (5) now just turn GOTO into BRA */ + if (!isHandled && (PCI(pc)->op == POC_GOTO)) { if (dist < MAX_DIST_BRA) { pCode *newBra = pic16_newpCode (POC_BRA, PCI(pc)->pcop); - isHandled = 1; - PCI(newBra)->label = PCI(pc)->label; - pic16_pCodeInsertAfter (pc, newBra); - pic16_pCodeInsertAfter(pc_prev, pic16_newpCodeCharP("goto-optimization 3")); - pc->destruct(pc); + //fprintf (stderr, "%s:%d: (5) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBra)->mnemonic, label); + if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc->prev, pic16_newpCodeCharP("(5) GOTO replaced by BRA")); } + pic16_pCodeReplace (pc, newBra); pc = newBra; opt++; + change++; } else { //fprintf (stderr, "(%d, too far for BRA)\n", dist); toofar++; } - } else { - //fprintf (stderr, "(in jumptable)\n"); - jumptabs++; - } - } // if (!isHandled) - } // if + } // if (!isHandled) + } // if - pc_prev = pc; - pc = pc_next; - } // while (pc) + pc_prev = pc; + pc = pc_next; + } // while (pc) + + pBlockRemoveUnusedLabels (pb); + + // This line enables goto chain resolution! + if (matchedInvertRule > 1) matchedInvertRule = 1; else matchedInvertRule = 0; + + iteration++; + } while (change); /* fixpoint iteration per pBlock */ } // for (pb) // emit some statistics concerning goto-optimization // (maybe this should be moved to the general statistics?) - fprintf (stderr, "optimize-goto: %d GOTO->BRA; (%d GOTOs too far and " - "%d GOTOs in jumptables ignored); " - "%d BTFSx, GOTO->Bcc (%d too far), %d jumps reordered\n", - opt, toofar, jumptabs, opt_cond, cond_toofar, opt_reorder); - /* - fprintf (stderr, "saved %d + %d + %d = %d bytes in program memory\n", - (4 - 2) * opt, - (6 - 2) * opt_cond, - (6 - 2) * opt_reorder, - (4 - 2) * opt + (6 - 2) * opt_cond + (6 - 2) * opt_reorder); - */ + if (pic16_debug_verbose || pic16_pcode_verbose) { + fprintf (stderr, "optimize-goto:\n" + "\t%5d GOTO->BRA; (%d GOTOs too far)\n" + "\t%5d BTFSx, GOTO->Bcc (%d too far)\n" + "\t%5d conditional \"skipping\" jumps inverted\n" + "\t%5d GOTOs to next instruction removed\n" + "\t%5d chained GOTOs resolved\n", + opt, toofar, opt_cond, cond_toofar, opt_reorder, opt_gotonext, opt_gotochain); + } // if } #undef IS_GOTO +#undef MAX_DIST_GOTO #undef MAX_DIST_BRA #undef MAX_DIST_BCC diff --git a/src/pic16/pcode.h b/src/pic16/pcode.h index 41f86412..43dd89f4 100644 --- a/src/pic16/pcode.h +++ b/src/pic16/pcode.h @@ -326,6 +326,8 @@ typedef enum { OPT_BEGIN, /* mark beginning of optimization block */ OPT_END, /* mark ending of optimization block */ + OPT_JUMPTABLE_BEGIN, /* mark beginning of a jumptable */ + OPT_JUMPTABLE_END /* mark end of jumptable */ } OPT_TYPE; /*********************************************************************** diff --git a/src/pic16/ralloc.c b/src/pic16/ralloc.c index 79351a97..a0523c99 100644 --- a/src/pic16/ralloc.c +++ b/src/pic16/ralloc.c @@ -881,7 +881,12 @@ pic16_allocDirReg (operand *op ) // fprintf(stderr, "%s:%d adding %s in direct registers\n", __FILE__, __LINE__, reg->name); // addSet(&pic16_dynDirectRegs, reg); - checkAddReg(&pic16_dynDirectRegs, reg); +#if 1 + if(!(IS_STATIC(OP_SYM_ETYPE(op)) + && OP_SYMBOL(op)->ival + )) +#endif + checkAddReg(&pic16_dynDirectRegs, reg); } } else {