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 char *Safe_strdup(char *str);
44 int getpCode(char *mnem,int dest);
45 extern pCodeInstruction *pic14Mnemonics[];
48 /****************************************************************/
50 * rootRules - defined in SDCCpeep.c
51 * This is a pointer to the (parsed) peephole rules that are
52 * defined in peep.def.
55 //extern peepRule *rootRules;
60 /****************************************************************/
61 /****************************************************************/
69 typedef struct pCodePeepSnippets
76 /****************************************************************/
80 /****************************************************************/
82 static pCodePeepSnippets *peepSnippets=NULL;
84 /****************************************************************/
88 /****************************************************************/
90 static pCodePeep *curPeep=NULL;
92 /****************************************************************/
96 /****************************************************************/
98 static pBlock *curBlock=NULL;
101 typedef struct pCodeToken
103 int tt; // token type;
112 pCodeToken tokArr[50];
128 typedef struct parsedPattern {
129 struct pcPattern *pcp;
133 #define MAX_PARSEDPATARR 50
134 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
135 unsigned int parsedPatIdx=0;
147 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
148 static char pcpat_number[] = {PCT_NUMBER, 0};
149 static char pcpat_string[] = {PCT_STRING, 0};
150 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
151 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
152 static char pcpat_comma[] = {PCT_COMMA, 0};
155 typedef struct pcPattern {
156 char pt; // Pattern type
157 char *tokens; // list of tokens that describe the pattern
158 void * (*f) (void *);
161 pcPattern pcpArr[] = {
162 {PCP_LABEL, pcpat_label, NULL},
163 {PCP_WILDSTR, pcpat_wildString, NULL},
164 {PCP_STR, pcpat_string, NULL},
165 {PCP_WILDVAR, pcpat_wildVar, NULL},
166 {PCP_COMMA, pcpat_comma, NULL},
167 {PCP_NUMBER, pcpat_number, NULL}
170 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
172 // Assembly Line Token
184 static char alt_label[] = { PCP_LABEL, 0};
185 static char alt_mnem0[] = { PCP_STR, 0};
186 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
187 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
188 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
189 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
190 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
191 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
193 static void * cvt_altpat_label(void *pp);
194 static void * cvt_altpat_mnem0(void *pp);
195 static void * cvt_altpat_mnem0a(void *pp);
196 static void * cvt_altpat_mnem1(void *pp);
197 static void * cvt_altpat_mnem1a(void *pp);
198 static void * cvt_altpat_mnem1b(void *pp);
199 static void * cvt_altpat_mnem2(void *pp);
200 static void * cvt_altpat_mnem2a(void *pp);
202 pcPattern altArr[] = {
203 {ALT_LABEL, alt_label, cvt_altpat_label},
204 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
205 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
206 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
207 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
208 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
209 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
210 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
214 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
216 // forward declarations
217 static void * DLL_append(_DLL *list, _DLL *next);
219 /*-----------------------------------------------------------------*/
220 /* cvt_extract_destination - helper function extracts the register */
221 /* destination from a parsedPattern. */
223 /*-----------------------------------------------------------------*/
224 static int cvt_extract_destination(parsedPattern *pp)
227 if(pp->pct[0].tt == PCT_STRING) {
229 // just check first letter for now
231 if(toupper(*pp->pct[0].tok.s) == 'F')
234 } else if (pp->pct[0].tt == PCT_NUMBER) {
244 /*-----------------------------------------------------------------*/
245 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
246 /* if *reg is the "status" register and *bit is one of the */
247 /* status bits, then this function will create a new pCode op */
248 /* containing the status register. */
249 /*-----------------------------------------------------------------*/
251 static pCodeOp *cvt_extract_status(char *reg, char *bit)
255 if(STRCASECMP(reg, pc_status.pcop.name))
262 if(toupper(*bit) == 'C')
263 return PCOP(popCopyGPR2Bit(&pc_status,PIC_C_BIT));
264 if(toupper(*bit) == 'Z')
265 return PCOP(popCopyGPR2Bit(&pc_status,PIC_Z_BIT));
269 if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
270 return PCOP(popCopyGPR2Bit(&pc_status,PIC_DC_BIT));
276 /*-----------------------------------------------------------------*/
277 /* cvt_altpat_label - convert assembly line type to a pCode label */
278 /* INPUT: pointer to the parsedPattern */
282 /* label pattern => '%' number ':' */
283 /* at this point, we wish to extract only the 'number' */
285 /*-----------------------------------------------------------------*/
286 static void * cvt_altpat_label(void *pp)
288 parsedPattern *p = pp;
290 fprintf(stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n);
291 return newpCodeOpLabel(-p->pct[1].tok.n);
295 /*-----------------------------------------------------------------*/
296 /*-----------------------------------------------------------------*/
297 static void * cvt_altpat_mnem0(void *pp)
299 parsedPattern *p = pp;
302 pCodeInstruction *pci=NULL;
304 fprintf(stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s);
306 opcode = getpCode(p->pct[0].tok.s,0);
308 fprintf(stderr, "Bad mnemonic\n");
312 pci = PCI(newpCode(opcode, NULL));
315 fprintf(stderr,"couldn't find mnemonic\n");
321 /*-----------------------------------------------------------------*/
322 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
325 /* pp[0] - wild var */
327 /*-----------------------------------------------------------------*/
328 static void * cvt_altpat_mnem0a(void *pp)
330 parsedPattern *p = pp;
332 fprintf(stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n);
334 return newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
338 /*-----------------------------------------------------------------*/
339 /* cvt_altpat_mem1 - convert assembly line type to a pCode */
340 /* instruction with 1 operand. */
343 /* pp[1] - Operand */
345 /*-----------------------------------------------------------------*/
346 static void * cvt_altpat_mnem1(void *pp)
349 parsedPattern *p = pp;
352 pCodeInstruction *pci=NULL;
355 fprintf(stderr,"altpat_mnem1 %s var %s\n", p->pct[0].tok.s,p[1].pct[0].tok.s);
357 opcode = getpCode(p->pct[0].tok.s,0);
359 fprintf(stderr, "Bad mnemonic\n");
363 if(pic14Mnemonics[opcode]->bit_inst)
364 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
366 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
369 pci = PCI(newpCode(opcode, pcosubtype));
372 fprintf(stderr,"couldn't find mnemonic\n");
378 /*-----------------------------------------------------------------*/
379 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
380 /* instruction with 1 wild operand. */
383 /* pp[1] - wild var */
385 /*-----------------------------------------------------------------*/
386 static void * cvt_altpat_mnem1a(void *pp)
388 parsedPattern *p = pp;
391 pCodeInstruction *pci=NULL;
394 fprintf(stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n);
396 opcode = getpCode(p->pct[0].tok.s,0);
398 fprintf(stderr, "Bad mnemonic\n");
402 if(pic14Mnemonics[opcode]->bit_inst)
403 pcosubtype = newpCodeOp(NULL,PO_BIT);
405 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
408 pci = PCI(newpCode(opcode,
409 newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
412 fprintf(stderr,"couldn't find mnemonic\n");
418 /*-----------------------------------------------------------------*/
419 /*-----------------------------------------------------------------*/
420 static void * cvt_altpat_mnem1b(void *pp)
422 parsedPattern *p = pp;
425 pCodeInstruction *pci=NULL;
427 fprintf(stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n);
429 opcode = getpCode(p->pct[0].tok.s,0);
431 fprintf(stderr, "Bad mnemonic\n");
435 pci = PCI(newpCode(opcode, newpCodeOpLit(p[1].pct[0].tok.n) ));
438 fprintf(stderr,"couldn't find mnemonic\n");
444 /*-----------------------------------------------------------------*/
445 /*-----------------------------------------------------------------*/
446 static void * cvt_altpat_mnem2(void *pp)
448 parsedPattern *p = pp;
452 pCodeInstruction *pci=NULL;
455 dest = cvt_extract_destination(&p[3]);
457 fprintf(stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
464 opcode = getpCode(p->pct[0].tok.s,dest);
466 fprintf(stderr, "Bad mnemonic\n");
470 if(pic14Mnemonics[opcode]->bit_inst) {
471 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
472 if(pcosubtype == NULL) {
473 fprintf(stderr, "bad operand?\n");
478 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
481 pci = PCI(newpCode(opcode,pcosubtype));
484 fprintf(stderr,"couldn't find mnemonic\n");
490 /*-----------------------------------------------------------------*/
491 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
492 /* instruction with 1 wild operand and a */
493 /* destination operand (e.g. w or f) */
496 /* pp[1] - wild var */
498 /* pp[3] - destination */
500 /*-----------------------------------------------------------------*/
501 static void * cvt_altpat_mnem2a(void *pp)
503 parsedPattern *p = pp;
507 pCodeInstruction *pci=NULL;
510 dest = cvt_extract_destination(&p[3]);
512 fprintf(stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
519 opcode = getpCode(p->pct[0].tok.s,dest);
521 fprintf(stderr, "Bad mnemonic\n");
525 if(pic14Mnemonics[opcode]->bit_inst)
526 pcosubtype = newpCodeOp(NULL,PO_BIT);
528 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
531 pci = PCI(newpCode(opcode,
532 newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
535 fprintf(stderr,"couldn't find mnemonic\n");
541 /*-----------------------------------------------------------------*/
542 /*-----------------------------------------------------------------*/
545 static void parseLineNode(char *ln)
556 tokArr[tokIdx++].tt = PCT_SPACE;
557 while (isspace (*ln))
564 tokArr[tokIdx].tt = PCT_NUMBER;
565 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
573 tokArr[tokIdx++].tt = PCT_PERCENT;
576 tokArr[tokIdx++].tt = PCT_COLON;
579 tokArr[tokIdx].tok.s = Safe_strdup(ln);
580 tokArr[tokIdx++].tt = PCT_COMMENT;
583 tokArr[tokIdx++].tt = PCT_COMMA;
592 while( (isalpha(*ln) || isdigit(*ln)) && i<49)
598 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
599 //fprintf(stderr," string %s",tokArr[tokIdx].tok.s);
601 tokArr[tokIdx++].tt = PCT_STRING;
608 tokArr[tokIdx].tt = 0;
612 /*-----------------------------------------------------------------*/
613 /*-----------------------------------------------------------------*/
617 void dump1Token(pCodeTokens tt)
622 fprintf(stderr, " space ");
625 fprintf(stderr, " pct ");
629 fprintf(stderr, " col ");
633 fprintf(stderr, " com ");
638 fprintf(stderr, " str ");
639 //fprintf(stderr,"%s",tokArr[i].tok.s);
642 fprintf(stderr, " num ");
643 //fprintf(stderr,"%d",tokArr[i].tok.n);
650 /*-----------------------------------------------------------------*/
651 /*-----------------------------------------------------------------*/
653 int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
657 if(!pct || !pat || !*pat)
660 //fprintf(stderr,"comparing against:\n");
662 while(i < max_tokens) {
665 //fprintf(stderr,"matched\n");
669 //dump1Token(*pat); fprintf(stderr,"\n");
683 /*-----------------------------------------------------------------*/
684 /*-----------------------------------------------------------------*/
686 int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
690 if(!pct || !pat || !*pct)
694 while(i < max_tokens) {
697 //fprintf(stderr,"matched\n");
701 //dump1Token(*pat); fprintf(stderr,"\n");
703 if( !pat || !pat->pcp )
706 if (pat->pcp->pt != *pct)
709 //fprintf(stderr," pct=%d\n",*pct);
718 /*-----------------------------------------------------------------*/
719 /*-----------------------------------------------------------------*/
721 int advTokIdx(int *v, int amt)
724 if((unsigned) (*v + amt) > tokIdx)
732 /*-----------------------------------------------------------------*/
733 /*-----------------------------------------------------------------*/
735 void dumpTokens(void)
743 for(i=0; i<=tokIdx; i++)
744 dump1Token(tokArr[i].tt);
757 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
758 char * cP1stop = NULL;
759 char * cP2ndop = NULL;
761 //pCodeOp *pcl = NULL; // Storage for a label
762 //pCodeOp *pco1 = NULL; // 1st operand
763 //pCodeOp *pco2 = NULL; // 2nd operand
764 //pCode *pc = NULL; // Mnemonic
775 ParseStates state = PS_START;
781 //fprintf(stderr,"ltokIdx = %d\n",ltokIdx);
783 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
784 && (advTokIdx(<okIdx, 1)) ) // eat space
788 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
790 //fprintf(stderr,"found token pattern match\n");
791 switch(pcpArr[lpcpIdx].pt) {
793 if(state == PS_START){
794 fprintf(stderr," label\n");
795 state = PS_HAVE_LABEL;
797 fprintf(stderr," bad state (%d) for label\n",state);
801 fprintf(stderr," %s is",tokArr[ltokIdx].tok.s);
805 fprintf(stderr," mnem\n");
806 cPmnem = tokArr[ltokIdx].tok.s;
807 state = PS_HAVE_MNEM;
810 fprintf(stderr," 1st operand\n");
811 cP1stop = tokArr[ltokIdx].tok.s;
812 //pco1 = newpCodeOp(NULL,PO_GPR_REGISTER);
813 state = PS_HAVE_1OPERAND;
815 case PS_HAVE_1OPERAND:
816 fprintf(stderr," error expecting comma\n");
819 fprintf(stderr," 2 operands\n");
820 cP2ndop = tokArr[ltokIdx].tok.s;
822 case PS_HAVE_2OPERANDS:
831 fprintf(stderr," wild mnem\n");
832 state = PS_HAVE_MNEM;
835 fprintf(stderr," 1st operand is wild\n");
836 state = PS_HAVE_1OPERAND;
838 case PS_HAVE_1OPERAND:
839 fprintf(stderr," error expecting comma\n");
842 fprintf(stderr," 2nd operand is wild\n");
844 case PS_HAVE_2OPERANDS:
853 fprintf(stderr," ERROR number\n");
856 fprintf(stderr," 1st operand is a number\n");
857 state = PS_HAVE_1OPERAND;
859 case PS_HAVE_1OPERAND:
860 fprintf(stderr," error expecting comma\n");
863 fprintf(stderr," 2nd operand is a number\n");
865 case PS_HAVE_2OPERANDS:
873 if(state == PS_HAVE_1OPERAND){
874 fprintf(stderr," got a comma\n");
875 state = PS_HAVE_COMMA;
877 fprintf(stderr," unexpected comma\n");
881 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
882 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
885 //dump1Token(tokArr[ltokIdx].tt);
887 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
888 fprintf(stderr," reached end \n");
895 } while ((++lpcpIdx < PCPATTERNS) && !matching);
899 parsedPatArr[lparsedPatIdx].pcp = NULL;
900 parsedPatArr[lparsedPatIdx].pct = NULL;
906 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
909 pc = altArr[k].f(&parsedPatArr[j]);
911 pc->print(stderr,pc);
912 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
918 while(j<=lparsedPatIdx && k<ALTPATTERNS);
921 fprintf(stderr,"\nConverting parsed line to pCode:\n\n");
925 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
926 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
927 fprintf(stderr," %d",parsedPatArr[j].pcp->pt);
930 while(j<lparsedPatIdx);
932 fprintf(stderr,"\n");
939 /*-----------------------------------------------------------------*/
940 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
943 /* SDCCpeeph parses the peep rules file and extracts variables, */
944 /* removes white space, and checks the syntax. This function */
945 /* extends that processing to produce pCode objects. You can kind */
946 /* think of this function as an "assembler", though instead of */
947 /* taking raw text to produce machine code, it produces pCode. */
949 /*-----------------------------------------------------------------*/
951 void peepRules2pCode(peepRule *rules)
956 pCodePeepSnippets *pcps;
958 for (pr = rules; pr; pr = pr->next) {
959 fprintf(stderr,"\nRule:\n\n");
961 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
962 curPeep = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
963 //curPeep->target = curPeep->replace = NULL;
964 curPeep->vars = NULL; curPeep->wildpCodes = NULL;
965 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
967 curPeep->target = curBlock = newpCodeChain(NULL, 'W', NULL);
969 for(ln = pr->match; ln; ln = ln->next) {
971 fprintf(stderr,"%s\n",ln->line);
973 parseLineNode(ln->line);
978 fprintf(stderr,"\nReplaced by:\n");
980 curPeep->replace = curBlock = newpCodeChain(NULL, 'W', NULL);
982 for(ln = pr->replace; ln; ln = ln->next)
983 fprintf(stderr,"%s\n",ln->line);
986 fprintf(stderr,"\nCondition: %s\n",pr->cond);
993 void printpCodeString(FILE *of, pCode *pc, int max)
997 while(pc && (i++<max)) {
1003 /*-----------------------------------------------------------------*/
1004 /* _DLL * DLL_append */
1006 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1007 /* If The list to which we want to append is non-existant then one */
1008 /* is created. Other wise, the end of the list is sought out and */
1009 /* a new DLL object is appended to it. In either case, the void */
1010 /* *data is added to the newly created DLL object. */
1011 /*-----------------------------------------------------------------*/
1013 static void * DLL_append(_DLL *list, _DLL *next)
1018 /* If there's no list, then create one: */
1020 next->next = next->prev = NULL;
1025 /* Search for the end of the list. */
1030 /* Now append the new DLL object */
1041 /*-----------------------------------------------------------------
1043 pCode peephole optimization
1046 The pCode "peep hole" optimization is not too unlike the peep hole
1047 optimization in SDCCpeeph.c. The major difference is that here we
1048 use pCode's whereas there we use ASCII strings. The advantage with
1049 pCode's is that we can ascertain flow information in the instructions
1053 <FIX ME> - elaborate...
1055 -----------------------------------------------------------------*/
1058 /*-----------------------------------------------------------------*/
1060 /*-----------------------------------------------------------------*/
1061 int pCodePeepCompare(pCode *pc, pCodePeep *pcp)
1063 pCode *pcfrom,*pcto;
1066 for( pcto=pcp->target; pcto; pcto=pcto->next) {
1068 pcfrom = findNextInstruction(pcfrom);
1071 (PCI(pcfrom)->op == PCI(pcto)->op ||
1072 PCI(pcto)->op == POC_WILD))
1079 /*-----------------------------------------------------------------*/
1081 /*-----------------------------------------------------------------*/
1082 void pCodePeepSearch(pCodePeep *snippet)
1090 /* compare the chain to the pCode that we've
1091 got so far. If a match is found, then replace
1094 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1095 for(pc = pb->pcHead; pc; pc = pc->next) {
1096 pCodePeepCompare(pc,snippet);
1104 pBlock *pBlockAppend(pBlock *pb1, pBlock *pb2)
1121 void pCodePeepInit(void)
1127 pCodePeepSnippets *pcps;
1129 /* Declare a peep code snippet */
1130 /* <FIXME> do I really need a separate struct just to DLL the snippets? */
1131 /* e.g. I could put the DLL into the pCodePeep structure */
1132 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1133 pcp = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1134 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1137 pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1138 addpCode2pBlock( pb, newpCode(POC_MOVFW, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1142 pcp->replace = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1144 /* Allocate space to store pointers to the wildcard variables */
1146 pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1147 pcp->nwildpCodes = 0;
1148 pcp->wildpCodes = NULL;
1150 pcp->postFalseCond = PCC_Z;
1151 pcp->postTrueCond = PCC_NONE;
1153 fprintf(stderr,"Peep rule\nTarget:\n");
1154 printpCodeString(stderr,pcp->target->pcHead, 10);
1155 fprintf(stderr,"Replaced with:\n");
1156 printpCodeString(stderr,pcp->replace->pcHead, 10);
1158 /* Now for another peep example */
1159 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1160 pcp = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1161 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1177 The %3 and %4 are wild opcodes. Since the opcodes
1178 are stored in a different array than the wild operands,
1179 they can have the same indices and not conflict. So
1180 below, the %3 is really a %0, %4 is a %1.
1187 // Create a new wild operand subtyped as a bit
1188 pcwb = newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1));
1191 pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSC,pcwb));
1193 pcl = newpCodeOpLabel(-1);
1194 pcw = newpCodeOpWild(1, pcp, pcl);
1195 addpCode2pBlock( pb, newpCode(POC_GOTO, pcw));
1196 addpCode2pBlock( pb, newpCodeWild(0,NULL,NULL));
1197 addpCode2pBlock( pb, newpCodeWild(1,NULL,pcw));
1202 pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSS, pcwb));
1203 addpCode2pBlock( pb, newpCodeWild(0,NULL,NULL));
1204 addpCode2pBlock( pb, newpCodeWild(1,NULL,pcw));
1208 /* Allocate space to store pointers to the wildcard variables */
1210 pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1211 pcp->nwildpCodes = 2;
1212 pcp->wildpCodes = Safe_calloc(pcp->nwildpCodes, sizeof(pCode *));
1214 pcp->postFalseCond = PCC_NONE;
1215 pcp->postTrueCond = PCC_NONE;
1229 /* Now for another peep example */
1230 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1231 pcp = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1232 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1237 pcw = newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER));
1239 pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, pcw));
1240 addpCode2pBlock( pb, newpCode(POC_MOVWF, pcw));
1244 pb = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, pcw));
1248 /* Allocate space to store pointers to the wildcard variables */
1250 pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1251 pcp->nwildpCodes = 0;
1252 pcp->wildpCodes = NULL;
1254 pcp->postFalseCond = PCC_NONE;
1255 pcp->postTrueCond = PCC_NONE;
1263 /*-----------------------------------------------------------------*/
1264 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1266 /* return conditions */
1267 /* 1 - The Condition was found for a pCode's input */
1268 /* 0 - No matching condition was found for the whole chain */
1269 /* -1 - The Condition was found for a pCode's output */
1271 /*-----------------------------------------------------------------*/
1272 int pCodeSearchCondition(pCode *pc, unsigned int cond)
1277 /* If we reach a function end (presumably an end since we most
1278 probably began the search in the middle of a function), then
1279 the condition was not found. */
1280 if(pc->type == PC_FUNCTION)
1283 if(pc->type == PC_OPCODE) {
1284 if(PCI(pc)->inCond & cond)
1286 if(PCI(pc)->outCond & cond)
1295 /*-----------------------------------------------------------------*/
1296 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1297 /* see they're the same. */
1298 /*-----------------------------------------------------------------*/
1299 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1301 int index; // index into wild card arrays
1303 if(pcs->type == pcd->type) {
1305 if(pcs->type == PC_OPCODE) {
1307 /* If the opcodes don't match then the line doesn't match */
1308 if(PCI(pcs)->op != PCI(pcd)->op)
1311 fprintf(stderr,"%s comparing\n",__FUNCTION__);
1312 pcs->print(stderr,pcs);
1313 pcd->print(stderr,pcd);
1315 /* Compare the operands */
1316 if(PCI(pcd)->pcop) {
1317 if (PCI(pcd)->pcop->type == PO_WILD) {
1318 index = PCOW(PCI(pcd)->pcop)->id;
1320 fprintf(stderr,"destination is wild\n");
1321 #ifdef DEBUG_PCODEPEEP
1322 if (index > peepBlock->nvars) {
1323 fprintf(stderr,"%s - variables exceeded\n",__FUNCTION__);
1327 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1331 if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1332 n = PCOR(PCI(pcs)->pcop)->r->name;
1334 n = PCI(pcs)->pcop->name;
1336 if(peepBlock->vars[index])
1337 return (strcmp(peepBlock->vars[index],n) == 0);
1339 peepBlock->vars[index] = n; //PCI(pcs)->pcop->name;
1345 /* The pcd has no operand. Lines match if pcs has no operand either*/
1346 return (PCI(pcs)->pcop == NULL);
1351 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1355 index = PCW(pcd)->id;
1357 fprintf(stderr,"%s comparing wild cards\n",__FUNCTION__);
1358 pcs->print(stderr,pcs);
1359 pcd->print(stderr,pcd);
1361 peepBlock->wildpCodes[PCW(pcd)->id] = pcs;
1363 /* Check for a label associated with this wild pCode */
1364 // If the wild card has a label, make sure the source code does too.
1365 if(PCW(pcd)->label) {
1369 labindex = PCOW(PCW(pcd)->label)->id;
1370 if(peepBlock->vars[labindex] == NULL) {
1371 // First time to encounter this label
1372 peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
1373 fprintf(stderr,"first time for a label\n");
1375 if(strcmp(peepBlock->vars[labindex],PCL(pcs->label->pc)->label) != 0) {
1376 fprintf(stderr,"labels don't match\n");
1379 fprintf(stderr,"matched a label\n");
1384 if(PCW(pcd)->operand) {
1385 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1386 if(peepBlock->vars[index]) {
1387 int i = (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
1389 fprintf(stderr," (matched)\n");
1391 fprintf(stderr," (no match: wild card operand mismatch\n");
1392 fprintf(stderr," peepblock= %s, pcodeop= %s\n",
1393 peepBlock->vars[index],
1394 PCI(pcs)->pcop->name);
1398 peepBlock->vars[index] = PCI(pcs)->pcop->name;
1403 pcs = findNextInstruction(pcs->next);
1405 fprintf(stderr," (next to match)\n");
1406 pcs->print(stderr,pcs);
1409 return 1; /* wild card matches */
1415 /*-----------------------------------------------------------------*/
1416 /*-----------------------------------------------------------------*/
1417 void pCodePeepClrVars(pCodePeep *pcp)
1424 for(i=0;i<pcp->nvars; i++)
1425 pcp->vars[i] = NULL;
1429 /*-----------------------------------------------------------------*/
1430 /*-----------------------------------------------------------------*/
1431 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
1437 pc2->next = pc1->next;
1439 pc1->next->prev = pc2;
1446 /*-----------------------------------------------------------------*/
1447 /* pCodeOpCopy - copy a pcode operator */
1448 /*-----------------------------------------------------------------*/
1449 static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
1451 pCodeOp *pcopnew=NULL;
1456 switch(pcop->type) {
1459 pcopnew = Safe_calloc(1,sizeof(pCodeOpBit) );
1460 PCOB(pcopnew)->bit = PCOB(pcop)->bit;
1461 PCOB(pcopnew)->inBitSpace = PCOB(pcop)->inBitSpace;
1466 /* Here we expand the wild card into the appropriate type: */
1467 /* By recursively calling pCodeOpCopy */
1468 if(PCOW(pcop)->matched)
1469 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
1472 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
1473 pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
1474 fprintf(stderr,"copied a wild op named %s\n",pcopnew->name);
1481 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1482 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
1487 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1488 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1491 case PO_GPR_REGISTER:
1493 case PO_SFR_REGISTER:
1502 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1506 pcopnew->type = pcop->type;
1507 pcopnew->name = Safe_strdup(pcop->name);
1513 /*-----------------------------------------------------------------*/
1514 /* pCodeCopy - copy a pcode */
1515 /*-----------------------------------------------------------------*/
1516 static pCode *pCodeCopy(pCode *pc)
1521 pcnew = newpCode(pc->type,pc->pcop);
1524 /*-----------------------------------------------------------------*/
1525 /*-----------------------------------------------------------------*/
1526 void pCodeDeleteChain(pCode *f,pCode *t)
1531 fprintf(stderr,"delete pCode:\n");
1539 /*-----------------------------------------------------------------*/
1540 /*-----------------------------------------------------------------*/
1541 int pCodePeepMatchRule(pCode *pc)
1543 pCodePeep *peepBlock;
1548 peeprules = (_DLL *)peepSnippets;
1551 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1552 if(!peepBlock || !peepBlock->target || !peepBlock->target->pcHead)
1555 pCodePeepClrVars(peepBlock);
1558 pct = peepBlock->target->pcHead;
1560 while(pct && pcin) {
1562 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1565 pcin = findNextInstruction(pcin->next);
1568 fprintf(stderr," matched\n");
1570 fprintf(stderr," end of code\n");
1572 fprintf(stderr," end of rule\n");
1575 if(matched && pcin) {
1577 /* So far we matched the rule up to the point of the conditions .
1578 * In other words, all of the opcodes match. Now we need to see
1579 * if the post conditions are satisfied.
1580 * First we check the 'postFalseCond'. This means that we check
1581 * to see if any of the subsequent pCode's in the pCode chain
1582 * following the point just past where we have matched depend on
1583 * the `postFalseCond' as input then we abort the match
1585 fprintf(stderr," matched rule so far, now checking conditions\n");
1586 if (peepBlock->postFalseCond &&
1587 (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
1591 if(matched && pcin) {
1597 /* We matched a rule! Now we have to go through and remove the
1598 inefficient code with the optimized version */
1600 fprintf(stderr, "Found a pcode peep match:\nRule:\n");
1601 printpCodeString(stderr,peepBlock->target->pcHead,10);
1602 fprintf(stderr,"first thing matched\n");
1603 pc->print(stderr,pc);
1604 fprintf(stderr,"last thing matched\n");
1605 pcin->print(stderr,pcin);
1607 /* Unlink the original code */
1609 pcprev->next = pcin;
1610 pcin->prev = pc->prev;
1611 pCodeDeleteChain(pc,pcin);
1613 /* Generate the replacement code */
1615 pcr = peepBlock->replace->pcHead; // This is the replacement code
1618 /* If the replace pcode is an instruction with an operand, */
1619 /* then duplicate the operand (and expand wild cards in the process). */
1620 if(pcr->type == PC_OPCODE) {
1622 pcop = pCodeOpCopy(PCI(pcr)->pcop);
1623 fprintf(stderr,"inserting pCode\n");
1624 pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
1625 } else if (pcr->type == PC_WILD) {
1626 pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
1631 pc->print(stderr,pc);
1638 peeprules = peeprules->next;
1654 /*******************/
1655 pCode *parseLineNode(char *ln)
1657 char buffer[50], *s;
1658 int state=0; //0 label, 1 mnemonic, 2 operand, 3 operand, 4 comment
1661 // pCodeLabel *pcl = NULL;
1671 /* skip white space */
1672 while (isspace (*ln))
1677 case 0: // look for a label
1678 case 1: // look for mnemonic
1689 var = strtol(ln, &ln, 10);
1691 // valid wild card label
1692 fprintf(stderr, " wildcard label: %d\n",var);
1695 fprintf(stderr, " wild opcode: %d\n",var), state++;
1699 // Extract the label/mnemonic from the line
1702 while(*ln && !(isspace(*ln) || *ln == ':'))
1707 fprintf(stderr," regular label: %s\n",buffer), ln++;
1709 fprintf(stderr," regular mnem: %s\n",buffer), state++;