1 /*-------------------------------------------------------------------------
3 pcodepeep.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
5 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 -------------------------------------------------------------------------*/
25 #include "common.h" // Include everything in the SDCC src directory
29 #include "pcodeflow.h"
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
35 #define STRCASECMP strcasecmp
38 pCodeOp *pic16_popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
40 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype);
41 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
42 pCode * pic16_findNextInstruction(pCode *pc);
43 int pic16_getpCode(char *mnem,int dest);
44 int pic16_getpCodePeepCommand(char *cmd);
45 void pic16_pBlockMergeLabels(pBlock *pb);
46 char *pCode2str(char *str, int size, pCode *pc);
47 char *pic16_get_op( pCodeOp *pcop,char *buf,int buf_size);
49 extern pCodeInstruction *pic16Mnemonics[];
52 #define IS_PCCOMMENT(x) ( x && (x->type==PC_COMMENT))
54 /****************************************************************/
56 * rootRules - defined in SDCCpeep.c
57 * This is a pointer to the (parsed) peephole rules that are
58 * defined in peep.def.
61 //extern peepRule *rootRules;
66 /****************************************************************/
67 /****************************************************************/
75 typedef struct pCodePeepSnippets
82 /****************************************************************/
86 /****************************************************************/
88 static pCodePeepSnippets *peepSnippets=NULL;
90 /****************************************************************/
94 /****************************************************************/
96 //static pCodePeep *curPeep=NULL;
98 /****************************************************************/
102 /****************************************************************/
104 //static pBlock *curBlock=NULL;
107 /****************************************************************/
109 /* max wild cards in a peep rule */
111 /****************************************************************/
113 //static int sMaxWildVar = 0;
114 //static int sMaxWildMnem = 0;
117 typedef struct pCodeToken
119 int tt; // token type;
128 pCodeToken tokArr[50];
129 static unsigned tokIdx=0;
147 typedef struct parsedPattern {
148 struct pcPattern *pcp;
152 #define MAX_PARSEDPATARR 50
153 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
154 //static unsigned int parsedPatIdx=0;
167 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
168 static char pcpat_number[] = {PCT_NUMBER, 0};
169 static char pcpat_string[] = {PCT_STRING, 0};
170 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
171 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
172 static char pcpat_comma[] = {PCT_COMMA, 0};
173 static char pcpat_comment[] = {PCT_COMMENT, 0};
176 typedef struct pcPattern {
177 char pt; // Pattern type
178 char *tokens; // list of tokens that describe the pattern
179 void * (*f) (void *,pCodeWildBlock *);
182 static pcPattern pcpArr[] = {
183 {PCP_LABEL, pcpat_label, NULL},
184 {PCP_WILDSTR, pcpat_wildString, NULL},
185 {PCP_STR, pcpat_string, NULL},
186 {PCP_WILDVAR, pcpat_wildVar, NULL},
187 {PCP_COMMA, pcpat_comma, NULL},
188 {PCP_COMMENT, pcpat_comment, NULL},
189 {PCP_NUMBER, pcpat_number, NULL}
192 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
194 // Assembly Line Token
208 static char alt_comment[] = { PCP_COMMENT, 0};
209 static char alt_label[] = { PCP_LABEL, 0};
210 static char alt_mnem0[] = { PCP_STR, 0};
211 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
212 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
213 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
214 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
215 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
216 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
217 static char alt_mnem3[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_NUMBER, 0};
219 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
220 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
221 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb);
222 static void * cvt_altpat_mnem0a(void *pp,pCodeWildBlock *pcwb);
223 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb);
224 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb);
225 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb);
226 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb);
227 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb);
228 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb);
230 static pcPattern altArr[] = {
231 {ALT_LABEL, alt_label, cvt_altpat_label},
232 {ALT_COMMENT, alt_comment,cvt_altpat_comment},
233 {ALT_MNEM3, alt_mnem3, cvt_altpat_mnem3},
234 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
235 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
236 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
237 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
238 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
239 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
240 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
244 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
246 // forward declarations
247 static void * DLL_append(_DLL *list, _DLL *next);
249 /*-----------------------------------------------------------------*/
250 /* cvt_extract_destination - helper function extracts the register */
251 /* destination from a parsedPattern. */
253 /*-----------------------------------------------------------------*/
254 static int cvt_extract_destination(parsedPattern *pp)
257 if(pp->pct[0].tt == PCT_STRING) {
259 // just check first letter for now
261 if(toupper(*pp->pct[0].tok.s) == 'F')
264 } else if (pp->pct[0].tt == PCT_NUMBER) {
274 /*-----------------------------------------------------------------*/
275 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
276 /* if *reg is the "status" register and *bit is one of the */
277 /* status bits, then this function will create a new pCode op */
278 /* containing the status register. */
279 /*-----------------------------------------------------------------*/
281 static pCodeOp *cvt_extract_status(char *reg, char *bit)
285 if(STRCASECMP(reg, pic16_pc_status.pcop.name))
292 if(toupper(*bit) == 'C')
293 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_C_BIT));
294 if(toupper(*bit) == 'Z')
295 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_Z_BIT));
299 if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
300 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_DC_BIT));
306 /*-----------------------------------------------------------------*/
307 /* cvt_altpat_label - convert assembly line type to a pCode label */
308 /* INPUT: pointer to the parsedPattern */
312 /* label pattern => '%' number ':' */
313 /* at this point, we wish to extract only the 'number' */
315 /*-----------------------------------------------------------------*/
316 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb)
318 parsedPattern *p = pp;
320 DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
321 return pic16_newpCodeLabel(NULL,-p->pct[1].tok.n);
325 /*-----------------------------------------------------------------*/
326 /* cvt_altpat_comment - convert assembly line type to a comment */
327 /* INPUT: pointer to the parsedPattern */
329 /* pp[0] - comment */
332 /*-----------------------------------------------------------------*/
333 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb)
335 parsedPattern *p = pp;
337 DFPRINTF((stderr,"altpat_comment = %s\n",p->pct[0].tok.s));
338 return pic16_newpCodeCharP(p->pct[0].tok.s);
342 /*-----------------------------------------------------------------*/
343 /* cvt_altpat_mem0 - convert assembly line type to a wild pCode */
348 /*-----------------------------------------------------------------*/
349 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb)
351 parsedPattern *p = pp;
354 pCodeInstruction *pci=NULL;
356 DFPRINTF((stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s));
358 opcode = pic16_getpCode(p->pct[0].tok.s,0);
361 /* look for special command strings like _NOTBITSKIP_ */
363 //fprintf(stderr, "Bad mnemonic\n");
365 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
367 // fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
371 pci = PCI(pic16_newpCode(opcode, NULL));
374 fprintf(stderr,"couldn't find mnemonic\n");
380 /*-----------------------------------------------------------------*/
381 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
384 /* pp[0] - wild var */
386 /*-----------------------------------------------------------------*/
387 static void * cvt_altpat_mnem0a(void *pp, pCodeWildBlock *pcwb)
389 parsedPattern *p = pp;
391 DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n));
393 /* Save the index of the maximum wildcard mnemonic */
395 //if(p[0].pct[1].tok.n > sMaxWildVar)
396 // sMaxWildMnem = p[0].pct[1].tok.n;
398 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
399 pcwb->nwildpCodes = p[0].pct[1].tok.n;
401 return pic16_newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
405 /*-----------------------------------------------------------------*/
406 /* cvt_altpat_mem1 - convert assembly line type to a pCode */
407 /* instruction with 1 operand. */
410 /* pp[1] - Operand */
412 /*-----------------------------------------------------------------*/
413 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb)
416 parsedPattern *p = pp;
419 pCodeInstruction *pci=NULL;
422 DFPRINTF((stderr,"altpat_mnem1 %s var %s\n", p->pct[0].tok.s,p[1].pct[0].tok.s));
424 opcode = pic16_getpCode(p->pct[0].tok.s,0);
426 //fprintf(stderr, "Bad mnemonic\n");
427 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
429 //fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
434 if(pic16Mnemonics[opcode]->isBitInst)
435 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
437 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
440 pci = PCI(pic16_newpCode(opcode, pcosubtype));
443 fprintf(stderr,"couldn't find mnemonic\n");
449 /*-----------------------------------------------------------------*/
450 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
451 /* instruction with 1 wild operand. */
454 /* pp[1] - wild var */
456 /*-----------------------------------------------------------------*/
457 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb)
459 parsedPattern *p = pp;
462 pCodeInstruction *pci=NULL;
465 DFPRINTF((stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n));
467 opcode = pic16_getpCode(p->pct[0].tok.s,0);
469 int cmd_id = pic16_getpCodePeepCommand(p->pct[0].tok.s);
473 fprintf(stderr, "Bad mnemonic\n");
477 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
478 pcwb->nwildpCodes = p[0].pct[1].tok.n;
480 pc = pic16_newpCodeWild(p[1].pct[1].tok.n,NULL,NULL);
484 PCW(pc)->mustNotBeBitSkipInst = 1;
487 PCW(pc)->mustBeBitSkipInst = 1;
490 PCW(pc)->invertBitSkipInst = 1;
495 if(pic16Mnemonics[opcode]->isBitInst)
496 pcosubtype = pic16_newpCodeOpBit(NULL,-1,0);
498 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
501 pci = PCI(pic16_newpCode(opcode,
502 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
504 /* Save the index of the maximum wildcard variable */
505 //if(p[1].pct[1].tok.n > sMaxWildVar)
506 // sMaxWildVar = p[1].pct[1].tok.n;
508 if(p[1].pct[1].tok.n > pcwb->nvars)
509 pcwb->nvars = p[1].pct[1].tok.n;
512 fprintf(stderr,"couldn't find mnemonic\n");
518 /*-----------------------------------------------------------------*/
519 /*-----------------------------------------------------------------*/
520 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb)
522 parsedPattern *p = pp;
525 pCodeInstruction *pci=NULL;
527 DFPRINTF((stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n));
529 opcode = pic16_getpCode(p->pct[0].tok.s,0);
531 fprintf(stderr, "Bad mnemonic\n");
535 pci = PCI(pic16_newpCode(opcode, pic16_newpCodeOpLit(p[1].pct[0].tok.n) ));
538 fprintf(stderr,"couldn't find mnemonic\n");
544 /*-----------------------------------------------------------------*/
545 /* cvt_altpat_mnem2 */
550 /* pp[3] - destination */
551 /*-----------------------------------------------------------------*/
552 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
554 parsedPattern *p = pp;
558 pCodeInstruction *pci=NULL;
561 dest = cvt_extract_destination(&p[3]);
563 DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
570 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
572 fprintf(stderr, "Bad mnemonic\n");
576 if(pic16Mnemonics[opcode]->isBitInst) {
577 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
578 if(pcosubtype == NULL) {
579 fprintf(stderr, "bad operand?\n");
584 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
587 pci = PCI(pic16_newpCode(opcode,pcosubtype));
590 fprintf(stderr,"couldn't find mnemonic\n");
596 /*-----------------------------------------------------------------*/
597 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
598 /* instruction with 1 wild operand and a */
599 /* destination operand (e.g. w or f) */
602 /* pp[1] - wild var */
604 /* pp[3] - destination */
606 /*-----------------------------------------------------------------*/
607 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
609 parsedPattern *p = pp;
613 pCodeInstruction *pci=NULL;
617 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
621 dest = cvt_extract_destination(&p[3]);
623 DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
630 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
632 fprintf(stderr, "Bad mnemonic\n");
636 if(pic16Mnemonics[opcode]->isBitInst)
637 pcosubtype = pic16_newpCodeOp(NULL,PO_BIT);
639 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
642 pci = PCI(pic16_newpCode(opcode,
643 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
645 /* Save the index of the maximum wildcard variable */
646 //if(p[1].pct[1].tok.n > sMaxWildVar)
647 // sMaxWildVar = p[1].pct[1].tok.n;
649 if(p[1].pct[1].tok.n > pcwb->nvars)
650 pcwb->nvars = p[1].pct[1].tok.n;
653 fprintf(stderr,"couldn't find mnemonic\n");
660 /*-----------------------------------------------------------------*/
661 /* cvt_altpat_mem3 - convert assembly line type to a pCode */
662 /* This rule is for bsf/bcf type instructions */
666 /* pp[1] - register */
670 /*-----------------------------------------------------------------*/
671 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
673 parsedPattern *p = pp;
675 int dest; // or could be bit position in the register
677 pCodeInstruction *pci=NULL;
678 pCodeOp *pcosubtype=NULL;
680 dest = cvt_extract_destination(&p[3]);
682 DFPRINTF((stderr,"altpat_mnem3 %s var %s bit (%d)\n",
688 opcode = pic16_getpCode(p->pct[0].tok.s,0);
690 fprintf(stderr, "Bad mnemonic\n");
695 if(pic16Mnemonics[opcode]->isBitInst) {
696 //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
698 //if(pcosubtype == NULL) {
699 pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0);
702 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
704 if(pcosubtype == NULL) {
705 fprintf(stderr, "Bad operand\n");
709 pci = PCI(pic16_newpCode(opcode, pcosubtype));
712 fprintf(stderr,"couldn't find mnemonic\n");
718 /*-----------------------------------------------------------------*/
719 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
720 /* by SDCCpeeph.c into a string of tokens. */
723 /* The tokenizer is of the classic type. When an item is encounterd*/
724 /* it is converted into a token. The token is a structure that */
725 /* encodes the item's type and it's value (when appropriate). */
727 /* Accepted token types: */
728 /* SPACE NUMBER STRING % : , ; */
732 /*-----------------------------------------------------------------*/
735 static void tokenizeLineNode(char *ln)
738 tokIdx = 0; // Starting off at the beginning
739 tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
748 // add a SPACE token and eat the extra spaces.
749 tokArr[tokIdx++].tt = PCT_SPACE;
750 while (isspace (*ln))
757 tokArr[tokIdx].tt = PCT_NUMBER;
758 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
766 tokArr[tokIdx++].tt = PCT_PERCENT;
769 tokArr[tokIdx++].tt = PCT_LESSTHAN;
772 tokArr[tokIdx++].tt = PCT_GREATERTHAN;
775 tokArr[tokIdx++].tt = PCT_COLON;
778 tokArr[tokIdx].tok.s = Safe_strdup(ln);
779 tokArr[tokIdx++].tt = PCT_COMMENT;
780 tokArr[tokIdx].tt = PCT_NULL;
783 tokArr[tokIdx++].tt = PCT_COMMA;
788 if(isalpha(*ln) || (*ln == '_') ) {
792 while( (isalpha(*ln) || isdigit(*ln) || (*ln == '_')) && i<49)
798 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
799 tokArr[tokIdx++].tt = PCT_STRING;
802 fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
803 fprintf(stderr, "Line: %s\n",lnstart);
804 fprintf(stderr, "Token: '%c'\n",*ln);
809 /* Advance to next character in input string .
810 * Note, if none of the tests passed above, then
811 * we effectively ignore the `bad' character.
812 * Since the line has already been parsed by SDCCpeeph,
813 * chance are that there are no invalid characters... */
819 tokArr[tokIdx].tt = 0;
823 /*-----------------------------------------------------------------*/
824 /*-----------------------------------------------------------------*/
828 static void dump1Token(pCodeTokens tt)
833 fprintf(stderr, " space ");
836 fprintf(stderr, " pct %%");
839 fprintf(stderr, " pct <");
841 case PCT_GREATERTHAN:
842 fprintf(stderr, " pct >");
845 fprintf(stderr, " col :");
848 fprintf(stderr, " comma , ");
851 fprintf(stderr, " comment ");
852 //fprintf(stderr,"%s",tokArr[i].tok.s);
855 fprintf(stderr, " str ");
856 //fprintf(stderr,"%s",tokArr[i].tok.s);
859 fprintf(stderr, " num ");
860 //fprintf(stderr,"%d",tokArr[i].tok.n);
863 fprintf(stderr, " null ");
870 /*-----------------------------------------------------------------*/
871 /*-----------------------------------------------------------------*/
873 static int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
877 if(!pct || !pat || !*pat)
880 //DFPRINTF((stderr,"comparing against:\n"));
882 while(i < max_tokens) {
885 //DFPRINTF((stderr,"matched\n"));
889 // dump1Token(*pat); fputc('\n', stderr); DFPRINTF((stderr,"\n"));
903 /*-----------------------------------------------------------------*/
904 /*-----------------------------------------------------------------*/
906 static int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
910 if(!pct || !pat || !*pct)
914 while(i < max_tokens) {
917 //DFPRINTF((stderr,"matched\n"));
921 //dump1Token(*pat); DFPRINTF((stderr,"\n"));
923 if( !pat || !pat->pcp )
926 if (pat->pcp->pt != *pct)
929 //DFPRINTF((stderr," pct=%d\n",*pct));
938 /*-----------------------------------------------------------------*/
939 /*-----------------------------------------------------------------*/
941 static int advTokIdx(int *v, int amt)
944 if((unsigned) (*v + amt) > tokIdx)
952 /*-----------------------------------------------------------------*/
953 /* parseTokens - convert the tokens corresponding to a single line */
954 /* of a peep hole assembly into a pCode object. */
959 /* This is a simple parser that looks for strings of the type */
960 /* allowed in the peep hole definition file. Essentially the format*/
961 /* is the same as a line of assembly: */
963 /* label: mnemonic op1, op2, op3 ; comment */
965 /* Some of these items aren't present. It's the job of the parser */
966 /* to determine which are and convert those into the appropriate */
968 /*-----------------------------------------------------------------*/
970 static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
981 for(i=0; i<=tokIdx; i++)
982 dump1Token(tokArr[i].tt);
995 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
996 char * cP1stop = NULL;
997 char * cP2ndop = NULL;
999 //pCodeOp *pcl = NULL; // Storage for a label
1000 //pCodeOp *pco1 = NULL; // 1st operand
1001 //pCodeOp *pco2 = NULL; // 2nd operand
1002 //pCode *pc = NULL; // Mnemonic
1013 ParseStates state = PS_START;
1020 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
1021 && (advTokIdx(<okIdx, 1)) ) // eat space
1025 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
1028 switch(pcpArr[lpcpIdx].pt) {
1030 if(state == PS_START){
1031 DFPRINTF((stderr," label\n"));
1032 state = PS_HAVE_LABEL;
1034 DFPRINTF((stderr," bad state (%d) for label\n",state));
1038 DFPRINTF((stderr," %s is",tokArr[ltokIdx].tok.s));
1042 DFPRINTF((stderr," mnem\n"));
1043 cPmnem = tokArr[ltokIdx].tok.s;
1044 state = PS_HAVE_MNEM;
1047 DFPRINTF((stderr," 1st operand\n"));
1048 cP1stop = tokArr[ltokIdx].tok.s;
1049 //pco1 = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
1050 state = PS_HAVE_1OPERAND;
1052 case PS_HAVE_1OPERAND:
1053 DFPRINTF((stderr," error expecting comma\n"));
1056 DFPRINTF((stderr," 2 operands\n"));
1057 cP2ndop = tokArr[ltokIdx].tok.s;
1059 case PS_HAVE_2OPERANDS:
1068 DFPRINTF((stderr," wild mnem\n"));
1069 state = PS_HAVE_MNEM;
1072 DFPRINTF((stderr," 1st operand is wild\n"));
1073 state = PS_HAVE_1OPERAND;
1075 case PS_HAVE_1OPERAND:
1076 DFPRINTF((stderr," error expecting comma\n"));
1079 DFPRINTF((stderr," 2nd operand is wild\n"));
1081 case PS_HAVE_2OPERANDS:
1090 fprintf(stderr," ERROR number\n");
1093 DFPRINTF((stderr," 1st operand is a number\n"));
1094 state = PS_HAVE_1OPERAND;
1096 case PS_HAVE_1OPERAND:
1097 fprintf(stderr," error expecting comma\n");
1100 DFPRINTF((stderr," 2nd operand is a number\n"));
1102 case PS_HAVE_2OPERANDS:
1110 if(state == PS_HAVE_1OPERAND){
1111 DFPRINTF((stderr," got a comma\n"));
1112 state = PS_HAVE_COMMA;
1114 fprintf(stderr," unexpected comma\n");
1120 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1121 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1124 //dump1Token(tokArr[ltokIdx].tt);
1126 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1127 DFPRINTF((stderr," reached end \n"));
1134 } while ((++lpcpIdx < PCPATTERNS) && !matching);
1138 parsedPatArr[lparsedPatIdx].pcp = NULL;
1139 parsedPatArr[lparsedPatIdx].pct = NULL;
1145 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1148 pc = altArr[k].f(&parsedPatArr[j],pcwb);
1149 //if(pc && pc->print)
1150 // pc->print(stderr,pc);
1151 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1153 //if(curBlock && pc)
1154 //pic16_addpCode2pBlock(curBlock, pc);
1158 return 0; // Only accept one line for now.
1160 pic16_addpCode2pBlock(pcwb->pb, pc);
1168 while(j<=lparsedPatIdx && k<ALTPATTERNS);
1171 DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1175 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1176 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1177 DFPRINTF((stderr," %d",parsedPatArr[j].pcp->pt));
1180 while(j<lparsedPatIdx);
1182 DFPRINTF((stderr,"\n"));
1189 /*-----------------------------------------------------------------*/
1191 /*-----------------------------------------------------------------*/
1192 static void peepRuleBlock2pCodeBlock( lineNode *ln, pCodeWildBlock *pcwb)
1198 for( ; ln; ln = ln->next) {
1200 //DFPRINTF((stderr,"%s\n",ln->line));
1201 // fprintf(stderr, "peep rule : %s\n", ln->line);
1203 tokenizeLineNode(ln->line);
1205 if(parseTokens(pcwb,NULL)) {
1207 fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
1208 fprintf(stderr,"Tokens:\n");
1210 dump1Token(tokArr[i].tt);
1217 /*-----------------------------------------------------------------*/
1219 /*-----------------------------------------------------------------*/
1220 pCode *pic16_AssembleLine(char *line)
1224 if(!line || !*line) {
1225 fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
1229 tokenizeLineNode(line);
1231 if(parseTokens(NULL,&pc))
1232 fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
1238 /*-----------------------------------------------------------------*/
1239 /* peepRuleCondition */
1240 /*-----------------------------------------------------------------*/
1241 static void peepRuleCondition(char *cond, pCodePeep *pcp)
1246 //DFPRINTF((stderr,"\nCondition: %s\n",cond));
1247 /* brute force compares for now */
1249 if(STRCASECMP(cond, "NZ") == 0) {
1250 //DFPRINTF((stderr,"found NZ\n"));
1251 pcp->postFalseCond = PCC_Z;
1258 static void initpCodeWildBlock(pCodeWildBlock *pcwb)
1261 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1267 pcwb->wildpCodes = NULL;
1268 pcwb->wildpCodeOps = NULL;
1271 pcwb->nwildpCodes = 0;
1276 static void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1283 pcwb->nops = pcwb->nvars;
1285 pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1286 pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1288 pcwb->nwildpCodes+=2;
1289 pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1293 static void initpCodePeep(pCodePeep *pcp)
1296 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1301 initpCodeWildBlock(&pcp->target);
1302 pcp->target.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1304 initpCodeWildBlock(&pcp->replace);
1305 pcp->replace.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1309 /*-----------------------------------------------------------------*/
1310 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1313 /* SDCCpeeph parses the peep rules file and extracts variables, */
1314 /* removes white space, and checks the syntax. This function */
1315 /* extends that processing to produce pCode objects. You can kind */
1316 /* think of this function as an "assembler", though instead of */
1317 /* taking raw text to produce machine code, it produces pCode. */
1319 /*-----------------------------------------------------------------*/
1320 extern void pic16initpCodePeepCommands(void);
1322 void pic16_peepRules2pCode(peepRule *rules)
1326 pCodePeep *currentRule;
1327 pCodePeepSnippets *pcps;
1329 pic16initpCodePeepCommands();
1331 /* The rules are in a linked-list. Each rule has two portions */
1332 /* There's the `target' and there's the `replace'. The target */
1333 /* is compared against the SDCC generated code and if it */
1334 /* matches, it gets replaced by the `replace' block of code. */
1336 /* Here we loop through each rule and convert the target's and*/
1337 /* replace's into pCode target and replace blocks */
1339 for (pr = rules; pr; pr = pr->next) {
1341 //DFPRINTF((stderr,"\nRule:\n\n"));
1343 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1344 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1346 currentRule = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1347 initpCodePeep(currentRule);
1349 /* Convert the target block */
1350 peepRuleBlock2pCodeBlock(pr->match, ¤tRule->target);
1352 //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1353 // pic16_printpBlock(stderr, currentRule->target.pb);
1355 //DFPRINTF((stderr,"target with labels merged:\n"));
1356 //pic16_pBlockMergeLabels(curBlock);
1357 pic16_pBlockMergeLabels(currentRule->target.pb);
1358 //pic16_printpBlock(stderr, currentRule->replace.pb);
1360 //#ifdef PCODE_DEBUG
1361 // pic16_printpBlock(stderr, curBlock);
1363 //DFPRINTF((stderr,"\nReplaced by:\n"));
1366 /* Convert the replace block */
1367 peepRuleBlock2pCodeBlock(pr->replace, ¤tRule->replace);
1369 //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1370 //pic16_printpBlock(stderr, curBlock);
1372 //DFPRINTF((stderr,"replace with labels merged:\n"));
1374 pic16_pBlockMergeLabels(currentRule->replace.pb);
1375 //pic16_printpBlock(stderr, currentRule->replace.pb);
1377 peepRuleCondition(pr->cond,currentRule);
1379 /* The rule has been converted to pCode. Now allocate
1380 * space for the wildcards */
1382 postinit_pCodeWildBlock(¤tRule->target);
1383 postinit_pCodeWildBlock(¤tRule->replace);
1385 //return; // debug ... don't want to go through all the rules yet
1389 pCodePeep *peepBlock;
1392 peeprules = (_DLL *)peepSnippets;
1393 //fprintf(stderr,"target rules\n");
1395 //fprintf(stderr," rule:\n");
1396 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1397 //pic16_printpBlock(stderr, peepBlock->target.pb);
1398 peeprules = peeprules->next;
1400 //fprintf(stderr," ... done\n");
1405 static void printpCodeString(FILE *of, pCode *pc, int max)
1409 while(pc && (i++<max)) {
1415 /*-----------------------------------------------------------------*/
1416 /* _DLL * DLL_append */
1418 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1419 /* If The list to which we want to append is non-existant then one */
1420 /* is created. Other wise, the end of the list is sought out and */
1421 /* a new DLL object is appended to it. In either case, the void */
1422 /* *data is added to the newly created DLL object. */
1423 /*-----------------------------------------------------------------*/
1425 static void * DLL_append(_DLL *list, _DLL *next)
1430 /* If there's no list, then create one: */
1432 next->next = next->prev = NULL;
1437 /* Search for the end of the list. */
1442 /* Now append the new DLL object */
1453 /*-----------------------------------------------------------------
1455 pCode peephole optimization
1458 The pCode "peep hole" optimization is not too unlike the peep hole
1459 optimization in SDCCpeeph.c. The major difference is that here we
1460 use pCode's whereas there we use ASCII strings. The advantage with
1461 pCode's is that we can ascertain flow information in the instructions
1465 <FIX ME> - elaborate...
1467 -----------------------------------------------------------------*/
1471 /*-----------------------------------------------------------------*/
1472 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1474 /* return conditions */
1475 /* 1 - The Condition was found for a pCode's input */
1476 /* 0 - No matching condition was found for the whole chain */
1477 /* -1 - The Condition was found for a pCode's output */
1479 /*-----------------------------------------------------------------*/
1480 int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond)
1482 //fprintf(stderr,"Checking conditions %d\n",cond);
1485 /* If we reach a function end (presumably an end since we most
1486 probably began the search in the middle of a function), then
1487 the condition was not found. */
1488 if(pc->type == PC_FUNCTION)
1491 if(pc->type == PC_OPCODE) {
1492 //fprintf(stderr," checking conditions of: ");
1493 //pc->print(stderr,pc);
1494 //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
1495 if(PCI(pc)->inCond & cond)
1497 if(PCI(pc)->outCond & cond)
1507 /*-----------------------------------------------------------------
1508 * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1510 * Compare two pCodeOp's and return 1 if they're the same
1511 *-----------------------------------------------------------------*/
1512 static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1516 if(!pcops || !pcopd)
1520 fprintf(stderr," Comparing operands %s",
1521 pic16_get_op( pcops,NULL,0));
1523 fprintf(stderr," to %s\n",
1524 pic16_get_op( pcopd,NULL,0));
1527 if(pcops->type != pcopd->type) {
1528 //fprintf(stderr," - fail - diff types\n");
1529 return 0; // different types
1532 if(pcops->type == PO_LITERAL) {
1534 if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
1541 pic16_get_op(pcops,b,50);
1543 n2 = pic16_get_op(pcopd,NULL,0);
1545 if( !n2 || strcmp(b,n2)) {
1546 //fprintf(stderr," - fail - diff names: %s, len=%d, %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1547 return 0; // different names
1550 switch(pcops->type) {
1552 if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1553 //fprintf(stderr, " - fail different instances\n");
1561 //fprintf(stderr," - pass\n");
1566 static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1570 /* Check for a label associated with this wild pCode */
1571 // If the wild card has a label, make sure the source code does too.
1572 if(PCI(pcd)->label) {
1573 pCode *pcl = PCI(pcd)->label->pc;
1576 int li = -PCL(pcl)->key;
1578 if(peepBlock->target.vars[li] == NULL) {
1579 if(PCI(pcs)->label) {
1580 DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1583 // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1584 DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1585 if(PCI(pcs)->label) {
1586 DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1592 if(!PCI(pcs)->label)
1595 labindex = -PCL(pcl)->key;
1596 if(peepBlock->target.vars[labindex] == NULL) {
1597 // First time to encounter this label
1598 peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1599 DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1602 if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1603 DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1606 DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1609 //DFPRINTF((stderr,"destination doesn't have a label\n"));
1614 //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1622 /*-----------------------------------------------------------------*/
1623 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1624 /* see they're the same. */
1626 /* In this context, "source" refers to the coded generated by gen.c*/
1627 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1628 /* ination has no wild cards, then MatchLine will compare the two */
1629 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1630 /* has wildcards, then those get expanded. When a wild card is */
1631 /* encountered for the first time it autmatically is considered a */
1632 /* match and the object that matches it is referenced in the */
1633 /* variables or opcodes array (depending on the type of match). */
1637 /* *peepBlock - A pointer to the peepBlock that contains the */
1638 /* entire rule to which the destination pcode belongs*/
1639 /* *pcs - a pointer to the source pcode */
1640 /* *pcd - a pointer to the destination pcode */
1643 /* 1 - pcodes match */
1644 /* 0 - pcodes don't match */
1647 /*-----------------------------------------------------------------*/
1649 static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1651 int index; // index into wild card arrays
1653 /* one-for-one match. Here the source and destination opcodes
1654 * are not wild. However, there may be a label or a wild operand */
1657 if(PCI(pcs)->label) {
1658 DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1662 if(pcs->type == pcd->type) {
1664 if(pcs->type == PC_OPCODE) {
1666 /* If the opcodes don't match then the line doesn't match */
1667 if(PCI(pcs)->op != PCI(pcd)->op)
1671 DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1672 pcs->print(stderr,pcs);
1673 pcd->print(stderr,pcd);
1676 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1679 /* Compare the operands */
1680 if(PCI(pcd)->pcop) {
1681 if (PCI(pcd)->pcop->type == PO_WILD) {
1682 index = PCOW(PCI(pcd)->pcop)->id;
1683 //DFPRINTF((stderr,"destination is wild\n"));
1684 #ifdef DEBUG_PCODEPEEP
1685 if (index > peepBlock->nops) {
1686 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1691 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1692 if(!peepBlock->target.wildpCodeOps[index]) {
1693 peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1695 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1699 pcs->print(stderr,pcs);
1700 pcd->print(stderr,pcd);
1702 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1703 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1707 return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1713 switch(PCI(pcs)->pcop->type) {
1717 n = PCOR(PCI(pcs)->pcop)->r->name;
1721 n = PCI(pcs)->pcop->name;
1724 if(peepBlock->target.vars[index])
1725 return (strcmp(peepBlock->target.vars[index],n) == 0);
1727 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1728 peepBlock->target.vars[index] = n;
1733 } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
1734 return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
1737 /* FIXME - need an else to check the case when the destination
1738 * isn't a wild card */
1740 /* The pcd has no operand. Lines match if pcs has no operand either*/
1741 return (PCI(pcs)->pcop == NULL);
1745 /* Compare a wild instruction to a regular one. */
1747 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1749 index = PCW(pcd)->id;
1751 DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
1752 pcs->print(stderr,pcs);
1753 pcd->print(stderr,pcd);
1755 peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
1757 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
1758 DFPRINTF((stderr," Failing because labels don't match\n"));
1762 if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1763 // doesn't match because the wild pcode must be a bit skip
1764 DFPRINTF((stderr," Failing match because bit skip is req\n"));
1765 //pcd->print(stderr,pcd);
1766 //pcs->print(stderr,pcs);
1770 if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1771 // doesn't match because the wild pcode must *not* be a bit skip
1772 DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
1773 //pcd->print(stderr,pcd);
1774 //pcs->print(stderr,pcs);
1778 if(PCW(pcd)->operand) {
1779 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1780 if(peepBlock->target.vars[index]) {
1781 int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
1785 DFPRINTF((stderr," (matched)\n"));
1787 DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
1788 DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n",
1789 peepBlock->target.vars[index],
1790 PCI(pcs)->pcop->name));
1795 DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
1796 peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
1801 pcs = pic16_findNextInstruction(pcs->next);
1803 //DFPRINTF((stderr," (next to match)\n"));
1804 //pcs->print(stderr,pcs);
1805 } else if(pcd->next) {
1806 /* oops, we ran out of code, but there's more to the rule */
1810 return 1; /* wild card matches */
1816 /*-----------------------------------------------------------------*/
1817 /*-----------------------------------------------------------------*/
1818 static void pCodePeepClrVars(pCodePeep *pcp)
1825 DFPRINTF((stderr," Clearing peep rule vars\n"));
1826 DFPRINTF((stderr," %d %d %d %d %d %d\n",
1827 pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
1828 pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
1830 for(i=0;i<pcp->target.nvars; i++)
1831 pcp->target.vars[i] = NULL;
1832 for(i=0;i<pcp->target.nops; i++)
1833 pcp->target.wildpCodeOps[i] = NULL;
1834 for(i=0;i<pcp->target.nwildpCodes; i++)
1835 pcp->target.wildpCodes[i] = NULL;
1837 for(i=0;i<pcp->replace.nvars; i++)
1838 pcp->replace.vars[i] = NULL;
1839 for(i=0;i<pcp->replace.nops; i++)
1840 pcp->replace.wildpCodeOps[i] = NULL;
1841 for(i=0;i<pcp->replace.nwildpCodes; i++)
1842 pcp->replace.wildpCodes[i] = NULL;
1848 /*-----------------------------------------------------------------*/
1849 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
1850 /* into the pCode chain containing pc1 */
1851 /*-----------------------------------------------------------------*/
1852 void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2)
1858 pc2->next = pc1->next;
1860 pc1->next->prev = pc2;
1868 /*-----------------------------------------------------------------*/
1869 /* pic16_pCodeOpCopy - copy a pcode operator */
1870 /*-----------------------------------------------------------------*/
1871 pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
1873 pCodeOp *pcopnew=NULL;
1878 switch(pcop->type) {
1881 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
1882 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1883 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
1884 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
1889 /* Here we expand the wild card into the appropriate type: */
1890 /* By recursively calling pCodeOpCopy */
1891 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
1892 if(PCOW(pcop)->matched)
1893 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->matched);
1896 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->subtype);
1897 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
1898 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
1905 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
1906 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1907 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
1911 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
1912 PCOI(pcopnew)->index = PCOI(pcop)->index;
1913 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
1914 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
1918 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
1919 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1920 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1923 #if 0 // mdubuc - To add
1930 pcopnew = pic16_newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
1931 PCOR(pcopnew)->r = PCOR(pcop)->r;
1932 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1933 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
1937 case PO_GPR_REGISTER:
1941 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
1942 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1943 PCOR(pcopnew)->r = PCOR(pcop)->r;
1944 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1945 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
1946 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
1950 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
1951 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1952 PCOR(pcopnew)->r = PCOR(pcop)->r;
1953 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1954 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
1957 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
1959 DFPRINTF((stderr,"pCodeOpCopy PO_BSR\n"));
1960 case PO_SFR_REGISTER:
1969 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
1970 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1974 pcopnew->type = pcop->type;
1976 pcopnew->name = Safe_strdup(pcop->name);
1978 pcopnew->name = NULL;
1984 /*-----------------------------------------------------------------*/
1985 /* pCodeCopy - copy a pcode */
1986 /*-----------------------------------------------------------------*/
1987 static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
1989 pCodeInstruction *new_pci;
1992 new_pci = PCI(pic16_newpCode(pci->inverted_op,pci->pcop));
1994 new_pci = PCI(pic16_newpCode(pci->op,pci->pcop));
1996 new_pci->pc.pb = pci->pc.pb;
1997 new_pci->from = pci->from;
1998 new_pci->to = pci->to;
1999 new_pci->label = pci->label;
2000 new_pci->pcflow = pci->pcflow;
2002 return PCODE(new_pci);
2005 /*-----------------------------------------------------------------*/
2006 /*-----------------------------------------------------------------*/
2007 static void pCodeDeleteChain(pCode *f,pCode *t)
2013 DFPRINTF((stderr,"delete pCode:\n"));
2015 //f->print(stderr,f);
2016 //f->delete(f); this dumps core...
2023 /*-----------------------------------------------------------------*/
2024 /*-----------------------------------------------------------------*/
2025 int pic16_pCodePeepMatchRule(pCode *pc)
2027 pCodePeep *peepBlock;
2029 pCodeCSource *pc_cline=NULL;
2033 peeprules = (_DLL *)peepSnippets;
2036 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
2038 if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
2039 fprintf(stderr, "skipping rule because target pb is NULL\n");
2043 pCodePeepClrVars(peepBlock);
2046 if(IS_PCCOMMENT(pcin))
2047 pc = pcin = pic16_findNextInstruction(pcin->next);
2049 pcin = pc = pic16_findNextInstruction(pc);
2051 pct = peepBlock->target.pb->pcHead;
2054 pCode *pcr = peepBlock->replace.pb->pcHead;
2055 if(pcr) pct->print(stderr,pcr);
2059 while(pct && pcin) {
2061 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
2064 pcin = pic16_findNextInstruction(pcin->next);
2067 //DFPRINTF((stderr," matched\n"));
2070 DFPRINTF((stderr," partial match... no more code\n"));
2071 // fprintf(stderr," partial match... no more code\n");
2075 DFPRINTF((stderr," end of rule\n"));
2079 if(matched && pcin) {
2081 /* So far we matched the rule up to the point of the conditions .
2082 * In other words, all of the opcodes match. Now we need to see
2083 * if the post conditions are satisfied.
2084 * First we check the 'postFalseCond'. This means that we check
2085 * to see if any of the subsequent pCode's in the pCode chain
2086 * following the point just past where we have matched depend on
2087 * the `postFalseCond' as input then we abort the match
2089 DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
2090 //pcin->print(stderr,pcin);
2092 if (pcin && peepBlock->postFalseCond &&
2093 (pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
2096 //fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
2099 //if(!matched) fprintf(stderr,"failed on conditions\n");
2108 /* We matched a rule! Now we have to go through and remove the
2109 inefficient code with the optimized version */
2111 DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
2112 printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
2113 DFPRINTF((stderr,"first thing matched\n"));
2114 pc->print(stderr,pc);
2116 DFPRINTF((stderr,"last thing matched\n"));
2117 pcin->print(stderr,pcin);
2122 /* Unlink the original code */
2124 pcprev->next = pcin;
2126 pcin->prev = pc->prev;
2132 /* Converted the deleted pCodes into comments */
2135 pCodeCSource *pc_cline2=NULL;
2140 while(pc && pc!=pcin) {
2142 if(pc->type == PC_OPCODE && PCI(pc)->cline) {
2144 pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2145 pc_cline2 = PCCS(pc_cline2->pc.next);
2147 pc_cline = pc_cline2 = PCI(pc)->cline;
2148 pc_cline->pc.seq = pc->seq;
2152 pCode2str(&buf[2], 254, pc);
2153 pic16_pCodeInsertAfter(pcprev, pic16_newpCodeCharP(buf));
2154 pcprev = pcprev->next;
2159 pc_cline2->pc.next = NULL;
2164 pCodeDeleteChain(pc,pcin);
2166 /* Generate the replacement code */
2168 pcr = peepBlock->replace.pb->pcHead; // This is the replacement code
2172 /* If the replace pcode is an instruction with an operand, */
2173 /* then duplicate the operand (and expand wild cards in the process). */
2174 if(pcr->type == PC_OPCODE) {
2175 if(PCI(pcr)->pcop) {
2176 /* The replacing instruction has an operand.
2178 if(PCI(pcr)->pcop->type == PO_WILD) {
2179 int index = PCOW(PCI(pcr)->pcop)->id;
2180 //DFPRINTF((stderr,"copying wildopcode\n"));
2181 if(peepBlock->target.wildpCodeOps[index])
2182 pcop = pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2184 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2186 pcop = pic16_pCodeOpCopy(PCI(pcr)->pcop);
2188 //DFPRINTF((stderr,"inserting pCode\n"));
2189 pic16_pCodeInsertAfter(pc, pic16_newpCode(PCI(pcr)->op,pcop));
2190 } else if (pcr->type == PC_WILD) {
2191 if(PCW(pcr)->invertBitSkipInst)
2192 DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2193 pic16_pCodeInsertAfter(pc,
2194 pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2195 PCW(pcr)->invertBitSkipInst));
2196 } else if (pcr->type == PC_COMMENT) {
2197 pic16_pCodeInsertAfter(pc, pic16_newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2203 DFPRINTF((stderr," NEW Code:"));
2204 if(pc) pc->print(stderr,pc);
2209 /* We have just replaced the inefficient code with the rule.
2210 * Now, we need to re-add the C-source symbols if there are any */
2214 pc = pic16_findNextInstruction(pc->next);
2215 PCI(pc)->cline = pc_cline;
2216 pc_cline = PCCS(pc_cline->pc.next);
2223 peeprules = peeprules->next;
2225 DFPRINTF((stderr," no rule matched\n"));