* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[fw/sdcc] / src / pic16 / pcodepeep.c
index 69aac418fd87b7ef0c7f4b904fb50c5481122211..ec373e3358477a89c119be5c21a0e67899355907 100644 (file)
 
 #include "common.h"   // Include everything in the SDCC src directory
 #include "newalloc.h"
+
 //#define PCODE_DEBUG
+
 #include "pcode.h"
 #include "pcodeflow.h"
 #include "ralloc.h"
 
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
 pCodeOp *pic16_popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
 
 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype);
+pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2);
 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
 pCode * pic16_findNextInstruction(pCode *pc);
 int pic16_getpCode(char *mnem,int dest);
 int pic16_getpCodePeepCommand(char *cmd);
 void pic16_pBlockMergeLabels(pBlock *pb);
-char *pCode2str(char *str, int size, pCode *pc);
-char *pic16_get_op( pCodeOp *pcop,char *buf,int buf_size);
+char *pic16_pCode2str(char *str, int size, pCode *pc);
+//char *pic16_get_op(pCodeOp *pcop,char *buf, size_t buf_size);
 pCodeOp *pic16_popCombine2(pCodeOp *, pCodeOp *, int);
 
 extern pCodeInstruction *pic16Mnemonics[];
@@ -219,7 +216,7 @@ static char alt_mnem1a[]    = { PCP_STR, PCP_WILDVAR, 0};
 static char alt_mnem1b[]    = { PCP_STR, PCP_NUMBER, 0};
 static char alt_mnem2[]     = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
 static char alt_mnem2a[]    = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
-//static char alt_mnem2b[]    = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_WILDVAR, 0};
+static char alt_mnem2b[]    = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_WILDVAR, 0};
 static char alt_mnem3[]     = { PCP_STR, PCP_STR, PCP_COMMA, PCP_NUMBER, 0};
 static char alt_mnem4[]            = { PCP_STR, PCP_NUMBER, PCP_COMMA, PCP_STR, 0};    // for lfsr 0 , name
 static char alt_mnem4a[]    = { PCP_STR, PCP_NUMBER, PCP_COMMA, PCP_NUMBER, 0}; // for lfsr 0 , value
@@ -233,7 +230,7 @@ static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb);
 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb);
 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb);
 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb);
-//static void * cvt_altpat_mnem2b(void *pp, pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem2b(void *pp, pCodeWildBlock *pcwb);
 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb);
 static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb);
 static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb);
@@ -245,7 +242,7 @@ static pcPattern altArr[] = {
   {ALT_MNEM4a,       alt_mnem4a, cvt_altpat_mnem4a},
   {ALT_MNEM4,        alt_mnem4,  cvt_altpat_mnem4},
   {ALT_MNEM3,        alt_mnem3,  cvt_altpat_mnem3},
-//  {ALT_MNEM2B,       alt_mnem2b, cvt_altpat_mnem2b},
+  {ALT_MNEM2B,       alt_mnem2b, cvt_altpat_mnem2b},
   {ALT_MNEM2A,       alt_mnem2a, cvt_altpat_mnem2a},
   {ALT_MNEM2,        alt_mnem2,  cvt_altpat_mnem2},
   {ALT_MNEM1B,       alt_mnem1b, cvt_altpat_mnem1b},
@@ -273,7 +270,7 @@ static int cvt_extract_destination(parsedPattern *pp)
 
     // just check first letter for now
 
-    if(toupper(*pp->pct[0].tok.s) == 'F')
+    if(toupper((unsigned char)*pp->pct[0].tok.s) == 'F')
       return 1;
 
   } else if (pp->pct[0].tt == PCT_NUMBER) {
@@ -304,14 +301,14 @@ static pCodeOp *cvt_extract_status(char *reg, char *bit)
 
   if(len == 1) {
     // check C,Z
-    if(toupper(*bit) == 'C')
+    if(toupper((unsigned char)*bit) == 'C')
       return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_C_BIT));
-    if(toupper(*bit) == 'Z')
+    if(toupper((unsigned char)*bit) == 'Z')
       return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_Z_BIT));
   }
 
   // Check DC
-  if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
+  if(len ==2 && toupper((unsigned char)bit[0]) == 'D' && toupper((unsigned char)bit[1]) == 'C')
     return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_DC_BIT));
 
   return NULL;
@@ -510,7 +507,7 @@ static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb)
   }
 
   if(pic16Mnemonics[opcode]->isBitInst)
-    pcosubtype = pic16_newpCodeOpBit(NULL,-1,0);
+    pcosubtype = pic16_newpCodeOpBit(NULL,-1,0, PO_GPR_REGISTER);
   else
     pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
 
@@ -634,7 +631,7 @@ static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
   int dest;
 
   pCodeInstruction *pci=NULL;
-  pCodeOp *pcosubtype;
+  pCodeOp *pcosubtype, *pcosubtype2;
 
   if(!pcwb) {
     fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
@@ -649,6 +646,14 @@ static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
          p[3].pct[0].tok.s,
          dest));
 
+#if 0
+  fprintf(stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
+         p->pct[0].tok.s,
+         p[1].pct[1].tok.n,
+         p[3].pct[0].tok.s,
+         dest);
+#endif
+
 
   opcode = pic16_getpCode(p->pct[0].tok.s,dest);
   if(opcode < 0) {
@@ -656,21 +661,26 @@ static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
     return NULL;
   }
 
-  if(pic16Mnemonics[opcode]->isBitInst)
+  if(pic16Mnemonics[opcode]->isBitInst) {
     pcosubtype = pic16_newpCodeOp(NULL,PO_BIT);
-  else
+    pcosubtype2 = NULL;
+  } else {
+#if 0
   if(pic16Mnemonics[opcode]->is2MemOp) {
-       return NULL;
        /* support for movff instruction */
-       pcosubtype = pic16_popCombine2(
-               pic16_newpCodeOp(p[1].pct[0].tok.s, PO_GPR_REGISTER),
-               pic16_newpCodeOp(p[3].pct[0].tok.s, PO_GPR_REGISTER), 0);
-  } else
-    pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
+       pcosubtype = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
+       pcosubtype2 = pic16_newpCodeOp(p[3].pct[0].tok.s, PO_STR);
+  } else {
+#endif
+    pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER); pcosubtype2 = NULL; }
 
 
-  pci = PCI(pic16_newpCode(opcode,
+  if(!pcosubtype2)
+       pci = PCI(pic16_newpCode(opcode,
                     pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
+  else
+       pci = PCI(pic16_newpCode(opcode,
+                    pic16_newpCodeOpWild2(p[1].pct[1].tok.n, p[3].pct[1].tok.n, pcwb, pcosubtype, pcosubtype2)));
 
   /* Save the index of the maximum wildcard variable */
   //if(p[1].pct[1].tok.n > sMaxWildVar)
@@ -686,7 +696,6 @@ static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
 
 }
 
-#if 0
 /*-----------------------------------------------------------------*/
 /* cvt_altpat_mem2b - convert assembly line type to a pCode        */
 /*                    instruction with 2 wild operands             */
@@ -704,7 +713,7 @@ static void * cvt_altpat_mnem2b(void *pp,pCodeWildBlock *pcwb)
   int dest;
 
   pCodeInstruction *pci=NULL;
-  pCodeOp *pcosubtype;
+  pCodeOp *pcosubtype, *pcosubtype2;
 
   if(!pcwb) {
     fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
@@ -718,6 +727,12 @@ static void * cvt_altpat_mnem2b(void *pp,pCodeWildBlock *pcwb)
          p[1].pct[1].tok.n,
          p[3].pct[1].tok.n));
 
+#if 0
+  fprintf(stderr,"altpat_mnem2b %s src: %d dst: %d\n",
+         p->pct[0].tok.s,
+         p[1].pct[1].tok.n,
+         p[3].pct[1].tok.n);
+#endif
 
   opcode = pic16_getpCode(p->pct[0].tok.s,dest);
   if(opcode < 0) {
@@ -727,13 +742,13 @@ static void * cvt_altpat_mnem2b(void *pp,pCodeWildBlock *pcwb)
 
   if(pic16Mnemonics[opcode]->is2MemOp) {
        /* support for movff instruction */
-       pcosubtype = pic16_popCombine2(
-               pic16_newpCodeOp(NULL, PO_GPR_REGISTER),
-               pic16_newpCodeOp(NULL, PO_GPR_REGISTER), 0);
-  } else pcosubtype = NULL;
+       pcosubtype = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
+       pcosubtype2 = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
+  } else pcosubtype = pcosubtype2 = NULL;
 
   pci = PCI(pic16_newpCode(opcode,
-                    pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
+                    pic16_newpCodeOpWild2(p[1].pct[1].tok.n, p[3].pct[1].tok.n,
+                       pcwb, pcosubtype, pcosubtype2)));
 
   /* Save the index of the maximum wildcard variable */
   //if(p[1].pct[1].tok.n > sMaxWildVar)
@@ -748,7 +763,6 @@ static void * cvt_altpat_mnem2b(void *pp,pCodeWildBlock *pcwb)
   return pci;
 
 }
-#endif
 
 
 /*-----------------------------------------------------------------*/
@@ -790,7 +804,7 @@ static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
     //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
 
     //if(pcosubtype == NULL) {
-    pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0);
+    pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0, PO_GPR_REGISTER);
     //}
   } else
     pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
@@ -942,15 +956,15 @@ static void tokenizeLineNode(char *ln)
 //     fprintf(stderr, "%s:%d: processing %s\n", __FILE__, __LINE__, ln); 
 
   while(*ln) {
-    if(isspace(*ln)) {
+    if(isspace((unsigned char)*ln)) {
       // add a SPACE token and eat the extra spaces.
       tokArr[tokIdx++].tt = PCT_SPACE;
-      while (isspace (*ln))
+      while (isspace ((unsigned char)*ln))
        ln++;
       continue;
     }
 
-    if(isdigit(*ln)) {
+    if(isdigit((unsigned char)*ln)) {
 
       tokArr[tokIdx].tt = PCT_NUMBER;
       tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
@@ -983,11 +997,11 @@ static void tokenizeLineNode(char *ln)
 
 
     default:                           // hack to allow : goto $
-      if(isalpha(*ln) || (*ln == '_')  || (!parsing_peeps && (*ln == '$'))) {
+      if(isalpha((unsigned char)*ln) || (*ln == '_')  || (!parsing_peeps && (*ln == '$'))) {
        char buffer[50];
        int i=0;
 
-       while( (isalpha(*ln)  ||  isdigit(*ln) || (*ln == '_') || (*ln == '$')) && i<49)
+       while( (isalpha((unsigned char)*ln) || isdigit((unsigned char)*ln) || (*ln == '_') || (*ln == '$')) && i<49)
          buffer[i++] = *ln++;
 
        ln--;
@@ -1719,13 +1733,13 @@ int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond)
  *-----------------------------------------------------------------*/
 static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
 {
-  char b[50], *n2;
+  char b[1024], *n2;
 
   if(!pcops || !pcopd)
     return 0;
 
 #if 0
-  fprintf(stderr," Comparing operands %s",
+  fprintf(stderr,"%s:%d Comparing operands %s", __FILE__, __LINE__, 
          pic16_get_op( pcops,NULL,0));
 
   fprintf(stderr," to %s\n",
@@ -1745,20 +1759,20 @@ static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
     return 0;
   }
 
-  b[0]=0;
-  pic16_get_op(pcops,b,50);
+  memset(b, 0, sizeof(b) );       //b[0]=0;
+  pic16_get_op(pcops,b, sizeof(b) );
 
   n2 = pic16_get_op(pcopd,NULL,0);
 
   if( !n2 || strcmp(b,n2)) {
-    //fprintf(stderr,"  - fail - diff names: %s, len=%d,  %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
+//     fprintf(stderr,"  - fail - diff names: %s, len=%d,  %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
     return 0;  // different names
   }
 
   switch(pcops->type) {
   case PO_DIR:
     if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
-      //fprintf(stderr, "  - fail different instances\n");
+//     fprintf(stderr, "  - fail different instances\n");
       return 0;
     }
     break;
@@ -1857,7 +1871,8 @@ static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 {
   int index;   // index into wild card arrays
-
+  int havematch=0;
+  
   /* one-for-one match. Here the source and destination opcodes 
    * are not wild. However, there may be a label or a wild operand */
 
@@ -1886,7 +1901,8 @@ static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 
       /* Compare the operands */
       if(PCI(pcd)->pcop) {
-       if (PCI(pcd)->pcop->type == PO_WILD) {
+       /* assert that optimizations do not touch operations that work on SFRs or INDF registers */
+       if ((PCI(pcd)->pcop->type == PO_WILD) && (!(PCI(pcs)->pcop) || ((PCI(pcs)->pcop->type != PO_SFR_REGISTER) && (PCI(pcs)->pcop->type != PO_INDF0)))) {
          index = PCOW(PCI(pcd)->pcop)->id;
          //DFPRINTF((stderr,"destination is wild\n"));
 #ifdef DEBUG_PCODEPEEP
@@ -1897,6 +1913,7 @@ static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 #endif
 
          PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
+         havematch = -1;
          if(!peepBlock->target.wildpCodeOps[index]) {
            peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
 
@@ -1912,10 +1929,11 @@ static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
              );
            */
 
-           return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
+           havematch = pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
+//         return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
          }
 
-         if(PCI(pcs)->pcop) {
+         if((havematch==-1) && PCI(pcs)->pcop) {
            char *n;
 
            switch(PCI(pcs)->pcop->type) {
@@ -1934,43 +1952,93 @@ static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
            else {
              DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
              peepBlock->target.vars[index] = n;
-             return 1;
+             havematch = 1;
+//           return 1;
            }
          }
-         
-         if(PCI(pcs)->is2MemOp) {
-           char *n;
 
-           switch(PCOP(PCOR2(PCI(pcs))->pcop2)->type) {
-           case PO_GPR_TEMP:
-           case PO_FSR0:
-             //case PO_INDF0:
-               n = PCOR(PCOR2(PCI(pcs))->pcop2)->r->name;
+         /* now check whether the second operand matches */
+         /* assert that optimizations do not touch operations that work on SFRs or INDF registers */
+         if(PCOW2(PCI(pcd)->pcop) && (PCOP2(PCI(pcd)->pcop)->pcopR->type == PO_WILD) && (!(PCOP2(PCI(pcs)->pcop)->pcopR) || ((PCOP2(PCI(pcs)->pcop)->pcopR->type != PO_SFR_REGISTER) && (PCOP2(PCI(pcs)->pcop)->pcopR) && (PCOP2(PCI(pcs)->pcop)->pcopR->type != PO_INDF0)))) {
+       
+//             fprintf(stderr, "%s:%d %s second operand is wild\n", __FILE__, __LINE__, __FUNCTION__);
+       
+                 index = PCOW2(PCI(pcd)->pcop)->id;
+               //DFPRINTF((stderr,"destination is wild\n"));
+#ifdef DEBUG_PCODEPEEP
+               if (index > peepBlock->nops) {
+                       DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
+                       exit(1);
+               }
+#endif
 
-             break;
-           default:
-             n = PCI(pcs)->pcop->name;
+               PCOW2(PCI(pcd)->pcop)->matched = PCOP2(PCI(pcs)->pcop)->pcopR;
+               if(!peepBlock->target.wildpCodeOps[index]) {
+                       peepBlock->target.wildpCodeOps[index] = PCOP2(PCI(pcs)->pcop)->pcopR;
+
+               //if(PCI(pcs)->pcop->type == PO_GPR_TEMP) 
+
+               } else {
+                       /*
+                       pcs->print(stderr,pcs);
+                       pcd->print(stderr,pcd);
+
+                       fprintf(stderr, "comparing operands of these instructions, result %d\n",
+                               pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
+                               );
+                       */
+
+                 return ((havematch==1) && pCodeOpCompare(PCOP2(PCI(pcs)->pcop)->pcopR,
+                               peepBlock->target.wildpCodeOps[index]));
+               }
+
+               if(PCOP2(PCI(pcs)->pcop)->pcopR) {
+                 char *n;
+
+                       switch(PCOP2(PCI(pcs)->pcop)->pcopR->type) {
+                       case PO_GPR_TEMP:
+                       case PO_FSR0:
+                     //case PO_INDF0:
+                               n = PCOR(PCOP2(PCI(pcs)->pcop)->pcopR)->r->name;
+                               break;
+                       default:
+                               n = PCOP2(PCI(pcs)->pcop)->pcopR->name;
+                       }
+
+                       if(peepBlock->target.vars[index])
+                               return  (havematch && (strcmp(peepBlock->target.vars[index],n) == 0));
+                       else {
+                               DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
+                               peepBlock->target.vars[index] = n;
+                               return (havematch==1);          //&& 1;
+                       }
+               }
+         
+         } else if (PCOW2(PCI(pcd)->pcop) && (PCOP2(PCI(pcd)->pcop)->pcopR->type == PO_WILD) && PCOP2(PCI(pcs)->pcop)->pcopR)
+           {
+             return 0;
+           } else {
+             return havematch;
            }
+#if 0
+        else if (PCI(pcd)->pcop->type == PO_LITERAL) {
+         return (havematch &&
+               pCodeOpCompare(PCOR2(PCI(pcs)->pcop)->pcop2, PCOR2(PCI(pcd)->pcop)->pcop2));
 
-           if(peepBlock->target.vars[index])
-             return  (strcmp(peepBlock->target.vars[index],n) == 0);
-           else {
-             DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
-             peepBlock->target.vars[index] = n;
-             return 1;
-           }
-         }
+       }
+#endif
 
        } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
          return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
 
        }
+  }
+
        /* FIXME - need an else to check the case when the destination 
         * isn't a wild card */
       } else
        /* The pcd has no operand. Lines match if pcs has no operand either*/
        return (PCI(pcs)->pcop == NULL);
-    }
   }
 
   /* Compare a wild instruction to a regular one. */
@@ -2107,13 +2175,58 @@ pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
     return NULL;
 
   switch(pcop->type) { 
+  case PO_NONE:
+  case PO_STR:
+  case PO_REL_ADDR:
+       pcopnew = Safe_calloc(1, sizeof (pCodeOp));
+       memcpy(pcopnew, pcop, sizeof (pCodeOp));
+       break;
+
+  case PO_W:
+  case PO_WREG:
+  case PO_STATUS:
+  case PO_BSR:
+  case PO_FSR0:
+  case PO_INDF0:
+  case PO_INTCON:
+  case PO_GPR_REGISTER:
+  case PO_GPR_TEMP:
+  case PO_SFR_REGISTER:
+  case PO_PCL:
+  case PO_PCLATH:
+  case PO_PCLATU:
+  case PO_PRODL:
+  case PO_PRODH:
+  case PO_DIR:
+    //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
+    /* XXX: might also be pCodeOpReg2 -- that's why the two structs are identical */
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
+    memcpy (pcopnew, pcop, sizeof(pCodeOpReg));
+    break;
+    
+  case PO_LITERAL:
+    //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
+    /* XXX: might also be pCodeOpLit2, that's why the two structs are identical... */
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
+    memcpy (pcopnew, pcop, sizeof(pCodeOpLit));
+    break;
+
+  case PO_IMMEDIATE:
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
+    memcpy (pcopnew, pcop, sizeof(pCodeOpImmd));
+    break;
+    
+  case PO_GPR_BIT:
   case PO_CRY:
   case PO_BIT:
-    //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
-    pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
-    PCORB(pcopnew)->bit = PCORB(pcop)->bit;
-    PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
+    pcopnew = Safe_calloc(1, sizeof (pCodeOpRegBit));
+    memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
+    break;
 
+  case PO_LABEL:
+    //DFPRINTF((stderr,"pCodeOpCopy label\n"));
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
+    memcpy (pcopnew, pcop, sizeof (pCodeOpLabel));
     break;
 
   case PO_WILD:
@@ -2128,84 +2241,19 @@ pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
       pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
       //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
     }
-
     return pcopnew;
     break;
 
-  case PO_LABEL:
-    //DFPRINTF((stderr,"pCodeOpCopy label\n"));
-    pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
-    PCOLAB(pcopnew)->key =  PCOLAB(pcop)->key;
-    break;
-
-  case PO_IMMEDIATE:
-    pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
-    PCOI(pcopnew)->index = PCOI(pcop)->index;
-    PCOI(pcopnew)->offset = PCOI(pcop)->offset;
-    PCOI(pcopnew)->_const = PCOI(pcop)->_const;
-    break;
-
-  case PO_LITERAL:
-    //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
-    pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
-    PCOL(pcopnew)->lit = PCOL(pcop)->lit;
-    break;
-
-#if 0 // mdubuc - To add
-  case PO_REL_ADDR:
-    break;
-#endif
-
-  case PO_GPR_BIT:
-
-    pcopnew = pic16_newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
-    PCOR(pcopnew)->r = PCOR(pcop)->r;
-    PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
-    DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
+  case PO_TWO_OPS:
+    pcopnew = pic16_newpCodeOp2( pic16_pCodeOpCopy( PCOP2(pcop)->pcopL ),
+    pic16_pCodeOpCopy( PCOP2(pcop)->pcopR ) );
     return pcopnew;
-    break;
-
-  case PO_GPR_REGISTER:
-  case PO_GPR_TEMP:
-  case PO_FSR0:
-  case PO_INDF0:
-    //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
-    pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
-    PCOR(pcopnew)->r = PCOR(pcop)->r;
-    PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
-    PCOR(pcopnew)->instance = PCOR(pcop)->instance;
-    DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
-    break;
-
-  case PO_DIR:
-    //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
-    pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
-    PCOR(pcopnew)->r = PCOR(pcop)->r;
-    PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
-    PCOR(pcopnew)->instance = PCOR(pcop)->instance;
-    break;
-  case PO_STATUS:
-    DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
-  case PO_BSR:
-    DFPRINTF((stderr,"pCodeOpCopy PO_BSR\n"));
-  case PO_SFR_REGISTER:
-  case PO_STR:
-  case PO_NONE:
-  case PO_W:
-  case PO_WREG:
-  case PO_INTCON:
-  case PO_PCL:
-  case PO_PCLATH:
-  case PO_PCLATU:
-  case PO_PRODL:
-  case PO_PRODH:
-  case PO_REL_ADDR:
-    //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
-    pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
 
-  }
+  default:
+    assert ( !"unhandled pCodeOp type copied" );
+  } // switch
 
-  pcopnew->type = pcop->type;
+  /* strdup pcop->name (prevent access to shared but released memory) */
   if(pcop->name)
     pcopnew->name = Safe_strdup(pcop->name);
   else
@@ -2263,6 +2311,7 @@ int pic16_pCodePeepMatchRule(pCode *pc)
   pCodeCSource *pc_cline=NULL;
   _DLL *peeprules;
   int matched;
+  pCode *pcr;
 
   peeprules = (_DLL *)peepSnippets;
 
@@ -2327,7 +2376,7 @@ int pic16_pCodePeepMatchRule(pCode *pc)
          (pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
        matched = 0;
 
-      //fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
+//     fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
 
 
       //if(!matched) fprintf(stderr,"failed on conditions\n");
@@ -2336,7 +2385,7 @@ int pic16_pCodePeepMatchRule(pCode *pc)
     if(matched) {
 
       pCode *pcprev;
-      pCode *pcr;
+//      pCode *pcr;
 
 
       /* We matched a rule! Now we have to go through and remove the
@@ -2360,16 +2409,16 @@ int pic16_pCodePeepMatchRule(pCode *pc)
        pcin->prev = pc->prev;
 
 
-#if 0
+#if 1
       {
        /*     DEBUG    */
        /* Converted the deleted pCodes into comments */
 
-       char buf[256];
+       char buf[1024];
        pCodeCSource *pc_cline2=NULL;
 
-       buf[0] = ';';
-       buf[1] = '#';
+//     buf[0] = ';';
+       buf[0] = '#';
 
        while(pc &&  pc!=pcin) {
 
@@ -2383,7 +2432,7 @@ int pic16_pCodePeepMatchRule(pCode *pc)
            }
          }
 
-         pCode2str(&buf[2], 254, pc);
+         pic16_pCode2str(&buf[1], sizeof( buf )-1, pc);
          pic16_pCodeInsertAfter(pcprev, pic16_newpCodeCharP(buf));
          pcprev = pcprev->next;
          pc = pc->next;
@@ -2397,6 +2446,8 @@ int pic16_pCodePeepMatchRule(pCode *pc)
       if(pcin)
        pCodeDeleteChain(pc,pcin);
 
+//     fprintf(stderr, "%s:%d rule matched\n", __FILE__, __LINE__);
+
       /* Generate the replacement code */
       pc = pcprev;
       pcr = peepBlock->replace.pb->pcHead;  // This is the replacement code
@@ -2411,6 +2462,7 @@ int pic16_pCodePeepMatchRule(pCode *pc)
             * Is it wild? */
            if(PCI(pcr)->pcop->type == PO_WILD) {
              int index = PCOW(PCI(pcr)->pcop)->id;
+//             fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
              //DFPRINTF((stderr,"copying wildopcode\n"));
              if(peepBlock->target.wildpCodeOps[index])
                pcop = pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
@@ -2419,6 +2471,26 @@ int pic16_pCodePeepMatchRule(pCode *pc)
            } else
              pcop = pic16_pCodeOpCopy(PCI(pcr)->pcop);
          }
+
+         if(PCI(pcr)->is2MemOp && PCOP2(PCI(pcr)->pcop)->pcopR) {
+           /* The replacing instruction has also a second operand.
+            * Is it wild? */
+//             fprintf(stderr, "%s:%d pcop2= %p\n", __FILE__, __LINE__, PCOR2(PCI(pcr)->pcop)->pcop2);
+           if(PCOP2(PCI(pcr)->pcop)->pcopR->type == PO_WILD) {
+             int index = PCOW2(PCI(pcr)->pcop)->id;
+//             fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
+             //DFPRINTF((stderr,"copying wildopcode\n"));
+             if(peepBlock->target.wildpCodeOps[index])
+               pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
+                       pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]), 0);
+             else
+               DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
+           } else
+             pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
+               pic16_pCodeOpCopy(PCOP2(PCI(pcr)->pcop)->pcopR), 0);
+             
+         }
+         
          //DFPRINTF((stderr,"inserting pCode\n"));
          pic16_pCodeInsertAfter(pc, pic16_newpCode(PCI(pcr)->op,pcop));
        } else if (pcr->type == PC_WILD) {