support/regression/tests/float.c: workaround 33 bit hex constant
[fw/sdcc] / src / pic / pcodepeep.c
index 6963f5fb385ee982b26defd462ad806c6805a3b3..4330c03f13ec40899b0a320eed1a23c3d04433b6 100644 (file)
@@ -35,7 +35,7 @@
 #endif
 
 pCodeOp *popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
-
+pCodeOp *popRegFromString(char *str, int size, int offset);
 
 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype);
 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
@@ -44,7 +44,7 @@ int getpCode(char *mnem,int dest);
 int getpCodePeepCommand(char *cmd);
 void pBlockMergeLabels(pBlock *pb);
 char *pCode2str(char *str, int size, pCode *pc);
-char *get_op( pCodeOp *pcop);
+char *get_op( pCodeOp *pcop,char *buf,int buf_size);
 
 extern pCodeInstruction *pic14Mnemonics[];
 
@@ -201,7 +201,8 @@ typedef enum {
   ALT_MNEM1A,
   ALT_MNEM1B,
   ALT_MNEM2,
-  ALT_MNEM2A
+  ALT_MNEM2A,
+  ALT_MNEM3
 } altPatterns;
 
 static char alt_comment[]   = { PCP_COMMENT, 0};
@@ -213,6 +214,7 @@ static char alt_mnem1a[]    = { PCP_STR, PCP_WILDVAR, 0};
 static char alt_mnem1b[]    = { PCP_STR, PCP_NUMBER, 0};
 static char alt_mnem2[]     = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
 static char alt_mnem2a[]    = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
+static char alt_mnem3[]     = { PCP_STR, PCP_STR, PCP_COMMA, PCP_NUMBER, 0};
 
 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
@@ -223,10 +225,12 @@ 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_mnem3(void *pp,pCodeWildBlock *pcwb);
 
 pcPattern altArr[] = {
   {ALT_LABEL,        alt_label,  cvt_altpat_label},
   {ALT_COMMENT,      alt_comment,cvt_altpat_comment},
+  {ALT_MNEM3,        alt_mnem3,  cvt_altpat_mnem3},
   {ALT_MNEM2A,       alt_mnem2a, cvt_altpat_mnem2a},
   {ALT_MNEM2,        alt_mnem2,  cvt_altpat_mnem2},
   {ALT_MNEM1B,       alt_mnem1b, cvt_altpat_mnem1b},
@@ -538,6 +542,12 @@ static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb)
 }
 
 /*-----------------------------------------------------------------*/
+/* cvt_altpat_mnem2                                                */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - var                                                    */
+/*  pp[2] - comma                                                  */
+/*  pp[3] - destination                                            */
 /*-----------------------------------------------------------------*/
 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
 {
@@ -603,6 +613,11 @@ static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
   pCodeInstruction *pci=NULL;
   pCodeOp *pcosubtype;
 
+  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_mnem2a %s var %d destination %s(%d)\n",
@@ -641,6 +656,65 @@ static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
 
 }
 
+
+/*-----------------------------------------------------------------*/
+/* cvt_altpat_mem3 -  convert assembly line type to a pCode        */
+/*                    This rule is for bsf/bcf type instructions   */
+/*                                                                 */
+/*                                                                 */
+/*  pp[0] - mnem                                                   */
+/*  pp[1] - register                                               */
+/*  pp[2] - comma                                                  */
+/*  pp[3] - number                                                 */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+static void * cvt_altpat_mnem3(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_mnem3 %s var %s bit (%d)\n",
+         p->pct[0].tok.s,
+         p[1].pct[0].tok.s,
+         p[3].pct[0].tok.n));
+
+
+  opcode = getpCode(p->pct[0].tok.s,0);
+  if(opcode < 0) {
+    fprintf(stderr, "Bad mnemonic\n");
+    return NULL;
+  }
+
+
+  if(pic14Mnemonics[opcode]->isBitInst) {
+    //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
+
+    //if(pcosubtype == NULL) {
+    pcosubtype = newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0);
+    //}
+  } else
+    pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
+
+  if(pcosubtype == NULL) {
+    fprintf(stderr, "Bad operand\n");
+    return NULL;
+  }
+
+  pci = PCI(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.      */
@@ -660,13 +734,14 @@ static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
 
 static void tokenizeLineNode(char *ln)
 {
-
+  char *lnstart=ln;
   tokIdx = 0;               // Starting off at the beginning
   tokArr[0].tt = PCT_NULL;  // and assume invalid character for first token.
 
   if(!ln || !*ln)
     return;
 
+
   while(*ln) {
 
     if(isspace(*ln)) {
@@ -723,6 +798,11 @@ static void tokenizeLineNode(char *ln)
        tokArr[tokIdx].tok.s = Safe_strdup(buffer);
        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);
       }
     }
 
@@ -747,7 +827,7 @@ static void tokenizeLineNode(char *ln)
 
 void dump1Token(pCodeTokens tt)
 {
-#ifdef PCODE_DEBUG
+
   switch(tt) {
   case PCT_SPACE:
     fprintf(stderr, " space ");
@@ -783,7 +863,7 @@ void dump1Token(pCodeTokens tt)
     fprintf(stderr, " null ");
 
   }
-#endif
+
 }
 
 
@@ -887,19 +967,23 @@ int advTokIdx(int *v, int amt)
 /* pcode.                                                          */
 /*-----------------------------------------------------------------*/
 
-void parseTokens(pCodeWildBlock *pcwb)
+int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
 {
-  unsigned i;
   pCode *pc;
+  int error = 0;
 
   if(!tokIdx)
-    return;
+    return error;
 
-  for(i=0; i<=tokIdx; i++)
-    dump1Token(tokArr[i].tt);
 #ifdef PCODE_DEBUG
-  fputc('\n',stderr);
+  {
+    unsigned i;
+    for(i=0; i<=tokIdx; i++)
+      dump1Token(tokArr[i].tt);
+    fputc('\n',stderr);
+  }
 #endif
+
   {
     int lparsedPatIdx=0;
     int lpcpIdx;
@@ -1028,6 +1112,8 @@ void parseTokens(pCodeWildBlock *pcwb)
              state = PS_HAVE_COMMA;
            } else
              fprintf(stderr,"  unexpected comma\n");
+           break;
+
          }
 
          matching = 1;
@@ -1066,7 +1152,14 @@ void parseTokens(pCodeWildBlock *pcwb)
 
          //if(curBlock && pc)
          //addpCode2pBlock(curBlock, pc);
-         addpCode2pBlock(pcwb->pb, pc);
+         if(pc) {
+           if (pcret) {
+             *pcret = pc;
+             return 0;       // Only accept one line for now.
+           } else
+             addpCode2pBlock(pcwb->pb, pc);
+         } else
+           error++;
        }
        j += c;
       }
@@ -1090,7 +1183,7 @@ void parseTokens(pCodeWildBlock *pcwb)
 
   }
 
-
+  return error;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1107,9 +1200,38 @@ void  peepRuleBlock2pCodeBlock(  lineNode *ln, pCodeWildBlock *pcwb)
     //DFPRINTF((stderr,"%s\n",ln->line));
 
     tokenizeLineNode(ln->line);
-    parseTokens(pcwb);
+    
+    if(parseTokens(pcwb,NULL)) {
+      int i;
+      fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
+      fprintf(stderr,"Tokens:\n");
+      for(i=0; i<5; i++)
+       dump1Token(tokArr[i].tt);
+      fputc('\n',stderr);
+      exit (1);
+    }
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+pCode *AssembleLine(char *line)
+{
+  pCode *pc=NULL;
 
+  if(!line || !*line) {
+    fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
+    return NULL;
   }
+
+  tokenizeLineNode(line);
+    
+  if(parseTokens(NULL,&pc))
+    fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
+
+  return pc;
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -1227,7 +1349,7 @@ void  peepRules2pCode(peepRule *rules)
     peepRuleBlock2pCodeBlock(pr->match, &currentRule->target);
 
     //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
-    //printpBlock(stderr, curBlock);
+    //printpBlock(stderr, currentRule->target.pb);
 
     //DFPRINTF((stderr,"target with labels merged:\n"));
     //pBlockMergeLabels(curBlock);
@@ -1356,7 +1478,7 @@ static void * DLL_append(_DLL *list, _DLL *next)
 /*-----------------------------------------------------------------*/
 int pCodeSearchCondition(pCode *pc, unsigned int cond)
 {
-
+  //fprintf(stderr,"Checking conditions %d\n",cond);
   while(pc) {
 
     /* If we reach a function end (presumably an end since we most
@@ -1366,6 +1488,9 @@ int pCodeSearchCondition(pCode *pc, unsigned int cond)
       return 0;
 
     if(pc->type == PC_OPCODE) {
+      //fprintf(stderr," checking conditions of: ");
+      //pc->print(stderr,pc);
+      //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
       if(PCI(pc)->inCond & cond)
        return 1;
       if(PCI(pc)->outCond & cond)
@@ -1385,24 +1510,38 @@ int pCodeSearchCondition(pCode *pc, unsigned int cond)
  *-----------------------------------------------------------------*/
 int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
 {
+  char b[50], *n2;
 
   if(!pcops || !pcopd)
     return 0;
-  /*
+/*
   fprintf(stderr," Comparing operands %s",
-         get_op( pcops));
+         get_op( pcops,NULL,0));
 
   fprintf(stderr," to %s\n",
-         get_op( pcopd));
-  */
+         get_op( pcopd,NULL,0));
+*/
 
   if(pcops->type != pcopd->type) {
     //fprintf(stderr,"  - fail - diff types\n");
     return 0;  // different types
   }
 
-  if(!pcops->name ||  !pcopd->name || strcmp(pcops->name,pcopd->name)) {
-    //fprintf(stderr,"  - fail - diff names\n");
+  if(pcops->type == PO_LITERAL) {
+
+    if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
+      return 1;
+
+    return 0;
+  }
+
+  b[0]=0;
+  get_op(pcops,b,50);
+
+  n2 = 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) );
     return 0;  // different names
   }
 
@@ -1539,7 +1678,6 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
       if(PCI(pcd)->pcop) {
        if (PCI(pcd)->pcop->type == PO_WILD) {
          index = PCOW(PCI(pcd)->pcop)->id;
-
          //DFPRINTF((stderr,"destination is wild\n"));
 #ifdef DEBUG_PCODEPEEP
          if (index > peepBlock->nops) {
@@ -1552,13 +1690,13 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
          if(!peepBlock->target.wildpCodeOps[index]) {
            peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
 
-           //if(PCI(pcs)->pcop->type == PO_GPR_TEMP) 
+           //fprintf(stderr, "first time for wild opcode #%d\n",index);
+           return 1;
 
          } 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])
              );
@@ -1574,7 +1712,8 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
            case PO_GPR_TEMP:
            case PO_FSR:
              //case PO_INDF:
-             n = PCOR(PCI(pcs)->pcop)->r->name;
+             //n = PCOR(PCI(pcs)->pcop)->r->name;
+             n = PCI(pcs)->pcop->name;
 
              break;
            default:
@@ -1590,9 +1729,26 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
            }
          }
 
+       } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
+         /*
+           pcs->print(stderr,pcs);
+           pcd->print(stderr,pcd);
+
+           fprintf(stderr, "comparing literal operands of these instructions, result %d\n",
+           pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop));
+         */
+         return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
+
+       } else {
+         /* FIXME - need an else to check the case when the destination 
+          * isn't a wild card */
+         /*
+         fprintf(stderr, "Destination is not wild: operand compare =%d\n",
+                 pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop));
+         */
+         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);
@@ -1603,7 +1759,6 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
 
   if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
 
-
     index = PCW(pcd)->id;
 #ifdef PCODE_DEBUG
     DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
@@ -1679,12 +1834,12 @@ void pCodePeepClrVars(pCodePeep *pcp)
   int i;
   if(!pcp)
     return;
-
+/*
   DFPRINTF((stderr," Clearing peep rule vars\n"));
   DFPRINTF((stderr," %d %d %d  %d %d %d\n",
            pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
            pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
-
+*/
   for(i=0;i<pcp->target.nvars; i++)
     pcp->target.vars[i] = NULL;
   for(i=0;i<pcp->target.nops; i++)
@@ -1723,6 +1878,26 @@ void pCodeInsertAfter(pCode *pc1, pCode *pc2)
 
 }
 
+/*------------------------------------------------------------------*/
+/*  pCodeInsertBefore - splice in the pCode chain starting with pc2 */
+/*                      into the pCode chain containing pc1         */
+/*------------------------------------------------------------------*/
+void pCodeInsertBefore(pCode *pc1, pCode *pc2)
+{
+
+  if(!pc1 || !pc2)
+    return;
+
+  pc2->prev = pc1->prev;
+  if(pc1->prev)
+    pc1->prev->next = pc2;
+
+  pc2->pb = pc1->pb;
+  pc2->next = pc1;
+  pc1->prev = pc2;
+
+}
+
 /*-----------------------------------------------------------------*/
 /* pCodeOpCopy - copy a pcode operator                             */
 /*-----------------------------------------------------------------*/
@@ -1770,6 +1945,7 @@ pCodeOp *pCodeOpCopy(pCodeOp *pcop)
     PCOI(pcopnew)->index = PCOI(pcop)->index;
     PCOI(pcopnew)->offset = PCOI(pcop)->offset;
     PCOI(pcopnew)->_const = PCOI(pcop)->_const;
+    PCOI(pcopnew)->_function = PCOI(pcop)->_function;
     break;
 
   case PO_LITERAL:
@@ -1787,6 +1963,7 @@ pCodeOp *pCodeOpCopy(pCodeOp *pcop)
     return pcopnew;
     break;
 
+  case PO_GPR_POINTER:
   case PO_GPR_REGISTER:
   case PO_GPR_TEMP:
   case PO_FSR:
@@ -1862,7 +2039,7 @@ void pCodeDeleteChain(pCode *f,pCode *t)
   while(f && f!=t) {
     DFPRINTF((stderr,"delete pCode:\n"));
     pc = f->next;
-    f->print(stderr,f);
+    //f->print(stderr,f);
     //f->delete(f);  this dumps core...
 
     f = pc;
@@ -1915,6 +2092,7 @@ int pCodePeepMatchRule(pCode *pc)
       pct = pct->next;
       //debug:
       //DFPRINTF((stderr,"    matched\n"));
+
       if(!pcin && pct) {
        DFPRINTF((stderr," partial match... no more code\n"));
        matched = 0; 
@@ -1924,7 +2102,7 @@ int pCodePeepMatchRule(pCode *pc)
       }
     }
 
-    if(matched) {
+    if(matched && pcin) {
 
       /* 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
@@ -1935,9 +2113,16 @@ int pCodePeepMatchRule(pCode *pc)
        * the `postFalseCond' as input then we abort the match
        */
       DFPRINTF((stderr,"    matched rule so far, now checking conditions\n"));
+      //pcin->print(stderr,pcin);
+      
       if (pcin && peepBlock->postFalseCond && 
          (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
        matched = 0;
+
+      //fprintf(stderr," condition results = %d\n",pCodeSearchCondition(pcin,peepBlock->postFalseCond));
+
+
+      //if(!matched) fprintf(stderr,"failed on conditions\n");
     }
 
     if(matched) {
@@ -1967,7 +2152,7 @@ int pCodePeepMatchRule(pCode *pc)
        pcin->prev = pc->prev;
 
 
-
+#if 0
       {
        /*     DEBUG    */
        /* Converted the deleted pCodes into comments */
@@ -1999,6 +2184,7 @@ int pCodePeepMatchRule(pCode *pc)
        if(pc_cline2)
          pc_cline2->pc.next = NULL;
       }
+#endif
 
       if(pcin)
        pCodeDeleteChain(pc,pcin);