- Register banking wasn't working for bit variables were.
[fw/sdcc] / src / pic / pcode.c
index 2acf43f53ee03805b66d5a4acc2a6f8822216b1d..066ad6335f129a99699af531e381b724e37bb5b4 100644 (file)
@@ -83,7 +83,8 @@ int GpcFlowSeq = 1;
 extern void RemoveUnusedRegisters(void);
 extern void RegsUnMapLiveRanges(void);
 extern void BuildFlowTree(pBlock *pb);
-extern void pCodeRegOptimizeRegUsage(void);
+extern void pCodeRegOptimizeRegUsage(int level);
+extern int picIsInitialized(void);
 
 /****************************************************************/
 /*                      Forward declarations                    */
@@ -434,6 +435,27 @@ pCodeInstruction pciCLRW = {
   PCC_W  // outCond
 };
 
+pCodeInstruction pciCLRWDT = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, 
+   //   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_CLRWDT,
+  "CLRWDT",
+  NULL, // from branch
+  NULL, // to branch
+  NULL, // label
+  NULL, // operand
+  NULL, // flow block
+  NULL, // C source 
+  0,    // num ops
+  0,0,  // dest, bit instruction
+  0,0,  // branch, skip
+  POC_NOP,
+  PCC_NONE, // inCond
+  PCC_NONE  // outCond
+};
+
 pCodeInstruction pciDECF = {
   {PC_OPCODE, NULL, NULL, 0, NULL, 
    //   genericAnalyze,
@@ -1295,6 +1317,7 @@ void pic14initMnemonics(void)
   pic14Mnemonics[POC_COMFW] = &pciCOMFW;
   pic14Mnemonics[POC_CLRF] = &pciCLRF;
   pic14Mnemonics[POC_CLRW] = &pciCLRW;
+  pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
   pic14Mnemonics[POC_DECF] = &pciDECF;
   pic14Mnemonics[POC_DECFW] = &pciDECFW;
   pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
@@ -1358,7 +1381,7 @@ int getpCode(char *mnem,unsigned dest)
   while(pci) {
 
     if(STRCASECMP(pci->mnemonic, mnem) == 0) {
-      if((pci->num_ops <= 1) || (pci->isModReg == dest))
+      if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
        return(pci->op);
     }
 
@@ -2083,6 +2106,9 @@ pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
   PCORB(pcop)->bit = bit;
   PCORB(pcop)->inBitSpace = inBitSpace;
 
+  /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
+  PCOR(pcop)->r = NULL;
+  PCOR(pcop)->rIdx = 0;
   return pcop;
 }
 
@@ -2110,7 +2136,6 @@ pCodeOp *newpCodeOpReg(int rIdx)
 
     if(PCOR(pcop)->r)
       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
-    //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
   }
 
   pcop->type = PCOR(pcop)->r->pc_type;
@@ -2155,6 +2180,13 @@ pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
     pcop = newpCodeOpReg(-1);
     break;
 
+  case PO_GPR_REGISTER:
+    if(name)
+      pcop = newpCodeOpRegFromStr(name);
+    else
+      pcop = newpCodeOpReg(-1);
+    break;
+
   default:
     pcop = Safe_calloc(1,sizeof(pCodeOp) );
     pcop->type = type;
@@ -2224,16 +2256,22 @@ void pCodeReadCodeTable(void)
 /*-----------------------------------------------------------------*/
 void addpCode2pBlock(pBlock *pb, pCode *pc)
 {
+
+  if(!pc)
+    return;
+
   if(!pb->pcHead) {
     /* If this is the first pcode to be added to a block that
      * was initialized with a NULL pcode, then go ahead and
      * make this pcode the head and tail */
     pb->pcHead  = pb->pcTail = pc;
   } else {
+    //    if(pb->pcTail)
     pb->pcTail->next = pc;
+
     pc->prev = pb->pcTail;
-    //pc->next = NULL;
     pc->pb = pb;
+
     pb->pcTail = pc;
   }
 }
@@ -2678,8 +2716,13 @@ static void genericPrint(FILE *of, pCode *pc)
     break;
 
   case PC_FLOW:
-    if(debug_verbose)
-      fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
+    if(debug_verbose) {
+      fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
+      if(PCFL(pc)->ancestor)
+       fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
+      fprintf(of,"\n");
+
+    }
     break;
 
   case PC_CSOURCE:
@@ -3339,14 +3382,22 @@ void BuildFlow(pBlock *pb)
       InsertpFlow(pc, &pflow);
       seq = 0;
 
-    } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
+    } else if (checkLabel(pc)) { 
 
       /* This instruction marks the beginning of a
        * new flow segment */
 
       pc->seq = 0;
-      seq = 1; 
-      InsertpFlow(findPrevInstruction(pc->prev), &pflow);
+      seq = 1;
+
+      /* If the previous pCode is not a flow object, then 
+       * insert a new flow object. (This check prevents 
+       * two consecutive flow objects from being insert in
+       * the case where a skip instruction preceeds an
+       * instruction containing a label.) */
+
+      if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
+       InsertpFlow(findPrevInstruction(pc->prev), &pflow);
 
       PCI(pc)->pcflow = PCFL(pflow);
       
@@ -3580,8 +3631,15 @@ void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
 
 }
 
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*
+ * void LinkFlow(pBlock *pb)
+ *
+ * In BuildFlow, the PIC code has been partitioned into contiguous
+ * non-branching segments. In LinkFlow, we determine the execution
+ * order of these segments. For example, if one of the segments ends
+ * with a skip, then we know that there are two possible flow segments
+ * to which control may be passed.
+ *-----------------------------------------------------------------*/
 void LinkFlow(pBlock *pb)
 {
   pCode *pc=NULL;
@@ -3622,7 +3680,7 @@ void LinkFlow(pBlock *pb)
       //pc->print(stderr,pc);
 
       if(!(pcol && isPCOLAB(pcol))) {
-       if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
+       if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
          pc->print(stderr,pc);
          fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
        }
@@ -3656,6 +3714,8 @@ void LinkFlow(pBlock *pb)
     
   }
 }
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
@@ -3764,7 +3824,7 @@ void BanksUsedFlow(pBlock *pb)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
+void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
 {
   pCode *new_pc;
 
@@ -3777,7 +3837,15 @@ void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
     new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
                      popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
 
-  pCodeInsertAfter(pc->prev, new_pc);
+  if(position) {
+    /* insert the bank switch after this pc instruction */
+    pCode *pcnext = findNextInstruction(pc);
+    pCodeInsertAfter(pc, new_pc);
+    if(pcnext)
+      pc = pcnext;
+
+  } else
+    pCodeInsertAfter(pc->prev, new_pc);
 
   /* Move the label, if there is one */
 
@@ -3830,18 +3898,18 @@ void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
        case 0:
          break;
        case 1:
-         insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
+         insertBankSwitch(0, 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);
+         insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+         insertBankSwitch(0, 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);
+           insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+           insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
          } else
-           insertBankSwitch(pc, -1, -1);
+           insertBankSwitch(0, pc, -1, -1);
          break;
          /*
            new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
@@ -4315,7 +4383,11 @@ void pBlockMergeLabels(pBlock *pb)
 
   /* Now loop through the pBlock and merge the labels with the opcodes */
 
-  for(pc = pb->pcHead; pc; pc = pc->next) {
+  pc = pb->pcHead;
+  //  for(pc = pb->pcHead; pc; pc = pc->next) {
+
+  while(pc) {
+    pCode *pcn = pc->next;
 
     if(pc->type == PC_LABEL) {
 
@@ -4323,8 +4395,6 @@ void pBlockMergeLabels(pBlock *pb)
       //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);
        
@@ -4340,10 +4410,7 @@ void pBlockMergeLabels(pBlock *pb)
        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);
@@ -4353,18 +4420,15 @@ void pBlockMergeLabels(pBlock *pb)
       /* 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;
       }
 
     }
-
+    pc = pcn;
   }
   pBlockRemoveUnusedLabels(pb);
 
@@ -4438,11 +4502,10 @@ void FixRegisterBanking(pBlock *pb)
 {
   pCode *pc=NULL;
   pCode *pcprev=NULL;
-  pCode *new_pc;
 
   int cur_bank;
   regs *reg;
-  //  return;
+
   if(!pb)
     return;
 
@@ -4466,60 +4529,102 @@ void FixRegisterBanking(pBlock *pb)
        //genericPrint(stderr, pc);
 
        reg = getRegFromInstruction(pc);
-       #if 0
+#if 0
        if(reg) {
          fprintf(stderr, "  %s  ",reg->name);
-         fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
+         fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
+                 reg->address,REG_BANK(reg),reg->isBitField);
 
        }
-       #endif
+#endif
        if(reg && REG_BANK(reg)!=cur_bank) {
+         //fprintf(stderr,"need to switch banks\n");
          /* 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);
-             */
+
+           switch(b & 3) {
+           case 0:
+             break;
+           case 1:
+             insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+             break;
+           case 2:
+             insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             break;
+           case 3:
+             if(cur_bank & 3) {
+               insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+               insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             } else
+               insertBankSwitch(0, pc, -1, -1);
+             break;
 
            }
 
-         } else {
+
+         }else {
            //fprintf(stderr, "Bummer can't switch banks\n");
            ;
          }
        }
+
+       pcprev = pc;
+
       }
 
-      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;
+  if(pcprev && cur_bank) {
+
+    int pos = 1;  /* Assume that the bank swithc instruction(s)
+                  * are inserted after this instruction */
+
+    if((PCI(pcprev)->op == POC_RETLW) || 
+       (PCI(pcprev)->op == POC_RETURN) || 
+       (PCI(pcprev)->op == POC_RETFIE)) {
+
+      /* oops, a RETURN - we need to switch banks *before* the RETURN */
+
+      pos = 0;
+
+    } 
+           
+    /* Brute force - make sure that we point to bank 0 at the
+     * end of each flow block */
+
+    switch(cur_bank & 3) {
+    case 0:
+      break;
+    case 1:
+      insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
+      break;
+    case 2:
+      insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
+      insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
+      break;
+    case 3:
+      insertBankSwitch(pos, pcprev, -1, -1);
+      break;
+
     }
+/*
+    new_pc = newpCode(POC_BCF,
+                     popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
+    pCodeInsertAfter(pcprev, new_pc);
+*/
+    cur_bank = 0;
+    //fprintf(stderr, "Brute force switch\n");
+  }
 
 }
 
@@ -4579,9 +4684,14 @@ void mergepBlocks(char dbName)
 /*-----------------------------------------------------------------*/
 /* AnalyzeFlow - Examine the flow of the code and optimize         */
 /*                                                                 */
+/* level 0 == minimal optimization                                 */
+/*   optimize registers that are used only by two instructions     */
+/* level 1 == maximal optimization                                 */
+/*   optimize by looking at pairs of instructions that use the     */
+/*   register.                                                     */
 /*-----------------------------------------------------------------*/
 
-void AnalyzeFlow(void)
+void AnalyzeFlow(int level)
 {
   static int times_called=0;
 
@@ -4638,10 +4748,10 @@ void AnalyzeFlow(void)
    * In this phase, the individual flow blocks are examined
    * to determine their order of excution.
    */
-  /*
+
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     BuildFlowTree(pb);
-  */
+
 
   /* Phase x - Flow Analysis - Used Banks
    *
@@ -4659,7 +4769,7 @@ void AnalyzeFlow(void)
   RemoveUnusedRegisters();
 
   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
-  pCodeRegOptimizeRegUsage();
+  pCodeRegOptimizeRegUsage(level);
 
   OptimizepCode('*');
 
@@ -4702,17 +4812,29 @@ void AnalyzeBanking(void)
 {
   pBlock  *pb;
 
+  if(!picIsInitialized()) {
+    fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
+    fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
+    fprintf(stderr,"support/scripts/inc2h.pl\n");
+    fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
+
+    exit(1);
+  }
+
   /* Phase x - Flow Analysis - Used Banks
    *
    * In this phase, the individual flow blocks are examined
    * to determine the Register Banks they use
    */
 
-  AnalyzeFlow();
-  AnalyzeFlow();
+  AnalyzeFlow(0);
+  AnalyzeFlow(1);
 
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     BanksUsedFlow(pb);
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    FixRegisterBanking(pb);
+
 }
 
 /*-----------------------------------------------------------------*/