Fixed compound expressions of the type y = (x+K) OP B, where x and y are variables...
[fw/sdcc] / src / pic / pcode.c
index 1bdeb311061dc8458873bf2539a70a8f4ccc1c63..cb2cfcc9ecb42655142ab8e52082402870c2e022 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,30 +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;
 
-#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))
+/* 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 = 1;                /* Set true to inundate .asm file */
 
-#define isCALL(x)       ((isPCI(x)) && (PCI(x)->op == POC_CALL))
-#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
+// static int GpCodeSequenceNumber = 1;
+int GpcFlowSeq = 1;
 
-#define isPCOLAB(x)     ((PCOP(x)->type) == PO_LABEL)
+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);
@@ -108,13 +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,size_t 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, 
@@ -132,6 +136,7 @@ pCodeInstruction pciADDWF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_REGISTER | PCC_Z) // outCond
@@ -153,6 +158,7 @@ pCodeInstruction pciADDFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_W | PCC_Z) // outCond
@@ -174,8 +180,9 @@ pCodeInstruction pciADDLW = {
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  1,    // literal operand
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
@@ -195,8 +202,9 @@ pCodeInstruction pciANDLW = {
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  1,    // literal operand
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z) // outCond
 };
 
@@ -216,6 +224,7 @@ pCodeInstruction pciANDWF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_REGISTER | PCC_Z) // outCond
@@ -237,6 +246,7 @@ pCodeInstruction pciANDFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_W | PCC_Z) // outCond
@@ -258,8 +268,9 @@ pCodeInstruction pciBCF = {
   2,    // num ops
   1,1,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_BSF,
-  PCC_REGISTER,   // inCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
   PCC_REGISTER // outCond
 };
 
@@ -279,9 +290,10 @@ pCodeInstruction pciBSF = {
   2,    // num ops
   1,1,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_BCF,
-  PCC_REGISTER,   // inCond
-  PCC_REGISTER // outCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
 };
 
 pCodeInstruction pciBTFSC = {
@@ -300,9 +312,10 @@ pCodeInstruction pciBTFSC = {
   2,    // num ops
   0,1,  // dest, bit instruction
   1,1,  // branch, skip
+  0,    // literal operand
   POC_BTFSS,
-  PCC_REGISTER,   // inCond
-  PCC_NONE // outCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  PCC_EXAMINE_PCOP // outCond
 };
 
 pCodeInstruction pciBTFSS = {
@@ -321,9 +334,10 @@ pCodeInstruction pciBTFSS = {
   2,    // num ops
   0,1,  // dest, bit instruction
   1,1,  // branch, skip
+  0,    // literal operand
   POC_BTFSC,
-  PCC_REGISTER,   // inCond
-  PCC_NONE // outCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  PCC_EXAMINE_PCOP // outCond
 };
 
 pCodeInstruction pciCALL = {
@@ -342,6 +356,7 @@ pCodeInstruction pciCALL = {
   1,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_NONE, // inCond
   PCC_NONE  // outCond
@@ -363,6 +378,7 @@ pCodeInstruction pciCOMF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,  // inCond
   PCC_REGISTER   // outCond
@@ -384,6 +400,7 @@ pCodeInstruction pciCOMFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,  // inCond
   PCC_W   // outCond
@@ -405,8 +422,9 @@ pCodeInstruction pciCLRF = {
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
-  PCC_REGISTER, // inCond
+  PCC_NONE, // inCond
   PCC_REGISTER  // outCond
 };
 
@@ -426,11 +444,34 @@ pCodeInstruction pciCLRW = {
   0,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   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
+  0,    // literal operand
+  POC_NOP,
+  PCC_NONE, // inCond
+  PCC_NONE  // outCond
+};
+
 pCodeInstruction pciDECF = {
   {PC_OPCODE, NULL, NULL, 0, NULL, 
    //   genericAnalyze,
@@ -447,6 +488,7 @@ pCodeInstruction pciDECF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   PCC_REGISTER    // outCond
@@ -468,6 +510,7 @@ pCodeInstruction pciDECFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   PCC_W    // outCond
@@ -489,6 +532,7 @@ pCodeInstruction pciDECFSZ = {
   2,    // num ops
   1,0,  // dest, bit instruction
   1,1,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   PCC_REGISTER    // outCond
@@ -510,6 +554,7 @@ pCodeInstruction pciDECFSZW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   1,1,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   PCC_W           // outCond
@@ -531,6 +576,7 @@ pCodeInstruction pciGOTO = {
   1,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_NONE,   // inCond
   PCC_NONE    // outCond
@@ -552,6 +598,7 @@ pCodeInstruction pciINCF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   PCC_REGISTER    // outCond
@@ -573,6 +620,7 @@ pCodeInstruction pciINCFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   PCC_W    // outCond
@@ -594,6 +642,7 @@ pCodeInstruction pciINCFSZ = {
   2,    // num ops
   1,0,  // dest, bit instruction
   1,1,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   PCC_REGISTER    // outCond
@@ -615,6 +664,7 @@ pCodeInstruction pciINCFSZW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   1,1,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   PCC_W           // outCond
@@ -636,6 +686,7 @@ pCodeInstruction pciIORWF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_REGISTER | PCC_Z) // outCond
@@ -657,6 +708,7 @@ pCodeInstruction pciIORFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_W | PCC_Z) // outCond
@@ -678,8 +730,9 @@ pCodeInstruction pciIORLW = {
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  1,    // literal operand
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z) // outCond
 };
 
@@ -699,6 +752,7 @@ pCodeInstruction pciMOVF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   PCC_Z // outCond
@@ -720,6 +774,7 @@ pCodeInstruction pciMOVFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_REGISTER,   // inCond
   (PCC_W | PCC_Z) // outCond
@@ -741,6 +796,7 @@ pCodeInstruction pciMOVWF = {
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_W,   // inCond
   PCC_REGISTER // outCond
@@ -748,7 +804,6 @@ pCodeInstruction pciMOVWF = {
 
 pCodeInstruction pciMOVLW = {
   {PC_OPCODE, NULL, NULL, 0, NULL, 
-   //   genericAnalyze,
    genericDestruct,
    genericPrint},
   POC_MOVLW,
@@ -762,8 +817,9 @@ pCodeInstruction pciMOVLW = {
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  1,    // literal operand
   POC_NOP,
-  PCC_NONE,   // inCond
+  (PCC_NONE | PCC_LITERAL),   // inCond
   PCC_W // outCond
 };
 
@@ -782,6 +838,7 @@ pCodeInstruction pciNOP = {
   0,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_NONE,   // inCond
   PCC_NONE // outCond
@@ -803,6 +860,7 @@ pCodeInstruction pciRETFIE = {
   0,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_NONE,   // inCond
   PCC_NONE // outCond (not true... affects the GIE bit too)
@@ -824,8 +882,9 @@ pCodeInstruction pciRETLW = {
   1,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
+  1,    // literal operand
   POC_NOP,
-  PCC_NONE,   // inCond
+  PCC_LITERAL,   // inCond
   PCC_W // outCond
 };
 
@@ -845,6 +904,7 @@ pCodeInstruction pciRETURN = {
   0,    // num ops
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_NONE,   // inCond
   PCC_NONE // outCond
@@ -866,6 +926,7 @@ pCodeInstruction pciRLF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_C | PCC_REGISTER),   // inCond
   (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
@@ -887,6 +948,7 @@ pCodeInstruction pciRLFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_C | PCC_REGISTER),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
@@ -908,6 +970,7 @@ pCodeInstruction pciRRF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_C | PCC_REGISTER),   // inCond
   (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
@@ -929,6 +992,7 @@ pCodeInstruction pciRRFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_C | PCC_REGISTER),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
@@ -950,6 +1014,7 @@ pCodeInstruction pciSUBWF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_REGISTER | PCC_Z) // outCond
@@ -971,6 +1036,7 @@ pCodeInstruction pciSUBFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_W | PCC_Z) // outCond
@@ -992,8 +1058,9 @@ pCodeInstruction pciSUBLW = {
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  1,    // literal operand
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
@@ -1013,6 +1080,7 @@ pCodeInstruction pciSWAPF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_REGISTER),   // inCond
   (PCC_REGISTER) // outCond
@@ -1034,6 +1102,7 @@ pCodeInstruction pciSWAPFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_REGISTER),   // inCond
   (PCC_W) // outCond
@@ -1055,6 +1124,7 @@ pCodeInstruction pciTRIS = {
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   PCC_NONE,   // inCond
   PCC_REGISTER // outCond
@@ -1076,6 +1146,7 @@ pCodeInstruction pciXORWF = {
   2,    // num ops
   1,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_REGISTER | PCC_Z) // outCond
@@ -1097,6 +1168,7 @@ pCodeInstruction pciXORFW = {
   2,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  0,    // literal operand
   POC_NOP,
   (PCC_W | PCC_REGISTER),   // inCond
   (PCC_W | PCC_Z) // outCond
@@ -1118,8 +1190,9 @@ pCodeInstruction pciXORLW = {
   1,    // num ops
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
+  1,    // literal operand
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
@@ -1127,10 +1200,8 @@ pCodeInstruction pciXORLW = {
 #define MAX_PIC14MNEMONICS 100
 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
 
-/* This definition needs to be part of configure.in */
-// #define USE_VSNPRINTF
 
-#ifdef USE_VSNPRINTF
+#ifdef HAVE_VSNPRINTF
   // Alas, vsnprintf is not ANSI standard, and does not exist
   // on Solaris (and probably other non-Gnu flavored Unixes).
 
@@ -1157,6 +1228,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,(int)*size);
   }
 
   *str += len;
@@ -1164,7 +1236,7 @@ void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
 
 }
 
-#else  //  USE_VSNPRINTF
+#else  //  HAVE_VSNPRINTF
 
 // This version is *not* safe, despite the name.
 
@@ -1185,6 +1257,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);
@@ -1193,7 +1266,7 @@ void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
 
 }
 
-#endif    //  USE_VSNPRINTF
+#endif    //  HAVE_VSNPRINTF
     
 
 extern  void initStack(int base_address, int size);
@@ -1203,13 +1276,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);
@@ -1229,6 +1307,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();
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -1282,6 +1363,7 @@ void pic14initMnemonics(void)
   pic14Mnemonics[POC_COMFW] = &pciCOMFW;
   pic14Mnemonics[POC_CLRF] = &pciCLRF;
   pic14Mnemonics[POC_CLRW] = &pciCLRW;
+  pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
   pic14Mnemonics[POC_DECF] = &pciDECF;
   pic14Mnemonics[POC_DECFW] = &pciDECFW;
   pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
@@ -1345,7 +1427,7 @@ int getpCode(char *mnem,unsigned dest)
   while(pci) {
 
     if(STRCASECMP(pci->mnemonic, mnem) == 0) {
-      if((pci->num_ops <= 1) || (pci->isModReg == dest))
+      if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
        return(pci->op);
     }
 
@@ -1503,7 +1585,7 @@ void pcode_test(void)
     char buffer[100];
 
     /* create the file name */
-    strcpy(buffer,srcFileName);
+    strcpy(buffer,dstFileName);
     strcat(buffer,".p");
 
     if( !(pFile = fopen(buffer, "w" ))) {
@@ -1587,11 +1669,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;
@@ -1751,19 +1833,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 )
@@ -1775,7 +1860,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;
@@ -1784,9 +1868,6 @@ 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;
@@ -1799,6 +1880,9 @@ pCode *newpCodeFlow(void )
   pcflow->ToConflicts = 0;
 
   pcflow->end = NULL;
+
+  pcflow->registers = newSet();
+
   return ( (pCode *)pcflow);
 
 }
@@ -1893,7 +1977,7 @@ pCode *newpCodeLabel(char *name, int key)
   if(s)
     pcl->label = Safe_strdup(s);
 
-
+  //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
   return ( (pCode *)pcl);
 
 }
@@ -1913,6 +1997,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;
 
@@ -1968,6 +2053,7 @@ pCodeOp *newpCodeOpLabel(char *name, int key)
 
   ((pCodeOpLabel *)pcop)->key = key;
 
+  //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
   return pcop;
 }
 
@@ -2003,13 +2089,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;
@@ -2059,6 +2153,9 @@ pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
   PCORB(pcop)->bit = bit;
   PCORB(pcop)->inBitSpace = inBitSpace;
 
+  /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
+  PCOR(pcop)->r = NULL;
+  PCOR(pcop)->rIdx = 0;
   return pcop;
 }
 
@@ -2086,7 +2183,6 @@ pCodeOp *newpCodeOpReg(int rIdx)
 
     if(PCOR(pcop)->r)
       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
-    //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
   }
 
   pcop->type = PCOR(pcop)->r->pc_type;
@@ -2131,6 +2227,13 @@ pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
     pcop = newpCodeOpReg(-1);
     break;
 
+  case PO_GPR_REGISTER:
+    if(name)
+      pcop = newpCodeOpRegFromStr(name);
+    else
+      pcop = newpCodeOpReg(-1);
+    break;
+
   default:
     pcop = Safe_calloc(1,sizeof(pCodeOp) );
     pcop->type = type;
@@ -2200,16 +2303,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;
   }
 }
@@ -2316,7 +2425,7 @@ void printpBlock(FILE *of, pBlock *pb)
 /*                                                                 */
 /*-----------------------------------------------------------------*/
 
-static void unlinkPC(pCode *pc)
+void unlinkpCode(pCode *pc)
 {
 
 
@@ -2333,13 +2442,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);
 
 }
 
@@ -2360,34 +2490,43 @@ void pBlockRegs(FILE *of, pBlock *pb)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-char *get_op(pCodeOp *pcop)
+char *get_op(pCodeOp *pcop,char *buffer, size_t 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) {
@@ -2403,15 +2542,19 @@ char *get_op(pCodeOp *pcop)
          SAFE_snprintf(&s,&size,"(%s + %d)",
                        pcop->name,
                        PCOI(pcop)->index );
-       } else
-         SAFE_snprintf(&s,&size,"%s",pcop->name);
+       } else {
+         if(PCOI(pcop)->offset)
+           SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
+         else
+           SAFE_snprintf(&s,&size,"%s",pcop->name);
+       }
       }
 
       return buffer;
 
     case PO_DIR:
       s = buffer;
-      size = sizeof(buffer);
+      //size = sizeof(buffer);
       if( PCOR(pcop)->instance) {
        SAFE_snprintf(&s,&size,"(%s + %d)",
                      pcop->name,
@@ -2422,8 +2565,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;
+      }
 
     }
   }
@@ -2438,9 +2586,12 @@ static char *get_op_from_instruction( pCodeInstruction *pcc)
 {
 
   if(pcc )
-    return get_op(pcc->pcop);
-  
+    return get_op(pcc->pcop,NULL,0);
+
+  /* gcc 3.2:  warning: concatenation of string literals with __FUNCTION__ is deprecated 
   return ("ERROR Null: "__FUNCTION__);
+  */
+  return ("ERROR Null: get_op_from_instruction");
 
 }
 
@@ -2454,7 +2605,7 @@ static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-char *pCode2str(char *str, int size, pCode *pc)
+char *pCode2str(char *str, size_t size, pCode *pc)
 {
   char *s = str;
 
@@ -2522,9 +2673,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;
@@ -2571,9 +2724,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
     {
@@ -2615,7 +2770,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=0x%x",pc->seq);
+      if(PCFL(pc)->ancestor)
+       fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
+      fprintf(of,"\n");
+
+    }
     break;
 
   case PC_CSOURCE:
@@ -2724,13 +2885,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;
@@ -2865,6 +3029,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
@@ -3074,6 +3241,7 @@ static void AnalyzeRETURN(pCode *pc)
 /*-----------------------------------------------------------------*/
 regs * getRegFromInstruction(pCode *pc)
 {
+
   if(!pc                   || 
      !isPCI(pc)            ||
      !PCI(pc)->pcop        ||
@@ -3083,7 +3251,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:
@@ -3091,8 +3261,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;
@@ -3150,10 +3324,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);
@@ -3183,7 +3358,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;
@@ -3204,7 +3380,7 @@ void BuildFlow(pBlock *pb)
 {
   pCode *pc;
   pCode *last_pci=NULL;
-  pCode *pflow;
+  pCode *pflow=NULL;
   int seq = 0;
 
   if(!pb)
@@ -3213,11 +3389,13 @@ 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 != NULL;
@@ -3258,14 +3436,22 @@ void BuildFlow(pBlock *pb)
       InsertpFlow(pc, &pflow);
       seq = 0;
 
-    } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
+    } else if (checkLabel(pc)) { 
 
       /* This instruction marks the beginning of a
        * new flow segment */
 
       pc->seq = 0;
-      seq = 1; 
-      InsertpFlow(findPrevInstruction(pc->prev), &pflow);
+      seq = 1;
+
+      /* If the previous pCode is not a flow object, then 
+       * insert a new flow object. (This check prevents 
+       * two consecutive flow objects from being insert in
+       * the case where a skip instruction preceeds an
+       * instruction containing a label.) */
+
+      if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
+       InsertpFlow(findPrevInstruction(pc->prev), &pflow);
 
       PCI(pc)->pcflow = PCFL(pflow);
       
@@ -3275,7 +3461,8 @@ void BuildFlow(pBlock *pb)
   }
 
   //fprintf (stderr,",end seq %d",GpcFlowSeq);
-  PCFL(pflow)->end = pb->pcTail;
+  if(pflow)
+    PCFL(pflow)->end = pb->pcTail;
 }
 
 /*-------------------------------------------------------------------*/
@@ -3287,27 +3474,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;
   }
 
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -3494,8 +3685,15 @@ void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
 
 }
 
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*
+ * void LinkFlow(pBlock *pb)
+ *
+ * In BuildFlow, the PIC code has been partitioned into contiguous
+ * non-branching segments. In LinkFlow, we determine the execution
+ * order of these segments. For example, if one of the segments ends
+ * with a skip, then we know that there are two possible flow segments
+ * to which control may be passed.
+ *-----------------------------------------------------------------*/
 void LinkFlow(pBlock *pb)
 {
   pCode *pc=NULL;
@@ -3536,7 +3734,7 @@ void LinkFlow(pBlock *pb)
       //pc->print(stderr,pc);
 
       if(!(pcol && isPCOLAB(pcol))) {
-       if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
+       if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
          pc->print(stderr,pc);
          fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
        }
@@ -3546,7 +3744,9 @@ void LinkFlow(pBlock *pb)
       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
        LinkFlow_pCode(PCI(pc),PCI(pct));
       else
-       fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
+       fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
+               __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
+  //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
 
       continue;
     }
@@ -3570,6 +3770,8 @@ void LinkFlow(pBlock *pb)
     
   }
 }
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
@@ -3678,7 +3880,7 @@ void BanksUsedFlow(pBlock *pb)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
+void insertBankSwitch(int position, pCode *pc, int Set_Clear, int RP_BankBit)
 {
   pCode *new_pc;
 
@@ -3691,7 +3893,15 @@ void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
     new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
                      popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
 
-  pCodeInsertAfter(pc->prev, new_pc);
+  if(position) {
+    /* insert the bank switch after this pc instruction */
+    pCode *pcnext = findNextInstruction(pc);
+    pCodeInsertAfter(pc, new_pc);
+    if(pcnext)
+      pc = pcnext;
+
+  } else
+    pCodeInsertAfter(pc->prev, new_pc);
 
   /* Move the label, if there is one */
 
@@ -3721,7 +3931,6 @@ void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
 
   while(isPCinFlow(pc,PCODE(pcfl))) {
 
-
     reg = getRegFromInstruction(pc);
 #if 0
     if(reg) {
@@ -3731,46 +3940,41 @@ void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
     }
 #endif
 
-    if(reg && REG_BANK(reg)!=cur_bank) {
+    if( ( (reg && REG_BANK(reg)!=cur_bank) || 
+         ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
+       (!isPCI_LIT(pc)) ){
+
       /* Examine the instruction before this one to make sure it is
        * not a skip type instruction */
       pcprev = findPrevpCode(pc->prev, PC_OPCODE);
+
       if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
-       int b = cur_bank ^ REG_BANK(reg);
+       int b;
+       int reg_bank;
+
+       reg_bank =  (reg) ? REG_BANK(reg) : 0;
+         
+       b = cur_bank ^ reg_bank;
 
        //fprintf(stderr, "Cool! can switch banks\n");
-       cur_bank = REG_BANK(reg);
+       cur_bank = reg_bank;
        switch(b & 3) {
        case 0:
          break;
        case 1:
-         insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
+         insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
          break;
        case 2:
-         insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
-         insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
+         insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+         insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
          break;
        case 3:
          if(cur_bank & 3) {
-           insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
-           insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
+           insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+           insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
          } else
-           insertBankSwitch(pc, -1, -1);
+           insertBankSwitch(0, pc, -1, -1);
          break;
-         /*
-           new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
-           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);
-         */
 
        }
 
@@ -4066,6 +4270,9 @@ int OptimizepBlock(pBlock *pb)
 */
 
   pc = findNextInstruction(pb->pcHead);
+  if(!pc)
+    return 0;
+
   pcprev = pc->prev;
   do {
 
@@ -4113,6 +4320,8 @@ pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
 {
 
+  char *s=NULL;
+
   if(isPCI(pc) && 
      (PCI(pc)->pcop) && 
      (PCI(pc)->pcop->type == PO_LABEL)) {
@@ -4123,9 +4332,19 @@ void exchangeLabels(pCodeLabel *pcl, pCode *pc)
     if(pcol->pcop.name)
       free(pcol->pcop.name);
 
-    sprintf(buffer,"_%05d_DS_",pcl->key);
-
-    pcol->pcop.name = Safe_strdup(buffer);
+    /* If the key is negative, then we (probably) have a label to
+     * a function and the name is already defined */
+       
+    if(pcl->key>0)
+      sprintf(s=buffer,"_%05d_DS_",pcl->key);
+    else 
+      s = pcl->label;
+
+    //sprintf(buffer,"_%05d_DS_",pcl->key);
+    if(!s) {
+      fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
+    }
+    pcol->pcop.name = Safe_strdup(s);
     pcol->key = pcl->key;
     //pc->print(stderr,pc);
 
@@ -4192,7 +4411,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));
@@ -4226,7 +4445,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) {
 
@@ -4234,10 +4457,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
@@ -4251,10 +4472,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);
@@ -4264,18 +4482,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);
 
@@ -4349,11 +4564,10 @@ void FixRegisterBanking(pBlock *pb)
 {
   pCode *pc=NULL;
   pCode *pcprev=NULL;
-  pCode *new_pc;
 
   int cur_bank;
   regs *reg;
-  //  return;
+
   if(!pb)
     return;
 
@@ -4377,63 +4591,151 @@ void FixRegisterBanking(pBlock *pb)
        //genericPrint(stderr, pc);
 
        reg = getRegFromInstruction(pc);
-       #if 0
+#if 0
        if(reg) {
          fprintf(stderr, "  %s  ",reg->name);
-         fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
+         fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
+                 reg->address,REG_BANK(reg),reg->isBitField);
 
        }
-       #endif
-       if(reg && REG_BANK(reg)!=cur_bank) {
+#endif
+
+       if( ( (reg && REG_BANK(reg)!=cur_bank) || 
+             ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
+           (!isPCI_LIT(pc)) ){
+
+
          /* Examine the instruction before this one to make sure it is
           * not a skip type instruction */
          pcprev = findPrevpCode(pc->prev, PC_OPCODE);
-         if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
-           int b = cur_bank ^ REG_BANK(reg);
 
-           //fprintf(stderr, "Cool! can switch banks\n");
-           cur_bank = REG_BANK(reg);
-           if(b & 1) {
-             new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
-                               popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
-             pCodeInsertAfter(pc->prev, new_pc);
-             if(PCI(pc)->label) { 
-               PCI(new_pc)->label = PCI(pc)->label;
-               PCI(pc)->label = NULL;
-             }
-             /*
-               new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
-               popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
-               pCodeInsertAfter(pc, new_pc);
-             */
+         if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
+           int b;
+           int reg_bank;
+
+           reg_bank =  (reg) ? REG_BANK(reg) : 0;
+         
+           b = cur_bank ^ reg_bank;
+
+           cur_bank = reg_bank;
+           switch(b & 3) {
+           case 0:
+             break;
+           case 1:
+             insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+             break;
+           case 2:
+             insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             break;
+           case 3:
+             if(cur_bank & 3) {
+               insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+               insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             } else
+               insertBankSwitch(0, pc, -1, -1);
+             break;
 
            }
 
-         } else {
+         }else {
            //fprintf(stderr, "Bummer can't switch banks\n");
            ;
          }
        }
+
+       pcprev = pc;
+
       }
 
-      pcprev = pc;
       pc = pc->next;
       // } while(pc && !(isPCFL(pc))); 
 
 
   }while (pc);
 
-    if(pcprev && cur_bank) {
-      /* Brute force - make sure that we point to bank 0 at the
-       * end of each flow block */
-      new_pc = newpCode(POC_BCF,
-                       popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
-      pCodeInsertAfter(pcprev, new_pc);
-      cur_bank = 0;
+  if(pcprev && cur_bank) {
+
+    int pos = 1;  /* Assume that the bank swithc instruction(s)
+                  * are inserted after this instruction */
+
+    if((PCI(pcprev)->op == POC_RETLW) || 
+       (PCI(pcprev)->op == POC_RETURN) || 
+       (PCI(pcprev)->op == POC_RETFIE)) {
+
+      /* oops, a RETURN - we need to switch banks *before* the RETURN */
+
+      pos = 0;
+
+    } 
+           
+    /* Brute force - make sure that we point to bank 0 at the
+     * end of each flow block */
+
+    switch(cur_bank & 3) {
+    case 0:
+      break;
+    case 1:
+      insertBankSwitch(pos, pcprev, 0, PIC_RP0_BIT);
+      break;
+    case 2:
+      insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
+      insertBankSwitch(pos, pcprev, 0, PIC_RP1_BIT);
+      break;
+    case 3:
+      insertBankSwitch(pos, pcprev, -1, -1);
+      break;
+
     }
+/*
+    new_pc = newpCode(POC_BCF,
+                     popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
+    pCodeInsertAfter(pcprev, new_pc);
+*/
+    cur_bank = 0;
+    //fprintf(stderr, "Brute force switch\n");
+  }
 
 }
 
+
+
+
+#if 0
+       if(reg && REG_BANK(reg)!=cur_bank) {
+         //fprintf(stderr,"need to switch banks\n");
+         /* Examine the instruction before this one to make sure it is
+          * not a skip type instruction */
+         pcprev = findPrevpCode(pc->prev, PC_OPCODE);
+         if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
+           int b = cur_bank ^ REG_BANK(reg);
+
+           cur_bank = REG_BANK(reg);
+
+           switch(b & 3) {
+           case 0:
+             break;
+           case 1:
+             insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+             break;
+           case 2:
+             insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             break;
+           case 3:
+             if(cur_bank & 3) {
+               insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
+               insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
+             } else
+               insertBankSwitch(0, pc, -1, -1);
+             break;
+
+           }
+#endif
+
+
+
+
 void pBlockDestruct(pBlock *pb)
 {
 
@@ -4488,12 +4790,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;
 
@@ -4501,6 +4809,18 @@ 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
@@ -4531,15 +4851,15 @@ void AnalyzeBanking(void)
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     LinkFlow(pb);
 
-
-  /* Phase x - Flow Analysis - Used Banks
+  /* Phase 3 - Flow Analysis - Flow Tree
    *
    * In this phase, the individual flow blocks are examined
-   * to determine the Register Banks they use
+   * to determine their order of excution.
    */
 
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
-    BanksUsedFlow(pb);
+    BuildFlowTree(pb);
+
 
   /* Phase x - Flow Analysis - Used Banks
    *
@@ -4550,6 +4870,18 @@ void AnalyzeBanking(void)
   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);
@@ -4564,6 +4896,7 @@ void AnalyzeBanking(void)
       FillFlow(PCFL(pcflow));
     }
   }
+
 /*
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
     pCode *pcflow;
@@ -4577,6 +4910,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   */
 /*                                                                 */
@@ -4658,7 +5026,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)
@@ -5176,6 +5545,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 */
@@ -5202,7 +5573,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__);