1 /*-------------------------------------------------------------------------
3 pcodepeep.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
24 #include "common.h" // Include everything in the SDCC src directory
29 #include "pcodeflow.h"
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
35 #define STRCASECMP strcasecmp
38 pCodeOp *popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
41 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype);
42 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
43 pCode * findNextInstruction(pCode *pc);
44 int getpCode(char *mnem,int dest);
45 void pBlockMergeLabels(pBlock *pb);
46 char *pCode2str(char *str, int size, pCode *pc);
48 extern pCodeInstruction *pic14Mnemonics[];
51 /****************************************************************/
53 * rootRules - defined in SDCCpeep.c
54 * This is a pointer to the (parsed) peephole rules that are
55 * defined in peep.def.
58 //extern peepRule *rootRules;
63 /****************************************************************/
64 /****************************************************************/
72 typedef struct pCodePeepSnippets
79 /****************************************************************/
83 /****************************************************************/
85 static pCodePeepSnippets *peepSnippets=NULL;
87 /****************************************************************/
91 /****************************************************************/
93 static pCodePeep *curPeep=NULL;
95 /****************************************************************/
99 /****************************************************************/
101 static pBlock *curBlock=NULL;
104 /****************************************************************/
106 /* max wild cards in a peep rule */
108 /****************************************************************/
110 static int sMaxWildVar = 0;
111 static int sMaxWildMnem = 0;
114 typedef struct pCodeToken
116 int tt; // token type;
125 pCodeToken tokArr[50];
142 typedef struct parsedPattern {
143 struct pcPattern *pcp;
147 #define MAX_PARSEDPATARR 50
148 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
149 unsigned int parsedPatIdx=0;
162 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
163 static char pcpat_number[] = {PCT_NUMBER, 0};
164 static char pcpat_string[] = {PCT_STRING, 0};
165 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
166 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
167 static char pcpat_comma[] = {PCT_COMMA, 0};
168 static char pcpat_comment[] = {PCT_COMMENT, 0};
171 typedef struct pcPattern {
172 char pt; // Pattern type
173 char *tokens; // list of tokens that describe the pattern
174 void * (*f) (void *);
177 pcPattern pcpArr[] = {
178 {PCP_LABEL, pcpat_label, NULL},
179 {PCP_WILDSTR, pcpat_wildString, NULL},
180 {PCP_STR, pcpat_string, NULL},
181 {PCP_WILDVAR, pcpat_wildVar, NULL},
182 {PCP_COMMA, pcpat_comma, NULL},
183 {PCP_COMMENT, pcpat_comment, NULL},
184 {PCP_NUMBER, pcpat_number, NULL}
187 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
189 // Assembly Line Token
202 static char alt_comment[] = { PCP_COMMENT, 0};
203 static char alt_label[] = { PCP_LABEL, 0};
204 static char alt_mnem0[] = { PCP_STR, 0};
205 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
206 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
207 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
208 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
209 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
210 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
212 static void * cvt_altpat_label(void *pp);
213 static void * cvt_altpat_comment(void *pp);
214 static void * cvt_altpat_mnem0(void *pp);
215 static void * cvt_altpat_mnem0a(void *pp);
216 static void * cvt_altpat_mnem1(void *pp);
217 static void * cvt_altpat_mnem1a(void *pp);
218 static void * cvt_altpat_mnem1b(void *pp);
219 static void * cvt_altpat_mnem2(void *pp);
220 static void * cvt_altpat_mnem2a(void *pp);
222 pcPattern altArr[] = {
223 {ALT_LABEL, alt_label, cvt_altpat_label},
224 {ALT_COMMENT, alt_comment,cvt_altpat_comment},
225 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
226 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
227 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
228 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
229 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
230 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
231 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
235 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
237 // forward declarations
238 static void * DLL_append(_DLL *list, _DLL *next);
240 /*-----------------------------------------------------------------*/
241 /* cvt_extract_destination - helper function extracts the register */
242 /* destination from a parsedPattern. */
244 /*-----------------------------------------------------------------*/
245 static int cvt_extract_destination(parsedPattern *pp)
248 if(pp->pct[0].tt == PCT_STRING) {
250 // just check first letter for now
252 if(toupper(*pp->pct[0].tok.s) == 'F')
255 } else if (pp->pct[0].tt == PCT_NUMBER) {
265 /*-----------------------------------------------------------------*/
266 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
267 /* if *reg is the "status" register and *bit is one of the */
268 /* status bits, then this function will create a new pCode op */
269 /* containing the status register. */
270 /*-----------------------------------------------------------------*/
272 static pCodeOp *cvt_extract_status(char *reg, char *bit)
276 if(STRCASECMP(reg, pc_status.pcop.name))
283 if(toupper(*bit) == 'C')
284 return PCOP(popCopyGPR2Bit(&pc_status,PIC_C_BIT));
285 if(toupper(*bit) == 'Z')
286 return PCOP(popCopyGPR2Bit(&pc_status,PIC_Z_BIT));
290 if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
291 return PCOP(popCopyGPR2Bit(&pc_status,PIC_DC_BIT));
297 /*-----------------------------------------------------------------*/
298 /* cvt_altpat_label - convert assembly line type to a pCode label */
299 /* INPUT: pointer to the parsedPattern */
303 /* label pattern => '%' number ':' */
304 /* at this point, we wish to extract only the 'number' */
306 /*-----------------------------------------------------------------*/
307 static void * cvt_altpat_label(void *pp)
309 parsedPattern *p = pp;
311 DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
312 return newpCodeLabel(NULL,-p->pct[1].tok.n);
316 /*-----------------------------------------------------------------*/
317 /* cvt_altpat_comment - convert assembly line type to a comment */
318 /* INPUT: pointer to the parsedPattern */
320 /* pp[0] - comment */
323 /*-----------------------------------------------------------------*/
324 static void * cvt_altpat_comment(void *pp)
326 parsedPattern *p = pp;
328 DFPRINTF((stderr,"altpat_comment = %s\n",p->pct[0].tok.s));
329 return newpCodeCharP(p->pct[0].tok.s);
333 /*-----------------------------------------------------------------*/
334 /*-----------------------------------------------------------------*/
335 static void * cvt_altpat_mnem0(void *pp)
337 parsedPattern *p = pp;
340 pCodeInstruction *pci=NULL;
342 DFPRINTF((stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s));
344 opcode = getpCode(p->pct[0].tok.s,0);
346 fprintf(stderr, "Bad mnemonic\n");
350 pci = PCI(newpCode(opcode, NULL));
353 fprintf(stderr,"couldn't find mnemonic\n");
359 /*-----------------------------------------------------------------*/
360 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
363 /* pp[0] - wild var */
365 /*-----------------------------------------------------------------*/
366 static void * cvt_altpat_mnem0a(void *pp)
368 parsedPattern *p = pp;
370 DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n));
372 /* Save the index of the maximum wildcard mnemonic */
374 if(p[0].pct[1].tok.n > sMaxWildVar)
375 sMaxWildMnem = p[0].pct[1].tok.n;
377 return newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
381 /*-----------------------------------------------------------------*/
382 /* cvt_altpat_mem1 - convert assembly line type to a pCode */
383 /* instruction with 1 operand. */
386 /* pp[1] - Operand */
388 /*-----------------------------------------------------------------*/
389 static void * cvt_altpat_mnem1(void *pp)
392 parsedPattern *p = pp;
395 pCodeInstruction *pci=NULL;
398 DFPRINTF((stderr,"altpat_mnem1 %s var %s\n", p->pct[0].tok.s,p[1].pct[0].tok.s));
400 opcode = getpCode(p->pct[0].tok.s,0);
402 fprintf(stderr, "Bad mnemonic\n");
406 if(pic14Mnemonics[opcode]->isBitInst)
407 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
409 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
412 pci = PCI(newpCode(opcode, pcosubtype));
415 fprintf(stderr,"couldn't find mnemonic\n");
421 /*-----------------------------------------------------------------*/
422 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
423 /* instruction with 1 wild operand. */
426 /* pp[1] - wild var */
428 /*-----------------------------------------------------------------*/
429 static void * cvt_altpat_mnem1a(void *pp)
431 parsedPattern *p = pp;
434 pCodeInstruction *pci=NULL;
437 DFPRINTF((stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n));
439 opcode = getpCode(p->pct[0].tok.s,0);
441 fprintf(stderr, "Bad mnemonic\n");
445 if(pic14Mnemonics[opcode]->isBitInst)
446 pcosubtype = newpCodeOpBit(NULL,-1,0);
448 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
451 pci = PCI(newpCode(opcode,
452 newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
454 /* Save the index of the maximum wildcard variable */
455 if(p[1].pct[1].tok.n > sMaxWildVar)
456 sMaxWildVar = p[1].pct[1].tok.n;
459 fprintf(stderr,"couldn't find mnemonic\n");
465 /*-----------------------------------------------------------------*/
466 /*-----------------------------------------------------------------*/
467 static void * cvt_altpat_mnem1b(void *pp)
469 parsedPattern *p = pp;
472 pCodeInstruction *pci=NULL;
474 DFPRINTF((stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n));
476 opcode = getpCode(p->pct[0].tok.s,0);
478 fprintf(stderr, "Bad mnemonic\n");
482 pci = PCI(newpCode(opcode, newpCodeOpLit(p[1].pct[0].tok.n) ));
485 fprintf(stderr,"couldn't find mnemonic\n");
491 /*-----------------------------------------------------------------*/
492 /*-----------------------------------------------------------------*/
493 static void * cvt_altpat_mnem2(void *pp)
495 parsedPattern *p = pp;
499 pCodeInstruction *pci=NULL;
502 dest = cvt_extract_destination(&p[3]);
504 DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
511 opcode = getpCode(p->pct[0].tok.s,dest);
513 fprintf(stderr, "Bad mnemonic\n");
517 if(pic14Mnemonics[opcode]->isBitInst) {
518 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
519 if(pcosubtype == NULL) {
520 fprintf(stderr, "bad operand?\n");
525 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
528 pci = PCI(newpCode(opcode,pcosubtype));
531 fprintf(stderr,"couldn't find mnemonic\n");
537 /*-----------------------------------------------------------------*/
538 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
539 /* instruction with 1 wild operand and a */
540 /* destination operand (e.g. w or f) */
543 /* pp[1] - wild var */
545 /* pp[3] - destination */
547 /*-----------------------------------------------------------------*/
548 static void * cvt_altpat_mnem2a(void *pp)
550 parsedPattern *p = pp;
554 pCodeInstruction *pci=NULL;
557 dest = cvt_extract_destination(&p[3]);
559 DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
566 opcode = getpCode(p->pct[0].tok.s,dest);
568 fprintf(stderr, "Bad mnemonic\n");
572 if(pic14Mnemonics[opcode]->isBitInst)
573 pcosubtype = newpCodeOp(NULL,PO_BIT);
575 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
578 pci = PCI(newpCode(opcode,
579 newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
581 /* Save the index of the maximum wildcard variable */
582 if(p[1].pct[1].tok.n > sMaxWildVar)
583 sMaxWildVar = p[1].pct[1].tok.n;
586 fprintf(stderr,"couldn't find mnemonic\n");
592 /*-----------------------------------------------------------------*/
593 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
594 /* by SDCCpeeph.c into a string of tokens. */
597 /* The tokenizer is of the classic type. When an item is encounterd*/
598 /* it is converted into a token. The token is a structure that */
599 /* encodes the item's type and it's value (when appropriate). */
601 /* Accepted token types: */
602 /* SPACE NUMBER STRING % : , ; */
606 /*-----------------------------------------------------------------*/
609 static void tokenizeLineNode(char *ln)
612 tokIdx = 0; // Starting off at the beginning
613 tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
621 // add a SPACE token and eat the extra spaces.
622 tokArr[tokIdx++].tt = PCT_SPACE;
623 while (isspace (*ln))
630 tokArr[tokIdx].tt = PCT_NUMBER;
631 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
639 tokArr[tokIdx++].tt = PCT_PERCENT;
642 tokArr[tokIdx++].tt = PCT_COLON;
645 tokArr[tokIdx].tok.s = Safe_strdup(ln);
646 tokArr[tokIdx++].tt = PCT_COMMENT;
647 tokArr[tokIdx].tt = PCT_NULL;
650 tokArr[tokIdx++].tt = PCT_COMMA;
659 while( (isalpha(*ln) || isdigit(*ln)) && i<49)
665 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
666 tokArr[tokIdx++].tt = PCT_STRING;
671 /* Advance to next character in input string .
672 * Note, if none of the tests passed above, then
673 * we effectively ignore the `bad' character.
674 * Since the line has already been parsed by SDCCpeeph,
675 * chance are that there are no invalid characters... */
681 tokArr[tokIdx].tt = 0;
685 /*-----------------------------------------------------------------*/
686 /*-----------------------------------------------------------------*/
690 void dump1Token(pCodeTokens tt)
695 fprintf(stderr, " space ");
698 fprintf(stderr, " pct ");
702 fprintf(stderr, " col ");
706 fprintf(stderr, " comma , ");
709 fprintf(stderr, " comment ");
710 //fprintf(stderr,"%s",tokArr[i].tok.s);
713 fprintf(stderr, " str ");
714 //fprintf(stderr,"%s",tokArr[i].tok.s);
717 fprintf(stderr, " num ");
718 //fprintf(stderr,"%d",tokArr[i].tok.n);
721 fprintf(stderr, " null ");
728 /*-----------------------------------------------------------------*/
729 /*-----------------------------------------------------------------*/
731 int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
735 if(!pct || !pat || !*pat)
738 //DFPRINTF((stderr,"comparing against:\n"));
740 while(i < max_tokens) {
743 //DFPRINTF((stderr,"matched\n"));
747 //dump1Token(*pat); DFPRINTF((stderr,"\n"));
761 /*-----------------------------------------------------------------*/
762 /*-----------------------------------------------------------------*/
764 int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
768 if(!pct || !pat || !*pct)
772 while(i < max_tokens) {
775 //DFPRINTF((stderr,"matched\n"));
779 //dump1Token(*pat); DFPRINTF((stderr,"\n"));
781 if( !pat || !pat->pcp )
784 if (pat->pcp->pt != *pct)
787 //DFPRINTF((stderr," pct=%d\n",*pct));
796 /*-----------------------------------------------------------------*/
797 /*-----------------------------------------------------------------*/
799 int advTokIdx(int *v, int amt)
802 if((unsigned) (*v + amt) > tokIdx)
810 /*-----------------------------------------------------------------*/
811 /* parseTokens - convert the tokens corresponding to a single line */
812 /* of a peep hole assembly into a pCode object. */
817 /* This is a simple parser that looks for strings of the type */
818 /* allowed in the peep hole definition file. Essentially the format*/
819 /* is the same as a line of assembly: */
821 /* label: mnemonic op1, op2, op3 ; comment */
823 /* Some of these items aren't present. It's the job of the parser */
824 /* to determine which are and convert those into the appropriate */
826 /*-----------------------------------------------------------------*/
828 void parseTokens(void)
836 for(i=0; i<=tokIdx; i++)
837 dump1Token(tokArr[i].tt);
849 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
850 char * cP1stop = NULL;
851 char * cP2ndop = NULL;
853 //pCodeOp *pcl = NULL; // Storage for a label
854 //pCodeOp *pco1 = NULL; // 1st operand
855 //pCodeOp *pco2 = NULL; // 2nd operand
856 //pCode *pc = NULL; // Mnemonic
867 ParseStates state = PS_START;
874 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
875 && (advTokIdx(<okIdx, 1)) ) // eat space
879 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
882 switch(pcpArr[lpcpIdx].pt) {
884 if(state == PS_START){
885 DFPRINTF((stderr," label\n"));
886 state = PS_HAVE_LABEL;
888 DFPRINTF((stderr," bad state (%d) for label\n",state));
892 DFPRINTF((stderr," %s is",tokArr[ltokIdx].tok.s));
896 DFPRINTF((stderr," mnem\n"));
897 cPmnem = tokArr[ltokIdx].tok.s;
898 state = PS_HAVE_MNEM;
901 DFPRINTF((stderr," 1st operand\n"));
902 cP1stop = tokArr[ltokIdx].tok.s;
903 //pco1 = newpCodeOp(NULL,PO_GPR_REGISTER);
904 state = PS_HAVE_1OPERAND;
906 case PS_HAVE_1OPERAND:
907 DFPRINTF((stderr," error expecting comma\n"));
910 DFPRINTF((stderr," 2 operands\n"));
911 cP2ndop = tokArr[ltokIdx].tok.s;
913 case PS_HAVE_2OPERANDS:
922 DFPRINTF((stderr," wild mnem\n"));
923 state = PS_HAVE_MNEM;
926 DFPRINTF((stderr," 1st operand is wild\n"));
927 state = PS_HAVE_1OPERAND;
929 case PS_HAVE_1OPERAND:
930 DFPRINTF((stderr," error expecting comma\n"));
933 DFPRINTF((stderr," 2nd operand is wild\n"));
935 case PS_HAVE_2OPERANDS:
944 fprintf(stderr," ERROR number\n");
947 DFPRINTF((stderr," 1st operand is a number\n"));
948 state = PS_HAVE_1OPERAND;
950 case PS_HAVE_1OPERAND:
951 fprintf(stderr," error expecting comma\n");
954 DFPRINTF((stderr," 2nd operand is a number\n"));
956 case PS_HAVE_2OPERANDS:
964 if(state == PS_HAVE_1OPERAND){
965 DFPRINTF((stderr," got a comma\n"));
966 state = PS_HAVE_COMMA;
968 fprintf(stderr," unexpected comma\n");
972 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
973 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
976 //dump1Token(tokArr[ltokIdx].tt);
978 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
979 DFPRINTF((stderr," reached end \n"));
986 } while ((++lpcpIdx < PCPATTERNS) && !matching);
990 parsedPatArr[lparsedPatIdx].pcp = NULL;
991 parsedPatArr[lparsedPatIdx].pct = NULL;
997 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1000 pc = altArr[k].f(&parsedPatArr[j]);
1001 //if(pc && pc->print)
1002 // pc->print(stderr,pc);
1003 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1005 addpCode2pBlock(curBlock, pc);
1011 while(j<=lparsedPatIdx && k<ALTPATTERNS);
1014 DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1018 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1019 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1020 DFPRINTF((stderr," %d",parsedPatArr[j].pcp->pt));
1023 while(j<lparsedPatIdx);
1025 DFPRINTF((stderr,"\n"));
1032 /*-----------------------------------------------------------------*/
1034 /*-----------------------------------------------------------------*/
1035 void peepRuleBlock2pCodeBlock( lineNode *ln)
1041 for( ; ln; ln = ln->next) {
1043 //DFPRINTF((stderr,"%s\n",ln->line));
1045 tokenizeLineNode(ln->line);
1051 /*-----------------------------------------------------------------*/
1052 /* peepRuleCondition */
1053 /*-----------------------------------------------------------------*/
1054 static void peepRuleCondition(char *cond)
1059 //DFPRINTF((stderr,"\nCondition: %s\n",cond));
1061 /* brute force compares for now */
1063 if(STRCASECMP(cond, "NZ") == 0) {
1064 //DFPRINTF((stderr,"found NZ\n"));
1065 curPeep->postFalseCond = PCC_Z;
1070 /*-----------------------------------------------------------------*/
1071 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1074 /* SDCCpeeph parses the peep rules file and extracts variables, */
1075 /* removes white space, and checks the syntax. This function */
1076 /* extends that processing to produce pCode objects. You can kind */
1077 /* think of this function as an "assembler", though instead of */
1078 /* taking raw text to produce machine code, it produces pCode. */
1080 /*-----------------------------------------------------------------*/
1082 void peepRules2pCode(peepRule *rules)
1086 pCodePeepSnippets *pcps;
1088 /* The rules are in a linked-list. Each rule has two portions */
1089 /* There's the `target' and there's the `replace'. The target */
1090 /* is compared against the SDCC generated code and if it */
1091 /* matches, it gets replaced by the `replace' block of code. */
1093 /* Here we loop through each rule and convert the target's and*/
1094 /* replace's into pCode target and replace blocks */
1096 for (pr = rules; pr; pr = pr->next) {
1098 //DFPRINTF((stderr,"\nRule:\n\n"));
1100 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1101 curPeep = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1103 curPeep->vars = NULL;
1104 curPeep->wildpCodes = NULL; curPeep->wildpCodeOps = NULL;
1105 curPeep->postFalseCond = PCC_NONE;
1106 curPeep->postTrueCond = PCC_NONE;
1108 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1110 curPeep->target = curBlock = newpCodeChain(NULL, 'W', NULL);
1114 /* Convert the target block */
1115 peepRuleBlock2pCodeBlock(pr->match);
1117 //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1118 //printpBlock(stderr, curBlock);
1120 //DFPRINTF((stderr,"target with labels merged:\n"));
1121 pBlockMergeLabels(curBlock);
1123 printpBlock(stderr, curBlock);
1126 //DFPRINTF((stderr,"\nReplaced by:\n"));
1129 curPeep->replace = curBlock = newpCodeChain(NULL, 'W', NULL);
1131 /* Convert the replace block */
1132 peepRuleBlock2pCodeBlock(pr->replace);
1134 //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1135 //printpBlock(stderr, curBlock);
1137 //DFPRINTF((stderr,"replace with labels merged:\n"));
1138 pBlockMergeLabels(curBlock);
1139 //printpBlock(stderr, curBlock);
1141 peepRuleCondition(pr->cond);
1143 /* The rule has been converted to pCode. Now allocate
1144 * space for the wildcards */
1147 curPeep->nvars = sMaxWildVar;
1148 curPeep->vars = Safe_calloc(sMaxWildVar, sizeof(char *));
1150 curPeep->nops = sMaxWildVar;
1151 curPeep->wildpCodeOps = Safe_calloc(sMaxWildVar, sizeof(pCodeOp *));
1153 curPeep->nwildpCodes = ++sMaxWildMnem;
1154 curPeep->wildpCodes = Safe_calloc(sMaxWildMnem, sizeof(char *));
1157 //return; // debug ... don't want to go through all the rules yet
1162 void printpCodeString(FILE *of, pCode *pc, int max)
1166 while(pc && (i++<max)) {
1172 /*-----------------------------------------------------------------*/
1173 /* _DLL * DLL_append */
1175 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1176 /* If The list to which we want to append is non-existant then one */
1177 /* is created. Other wise, the end of the list is sought out and */
1178 /* a new DLL object is appended to it. In either case, the void */
1179 /* *data is added to the newly created DLL object. */
1180 /*-----------------------------------------------------------------*/
1182 static void * DLL_append(_DLL *list, _DLL *next)
1187 /* If there's no list, then create one: */
1189 next->next = next->prev = NULL;
1194 /* Search for the end of the list. */
1199 /* Now append the new DLL object */
1210 /*-----------------------------------------------------------------
1212 pCode peephole optimization
1215 The pCode "peep hole" optimization is not too unlike the peep hole
1216 optimization in SDCCpeeph.c. The major difference is that here we
1217 use pCode's whereas there we use ASCII strings. The advantage with
1218 pCode's is that we can ascertain flow information in the instructions
1222 <FIX ME> - elaborate...
1224 -----------------------------------------------------------------*/
1228 /*-----------------------------------------------------------------*/
1229 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1231 /* return conditions */
1232 /* 1 - The Condition was found for a pCode's input */
1233 /* 0 - No matching condition was found for the whole chain */
1234 /* -1 - The Condition was found for a pCode's output */
1236 /*-----------------------------------------------------------------*/
1237 int pCodeSearchCondition(pCode *pc, unsigned int cond)
1242 /* If we reach a function end (presumably an end since we most
1243 probably began the search in the middle of a function), then
1244 the condition was not found. */
1245 if(pc->type == PC_FUNCTION)
1248 if(pc->type == PC_OPCODE) {
1249 if(PCI(pc)->inCond & cond)
1251 if(PCI(pc)->outCond & cond)
1261 int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1265 /* Check for a label associated with this wild pCode */
1266 // If the wild card has a label, make sure the source code does too.
1267 if(PCI(pcd)->label) {
1270 if(!PCI(pcs)->label)
1273 pcl = PCI(pcd)->label->pc;
1275 labindex = -PCL(pcl)->key;
1276 //DFPRINTF((stderr,"label id = %d (labindex = %d)\n",PCL(pcl)->key,labindex));
1277 if(peepBlock->vars[labindex] == NULL) {
1278 // First time to encounter this label
1279 peepBlock->vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1280 //DFPRINTF((stderr,"first time for a label: %d %s\n",labindex, peepBlock->vars[labindex]));
1282 if(strcmp(peepBlock->vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1283 // DFPRINTF((stderr,"labels don't match\n"));
1286 //DFPRINTF((stderr,"matched a label\n"));
1289 // DFPRINTF((stderr,"destination doesn't have a label\n"));
1299 /*-----------------------------------------------------------------*/
1300 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1301 /* see they're the same. */
1303 /* In this context, "source" refers to the coded generated by gen.c*/
1304 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1305 /* ination has no wild cards, then MatchLine will compare the two */
1306 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1307 /* has wildcards, then those get expanded. When a wild card is */
1308 /* encountered for the first time it autmatically is considered a */
1309 /* match and the object that matches it is referenced in the */
1310 /* variables or opcodes array (depending on the type of match). */
1314 /* *peepBlock - A pointer to the peepBlock that contains the */
1315 /* entire rule to which the destination pcode belongs*/
1316 /* *pcs - a pointer to the source pcode */
1317 /* *pcd - a pointer to the destination pcode */
1320 /* 1 - pcodes match */
1321 /* 0 - pcodes don't match */
1324 /*-----------------------------------------------------------------*/
1326 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1328 int index; // index into wild card arrays
1330 if(pcs->type == pcd->type) {
1332 if(pcs->type == PC_OPCODE) {
1334 /* If the opcodes don't match then the line doesn't match */
1335 if(PCI(pcs)->op != PCI(pcd)->op)
1339 DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1340 pcs->print(stderr,pcs);
1341 pcd->print(stderr,pcd);
1344 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1347 /* Compare the operands */
1348 if(PCI(pcd)->pcop) {
1349 if (PCI(pcd)->pcop->type == PO_WILD) {
1350 index = PCOW(PCI(pcd)->pcop)->id;
1352 //DFPRINTF((stderr,"destination is wild\n"));
1353 #ifdef DEBUG_PCODEPEEP
1354 if (index > peepBlock->nops) {
1355 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1359 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1360 if(!peepBlock->wildpCodeOps[index]) {
1361 peepBlock->wildpCodeOps[index] = PCI(pcs)->pcop;
1363 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1369 switch(PCI(pcs)->pcop->type) {
1373 n = PCOR(PCI(pcs)->pcop)->r->name;
1377 n = PCI(pcs)->pcop->name;
1380 if(peepBlock->vars[index])
1381 return (strcmp(peepBlock->vars[index],n) == 0);
1383 // DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1384 peepBlock->vars[index] = n;
1389 /* FIXME - need an else to check the case when the destination
1390 * isn't a wild card */
1392 /* The pcd has no operand. Lines match if pcs has no operand either*/
1393 return (PCI(pcs)->pcop == NULL);
1398 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1401 index = PCW(pcd)->id;
1403 // DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
1404 //pcs->print(stderr,pcs);
1405 //pcd->print(stderr,pcd);
1407 peepBlock->wildpCodes[PCW(pcd)->id] = pcs;
1409 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1412 if(PCW(pcd)->operand) {
1413 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1414 if(peepBlock->vars[index]) {
1415 int i = (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
1418 DFPRINTF((stderr," (matched)\n"));
1420 DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
1421 DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n"),
1422 peepBlock->vars[index],
1423 PCI(pcs)->pcop->name);
1428 peepBlock->vars[index] = PCI(pcs)->pcop->name;
1433 pcs = findNextInstruction(pcs->next);
1435 //DFPRINTF((stderr," (next to match)\n"));
1436 //pcs->print(stderr,pcs);
1437 } else if(pcd->next) {
1438 /* oops, we ran out of code, but there's more to the rule */
1442 return 1; /* wild card matches */
1448 /*-----------------------------------------------------------------*/
1449 /*-----------------------------------------------------------------*/
1450 void pCodePeepClrVars(pCodePeep *pcp)
1457 for(i=0;i<pcp->nvars; i++) {
1458 pcp->vars[i] = NULL;
1459 pcp->wildpCodeOps[i] = NULL;
1463 /*-----------------------------------------------------------------*/
1464 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
1465 /* into the pCode chain containing pc1 */
1466 /*-----------------------------------------------------------------*/
1467 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
1473 pc2->next = pc1->next;
1475 pc1->next->prev = pc2;
1483 /*-----------------------------------------------------------------*/
1484 /* pCodeOpCopy - copy a pcode operator */
1485 /*-----------------------------------------------------------------*/
1486 static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
1488 pCodeOp *pcopnew=NULL;
1493 switch(pcop->type) {
1496 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
1497 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1498 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
1499 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
1504 /* Here we expand the wild card into the appropriate type: */
1505 /* By recursively calling pCodeOpCopy */
1506 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
1507 if(PCOW(pcop)->matched)
1508 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
1511 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
1512 pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
1513 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
1520 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
1521 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1522 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
1527 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
1528 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1529 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1532 case PO_GPR_REGISTER:
1537 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
1538 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1539 PCOR(pcopnew)->r = PCOR(pcop)->r;
1540 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1541 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
1545 //DFPRINTF((stderr,"pCodeOpCopy PO_DIR\n"));
1546 case PO_SFR_REGISTER:
1555 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
1556 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1560 pcopnew->type = pcop->type;
1562 pcopnew->name = Safe_strdup(pcop->name);
1564 pcopnew->name = NULL;
1570 /*-----------------------------------------------------------------*/
1571 /* pCodeCopy - copy a pcode */
1572 /*-----------------------------------------------------------------*/
1573 static pCode *pCodeCopy(pCode *pc)
1578 pcnew = newpCode(pc->type,pc->pcop);
1581 /*-----------------------------------------------------------------*/
1582 /*-----------------------------------------------------------------*/
1583 void pCodeDeleteChain(pCode *f,pCode *t)
1589 DFPRINTF((stderr,"delete pCode:\n"));
1592 //f->delete(f); this dumps core...
1599 /*-----------------------------------------------------------------*/
1600 /*-----------------------------------------------------------------*/
1601 int pCodePeepMatchRule(pCode *pc)
1603 pCodePeep *peepBlock;
1608 peeprules = (_DLL *)peepSnippets;
1611 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1612 if(!peepBlock || !peepBlock->target || !peepBlock->target->pcHead)
1615 pCodePeepClrVars(peepBlock);
1618 pct = peepBlock->target->pcHead;
1620 while(pct && pcin) {
1622 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1625 pcin = findNextInstruction(pcin->next);
1628 //DFPRINTF((stderr," matched\n"));
1630 DFPRINTF((stderr," end of code\n"));
1632 DFPRINTF((stderr," end of rule\n"));
1637 /* So far we matched the rule up to the point of the conditions .
1638 * In other words, all of the opcodes match. Now we need to see
1639 * if the post conditions are satisfied.
1640 * First we check the 'postFalseCond'. This means that we check
1641 * to see if any of the subsequent pCode's in the pCode chain
1642 * following the point just past where we have matched depend on
1643 * the `postFalseCond' as input then we abort the match
1645 DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
1646 if (pcin && peepBlock->postFalseCond &&
1647 (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
1657 /* We matched a rule! Now we have to go through and remove the
1658 inefficient code with the optimized version */
1660 DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
1661 printpCodeString(stderr,peepBlock->target->pcHead,10);
1662 DFPRINTF((stderr,"first thing matched\n"));
1663 pc->print(stderr,pc);
1666 DFPRINTF((stderr,"last thing matched\n"));
1667 pcin->print(stderr,pcin);
1670 /* Unlink the original code */
1672 pcprev->next = pcin;
1674 pcin->prev = pc->prev;
1678 /* Converted the deleted pCodes into comments */
1685 while(pc && pc!=pcin) {
1686 pCode2str(&buf[2], 254, pc);
1687 pCodeInsertAfter(pcprev, newpCodeCharP(buf));
1688 pcprev = pcprev->next;
1694 pCodeDeleteChain(pc,pcin);
1696 /* Generate the replacement code */
1698 pcr = peepBlock->replace->pcHead; // This is the replacement code
1701 /* If the replace pcode is an instruction with an operand, */
1702 /* then duplicate the operand (and expand wild cards in the process). */
1703 if(pcr->type == PC_OPCODE) {
1704 if(PCI(pcr)->pcop) {
1705 /* The replacing instruction has an operand.
1707 if(PCI(pcr)->pcop->type == PO_WILD) {
1708 int index = PCOW(PCI(pcr)->pcop)->id;
1709 //DFPRINTF((stderr,"copying wildopcode\n"));
1710 if(peepBlock->wildpCodeOps[index])
1711 pcop = pCodeOpCopy(peepBlock->wildpCodeOps[index]);
1713 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
1715 pcop = pCodeOpCopy(PCI(pcr)->pcop);
1717 //DFPRINTF((stderr,"inserting pCode\n"));
1718 pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
1719 } else if (pcr->type == PC_WILD) {
1720 pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
1721 } else if (pcr->type == PC_COMMENT) {
1722 pCodeInsertAfter(pc, newpCodeCharP( ((pCodeComment *)(pcr))->comment));
1728 // pc->print(stderr,pc);
1735 peeprules = peeprules->next;