0,0, // dest, bit instruction
0,0, // branch, skip
POC_NOP,
- PCC_W, // inCond
+ (PCC_W | PCC_LITERAL), // inCond
(PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
};
0,0, // dest, bit instruction
0,0, // branch, skip
POC_NOP,
- PCC_W, // inCond
+ (PCC_W | PCC_LITERAL), // inCond
(PCC_W | PCC_Z) // outCond
};
1,1, // dest, bit instruction
0,0, // branch, skip
POC_BSF,
- PCC_REGISTER, // inCond
+ (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
PCC_REGISTER // outCond
};
1,1, // dest, bit instruction
0,0, // branch, skip
POC_BCF,
- PCC_REGISTER, // inCond
- PCC_REGISTER // outCond
+ (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
+ (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
};
pCodeInstruction pciBTFSC = {
0,1, // dest, bit instruction
1,1, // branch, skip
POC_BTFSS,
- PCC_REGISTER, // inCond
- PCC_NONE // outCond
+ (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
+ PCC_EXAMINE_PCOP // outCond
};
pCodeInstruction pciBTFSS = {
0,1, // dest, bit instruction
1,1, // branch, skip
POC_BTFSC,
- PCC_REGISTER, // inCond
- PCC_NONE // outCond
+ (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
+ PCC_EXAMINE_PCOP // outCond
};
pCodeInstruction pciCALL = {
0,0, // dest, bit instruction
0,0, // branch, skip
POC_NOP,
- PCC_W, // inCond
+ (PCC_W | PCC_LITERAL), // inCond
(PCC_W | PCC_Z) // outCond
};
0,0, // dest, bit instruction
0,0, // branch, skip
POC_NOP,
- PCC_NONE, // inCond
+ (PCC_NONE | PCC_LITERAL), // inCond
PCC_W // outCond
};
0,0, // dest, bit instruction
1,0, // branch, skip
POC_NOP,
- PCC_NONE, // inCond
+ PCC_LITERAL, // inCond
PCC_W // outCond
};
0,0, // dest, bit instruction
0,0, // branch, skip
POC_NOP,
- PCC_W, // inCond
+ (PCC_W | PCC_LITERAL), // inCond
(PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
};
0,0, // dest, bit instruction
0,0, // branch, skip
POC_NOP,
- PCC_W, // inCond
+ (PCC_W | PCC_LITERAL), // inCond
(PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
};
memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
pci->pcop = pcop;
- if(pci->inCond == PCC_EXAMINE_PCOP)
- pci->inCond = RegCond(pcop);
+ if(pci->inCond & PCC_EXAMINE_PCOP)
+ pci->inCond |= RegCond(pcop);
- if(pci->outCond == PCC_EXAMINE_PCOP)
- pci->outCond = RegCond(pcop);
+ if(pci->outCond & PCC_EXAMINE_PCOP)
+ pci->outCond |= RegCond(pcop);
pci->pc.prev = pci->pc.next = NULL;
return (pCode *)pci;
pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
pcop->type = PO_IMMEDIATE;
if(name) {
+ regs *r = dirregWithName(name);
pcop->name = Safe_strdup(name);
+ PCOI(pcop)->r = r;
+ if(r) {
+ //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
+ PCOI(pcop)->rIdx = r->rIdx;
+ } else {
+ //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
+ PCOI(pcop)->rIdx = -1;
+ }
//fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
} else {
pcop->name = NULL;
}
-
PCOI(pcop)->index = index;
PCOI(pcop)->offset = offset;
PCOI(pcop)->_const = code_space;
/*-----------------------------------------------------------------*/
regs * getRegFromInstruction(pCode *pc)
{
+
if(!pc ||
!isPCI(pc) ||
!PCI(pc)->pcop ||
return PCOR(PCI(pc)->pcop)->r;
case PO_IMMEDIATE:
+ if(PCOI(PCI(pc)->pcop)->r)
+ return (PCOI(PCI(pc)->pcop)->r);
+
//fprintf(stderr, "getRegFromInstruction - immediate\n");
- return NULL; // PCOR(PCI(pc)->pcop)->r;
+ return dirregWithName(PCI(pc)->pcop->name);
+ //return NULL; // PCOR(PCI(pc)->pcop)->r;
case PO_GPR_BIT:
return PCOR(PCI(pc)->pcop)->r;
// for(pb = the_pFile->pbHead; pb; pb = pb->next)
pCodeRegOptimizeRegUsage();
+ OptimizepCode('*');
+
/*
for(pb = the_pFile->pbHead; pb; pb = pb->next)
DumpFlow(pb);
static void tokenizeLineNode(char *ln)
{
-
+ char *lnstart=ln;
tokIdx = 0; // Starting off at the beginning
tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
if(!ln || !*ln)
return;
+
while(*ln) {
if(isspace(*ln)) {
tokArr[tokIdx].tok.s = Safe_strdup(buffer);
tokArr[tokIdx++].tt = PCT_STRING;
+ } else {
+ fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
+ fprintf(stderr, "Line: %s\n",lnstart);
+ fprintf(stderr, "Token: '%c'\n",*ln);
+ exit(1);
}
}
state = PS_HAVE_COMMA;
} else
fprintf(stderr," unexpected comma\n");
+ break;
+
}
matching = 1;
peepRuleBlock2pCodeBlock(pr->match, ¤tRule->target);
//DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
- //printpBlock(stderr, curBlock);
+ //printpBlock(stderr, currentRule->target.pb);
//DFPRINTF((stderr,"target with labels merged:\n"));
//pBlockMergeLabels(curBlock);
/*-----------------------------------------------------------------*/
int pCodeSearchCondition(pCode *pc, unsigned int cond)
{
-
+ //fprintf(stderr,"Checking conditions %d\n",cond);
while(pc) {
/* If we reach a function end (presumably an end since we most
if(pc->type == PC_OPCODE) {
//fprintf(stderr," checking conditions of: ");
//pc->print(stderr,pc);
+ //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
if(PCI(pc)->inCond & cond)
return 1;
if(PCI(pc)->outCond & cond)
return 0; // different types
}
+ if(pcops->type == PO_LITERAL) {
+
+ if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
+ return 1;
+
+ return 0;
+ }
+
b[0]=0;
get_op(pcops,b,50);
if(PCI(pcd)->pcop) {
if (PCI(pcd)->pcop->type == PO_WILD) {
index = PCOW(PCI(pcd)->pcop)->id;
-
//DFPRINTF((stderr,"destination is wild\n"));
#ifdef DEBUG_PCODEPEEP
if (index > peepBlock->nops) {
}
}
+ } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
+ return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
+
}
/* FIXME - need an else to check the case when the destination
* isn't a wild card */
if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
-
index = PCW(pcd)->id;
#ifdef PCODE_DEBUG
DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
int i;
if(!pcp)
return;
-
+/*
DFPRINTF((stderr," Clearing peep rule vars\n"));
DFPRINTF((stderr," %d %d %d %d %d %d\n",
pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
-
+*/
for(i=0;i<pcp->target.nvars; i++)
pcp->target.vars[i] = NULL;
for(i=0;i<pcp->target.nops; i++)
}
}
- if(matched) {
+ if(matched && pcin) {
- //pCode *pcr = peepBlock->replace.pb->pcHead;
- //if(pcr) pcr->print(stderr,pcr);
-
/* So far we matched the rule up to the point of the conditions .
* In other words, all of the opcodes match. Now we need to see
* if the post conditions are satisfied.
* the `postFalseCond' as input then we abort the match
*/
DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
+ //pcin->print(stderr,pcin);
+
if (pcin && peepBlock->postFalseCond &&
(pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
matched = 0;
- if(!matched) fprintf(stderr,"failed on conditions\n");
+ //fprintf(stderr," condition results = %d\n",pCodeSearchCondition(pcin,peepBlock->postFalseCond));
+
+
+ //if(!matched) fprintf(stderr,"failed on conditions\n");
}
if(matched) {
pcin->prev = pc->prev;
-#if 0
+ //#if 0
{
/* DEBUG */
/* Converted the deleted pCodes into comments */
if(pc_cline2)
pc_cline2->pc.next = NULL;
}
-#endif
+ //#endif
if(pcin)
pCodeDeleteChain(pc,pcin);
extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
extern void dbg_dumpregusage(void);
+extern pCode * findPrevInstruction(pCode *pci);
void unlinkpCode(pCode *pc);
int total_registers_saved=0;
for (reg = setFirstItem(fregs) ; reg ;
reg = setNextItem(fregs)) {
-
- fprintf (stderr, "%s addr=0x%03x rIdx=0x%03x",
- reg->name,
- reg->address,
- reg->rIdx);
-
- pcfl = setFirstItem(reg->reglives.usedpFlows);
- if(pcfl)
- fprintf(stderr, "\n used in seq");
-
- while(pcfl) {
- fprintf(stderr," 0x%03x",pcfl->seq);
- pcfl = setNextItem(reg->reglives.usedpFlows);
- }
- pcfl = setFirstItem(reg->reglives.assignedpFlows);
- if(pcfl)
- fprintf(stderr, "\n assigned in seq");
+ if(elementsInSet(reg->reglives.usedpCodes)) {
+
+ fprintf (stderr, "%s addr=0x%03x rIdx=0x%03x",
+ reg->name,
+ reg->address,
+ reg->rIdx);
- while(pcfl) {
- fprintf(stderr," 0x%03x",pcfl->seq);
- pcfl = setNextItem(reg->reglives.assignedpFlows);
- }
+ pcfl = setFirstItem(reg->reglives.usedpFlows);
+ if(pcfl)
+ fprintf(stderr, "\n used in seq");
- pc = setFirstItem(reg->reglives.usedpCodes);
- if(pc)
- fprintf(stderr, "\n used in instructions ");
+ while(pcfl) {
+ fprintf(stderr," 0x%03x",pcfl->seq);
+ pcfl = setNextItem(reg->reglives.usedpFlows);
+ }
- while(pc) {
- pcfl = PCODE(PCI(pc)->pcflow);
+ pcfl = setFirstItem(reg->reglives.assignedpFlows);
if(pcfl)
- fprintf(stderr," 0x%03x:",pcfl->seq);
- fprintf(stderr,"0x%03x",pc->seq);
+ fprintf(stderr, "\n assigned in seq");
- pc = setNextItem(reg->reglives.usedpCodes);
- }
+ while(pcfl) {
+ fprintf(stderr," 0x%03x",pcfl->seq);
+ pcfl = setNextItem(reg->reglives.assignedpFlows);
+ }
+
+ pc = setFirstItem(reg->reglives.usedpCodes);
+ if(pc)
+ fprintf(stderr, "\n used in instructions ");
- fprintf(stderr, "\n");
+ while(pc) {
+ pcfl = PCODE(PCI(pc)->pcflow);
+ if(pcfl)
+ fprintf(stderr," 0x%03x:",pcfl->seq);
+ fprintf(stderr,"0x%03x",pc->seq);
+
+ pc = setNextItem(reg->reglives.usedpCodes);
+ }
+ fprintf(stderr, "\n");
+ }
}
}
addSetIfnotP(& (PCFL(pcfl)->registers), reg);
- if(PCC_REGISTER & PCI(pc)->inCond)
+ if((PCC_REGISTER | PCC_LITERAL) & PCI(pc)->inCond)
addSetIfnotP(& (reg->reglives.usedpFlows), pcfl);
if(PCC_REGISTER & PCI(pc)->outCond)
}
- //dbg_dumpregusage();
+// dbg_dumpregusage();
}
*-----------------------------------------------------------------*/
static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, regs *reg)
{
+ if(!reg)
+ return;
+
+ if(pc1) {
+ deleteSetItem (&(reg->reglives.usedpCodes),pc1);
+ pc1->destruct(pc1);
+ }
- deleteSetItem (&(reg->reglives.usedpCodes),pc1);
- deleteSetItem (&(reg->reglives.usedpCodes),pc2);
- deleteSetItem (&(PCFL(pcflow)->registers), reg);
+ if(pc2) {
+ deleteSetItem (&(reg->reglives.usedpCodes),pc2);
+ pc2->destruct(pc2);
- pc1->destruct(pc1);
- pc2->destruct(pc2);
+ deleteSetItem (&(PCFL(pcflow)->registers), reg);
+
+ reg->isFree = 1;
+ reg->wasUsed = 0;
+
+ }
- reg->isFree = 1;
- reg->wasUsed = 0;
pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
}
while(fregs) {
+ pCode *pcfl_used, *pcfl_assigned;
/* Step through the set by directly accessing the 'next' pointer.
* We could also step through by using the set API, but the
reg = fregs->item;
fregs = fregs->next;
- used = elementsInSet(reg->reglives.usedpCodes);
+ pcfl_used = setFirstItem(reg->reglives.usedpFlows);
+ pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows);
+
+ used = elementsInSet(reg->reglives.usedpCodes);
if(used == 2) {
- pCode *pcfl_used, *pcfl_assigned;
+ /*
+ * In this section, all registers that are used in only in two
+ * instructions are examined. If possible, they're optimized out.
+ */
+
pCode *pc1, *pc2;
- pCode *t;
+ pCode *pct1, *pct2; /* two temporaries */
+ regs *reg1, *reg2;
- /* This register has only been used twice. Chances are we can
- get rid of it */
/*
fprintf (stderr, "OptimizeRegUsage: %s addr=0x%03x rIdx=0x%03x used=%d\n",
reg->name,
reg->address,
reg->rIdx, used);
*/
- pcfl_used = setFirstItem(reg->reglives.usedpFlows);
- pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows);
-
pc1 = setFirstItem(reg->reglives.usedpCodes);
pc2 = setNextItem(reg->reglives.usedpCodes);
expected case - the register has been assigned a value and is
subsequently used
*/
+
//fprintf(stderr," used only twice\n");
if(pcfl_used->seq == pcfl_assigned->seq) {
//fprintf(stderr, " and used in same flow\n");
if(pc2->seq < pc1->seq) {
- t = pc2;
+ pct1 = pc2;
pc2 = pc1;
- pc1 = t;
+ pc1 = pct1;
}
//pc1->print(stderr,pc1);
//pc2->print(stderr,pc2);
- /* ADHOC pattern checking */
+ /* ADHOC pattern checking
+ * Now look for specific sequences that are easy to optimize.
+ * Many of these sequences are characteristic of the compiler
+ * (i.e. it'd probably be a waste of time to apply these adhoc
+ * checks to hand written assembly.)
+ *
+ */
if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
+
+ /*
+ clrf reg
+ stuff...
+ movf reg,w
+
+ can be replaced with
+
+ stuff...
+ movlw 0
+ */
+
pCode *newpc;
//fprintf(stderr, " CLRF/MOVFW. instruction after MOVFW is:\n");
- t = findNextInstruction(pc2->next);
+ pct1 = findNextInstruction(pc2->next);
//t->print(stderr,t);
- if(PCI(t)->op == POC_MOVWF) {
- newpc = newpCode(POC_CLRF, PCI(t)->pcop);
+ if(PCI(pct1)->op == POC_MOVWF) {
+ newpc = newpCode(POC_CLRF, PCI(pct1)->pcop);
+ pct1->destruct(pct1);
} else {
newpc = newpCode(POC_MOVLW, newpCodeOpLit(0));
}
+ pCodeInsertAfter(pc2, newpc);
PCI(newpc)->pcflow = PCFL(pcfl_used);
- newpc->seq = t->seq;
-
- pCodeInsertAfter(t, newpc);
+ newpc->seq = pc2->seq;
- t->destruct(t);
Remove2pcodes(pcfl_used, pc1, pc2, reg);
total_registers_saved++; // debugging stats.
Remove2pcodes(pcfl_used, pc1, pc2, reg);
total_registers_saved++; // debugging stats.
- } else if((PCI(pc1)->op == POC_MOVWF) && (PCI(pc2)->op == POC_MOVFW) ){
- //fprintf(stderr, " MOVWF/MOVFW. instruction after MOVFW is:\n");
- t = findNextInstruction(pc2->next);
- // t->print(stderr,t);
-
- if(PCI(t)->op == POC_MOVWF) {
- regs *nextreg = getRegFromInstruction(t);
- if(nextreg && !regUsedinRange(pc1,pc2,nextreg)) {
- t->seq = pc1->seq;
- unlinkpCode(t);
- pCodeInsertAfter(pc1,t);
+ } else if(PCI(pc1)->op == POC_MOVWF) {
+
+ pct2 = findNextInstruction(pc2->next);
+
+ if(PCI(pc2)->op == POC_MOVFW) {
+ //fprintf(stderr, " MOVWF/MOVFW. instruction after MOVFW is:\n");
+ // t->print(stderr,t);
+
+ if(PCI(pct2)->op == POC_MOVWF) {
+ reg2 = getRegFromInstruction(pct2);
+ if(reg2 && !regUsedinRange(pc1,pc2,reg2)) {
+ pct2->seq = pc1->seq;
+ unlinkpCode(pct2);
+ pCodeInsertAfter(pc1,pct2);
+ Remove2pcodes(pcfl_used, pc1, pc2, reg);
+ total_registers_saved++; // debugging stats.
+ continue;
+ }
+ }
+ }
+
+ pct1 = findPrevInstruction(pc1->prev);
+ if(pct1 &&
+ (PCI(pct1)->pcflow == PCI(pc1)->pcflow) &&
+ (PCI(pct1)->op == POC_MOVFW)) {
+
+ reg1 = getRegFromInstruction(pct1);
+ if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
+ /*
+ movf reg1,w
+ movwf reg
+
+ stuff...
+ opcode reg,w
+ */
+ pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
+ pCodeInsertAfter(pc2, pct2);
+ PCI(pct2)->pcflow = PCFL(pcfl_used);
+ pct2->seq = pc2->seq;
+
Remove2pcodes(pcfl_used, pc1, pc2, reg);
+ Remove2pcodes(pcfl_used, pct1, NULL, reg1);
total_registers_saved++; // debugging stats.
+
}
}
+
+
}
} else {
/*
register has been used twice without ever being assigned */
fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name);
+
} else {
- fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
+ //fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
+ Remove2pcodes(pcfl_assigned, pc1, pc2, reg);
+ total_registers_saved++; // debugging stats.
}
} else {
- //if(used) fprintf (stderr, " over used OptimizeRegUsage: %s used=%d\n", reg->name, used);
-
- }
- }
+ if(used && !pcfl_used && pcfl_assigned) {
+ pCode *pc;
-#if 0
- pcfl = setFirstItem(reg->reglives.usedpFlows);
- if(pcfl)
- fprintf(stderr, "\n used in seq");
+ //fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
- while(pcfl) {
- fprintf(stderr," 0x%03x",pcfl->seq);
- pcfl = setNextItem(reg->reglives.usedpFlows);
- }
+ pc = setFirstItem(reg->reglives.usedpCodes);
+ while(pc) {
+ pcfl_assigned = PCI(pc)->pcflow;
+ deleteSetItem (&(PCFL(pcfl_assigned)->registers), reg);
+ deleteSetItem (&(reg->reglives.usedpCodes),pc);
+ pc->destruct(pc);
- pcfl = setFirstItem(reg->reglives.assignedpFlows);
- if(pcfl)
- fprintf(stderr, "\n assigned in seq");
+ pc = setNextItem(reg->reglives.usedpCodes);
+ }
- while(pcfl) {
- fprintf(stderr," 0x%03x",pcfl->seq);
- pcfl = setNextItem(reg->reglives.assignedpFlows);
- }
- pc = setFirstItem(reg->reglives.usedpCodes);
- if(pc)
- fprintf(stderr, "\n used in instructions ");
+ reg->isFree = 1;
+ reg->wasUsed = 0;
- while(pc) {
- pcfl = PCODE(PCI(pc)->pcflow);
- if(pcfl)
- fprintf(stderr," 0x%03x:",pcfl->seq);
- fprintf(stderr,"0x%03x",pc->seq);
+ total_registers_saved++; // debugging stats.
+ }
- pc = setNextItem(reg->reglives.usedpCodes);
}
- fprintf(stderr, "\n");
-
}
-#endif
+
}
/*-----------------------------------------------------------------*
* void pCodeRegOptimeRegUsage(pBlock *pb)
/* Identify registers used in one flow sequence */
OptimizeRegUsage(dynAllocRegs);
+ OptimizeRegUsage(dynStackRegs);
+ OptimizeRegUsage(dynDirectRegs);
if(total_registers_saved != saved)
fprintf(stderr, " *** Saved %d registers, total saved %d ***\n", total_registers_saved-saved,total_registers_saved);
} while( passes-- && (total_registers_saved != saved));
+/*
+ fprintf(stderr,"dynamically allocated regs:\n");
+ dbg_regusage(dynAllocRegs);
+ fprintf(stderr,"stack regs:\n");
+ dbg_regusage(dynStackRegs);
+ fprintf(stderr,"direct regs:\n");
+ dbg_regusage(dynDirectRegs);
+*/
+
}