fixed bug #466587
[fw/sdcc] / src / pic / pcode.c
index de33c26d2a170cf660ee2f5c60098075fe4a398d..dd15d09c0b03d5b37671a65ac30be36d06ca3f16 100644 (file)
 
 #include "pcode.h"
 #include "ralloc.h"
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
 // Eventually this will go into device dependent files:
 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;
 
@@ -250,7 +226,6 @@ pCodeInstruction pciCALL = {
   PCC_NONE  // outCond
 };
 
-//fixme - need a COMFW instruction.
 pCodeInstruction pciCOMF = {
   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
    genericAnalyze,
@@ -260,9 +235,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 = {
@@ -552,7 +541,7 @@ pCodeInstruction pciRETURN = {
    AnalyzeRETURN,
    genericDestruct,
    genericPrint},
-  POC_RETLW,
+  POC_RETURN,
   "RETURN",
   NULL, // operand
   0,    // num ops
@@ -562,6 +551,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,
@@ -604,6 +649,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,
@@ -682,6 +754,39 @@ 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, ...)
+{
+  va_list val;
+  int len;
+
+  if(!str || !*str)
+    return;
+
+  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)
 {
 
@@ -735,6 +840,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;
@@ -756,9 +862,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;
@@ -777,7 +889,7 @@ void pic14initMnemonics(void)
   mnemonics_initialized = 1;
 }
 
-int getpCode(char *mnem)
+int getpCode(char *mnem,unsigned dest)
 {
 
   pCodeInstruction *pci;
@@ -790,8 +902,11 @@ int getpCode(char *mnem)
 
   while(pci) {
 
-    if(strcasecmp(pci->mnemonic, mnem) == 0)
-      return(pci->op);
+    if(STRCASECMP(pci->mnemonic, mnem) == 0) {
+      if((pci->num_ops <= 1) || (pci->dest == dest))
+       return(pci->op);
+    }
+
     pci = hTabNextItemWK (pic14MnemonicsHash);
   
   }
@@ -983,6 +1098,10 @@ pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
 /* line (of assembly code) is declared matched. Note that the      */
 /* operand may be wild too.                                        */
 /*                                                                 */
+/*   Note, a wild instruction is specified just like a wild var:   */
+/*      %4     ; A wild instruction,                               */
+/*  See the peeph.def file for additional examples                 */
+/*                                                                 */
 /*-----------------------------------------------------------------*/
 
 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
@@ -1001,7 +1120,7 @@ pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_la
   pcw->pc.destruct = genericDestruct;
   pcw->pc.print = genericPrint;
 
-  pcw->id = pCodeID;
+  pcw->id = pCodeID;              // this is the 'n' in %n
   pcw->operand = optional_operand;
   pcw->label   = optional_label;
 
@@ -1079,10 +1198,11 @@ static void pCodeLabelDestruct(pCode *pc)
 
   unlinkPC(pc);
 
-  if(PCL(pc)->label)
+  if((pc->type == PC_LABEL) && PCL(pc)->label)
     free(PCL(pc)->label);
 
   free(pc);
+
 }
 
 pCode *newpCodeLabel(int key)
@@ -1130,7 +1250,7 @@ pBlock *newpBlock(void)
 
   pBlock *PpB;
 
-  _ALLOC(PpB,sizeof(pBlock));
+  PpB = Safe_calloc(1,sizeof(pBlock) );
   PpB->next = PpB->prev = NULL;
 
   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
@@ -1142,7 +1262,7 @@ pBlock *newpBlock(void)
 }
 
 /*-----------------------------------------------------------------*/
-/* newpCodeChain - create a new chain of pCodes                    */
+/* newpCodeChai0n - create a new chain of pCodes                    */
 /*-----------------------------------------------------------------*
  *
  *  This function will create a new pBlock and the pointer to the
@@ -1162,20 +1282,6 @@ pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
   return pB;
 }
 
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
-
-pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
-{
-  pCodeOp *pcop;
-
-  pcop = Safe_calloc(1,sizeof(pCodeOp) );
-  pcop->type = type;
-  pcop->name = Safe_strdup(name);   
-
-  return pcop;
-}
-
 /*-----------------------------------------------------------------*/
 /* newpCodeOpLabel - Create a new label given the key              */
 /*  Note, a negative key means that the label is part of wild card */
@@ -1208,11 +1314,14 @@ pCodeOp *newpCodeOpLit(int lit)
   pCodeOp *pcop;
 
 
-  _ALLOC(pcop,sizeof(pCodeOpLit) );
+  pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
   pcop->type = PO_LITERAL;
-  sprintf(s,"0x%02x",lit);
-  _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
-  strcpy(pcop->name,s);
+  if(lit>=0) {
+    sprintf(s,"0x%02x",lit);
+    pcop->name = Safe_strdup(s);
+  } else
+    pcop->name = NULL;
+
   ((pCodeOpLit *)pcop)->lit = lit;
 
   return pcop;
@@ -1242,18 +1351,58 @@ 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;
 
-  _ALLOC(pcop,sizeof(pCodeOpBit) );
+  pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
   pcop->type = PO_BIT;
   pcop->name = Safe_strdup(s);   
+
   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;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
+pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
+{
+  pCodeOp *pcop;
+
+  switch(type) {
+  case PO_BIT:
+    pcop = newpCodeOpBit(name, -1,0);
+    break;
+
+  case PO_LITERAL:
+    pcop = newpCodeOpLit(-1);
+    break;
+
+  case PO_LABEL:
+    pcop = newpCodeOpLabel(-1);
+    break;
+
+  default:
+    pcop = Safe_calloc(1,sizeof(pCodeOp) );
+    pcop->type = type;
+    pcop->name = Safe_strdup(name);   
+  }
 
   return pcop;
 }
@@ -1263,12 +1412,18 @@ pCodeOp *newpCodeOpBit(char *s, int bit)
 /*-----------------------------------------------------------------*/
 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;
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -1336,18 +1491,26 @@ 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)
 {
+  fprintf(stderr,"warning, calling default pCode destructor\n");
+
   unlinkPC(pc);
 
-  fprintf(stderr,"warning, calling default pCode destructor\n");
   free(pc);
+
 }
 
 
@@ -1358,7 +1521,6 @@ void pBlockRegs(FILE *of, pBlock *pb)
 
   r = setFirstItem(pb->registers);
   while (r) {
-    fprintf(of,"   %s\n",r->name);
     r = setNextItem(pb->registers);
   }
 }
@@ -1375,8 +1537,9 @@ static char *get_op( pCodeInstruction *pcc)
 
     case PO_FSR:
     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;
 
@@ -1398,6 +1561,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                */
 /*-----------------------------------------------------------------*/
@@ -1423,41 +1652,13 @@ static void genericPrint(FILE *of, pCode *pc)
       }
     }
 
-    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);
     }
 
     {
@@ -1486,6 +1687,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 );
@@ -1547,10 +1751,26 @@ 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);
 
 }
 /*-----------------------------------------------------------------*/
+static void  unlinkpCodeFromBranch(pBranch *pb , pCode *pc)
+{
+  pBranch *b, *bprev;
+
+  bprev = NULL;
+  b = pb;
+  while(b) {
+    if(b->pc == pc) {
+      if(bprev)
+       bprev->next = b->next;
+    }
+    bprev = b;
+    b = b->next;
+  }
+
+}
 
 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
 {
@@ -1686,6 +1906,29 @@ static void genericAnalyze(pCode *pc)
   }
 }
 
+/*-----------------------------------------------------------------*/
+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;
+}
+
 /*-----------------------------------------------------------------*/
 /* findLabel - Search the pCode for a particular label             */
 /*-----------------------------------------------------------------*/
@@ -1693,29 +1936,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);
@@ -1730,7 +1959,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;
@@ -1841,14 +2070,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->label, pc);
+       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  */
@@ -1863,18 +2157,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
@@ -1886,9 +2184,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);
 
 }
 
@@ -1939,6 +2242,8 @@ void AnalyzepCode(char dbName)
   /* 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);
     }