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);
49 pCodeOp *pic16_popCombine2(pCodeOp *, pCodeOp *, int);
51 extern pCodeInstruction *pic16Mnemonics[];
52 static int parsing_peeps=1;
54 #define IS_PCCOMMENT(x) ( x && (x->type==PC_COMMENT))
56 /****************************************************************/
58 * rootRules - defined in SDCCpeep.c
59 * This is a pointer to the (parsed) peephole rules that are
60 * defined in peep.def.
63 //extern peepRule *rootRules;
68 /****************************************************************/
69 /****************************************************************/
77 typedef struct pCodePeepSnippets
84 /****************************************************************/
88 /****************************************************************/
90 static pCodePeepSnippets *peepSnippets=NULL;
92 /****************************************************************/
96 /****************************************************************/
98 //static pCodePeep *curPeep=NULL;
100 /****************************************************************/
104 /****************************************************************/
106 //static pBlock *curBlock=NULL;
109 /****************************************************************/
111 /* max wild cards in a peep rule */
113 /****************************************************************/
115 //static int sMaxWildVar = 0;
116 //static int sMaxWildMnem = 0;
119 typedef struct pCodeToken
121 int tt; // token type;
130 pCodeToken tokArr[50];
131 static unsigned tokIdx=0;
149 typedef struct parsedPattern {
150 struct pcPattern *pcp;
154 #define MAX_PARSEDPATARR 50
155 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
156 //static unsigned int parsedPatIdx=0;
169 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
170 static char pcpat_number[] = {PCT_NUMBER, 0};
171 static char pcpat_string[] = {PCT_STRING, 0};
172 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
173 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
174 static char pcpat_comma[] = {PCT_COMMA, 0};
175 static char pcpat_comment[] = {PCT_COMMENT, 0};
178 typedef struct pcPattern {
179 char pt; // Pattern type
180 char *tokens; // list of tokens that describe the pattern
181 void * (*f) (void *,pCodeWildBlock *);
184 static pcPattern pcpArr[] = {
185 {PCP_LABEL, pcpat_label, NULL},
186 {PCP_WILDSTR, pcpat_wildString, NULL},
187 {PCP_STR, pcpat_string, NULL},
188 {PCP_WILDVAR, pcpat_wildVar, NULL},
189 {PCP_COMMA, pcpat_comma, NULL},
190 {PCP_COMMENT, pcpat_comment, NULL},
191 {PCP_NUMBER, pcpat_number, NULL}
194 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
196 // Assembly Line Token
213 static char alt_comment[] = { PCP_COMMENT, 0};
214 static char alt_label[] = { PCP_LABEL, 0};
215 static char alt_mnem0[] = { PCP_STR, 0};
216 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
217 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
218 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
219 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
220 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
221 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
222 //static char alt_mnem2b[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_WILDVAR, 0};
223 static char alt_mnem3[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_NUMBER, 0};
224 static char alt_mnem4[] = { PCP_STR, PCP_NUMBER, PCP_COMMA, PCP_STR, 0}; // for lfsr 0 , name
225 static char alt_mnem4a[] = { PCP_STR, PCP_NUMBER, PCP_COMMA, PCP_NUMBER, 0}; // for lfsr 0 , value
227 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
228 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
229 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb);
230 static void * cvt_altpat_mnem0a(void *pp,pCodeWildBlock *pcwb);
231 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb);
232 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb);
233 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb);
234 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb);
235 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb);
236 //static void * cvt_altpat_mnem2b(void *pp, pCodeWildBlock *pcwb);
237 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb);
238 static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb);
239 static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb);
241 /* NOTE: Order is important in the following table */
242 static pcPattern altArr[] = {
243 {ALT_LABEL, alt_label, cvt_altpat_label},
244 {ALT_COMMENT, alt_comment,cvt_altpat_comment},
245 {ALT_MNEM4a, alt_mnem4a, cvt_altpat_mnem4a},
246 {ALT_MNEM4, alt_mnem4, cvt_altpat_mnem4},
247 {ALT_MNEM3, alt_mnem3, cvt_altpat_mnem3},
248 // {ALT_MNEM2B, alt_mnem2b, cvt_altpat_mnem2b},
249 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
250 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
251 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
252 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
253 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
254 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
255 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
259 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
261 // forward declarations
262 static void * DLL_append(_DLL *list, _DLL *next);
264 /*-----------------------------------------------------------------*/
265 /* cvt_extract_destination - helper function extracts the register */
266 /* destination from a parsedPattern. */
268 /*-----------------------------------------------------------------*/
269 static int cvt_extract_destination(parsedPattern *pp)
272 if(pp->pct[0].tt == PCT_STRING) {
274 // just check first letter for now
276 if(toupper(*pp->pct[0].tok.s) == 'F')
279 } else if (pp->pct[0].tt == PCT_NUMBER) {
289 /*-----------------------------------------------------------------*/
290 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
291 /* if *reg is the "status" register and *bit is one of the */
292 /* status bits, then this function will create a new pCode op */
293 /* containing the status register. */
294 /*-----------------------------------------------------------------*/
296 static pCodeOp *cvt_extract_status(char *reg, char *bit)
300 if(STRCASECMP(reg, pic16_pc_status.pcop.name))
307 if(toupper(*bit) == 'C')
308 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_C_BIT));
309 if(toupper(*bit) == 'Z')
310 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_Z_BIT));
314 if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
315 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_DC_BIT));
321 /*-----------------------------------------------------------------*/
322 /* cvt_altpat_label - convert assembly line type to a pCode label */
323 /* INPUT: pointer to the parsedPattern */
327 /* label pattern => '%' number ':' */
328 /* at this point, we wish to extract only the 'number' */
330 /*-----------------------------------------------------------------*/
331 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb)
333 parsedPattern *p = pp;
335 DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
336 return pic16_newpCodeLabel(NULL,-p->pct[1].tok.n);
340 /*-----------------------------------------------------------------*/
341 /* cvt_altpat_comment - convert assembly line type to a comment */
342 /* INPUT: pointer to the parsedPattern */
344 /* pp[0] - comment */
347 /*-----------------------------------------------------------------*/
348 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb)
350 parsedPattern *p = pp;
352 DFPRINTF((stderr,"altpat_comment = %s\n",p->pct[0].tok.s));
353 return pic16_newpCodeCharP(p->pct[0].tok.s);
357 /*-----------------------------------------------------------------*/
358 /* cvt_altpat_mem0 - convert assembly line type to a wild pCode */
363 /*-----------------------------------------------------------------*/
364 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb)
366 parsedPattern *p = pp;
369 pCodeInstruction *pci=NULL;
371 DFPRINTF((stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s));
373 opcode = pic16_getpCode(p->pct[0].tok.s,0);
376 /* look for special command strings like _NOTBITSKIP_ */
378 //fprintf(stderr, "Bad mnemonic\n");
380 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
382 // fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
386 pci = PCI(pic16_newpCode(opcode, NULL));
389 fprintf(stderr,"couldn't find mnemonic\n");
395 /*-----------------------------------------------------------------*/
396 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
399 /* pp[0] - wild var */
401 /*-----------------------------------------------------------------*/
402 static void * cvt_altpat_mnem0a(void *pp, pCodeWildBlock *pcwb)
404 parsedPattern *p = pp;
406 DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n));
408 /* Save the index of the maximum wildcard mnemonic */
410 //if(p[0].pct[1].tok.n > sMaxWildVar)
411 // sMaxWildMnem = p[0].pct[1].tok.n;
413 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
414 pcwb->nwildpCodes = p[0].pct[1].tok.n;
416 return pic16_newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
420 /*-----------------------------------------------------------------*/
421 /* cvt_altpat_mem1 - convert assembly line type to a pCode */
422 /* instruction with 1 operand. */
425 /* pp[1] - Operand */
427 /*-----------------------------------------------------------------*/
428 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb)
431 parsedPattern *p = pp;
434 pCodeInstruction *pci=NULL;
437 DFPRINTF((stderr,"altpat_mnem1 %s var %s\n", p->pct[0].tok.s,p[1].pct[0].tok.s));
439 opcode = pic16_getpCode(p->pct[0].tok.s,0);
441 //fprintf(stderr, "Bad mnemonic\n");
442 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
444 //fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
449 if(pic16Mnemonics[opcode]->isBitInst)
450 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
452 // fprintf(stderr, "%s:%d tok.s= %s\n", __FILE__, __LINE__, p[1].pct[0].tok.s);
453 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_STR); //GPR_REGISTER);
457 pci = PCI(pic16_newpCode(opcode, pcosubtype));
460 fprintf(stderr,"couldn't find mnemonic\n");
466 /*-----------------------------------------------------------------*/
467 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
468 /* instruction with 1 wild operand. */
471 /* pp[1] - wild var */
473 /*-----------------------------------------------------------------*/
474 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb)
476 parsedPattern *p = pp;
479 pCodeInstruction *pci=NULL;
482 DFPRINTF((stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n));
484 opcode = pic16_getpCode(p->pct[0].tok.s,0);
486 int cmd_id = pic16_getpCodePeepCommand(p->pct[0].tok.s);
490 fprintf(stderr, "Bad mnemonic\n");
494 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
495 pcwb->nwildpCodes = p[0].pct[1].tok.n;
497 pc = pic16_newpCodeWild(p[1].pct[1].tok.n,NULL,NULL);
501 PCW(pc)->mustNotBeBitSkipInst = 1;
504 PCW(pc)->mustBeBitSkipInst = 1;
507 PCW(pc)->invertBitSkipInst = 1;
512 if(pic16Mnemonics[opcode]->isBitInst)
513 pcosubtype = pic16_newpCodeOpBit(NULL,-1,0);
515 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
518 pci = PCI(pic16_newpCode(opcode,
519 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
521 /* Save the index of the maximum wildcard variable */
522 //if(p[1].pct[1].tok.n > sMaxWildVar)
523 // sMaxWildVar = p[1].pct[1].tok.n;
525 if(p[1].pct[1].tok.n > pcwb->nvars)
526 pcwb->nvars = p[1].pct[1].tok.n;
529 fprintf(stderr,"couldn't find mnemonic\n");
535 /*-----------------------------------------------------------------*/
536 /*-----------------------------------------------------------------*/
537 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb)
539 parsedPattern *p = pp;
542 pCodeInstruction *pci=NULL;
544 DFPRINTF((stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n));
546 opcode = pic16_getpCode(p->pct[0].tok.s,0);
548 fprintf(stderr, "Bad mnemonic\n");
552 pci = PCI(pic16_newpCode(opcode, pic16_newpCodeOpLit(p[1].pct[0].tok.n) ));
555 fprintf(stderr,"couldn't find mnemonic\n");
561 /*-----------------------------------------------------------------*/
562 /* cvt_altpat_mnem2 */
567 /* pp[3] - destination */
568 /*-----------------------------------------------------------------*/
569 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
571 parsedPattern *p = pp;
575 pCodeInstruction *pci=NULL;
578 dest = cvt_extract_destination(&p[3]);
580 DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
586 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
588 fprintf(stderr, "Bad mnemonic\n");
592 if(pic16Mnemonics[opcode]->isBitInst) {
593 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
594 if(pcosubtype == NULL) {
595 fprintf(stderr, "bad operand?\n");
600 if(pic16Mnemonics[opcode]->is2MemOp) {
601 /* support for movff instruction */
602 pcosubtype = pic16_popCombine2(
603 pic16_newpCodeOp(p[1].pct[0].tok.s, PO_GPR_REGISTER),
604 pic16_newpCodeOp(p[3].pct[0].tok.s, PO_GPR_REGISTER), 0);
606 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
610 pci = PCI(pic16_newpCode(opcode,pcosubtype));
613 fprintf(stderr,"couldn't find mnemonic\n");
619 /*-----------------------------------------------------------------*/
620 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
621 /* instruction with 1 wild operand and a */
622 /* destination operand (e.g. w or f) */
625 /* pp[1] - wild var */
627 /* pp[3] - destination */
629 /*-----------------------------------------------------------------*/
630 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
632 parsedPattern *p = pp;
636 pCodeInstruction *pci=NULL;
640 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
644 dest = cvt_extract_destination(&p[3]);
646 DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
653 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
655 fprintf(stderr, "Bad mnemonic\n");
659 if(pic16Mnemonics[opcode]->isBitInst)
660 pcosubtype = pic16_newpCodeOp(NULL,PO_BIT);
662 if(pic16Mnemonics[opcode]->is2MemOp) {
664 /* support for movff instruction */
665 pcosubtype = pic16_popCombine2(
666 pic16_newpCodeOp(p[1].pct[0].tok.s, PO_GPR_REGISTER),
667 pic16_newpCodeOp(p[3].pct[0].tok.s, PO_GPR_REGISTER), 0);
669 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
672 pci = PCI(pic16_newpCode(opcode,
673 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
675 /* Save the index of the maximum wildcard variable */
676 //if(p[1].pct[1].tok.n > sMaxWildVar)
677 // sMaxWildVar = p[1].pct[1].tok.n;
679 if(p[1].pct[1].tok.n > pcwb->nvars)
680 pcwb->nvars = p[1].pct[1].tok.n;
683 fprintf(stderr,"couldn't find mnemonic\n");
690 /*-----------------------------------------------------------------*/
691 /* cvt_altpat_mem2b - convert assembly line type to a pCode */
692 /* instruction with 2 wild operands */
695 /* pp[1] - wild var */
697 /* pp[3] - wild var */
699 /*-----------------------------------------------------------------*/
700 static void * cvt_altpat_mnem2b(void *pp,pCodeWildBlock *pcwb)
702 parsedPattern *p = pp;
706 pCodeInstruction *pci=NULL;
710 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
714 dest = cvt_extract_destination(&p[3]);
716 DFPRINTF((stderr,"altpat_mnem2b %s src %d dst (%d)\n",
722 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
724 fprintf(stderr, "Bad mnemonic\n");
728 if(pic16Mnemonics[opcode]->is2MemOp) {
729 /* support for movff instruction */
730 pcosubtype = pic16_popCombine2(
731 pic16_newpCodeOp(NULL, PO_GPR_REGISTER),
732 pic16_newpCodeOp(NULL, PO_GPR_REGISTER), 0);
733 } else pcosubtype = NULL;
735 pci = PCI(pic16_newpCode(opcode,
736 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
738 /* Save the index of the maximum wildcard variable */
739 //if(p[1].pct[1].tok.n > sMaxWildVar)
740 // sMaxWildVar = p[1].pct[1].tok.n;
742 if(p[1].pct[1].tok.n > pcwb->nvars)
743 pcwb->nvars = p[1].pct[1].tok.n;
746 fprintf(stderr,"couldn't find mnemonic\n");
754 /*-----------------------------------------------------------------*/
755 /* cvt_altpat_mem3 - convert assembly line type to a pCode */
756 /* This rule is for bsf/bcf type instructions */
760 /* pp[1] - register */
764 /*-----------------------------------------------------------------*/
765 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
767 parsedPattern *p = pp;
769 int dest; // or could be bit position in the register
771 pCodeInstruction *pci=NULL;
772 pCodeOp *pcosubtype=NULL;
774 dest = cvt_extract_destination(&p[3]);
776 DFPRINTF((stderr,"altpat_mnem3 %s var %s bit (%d)\n",
782 opcode = pic16_getpCode(p->pct[0].tok.s,0);
784 fprintf(stderr, "Bad mnemonic\n");
789 if(pic16Mnemonics[opcode]->isBitInst) {
790 //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
792 //if(pcosubtype == NULL) {
793 pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0);
796 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
798 if(pcosubtype == NULL) {
799 fprintf(stderr, "Bad operand\n");
803 pci = PCI(pic16_newpCode(opcode, pcosubtype));
806 fprintf(stderr,"couldn't find mnemonic\n");
812 /*-----------------------------------------------------------------*/
813 /* cvt_altpat_mem4 - convert assembly line type to a pCode */
814 /* This rule is for lfsr instruction */
822 /*-----------------------------------------------------------------*/
823 static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb)
825 parsedPattern *p = pp;
827 int dest; // or could be bit position in the register
829 pCodeInstruction *pci=NULL;
830 pCodeOp *pcosubtype=NULL;
832 dest = cvt_extract_destination(&p[3]);
834 DFPRINTF((stderr,"altpat_mnem4 %s fsr %d source %s\n",
839 opcode = pic16_getpCode(p->pct[0].tok.s,0);
841 fprintf(stderr, "Bad mnemonic\n");
844 DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
846 if(pic16Mnemonics[opcode]->is2LitOp) {
847 pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOp(p[3].pct[0].tok.s, PO_STR));
850 if(pcosubtype == NULL) {
851 fprintf(stderr, "Bad operand\n");
855 pci = PCI(pic16_newpCode(opcode, pcosubtype));
858 fprintf(stderr,"couldn't find mnemonic\n");
864 /*-----------------------------------------------------------------*/
865 /* cvt_altpat_mem4a - convert assembly line type to a pCode */
866 /* This rule is for lfsr instruction */
874 /*-----------------------------------------------------------------*/
875 static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb)
877 parsedPattern *p = pp;
879 int dest; // or could be bit position in the register
881 pCodeInstruction *pci=NULL;
882 pCodeOp *pcosubtype=NULL;
884 dest = cvt_extract_destination(&p[3]);
886 DFPRINTF((stderr,"altpat_mnem4a %s fsr %d value 0x%02x\n",
891 opcode = pic16_getpCode(p->pct[0].tok.s,0);
893 fprintf(stderr, "Bad mnemonic\n");
896 DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
898 if(pic16Mnemonics[opcode]->is2LitOp) {
899 pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOpLit(p[3].pct[0].tok.n));
902 if(pcosubtype == NULL) {
903 fprintf(stderr, "Bad operand\n");
907 pci = PCI(pic16_newpCode(opcode, pcosubtype));
910 fprintf(stderr,"couldn't find mnemonic\n");
916 /*-----------------------------------------------------------------*/
917 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
918 /* by SDCCpeeph.c into a string of tokens. */
921 /* The tokenizer is of the classic type. When an item is encounterd*/
922 /* it is converted into a token. The token is a structure that */
923 /* encodes the item's type and it's value (when appropriate). */
925 /* Accepted token types: */
926 /* SPACE NUMBER STRING % : , ; */
930 /*-----------------------------------------------------------------*/
933 static void tokenizeLineNode(char *ln)
936 tokIdx = 0; // Starting off at the beginning
937 tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
942 // fprintf(stderr, "%s:%d: processing %s\n", __FILE__, __LINE__, ln);
946 // add a SPACE token and eat the extra spaces.
947 tokArr[tokIdx++].tt = PCT_SPACE;
948 while (isspace (*ln))
955 tokArr[tokIdx].tt = PCT_NUMBER;
956 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
964 tokArr[tokIdx++].tt = PCT_PERCENT;
967 tokArr[tokIdx++].tt = PCT_LESSTHAN;
970 tokArr[tokIdx++].tt = PCT_GREATERTHAN;
973 tokArr[tokIdx++].tt = PCT_COLON;
976 tokArr[tokIdx].tok.s = Safe_strdup(ln);
977 tokArr[tokIdx++].tt = PCT_COMMENT;
978 tokArr[tokIdx].tt = PCT_NULL;
981 tokArr[tokIdx++].tt = PCT_COMMA;
985 default: // hack to allow : goto $
986 if(isalpha(*ln) || (*ln == '_') || (!parsing_peeps && (*ln == '$'))) {
990 while( (isalpha(*ln) || isdigit(*ln) || (*ln == '_') || (*ln == '$')) && i<49)
996 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
997 tokArr[tokIdx++].tt = PCT_STRING;
1001 fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
1002 fprintf(stderr, "Line: %s\n",lnstart);
1003 fprintf(stderr, "Token: '%c'\n",*ln);
1009 /* Advance to next character in input string .
1010 * Note, if none of the tests passed above, then
1011 * we effectively ignore the `bad' character.
1012 * Since the line has already been parsed by SDCCpeeph,
1013 * chance are that there are no invalid characters... */
1019 tokArr[tokIdx].tt = 0;
1023 /*-----------------------------------------------------------------*/
1024 /*-----------------------------------------------------------------*/
1028 static void dump1Token(pCodeTokens tt)
1033 fprintf(stderr, " space ");
1036 fprintf(stderr, " pct %%");
1039 fprintf(stderr, " pct <");
1041 case PCT_GREATERTHAN:
1042 fprintf(stderr, " pct >");
1045 fprintf(stderr, " col :");
1048 fprintf(stderr, " comma , ");
1051 fprintf(stderr, " comment ");
1052 //fprintf(stderr,"%s",tokArr[i].tok.s);
1055 fprintf(stderr, " str ");
1056 //fprintf(stderr,"%s",tokArr[i].tok.s);
1059 fprintf(stderr, " num ");
1060 //fprintf(stderr,"%d",tokArr[i].tok.n);
1063 fprintf(stderr, " null ");
1070 /*-----------------------------------------------------------------*/
1071 /*-----------------------------------------------------------------*/
1073 static int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
1077 if(!pct || !pat || !*pat)
1080 //DFPRINTF((stderr,"comparing against:\n"));
1082 while(i < max_tokens) {
1085 //DFPRINTF((stderr,"matched\n"));
1089 // dump1Token(*pat); fputc('\n', stderr); DFPRINTF((stderr,"\n"));
1103 /*-----------------------------------------------------------------*/
1104 /*-----------------------------------------------------------------*/
1106 static int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
1110 if(!pct || !pat || !*pct)
1114 while(i < max_tokens) {
1117 DFPRINTF((stderr,"matched\n"));
1121 // dump1Token(*pat); DFPRINTF((stderr,"\n"));
1123 if( !pat || !pat->pcp )
1126 if (pat->pcp->pt != *pct)
1129 DFPRINTF((stderr," pct=%d\n",*pct));
1138 /*-----------------------------------------------------------------*/
1139 /*-----------------------------------------------------------------*/
1141 static int advTokIdx(int *v, int amt)
1144 if((unsigned) (*v + amt) > tokIdx)
1152 /*-----------------------------------------------------------------*/
1153 /* parseTokens - convert the tokens corresponding to a single line */
1154 /* of a peep hole assembly into a pCode object. */
1159 /* This is a simple parser that looks for strings of the type */
1160 /* allowed in the peep hole definition file. Essentially the format*/
1161 /* is the same as a line of assembly: */
1163 /* label: mnemonic op1, op2, op3 ; comment */
1165 /* Some of these items aren't present. It's the job of the parser */
1166 /* to determine which are and convert those into the appropriate */
1168 /*-----------------------------------------------------------------*/
1170 static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
1181 for(i=0; i<=tokIdx; i++)
1182 dump1Token(tokArr[i].tt);
1188 int lparsedPatIdx=0;
1195 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
1196 char * cP1stop = NULL;
1197 char * cP2ndop = NULL;
1199 //pCodeOp *pcl = NULL; // Storage for a label
1200 //pCodeOp *pco1 = NULL; // 1st operand
1201 //pCodeOp *pco2 = NULL; // 2nd operand
1202 //pCode *pc = NULL; // Mnemonic
1213 ParseStates state = PS_START;
1220 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
1221 && (advTokIdx(<okIdx, 1)) ) // eat space
1225 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
1228 switch(pcpArr[lpcpIdx].pt) {
1230 if(state == PS_START){
1231 DFPRINTF((stderr," label\n"));
1232 state = PS_HAVE_LABEL;
1234 DFPRINTF((stderr," bad state (%d) for label\n",state));
1238 DFPRINTF((stderr," %s is",tokArr[ltokIdx].tok.s));
1242 DFPRINTF((stderr," mnem\n"));
1243 cPmnem = tokArr[ltokIdx].tok.s;
1244 state = PS_HAVE_MNEM;
1247 DFPRINTF((stderr," 1st operand\n"));
1248 cP1stop = tokArr[ltokIdx].tok.s;
1249 //pco1 = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
1250 state = PS_HAVE_1OPERAND;
1252 case PS_HAVE_1OPERAND:
1253 DFPRINTF((stderr," error expecting comma\n"));
1256 DFPRINTF((stderr," 2 operands\n"));
1257 cP2ndop = tokArr[ltokIdx].tok.s;
1259 case PS_HAVE_2OPERANDS:
1268 DFPRINTF((stderr," wild mnem\n"));
1269 state = PS_HAVE_MNEM;
1272 DFPRINTF((stderr," 1st operand is wild\n"));
1273 state = PS_HAVE_1OPERAND;
1275 case PS_HAVE_1OPERAND:
1276 DFPRINTF((stderr," error expecting comma\n"));
1279 DFPRINTF((stderr," 2nd operand is wild\n"));
1281 case PS_HAVE_2OPERANDS:
1290 fprintf(stderr," ERROR number\n");
1293 DFPRINTF((stderr," 1st operand is a number\n"));
1294 state = PS_HAVE_1OPERAND;
1296 case PS_HAVE_1OPERAND:
1297 fprintf(stderr," error expecting comma\n");
1300 DFPRINTF((stderr," 2nd operand is a number\n"));
1302 case PS_HAVE_2OPERANDS:
1310 if(state == PS_HAVE_1OPERAND){
1311 DFPRINTF((stderr," got a comma\n"));
1312 state = PS_HAVE_COMMA;
1314 fprintf(stderr," unexpected comma\n");
1320 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1321 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1324 // dump1Token(tokArr[ltokIdx].tt);
1326 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1327 DFPRINTF((stderr," reached end \n"));
1334 } while ((++lpcpIdx < PCPATTERNS) && !matching);
1338 parsedPatArr[lparsedPatIdx].pcp = NULL;
1339 parsedPatArr[lparsedPatIdx].pct = NULL;
1345 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1348 pc = altArr[k].f(&parsedPatArr[j],pcwb);
1349 //if(pc && pc->print)
1350 // pc->print(stderr,pc);
1351 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1353 //if(curBlock && pc)
1354 //pic16_addpCode2pBlock(curBlock, pc);
1358 return 0; // Only accept one line for now.
1360 pic16_addpCode2pBlock(pcwb->pb, pc);
1368 while(j<=lparsedPatIdx && k<ALTPATTERNS);
1371 DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1375 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1376 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1377 DFPRINTF((stderr," %d",parsedPatArr[j].pcp->pt));
1380 while(j<lparsedPatIdx);
1382 DFPRINTF((stderr,"\n"));
1389 /*-----------------------------------------------------------------*/
1391 /*-----------------------------------------------------------------*/
1392 static void peepRuleBlock2pCodeBlock( lineNode *ln, pCodeWildBlock *pcwb)
1398 for( ; ln; ln = ln->next) {
1400 //DFPRINTF((stderr,"%s\n",ln->line));
1401 // fprintf(stderr, "peep rule : %s\n", ln->line);
1403 tokenizeLineNode(ln->line);
1405 if(parseTokens(pcwb,NULL)) {
1407 fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
1408 fprintf(stderr,"Tokens:\n");
1410 dump1Token(tokArr[i].tt);
1417 /*-----------------------------------------------------------------*/
1418 /* pic16_AssembleLine - parse line and return the pCode equivalent */
1419 /* peeps=1 if parsing peep rules, 0 otherwise */
1420 /*-----------------------------------------------------------------*/
1421 pCode *pic16_AssembleLine(char *line, int peeps)
1425 if(!line || !*line) {
1426 fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
1430 parsing_peeps = peeps;
1432 tokenizeLineNode(line);
1434 if(parseTokens(NULL,&pc))
1435 fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
1437 DFPRINTF((stderr, "pc= %p\n", pc));
1438 // if(pc)pc->print(stderr, pc);
1446 /*-----------------------------------------------------------------*/
1447 /* peepRuleCondition */
1448 /*-----------------------------------------------------------------*/
1449 static void peepRuleCondition(char *cond, pCodePeep *pcp)
1454 //DFPRINTF((stderr,"\nCondition: %s\n",cond));
1455 /* brute force compares for now */
1457 if(STRCASECMP(cond, "NZ") == 0) {
1458 //DFPRINTF((stderr,"found NZ\n"));
1459 pcp->postFalseCond = PCC_Z;
1466 static void initpCodeWildBlock(pCodeWildBlock *pcwb)
1469 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1475 pcwb->wildpCodes = NULL;
1476 pcwb->wildpCodeOps = NULL;
1479 pcwb->nwildpCodes = 0;
1484 static void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1491 pcwb->nops = pcwb->nvars;
1493 pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1494 pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1496 pcwb->nwildpCodes+=2;
1497 pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1501 static void initpCodePeep(pCodePeep *pcp)
1504 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1509 initpCodeWildBlock(&pcp->target);
1510 pcp->target.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1512 initpCodeWildBlock(&pcp->replace);
1513 pcp->replace.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1517 /*-----------------------------------------------------------------*/
1518 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1521 /* SDCCpeeph parses the peep rules file and extracts variables, */
1522 /* removes white space, and checks the syntax. This function */
1523 /* extends that processing to produce pCode objects. You can kind */
1524 /* think of this function as an "assembler", though instead of */
1525 /* taking raw text to produce machine code, it produces pCode. */
1527 /*-----------------------------------------------------------------*/
1528 extern void pic16initpCodePeepCommands(void);
1530 void pic16_peepRules2pCode(peepRule *rules)
1534 pCodePeep *currentRule;
1535 pCodePeepSnippets *pcps;
1537 pic16initpCodePeepCommands();
1539 /* The rules are in a linked-list. Each rule has two portions */
1540 /* There's the `target' and there's the `replace'. The target */
1541 /* is compared against the SDCC generated code and if it */
1542 /* matches, it gets replaced by the `replace' block of code. */
1544 /* Here we loop through each rule and convert the target's and*/
1545 /* replace's into pCode target and replace blocks */
1547 for (pr = rules; pr; pr = pr->next) {
1549 //DFPRINTF((stderr,"\nRule:\n\n"));
1551 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1552 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1554 currentRule = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1555 initpCodePeep(currentRule);
1557 /* Convert the target block */
1558 peepRuleBlock2pCodeBlock(pr->match, ¤tRule->target);
1560 //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1561 // pic16_printpBlock(stderr, currentRule->target.pb);
1563 //DFPRINTF((stderr,"target with labels merged:\n"));
1564 //pic16_pBlockMergeLabels(curBlock);
1565 pic16_pBlockMergeLabels(currentRule->target.pb);
1566 //pic16_printpBlock(stderr, currentRule->replace.pb);
1568 //#ifdef PCODE_DEBUG
1569 // pic16_printpBlock(stderr, curBlock);
1571 //DFPRINTF((stderr,"\nReplaced by:\n"));
1574 /* Convert the replace block */
1575 peepRuleBlock2pCodeBlock(pr->replace, ¤tRule->replace);
1577 //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1578 //pic16_printpBlock(stderr, curBlock);
1580 //DFPRINTF((stderr,"replace with labels merged:\n"));
1582 pic16_pBlockMergeLabels(currentRule->replace.pb);
1583 //pic16_printpBlock(stderr, currentRule->replace.pb);
1585 peepRuleCondition(pr->cond,currentRule);
1587 /* The rule has been converted to pCode. Now allocate
1588 * space for the wildcards */
1590 postinit_pCodeWildBlock(¤tRule->target);
1591 postinit_pCodeWildBlock(¤tRule->replace);
1593 //return; // debug ... don't want to go through all the rules yet
1597 pCodePeep *peepBlock;
1600 peeprules = (_DLL *)peepSnippets;
1601 //fprintf(stderr,"target rules\n");
1603 //fprintf(stderr," rule:\n");
1604 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1605 //pic16_printpBlock(stderr, peepBlock->target.pb);
1606 peeprules = peeprules->next;
1608 //fprintf(stderr," ... done\n");
1613 static void printpCodeString(FILE *of, pCode *pc, int max)
1617 while(pc && (i++<max)) {
1623 /*-----------------------------------------------------------------*/
1624 /* _DLL * DLL_append */
1626 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1627 /* If The list to which we want to append is non-existant then one */
1628 /* is created. Other wise, the end of the list is sought out and */
1629 /* a new DLL object is appended to it. In either case, the void */
1630 /* *data is added to the newly created DLL object. */
1631 /*-----------------------------------------------------------------*/
1633 static void * DLL_append(_DLL *list, _DLL *next)
1638 /* If there's no list, then create one: */
1640 next->next = next->prev = NULL;
1645 /* Search for the end of the list. */
1650 /* Now append the new DLL object */
1661 /*-----------------------------------------------------------------
1663 pCode peephole optimization
1666 The pCode "peep hole" optimization is not too unlike the peep hole
1667 optimization in SDCCpeeph.c. The major difference is that here we
1668 use pCode's whereas there we use ASCII strings. The advantage with
1669 pCode's is that we can ascertain flow information in the instructions
1673 <FIX ME> - elaborate...
1675 -----------------------------------------------------------------*/
1679 /*-----------------------------------------------------------------*/
1680 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1682 /* return conditions */
1683 /* 1 - The Condition was found for a pCode's input */
1684 /* 0 - No matching condition was found for the whole chain */
1685 /* -1 - The Condition was found for a pCode's output */
1687 /*-----------------------------------------------------------------*/
1688 int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond)
1690 //fprintf(stderr,"Checking conditions %d\n",cond);
1693 /* If we reach a function end (presumably an end since we most
1694 probably began the search in the middle of a function), then
1695 the condition was not found. */
1696 if(pc->type == PC_FUNCTION)
1699 if(pc->type == PC_OPCODE) {
1700 //fprintf(stderr," checking conditions of: ");
1701 //pc->print(stderr,pc);
1702 //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
1703 if(PCI(pc)->inCond & cond)
1705 if(PCI(pc)->outCond & cond)
1715 /*-----------------------------------------------------------------
1716 * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1718 * Compare two pCodeOp's and return 1 if they're the same
1719 *-----------------------------------------------------------------*/
1720 static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1724 if(!pcops || !pcopd)
1728 fprintf(stderr," Comparing operands %s",
1729 pic16_get_op( pcops,NULL,0));
1731 fprintf(stderr," to %s\n",
1732 pic16_get_op( pcopd,NULL,0));
1735 if(pcops->type != pcopd->type) {
1736 //fprintf(stderr," - fail - diff types\n");
1737 return 0; // different types
1740 if(pcops->type == PO_LITERAL) {
1742 if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
1749 pic16_get_op(pcops,b,50);
1751 n2 = pic16_get_op(pcopd,NULL,0);
1753 if( !n2 || strcmp(b,n2)) {
1754 //fprintf(stderr," - fail - diff names: %s, len=%d, %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1755 return 0; // different names
1758 switch(pcops->type) {
1760 if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1761 //fprintf(stderr, " - fail different instances\n");
1769 //fprintf(stderr," - pass\n");
1774 static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1778 /* Check for a label associated with this wild pCode */
1779 // If the wild card has a label, make sure the source code does too.
1780 if(PCI(pcd)->label) {
1781 pCode *pcl = PCI(pcd)->label->pc;
1784 int li = -PCL(pcl)->key;
1786 if(peepBlock->target.vars[li] == NULL) {
1787 if(PCI(pcs)->label) {
1788 DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1791 // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1792 DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1793 if(PCI(pcs)->label) {
1794 DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1800 if(!PCI(pcs)->label)
1803 labindex = -PCL(pcl)->key;
1804 if(peepBlock->target.vars[labindex] == NULL) {
1805 // First time to encounter this label
1806 peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1807 DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1810 if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1811 DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1814 DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1817 //DFPRINTF((stderr,"destination doesn't have a label\n"));
1822 //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1830 /*-----------------------------------------------------------------*/
1831 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1832 /* see they're the same. */
1834 /* In this context, "source" refers to the coded generated by gen.c*/
1835 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1836 /* ination has no wild cards, then MatchLine will compare the two */
1837 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1838 /* has wildcards, then those get expanded. When a wild card is */
1839 /* encountered for the first time it autmatically is considered a */
1840 /* match and the object that matches it is referenced in the */
1841 /* variables or opcodes array (depending on the type of match). */
1845 /* *peepBlock - A pointer to the peepBlock that contains the */
1846 /* entire rule to which the destination pcode belongs*/
1847 /* *pcs - a pointer to the source pcode */
1848 /* *pcd - a pointer to the destination pcode */
1851 /* 1 - pcodes match */
1852 /* 0 - pcodes don't match */
1855 /*-----------------------------------------------------------------*/
1857 static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1859 int index; // index into wild card arrays
1861 /* one-for-one match. Here the source and destination opcodes
1862 * are not wild. However, there may be a label or a wild operand */
1865 if(PCI(pcs)->label) {
1866 DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1870 if(pcs->type == pcd->type) {
1872 if(pcs->type == PC_OPCODE) {
1874 /* If the opcodes don't match then the line doesn't match */
1875 if(PCI(pcs)->op != PCI(pcd)->op)
1879 DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1880 pcs->print(stderr,pcs);
1881 pcd->print(stderr,pcd);
1884 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1887 /* Compare the operands */
1888 if(PCI(pcd)->pcop) {
1889 if (PCI(pcd)->pcop->type == PO_WILD) {
1890 index = PCOW(PCI(pcd)->pcop)->id;
1891 //DFPRINTF((stderr,"destination is wild\n"));
1892 #ifdef DEBUG_PCODEPEEP
1893 if (index > peepBlock->nops) {
1894 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1899 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1900 if(!peepBlock->target.wildpCodeOps[index]) {
1901 peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1903 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1907 pcs->print(stderr,pcs);
1908 pcd->print(stderr,pcd);
1910 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1911 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1915 return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1918 if(PCI(pcs)->pcop) {
1921 switch(PCI(pcs)->pcop->type) {
1925 n = PCOR(PCI(pcs)->pcop)->r->name;
1929 n = PCI(pcs)->pcop->name;
1932 if(peepBlock->target.vars[index])
1933 return (strcmp(peepBlock->target.vars[index],n) == 0);
1935 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1936 peepBlock->target.vars[index] = n;
1941 if(PCI(pcs)->is2MemOp) {
1944 switch(PCOP(PCOR2(PCI(pcs))->pcop2)->type) {
1948 n = PCOR(PCOR2(PCI(pcs))->pcop2)->r->name;
1952 n = PCI(pcs)->pcop->name;
1955 if(peepBlock->target.vars[index])
1956 return (strcmp(peepBlock->target.vars[index],n) == 0);
1958 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1959 peepBlock->target.vars[index] = n;
1964 } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
1965 return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
1968 /* FIXME - need an else to check the case when the destination
1969 * isn't a wild card */
1971 /* The pcd has no operand. Lines match if pcs has no operand either*/
1972 return (PCI(pcs)->pcop == NULL);
1976 /* Compare a wild instruction to a regular one. */
1978 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1980 index = PCW(pcd)->id;
1982 DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
1983 pcs->print(stderr,pcs);
1984 pcd->print(stderr,pcd);
1986 peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
1988 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
1989 DFPRINTF((stderr," Failing because labels don't match\n"));
1993 if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1994 // doesn't match because the wild pcode must be a bit skip
1995 DFPRINTF((stderr," Failing match because bit skip is req\n"));
1996 //pcd->print(stderr,pcd);
1997 //pcs->print(stderr,pcs);
2001 if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
2002 // doesn't match because the wild pcode must *not* be a bit skip
2003 DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
2004 //pcd->print(stderr,pcd);
2005 //pcs->print(stderr,pcs);
2009 if(PCW(pcd)->operand) {
2010 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
2011 if(peepBlock->target.vars[index]) {
2012 int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
2016 DFPRINTF((stderr," (matched)\n"));
2018 DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
2019 DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n",
2020 peepBlock->target.vars[index],
2021 PCI(pcs)->pcop->name));
2026 DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
2027 peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
2032 pcs = pic16_findNextInstruction(pcs->next);
2034 //DFPRINTF((stderr," (next to match)\n"));
2035 //pcs->print(stderr,pcs);
2036 } else if(pcd->next) {
2037 /* oops, we ran out of code, but there's more to the rule */
2041 return 1; /* wild card matches */
2047 /*-----------------------------------------------------------------*/
2048 /*-----------------------------------------------------------------*/
2049 static void pCodePeepClrVars(pCodePeep *pcp)
2056 DFPRINTF((stderr," Clearing peep rule vars\n"));
2057 DFPRINTF((stderr," %d %d %d %d %d %d\n",
2058 pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
2059 pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
2061 for(i=0;i<pcp->target.nvars; i++)
2062 pcp->target.vars[i] = NULL;
2063 for(i=0;i<pcp->target.nops; i++)
2064 pcp->target.wildpCodeOps[i] = NULL;
2065 for(i=0;i<pcp->target.nwildpCodes; i++)
2066 pcp->target.wildpCodes[i] = NULL;
2068 for(i=0;i<pcp->replace.nvars; i++)
2069 pcp->replace.vars[i] = NULL;
2070 for(i=0;i<pcp->replace.nops; i++)
2071 pcp->replace.wildpCodeOps[i] = NULL;
2072 for(i=0;i<pcp->replace.nwildpCodes; i++)
2073 pcp->replace.wildpCodes[i] = NULL;
2079 /*-----------------------------------------------------------------*/
2080 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2081 /* into the pCode chain containing pc1 */
2082 /*-----------------------------------------------------------------*/
2083 void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2)
2089 pc2->next = pc1->next;
2091 pc1->next->prev = pc2;
2099 /*-----------------------------------------------------------------*/
2100 /* pic16_pCodeOpCopy - copy a pcode operator */
2101 /*-----------------------------------------------------------------*/
2102 pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
2104 pCodeOp *pcopnew=NULL;
2109 switch(pcop->type) {
2112 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2113 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2114 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2115 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2120 /* Here we expand the wild card into the appropriate type: */
2121 /* By recursively calling pCodeOpCopy */
2122 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2123 if(PCOW(pcop)->matched)
2124 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->matched);
2127 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->subtype);
2128 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2129 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2136 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2137 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2138 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2142 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2143 PCOI(pcopnew)->index = PCOI(pcop)->index;
2144 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2145 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2149 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2150 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2151 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2154 #if 0 // mdubuc - To add
2161 pcopnew = pic16_newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2162 PCOR(pcopnew)->r = PCOR(pcop)->r;
2163 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2164 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2168 case PO_GPR_REGISTER:
2172 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2173 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2174 PCOR(pcopnew)->r = PCOR(pcop)->r;
2175 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2176 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2177 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2181 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2182 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2183 PCOR(pcopnew)->r = PCOR(pcop)->r;
2184 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2185 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2188 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2190 DFPRINTF((stderr,"pCodeOpCopy PO_BSR\n"));
2191 case PO_SFR_REGISTER:
2203 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2204 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2208 pcopnew->type = pcop->type;
2210 pcopnew->name = Safe_strdup(pcop->name);
2212 pcopnew->name = NULL;
2218 /*-----------------------------------------------------------------*/
2219 /* pCodeCopy - copy a pcode */
2220 /*-----------------------------------------------------------------*/
2221 static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2223 pCodeInstruction *new_pci;
2226 new_pci = PCI(pic16_newpCode(pci->inverted_op,pci->pcop));
2228 new_pci = PCI(pic16_newpCode(pci->op,pci->pcop));
2230 new_pci->pc.pb = pci->pc.pb;
2231 new_pci->from = pci->from;
2232 new_pci->to = pci->to;
2233 new_pci->label = pci->label;
2234 new_pci->pcflow = pci->pcflow;
2236 return PCODE(new_pci);
2239 /*-----------------------------------------------------------------*/
2240 /*-----------------------------------------------------------------*/
2241 static void pCodeDeleteChain(pCode *f,pCode *t)
2247 DFPRINTF((stderr,"delete pCode:\n"));
2249 //f->print(stderr,f);
2250 //f->delete(f); this dumps core...
2257 /*-----------------------------------------------------------------*/
2258 /*-----------------------------------------------------------------*/
2259 int pic16_pCodePeepMatchRule(pCode *pc)
2261 pCodePeep *peepBlock;
2263 pCodeCSource *pc_cline=NULL;
2267 peeprules = (_DLL *)peepSnippets;
2270 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
2272 if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
2273 fprintf(stderr, "skipping rule because target pb is NULL\n");
2277 pCodePeepClrVars(peepBlock);
2280 if(IS_PCCOMMENT(pcin))
2281 pc = pcin = pic16_findNextInstruction(pcin->next);
2283 pcin = pc = pic16_findNextInstruction(pc);
2285 pct = peepBlock->target.pb->pcHead;
2288 pCode *pcr = peepBlock->replace.pb->pcHead;
2289 if(pcr) pct->print(stderr,pcr);
2293 while(pct && pcin) {
2295 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
2298 pcin = pic16_findNextInstruction(pcin->next);
2301 //DFPRINTF((stderr," matched\n"));
2304 DFPRINTF((stderr," partial match... no more code\n"));
2305 // fprintf(stderr," partial match... no more code\n");
2309 DFPRINTF((stderr," end of rule\n"));
2313 if(matched && pcin) {
2315 /* So far we matched the rule up to the point of the conditions .
2316 * In other words, all of the opcodes match. Now we need to see
2317 * if the post conditions are satisfied.
2318 * First we check the 'postFalseCond'. This means that we check
2319 * to see if any of the subsequent pCode's in the pCode chain
2320 * following the point just past where we have matched depend on
2321 * the `postFalseCond' as input then we abort the match
2323 DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
2324 //pcin->print(stderr,pcin);
2326 if (pcin && peepBlock->postFalseCond &&
2327 (pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
2330 //fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
2333 //if(!matched) fprintf(stderr,"failed on conditions\n");
2342 /* We matched a rule! Now we have to go through and remove the
2343 inefficient code with the optimized version */
2345 DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
2346 // printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
2347 DFPRINTF((stderr,"first thing matched\n"));
2348 pc->print(stderr,pc);
2350 DFPRINTF((stderr,"last thing matched\n"));
2351 pcin->print(stderr,pcin);
2356 /* Unlink the original code */
2358 pcprev->next = pcin;
2360 pcin->prev = pc->prev;
2366 /* Converted the deleted pCodes into comments */
2369 pCodeCSource *pc_cline2=NULL;
2374 while(pc && pc!=pcin) {
2376 if(pc->type == PC_OPCODE && PCI(pc)->cline) {
2378 pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2379 pc_cline2 = PCCS(pc_cline2->pc.next);
2381 pc_cline = pc_cline2 = PCI(pc)->cline;
2382 pc_cline->pc.seq = pc->seq;
2386 pCode2str(&buf[2], 254, pc);
2387 pic16_pCodeInsertAfter(pcprev, pic16_newpCodeCharP(buf));
2388 pcprev = pcprev->next;
2393 pc_cline2->pc.next = NULL;
2398 pCodeDeleteChain(pc,pcin);
2400 /* Generate the replacement code */
2402 pcr = peepBlock->replace.pb->pcHead; // This is the replacement code
2406 /* If the replace pcode is an instruction with an operand, */
2407 /* then duplicate the operand (and expand wild cards in the process). */
2408 if(pcr->type == PC_OPCODE) {
2409 if(PCI(pcr)->pcop) {
2410 /* The replacing instruction has an operand.
2412 if(PCI(pcr)->pcop->type == PO_WILD) {
2413 int index = PCOW(PCI(pcr)->pcop)->id;
2414 //DFPRINTF((stderr,"copying wildopcode\n"));
2415 if(peepBlock->target.wildpCodeOps[index])
2416 pcop = pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2418 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2420 pcop = pic16_pCodeOpCopy(PCI(pcr)->pcop);
2422 //DFPRINTF((stderr,"inserting pCode\n"));
2423 pic16_pCodeInsertAfter(pc, pic16_newpCode(PCI(pcr)->op,pcop));
2424 } else if (pcr->type == PC_WILD) {
2425 if(PCW(pcr)->invertBitSkipInst)
2426 DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2427 pic16_pCodeInsertAfter(pc,
2428 pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2429 PCW(pcr)->invertBitSkipInst));
2430 } else if (pcr->type == PC_COMMENT) {
2431 pic16_pCodeInsertAfter(pc, pic16_newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2437 DFPRINTF((stderr," NEW Code:"));
2438 if(pc) pc->print(stderr,pc);
2443 /* We have just replaced the inefficient code with the rule.
2444 * Now, we need to re-add the C-source symbols if there are any */
2448 pc = pic16_findNextInstruction(pc->next);
2449 PCI(pc)->cline = pc_cline;
2450 pc_cline = PCCS(pc_cline->pc.next);
2457 peeprules = peeprules->next;
2459 DFPRINTF((stderr," no rule matched\n"));