+ pc = pb->pcHead;
+ while(pc) {
+ pCode *pcn = pc->next;
+
+ if(isPCI(pc)) {
+ pc->seq = 0;
+ PCI(pc)->pcflow = NULL;
+ pc = pcn;
+ } else if(isPCFL(pc)) {
+ unlinkpCode(pc);
+ pc->destruct(pc);
+ } else
+ pc = pcn;
+
+ }
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+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 FlowStats(pCodeFlow *pcflow)
+{
+
+ pCode *pc;
+
+ if(!isPCFL(pcflow))
+ return;
+
+ fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
+
+ pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
+
+ if(!pc) {
+ fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
+ return;
+ }
+
+
+ fprintf(stderr, " FlowStats inCond: ");
+ dumpCond(pcflow->inCond);
+ fprintf(stderr, " FlowStats outCond: ");
+ dumpCond(pcflow->outCond);
+
+}
+
+/*-----------------------------------------------------------------*
+ * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
+ * if it affects the banking bits.
+ *
+ * return: -1 == Banking bits are unaffected by this pCode.
+ *
+ * return: > 0 == Banking bits are affected.
+ *
+ * If the banking bits are affected, then the returned value describes
+ * which bits are affected and how they're affected. The lower half
+ * of the integer maps to the bits that are affected, the upper half
+ * to whether they're set or cleared.
+ *
+ *-----------------------------------------------------------------*/
+#define SET_BANK_BIT (1 << 16)
+#define CLR_BANK_BIT 0
+
+int isBankInstruction(pCode *pc)
+{
+ regs *reg;
+ int bank = -1;
+
+ if(!isPCI(pc))
+ return -1;
+
+ if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
+
+ /* 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, " isBankInstruction - Set RP0\n");
+ return SET_BANK_BIT | PIC_RP0_BIT;
+ }
+
+ if(PCORB(pcop)->bit == PIC_RP1_BIT) {
+ //fprintf(stderr, " isBankInstruction - Set RP1\n");
+ return CLR_BANK_BIT | PIC_RP0_BIT;
+ }
+ break;
+
+ case POC_BCF:
+ if(PCORB(pcop)->bit == PIC_RP0_BIT) {
+ //fprintf(stderr, " isBankInstruction - Clr RP0\n");
+ return CLR_BANK_BIT | PIC_RP1_BIT;
+ }
+ if(PCORB(pcop)->bit == PIC_RP1_BIT) {
+ //fprintf(stderr, " isBankInstruction - Clr RP1\n");
+ return CLR_BANK_BIT | PIC_RP1_BIT;
+ }
+ break;
+ default:
+ //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
+ //genericPrint(stderr, pc);
+ ;
+ }
+ }
+
+ }
+
+ return bank;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+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 {
+ isBankInstruction(pc);
+ pc = pc->next;
+ } while (pc && (pc != pcflow->end) && !isPCFL(pc));
+
+/*
+ if(!pc ) {
+ fprintf(stderr, " FillFlow - Bad end of flow\n");
+ } else {
+ fprintf(stderr, " FillFlow - Ending flow with\n ");
+ pc->print(stderr,pc);
+ }
+
+ fprintf(stderr, " FillFlow inCond: ");
+ dumpCond(pcflow->inCond);
+ fprintf(stderr, " FillFlow outCond: ");
+ dumpCond(pcflow->outCond);
+*/
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
+{
+ pCodeFlowLink *fromLink, *toLink;
+
+ if(!from || !to || !to->pcflow || !from->pcflow)
+ return;
+
+ fromLink = newpCodeFlowLink(from->pcflow);
+ toLink = newpCodeFlowLink(to->pcflow);
+
+ addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
+ addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void LinkFlow(pBlock *pb)
+{
+ pCode *pc=NULL;
+ pCode *pcflow;
+ pCode *pct;
+
+ //fprintf(stderr,"linkflow \n");
+
+ for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+ pcflow != NULL;
+ pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
+
+ if(!isPCFL(pcflow))
+ fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
+
+ //fprintf(stderr," link: ");
+ //pcflow->print(stderr,pcflow);
+
+ //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");
+ //pc->print(stderr,pc);
+ 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)) {
+ pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
+
+ //fprintf(stderr, "ends with branch\n ");
+ //pc->print(stderr,pc);
+
+ if(!(pcol && isPCOLAB(pcol))) {
+ if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
+ pc->print(stderr,pc);
+ fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
+ }
+ continue;
+ }
+
+ if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
+ LinkFlow_pCode(PCI(pc),PCI(pct));
+ else
+ fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
+
+ continue;
+ }
+
+ if(isPCI(pc)) {
+ //fprintf(stderr, "ends with non-branching instruction:\n");
+ //pc->print(stderr,pc);
+
+ LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
+
+ continue;
+ }
+
+ if(pc) {
+ //fprintf(stderr, "ends with unknown\n");
+ //pc->print(stderr,pc);
+ continue;
+ }
+
+ //fprintf(stderr, "ends with nothing: ERROR\n");
+
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+int isPCinFlow(pCode *pc, pCode *pcflow)
+{
+
+ if(!pc || !pcflow)
+ return 0;
+
+ if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
+ return 0;
+
+ if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
+ return 1;
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void BanksUsedFlow2(pCode *pcflow)
+{
+ pCode *pc=NULL;
+
+ int bank = -1;
+ bool RegUsed = 0;
+
+ regs *reg;
+
+ if(!isPCFL(pcflow)) {
+ fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
+ return;
+ }
+
+ pc = findNextInstruction(pcflow->next);
+
+ PCFL(pcflow)->lastBank = -1;
+
+ while(isPCinFlow(pc,pcflow)) {
+
+ int bank_selected = isBankInstruction(pc);
+
+ //if(PCI(pc)->pcflow)
+ //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
+
+ if(bank_selected > 0) {
+ //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
+
+ /* This instruction is modifying banking bits before accessing registers */
+ if(!RegUsed)
+ PCFL(pcflow)->firstBank = -1;
+
+ if(PCFL(pcflow)->lastBank == -1)
+ PCFL(pcflow)->lastBank = 0;
+
+ bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
+ if(bank_selected & SET_BANK_BIT)
+ PCFL(pcflow)->lastBank |= bank;
+
+
+ } else {
+ reg = getRegFromInstruction(pc);
+
+ if(reg && !isREGinBank(reg, bank)) {
+ int allbanks = REGallBanks(reg);
+ if(bank == -1)
+ PCFL(pcflow)->firstBank = allbanks;
+
+ PCFL(pcflow)->lastBank = allbanks;
+
+ bank = allbanks;
+ }
+ RegUsed = 1;
+ }
+
+ pc = findNextInstruction(pc->next);
+ }
+
+// fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
+// pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
+
+
+
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void BanksUsedFlow(pBlock *pb)
+{
+ pCode *pcflow;
+
+
+ //pb->pcHead->print(stderr, pb->pcHead);
+
+ pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+ //pcflow->print(stderr,pcflow);
+
+ for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+ pcflow != NULL;
+ pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
+
+ BanksUsedFlow2(pcflow);
+ }
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
+{
+ pCode *new_pc;
+
+ if(!pc)
+ return;
+
+ if(RP_BankBit < 0)
+ new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
+ else
+ new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
+ popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
+
+ pCodeInsertAfter(pc->prev, new_pc);
+
+ /* Move the label, if there is one */
+
+ if(PCI(pc)->label) {
+ PCI(new_pc)->label = PCI(pc)->label;
+ PCI(pc)->label = NULL;
+ }
+
+ /* The new instruction has the same pcflow block */
+ PCI(new_pc)->pcflow = PCI(pc)->pcflow;
+
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
+{
+ pCode *pc=NULL;
+ pCode *pcprev=NULL;
+ pCode *new_pc;
+
+ regs *reg;
+
+ if(!pcfl)
+ return;
+
+ pc = findNextInstruction(pcfl->pc.next);
+
+ while(isPCinFlow(pc,PCODE(pcfl))) {
+
+
+ reg = getRegFromInstruction(pc);
+#if 0
+ if(reg) {
+ fprintf(stderr, " %s ",reg->name);
+ fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
+
+ }
+#endif
+
+ if(reg && REG_BANK(reg)!=cur_bank) {
+ /* Examine the instruction before this one to make sure it is
+ * not a skip type instruction */
+ pcprev = findPrevpCode(pc->prev, PC_OPCODE);
+ if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
+ int b = cur_bank ^ REG_BANK(reg);
+
+ //fprintf(stderr, "Cool! can switch banks\n");
+ cur_bank = REG_BANK(reg);
+ switch(b & 3) {
+ case 0:
+ break;
+ case 1:
+ insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
+ break;
+ case 2:
+ insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
+ insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
+ break;
+ case 3:
+ if(cur_bank & 3) {
+ insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
+ insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
+ } else
+ insertBankSwitch(pc, -1, -1);
+ break;
+ /*
+ new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
+ popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
+ pCodeInsertAfter(pc->prev, new_pc);
+ if(PCI(pc)->label) {
+ PCI(new_pc)->label = PCI(pc)->label;
+ PCI(pc)->label = NULL;
+ }
+ */
+ /*
+ new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
+ popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
+ pCodeInsertAfter(pc, new_pc);
+ */
+
+ }
+
+ } else {
+ //fprintf(stderr, "Bummer can't switch banks\n");
+ ;
+ }
+ }
+
+ pcprev = pc;
+ pc = findNextInstruction(pc->next);
+
+ }
+
+ if(pcprev && cur_bank) {
+ /* Brute force - make sure that we point to bank 0 at the
+ * end of each flow block */
+ new_pc = newpCode(POC_BCF,
+ popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
+ pCodeInsertAfter(pcprev, new_pc);
+ cur_bank = 0;
+ }
+
+}
+
+/*-----------------------------------------------------------------*/
+/*int compareBankFlow - compare the banking requirements between */
+/* flow objects. */
+/*-----------------------------------------------------------------*/
+int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
+{
+
+ if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
+ return 0;
+
+ if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
+ return 0;
+
+ if(pcflow->firstBank == -1)
+ return 0;
+
+
+ if(pcflowLink->pcflow->firstBank == -1) {
+ pCodeFlowLink *pctl = setFirstItem( toORfrom ?
+ pcflowLink->pcflow->to :
+ pcflowLink->pcflow->from);
+ return compareBankFlow(pcflow, pctl, toORfrom);
+ }
+
+ if(toORfrom) {
+ if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
+ return 0;
+
+ pcflowLink->bank_conflict++;
+ pcflowLink->pcflow->FromConflicts++;
+ pcflow->ToConflicts++;
+ } else {
+
+ if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
+ return 0;
+
+ pcflowLink->bank_conflict++;
+ pcflowLink->pcflow->ToConflicts++;
+ pcflow->FromConflicts++;
+
+ }
+ /*
+ fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
+ pcflowLink->pcflow->pc.seq,
+ pcflowLink->pcflow->FromConflicts,
+ pcflowLink->pcflow->ToConflicts);
+ */
+ return 1;
+
+}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void FixBankFlow(pBlock *pb)
+{
+ pCode *pc=NULL;
+ pCode *pcflow;
+ pCodeFlowLink *pcfl;
+
+ pCode *pcflow_max_To=NULL;
+ pCode *pcflow_max_From=NULL;
+ int max_ToConflicts=0;
+ int max_FromConflicts=0;
+
+ //fprintf(stderr,"Fix Bank flow \n");
+ pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+
+
+ /*
+ First loop through all of the flow objects in this pcode block
+ and fix the ones that have banking conflicts between the
+ entry and exit.
+ */
+
+ //fprintf(stderr, "FixBankFlow - Phase 1\n");
+
+ for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+ pcflow != NULL;
+ pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
+
+ if(!isPCFL(pcflow)) {
+ fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
+ continue;
+ }
+
+ if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
+ PCFL(pcflow)->firstBank >= 0 &&
+ PCFL(pcflow)->lastBank >= 0 ) {
+
+ int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
+ PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
+
+ FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
+ BanksUsedFlow2(pcflow);
+
+ }
+ }
+
+ //fprintf(stderr, "FixBankFlow - Phase 2\n");
+
+ for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+ pcflow != NULL;
+ pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
+
+ int nFlows;
+ int nConflicts;
+
+ if(!isPCFL(pcflow)) {
+ fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
+ continue;
+ }
+
+ PCFL(pcflow)->FromConflicts = 0;
+ PCFL(pcflow)->ToConflicts = 0;
+
+ nFlows = 0;
+ nConflicts = 0;
+
+ //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
+ pcfl = setFirstItem(PCFL(pcflow)->from);
+ while (pcfl) {
+
+ pc = PCODE(pcfl->pcflow);
+
+ if(!isPCFL(pc)) {
+ fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
+ pc->print(stderr,pc);
+ }
+
+ nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
+ nFlows++;
+
+ pcfl=setNextItem(PCFL(pcflow)->from);
+ }
+
+ if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
+ //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
+
+ FixRegisterBankingInFlow(PCFL(pcflow),0);
+ BanksUsedFlow2(pcflow);
+
+ continue; /* Don't need to check the flow from here - it's already been fixed */
+
+ }
+
+ nFlows = 0;
+ nConflicts = 0;
+
+ pcfl = setFirstItem(PCFL(pcflow)->to);
+ while (pcfl) {
+
+ pc = PCODE(pcfl->pcflow);
+ if(!isPCFL(pc)) {
+ fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
+ pc->print(stderr,pc);
+ }
+
+ nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
+ nFlows++;
+
+ pcfl=setNextItem(PCFL(pcflow)->to);
+ }
+
+ if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
+ //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
+
+ FixRegisterBankingInFlow(PCFL(pcflow),0);
+ BanksUsedFlow2(pcflow);
+ }
+ }
+
+ /*
+ Loop through the flow objects again and find the ones with the
+ maximum conflicts
+ */
+
+ for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+ pcflow != NULL;
+ pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
+
+ if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
+ pcflow_max_To = pcflow;
+
+ if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
+ pcflow_max_From = pcflow;
+ }
+/*
+ if(pcflow_max_To)
+ fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
+ PCFL(pcflow_max_To)->pc.seq,
+ PCFL(pcflow_max_To)->ToConflicts);
+
+ if(pcflow_max_From)
+ fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
+ PCFL(pcflow_max_From)->pc.seq,
+ PCFL(pcflow_max_From)->FromConflicts);
+*/
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void DumpFlow(pBlock *pb)
+{
+ pCode *pc=NULL;
+ pCode *pcflow;
+ pCodeFlowLink *pcfl;
+
+
+ fprintf(stderr,"Dump flow \n");
+ pb->pcHead->print(stderr, pb->pcHead);
+
+ pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+ pcflow->print(stderr,pcflow);
+
+ for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
+ pcflow != NULL;
+ pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
+
+ if(!isPCFL(pcflow)) {
+ fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
+ continue;
+ }
+ fprintf(stderr,"dumping: ");
+ pcflow->print(stderr,pcflow);
+ FlowStats(PCFL(pcflow));
+
+ for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
+
+ pc = PCODE(pcfl->pcflow);
+
+ fprintf(stderr, " from seq %d:\n",pc->seq);
+ if(!isPCFL(pc)) {
+ fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
+ pc->print(stderr,pc);
+ }
+
+ }
+
+ for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
+
+ pc = PCODE(pcfl->pcflow);
+
+ fprintf(stderr, " to seq %d:\n",pc->seq);
+ if(!isPCFL(pc)) {
+ fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
+ pc->print(stderr,pc);
+ }
+
+ }
+
+ }
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+int OptimizepBlock(pBlock *pb)
+{
+ pCode *pc, *pcprev;
+ 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);
+*/
+
+ pc = findNextInstruction(pb->pcHead);
+ pcprev = pc->prev;
+ do {
+
+
+ if(pCodePeepMatchRule(pc)) {
+
+ matches++;
+
+ if(pcprev)
+ pc = findNextInstruction(pcprev->next);
+ else
+ pc = findNextInstruction(pb->pcHead);
+ } else
+ pc = findNextInstruction(pc->next);
+ } while(pc);
+
+ if(matches)
+ DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
+ return matches;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pBlockRemoveUnusedLabels - remove the pCode labels from the */
+/*-----------------------------------------------------------------*/
+pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
+{
+ pCode *pc;
+
+ for(pc = pcs; pc; pc = pc->next) {
+
+ if((pc->type == PC_OPCODE) &&
+ (PCI(pc)->pcop) &&
+ (PCI(pc)->pcop->type == PO_LABEL) &&
+ (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
+ return pc;
+ }
+
+
+ return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void exchangeLabels(pCodeLabel *pcl, pCode *pc)
+{
+
+ if(isPCI(pc) &&
+ (PCI(pc)->pcop) &&
+ (PCI(pc)->pcop->type == PO_LABEL)) {
+
+ pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
+
+ //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
+ if(pcol->pcop.name)
+ free(pcol->pcop.name);
+
+ sprintf(buffer,"_%05d_DS_",pcl->key);
+
+ pcol->pcop.name = Safe_strdup(buffer);
+ pcol->key = pcl->key;
+ //pc->print(stderr,pc);
+
+ }
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* pBlockRemoveUnusedLabels - remove the pCode labels from the */
+/* pCode chain if they're not used. */
+/*-----------------------------------------------------------------*/
+void pBlockRemoveUnusedLabels(pBlock *pb)
+{
+ pCode *pc; pCodeLabel *pcl;
+
+ if(!pb)
+ return;
+
+ for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
+
+ pBranch *pbr = PCI(pc)->label;
+ if(pbr && pbr->next) {
+ pCode *pcd = pb->pcHead;
+
+ //fprintf(stderr, "multiple labels\n");
+ //pc->print(stderr,pc);
+
+ pbr = pbr->next;
+ while(pbr) {
+
+ while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
+ //fprintf(stderr,"Used by:\n");
+ //pcd->print(stderr,pcd);
+
+ exchangeLabels(PCL(pbr->pc),pcd);
+
+ pcd = pcd->next;
+ }
+ pbr = pbr->next;
+ }
+ }
+ }
+
+ for(pc = pb->pcHead; pc; pc = pc->next) {
+
+ if(isPCL(pc)) // pc->type == PC_LABEL)
+ pcl = PCL(pc);
+ else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
+ pcl = PCL(PCI(pc)->label->pc);
+ else continue;
+
+ //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
+
+ /* This pCode is a label, so search the pBlock to see if anyone
+ * refers to it */
+
+ if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
+ //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
+ /* Couldn't find an instruction that refers to this label
+ * So, unlink the pCode label from it's pCode chain
+ * and destroy the label */
+ //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
+
+ DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
+ if(pc->type == PC_LABEL) {
+ unlinkpCode(pc);
+ pCodeLabelDestruct(pc);
+ } else {
+ unlinkpCodeFromBranch(pc, PCODE(pcl));
+ /*if(pc->label->next == NULL && pc->label->pc == NULL) {
+ free(pc->label);
+ }*/
+ }
+
+ }
+ }
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* pBlockMergeLabels - remove the pCode labels from the pCode */
+/* chain and put them into pBranches that are */
+/* associated with the appropriate pCode */
+/* instructions. */
+/*-----------------------------------------------------------------*/
+void pBlockMergeLabels(pBlock *pb)
+{
+ pBranch *pbr;
+ pCode *pc, *pcnext=NULL;
+
+ if(!pb)
+ return;
+
+ /* First, Try to remove any unused labels */
+ //pBlockRemoveUnusedLabels(pb);
+
+ /* Now loop through the pBlock and merge the labels with the opcodes */
+
+ for(pc = pb->pcHead; pc; pc = pc->next) {
+
+ if(pc->type == PC_LABEL) {
+
+ //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
+ //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
+ if((pcnext = findNextInstruction(pc) )) {
+
+ pCode *pcn = pc->next;
+
+ // Unlink the pCode label from it's pCode chain
+ unlinkpCode(pc);
+
+ //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
+ // And link it into the instruction's pBranch labels. (Note, since
+ // it's possible to have multiple labels associated with one instruction
+ // we must provide a means to accomodate the additional labels. Thus
+ // the labels are placed into the singly-linked list "label" as
+ // opposed to being a single member of the pCodeInstruction.)
+
+ //_ALLOC(pbr,sizeof(pBranch));
+ pbr = Safe_calloc(1,sizeof(pBranch));
+ pbr->pc = pc;
+ pbr->next = NULL;
+
+
+ PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
+
+ pc = pcn;
+
+ } else {
+ fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
+ }
+ } else if(pc->type == PC_CSOURCE) {
+
+ /* merge the source line symbolic info into the next instruction */
+ if((pcnext = findNextInstruction(pc) )) {
+
+ pCode *pcn = pc->next;
+
+ // Unlink the pCode label from it's pCode chain
+ unlinkpCode(pc);
+ PCI(pcnext)->cline = PCCS(pc);
+ //fprintf(stderr, "merging CSRC\n");
+ //genericPrint(stderr,pcnext);
+ pc = pcn;
+ }
+
+ }
+
+ }
+ pBlockRemoveUnusedLabels(pb);
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+int OptimizepCode(char dbName)
+{
+#define MAX_PASSES 4
+
+ int matches = 0;
+ int passes = 0;
+ pBlock *pb;
+
+ if(!the_pFile)
+ return 0;
+
+ DFPRINTF((stderr," Optimizing pCode\n"));
+
+ do {
+ matches = 0;
+ for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+ if('*' == dbName || getpBlock_dbName(pb) == dbName)
+ matches += OptimizepBlock(pb);
+ }
+ }
+ while(matches && ++passes < MAX_PASSES);
+
+ return matches;
+}
+
+/*-----------------------------------------------------------------*/
+/* popCopyGPR2Bit - copy a pcode operator */
+/*-----------------------------------------------------------------*/
+
+pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
+{
+ pCodeOp *pcop;
+
+ pcop = newpCodeOpBit(pc->name, bitval, 0);
+
+ if( !( (pcop->type == PO_LABEL) ||
+ (pcop->type == PO_LITERAL) ||
+ (pcop->type == PO_STR) ))
+ PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
+
+ return pcop;
+}
+
+
+
+#if 0
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+int InstructionRegBank(pCode *pc)
+{
+ regs *reg;
+
+ if( (reg = getRegFromInstruction(pc)) == NULL)
+ return -1;
+
+ return REG_BANK(reg);
+
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void FixRegisterBanking(pBlock *pb)
+{
+ pCode *pc=NULL;
+ pCode *pcprev=NULL;
+ pCode *new_pc;
+
+ int cur_bank;
+ regs *reg;
+ // return;
+ if(!pb)
+ return;
+
+ //pc = findNextpCode(pb->pcHead, PC_FLOW);
+ pc = findNextpCode(pb->pcHead, PC_OPCODE);
+ if(!pc)
+ return;
+ /* loop through all of the flow blocks with in one pblock */
+
+ //fprintf(stderr,"Register banking\n");
+ cur_bank = 0;
+ do {
+ /* at this point, pc should point to a PC_FLOW object */
+
+
+ /* for each flow block, determine the register banking
+ requirements */
+
+ // do {
+ if(isPCI(pc)) {
+ //genericPrint(stderr, pc);
+
+ reg = getRegFromInstruction(pc);
+ #if 0
+ if(reg) {
+ fprintf(stderr, " %s ",reg->name);
+ fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
+
+ }
+ #endif
+ if(reg && REG_BANK(reg)!=cur_bank) {
+ /* Examine the instruction before this one to make sure it is
+ * not a skip type instruction */
+ pcprev = findPrevpCode(pc->prev, PC_OPCODE);
+ if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
+ int b = cur_bank ^ REG_BANK(reg);
+
+ //fprintf(stderr, "Cool! can switch banks\n");
+ cur_bank = REG_BANK(reg);
+ if(b & 1) {
+ new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
+ popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
+ pCodeInsertAfter(pc->prev, new_pc);
+ if(PCI(pc)->label) {
+ PCI(new_pc)->label = PCI(pc)->label;
+ PCI(pc)->label = NULL;
+ }
+ /*
+ new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
+ popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
+ pCodeInsertAfter(pc, new_pc);
+ */
+
+ }
+
+ } else {
+ //fprintf(stderr, "Bummer can't switch banks\n");
+ ;
+ }
+ }
+ }
+
+ pcprev = pc;
+ pc = pc->next;
+ // } while(pc && !(isPCFL(pc)));
+
+
+ }while (pc);
+
+ if(pcprev && cur_bank) {
+ /* Brute force - make sure that we point to bank 0 at the
+ * end of each flow block */
+ new_pc = newpCode(POC_BCF,
+ popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
+ pCodeInsertAfter(pcprev, new_pc);
+ cur_bank = 0;
+ }
+
+}
+
+void pBlockDestruct(pBlock *pb)
+{
+
+ if(!pb)
+ return;
+
+
+ free(pb);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
+/* name dbName and combine them */
+/* into one block */
+/*-----------------------------------------------------------------*/
+void mergepBlocks(char dbName)
+{
+
+ pBlock *pb, *pbmerged = NULL,*pbn;
+
+ pb = the_pFile->pbHead;
+
+ //fprintf(stderr," merging blocks named %c\n",dbName);
+ while(pb) {
+
+ pbn = pb->next;
+ //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
+ if( getpBlock_dbName(pb) == dbName) {
+
+ //fprintf(stderr," merged block %c\n",dbName);
+
+ if(!pbmerged) {
+ pbmerged = pb;
+ } else {
+ addpCode2pBlock(pbmerged, pb->pcHead);
+ /* addpCode2pBlock doesn't handle the tail: */
+ pbmerged->pcTail = pb->pcTail;
+
+ pb->prev->next = pbn;
+ if(pbn)
+ pbn->prev = pb->prev;