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 pCodeOp *pic16_popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
37 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype);
38 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2);
39 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
40 pCode * pic16_findNextInstruction(pCode *pc);
41 int pic16_getpCode(char *mnem,int dest);
42 int pic16_getpCodePeepCommand(char *cmd);
43 void pic16_pBlockMergeLabels(pBlock *pb);
44 char *pic16_pCode2str(char *str, int size, pCode *pc);
45 //char *pic16_get_op(pCodeOp *pcop,char *buf, size_t buf_size);
46 pCodeOp *pic16_popCombine2(pCodeOp *, pCodeOp *, int);
48 extern pCodeInstruction *pic16Mnemonics[];
49 static int parsing_peeps=1;
51 #define IS_PCCOMMENT(x) ( x && (x->type==PC_COMMENT))
53 /****************************************************************/
55 * rootRules - defined in SDCCpeep.c
56 * This is a pointer to the (parsed) peephole rules that are
57 * defined in peep.def.
60 //extern peepRule *rootRules;
65 /****************************************************************/
66 /****************************************************************/
74 typedef struct pCodePeepSnippets
81 /****************************************************************/
85 /****************************************************************/
87 static pCodePeepSnippets *peepSnippets=NULL;
89 /****************************************************************/
93 /****************************************************************/
95 //static pCodePeep *curPeep=NULL;
97 /****************************************************************/
101 /****************************************************************/
103 //static pBlock *curBlock=NULL;
106 /****************************************************************/
108 /* max wild cards in a peep rule */
110 /****************************************************************/
112 //static int sMaxWildVar = 0;
113 //static int sMaxWildMnem = 0;
116 typedef struct pCodeToken
118 int tt; // token type;
127 pCodeToken tokArr[50];
128 static unsigned tokIdx=0;
146 typedef struct parsedPattern {
147 struct pcPattern *pcp;
151 #define MAX_PARSEDPATARR 50
152 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
153 //static unsigned int parsedPatIdx=0;
166 static char pcpat_label[] = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
167 static char pcpat_number[] = {PCT_NUMBER, 0};
168 static char pcpat_string[] = {PCT_STRING, 0};
169 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
170 static char pcpat_wildVar[] = {PCT_PERCENT, PCT_NUMBER, 0};
171 static char pcpat_comma[] = {PCT_COMMA, 0};
172 static char pcpat_comment[] = {PCT_COMMENT, 0};
175 typedef struct pcPattern {
176 char pt; // Pattern type
177 char *tokens; // list of tokens that describe the pattern
178 void * (*f) (void *,pCodeWildBlock *);
181 static pcPattern pcpArr[] = {
182 {PCP_LABEL, pcpat_label, NULL},
183 {PCP_WILDSTR, pcpat_wildString, NULL},
184 {PCP_STR, pcpat_string, NULL},
185 {PCP_WILDVAR, pcpat_wildVar, NULL},
186 {PCP_COMMA, pcpat_comma, NULL},
187 {PCP_COMMENT, pcpat_comment, NULL},
188 {PCP_NUMBER, pcpat_number, NULL}
191 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
193 // Assembly Line Token
210 static char alt_comment[] = { PCP_COMMENT, 0};
211 static char alt_label[] = { PCP_LABEL, 0};
212 static char alt_mnem0[] = { PCP_STR, 0};
213 static char alt_mnem0a[] = { PCP_WILDVAR, 0};
214 static char alt_mnem1[] = { PCP_STR, PCP_STR, 0};
215 static char alt_mnem1a[] = { PCP_STR, PCP_WILDVAR, 0};
216 static char alt_mnem1b[] = { PCP_STR, PCP_NUMBER, 0};
217 static char alt_mnem2[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
218 static char alt_mnem2a[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
219 static char alt_mnem2b[] = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_WILDVAR, 0};
220 static char alt_mnem3[] = { PCP_STR, PCP_STR, PCP_COMMA, PCP_NUMBER, 0};
221 static char alt_mnem4[] = { PCP_STR, PCP_NUMBER, PCP_COMMA, PCP_STR, 0}; // for lfsr 0 , name
222 static char alt_mnem4a[] = { PCP_STR, PCP_NUMBER, PCP_COMMA, PCP_NUMBER, 0}; // for lfsr 0 , value
224 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
225 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
226 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb);
227 static void * cvt_altpat_mnem0a(void *pp,pCodeWildBlock *pcwb);
228 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb);
229 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb);
230 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb);
231 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb);
232 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb);
233 static void * cvt_altpat_mnem2b(void *pp, pCodeWildBlock *pcwb);
234 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb);
235 static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb);
236 static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb);
238 /* NOTE: Order is important in the following table */
239 static pcPattern altArr[] = {
240 {ALT_LABEL, alt_label, cvt_altpat_label},
241 {ALT_COMMENT, alt_comment,cvt_altpat_comment},
242 {ALT_MNEM4a, alt_mnem4a, cvt_altpat_mnem4a},
243 {ALT_MNEM4, alt_mnem4, cvt_altpat_mnem4},
244 {ALT_MNEM3, alt_mnem3, cvt_altpat_mnem3},
245 {ALT_MNEM2B, alt_mnem2b, cvt_altpat_mnem2b},
246 {ALT_MNEM2A, alt_mnem2a, cvt_altpat_mnem2a},
247 {ALT_MNEM2, alt_mnem2, cvt_altpat_mnem2},
248 {ALT_MNEM1B, alt_mnem1b, cvt_altpat_mnem1b},
249 {ALT_MNEM1A, alt_mnem1a, cvt_altpat_mnem1a},
250 {ALT_MNEM1, alt_mnem1, cvt_altpat_mnem1},
251 {ALT_MNEM0A, alt_mnem0a, cvt_altpat_mnem0a},
252 {ALT_MNEM0, alt_mnem0, cvt_altpat_mnem0},
256 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
258 // forward declarations
259 static void * DLL_append(_DLL *list, _DLL *next);
261 /*-----------------------------------------------------------------*/
262 /* cvt_extract_destination - helper function extracts the register */
263 /* destination from a parsedPattern. */
265 /*-----------------------------------------------------------------*/
266 static int cvt_extract_destination(parsedPattern *pp)
269 if(pp->pct[0].tt == PCT_STRING) {
271 // just check first letter for now
273 if(toupper((unsigned char)*pp->pct[0].tok.s) == 'F')
276 } else if (pp->pct[0].tt == PCT_NUMBER) {
286 /*-----------------------------------------------------------------*/
287 /* pCodeOp *cvt_extract_status(char *reg, char *bit) */
288 /* if *reg is the "status" register and *bit is one of the */
289 /* status bits, then this function will create a new pCode op */
290 /* containing the status register. */
291 /*-----------------------------------------------------------------*/
293 static pCodeOp *cvt_extract_status(char *reg, char *bit)
297 if(STRCASECMP(reg, pic16_pc_status.pcop.name))
304 if(toupper((unsigned char)*bit) == 'C')
305 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_C_BIT));
306 if(toupper((unsigned char)*bit) == 'Z')
307 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_Z_BIT));
311 if(len ==2 && toupper((unsigned char)bit[0]) == 'D' && toupper((unsigned char)bit[1]) == 'C')
312 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_DC_BIT));
318 /*-----------------------------------------------------------------*/
319 /* cvt_altpat_label - convert assembly line type to a pCode label */
320 /* INPUT: pointer to the parsedPattern */
324 /* label pattern => '%' number ':' */
325 /* at this point, we wish to extract only the 'number' */
327 /*-----------------------------------------------------------------*/
328 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb)
330 parsedPattern *p = pp;
332 DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
333 return pic16_newpCodeLabel(NULL,-p->pct[1].tok.n);
337 /*-----------------------------------------------------------------*/
338 /* cvt_altpat_comment - convert assembly line type to a comment */
339 /* INPUT: pointer to the parsedPattern */
341 /* pp[0] - comment */
344 /*-----------------------------------------------------------------*/
345 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb)
347 parsedPattern *p = pp;
349 DFPRINTF((stderr,"altpat_comment = %s\n",p->pct[0].tok.s));
350 return pic16_newpCodeCharP(p->pct[0].tok.s);
354 /*-----------------------------------------------------------------*/
355 /* cvt_altpat_mem0 - convert assembly line type to a wild pCode */
360 /*-----------------------------------------------------------------*/
361 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb)
363 parsedPattern *p = pp;
366 pCodeInstruction *pci=NULL;
368 DFPRINTF((stderr,"altpat_mnem0 %s\n", p->pct[0].tok.s));
370 opcode = pic16_getpCode(p->pct[0].tok.s,0);
373 /* look for special command strings like _NOTBITSKIP_ */
375 //fprintf(stderr, "Bad mnemonic\n");
377 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
379 // fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
383 pci = PCI(pic16_newpCode(opcode, NULL));
386 fprintf(stderr,"couldn't find mnemonic\n");
392 /*-----------------------------------------------------------------*/
393 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode */
396 /* pp[0] - wild var */
398 /*-----------------------------------------------------------------*/
399 static void * cvt_altpat_mnem0a(void *pp, pCodeWildBlock *pcwb)
401 parsedPattern *p = pp;
403 DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n", p[0].pct[1].tok.n));
405 /* Save the index of the maximum wildcard mnemonic */
407 //if(p[0].pct[1].tok.n > sMaxWildVar)
408 // sMaxWildMnem = p[0].pct[1].tok.n;
410 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
411 pcwb->nwildpCodes = p[0].pct[1].tok.n;
413 return pic16_newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
417 /*-----------------------------------------------------------------*/
418 /* cvt_altpat_mem1 - convert assembly line type to a pCode */
419 /* instruction with 1 operand. */
422 /* pp[1] - Operand */
424 /*-----------------------------------------------------------------*/
425 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb)
428 parsedPattern *p = pp;
431 pCodeInstruction *pci=NULL;
434 DFPRINTF((stderr,"altpat_mnem1 %s var %s\n", p->pct[0].tok.s,p[1].pct[0].tok.s));
436 opcode = pic16_getpCode(p->pct[0].tok.s,0);
438 //fprintf(stderr, "Bad mnemonic\n");
439 opcode = pic16_getpCodePeepCommand(p->pct[0].tok.s);
441 //fprintf(stderr," but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
446 if(pic16Mnemonics[opcode]->isBitInst)
447 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
449 // fprintf(stderr, "%s:%d tok.s= %s\n", __FILE__, __LINE__, p[1].pct[0].tok.s);
450 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_STR); //GPR_REGISTER);
454 pci = PCI(pic16_newpCode(opcode, pcosubtype));
457 fprintf(stderr,"couldn't find mnemonic\n");
463 /*-----------------------------------------------------------------*/
464 /* cvt_altpat_mem1a - convert assembly line type to a pCode */
465 /* instruction with 1 wild operand. */
468 /* pp[1] - wild var */
470 /*-----------------------------------------------------------------*/
471 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb)
473 parsedPattern *p = pp;
476 pCodeInstruction *pci=NULL;
479 DFPRINTF((stderr,"altpat_mnem1a %s var %d\n", p->pct[0].tok.s,p[1].pct[1].tok.n));
481 opcode = pic16_getpCode(p->pct[0].tok.s,0);
483 int cmd_id = pic16_getpCodePeepCommand(p->pct[0].tok.s);
487 fprintf(stderr, "Bad mnemonic\n");
491 if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
492 pcwb->nwildpCodes = p[0].pct[1].tok.n;
494 pc = pic16_newpCodeWild(p[1].pct[1].tok.n,NULL,NULL);
498 PCW(pc)->mustNotBeBitSkipInst = 1;
501 PCW(pc)->mustBeBitSkipInst = 1;
504 PCW(pc)->invertBitSkipInst = 1;
509 if(pic16Mnemonics[opcode]->isBitInst)
510 pcosubtype = pic16_newpCodeOpBit(NULL,-1,0, PO_GPR_REGISTER);
512 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
515 pci = PCI(pic16_newpCode(opcode,
516 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
518 /* Save the index of the maximum wildcard variable */
519 //if(p[1].pct[1].tok.n > sMaxWildVar)
520 // sMaxWildVar = p[1].pct[1].tok.n;
522 if(p[1].pct[1].tok.n > pcwb->nvars)
523 pcwb->nvars = p[1].pct[1].tok.n;
526 fprintf(stderr,"couldn't find mnemonic\n");
532 /*-----------------------------------------------------------------*/
533 /*-----------------------------------------------------------------*/
534 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb)
536 parsedPattern *p = pp;
539 pCodeInstruction *pci=NULL;
541 DFPRINTF((stderr,"altpat_mnem1b %s var %d\n", p->pct[0].tok.s,p[1].pct[0].tok.n));
543 opcode = pic16_getpCode(p->pct[0].tok.s,0);
545 fprintf(stderr, "Bad mnemonic\n");
549 pci = PCI(pic16_newpCode(opcode, pic16_newpCodeOpLit(p[1].pct[0].tok.n) ));
552 fprintf(stderr,"couldn't find mnemonic\n");
558 /*-----------------------------------------------------------------*/
559 /* cvt_altpat_mnem2 */
564 /* pp[3] - destination */
565 /*-----------------------------------------------------------------*/
566 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
568 parsedPattern *p = pp;
572 pCodeInstruction *pci=NULL;
575 dest = cvt_extract_destination(&p[3]);
577 DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
583 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
585 fprintf(stderr, "Bad mnemonic\n");
589 if(pic16Mnemonics[opcode]->isBitInst) {
590 pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
591 if(pcosubtype == NULL) {
592 fprintf(stderr, "bad operand?\n");
597 if(pic16Mnemonics[opcode]->is2MemOp) {
598 /* support for movff instruction */
599 pcosubtype = pic16_popCombine2(
600 pic16_newpCodeOp(p[1].pct[0].tok.s, PO_GPR_REGISTER),
601 pic16_newpCodeOp(p[3].pct[0].tok.s, PO_GPR_REGISTER), 0);
603 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
607 pci = PCI(pic16_newpCode(opcode,pcosubtype));
610 fprintf(stderr,"couldn't find mnemonic\n");
616 /*-----------------------------------------------------------------*/
617 /* cvt_altpat_mem2a - convert assembly line type to a pCode */
618 /* instruction with 1 wild operand and a */
619 /* destination operand (e.g. w or f) */
622 /* pp[1] - wild var */
624 /* pp[3] - destination */
626 /*-----------------------------------------------------------------*/
627 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
629 parsedPattern *p = pp;
633 pCodeInstruction *pci=NULL;
634 pCodeOp *pcosubtype, *pcosubtype2;
637 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
641 dest = cvt_extract_destination(&p[3]);
643 DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
650 fprintf(stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
658 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
660 fprintf(stderr, "Bad mnemonic\n");
664 if(pic16Mnemonics[opcode]->isBitInst) {
665 pcosubtype = pic16_newpCodeOp(NULL,PO_BIT);
669 if(pic16Mnemonics[opcode]->is2MemOp) {
670 /* support for movff instruction */
671 pcosubtype = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
672 pcosubtype2 = pic16_newpCodeOp(p[3].pct[0].tok.s, PO_STR);
675 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER); pcosubtype2 = NULL; }
679 pci = PCI(pic16_newpCode(opcode,
680 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
682 pci = PCI(pic16_newpCode(opcode,
683 pic16_newpCodeOpWild2(p[1].pct[1].tok.n, p[3].pct[1].tok.n, pcwb, pcosubtype, pcosubtype2)));
685 /* Save the index of the maximum wildcard variable */
686 //if(p[1].pct[1].tok.n > sMaxWildVar)
687 // sMaxWildVar = p[1].pct[1].tok.n;
689 if(p[1].pct[1].tok.n > pcwb->nvars)
690 pcwb->nvars = p[1].pct[1].tok.n;
693 fprintf(stderr,"couldn't find mnemonic\n");
699 /*-----------------------------------------------------------------*/
700 /* cvt_altpat_mem2b - convert assembly line type to a pCode */
701 /* instruction with 2 wild operands */
704 /* pp[1] - wild var */
706 /* pp[3] - wild var */
708 /*-----------------------------------------------------------------*/
709 static void * cvt_altpat_mnem2b(void *pp,pCodeWildBlock *pcwb)
711 parsedPattern *p = pp;
715 pCodeInstruction *pci=NULL;
716 pCodeOp *pcosubtype, *pcosubtype2;
719 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
723 dest = cvt_extract_destination(&p[3]);
725 DFPRINTF((stderr,"altpat_mnem2b %s src %d dst (%d)\n",
731 fprintf(stderr,"altpat_mnem2b %s src: %d dst: %d\n",
737 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
739 fprintf(stderr, "Bad mnemonic\n");
743 if(pic16Mnemonics[opcode]->is2MemOp) {
744 /* support for movff instruction */
745 pcosubtype = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
746 pcosubtype2 = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
747 } else pcosubtype = pcosubtype2 = NULL;
749 pci = PCI(pic16_newpCode(opcode,
750 pic16_newpCodeOpWild2(p[1].pct[1].tok.n, p[3].pct[1].tok.n,
751 pcwb, pcosubtype, pcosubtype2)));
753 /* Save the index of the maximum wildcard variable */
754 //if(p[1].pct[1].tok.n > sMaxWildVar)
755 // sMaxWildVar = p[1].pct[1].tok.n;
757 if(p[1].pct[1].tok.n > pcwb->nvars)
758 pcwb->nvars = p[1].pct[1].tok.n;
761 fprintf(stderr,"couldn't find mnemonic\n");
768 /*-----------------------------------------------------------------*/
769 /* cvt_altpat_mem3 - convert assembly line type to a pCode */
770 /* This rule is for bsf/bcf type instructions */
774 /* pp[1] - register */
778 /*-----------------------------------------------------------------*/
779 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
781 parsedPattern *p = pp;
783 int dest; // or could be bit position in the register
785 pCodeInstruction *pci=NULL;
786 pCodeOp *pcosubtype=NULL;
788 dest = cvt_extract_destination(&p[3]);
790 DFPRINTF((stderr,"altpat_mnem3 %s var %s bit (%d)\n",
796 opcode = pic16_getpCode(p->pct[0].tok.s,0);
798 fprintf(stderr, "Bad mnemonic\n");
803 if(pic16Mnemonics[opcode]->isBitInst) {
804 //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
806 //if(pcosubtype == NULL) {
807 pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0, PO_GPR_REGISTER);
810 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
812 if(pcosubtype == NULL) {
813 fprintf(stderr, "Bad operand\n");
817 pci = PCI(pic16_newpCode(opcode, pcosubtype));
820 fprintf(stderr,"couldn't find mnemonic\n");
826 /*-----------------------------------------------------------------*/
827 /* cvt_altpat_mem4 - convert assembly line type to a pCode */
828 /* This rule is for lfsr instruction */
836 /*-----------------------------------------------------------------*/
837 static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb)
839 parsedPattern *p = pp;
841 int dest; // or could be bit position in the register
843 pCodeInstruction *pci=NULL;
844 pCodeOp *pcosubtype=NULL;
846 dest = cvt_extract_destination(&p[3]);
848 DFPRINTF((stderr,"altpat_mnem4 %s fsr %d source %s\n",
853 opcode = pic16_getpCode(p->pct[0].tok.s,0);
855 fprintf(stderr, "Bad mnemonic\n");
858 DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
860 if(pic16Mnemonics[opcode]->is2LitOp) {
861 pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOp(p[3].pct[0].tok.s, PO_STR));
864 if(pcosubtype == NULL) {
865 fprintf(stderr, "Bad operand\n");
869 pci = PCI(pic16_newpCode(opcode, pcosubtype));
872 fprintf(stderr,"couldn't find mnemonic\n");
878 /*-----------------------------------------------------------------*/
879 /* cvt_altpat_mem4a - convert assembly line type to a pCode */
880 /* This rule is for lfsr instruction */
888 /*-----------------------------------------------------------------*/
889 static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb)
891 parsedPattern *p = pp;
893 int dest; // or could be bit position in the register
895 pCodeInstruction *pci=NULL;
896 pCodeOp *pcosubtype=NULL;
898 dest = cvt_extract_destination(&p[3]);
900 DFPRINTF((stderr,"altpat_mnem4a %s fsr %d value 0x%02x\n",
905 opcode = pic16_getpCode(p->pct[0].tok.s,0);
907 fprintf(stderr, "Bad mnemonic\n");
910 DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
912 if(pic16Mnemonics[opcode]->is2LitOp) {
913 pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOpLit(p[3].pct[0].tok.n));
916 if(pcosubtype == NULL) {
917 fprintf(stderr, "Bad operand\n");
921 pci = PCI(pic16_newpCode(opcode, pcosubtype));
924 fprintf(stderr,"couldn't find mnemonic\n");
930 /*-----------------------------------------------------------------*/
931 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
932 /* by SDCCpeeph.c into a string of tokens. */
935 /* The tokenizer is of the classic type. When an item is encounterd*/
936 /* it is converted into a token. The token is a structure that */
937 /* encodes the item's type and it's value (when appropriate). */
939 /* Accepted token types: */
940 /* SPACE NUMBER STRING % : , ; */
944 /*-----------------------------------------------------------------*/
947 static void tokenizeLineNode(char *ln)
950 tokIdx = 0; // Starting off at the beginning
951 tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
956 // fprintf(stderr, "%s:%d: processing %s\n", __FILE__, __LINE__, ln);
959 if(isspace((unsigned char)*ln)) {
960 // add a SPACE token and eat the extra spaces.
961 tokArr[tokIdx++].tt = PCT_SPACE;
962 while (isspace ((unsigned char)*ln))
967 if(isdigit((unsigned char)*ln)) {
969 tokArr[tokIdx].tt = PCT_NUMBER;
970 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
978 tokArr[tokIdx++].tt = PCT_PERCENT;
981 tokArr[tokIdx++].tt = PCT_LESSTHAN;
984 tokArr[tokIdx++].tt = PCT_GREATERTHAN;
987 tokArr[tokIdx++].tt = PCT_COLON;
990 tokArr[tokIdx].tok.s = Safe_strdup(ln);
991 tokArr[tokIdx++].tt = PCT_COMMENT;
992 tokArr[tokIdx].tt = PCT_NULL;
995 tokArr[tokIdx++].tt = PCT_COMMA;
999 default: // hack to allow : goto $
1000 if(isalpha((unsigned char)*ln) || (*ln == '_') || (!parsing_peeps && (*ln == '$'))) {
1004 while( (isalpha((unsigned char)*ln) || isdigit((unsigned char)*ln) || (*ln == '_') || (*ln == '$')) && i<49)
1005 buffer[i++] = *ln++;
1010 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
1011 tokArr[tokIdx++].tt = PCT_STRING;
1015 fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
1016 fprintf(stderr, "Line: %s\n",lnstart);
1017 fprintf(stderr, "Token: '%c'\n",*ln);
1023 /* Advance to next character in input string .
1024 * Note, if none of the tests passed above, then
1025 * we effectively ignore the `bad' character.
1026 * Since the line has already been parsed by SDCCpeeph,
1027 * chance are that there are no invalid characters... */
1033 tokArr[tokIdx].tt = 0;
1037 /*-----------------------------------------------------------------*/
1038 /*-----------------------------------------------------------------*/
1042 static void dump1Token(pCodeTokens tt)
1047 fprintf(stderr, " space ");
1050 fprintf(stderr, " pct %%");
1053 fprintf(stderr, " pct <");
1055 case PCT_GREATERTHAN:
1056 fprintf(stderr, " pct >");
1059 fprintf(stderr, " col :");
1062 fprintf(stderr, " comma , ");
1065 fprintf(stderr, " comment ");
1066 //fprintf(stderr,"%s",tokArr[i].tok.s);
1069 fprintf(stderr, " str ");
1070 //fprintf(stderr,"%s",tokArr[i].tok.s);
1073 fprintf(stderr, " num ");
1074 //fprintf(stderr,"%d",tokArr[i].tok.n);
1077 fprintf(stderr, " null ");
1084 /*-----------------------------------------------------------------*/
1085 /*-----------------------------------------------------------------*/
1087 static int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
1091 if(!pct || !pat || !*pat)
1094 //DFPRINTF((stderr,"comparing against:\n"));
1096 while(i < max_tokens) {
1099 //DFPRINTF((stderr,"matched\n"));
1103 // dump1Token(*pat); fputc('\n', stderr); DFPRINTF((stderr,"\n"));
1117 /*-----------------------------------------------------------------*/
1118 /*-----------------------------------------------------------------*/
1120 static int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
1124 if(!pct || !pat || !*pct)
1128 while(i < max_tokens) {
1131 DFPRINTF((stderr,"matched\n"));
1135 // dump1Token(*pat); DFPRINTF((stderr,"\n"));
1137 if( !pat || !pat->pcp )
1140 if (pat->pcp->pt != *pct)
1143 DFPRINTF((stderr," pct=%d\n",*pct));
1152 /*-----------------------------------------------------------------*/
1153 /*-----------------------------------------------------------------*/
1155 static int advTokIdx(int *v, int amt)
1158 if((unsigned) (*v + amt) > tokIdx)
1166 /*-----------------------------------------------------------------*/
1167 /* parseTokens - convert the tokens corresponding to a single line */
1168 /* of a peep hole assembly into a pCode object. */
1173 /* This is a simple parser that looks for strings of the type */
1174 /* allowed in the peep hole definition file. Essentially the format*/
1175 /* is the same as a line of assembly: */
1177 /* label: mnemonic op1, op2, op3 ; comment */
1179 /* Some of these items aren't present. It's the job of the parser */
1180 /* to determine which are and convert those into the appropriate */
1182 /*-----------------------------------------------------------------*/
1184 static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
1195 for(i=0; i<=tokIdx; i++)
1196 dump1Token(tokArr[i].tt);
1202 int lparsedPatIdx=0;
1209 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
1210 char * cP1stop = NULL;
1211 char * cP2ndop = NULL;
1213 //pCodeOp *pcl = NULL; // Storage for a label
1214 //pCodeOp *pco1 = NULL; // 1st operand
1215 //pCodeOp *pco2 = NULL; // 2nd operand
1216 //pCode *pc = NULL; // Mnemonic
1227 ParseStates state = PS_START;
1234 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
1235 && (advTokIdx(<okIdx, 1)) ) // eat space
1239 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
1242 switch(pcpArr[lpcpIdx].pt) {
1244 if(state == PS_START){
1245 DFPRINTF((stderr," label\n"));
1246 state = PS_HAVE_LABEL;
1248 DFPRINTF((stderr," bad state (%d) for label\n",state));
1252 DFPRINTF((stderr," %s is",tokArr[ltokIdx].tok.s));
1256 DFPRINTF((stderr," mnem\n"));
1257 cPmnem = tokArr[ltokIdx].tok.s;
1258 state = PS_HAVE_MNEM;
1261 DFPRINTF((stderr," 1st operand\n"));
1262 cP1stop = tokArr[ltokIdx].tok.s;
1263 //pco1 = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
1264 state = PS_HAVE_1OPERAND;
1266 case PS_HAVE_1OPERAND:
1267 DFPRINTF((stderr," error expecting comma\n"));
1270 DFPRINTF((stderr," 2 operands\n"));
1271 cP2ndop = tokArr[ltokIdx].tok.s;
1273 case PS_HAVE_2OPERANDS:
1282 DFPRINTF((stderr," wild mnem\n"));
1283 state = PS_HAVE_MNEM;
1286 DFPRINTF((stderr," 1st operand is wild\n"));
1287 state = PS_HAVE_1OPERAND;
1289 case PS_HAVE_1OPERAND:
1290 DFPRINTF((stderr," error expecting comma\n"));
1293 DFPRINTF((stderr," 2nd operand is wild\n"));
1295 case PS_HAVE_2OPERANDS:
1304 fprintf(stderr," ERROR number\n");
1307 DFPRINTF((stderr," 1st operand is a number\n"));
1308 state = PS_HAVE_1OPERAND;
1310 case PS_HAVE_1OPERAND:
1311 fprintf(stderr," error expecting comma\n");
1314 DFPRINTF((stderr," 2nd operand is a number\n"));
1316 case PS_HAVE_2OPERANDS:
1324 if(state == PS_HAVE_1OPERAND){
1325 DFPRINTF((stderr," got a comma\n"));
1326 state = PS_HAVE_COMMA;
1328 fprintf(stderr," unexpected comma\n");
1334 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1335 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1338 // dump1Token(tokArr[ltokIdx].tt);
1340 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1341 DFPRINTF((stderr," reached end \n"));
1348 } while ((++lpcpIdx < PCPATTERNS) && !matching);
1352 parsedPatArr[lparsedPatIdx].pcp = NULL;
1353 parsedPatArr[lparsedPatIdx].pct = NULL;
1359 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1362 pc = altArr[k].f(&parsedPatArr[j],pcwb);
1363 //if(pc && pc->print)
1364 // pc->print(stderr,pc);
1365 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1367 //if(curBlock && pc)
1368 //pic16_addpCode2pBlock(curBlock, pc);
1372 return 0; // Only accept one line for now.
1374 pic16_addpCode2pBlock(pcwb->pb, pc);
1382 while(j<=lparsedPatIdx && k<ALTPATTERNS);
1385 DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1389 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1390 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1391 DFPRINTF((stderr," %d",parsedPatArr[j].pcp->pt));
1394 while(j<lparsedPatIdx);
1396 DFPRINTF((stderr,"\n"));
1403 /*-----------------------------------------------------------------*/
1405 /*-----------------------------------------------------------------*/
1406 static void peepRuleBlock2pCodeBlock( lineNode *ln, pCodeWildBlock *pcwb)
1412 for( ; ln; ln = ln->next) {
1414 //DFPRINTF((stderr,"%s\n",ln->line));
1415 // fprintf(stderr, "peep rule : %s\n", ln->line);
1417 tokenizeLineNode(ln->line);
1419 if(parseTokens(pcwb,NULL)) {
1421 fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
1422 fprintf(stderr,"Tokens:\n");
1424 dump1Token(tokArr[i].tt);
1431 /*-----------------------------------------------------------------*/
1432 /* pic16_AssembleLine - parse line and return the pCode equivalent */
1433 /* peeps=1 if parsing peep rules, 0 otherwise */
1434 /*-----------------------------------------------------------------*/
1435 pCode *pic16_AssembleLine(char *line, int peeps)
1439 if(!line || !*line) {
1440 fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
1444 parsing_peeps = peeps;
1446 tokenizeLineNode(line);
1448 if(parseTokens(NULL,&pc))
1449 fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
1451 DFPRINTF((stderr, "pc= %p\n", pc));
1452 // if(pc)pc->print(stderr, pc);
1460 /*-----------------------------------------------------------------*/
1461 /* peepRuleCondition */
1462 /*-----------------------------------------------------------------*/
1463 static void peepRuleCondition(char *cond, pCodePeep *pcp)
1468 //DFPRINTF((stderr,"\nCondition: %s\n",cond));
1469 /* brute force compares for now */
1471 if(STRCASECMP(cond, "NZ") == 0) {
1472 //DFPRINTF((stderr,"found NZ\n"));
1473 pcp->postFalseCond = PCC_Z;
1480 static void initpCodeWildBlock(pCodeWildBlock *pcwb)
1483 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1489 pcwb->wildpCodes = NULL;
1490 pcwb->wildpCodeOps = NULL;
1493 pcwb->nwildpCodes = 0;
1498 static void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1505 pcwb->nops = pcwb->nvars;
1507 pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1508 pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1510 pcwb->nwildpCodes+=2;
1511 pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1515 static void initpCodePeep(pCodePeep *pcp)
1518 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1523 initpCodeWildBlock(&pcp->target);
1524 pcp->target.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1526 initpCodeWildBlock(&pcp->replace);
1527 pcp->replace.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1531 /*-----------------------------------------------------------------*/
1532 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1535 /* SDCCpeeph parses the peep rules file and extracts variables, */
1536 /* removes white space, and checks the syntax. This function */
1537 /* extends that processing to produce pCode objects. You can kind */
1538 /* think of this function as an "assembler", though instead of */
1539 /* taking raw text to produce machine code, it produces pCode. */
1541 /*-----------------------------------------------------------------*/
1542 extern void pic16initpCodePeepCommands(void);
1544 void pic16_peepRules2pCode(peepRule *rules)
1548 pCodePeep *currentRule;
1549 pCodePeepSnippets *pcps;
1551 pic16initpCodePeepCommands();
1553 /* The rules are in a linked-list. Each rule has two portions */
1554 /* There's the `target' and there's the `replace'. The target */
1555 /* is compared against the SDCC generated code and if it */
1556 /* matches, it gets replaced by the `replace' block of code. */
1558 /* Here we loop through each rule and convert the target's and*/
1559 /* replace's into pCode target and replace blocks */
1561 for (pr = rules; pr; pr = pr->next) {
1563 //DFPRINTF((stderr,"\nRule:\n\n"));
1565 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1566 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1568 currentRule = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1569 initpCodePeep(currentRule);
1571 /* Convert the target block */
1572 peepRuleBlock2pCodeBlock(pr->match, ¤tRule->target);
1574 //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1575 // pic16_printpBlock(stderr, currentRule->target.pb);
1577 //DFPRINTF((stderr,"target with labels merged:\n"));
1578 //pic16_pBlockMergeLabels(curBlock);
1579 pic16_pBlockMergeLabels(currentRule->target.pb);
1580 //pic16_printpBlock(stderr, currentRule->replace.pb);
1582 //#ifdef PCODE_DEBUG
1583 // pic16_printpBlock(stderr, curBlock);
1585 //DFPRINTF((stderr,"\nReplaced by:\n"));
1588 /* Convert the replace block */
1589 peepRuleBlock2pCodeBlock(pr->replace, ¤tRule->replace);
1591 //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1592 //pic16_printpBlock(stderr, curBlock);
1594 //DFPRINTF((stderr,"replace with labels merged:\n"));
1596 pic16_pBlockMergeLabels(currentRule->replace.pb);
1597 //pic16_printpBlock(stderr, currentRule->replace.pb);
1599 peepRuleCondition(pr->cond,currentRule);
1601 /* The rule has been converted to pCode. Now allocate
1602 * space for the wildcards */
1604 postinit_pCodeWildBlock(¤tRule->target);
1605 postinit_pCodeWildBlock(¤tRule->replace);
1607 //return; // debug ... don't want to go through all the rules yet
1611 pCodePeep *peepBlock;
1614 peeprules = (_DLL *)peepSnippets;
1615 //fprintf(stderr,"target rules\n");
1617 //fprintf(stderr," rule:\n");
1618 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1619 //pic16_printpBlock(stderr, peepBlock->target.pb);
1620 peeprules = peeprules->next;
1622 //fprintf(stderr," ... done\n");
1627 static void printpCodeString(FILE *of, pCode *pc, int max)
1631 while(pc && (i++<max)) {
1637 /*-----------------------------------------------------------------*/
1638 /* _DLL * DLL_append */
1640 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1641 /* If The list to which we want to append is non-existant then one */
1642 /* is created. Other wise, the end of the list is sought out and */
1643 /* a new DLL object is appended to it. In either case, the void */
1644 /* *data is added to the newly created DLL object. */
1645 /*-----------------------------------------------------------------*/
1647 static void * DLL_append(_DLL *list, _DLL *next)
1652 /* If there's no list, then create one: */
1654 next->next = next->prev = NULL;
1659 /* Search for the end of the list. */
1664 /* Now append the new DLL object */
1675 /*-----------------------------------------------------------------
1677 pCode peephole optimization
1680 The pCode "peep hole" optimization is not too unlike the peep hole
1681 optimization in SDCCpeeph.c. The major difference is that here we
1682 use pCode's whereas there we use ASCII strings. The advantage with
1683 pCode's is that we can ascertain flow information in the instructions
1687 <FIX ME> - elaborate...
1689 -----------------------------------------------------------------*/
1693 /*-----------------------------------------------------------------*/
1694 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1696 /* return conditions */
1697 /* 1 - The Condition was found for a pCode's input */
1698 /* 0 - No matching condition was found for the whole chain */
1699 /* -1 - The Condition was found for a pCode's output */
1701 /*-----------------------------------------------------------------*/
1702 int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond)
1704 //fprintf(stderr,"Checking conditions %d\n",cond);
1707 /* If we reach a function end (presumably an end since we most
1708 probably began the search in the middle of a function), then
1709 the condition was not found. */
1710 if(pc->type == PC_FUNCTION)
1713 if(pc->type == PC_OPCODE) {
1714 //fprintf(stderr," checking conditions of: ");
1715 //pc->print(stderr,pc);
1716 //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
1717 if(PCI(pc)->inCond & cond)
1719 if(PCI(pc)->outCond & cond)
1729 /*-----------------------------------------------------------------
1730 * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1732 * Compare two pCodeOp's and return 1 if they're the same
1733 *-----------------------------------------------------------------*/
1734 static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1738 if(!pcops || !pcopd)
1742 fprintf(stderr,"%s:%d Comparing operands %s", __FILE__, __LINE__,
1743 pic16_get_op( pcops,NULL,0));
1745 fprintf(stderr," to %s\n",
1746 pic16_get_op( pcopd,NULL,0));
1749 if(pcops->type != pcopd->type) {
1750 //fprintf(stderr," - fail - diff types\n");
1751 return 0; // different types
1754 if(pcops->type == PO_LITERAL) {
1756 if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
1762 memset(b, 0, sizeof(b) ); //b[0]=0;
1763 pic16_get_op(pcops,b, sizeof(b) );
1765 n2 = pic16_get_op(pcopd,NULL,0);
1767 if( !n2 || strcmp(b,n2)) {
1768 // fprintf(stderr," - fail - diff names: %s, len=%d, %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1769 return 0; // different names
1772 switch(pcops->type) {
1774 if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1775 // fprintf(stderr, " - fail different instances\n");
1783 //fprintf(stderr," - pass\n");
1788 static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1792 /* Check for a label associated with this wild pCode */
1793 // If the wild card has a label, make sure the source code does too.
1794 if(PCI(pcd)->label) {
1795 pCode *pcl = PCI(pcd)->label->pc;
1798 int li = -PCL(pcl)->key;
1800 if(peepBlock->target.vars[li] == NULL) {
1801 if(PCI(pcs)->label) {
1802 DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1805 // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1806 DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1807 if(PCI(pcs)->label) {
1808 DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1814 if(!PCI(pcs)->label)
1817 labindex = -PCL(pcl)->key;
1818 if(peepBlock->target.vars[labindex] == NULL) {
1819 // First time to encounter this label
1820 peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1821 DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1824 if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1825 DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1828 DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1831 //DFPRINTF((stderr,"destination doesn't have a label\n"));
1836 //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1844 /*-----------------------------------------------------------------*/
1845 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1846 /* see they're the same. */
1848 /* In this context, "source" refers to the coded generated by gen.c*/
1849 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1850 /* ination has no wild cards, then MatchLine will compare the two */
1851 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1852 /* has wildcards, then those get expanded. When a wild card is */
1853 /* encountered for the first time it autmatically is considered a */
1854 /* match and the object that matches it is referenced in the */
1855 /* variables or opcodes array (depending on the type of match). */
1859 /* *peepBlock - A pointer to the peepBlock that contains the */
1860 /* entire rule to which the destination pcode belongs*/
1861 /* *pcs - a pointer to the source pcode */
1862 /* *pcd - a pointer to the destination pcode */
1865 /* 1 - pcodes match */
1866 /* 0 - pcodes don't match */
1869 /*-----------------------------------------------------------------*/
1871 static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1873 int index; // index into wild card arrays
1876 /* one-for-one match. Here the source and destination opcodes
1877 * are not wild. However, there may be a label or a wild operand */
1880 if(PCI(pcs)->label) {
1881 DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1885 if(pcs->type == pcd->type) {
1887 if(pcs->type == PC_OPCODE) {
1889 /* If the opcodes don't match then the line doesn't match */
1890 if(PCI(pcs)->op != PCI(pcd)->op)
1894 DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1895 pcs->print(stderr,pcs);
1896 pcd->print(stderr,pcd);
1899 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1902 /* Compare the operands */
1903 if(PCI(pcd)->pcop) {
1904 /* assert that optimizations do not touch operations that work on SFRs or INDF registers */
1905 if ((PCI(pcd)->pcop->type == PO_WILD) && (!(PCI(pcs)->pcop) || ((PCI(pcs)->pcop->type != PO_SFR_REGISTER) && (PCI(pcs)->pcop->type != PO_INDF0)))) {
1906 index = PCOW(PCI(pcd)->pcop)->id;
1907 //DFPRINTF((stderr,"destination is wild\n"));
1908 #ifdef DEBUG_PCODEPEEP
1909 if (index > peepBlock->nops) {
1910 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1915 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1917 if(!peepBlock->target.wildpCodeOps[index]) {
1918 peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1920 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1924 pcs->print(stderr,pcs);
1925 pcd->print(stderr,pcd);
1927 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1928 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1932 havematch = pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1933 // return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1936 if((havematch==-1) && PCI(pcs)->pcop) {
1939 switch(PCI(pcs)->pcop->type) {
1943 n = PCOR(PCI(pcs)->pcop)->r->name;
1947 n = PCI(pcs)->pcop->name;
1950 if(peepBlock->target.vars[index])
1951 return (strcmp(peepBlock->target.vars[index],n) == 0);
1953 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1954 peepBlock->target.vars[index] = n;
1960 /* now check whether the second operand matches */
1961 /* assert that optimizations do not touch operations that work on SFRs or INDF registers */
1962 if(PCOW2(PCI(pcd)->pcop) && (PCOP2(PCI(pcd)->pcop)->pcopR->type == PO_WILD) && (!(PCOP2(PCI(pcs)->pcop)->pcopR) || ((PCOP2(PCI(pcs)->pcop)->pcopR->type != PO_SFR_REGISTER) && (PCOP2(PCI(pcs)->pcop)->pcopR) && (PCOP2(PCI(pcs)->pcop)->pcopR->type != PO_INDF0)))) {
1964 // fprintf(stderr, "%s:%d %s second operand is wild\n", __FILE__, __LINE__, __FUNCTION__);
1966 index = PCOW2(PCI(pcd)->pcop)->id;
1967 //DFPRINTF((stderr,"destination is wild\n"));
1968 #ifdef DEBUG_PCODEPEEP
1969 if (index > peepBlock->nops) {
1970 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1975 PCOW2(PCI(pcd)->pcop)->matched = PCOP2(PCI(pcs)->pcop)->pcopR;
1976 if(!peepBlock->target.wildpCodeOps[index]) {
1977 peepBlock->target.wildpCodeOps[index] = PCOP2(PCI(pcs)->pcop)->pcopR;
1979 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1983 pcs->print(stderr,pcs);
1984 pcd->print(stderr,pcd);
1986 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1987 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1991 return ((havematch==1) && pCodeOpCompare(PCOP2(PCI(pcs)->pcop)->pcopR,
1992 peepBlock->target.wildpCodeOps[index]));
1995 if(PCOP2(PCI(pcs)->pcop)->pcopR) {
1998 switch(PCOP2(PCI(pcs)->pcop)->pcopR->type) {
2002 n = PCOR(PCOP2(PCI(pcs)->pcop)->pcopR)->r->name;
2005 n = PCOP2(PCI(pcs)->pcop)->pcopR->name;
2008 if(peepBlock->target.vars[index])
2009 return (havematch && (strcmp(peepBlock->target.vars[index],n) == 0));
2011 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
2012 peepBlock->target.vars[index] = n;
2013 return (havematch==1); //&& 1;
2017 } else if (PCOW2(PCI(pcd)->pcop) && (PCOP2(PCI(pcd)->pcop)->pcopR->type == PO_WILD) && PCOP2(PCI(pcs)->pcop)->pcopR)
2024 else if (PCI(pcd)->pcop->type == PO_LITERAL) {
2025 return (havematch &&
2026 pCodeOpCompare(PCOR2(PCI(pcs)->pcop)->pcop2, PCOR2(PCI(pcd)->pcop)->pcop2));
2031 } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
2032 return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
2037 /* FIXME - need an else to check the case when the destination
2038 * isn't a wild card */
2040 /* The pcd has no operand. Lines match if pcs has no operand either*/
2041 return (PCI(pcs)->pcop == NULL);
2044 /* Compare a wild instruction to a regular one. */
2046 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
2048 index = PCW(pcd)->id;
2050 DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
2051 pcs->print(stderr,pcs);
2052 pcd->print(stderr,pcd);
2054 peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
2056 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
2057 DFPRINTF((stderr," Failing because labels don't match\n"));
2061 if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
2062 // doesn't match because the wild pcode must be a bit skip
2063 DFPRINTF((stderr," Failing match because bit skip is req\n"));
2064 //pcd->print(stderr,pcd);
2065 //pcs->print(stderr,pcs);
2069 if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
2070 // doesn't match because the wild pcode must *not* be a bit skip
2071 DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
2072 //pcd->print(stderr,pcd);
2073 //pcs->print(stderr,pcs);
2077 if(PCW(pcd)->operand) {
2078 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
2079 if(peepBlock->target.vars[index]) {
2080 int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
2084 DFPRINTF((stderr," (matched)\n"));
2086 DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
2087 DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n",
2088 peepBlock->target.vars[index],
2089 PCI(pcs)->pcop->name));
2094 DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
2095 peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
2100 pcs = pic16_findNextInstruction(pcs->next);
2102 //DFPRINTF((stderr," (next to match)\n"));
2103 //pcs->print(stderr,pcs);
2104 } else if(pcd->next) {
2105 /* oops, we ran out of code, but there's more to the rule */
2109 return 1; /* wild card matches */
2115 /*-----------------------------------------------------------------*/
2116 /*-----------------------------------------------------------------*/
2117 static void pCodePeepClrVars(pCodePeep *pcp)
2124 DFPRINTF((stderr," Clearing peep rule vars\n"));
2125 DFPRINTF((stderr," %d %d %d %d %d %d\n",
2126 pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
2127 pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
2129 for(i=0;i<pcp->target.nvars; i++)
2130 pcp->target.vars[i] = NULL;
2131 for(i=0;i<pcp->target.nops; i++)
2132 pcp->target.wildpCodeOps[i] = NULL;
2133 for(i=0;i<pcp->target.nwildpCodes; i++)
2134 pcp->target.wildpCodes[i] = NULL;
2136 for(i=0;i<pcp->replace.nvars; i++)
2137 pcp->replace.vars[i] = NULL;
2138 for(i=0;i<pcp->replace.nops; i++)
2139 pcp->replace.wildpCodeOps[i] = NULL;
2140 for(i=0;i<pcp->replace.nwildpCodes; i++)
2141 pcp->replace.wildpCodes[i] = NULL;
2147 /*-----------------------------------------------------------------*/
2148 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2149 /* into the pCode chain containing pc1 */
2150 /*-----------------------------------------------------------------*/
2151 void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2)
2157 pc2->next = pc1->next;
2159 pc1->next->prev = pc2;
2167 /*-----------------------------------------------------------------*/
2168 /* pic16_pCodeOpCopy - copy a pcode operator */
2169 /*-----------------------------------------------------------------*/
2170 pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
2172 pCodeOp *pcopnew=NULL;
2177 switch(pcop->type) {
2181 pcopnew = Safe_calloc(1, sizeof (pCodeOp));
2182 memcpy(pcopnew, pcop, sizeof (pCodeOp));
2192 case PO_GPR_REGISTER:
2194 case PO_SFR_REGISTER:
2201 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2202 /* XXX: might also be pCodeOpReg2 -- that's why the two structs are identical */
2203 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2204 memcpy (pcopnew, pcop, sizeof(pCodeOpReg));
2208 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2209 /* XXX: might also be pCodeOpLit2, that's why the two structs are identical... */
2210 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2211 memcpy (pcopnew, pcop, sizeof(pCodeOpLit));
2215 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2216 memcpy (pcopnew, pcop, sizeof(pCodeOpImmd));
2222 pcopnew = Safe_calloc(1, sizeof (pCodeOpRegBit));
2223 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2227 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2228 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2229 memcpy (pcopnew, pcop, sizeof (pCodeOpLabel));
2233 /* Here we expand the wild card into the appropriate type: */
2234 /* By recursively calling pCodeOpCopy */
2235 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2236 if(PCOW(pcop)->matched)
2237 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->matched);
2240 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->subtype);
2241 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2242 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2248 pcopnew = pic16_newpCodeOp2( pic16_pCodeOpCopy( PCOP2(pcop)->pcopL ),
2249 pic16_pCodeOpCopy( PCOP2(pcop)->pcopR ) );
2253 assert ( !"unhandled pCodeOp type copied" );
2256 /* strdup pcop->name (prevent access to shared but released memory) */
2258 pcopnew->name = Safe_strdup(pcop->name);
2260 pcopnew->name = NULL;
2266 /*-----------------------------------------------------------------*/
2267 /* pCodeCopy - copy a pcode */
2268 /*-----------------------------------------------------------------*/
2269 static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2271 pCodeInstruction *new_pci;
2274 new_pci = PCI(pic16_newpCode(pci->inverted_op,pci->pcop));
2276 new_pci = PCI(pic16_newpCode(pci->op,pci->pcop));
2278 new_pci->pc.pb = pci->pc.pb;
2279 new_pci->from = pci->from;
2280 new_pci->to = pci->to;
2281 new_pci->label = pci->label;
2282 new_pci->pcflow = pci->pcflow;
2284 return PCODE(new_pci);
2287 /*-----------------------------------------------------------------*/
2288 /*-----------------------------------------------------------------*/
2289 static void pCodeDeleteChain(pCode *f,pCode *t)
2295 DFPRINTF((stderr,"delete pCode:\n"));
2297 //f->print(stderr,f);
2298 //f->delete(f); this dumps core...
2305 /*-----------------------------------------------------------------*/
2306 /*-----------------------------------------------------------------*/
2307 int pic16_pCodePeepMatchRule(pCode *pc)
2309 pCodePeep *peepBlock;
2311 pCodeCSource *pc_cline=NULL;
2316 peeprules = (_DLL *)peepSnippets;
2319 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
2321 if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
2322 fprintf(stderr, "skipping rule because target pb is NULL\n");
2326 pCodePeepClrVars(peepBlock);
2329 if(IS_PCCOMMENT(pcin))
2330 pc = pcin = pic16_findNextInstruction(pcin->next);
2332 pcin = pc = pic16_findNextInstruction(pc);
2334 pct = peepBlock->target.pb->pcHead;
2337 pCode *pcr = peepBlock->replace.pb->pcHead;
2338 if(pcr) pct->print(stderr,pcr);
2342 while(pct && pcin) {
2344 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
2347 pcin = pic16_findNextInstruction(pcin->next);
2350 //DFPRINTF((stderr," matched\n"));
2353 DFPRINTF((stderr," partial match... no more code\n"));
2354 // fprintf(stderr," partial match... no more code\n");
2358 DFPRINTF((stderr," end of rule\n"));
2362 if(matched && pcin) {
2364 /* So far we matched the rule up to the point of the conditions .
2365 * In other words, all of the opcodes match. Now we need to see
2366 * if the post conditions are satisfied.
2367 * First we check the 'postFalseCond'. This means that we check
2368 * to see if any of the subsequent pCode's in the pCode chain
2369 * following the point just past where we have matched depend on
2370 * the `postFalseCond' as input then we abort the match
2372 DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
2373 //pcin->print(stderr,pcin);
2375 if (pcin && peepBlock->postFalseCond &&
2376 (pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
2379 // fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
2382 //if(!matched) fprintf(stderr,"failed on conditions\n");
2391 /* We matched a rule! Now we have to go through and remove the
2392 inefficient code with the optimized version */
2394 DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
2395 // printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
2396 DFPRINTF((stderr,"first thing matched\n"));
2397 pc->print(stderr,pc);
2399 DFPRINTF((stderr,"last thing matched\n"));
2400 pcin->print(stderr,pcin);
2405 /* Unlink the original code */
2407 pcprev->next = pcin;
2409 pcin->prev = pc->prev;
2415 /* Converted the deleted pCodes into comments */
2418 pCodeCSource *pc_cline2=NULL;
2423 while(pc && pc!=pcin) {
2425 if(pc->type == PC_OPCODE && PCI(pc)->cline) {
2427 pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2428 pc_cline2 = PCCS(pc_cline2->pc.next);
2430 pc_cline = pc_cline2 = PCI(pc)->cline;
2431 pc_cline->pc.seq = pc->seq;
2435 pic16_pCode2str(&buf[1], sizeof( buf )-1, pc);
2436 pic16_pCodeInsertAfter(pcprev, pic16_newpCodeCharP(buf));
2437 pcprev = pcprev->next;
2442 pc_cline2->pc.next = NULL;
2447 pCodeDeleteChain(pc,pcin);
2449 // fprintf(stderr, "%s:%d rule matched\n", __FILE__, __LINE__);
2451 /* Generate the replacement code */
2453 pcr = peepBlock->replace.pb->pcHead; // This is the replacement code
2457 /* If the replace pcode is an instruction with an operand, */
2458 /* then duplicate the operand (and expand wild cards in the process). */
2459 if(pcr->type == PC_OPCODE) {
2460 if(PCI(pcr)->pcop) {
2461 /* The replacing instruction has an operand.
2463 if(PCI(pcr)->pcop->type == PO_WILD) {
2464 int index = PCOW(PCI(pcr)->pcop)->id;
2465 // fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
2466 //DFPRINTF((stderr,"copying wildopcode\n"));
2467 if(peepBlock->target.wildpCodeOps[index])
2468 pcop = pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2470 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2472 pcop = pic16_pCodeOpCopy(PCI(pcr)->pcop);
2475 if(PCI(pcr)->is2MemOp && PCOP2(PCI(pcr)->pcop)->pcopR) {
2476 /* The replacing instruction has also a second operand.
2478 // fprintf(stderr, "%s:%d pcop2= %p\n", __FILE__, __LINE__, PCOR2(PCI(pcr)->pcop)->pcop2);
2479 if(PCOP2(PCI(pcr)->pcop)->pcopR->type == PO_WILD) {
2480 int index = PCOW2(PCI(pcr)->pcop)->id;
2481 // fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
2482 //DFPRINTF((stderr,"copying wildopcode\n"));
2483 if(peepBlock->target.wildpCodeOps[index])
2484 pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
2485 pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]), 0);
2487 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2489 pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
2490 pic16_pCodeOpCopy(PCOP2(PCI(pcr)->pcop)->pcopR), 0);
2494 //DFPRINTF((stderr,"inserting pCode\n"));
2495 pic16_pCodeInsertAfter(pc, pic16_newpCode(PCI(pcr)->op,pcop));
2496 } else if (pcr->type == PC_WILD) {
2497 if(PCW(pcr)->invertBitSkipInst)
2498 DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2499 pic16_pCodeInsertAfter(pc,
2500 pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2501 PCW(pcr)->invertBitSkipInst));
2502 } else if (pcr->type == PC_COMMENT) {
2503 pic16_pCodeInsertAfter(pc, pic16_newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2509 DFPRINTF((stderr," NEW Code:"));
2510 if(pc) pc->print(stderr,pc);
2515 /* We have just replaced the inefficient code with the rule.
2516 * Now, we need to re-add the C-source symbols if there are any */
2520 pc = pic16_findNextInstruction(pc->next);
2521 PCI(pc)->cline = pc_cline;
2522 pc_cline = PCCS(pc_cline->pc.next);
2529 peeprules = peeprules->next;
2531 DFPRINTF((stderr," no rule matched\n"));