Improved the Register Banking algorithm.
authorsdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 13 Jun 2002 13:57:18 +0000 (13:57 +0000)
committersdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 13 Jun 2002 13:57:18 +0000 (13:57 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2023 4a8a32a2-be11-0410-ad9d-d568d2c75423

src/pic/device.c
src/pic/device.h
src/pic/gen.c
src/pic/genarith.c
src/pic/pcode.c
src/pic/pcode.h
src/pic/ralloc.c

index 4e92fed441fcfbcbd18e69367a11657880b1752e..bf465f3817ba7024c3d1e621066988f4d4526693 100644 (file)
@@ -120,6 +120,7 @@ static PIC_device Pics[] = {
     p16f627_mem,                     /* ram mem map */
     p16f627_sfr,                     /* sfr mem map */
     0,                               /* max ram address (calculated) */
+    0x80,                            /* Bank Mask */
   },
 
   {
@@ -127,6 +128,7 @@ static PIC_device Pics[] = {
     p16f627_mem,
     p16f627_sfr,
     0,
+    0x80,
   },
 
   {
@@ -134,6 +136,7 @@ static PIC_device Pics[] = {
     p16f84_mem,
     p16f84_sfr,
     0,
+    0x80,
   },
 
   {
@@ -141,6 +144,7 @@ static PIC_device Pics[] = {
     p16f877_mem,
     p16f877_sfr,
     0,
+    0x180,
   },
 
 };
@@ -204,6 +208,36 @@ static void addMem(memRange *ranges,int type)
 
 }
 
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+
+int isREGinBank(regs *reg, int bank)
+{
+
+  if(!reg || !pic)
+    return 0;
+
+  if(((reg->address | reg->alias) & pic->bankMask & bank) == bank)
+    return 1;
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+int REGallBanks(regs *reg)
+{
+
+  if(!reg || !pic)
+    return 0;
+
+  return ((reg->address | reg->alias) & pic->bankMask);
+
+}
+
+/*-----------------------------------------------------------------*
+ *-----------------------------------------------------------------*/
+
 static void addMaps(PIC_device *pPic)
 {
   int i;
index 2d2a06323f4c4d1cde7bddf70d0b5c5511acf762..3c5c9e296fb3e8266f91847ba9bba8d3e6368945 100644 (file)
@@ -79,7 +79,8 @@ typedef struct PIC_device {
   memRange *ram;              /* RAM memory map */
   memRange *sfr;              /* SFR memory map */
 
-  int maxRAMaddress;         /* maximum value for a data address */
+  int maxRAMaddress;          /* maximum value for a data address */
+  int bankMask;               /* Bitmask that is ANDed with address to extract banking bits */
   //  int hasAliasedRAM:1;        /* True if there are bank independent registers */
 
 } PIC_device;
@@ -93,5 +94,7 @@ typedef struct PIC_device {
 /****************************************/
 void assignConfigWordValue(int address, int value);
 int getConfigWord(int address);
+int isREGinBank(regs *reg, int bank);
+int REGallBanks(regs *reg);
 
 #endif  /* __DEVICE_H__ */
index 975ead83e0f7c7a5aa13781fa3bbdecf716dc4d7..4ae2f23c69dd9cb61c7b04fd5cc2ec818ec1393f 100644 (file)
@@ -819,7 +819,7 @@ void aopOp (operand *op, iCode *ic, bool result)
             aop->size = getSize(sym->type);
             for ( i = 0 ; i < 2 ; i++ )
                 aop->aopu.aop_str[i] = accUse[i];
-           DEBUGpic14_emitcode(";","%d",__LINE__);
+           DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
             return;  
        }
 
@@ -1312,9 +1312,10 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
        if(PCOR(pcop)->r == NULL) {
          //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
          PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
-       } 
-
-      DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
+         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
+       } else {
+         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
+       }
        PCOR(pcop)->instance = offset;
 
        return pcop;
@@ -1326,6 +1327,9 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
        pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
        PCOR(pcop)->rIdx = rIdx;
        PCOR(pcop)->r = pic14_regWithIdx(rIdx);
+       PCOR(pcop)->r->wasUsed=1;
+       PCOR(pcop)->r->isFree=0;
+
        PCOR(pcop)->instance = offset;
        pcop->type = PCOR(pcop)->r->pc_type;
        //rs = aop->aopu.aop_reg[offset]->name;
@@ -1357,7 +1361,8 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
       */
 
     case AOP_PCODE:
-      DEBUGpic14_emitcode(";","popGet AOP_PCODE%d",__LINE__);
+      DEBUGpic14_emitcode(";","popGet AOP_PCODE %d %s",__LINE__, 
+                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
       pcop = pCodeOpCopy(aop->aopu.pcop);
       PCOI(pcop)->offset = offset;
       return pcop;
index 2e701a04254b396bf9930c553fc06c952df182bc..8b4aa9646260532df65ed693de1a09ff6097bc7a 100644 (file)
@@ -1500,6 +1500,7 @@ void genUMult8XLit_16 (operand *left,
 
   unsigned int lit;
   unsigned int i,have_first_bit;
+  int same;
 
   if (AOP_TYPE(right) != AOP_LIT){
     fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
@@ -1515,11 +1516,55 @@ void genUMult8XLit_16 (operand *left,
   lit &= 0xff;
   pic14_emitcode(";","Unrolled 8 X 8 multiplication");
 
+  same = pic14_sameRegs(AOP(left), AOP(result));
+
+  if(same) {
+    switch(lit) {
+    case 0:
+      emitpcode(POC_CLRF,  popGet(AOP(left),0));
+      return;
+    case 2:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 3:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 4:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 16:
+      emitpcode(POC_SWAPFW, popGet(AOP(left),0));
+      emitpcode(POC_ANDLW,  popGetLit(0xf0));
+      emitpcode(POC_MOVWF,  popGet(AOP(left),0));
+      return;
+    case 17:
+      emitpcode(POC_SWAPFW, popGet(AOP(left),0));
+      emitpcode(POC_ANDLW,  popGetLit(0xf0));
+      emitpcode(POC_ADDWF,  popGet(AOP(left),0));
+      return;
+
+    }
+  } else {
+
+    switch(lit) {
+    case 0:
+      emitpcode(POC_CLRF,  popGet(AOP(result),0));
+      emitpcode(POC_CLRF,  popCopyReg(result_hi));
+      return;
+    case 2:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_MOVWF, popGet(AOP(result),0));
+      emitpcode(POC_ADDWF, popGet(AOP(result),0));
+      emitpcode(POC_CLRF,  popCopyReg(result_hi));
+      emitpcode(POC_RLF,   popCopyReg(result_hi));
+      return;
+    }
 
-  if(!lit) {
-    emitpcode(POC_CLRF,  popGet(AOP(result),0));
-    emitpcode(POC_CLRF,  popCopyReg(result_hi));
-    return;
   }
 
   emitpcode(POC_MOVFW, popGet(AOP(left),0));
@@ -1563,6 +1608,11 @@ void genUMult8X8_16 (operand *left,
     result_hi = PCOR(popGet(AOP(result),1));
   }
 
+  if (AOP_TYPE(right) == AOP_LIT) {
+    genUMult8XLit_16(left,right,result,result_hi);
+    return;
+  }
+
   if(!looped) {
     pic14_emitcode(";","Unrolled 8 X 8 multiplication");
 
@@ -1601,16 +1651,19 @@ void genUMult8X8_16 (operand *left,
 
   } else {
     symbol  *tlbl = newiTempLabel(NULL);
-    pCodeOp *temp = popGetTempReg();
+    pCodeOp *temp;
 
 
     pic14_emitcode(";","Looped 8 X 8 multiplication");
 
     emitpcode(POC_CLRF,  popGet(AOP(result),0));
     emitpcode(POC_CLRF,  popCopyReg(result_hi));
+
     emitpcode(POC_BSF,   newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),7,0));
 
     emitpcode(POC_MOVFW, popGet(AOP(right),0));
+
+    temp = popGetTempReg();
     emitpcode(POC_MOVWF, popCopyReg(PCOR(temp)));
 
     emitpcode(POC_MOVFW, popGet(AOP(left),0));
index f3d3f56fe2c2a8cfe9abb0561bcee5f80ad6bfd3..1bdeb311061dc8458873bf2539a70a8f4ccc1c63 100644 (file)
@@ -87,6 +87,8 @@ static int GpcFlowSeq = 1;
 #define isCALL(x)       ((isPCI(x)) && (PCI(x)->op == POC_CALL))
 #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
 
+#define isPCOLAB(x)     ((PCOP(x)->type) == PO_LABEL)
+
 /****************************************************************/
 /*                      Forward declarations                    */
 /****************************************************************/
@@ -111,6 +113,8 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
 int pCodePeepMatchRule(pCode *pc);
 void pBlockStats(FILE *of, pBlock *pb);
 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
+extern pCodeOp *popCopyReg(pCodeOpReg *pc);
+pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
 
 pCodeInstruction pciADDWF = {
   {PC_OPCODE, NULL, NULL, 0, NULL, 
@@ -1788,11 +1792,31 @@ pCode *newpCodeFlow(void )
   pcflow->inCond = PCC_NONE;
   pcflow->outCond = PCC_NONE;
 
+  pcflow->firstBank = -1;
+  pcflow->lastBank = -1;
+
+  pcflow->FromConflicts = 0;
+  pcflow->ToConflicts = 0;
+
   pcflow->end = NULL;
   return ( (pCode *)pcflow);
 
 }
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
+{
+  pCodeFlowLink *pcflowLink;
+
+  pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
+
+  pcflowLink->pcflow = pcflow;
+  pcflowLink->bank_conflict = 0;
+
+  return pcflowLink;
+}
+
 /*-----------------------------------------------------------------*/
 /* newpCodeCSource - create a new pCode Source Symbol              */
 /*-----------------------------------------------------------------*/
@@ -2888,6 +2912,23 @@ int checkLabel(pCode *pc)
   return FALSE;
 }
 
+/*-----------------------------------------------------------------*/
+/* findLabelinpBlock - Search the pCode for a particular label     */
+/*-----------------------------------------------------------------*/
+pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
+{
+  pCode  *pc;
+
+  if(!pb)
+    return NULL;
+
+  for(pc = pb->pcHead; pc; pc = pc->next) 
+    if(compareLabel(pc,pcop_label))
+      return pc;
+    
+  return NULL;
+}
+
 /*-----------------------------------------------------------------*/
 /* findLabel - Search the pCode for a particular label             */
 /*-----------------------------------------------------------------*/
@@ -2900,10 +2941,8 @@ pCode * findLabel(pCodeOpLabel *pcop_label)
     return NULL;
 
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    for(pc = pb->pcHead; pc; pc = pc->next) 
-      if(compareLabel(pc,pcop_label))
-       return pc;
-    
+    if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
+      return pc;
   }
 
   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
@@ -3180,12 +3219,16 @@ void BuildFlow(pBlock *pb)
   pb->pcHead = pflow;        /* Make the Flow object the head */
   pflow->pb = pb;
 
-  for( pc = findNextInstruction(pb->pcHead); 
-      (pc=findNextInstruction(pc)) != NULL; ) { 
+  for( pc = findNextInstruction(pb->pcHead);
+       pc != NULL;
+       pc=findNextInstruction(pc)) { 
 
     pc->seq = seq++;
     PCI(pc)->pcflow = PCFL(pflow);
 
+    //fprintf(stderr," build: ");
+    //pflow->print(stderr,pflow);
+
     if( PCI(pc)->isSkip) {
 
       /* The two instructions immediately following this one 
@@ -3324,6 +3367,74 @@ void FlowStats(pCodeFlow *pcflow)
 
 }
 
+/*-----------------------------------------------------------------*
+ * 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)
@@ -3347,56 +3458,7 @@ void FillFlow(pCodeFlow *pcflow)
   cur_bank = -1;
 
   do {
-    regs *reg;
-
-    if(isPCI(pc)) {
-
-      int inCond = PCI(pc)->inCond;
-      int outCond = PCI(pc)->outCond;
-
-      if( (reg = getRegFromInstruction(pc)) != NULL) {
-       if(isSTATUS_REG(reg)) {
-
-         //fprintf(stderr, "  FillFlow - Status register\n");
-         //pc->print(stderr,pc);
-         /* 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);
-      }
-
-      pcflow->inCond |= (inCond &  ~pcflow->outCond);
-      pcflow->outCond |= outCond;
-    } 
-
+    isBankInstruction(pc);
     pc = pc->next;
   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
 
@@ -3419,12 +3481,16 @@ void FillFlow(pCodeFlow *pcflow)
 /*-----------------------------------------------------------------*/
 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
 {
+  pCodeFlowLink *fromLink, *toLink;
 
   if(!from || !to || !to->pcflow || !from->pcflow)
     return;
 
-  addSet(&(from->pcflow->to), to->pcflow);
-  addSet(&(to->pcflow->from), from->pcflow);
+  fromLink = newpCodeFlowLink(from->pcflow);
+  toLink   = newpCodeFlowLink(to->pcflow);
+
+  addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
+  addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
 
 }
 
@@ -3437,12 +3503,17 @@ void LinkFlow(pBlock *pb)
   pCode *pct;
 
   //fprintf(stderr,"linkflow \n");
+
   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
-       (pcflow = findNextpCode(pcflow->next, PC_FLOW)) != NULL;) {
+       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;
@@ -3450,6 +3521,7 @@ void LinkFlow(pBlock *pb)
     //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);
@@ -3457,22 +3529,526 @@ void LinkFlow(pBlock *pb)
       continue;
     }
 
-    //if(isPCI_BRANCH(pc)) {
-    //fprintf(stderr, "ends with branch\n");
+    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;
+    }
 
-    // continue;
-    //}
-    #if 0
     if(isPCI(pc)) {
-      fprintf(stderr, "ends with non-branching instruction:\n");
+      //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));
+
     }
-    else 
-      fprintf(stderr, "has no end pcode\n");
-    #endif 
+#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)
@@ -3781,7 +4357,8 @@ void FixRegisterBanking(pBlock *pb)
   if(!pb)
     return;
 
-  pc = findNextpCode(pb->pcHead, PC_FLOW);
+  //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 */
@@ -3795,7 +4372,7 @@ void FixRegisterBanking(pBlock *pb)
     /* for each flow block, determine the register banking 
        requirements */
 
-    do {
+    //    do {
       if(isPCI(pc)) {
        //genericPrint(stderr, pc);
 
@@ -3841,7 +4418,10 @@ void FixRegisterBanking(pBlock *pb)
 
       pcprev = pc;
       pc = pc->next;
-    } while(pc && !(isPCFL(pc))); 
+      // } while(pc && !(isPCFL(pc))); 
+
+
+  }while (pc);
 
     if(pcprev && cur_bank) {
       /* Brute force - make sure that we point to bank 0 at the
@@ -3852,8 +4432,6 @@ void FixRegisterBanking(pBlock *pb)
       cur_bank = 0;
     }
 
-  }while (pc);
-
 }
 
 void pBlockDestruct(pBlock *pb)
@@ -3923,6 +4501,15 @@ void AnalyzeBanking(void)
     return;
 
 
+  /* Phase 2 - Flow Analysis - Register Banking
+   *
+   * In this phase, the individual flow blocks are examined
+   * and register banking is fixed.
+   */
+
+  //for(pb = the_pFile->pbHead; pb; pb = pb->next)
+  //FixRegisterBanking(pb);
+
   /* Phase 2 - Flow Analysis
    *
    * In this phase, the pCode is partition into pCodeFlow 
@@ -3934,6 +4521,7 @@ void AnalyzeBanking(void)
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     BuildFlow(pb);
 
+
   /* Phase 2 - Flow Analysis - linking flow blocks
    *
    * In this phase, the individual flow blocks are examined
@@ -3943,9 +4531,29 @@ void AnalyzeBanking(void)
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     LinkFlow(pb);
 
+
+  /* Phase x - Flow Analysis - Used Banks
+   *
+   * In this phase, the individual flow blocks are examined
+   * to determine the Register Banks they use
+   */
+
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
-    FixRegisterBanking(pb);
+    BanksUsedFlow(pb);
 
+  /* Phase x - Flow Analysis - Used Banks
+   *
+   * In this phase, the individual flow blocks are examined
+   * to determine the Register Banks they use
+   */
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    FixBankFlow(pb);
+
+/*
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    DumpFlow(pb);
+*/
   /* debug stuff */ 
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
     pCode *pcflow;
@@ -4218,6 +4826,7 @@ void pBlockStats(FILE *of, pBlock *pb)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
+#if 0
 static void sequencepCode(void)
 {
   pBlock *pb;
@@ -4233,6 +4842,7 @@ static void sequencepCode(void)
   }
 
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
index f3c05fd57ffc3537eaef729e28eadf88a49f443a..8e4dd51acb5c49fc9a77d119074ce43f0a6062d4 100644 (file)
@@ -445,8 +445,35 @@ typedef struct pCodeFlow
   int inCond;   /* Input conditions - stuff assumed defined at entry */
   int outCond;  /* Output conditions - stuff modified by flow block */
 
+  int firstBank; /* The first and last bank flags are the first and last */
+  int lastBank;  /* register banks used within one flow object */
+
+  int FromConflicts;
+  int ToConflicts;
+
 } pCodeFlow;
 
+/*************************************************
+  pCodeFlowLink
+
+  The Flow Link object is used to record information
+ about how consecutive excutive Flow objects are related.
+ The pCodeFlow objects demarcate the pCodeInstructions
+ into contiguous chunks. The FlowLink records conflicts
+ in the discontinuities. For example, if one Flow object
+ references a register in bank 0 and the next Flow object
+ references a register in bank 1, then there is a discontinuity
+ in the banking registers.
+
+*/
+typedef struct pCodeFlowLink
+{
+  pCodeFlow  *pcflow;   /* pointer to linked pCodeFlow object */
+
+  int bank_conflict;    /* records bank conflicts */
+
+} pCodeFlowLink;
+
 /*************************************************
     pCodeInstruction
 
index 58258c9a5d26c27d751e29679cf5d01be7940b86..f417f06481752bce556717ecd8e80da7ca83f7c1 100644 (file)
@@ -645,13 +645,13 @@ allocDirReg (operand *op )
     if(!IS_CONFIG_ADDRESS(address)) {
       reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,getSize (OP_SYMBOL (op)->type),0 );
       debugLog ("  -- added %s to hash, size = %d\n", name,reg->size);
-
+/*
       if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
        reg->isFixed = 1;
        reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
        debugLog ("  -- and it is at a fixed address 0x%02x\n",reg->address);
       }
-
+*/
       hTabAddItem(&dynDirectRegNames, regname2key(name), reg);
       if (IS_BITVAR (OP_SYM_ETYPE(op)))
        addSet(&dynDirectBitRegs, reg);
@@ -663,6 +663,12 @@ allocDirReg (operand *op )
     }
   }
 
+  if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
+    reg->isFixed = 1;
+    reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
+    debugLog ("  -- and it is at a fixed address 0x%02x\n",reg->address);
+  }
+
   return reg;
 }
 
@@ -3113,12 +3119,14 @@ packRegsForAccUse (iCode * ic)
   if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
     return;
   }
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
 
   /* if + or - then it has to be one byte result */
   if ((ic->op == '+' || ic->op == '-')
       && getSize (operandType (IC_RESULT (ic))) > 1)
     return;
 
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
   /* if shift operation make sure right side is not a literal */
   if (ic->op == RIGHT_OP &&
       (isOperandLiteral (IC_RIGHT (ic)) ||
@@ -3148,6 +3156,7 @@ packRegsForAccUse (iCode * ic)
                               bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
     return;
 
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
   if (ic->next != uic)
     return;
 
@@ -3164,6 +3173,7 @@ packRegsForAccUse (iCode * ic)
       getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
     return;
 
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
   if (uic->op != '=' &&
       !IS_ARITHMETIC_OP (uic) &&
       !IS_BITWISE_OP (uic) &&
@@ -3171,6 +3181,7 @@ packRegsForAccUse (iCode * ic)
       uic->op != RIGHT_OP)
     return;
 
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
   /* if used in ^ operation then make sure right is not a 
      literl */
   if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
@@ -3211,14 +3222,17 @@ packRegsForAccUse (iCode * ic)
       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
     return;
 
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
   /* if one of them is a literal then we can */
-  if ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
-      (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))
+  if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
+       (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))  &&
+       (getSize (operandType (IC_RESULT (uic))) <= 1))
     {
       OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
       return;
     }
 
+  debugLog ("  %s:%d\n", __FUNCTION__,__LINE__);
   /* if the other one is not on stack then we can */
   if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
       (IS_ITEMP (IC_RIGHT (uic)) ||