pCode peep is fully working for the PIC port.
authorsdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 27 Aug 2001 01:06:42 +0000 (01:06 +0000)
committersdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 27 Aug 2001 01:06:42 +0000 (01:06 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1176 4a8a32a2-be11-0410-ad9d-d568d2c75423

src/SDCCpeeph.c
src/pic/pcode.c
src/pic/pcode.h
src/pic/pcodepeep.c
src/pic/peeph.def
src/regression/Makefile
src/regression/b.c

index 0ae38500ffee4d56c6503cb49da3918c02c34eb7..0a5a8d2394d0a65a388d7182362481aa35848211 100644 (file)
@@ -48,6 +48,10 @@ static bool matchLine (char *, char *, hTab **);
 #define FBYNAME(x) int x (hTab *vars, lineNode *currPl, lineNode *head, \
         const char *cmdLine)
 
+#if !OPT_DISABLE_PIC
+void  peepRules2pCode(peepRule *);
+#endif
+
 /*-----------------------------------------------------------------*/
 /* pcDistance - afinds a label back ward or forward                */
 /*-----------------------------------------------------------------*/
@@ -1050,7 +1054,7 @@ readFileIntoBuffer (char *fname)
 }
 
 /*-----------------------------------------------------------------*/
-/* initPeepHole - initiaises the peep hole optimizer stuff         */
+/* initPeepHole - initialises the peep hole optimizer stuff        */
 /*-----------------------------------------------------------------*/
 void 
 initPeepHole ()
@@ -1066,4 +1070,15 @@ initPeepHole ()
       readRules (s = readFileIntoBuffer (options.peep_file));
       setToNull ((void **) &s);
     }
+
+
+#if !OPT_DISABLE_PIC
+  /* Convert the peep rules into pcode.
+     NOTE: this is only support in the PIC port (at the moment)
+  */
+  if (TARGET_IS_PIC) {
+    peepRules2pCode(rootRules);
+  }
+#endif
+
 }
index ccc1b43e3747bb6cf9122541f86cca77abd74fca..16bd38f9ab2bebb69d8058f8be5193916e38f663 100644 (file)
@@ -689,6 +689,31 @@ char *Safe_strdup(char *str)
     
 }
 
+
+/*-----------------------------------------------------------------*/
+/* SAFE_snprintf - like snprintf except the string pointer is      */
+/*                 after the string has been printed to. This is   */
+/*                 useful for printing to string as though if it   */
+/*                 were a stream.                                  */
+/*-----------------------------------------------------------------*/
+void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
+{
+  va_list val;
+  int len;
+
+  if(!str || !*str)
+    return;
+
+  va_start(val, format);
+  vsnprintf(*str, *size, format, val);
+  va_end (val);
+
+  len = strlen(*str);
+  *str += len;
+  *size -= len;
+
+}
+
 void  pCodeInitRegisters(void)
 {
 
@@ -1157,7 +1182,7 @@ pBlock *newpBlock(void)
 }
 
 /*-----------------------------------------------------------------*/
-/* newpCodeChain - create a new chain of pCodes                    */
+/* newpCodeChai0n - create a new chain of pCodes                    */
 /*-----------------------------------------------------------------*
  *
  *  This function will create a new pBlock and the pointer to the
@@ -1297,12 +1322,18 @@ pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
 /*-----------------------------------------------------------------*/
 void addpCode2pBlock(pBlock *pb, pCode *pc)
 {
-
-  pb->pcTail->next = pc;
-  pc->prev = pb->pcTail;
-  pc->next = NULL;
-  pc->pb = pb;
-  pb->pcTail = pc;
+  if(!pb->pcHead) {
+    /* If this is the first pcode to be added to a block that
+     * was initialized with a NULL pcode, then go ahead and
+     * make this pcode the head and tail */
+    pb->pcHead  = pb->pcTail = pc;
+  } else {
+    pb->pcTail->next = pc;
+    pc->prev = pb->pcTail;
+    pc->next = NULL;
+    pc->pb = pb;
+    pb->pcTail = pc;
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -1394,7 +1425,6 @@ void pBlockRegs(FILE *of, pBlock *pb)
 
   r = setFirstItem(pb->registers);
   while (r) {
-    fprintf(of,"   %s\n",r->name);
     r = setNextItem(pb->registers);
   }
 }
@@ -1412,7 +1442,7 @@ static char *get_op( pCodeInstruction *pcc)
     case PO_FSR:
     case PO_GPR_TEMP:
       r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
-      fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
+      //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
       pBlockRegs(stderr,pcc->pc.pb);
       return r->name;
 
@@ -1434,6 +1464,70 @@ static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
   fprintf(of,"pcodeopprint\n");
 }
 
+char *pCode2str(char *str, int size, pCode *pc)
+{
+  char *s = str;
+
+  switch(pc->type) {
+
+  case PC_OPCODE:
+
+    SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
+
+    if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
+
+      if(PCI(pc)->bit_inst) {
+       if(PCI(pc)->pcop->type == PO_BIT) {
+         if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
+           SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
+                         PCI(pc)->pcop->name ,
+                         PCI(pc)->pcop->name );
+         else
+           SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)), 
+                         (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
+       } else
+         SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
+       //PCI(pc)->pcop->t.bit );
+      } else {
+
+       if(PCI(pc)->pcop->type == PO_BIT) {
+         if( PCI(pc)->num_ops == 2)
+           SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
+         else
+           SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
+
+       }else {
+         SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
+
+         if( PCI(pc)->num_ops == 2)
+           SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
+       }
+      }
+
+    }
+    break;
+
+  case PC_COMMENT:
+    /* assuming that comment ends with a \n */
+    SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
+    break;
+
+  case PC_LABEL:
+    SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
+    break;
+  case PC_FUNCTION:
+    SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
+    break;
+  case PC_WILD:
+    SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
+    break;
+
+  }
+
+  return str;
+
+}
+
 /*-----------------------------------------------------------------*/
 /* genericPrint - the contents of a pCode to a file                */
 /*-----------------------------------------------------------------*/
@@ -1459,41 +1553,13 @@ static void genericPrint(FILE *of, pCode *pc)
       }
     }
 
-    fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
-    if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
 
-      if(PCI(pc)->bit_inst) {
-       if(PCI(pc)->pcop->type == PO_BIT) {
-         if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
-           fprintf(of,"(%s >> 3), (%s & 7)", 
-                   PCI(pc)->pcop->name ,
-                   PCI(pc)->pcop->name );
-         else
-           fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
-       } else
-         fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
-       //PCI(pc)->pcop->t.bit );
-      } else {
-
-       if(PCI(pc)->pcop->type == PO_BIT) {
-         if( PCI(pc)->num_ops == 2)
-           fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
-         else
-           fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
-
-/*
-         if( PCI(pc)->num_ops == 2)
-           fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
-         else
-           fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
-*/
-       }else {
-         fprintf(of,"%s",get_op(PCI(pc)));
+    {
+      char str[256];
+      
+      pCode2str(str, 256, pc);
 
-         if( PCI(pc)->num_ops == 2)
-           fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
-       }
-      }
+      fprintf(of,"%s",str);
     }
 
     {
@@ -1522,6 +1588,9 @@ static void genericPrint(FILE *of, pCode *pc)
 
   case PC_WILD:
     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
+    if(pc->label)
+      pCodePrintLabel(of, pc->label->pc);
+
     if(PCW(pc)->operand) {
       fprintf(of,";\toperand  ");
       pCodeOpPrint(of,PCW(pc)->operand );
@@ -1583,7 +1652,7 @@ static void pCodePrintLabel(FILE *of, pCode *pc)
   else if (PCL(pc)->key >=0) 
     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
   else
-    fprintf(of,";wild card label\n");
+    fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
 
 }
 /*-----------------------------------------------------------------*/
@@ -1766,7 +1835,7 @@ pCode * findNextInstruction(pCode *pc)
 {
 
   while(pc) {
-    if(pc->type == PC_OPCODE)
+    if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
       return pc;
 
     pc = pc->next;
index 5efd207e8095dc6067b3392b555670ca3304ecb6..4f2afc36d3e9ab4f40fcd879d5d4ea0963b697f4 100644 (file)
@@ -499,8 +499,11 @@ typedef struct pCodePeep {
 
   int     nvars;       // Number of wildcard registers in target.
   char  **vars;        // array of pointers to them
+  int     nops;             // Number of wildcard operands in target.
+  pCodeOp **wildpCodeOps;   // array of pointers to the pCodeOp's.
+
   int     nwildpCodes; // Number of wildcard pCodes in target/replace
-  pCode **wildpCodes;  // array of pointers to the pCodeOp's.
+  pCode **wildpCodes;  // array of pointers to the pCode's.
 
 
   /* (Note: a wildcard register is a place holder. Any register
index 0514d1f3a3b7412d82cc5d9309c44fd659437220..c51bcb42021145988b9d0852f1bd5e23547ee8eb 100644 (file)
@@ -42,6 +42,9 @@ pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_la
 pCode * findNextInstruction(pCode *pc);
 char *Safe_strdup(char *str);
 int getpCode(char *mnem,int dest);
+void pBlockMergeLabels(pBlock *pb);
+char *pCode2str(char *str, int size, pCode *pc);
+
 extern pCodeInstruction *pic14Mnemonics[];
 
 
@@ -98,6 +101,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;
@@ -114,6 +127,7 @@ unsigned   tokIdx=0;
 
 
 typedef enum  {
+  PCT_NULL=0,
   PCT_SPACE=1,
   PCT_PERCENT,
   PCT_COLON,
@@ -141,7 +155,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};
@@ -150,6 +165,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 {
@@ -164,6 +180,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}
 };
 
@@ -172,6 +189,7 @@ pcPattern pcpArr[] = {
 // Assembly Line Token
 typedef enum {
   ALT_LABEL=1,
+  ALT_COMMENT,
   ALT_MNEM0,
   ALT_MNEM0A,
   ALT_MNEM1,
@@ -181,6 +199,7 @@ 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};
@@ -191,6 +210,7 @@ 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);
@@ -201,6 +221,7 @@ 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},
@@ -288,7 +309,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);
 
 }
 
@@ -331,6 +369,11 @@ static void * cvt_altpat_mnem0a(void *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);
 
 }
@@ -400,7 +443,7 @@ static void * cvt_altpat_mnem1a(void *pp)
   }
 
   if(pic14Mnemonics[opcode]->bit_inst)
-    pcosubtype = newpCodeOp(NULL,PO_BIT);
+    pcosubtype = newpCodeOpBit(NULL,-1);
   else
     pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
 
@@ -408,6 +451,10 @@ static void * cvt_altpat_mnem1a(void *pp)
   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");
 
@@ -531,6 +578,10 @@ static void * cvt_altpat_mnem2a(void *pp)
   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");
 
@@ -539,13 +590,27 @@ static void * cvt_altpat_mnem2a(void *pp)
 }
 
 /*-----------------------------------------------------------------*/
+/* 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;
@@ -553,6 +618,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++;
@@ -578,6 +644,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;
@@ -596,13 +663,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;
@@ -630,10 +703,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);
@@ -641,7 +716,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 ");
 
   }
 }
@@ -730,9 +807,24 @@ 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)
 {
   unsigned i;
   pCode *pc;
@@ -743,7 +835,6 @@ void dumpTokens(void)
   for(i=0; i<=tokIdx; i++)
     dump1Token(tokArr[i].tt);
 
-
   fputc('\n',stderr);
 
   {
@@ -778,7 +869,6 @@ void dumpTokens(void)
 
       lpcpIdx=0;
       matching = 0;
-      //fprintf(stderr,"ltokIdx = %d\n",ltokIdx);
 
       if(  ((tokArr[ltokIdx].tt == PCT_SPACE) )
           && (advTokIdx(&ltokIdx, 1)) ) // eat space
@@ -787,7 +877,7 @@ void dumpTokens(void)
       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){
@@ -910,6 +1000,8 @@ void dumpTokens(void)
          if(pc && pc->print)
            pc->print(stderr,pc);
          //if(pc && pc->destruct) pc->destruct(pc); dumps core?
+         if(curBlock && pc)
+           addpCode2pBlock(curBlock, pc);
        }
        j += c;
       }
@@ -936,6 +1028,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.                                        */
@@ -951,41 +1081,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));
-    //curPeep->target = curPeep->replace = NULL;
-    curPeep->vars = NULL; curPeep->wildpCodes = NULL;
+
+    curPeep->vars = NULL; 
+    curPeep->wildpCodes = NULL; curPeep->wildpCodeOps = NULL;
+    curPeep->postFalseCond = PCC_NONE;
+    curPeep->postTrueCond  = PCC_NONE;
+
     peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
 
     curPeep->target = curBlock = newpCodeChain(NULL, 'W', NULL);
+    sMaxWildVar  = 0;
+    sMaxWildMnem = 0;
 
-    for(ln = pr->match; ln; ln = ln->next) {
+    /* Convert the target block */
+    peepRuleBlock2pCodeBlock(pr->match);
 
-      fprintf(stderr,"%s\n",ln->line);
+    fprintf(stderr,"finished target, here it is in pcode form:\n");
+    printpBlock(stderr, curBlock);
 
-      parseLineNode(ln->line);
-      dumpTokens();
-
-    }
+    fprintf(stderr,"target with labels merged:\n");
+    pBlockMergeLabels(curBlock);
+    printpBlock(stderr, curBlock);
 
     fprintf(stderr,"\nReplaced by:\n");
 
+
     curPeep->replace = curBlock = newpCodeChain(NULL, 'W', NULL);
 
-    for(ln = pr->replace; ln; ln = ln->next)
-      fprintf(stderr,"%s\n",ln->line);
+    /* Convert the replace block */
+    peepRuleBlock2pCodeBlock(pr->replace);
 
-    if(pr->cond)
-      fprintf(stderr,"\nCondition:  %s\n",pr->cond);
+    fprintf(stderr,"finished replace block, here it is in pcode form:\n");
+    printpBlock(stderr, curBlock);
 
-    return;
+    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
   }
 
 }
@@ -1129,6 +1295,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);
@@ -1171,8 +1353,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,
@@ -1319,16 +1501,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;
@@ -1362,11 +1550,15 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 
     /* 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(pcd->label) {
+      pCode *pcl;
+
       if(!pcs->label)
        return 0;
 
-      labindex = PCOW(PCW(pcd)->label)->id;
+      pcl = pcd->label->pc;
+
+      labindex = PCOW(pcl)->id;
       if(peepBlock->vars[labindex] == NULL) {
        // First time to encounter this label
        peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
@@ -1378,8 +1570,8 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
        }
        fprintf(stderr,"matched a label\n");
       }
-
-    }
+    } else 
+      fprintf(stderr,"wild card doesn't have a label\n");
 
     if(PCW(pcd)->operand) {
       PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
@@ -1421,12 +1613,15 @@ void pCodePeepClrVars(pCodePeep *pcp)
   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)
 {
@@ -1438,6 +1633,7 @@ void pCodeInsertAfter(pCode *pc1, pCode *pc2)
   if(pc1->next)
     pc1->next->prev = pc2;
 
+  pc2->pb = pc1->pb;
   pc2->prev = pc1;
   pc1->next = pc2;
 
@@ -1456,6 +1652,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;
@@ -1465,6 +1662,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 {
@@ -1478,20 +1676,30 @@ 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:
+    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:
@@ -1499,6 +1707,7 @@ static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
   case PO_FSR:
   case PO_INDF:
 
+    fprintf(stderr,"pCodeOpCopy register type %d\n", pcop->type);
     pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
 
   }
@@ -1527,12 +1736,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;
+
   }
 
 }
@@ -1608,6 +1820,24 @@ int pCodePeepMatchRule(pCode *pc)
       pcprev = pc->prev;
       pcprev->next = 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;
+       }
+      }
+
       pCodeDeleteChain(pc,pcin);
 
       /* Generate the replacement code */
@@ -1618,12 +1848,25 @@ 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));
        }
 
 
index 3a60c535ca6b49625bf14c8cb5c317efaa921ea4..6cbd71ad4e4d70378bdd92a3d4eed777185995f7 100644 (file)
-//bogus test for pcode
-replace restart {
-       movf    %1,w    ;comment at end
-%4:    movf    %1,w
-       RETURN
-       clrf    INDF
-       movlw   0xa5
-       movf    fsr,w
-       incf    indf,f
-       %2
-} by {
-       ; peep test remove redundant move
-%4:    movf    %1,w    ;another comment
-       %2
-} if AYBABTU %3
+// PIC Port Peep rules
+//
+//
+// INTRODUCTION:
+//
+// The peep hole optimizer searchs the
+// the SDCC generated code for small snippets
+// that can be optimized. As a user, you have
+// control over this optimization process without
+// having to learn the SDCC source code. (However
+// you'll still need access to the source since
+// these rules are compiled into the source.)
+//
+// The way it works is you specify the target
+// snippet that you want replaced with a more 
+// efficient snippet that you write. Wild card
+// variables allow the rules to be parameterized.
+// 
+// In all of the SDCC ports, labels and operands
+// can be wild cards. However, in the PIC even the
+// instructions can be wild cards.
+//
+// EXAMPLE:
+//
+// Consider Peep Rule 1 as an example. This rule
+// replaces some code like:
+//
+//   skpz           ;i.e. btfss status,Z
+//    goto    lab1
+//   clrw
+//lab1:
+//
+// with:
+//
+//   skpnz     ;i.e. btfsc status,Z
+//    clrw
+//lab1
+//
+// However, the Rule has wild cards four wild cards.
+// The first allows the btfss instruction operate
+// on anything, not just the Z bit in status register.
+// The second wild card applies to a label.
+// The third wild card is for an instruction - any
+// single instruction can be substituted.
+// The fourth wild card is also an instruction. It's
+// just an instruction place holder associated with
+// a label (think of it as the PIC Port author's laziness
+// imposed upon the user).
+//
+//
+// CONDITIONS
+//
+// There are certain instances where a peep rule may not
+// be applicable. Consider this subtle example:
+//
+//     movwf    R0
+//     movf     R0,W
+//
+// It would seem that the second move is unnecessary. But
+// be careful! The movf instruction affects the 'Z' bit.
+// So if this sequence is followed by a btfsc status,Z, you
+// will have to leave the second move in.
+//
+// To get around this proble, the peep rule can be followed
+// by a conditon:  "if NZ". Which is to say, apply the rule
+// if Z bit is not needed in the code that follows. The optimizer
+// is smart enough to look more than one instruction past the
+// target block...
+//
+//
 
 
-// peep 1
 replace restart {
-       movf    %1,w
-       movwf   %2
-       movf    %2,w
+        btfss  %1
+        goto   %2
+       %3
+%2:    %4
 } by {
-       ; peep 1 - Removed redundant move
-       movf    %1,w
-       movwf   %2
+       ;peep 1 - test/jump to test/skip
+       btfsc   %1
+       %3
+%2:    %4
 }
 
-// peep 2
 replace restart {
-       decf    %1,f
-       movf    %1,w
-       btfss   status,z
-       goto    %2
+        btfsc  %1
+        goto   %2
+       %3
+%2:    %4
 } by {
-       ; peep 2 - decf/mov/skpz to decfsz
-       decfsz  %1,f
-        goto   %2
+       ;peep 1a - test/jump to test/skip
+       btfss   %1
+       %3
+%2:    %4
 }
 
-// peep 3
-replace restart {
-       movwf   %1
-       movf    %1,w
-       xorlw   %2
-} by {
-       ; peep 3 - redundant move
-       movwf   %1
-       xorlw   %2
-}
 
-// peep 4
-replace restart {
-        btfsc  %1,%2
-        goto   %3
-       incf    %4,f
-%3:
-} by {
-       ;peep 4 - test/jump to test/skip
-       btfss   %1,%2
-       incf   %4,f
-%3:
-}
+//bogus test for pcode
+//replace restart {
+//     movf    %1,w    ;comment at end
+//%4:  movf    %1,w
+//     RETURN
+//     clrf    INDF
+//     movlw   0xa5
+//     movf    fsr,w
+//     incf    indf,f
+//     %2
+//} by {
+//     ; peep test remove redundant move
+//%4:  movf    %1,w    ;another comment
+//     %2
+//} if AYBABTU %3
 
 
-// peep 5
+// peep 2
 replace restart {
-        btfss  %1,%2
-        goto   %3
-       incf    %4,f
-%3:
+       movwf   %1
+       movf    %1,w
 } by {
-       ;peep 5 - test/jump to test/skip
-       btfsc   %1,%2
-       incf   %4,f
-%3:
-}
+       ; peep 2 - Removed redundant move
+       movwf   %1
+} if NZ
 
-// peep 6
+// peep 3
 replace restart {
-        btfss  %1,%2
-        goto   %3
-%4:
-       incf    %5,f
-%3:
+       decf    %1,f
+       movf    %1,w
+       btfss   status,z
+       goto    %2
 } by {
-       ;peep 6 - test/jump to test/skip
-       btfsc   %1,%2
-%4:
-       incf   %5,f
-%3:
+       ; peep 3 - decf/mov/skpz to decfsz
+       decfsz  %1,f
+        goto   %2
 }
 
-// peep 7
-replace restart {
-        btfsc  %1,%2
-        goto   %3
-%4:
-       incf    %5,f
-%3:
-} by {
-       ;peep 6 - test/jump to test/skip
-       btfss   %1,%2
-%4:
-       incf   %5,f
-%3:
-}
 
 replace restart {
        movf    %1,w
@@ -114,13 +142,6 @@ replace restart {
        movf    %1,w
 }
 
-replace restart {
-       movwf   %1
-       movf    %1,w
-} by {
-       ; peep 9 - Removed redundant move
-       movwf   %1
-}
 
 replace restart {
        movlw   %1
@@ -139,4 +160,3 @@ replace restart {
        ; peep 11 - Removed redundant move
        movwf   %1
 }
-
index eb1b16c134020e187e5b21f28281537930f0c197..a0d97077b073a7411c8d8220ec68b62a2c432512 100644 (file)
@@ -80,7 +80,7 @@ all:  test
 # The .cod files are generated by gpasm
 # these get loaded by gpsim.
 .asm.cod:
-       gpasm $*.asm
+       gpasm -c $*.asm
 
 # The .stc files are script files for gpsim
 .cod.stc:
index 4335f7913456c6efd89374d86deb8f176bdf6b2f..cf09e5c3fe92f2fbe0a942aa9414d550c0e84914 100644 (file)
@@ -1,5 +1,6 @@
 
 unsigned char success = 0;
+unsigned char dummy = 0;
 
 unsigned char uchar0=0;
 unsigned char uchar1=0;
@@ -8,7 +9,7 @@ unsigned char uchar2=0;
 
 void done(void)
 {
-  success++;
+  dummy++;
 }
 /*
 void incptr(unsigned char *ucP)