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
32 pCodeOp *popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
35 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype);
36 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
37 pCode * findNextInstruction(pCode *pc);
38 char *Safe_strdup(char *str);
39 int getpCode(char *mnem,int dest);
40 extern pCodeInstruction *pic14Mnemonics[];
43 /****************************************************************/
45 * rootRules - defined in SDCCpeep.c
46 * This is a pointer to the (parsed) peephole rules that are
47 * defined in peep.def.
50 //extern peepRule *rootRules;
55 /****************************************************************/
56 /****************************************************************/
64 typedef struct pCodePeepSnippets
71 /****************************************************************/
75 /****************************************************************/
77 static pCodePeepSnippets *peepSnippets=NULL;
79 /****************************************************************/
83 /****************************************************************/
85 static pCodePeep *curPeep=NULL;
87 /****************************************************************/
91 /****************************************************************/
93 static pBlock *curBlock=NULL;
96 typedef struct pCodeToken
98 int tt; // token type;
107 pCodeToken tokArr[50];
123 typedef struct parsedPattern {
124 struct pcPattern *pcp;
128 #define MAX_PARSEDPATARR 50
129 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
130 unsigned int parsedPatIdx=0;
142 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
143 static char pcpat_number[] = {PCT_NUMBER, 0};
144 static char pcpat_string[] = {PCT_STRING, 0};
145 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
146 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
147 static char pcpat_comma[] = {PCT_COMMA, 0};
150 typedef struct pcPattern {
151 char pt; // Pattern type
152 char *tokens; // list of tokens that describe the pattern
153 void * (*f) (void *);
156 pcPattern pcpArr[] = {
157 {PCP_LABEL, pcpat_label, NULL},
158 {PCP_WILDSTR, pcpat_wildString, NULL},
159 {PCP_STR, pcpat_string, NULL},
160 {PCP_WILDVAR, pcpat_wildVar, NULL},
161 {PCP_COMMA, pcpat_comma, NULL},
162 {PCP_NUMBER, pcpat_number, NULL}
165 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
167 // Assembly Line Token
179 static char alt_label[] = { PCP_LABEL, 0};
180 static char alt_mnem0[] = { PCP_STR, 0};
181 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
182 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
183 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
184 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
185 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
186 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
188 static void * cvt_altpat_label(void *pp);
189 static void * cvt_altpat_mnem0(void *pp);
190 static void * cvt_altpat_mnem0a(void *pp);
191 static void * cvt_altpat_mnem1(void *pp);
192 static void * cvt_altpat_mnem1a(void *pp);
193 static void * cvt_altpat_mnem1b(void *pp);
194 static void * cvt_altpat_mnem2(void *pp);
195 static void * cvt_altpat_mnem2a(void *pp);
197 pcPattern altArr[] = {
198 {ALT_LABEL, alt_label, cvt_altpat_label},
199 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
200 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
201 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
202 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
203 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
204 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
205 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
209 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
211 // forward declarations
212 static void * DLL_append(_DLL *list, _DLL *next);
214 /*-----------------------------------------------------------------*/
215 /* cvt_extract_destination - helper function extracts the register */
216 /* destination from a parsedPattern. */
218 /*-----------------------------------------------------------------*/
219 static int cvt_extract_destination(parsedPattern *pp)
222 if(pp->pct[0].tt == PCT_STRING) {
224 // just check first letter for now
226 if(toupper(*pp->pct[0].tok.s) == 'F')
229 } else if (pp->pct[0].tt == PCT_NUMBER) {
239 /*-----------------------------------------------------------------*/
240 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
241 /* if *reg is the "status" register and *bit is one of the */
242 /* status bits, then this function will create a new pCode op */
243 /* containing the status register. */
244 /*-----------------------------------------------------------------*/
246 static pCodeOp *cvt_extract_status(char *reg, char *bit)
250 if(strcasecmp(reg, pc_status.pcop.name))
257 if(toupper(*bit) == 'C')
258 return PCOP(popCopyGPR2Bit(&pc_status,PIC_C_BIT));
259 if(toupper(*bit) == 'Z')
260 return PCOP(popCopyGPR2Bit(&pc_status,PIC_Z_BIT));
264 if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
265 return PCOP(popCopyGPR2Bit(&pc_status,PIC_DC_BIT));
271 /*-----------------------------------------------------------------*/
272 /* cvt_altpat_label - convert assembly line type to a pCode label */
273 /* INPUT: pointer to the parsedPattern */
277 /* label pattern => '%' number ':' */
278 /* at this point, we wish to extract only the 'number' */
280 /*-----------------------------------------------------------------*/
281 static void * cvt_altpat_label(void *pp)
283 parsedPattern *p = pp;
285 fprintf(stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n);
286 return newpCodeOpLabel(-p->pct[1].tok.n);
290 /*-----------------------------------------------------------------*/
291 /*-----------------------------------------------------------------*/
292 static void * cvt_altpat_mnem0(void *pp)
294 parsedPattern *p = pp;
297 pCodeInstruction *pci=NULL;
299 fprintf(stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s);
301 opcode = getpCode(p->pct[0].tok.s,0);
303 fprintf(stderr, "Bad mnemonic\n");
307 pci = PCI(newpCode(opcode, NULL));
310 fprintf(stderr,"couldn't find mnemonic\n");
316 /*-----------------------------------------------------------------*/
317 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
320 /* pp[0] - wild var */
322 /*-----------------------------------------------------------------*/
323 static void * cvt_altpat_mnem0a(void *pp)
325 parsedPattern *p = pp;
327 fprintf(stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n);
329 return newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
333 /*-----------------------------------------------------------------*/
334 /* cvt_altpat_mem1 - convert assembly line type to a pCode */
335 /* instruction with 1 operand. */
338 /* pp[1] - Operand */
340 /*-----------------------------------------------------------------*/
341 static void * cvt_altpat_mnem1(void *pp)
344 parsedPattern *p = pp;
347 pCodeInstruction *pci=NULL;
350 fprintf(stderr,"altpat_mnem1 %s var %s\n", p->pct[0].tok.s,p[1].pct[0].tok.s);
352 opcode = getpCode(p->pct[0].tok.s,0);
354 fprintf(stderr, "Bad mnemonic\n");
358 if(pic14Mnemonics[opcode]->bit_inst)
359 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
361 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
364 pci = PCI(newpCode(opcode, pcosubtype));
367 fprintf(stderr,"couldn't find mnemonic\n");
373 /*-----------------------------------------------------------------*/
374 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
375 /* instruction with 1 wild operand. */
378 /* pp[1] - wild var */
380 /*-----------------------------------------------------------------*/
381 static void * cvt_altpat_mnem1a(void *pp)
383 parsedPattern *p = pp;
386 pCodeInstruction *pci=NULL;
389 fprintf(stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n);
391 opcode = getpCode(p->pct[0].tok.s,0);
393 fprintf(stderr, "Bad mnemonic\n");
397 if(pic14Mnemonics[opcode]->bit_inst)
398 pcosubtype = newpCodeOp(NULL,PO_BIT);
400 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
403 pci = PCI(newpCode(opcode,
404 newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
407 fprintf(stderr,"couldn't find mnemonic\n");
413 /*-----------------------------------------------------------------*/
414 /*-----------------------------------------------------------------*/
415 static void * cvt_altpat_mnem1b(void *pp)
417 parsedPattern *p = pp;
420 pCodeInstruction *pci=NULL;
422 fprintf(stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n);
424 opcode = getpCode(p->pct[0].tok.s,0);
426 fprintf(stderr, "Bad mnemonic\n");
430 pci = PCI(newpCode(opcode, newpCodeOpLit(p[1].pct[0].tok.n) ));
433 fprintf(stderr,"couldn't find mnemonic\n");
439 /*-----------------------------------------------------------------*/
440 /*-----------------------------------------------------------------*/
441 static void * cvt_altpat_mnem2(void *pp)
443 parsedPattern *p = pp;
447 pCodeInstruction *pci=NULL;
450 dest = cvt_extract_destination(&p[3]);
452 fprintf(stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
459 opcode = getpCode(p->pct[0].tok.s,dest);
461 fprintf(stderr, "Bad mnemonic\n");
465 if(pic14Mnemonics[opcode]->bit_inst) {
466 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
467 if(pcosubtype == NULL) {
468 fprintf(stderr, "bad operand?\n");
473 pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
476 pci = PCI(newpCode(opcode,pcosubtype));
479 fprintf(stderr,"couldn't find mnemonic\n");
485 /*-----------------------------------------------------------------*/
486 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
487 /* instruction with 1 wild operand and a */
488 /* destination operand (e.g. w or f) */
491 /* pp[1] - wild var */
493 /* pp[3] - destination */
495 /*-----------------------------------------------------------------*/
496 static void * cvt_altpat_mnem2a(void *pp)
498 parsedPattern *p = pp;
502 pCodeInstruction *pci=NULL;
505 dest = cvt_extract_destination(&p[3]);
507 fprintf(stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
514 opcode = getpCode(p->pct[0].tok.s,dest);
516 fprintf(stderr, "Bad mnemonic\n");
520 if(pic14Mnemonics[opcode]->bit_inst)
521 pcosubtype = newpCodeOp(NULL,PO_BIT);
523 pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
526 pci = PCI(newpCode(opcode,
527 newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
530 fprintf(stderr,"couldn't find mnemonic\n");
536 /*-----------------------------------------------------------------*/
537 /*-----------------------------------------------------------------*/
540 static void parseLineNode(char *ln)
551 tokArr[tokIdx++].tt = PCT_SPACE;
552 while (isspace (*ln))
559 tokArr[tokIdx].tt = PCT_NUMBER;
560 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
568 tokArr[tokIdx++].tt = PCT_PERCENT;
571 tokArr[tokIdx++].tt = PCT_COLON;
574 tokArr[tokIdx].tok.s = Safe_strdup(ln);
575 tokArr[tokIdx++].tt = PCT_COMMENT;
578 tokArr[tokIdx++].tt = PCT_COMMA;
587 while( (isalpha(*ln) || isdigit(*ln)) && i<49)
593 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
594 //fprintf(stderr," string %s",tokArr[tokIdx].tok.s);
596 tokArr[tokIdx++].tt = PCT_STRING;
603 tokArr[tokIdx].tt = 0;
607 /*-----------------------------------------------------------------*/
608 /*-----------------------------------------------------------------*/
612 void dump1Token(pCodeTokens tt)
617 fprintf(stderr, " space ");
620 fprintf(stderr, " pct ");
624 fprintf(stderr, " col ");
628 fprintf(stderr, " com ");
633 fprintf(stderr, " str ");
634 //fprintf(stderr,"%s",tokArr[i].tok.s);
637 fprintf(stderr, " num ");
638 //fprintf(stderr,"%d",tokArr[i].tok.n);
645 /*-----------------------------------------------------------------*/
646 /*-----------------------------------------------------------------*/
648 int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
652 if(!pct || !pat || !*pat)
655 //fprintf(stderr,"comparing against:\n");
657 while(i < max_tokens) {
660 //fprintf(stderr,"matched\n");
664 //dump1Token(*pat); fprintf(stderr,"\n");
678 /*-----------------------------------------------------------------*/
679 /*-----------------------------------------------------------------*/
681 int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
685 if(!pct || !pat || !*pct)
689 while(i < max_tokens) {
692 //fprintf(stderr,"matched\n");
696 //dump1Token(*pat); fprintf(stderr,"\n");
698 if( !pat || !pat->pcp )
701 if (pat->pcp->pt != *pct)
704 //fprintf(stderr," pct=%d\n",*pct);
713 /*-----------------------------------------------------------------*/
714 /*-----------------------------------------------------------------*/
716 int advTokIdx(int *v, int amt)
719 if(*v + amt > tokIdx)
727 /*-----------------------------------------------------------------*/
728 /*-----------------------------------------------------------------*/
730 void dumpTokens(void)
738 for(i=0; i<=tokIdx; i++)
739 dump1Token(tokArr[i].tt);
752 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
753 char * cP1stop = NULL;
754 char * cP2ndop = NULL;
756 //pCodeOp *pcl = NULL; // Storage for a label
757 //pCodeOp *pco1 = NULL; // 1st operand
758 //pCodeOp *pco2 = NULL; // 2nd operand
759 //pCode *pc = NULL; // Mnemonic
770 ParseStates state = PS_START;
776 //fprintf(stderr,"ltokIdx = %d\n",ltokIdx);
778 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
779 && (advTokIdx(<okIdx, 1)) ) // eat space
783 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
785 //fprintf(stderr,"found token pattern match\n");
786 switch(pcpArr[lpcpIdx].pt) {
788 if(state == PS_START){
789 fprintf(stderr," label\n");
790 state = PS_HAVE_LABEL;
792 fprintf(stderr," bad state (%d) for label\n",state);
796 fprintf(stderr," %s is",tokArr[ltokIdx].tok.s);
800 fprintf(stderr," mnem\n");
801 cPmnem = tokArr[ltokIdx].tok.s;
802 state = PS_HAVE_MNEM;
805 fprintf(stderr," 1st operand\n");
806 cP1stop = tokArr[ltokIdx].tok.s;
807 //pco1 = newpCodeOp(NULL,PO_GPR_REGISTER);
808 state = PS_HAVE_1OPERAND;
810 case PS_HAVE_1OPERAND:
811 fprintf(stderr," error expecting comma\n");
814 fprintf(stderr," 2 operands\n");
815 cP2ndop = tokArr[ltokIdx].tok.s;
817 case PS_HAVE_2OPERANDS:
826 fprintf(stderr," wild mnem\n");
827 state = PS_HAVE_MNEM;
830 fprintf(stderr," 1st operand is wild\n");
831 state = PS_HAVE_1OPERAND;
833 case PS_HAVE_1OPERAND:
834 fprintf(stderr," error expecting comma\n");
837 fprintf(stderr," 2nd operand is wild\n");
839 case PS_HAVE_2OPERANDS:
848 fprintf(stderr," ERROR number\n");
851 fprintf(stderr," 1st operand is a number\n");
852 state = PS_HAVE_1OPERAND;
854 case PS_HAVE_1OPERAND:
855 fprintf(stderr," error expecting comma\n");
858 fprintf(stderr," 2nd operand is a number\n");
860 case PS_HAVE_2OPERANDS:
868 if(state == PS_HAVE_1OPERAND){
869 fprintf(stderr," got a comma\n");
870 state = PS_HAVE_COMMA;
872 fprintf(stderr," unexpected comma\n");
876 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
877 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
880 //dump1Token(tokArr[ltokIdx].tt);
882 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
883 fprintf(stderr," reached end \n");
890 } while ((++lpcpIdx < PCPATTERNS) && !matching);
894 parsedPatArr[lparsedPatIdx].pcp = NULL;
895 parsedPatArr[lparsedPatIdx].pct = NULL;
901 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
904 pc = altArr[k].f(&parsedPatArr[j]);
906 pc->print(stderr,pc);
907 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
913 while(j<=lparsedPatIdx && k<ALTPATTERNS);
916 fprintf(stderr,"\nConverting parsed line to pCode:\n\n");
920 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
921 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
922 fprintf(stderr," %d",parsedPatArr[j].pcp->pt);
925 while(j<lparsedPatIdx);
927 fprintf(stderr,"\n");
934 /*-----------------------------------------------------------------*/
935 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
938 /* SDCCpeeph parses the peep rules file and extracts variables, */
939 /* removes white space, and checks the syntax. This function */
940 /* extends that processing to produce pCode objects. You can kind */
941 /* think of this function as an "assembler", though instead of */
942 /* taking raw text to produce machine code, it produces pCode. */
944 /*-----------------------------------------------------------------*/
946 void peepRules2pCode(peepRule *rules)
951 pCodePeepSnippets *pcps;
953 for (pr = rules; pr; pr = pr->next) {
954 fprintf(stderr,"\nRule:\n\n");
956 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
957 curPeep = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
958 //curPeep->target = curPeep->replace = NULL;
959 curPeep->vars = NULL; curPeep->wildpCodes = NULL;
960 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
962 curPeep->target = curBlock = newpCodeChain(NULL, 'W', NULL);
964 for(ln = pr->match; ln; ln = ln->next) {
966 fprintf(stderr,"%s\n",ln->line);
968 parseLineNode(ln->line);
973 fprintf(stderr,"\nReplaced by:\n");
975 curPeep->replace = curBlock = newpCodeChain(NULL, 'W', NULL);
977 for(ln = pr->replace; ln; ln = ln->next)
978 fprintf(stderr,"%s\n",ln->line);
981 fprintf(stderr,"\nCondition: %s\n",pr->cond);
988 void printpCodeString(FILE *of, pCode *pc, int max)
992 while(pc && (i++<max)) {
998 /*-----------------------------------------------------------------*/
999 /* _DLL * DLL_append */
1001 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1002 /* If The list to which we want to append is non-existant then one */
1003 /* is created. Other wise, the end of the list is sought out and */
1004 /* a new DLL object is appended to it. In either case, the void */
1005 /* *data is added to the newly created DLL object. */
1006 /*-----------------------------------------------------------------*/
1008 static void * DLL_append(_DLL *list, _DLL *next)
1013 /* If there's no list, then create one: */
1015 next->next = next->prev = NULL;
1020 /* Search for the end of the list. */
1025 /* Now append the new DLL object */
1036 /*-----------------------------------------------------------------
1038 pCode peephole optimization
1041 The pCode "peep hole" optimization is not too unlike the peep hole
1042 optimization in SDCCpeeph.c. The major difference is that here we
1043 use pCode's whereas there we use ASCII strings. The advantage with
1044 pCode's is that we can ascertain flow information in the instructions
1048 <FIX ME> - elaborate...
1050 -----------------------------------------------------------------*/
1053 /*-----------------------------------------------------------------*/
1055 /*-----------------------------------------------------------------*/
1056 int pCodePeepCompare(pCode *pc, pCodePeep *pcp)
1058 pCode *pcfrom,*pcto;
1061 for( pcto=pcp->target; pcto; pcto=pcto->next) {
1063 pcfrom = findNextInstruction(pcfrom);
1066 (PCI(pcfrom)->op == PCI(pcto)->op ||
1067 PCI(pcto)->op == POC_WILD))
1074 /*-----------------------------------------------------------------*/
1076 /*-----------------------------------------------------------------*/
1077 void pCodePeepSearch(pCodePeep *snippet)
1085 /* compare the chain to the pCode that we've
1086 got so far. If a match is found, then replace
1089 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1090 for(pc = pb->pcHead; pc; pc = pc->next) {
1091 pCodePeepCompare(pc,snippet);
1099 pBlock *pBlockAppend(pBlock *pb1, pBlock *pb2)
1116 void pCodePeepInit(void)
1122 pCodePeepSnippets *pcps;
1124 /* Declare a peep code snippet */
1125 /* <FIXME> do I really need a separate struct just to DLL the snippets? */
1126 /* e.g. I could put the DLL into the pCodePeep structure */
1127 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1128 pcp = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1129 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1132 pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1133 addpCode2pBlock( pb, newpCode(POC_MOVFW, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1137 pcp->replace = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1139 /* Allocate space to store pointers to the wildcard variables */
1141 pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1142 pcp->nwildpCodes = 0;
1143 pcp->wildpCodes = NULL;
1145 pcp->postFalseCond = PCC_Z;
1146 pcp->postTrueCond = PCC_NONE;
1148 fprintf(stderr,"Peep rule\nTarget:\n");
1149 printpCodeString(stderr,pcp->target->pcHead, 10);
1150 fprintf(stderr,"Replaced with:\n");
1151 printpCodeString(stderr,pcp->replace->pcHead, 10);
1153 /* Now for another peep example */
1154 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1155 pcp = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1156 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1172 The %3 and %4 are wild opcodes. Since the opcodes
1173 are stored in a different array than the wild operands,
1174 they can have the same indices and not conflict. So
1175 below, the %3 is really a %0, %4 is a %1.
1182 // Create a new wild operand subtyped as a bit
1183 pcwb = newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1));
1186 pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSC,pcwb));
1188 pcl = newpCodeOpLabel(-1);
1189 pcw = newpCodeOpWild(1, pcp, pcl);
1190 addpCode2pBlock( pb, newpCode(POC_GOTO, pcw));
1191 addpCode2pBlock( pb, newpCodeWild(0,NULL,NULL));
1192 addpCode2pBlock( pb, newpCodeWild(1,NULL,pcw));
1197 pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSS, pcwb));
1198 addpCode2pBlock( pb, newpCodeWild(0,NULL,NULL));
1199 addpCode2pBlock( pb, newpCodeWild(1,NULL,pcw));
1203 /* Allocate space to store pointers to the wildcard variables */
1205 pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1206 pcp->nwildpCodes = 2;
1207 pcp->wildpCodes = Safe_calloc(pcp->nwildpCodes, sizeof(pCode *));
1209 pcp->postFalseCond = PCC_NONE;
1210 pcp->postTrueCond = PCC_NONE;
1224 /* Now for another peep example */
1225 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1226 pcp = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1227 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1232 pcw = newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER));
1234 pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, pcw));
1235 addpCode2pBlock( pb, newpCode(POC_MOVWF, pcw));
1239 pb = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, pcw));
1243 /* Allocate space to store pointers to the wildcard variables */
1245 pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1246 pcp->nwildpCodes = 0;
1247 pcp->wildpCodes = NULL;
1249 pcp->postFalseCond = PCC_NONE;
1250 pcp->postTrueCond = PCC_NONE;
1258 /*-----------------------------------------------------------------*/
1259 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1261 /* return conditions */
1262 /* 1 - The Condition was found for a pCode's input */
1263 /* 0 - No matching condition was found for the whole chain */
1264 /* -1 - The Condition was found for a pCode's output */
1266 /*-----------------------------------------------------------------*/
1267 int pCodeSearchCondition(pCode *pc, unsigned int cond)
1272 /* If we reach a function end (presumably an end since we most
1273 probably began the search in the middle of a function), then
1274 the condition was not found. */
1275 if(pc->type == PC_FUNCTION)
1278 if(pc->type == PC_OPCODE) {
1279 if(PCI(pc)->inCond & cond)
1281 if(PCI(pc)->outCond & cond)
1290 /*-----------------------------------------------------------------*/
1291 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1292 /* see they're the same. */
1293 /*-----------------------------------------------------------------*/
1294 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1296 int index; // index into wild card arrays
1298 if(pcs->type == pcd->type) {
1300 if(pcs->type == PC_OPCODE) {
1302 /* If the opcodes don't match then the line doesn't match */
1303 if(PCI(pcs)->op != PCI(pcd)->op)
1306 fprintf(stderr,"%s comparing\n",__FUNCTION__);
1307 pcs->print(stderr,pcs);
1308 pcd->print(stderr,pcd);
1310 /* Compare the operands */
1311 if(PCI(pcd)->pcop) {
1312 if (PCI(pcd)->pcop->type == PO_WILD) {
1313 index = PCOW(PCI(pcd)->pcop)->id;
1315 fprintf(stderr,"destination is wild\n");
1316 #ifdef DEBUG_PCODEPEEP
1317 if (index > peepBlock->nvars) {
1318 fprintf(stderr,"%s - variables exceeded\n",__FUNCTION__);
1322 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1326 if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1327 n = PCOR(PCI(pcs)->pcop)->r->name;
1329 n = PCI(pcs)->pcop->name;
1331 if(peepBlock->vars[index])
1332 return (strcmp(peepBlock->vars[index],n) == 0);
1334 peepBlock->vars[index] = n; //PCI(pcs)->pcop->name;
1340 /* The pcd has no operand. Lines match if pcs has no operand either*/
1341 return (PCI(pcs)->pcop == NULL);
1346 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1350 index = PCW(pcd)->id;
1352 fprintf(stderr,"%s comparing wild cards\n",__FUNCTION__);
1353 pcs->print(stderr,pcs);
1354 pcd->print(stderr,pcd);
1356 peepBlock->wildpCodes[PCW(pcd)->id] = pcs;
1358 /* Check for a label associated with this wild pCode */
1359 // If the wild card has a label, make sure the source code does too.
1360 if(PCW(pcd)->label) {
1364 labindex = PCOW(PCW(pcd)->label)->id;
1365 if(peepBlock->vars[labindex] == NULL) {
1366 // First time to encounter this label
1367 peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
1368 fprintf(stderr,"first time for a label\n");
1370 if(strcmp(peepBlock->vars[labindex],PCL(pcs->label->pc)->label) != 0) {
1371 fprintf(stderr,"labels don't match\n");
1374 fprintf(stderr,"matched a label\n");
1379 if(PCW(pcd)->operand) {
1380 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1381 if(peepBlock->vars[index]) {
1382 int i = (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
1384 fprintf(stderr," (matched)\n");
1386 fprintf(stderr," (no match: wild card operand mismatch\n");
1387 fprintf(stderr," peepblock= %s, pcodeop= %s\n",
1388 peepBlock->vars[index],
1389 PCI(pcs)->pcop->name);
1393 peepBlock->vars[index] = PCI(pcs)->pcop->name;
1398 pcs = findNextInstruction(pcs->next);
1400 fprintf(stderr," (next to match)\n");
1401 pcs->print(stderr,pcs);
1404 return 1; /* wild card matches */
1410 /*-----------------------------------------------------------------*/
1411 /*-----------------------------------------------------------------*/
1412 void pCodePeepClrVars(pCodePeep *pcp)
1419 for(i=0;i<pcp->nvars; i++)
1420 pcp->vars[i] = NULL;
1424 /*-----------------------------------------------------------------*/
1425 /*-----------------------------------------------------------------*/
1426 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
1432 pc2->next = pc1->next;
1434 pc1->next->prev = pc2;
1441 /*-----------------------------------------------------------------*/
1442 /* pCodeOpCopy - copy a pcode operator */
1443 /*-----------------------------------------------------------------*/
1444 static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
1446 pCodeOp *pcopnew=NULL;
1451 switch(pcop->type) {
1454 pcopnew = Safe_calloc(1,sizeof(pCodeOpBit) );
1455 PCOB(pcopnew)->bit = PCOB(pcop)->bit;
1456 PCOB(pcopnew)->inBitSpace = PCOB(pcop)->inBitSpace;
1461 /* Here we expand the wild card into the appropriate type: */
1462 /* By recursively calling pCodeOpCopy */
1463 if(PCOW(pcop)->matched)
1464 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
1467 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
1468 pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
1469 fprintf(stderr,"copied a wild op named %s\n",pcopnew->name);
1476 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1477 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
1482 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1483 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1486 case PO_GPR_REGISTER:
1488 case PO_SFR_REGISTER:
1497 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1501 pcopnew->type = pcop->type;
1502 pcopnew->name = Safe_strdup(pcop->name);
1508 /*-----------------------------------------------------------------*/
1509 /* pCodeCopy - copy a pcode */
1510 /*-----------------------------------------------------------------*/
1511 static pCode *pCodeCopy(pCode *pc)
1516 pcnew = newpCode(pc->type,pc->pcop);
1519 /*-----------------------------------------------------------------*/
1520 /*-----------------------------------------------------------------*/
1521 void pCodeDeleteChain(pCode *f,pCode *t)
1526 fprintf(stderr,"delete pCode:\n");
1534 /*-----------------------------------------------------------------*/
1535 /*-----------------------------------------------------------------*/
1536 int pCodePeepMatchRule(pCode *pc)
1538 pCodePeep *peepBlock;
1543 peeprules = (_DLL *)peepSnippets;
1546 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1547 if(!peepBlock || !peepBlock->target || !peepBlock->target->pcHead)
1550 pCodePeepClrVars(peepBlock);
1553 pct = peepBlock->target->pcHead;
1555 while(pct && pcin) {
1557 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1560 pcin = findNextInstruction(pcin->next);
1563 fprintf(stderr," matched\n");
1565 fprintf(stderr," end of code\n");
1567 fprintf(stderr," end of rule\n");
1570 if(matched && pcin) {
1572 /* So far we matched the rule up to the point of the conditions .
1573 * In other words, all of the opcodes match. Now we need to see
1574 * if the post conditions are satisfied.
1575 * First we check the 'postFalseCond'. This means that we check
1576 * to see if any of the subsequent pCode's in the pCode chain
1577 * following the point just past where we have matched depend on
1578 * the `postFalseCond' as input then we abort the match
1580 fprintf(stderr," matched rule so far, now checking conditions\n");
1581 if (peepBlock->postFalseCond &&
1582 (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
1586 if(matched && pcin) {
1592 /* We matched a rule! Now we have to go through and remove the
1593 inefficient code with the optimized version */
1595 fprintf(stderr, "Found a pcode peep match:\nRule:\n");
1596 printpCodeString(stderr,peepBlock->target->pcHead,10);
1597 fprintf(stderr,"first thing matched\n");
1598 pc->print(stderr,pc);
1599 fprintf(stderr,"last thing matched\n");
1600 pcin->print(stderr,pcin);
1602 /* Unlink the original code */
1604 pcprev->next = pcin;
1605 pcin->prev = pc->prev;
1606 pCodeDeleteChain(pc,pcin);
1608 /* Generate the replacement code */
1610 pcr = peepBlock->replace->pcHead; // This is the replacement code
1613 /* If the replace pcode is an instruction with an operand, */
1614 /* then duplicate the operand (and expand wild cards in the process). */
1615 if(pcr->type == PC_OPCODE) {
1617 pcop = pCodeOpCopy(PCI(pcr)->pcop);
1618 fprintf(stderr,"inserting pCode\n");
1619 pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
1620 } else if (pcr->type == PC_WILD) {
1621 pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
1626 pc->print(stderr,pc);
1633 peeprules = peeprules->next;
1649 /*******************/
1650 pCode *parseLineNode(char *ln)
1652 char buffer[50], *s;
1653 int state=0; //0 label, 1 mnemonic, 2 operand, 3 operand, 4 comment
1656 // pCodeLabel *pcl = NULL;
1666 /* skip white space */
1667 while (isspace (*ln))
1672 case 0: // look for a label
1673 case 1: // look for mnemonic
1684 var = strtol(ln, &ln, 10);
1686 // valid wild card label
1687 fprintf(stderr, " wildcard label: %d\n",var);
1690 fprintf(stderr, " wild opcode: %d\n",var), state++;
1694 // Extract the label/mnemonic from the line
1697 while(*ln && !(isspace(*ln) || *ln == ':'))
1702 fprintf(stderr," regular label: %s\n",buffer), ln++;
1704 fprintf(stderr," regular mnem: %s\n",buffer), state++;