Added pcodeflow.c - much of pcode.c will eventually get moved here.
[fw/sdcc] / src / pic / pcode.c
index 2c0c54268b950e732c0bf4738d823b3a50140ea9..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,24 +70,27 @@ static hTab *pic14pCodePeepCommandsHash = NULL;
 
 
 static pFile *the_pFile = NULL;
-static int peepOptimizing = 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 */
+
 static int GpCodeSequenceNumber = 1;
-static int GpcFlowSeq = 1;
+int GpcFlowSeq = 1;
 
-#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 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);
@@ -102,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, 
@@ -120,6 +132,7 @@ pCodeInstruction pciADDWF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -140,6 +153,7 @@ pCodeInstruction pciADDFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -160,11 +174,12 @@ pCodeInstruction pciADDLW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   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
 };
 
@@ -180,11 +195,12 @@ pCodeInstruction pciANDLW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z) // outCond
 };
 
@@ -200,6 +216,7 @@ pCodeInstruction pciANDWF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -220,6 +237,7 @@ pCodeInstruction pciANDFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -240,11 +258,12 @@ pCodeInstruction pciBCF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,1,  // dest, bit instruction
   0,0,  // branch, skip
   POC_BSF,
-  PCC_REGISTER,   // inCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
   PCC_REGISTER // outCond
 };
 
@@ -260,12 +279,13 @@ pCodeInstruction pciBSF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   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 = {
@@ -280,12 +300,13 @@ pCodeInstruction pciBTFSC = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   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 = {
@@ -300,12 +321,13 @@ pCodeInstruction pciBTFSS = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   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 = {
@@ -320,6 +342,7 @@ pCodeInstruction pciCALL = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
@@ -340,6 +363,7 @@ pCodeInstruction pciCOMF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -360,6 +384,7 @@ pCodeInstruction pciCOMFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -380,11 +405,12 @@ pCodeInstruction pciCLRF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_REGISTER, // inCond
+  PCC_NONE, // inCond
   PCC_REGISTER  // outCond
 };
 
@@ -400,14 +426,36 @@ pCodeInstruction pciCLRW = {
   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_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,
@@ -420,6 +468,7 @@ pCodeInstruction pciDECF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -440,6 +489,7 @@ pCodeInstruction pciDECFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -460,6 +510,7 @@ pCodeInstruction pciDECFSZ = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   1,1,  // branch, skip
@@ -480,6 +531,7 @@ pCodeInstruction pciDECFSZW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   1,1,  // branch, skip
@@ -500,6 +552,7 @@ pCodeInstruction pciGOTO = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
@@ -520,6 +573,7 @@ pCodeInstruction pciINCF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -540,6 +594,7 @@ pCodeInstruction pciINCFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -560,6 +615,7 @@ pCodeInstruction pciINCFSZ = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   1,1,  // branch, skip
@@ -580,6 +636,7 @@ pCodeInstruction pciINCFSZW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   1,1,  // branch, skip
@@ -600,6 +657,7 @@ pCodeInstruction pciIORWF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -620,6 +678,7 @@ pCodeInstruction pciIORFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -640,11 +699,12 @@ pCodeInstruction pciIORLW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z) // outCond
 };
 
@@ -660,6 +720,7 @@ pCodeInstruction pciMOVF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -680,6 +741,7 @@ pCodeInstruction pciMOVFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -700,6 +762,7 @@ pCodeInstruction pciMOVWF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -720,11 +783,12 @@ pCodeInstruction pciMOVLW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_NONE,   // inCond
+  (PCC_NONE | PCC_LITERAL),   // inCond
   PCC_W // outCond
 };
 
@@ -739,6 +803,7 @@ pCodeInstruction pciNOP = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   0,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -759,6 +824,7 @@ pCodeInstruction pciRETFIE = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   0,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
@@ -779,11 +845,12 @@ pCodeInstruction pciRETLW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
   POC_NOP,
-  PCC_NONE,   // inCond
+  PCC_LITERAL,   // inCond
   PCC_W // outCond
 };
 
@@ -799,6 +866,7 @@ pCodeInstruction pciRETURN = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   0,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
@@ -819,6 +887,7 @@ pCodeInstruction pciRLF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -839,6 +908,7 @@ pCodeInstruction pciRLFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -859,6 +929,7 @@ pCodeInstruction pciRRF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -879,6 +950,7 @@ pCodeInstruction pciRRFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -899,6 +971,7 @@ pCodeInstruction pciSUBWF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -919,6 +992,7 @@ pCodeInstruction pciSUBFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -939,11 +1013,12 @@ pCodeInstruction pciSUBLW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   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
 };
 
@@ -959,6 +1034,7 @@ pCodeInstruction pciSWAPF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -979,6 +1055,7 @@ pCodeInstruction pciSWAPFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -999,6 +1076,7 @@ pCodeInstruction pciTRIS = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -1019,6 +1097,7 @@ pCodeInstruction pciXORWF = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -1039,6 +1118,7 @@ pCodeInstruction pciXORFW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
@@ -1059,11 +1139,12 @@ pCodeInstruction pciXORLW = {
   NULL, // label
   NULL, // operand
   NULL, // flow block
+  NULL, // C source 
   1,    // num ops
   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
 };
 
@@ -1101,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;
@@ -1129,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);
@@ -1147,13 +1230,18 @@ extern void init_pic(char *);
 
 void  pCodeInitRegisters(void)
 {
+  static int initialized=0;
+
+  if(initialized)
+    return;
+  initialized = 1;
 
-  initStack(0x38, 8);
+  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);
@@ -1173,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();
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -1531,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;
@@ -1672,6 +1763,8 @@ pCode *newpCodeFunction(char *mod,char *f)
   pcf->pc.destruct = genericDestruct;
   pcf->pc.print = pCodePrintFunction;
 
+  pcf->ncalled = 0;
+
   if(mod) {
     //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
     pcf->modname = Safe_calloc(1,strlen(mod)+1);
@@ -1693,7 +1786,23 @@ pCode *newpCodeFunction(char *mod,char *f)
 /*-----------------------------------------------------------------*/
 /* newpCodeFlow                                                    */
 /*-----------------------------------------------------------------*/
+void destructpCodeFlow(pCode *pc)
+{
+  if(!pc || !isPCFL(pc))
+    return;
+
+/*
+  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 )
 {
@@ -1704,28 +1813,79 @@ 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;
-  pcflow->pc.destruct = genericDestruct;
+  pcflow->pc.destruct = destructpCodeFlow;
   pcflow->pc.print = genericPrint;
 
   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              */
+/*-----------------------------------------------------------------*/
+
+pCode *newpCodeCSource(int ln, char *f, char *l)
+{
+
+  pCodeCSource *pccs;
+    
+  pccs = Safe_calloc(1,sizeof(pCodeCSource));
+
+  pccs->pc.type = PC_CSOURCE;
+  pccs->pc.prev = pccs->pc.next = NULL;
+  pccs->pc.pb = NULL;
+
+  pccs->pc.destruct = genericDestruct;
+  pccs->pc.print = genericPrint;
+
+  pccs->line_number = ln;
+  if(l)
+    pccs->line = Safe_strdup(l);
+  else
+    pccs->line = NULL;
+
+  if(f)
+    pccs->file_name = Safe_strdup(f);
+  else
+    pccs->file_name = NULL;
+
+  return ( (pCode *)pccs);
+
+}
 /*-----------------------------------------------------------------*/
 /* pCodeLabelDestruct - free memory used by a label.               */
 /*-----------------------------------------------------------------*/
@@ -1790,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;
 
@@ -1880,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;
@@ -2077,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;
   }
 }
@@ -2113,6 +2288,43 @@ void addpBlock(pBlock *pb)
   the_pFile->pbTail = pb;
 }
 
+/*-----------------------------------------------------------------*/
+/* removepBlock - remove a pBlock from the pFile                   */
+/*-----------------------------------------------------------------*/
+void removepBlock(pBlock *pb)
+{
+  pBlock *pbs;
+
+  if(!the_pFile)
+    return;
+
+
+  //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
+
+  for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
+    if(pbs == pb) {
+
+      if(pbs == the_pFile->pbHead)
+       the_pFile->pbHead = pbs->next;
+
+      if (pbs == the_pFile->pbTail) 
+       the_pFile->pbTail = pbs->prev;
+
+      if(pbs->next)
+       pbs->next->prev = pbs->prev;
+
+      if(pbs->prev)
+       pbs->prev->next = pbs->next;
+
+      return;
+
+    }
+  }
+
+  fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
+
+}
+
 /*-----------------------------------------------------------------*/
 /* printpCode - write the contents of a pCode to a file            */
 /*-----------------------------------------------------------------*/
@@ -2156,11 +2368,15 @@ void printpBlock(FILE *of, pBlock *pb)
 /*                                                                 */
 /*-----------------------------------------------------------------*/
 
-static void unlinkPC(pCode *pc)
+void unlinkpCode(pCode *pc)
 {
 
 
   if(pc) {
+#ifdef PCODE_DEBUG
+    fprintf(stderr,"Unlinking: ");
+    printpCode(stderr, pc);
+#endif
     if(pc->prev) 
       pc->prev->next = pc->next;
     if(pc->next)
@@ -2169,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);
 
 }
 
@@ -2196,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) {
@@ -2247,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,
@@ -2258,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;
+      }
 
     }
   }
@@ -2274,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__);
 
@@ -2285,9 +2536,11 @@ static char *get_op_from_instruction( pCodeInstruction *pcc)
 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
 {
 
-  fprintf(of,"pcodeopprint\n");
+  fprintf(of,"pcodeopprint- not implemented\n");
 }
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
 char *pCode2str(char *str, int size, pCode *pc)
 {
   char *s = str;
@@ -2355,6 +2608,12 @@ char *pCode2str(char *str, int size, pCode *pc)
   case PC_FLOW:
     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);
+    break;
+
+  case PC_BAD:
+    SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
   }
 
   return str;
@@ -2390,6 +2649,8 @@ static void genericPrint(FILE *of, pCode *pc)
       }
     }
 
+    if(PCI(pc)->cline) 
+      genericPrint(of,PCODE(PCI(pc)->cline));
 
     {
       char str[256];
@@ -2399,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
     {
@@ -2443,9 +2706,13 @@ 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:
+    fprintf(of,";#CSRC\t%s %d\n;  %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
+    break;
   case PC_LABEL:
   default:
     fprintf(of,"unknown pCode type %d\n",pc->type);
@@ -2523,8 +2790,12 @@ static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
 
   }
 
+  //fprintf (stderr, "%s \n",__FUNCTION__);
+  //pcl->print(stderr,pcl);
+  //pc->print(stderr,pc);
   while(b) {
     if(b->pc == pc) {
+      //fprintf (stderr, "found label\n");
 
       /* Found a label */
       if(bprev) {
@@ -2541,41 +2812,20 @@ static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
     b = b->next;
   }
 
-#if 0
-
-  original stuff:
-
-  bprev = NULL;
-  b = pcl->label;
-  while(b) {
-    if(b->pc == pc) {
-
-      /* Found a label */
-      if(bprev) {
-       bprev->next = b->next;  /* Not first pCode in chain */
-       free(b);
-      } else {
-       pc->destruct(pc);
-       pcl->label = b->next;   /* First pCode in chain */
-       free(b);
-      }
-      return;  /* A label can't occur more than once */
-    }
-    bprev = b;
-    b = b->next;
-  }
-#endif
 }
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-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;
@@ -2710,10 +2960,14 @@ 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
 
+/*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
 {
@@ -2737,6 +2991,42 @@ int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
   return FALSE;
 }
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+int checkLabel(pCode *pc)
+{
+  pBranch *pbr;
+
+  if(pc && isPCI(pc)) {
+    pbr = PCI(pc)->label;
+    while(pbr) {
+      if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
+       return TRUE;
+
+      pbr = pbr->next;
+    }
+  }
+
+  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             */
 /*-----------------------------------------------------------------*/
@@ -2749,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);
@@ -2796,12 +3084,14 @@ pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
 /* findNextInstruction - given a pCode, find the next instruction  */
 /*                       in the linked list                        */
 /*-----------------------------------------------------------------*/
-pCode * findNextInstruction(pCode *pc)
+pCode * findNextInstruction(pCode *pci)
 {
+  pCode *pc = pci;
 
   while(pc) {
     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
       return pc;
+
 #ifdef PCODE_DEBUG
     fprintf(stderr,"findNextInstruction:  ");
     printpCode(stderr, pc);
@@ -2813,9 +3103,18 @@ pCode * findNextInstruction(pCode *pc)
   return NULL;
 }
 
+/*-----------------------------------------------------------------*/
+/* findNextInstruction - given a pCode, find the next instruction  */
+/*                       in the linked list                        */
+/*-----------------------------------------------------------------*/
+pCode * findPrevInstruction(pCode *pci)
+{
+  return findPrevpCode(pci, PC_OPCODE);
+}
+
 /*-----------------------------------------------------------------*/
 /* findFunctionEnd - given a pCode find the end of the function    */
-/*                   that contains it     t                        */
+/*                   that contains it                              */
 /*-----------------------------------------------------------------*/
 pCode * findFunctionEnd(pCode *pc)
 {
@@ -2873,6 +3172,7 @@ static void AnalyzeRETURN(pCode *pc)
 /*-----------------------------------------------------------------*/
 regs * getRegFromInstruction(pCode *pc)
 {
+
   if(!pc                   || 
      !isPCI(pc)            ||
      !PCI(pc)->pcop        ||
@@ -2882,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:
@@ -2890,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;
@@ -2949,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);
@@ -2982,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;
@@ -3003,7 +3311,7 @@ void BuildFlow(pBlock *pb)
 {
   pCode *pc;
   pCode *last_pci=NULL;
-  pCode *pflow;
+  pCode *pflow=NULL;
   int seq = 0;
 
   if(!pb)
@@ -3012,34 +3320,61 @@ 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);
 
-  for( pc = findNextInstruction(pb->pcHead); 
-      (pc=findNextInstruction(pc)) != NULL; ) { 
+  //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 != NULL;
+       pc=findNextInstruction(pc)) { 
 
     pc->seq = seq++;
     PCI(pc)->pcflow = PCFL(pflow);
 
-    if(PCI(pc)->isSkip || PCI(pc)->isBranch)  {
+    //fprintf(stderr," build: ");
+    //pflow->print(stderr,pflow);
+
+    if( PCI(pc)->isSkip) {
+
+      /* The two instructions immediately following this one 
+       * mark the beginning of a new flow segment */
+
+      while(pc && PCI(pc)->isSkip) {
+
+       PCI(pc)->pcflow = PCFL(pflow);
+       pc->seq = seq-1;
+       seq = 1;
+
+       InsertpFlow(pc, &pflow);
+       pc=findNextInstruction(pc->next);
+      }
+
+      seq = 0;
+
+      if(!pc)
+       break;
+
+      PCI(pc)->pcflow = PCFL(pflow);
+      pc->seq = 0;
+      InsertpFlow(pc, &pflow);
 
-      /* The instruction immediately following this one 
-       * marks the beginning of a new flow segment */
+    } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next)))  {
 
       InsertpFlow(pc, &pflow);
       seq = 0;
-         
-    } else if (PCI_HAS_LABEL(pc)) {
+
+    } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
 
       /* This instruction marks the beginning of a
        * new flow segment */
 
       pc->seq = 0;
       seq = 1; 
-      InsertpFlow(pc->prev, &pflow);
+      InsertpFlow(findPrevInstruction(pc->prev), &pflow);
 
       PCI(pc)->pcflow = PCFL(pflow);
       
@@ -3049,7 +3384,44 @@ void BuildFlow(pBlock *pb)
   }
 
   //fprintf (stderr,",end seq %d",GpcFlowSeq);
-  PCFL(pflow)->end = pb->pcTail;
+  if(pflow)
+    PCFL(pflow)->end = pb->pcTail;
+}
+
+/*-------------------------------------------------------------------*/
+/* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
+/*                           the flow blocks.                        */
+/*
+ * unBuildFlow removes pCodeFlow objects from a pCode chain
+ */
+/*-----------------------------------------------------------------*/
+void unBuildFlow(pBlock *pb)
+{
+  pCode *pc,*pcnext;
+
+  if(!pb)
+    return;
+
+  pc = pb->pcHead;
+
+  while(pc) {
+    pcnext = pc->next;
+
+    if(isPCI(pc)) {
+
+      pc->seq = 0;
+      if(PCI(pc)->pcflow) {
+       //free(PCI(pc)->pcflow);
+       PCI(pc)->pcflow = NULL;
+      }
+
+    } else if(isPCFL(pc) )
+      pc->destruct(pc);
+
+    pc = pcnext;
+  }
+
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -3084,119 +3456,185 @@ void dumpCond(int cond)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-void FillFlow(pCodeFlow *pcflow)
+void FlowStats(pCodeFlow *pcflow)
 {
 
   pCode *pc;
-  int cur_bank;
 
   if(!isPCFL(pcflow))
     return;
 
-  //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
+  fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
 
   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
+
   if(!pc) {
-    //    fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
+    fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
     return;
   }
 
-  cur_bank = -1;
-
-  do {
-    //regs *reg;
-
-    int inCond = PCI(pc)->inCond;
-    int outCond = PCI(pc)->outCond;
-#if 0
-    if( (reg = getRegFromInstruction(pc)) != NULL) {
-      if(isSTATUS_REG(reg)) {
-
-       //fprintf(stderr, "  FillFlow - Status register\n");
-
-       /* 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);
-    }
-#endif
+  fprintf(stderr, "  FlowStats inCond: ");
+  dumpCond(pcflow->inCond);
+  fprintf(stderr, "  FlowStats outCond: ");
+  dumpCond(pcflow->outCond);
 
-    pcflow->inCond |= (inCond &  ~pcflow->outCond);
-    pcflow->outCond |= outCond;
+}
 
-    
+/*-----------------------------------------------------------------*
+ * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
+ *    if it affects the banking bits. 
+ * 
+ * return: -1 == Banking bits are unaffected by this pCode.
+ *
+ * return: > 0 == Banking bits are affected.
+ *
+ *  If the banking bits are affected, then the returned value describes
+ * which bits are affected and how they're affected. The lower half
+ * of the integer maps to the bits that are affected, the upper half
+ * to whether they're set or cleared.
+ *
+ *-----------------------------------------------------------------*/
+#define SET_BANK_BIT (1 << 16)
+#define CLR_BANK_BIT 0
 
+int isBankInstruction(pCode *pc)
+{
+  regs *reg;
+  int bank = -1;
 
-    pc = findNextpCode(pc->next, PC_OPCODE);
-  } while (pc && (pc != pcflow->end));
+  if(!isPCI(pc))
+    return -1;
 
-#if 0
-  if(!pc)
-    fprintf(stderr, "  FillFlow - Bad end of flow\n");
+  if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
 
+    /* Check to see if the register banks are changing */
+    if(PCI(pc)->isModReg) {
+
+      pCodeOp *pcop = PCI(pc)->pcop;
+      switch(PCI(pc)->op) {
+
+      case POC_BSF:
+       if(PCORB(pcop)->bit == PIC_RP0_BIT) {
+         //fprintf(stderr, "  isBankInstruction - Set RP0\n");
+         return  SET_BANK_BIT | PIC_RP0_BIT;
+       }
+
+       if(PCORB(pcop)->bit == PIC_RP1_BIT) {
+         //fprintf(stderr, "  isBankInstruction - Set RP1\n");
+         return  CLR_BANK_BIT | PIC_RP0_BIT;
+       }
+       break;
+
+      case POC_BCF:
+       if(PCORB(pcop)->bit == PIC_RP0_BIT) {
+         //fprintf(stderr, "  isBankInstruction - Clr RP0\n");
+         return  CLR_BANK_BIT | PIC_RP1_BIT;
+       }
+       if(PCORB(pcop)->bit == PIC_RP1_BIT) {
+         //fprintf(stderr, "  isBankInstruction - Clr RP1\n");
+         return  CLR_BANK_BIT | PIC_RP1_BIT;
+       }
+       break;
+      default:
+       //fprintf(stderr, "  isBankInstruction - Status register is getting Modified by:\n");
+       //genericPrint(stderr, pc);
+       ;
+      }
+    }
+
+  }
+
+  return bank;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void FillFlow(pCodeFlow *pcflow)
+{
+
+  pCode *pc;
+  int cur_bank;
+
+  if(!isPCFL(pcflow))
+    return;
+
+  //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
+
+  pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
+
+  if(!pc) {
+    //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
+    return;
+  }
+
+  cur_bank = -1;
+
+  do {
+    isBankInstruction(pc);
+    pc = pc->next;
+  } while (pc && (pc != pcflow->end) && !isPCFL(pc));
+
+/*
+  if(!pc ) {
+    fprintf(stderr, "  FillFlow - Bad end of flow\n");
+  } else {
+    fprintf(stderr, "  FillFlow - Ending flow with\n  ");
+    pc->print(stderr,pc);
+  }
 
   fprintf(stderr, "  FillFlow inCond: ");
   dumpCond(pcflow->inCond);
   fprintf(stderr, "  FillFlow outCond: ");
   dumpCond(pcflow->outCond);
-#endif
+*/
 }
+
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 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;
   pCode *pcflow;
   pCode *pct;
 
-  
+  //fprintf(stderr,"linkflow \n");
+
   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
-      (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
-      pcflow = pcflow->next) {
+       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;
@@ -3204,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);
@@ -3212,34 +3651,563 @@ void LinkFlow(pBlock *pb)
     }
 
     if(isPCI_BRANCH(pc)) {
-      //fprintf(stderr, "ends with branch\n");
+      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;
     }
-#if 0
+
+    if(isPCI(pc)) {
+      //fprintf(stderr, "ends with non-branching instruction:\n");
+      //pc->print(stderr,pc);
+
+      LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
+
+      continue;
+    }
+
     if(pc) {
-      fprintf(stderr, "has an unrecognized ending:\n");
-      pc->print(stderr,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)
 {
-  pCode *pc;
+  pCode *pc, *pcprev;
   int matches =0;
 
   if(!pb || !peepOptimizing)
     return 0;
 
   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
+/*
   for(pc = pb->pcHead; pc; pc = pc->next)
     matches += pCodePeepMatchRule(pc);
+*/
+
+  pc = findNextInstruction(pb->pcHead);
+  if(!pc)
+    return 0;
+
+  pcprev = pc->prev;
+  do {
+
+
+    if(pCodePeepMatchRule(pc)) {
+
+      matches++;
+
+      if(pcprev)
+       pc = findNextInstruction(pcprev->next);
+      else 
+       pc = findNextInstruction(pb->pcHead);
+    } else
+      pc = findNextInstruction(pc->next);
+  } while(pc);
+
   if(matches)
     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
   return matches;
@@ -3261,9 +4229,35 @@ pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
       return pc;
   }
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void exchangeLabels(pCodeLabel *pcl, pCode *pc)
+{
+
+  if(isPCI(pc) && 
+     (PCI(pc)->pcop) && 
+     (PCI(pc)->pcop->type == PO_LABEL)) {
+
+    pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
+
+    //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
+    if(pcol->pcop.name)
+      free(pcol->pcop.name);
+
+    sprintf(buffer,"_%05d_DS_",pcl->key);
+
+    pcol->pcop.name = Safe_strdup(buffer);
+    pcol->key = pcl->key;
+    //pc->print(stderr,pc);
+
+  }
+
 
-  return NULL;
 }
 
 /*-----------------------------------------------------------------*/
@@ -3277,26 +4271,54 @@ void pBlockRemoveUnusedLabels(pBlock *pb)
   if(!pb)
     return;
 
+  for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
+
+    pBranch *pbr = PCI(pc)->label;
+    if(pbr && pbr->next) {
+      pCode *pcd = pb->pcHead;
+
+      //fprintf(stderr, "multiple labels\n");
+      //pc->print(stderr,pc);
+
+      pbr = pbr->next;
+      while(pbr) {
+
+       while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
+         //fprintf(stderr,"Used by:\n");
+         //pcd->print(stderr,pcd);
+
+         exchangeLabels(PCL(pbr->pc),pcd);
+
+         pcd = pcd->next;
+       }
+       pbr = pbr->next;
+      }
+    }
+  }
+
   for(pc = pb->pcHead; pc; pc = pc->next) {
 
-    if(pc->type == PC_LABEL)
+    if(isPCL(pc)) // pc->type == PC_LABEL)
       pcl = PCL(pc);
-    else if ((pc->type == PC_OPCODE) && PCI(pc)->label)
+    else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
       pcl = PCL(PCI(pc)->label->pc);
     else continue;
 
-      /* This pCode is a label, so search the pBlock to see if anyone
-       * refers to it */
+    //fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
+
+    /* This pCode is a label, so search the pBlock to see if anyone
+     * refers to it */
 
     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
+    //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
       /* Couldn't find an instruction that refers to this label
        * So, unlink the pCode label from it's pCode chain
        * and destroy the label */
+      //fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
 
-      DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key));
-
+      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));
@@ -3330,35 +4352,52 @@ 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) {
+
+      //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
       //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
-      if( !(pcnext = findNextInstruction(pc)) ) 
-       return;  // Couldn't find an instruction associated with this label
-
-      // Unlink the pCode label from it's pCode chain
-      unlinkPC(pc);
-
-      //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
-      // And link it into the instruction's pBranch labels. (Note, since
-      // it's possible to have multiple labels associated with one instruction
-      // we must provide a means to accomodate the additional labels. Thus
-      // the labels are placed into the singly-linked list "label" as 
-      // opposed to being a single member of the pCodeInstruction.)
-
-      //_ALLOC(pbr,sizeof(pBranch));
-      pbr = Safe_calloc(1,sizeof(pBranch));
-      pbr->pc = pc;
-      pbr->next = NULL;
-
-      PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
-      if(pcnext->prev) 
-       pc = pcnext->prev;
-      else
-       pc = pcnext;
-    }
+      if((pcnext = findNextInstruction(pc) )) {
+
+       // Unlink the pCode label from it's pCode chain
+       unlinkpCode(pc);
+       
+       //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
+       // And link it into the instruction's pBranch labels. (Note, since
+       // it's possible to have multiple labels associated with one instruction
+       // we must provide a means to accomodate the additional labels. Thus
+       // the labels are placed into the singly-linked list "label" as 
+       // opposed to being a single member of the pCodeInstruction.)
+
+       //_ALLOC(pbr,sizeof(pBranch));
+       pbr = Safe_calloc(1,sizeof(pBranch));
+       pbr->pc = pc;
+       pbr->next = NULL;
+
+       PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
+
+      } else {
+       fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
+      }
+    } else if(pc->type == PC_CSOURCE) {
+
+      /* merge the source line symbolic info into the next instruction */
+      if((pcnext = findNextInstruction(pc) )) {
 
+       // Unlink the pCode label from it's pCode chain
+       unlinkpCode(pc);
+       PCI(pcnext)->cline = PCCS(pc);
+       //fprintf(stderr, "merging CSRC\n");
+       //genericPrint(stderr,pcnext);
+      }
+
+    }
+    pc = pcn;
   }
   pBlockRemoveUnusedLabels(pb);
 
@@ -3366,7 +4405,7 @@ void pBlockMergeLabels(pBlock *pb)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-void OptimizepCode(char dbName)
+int OptimizepCode(char dbName)
 {
 #define MAX_PASSES 4
 
@@ -3375,11 +4414,12 @@ void OptimizepCode(char dbName)
   pBlock *pb;
 
   if(!the_pFile)
-    return;
+    return 0;
 
   DFPRINTF((stderr," Optimizing pCode\n"));
 
   do {
+    matches = 0;
     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
       if('*' == dbName || getpBlock_dbName(pb) == dbName)
        matches += OptimizepBlock(pb);
@@ -3387,6 +4427,7 @@ void OptimizepCode(char dbName)
   }
   while(matches && ++passes < MAX_PASSES);
 
+  return matches;
 }
 
 /*-----------------------------------------------------------------*/
@@ -3438,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 */
@@ -3452,7 +4494,7 @@ void FixRegisterBanking(pBlock *pb)
     /* for each flow block, determine the register banking 
        requirements */
 
-    do {
+    //    do {
       if(isPCI(pc)) {
        //genericPrint(stderr, pc);
 
@@ -3498,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
@@ -3509,8 +4554,6 @@ void FixRegisterBanking(pBlock *pb)
       cur_bank = 0;
     }
 
-  }while (pc);
-
 }
 
 void pBlockDestruct(pBlock *pb)
@@ -3567,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;
 
@@ -3580,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 
@@ -3591,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
@@ -3600,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;
@@ -3614,6 +4717,51 @@ void AnalyzeBanking(void)
     }
   }
 
+/*
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    pCode *pcflow;
+    for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
+        (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
+        pcflow = pcflow->next) {
+
+      FlowStats(PCFL(pcflow));
+    }
+  }
+*/
+}
+
+/*-----------------------------------------------------------------*/
+/* 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);
 
 }
 
@@ -3663,7 +4811,7 @@ void buildCallTree(void    )
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
     pCode *pc_fstart=NULL;
     for(pc = pb->pcHead; pc; pc = pc->next) {
-      if(isPCF(pc)) {  //pc->type == PC_FUNCTION) {
+      if(isPCF(pc)) {
        if (PCF(pc)->fname) {
 
          if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
@@ -3672,7 +4820,6 @@ void buildCallTree(void    )
            pb->dbName = 'M';
          }
 
-         //_ALLOC(pbr,sizeof(pBranch));
          pbr = Safe_calloc(1,sizeof(pBranch));
          pbr->pc = pc_fstart = pc;
          pbr->next = NULL;
@@ -3690,7 +4837,7 @@ void buildCallTree(void    )
 
          addSet(&pb->function_exits, pc);
        }
-      } else if(isCALL(pc)) {// if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+      } else if(isCALL(pc)) {
        addSet(&pb->function_calls,pc);
       }
     }
@@ -3699,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)
@@ -3742,25 +4890,23 @@ void AnalyzepCode(char dbName)
   do {
 
     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
+    //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
 
     /* First, merge the labels with the instructions */
     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
 
        DFPRINTF((stderr," analyze and merging block %c\n",dbName));
-       //fprintf(stderr," analyze and merging block %c\n",getpBlock_dbName(pb));
+       //fprintf(stderr," analyze and merging block %c\n",dbName);
        pBlockMergeLabels(pb);
        AnalyzepBlock(pb);
+      } else {
+       DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
       }
     }
 
-    changes = 0;
+    changes = OptimizepCode(dbName);
 
-    for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-      if('*' == dbName || getpBlock_dbName(pb) == dbName)
-       changes += OptimizepBlock(pb);
-    }
-      
   } while(changes && (i++ < MAX_PASSES));
 
   buildCallTree();
@@ -3869,6 +5015,7 @@ void pBlockStats(FILE *of, pBlock *pb)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
+#if 0
 static void sequencepCode(void)
 {
   pBlock *pb;
@@ -3884,6 +5031,7 @@ static void sequencepCode(void)
   }
 
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
@@ -4006,10 +5154,10 @@ void pct2(FILE *of,pBlock *pb,int indent)
   //  set *registersInCallPath = NULL;
 
   if(!of)
-    return;// registers;
+    return;
 
   if(indent > 10)
-    return; // registers;   //recursion ?
+    return; //recursion ?
 
   pc = setFirstItem(pb->function_entries);
 
@@ -4044,77 +5192,6 @@ void pct2(FILE *of,pBlock *pb,int indent)
 
 }
 
-#if 0
-  fprintf(stderr,"pBlock before register optim.\n");
-  pBlockStats(stderr,pb);  // debug
-
-  if(registersInCallPath) {
-    /* registers were used in the functions this pBlock has called */
-    /* so now, we need to see if these collide with the ones we are using here */
-
-    regs *r1,*r2, *newreg;
-
-    fprintf(stderr,"comparing registers\n");
-
-    r1 = setFirstItem(registersInCallPath);
-    while(r1) {
-
-      r2 = setFirstItem(pb->registers);
-
-      while(r2) {
-
-       if(r2->rIdx == r1->rIdx) {
-         newreg = pic14_findFreeReg();
-
-
-         if(!newreg) {
-           fprintf(stderr,"Bummer, no more registers.\n");
-           exit(1);
-         }
-
-         fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
-                 r1->rIdx, newreg->rIdx);
-         r2->rIdx = newreg->rIdx;
-         //if(r2->name) free(r2->name);
-         if(newreg->name)
-           r2->name = Safe_strdup(newreg->name);
-         else
-           r2->name = NULL;
-         newreg->isFree = 0;
-         newreg->wasUsed = 1;
-       }
-       r2 = setNextItem(pb->registers);
-      }
-
-      r1 = setNextItem(registersInCallPath);
-    }
-
-    /* Collisions have been resolved. Now free the registers in the call path */
-    r1 = setFirstItem(registersInCallPath);
-    while(r1) {
-      newreg = pic14_regWithIdx(r1->rIdx);
-      newreg->isFree = 1;
-      r1 = setNextItem(registersInCallPath);
-    }
-
-  } else
-    MarkUsedRegisters(pb->registers);
-
-  registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
-
-  if(registers) 
-    fprintf(stderr,"returning regs\n");
-  else
-    fprintf(stderr,"not returning regs\n");
-
-  fprintf(stderr,"pBlock after register optim.\n");
-  pBlockStats(stderr,pb);  // debug
-
-
-  return registers;
-
-#endif
-
 
 /*-----------------------------------------------------------------*/
 /* printCallTree - writes the call tree to a file                  */
@@ -4161,17 +5238,6 @@ void printCallTree(FILE *of)
   }
 
 
-  /* Re-allocate the registers so that there are no collisions
-   * between local variables when one function call another */
-#if 0
-  pic14_deallocateAllRegs();
-
-  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    if(!pb->visited)
-      register_usage(pb);
-  }
-#endif
-
   fprintf(of,"\n**************\n\na better call tree\n");
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
     if(pb->visited)
@@ -4182,3 +5248,156 @@ void printCallTree(FILE *of)
     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
   }
 }
+
+
+
+/*-----------------------------------------------------------------*/
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+void InlineFunction(pBlock *pb)
+{
+  pCode *pc;
+  pCode *pc_call;
+
+  if(!pb)
+    return;
+
+  pc = setFirstItem(pb->function_calls);
+
+  for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+    if(isCALL(pc)) {
+      pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
+      pCode *pct;
+      pCode *pce;
+
+      pBranch *pbr;
+
+      if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
+       
+       //fprintf(stderr,"Cool can inline:\n");
+       //pcn->print(stderr,pcn);
+
+       //fprintf(stderr,"recursive call Inline\n");
+       InlineFunction(pcn->pb);
+       //fprintf(stderr,"return from recursive call Inline\n");
+
+       /*
+         At this point, *pc points to a CALL mnemonic, and
+         *pcn points to the function that is being called.
+
+         To in-line this call, we need to remove the CALL
+         and RETURN(s), and link the function pCode in with
+         the CALLee pCode.
+
+       */
+
+
+       /* Remove the CALL */
+       pc_call = pc;
+       pc = pc->prev;
+
+       /* remove callee pBlock from the pBlock linked list */
+       removepBlock(pcn->pb);
+
+       pce = pcn;
+       while(pce) {
+         pce->pb = pb;
+         pce = pce->next;
+       }
+
+       /* Remove the Function pCode */
+       pct = findNextInstruction(pcn->next);
+
+       /* Link the function with the callee */
+       pc->next = pcn->next;
+       pcn->next->prev = pc;
+       
+       /* Convert the function name into a label */
+
+       pbr = Safe_calloc(1,sizeof(pBranch));
+       pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
+       pbr->next = NULL;
+       PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
+       PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
+
+       /* turn all of the return's except the last into goto's */
+       /* check case for 2 instruction pBlocks */
+       pce = findNextInstruction(pcn->next);
+       while(pce) {
+         pCode *pce_next = findNextInstruction(pce->next);
+
+         if(pce_next == NULL) {
+           /* found the last return */
+           pCode *pc_call_next =  findNextInstruction(pc_call->next);
+
+           //fprintf(stderr,"found last return\n");
+           //pce->print(stderr,pce);
+           pce->prev->next = pc_call->next;
+           pc_call->next->prev = pce->prev;
+           PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
+                                                     PCI(pce)->label);
+         }
+
+         pce = pce_next;
+       }
+
+
+      }
+    } else
+      fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
+void InlinepCode(void)
+{
+
+  pBlock  *pb;
+  pCode   *pc;
+
+  if(!the_pFile)
+    return;
+
+  if(!functionInlining)
+    return;
+
+  /* Loop through all of the function definitions and count the
+   * number of times each one is called */
+  //fprintf(stderr,"inlining %d\n",__LINE__);
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+
+    pc = setFirstItem(pb->function_calls);
+
+    for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+      if(isCALL(pc)) {
+       pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
+       if(pcn && isPCF(pcn)) {
+         PCF(pcn)->ncalled++;
+       }
+      } else
+       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+    }
+  }
+
+  //fprintf(stderr,"inlining %d\n",__LINE__);
+
+  /* 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__);
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    unBuildFlow(pb);
+
+}