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
31 #if defined(__BORLANDC__) || defined(_MSC_VER)
32 #define STRCASECMP stricmp
34 #define STRCASECMP strcasecmp
37 pCodeOp *popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
40 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype);
41 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
42 pCode * findNextInstruction(pCode *pc);
43 int getpCode(char *mnem,int dest);
44 void pBlockMergeLabels(pBlock *pb);
45 char *pCode2str(char *str, int size, pCode *pc);
47 extern pCodeInstruction *pic14Mnemonics[];
50 /****************************************************************/
52 * rootRules - defined in SDCCpeep.c
53 * This is a pointer to the (parsed) peephole rules that are
54 * defined in peep.def.
57 //extern peepRule *rootRules;
62 /****************************************************************/
63 /****************************************************************/
71 typedef struct pCodePeepSnippets
78 /****************************************************************/
82 /****************************************************************/
84 static pCodePeepSnippets *peepSnippets=NULL;
86 /****************************************************************/
90 /****************************************************************/
92 static pCodePeep *curPeep=NULL;
94 /****************************************************************/
98 /****************************************************************/
100 static pBlock *curBlock=NULL;
103 /****************************************************************/
105 /* max wild cards in a peep rule */
107 /****************************************************************/
109 static int sMaxWildVar = 0;
110 static int sMaxWildMnem = 0;
113 typedef struct pCodeToken
115 int tt; // token type;
124 pCodeToken tokArr[50];
141 typedef struct parsedPattern {
142 struct pcPattern *pcp;
146 #define MAX_PARSEDPATARR 50
147 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
148 unsigned int parsedPatIdx=0;
161 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
162 static char pcpat_number[] = {PCT_NUMBER, 0};
163 static char pcpat_string[] = {PCT_STRING, 0};
164 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
165 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
166 static char pcpat_comma[] = {PCT_COMMA, 0};
167 static char pcpat_comment[] = {PCT_COMMENT, 0};
170 typedef struct pcPattern {
171 char pt; // Pattern type
172 char *tokens; // list of tokens that describe the pattern
173 void * (*f) (void *);
176 pcPattern pcpArr[] = {
177 {PCP_LABEL, pcpat_label, NULL},
178 {PCP_WILDSTR, pcpat_wildString, NULL},
179 {PCP_STR, pcpat_string, NULL},
180 {PCP_WILDVAR, pcpat_wildVar, NULL},
181 {PCP_COMMA, pcpat_comma, NULL},
182 {PCP_COMMENT, pcpat_comment, NULL},
183 {PCP_NUMBER, pcpat_number, NULL}
186 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
188 // Assembly Line Token
201 static char alt_comment[] = { PCP_COMMENT, 0};
202 static char alt_label[] = { PCP_LABEL, 0};
203 static char alt_mnem0[] = { PCP_STR, 0};
204 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
205 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
206 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
207 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
208 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
209 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
211 static void * cvt_altpat_label(void *pp);
212 static void * cvt_altpat_comment(void *pp);
213 static void * cvt_altpat_mnem0(void *pp);
214 static void * cvt_altpat_mnem0a(void *pp);
215 static void * cvt_altpat_mnem1(void *pp);
216 static void * cvt_altpat_mnem1a(void *pp);
217 static void * cvt_altpat_mnem1b(void *pp);
218 static void * cvt_altpat_mnem2(void *pp);
219 static void * cvt_altpat_mnem2a(void *pp);
221 pcPattern altArr[] = {
222 {ALT_LABEL, alt_label, cvt_altpat_label},
223 {ALT_COMMENT, alt_comment,cvt_altpat_comment},
224 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
225 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
226 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
227 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
228 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
229 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
230 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
234 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
236 // forward declarations
237 static void * DLL_append(_DLL *list, _DLL *next);
239 /*-----------------------------------------------------------------*/
240 /* cvt_extract_destination - helper function extracts the register */
241 /* destination from a parsedPattern. */
243 /*-----------------------------------------------------------------*/
244 static int cvt_extract_destination(parsedPattern *pp)
247 if(pp->pct[0].tt == PCT_STRING) {
249 // just check first letter for now
251 if(toupper(*pp->pct[0].tok.s) == 'F')
254 } else if (pp->pct[0].tt == PCT_NUMBER) {
264 /*-----------------------------------------------------------------*/
265 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
266 /* if *reg is the "status" register and *bit is one of the */
267 /* status bits, then this function will create a new pCode op */
268 /* containing the status register. */
269 /*-----------------------------------------------------------------*/
271 static pCodeOp *cvt_extract_status(char *reg, char *bit)
275 if(STRCASECMP(reg, pc_status.pcop.name))
282 if(toupper(*bit) == 'C')
283 return PCOP(popCopyGPR2Bit(&pc_status,PIC_C_BIT));
284 if(toupper(*bit) == 'Z')
285 return PCOP(popCopyGPR2Bit(&pc_status,PIC_Z_BIT));
289 if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
290 return PCOP(popCopyGPR2Bit(&pc_status,PIC_DC_BIT));
296 /*-----------------------------------------------------------------*/
297 /* cvt_altpat_label - convert assembly line type to a pCode label */
298 /* INPUT: pointer to the parsedPattern */
302 /* label pattern => '%' number ':' */
303 /* at this point, we wish to extract only the 'number' */
305 /*-----------------------------------------------------------------*/
306 static void * cvt_altpat_label(void *pp)
308 parsedPattern *p = pp;
310 DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
311 return newpCodeLabel(-p->pct[1].tok.n);
315 /*-----------------------------------------------------------------*/
316 /* cvt_altpat_comment - convert assembly line type to a comment */
317 /* INPUT: pointer to the parsedPattern */
319 /* pp[0] - comment */
322 /*-----------------------------------------------------------------*/
323 static void * cvt_altpat_comment(void *pp)
325 parsedPattern *p = pp;
327 DFPRINTF((stderr,"altpat_comment = %s\n",p->pct[0].tok.s));
328 return newpCodeCharP(p->pct[0].tok.s);
332 /*-----------------------------------------------------------------*/
333 /*-----------------------------------------------------------------*/
334 static void * cvt_altpat_mnem0(void *pp)
336 parsedPattern *p = pp;
339 pCodeInstruction *pci=NULL;
341 DFPRINTF((stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s));
343 opcode = getpCode(p->pct[0].tok.s,0);
345 fprintf(stderr, "Bad mnemonic\n");
349 pci = PCI(newpCode(opcode, NULL));
352 fprintf(stderr,"couldn't find mnemonic\n");
358 /*-----------------------------------------------------------------*/
359 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
362 /* pp[0] - wild var */
364 /*-----------------------------------------------------------------*/
365 static void * cvt_altpat_mnem0a(void *pp)
367 parsedPattern *p = pp;
369 DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n));
371 /* Save the index of the maximum wildcard mnemonic */
373 if(p[0].pct[1].tok.n > sMaxWildVar)
374 sMaxWildMnem = p[0].pct[1].tok.n;
376 return newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
380 /*-----------------------------------------------------------------*/
381 /* cvt_altpat_mem1 - convert assembly line type to a pCode */
382 /* instruction with 1 operand. */
385 /* pp[1] - Operand */
387 /*-----------------------------------------------------------------*/
388 static void * cvt_altpat_mnem1(void *pp)
391 parsedPattern *p = pp;
394 pCodeInstruction *pci=NULL;
397 DFPRINTF((stderr,"altpat_mnem1 %s var %s\n", p->pct[0].tok.s,p[1].pct[0].tok.s));
399 opcode = getpCode(p->pct[0].tok.s,0);
401 fprintf(stderr, "Bad mnemonic\n");
405 if(pic14Mnemonics[opcode]->bit_inst)
406 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
408 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
411 pci = PCI(newpCode(opcode, pcosubtype));
414 fprintf(stderr,"couldn't find mnemonic\n");
420 /*-----------------------------------------------------------------*/
421 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
422 /* instruction with 1 wild operand. */
425 /* pp[1] - wild var */
427 /*-----------------------------------------------------------------*/
428 static void * cvt_altpat_mnem1a(void *pp)
430 parsedPattern *p = pp;
433 pCodeInstruction *pci=NULL;
436 DFPRINTF((stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n));
438 opcode = getpCode(p->pct[0].tok.s,0);
440 fprintf(stderr, "Bad mnemonic\n");
444 if(pic14Mnemonics[opcode]->bit_inst)
445 pcosubtype = newpCodeOpBit(NULL,-1,0);
447 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
450 pci = PCI(newpCode(opcode,
451 newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
453 /* Save the index of the maximum wildcard variable */
454 if(p[1].pct[1].tok.n > sMaxWildVar)
455 sMaxWildVar = p[1].pct[1].tok.n;
458 fprintf(stderr,"couldn't find mnemonic\n");
464 /*-----------------------------------------------------------------*/
465 /*-----------------------------------------------------------------*/
466 static void * cvt_altpat_mnem1b(void *pp)
468 parsedPattern *p = pp;
471 pCodeInstruction *pci=NULL;
473 DFPRINTF((stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n));
475 opcode = getpCode(p->pct[0].tok.s,0);
477 fprintf(stderr, "Bad mnemonic\n");
481 pci = PCI(newpCode(opcode, newpCodeOpLit(p[1].pct[0].tok.n) ));
484 fprintf(stderr,"couldn't find mnemonic\n");
490 /*-----------------------------------------------------------------*/
491 /*-----------------------------------------------------------------*/
492 static void * cvt_altpat_mnem2(void *pp)
494 parsedPattern *p = pp;
498 pCodeInstruction *pci=NULL;
501 dest = cvt_extract_destination(&p[3]);
503 DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
510 opcode = getpCode(p->pct[0].tok.s,dest);
512 fprintf(stderr, "Bad mnemonic\n");
516 if(pic14Mnemonics[opcode]->bit_inst) {
517 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
518 if(pcosubtype == NULL) {
519 fprintf(stderr, "bad operand?\n");
524 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
527 pci = PCI(newpCode(opcode,pcosubtype));
530 fprintf(stderr,"couldn't find mnemonic\n");
536 /*-----------------------------------------------------------------*/
537 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
538 /* instruction with 1 wild operand and a */
539 /* destination operand (e.g. w or f) */
542 /* pp[1] - wild var */
544 /* pp[3] - destination */
546 /*-----------------------------------------------------------------*/
547 static void * cvt_altpat_mnem2a(void *pp)
549 parsedPattern *p = pp;
553 pCodeInstruction *pci=NULL;
556 dest = cvt_extract_destination(&p[3]);
558 DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
565 opcode = getpCode(p->pct[0].tok.s,dest);
567 fprintf(stderr, "Bad mnemonic\n");
571 if(pic14Mnemonics[opcode]->bit_inst)
572 pcosubtype = newpCodeOp(NULL,PO_BIT);
574 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
577 pci = PCI(newpCode(opcode,
578 newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
580 /* Save the index of the maximum wildcard variable */
581 if(p[1].pct[1].tok.n > sMaxWildVar)
582 sMaxWildVar = p[1].pct[1].tok.n;
585 fprintf(stderr,"couldn't find mnemonic\n");
591 /*-----------------------------------------------------------------*/
592 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
593 /* by SDCCpeeph.c into a string of tokens. */
596 /* The tokenizer is of the classic type. When an item is encounterd*/
597 /* it is converted into a token. The token is a structure that */
598 /* encodes the item's type and it's value (when appropriate). */
600 /* Accepted token types: */
601 /* SPACE NUMBER STRING % : , ; */
605 /*-----------------------------------------------------------------*/
608 static void tokenizeLineNode(char *ln)
611 tokIdx = 0; // Starting off at the beginning
612 tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
620 // add a SPACE token and eat the extra spaces.
621 tokArr[tokIdx++].tt = PCT_SPACE;
622 while (isspace (*ln))
629 tokArr[tokIdx].tt = PCT_NUMBER;
630 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
638 tokArr[tokIdx++].tt = PCT_PERCENT;
641 tokArr[tokIdx++].tt = PCT_COLON;
644 tokArr[tokIdx].tok.s = Safe_strdup(ln);
645 tokArr[tokIdx++].tt = PCT_COMMENT;
646 tokArr[tokIdx].tt = PCT_NULL;
649 tokArr[tokIdx++].tt = PCT_COMMA;
658 while( (isalpha(*ln) || isdigit(*ln)) && i<49)
664 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
665 tokArr[tokIdx++].tt = PCT_STRING;
670 /* Advance to next character in input string .
671 * Note, if none of the tests passed above, then
672 * we effectively ignore the `bad' character.
673 * Since the line has already been parsed by SDCCpeeph,
674 * chance are that there are no invalid characters... */
680 tokArr[tokIdx].tt = 0;
684 /*-----------------------------------------------------------------*/
685 /*-----------------------------------------------------------------*/
689 void dump1Token(pCodeTokens tt)
694 fprintf(stderr, " space ");
697 fprintf(stderr, " pct ");
701 fprintf(stderr, " col ");
705 fprintf(stderr, " comma , ");
708 fprintf(stderr, " comment ");
709 //fprintf(stderr,"%s",tokArr[i].tok.s);
712 fprintf(stderr, " str ");
713 //fprintf(stderr,"%s",tokArr[i].tok.s);
716 fprintf(stderr, " num ");
717 //fprintf(stderr,"%d",tokArr[i].tok.n);
720 fprintf(stderr, " null ");
727 /*-----------------------------------------------------------------*/
728 /*-----------------------------------------------------------------*/
730 int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
734 if(!pct || !pat || !*pat)
737 //DFPRINTF((stderr,"comparing against:\n"));
739 while(i < max_tokens) {
742 //DFPRINTF((stderr,"matched\n"));
746 //dump1Token(*pat); DFPRINTF((stderr,"\n"));
760 /*-----------------------------------------------------------------*/
761 /*-----------------------------------------------------------------*/
763 int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
767 if(!pct || !pat || !*pct)
771 while(i < max_tokens) {
774 //DFPRINTF((stderr,"matched\n"));
778 //dump1Token(*pat); DFPRINTF((stderr,"\n"));
780 if( !pat || !pat->pcp )
783 if (pat->pcp->pt != *pct)
786 //DFPRINTF((stderr," pct=%d\n",*pct));
795 /*-----------------------------------------------------------------*/
796 /*-----------------------------------------------------------------*/
798 int advTokIdx(int *v, int amt)
801 if((unsigned) (*v + amt) > tokIdx)
809 /*-----------------------------------------------------------------*/
810 /* parseTokens - convert the tokens corresponding to a single line */
811 /* of a peep hole assembly into a pCode object. */
816 /* This is a simple parser that looks for strings of the type */
817 /* allowed in the peep hole definition file. Essentially the format*/
818 /* is the same as a line of assembly: */
820 /* label: mnemonic op1, op2, op3 ; comment */
822 /* Some of these items aren't present. It's the job of the parser */
823 /* to determine which are and convert those into the appropriate */
825 /*-----------------------------------------------------------------*/
827 void parseTokens(void)
835 for(i=0; i<=tokIdx; i++)
836 dump1Token(tokArr[i].tt);
848 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
849 char * cP1stop = NULL;
850 char * cP2ndop = NULL;
852 //pCodeOp *pcl = NULL; // Storage for a label
853 //pCodeOp *pco1 = NULL; // 1st operand
854 //pCodeOp *pco2 = NULL; // 2nd operand
855 //pCode *pc = NULL; // Mnemonic
866 ParseStates state = PS_START;
873 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
874 && (advTokIdx(<okIdx, 1)) ) // eat space
878 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
881 switch(pcpArr[lpcpIdx].pt) {
883 if(state == PS_START){
884 DFPRINTF((stderr," label\n"));
885 state = PS_HAVE_LABEL;
887 DFPRINTF((stderr," bad state (%d) for label\n",state));
891 DFPRINTF((stderr," %s is",tokArr[ltokIdx].tok.s));
895 DFPRINTF((stderr," mnem\n"));
896 cPmnem = tokArr[ltokIdx].tok.s;
897 state = PS_HAVE_MNEM;
900 DFPRINTF((stderr," 1st operand\n"));
901 cP1stop = tokArr[ltokIdx].tok.s;
902 //pco1 = newpCodeOp(NULL,PO_GPR_REGISTER);
903 state = PS_HAVE_1OPERAND;
905 case PS_HAVE_1OPERAND:
906 DFPRINTF((stderr," error expecting comma\n"));
909 DFPRINTF((stderr," 2 operands\n"));
910 cP2ndop = tokArr[ltokIdx].tok.s;
912 case PS_HAVE_2OPERANDS:
921 DFPRINTF((stderr," wild mnem\n"));
922 state = PS_HAVE_MNEM;
925 DFPRINTF((stderr," 1st operand is wild\n"));
926 state = PS_HAVE_1OPERAND;
928 case PS_HAVE_1OPERAND:
929 DFPRINTF((stderr," error expecting comma\n"));
932 DFPRINTF((stderr," 2nd operand is wild\n"));
934 case PS_HAVE_2OPERANDS:
943 fprintf(stderr," ERROR number\n");
946 DFPRINTF((stderr," 1st operand is a number\n"));
947 state = PS_HAVE_1OPERAND;
949 case PS_HAVE_1OPERAND:
950 fprintf(stderr," error expecting comma\n");
953 DFPRINTF((stderr," 2nd operand is a number\n"));
955 case PS_HAVE_2OPERANDS:
963 if(state == PS_HAVE_1OPERAND){
964 DFPRINTF((stderr," got a comma\n"));
965 state = PS_HAVE_COMMA;
967 fprintf(stderr," unexpected comma\n");
971 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
972 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
975 //dump1Token(tokArr[ltokIdx].tt);
977 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
978 DFPRINTF((stderr," reached end \n"));
985 } while ((++lpcpIdx < PCPATTERNS) && !matching);
989 parsedPatArr[lparsedPatIdx].pcp = NULL;
990 parsedPatArr[lparsedPatIdx].pct = NULL;
996 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
999 pc = altArr[k].f(&parsedPatArr[j]);
1000 //if(pc && pc->print)
1001 // pc->print(stderr,pc);
1002 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1004 addpCode2pBlock(curBlock, pc);
1010 while(j<=lparsedPatIdx && k<ALTPATTERNS);
1013 DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1017 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1018 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1019 DFPRINTF((stderr," %d",parsedPatArr[j].pcp->pt));
1022 while(j<lparsedPatIdx);
1024 DFPRINTF((stderr,"\n"));
1031 /*-----------------------------------------------------------------*/
1033 /*-----------------------------------------------------------------*/
1034 void peepRuleBlock2pCodeBlock( lineNode *ln)
1040 for( ; ln; ln = ln->next) {
1042 //DFPRINTF((stderr,"%s\n",ln->line));
1044 tokenizeLineNode(ln->line);
1050 /*-----------------------------------------------------------------*/
1051 /* peepRuleCondition */
1052 /*-----------------------------------------------------------------*/
1053 static void peepRuleCondition(char *cond)
1058 //DFPRINTF((stderr,"\nCondition: %s\n",cond));
1060 /* brute force compares for now */
1062 if(STRCASECMP(cond, "NZ") == 0) {
1063 //DFPRINTF((stderr,"found NZ\n"));
1064 curPeep->postFalseCond = PCC_Z;
1069 /*-----------------------------------------------------------------*/
1070 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1073 /* SDCCpeeph parses the peep rules file and extracts variables, */
1074 /* removes white space, and checks the syntax. This function */
1075 /* extends that processing to produce pCode objects. You can kind */
1076 /* think of this function as an "assembler", though instead of */
1077 /* taking raw text to produce machine code, it produces pCode. */
1079 /*-----------------------------------------------------------------*/
1081 void peepRules2pCode(peepRule *rules)
1085 pCodePeepSnippets *pcps;
1087 /* The rules are in a linked-list. Each rule has two portions */
1088 /* There's the `target' and there's the `replace'. The target */
1089 /* is compared against the SDCC generated code and if it */
1090 /* matches, it gets replaced by the `replace' block of code. */
1092 /* Here we loop through each rule and convert the target's and*/
1093 /* replace's into pCode target and replace blocks */
1095 for (pr = rules; pr; pr = pr->next) {
1097 //DFPRINTF((stderr,"\nRule:\n\n"));
1099 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1100 curPeep = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1102 curPeep->vars = NULL;
1103 curPeep->wildpCodes = NULL; curPeep->wildpCodeOps = NULL;
1104 curPeep->postFalseCond = PCC_NONE;
1105 curPeep->postTrueCond = PCC_NONE;
1107 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1109 curPeep->target = curBlock = newpCodeChain(NULL, 'W', NULL);
1113 /* Convert the target block */
1114 peepRuleBlock2pCodeBlock(pr->match);
1116 //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1117 //printpBlock(stderr, curBlock);
1119 //DFPRINTF((stderr,"target with labels merged:\n"));
1120 pBlockMergeLabels(curBlock);
1122 printpBlock(stderr, curBlock);
1125 //DFPRINTF((stderr,"\nReplaced by:\n"));
1128 curPeep->replace = curBlock = newpCodeChain(NULL, 'W', NULL);
1130 /* Convert the replace block */
1131 peepRuleBlock2pCodeBlock(pr->replace);
1133 //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1134 //printpBlock(stderr, curBlock);
1136 //DFPRINTF((stderr,"replace with labels merged:\n"));
1137 pBlockMergeLabels(curBlock);
1138 //printpBlock(stderr, curBlock);
1140 peepRuleCondition(pr->cond);
1142 /* The rule has been converted to pCode. Now allocate
1143 * space for the wildcards */
1146 curPeep->nvars = sMaxWildVar;
1147 curPeep->vars = Safe_calloc(sMaxWildVar, sizeof(char *));
1149 curPeep->nops = sMaxWildVar;
1150 curPeep->wildpCodeOps = Safe_calloc(sMaxWildVar, sizeof(pCodeOp *));
1152 curPeep->nwildpCodes = ++sMaxWildMnem;
1153 curPeep->wildpCodes = Safe_calloc(sMaxWildMnem, sizeof(char *));
1156 //return; // debug ... don't want to go through all the rules yet
1161 void printpCodeString(FILE *of, pCode *pc, int max)
1165 while(pc && (i++<max)) {
1171 /*-----------------------------------------------------------------*/
1172 /* _DLL * DLL_append */
1174 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1175 /* If The list to which we want to append is non-existant then one */
1176 /* is created. Other wise, the end of the list is sought out and */
1177 /* a new DLL object is appended to it. In either case, the void */
1178 /* *data is added to the newly created DLL object. */
1179 /*-----------------------------------------------------------------*/
1181 static void * DLL_append(_DLL *list, _DLL *next)
1186 /* If there's no list, then create one: */
1188 next->next = next->prev = NULL;
1193 /* Search for the end of the list. */
1198 /* Now append the new DLL object */
1209 /*-----------------------------------------------------------------
1211 pCode peephole optimization
1214 The pCode "peep hole" optimization is not too unlike the peep hole
1215 optimization in SDCCpeeph.c. The major difference is that here we
1216 use pCode's whereas there we use ASCII strings. The advantage with
1217 pCode's is that we can ascertain flow information in the instructions
1221 <FIX ME> - elaborate...
1223 -----------------------------------------------------------------*/
1227 /*-----------------------------------------------------------------*/
1228 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1230 /* return conditions */
1231 /* 1 - The Condition was found for a pCode's input */
1232 /* 0 - No matching condition was found for the whole chain */
1233 /* -1 - The Condition was found for a pCode's output */
1235 /*-----------------------------------------------------------------*/
1236 int pCodeSearchCondition(pCode *pc, unsigned int cond)
1241 /* If we reach a function end (presumably an end since we most
1242 probably began the search in the middle of a function), then
1243 the condition was not found. */
1244 if(pc->type == PC_FUNCTION)
1247 if(pc->type == PC_OPCODE) {
1248 if(PCI(pc)->inCond & cond)
1250 if(PCI(pc)->outCond & cond)
1260 int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1264 /* Check for a label associated with this wild pCode */
1265 // If the wild card has a label, make sure the source code does too.
1272 pcl = pcd->label->pc;
1274 labindex = -PCL(pcl)->key;
1275 //DFPRINTF((stderr,"label id = %d (labindex = %d)\n",PCL(pcl)->key,labindex));
1276 if(peepBlock->vars[labindex] == NULL) {
1277 // First time to encounter this label
1278 peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
1279 //DFPRINTF((stderr,"first time for a label: %d %s\n",labindex, peepBlock->vars[labindex]));
1281 if(strcmp(peepBlock->vars[labindex],PCL(pcs->label->pc)->label) != 0) {
1282 // DFPRINTF((stderr,"labels don't match\n"));
1285 //DFPRINTF((stderr,"matched a label\n"));
1288 // DFPRINTF((stderr,"destination doesn't have a label\n"));
1298 /*-----------------------------------------------------------------*/
1299 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1300 /* see they're the same. */
1302 /* In this context, "source" refers to the coded generated by gen.c*/
1303 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1304 /* ination has no wild cards, then MatchLine will compare the two */
1305 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1306 /* has wildcards, then those get expanded. When a wild card is */
1307 /* encountered for the first time it autmatically is considered a */
1308 /* match and the object that matches it is referenced in the */
1309 /* variables or opcodes array (depending on the type of match). */
1313 /* *peepBlock - A pointer to the peepBlock that contains the */
1314 /* entire rule to which the destination pcode belongs*/
1315 /* *pcs - a pointer to the source pcode */
1316 /* *pcd - a pointer to the destination pcode */
1319 /* 1 - pcodes match */
1320 /* 0 - pcodes don't match */
1323 /*-----------------------------------------------------------------*/
1325 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1327 int index; // index into wild card arrays
1329 if(pcs->type == pcd->type) {
1331 if(pcs->type == PC_OPCODE) {
1333 /* If the opcodes don't match then the line doesn't match */
1334 if(PCI(pcs)->op != PCI(pcd)->op)
1338 DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1339 pcs->print(stderr,pcs);
1340 pcd->print(stderr,pcd);
1343 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1346 /* Compare the operands */
1347 if(PCI(pcd)->pcop) {
1348 if (PCI(pcd)->pcop->type == PO_WILD) {
1349 index = PCOW(PCI(pcd)->pcop)->id;
1351 //DFPRINTF((stderr,"destination is wild\n"));
1352 #ifdef DEBUG_PCODEPEEP
1353 if (index > peepBlock->nops) {
1354 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1358 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1359 if(!peepBlock->wildpCodeOps[index]) {
1360 peepBlock->wildpCodeOps[index] = PCI(pcs)->pcop;
1362 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1368 switch(PCI(pcs)->pcop->type) {
1372 n = PCOR(PCI(pcs)->pcop)->r->name;
1376 n = PCI(pcs)->pcop->name;
1379 if(peepBlock->vars[index])
1380 return (strcmp(peepBlock->vars[index],n) == 0);
1382 // DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1383 peepBlock->vars[index] = n;
1388 /* FIXME - need an else to check the case when the destination
1389 * isn't a wild card */
1391 /* The pcd has no operand. Lines match if pcs has no operand either*/
1392 return (PCI(pcs)->pcop == NULL);
1397 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1400 index = PCW(pcd)->id;
1402 // DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
1403 //pcs->print(stderr,pcs);
1404 //pcd->print(stderr,pcd);
1406 peepBlock->wildpCodes[PCW(pcd)->id] = pcs;
1408 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1411 if(PCW(pcd)->operand) {
1412 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1413 if(peepBlock->vars[index]) {
1414 int i = (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
1417 DFPRINTF((stderr," (matched)\n"));
1419 DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
1420 DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n"),
1421 peepBlock->vars[index],
1422 PCI(pcs)->pcop->name);
1427 peepBlock->vars[index] = PCI(pcs)->pcop->name;
1432 pcs = findNextInstruction(pcs->next);
1434 //DFPRINTF((stderr," (next to match)\n"));
1435 //pcs->print(stderr,pcs);
1436 } else if(pcd->next) {
1437 /* oops, we ran out of code, but there's more to the rule */
1441 return 1; /* wild card matches */
1447 /*-----------------------------------------------------------------*/
1448 /*-----------------------------------------------------------------*/
1449 void pCodePeepClrVars(pCodePeep *pcp)
1456 for(i=0;i<pcp->nvars; i++) {
1457 pcp->vars[i] = NULL;
1458 pcp->wildpCodeOps[i] = NULL;
1462 /*-----------------------------------------------------------------*/
1463 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
1464 /* into the pCode chain containing pc1 */
1465 /*-----------------------------------------------------------------*/
1466 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
1472 pc2->next = pc1->next;
1474 pc1->next->prev = pc2;
1482 /*-----------------------------------------------------------------*/
1483 /* pCodeOpCopy - copy a pcode operator */
1484 /*-----------------------------------------------------------------*/
1485 static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
1487 pCodeOp *pcopnew=NULL;
1492 switch(pcop->type) {
1495 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
1496 pcopnew = Safe_calloc(1,sizeof(pCodeOpBit) );
1497 PCOB(pcopnew)->bit = PCOB(pcop)->bit;
1498 PCOB(pcopnew)->inBitSpace = PCOB(pcop)->inBitSpace;
1503 /* Here we expand the wild card into the appropriate type: */
1504 /* By recursively calling pCodeOpCopy */
1505 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
1506 if(PCOW(pcop)->matched)
1507 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
1510 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
1511 pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
1512 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
1519 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
1520 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1521 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
1526 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
1527 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1528 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1531 case PO_GPR_REGISTER:
1536 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
1537 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1538 PCOR(pcopnew)->r = PCOR(pcop)->r;
1539 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1540 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
1544 //DFPRINTF((stderr,"pCodeOpCopy PO_DIR\n"));
1545 case PO_SFR_REGISTER:
1553 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
1554 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1558 pcopnew->type = pcop->type;
1560 pcopnew->name = Safe_strdup(pcop->name);
1562 pcopnew->name = NULL;
1568 /*-----------------------------------------------------------------*/
1569 /* pCodeCopy - copy a pcode */
1570 /*-----------------------------------------------------------------*/
1571 static pCode *pCodeCopy(pCode *pc)
1576 pcnew = newpCode(pc->type,pc->pcop);
1579 /*-----------------------------------------------------------------*/
1580 /*-----------------------------------------------------------------*/
1581 void pCodeDeleteChain(pCode *f,pCode *t)
1587 DFPRINTF((stderr,"delete pCode:\n"));
1590 //f->delete(f); this dumps core...
1597 /*-----------------------------------------------------------------*/
1598 /*-----------------------------------------------------------------*/
1599 int pCodePeepMatchRule(pCode *pc)
1601 pCodePeep *peepBlock;
1606 peeprules = (_DLL *)peepSnippets;
1609 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1610 if(!peepBlock || !peepBlock->target || !peepBlock->target->pcHead)
1613 pCodePeepClrVars(peepBlock);
1616 pct = peepBlock->target->pcHead;
1618 while(pct && pcin) {
1620 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1623 pcin = findNextInstruction(pcin->next);
1626 //DFPRINTF((stderr," matched\n"));
1628 DFPRINTF((stderr," end of code\n"));
1630 DFPRINTF((stderr," end of rule\n"));
1635 /* So far we matched the rule up to the point of the conditions .
1636 * In other words, all of the opcodes match. Now we need to see
1637 * if the post conditions are satisfied.
1638 * First we check the 'postFalseCond'. This means that we check
1639 * to see if any of the subsequent pCode's in the pCode chain
1640 * following the point just past where we have matched depend on
1641 * the `postFalseCond' as input then we abort the match
1643 DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
1644 if (pcin && peepBlock->postFalseCond &&
1645 (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
1655 /* We matched a rule! Now we have to go through and remove the
1656 inefficient code with the optimized version */
1658 DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
1659 printpCodeString(stderr,peepBlock->target->pcHead,10);
1660 DFPRINTF((stderr,"first thing matched\n"));
1661 pc->print(stderr,pc);
1664 DFPRINTF((stderr,"last thing matched\n"));
1665 pcin->print(stderr,pcin);
1668 /* Unlink the original code */
1670 pcprev->next = pcin;
1672 pcin->prev = pc->prev;
1676 /* Converted the deleted pCodes into comments */
1683 while(pc && pc!=pcin) {
1684 pCode2str(&buf[2], 254, pc);
1685 pCodeInsertAfter(pcprev, newpCodeCharP(buf));
1686 pcprev = pcprev->next;
1692 pCodeDeleteChain(pc,pcin);
1694 /* Generate the replacement code */
1696 pcr = peepBlock->replace->pcHead; // This is the replacement code
1699 /* If the replace pcode is an instruction with an operand, */
1700 /* then duplicate the operand (and expand wild cards in the process). */
1701 if(pcr->type == PC_OPCODE) {
1702 if(PCI(pcr)->pcop) {
1703 /* The replacing instruction has an operand.
1705 if(PCI(pcr)->pcop->type == PO_WILD) {
1706 int index = PCOW(PCI(pcr)->pcop)->id;
1707 //DFPRINTF((stderr,"copying wildopcode\n"));
1708 if(peepBlock->wildpCodeOps[index])
1709 pcop = pCodeOpCopy(peepBlock->wildpCodeOps[index]);
1711 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
1713 pcop = pCodeOpCopy(PCI(pcr)->pcop);
1715 //DFPRINTF((stderr,"inserting pCode\n"));
1716 pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
1717 } else if (pcr->type == PC_WILD) {
1718 pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
1719 } else if (pcr->type == PC_COMMENT) {
1720 pCodeInsertAfter(pc, newpCodeCharP( ((pCodeComment *)(pcr))->comment));
1726 // pc->print(stderr,pc);
1733 peeprules = peeprules->next;