1 /*-------------------------------------------------------------------------
3 pcodepeep.c - post code generation
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
26 #include "common.h" // Include everything in the SDCC src directory
30 #include "pcodeflow.h"
33 #if defined(__BORLANDC__) || defined(_MSC_VER)
34 #define STRCASECMP stricmp
36 #define STRCASECMP strcasecmp
39 pCodeOp *pic16_popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
41 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype);
42 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
43 pCode * pic16_findNextInstruction(pCode *pc);
44 int pic16_getpCode(char *mnem,int dest);
45 int pic16_getpCodePeepCommand(char *cmd);
46 void pic16_pBlockMergeLabels(pBlock *pb);
47 char *pCode2str(char *str, int size, pCode *pc);
48 char *pic16_get_op( pCodeOp *pcop,char *buf,int buf_size);
50 extern pCodeInstruction *pic16Mnemonics[];
53 #define IS_PCCOMMENT(x) ( x && (x->type==PC_COMMENT))
55 /****************************************************************/
57 * rootRules - defined in SDCCpeep.c
58 * This is a pointer to the (parsed) peephole rules that are
59 * defined in peep.def.
62 //extern peepRule *rootRules;
67 /****************************************************************/
68 /****************************************************************/
76 typedef struct pCodePeepSnippets
83 /****************************************************************/
87 /****************************************************************/
89 static pCodePeepSnippets *peepSnippets=NULL;
91 /****************************************************************/
95 /****************************************************************/
97 //static pCodePeep *curPeep=NULL;
99 /****************************************************************/
103 /****************************************************************/
105 //static pBlock *curBlock=NULL;
108 /****************************************************************/
110 /* max wild cards in a peep rule */
112 /****************************************************************/
114 //static int sMaxWildVar = 0;
115 //static int sMaxWildMnem = 0;
118 typedef struct pCodeToken
120 int tt; // token type;
129 pCodeToken tokArr[50];
130 static unsigned tokIdx=0;
148 typedef struct parsedPattern {
149 struct pcPattern *pcp;
153 #define MAX_PARSEDPATARR 50
154 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
155 //static unsigned int parsedPatIdx=0;
168 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
169 static char pcpat_number[] = {PCT_NUMBER, 0};
170 static char pcpat_string[] = {PCT_STRING, 0};
171 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
172 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
173 static char pcpat_comma[] = {PCT_COMMA, 0};
174 static char pcpat_comment[] = {PCT_COMMENT, 0};
177 typedef struct pcPattern {
178 char pt; // Pattern type
179 char *tokens; // list of tokens that describe the pattern
180 void * (*f) (void *,pCodeWildBlock *);
183 static pcPattern pcpArr[] = {
184 {PCP_LABEL, pcpat_label, NULL},
185 {PCP_WILDSTR, pcpat_wildString, NULL},
186 {PCP_STR, pcpat_string, NULL},
187 {PCP_WILDVAR, pcpat_wildVar, NULL},
188 {PCP_COMMA, pcpat_comma, NULL},
189 {PCP_COMMENT, pcpat_comment, NULL},
190 {PCP_NUMBER, pcpat_number, NULL}
193 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
195 // Assembly Line Token
209 static char alt_comment[] = { PCP_COMMENT, 0};
210 static char alt_label[] = { PCP_LABEL, 0};
211 static char alt_mnem0[] = { PCP_STR, 0};
212 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
213 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
214 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
215 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
216 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
217 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
218 static char alt_mnem3[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_NUMBER, 0};
220 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
221 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
222 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb);
223 static void * cvt_altpat_mnem0a(void *pp,pCodeWildBlock *pcwb);
224 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb);
225 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb);
226 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb);
227 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb);
228 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb);
229 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb);
231 static pcPattern altArr[] = {
232 {ALT_LABEL, alt_label, cvt_altpat_label},
233 {ALT_COMMENT, alt_comment,cvt_altpat_comment},
234 {ALT_MNEM3, alt_mnem3, cvt_altpat_mnem3},
235 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
236 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
237 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
238 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
239 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
240 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
241 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
245 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
247 // forward declarations
248 static void * DLL_append(_DLL *list, _DLL *next);
250 /*-----------------------------------------------------------------*/
251 /* cvt_extract_destination - helper function extracts the register */
252 /* destination from a parsedPattern. */
254 /*-----------------------------------------------------------------*/
255 static int cvt_extract_destination(parsedPattern *pp)
258 if(pp->pct[0].tt == PCT_STRING) {
260 // just check first letter for now
262 if(toupper(*pp->pct[0].tok.s) == 'F')
265 } else if (pp->pct[0].tt == PCT_NUMBER) {
275 /*-----------------------------------------------------------------*/
276 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
277 /* if *reg is the "status" register and *bit is one of the */
278 /* status bits, then this function will create a new pCode op */
279 /* containing the status register. */
280 /*-----------------------------------------------------------------*/
282 static pCodeOp *cvt_extract_status(char *reg, char *bit)
286 if(STRCASECMP(reg, pic16_pc_status.pcop.name))
293 if(toupper(*bit) == 'C')
294 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_C_BIT));
295 if(toupper(*bit) == 'Z')
296 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_Z_BIT));
300 if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
301 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_DC_BIT));
307 /*-----------------------------------------------------------------*/
308 /* cvt_altpat_label - convert assembly line type to a pCode label */
309 /* INPUT: pointer to the parsedPattern */
313 /* label pattern => '%' number ':' */
314 /* at this point, we wish to extract only the 'number' */
316 /*-----------------------------------------------------------------*/
317 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb)
319 parsedPattern *p = pp;
321 DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
322 return pic16_newpCodeLabel(NULL,-p->pct[1].tok.n);
326 /*-----------------------------------------------------------------*/
327 /* cvt_altpat_comment - convert assembly line type to a comment */
328 /* INPUT: pointer to the parsedPattern */
330 /* pp[0] - comment */
333 /*-----------------------------------------------------------------*/
334 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb)
336 parsedPattern *p = pp;
338 DFPRINTF((stderr,"altpat_comment = %s\n",p->pct[0].tok.s));
339 return pic16_newpCodeCharP(p->pct[0].tok.s);
343 /*-----------------------------------------------------------------*/
344 /* cvt_altpat_mem0 - convert assembly line type to a wild pCode */
349 /*-----------------------------------------------------------------*/
350 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb)
352 parsedPattern *p = pp;
355 pCodeInstruction *pci=NULL;
357 DFPRINTF((stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s));
359 opcode = pic16_getpCode(p->pct[0].tok.s,0);
362 /* look for special command strings like _NOTBITSKIP_ */
364 //fprintf(stderr, "Bad mnemonic\n");
366 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
368 // fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
372 pci = PCI(pic16_newpCode(opcode, NULL));
375 fprintf(stderr,"couldn't find mnemonic\n");
381 /*-----------------------------------------------------------------*/
382 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
385 /* pp[0] - wild var */
387 /*-----------------------------------------------------------------*/
388 static void * cvt_altpat_mnem0a(void *pp, pCodeWildBlock *pcwb)
390 parsedPattern *p = pp;
392 DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n));
394 /* Save the index of the maximum wildcard mnemonic */
396 //if(p[0].pct[1].tok.n > sMaxWildVar)
397 // sMaxWildMnem = p[0].pct[1].tok.n;
399 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
400 pcwb->nwildpCodes = p[0].pct[1].tok.n;
402 return pic16_newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
406 /*-----------------------------------------------------------------*/
407 /* cvt_altpat_mem1 - convert assembly line type to a pCode */
408 /* instruction with 1 operand. */
411 /* pp[1] - Operand */
413 /*-----------------------------------------------------------------*/
414 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb)
417 parsedPattern *p = pp;
420 pCodeInstruction *pci=NULL;
423 DFPRINTF((stderr,"altpat_mnem1 %s var %s\n", p->pct[0].tok.s,p[1].pct[0].tok.s));
425 opcode = pic16_getpCode(p->pct[0].tok.s,0);
427 //fprintf(stderr, "Bad mnemonic\n");
428 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
430 //fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
435 if(pic16Mnemonics[opcode]->isBitInst)
436 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
438 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
441 pci = PCI(pic16_newpCode(opcode, pcosubtype));
444 fprintf(stderr,"couldn't find mnemonic\n");
450 /*-----------------------------------------------------------------*/
451 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
452 /* instruction with 1 wild operand. */
455 /* pp[1] - wild var */
457 /*-----------------------------------------------------------------*/
458 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb)
460 parsedPattern *p = pp;
463 pCodeInstruction *pci=NULL;
466 DFPRINTF((stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n));
468 opcode = pic16_getpCode(p->pct[0].tok.s,0);
470 int cmd_id = pic16_getpCodePeepCommand(p->pct[0].tok.s);
474 fprintf(stderr, "Bad mnemonic\n");
478 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
479 pcwb->nwildpCodes = p[0].pct[1].tok.n;
481 pc = pic16_newpCodeWild(p[1].pct[1].tok.n,NULL,NULL);
485 PCW(pc)->mustNotBeBitSkipInst = 1;
488 PCW(pc)->mustBeBitSkipInst = 1;
491 PCW(pc)->invertBitSkipInst = 1;
496 if(pic16Mnemonics[opcode]->isBitInst)
497 pcosubtype = pic16_newpCodeOpBit(NULL,-1,0);
499 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
502 pci = PCI(pic16_newpCode(opcode,
503 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
505 /* Save the index of the maximum wildcard variable */
506 //if(p[1].pct[1].tok.n > sMaxWildVar)
507 // sMaxWildVar = p[1].pct[1].tok.n;
509 if(p[1].pct[1].tok.n > pcwb->nvars)
510 pcwb->nvars = p[1].pct[1].tok.n;
513 fprintf(stderr,"couldn't find mnemonic\n");
519 /*-----------------------------------------------------------------*/
520 /*-----------------------------------------------------------------*/
521 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb)
523 parsedPattern *p = pp;
526 pCodeInstruction *pci=NULL;
528 DFPRINTF((stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n));
530 opcode = pic16_getpCode(p->pct[0].tok.s,0);
532 fprintf(stderr, "Bad mnemonic\n");
536 pci = PCI(pic16_newpCode(opcode, pic16_newpCodeOpLit(p[1].pct[0].tok.n) ));
539 fprintf(stderr,"couldn't find mnemonic\n");
545 /*-----------------------------------------------------------------*/
546 /* cvt_altpat_mnem2 */
551 /* pp[3] - destination */
552 /*-----------------------------------------------------------------*/
553 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
555 parsedPattern *p = pp;
559 pCodeInstruction *pci=NULL;
562 dest = cvt_extract_destination(&p[3]);
564 DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
571 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
573 fprintf(stderr, "Bad mnemonic\n");
577 if(pic16Mnemonics[opcode]->isBitInst) {
578 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
579 if(pcosubtype == NULL) {
580 fprintf(stderr, "bad operand?\n");
585 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
588 pci = PCI(pic16_newpCode(opcode,pcosubtype));
591 fprintf(stderr,"couldn't find mnemonic\n");
597 /*-----------------------------------------------------------------*/
598 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
599 /* instruction with 1 wild operand and a */
600 /* destination operand (e.g. w or f) */
603 /* pp[1] - wild var */
605 /* pp[3] - destination */
607 /*-----------------------------------------------------------------*/
608 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
610 parsedPattern *p = pp;
614 pCodeInstruction *pci=NULL;
618 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
622 dest = cvt_extract_destination(&p[3]);
624 DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
631 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
633 fprintf(stderr, "Bad mnemonic\n");
637 if(pic16Mnemonics[opcode]->isBitInst)
638 pcosubtype = pic16_newpCodeOp(NULL,PO_BIT);
640 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
643 pci = PCI(pic16_newpCode(opcode,
644 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
646 /* Save the index of the maximum wildcard variable */
647 //if(p[1].pct[1].tok.n > sMaxWildVar)
648 // sMaxWildVar = p[1].pct[1].tok.n;
650 if(p[1].pct[1].tok.n > pcwb->nvars)
651 pcwb->nvars = p[1].pct[1].tok.n;
654 fprintf(stderr,"couldn't find mnemonic\n");
661 /*-----------------------------------------------------------------*/
662 /* cvt_altpat_mem3 - convert assembly line type to a pCode */
663 /* This rule is for bsf/bcf type instructions */
667 /* pp[1] - register */
671 /*-----------------------------------------------------------------*/
672 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
674 parsedPattern *p = pp;
676 int dest; // or could be bit position in the register
678 pCodeInstruction *pci=NULL;
679 pCodeOp *pcosubtype=NULL;
681 dest = cvt_extract_destination(&p[3]);
683 DFPRINTF((stderr,"altpat_mnem3 %s var %s bit (%d)\n",
689 opcode = pic16_getpCode(p->pct[0].tok.s,0);
691 fprintf(stderr, "Bad mnemonic\n");
696 if(pic16Mnemonics[opcode]->isBitInst) {
697 //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
699 //if(pcosubtype == NULL) {
700 pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0);
703 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
705 if(pcosubtype == NULL) {
706 fprintf(stderr, "Bad operand\n");
710 pci = PCI(pic16_newpCode(opcode, pcosubtype));
713 fprintf(stderr,"couldn't find mnemonic\n");
719 /*-----------------------------------------------------------------*/
720 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
721 /* by SDCCpeeph.c into a string of tokens. */
724 /* The tokenizer is of the classic type. When an item is encounterd*/
725 /* it is converted into a token. The token is a structure that */
726 /* encodes the item's type and it's value (when appropriate). */
728 /* Accepted token types: */
729 /* SPACE NUMBER STRING % : , ; */
733 /*-----------------------------------------------------------------*/
736 static void tokenizeLineNode(char *ln)
739 tokIdx = 0; // Starting off at the beginning
740 tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
749 // add a SPACE token and eat the extra spaces.
750 tokArr[tokIdx++].tt = PCT_SPACE;
751 while (isspace (*ln))
758 tokArr[tokIdx].tt = PCT_NUMBER;
759 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
767 tokArr[tokIdx++].tt = PCT_PERCENT;
770 tokArr[tokIdx++].tt = PCT_LESSTHAN;
773 tokArr[tokIdx++].tt = PCT_GREATERTHAN;
776 tokArr[tokIdx++].tt = PCT_COLON;
779 tokArr[tokIdx].tok.s = Safe_strdup(ln);
780 tokArr[tokIdx++].tt = PCT_COMMENT;
781 tokArr[tokIdx].tt = PCT_NULL;
784 tokArr[tokIdx++].tt = PCT_COMMA;
789 if(isalpha(*ln) || (*ln == '_') ) {
793 while( (isalpha(*ln) || isdigit(*ln) || (*ln == '_')) && i<49)
799 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
800 tokArr[tokIdx++].tt = PCT_STRING;
803 fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
804 fprintf(stderr, "Line: %s\n",lnstart);
805 fprintf(stderr, "Token: '%c'\n",*ln);
810 /* Advance to next character in input string .
811 * Note, if none of the tests passed above, then
812 * we effectively ignore the `bad' character.
813 * Since the line has already been parsed by SDCCpeeph,
814 * chance are that there are no invalid characters... */
820 tokArr[tokIdx].tt = 0;
824 /*-----------------------------------------------------------------*/
825 /*-----------------------------------------------------------------*/
829 static void dump1Token(pCodeTokens tt)
834 fprintf(stderr, " space ");
837 fprintf(stderr, " pct %%");
840 fprintf(stderr, " pct <");
842 case PCT_GREATERTHAN:
843 fprintf(stderr, " pct >");
846 fprintf(stderr, " col :");
849 fprintf(stderr, " comma , ");
852 fprintf(stderr, " comment ");
853 //fprintf(stderr,"%s",tokArr[i].tok.s);
856 fprintf(stderr, " str ");
857 //fprintf(stderr,"%s",tokArr[i].tok.s);
860 fprintf(stderr, " num ");
861 //fprintf(stderr,"%d",tokArr[i].tok.n);
864 fprintf(stderr, " null ");
871 /*-----------------------------------------------------------------*/
872 /*-----------------------------------------------------------------*/
874 static int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
878 if(!pct || !pat || !*pat)
881 //DFPRINTF((stderr,"comparing against:\n"));
883 while(i < max_tokens) {
886 //DFPRINTF((stderr,"matched\n"));
890 // dump1Token(*pat); fputc('\n', stderr); DFPRINTF((stderr,"\n"));
904 /*-----------------------------------------------------------------*/
905 /*-----------------------------------------------------------------*/
907 static int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
911 if(!pct || !pat || !*pct)
915 while(i < max_tokens) {
918 //DFPRINTF((stderr,"matched\n"));
922 //dump1Token(*pat); DFPRINTF((stderr,"\n"));
924 if( !pat || !pat->pcp )
927 if (pat->pcp->pt != *pct)
930 //DFPRINTF((stderr," pct=%d\n",*pct));
939 /*-----------------------------------------------------------------*/
940 /*-----------------------------------------------------------------*/
942 static int advTokIdx(int *v, int amt)
945 if((unsigned) (*v + amt) > tokIdx)
953 /*-----------------------------------------------------------------*/
954 /* parseTokens - convert the tokens corresponding to a single line */
955 /* of a peep hole assembly into a pCode object. */
960 /* This is a simple parser that looks for strings of the type */
961 /* allowed in the peep hole definition file. Essentially the format*/
962 /* is the same as a line of assembly: */
964 /* label: mnemonic op1, op2, op3 ; comment */
966 /* Some of these items aren't present. It's the job of the parser */
967 /* to determine which are and convert those into the appropriate */
969 /*-----------------------------------------------------------------*/
971 static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
982 for(i=0; i<=tokIdx; i++)
983 dump1Token(tokArr[i].tt);
996 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
997 char * cP1stop = NULL;
998 char * cP2ndop = NULL;
1000 //pCodeOp *pcl = NULL; // Storage for a label
1001 //pCodeOp *pco1 = NULL; // 1st operand
1002 //pCodeOp *pco2 = NULL; // 2nd operand
1003 //pCode *pc = NULL; // Mnemonic
1014 ParseStates state = PS_START;
1021 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
1022 && (advTokIdx(<okIdx, 1)) ) // eat space
1026 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
1029 switch(pcpArr[lpcpIdx].pt) {
1031 if(state == PS_START){
1032 DFPRINTF((stderr," label\n"));
1033 state = PS_HAVE_LABEL;
1035 DFPRINTF((stderr," bad state (%d) for label\n",state));
1039 DFPRINTF((stderr," %s is",tokArr[ltokIdx].tok.s));
1043 DFPRINTF((stderr," mnem\n"));
1044 cPmnem = tokArr[ltokIdx].tok.s;
1045 state = PS_HAVE_MNEM;
1048 DFPRINTF((stderr," 1st operand\n"));
1049 cP1stop = tokArr[ltokIdx].tok.s;
1050 //pco1 = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
1051 state = PS_HAVE_1OPERAND;
1053 case PS_HAVE_1OPERAND:
1054 DFPRINTF((stderr," error expecting comma\n"));
1057 DFPRINTF((stderr," 2 operands\n"));
1058 cP2ndop = tokArr[ltokIdx].tok.s;
1060 case PS_HAVE_2OPERANDS:
1069 DFPRINTF((stderr," wild mnem\n"));
1070 state = PS_HAVE_MNEM;
1073 DFPRINTF((stderr," 1st operand is wild\n"));
1074 state = PS_HAVE_1OPERAND;
1076 case PS_HAVE_1OPERAND:
1077 DFPRINTF((stderr," error expecting comma\n"));
1080 DFPRINTF((stderr," 2nd operand is wild\n"));
1082 case PS_HAVE_2OPERANDS:
1091 fprintf(stderr," ERROR number\n");
1094 DFPRINTF((stderr," 1st operand is a number\n"));
1095 state = PS_HAVE_1OPERAND;
1097 case PS_HAVE_1OPERAND:
1098 fprintf(stderr," error expecting comma\n");
1101 DFPRINTF((stderr," 2nd operand is a number\n"));
1103 case PS_HAVE_2OPERANDS:
1111 if(state == PS_HAVE_1OPERAND){
1112 DFPRINTF((stderr," got a comma\n"));
1113 state = PS_HAVE_COMMA;
1115 fprintf(stderr," unexpected comma\n");
1121 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1122 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1125 //dump1Token(tokArr[ltokIdx].tt);
1127 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1128 DFPRINTF((stderr," reached end \n"));
1135 } while ((++lpcpIdx < PCPATTERNS) && !matching);
1139 parsedPatArr[lparsedPatIdx].pcp = NULL;
1140 parsedPatArr[lparsedPatIdx].pct = NULL;
1146 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1149 pc = altArr[k].f(&parsedPatArr[j],pcwb);
1150 //if(pc && pc->print)
1151 // pc->print(stderr,pc);
1152 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1154 //if(curBlock && pc)
1155 //pic16_addpCode2pBlock(curBlock, pc);
1159 return 0; // Only accept one line for now.
1161 pic16_addpCode2pBlock(pcwb->pb, pc);
1169 while(j<=lparsedPatIdx && k<ALTPATTERNS);
1172 DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1176 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1177 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1178 DFPRINTF((stderr," %d",parsedPatArr[j].pcp->pt));
1181 while(j<lparsedPatIdx);
1183 DFPRINTF((stderr,"\n"));
1190 /*-----------------------------------------------------------------*/
1192 /*-----------------------------------------------------------------*/
1193 static void peepRuleBlock2pCodeBlock( lineNode *ln, pCodeWildBlock *pcwb)
1199 for( ; ln; ln = ln->next) {
1201 //DFPRINTF((stderr,"%s\n",ln->line));
1202 // fprintf(stderr, "peep rule : %s\n", ln->line);
1204 tokenizeLineNode(ln->line);
1206 if(parseTokens(pcwb,NULL)) {
1208 fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
1209 fprintf(stderr,"Tokens:\n");
1211 dump1Token(tokArr[i].tt);
1218 /*-----------------------------------------------------------------*/
1220 /*-----------------------------------------------------------------*/
1221 pCode *pic16_AssembleLine(char *line)
1225 if(!line || !*line) {
1226 fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
1230 tokenizeLineNode(line);
1232 if(parseTokens(NULL,&pc))
1233 fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
1239 /*-----------------------------------------------------------------*/
1240 /* peepRuleCondition */
1241 /*-----------------------------------------------------------------*/
1242 static void peepRuleCondition(char *cond, pCodePeep *pcp)
1247 //DFPRINTF((stderr,"\nCondition: %s\n",cond));
1248 /* brute force compares for now */
1250 if(STRCASECMP(cond, "NZ") == 0) {
1251 //DFPRINTF((stderr,"found NZ\n"));
1252 pcp->postFalseCond = PCC_Z;
1259 static void initpCodeWildBlock(pCodeWildBlock *pcwb)
1262 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1268 pcwb->wildpCodes = NULL;
1269 pcwb->wildpCodeOps = NULL;
1272 pcwb->nwildpCodes = 0;
1277 static void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1284 pcwb->nops = pcwb->nvars;
1286 pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1287 pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1289 pcwb->nwildpCodes+=2;
1290 pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1294 static void initpCodePeep(pCodePeep *pcp)
1297 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1302 initpCodeWildBlock(&pcp->target);
1303 pcp->target.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1305 initpCodeWildBlock(&pcp->replace);
1306 pcp->replace.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1310 /*-----------------------------------------------------------------*/
1311 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1314 /* SDCCpeeph parses the peep rules file and extracts variables, */
1315 /* removes white space, and checks the syntax. This function */
1316 /* extends that processing to produce pCode objects. You can kind */
1317 /* think of this function as an "assembler", though instead of */
1318 /* taking raw text to produce machine code, it produces pCode. */
1320 /*-----------------------------------------------------------------*/
1321 extern void pic16initpCodePeepCommands(void);
1323 void pic16_peepRules2pCode(peepRule *rules)
1327 pCodePeep *currentRule;
1328 pCodePeepSnippets *pcps;
1330 pic16initpCodePeepCommands();
1332 /* The rules are in a linked-list. Each rule has two portions */
1333 /* There's the `target' and there's the `replace'. The target */
1334 /* is compared against the SDCC generated code and if it */
1335 /* matches, it gets replaced by the `replace' block of code. */
1337 /* Here we loop through each rule and convert the target's and*/
1338 /* replace's into pCode target and replace blocks */
1340 for (pr = rules; pr; pr = pr->next) {
1342 //DFPRINTF((stderr,"\nRule:\n\n"));
1344 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1345 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1347 currentRule = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1348 initpCodePeep(currentRule);
1350 /* Convert the target block */
1351 peepRuleBlock2pCodeBlock(pr->match, ¤tRule->target);
1353 //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1354 // pic16_printpBlock(stderr, currentRule->target.pb);
1356 //DFPRINTF((stderr,"target with labels merged:\n"));
1357 //pic16_pBlockMergeLabels(curBlock);
1358 pic16_pBlockMergeLabels(currentRule->target.pb);
1359 //pic16_printpBlock(stderr, currentRule->replace.pb);
1361 //#ifdef PCODE_DEBUG
1362 // pic16_printpBlock(stderr, curBlock);
1364 //DFPRINTF((stderr,"\nReplaced by:\n"));
1367 /* Convert the replace block */
1368 peepRuleBlock2pCodeBlock(pr->replace, ¤tRule->replace);
1370 //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1371 //pic16_printpBlock(stderr, curBlock);
1373 //DFPRINTF((stderr,"replace with labels merged:\n"));
1375 pic16_pBlockMergeLabels(currentRule->replace.pb);
1376 //pic16_printpBlock(stderr, currentRule->replace.pb);
1378 peepRuleCondition(pr->cond,currentRule);
1380 /* The rule has been converted to pCode. Now allocate
1381 * space for the wildcards */
1383 postinit_pCodeWildBlock(¤tRule->target);
1384 postinit_pCodeWildBlock(¤tRule->replace);
1386 //return; // debug ... don't want to go through all the rules yet
1390 pCodePeep *peepBlock;
1393 peeprules = (_DLL *)peepSnippets;
1394 //fprintf(stderr,"target rules\n");
1396 //fprintf(stderr," rule:\n");
1397 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1398 //pic16_printpBlock(stderr, peepBlock->target.pb);
1399 peeprules = peeprules->next;
1401 //fprintf(stderr," ... done\n");
1406 static void printpCodeString(FILE *of, pCode *pc, int max)
1410 while(pc && (i++<max)) {
1416 /*-----------------------------------------------------------------*/
1417 /* _DLL * DLL_append */
1419 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1420 /* If The list to which we want to append is non-existant then one */
1421 /* is created. Other wise, the end of the list is sought out and */
1422 /* a new DLL object is appended to it. In either case, the void */
1423 /* *data is added to the newly created DLL object. */
1424 /*-----------------------------------------------------------------*/
1426 static void * DLL_append(_DLL *list, _DLL *next)
1431 /* If there's no list, then create one: */
1433 next->next = next->prev = NULL;
1438 /* Search for the end of the list. */
1443 /* Now append the new DLL object */
1454 /*-----------------------------------------------------------------
1456 pCode peephole optimization
1459 The pCode "peep hole" optimization is not too unlike the peep hole
1460 optimization in SDCCpeeph.c. The major difference is that here we
1461 use pCode's whereas there we use ASCII strings. The advantage with
1462 pCode's is that we can ascertain flow information in the instructions
1466 <FIX ME> - elaborate...
1468 -----------------------------------------------------------------*/
1472 /*-----------------------------------------------------------------*/
1473 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1475 /* return conditions */
1476 /* 1 - The Condition was found for a pCode's input */
1477 /* 0 - No matching condition was found for the whole chain */
1478 /* -1 - The Condition was found for a pCode's output */
1480 /*-----------------------------------------------------------------*/
1481 int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond)
1483 //fprintf(stderr,"Checking conditions %d\n",cond);
1486 /* If we reach a function end (presumably an end since we most
1487 probably began the search in the middle of a function), then
1488 the condition was not found. */
1489 if(pc->type == PC_FUNCTION)
1492 if(pc->type == PC_OPCODE) {
1493 //fprintf(stderr," checking conditions of: ");
1494 //pc->print(stderr,pc);
1495 //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
1496 if(PCI(pc)->inCond & cond)
1498 if(PCI(pc)->outCond & cond)
1508 /*-----------------------------------------------------------------
1509 * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1511 * Compare two pCodeOp's and return 1 if they're the same
1512 *-----------------------------------------------------------------*/
1513 static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1517 if(!pcops || !pcopd)
1521 fprintf(stderr," Comparing operands %s",
1522 pic16_get_op( pcops,NULL,0));
1524 fprintf(stderr," to %s\n",
1525 pic16_get_op( pcopd,NULL,0));
1528 if(pcops->type != pcopd->type) {
1529 //fprintf(stderr," - fail - diff types\n");
1530 return 0; // different types
1533 if(pcops->type == PO_LITERAL) {
1535 if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
1542 pic16_get_op(pcops,b,50);
1544 n2 = pic16_get_op(pcopd,NULL,0);
1546 if( !n2 || strcmp(b,n2)) {
1547 //fprintf(stderr," - fail - diff names: %s, len=%d, %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1548 return 0; // different names
1551 switch(pcops->type) {
1553 if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1554 //fprintf(stderr, " - fail different instances\n");
1562 //fprintf(stderr," - pass\n");
1567 static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1571 /* Check for a label associated with this wild pCode */
1572 // If the wild card has a label, make sure the source code does too.
1573 if(PCI(pcd)->label) {
1574 pCode *pcl = PCI(pcd)->label->pc;
1577 int li = -PCL(pcl)->key;
1579 if(peepBlock->target.vars[li] == NULL) {
1580 if(PCI(pcs)->label) {
1581 DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1584 // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1585 DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1586 if(PCI(pcs)->label) {
1587 DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1593 if(!PCI(pcs)->label)
1596 labindex = -PCL(pcl)->key;
1597 if(peepBlock->target.vars[labindex] == NULL) {
1598 // First time to encounter this label
1599 peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1600 DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1603 if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1604 DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1607 DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1610 //DFPRINTF((stderr,"destination doesn't have a label\n"));
1615 //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1623 /*-----------------------------------------------------------------*/
1624 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1625 /* see they're the same. */
1627 /* In this context, "source" refers to the coded generated by gen.c*/
1628 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1629 /* ination has no wild cards, then MatchLine will compare the two */
1630 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1631 /* has wildcards, then those get expanded. When a wild card is */
1632 /* encountered for the first time it autmatically is considered a */
1633 /* match and the object that matches it is referenced in the */
1634 /* variables or opcodes array (depending on the type of match). */
1638 /* *peepBlock - A pointer to the peepBlock that contains the */
1639 /* entire rule to which the destination pcode belongs*/
1640 /* *pcs - a pointer to the source pcode */
1641 /* *pcd - a pointer to the destination pcode */
1644 /* 1 - pcodes match */
1645 /* 0 - pcodes don't match */
1648 /*-----------------------------------------------------------------*/
1650 static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1652 int index; // index into wild card arrays
1654 /* one-for-one match. Here the source and destination opcodes
1655 * are not wild. However, there may be a label or a wild operand */
1658 if(PCI(pcs)->label) {
1659 DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1663 if(pcs->type == pcd->type) {
1665 if(pcs->type == PC_OPCODE) {
1667 /* If the opcodes don't match then the line doesn't match */
1668 if(PCI(pcs)->op != PCI(pcd)->op)
1672 DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1673 pcs->print(stderr,pcs);
1674 pcd->print(stderr,pcd);
1677 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1680 /* Compare the operands */
1681 if(PCI(pcd)->pcop) {
1682 if (PCI(pcd)->pcop->type == PO_WILD) {
1683 index = PCOW(PCI(pcd)->pcop)->id;
1684 //DFPRINTF((stderr,"destination is wild\n"));
1685 #ifdef DEBUG_PCODEPEEP
1686 if (index > peepBlock->nops) {
1687 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1692 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1693 if(!peepBlock->target.wildpCodeOps[index]) {
1694 peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1696 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1700 pcs->print(stderr,pcs);
1701 pcd->print(stderr,pcd);
1703 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1704 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1708 return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1714 switch(PCI(pcs)->pcop->type) {
1718 n = PCOR(PCI(pcs)->pcop)->r->name;
1722 n = PCI(pcs)->pcop->name;
1725 if(peepBlock->target.vars[index])
1726 return (strcmp(peepBlock->target.vars[index],n) == 0);
1728 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1729 peepBlock->target.vars[index] = n;
1734 } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
1735 return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
1738 /* FIXME - need an else to check the case when the destination
1739 * isn't a wild card */
1741 /* The pcd has no operand. Lines match if pcs has no operand either*/
1742 return (PCI(pcs)->pcop == NULL);
1746 /* Compare a wild instruction to a regular one. */
1748 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1750 index = PCW(pcd)->id;
1752 DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
1753 pcs->print(stderr,pcs);
1754 pcd->print(stderr,pcd);
1756 peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
1758 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
1759 DFPRINTF((stderr," Failing because labels don't match\n"));
1763 if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1764 // doesn't match because the wild pcode must be a bit skip
1765 DFPRINTF((stderr," Failing match because bit skip is req\n"));
1766 //pcd->print(stderr,pcd);
1767 //pcs->print(stderr,pcs);
1771 if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1772 // doesn't match because the wild pcode must *not* be a bit skip
1773 DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
1774 //pcd->print(stderr,pcd);
1775 //pcs->print(stderr,pcs);
1779 if(PCW(pcd)->operand) {
1780 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1781 if(peepBlock->target.vars[index]) {
1782 int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
1786 DFPRINTF((stderr," (matched)\n"));
1788 DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
1789 DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n",
1790 peepBlock->target.vars[index],
1791 PCI(pcs)->pcop->name));
1796 DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
1797 peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
1802 pcs = pic16_findNextInstruction(pcs->next);
1804 //DFPRINTF((stderr," (next to match)\n"));
1805 //pcs->print(stderr,pcs);
1806 } else if(pcd->next) {
1807 /* oops, we ran out of code, but there's more to the rule */
1811 return 1; /* wild card matches */
1817 /*-----------------------------------------------------------------*/
1818 /*-----------------------------------------------------------------*/
1819 static void pCodePeepClrVars(pCodePeep *pcp)
1826 DFPRINTF((stderr," Clearing peep rule vars\n"));
1827 DFPRINTF((stderr," %d %d %d %d %d %d\n",
1828 pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
1829 pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
1831 for(i=0;i<pcp->target.nvars; i++)
1832 pcp->target.vars[i] = NULL;
1833 for(i=0;i<pcp->target.nops; i++)
1834 pcp->target.wildpCodeOps[i] = NULL;
1835 for(i=0;i<pcp->target.nwildpCodes; i++)
1836 pcp->target.wildpCodes[i] = NULL;
1838 for(i=0;i<pcp->replace.nvars; i++)
1839 pcp->replace.vars[i] = NULL;
1840 for(i=0;i<pcp->replace.nops; i++)
1841 pcp->replace.wildpCodeOps[i] = NULL;
1842 for(i=0;i<pcp->replace.nwildpCodes; i++)
1843 pcp->replace.wildpCodes[i] = NULL;
1849 /*-----------------------------------------------------------------*/
1850 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
1851 /* into the pCode chain containing pc1 */
1852 /*-----------------------------------------------------------------*/
1853 void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2)
1859 pc2->next = pc1->next;
1861 pc1->next->prev = pc2;
1869 /*-----------------------------------------------------------------*/
1870 /* pic16_pCodeOpCopy - copy a pcode operator */
1871 /*-----------------------------------------------------------------*/
1872 pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
1874 pCodeOp *pcopnew=NULL;
1879 switch(pcop->type) {
1882 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
1883 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1884 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
1885 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
1890 /* Here we expand the wild card into the appropriate type: */
1891 /* By recursively calling pCodeOpCopy */
1892 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
1893 if(PCOW(pcop)->matched)
1894 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->matched);
1897 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->subtype);
1898 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
1899 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
1906 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
1907 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1908 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
1912 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
1913 PCOI(pcopnew)->index = PCOI(pcop)->index;
1914 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
1915 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
1919 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
1920 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1921 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1924 #if 0 // mdubuc - To add
1931 pcopnew = pic16_newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
1932 PCOR(pcopnew)->r = PCOR(pcop)->r;
1933 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1934 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
1938 case PO_GPR_REGISTER:
1942 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
1943 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1944 PCOR(pcopnew)->r = PCOR(pcop)->r;
1945 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1946 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
1947 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
1951 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
1952 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1953 PCOR(pcopnew)->r = PCOR(pcop)->r;
1954 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1955 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
1958 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
1960 DFPRINTF((stderr,"pCodeOpCopy PO_BSR\n"));
1961 case PO_SFR_REGISTER:
1970 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
1971 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1975 pcopnew->type = pcop->type;
1977 pcopnew->name = Safe_strdup(pcop->name);
1979 pcopnew->name = NULL;
1985 /*-----------------------------------------------------------------*/
1986 /* pCodeCopy - copy a pcode */
1987 /*-----------------------------------------------------------------*/
1988 static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
1990 pCodeInstruction *new_pci;
1993 new_pci = PCI(pic16_newpCode(pci->inverted_op,pci->pcop));
1995 new_pci = PCI(pic16_newpCode(pci->op,pci->pcop));
1997 new_pci->pc.pb = pci->pc.pb;
1998 new_pci->from = pci->from;
1999 new_pci->to = pci->to;
2000 new_pci->label = pci->label;
2001 new_pci->pcflow = pci->pcflow;
2003 return PCODE(new_pci);
2006 /*-----------------------------------------------------------------*/
2007 /*-----------------------------------------------------------------*/
2008 static void pCodeDeleteChain(pCode *f,pCode *t)
2014 DFPRINTF((stderr,"delete pCode:\n"));
2016 //f->print(stderr,f);
2017 //f->delete(f); this dumps core...
2024 /*-----------------------------------------------------------------*/
2025 /*-----------------------------------------------------------------*/
2026 int pic16_pCodePeepMatchRule(pCode *pc)
2028 pCodePeep *peepBlock;
2030 pCodeCSource *pc_cline=NULL;
2034 peeprules = (_DLL *)peepSnippets;
2037 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
2039 if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
2040 fprintf(stderr, "skipping rule because target pb is NULL\n");
2044 pCodePeepClrVars(peepBlock);
2047 if(IS_PCCOMMENT(pcin))
2048 pc = pcin = pic16_findNextInstruction(pcin->next);
2050 pcin = pc = pic16_findNextInstruction(pc);
2052 pct = peepBlock->target.pb->pcHead;
2055 pCode *pcr = peepBlock->replace.pb->pcHead;
2056 if(pcr) pct->print(stderr,pcr);
2060 while(pct && pcin) {
2062 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
2065 pcin = pic16_findNextInstruction(pcin->next);
2068 //DFPRINTF((stderr," matched\n"));
2071 DFPRINTF((stderr," partial match... no more code\n"));
2072 // fprintf(stderr," partial match... no more code\n");
2076 DFPRINTF((stderr," end of rule\n"));
2080 if(matched && pcin) {
2082 /* So far we matched the rule up to the point of the conditions .
2083 * In other words, all of the opcodes match. Now we need to see
2084 * if the post conditions are satisfied.
2085 * First we check the 'postFalseCond'. This means that we check
2086 * to see if any of the subsequent pCode's in the pCode chain
2087 * following the point just past where we have matched depend on
2088 * the `postFalseCond' as input then we abort the match
2090 DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
2091 //pcin->print(stderr,pcin);
2093 if (pcin && peepBlock->postFalseCond &&
2094 (pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
2097 //fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
2100 //if(!matched) fprintf(stderr,"failed on conditions\n");
2109 /* We matched a rule! Now we have to go through and remove the
2110 inefficient code with the optimized version */
2112 DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
2113 printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
2114 DFPRINTF((stderr,"first thing matched\n"));
2115 pc->print(stderr,pc);
2117 DFPRINTF((stderr,"last thing matched\n"));
2118 pcin->print(stderr,pcin);
2123 /* Unlink the original code */
2125 pcprev->next = pcin;
2127 pcin->prev = pc->prev;
2133 /* Converted the deleted pCodes into comments */
2136 pCodeCSource *pc_cline2=NULL;
2141 while(pc && pc!=pcin) {
2143 if(pc->type == PC_OPCODE && PCI(pc)->cline) {
2145 pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2146 pc_cline2 = PCCS(pc_cline2->pc.next);
2148 pc_cline = pc_cline2 = PCI(pc)->cline;
2149 pc_cline->pc.seq = pc->seq;
2153 pCode2str(&buf[2], 254, pc);
2154 pic16_pCodeInsertAfter(pcprev, pic16_newpCodeCharP(buf));
2155 pcprev = pcprev->next;
2160 pc_cline2->pc.next = NULL;
2165 pCodeDeleteChain(pc,pcin);
2167 /* Generate the replacement code */
2169 pcr = peepBlock->replace.pb->pcHead; // This is the replacement code
2173 /* If the replace pcode is an instruction with an operand, */
2174 /* then duplicate the operand (and expand wild cards in the process). */
2175 if(pcr->type == PC_OPCODE) {
2176 if(PCI(pcr)->pcop) {
2177 /* The replacing instruction has an operand.
2179 if(PCI(pcr)->pcop->type == PO_WILD) {
2180 int index = PCOW(PCI(pcr)->pcop)->id;
2181 //DFPRINTF((stderr,"copying wildopcode\n"));
2182 if(peepBlock->target.wildpCodeOps[index])
2183 pcop = pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2185 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2187 pcop = pic16_pCodeOpCopy(PCI(pcr)->pcop);
2189 //DFPRINTF((stderr,"inserting pCode\n"));
2190 pic16_pCodeInsertAfter(pc, pic16_newpCode(PCI(pcr)->op,pcop));
2191 } else if (pcr->type == PC_WILD) {
2192 if(PCW(pcr)->invertBitSkipInst)
2193 DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2194 pic16_pCodeInsertAfter(pc,
2195 pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2196 PCW(pcr)->invertBitSkipInst));
2197 } else if (pcr->type == PC_COMMENT) {
2198 pic16_pCodeInsertAfter(pc, pic16_newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2204 DFPRINTF((stderr," NEW Code:"));
2205 if(pc) pc->print(stderr,pc);
2210 /* We have just replaced the inefficient code with the rule.
2211 * Now, we need to re-add the C-source symbols if there are any */
2215 pc = pic16_findNextInstruction(pc->next);
2216 PCI(pc)->cline = pc_cline;
2217 pc_cline = PCCS(pc_cline->pc.next);
2224 peeprules = peeprules->next;
2226 DFPRINTF((stderr," no rule matched\n"));