Fixed up s51 autodetect
[fw/sdcc] / src / pic / pcode.c
index 9c3e288bf4fb7641925e932e75b6f052cd681cc0..04744116156dab934da3623bd6db45f88ebaf28c 100644 (file)
 pCodeOpReg pc_status    = {{PO_STATUS,  "STATUS"}, -1, NULL,NULL};
 pCodeOpReg pc_indf      = {{PO_INDF,    "INDF"}, -1, NULL,NULL};
 pCodeOpReg pc_fsr       = {{PO_FSR,     "FSR"}, -1, NULL,NULL};
+pCodeOpReg pc_pcl       = {{PO_PCL,     "PCL"}, -1, NULL,NULL};
+pCodeOpReg pc_pclath    = {{PO_PCLATH,  "PCLATH"}, -1, NULL,NULL};
 
 static int mnemonics_initialized = 0;
 
-#if 0
-//static char *PIC_mnemonics[] = {
-static char *scpADDLW = "ADDLW";
-static char *scpADDWF = "ADDWF";
-static char *scpANDLW = "ANDLW";
-static char *scpANDWF = "ANDWF";
-static char *scpBCF = "BCF";
-static char *scpBSF = "BSF";
-static char *scpBTFSC = "BTFSC";
-static char *scpBTFSS = "BTFSS";
-static char *scpCALL = "CALL";
-static char *scpCOMF = "COMF";
-static char *scpCLRF = "CLRF";
-static char *scpCLRW = "CLRW";
-static char *scpDECF = "DECF";
-static char *scpDECFSZ = "DECFSZ";
-static char *scpGOTO = "GOTO";
-static char *scpINCF = "INCF";
-static char *scpINCFSZ = "INCFSZ";
-static char *scpIORLW = "IORLW";
-static char *scpIORWF = "IORWF";
-static char *scpMOVF = "MOVF";
-static char *scpMOVLW = "MOVLW";
-static char *scpMOVWF = "MOVWF";
-static char *scpNEGF = "NEGF";
-static char *scpRETLW = "RETLW";
-static char *scpRETURN = "RETURN";
-static char *scpSUBLW = "SUBLW";
-static char *scpSUBWF = "SUBWF";
-static char *scpTRIS = "TRIS";
-static char *scpXORLW = "XORLW";
-static char *scpXORWF = "XORWF";
-#endif
 
 static hTab *pic14MnemonicsHash = NULL;
 
 
 
 static pFile *the_pFile = NULL;
-static int peepOptimizing = 1;
+static int peepOptimizing = 0;
 static int GpCodeSequenceNumber = 1;
 
 /****************************************************************/
@@ -101,6 +70,7 @@ static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
 static char *get_op( pCodeInstruction *pcc);
 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
 int pCodePeepMatchRule(pCode *pc);
+void pBlockStats(FILE *of, pBlock *pb);
 
 
 pCodeInstruction pciADDWF = {
@@ -257,7 +227,6 @@ pCodeInstruction pciCALL = {
   PCC_NONE  // outCond
 };
 
-//fixme - need a COMFW instruction.
 pCodeInstruction pciCOMF = {
   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
    genericAnalyze,
@@ -267,9 +236,23 @@ pCodeInstruction pciCOMF = {
   "COMF",
   NULL, // operand
   2,    // num ops
+  1,0,  // dest, bit instruction
+  PCC_REGISTER,  // inCond
+  PCC_REGISTER   // outCond
+};
+
+pCodeInstruction pciCOMFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
+   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_COMFW,
+  "COMF",
+  NULL, // operand
+  2,    // num ops
   0,0,  // dest, bit instruction
-  PCC_NONE, // inCond
-  PCC_NONE  // outCond
+  PCC_REGISTER,  // inCond
+  PCC_  // outCond
 };
 
 pCodeInstruction pciCLRF = {
@@ -569,6 +552,62 @@ pCodeInstruction pciRETURN = {
 };
 
 
+pCodeInstruction pciRLF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
+   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RLF,
+  "RLF",
+  NULL, // operand
+  2,    // num ops
+  1,0,  // dest, bit instruction
+  (PCC_C | PCC_REGISTER),   // inCond
+  (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
+};
+
+pCodeInstruction pciRLFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
+   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RLFW,
+  "RLF",
+  NULL, // operand
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  (PCC_C | PCC_REGISTER),   // inCond
+  (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
+};
+
+pCodeInstruction pciRRF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
+   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RRF,
+  "RRF",
+  NULL, // operand
+  2,    // num ops
+  1,0,  // dest, bit instruction
+  (PCC_C | PCC_REGISTER),   // inCond
+  (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
+};
+
+pCodeInstruction pciRRFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
+   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_RRFW,
+  "RRF",
+  NULL, // operand
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  (PCC_C | PCC_REGISTER),   // inCond
+  (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
+};
+
 pCodeInstruction pciSUBWF = {
   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
    genericAnalyze,
@@ -611,6 +650,33 @@ pCodeInstruction pciSUBLW = {
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
+pCodeInstruction pciSWAPF = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
+   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SWAPF,
+  "SWAPF",
+  NULL, // operand
+  2,    // num ops
+  1,0,  // dest, bit instruction
+  (PCC_REGISTER),   // inCond
+  (PCC_REGISTER) // outCond
+};
+
+pCodeInstruction pciSWAPFW = {
+  {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
+   genericAnalyze,
+   genericDestruct,
+   genericPrint},
+  POC_SWAPFW,
+  "SWAPF",
+  NULL, // operand
+  2,    // num ops
+  0,0,  // dest, bit instruction
+  (PCC_REGISTER),   // inCond
+  (PCC_W) // outCond
+};
 pCodeInstruction pciTRIS = {
   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
    genericAnalyze,
@@ -672,21 +738,36 @@ pCodeInstruction pciXORLW = {
 #define MAX_PIC14MNEMONICS 100
 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
 
-char *Safe_strdup(char *str)
+/*-----------------------------------------------------------------*/
+/* SAFE_snprintf - like snprintf except the string pointer is      */
+/*                 after the string has been printed to. This is   */
+/*                 useful for printing to string as though if it   */
+/*                 were a stream.                                  */
+/*-----------------------------------------------------------------*/
+void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
 {
-  char *copy;
+  va_list val;
+  int len;
 
-  if(!str)
-    return NULL;
-
-  copy = strdup(str);
-  if(!copy) {
-    fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
-    exit(1);
-  }
+  if(!str || !*str)
+    return;
 
-  return copy;
+  va_start(val, format);
+#if 0
+  // Alas, vsnprintf is not ANSI standard, and does not exist
+  // on Solaris (and probably other non-Gnu flavored Unixes).
+  vsnprintf(*str, *size, format, val);
+#else
+  // This, of course, is *not* safe, despite the name.
+  vsprintf(*str, format, val);
+#endif
     
+  va_end (val);
+
+  len = strlen(*str);
+  *str += len;
+  *size -= len;
+
 }
 
 void  pCodeInitRegisters(void)
@@ -695,6 +776,9 @@ void  pCodeInitRegisters(void)
   pc_fsr.rIdx = 4;
   pc_fsr.r = pic14_regWithIdx(4);
 
+  pc_indf.rIdx = 0;
+  pc_indf.r = pic14_regWithIdx(0);
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -742,6 +826,7 @@ void pic14initMnemonics(void)
   pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
   pic14Mnemonics[POC_CALL] = &pciCALL;
   pic14Mnemonics[POC_COMF] = &pciCOMF;
+  pic14Mnemonics[POC_COMFW] = &pciCOMFW;
   pic14Mnemonics[POC_CLRF] = &pciCLRF;
   pic14Mnemonics[POC_CLRW] = &pciCLRW;
   pic14Mnemonics[POC_DECF] = &pciDECF;
@@ -763,9 +848,15 @@ void pic14initMnemonics(void)
   pic14Mnemonics[POC_NEGF] = &pciNEGF;
   pic14Mnemonics[POC_RETLW] = &pciRETLW;
   pic14Mnemonics[POC_RETURN] = &pciRETURN;
+  pic14Mnemonics[POC_RLF] = &pciRLF;
+  pic14Mnemonics[POC_RLFW] = &pciRLFW;
+  pic14Mnemonics[POC_RRF] = &pciRRF;
+  pic14Mnemonics[POC_RRFW] = &pciRRFW;
   pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
   pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
   pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
+  pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
+  pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
   pic14Mnemonics[POC_TRIS] = &pciTRIS;
   pic14Mnemonics[POC_XORLW] = &pciXORLW;
   pic14Mnemonics[POC_XORWF] = &pciXORWF;
@@ -784,7 +875,7 @@ void pic14initMnemonics(void)
   mnemonics_initialized = 1;
 }
 
-int getpCode(char *mnem,int dest)
+int getpCode(char *mnem,unsigned dest)
 {
 
   pCodeInstruction *pci;
@@ -871,8 +962,10 @@ void copypCode(FILE *of, char dbName)
     return;
 
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    if(getpBlock_dbName(pb) == dbName)
+    if(getpBlock_dbName(pb) == dbName) {
+      pBlockStats(of,pb);
       printpBlock(of,pb);
+    }
   }
 
 }
@@ -912,6 +1005,13 @@ void pcode_test(void)
     }
   }
 }
+/*-----------------------------------------------------------------*/
+/* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg-  */
+/*      ister, RegCond will return the bit being referenced.       */
+/*                                                                 */
+/* fixme - why not just OR in the pcop bit field                   */
+/*-----------------------------------------------------------------*/
+
 static int RegCond(pCodeOp *pcop)
 {
 
@@ -1043,7 +1143,10 @@ pCode *newpCodeCharP(char *cP)
   pcc->pc.destruct = genericDestruct;
   pcc->pc.print = genericPrint;
 
-  pcc->comment = Safe_strdup(cP);
+  if(cP)
+    pcc->comment = Safe_strdup(cP);
+  else
+    pcc->comment = NULL;
 
   return ( (pCode *)pcc);
 
@@ -1085,15 +1188,16 @@ pCode *newpCodeFunction(char *mod,char *f)
 
 }
 
+/*-----------------------------------------------------------------*/
+/* pCodeLabelDestruct - free memory used by a label.               */
+/*-----------------------------------------------------------------*/
 static void pCodeLabelDestruct(pCode *pc)
 {
 
   if(!pc)
     return;
 
-  unlinkPC(pc);
-
-  if(PCL(pc)->label)
+  if((pc->type == PC_LABEL) && PCL(pc)->label)
     free(PCL(pc)->label);
 
   free(pc);
@@ -1119,11 +1223,13 @@ pCode *newpCodeLabel(int key)
 
   pcl->key = key;
 
+  pcl->label = NULL;
   if(key>0) {
     sprintf(s,"_%05d_DS_",key);
-    pcl->label = Safe_strdup(s);
-  } else
-    pcl->label = NULL;
+    if(s)
+      pcl->label = Safe_strdup(s);
+  }
+
 
   return ( (pCode *)pcl);
 
@@ -1132,7 +1238,10 @@ pCode *newpCodeLabelStr(char *str)
 {
   pCode *pc = newpCodeLabel(-1);
 
-  PCL(pc)->label = Safe_strdup(str);
+  if(str)
+    PCL(pc)->label = Safe_strdup(str);
+  else
+    PCL(pc)->label = NULL;
 
   return pc;
 }
@@ -1192,17 +1301,21 @@ pCodeOp *newpCodeOpLabel(int key)
   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
   pcop->type = PO_LABEL;
 
+  pcop->name = NULL;
   if(key>0) {
     sprintf(s,"_%05d_DS_",key);
-    pcop->name = Safe_strdup(s);
-  } else
-    pcop->name = NULL;
+    if(s)
+      pcop->name = Safe_strdup(s);
+  } 
+
 
   ((pCodeOpLabel *)pcop)->key = key;
 
   return pcop;
 }
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
 pCodeOp *newpCodeOpLit(int lit)
 {
   char *s = buffer;
@@ -1211,17 +1324,21 @@ pCodeOp *newpCodeOpLit(int lit)
 
   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
   pcop->type = PO_LITERAL;
+  pcop->name = NULL;
   if(lit>=0) {
     sprintf(s,"0x%02x",lit);
-    pcop->name = Safe_strdup(s);
-  } else
-    pcop->name = NULL;
+    if(s)
+      pcop->name = Safe_strdup(s);
+  } 
+
 
   ((pCodeOpLit *)pcop)->lit = lit;
 
   return pcop;
 }
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
 {
   char *s = buffer;
@@ -1246,19 +1363,34 @@ pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
   return pcop;
 }
 
-pCodeOp *newpCodeOpBit(char *s, int bit)
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
 {
   pCodeOp *pcop;
 
   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
   pcop->type = PO_BIT;
-  pcop->name = Safe_strdup(s);   
+  if(s)
+    pcop->name = Safe_strdup(s);   
+  else
+    pcop->name = NULL;
 
   PCOB(pcop)->bit = bit;
-  if(bit>=0)
-    PCOB(pcop)->inBitSpace = 1;
-  else
-    PCOB(pcop)->inBitSpace = 0;
+  PCOB(pcop)->inBitSpace = inBitSpace;
+
+  return pcop;
+}
+
+pCodeOp *newpCodeOpReg(int rIdx)
+{
+  pCodeOp *pcop;
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+
+  PCOR(pcop)->rIdx = rIdx;
+  PCOR(pcop)->r = pic14_regWithIdx(rIdx);
+  pcop->type = PCOR(pcop)->r->pc_type;
 
   return pcop;
 }
@@ -1272,7 +1404,7 @@ pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
 
   switch(type) {
   case PO_BIT:
-    pcop = newpCodeOpBit(name, -1);
+    pcop = newpCodeOpBit(name, -1,0);
     break;
 
   case PO_LITERAL:
@@ -1286,7 +1418,10 @@ pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
   default:
     pcop = Safe_calloc(1,sizeof(pCodeOp) );
     pcop->type = type;
-    pcop->name = Safe_strdup(name);   
+    if(name)
+      pcop->name = Safe_strdup(name);   
+    else
+      pcop->name = NULL;
   }
 
   return pcop;
@@ -1297,12 +1432,18 @@ pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
 /*-----------------------------------------------------------------*/
 void addpCode2pBlock(pBlock *pb, pCode *pc)
 {
-
-  pb->pcTail->next = pc;
-  pc->prev = pb->pcTail;
-  pc->next = NULL;
-  pc->pb = pb;
-  pb->pcTail = pc;
+  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 {
+    pb->pcTail->next = pc;
+    pc->prev = pb->pcTail;
+    pc->next = NULL;
+    pc->pb = pb;
+    pb->pcTail = pc;
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -1313,7 +1454,7 @@ void addpBlock(pBlock *pb)
 
   if(!the_pFile) {
     /* First time called, we'll pass through here. */
-    _ALLOC(the_pFile,sizeof(the_pFile));
+    _ALLOC(the_pFile,sizeof(pFile));
     the_pFile->pbHead = the_pFile->pbTail = pb;
     the_pFile->functions = NULL;
     return;
@@ -1370,10 +1511,16 @@ void printpBlock(FILE *of, pBlock *pb)
 
 static void unlinkPC(pCode *pc)
 {
-  if(pc  && pc->prev && pc->next) {
 
-    pc->prev->next = pc->next;
-    pc->next->prev = pc->prev;
+
+  if(pc) {
+
+    if(pc->prev) 
+      pc->prev->next = pc->next;
+    if(pc->next)
+      pc->next->prev = pc->prev;
+
+    pc->prev = pc->next = NULL;
   }
 }
 static void genericDestruct(pCode *pc)
@@ -1387,6 +1534,8 @@ static void genericDestruct(pCode *pc)
 }
 
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
 void pBlockRegs(FILE *of, pBlock *pb)
 {
 
@@ -1394,7 +1543,6 @@ void pBlockRegs(FILE *of, pBlock *pb)
 
   r = setFirstItem(pb->registers);
   while (r) {
-    fprintf(of,"   %s\n",r->name);
     r = setNextItem(pb->registers);
   }
 }
@@ -1408,11 +1556,16 @@ static char *get_op( pCodeInstruction *pcc)
 
 
     switch(pcc->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;
+      break;
     case PO_GPR_TEMP:
+    case PO_GPR_BIT:
       r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
-      fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
+      //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
       pBlockRegs(stderr,pcc->pc.pb);
       return r->name;
 
@@ -1434,6 +1587,72 @@ static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
   fprintf(of,"pcodeopprint\n");
 }
 
+char *pCode2str(char *str, int size, pCode *pc)
+{
+  char *s = str;
+
+  switch(pc->type) {
+
+  case PC_OPCODE:
+
+    SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
+
+    if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
+
+      if(PCI(pc)->bit_inst) {
+       if(PCI(pc)->pcop->type == PO_BIT) {
+         if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
+           SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
+                         PCI(pc)->pcop->name ,
+                         PCI(pc)->pcop->name );
+         else
+           SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)), 
+                         (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
+       } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
+         SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
+       }else
+         SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
+       //PCI(pc)->pcop->t.bit );
+      } else {
+
+       if(PCI(pc)->pcop->type == PO_BIT) {
+         if( PCI(pc)->num_ops == 2)
+           SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
+         else
+           SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
+
+       }else {
+         SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
+
+         if( PCI(pc)->num_ops == 2)
+           SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
+       }
+      }
+
+    }
+    break;
+
+  case PC_COMMENT:
+    /* assuming that comment ends with a \n */
+    SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
+    break;
+
+  case PC_LABEL:
+    SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
+    break;
+  case PC_FUNCTION:
+    SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
+    break;
+  case PC_WILD:
+    SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
+    break;
+
+  }
+
+  return str;
+
+}
+
 /*-----------------------------------------------------------------*/
 /* genericPrint - the contents of a pCode to a file                */
 /*-----------------------------------------------------------------*/
@@ -1452,48 +1671,20 @@ static void genericPrint(FILE *of, pCode *pc)
     // If the opcode has a label, print that first
     {
       pBranch *pbl = pc->label;
-      while(pbl) {
+      while(pbl && pbl->pc) {
        if(pbl->pc->type == PC_LABEL)
          pCodePrintLabel(of, pbl->pc);
        pbl = pbl->next;
       }
     }
 
-    fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
-    if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
-
-      if(PCI(pc)->bit_inst) {
-       if(PCI(pc)->pcop->type == PO_BIT) {
-         if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
-           fprintf(of,"(%s >> 3), (%s & 7)", 
-                   PCI(pc)->pcop->name ,
-                   PCI(pc)->pcop->name );
-         else
-           fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
-       } else
-         fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
-       //PCI(pc)->pcop->t.bit );
-      } else {
-
-       if(PCI(pc)->pcop->type == PO_BIT) {
-         if( PCI(pc)->num_ops == 2)
-           fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
-         else
-           fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
 
-/*
-         if( PCI(pc)->num_ops == 2)
-           fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
-         else
-           fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
-*/
-       }else {
-         fprintf(of,"%s",get_op(PCI(pc)));
+    {
+      char str[256];
+      
+      pCode2str(str, 256, pc);
 
-         if( PCI(pc)->num_ops == 2)
-           fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
-       }
-      }
+      fprintf(of,"%s",str);
     }
 
     {
@@ -1522,6 +1713,9 @@ static void genericPrint(FILE *of, pCode *pc)
 
   case PC_WILD:
     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
+    if(pc->label)
+      pCodePrintLabel(of, pc->label->pc);
+
     if(PCW(pc)->operand) {
       fprintf(of,";\toperand  ");
       pCodeOpPrint(of,PCW(pc)->operand );
@@ -1583,11 +1777,41 @@ static void pCodePrintLabel(FILE *of, pCode *pc)
   else if (PCL(pc)->key >=0) 
     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
   else
-    fprintf(of,";wild card label\n");
+    fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
 
 }
 /*-----------------------------------------------------------------*/
+/* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
+/*                         remove it if it is found.               */
+/*-----------------------------------------------------------------*/
+static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
+{
+  pBranch *b, *bprev;
+
+  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;
+  }
+
+}
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
 {
   pBranch *b;
@@ -1718,8 +1942,33 @@ static void genericAnalyze(pCode *pc)
        } else
          npc = npc->next;
       }
+      /* reached the end of the pcode chain without finding
+       * an instruction we could link to. */
+    }
+  }
+}
+
+/*-----------------------------------------------------------------*/
+int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
+{
+  pBranch *pbr;
+
+  if(pc->type == PC_LABEL) {
+    if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
+      return TRUE;
+  }
+  if(pc->type == PC_OPCODE) {
+    pbr = pc->label;
+    while(pbr) {
+      if(pbr->pc->type == PC_LABEL) {
+       if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
+         return TRUE;
+      }
+      pbr = pbr->next;
     }
   }
+
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1729,29 +1978,15 @@ pCode * findLabel(pCodeOpLabel *pcop_label)
 {
   pBlock *pb;
   pCode  *pc;
-  pBranch *pbr;
 
   if(!the_pFile)
     return NULL;
 
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    for(pc = pb->pcHead; pc; pc = pc->next) {
-      if(pc->type == PC_LABEL) {
-       if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
-         return pc;
-      }
-      if(pc->type == PC_OPCODE) {
-       pbr = pc->label;
-       while(pbr) {
-         if(pbr->pc->type == PC_LABEL) {
-           if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
-             return pc;
-         }
-         pbr = pbr->next;
-       }
-      }
-
-    }
+    for(pc = pb->pcHead; pc; pc = pc->next) 
+      if(compareLabel(pc,pcop_label))
+       return pc;
+    
   }
 
   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
@@ -1766,7 +2001,7 @@ pCode * findNextInstruction(pCode *pc)
 {
 
   while(pc) {
-    if(pc->type == PC_OPCODE)
+    if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
       return pc;
 
     pc = pc->next;
@@ -1829,6 +2064,8 @@ static void AnalyzeRETURN(pCode *pc)
 
 }
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
 
 void AnalyzepBlock(pBlock *pb)
 {
@@ -1843,7 +2080,7 @@ void AnalyzepBlock(pBlock *pb)
       if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
 
        /* Loop through all of the registers declared so far in
-          this block and see if we find this new there */
+          this block and see if we find this one there */
 
        regs *r = setFirstItem(pb->registers);
 
@@ -1869,6 +2106,8 @@ void AnalyzepBlock(pBlock *pb)
   }
 }
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
 int OptimizepBlock(pBlock *pb)
 {
   pCode *pc;
@@ -1877,14 +2116,79 @@ int OptimizepBlock(pBlock *pb)
   if(!pb || !peepOptimizing)
     return 0;
 
-  fprintf(stderr," Optimizing pBlock\n");
-
+  fprintf(stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb));
   for(pc = pb->pcHead; pc; pc = pc->next)
     matches += pCodePeepMatchRule(pc);
 
   return matches;
 
 }
+
+/*-----------------------------------------------------------------*/
+/* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
+/*-----------------------------------------------------------------*/
+pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
+{
+  pCode *pc;
+
+  for(pc = pcs; pc; pc = pc->next) {
+
+    if((pc->type == PC_OPCODE) && 
+       (PCI(pc)->pcop) && 
+       (PCI(pc)->pcop->type == PO_LABEL) &&
+       (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
+      return pc;
+  }
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
+/*                            pCode chain if they're not used.     */
+/*-----------------------------------------------------------------*/
+void pBlockRemoveUnusedLabels(pBlock *pb)
+{
+  pCode *pc; pCodeLabel *pcl;
+
+  if(!pb)
+    return;
+
+  for(pc = pb->pcHead; pc; pc = pc->next) {
+
+    if(pc->type == PC_LABEL)
+      pcl = PCL(pc);
+    else if (pc->label)
+      pcl = PCL(pc->label->pc);
+    else continue;
+
+      /* This pCode is a label, so search the pBlock to see if anyone
+       * refers to it */
+
+    if( (pcl->key>0) && (!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\n", pcl->key);
+
+      if(pc->type == PC_LABEL) {
+       unlinkPC(pc);
+       pCodeLabelDestruct(pc);
+      } else {
+       unlinkpCodeFromBranch(pc, PCODE(pcl));
+       /*if(pc->label->next == NULL && pc->label->pc == NULL) {
+         free(pc->label);
+       }*/
+      }
+
+    }
+  }
+
+}
+
+
 /*-----------------------------------------------------------------*/
 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
 /*                     chain and put them into pBranches that are  */
@@ -1899,18 +2203,22 @@ void pBlockMergeLabels(pBlock *pb)
   if(!pb)
     return;
 
+  /* First, Try to remove any unused labels */
+  //pBlockRemoveUnusedLabels(pb);
+
+  /* Now loop through the pBlock and merge the labels with the opcodes */
+
   for(pc = pb->pcHead; pc; pc = pc->next) {
 
     if(pc->type == 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
-      if(pc->prev) 
-       pc->prev->next = pc->next;
-      if(pc->next)
-       pc->next->prev = pc->prev;
+      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
@@ -1922,9 +2230,14 @@ void pBlockMergeLabels(pBlock *pb)
       pbr->next = NULL;
 
       pcnext->label = pBranchAppend(pcnext->label,pbr);
+      if(pcnext->prev) 
+       pc = pcnext->prev;
+      else
+       pc = pcnext;
     }
 
   }
+  pBlockRemoveUnusedLabels(pb);
 
 }
 
@@ -1967,23 +2280,32 @@ void AnalyzepCode(char dbName)
   pCode *pc;
   pBranch *pbr;
 
+  int i,changes;
+
   if(!the_pFile)
     return;
 
   fprintf(stderr," Analyzing pCode");
 
-  /* First, merge the labels with the instructions */
-  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    if('*' == dbName || getpBlock_dbName(pb) == dbName) {
-      pBlockMergeLabels(pb);
-      AnalyzepBlock(pb);
+  changes = 0;
+  i = 0;
+  do {
+    /* First, merge the labels with the instructions */
+    for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+      if('*' == dbName || getpBlock_dbName(pb) == dbName) {
+
+       fprintf(stderr," analyze and merging block %c\n",dbName);
+       pBlockMergeLabels(pb);
+       AnalyzepBlock(pb);
+      }
     }
-  }
 
-  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    if('*' == dbName || getpBlock_dbName(pb) == dbName)
-      OptimizepBlock(pb);
-  }
+    for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+      if('*' == dbName || getpBlock_dbName(pb) == dbName)
+       changes += OptimizepBlock(pb);
+    }
+      
+  } while(changes && (i++ < MAX_PASSES));
 
   /* Now build the call tree.
      First we examine all of the pCodes for functions.
@@ -2106,26 +2428,28 @@ void pBlockStats(FILE *of, pBlock *pb)
   pCode *pc;
   regs  *r;
 
-  fprintf(of,"***\n  pBlock Stats\n***\n");
+  fprintf(of,";***\n;  pBlock Stats\n;***\n");
 
   // for now just print the first element of each set
   pc = setFirstItem(pb->function_entries);
   if(pc) {
-    fprintf(of,"entry\n");
+    fprintf(of,";entry:  ");
     pc->print(of,pc);
   }
   pc = setFirstItem(pb->function_exits);
   if(pc) {
-    fprintf(of,"has an exit\n");
-    pc->print(of,pc);
+    fprintf(of,";has an exit\n");
+    //pc->print(of,pc);
   }
 
   pc = setFirstItem(pb->function_calls);
   if(pc) {
-    fprintf(of,"functions called\n");
+    fprintf(of,";functions called:\n");
 
     while(pc) {
-      pc->print(of,pc);
+      if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+       fprintf(of,";   %s\n",get_op(PCI(pc)));
+      }
       pc = setNextItem(pb->function_calls);
     }
   }
@@ -2134,10 +2458,10 @@ void pBlockStats(FILE *of, pBlock *pb)
   if(r) {
     int n = elementsInSet(pb->registers);
 
-    fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
+    fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
 
     while (r) {
-      fprintf(of,"   %s\n",r->name);
+      fprintf(of,";   %s\n",r->name);
       r = setNextItem(pb->registers);
     }
   }
@@ -2197,6 +2521,10 @@ set *register_usage(pBlock *pb)
 
 
   pBlockStats(stderr,pb);  // debug
+
+  // Mark the registers in this block as used.
+
+  MarkUsedRegisters(pb->registers);
   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 */
@@ -2211,10 +2539,10 @@ set *register_usage(pBlock *pb)
 
       r2 = setFirstItem(pb->registers);
 
-      while(r2) {
+      while(r2 && (r1->type != REG_STK)) {
 
        if(r2->rIdx == r1->rIdx) {
-         newreg = pic14_findFreeReg();
+         newreg = pic14_findFreeReg(REG_GPR);
 
 
          if(!newreg) {
@@ -2226,7 +2554,10 @@ set *register_usage(pBlock *pb)
                  r1->rIdx, newreg->rIdx);
          r2->rIdx = newreg->rIdx;
          //if(r2->name) free(r2->name);
-         r2->name = Safe_strdup(newreg->name);
+         if(newreg->name)
+           r2->name = Safe_strdup(newreg->name);
+         else
+           r2->name = NULL;
          newreg->isFree = 0;
          newreg->wasUsed = 1;
        }
@@ -2239,13 +2570,15 @@ set *register_usage(pBlock *pb)
     /* 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;
+      if(r1->type != REG_STK) {
+       newreg = pic14_regWithIdx(r1->rIdx);
+       newreg->isFree = 1;
+      }
       r1 = setNextItem(registersInCallPath);
     }
 
-  } else
-    MarkUsedRegisters(pb->registers);
+  }// else
+  //    MarkUsedRegisters(pb->registers);
 
   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
 
@@ -2342,7 +2675,10 @@ void pct2(FILE *of,pBlock *pb,int indent)
                  r1->rIdx, newreg->rIdx);
          r2->rIdx = newreg->rIdx;
          //if(r2->name) free(r2->name);
-         r2->name = Safe_strdup(newreg->name);
+         if(newreg->name)
+           r2->name = Safe_strdup(newreg->name);
+         else
+           r2->name = NULL;
          newreg->isFree = 0;
          newreg->wasUsed = 1;
        }