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 -------------------------------------------------------------------------*/
22 #include "pcodeflow.h"
27 #define IS_PCCOMMENT(x) ( x && (x->type==PC_COMMENT))
29 /****************************************************************/
31 * rootRules - defined in SDCCpeep.c
32 * This is a pointer to the (parsed) peephole rules that are
33 * defined in peep.def.
36 //extern peepRule *rootRules;
41 /****************************************************************/
42 /****************************************************************/
50 typedef struct pCodePeepSnippets
57 /****************************************************************/
61 /****************************************************************/
63 static pCodePeepSnippets *peepSnippets=NULL;
65 /****************************************************************/
69 /****************************************************************/
71 //static pCodePeep *curPeep=NULL;
73 /****************************************************************/
77 /****************************************************************/
79 //static pBlock *curBlock=NULL;
82 /****************************************************************/
84 /* max wild cards in a peep rule */
86 /****************************************************************/
88 //static int sMaxWildVar = 0;
89 //static int sMaxWildMnem = 0;
92 typedef struct pCodeToken
94 int tt; // token type;
103 static pCodeToken tokArr[50];
104 static unsigned tokIdx=0;
122 typedef struct parsedPattern {
123 struct pcPattern *pcp;
127 #define MAX_PARSEDPATARR 50
128 static parsedPattern parsedPatArr[MAX_PARSEDPATARR];
130 static unsigned int parsedPatIdx=0;
143 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
144 static char pcpat_number[] = {PCT_NUMBER, 0};
145 static char pcpat_string[] = {PCT_STRING, 0};
146 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
147 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
148 static char pcpat_comma[] = {PCT_COMMA, 0};
149 static char pcpat_comment[] = {PCT_COMMENT, 0};
152 typedef struct pcPattern {
153 char pt; // Pattern type
154 char *tokens; // list of tokens that describe the pattern
155 void * (*f) (void *,pCodeWildBlock *);
158 static pcPattern pcpArr[] = {
159 {PCP_LABEL, pcpat_label, NULL},
160 {PCP_WILDSTR, pcpat_wildString, NULL},
161 {PCP_STR, pcpat_string, NULL},
162 {PCP_WILDVAR, pcpat_wildVar, NULL},
163 {PCP_COMMA, pcpat_comma, NULL},
164 {PCP_COMMENT, pcpat_comment, NULL},
165 {PCP_NUMBER, pcpat_number, NULL}
168 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
170 // Assembly Line Token
184 static char alt_comment[] = { PCP_COMMENT, 0};
185 static char alt_label[] = { PCP_LABEL, 0};
186 static char alt_mnem0[] = { PCP_STR, 0};
187 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
188 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
189 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
190 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
191 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
192 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
193 static char alt_mnem3[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_NUMBER, 0};
195 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
196 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
197 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb);
198 static void * cvt_altpat_mnem0a(void *pp,pCodeWildBlock *pcwb);
199 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb);
200 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb);
201 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb);
202 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb);
203 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb);
204 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb);
206 static pcPattern altArr[] = {
207 {ALT_LABEL, alt_label, cvt_altpat_label},
208 {ALT_COMMENT, alt_comment,cvt_altpat_comment},
209 {ALT_MNEM3, alt_mnem3, cvt_altpat_mnem3},
210 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
211 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
212 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
213 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
214 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
215 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
216 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
220 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
222 // forward declarations
223 static void * DLL_append(_DLL *list, _DLL *next);
225 /*-----------------------------------------------------------------*/
226 /* cvt_extract_destination - helper function extracts the register */
227 /* destination from a parsedPattern. */
229 /*-----------------------------------------------------------------*/
230 static int cvt_extract_destination(parsedPattern *pp)
233 if(pp->pct[0].tt == PCT_STRING) {
235 // just check first letter for now
237 if(toupper((unsigned char)*pp->pct[0].tok.s) == 'F')
240 } else if (pp->pct[0].tt == PCT_NUMBER) {
250 /*-----------------------------------------------------------------*/
251 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
252 /* if *reg is the "status" register and *bit is one of the */
253 /* status bits, then this function will create a new pCode op */
254 /* containing the status register. */
255 /*-----------------------------------------------------------------*/
257 static pCodeOp *cvt_extract_status(char *reg, char *bit)
261 if(STRCASECMP(reg, pc_status.pcop.name))
268 if(toupper((unsigned char)*bit) == 'C')
269 return PCOP(popCopyGPR2Bit(PCOP(&pc_status),PIC_C_BIT));
270 if(toupper((unsigned char)*bit) == 'Z')
271 return PCOP(popCopyGPR2Bit(PCOP(&pc_status),PIC_Z_BIT));
275 if(len ==2 && toupper((unsigned char)bit[0]) == 'D' && toupper((unsigned char)bit[1]) == 'C')
276 return PCOP(popCopyGPR2Bit(PCOP(&pc_status),PIC_DC_BIT));
282 /*-----------------------------------------------------------------*/
283 /* cvt_altpat_label - convert assembly line type to a pCode label */
284 /* INPUT: pointer to the parsedPattern */
288 /* label pattern => '%' number ':' */
289 /* at this point, we wish to extract only the 'number' */
291 /*-----------------------------------------------------------------*/
292 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb)
294 parsedPattern *p = pp;
296 DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
297 return newpCodeLabel(NULL,-p->pct[1].tok.n);
301 /*-----------------------------------------------------------------*/
302 /* cvt_altpat_comment - convert assembly line type to a comment */
303 /* INPUT: pointer to the parsedPattern */
305 /* pp[0] - comment */
308 /*-----------------------------------------------------------------*/
309 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb)
311 parsedPattern *p = pp;
313 DFPRINTF((stderr,"altpat_comment = %s\n",p->pct[0].tok.s));
314 return newpCodeCharP(p->pct[0].tok.s);
318 /*-----------------------------------------------------------------*/
319 /* cvt_altpat_mem0 - convert assembly line type to a wild pCode */
324 /*-----------------------------------------------------------------*/
325 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb)
327 parsedPattern *p = pp;
330 pCodeInstruction *pci=NULL;
332 DFPRINTF((stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s));
334 opcode = getpCode(p->pct[0].tok.s,0);
337 /* look for special command strings like _NOTBITSKIP_ */
339 //fprintf(stderr, "Bad mnemonic\n");
341 opcode = getpCodePeepCommand(p->pct[0].tok.s);
343 // fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
347 pci = PCI(newpCode(opcode, NULL));
350 fprintf(stderr,"couldn't find mnemonic\n");
356 /*-----------------------------------------------------------------*/
357 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
360 /* pp[0] - wild var */
362 /*-----------------------------------------------------------------*/
363 static void * cvt_altpat_mnem0a(void *pp, pCodeWildBlock *pcwb)
365 parsedPattern *p = pp;
367 DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n));
369 /* Save the index of the maximum wildcard mnemonic */
371 //if(p[0].pct[1].tok.n > sMaxWildVar)
372 // sMaxWildMnem = p[0].pct[1].tok.n;
374 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
375 pcwb->nwildpCodes = 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,pCodeWildBlock *pcwb)
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");
403 opcode = getpCodePeepCommand(p->pct[0].tok.s);
405 //fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
410 if(pic14Mnemonics[opcode]->isBitInst)
411 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
413 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
416 pci = PCI(newpCode(opcode, pcosubtype));
419 fprintf(stderr,"couldn't find mnemonic\n");
425 /*-----------------------------------------------------------------*/
426 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
427 /* instruction with 1 wild operand. */
430 /* pp[1] - wild var */
432 /*-----------------------------------------------------------------*/
433 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb)
435 parsedPattern *p = pp;
438 pCodeInstruction *pci=NULL;
441 DFPRINTF((stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n));
443 opcode = getpCode(p->pct[0].tok.s,0);
445 int cmd_id = getpCodePeepCommand(p->pct[0].tok.s);
449 fprintf(stderr, "Bad mnemonic\n");
453 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
454 pcwb->nwildpCodes = p[0].pct[1].tok.n;
456 pc = newpCodeWild(p[1].pct[1].tok.n,NULL,NULL);
460 PCW(pc)->mustNotBeBitSkipInst = 1;
463 PCW(pc)->mustBeBitSkipInst = 1;
466 PCW(pc)->invertBitSkipInst = 1;
471 if(pic14Mnemonics[opcode]->isBitInst)
472 pcosubtype = newpCodeOpBit(NULL,-1,0);
474 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
477 pci = PCI(newpCode(opcode,
478 newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
480 /* Save the index of the maximum wildcard variable */
481 //if(p[1].pct[1].tok.n > sMaxWildVar)
482 // sMaxWildVar = p[1].pct[1].tok.n;
484 if(p[1].pct[1].tok.n > pcwb->nvars)
485 pcwb->nvars = p[1].pct[1].tok.n;
488 fprintf(stderr,"couldn't find mnemonic\n");
494 /*-----------------------------------------------------------------*/
495 /*-----------------------------------------------------------------*/
496 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb)
498 parsedPattern *p = pp;
501 pCodeInstruction *pci=NULL;
503 DFPRINTF((stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n));
505 opcode = getpCode(p->pct[0].tok.s,0);
507 fprintf(stderr, "Bad mnemonic\n");
511 pci = PCI(newpCode(opcode, newpCodeOpLit(p[1].pct[0].tok.n) ));
514 fprintf(stderr,"couldn't find mnemonic\n");
520 /*-----------------------------------------------------------------*/
521 /* cvt_altpat_mnem2 */
526 /* pp[3] - destination */
527 /*-----------------------------------------------------------------*/
528 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
530 parsedPattern *p = pp;
534 pCodeInstruction *pci=NULL;
537 dest = cvt_extract_destination(&p[3]);
539 DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
546 opcode = getpCode(p->pct[0].tok.s,dest);
548 fprintf(stderr, "Bad mnemonic\n");
552 if(pic14Mnemonics[opcode]->isBitInst) {
553 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
554 if(pcosubtype == NULL) {
555 fprintf(stderr, "bad operand?\n");
560 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
563 pci = PCI(newpCode(opcode,pcosubtype));
566 fprintf(stderr,"couldn't find mnemonic\n");
572 /*-----------------------------------------------------------------*/
573 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
574 /* instruction with 1 wild operand and a */
575 /* destination operand (e.g. w or f) */
578 /* pp[1] - wild var */
580 /* pp[3] - destination */
582 /*-----------------------------------------------------------------*/
583 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
585 parsedPattern *p = pp;
589 pCodeInstruction *pci=NULL;
593 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
597 dest = cvt_extract_destination(&p[3]);
599 DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
606 opcode = getpCode(p->pct[0].tok.s,dest);
608 fprintf(stderr, "Bad mnemonic\n");
612 if(pic14Mnemonics[opcode]->isBitInst)
613 pcosubtype = newpCodeOp(NULL,PO_BIT);
615 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
618 pci = PCI(newpCode(opcode,
619 newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
621 /* Save the index of the maximum wildcard variable */
622 //if(p[1].pct[1].tok.n > sMaxWildVar)
623 // sMaxWildVar = p[1].pct[1].tok.n;
625 if(p[1].pct[1].tok.n > pcwb->nvars)
626 pcwb->nvars = p[1].pct[1].tok.n;
629 fprintf(stderr,"couldn't find mnemonic\n");
636 /*-----------------------------------------------------------------*/
637 /* cvt_altpat_mem3 - convert assembly line type to a pCode */
638 /* This rule is for bsf/bcf type instructions */
642 /* pp[1] - register */
646 /*-----------------------------------------------------------------*/
647 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
649 parsedPattern *p = pp;
651 int dest; // or could be bit position in the register
653 pCodeInstruction *pci=NULL;
654 pCodeOp *pcosubtype=NULL;
656 dest = cvt_extract_destination(&p[3]);
658 DFPRINTF((stderr,"altpat_mnem3 %s var %s bit (%d)\n",
664 opcode = getpCode(p->pct[0].tok.s,0);
666 fprintf(stderr, "Bad mnemonic\n");
671 if(pic14Mnemonics[opcode]->isBitInst) {
672 //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
674 //if(pcosubtype == NULL) {
675 pcosubtype = newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0);
678 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
680 if(pcosubtype == NULL) {
681 fprintf(stderr, "Bad operand\n");
685 pci = PCI(newpCode(opcode, pcosubtype));
688 fprintf(stderr,"couldn't find mnemonic\n");
694 /*-----------------------------------------------------------------*/
695 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
696 /* by SDCCpeeph.c into a string of tokens. */
699 /* The tokenizer is of the classic type. When an item is encounterd*/
700 /* it is converted into a token. The token is a structure that */
701 /* encodes the item's type and it's value (when appropriate). */
703 /* Accepted token types: */
704 /* SPACE NUMBER STRING % : , ; */
708 /*-----------------------------------------------------------------*/
711 static void tokenizeLineNode(char *ln)
714 tokIdx = 0; // Starting off at the beginning
715 tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
723 if(isspace((unsigned char)*ln)) {
724 // add a SPACE token and eat the extra spaces.
725 tokArr[tokIdx++].tt = PCT_SPACE;
726 while (isspace ((unsigned char)*ln))
731 if(isdigit((unsigned char)*ln)) {
733 tokArr[tokIdx].tt = PCT_NUMBER;
734 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
742 tokArr[tokIdx++].tt = PCT_PERCENT;
745 tokArr[tokIdx++].tt = PCT_LESSTHAN;
748 tokArr[tokIdx++].tt = PCT_GREATERTHAN;
751 tokArr[tokIdx++].tt = PCT_COLON;
754 tokArr[tokIdx].tok.s = Safe_strdup(ln);
755 tokArr[tokIdx++].tt = PCT_COMMENT;
756 tokArr[tokIdx].tt = PCT_NULL;
759 tokArr[tokIdx++].tt = PCT_COMMA;
764 if(isalpha((unsigned char)*ln) || (*ln == '_') ) {
768 while( (isalpha((unsigned char)*ln) || isdigit((unsigned char)*ln) || (*ln == '_')) && i<49)
774 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
775 tokArr[tokIdx++].tt = PCT_STRING;
778 fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
779 fprintf(stderr, "Line: %s\n",lnstart);
780 fprintf(stderr, "Token: '%c'\n",*ln);
785 /* Advance to next character in input string .
786 * Note, if none of the tests passed above, then
787 * we effectively ignore the `bad' character.
788 * Since the line has already been parsed by SDCCpeeph,
789 * chance are that there are no invalid characters... */
795 tokArr[tokIdx].tt = 0;
799 /*-----------------------------------------------------------------*/
800 /*-----------------------------------------------------------------*/
804 static void dump1Token(pCodeTokens tt)
809 fprintf(stderr, " space ");
812 fprintf(stderr, " pct %%");
815 fprintf(stderr, " pct <");
817 case PCT_GREATERTHAN:
818 fprintf(stderr, " pct >");
821 fprintf(stderr, " col :");
824 fprintf(stderr, " comma , ");
827 fprintf(stderr, " comment ");
828 //fprintf(stderr,"%s",tokArr[i].tok.s);
831 fprintf(stderr, " str ");
832 //fprintf(stderr,"%s",tokArr[i].tok.s);
835 fprintf(stderr, " num ");
836 //fprintf(stderr,"%d",tokArr[i].tok.n);
839 fprintf(stderr, " null ");
846 /*-----------------------------------------------------------------*/
847 /*-----------------------------------------------------------------*/
849 static int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
853 if(!pct || !pat || !*pat)
856 //DFPRINTF((stderr,"comparing against:\n"));
858 while(i < max_tokens) {
861 //DFPRINTF((stderr,"matched\n"));
865 //dump1Token(*pat); DFPRINTF((stderr,"\n"));
879 /*-----------------------------------------------------------------*/
880 /*-----------------------------------------------------------------*/
882 static int altComparePattern(char *pct, parsedPattern *pat, int max_tokens)
886 if(!pct || !pat || !*pct)
890 while(i < max_tokens) {
893 //DFPRINTF((stderr,"matched\n"));
897 //dump1Token(*pat); DFPRINTF((stderr,"\n"));
899 if( !pat || !pat->pcp )
902 if (pat->pcp->pt != *pct)
905 //DFPRINTF((stderr," pct=%d\n",*pct));
914 /*-----------------------------------------------------------------*/
915 /*-----------------------------------------------------------------*/
917 static int advTokIdx(int *v, int amt)
920 if((unsigned) (*v + amt) > tokIdx)
928 /*-----------------------------------------------------------------*/
929 /* parseTokens - convert the tokens corresponding to a single line */
930 /* of a peep hole assembly into a pCode object. */
935 /* This is a simple parser that looks for strings of the type */
936 /* allowed in the peep hole definition file. Essentially the format*/
937 /* is the same as a line of assembly: */
939 /* label: mnemonic op1, op2, op3 ; comment */
941 /* Some of these items aren't present. It's the job of the parser */
942 /* to determine which are and convert those into the appropriate */
944 /*-----------------------------------------------------------------*/
946 static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
957 for(i=0; i<=tokIdx; i++)
958 dump1Token(tokArr[i].tt);
971 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
972 char * cP1stop = NULL;
973 char * cP2ndop = NULL;
975 //pCodeOp *pcl = NULL; // Storage for a label
976 //pCodeOp *pco1 = NULL; // 1st operand
977 //pCodeOp *pco2 = NULL; // 2nd operand
978 //pCode *pc = NULL; // Mnemonic
989 ParseStates state = PS_START;
996 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
997 && (advTokIdx(<okIdx, 1)) ) // eat space
1001 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
1004 switch(pcpArr[lpcpIdx].pt) {
1006 if(state == PS_START){
1007 DFPRINTF((stderr," label\n"));
1008 state = PS_HAVE_LABEL;
1010 DFPRINTF((stderr," bad state (%d) for label\n",state));
1014 DFPRINTF((stderr," %s is",tokArr[ltokIdx].tok.s));
1018 DFPRINTF((stderr," mnem\n"));
1019 cPmnem = tokArr[ltokIdx].tok.s;
1020 state = PS_HAVE_MNEM;
1023 DFPRINTF((stderr," 1st operand\n"));
1024 cP1stop = tokArr[ltokIdx].tok.s;
1025 //pco1 = newpCodeOp(NULL,PO_GPR_REGISTER);
1026 state = PS_HAVE_1OPERAND;
1028 case PS_HAVE_1OPERAND:
1029 DFPRINTF((stderr," error expecting comma\n"));
1032 DFPRINTF((stderr," 2 operands\n"));
1033 cP2ndop = tokArr[ltokIdx].tok.s;
1035 case PS_HAVE_2OPERANDS:
1044 DFPRINTF((stderr," wild mnem\n"));
1045 state = PS_HAVE_MNEM;
1048 DFPRINTF((stderr," 1st operand is wild\n"));
1049 state = PS_HAVE_1OPERAND;
1051 case PS_HAVE_1OPERAND:
1052 DFPRINTF((stderr," error expecting comma\n"));
1055 DFPRINTF((stderr," 2nd operand is wild\n"));
1057 case PS_HAVE_2OPERANDS:
1066 fprintf(stderr," ERROR number\n");
1069 DFPRINTF((stderr," 1st operand is a number\n"));
1070 state = PS_HAVE_1OPERAND;
1072 case PS_HAVE_1OPERAND:
1073 fprintf(stderr," error expecting comma\n");
1076 DFPRINTF((stderr," 2nd operand is a number\n"));
1078 case PS_HAVE_2OPERANDS:
1086 if(state == PS_HAVE_1OPERAND){
1087 DFPRINTF((stderr," got a comma\n"));
1088 state = PS_HAVE_COMMA;
1090 fprintf(stderr," unexpected comma\n");
1096 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1097 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1100 //dump1Token(tokArr[ltokIdx].tt);
1102 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1103 DFPRINTF((stderr," reached end \n"));
1110 } while ((++lpcpIdx < PCPATTERNS) && !matching);
1114 parsedPatArr[lparsedPatIdx].pcp = NULL;
1115 parsedPatArr[lparsedPatIdx].pct = NULL;
1121 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1124 pc = altArr[k].f(&parsedPatArr[j],pcwb);
1125 //if(pc && pc->print)
1126 // pc->print(stderr,pc);
1127 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1129 //if(curBlock && pc)
1130 //addpCode2pBlock(curBlock, pc);
1134 return 0; // Only accept one line for now.
1136 addpCode2pBlock(pcwb->pb, pc);
1144 while(j<=lparsedPatIdx && k<ALTPATTERNS);
1147 DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1151 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1152 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1153 DFPRINTF((stderr," %d",parsedPatArr[j].pcp->pt));
1156 while(j<lparsedPatIdx);
1158 DFPRINTF((stderr,"\n"));
1165 /*-----------------------------------------------------------------*/
1167 /*-----------------------------------------------------------------*/
1168 static void peepRuleBlock2pCodeBlock(lineNode *ln, pCodeWildBlock *pcwb)
1174 for( ; ln; ln = ln->next) {
1176 //DFPRINTF((stderr,"%s\n",ln->line));
1178 tokenizeLineNode(ln->line);
1180 if(parseTokens(pcwb,NULL)) {
1182 fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
1183 fprintf(stderr,"Tokens:\n");
1185 dump1Token(tokArr[i].tt);
1193 /*-----------------------------------------------------------------*/
1195 /*-----------------------------------------------------------------*/
1196 static pCode *AssembleLine(char *line)
1200 if(!line || !*line) {
1201 fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
1205 tokenizeLineNode(line);
1207 if(parseTokens(NULL,&pc))
1208 fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
1215 /*-----------------------------------------------------------------*/
1216 /* peepRuleCondition */
1217 /*-----------------------------------------------------------------*/
1218 static void peepRuleCondition(char *cond, pCodePeep *pcp)
1223 //DFPRINTF((stderr,"\nCondition: %s\n",cond));
1224 /* brute force compares for now */
1226 if(STRCASECMP(cond, "NZ") == 0) {
1227 //DFPRINTF((stderr,"found NZ\n"));
1228 pcp->postFalseCond = PCC_Z;
1234 static void initpCodeWildBlock(pCodeWildBlock *pcwb)
1237 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1243 pcwb->wildpCodes = NULL;
1244 pcwb->wildpCodeOps = NULL;
1247 pcwb->nwildpCodes = 0;
1252 static void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1259 pcwb->nops = pcwb->nvars;
1261 pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1262 pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1264 pcwb->nwildpCodes+=2;
1265 pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1269 static void initpCodePeep(pCodePeep *pcp)
1272 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1277 initpCodeWildBlock(&pcp->target);
1278 pcp->target.pb = newpCodeChain(NULL, 'W', NULL);
1280 initpCodeWildBlock(&pcp->replace);
1281 pcp->replace.pb = newpCodeChain(NULL, 'W', NULL);
1285 /*-----------------------------------------------------------------*/
1286 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1289 /* SDCCpeeph parses the peep rules file and extracts variables, */
1290 /* removes white space, and checks the syntax. This function */
1291 /* extends that processing to produce pCode objects. You can kind */
1292 /* think of this function as an "assembler", though instead of */
1293 /* taking raw text to produce machine code, it produces pCode. */
1295 /*-----------------------------------------------------------------*/
1296 void peepRules2pCode(peepRule *rules)
1300 pCodePeep *currentRule;
1301 pCodePeepSnippets *pcps;
1303 pic14initpCodePeepCommands();
1305 /* The rules are in a linked-list. Each rule has two portions */
1306 /* There's the `target' and there's the `replace'. The target */
1307 /* is compared against the SDCC generated code and if it */
1308 /* matches, it gets replaced by the `replace' block of code. */
1310 /* Here we loop through each rule and convert the target's and*/
1311 /* replace's into pCode target and replace blocks */
1313 for (pr = rules; pr; pr = pr->next) {
1315 //DFPRINTF((stderr,"\nRule:\n\n"));
1317 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1318 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1320 currentRule = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1321 initpCodePeep(currentRule);
1323 /* Convert the target block */
1324 peepRuleBlock2pCodeBlock(pr->match, ¤tRule->target);
1326 //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1327 //printpBlock(stderr, currentRule->target.pb);
1329 //DFPRINTF((stderr,"target with labels merged:\n"));
1330 //pBlockMergeLabels(curBlock);
1331 pBlockMergeLabels(currentRule->target.pb);
1332 //printpBlock(stderr, currentRule->replace.pb);
1334 //#ifdef PCODE_DEBUG
1335 // printpBlock(stderr, curBlock);
1337 //DFPRINTF((stderr,"\nReplaced by:\n"));
1340 /* Convert the replace block */
1341 peepRuleBlock2pCodeBlock(pr->replace, ¤tRule->replace);
1343 //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1344 //printpBlock(stderr, curBlock);
1346 //DFPRINTF((stderr,"replace with labels merged:\n"));
1348 pBlockMergeLabels(currentRule->replace.pb);
1349 //printpBlock(stderr, currentRule->replace.pb);
1351 peepRuleCondition(pr->cond,currentRule);
1353 /* The rule has been converted to pCode. Now allocate
1354 * space for the wildcards */
1356 postinit_pCodeWildBlock(¤tRule->target);
1357 postinit_pCodeWildBlock(¤tRule->replace);
1359 //return; // debug ... don't want to go through all the rules yet
1363 pCodePeep *peepBlock;
1366 peeprules = (_DLL *)peepSnippets;
1367 //fprintf(stderr,"target rules\n");
1369 //fprintf(stderr," rule:\n");
1370 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1371 //printpBlock(stderr, peepBlock->target.pb);
1372 peeprules = peeprules->next;
1374 //fprintf(stderr," ... done\n");
1380 static void printpCodeString(FILE *of, pCode *pc, int max)
1384 while(pc && (i++<max)) {
1391 /*-----------------------------------------------------------------*/
1392 /* _DLL * DLL_append */
1394 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1395 /* If The list to which we want to append is non-existant then one */
1396 /* is created. Other wise, the end of the list is sought out and */
1397 /* a new DLL object is appended to it. In either case, the void */
1398 /* *data is added to the newly created DLL object. */
1399 /*-----------------------------------------------------------------*/
1401 static void * DLL_append(_DLL *list, _DLL *next)
1406 /* If there's no list, then create one: */
1408 next->next = next->prev = NULL;
1413 /* Search for the end of the list. */
1418 /* Now append the new DLL object */
1429 /*-----------------------------------------------------------------
1431 pCode peephole optimization
1434 The pCode "peep hole" optimization is not too unlike the peep hole
1435 optimization in SDCCpeeph.c. The major difference is that here we
1436 use pCode's whereas there we use ASCII strings. The advantage with
1437 pCode's is that we can ascertain flow information in the instructions
1441 <FIX ME> - elaborate...
1443 -----------------------------------------------------------------*/
1447 /*-----------------------------------------------------------------*/
1448 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1450 /* return conditions */
1451 /* 1 - The Condition was found for a pCode's input */
1452 /* 0 - No matching condition was found for the whole chain */
1453 /* -1 - The Condition was found for a pCode's output */
1455 /*-----------------------------------------------------------------*/
1456 int pCodeSearchCondition(pCode *pc, unsigned int cond, int contIfSkip)
1460 /* If we reach a function end (presumably an end since we most
1461 probably began the search in the middle of a function), then
1462 the condition was not found. */
1463 if(pc->type == PC_FUNCTION)
1466 if(pc->type == PC_OPCODE) {
1467 if(PCI(pc)->inCond & cond) {
1469 /* If previous instruction is a skip then continue search as condiction is not certain */
1470 pCode *pcp = findPrevInstruction(pc->prev);
1471 if (pcp && !isPCI_SKIP(pcp)) {
1478 if(PCI(pc)->outCond & cond) {
1480 /* If previous instruction is a skip then continue search as condiction is not certain */
1481 pCode *pcp = findPrevInstruction(pc->prev);
1482 if (pcp && !isPCI_SKIP(pcp)) {
1497 /*-----------------------------------------------------------------
1498 * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1500 * Compare two pCodeOp's and return 1 if they're the same
1501 *-----------------------------------------------------------------*/
1502 static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1506 if(!pcops || !pcopd)
1509 fprintf(stderr," Comparing operands %s",
1510 get_op( pcops,NULL,0));
1512 fprintf(stderr," to %s\n",
1513 get_op( pcopd,NULL,0));
1516 if(pcops->type != pcopd->type) {
1517 //fprintf(stderr," - fail - diff types\n");
1518 return 0; // different types
1521 if(pcops->type == PO_LITERAL) {
1523 if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
1532 n2 = get_op(pcopd,NULL,0);
1534 if( !n2 || strcmp(b,n2)) {
1535 //fprintf(stderr," - fail - diff names: %s, len=%d, %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1536 return 0; // different names
1539 switch(pcops->type) {
1541 if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1542 //fprintf(stderr, " - fail different instances\n");
1550 //fprintf(stderr," - pass\n");
1555 static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1559 /* Check for a label associated with this wild pCode */
1560 // If the wild card has a label, make sure the source code does too.
1561 if(PCI(pcd)->label) {
1562 pCode *pcl = PCI(pcd)->label->pc;
1565 int li = -PCL(pcl)->key;
1567 if(peepBlock->target.vars[li] == NULL) {
1568 if(PCI(pcs)->label) {
1569 DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1572 // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1573 DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1574 if(PCI(pcs)->label) {
1575 DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1581 if(!PCI(pcs)->label)
1584 labindex = -PCL(pcl)->key;
1585 if(peepBlock->target.vars[labindex] == NULL) {
1586 // First time to encounter this label
1587 peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1588 DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1591 if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1592 DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1595 DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1598 //DFPRINTF((stderr,"destination doesn't have a label\n"));
1603 //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1611 /*-----------------------------------------------------------------*/
1612 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1613 /* see they're the same. */
1615 /* In this context, "source" refers to the coded generated by gen.c*/
1616 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1617 /* ination has no wild cards, then MatchLine will compare the two */
1618 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1619 /* has wildcards, then those get expanded. When a wild card is */
1620 /* encountered for the first time it autmatically is considered a */
1621 /* match and the object that matches it is referenced in the */
1622 /* variables or opcodes array (depending on the type of match). */
1626 /* *peepBlock - A pointer to the peepBlock that contains the */
1627 /* entire rule to which the destination pcode belongs*/
1628 /* *pcs - a pointer to the source pcode */
1629 /* *pcd - a pointer to the destination pcode */
1632 /* 1 - pcodes match */
1633 /* 0 - pcodes don't match */
1636 /*-----------------------------------------------------------------*/
1638 static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1640 int index; // index into wild card arrays
1642 /* one-for-one match. Here the source and destination opcodes
1643 * are not wild. However, there may be a label or a wild operand */
1646 if(PCI(pcs)->label) {
1647 DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1651 if(pcs->type == pcd->type) {
1653 if(pcs->type == PC_OPCODE) {
1655 /* If the opcodes don't match then the line doesn't match */
1656 if(PCI(pcs)->op != PCI(pcd)->op)
1660 DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1661 pcs->print(stderr,pcs);
1662 pcd->print(stderr,pcd);
1665 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1668 /* Compare the operands */
1669 if(PCI(pcd)->pcop) {
1670 // Volatile types should not be deleted or modified, these include SFR, externs and publics
1671 // They can be used as a matched, however if a match is found then the optimiser intends
1672 // to change some aspect of a block of code, which is most likely a critcal one. As this
1673 // method of optimisation does not allow a means to distiguishing what may change, it is
1674 // best to just negate any match.
1675 if (PCI(pcs)->pcop) {
1677 pCodeOp *pcop = PCI(pcs)->pcop;
1678 switch(pcop->type) {
1686 case PO_SFR_REGISTER:
1687 return 0; // SFR - do not modify
1689 case PO_GPR_REGISTER:
1692 case PO_GPR_POINTER:
1694 if (r->isPublic||r->isExtern||r->isFixed) // Changes to these types of registers should not be changed as they may be used else where
1700 if (PCI(pcd)->pcop->type == PO_WILD) {
1702 index = PCOW(PCI(pcd)->pcop)->id;
1703 //DFPRINTF((stderr,"destination is wild\n"));
1704 #ifdef DEBUG_PCODEPEEP
1705 if (index > peepBlock->nops) {
1706 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1710 n = PCI(pcs)->pcop->name;
1711 if(peepBlock->target.vars[index]) {
1712 if ((!n)||(strcmp(peepBlock->target.vars[index],n) != 0))
1713 return 0; // variable is different
1715 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1716 peepBlock->target.vars[index] = n;
1719 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1720 if(!peepBlock->target.wildpCodeOps[index]) {
1721 peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1723 //fprintf(stderr, "first time for wild opcode #%d\n",index);
1728 pcs->print(stderr,pcs);
1729 pcd->print(stderr,pcd);
1730 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1731 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1735 return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1741 switch(PCI(pcs)->pcop->type) {
1745 //n = PCOR(PCI(pcs)->pcop)->r->name;
1746 n = PCI(pcs)->pcop->name;
1750 n = PCI(pcs)->pcop->name;
1753 if(peepBlock->target.vars[index])
1754 return (strcmp(peepBlock->target.vars[index],n) == 0);
1756 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1757 peepBlock->target.vars[index] = n;
1762 } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
1764 pcs->print(stderr,pcs);
1765 pcd->print(stderr,pcd);
1767 fprintf(stderr, "comparing literal operands of these instructions, result %d\n",
1768 pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop));
1770 return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
1773 /* FIXME - need an else to check the case when the destination
1774 * isn't a wild card */
1776 fprintf(stderr, "Destination is not wild: operand compare =%d\n",
1777 pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop));
1779 return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
1783 /* The pcd has no operand. Lines match if pcs has no operand either*/
1784 return (PCI(pcs)->pcop == NULL);
1788 /* Compare a wild instruction to a regular one. */
1790 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1792 index = PCW(pcd)->id;
1794 DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
1795 pcs->print(stderr,pcs);
1796 pcd->print(stderr,pcd);
1798 peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
1800 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
1801 DFPRINTF((stderr," Failing because labels don't match\n"));
1805 if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1806 // doesn't match because the wild pcode must be a bit skip
1807 DFPRINTF((stderr," Failing match because bit skip is req\n"));
1808 //pcd->print(stderr,pcd);
1809 //pcs->print(stderr,pcs);
1813 if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1814 // doesn't match because the wild pcode must *not* be a bit skip
1815 DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
1816 //pcd->print(stderr,pcd);
1817 //pcs->print(stderr,pcs);
1821 if(PCW(pcd)->operand) {
1822 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1823 if(peepBlock->target.vars[index]) {
1824 int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
1828 DFPRINTF((stderr," (matched)\n"));
1830 DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
1831 DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n",
1832 peepBlock->target.vars[index],
1833 PCI(pcs)->pcop->name));
1838 DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
1839 peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
1844 pcs = findNextInstruction(pcs->next);
1846 //DFPRINTF((stderr," (next to match)\n"));
1847 //pcs->print(stderr,pcs);
1848 } else if(pcd->next) {
1849 /* oops, we ran out of code, but there's more to the rule */
1853 return 1; /* wild card matches */
1859 /*-----------------------------------------------------------------*/
1860 /*-----------------------------------------------------------------*/
1861 static void pCodePeepClrVars(pCodePeep *pcp)
1868 DFPRINTF((stderr," Clearing peep rule vars\n"));
1869 DFPRINTF((stderr," %d %d %d %d %d %d\n",
1870 pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
1871 pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
1873 for(i=0;i<pcp->target.nvars; i++)
1874 pcp->target.vars[i] = NULL;
1875 for(i=0;i<pcp->target.nops; i++)
1876 pcp->target.wildpCodeOps[i] = NULL;
1877 for(i=0;i<pcp->target.nwildpCodes; i++)
1878 pcp->target.wildpCodes[i] = NULL;
1880 for(i=0;i<pcp->replace.nvars; i++)
1881 pcp->replace.vars[i] = NULL;
1882 for(i=0;i<pcp->replace.nops; i++)
1883 pcp->replace.wildpCodeOps[i] = NULL;
1884 for(i=0;i<pcp->replace.nwildpCodes; i++)
1885 pcp->replace.wildpCodes[i] = NULL;
1891 /*-----------------------------------------------------------------*/
1892 /*-----------------------------------------------------------------*/
1893 int pCodePeepMatchRule(pCode *pc)
1895 pCodePeep *peepBlock;
1897 pCodeCSource *pc_cline=NULL;
1901 peeprules = (_DLL *)peepSnippets;
1904 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1906 if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
1907 fprintf(stderr, "skipping rule because target pb is NULL\n");
1911 pCodePeepClrVars(peepBlock);
1914 if(IS_PCCOMMENT(pcin))
1915 pc = pcin = findNextInstruction(pcin->next);
1917 pcin = pc = findNextInstruction(pc);
1919 pct = peepBlock->target.pb->pcHead;
1922 pCode *pcr = peepBlock->replace.pb->pcHead;
1923 if(pcr) pct->print(stderr,pcr);
1927 while(pct && pcin) {
1929 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1932 pcin = findNextInstruction(pcin->next);
1935 //DFPRINTF((stderr," matched\n"));
1938 DFPRINTF((stderr," partial match... no more code\n"));
1942 DFPRINTF((stderr," end of rule\n"));
1946 if(matched && pcin) {
1948 /* So far we matched the rule up to the point of the conditions .
1949 * In other words, all of the opcodes match. Now we need to see
1950 * if the post conditions are satisfied.
1951 * First we check the 'postFalseCond'. This means that we check
1952 * to see if any of the subsequent pCode's in the pCode chain
1953 * following the point just past where we have matched depend on
1954 * the `postFalseCond' as input then we abort the match
1956 DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
1957 //pcin->print(stderr,pcin);
1959 if (pcin && peepBlock->postFalseCond &&
1960 (pCodeSearchCondition(pcin,peepBlock->postFalseCond,0) > 0) )
1963 //fprintf(stderr," condition results = %d\n",pCodeSearchCondition(pcin,peepBlock->postFalseCond));
1966 //if(!matched) fprintf(stderr,"failed on conditions\n");
1975 /* We matched a rule! Now we have to go through and remove the
1976 inefficient code with the optimized version */
1978 DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
1979 printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
1980 DFPRINTF((stderr,"first thing matched\n"));
1981 pc->print(stderr,pc);
1983 DFPRINTF((stderr,"last thing matched\n"));
1984 pcin->print(stderr,pcin);
1989 /* Unlink the original code */
1992 pcprev->next = pcin;
1994 pcin->prev = pc->prev;
2000 /* Converted the deleted pCodes into comments */
2003 pCodeCSource *pc_cline2=NULL;
2008 while(pc && pc!=pcin) {
2010 if(pc->type == PC_OPCODE && PCI(pc)->cline) {
2012 pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2013 pc_cline2 = PCCS(pc_cline2->pc.next);
2015 pc_cline = pc_cline2 = PCI(pc)->cline;
2016 pc_cline->pc.seq = pc->seq;
2020 pCode2str(&buf[2], 254, pc);
2021 pCodeInsertAfter(pcprev, newpCodeCharP(buf));
2022 pcprev = pcprev->next;
2027 pc_cline2->pc.next = NULL;
2032 pCodeDeleteChain(pc,pcin);
2034 /* Generate the replacement code */
2036 pcr = peepBlock->replace.pb->pcHead; // This is the replacement code
2040 /* If the replace pcode is an instruction with an operand, */
2041 /* then duplicate the operand (and expand wild cards in the process). */
2042 if(pcr->type == PC_OPCODE) {
2043 if(PCI(pcr)->pcop) {
2044 /* The replacing instruction has an operand.
2046 if(PCI(pcr)->pcop->type == PO_WILD) {
2047 int index = PCOW(PCI(pcr)->pcop)->id;
2048 //DFPRINTF((stderr,"copying wildopcode\n"));
2049 if(peepBlock->target.wildpCodeOps[index])
2050 pcop = pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2052 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2054 pcop = pCodeOpCopy(PCI(pcr)->pcop);
2056 //DFPRINTF((stderr,"inserting pCode\n"));
2057 pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
2058 } else if (pcr->type == PC_WILD) {
2059 if(PCW(pcr)->invertBitSkipInst)
2060 DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2061 pCodeInsertAfter(pc,
2062 pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2063 PCW(pcr)->invertBitSkipInst));
2064 } else if (pcr->type == PC_COMMENT) {
2065 pCodeInsertAfter(pc, newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2070 DFPRINTF((stderr," NEW Code:"));
2071 if(pc) pc->print(stderr,pc);
2076 /* We have just replaced the inefficient code with the rule.
2077 * Now, we need to re-add the C-source symbols if there are any */
2079 while(pc && pc_cline ) {
2081 pc = findNextInstruction(pc->next);
2083 PCI(pc)->cline = pc_cline;
2084 pc_cline = PCCS(pc_cline->pc.next);
2088 /* Copy C code comments to new code. */
2091 for (; pc && pcout!=pcin; pcout=pcout->next) {
2092 if (pcout->type==PC_OPCODE && PCI(pcout)->cline) {
2093 while (pc->type!=PC_OPCODE || PCI(pc)->cline) {
2099 PCI(pc)->cline = PCI(pcout)->cline;
2107 peeprules = peeprules->next;
2109 DFPRINTF((stderr," no rule matched\n"));