Added more PIC regression testing.
[fw/sdcc] / src / pic / pcodepeep.c
index 40eb56ed56e700cb355e2fd06498966416d3aebc..c97802df724711eeabd11e5b5112e02a9453533f 100644 (file)
 #include "pcode.h"
 #include "ralloc.h"
 
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+pCodeOp *popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
+
 
 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype);
 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
 pCode * findNextInstruction(pCode *pc);
-char *Safe_strdup(char *str);
-int getpCode(char *mnem);
+int getpCode(char *mnem,int dest);
+void pBlockMergeLabels(pBlock *pb);
+char *pCode2str(char *str, int size, pCode *pc);
+
+extern pCodeInstruction *pic14Mnemonics[];
+
 
 /****************************************************************/
 /*
@@ -88,6 +100,16 @@ static pCodePeep          *curPeep=NULL;
 static pBlock             *curBlock=NULL;
 
 
+/****************************************************************/
+/*                                                              */
+/* max wild cards in a peep rule                                */
+/*                                                              */
+/****************************************************************/
+
+static int                sMaxWildVar   = 0;
+static int                sMaxWildMnem  = 0;
+
+
 typedef struct pCodeToken 
 {
   int tt;  // token type;
@@ -104,6 +126,7 @@ unsigned   tokIdx=0;
 
 
 typedef enum  {
+  PCT_NULL=0,
   PCT_SPACE=1,
   PCT_PERCENT,
   PCT_COLON,
@@ -131,7 +154,8 @@ typedef enum {
   PCP_STR,
   PCP_WILDVAR,
   PCP_WILDSTR,
-  PCP_COMMA
+  PCP_COMMA,
+  PCP_COMMENT
 } pCodePatterns;
 
 static char pcpat_label[]      = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
@@ -140,6 +164,7 @@ static char pcpat_string[]     = {PCT_STRING, 0};
 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
 static char pcpat_wildVar[]    = {PCT_PERCENT, PCT_NUMBER, 0};
 static char pcpat_comma[]      = {PCT_COMMA, 0};
+static char pcpat_comment[]    = {PCT_COMMENT, 0};
 
 
 typedef struct pcPattern {
@@ -154,6 +179,7 @@ pcPattern pcpArr[] = {
   {PCP_STR,       pcpat_string,     NULL},
   {PCP_WILDVAR,   pcpat_wildVar,    NULL},
   {PCP_COMMA,     pcpat_comma,      NULL},
+  {PCP_COMMENT,   pcpat_comment,    NULL},
   {PCP_NUMBER,    pcpat_number,     NULL}
 };
 
@@ -162,7 +188,9 @@ pcPattern pcpArr[] = {
 // Assembly Line Token
 typedef enum {
   ALT_LABEL=1,
+  ALT_COMMENT,
   ALT_MNEM0,
+  ALT_MNEM0A,
   ALT_MNEM1,
   ALT_MNEM1A,
   ALT_MNEM1B,
@@ -170,8 +198,10 @@ typedef enum {
   ALT_MNEM2A
 } altPatterns;
 
+static char alt_comment[]   = { PCP_COMMENT, 0};
 static char alt_label[]     = { PCP_LABEL, 0};
 static char alt_mnem0[]     = { PCP_STR, 0};
+static char alt_mnem0a[]    = { PCP_WILDVAR, 0};
 static char alt_mnem1[]     = { PCP_STR, PCP_STR, 0};
 static char alt_mnem1a[]    = { PCP_STR, PCP_WILDVAR, 0};
 static char alt_mnem1b[]    = { PCP_STR, PCP_NUMBER, 0};
@@ -179,7 +209,9 @@ 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 void * cvt_altpat_label(void *pp);
+static void * cvt_altpat_comment(void *pp);
 static void * cvt_altpat_mnem0(void *pp);
+static void * cvt_altpat_mnem0a(void *pp);
 static void * cvt_altpat_mnem1(void *pp);
 static void * cvt_altpat_mnem1a(void *pp);
 static void * cvt_altpat_mnem1b(void *pp);
@@ -188,17 +220,79 @@ static void * cvt_altpat_mnem2a(void *pp);
 
 pcPattern altArr[] = {
   {ALT_LABEL,        alt_label,  cvt_altpat_label},
+  {ALT_COMMENT,      alt_comment,cvt_altpat_comment},
   {ALT_MNEM2A,       alt_mnem2a, cvt_altpat_mnem2a},
   {ALT_MNEM2,        alt_mnem2,  cvt_altpat_mnem2},
   {ALT_MNEM1B,       alt_mnem1b, cvt_altpat_mnem1b},
   {ALT_MNEM1A,       alt_mnem1a, cvt_altpat_mnem1a},
   {ALT_MNEM1,        alt_mnem1,  cvt_altpat_mnem1},
+  {ALT_MNEM0A,       alt_mnem0a, cvt_altpat_mnem0a},
   {ALT_MNEM0,        alt_mnem0,  cvt_altpat_mnem0},
 
 };
 
 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
 
+// forward declarations
+static void * DLL_append(_DLL *list, _DLL *next);
+
+/*-----------------------------------------------------------------*/
+/* cvt_extract_destination - helper function extracts the register */
+/*                           destination from a parsedPattern.     */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static int cvt_extract_destination(parsedPattern *pp)
+{
+
+  if(pp->pct[0].tt == PCT_STRING) {
+
+    // just check first letter for now
+
+    if(toupper(*pp->pct[0].tok.s) == 'F')
+      return 1;
+
+  } else if (pp->pct[0].tt == PCT_NUMBER) {
+
+    if(pp->pct[0].tok.n)
+      return 1;
+  }
+
+  return 0;
+
+}
+
+/*-----------------------------------------------------------------*/
+/*  pCodeOp *cvt_extract_status(char *reg, char *bit)              */
+/*     if *reg is the "status" register and *bit is one of the     */
+/*     status bits, then this function will create a new pCode op  */
+/*     containing the status register.                             */
+/*-----------------------------------------------------------------*/
+
+static pCodeOp *cvt_extract_status(char *reg, char *bit)
+{
+  int len;
+
+  if(STRCASECMP(reg, pc_status.pcop.name))
+    return NULL;
+
+  len = strlen(bit);
+
+  if(len == 1) {
+    // check C,Z
+    if(toupper(*bit) == 'C')
+      return PCOP(popCopyGPR2Bit(&pc_status,PIC_C_BIT));
+    if(toupper(*bit) == 'Z')
+      return PCOP(popCopyGPR2Bit(&pc_status,PIC_Z_BIT));
+  }
+
+  // Check DC
+  if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
+    return PCOP(popCopyGPR2Bit(&pc_status,PIC_DC_BIT));
+
+  return NULL;
+
+}
+
 /*-----------------------------------------------------------------*/
 /* cvt_altpat_label - convert assembly line type to a pCode label  */
 /* INPUT: pointer to the parsedPattern                             */
@@ -214,7 +308,24 @@ static void * cvt_altpat_label(void *pp)
   parsedPattern *p = pp;
 
   fprintf(stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n);
-  return newpCodeOpLabel(-p->pct[1].tok.n);
+  return newpCodeLabel(-p->pct[1].tok.n);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_comment - convert assembly line type to a comment    */
+/* INPUT: pointer to the parsedPattern                             */
+/*                                                                 */
+/*  pp[0] - comment                                                */
+/*                                                                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_comment(void *pp)
+{
+  parsedPattern *p = pp;
+
+  fprintf(stderr,"altpat_comment  = %s\n",p->pct[0].tok.s);
+  return newpCodeCharP(p->pct[0].tok.s);
 
 }
 
@@ -222,16 +333,88 @@ static void * cvt_altpat_label(void *pp)
 /*-----------------------------------------------------------------*/
 static void * cvt_altpat_mnem0(void *pp)
 {
-  fprintf(stderr,"altpat_mnem0\n");
-  return NULL;
+  parsedPattern *p = pp;
+  int opcode;
+
+  pCodeInstruction *pci=NULL;
+
+  fprintf(stderr,"altpat_mnem0 %s\n",  p->pct[0].tok.s);
+
+  opcode = getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+  pci = PCI(newpCode(opcode, NULL));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+
+  return pci;
 }
 
 /*-----------------------------------------------------------------*/
+/* cvt_altpat_mem0a - convert assembly line type to a wild pCode   */
+/*                    instruction                                  */
+/*                                                                 */
+/*  pp[0] - wild var                                               */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem0a(void *pp)
+{
+  parsedPattern *p = pp;
+
+  fprintf(stderr,"altpat_mnem0a wild mnem # %d\n",  p[0].pct[1].tok.n);
+
+  /* Save the index of the maximum wildcard mnemonic */
+
+  if(p[0].pct[1].tok.n > sMaxWildVar)
+    sMaxWildMnem = p[0].pct[1].tok.n;
+
+  return newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem1 - convert assembly line type to a pCode         */
+/*                   instruction with 1 operand.                   */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - Operand                                                */
+/*                                                                 */
 /*-----------------------------------------------------------------*/
 static void * cvt_altpat_mnem1(void *pp)
 {
-  fprintf(stderr,"altpat_mnem1\n");
-  return NULL;
+
+  parsedPattern *p = pp;
+  int opcode;
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype;
+
+  fprintf(stderr,"altpat_mnem1 %s var %s\n",  p->pct[0].tok.s,p[1].pct[0].tok.s);
+
+  opcode = getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+  if(pic14Mnemonics[opcode]->bit_inst)
+    pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
+  else
+    pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
+
+
+  pci = PCI(newpCode(opcode, pcosubtype));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+
+  return pci;
 }
 
 /*-----------------------------------------------------------------*/
@@ -245,22 +428,35 @@ static void * cvt_altpat_mnem1(void *pp)
 static void * cvt_altpat_mnem1a(void *pp)
 {
   parsedPattern *p = pp;
+  int opcode;
 
   pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype;
+
+  fprintf(stderr,"altpat_mnem1a %s var %d\n",  p->pct[0].tok.s,p[1].pct[1].tok.n);
+
+  opcode = getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
 
-  //    pCodeOp *pcw;
+  if(pic14Mnemonics[opcode]->bit_inst)
+    pcosubtype = newpCodeOpBit(NULL,-1,0);
+  else
+    pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
 
-  //  pcw = newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER));
 
-  fprintf(stderr,"altpat_mnem1a %s var %d\n",  p->pct[0].tok.s,p[1].pct[1].tok.n);
+  pci = PCI(newpCode(opcode,
+                    newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
 
-/*
-  pci = PCI(newpCode(getpCode(p->pct[0].tok.s),
-                    newpCodeOpWild(p[1].pct[1].tok.n, curPeep, NULL)));
+  /* Save the index of the maximum wildcard variable */
+  if(p[1].pct[1].tok.n > sMaxWildVar)
+    sMaxWildVar = p[1].pct[1].tok.n;
 
   if(!pci)
     fprintf(stderr,"couldn't find mnemonic\n");
-*/
+
 
   return pci;
 }
@@ -269,72 +465,151 @@ static void * cvt_altpat_mnem1a(void *pp)
 /*-----------------------------------------------------------------*/
 static void * cvt_altpat_mnem1b(void *pp)
 {
-  fprintf(stderr,"altpat_mnem1b\n");
-  return NULL;
+  parsedPattern *p = pp;
+  int opcode;
+
+  pCodeInstruction *pci=NULL;
+
+  fprintf(stderr,"altpat_mnem1b %s var %d\n",  p->pct[0].tok.s,p[1].pct[0].tok.n);
+
+  opcode = getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+  pci = PCI(newpCode(opcode, newpCodeOpLit(p[1].pct[0].tok.n) ));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+
+  return pci;
 }
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 static void * cvt_altpat_mnem2(void *pp)
 {
-  fprintf(stderr,"altpat_mnem2\n");
-  return NULL;
+  parsedPattern *p = pp;
+  int opcode;
+  int dest;
+
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype;
+
+  dest = cvt_extract_destination(&p[3]);
+
+  fprintf(stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
+         p->pct[0].tok.s,
+         p[1].pct[0].tok.s,
+         p[3].pct[0].tok.s,
+         dest);
+
+
+  opcode = getpCode(p->pct[0].tok.s,dest);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+  if(pic14Mnemonics[opcode]->bit_inst) {
+    pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
+    if(pcosubtype == NULL) {
+      fprintf(stderr, "bad operand?\n");
+      return NULL;
+    }
+      
+  } else
+    pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
+
+
+  pci = PCI(newpCode(opcode,pcosubtype));
+
+  if(!pci)
+    fprintf(stderr,"couldn't find mnemonic\n");
+
+  return pci;
+
 }
 
 /*-----------------------------------------------------------------*/
+/* cvt_altpat_mem2a - convert assembly line type to a pCode        */
+/*                    instruction with 1 wild operand and a        */
+/*                    destination operand (e.g. w or f)            */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - wild var                                               */
+/*  pp[2] - comma                                                  */
+/*  pp[3] - destination                                            */
+/*                                                                 */
 /*-----------------------------------------------------------------*/
 static void * cvt_altpat_mnem2a(void *pp)
 {
-  fprintf(stderr,"altpat_mnem2a\n");
-  return NULL;
-}
+  parsedPattern *p = pp;
+  int opcode;
+  int dest;
 
+  pCodeInstruction *pci=NULL;
+  pCodeOp *pcosubtype;
 
+  dest = cvt_extract_destination(&p[3]);
 
+  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);
 
-#if 0
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
-static pCode * cvt_pcpat_wildMnem(parsedPattern *pp)
-{
-  fprintf(stderr,"pcpat_wildMnem\n");
-  return NULL;
-}
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
-static pCode * cvt_pcpat_Mnem(parsedPattern *pp)
-{
-  fprintf(stderr,"pcpat_Mnem\n");
-  return NULL;
-}
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
-static pCode * cvt_pcpat_wildVar(parsedPattern *pp)
-{
-  fprintf(stderr,"pcpat_wildVar\n");
-  return NULL;
-}
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
-static pCode * cvt_pcpat_var(parsedPattern *pp)
-{
-  fprintf(stderr,"pcpat_var\n");
-  return NULL;
-}
-#endif
+
+  opcode = getpCode(p->pct[0].tok.s,dest);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+  if(pic14Mnemonics[opcode]->bit_inst)
+    pcosubtype = newpCodeOp(NULL,PO_BIT);
+  else
+    pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
 
 
+  pci = PCI(newpCode(opcode,
+                    newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
 
+  /* Save the index of the maximum wildcard variable */
+  if(p[1].pct[1].tok.n > sMaxWildVar)
+    sMaxWildVar = p[1].pct[1].tok.n;
 
+  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.      */
+/*                                                                 */
+/*                                                                 */
+/* The tokenizer is of the classic type. When an item is encounterd*/
+/* it is converted into a token. The token is a structure that     */
+/* encodes the item's type and it's value (when appropriate).      */
+/*                                                                 */
+/* Accepted token types:                                           */
+/*    SPACE  NUMBER STRING  %  : ,  ;                              */
+/*                                                                 */
+/*                                                                 */
+/*                                                                 */
 /*-----------------------------------------------------------------*/
 
 
-static void parseLineNode(char *ln)
+static void tokenizeLineNode(char *ln)
 {
 
-  tokIdx = 0;
+  tokIdx = 0;               // Starting off at the beginning
+  tokArr[0].tt = PCT_NULL;  // and assume invalid character for first token.
 
   if(!ln || !*ln)
     return;
@@ -342,6 +617,7 @@ static void parseLineNode(char *ln)
   while(*ln) {
 
     if(isspace(*ln)) {
+      // add a SPACE token and eat the extra spaces.
       tokArr[tokIdx++].tt = PCT_SPACE;
       while (isspace (*ln))
        ln++;
@@ -351,7 +627,7 @@ static void parseLineNode(char *ln)
     if(isdigit(*ln)) {
 
       tokArr[tokIdx].tt = PCT_NUMBER;
-      tokArr[tokIdx++].tok.n = strtol(ln, &ln, 10);
+      tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
 
       continue;
 
@@ -367,6 +643,7 @@ static void parseLineNode(char *ln)
     case ';':
       tokArr[tokIdx].tok.s = Safe_strdup(ln);
       tokArr[tokIdx++].tt = PCT_COMMENT;
+      tokArr[tokIdx].tt = PCT_NULL;
       return;
     case ',':
       tokArr[tokIdx++].tt = PCT_COMMA;
@@ -385,13 +662,19 @@ static void parseLineNode(char *ln)
        buffer[i] = 0;
 
        tokArr[tokIdx].tok.s = Safe_strdup(buffer);
-       //fprintf(stderr," string %s",tokArr[tokIdx].tok.s);
-
        tokArr[tokIdx++].tt = PCT_STRING;
 
       }
     }
+
+    /* Advance to next character in input string .
+     * Note, if none of the tests passed above, then 
+     * we effectively ignore the `bad' character.
+     * Since the line has already been parsed by SDCCpeeph,
+     * chance are that there are no invalid characters... */
+
     ln++;
+
   }
 
   tokArr[tokIdx].tt = 0;
@@ -419,10 +702,12 @@ void dump1Token(pCodeTokens tt)
     fputc(':',stderr);
     break;
   case PCT_COMMA:
-    fprintf(stderr, " com ");
-    fputc(',',stderr);
+    fprintf(stderr, " comma , ");
     break;
   case PCT_COMMENT:
+    fprintf(stderr, " comment ");
+    //fprintf(stderr,"%s",tokArr[i].tok.s);
+    break;
   case PCT_STRING:
     fprintf(stderr, " str ");
     //fprintf(stderr,"%s",tokArr[i].tok.s);
@@ -430,7 +715,9 @@ void dump1Token(pCodeTokens tt)
   case PCT_NUMBER:
     fprintf(stderr, " num ");
     //fprintf(stderr,"%d",tokArr[i].tok.n);
-
+    break;
+  case PCT_NULL:
+    fprintf(stderr, " null ");
 
   }
 }
@@ -510,7 +797,7 @@ int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
 int advTokIdx(int *v, int amt)
 {
 
-  if(*v + amt > tokIdx)
+  if((unsigned) (*v + amt) > tokIdx)
     return 1;
 
   *v += amt;
@@ -519,11 +806,26 @@ int advTokIdx(int *v, int amt)
 }
 
 /*-----------------------------------------------------------------*/
+/* parseTokens - convert the tokens corresponding to a single line */
+/*               of a peep hole assembly into a pCode object.      */
+/*                                                                 */
+/*                                                                 */
+/*                                                                 */
+/*                                                                 */
+/* This is a simple parser that looks for strings of the type      */
+/* allowed in the peep hole definition file. Essentially the format*/
+/* is the same as a line of assembly:                              */
+/*                                                                 */
+/*  label:    mnemonic   op1, op2, op3    ; comment                */
+/*                                                                 */
+/* Some of these items aren't present. It's the job of the parser  */
+/* to determine which are and convert those into the appropriate   */
+/* pcode.                                                          */
 /*-----------------------------------------------------------------*/
 
-void dumpTokens(void)
+void parseTokens(void)
 {
-  int i;
+  unsigned i;
   pCode *pc;
 
   if(!tokIdx)
@@ -532,7 +834,6 @@ void dumpTokens(void)
   for(i=0; i<=tokIdx; i++)
     dump1Token(tokArr[i].tt);
 
-
   fputc('\n',stderr);
 
   {
@@ -540,7 +841,8 @@ void dumpTokens(void)
     int lpcpIdx;
     int ltokIdx =0;
     int matching = 0;
-    int j,k;
+    int j=0;
+    int k=0;
 
     char * cPmnem  = NULL;     // Pointer to non-wild mnemonic (if any)
     char * cP1stop = NULL;
@@ -566,16 +868,15 @@ void dumpTokens(void)
 
       lpcpIdx=0;
       matching = 0;
-      //fprintf(stderr,"ltokIdx = %d\n",ltokIdx);
 
-      if(  ((tokArr[ltokIdx].tt == PCT_SPACE) )//|| (tokArr[ltokIdx].tt == PCT_COMMA))
+      if(  ((tokArr[ltokIdx].tt == PCT_SPACE) )
           && (advTokIdx(&ltokIdx, 1)) ) // eat space
        break;
 
       do {
        j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
        if( j ) {
-         //fprintf(stderr,"found token pattern match\n");
+
          switch(pcpArr[lpcpIdx].pt) {
          case  PCP_LABEL:
            if(state == PS_START){
@@ -690,14 +991,16 @@ void dumpTokens(void)
     j=k=0;
     do {
       int c;
-      //fprintf(stderr,"comparing alt pattern %d (first token %d)\n",k,altArr[k].tokens[0]);
+
       if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
-       //fprintf(stderr," found a valid assembly line!!!\n");
+
        if( altArr[k].f) {
          pc = altArr[k].f(&parsedPatArr[j]);
          if(pc && pc->print)
            pc->print(stderr,pc);
-         if(pc && pc->destruct) pc->destruct(pc);
+         //if(pc && pc->destruct) pc->destruct(pc); dumps core?
+         if(curBlock && pc)
+           addpCode2pBlock(curBlock, pc);
        }
        j += c;
       }
@@ -705,7 +1008,7 @@ void dumpTokens(void)
     }
     while(j<=lparsedPatIdx && k<ALTPATTERNS);
 
-
+/*
     fprintf(stderr,"\nConverting parsed line to pCode:\n\n");
 
     j = 0;
@@ -716,7 +1019,7 @@ void dumpTokens(void)
       j++;
     }
     while(j<lparsedPatIdx);
-
+*/
     fprintf(stderr,"\n");
 
   }
@@ -724,6 +1027,44 @@ void dumpTokens(void)
 
 }
 
+/*-----------------------------------------------------------------*/
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+void  peepRuleBlock2pCodeBlock(  lineNode *ln)
+{
+
+  if(!ln)
+    return;
+
+  for( ; ln; ln = ln->next) {
+
+    fprintf(stderr,"%s\n",ln->line);
+
+    tokenizeLineNode(ln->line);
+    parseTokens();
+
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* peepRuleCondition                                               */
+/*-----------------------------------------------------------------*/
+static void   peepRuleCondition(char *cond)
+{
+  if(!cond)
+    return;
+
+  fprintf(stderr,"\nCondition:  %s\n",cond);
+
+  /* brute force compares for now */
+
+  if(STRCASECMP(cond, "NZ") == 0) {
+    fprintf(stderr,"found NZ\n");
+    curPeep->postFalseCond = PCC_Z;
+
+  }
+
+}
 /*-----------------------------------------------------------------*/
 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
 /*                   pCode.                                        */
@@ -739,32 +1080,77 @@ void dumpTokens(void)
 void  peepRules2pCode(peepRule *rules)
 {
   peepRule *pr;
-  lineNode *ln;
 
   pCodePeepSnippets *pcps;
 
+  /* The rules are in a linked-list. Each rule has two portions */
+  /* There's the `target' and there's the `replace'. The target */
+  /* is compared against the SDCC generated code and if it      */
+  /* matches, it gets replaced by the `replace' block of code.  */
+  /*                                                            */
+  /* Here we loop through each rule and convert the target's and*/
+  /* replace's into pCode target and replace blocks             */
+
   for (pr = rules; pr; pr = pr->next) {
+
     fprintf(stderr,"\nRule:\n\n");
 
     pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
     curPeep = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
-    //peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
 
-    for(ln = pr->match; ln; ln = ln->next) {
-      fprintf(stderr,"%s\n",ln->line);
+    curPeep->vars = NULL; 
+    curPeep->wildpCodes = NULL; curPeep->wildpCodeOps = NULL;
+    curPeep->postFalseCond = PCC_NONE;
+    curPeep->postTrueCond  = PCC_NONE;
 
-      parseLineNode(ln->line);
-      dumpTokens();
+    peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
 
-    }
+    curPeep->target = curBlock = newpCodeChain(NULL, 'W', NULL);
+    sMaxWildVar  = 0;
+    sMaxWildMnem = 0;
+
+    /* Convert the target block */
+    peepRuleBlock2pCodeBlock(pr->match);
+
+    fprintf(stderr,"finished target, here it is in pcode form:\n");
+    printpBlock(stderr, curBlock);
+
+    fprintf(stderr,"target with labels merged:\n");
+    pBlockMergeLabels(curBlock);
+    printpBlock(stderr, curBlock);
 
     fprintf(stderr,"\nReplaced by:\n");
-    for(ln = pr->replace; ln; ln = ln->next)
-      fprintf(stderr,"%s\n",ln->line);
 
-    if(pr->cond)
-      fprintf(stderr,"\nCondition:  %s\n",pr->cond);
 
+    curPeep->replace = curBlock = newpCodeChain(NULL, 'W', NULL);
+
+    /* Convert the replace block */
+    peepRuleBlock2pCodeBlock(pr->replace);
+
+    fprintf(stderr,"finished replace block, here it is in pcode form:\n");
+    printpBlock(stderr, curBlock);
+
+    fprintf(stderr,"replace with labels merged:\n");
+    pBlockMergeLabels(curBlock);
+    printpBlock(stderr, curBlock);
+
+    peepRuleCondition(pr->cond);
+
+    /* The rule has been converted to pCode. Now allocate
+     * space for the wildcards */
+
+     ++sMaxWildVar;
+    curPeep->nvars = sMaxWildVar;
+    curPeep->vars = Safe_calloc(sMaxWildVar, sizeof(char *));
+
+    curPeep->nops = sMaxWildVar;
+    curPeep->wildpCodeOps = Safe_calloc(sMaxWildVar, sizeof(pCodeOp *));
+
+    curPeep->nwildpCodes = ++sMaxWildMnem;
+    curPeep->wildpCodes = Safe_calloc(sMaxWildMnem, sizeof(char *));
+
+
+    //return; // debug ... don't want to go through all the rules yet
   }
 
 }
@@ -899,6 +1285,7 @@ pBlock *pBlockAppend(pBlock *pb1, pBlock *pb2)
 
 void pCodePeepInit(void)
 {
+#if 0
   pBlock *pb;
   //  pCode *pc;
   pCodePeep *pcp;
@@ -907,6 +1294,22 @@ void pCodePeepInit(void)
   /* Declare a peep code snippet */
   /* <FIXME> do I really need a separate struct just to DLL the snippets? */
   /* e.g. I could put the DLL into the pCodePeep structure */
+
+  /* 
+
+     target:
+  
+     movwf %1
+     movf  %1,w
+  
+     replace:
+
+     movwf %1
+
+     Condition:
+     false condition - PCC_Z (Z bit is not used as input to subsequent code)
+     true condition - none
+  */
   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
@@ -949,8 +1352,8 @@ void pCodePeepInit(void)
 
       replace:
           btfss  %0
-      %1:  %4
           %3
+      %1:  %4
 
          The %3 and %4 are wild opcodes. Since the opcodes
          are stored in a different array than the wild operands,
@@ -963,7 +1366,7 @@ void pCodePeepInit(void)
     pCodeOp *pcwb;
 
     // Create a new wild operand subtyped as a bit
-    pcwb =  newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1));
+    pcwb =  newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1,0));
 
     // Create a 
     pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSC,pcwb));
@@ -1035,7 +1438,7 @@ void pCodePeepInit(void)
 
 
 
-
+#endif
 }
 
 /*-----------------------------------------------------------------*/
@@ -1070,10 +1473,72 @@ int pCodeSearchCondition(pCode *pc, unsigned int cond)
 
   return 0;
 }
+
+int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
+{
+  int labindex;
+
+  /* Check for a label associated with this wild pCode */
+  // If the wild card has a label, make sure the source code does too.
+  if(pcd->label) {
+    pCode *pcl;
+
+    if(!pcs->label)
+      return 0;
+
+    pcl = pcd->label->pc;
+    //labindex = PCOW(pcl)->id;
+    labindex = -PCL(pcl)->key;
+    fprintf(stderr,"label id = %d (labindex = %d)\n",PCL(pcl)->key,labindex);
+    if(peepBlock->vars[labindex] == NULL) {
+      // First time to encounter this label
+      peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
+      fprintf(stderr,"first time for a label: %d %s\n",labindex, peepBlock->vars[labindex]);
+    } else {
+      if(strcmp(peepBlock->vars[labindex],PCL(pcs->label->pc)->label) != 0) {
+       fprintf(stderr,"labels don't match\n");
+       return 0;
+      }
+      fprintf(stderr,"matched a label\n");
+    }
+  } else {
+    fprintf(stderr,"destination doesn't have a label\n");
+
+    if(pcs->label)
+      return 0;
+  }
+
+  return 1;
+    
+}
+
 /*-----------------------------------------------------------------*/
 /* pCodePeepMatchLine - Compare source and destination pCodes to   */
 /*                      see they're the same.                      */
+/*                                                                 */
+/* In this context, "source" refers to the coded generated by gen.c*/
+/* and "destination" refers to a pcode in a peep rule. If the dest-*/
+/* ination has no wild cards, then MatchLine will compare the two  */
+/* pcodes (src and dest) for a one-to-one match. If the destination*/
+/* has wildcards, then those get expanded. When a wild card is     */
+/* encountered for the first time it autmatically is considered a  */
+/* match and the object that matches it is referenced in the       */
+/* variables or opcodes array (depending on the type of match).    */
+/*                                                                 */
+/*                                                                 */
+/* Inputs:                                                         */
+/*  *peepBlock - A pointer to the peepBlock that contains the      */
+/*               entire rule to which the destination pcode belongs*/
+/*  *pcs - a pointer to the source pcode                           */
+/*  *pcd - a pointer to the destination pcode                      */
+/*                                                                 */
+/* Returns:                                                        */
+/*  1 - pcodes match                                               */
+/*  0 - pcodes don't match                                         */
+/*                                                                 */
+/*                                                                 */
 /*-----------------------------------------------------------------*/
+
 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 {
   int index;   // index into wild card arrays
@@ -1090,6 +1555,9 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
       pcs->print(stderr,pcs);
       pcd->print(stderr,pcd);
 
+      if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
+       return 0;
+
       /* Compare the operands */
       if(PCI(pcd)->pcop) {
        if (PCI(pcd)->pcop->type == PO_WILD) {
@@ -1097,16 +1565,22 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 
          fprintf(stderr,"destination is wild\n");
 #ifdef DEBUG_PCODEPEEP
-         if (index > peepBlock->nvars) {
+         if (index > peepBlock->nops) {
            fprintf(stderr,"%s - variables exceeded\n",__FUNCTION__);
            exit(1);
          }
 #endif
          PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
+         if(!peepBlock->wildpCodeOps[index]) {
+           peepBlock->wildpCodeOps[index] = PCI(pcs)->pcop;
+
+           //if(PCI(pcs)->pcop->type == PO_GPR_TEMP) 
+
+         }
          {
            char *n;
 
-           if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
+           if(PCI(pcs)->pcop->type == PO_GPR_TEMP) 
              n = PCOR(PCI(pcs)->pcop)->r->name;
            else
              n = PCI(pcs)->pcop->name;
@@ -1114,11 +1588,14 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
            if(peepBlock->vars[index])
              return  (strcmp(peepBlock->vars[index],n) == 0);
            else {
+             fprintf(stderr,"first time for a variable: %d, %s\n",index,n);
              peepBlock->vars[index] = n; //PCI(pcs)->pcop->name;
              return 1;
            }
          }
        }
+       /* 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);
@@ -1128,7 +1605,6 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 
   if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
 
-    int labindex;
 
     index = PCW(pcd)->id;
 
@@ -1138,26 +1614,8 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 
     peepBlock->wildpCodes[PCW(pcd)->id] = pcs;
 
-    /* Check for a label associated with this wild pCode */
-    // If the wild card has a label, make sure the source code does too.
-    if(PCW(pcd)->label) {
-      if(!pcs->label)
-       return 0;
-
-      labindex = PCOW(PCW(pcd)->label)->id;
-      if(peepBlock->vars[labindex] == NULL) {
-       // First time to encounter this label
-       peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
-       fprintf(stderr,"first time for a label\n");
-      } else {
-       if(strcmp(peepBlock->vars[labindex],PCL(pcs->label->pc)->label) != 0) {
-         fprintf(stderr,"labels don't match\n");
-         return 0;
-       }
-       fprintf(stderr,"matched a label\n");
-      }
-
-    }
+    if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
+      return 0;
 
     if(PCW(pcd)->operand) {
       PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
@@ -1182,6 +1640,9 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
     if(pcs) {
       fprintf(stderr," (next to match)\n");
       pcs->print(stderr,pcs);
+    } else if(pcd->next) {
+      /* oops, we ran out of code, but there's more to the rule */
+      return 0;
     }
 
     return 1; /*  wild card matches */
@@ -1196,13 +1657,18 @@ void pCodePeepClrVars(pCodePeep *pcp)
 {
 
   int i;
+  if(!pcp)
+    return;
 
-  for(i=0;i<pcp->nvars; i++)
+  for(i=0;i<pcp->nvars; i++) {
     pcp->vars[i] = NULL;
-
+    pcp->wildpCodeOps[i] = NULL;
+  }
 }
 
 /*-----------------------------------------------------------------*/
+/*  pCodeInsertAfter - splice in the pCode chain starting with pc2 */
+/*                     into the pCode chain containing pc1         */
 /*-----------------------------------------------------------------*/
 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
 {
@@ -1214,6 +1680,7 @@ void pCodeInsertAfter(pCode *pc1, pCode *pc2)
   if(pc1->next)
     pc1->next->prev = pc2;
 
+  pc2->pb = pc1->pb;
   pc2->prev = pc1;
   pc1->next = pc2;
 
@@ -1232,6 +1699,7 @@ static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
   switch(pcop->type) { 
   case PO_CRY:
   case PO_BIT:
+    fprintf(stderr,"pCodeOpCopy bit\n");
     pcopnew = Safe_calloc(1,sizeof(pCodeOpBit) );
     PCOB(pcopnew)->bit = PCOB(pcop)->bit;
     PCOB(pcopnew)->inBitSpace = PCOB(pcop)->inBitSpace;
@@ -1241,6 +1709,7 @@ static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
   case PO_WILD:
     /* Here we expand the wild card into the appropriate type: */
     /* By recursively calling pCodeOpCopy */
+    fprintf(stderr,"pCodeOpCopy wild\n");
     if(PCOW(pcop)->matched)
       pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
     else {
@@ -1254,33 +1723,50 @@ static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
     break;
 
   case PO_LABEL:
+    fprintf(stderr,"pCodeOpCopy label\n");
     pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
     PCOLAB(pcopnew)->key =  PCOLAB(pcop)->key;
     break;
 
   case PO_LITERAL:
   case PO_IMMEDIATE:
+    fprintf(stderr,"pCodeOpCopy lit\n");
     pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
     PCOL(pcopnew)->lit = PCOL(pcop)->lit;
     break;
 
   case PO_GPR_REGISTER:
   case PO_GPR_TEMP:
-  case PO_SFR_REGISTER:
+  case PO_GPR_BIT:
+    fprintf(stderr,"pCodeOpCopy GPR register\n");
+    pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
+    PCOR(pcopnew)->r = PCOR(pcop)->r;
+    PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
+    fprintf(stderr," register index %d\n", PCOR(pcop)->r->rIdx);
+    break;
+
   case PO_DIR:
+    fprintf(stderr,"pCodeOpCopy PO_DIR\n");
+  case PO_SFR_REGISTER:
   case PO_STR:
   case PO_NONE:
   case PO_W:
   case PO_STATUS:
   case PO_FSR:
   case PO_INDF:
+  case PO_PCL:
+  case PO_PCLATH:
 
+    fprintf(stderr,"pCodeOpCopy register type %d\n", pcop->type);
     pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
 
   }
 
   pcopnew->type = pcop->type;
-  pcopnew->name = Safe_strdup(pcop->name);
+  if(pcop->name)
+    pcopnew->name = Safe_strdup(pcop->name);
+  else
+    pcopnew->name = NULL;
 
   return pcopnew;
 }
@@ -1303,12 +1789,15 @@ void pCodeDeleteChain(pCode *f,pCode *t)
 {
   pCode *pc;
 
+
   while(f && f!=t) {
     fprintf(stderr,"delete pCode:\n");
     pc = f->next;
     f->print(stderr,f);
-    //f->delete(f);
+    //f->delete(f);  this dumps core...
+
     f = pc;
+
   }
 
 }
@@ -1325,6 +1814,9 @@ int pCodePeepMatchRule(pCode *pc)
 
   while(peeprules) {
     peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
+    if(!peepBlock || !peepBlock->target || !peepBlock->target->pcHead)
+      goto next_rule;
+
     pCodePeepClrVars(peepBlock);
 
     pcin = pc;
@@ -1345,7 +1837,7 @@ int pCodePeepMatchRule(pCode *pc)
        fprintf(stderr," end of rule\n");
     }
 
-    if(matched && pcin) {
+    if(matched) {
 
       /* So far we matched the rule up to the point of the conditions .
        * In other words, all of the opcodes match. Now we need to see
@@ -1356,12 +1848,12 @@ int pCodePeepMatchRule(pCode *pc)
        * the `postFalseCond' as input then we abort the match
        */
       fprintf(stderr,"    matched rule so far, now checking conditions\n");
-      if (peepBlock->postFalseCond && 
+      if (pcin && peepBlock->postFalseCond && 
          (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
        matched = 0;
     }
 
-    if(matched && pcin) {
+    if(matched) {
 
       pCode *pcprev;
       pCode *pcr;
@@ -1374,14 +1866,36 @@ int pCodePeepMatchRule(pCode *pc)
       printpCodeString(stderr,peepBlock->target->pcHead,10);
       fprintf(stderr,"first thing matched\n");
       pc->print(stderr,pc);
-      fprintf(stderr,"last thing matched\n");
-      pcin->print(stderr,pcin);
+      if(pcin) {
+       fprintf(stderr,"last thing matched\n");
+       pcin->print(stderr,pcin);
+      }
 
       /* Unlink the original code */
       pcprev = pc->prev;
       pcprev->next = pcin;
-      pcin->prev = pc->prev;
-      pCodeDeleteChain(pc,pcin);
+      if(pcin) 
+       pcin->prev = pc->prev;
+
+      {
+       /*     DEBUG    */
+       /* Converted the deleted pCodes into comments */
+
+       char buf[256];
+
+       buf[0] = ';';
+       buf[1] = '#';
+
+       while(pc &&  pc!=pcin) {
+         pCode2str(&buf[2], 254, pc);
+         pCodeInsertAfter(pcprev, newpCodeCharP(buf));
+         pcprev = pcprev->next;
+         pc = pc->next;
+       }
+      }
+
+      if(pcin)
+       pCodeDeleteChain(pc,pcin);
 
       /* Generate the replacement code */
       pc = pcprev;
@@ -1391,23 +1905,37 @@ int pCodePeepMatchRule(pCode *pc)
        /* If the replace pcode is an instruction with an operand, */
        /* then duplicate the operand (and expand wild cards in the process). */
        if(pcr->type == PC_OPCODE) {
-         if(PCI(pcr)->pcop)
-           pcop = pCodeOpCopy(PCI(pcr)->pcop);
+         if(PCI(pcr)->pcop) {
+           /* The replacing instruction has an operand.
+            * Is it wild? */
+           if(PCI(pcr)->pcop->type == PO_WILD) {
+             int index = PCOW(PCI(pcr)->pcop)->id;
+             fprintf(stderr,"copying wildopcode\n");
+             if(peepBlock->wildpCodeOps[index])
+               pcop = pCodeOpCopy(peepBlock->wildpCodeOps[index]);
+             else
+               fprintf(stderr,"error, wildopcode in replace but not source?\n");
+           } else
+             pcop = pCodeOpCopy(PCI(pcr)->pcop);
+         }
          fprintf(stderr,"inserting pCode\n");
          pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
        } else if (pcr->type == PC_WILD) {
          pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
+       } else if (pcr->type == PC_COMMENT) {
+         pCodeInsertAfter(pc, newpCodeCharP( ((pCodeComment *)(pcr))->comment));
        }
 
 
        pc = pc->next;
-       pc->print(stderr,pc);
+       if(pc)
+         pc->print(stderr,pc);
        pcr = pcr->next;
       }
 
       return 1;
     }
-
+  next_rule:
     peeprules = peeprules->next;
   }