+ pBranchLink(pc,findNextInstruction(pc->next));
+ pBranchLink(pc,findNextInstruction(pc->next->next));
+
+}
+
+static void AnalyzeRETURN(pCode *pc)
+{
+
+ // branch_link(pc,findFunctionEnd(pc->next));
+
+}
+
+#endif
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+regs * getRegFromInstruction(pCode *pc)
+{
+ if(!pc ||
+ !isPCI(pc) ||
+ !PCI(pc)->pcop ||
+ PCI(pc)->num_ops == 0 )
+ return NULL;
+
+ switch(PCI(pc)->pcop->type) {
+ case PO_INDF:
+ case PO_FSR:
+ return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
+
+ case PO_BIT:
+ case PO_GPR_TEMP:
+ fprintf(stderr, "getRegFromInstruction - bit or temp\n");
+ return PCOR(PCI(pc)->pcop)->r;
+
+ case PO_IMMEDIATE:
+ fprintf(stderr, "getRegFromInstruction - immediate\n");
+ return NULL; // PCOR(PCI(pc)->pcop)->r;
+
+ case PO_GPR_BIT:
+ return PCOR(PCI(pc)->pcop)->r;
+
+ case PO_DIR:
+ fprintf(stderr, "getRegFromInstruction - dir\n");
+ //return NULL; PCOR(PCI(pc)->pcop)->r;
+ return PCOR(PCI(pc)->pcop)->r;
+ case PO_LITERAL:
+ fprintf(stderr, "getRegFromInstruction - literal\n");
+ break;
+
+ default:
+ fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
+ genericPrint(stderr, pc);
+ break;
+ }
+
+ return NULL;
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+void AnalyzepBlock(pBlock *pb)
+{
+ pCode *pc;
+
+ if(!pb)
+ return;
+
+ /* Find all of the registers used in this pBlock
+ * by looking at each instruction and examining it's
+ * operands
+ */
+ for(pc = pb->pcHead; pc; pc = pc->next) {
+
+ /* Is this an instruction with operands? */
+ if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
+
+ if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
+
+ /* Loop through all of the registers declared so far in
+ this block and see if we find this one there */
+
+ regs *r = setFirstItem(pb->tregisters);
+
+ while(r) {
+ if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
+ PCOR(PCI(pc)->pcop)->r = r;
+ break;
+ }
+ r = setNextItem(pb->tregisters);
+ }
+
+ if(!r) {
+ /* register wasn't found */
+ r = Safe_calloc(1, sizeof(regs));
+ memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
+ addSet(&pb->tregisters, r);
+ PCOR(PCI(pc)->pcop)->r = r;
+ //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
+ }/* else
+ fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
+ */
+ }
+ if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
+ if(PCOR(PCI(pc)->pcop)->r) {
+ pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
+ DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
+ } else {
+ if(PCI(pc)->pcop->name)
+ fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
+ else
+ fprintf(stderr,"ERROR: NULL register\n");
+ }
+ }
+ }
+
+
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* */
+/*-----------------------------------------------------------------*/
+#define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
+
+void InsertpFlow(pCode *pc, pCode **pflow)
+{
+ PCFL(*pflow)->end = pc;
+
+ if(!pc || !pc->next)
+ return;
+
+ *pflow = newpCodeFlow();
+ pCodeInsertAfter(pc, *pflow);
+}
+
+/*-----------------------------------------------------------------*/
+/* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
+/* the flow blocks. */
+/*
+ * BuildFlow inserts pCodeFlow objects into the pCode chain at each
+ * point the instruction flow changes.
+ */
+/*-----------------------------------------------------------------*/
+void BuildFlow(pBlock *pb)
+{
+ pCode *pc;
+ pCode *last_pci=NULL;
+ pCode *pflow;
+ int seq = 0;
+
+ if(!pb)
+ return;
+
+ //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
+ /* Insert a pCodeFlow object at the beginning of a pBlock */
+
+ pflow = newpCodeFlow(); /* Create a new Flow object */
+ pflow->next = pb->pcHead; /* Make the current head the next object */
+ pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
+ pb->pcHead = pflow; /* Make the Flow object the head */
+ pflow->pb = pb;
+
+ for( pc = findNextInstruction(pb->pcHead);
+ (pc=findNextInstruction(pc)) != NULL; ) {
+
+ pc->seq = seq++;
+ PCI(pc)->pcflow = PCFL(pflow);
+
+ if(PCI(pc)->isSkip || PCI(pc)->isBranch) {
+
+ /* The instruction immediately following this one
+ * marks the beginning of a new flow segment */
+
+ InsertpFlow(pc, &pflow);
+ seq = 0;
+
+ } else if (PCI_HAS_LABEL(pc)) {
+
+ /* This instruction marks the beginning of a
+ * new flow segment */
+
+ pc->seq = 0;
+ seq = 1;
+ InsertpFlow(pc->prev, &pflow);
+
+ PCI(pc)->pcflow = PCFL(pflow);
+
+ }
+ last_pci = pc;
+ pc = pc->next;
+ }
+
+ //fprintf (stderr,",end seq %d",GpcFlowSeq);
+ PCFL(pflow)->end = pb->pcTail;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void dumpCond(int cond)
+{
+
+ static char *pcc_str[] = {
+ //"PCC_NONE",
+ "PCC_REGISTER",
+ "PCC_C",
+ "PCC_Z",
+ "PCC_DC",
+ "PCC_W",
+ "PCC_EXAMINE_PCOP",
+ "PCC_REG_BANK0",
+ "PCC_REG_BANK1",
+ "PCC_REG_BANK2",
+ "PCC_REG_BANK3"
+ };
+
+ int ncond = sizeof(pcc_str) / sizeof(char *);
+ int i,j;
+
+ fprintf(stderr, "0x%04X\n",cond);
+
+ for(i=0,j=1; i<ncond; i++, j<<=1)
+ if(cond & j)
+ fprintf(stderr, " %s\n",pcc_str[i]);
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void FillFlow(pCodeFlow *pcflow)
+{
+
+ pCode *pc;
+ int cur_bank;
+
+ if(!isPCFL(pcflow))
+ return;
+
+ // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
+
+ pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
+ if(!pc) {
+ // fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
+ return;
+ }
+
+ cur_bank = -1;
+
+ do {
+ //regs *reg;
+
+ int inCond = PCI(pc)->inCond;
+ int outCond = PCI(pc)->outCond;
+#if 0
+ if( (reg = getRegFromInstruction(pc)) != NULL) {
+ if(isSTATUS_REG(reg)) {
+
+ //fprintf(stderr, " FillFlow - Status register\n");
+
+ /* Check to see if the register banks are changing */
+ if(PCI(pc)->isModReg) {
+
+ pCodeOp *pcop = PCI(pc)->pcop;
+ switch(PCI(pc)->op) {
+ case POC_BSF:
+ if(PCORB(pcop)->bit == PIC_RP0_BIT)
+ fprintf(stderr, " FillFlow - Set RP0\n");
+ //outCond |= PCC_REG_BANK1;
+ if(PCORB(pcop)->bit == PIC_RP1_BIT)
+ fprintf(stderr, " FillFlow - Set RP1\n");
+ //outCond |= PCC_REG_BANK3;
+ break;
+
+ case POC_BCF:
+ if(PCORB(pcop)->bit == PIC_RP0_BIT)
+ fprintf(stderr, " FillFlow - Clr RP0\n");
+ //outCond |= PCC_REG_BANK1;
+ if(PCORB(pcop)->bit == PIC_RP1_BIT)
+ fprintf(stderr, " FillFlow - Clr RP1\n");
+ //outCond |= PCC_REG_BANK3;
+ break;
+
+ default:
+ fprintf(stderr, " FillFlow - Status register is getting Modified by:\n");
+ genericPrint(stderr, pc);
+ }
+ }
+
+ } else
+ inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3);
+ }
+#endif
+
+ pcflow->inCond |= (inCond & ~pcflow->outCond);
+ pcflow->outCond |= outCond;
+
+
+
+
+ pc = findNextpCode(pc->next, PC_OPCODE);
+ } while (pc && (pc != pcflow->end));
+
+#if 0
+ if(!pc)
+ fprintf(stderr, " FillFlow - Bad end of flow\n");
+
+
+ fprintf(stderr, " FillFlow inCond: ");
+ dumpCond(pcflow->inCond);
+ fprintf(stderr, " FillFlow outCond: ");
+ dumpCond(pcflow->outCond);
+#endif
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
+{
+
+ if(!from || !to || !to->pcflow || !from->pcflow)
+ return;
+
+ addSet(&(from->pcflow->to), to->pcflow);
+ addSet(&(to->pcflow->from), from->pcflow);
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void LinkFlow(pBlock *pb)
+{
+ pCode *pc=NULL;
+ pCode *pcflow;
+ pCode *pct;
+
+
+ for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+ (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
+ pcflow = pcflow->next) {
+
+ if(!isPCFL(pcflow))
+ fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
+
+ //FillFlow(PCFL(pcflow));
+
+ pc = PCFL(pcflow)->end;
+
+ //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
+ if(isPCI_SKIP(pc)) {
+ //fprintf(stderr, "ends with skip\n");
+ pct=findNextInstruction(pc->next);
+ LinkFlow_pCode(PCI(pc),PCI(pct));
+ pct=findNextInstruction(pct->next);
+ LinkFlow_pCode(PCI(pc),PCI(pct));
+ continue;
+ }
+
+ if(isPCI_BRANCH(pc)) {
+ //fprintf(stderr, "ends with branch\n");
+
+ continue;
+ }
+#if 0
+ if(pc) {
+ fprintf(stderr, "has an unrecognized ending:\n");
+ pc->print(stderr,pc);
+ }
+ else
+ fprintf(stderr, "has no end pcode\n");
+#endif
+
+ }
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+int OptimizepBlock(pBlock *pb)
+{
+ pCode *pc;
+ int matches =0;
+
+ if(!pb || !peepOptimizing)
+ return 0;
+
+ DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
+ for(pc = pb->pcHead; pc; pc = pc->next)
+ matches += pCodePeepMatchRule(pc);
+ if(matches)
+ DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
+ return matches;