* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[fw/sdcc] / src / pic16 / pcodepeep.c
index a6786be4c1073785ffa9e10940256f555d79118c..ec373e3358477a89c119be5c21a0e67899355907 100644 (file)
@@ -1,6 +1,7 @@
 /*-------------------------------------------------------------------------
 
-   pcodepeep.c - post code generation
+  pcodepeep.c - post code generation
+
    Written By -  Scott Dattalo scott@dattalo.com
    Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
 
 
 #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[];
-
+static int parsing_peeps=1;
 
 #define IS_PCCOMMENT(x) ( x && (x->type==PC_COMMENT))
 
@@ -202,7 +201,10 @@ typedef enum {
   ALT_MNEM1B,
   ALT_MNEM2,
   ALT_MNEM2A,
-  ALT_MNEM3
+  ALT_MNEM2B,
+  ALT_MNEM3,
+  ALT_MNEM4,
+  ALT_MNEM4a
 } altPatterns;
 
 static char alt_comment[]   = { PCP_COMMENT, 0};
@@ -214,7 +216,10 @@ 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_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
 
 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
@@ -225,12 +230,19 @@ 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_mnem3(void *pp,pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb);
+static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb);
 
+/* NOTE: Order is important in the following table */
 static pcPattern altArr[] = {
   {ALT_LABEL,        alt_label,  cvt_altpat_label},
   {ALT_COMMENT,      alt_comment,cvt_altpat_comment},
+  {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_MNEM2A,       alt_mnem2a, cvt_altpat_mnem2a},
   {ALT_MNEM2,        alt_mnem2,  cvt_altpat_mnem2},
   {ALT_MNEM1B,       alt_mnem1b, cvt_altpat_mnem1b},
@@ -258,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) {
@@ -289,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;
@@ -433,8 +445,10 @@ static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb)
 
   if(pic16Mnemonics[opcode]->isBitInst)
     pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
-  else
-    pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
+  else {
+//     fprintf(stderr, "%s:%d tok.s= %s\n", __FILE__, __LINE__, p[1].pct[0].tok.s);
+    pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_STR);   //GPR_REGISTER);
+  }
 
 
   pci = PCI(pic16_newpCode(opcode, pcosubtype));
@@ -493,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);
 
@@ -566,7 +580,6 @@ static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
          p[3].pct[0].tok.s,
          dest));
 
-
   opcode = pic16_getpCode(p->pct[0].tok.s,dest);
   if(opcode < 0) {
     fprintf(stderr, "Bad mnemonic\n");
@@ -580,8 +593,15 @@ static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
       return NULL;
     }
       
+  } else
+  if(pic16Mnemonics[opcode]->is2MemOp) {
+       /* 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(p[1].pct[0].tok.s,PO_GPR_REGISTER);
 
 
   pci = PCI(pic16_newpCode(opcode,pcosubtype));
@@ -611,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__);
@@ -626,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) {
@@ -633,14 +661,94 @@ 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);
+    pcosubtype2 = NULL;
+  } else {
+#if 0
+  if(pic16Mnemonics[opcode]->is2MemOp) {
+       /* support for movff instruction */
+       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; }
+
+
+  if(!pcosubtype2)
+       pci = PCI(pic16_newpCode(opcode,
+                    pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
   else
-    pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
+       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)
+  //  sMaxWildVar = p[1].pct[1].tok.n;
+
+  if(p[1].pct[1].tok.n > pcwb->nvars)
+    pcwb->nvars = p[1].pct[1].tok.n;
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+  return pci;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem2b - convert assembly line type to a pCode        */
+/*                    instruction with 2 wild operands             */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - wild var                                               */
+/*  pp[2] - comma                                                  */
+/*  pp[3] - wild var                                               */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem2b(void *pp,pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+  int opcode;
+  int dest;
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype, *pcosubtype2;
+
+  if(!pcwb) {
+    fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
+    return NULL;
+  }
+
+  dest = cvt_extract_destination(&p[3]);
+
+  DFPRINTF((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));
+
+#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) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+  if(pic16Mnemonics[opcode]->is2MemOp) {
+       /* support for movff instruction */
+       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)
@@ -696,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);
@@ -715,6 +823,110 @@ static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
 
 }
 
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem4 -  convert assembly line type to a pCode        */
+/*                    This rule is for lfsr instruction            */
+/*                                                                 */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - number                                                 */
+/*  pp[2] - comma                                                  */
+/*  pp[3] - source                                                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+  int opcode;
+  int dest;  // or could be bit position in the register
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype=NULL;
+
+  dest = cvt_extract_destination(&p[3]);
+
+  DFPRINTF((stderr,"altpat_mnem4 %s fsr %d source %s\n",
+         p->pct[0].tok.s,
+         p[1].pct[0].tok.n,
+         p[3].pct[0].tok.s));
+
+  opcode = pic16_getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+  DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
+
+  if(pic16Mnemonics[opcode]->is2LitOp) {
+    pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOp(p[3].pct[0].tok.s, PO_STR));
+  }
+
+  if(pcosubtype == NULL) {
+    fprintf(stderr, "Bad operand\n");
+    return NULL;
+  }
+
+  pci = PCI(pic16_newpCode(opcode, pcosubtype));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+  return pci;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem4a -  convert assembly line type to a pCode       */
+/*                    This rule is for lfsr instruction            */
+/*                                                                 */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - number                                                 */
+/*  pp[2] - comma                                                  */
+/*  pp[3] - value                                                  */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb)
+{
+  parsedPattern *p = pp;
+  int opcode;
+  int dest;  // or could be bit position in the register
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype=NULL;
+
+  dest = cvt_extract_destination(&p[3]);
+
+  DFPRINTF((stderr,"altpat_mnem4a %s fsr %d value 0x%02x\n",
+         p->pct[0].tok.s,
+         p[1].pct[0].tok.n,
+         p[3].pct[0].tok.n));
+
+  opcode = pic16_getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+  DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
+
+  if(pic16Mnemonics[opcode]->is2LitOp) {
+    pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOpLit(p[3].pct[0].tok.n));
+  }
+
+  if(pcosubtype == NULL) {
+    fprintf(stderr, "Bad operand\n");
+    return NULL;
+  }
+
+  pci = PCI(pic16_newpCode(opcode, pcosubtype));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+  return pci;
+
+}
+
 /*-----------------------------------------------------------------*/
 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
 /*                    by SDCCpeeph.c into a string of tokens.      */
@@ -741,18 +953,18 @@ static void tokenizeLineNode(char *ln)
   if(!ln || !*ln)
     return;
 
+//     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);
@@ -784,12 +996,12 @@ static void tokenizeLineNode(char *ln)
       break;
 
 
-    default:
-      if(isalpha(*ln) || (*ln == '_') ) {
+    default:                           // hack to allow : goto $
+      if(isalpha((unsigned char)*ln) || (*ln == '_')  || (!parsing_peeps && (*ln == '$'))) {
        char buffer[50];
        int i=0;
 
-       while( (isalpha(*ln)  ||  isdigit(*ln) || (*ln == '_')) && i<49)
+       while( (isalpha((unsigned char)*ln) || isdigit((unsigned char)*ln) || (*ln == '_') || (*ln == '$')) && i<49)
          buffer[i++] = *ln++;
 
        ln--;
@@ -799,10 +1011,12 @@ static void tokenizeLineNode(char *ln)
        tokArr[tokIdx++].tt = PCT_STRING;
 
       } else {
-       fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
-       fprintf(stderr, "Line: %s\n",lnstart);
-       fprintf(stderr, "Token: '%c'\n",*ln);
-       exit(1);
+       if(parsing_peeps) {
+               fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
+               fprintf(stderr, "Line: %s\n",lnstart);
+               fprintf(stderr, "Token: '%c'\n",*ln);
+               exit(1);
+       }
       }
     }
 
@@ -914,11 +1128,11 @@ static int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
   while(i < max_tokens) {
 
     if(*pct == 0) {
-      //DFPRINTF((stderr,"matched\n"));
+       DFPRINTF((stderr,"matched\n"));
       return i;
     }
 
-    //dump1Token(*pat); DFPRINTF((stderr,"\n"));
+//     dump1Token(*pat); DFPRINTF((stderr,"\n"));
 
     if( !pat || !pat->pcp )
       return 0;
@@ -926,7 +1140,7 @@ static int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
     if (pat->pcp->pt != *pct)  
       return 0;
 
-    //DFPRINTF((stderr," pct=%d\n",*pct));
+       DFPRINTF((stderr," pct=%d\n",*pct));
     pct++;
     pat++;
     i++;
@@ -1121,7 +1335,7 @@ static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
          parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
          lparsedPatIdx++;
 
-         //dump1Token(tokArr[ltokIdx].tt);
+//             dump1Token(tokArr[ltokIdx].tt);
 
          if(advTokIdx(&ltokIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
            DFPRINTF((stderr," reached end \n"));
@@ -1215,9 +1429,10 @@ static void  peepRuleBlock2pCodeBlock(  lineNode *ln, pCodeWildBlock *pcwb)
 }
 
 /*-----------------------------------------------------------------*/
-/*                                                                 */
+/* pic16_AssembleLine - parse line and return the pCode equivalent */
+/*                      peeps=1 if parsing peep rules, 0 otherwise */
 /*-----------------------------------------------------------------*/
-pCode *pic16_AssembleLine(char *line)
+pCode *pic16_AssembleLine(char *line, int peeps)
 {
   pCode *pc=NULL;
 
@@ -1226,11 +1441,18 @@ pCode *pic16_AssembleLine(char *line)
     return NULL;
   }
 
+  parsing_peeps = peeps;
+
   tokenizeLineNode(line);
     
   if(parseTokens(NULL,&pc))
     fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
+  else {
+       DFPRINTF((stderr, "pc= %p\n", pc));
+//     if(pc)pc->print(stderr, pc);
+  }
 
+  parsing_peeps = 1;
   return pc;
 
 }
@@ -1511,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 1
-  fprintf(stderr," Comparing operands %s",
+#if 0
+  fprintf(stderr,"%s:%d Comparing operands %s", __FILE__, __LINE__, 
          pic16_get_op( pcops,NULL,0));
 
   fprintf(stderr," to %s\n",
@@ -1537,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;
@@ -1649,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 */
 
@@ -1678,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
@@ -1689,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;
 
@@ -1704,17 +1929,18 @@ 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((havematch==-1) && PCI(pcs)->pcop) {
            char *n;
 
            switch(PCI(pcs)->pcop->type) {
            case PO_GPR_TEMP:
            case PO_FSR0:
              //case PO_INDF0:
-             n = PCOR(PCI(pcs)->pcop)->r->name;
+               n = PCOR(PCI(pcs)->pcop)->r->name;
 
              break;
            default:
@@ -1726,20 +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;
            }
          }
 
+         /* 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
+
+               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));
+
+       }
+#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. */
@@ -1876,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:
@@ -1897,81 +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_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
@@ -2029,6 +2311,7 @@ int pic16_pCodePeepMatchRule(pCode *pc)
   pCodeCSource *pc_cline=NULL;
   _DLL *peeprules;
   int matched;
+  pCode *pcr;
 
   peeprules = (_DLL *)peepSnippets;
 
@@ -2093,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");
@@ -2102,14 +2385,14 @@ 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
         inefficient code with the optimized version */
 #ifdef PCODE_DEBUG
       DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
-      printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
+//      printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
       DFPRINTF((stderr,"first thing matched\n"));
       pc->print(stderr,pc);
       if(pcin) {
@@ -2126,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) {
 
@@ -2149,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;
@@ -2163,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
@@ -2177,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]);
@@ -2185,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) {