+/*-----------------------------------------------------------------*/
+/* Set bank selection if necessary */
+/*-----------------------------------------------------------------*/
+static int DoBankSelect(pCode *pc, int cur_bank) {
+ pCode *pcprev;
+ regs *reg;
+
+ if(!isPCI(pc))
+ return cur_bank;
+
+ if (isCALL(pc)) {
+ pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
+ LastRegIdx = -1; /* do not know which register is touched in the called function... */
+ if (pcf && isPCF(pcf)) {
+ pCode *pcfr;
+ int rbank = 'U'; // Undetermined
+ FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
+ // Check all the returns to work out what bank is selected
+ for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
+ if (isPCI(pcfr)) {
+ if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
+ if (rbank == 'U')
+ rbank = PCI(pcfr)->pcflow->lastBank;
+ else
+ if (rbank != PCI(pcfr)->pcflow->lastBank)
+ return -1; // Unknown bank - multiple returns with different banks
+ }
+ }
+ }
+ if (rbank == 'U')
+ return -1; // Unknown bank
+ return rbank;
+ } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
+ /* Extern functions may use registers in different bank - must call banksel */
+ return -1; /* Unknown bank */
+ }
+ /* play safe... */
+ return -1;
+ }
+
+ if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
+ return -1; /* New bank unknown - linkers choice. */
+ }
+
+ reg = getRegFromInstruction(pc);
+ if (reg) {
+ if (IsBankChange(pc,reg,&cur_bank))
+ return cur_bank;
+ if (!isPCI_LIT(pc)) {
+
+ /* Examine the instruction before this one to make sure it is
+ * not a skip type instruction */
+ pcprev = findPrevpCode(pc->prev, PC_OPCODE);
+
+ /* This approach does not honor the presence of labels at this instruction... */
+ //if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
+ cur_bank = BankSelect(PCI(pc),cur_bank,reg);
+ //} else {
+ // cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
+ //}
+ if (!PCI(pc)->pcflow)
+ fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
+ else
+ PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
+ }
+ }
+ return cur_bank;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+/*
+static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
+{
+ pCode *pc=NULL;
+ pCode *pcprev=NULL;
+
+ if(!pcfl)
+ return;
+
+ pc = findNextInstruction(pcfl->pc.next);
+
+ while(isPCinFlow(pc,PCODE(pcfl))) {
+
+ cur_bank = DoBankSelect(pc,cur_bank);
+ pcprev = pc;
+ pc = findNextInstruction(pc->next);
+
+ }
+
+ if(pcprev && cur_bank) {
+ // Set bank state to unknown at the end of each flow block
+ cur_bank = -1;
+ }
+
+}
+*/
+/*-----------------------------------------------------------------*/
+/*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),-1);
+ 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),-1);
+ 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);
+ * /
+}
+*/