Added pcodeflow.c - much of pcode.c will eventually get moved here.
[fw/sdcc] / src / pic / pcode.c
index f3d3f56fe2c2a8cfe9abb0561bcee5f80ad6bfd3..41c8f80dc410da1183a16ac61a8472048b9fb7d4 100644 (file)
@@ -50,12 +50,12 @@ peepCommand peepCommands[] = {
 
 
 // Eventually this will go into device dependent files:
-pCodeOpReg pc_status    = {{PO_STATUS,  "STATUS"}, -1, NULL,0,NULL};
+pCodeOpReg pc_status    = {{PO_STATUS,  "_STATUS"}, -1, NULL,0,NULL};
 pCodeOpReg pc_indf      = {{PO_INDF,    "INDF"}, -1, NULL,0,NULL};
 pCodeOpReg pc_fsr       = {{PO_FSR,     "FSR"}, -1, NULL,0,NULL};
 pCodeOpReg pc_intcon    = {{PO_INTCON,  ""}, -1, NULL,0,NULL};
 pCodeOpReg pc_pcl       = {{PO_PCL,     "PCL"}, -1, NULL,0,NULL};
-pCodeOpReg pc_pclath    = {{PO_PCLATH,  "PCLATH"}, -1, NULL,0,NULL};
+pCodeOpReg pc_pclath    = {{PO_PCLATH,  "_PCLATH"}, -1, NULL,0,NULL};
 
 pCodeOpReg pc_kzero     = {{PO_GPR_REGISTER,  "KZ"}, -1, NULL,0,NULL};
 pCodeOpReg pc_wsave     = {{PO_GPR_REGISTER,  "WSAVE"}, -1, NULL,0,NULL};
@@ -70,28 +70,27 @@ static hTab *pic14pCodePeepCommandsHash = NULL;
 
 
 static pFile *the_pFile = NULL;
-static int peepOptimizing = 1;
-static int GpCodeSequenceNumber = 1;
-static int GpcFlowSeq = 1;
+static pBlock *pb_dead_pcodes = NULL;
+
+/* Hardcoded flags to change the behavior of the PIC port */
+static int peepOptimizing = 1;        /* run the peephole optimizer if nonzero */
+static int functionInlining = 1;      /* inline functions if nonzero */
+int debug_verbose = 0;                /* Set true to inundate .asm file */
 
-#define isPCI(x)        ((PCODE(x)->type == PC_OPCODE))
-#define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isBranch)
-#define isPCI_SKIP(x)   ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip)
-#define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip && PCI(x)->isBitInst)
-#define isPCFL(x)       ((PCODE(x)->type == PC_FLOW))
-#define isPCF(x)        ((PCODE(x)->type == PC_FUNCTION))
-#define isPCL(x)        ((PCODE(x)->type == PC_LABEL))
-#define isPCW(x)        ((PCODE(x)->type == PC_WILD))
-#define isPCCS(x)       ((PCODE(x)->type == PC_CSOURCE))
+static int GpCodeSequenceNumber = 1;
+int GpcFlowSeq = 1;
 
-#define isCALL(x)       ((isPCI(x)) && (PCI(x)->op == POC_CALL))
-#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
+extern void RemoveUnusedRegisters(void);
+extern void RegsUnMapLiveRanges(void);
+extern void BuildFlowTree(pBlock *pb);
+extern void pCodeRegOptimizeRegUsage(int level);
+extern int picIsInitialized(void);
 
 /****************************************************************/
 /*                      Forward declarations                    */
 /****************************************************************/
 
-static void unlinkPC(pCode *pc);
+void unlinkpCode(pCode *pc);
 #if 0
 static void genericAnalyze(pCode *pc);
 static void AnalyzeGOTO(pCode *pc);
@@ -106,11 +105,20 @@ static void pCodePrintLabel(FILE *of, pCode *pc);
 static void pCodePrintFunction(FILE *of, pCode *pc);
 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
 static char *get_op_from_instruction( pCodeInstruction *pcc);
-char *get_op( pCodeOp *pcop);
+char *get_op( pCodeOp *pcop,char *buff,int buf_size);
 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
 int pCodePeepMatchRule(pCode *pc);
 void pBlockStats(FILE *of, pBlock *pb);
+pBlock *newpBlock(void);
 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
+extern pCodeOp *popCopyReg(pCodeOpReg *pc);
+pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
+void pCodeRegMapLiveRanges(pBlock *pb);
+
+
+/****************************************************************/
+/*                    PIC Instructions                          */
+/****************************************************************/
 
 pCodeInstruction pciADDWF = {
   {PC_OPCODE, NULL, NULL, 0, NULL, 
@@ -171,7 +179,7 @@ pCodeInstruction pciADDLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
@@ -192,7 +200,7 @@ pCodeInstruction pciANDLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z) // outCond
 };
 
@@ -255,7 +263,7 @@ pCodeInstruction pciBCF = {
   1,1,  // dest, bit instruction
   0,0,  // branch, skip
   POC_BSF,
-  PCC_REGISTER,   // inCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
   PCC_REGISTER // outCond
 };
 
@@ -276,8 +284,8 @@ pCodeInstruction pciBSF = {
   1,1,  // dest, bit instruction
   0,0,  // branch, skip
   POC_BCF,
-  PCC_REGISTER,   // inCond
-  PCC_REGISTER // outCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
 };
 
 pCodeInstruction pciBTFSC = {
@@ -297,8 +305,8 @@ pCodeInstruction pciBTFSC = {
   0,1,  // dest, bit instruction
   1,1,  // branch, skip
   POC_BTFSS,
-  PCC_REGISTER,   // inCond
-  PCC_NONE // outCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  PCC_EXAMINE_PCOP // outCond
 };
 
 pCodeInstruction pciBTFSS = {
@@ -318,8 +326,8 @@ pCodeInstruction pciBTFSS = {
   0,1,  // dest, bit instruction
   1,1,  // branch, skip
   POC_BTFSC,
-  PCC_REGISTER,   // inCond
-  PCC_NONE // outCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  PCC_EXAMINE_PCOP // outCond
 };
 
 pCodeInstruction pciCALL = {
@@ -402,7 +410,7 @@ pCodeInstruction pciCLRF = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_REGISTER, // inCond
+  PCC_NONE, // inCond
   PCC_REGISTER  // outCond
 };
 
@@ -423,10 +431,31 @@ pCodeInstruction pciCLRW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W, // inCond
+  PCC_NONE, // inCond
   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,
@@ -675,7 +704,7 @@ pCodeInstruction pciIORLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z) // outCond
 };
 
@@ -759,7 +788,7 @@ pCodeInstruction pciMOVLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_NONE,   // inCond
+  (PCC_NONE | PCC_LITERAL),   // inCond
   PCC_W // outCond
 };
 
@@ -821,7 +850,7 @@ pCodeInstruction pciRETLW = {
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
   POC_NOP,
-  PCC_NONE,   // inCond
+  PCC_LITERAL,   // inCond
   PCC_W // outCond
 };
 
@@ -989,7 +1018,7 @@ pCodeInstruction pciSUBLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
@@ -1115,7 +1144,7 @@ pCodeInstruction pciXORLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
@@ -1153,6 +1182,7 @@ void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
   len = strlen(*str);
   if(len > *size) {
     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
+    fprintf(stderr,"len = %d is > str size %d\n",len,*size);
   }
 
   *str += len;
@@ -1181,6 +1211,7 @@ void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
   len = strlen(buffer);
   if(len > *size) {
     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
+    fprintf(stderr,"len = %d is > str size %d\n",len,*size);
   }
 
   strcpy(*str, buffer);
@@ -1199,13 +1230,18 @@ extern void init_pic(char *);
 
 void  pCodeInitRegisters(void)
 {
+  static int initialized=0;
+
+  if(initialized)
+    return;
+  initialized = 1;
 
   initStack(0xfff, 8);
   init_pic(port->processor);
 
-  pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
+  pc_status.r = allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
   pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
-  pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
+  pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
   pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
   pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
   pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
@@ -1225,6 +1261,9 @@ void  pCodeInitRegisters(void)
   pc_wsave.rIdx = IDX_WSAVE;
   pc_ssave.rIdx = IDX_SSAVE;
 
+  /* probably should put this in a separate initialization routine */
+  pb_dead_pcodes = newpBlock();
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -1583,11 +1622,11 @@ pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
     memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
     pci->pcop = pcop;
 
-    if(pci->inCond == PCC_EXAMINE_PCOP)
-      pci->inCond   = RegCond(pcop);
+    if(pci->inCond & PCC_EXAMINE_PCOP)
+      pci->inCond  |= RegCond(pcop);
 
-    if(pci->outCond == PCC_EXAMINE_PCOP)
-      pci->outCond   = RegCond(pcop);
+    if(pci->outCond & PCC_EXAMINE_PCOP)
+      pci->outCond  |= RegCond(pcop);
 
     pci->pc.prev = pci->pc.next = NULL;
     return (pCode *)pci;
@@ -1747,19 +1786,22 @@ pCode *newpCodeFunction(char *mod,char *f)
 /*-----------------------------------------------------------------*/
 /* newpCodeFlow                                                    */
 /*-----------------------------------------------------------------*/
-
 void destructpCodeFlow(pCode *pc)
 {
   if(!pc || !isPCFL(pc))
     return;
 
-  if(PCFL(pc)->uses)
-    free(PCFL(pc)->uses);
 /*
   if(PCFL(pc)->from)
   if(PCFL(pc)->to)
 */
+  unlinkpCode(pc);
+
+  deleteSet(&PCFL(pc)->registers);
+  deleteSet(&PCFL(pc)->from);
+  deleteSet(&PCFL(pc)->to);
   free(pc);
+
 }
 
 pCode *newpCodeFlow(void )
@@ -1771,7 +1813,6 @@ pCode *newpCodeFlow(void )
 
   pcflow->pc.type = PC_FLOW;
   pcflow->pc.prev = pcflow->pc.next = NULL;
-  //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
   pcflow->pc.pb = NULL;
 
   //  pcflow->pc.analyze = genericAnalyze;
@@ -1780,19 +1821,39 @@ pCode *newpCodeFlow(void )
 
   pcflow->pc.seq = GpcFlowSeq++;
 
-  pcflow->nuses = 7;
-  pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
-
   pcflow->from = pcflow->to = NULL;
 
   pcflow->inCond = PCC_NONE;
   pcflow->outCond = PCC_NONE;
 
+  pcflow->firstBank = -1;
+  pcflow->lastBank = -1;
+
+  pcflow->FromConflicts = 0;
+  pcflow->ToConflicts = 0;
+
   pcflow->end = NULL;
+
+  pcflow->registers = newSet();
+
   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              */
 /*-----------------------------------------------------------------*/
@@ -1889,6 +1950,7 @@ pBlock *newpBlock(void)
   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
   PpB->tregisters = NULL;
   PpB->visited = 0;
+  PpB->FlowTree = NULL;
 
   return PpB;
 
@@ -1979,13 +2041,21 @@ pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
   pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
   pcop->type = PO_IMMEDIATE;
   if(name) {
+    regs *r = dirregWithName(name);
     pcop->name = Safe_strdup(name);
+    PCOI(pcop)->r = r;
+    if(r) {
+      //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
+      PCOI(pcop)->rIdx = r->rIdx;
+    } else {
+      //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
+      PCOI(pcop)->rIdx = -1;
+    }
     //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
   } else {
     pcop->name = NULL;
   }
 
-
   PCOI(pcop)->index = index;
   PCOI(pcop)->offset = offset;
   PCOI(pcop)->_const = code_space;
@@ -2176,16 +2246,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;
   }
 }
@@ -2292,7 +2368,7 @@ void printpBlock(FILE *of, pBlock *pb)
 /*                                                                 */
 /*-----------------------------------------------------------------*/
 
-static void unlinkPC(pCode *pc)
+void unlinkpCode(pCode *pc)
 {
 
 
@@ -2309,13 +2385,34 @@ static void unlinkPC(pCode *pc)
     pc->prev = pc->next = NULL;
   }
 }
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
 static void genericDestruct(pCode *pc)
 {
-  //fprintf(stderr,"warning, calling default pCode destructor\n");
 
-  unlinkPC(pc);
+  unlinkpCode(pc);
 
-  free(pc);
+  if(isPCI(pc)) {
+    /* For instructions, tell the register (if there's one used)
+     * that it's no longer needed */
+    regs *reg = getRegFromInstruction(pc);
+    if(reg)
+      deleteSetItem (&(reg->reglives.usedpCodes),pc);
+  }
+
+  /* Instead of deleting the memory used by this pCode, mark
+   * the object as bad so that if there's a pointer to this pCode
+   * dangling around somewhere then (hopefully) when the type is
+   * checked we'll catch it.
+   */
+
+  pc->type = PC_BAD;
+
+  addpCode2pBlock(pb_dead_pcodes, pc);
+
+  //free(pc);
 
 }
 
@@ -2336,34 +2433,43 @@ void pBlockRegs(FILE *of, pBlock *pb)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-char *get_op(pCodeOp *pcop)
+char *get_op(pCodeOp *pcop,char *buffer, int size)
 {
   regs *r;
-  static char buffer[50];
+  static char b[50];
   char *s;
-  int size;
+  int use_buffer = 1;    // copy the string to the passed buffer pointer
 
+  if(!buffer) {
+    buffer = b;
+    size = sizeof(b);
+    use_buffer = 0;     // Don't bother copying the string to the buffer.
+  } 
 
   if(pcop) {
     switch(pcop->type) {
     case PO_INDF:
     case PO_FSR:
-      //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
-      //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
-      //return r->name;
+      if(use_buffer) {
+       SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
+       return buffer;
+      }
       return PCOR(pcop)->r->name;
       break;
     case PO_GPR_TEMP:
       r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
-      //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
+
+      if(use_buffer) {
+       SAFE_snprintf(&buffer,&size,"%s",r->name);
+       return buffer;
+      }
+
       return r->name;
 
-      //    case PO_GPR_BIT:
-      //      return PCOR(pcc->pcop)->r)->name;
+
     case PO_IMMEDIATE:
       s = buffer;
-      size = sizeof(buffer);
-      //fprintf(stderr,"PO_IMMEDIATE name = %s  offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset);
+
       if(PCOI(pcop)->_const) {
 
        if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
@@ -2387,7 +2493,7 @@ char *get_op(pCodeOp *pcop)
 
     case PO_DIR:
       s = buffer;
-      size = sizeof(buffer);
+      //size = sizeof(buffer);
       if( PCOR(pcop)->instance) {
        SAFE_snprintf(&s,&size,"(%s + %d)",
                      pcop->name,
@@ -2398,8 +2504,13 @@ char *get_op(pCodeOp *pcop)
       return buffer;
 
     default:
-      if  (pcop->name)
+      if  (pcop->name) {
+       if(use_buffer) {
+         SAFE_snprintf(&buffer,&size,"%s",pcop->name);
+         return buffer;
+       }
        return pcop->name;
+      }
 
     }
   }
@@ -2414,7 +2525,7 @@ static char *get_op_from_instruction( pCodeInstruction *pcc)
 {
 
   if(pcc )
-    return get_op(pcc->pcop);
+    return get_op(pcc->pcop,NULL,0);
   
   return ("ERROR Null: "__FUNCTION__);
 
@@ -2498,9 +2609,11 @@ char *pCode2str(char *str, int size, pCode *pc)
     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
     break;
   case PC_CSOURCE:
-  SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
+    SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
     break;
 
+  case PC_BAD:
+    SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
   }
 
   return str;
@@ -2547,9 +2660,11 @@ static void genericPrint(FILE *of, pCode *pc)
       fprintf(of,"%s",str);
 
       /* Debug */
-      fprintf(of, "\t;key=%03x",pc->seq);
-      if(PCI(pc)->pcflow)
-       fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
+      if(debug_verbose) {
+       fprintf(of, "\t;key=%03x",pc->seq);
+       if(PCI(pc)->pcflow)
+         fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
+      }
     }
 #if 0
     {
@@ -2591,7 +2706,8 @@ static void genericPrint(FILE *of, pCode *pc)
     break;
 
   case PC_FLOW:
-    fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
+    if(debug_verbose)
+      fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
     break;
 
   case PC_CSOURCE:
@@ -2700,13 +2816,16 @@ static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-static pBranch * pBranchAppend(pBranch *h, pBranch *n)
+pBranch * pBranchAppend(pBranch *h, pBranch *n)
 {
   pBranch *b;
 
   if(!h)
     return n;
 
+  if(h == n)
+    return n;
+
   b = h;
   while(b->next)
     b = b->next;
@@ -2841,6 +2960,9 @@ static void genericAnalyze(pCode *pc)
     fprintf(stderr,"analyze PC_FLOW\n");
 
     return;
+  case PC_BAD:
+    fprintf(stderr,,";A bad pCode is being used\n");
+
   }
 }
 #endif
@@ -2888,6 +3010,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 +3039,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);
@@ -3035,6 +3172,7 @@ static void AnalyzeRETURN(pCode *pc)
 /*-----------------------------------------------------------------*/
 regs * getRegFromInstruction(pCode *pc)
 {
+
   if(!pc                   || 
      !isPCI(pc)            ||
      !PCI(pc)->pcop        ||
@@ -3044,7 +3182,9 @@ regs * getRegFromInstruction(pCode *pc)
   switch(PCI(pc)->pcop->type) {
   case PO_INDF:
   case PO_FSR:
-    return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
+    return PCOR(PCI(pc)->pcop)->r;
+
+    //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
 
   case PO_BIT:
   case PO_GPR_TEMP:
@@ -3052,8 +3192,12 @@ regs * getRegFromInstruction(pCode *pc)
     return PCOR(PCI(pc)->pcop)->r;
 
   case PO_IMMEDIATE:
+    if(PCOI(PCI(pc)->pcop)->r)
+      return (PCOI(PCI(pc)->pcop)->r);
+
     //fprintf(stderr, "getRegFromInstruction - immediate\n");
-    return NULL; // PCOR(PCI(pc)->pcop)->r;
+    return dirregWithName(PCI(pc)->pcop->name);
+    //return NULL; // PCOR(PCI(pc)->pcop)->r;
 
   case PO_GPR_BIT:
     return PCOR(PCI(pc)->pcop)->r;
@@ -3111,10 +3255,11 @@ void AnalyzepBlock(pBlock *pb)
 
        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;
+         //r = Safe_calloc(1, sizeof(regs));
+         //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
+         //addSet(&pb->tregisters, r);
+         addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->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);
@@ -3144,7 +3289,8 @@ void AnalyzepBlock(pBlock *pb)
 
 void InsertpFlow(pCode *pc, pCode **pflow)
 {
-  PCFL(*pflow)->end = pc;
+  if(*pflow)
+    PCFL(*pflow)->end = pc;
 
   if(!pc || !pc->next)
     return;
@@ -3165,7 +3311,7 @@ void BuildFlow(pBlock *pb)
 {
   pCode *pc;
   pCode *last_pci=NULL;
-  pCode *pflow;
+  pCode *pflow=NULL;
   int seq = 0;
 
   if(!pb)
@@ -3174,18 +3320,24 @@ void BuildFlow(pBlock *pb)
   //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;
+  InsertpFlow(pb->pcHead, &pflow);
+
+  //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; ) { 
+  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 
@@ -3232,7 +3384,8 @@ void BuildFlow(pBlock *pb)
   }
 
   //fprintf (stderr,",end seq %d",GpcFlowSeq);
-  PCFL(pflow)->end = pb->pcTail;
+  if(pflow)
+    PCFL(pflow)->end = pb->pcTail;
 }
 
 /*-------------------------------------------------------------------*/
@@ -3244,27 +3397,31 @@ void BuildFlow(pBlock *pb)
 /*-----------------------------------------------------------------*/
 void unBuildFlow(pBlock *pb)
 {
-  pCode *pc;
+  pCode *pc,*pcnext;
 
   if(!pb)
     return;
 
   pc = pb->pcHead;
+
   while(pc) {
-    pCode *pcn = pc->next;
+    pcnext = pc->next;
 
     if(isPCI(pc)) {
+
       pc->seq = 0;
-      PCI(pc)->pcflow = NULL;
-      pc = pcn;
-    } else if(isPCFL(pc)) {
-      unlinkPC(pc);
+      if(PCI(pc)->pcflow) {
+       //free(PCI(pc)->pcflow);
+       PCI(pc)->pcflow = NULL;
+      }
+
+    } else if(isPCFL(pc) )
       pc->destruct(pc);
-    } else 
-      pc = pcn;
 
+    pc = pcnext;
   }
 
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -3324,6 +3481,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 +3572,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,17 +3595,28 @@ 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);
 
 }
 
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*
+ * 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;
@@ -3437,12 +3624,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 +3642,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 +3650,528 @@ 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_RETLW) && (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;
     }
-    else 
-      fprintf(stderr, "has no end pcode\n");
-    #endif 
+
+    //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)
@@ -3490,6 +4189,9 @@ int OptimizepBlock(pBlock *pb)
 */
 
   pc = findNextInstruction(pb->pcHead);
+  if(!pc)
+    return 0;
+
   pcprev = pc->prev;
   do {
 
@@ -3616,7 +4318,7 @@ void pBlockRemoveUnusedLabels(pBlock *pb)
 
       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
       if(pc->type == PC_LABEL) {
-       unlinkPC(pc);
+       unlinkpCode(pc);
        pCodeLabelDestruct(pc);
       } else {
        unlinkpCodeFromBranch(pc, PCODE(pcl));
@@ -3650,7 +4352,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) {
 
@@ -3658,10 +4364,8 @@ 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
-       unlinkPC(pc);
+       unlinkpCode(pc);
        
        //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
        // And link it into the instruction's pBranch labels. (Note, since
@@ -3675,10 +4379,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);
@@ -3688,18 +4389,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
-       unlinkPC(pc);
+       unlinkpCode(pc);
        PCI(pcnext)->cline = PCCS(pc);
        //fprintf(stderr, "merging CSRC\n");
        //genericPrint(stderr,pcnext);
-       pc = pcn;
       }
 
     }
-
+    pc = pcn;
   }
   pBlockRemoveUnusedLabels(pb);
 
@@ -3781,7 +4479,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 +4494,7 @@ void FixRegisterBanking(pBlock *pb)
     /* for each flow block, determine the register banking 
        requirements */
 
-    do {
+    //    do {
       if(isPCI(pc)) {
        //genericPrint(stderr, pc);
 
@@ -3841,7 +4540,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 +4554,6 @@ void FixRegisterBanking(pBlock *pb)
       cur_bank = 0;
     }
 
-  }while (pc);
-
 }
 
 void pBlockDestruct(pBlock *pb)
@@ -3910,12 +4610,18 @@ void mergepBlocks(char dbName)
 }
 
 /*-----------------------------------------------------------------*/
-/* AnalyzeBanking - Called after the memory addresses have been    */
-/*                  assigned to the registers.                     */
+/* 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 AnalyzeBanking(void)
+
+void AnalyzeFlow(int level)
 {
+  static int times_called=0;
 
   pBlock *pb;
 
@@ -3923,6 +4629,27 @@ void AnalyzeBanking(void)
     return;
 
 
+  /* if this is not the first time this function has been called,
+     then clean up old flow information */
+  if(times_called++) {
+    for(pb = the_pFile->pbHead; pb; pb = pb->next)
+      unBuildFlow(pb);
+
+    RegsUnMapLiveRanges();
+
+  }
+
+  GpcFlowSeq = 1;
+
+  /* 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 +4661,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 +4671,41 @@ void AnalyzeBanking(void)
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     LinkFlow(pb);
 
+  /* Phase 3 - Flow Analysis - Flow Tree
+   *
+   * In this phase, the individual flow blocks are examined
+   * to determine their order of excution.
+   */
+  /*
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
-    FixRegisterBanking(pb);
+    BuildFlowTree(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)
+    pCodeRegMapLiveRanges(pb);
+
+  RemoveUnusedRegisters();
+
+  //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+  pCodeRegOptimizeRegUsage(level);
+
+  OptimizepCode('*');
+
+
+/*
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    DumpFlow(pb);
+*/
   /* debug stuff */ 
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
     pCode *pcflow;
@@ -3956,6 +4716,7 @@ void AnalyzeBanking(void)
       FillFlow(PCFL(pcflow));
     }
   }
+
 /*
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
     pCode *pcflow;
@@ -3969,6 +4730,41 @@ void AnalyzeBanking(void)
 */
 }
 
+/*-----------------------------------------------------------------*/
+/* AnalyzeBanking - Called after the memory addresses have been    */
+/*                  assigned to the registers.                     */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+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(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);
+
+}
+
 /*-----------------------------------------------------------------*/
 /* buildCallTree - look at the flow and extract all of the calls   */
 /*                                                                 */
@@ -4050,7 +4846,8 @@ void buildCallTree(void    )
   /* Re-allocate the registers so that there are no collisions
    * between local variables when one function call another */
 
-  pic14_deallocateAllRegs();
+  // this is weird...
+  //  pic14_deallocateAllRegs();
 
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
     if(!pb->visited)
@@ -4218,6 +5015,7 @@ void pBlockStats(FILE *of, pBlock *pb)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
+#if 0
 static void sequencepCode(void)
 {
   pBlock *pb;
@@ -4233,6 +5031,7 @@ static void sequencepCode(void)
   }
 
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
@@ -4566,6 +5365,8 @@ void InlinepCode(void)
   if(!the_pFile)
     return;
 
+  if(!functionInlining)
+    return;
 
   /* Loop through all of the function definitions and count the
    * number of times each one is called */
@@ -4592,7 +5393,7 @@ void InlinepCode(void)
 
   /* Now, Loop through the function definitions again, but this
    * time inline those functions that have only been called once. */
-
+  
   InlineFunction(the_pFile->pbHead);
   //fprintf(stderr,"inlining %d\n",__LINE__);