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
32 #include "pcodeflow.h"
35 #if defined(__BORLANDC__) || defined(_MSC_VER)
36 #define STRCASECMP stricmp
38 #define STRCASECMP strcasecmp
41 pCodeOp *pic16_popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
43 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype);
44 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2);
45 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
46 pCode * pic16_findNextInstruction(pCode *pc);
47 int pic16_getpCode(char *mnem,int dest);
48 int pic16_getpCodePeepCommand(char *cmd);
49 void pic16_pBlockMergeLabels(pBlock *pb);
50 char *pic16_pCode2str(char *str, int size, pCode *pc);
51 char *pic16_get_op( pCodeOp *pcop,char *buf,int buf_size);
52 pCodeOp *pic16_popCombine2(pCodeOp *, pCodeOp *, int);
54 extern pCodeInstruction *pic16Mnemonics[];
55 static int parsing_peeps=1;
57 #define IS_PCCOMMENT(x) ( x && (x->type==PC_COMMENT))
59 /****************************************************************/
61 * rootRules - defined in SDCCpeep.c
62 * This is a pointer to the (parsed) peephole rules that are
63 * defined in peep.def.
66 //extern peepRule *rootRules;
71 /****************************************************************/
72 /****************************************************************/
80 typedef struct pCodePeepSnippets
87 /****************************************************************/
91 /****************************************************************/
93 static pCodePeepSnippets *peepSnippets=NULL;
95 /****************************************************************/
99 /****************************************************************/
101 //static pCodePeep *curPeep=NULL;
103 /****************************************************************/
107 /****************************************************************/
109 //static pBlock *curBlock=NULL;
112 /****************************************************************/
114 /* max wild cards in a peep rule */
116 /****************************************************************/
118 //static int sMaxWildVar = 0;
119 //static int sMaxWildMnem = 0;
122 typedef struct pCodeToken
124 int tt; // token type;
133 pCodeToken tokArr[50];
134 static unsigned tokIdx=0;
152 typedef struct parsedPattern {
153 struct pcPattern *pcp;
157 #define MAX_PARSEDPATARR 50
158 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
159 //static unsigned int parsedPatIdx=0;
172 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
173 static char pcpat_number[] = {PCT_NUMBER, 0};
174 static char pcpat_string[] = {PCT_STRING, 0};
175 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
176 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
177 static char pcpat_comma[] = {PCT_COMMA, 0};
178 static char pcpat_comment[] = {PCT_COMMENT, 0};
181 typedef struct pcPattern {
182 char pt; // Pattern type
183 char *tokens; // list of tokens that describe the pattern
184 void * (*f) (void *,pCodeWildBlock *);
187 static pcPattern pcpArr[] = {
188 {PCP_LABEL, pcpat_label, NULL},
189 {PCP_WILDSTR, pcpat_wildString, NULL},
190 {PCP_STR, pcpat_string, NULL},
191 {PCP_WILDVAR, pcpat_wildVar, NULL},
192 {PCP_COMMA, pcpat_comma, NULL},
193 {PCP_COMMENT, pcpat_comment, NULL},
194 {PCP_NUMBER, pcpat_number, NULL}
197 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
199 // Assembly Line Token
216 static char alt_comment[] = { PCP_COMMENT, 0};
217 static char alt_label[] = { PCP_LABEL, 0};
218 static char alt_mnem0[] = { PCP_STR, 0};
219 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
220 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
221 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
222 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
223 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
224 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
225 static char alt_mnem2b[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_WILDVAR, 0};
226 static char alt_mnem3[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_NUMBER, 0};
227 static char alt_mnem4[] = { PCP_STR, PCP_NUMBER, PCP_COMMA, PCP_STR, 0}; // for lfsr 0 , name
228 static char alt_mnem4a[] = { PCP_STR, PCP_NUMBER, PCP_COMMA, PCP_NUMBER, 0}; // for lfsr 0 , value
230 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
231 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
232 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb);
233 static void * cvt_altpat_mnem0a(void *pp,pCodeWildBlock *pcwb);
234 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb);
235 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb);
236 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb);
237 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb);
238 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb);
239 static void * cvt_altpat_mnem2b(void *pp, pCodeWildBlock *pcwb);
240 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb);
241 static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb);
242 static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb);
244 /* NOTE: Order is important in the following table */
245 static pcPattern altArr[] = {
246 {ALT_LABEL, alt_label, cvt_altpat_label},
247 {ALT_COMMENT, alt_comment,cvt_altpat_comment},
248 {ALT_MNEM4a, alt_mnem4a, cvt_altpat_mnem4a},
249 {ALT_MNEM4, alt_mnem4, cvt_altpat_mnem4},
250 {ALT_MNEM3, alt_mnem3, cvt_altpat_mnem3},
251 {ALT_MNEM2B, alt_mnem2b, cvt_altpat_mnem2b},
252 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
253 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
254 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
255 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
256 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
257 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
258 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
262 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
264 // forward declarations
265 static void * DLL_append(_DLL *list, _DLL *next);
267 /*-----------------------------------------------------------------*/
268 /* cvt_extract_destination - helper function extracts the register */
269 /* destination from a parsedPattern. */
271 /*-----------------------------------------------------------------*/
272 static int cvt_extract_destination(parsedPattern *pp)
275 if(pp->pct[0].tt == PCT_STRING) {
277 // just check first letter for now
279 if(toupper(*pp->pct[0].tok.s) == 'F')
282 } else if (pp->pct[0].tt == PCT_NUMBER) {
292 /*-----------------------------------------------------------------*/
293 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
294 /* if *reg is the "status" register and *bit is one of the */
295 /* status bits, then this function will create a new pCode op */
296 /* containing the status register. */
297 /*-----------------------------------------------------------------*/
299 static pCodeOp *cvt_extract_status(char *reg, char *bit)
303 if(STRCASECMP(reg, pic16_pc_status.pcop.name))
310 if(toupper(*bit) == 'C')
311 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_C_BIT));
312 if(toupper(*bit) == 'Z')
313 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_Z_BIT));
317 if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
318 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_DC_BIT));
324 /*-----------------------------------------------------------------*/
325 /* cvt_altpat_label - convert assembly line type to a pCode label */
326 /* INPUT: pointer to the parsedPattern */
330 /* label pattern => '%' number ':' */
331 /* at this point, we wish to extract only the 'number' */
333 /*-----------------------------------------------------------------*/
334 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb)
336 parsedPattern *p = pp;
338 DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
339 return pic16_newpCodeLabel(NULL,-p->pct[1].tok.n);
343 /*-----------------------------------------------------------------*/
344 /* cvt_altpat_comment - convert assembly line type to a comment */
345 /* INPUT: pointer to the parsedPattern */
347 /* pp[0] - comment */
350 /*-----------------------------------------------------------------*/
351 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb)
353 parsedPattern *p = pp;
355 DFPRINTF((stderr,"altpat_comment = %s\n",p->pct[0].tok.s));
356 return pic16_newpCodeCharP(p->pct[0].tok.s);
360 /*-----------------------------------------------------------------*/
361 /* cvt_altpat_mem0 - convert assembly line type to a wild pCode */
366 /*-----------------------------------------------------------------*/
367 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb)
369 parsedPattern *p = pp;
372 pCodeInstruction *pci=NULL;
374 DFPRINTF((stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s));
376 opcode = pic16_getpCode(p->pct[0].tok.s,0);
379 /* look for special command strings like _NOTBITSKIP_ */
381 //fprintf(stderr, "Bad mnemonic\n");
383 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
385 // fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
389 pci = PCI(pic16_newpCode(opcode, NULL));
392 fprintf(stderr,"couldn't find mnemonic\n");
398 /*-----------------------------------------------------------------*/
399 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
402 /* pp[0] - wild var */
404 /*-----------------------------------------------------------------*/
405 static void * cvt_altpat_mnem0a(void *pp, pCodeWildBlock *pcwb)
407 parsedPattern *p = pp;
409 DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n));
411 /* Save the index of the maximum wildcard mnemonic */
413 //if(p[0].pct[1].tok.n > sMaxWildVar)
414 // sMaxWildMnem = p[0].pct[1].tok.n;
416 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
417 pcwb->nwildpCodes = p[0].pct[1].tok.n;
419 return pic16_newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
423 /*-----------------------------------------------------------------*/
424 /* cvt_altpat_mem1 - convert assembly line type to a pCode */
425 /* instruction with 1 operand. */
428 /* pp[1] - Operand */
430 /*-----------------------------------------------------------------*/
431 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb)
434 parsedPattern *p = pp;
437 pCodeInstruction *pci=NULL;
440 DFPRINTF((stderr,"altpat_mnem1 %s var %s\n", p->pct[0].tok.s,p[1].pct[0].tok.s));
442 opcode = pic16_getpCode(p->pct[0].tok.s,0);
444 //fprintf(stderr, "Bad mnemonic\n");
445 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
447 //fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
452 if(pic16Mnemonics[opcode]->isBitInst)
453 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
455 // fprintf(stderr, "%s:%d tok.s= %s\n", __FILE__, __LINE__, p[1].pct[0].tok.s);
456 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_STR); //GPR_REGISTER);
460 pci = PCI(pic16_newpCode(opcode, pcosubtype));
463 fprintf(stderr,"couldn't find mnemonic\n");
469 /*-----------------------------------------------------------------*/
470 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
471 /* instruction with 1 wild operand. */
474 /* pp[1] - wild var */
476 /*-----------------------------------------------------------------*/
477 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb)
479 parsedPattern *p = pp;
482 pCodeInstruction *pci=NULL;
485 DFPRINTF((stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n));
487 opcode = pic16_getpCode(p->pct[0].tok.s,0);
489 int cmd_id = pic16_getpCodePeepCommand(p->pct[0].tok.s);
493 fprintf(stderr, "Bad mnemonic\n");
497 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
498 pcwb->nwildpCodes = p[0].pct[1].tok.n;
500 pc = pic16_newpCodeWild(p[1].pct[1].tok.n,NULL,NULL);
504 PCW(pc)->mustNotBeBitSkipInst = 1;
507 PCW(pc)->mustBeBitSkipInst = 1;
510 PCW(pc)->invertBitSkipInst = 1;
515 if(pic16Mnemonics[opcode]->isBitInst)
516 pcosubtype = pic16_newpCodeOpBit(NULL,-1,0);
518 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
521 pci = PCI(pic16_newpCode(opcode,
522 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
524 /* Save the index of the maximum wildcard variable */
525 //if(p[1].pct[1].tok.n > sMaxWildVar)
526 // sMaxWildVar = p[1].pct[1].tok.n;
528 if(p[1].pct[1].tok.n > pcwb->nvars)
529 pcwb->nvars = p[1].pct[1].tok.n;
532 fprintf(stderr,"couldn't find mnemonic\n");
538 /*-----------------------------------------------------------------*/
539 /*-----------------------------------------------------------------*/
540 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb)
542 parsedPattern *p = pp;
545 pCodeInstruction *pci=NULL;
547 DFPRINTF((stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n));
549 opcode = pic16_getpCode(p->pct[0].tok.s,0);
551 fprintf(stderr, "Bad mnemonic\n");
555 pci = PCI(pic16_newpCode(opcode, pic16_newpCodeOpLit(p[1].pct[0].tok.n) ));
558 fprintf(stderr,"couldn't find mnemonic\n");
564 /*-----------------------------------------------------------------*/
565 /* cvt_altpat_mnem2 */
570 /* pp[3] - destination */
571 /*-----------------------------------------------------------------*/
572 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
574 parsedPattern *p = pp;
578 pCodeInstruction *pci=NULL;
581 dest = cvt_extract_destination(&p[3]);
583 DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
589 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
591 fprintf(stderr, "Bad mnemonic\n");
595 if(pic16Mnemonics[opcode]->isBitInst) {
596 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
597 if(pcosubtype == NULL) {
598 fprintf(stderr, "bad operand?\n");
603 if(pic16Mnemonics[opcode]->is2MemOp) {
604 /* support for movff instruction */
605 pcosubtype = pic16_popCombine2(
606 pic16_newpCodeOp(p[1].pct[0].tok.s, PO_GPR_REGISTER),
607 pic16_newpCodeOp(p[3].pct[0].tok.s, PO_GPR_REGISTER), 0);
609 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
613 pci = PCI(pic16_newpCode(opcode,pcosubtype));
616 fprintf(stderr,"couldn't find mnemonic\n");
622 /*-----------------------------------------------------------------*/
623 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
624 /* instruction with 1 wild operand and a */
625 /* destination operand (e.g. w or f) */
628 /* pp[1] - wild var */
630 /* pp[3] - destination */
632 /*-----------------------------------------------------------------*/
633 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
635 parsedPattern *p = pp;
639 pCodeInstruction *pci=NULL;
640 pCodeOp *pcosubtype, *pcosubtype2;
643 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
647 dest = cvt_extract_destination(&p[3]);
649 DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
656 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
658 fprintf(stderr, "Bad mnemonic\n");
662 if(pic16Mnemonics[opcode]->isBitInst) {
663 pcosubtype = pic16_newpCodeOp(NULL,PO_BIT);
666 if(pic16Mnemonics[opcode]->is2MemOp) {
668 /* support for movff instruction */
669 pcosubtype = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
670 pcosubtype2 = pic16_newpCodeOp(p[3].pct[0].tok.s, PO_GPR_REGISTER);
672 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER); pcosubtype2 = NULL; }
676 pci = PCI(pic16_newpCode(opcode,
677 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
679 pci = PCI(pic16_newpCode(opcode,
680 pic16_newpCodeOpWild2(p[1].pct[1].tok.n, p[3].pct[1].tok.n, pcwb, pcosubtype, pcosubtype2)));
682 /* Save the index of the maximum wildcard variable */
683 //if(p[1].pct[1].tok.n > sMaxWildVar)
684 // sMaxWildVar = p[1].pct[1].tok.n;
686 if(p[1].pct[1].tok.n > pcwb->nvars)
687 pcwb->nvars = p[1].pct[1].tok.n;
690 fprintf(stderr,"couldn't find mnemonic\n");
697 /*-----------------------------------------------------------------*/
698 /* cvt_altpat_mem2b - convert assembly line type to a pCode */
699 /* instruction with 2 wild operands */
702 /* pp[1] - wild var */
704 /* pp[3] - wild var */
706 /*-----------------------------------------------------------------*/
707 static void * cvt_altpat_mnem2b(void *pp,pCodeWildBlock *pcwb)
709 parsedPattern *p = pp;
713 pCodeInstruction *pci=NULL;
714 pCodeOp *pcosubtype, *pcosubtype2;
717 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
721 dest = cvt_extract_destination(&p[3]);
723 DFPRINTF((stderr,"altpat_mnem2b %s src %d dst (%d)\n",
729 fprintf(stderr,"altpat_mnem2b %s src: %d dst: %d\n",
735 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
737 fprintf(stderr, "Bad mnemonic\n");
741 if(pic16Mnemonics[opcode]->is2MemOp) {
742 /* support for movff instruction */
743 pcosubtype = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
744 pcosubtype2 = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
745 } else pcosubtype = pcosubtype2 = NULL;
747 pci = PCI(pic16_newpCode(opcode,
748 pic16_newpCodeOpWild2(p[1].pct[1].tok.n, p[3].pct[1].tok.n,
749 pcwb, pcosubtype, pcosubtype2)));
751 /* Save the index of the maximum wildcard variable */
752 //if(p[1].pct[1].tok.n > sMaxWildVar)
753 // sMaxWildVar = p[1].pct[1].tok.n;
755 if(p[1].pct[1].tok.n > pcwb->nvars)
756 pcwb->nvars = p[1].pct[1].tok.n;
759 fprintf(stderr,"couldn't find mnemonic\n");
767 /*-----------------------------------------------------------------*/
768 /* cvt_altpat_mem3 - convert assembly line type to a pCode */
769 /* This rule is for bsf/bcf type instructions */
773 /* pp[1] - register */
777 /*-----------------------------------------------------------------*/
778 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
780 parsedPattern *p = pp;
782 int dest; // or could be bit position in the register
784 pCodeInstruction *pci=NULL;
785 pCodeOp *pcosubtype=NULL;
787 dest = cvt_extract_destination(&p[3]);
789 DFPRINTF((stderr,"altpat_mnem3 %s var %s bit (%d)\n",
795 opcode = pic16_getpCode(p->pct[0].tok.s,0);
797 fprintf(stderr, "Bad mnemonic\n");
802 if(pic16Mnemonics[opcode]->isBitInst) {
803 //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
805 //if(pcosubtype == NULL) {
806 pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0);
809 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
811 if(pcosubtype == NULL) {
812 fprintf(stderr, "Bad operand\n");
816 pci = PCI(pic16_newpCode(opcode, pcosubtype));
819 fprintf(stderr,"couldn't find mnemonic\n");
825 /*-----------------------------------------------------------------*/
826 /* cvt_altpat_mem4 - convert assembly line type to a pCode */
827 /* This rule is for lfsr instruction */
835 /*-----------------------------------------------------------------*/
836 static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb)
838 parsedPattern *p = pp;
840 int dest; // or could be bit position in the register
842 pCodeInstruction *pci=NULL;
843 pCodeOp *pcosubtype=NULL;
845 dest = cvt_extract_destination(&p[3]);
847 DFPRINTF((stderr,"altpat_mnem4 %s fsr %d source %s\n",
852 opcode = pic16_getpCode(p->pct[0].tok.s,0);
854 fprintf(stderr, "Bad mnemonic\n");
857 DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
859 if(pic16Mnemonics[opcode]->is2LitOp) {
860 pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOp(p[3].pct[0].tok.s, PO_STR));
863 if(pcosubtype == NULL) {
864 fprintf(stderr, "Bad operand\n");
868 pci = PCI(pic16_newpCode(opcode, pcosubtype));
871 fprintf(stderr,"couldn't find mnemonic\n");
877 /*-----------------------------------------------------------------*/
878 /* cvt_altpat_mem4a - convert assembly line type to a pCode */
879 /* This rule is for lfsr instruction */
887 /*-----------------------------------------------------------------*/
888 static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb)
890 parsedPattern *p = pp;
892 int dest; // or could be bit position in the register
894 pCodeInstruction *pci=NULL;
895 pCodeOp *pcosubtype=NULL;
897 dest = cvt_extract_destination(&p[3]);
899 DFPRINTF((stderr,"altpat_mnem4a %s fsr %d value 0x%02x\n",
904 opcode = pic16_getpCode(p->pct[0].tok.s,0);
906 fprintf(stderr, "Bad mnemonic\n");
909 DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
911 if(pic16Mnemonics[opcode]->is2LitOp) {
912 pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOpLit(p[3].pct[0].tok.n));
915 if(pcosubtype == NULL) {
916 fprintf(stderr, "Bad operand\n");
920 pci = PCI(pic16_newpCode(opcode, pcosubtype));
923 fprintf(stderr,"couldn't find mnemonic\n");
929 /*-----------------------------------------------------------------*/
930 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
931 /* by SDCCpeeph.c into a string of tokens. */
934 /* The tokenizer is of the classic type. When an item is encounterd*/
935 /* it is converted into a token. The token is a structure that */
936 /* encodes the item's type and it's value (when appropriate). */
938 /* Accepted token types: */
939 /* SPACE NUMBER STRING % : , ; */
943 /*-----------------------------------------------------------------*/
946 static void tokenizeLineNode(char *ln)
949 tokIdx = 0; // Starting off at the beginning
950 tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
955 // fprintf(stderr, "%s:%d: processing %s\n", __FILE__, __LINE__, ln);
959 // add a SPACE token and eat the extra spaces.
960 tokArr[tokIdx++].tt = PCT_SPACE;
961 while (isspace (*ln))
968 tokArr[tokIdx].tt = PCT_NUMBER;
969 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
977 tokArr[tokIdx++].tt = PCT_PERCENT;
980 tokArr[tokIdx++].tt = PCT_LESSTHAN;
983 tokArr[tokIdx++].tt = PCT_GREATERTHAN;
986 tokArr[tokIdx++].tt = PCT_COLON;
989 tokArr[tokIdx].tok.s = Safe_strdup(ln);
990 tokArr[tokIdx++].tt = PCT_COMMENT;
991 tokArr[tokIdx].tt = PCT_NULL;
994 tokArr[tokIdx++].tt = PCT_COMMA;
998 default: // hack to allow : goto $
999 if(isalpha(*ln) || (*ln == '_') || (!parsing_peeps && (*ln == '$'))) {
1003 while( (isalpha(*ln) || isdigit(*ln) || (*ln == '_') || (*ln == '$')) && i<49)
1004 buffer[i++] = *ln++;
1009 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
1010 tokArr[tokIdx++].tt = PCT_STRING;
1014 fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
1015 fprintf(stderr, "Line: %s\n",lnstart);
1016 fprintf(stderr, "Token: '%c'\n",*ln);
1022 /* Advance to next character in input string .
1023 * Note, if none of the tests passed above, then
1024 * we effectively ignore the `bad' character.
1025 * Since the line has already been parsed by SDCCpeeph,
1026 * chance are that there are no invalid characters... */
1032 tokArr[tokIdx].tt = 0;
1036 /*-----------------------------------------------------------------*/
1037 /*-----------------------------------------------------------------*/
1041 static void dump1Token(pCodeTokens tt)
1046 fprintf(stderr, " space ");
1049 fprintf(stderr, " pct %%");
1052 fprintf(stderr, " pct <");
1054 case PCT_GREATERTHAN:
1055 fprintf(stderr, " pct >");
1058 fprintf(stderr, " col :");
1061 fprintf(stderr, " comma , ");
1064 fprintf(stderr, " comment ");
1065 //fprintf(stderr,"%s",tokArr[i].tok.s);
1068 fprintf(stderr, " str ");
1069 //fprintf(stderr,"%s",tokArr[i].tok.s);
1072 fprintf(stderr, " num ");
1073 //fprintf(stderr,"%d",tokArr[i].tok.n);
1076 fprintf(stderr, " null ");
1083 /*-----------------------------------------------------------------*/
1084 /*-----------------------------------------------------------------*/
1086 static int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
1090 if(!pct || !pat || !*pat)
1093 //DFPRINTF((stderr,"comparing against:\n"));
1095 while(i < max_tokens) {
1098 //DFPRINTF((stderr,"matched\n"));
1102 // dump1Token(*pat); fputc('\n', stderr); DFPRINTF((stderr,"\n"));
1116 /*-----------------------------------------------------------------*/
1117 /*-----------------------------------------------------------------*/
1119 static int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
1123 if(!pct || !pat || !*pct)
1127 while(i < max_tokens) {
1130 DFPRINTF((stderr,"matched\n"));
1134 // dump1Token(*pat); DFPRINTF((stderr,"\n"));
1136 if( !pat || !pat->pcp )
1139 if (pat->pcp->pt != *pct)
1142 DFPRINTF((stderr," pct=%d\n",*pct));
1151 /*-----------------------------------------------------------------*/
1152 /*-----------------------------------------------------------------*/
1154 static int advTokIdx(int *v, int amt)
1157 if((unsigned) (*v + amt) > tokIdx)
1165 /*-----------------------------------------------------------------*/
1166 /* parseTokens - convert the tokens corresponding to a single line */
1167 /* of a peep hole assembly into a pCode object. */
1172 /* This is a simple parser that looks for strings of the type */
1173 /* allowed in the peep hole definition file. Essentially the format*/
1174 /* is the same as a line of assembly: */
1176 /* label: mnemonic op1, op2, op3 ; comment */
1178 /* Some of these items aren't present. It's the job of the parser */
1179 /* to determine which are and convert those into the appropriate */
1181 /*-----------------------------------------------------------------*/
1183 static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
1194 for(i=0; i<=tokIdx; i++)
1195 dump1Token(tokArr[i].tt);
1201 int lparsedPatIdx=0;
1208 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
1209 char * cP1stop = NULL;
1210 char * cP2ndop = NULL;
1212 //pCodeOp *pcl = NULL; // Storage for a label
1213 //pCodeOp *pco1 = NULL; // 1st operand
1214 //pCodeOp *pco2 = NULL; // 2nd operand
1215 //pCode *pc = NULL; // Mnemonic
1226 ParseStates state = PS_START;
1233 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
1234 && (advTokIdx(<okIdx, 1)) ) // eat space
1238 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
1241 switch(pcpArr[lpcpIdx].pt) {
1243 if(state == PS_START){
1244 DFPRINTF((stderr," label\n"));
1245 state = PS_HAVE_LABEL;
1247 DFPRINTF((stderr," bad state (%d) for label\n",state));
1251 DFPRINTF((stderr," %s is",tokArr[ltokIdx].tok.s));
1255 DFPRINTF((stderr," mnem\n"));
1256 cPmnem = tokArr[ltokIdx].tok.s;
1257 state = PS_HAVE_MNEM;
1260 DFPRINTF((stderr," 1st operand\n"));
1261 cP1stop = tokArr[ltokIdx].tok.s;
1262 //pco1 = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
1263 state = PS_HAVE_1OPERAND;
1265 case PS_HAVE_1OPERAND:
1266 DFPRINTF((stderr," error expecting comma\n"));
1269 DFPRINTF((stderr," 2 operands\n"));
1270 cP2ndop = tokArr[ltokIdx].tok.s;
1272 case PS_HAVE_2OPERANDS:
1281 DFPRINTF((stderr," wild mnem\n"));
1282 state = PS_HAVE_MNEM;
1285 DFPRINTF((stderr," 1st operand is wild\n"));
1286 state = PS_HAVE_1OPERAND;
1288 case PS_HAVE_1OPERAND:
1289 DFPRINTF((stderr," error expecting comma\n"));
1292 DFPRINTF((stderr," 2nd operand is wild\n"));
1294 case PS_HAVE_2OPERANDS:
1303 fprintf(stderr," ERROR number\n");
1306 DFPRINTF((stderr," 1st operand is a number\n"));
1307 state = PS_HAVE_1OPERAND;
1309 case PS_HAVE_1OPERAND:
1310 fprintf(stderr," error expecting comma\n");
1313 DFPRINTF((stderr," 2nd operand is a number\n"));
1315 case PS_HAVE_2OPERANDS:
1323 if(state == PS_HAVE_1OPERAND){
1324 DFPRINTF((stderr," got a comma\n"));
1325 state = PS_HAVE_COMMA;
1327 fprintf(stderr," unexpected comma\n");
1333 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1334 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1337 // dump1Token(tokArr[ltokIdx].tt);
1339 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1340 DFPRINTF((stderr," reached end \n"));
1347 } while ((++lpcpIdx < PCPATTERNS) && !matching);
1351 parsedPatArr[lparsedPatIdx].pcp = NULL;
1352 parsedPatArr[lparsedPatIdx].pct = NULL;
1358 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1361 pc = altArr[k].f(&parsedPatArr[j],pcwb);
1362 //if(pc && pc->print)
1363 // pc->print(stderr,pc);
1364 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1366 //if(curBlock && pc)
1367 //pic16_addpCode2pBlock(curBlock, pc);
1371 return 0; // Only accept one line for now.
1373 pic16_addpCode2pBlock(pcwb->pb, pc);
1381 while(j<=lparsedPatIdx && k<ALTPATTERNS);
1384 DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1388 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1389 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1390 DFPRINTF((stderr," %d",parsedPatArr[j].pcp->pt));
1393 while(j<lparsedPatIdx);
1395 DFPRINTF((stderr,"\n"));
1402 /*-----------------------------------------------------------------*/
1404 /*-----------------------------------------------------------------*/
1405 static void peepRuleBlock2pCodeBlock( lineNode *ln, pCodeWildBlock *pcwb)
1411 for( ; ln; ln = ln->next) {
1413 //DFPRINTF((stderr,"%s\n",ln->line));
1414 // fprintf(stderr, "peep rule : %s\n", ln->line);
1416 tokenizeLineNode(ln->line);
1418 if(parseTokens(pcwb,NULL)) {
1420 fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
1421 fprintf(stderr,"Tokens:\n");
1423 dump1Token(tokArr[i].tt);
1430 /*-----------------------------------------------------------------*/
1431 /* pic16_AssembleLine - parse line and return the pCode equivalent */
1432 /* peeps=1 if parsing peep rules, 0 otherwise */
1433 /*-----------------------------------------------------------------*/
1434 pCode *pic16_AssembleLine(char *line, int peeps)
1438 if(!line || !*line) {
1439 fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
1443 parsing_peeps = peeps;
1445 tokenizeLineNode(line);
1447 if(parseTokens(NULL,&pc))
1448 fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
1450 DFPRINTF((stderr, "pc= %p\n", pc));
1451 // if(pc)pc->print(stderr, pc);
1459 /*-----------------------------------------------------------------*/
1460 /* peepRuleCondition */
1461 /*-----------------------------------------------------------------*/
1462 static void peepRuleCondition(char *cond, pCodePeep *pcp)
1467 //DFPRINTF((stderr,"\nCondition: %s\n",cond));
1468 /* brute force compares for now */
1470 if(STRCASECMP(cond, "NZ") == 0) {
1471 //DFPRINTF((stderr,"found NZ\n"));
1472 pcp->postFalseCond = PCC_Z;
1479 static void initpCodeWildBlock(pCodeWildBlock *pcwb)
1482 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1488 pcwb->wildpCodes = NULL;
1489 pcwb->wildpCodeOps = NULL;
1492 pcwb->nwildpCodes = 0;
1497 static void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1504 pcwb->nops = pcwb->nvars;
1506 pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1507 pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1509 pcwb->nwildpCodes+=2;
1510 pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1514 static void initpCodePeep(pCodePeep *pcp)
1517 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1522 initpCodeWildBlock(&pcp->target);
1523 pcp->target.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1525 initpCodeWildBlock(&pcp->replace);
1526 pcp->replace.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1530 /*-----------------------------------------------------------------*/
1531 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1534 /* SDCCpeeph parses the peep rules file and extracts variables, */
1535 /* removes white space, and checks the syntax. This function */
1536 /* extends that processing to produce pCode objects. You can kind */
1537 /* think of this function as an "assembler", though instead of */
1538 /* taking raw text to produce machine code, it produces pCode. */
1540 /*-----------------------------------------------------------------*/
1541 extern void pic16initpCodePeepCommands(void);
1543 void pic16_peepRules2pCode(peepRule *rules)
1547 pCodePeep *currentRule;
1548 pCodePeepSnippets *pcps;
1550 pic16initpCodePeepCommands();
1552 /* The rules are in a linked-list. Each rule has two portions */
1553 /* There's the `target' and there's the `replace'. The target */
1554 /* is compared against the SDCC generated code and if it */
1555 /* matches, it gets replaced by the `replace' block of code. */
1557 /* Here we loop through each rule and convert the target's and*/
1558 /* replace's into pCode target and replace blocks */
1560 for (pr = rules; pr; pr = pr->next) {
1562 //DFPRINTF((stderr,"\nRule:\n\n"));
1564 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1565 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1567 currentRule = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1568 initpCodePeep(currentRule);
1570 /* Convert the target block */
1571 peepRuleBlock2pCodeBlock(pr->match, ¤tRule->target);
1573 //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1574 // pic16_printpBlock(stderr, currentRule->target.pb);
1576 //DFPRINTF((stderr,"target with labels merged:\n"));
1577 //pic16_pBlockMergeLabels(curBlock);
1578 pic16_pBlockMergeLabels(currentRule->target.pb);
1579 //pic16_printpBlock(stderr, currentRule->replace.pb);
1581 //#ifdef PCODE_DEBUG
1582 // pic16_printpBlock(stderr, curBlock);
1584 //DFPRINTF((stderr,"\nReplaced by:\n"));
1587 /* Convert the replace block */
1588 peepRuleBlock2pCodeBlock(pr->replace, ¤tRule->replace);
1590 //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1591 //pic16_printpBlock(stderr, curBlock);
1593 //DFPRINTF((stderr,"replace with labels merged:\n"));
1595 pic16_pBlockMergeLabels(currentRule->replace.pb);
1596 //pic16_printpBlock(stderr, currentRule->replace.pb);
1598 peepRuleCondition(pr->cond,currentRule);
1600 /* The rule has been converted to pCode. Now allocate
1601 * space for the wildcards */
1603 postinit_pCodeWildBlock(¤tRule->target);
1604 postinit_pCodeWildBlock(¤tRule->replace);
1606 //return; // debug ... don't want to go through all the rules yet
1610 pCodePeep *peepBlock;
1613 peeprules = (_DLL *)peepSnippets;
1614 //fprintf(stderr,"target rules\n");
1616 //fprintf(stderr," rule:\n");
1617 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1618 //pic16_printpBlock(stderr, peepBlock->target.pb);
1619 peeprules = peeprules->next;
1621 //fprintf(stderr," ... done\n");
1626 static void printpCodeString(FILE *of, pCode *pc, int max)
1630 while(pc && (i++<max)) {
1636 /*-----------------------------------------------------------------*/
1637 /* _DLL * DLL_append */
1639 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1640 /* If The list to which we want to append is non-existant then one */
1641 /* is created. Other wise, the end of the list is sought out and */
1642 /* a new DLL object is appended to it. In either case, the void */
1643 /* *data is added to the newly created DLL object. */
1644 /*-----------------------------------------------------------------*/
1646 static void * DLL_append(_DLL *list, _DLL *next)
1651 /* If there's no list, then create one: */
1653 next->next = next->prev = NULL;
1658 /* Search for the end of the list. */
1663 /* Now append the new DLL object */
1674 /*-----------------------------------------------------------------
1676 pCode peephole optimization
1679 The pCode "peep hole" optimization is not too unlike the peep hole
1680 optimization in SDCCpeeph.c. The major difference is that here we
1681 use pCode's whereas there we use ASCII strings. The advantage with
1682 pCode's is that we can ascertain flow information in the instructions
1686 <FIX ME> - elaborate...
1688 -----------------------------------------------------------------*/
1692 /*-----------------------------------------------------------------*/
1693 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1695 /* return conditions */
1696 /* 1 - The Condition was found for a pCode's input */
1697 /* 0 - No matching condition was found for the whole chain */
1698 /* -1 - The Condition was found for a pCode's output */
1700 /*-----------------------------------------------------------------*/
1701 int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond)
1703 //fprintf(stderr,"Checking conditions %d\n",cond);
1706 /* If we reach a function end (presumably an end since we most
1707 probably began the search in the middle of a function), then
1708 the condition was not found. */
1709 if(pc->type == PC_FUNCTION)
1712 if(pc->type == PC_OPCODE) {
1713 //fprintf(stderr," checking conditions of: ");
1714 //pc->print(stderr,pc);
1715 //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
1716 if(PCI(pc)->inCond & cond)
1718 if(PCI(pc)->outCond & cond)
1728 /*-----------------------------------------------------------------
1729 * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1731 * Compare two pCodeOp's and return 1 if they're the same
1732 *-----------------------------------------------------------------*/
1733 static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1737 if(!pcops || !pcopd)
1741 fprintf(stderr," Comparing operands %s",
1742 pic16_get_op( pcops,NULL,0));
1744 fprintf(stderr," to %s\n",
1745 pic16_get_op( pcopd,NULL,0));
1748 if(pcops->type != pcopd->type) {
1749 //fprintf(stderr," - fail - diff types\n");
1750 return 0; // different types
1753 if(pcops->type == PO_LITERAL) {
1755 if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
1762 pic16_get_op(pcops,b,50);
1764 n2 = pic16_get_op(pcopd,NULL,0);
1766 if( !n2 || strcmp(b,n2)) {
1767 //fprintf(stderr," - fail - diff names: %s, len=%d, %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1768 return 0; // different names
1771 switch(pcops->type) {
1773 if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1774 //fprintf(stderr, " - fail different instances\n");
1782 //fprintf(stderr," - pass\n");
1787 static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1791 /* Check for a label associated with this wild pCode */
1792 // If the wild card has a label, make sure the source code does too.
1793 if(PCI(pcd)->label) {
1794 pCode *pcl = PCI(pcd)->label->pc;
1797 int li = -PCL(pcl)->key;
1799 if(peepBlock->target.vars[li] == NULL) {
1800 if(PCI(pcs)->label) {
1801 DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1804 // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1805 DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1806 if(PCI(pcs)->label) {
1807 DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1813 if(!PCI(pcs)->label)
1816 labindex = -PCL(pcl)->key;
1817 if(peepBlock->target.vars[labindex] == NULL) {
1818 // First time to encounter this label
1819 peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1820 DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1823 if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1824 DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1827 DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1830 //DFPRINTF((stderr,"destination doesn't have a label\n"));
1835 //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1843 /*-----------------------------------------------------------------*/
1844 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1845 /* see they're the same. */
1847 /* In this context, "source" refers to the coded generated by gen.c*/
1848 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1849 /* ination has no wild cards, then MatchLine will compare the two */
1850 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1851 /* has wildcards, then those get expanded. When a wild card is */
1852 /* encountered for the first time it autmatically is considered a */
1853 /* match and the object that matches it is referenced in the */
1854 /* variables or opcodes array (depending on the type of match). */
1858 /* *peepBlock - A pointer to the peepBlock that contains the */
1859 /* entire rule to which the destination pcode belongs*/
1860 /* *pcs - a pointer to the source pcode */
1861 /* *pcd - a pointer to the destination pcode */
1864 /* 1 - pcodes match */
1865 /* 0 - pcodes don't match */
1868 /*-----------------------------------------------------------------*/
1870 static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1872 int index; // index into wild card arrays
1875 /* one-for-one match. Here the source and destination opcodes
1876 * are not wild. However, there may be a label or a wild operand */
1879 if(PCI(pcs)->label) {
1880 DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1884 if(pcs->type == pcd->type) {
1886 if(pcs->type == PC_OPCODE) {
1888 /* If the opcodes don't match then the line doesn't match */
1889 if(PCI(pcs)->op != PCI(pcd)->op)
1893 DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1894 pcs->print(stderr,pcs);
1895 pcd->print(stderr,pcd);
1898 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1901 /* Compare the operands */
1902 if(PCI(pcd)->pcop) {
1903 if (PCI(pcd)->pcop->type == PO_WILD) {
1904 index = PCOW(PCI(pcd)->pcop)->id;
1905 //DFPRINTF((stderr,"destination is wild\n"));
1906 #ifdef DEBUG_PCODEPEEP
1907 if (index > peepBlock->nops) {
1908 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1913 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1914 if(!peepBlock->target.wildpCodeOps[index]) {
1915 peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1917 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1921 pcs->print(stderr,pcs);
1922 pcd->print(stderr,pcd);
1924 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1925 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1929 havematch = pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1930 // return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1933 if(!havematch && PCI(pcs)->pcop) {
1936 switch(PCI(pcs)->pcop->type) {
1940 n = PCOR(PCI(pcs)->pcop)->r->name;
1944 n = PCI(pcs)->pcop->name;
1947 if(peepBlock->target.vars[index])
1948 return (strcmp(peepBlock->target.vars[index],n) == 0);
1950 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1951 peepBlock->target.vars[index] = n;
1957 /* now check whether the second operand matches */
1958 if(PCI(pcd)->is2MemOp && (PCOR2(PCI(pcd)->pcop)->pcop2->type == PO_WILD)) {
1960 fprintf(stderr, "%s:%d %s second operand is wild\n", __FILE__, __LINE__, __FUNCTION__);
1962 index = PCOW(PCI(pcd)->pcop)->id2;
1963 //DFPRINTF((stderr,"destination is wild\n"));
1964 #ifdef DEBUG_PCODEPEEP
1965 if (index > peepBlock->nops) {
1966 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1971 PCOW(PCI(pcd)->pcop)->matched2 = PCOR2(PCI(pcs)->pcop)->pcop2;
1972 if(!peepBlock->target.wildpCodeOps[index]) {
1973 peepBlock->target.wildpCodeOps[index] = PCOR2(PCI(pcs)->pcop)->pcop2;
1975 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1979 pcs->print(stderr,pcs);
1980 pcd->print(stderr,pcd);
1982 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1983 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1987 return (havematch && pCodeOpCompare(PCOR2(PCI(pcs)->pcop)->pcop2,
1988 peepBlock->target.wildpCodeOps[index]));
1991 if(PCOR2(PCI(pcs)->pcop)->pcop2) {
1994 switch(PCOR2(PCI(pcs)->pcop)->pcop2->type) {
1998 n = PCOR(PCOR2(PCI(pcs)->pcop)->pcop2)->r->name;
2001 n = PCOR2(PCI(pcs)->pcop)->pcop2->name;
2004 if(peepBlock->target.vars[index])
2005 return (havematch && (strcmp(peepBlock->target.vars[index],n) == 0));
2007 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
2008 peepBlock->target.vars[index] = n;
2009 return (havematch); //&& 1;
2013 } else return (havematch);
2015 else if (PCI(pcd)->pcop->type == PO_LITERAL) {
2016 return (havematch &&
2017 pCodeOpCompare(PCOR2(PCI(pcs)->pcop)->pcop2, PCOR2(PCI(pcd)->pcop)->pcop2);
2022 } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
2023 return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
2028 /* FIXME - need an else to check the case when the destination
2029 * isn't a wild card */
2031 /* The pcd has no operand. Lines match if pcs has no operand either*/
2032 return (PCI(pcs)->pcop == NULL);
2035 /* Compare a wild instruction to a regular one. */
2037 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
2039 index = PCW(pcd)->id;
2041 DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
2042 pcs->print(stderr,pcs);
2043 pcd->print(stderr,pcd);
2045 peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
2047 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
2048 DFPRINTF((stderr," Failing because labels don't match\n"));
2052 if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
2053 // doesn't match because the wild pcode must be a bit skip
2054 DFPRINTF((stderr," Failing match because bit skip is req\n"));
2055 //pcd->print(stderr,pcd);
2056 //pcs->print(stderr,pcs);
2060 if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
2061 // doesn't match because the wild pcode must *not* be a bit skip
2062 DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
2063 //pcd->print(stderr,pcd);
2064 //pcs->print(stderr,pcs);
2068 if(PCW(pcd)->operand) {
2069 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
2070 if(peepBlock->target.vars[index]) {
2071 int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
2075 DFPRINTF((stderr," (matched)\n"));
2077 DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
2078 DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n",
2079 peepBlock->target.vars[index],
2080 PCI(pcs)->pcop->name));
2085 DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
2086 peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
2091 pcs = pic16_findNextInstruction(pcs->next);
2093 //DFPRINTF((stderr," (next to match)\n"));
2094 //pcs->print(stderr,pcs);
2095 } else if(pcd->next) {
2096 /* oops, we ran out of code, but there's more to the rule */
2100 return 1; /* wild card matches */
2106 /*-----------------------------------------------------------------*/
2107 /*-----------------------------------------------------------------*/
2108 static void pCodePeepClrVars(pCodePeep *pcp)
2115 DFPRINTF((stderr," Clearing peep rule vars\n"));
2116 DFPRINTF((stderr," %d %d %d %d %d %d\n",
2117 pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
2118 pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
2120 for(i=0;i<pcp->target.nvars; i++)
2121 pcp->target.vars[i] = NULL;
2122 for(i=0;i<pcp->target.nops; i++)
2123 pcp->target.wildpCodeOps[i] = NULL;
2124 for(i=0;i<pcp->target.nwildpCodes; i++)
2125 pcp->target.wildpCodes[i] = NULL;
2127 for(i=0;i<pcp->replace.nvars; i++)
2128 pcp->replace.vars[i] = NULL;
2129 for(i=0;i<pcp->replace.nops; i++)
2130 pcp->replace.wildpCodeOps[i] = NULL;
2131 for(i=0;i<pcp->replace.nwildpCodes; i++)
2132 pcp->replace.wildpCodes[i] = NULL;
2138 /*-----------------------------------------------------------------*/
2139 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2140 /* into the pCode chain containing pc1 */
2141 /*-----------------------------------------------------------------*/
2142 void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2)
2148 pc2->next = pc1->next;
2150 pc1->next->prev = pc2;
2158 /*-----------------------------------------------------------------*/
2159 /* pic16_pCodeOpCopy - copy a pcode operator */
2160 /*-----------------------------------------------------------------*/
2161 pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
2163 pCodeOp *pcopnew=NULL;
2168 switch(pcop->type) {
2171 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2172 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2173 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2174 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2179 /* Here we expand the wild card into the appropriate type: */
2180 /* By recursively calling pCodeOpCopy */
2181 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2182 if(PCOW(pcop)->matched)
2183 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->matched);
2186 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->subtype);
2187 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2188 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2195 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2196 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2197 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2201 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2202 PCOI(pcopnew)->index = PCOI(pcop)->index;
2203 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2204 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2208 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2209 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2210 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2213 #if 0 // mdubuc - To add
2220 pcopnew = pic16_newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2221 PCOR(pcopnew)->r = PCOR(pcop)->r;
2222 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2223 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2227 case PO_GPR_REGISTER:
2231 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2232 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2233 PCOR(pcopnew)->r = PCOR(pcop)->r;
2234 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2235 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2236 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2240 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2241 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2242 PCOR(pcopnew)->r = PCOR(pcop)->r;
2243 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2244 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2247 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2249 DFPRINTF((stderr,"pCodeOpCopy PO_BSR\n"));
2250 case PO_SFR_REGISTER:
2262 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2263 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2267 pcopnew->type = pcop->type;
2269 pcopnew->name = Safe_strdup(pcop->name);
2271 pcopnew->name = NULL;
2277 /*-----------------------------------------------------------------*/
2278 /* pCodeCopy - copy a pcode */
2279 /*-----------------------------------------------------------------*/
2280 static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2282 pCodeInstruction *new_pci;
2285 new_pci = PCI(pic16_newpCode(pci->inverted_op,pci->pcop));
2287 new_pci = PCI(pic16_newpCode(pci->op,pci->pcop));
2289 new_pci->pc.pb = pci->pc.pb;
2290 new_pci->from = pci->from;
2291 new_pci->to = pci->to;
2292 new_pci->label = pci->label;
2293 new_pci->pcflow = pci->pcflow;
2295 return PCODE(new_pci);
2298 /*-----------------------------------------------------------------*/
2299 /*-----------------------------------------------------------------*/
2300 static void pCodeDeleteChain(pCode *f,pCode *t)
2306 DFPRINTF((stderr,"delete pCode:\n"));
2308 //f->print(stderr,f);
2309 //f->delete(f); this dumps core...
2316 /*-----------------------------------------------------------------*/
2317 /*-----------------------------------------------------------------*/
2318 int pic16_pCodePeepMatchRule(pCode *pc)
2320 pCodePeep *peepBlock;
2322 pCodeCSource *pc_cline=NULL;
2326 peeprules = (_DLL *)peepSnippets;
2329 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
2331 if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
2332 fprintf(stderr, "skipping rule because target pb is NULL\n");
2336 pCodePeepClrVars(peepBlock);
2339 if(IS_PCCOMMENT(pcin))
2340 pc = pcin = pic16_findNextInstruction(pcin->next);
2342 pcin = pc = pic16_findNextInstruction(pc);
2344 pct = peepBlock->target.pb->pcHead;
2347 pCode *pcr = peepBlock->replace.pb->pcHead;
2348 if(pcr) pct->print(stderr,pcr);
2352 while(pct && pcin) {
2354 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
2357 pcin = pic16_findNextInstruction(pcin->next);
2360 //DFPRINTF((stderr," matched\n"));
2363 DFPRINTF((stderr," partial match... no more code\n"));
2364 // fprintf(stderr," partial match... no more code\n");
2368 DFPRINTF((stderr," end of rule\n"));
2372 if(matched && pcin) {
2374 /* So far we matched the rule up to the point of the conditions .
2375 * In other words, all of the opcodes match. Now we need to see
2376 * if the post conditions are satisfied.
2377 * First we check the 'postFalseCond'. This means that we check
2378 * to see if any of the subsequent pCode's in the pCode chain
2379 * following the point just past where we have matched depend on
2380 * the `postFalseCond' as input then we abort the match
2382 DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
2383 //pcin->print(stderr,pcin);
2385 if (pcin && peepBlock->postFalseCond &&
2386 (pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
2389 //fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
2392 //if(!matched) fprintf(stderr,"failed on conditions\n");
2401 /* We matched a rule! Now we have to go through and remove the
2402 inefficient code with the optimized version */
2404 DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
2405 // printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
2406 DFPRINTF((stderr,"first thing matched\n"));
2407 pc->print(stderr,pc);
2409 DFPRINTF((stderr,"last thing matched\n"));
2410 pcin->print(stderr,pcin);
2415 /* Unlink the original code */
2417 pcprev->next = pcin;
2419 pcin->prev = pc->prev;
2425 /* Converted the deleted pCodes into comments */
2428 pCodeCSource *pc_cline2=NULL;
2433 while(pc && pc!=pcin) {
2435 if(pc->type == PC_OPCODE && PCI(pc)->cline) {
2437 pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2438 pc_cline2 = PCCS(pc_cline2->pc.next);
2440 pc_cline = pc_cline2 = PCI(pc)->cline;
2441 pc_cline->pc.seq = pc->seq;
2445 pic16_pCode2str(&buf[2], 254, pc);
2446 pic16_pCodeInsertAfter(pcprev, pic16_newpCodeCharP(buf));
2447 pcprev = pcprev->next;
2452 pc_cline2->pc.next = NULL;
2457 pCodeDeleteChain(pc,pcin);
2459 fprintf(stderr, "%s:%d rule matched\n", __FILE__, __LINE__);
2461 /* Generate the replacement code */
2463 pcr = peepBlock->replace.pb->pcHead; // This is the replacement code
2467 /* If the replace pcode is an instruction with an operand, */
2468 /* then duplicate the operand (and expand wild cards in the process). */
2469 if(pcr->type == PC_OPCODE) {
2470 if(PCI(pcr)->pcop) {
2471 /* The replacing instruction has an operand.
2473 if(PCI(pcr)->pcop->type == PO_WILD) {
2474 int index = PCOW(PCI(pcr)->pcop)->id;
2475 fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
2476 //DFPRINTF((stderr,"copying wildopcode\n"));
2477 if(peepBlock->target.wildpCodeOps[index])
2478 pcop = pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2480 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2482 pcop = pic16_pCodeOpCopy(PCI(pcr)->pcop);
2485 if(PCI(pcr)->is2MemOp && PCOR2(PCI(pcr)->pcop)->pcop2) {
2486 /* The replacing instruction has also a second operand.
2488 fprintf(stderr, "%s:%d pcop2= %p\n", __FILE__, __LINE__, PCOR2(PCI(pcr)->pcop)->pcop2);
2489 if(PCOR2(PCI(pcr)->pcop)->pcop2->type == PO_WILD) {
2490 int index = PCOW(PCI(pcr)->pcop)->id2;
2491 fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
2492 //DFPRINTF((stderr,"copying wildopcode\n"));
2493 if(peepBlock->target.wildpCodeOps[index])
2494 pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
2495 pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]), 0);
2497 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2499 pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
2500 pic16_pCodeOpCopy(PCI(pcr)->pcop), 0);
2504 //DFPRINTF((stderr,"inserting pCode\n"));
2505 pic16_pCodeInsertAfter(pc, pic16_newpCode(PCI(pcr)->op,pcop));
2506 } else if (pcr->type == PC_WILD) {
2507 if(PCW(pcr)->invertBitSkipInst)
2508 DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2509 pic16_pCodeInsertAfter(pc,
2510 pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2511 PCW(pcr)->invertBitSkipInst));
2512 } else if (pcr->type == PC_COMMENT) {
2513 pic16_pCodeInsertAfter(pc, pic16_newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2519 DFPRINTF((stderr," NEW Code:"));
2520 if(pc) pc->print(stderr,pc);
2525 /* We have just replaced the inefficient code with the rule.
2526 * Now, we need to re-add the C-source symbols if there are any */
2530 pc = pic16_findNextInstruction(pc->next);
2531 PCI(pc)->cline = pc_cline;
2532 pc_cline = PCCS(pc_cline->pc.next);
2539 peeprules = peeprules->next;
2541 DFPRINTF((stderr," no rule matched\n"));