+2004-12-20 Vangelis Rokas <vrokas AT otenet.gr>
+
+ * 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 <sourceforge.brock AT dse.nl>
* src/ds390/gen.c (genCpl): fixed bit=~(char/bit) bugs, added warning
do {
a<<=1;
exp--;
- } while (a > HIDDEN);
+ } while (a < HIDDEN);
}
#if 0
/*-----------------------------------------------------------------*/
FILE *createDumpFile (int id) {
struct _dumpFiles *dumpFilesPtr=dumpFiles;
-
+ static int dumpIndex=0;
+ static char dumpIndexStr[32];
+
while (dumpFilesPtr->id) {
if (dumpFilesPtr->id==id)
break;
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;
}
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 */
static void
geniCodeReceive (value * args)
{
+ unsigned char paramByteCounter = 0;
+
/* for all arguments that are passed in registers */
while (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);
}
}
}
}
+// fprintf(stderr, "%s:%d IS_SYMOP left\t", __FILE__, __LINE__);printOperand(IC_LEFT(ic), stderr);
+// fprintf(stderr, "\n");
}
if (IS_SYMOP(IC_RIGHT(ic)))
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)))
/* 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)))
{
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);
for(i=0;i<aop->size;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]));
}
if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
for(i=0;i<aop->size;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)));
}
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__);
/*-----------------------------------------------------------------*/
/* 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);
/* 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);
offset++;
// debugf("receive from WREG\n", 0);
}
+ GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
}
// GpsuedoStkPtr++;
_G.stack_lat = AOP_SIZE(oper)-1;
while (size) {
size--;
GpsuedoStkPtr++;
- popaopidx(AOP(oper), offset, GpsuedoStkPtr);
+ popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
// debugf("receive from STACK\n", 0);
offset++;
}
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));
}
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;
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;
}
}
/* 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 */
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;
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;
}
// 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))
} 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) ) {
#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))) {
pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
}
+ pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
}
}
} 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);
}
const char *pic16_pCodeOpType( pCodeOp *pcop);
int pic16_my_powof2 (unsigned long num);
+void mov2w (asmop *aop, int offset);
void dumpiCode(iCode *lic);
#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
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;
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));
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;
}
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 {
/* 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));
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;
}
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++;
}
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));
} 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));
// 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));
// add first bytes
for(i=0; i<size; i++) {
if (AOP_TYPE(right) != AOP_ACC)
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),i));
+ mov2w(AOP(right),i);
if (pic16_sameRegs(AOP(left), AOP(result)))
{
if(i) { // add with carry
pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
} else { // not same
- D_POS (">>> 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 {
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));
}
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));
}
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));
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));
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));
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");
}
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));
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));
}
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));
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)));
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)));
} 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)));
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));
#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
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)));
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)));
} 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)));
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));
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
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);
}
}
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);
/* 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
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);
}
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 */
*/
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) {
}
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;
}
* 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;
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);
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
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
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.
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:
- // <pred.>;
- // labels1: Bcc label2;
- // GOTO somewhere; ; <-- instruction referenced by pc
- // label2: <cont.>
- // and replace it by
- // labels1: B#(cc) somewhere; ; #(cc) is the negated condition cc
- // label2: <cont.>
- // ATTENTION: all labels pointing to "Bcc label2" must be attached
- // to <cont.> instead
- // ATTENTION: This optimization is only valid if <pred.> 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:
+ // <pred.>;
+ // labels1: Bcc label2;
+ // GOTO somewhere; ; <-- instruction referenced by pc
+ // label2: <cont.>
+ // and replace it by
+ // labels1: B#(cc) somewhere; ; #(cc) is the negated condition cc
+ // label2: <cont.>
+ // ATTENTION: all labels pointing to "Bcc label2" must be attached
+ // to <cont.> instead
+ // ATTENTION: This optimization is only valid if <pred.> 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
{
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;
/***********************************************************************
// 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 {