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, size_t 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((unsigned char)*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((unsigned char)*bit) == 'C')
311 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_C_BIT));
312 if(toupper((unsigned char)*bit) == 'Z')
313 return PCOP(pic16_popCopyGPR2Bit(&pic16_pc_status,PIC_Z_BIT));
317 if(len ==2 && toupper((unsigned char)bit[0]) == 'D' && toupper((unsigned char)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, PO_GPR_REGISTER);
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 fprintf(stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
664 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
666 fprintf(stderr, "Bad mnemonic\n");
670 if(pic16Mnemonics[opcode]->isBitInst) {
671 pcosubtype = pic16_newpCodeOp(NULL,PO_BIT);
675 if(pic16Mnemonics[opcode]->is2MemOp) {
676 /* support for movff instruction */
677 pcosubtype = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
678 pcosubtype2 = pic16_newpCodeOp(p[3].pct[0].tok.s, PO_STR);
681 pcosubtype = pic16_newpCodeOp(NULL,PO_GPR_REGISTER); pcosubtype2 = NULL; }
685 pci = PCI(pic16_newpCode(opcode,
686 pic16_newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
688 pci = PCI(pic16_newpCode(opcode,
689 pic16_newpCodeOpWild2(p[1].pct[1].tok.n, p[3].pct[1].tok.n, pcwb, pcosubtype, pcosubtype2)));
691 /* Save the index of the maximum wildcard variable */
692 //if(p[1].pct[1].tok.n > sMaxWildVar)
693 // sMaxWildVar = p[1].pct[1].tok.n;
695 if(p[1].pct[1].tok.n > pcwb->nvars)
696 pcwb->nvars = p[1].pct[1].tok.n;
699 fprintf(stderr,"couldn't find mnemonic\n");
705 /*-----------------------------------------------------------------*/
706 /* cvt_altpat_mem2b - convert assembly line type to a pCode */
707 /* instruction with 2 wild operands */
710 /* pp[1] - wild var */
712 /* pp[3] - wild var */
714 /*-----------------------------------------------------------------*/
715 static void * cvt_altpat_mnem2b(void *pp,pCodeWildBlock *pcwb)
717 parsedPattern *p = pp;
721 pCodeInstruction *pci=NULL;
722 pCodeOp *pcosubtype, *pcosubtype2;
725 fprintf(stderr,"ERROR %s:%d - can't assemble line\n",__FILE__,__LINE__);
729 dest = cvt_extract_destination(&p[3]);
731 DFPRINTF((stderr,"altpat_mnem2b %s src %d dst (%d)\n",
737 fprintf(stderr,"altpat_mnem2b %s src: %d dst: %d\n",
743 opcode = pic16_getpCode(p->pct[0].tok.s,dest);
745 fprintf(stderr, "Bad mnemonic\n");
749 if(pic16Mnemonics[opcode]->is2MemOp) {
750 /* support for movff instruction */
751 pcosubtype = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
752 pcosubtype2 = pic16_newpCodeOp(NULL, PO_GPR_REGISTER);
753 } else pcosubtype = pcosubtype2 = NULL;
755 pci = PCI(pic16_newpCode(opcode,
756 pic16_newpCodeOpWild2(p[1].pct[1].tok.n, p[3].pct[1].tok.n,
757 pcwb, pcosubtype, pcosubtype2)));
759 /* Save the index of the maximum wildcard variable */
760 //if(p[1].pct[1].tok.n > sMaxWildVar)
761 // sMaxWildVar = p[1].pct[1].tok.n;
763 if(p[1].pct[1].tok.n > pcwb->nvars)
764 pcwb->nvars = p[1].pct[1].tok.n;
767 fprintf(stderr,"couldn't find mnemonic\n");
774 /*-----------------------------------------------------------------*/
775 /* cvt_altpat_mem3 - convert assembly line type to a pCode */
776 /* This rule is for bsf/bcf type instructions */
780 /* pp[1] - register */
784 /*-----------------------------------------------------------------*/
785 static void * cvt_altpat_mnem3(void *pp,pCodeWildBlock *pcwb)
787 parsedPattern *p = pp;
789 int dest; // or could be bit position in the register
791 pCodeInstruction *pci=NULL;
792 pCodeOp *pcosubtype=NULL;
794 dest = cvt_extract_destination(&p[3]);
796 DFPRINTF((stderr,"altpat_mnem3 %s var %s bit (%d)\n",
802 opcode = pic16_getpCode(p->pct[0].tok.s,0);
804 fprintf(stderr, "Bad mnemonic\n");
809 if(pic16Mnemonics[opcode]->isBitInst) {
810 //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
812 //if(pcosubtype == NULL) {
813 pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0, PO_GPR_REGISTER);
816 pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
818 if(pcosubtype == NULL) {
819 fprintf(stderr, "Bad operand\n");
823 pci = PCI(pic16_newpCode(opcode, pcosubtype));
826 fprintf(stderr,"couldn't find mnemonic\n");
832 /*-----------------------------------------------------------------*/
833 /* cvt_altpat_mem4 - convert assembly line type to a pCode */
834 /* This rule is for lfsr instruction */
842 /*-----------------------------------------------------------------*/
843 static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb)
845 parsedPattern *p = pp;
847 int dest; // or could be bit position in the register
849 pCodeInstruction *pci=NULL;
850 pCodeOp *pcosubtype=NULL;
852 dest = cvt_extract_destination(&p[3]);
854 DFPRINTF((stderr,"altpat_mnem4 %s fsr %d source %s\n",
859 opcode = pic16_getpCode(p->pct[0].tok.s,0);
861 fprintf(stderr, "Bad mnemonic\n");
864 DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
866 if(pic16Mnemonics[opcode]->is2LitOp) {
867 pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOp(p[3].pct[0].tok.s, PO_STR));
870 if(pcosubtype == NULL) {
871 fprintf(stderr, "Bad operand\n");
875 pci = PCI(pic16_newpCode(opcode, pcosubtype));
878 fprintf(stderr,"couldn't find mnemonic\n");
884 /*-----------------------------------------------------------------*/
885 /* cvt_altpat_mem4a - convert assembly line type to a pCode */
886 /* This rule is for lfsr instruction */
894 /*-----------------------------------------------------------------*/
895 static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb)
897 parsedPattern *p = pp;
899 int dest; // or could be bit position in the register
901 pCodeInstruction *pci=NULL;
902 pCodeOp *pcosubtype=NULL;
904 dest = cvt_extract_destination(&p[3]);
906 DFPRINTF((stderr,"altpat_mnem4a %s fsr %d value 0x%02x\n",
911 opcode = pic16_getpCode(p->pct[0].tok.s,0);
913 fprintf(stderr, "Bad mnemonic\n");
916 DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
918 if(pic16Mnemonics[opcode]->is2LitOp) {
919 pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOpLit(p[3].pct[0].tok.n));
922 if(pcosubtype == NULL) {
923 fprintf(stderr, "Bad operand\n");
927 pci = PCI(pic16_newpCode(opcode, pcosubtype));
930 fprintf(stderr,"couldn't find mnemonic\n");
936 /*-----------------------------------------------------------------*/
937 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
938 /* by SDCCpeeph.c into a string of tokens. */
941 /* The tokenizer is of the classic type. When an item is encounterd*/
942 /* it is converted into a token. The token is a structure that */
943 /* encodes the item's type and it's value (when appropriate). */
945 /* Accepted token types: */
946 /* SPACE NUMBER STRING % : , ; */
950 /*-----------------------------------------------------------------*/
953 static void tokenizeLineNode(char *ln)
956 tokIdx = 0; // Starting off at the beginning
957 tokArr[0].tt = PCT_NULL; // and assume invalid character for first token.
962 // fprintf(stderr, "%s:%d: processing %s\n", __FILE__, __LINE__, ln);
965 if(isspace((unsigned char)*ln)) {
966 // add a SPACE token and eat the extra spaces.
967 tokArr[tokIdx++].tt = PCT_SPACE;
968 while (isspace ((unsigned char)*ln))
973 if(isdigit((unsigned char)*ln)) {
975 tokArr[tokIdx].tt = PCT_NUMBER;
976 tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
984 tokArr[tokIdx++].tt = PCT_PERCENT;
987 tokArr[tokIdx++].tt = PCT_LESSTHAN;
990 tokArr[tokIdx++].tt = PCT_GREATERTHAN;
993 tokArr[tokIdx++].tt = PCT_COLON;
996 tokArr[tokIdx].tok.s = Safe_strdup(ln);
997 tokArr[tokIdx++].tt = PCT_COMMENT;
998 tokArr[tokIdx].tt = PCT_NULL;
1001 tokArr[tokIdx++].tt = PCT_COMMA;
1005 default: // hack to allow : goto $
1006 if(isalpha((unsigned char)*ln) || (*ln == '_') || (!parsing_peeps && (*ln == '$'))) {
1010 while( (isalpha((unsigned char)*ln) || isdigit((unsigned char)*ln) || (*ln == '_') || (*ln == '$')) && i<49)
1011 buffer[i++] = *ln++;
1016 tokArr[tokIdx].tok.s = Safe_strdup(buffer);
1017 tokArr[tokIdx++].tt = PCT_STRING;
1021 fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
1022 fprintf(stderr, "Line: %s\n",lnstart);
1023 fprintf(stderr, "Token: '%c'\n",*ln);
1029 /* Advance to next character in input string .
1030 * Note, if none of the tests passed above, then
1031 * we effectively ignore the `bad' character.
1032 * Since the line has already been parsed by SDCCpeeph,
1033 * chance are that there are no invalid characters... */
1039 tokArr[tokIdx].tt = 0;
1043 /*-----------------------------------------------------------------*/
1044 /*-----------------------------------------------------------------*/
1048 static void dump1Token(pCodeTokens tt)
1053 fprintf(stderr, " space ");
1056 fprintf(stderr, " pct %%");
1059 fprintf(stderr, " pct <");
1061 case PCT_GREATERTHAN:
1062 fprintf(stderr, " pct >");
1065 fprintf(stderr, " col :");
1068 fprintf(stderr, " comma , ");
1071 fprintf(stderr, " comment ");
1072 //fprintf(stderr,"%s",tokArr[i].tok.s);
1075 fprintf(stderr, " str ");
1076 //fprintf(stderr,"%s",tokArr[i].tok.s);
1079 fprintf(stderr, " num ");
1080 //fprintf(stderr,"%d",tokArr[i].tok.n);
1083 fprintf(stderr, " null ");
1090 /*-----------------------------------------------------------------*/
1091 /*-----------------------------------------------------------------*/
1093 static int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
1097 if(!pct || !pat || !*pat)
1100 //DFPRINTF((stderr,"comparing against:\n"));
1102 while(i < max_tokens) {
1105 //DFPRINTF((stderr,"matched\n"));
1109 // dump1Token(*pat); fputc('\n', stderr); DFPRINTF((stderr,"\n"));
1123 /*-----------------------------------------------------------------*/
1124 /*-----------------------------------------------------------------*/
1126 static int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
1130 if(!pct || !pat || !*pct)
1134 while(i < max_tokens) {
1137 DFPRINTF((stderr,"matched\n"));
1141 // dump1Token(*pat); DFPRINTF((stderr,"\n"));
1143 if( !pat || !pat->pcp )
1146 if (pat->pcp->pt != *pct)
1149 DFPRINTF((stderr," pct=%d\n",*pct));
1158 /*-----------------------------------------------------------------*/
1159 /*-----------------------------------------------------------------*/
1161 static int advTokIdx(int *v, int amt)
1164 if((unsigned) (*v + amt) > tokIdx)
1172 /*-----------------------------------------------------------------*/
1173 /* parseTokens - convert the tokens corresponding to a single line */
1174 /* of a peep hole assembly into a pCode object. */
1179 /* This is a simple parser that looks for strings of the type */
1180 /* allowed in the peep hole definition file. Essentially the format*/
1181 /* is the same as a line of assembly: */
1183 /* label: mnemonic op1, op2, op3 ; comment */
1185 /* Some of these items aren't present. It's the job of the parser */
1186 /* to determine which are and convert those into the appropriate */
1188 /*-----------------------------------------------------------------*/
1190 static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
1201 for(i=0; i<=tokIdx; i++)
1202 dump1Token(tokArr[i].tt);
1208 int lparsedPatIdx=0;
1215 char * cPmnem = NULL; // Pointer to non-wild mnemonic (if any)
1216 char * cP1stop = NULL;
1217 char * cP2ndop = NULL;
1219 //pCodeOp *pcl = NULL; // Storage for a label
1220 //pCodeOp *pco1 = NULL; // 1st operand
1221 //pCodeOp *pco2 = NULL; // 2nd operand
1222 //pCode *pc = NULL; // Mnemonic
1233 ParseStates state = PS_START;
1240 if( ((tokArr[ltokIdx].tt == PCT_SPACE) )
1241 && (advTokIdx(<okIdx, 1)) ) // eat space
1245 j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
1248 switch(pcpArr[lpcpIdx].pt) {
1250 if(state == PS_START){
1251 DFPRINTF((stderr," label\n"));
1252 state = PS_HAVE_LABEL;
1254 DFPRINTF((stderr," bad state (%d) for label\n",state));
1258 DFPRINTF((stderr," %s is",tokArr[ltokIdx].tok.s));
1262 DFPRINTF((stderr," mnem\n"));
1263 cPmnem = tokArr[ltokIdx].tok.s;
1264 state = PS_HAVE_MNEM;
1267 DFPRINTF((stderr," 1st operand\n"));
1268 cP1stop = tokArr[ltokIdx].tok.s;
1269 //pco1 = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
1270 state = PS_HAVE_1OPERAND;
1272 case PS_HAVE_1OPERAND:
1273 DFPRINTF((stderr," error expecting comma\n"));
1276 DFPRINTF((stderr," 2 operands\n"));
1277 cP2ndop = tokArr[ltokIdx].tok.s;
1279 case PS_HAVE_2OPERANDS:
1288 DFPRINTF((stderr," wild mnem\n"));
1289 state = PS_HAVE_MNEM;
1292 DFPRINTF((stderr," 1st operand is wild\n"));
1293 state = PS_HAVE_1OPERAND;
1295 case PS_HAVE_1OPERAND:
1296 DFPRINTF((stderr," error expecting comma\n"));
1299 DFPRINTF((stderr," 2nd operand is wild\n"));
1301 case PS_HAVE_2OPERANDS:
1310 fprintf(stderr," ERROR number\n");
1313 DFPRINTF((stderr," 1st operand is a number\n"));
1314 state = PS_HAVE_1OPERAND;
1316 case PS_HAVE_1OPERAND:
1317 fprintf(stderr," error expecting comma\n");
1320 DFPRINTF((stderr," 2nd operand is a number\n"));
1322 case PS_HAVE_2OPERANDS:
1330 if(state == PS_HAVE_1OPERAND){
1331 DFPRINTF((stderr," got a comma\n"));
1332 state = PS_HAVE_COMMA;
1334 fprintf(stderr," unexpected comma\n");
1340 parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1341 parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1344 // dump1Token(tokArr[ltokIdx].tt);
1346 if(advTokIdx(<okIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1347 DFPRINTF((stderr," reached end \n"));
1354 } while ((++lpcpIdx < PCPATTERNS) && !matching);
1358 parsedPatArr[lparsedPatIdx].pcp = NULL;
1359 parsedPatArr[lparsedPatIdx].pct = NULL;
1365 if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1368 pc = altArr[k].f(&parsedPatArr[j],pcwb);
1369 //if(pc && pc->print)
1370 // pc->print(stderr,pc);
1371 //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1373 //if(curBlock && pc)
1374 //pic16_addpCode2pBlock(curBlock, pc);
1378 return 0; // Only accept one line for now.
1380 pic16_addpCode2pBlock(pcwb->pb, pc);
1388 while(j<=lparsedPatIdx && k<ALTPATTERNS);
1391 DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1395 if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1396 parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1397 DFPRINTF((stderr," %d",parsedPatArr[j].pcp->pt));
1400 while(j<lparsedPatIdx);
1402 DFPRINTF((stderr,"\n"));
1409 /*-----------------------------------------------------------------*/
1411 /*-----------------------------------------------------------------*/
1412 static void peepRuleBlock2pCodeBlock( lineNode *ln, pCodeWildBlock *pcwb)
1418 for( ; ln; ln = ln->next) {
1420 //DFPRINTF((stderr,"%s\n",ln->line));
1421 // fprintf(stderr, "peep rule : %s\n", ln->line);
1423 tokenizeLineNode(ln->line);
1425 if(parseTokens(pcwb,NULL)) {
1427 fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
1428 fprintf(stderr,"Tokens:\n");
1430 dump1Token(tokArr[i].tt);
1437 /*-----------------------------------------------------------------*/
1438 /* pic16_AssembleLine - parse line and return the pCode equivalent */
1439 /* peeps=1 if parsing peep rules, 0 otherwise */
1440 /*-----------------------------------------------------------------*/
1441 pCode *pic16_AssembleLine(char *line, int peeps)
1445 if(!line || !*line) {
1446 fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
1450 parsing_peeps = peeps;
1452 tokenizeLineNode(line);
1454 if(parseTokens(NULL,&pc))
1455 fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
1457 DFPRINTF((stderr, "pc= %p\n", pc));
1458 // if(pc)pc->print(stderr, pc);
1466 /*-----------------------------------------------------------------*/
1467 /* peepRuleCondition */
1468 /*-----------------------------------------------------------------*/
1469 static void peepRuleCondition(char *cond, pCodePeep *pcp)
1474 //DFPRINTF((stderr,"\nCondition: %s\n",cond));
1475 /* brute force compares for now */
1477 if(STRCASECMP(cond, "NZ") == 0) {
1478 //DFPRINTF((stderr,"found NZ\n"));
1479 pcp->postFalseCond = PCC_Z;
1486 static void initpCodeWildBlock(pCodeWildBlock *pcwb)
1489 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1495 pcwb->wildpCodes = NULL;
1496 pcwb->wildpCodeOps = NULL;
1499 pcwb->nwildpCodes = 0;
1504 static void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1511 pcwb->nops = pcwb->nvars;
1513 pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1514 pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1516 pcwb->nwildpCodes+=2;
1517 pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1521 static void initpCodePeep(pCodePeep *pcp)
1524 // pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1529 initpCodeWildBlock(&pcp->target);
1530 pcp->target.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1532 initpCodeWildBlock(&pcp->replace);
1533 pcp->replace.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1537 /*-----------------------------------------------------------------*/
1538 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1541 /* SDCCpeeph parses the peep rules file and extracts variables, */
1542 /* removes white space, and checks the syntax. This function */
1543 /* extends that processing to produce pCode objects. You can kind */
1544 /* think of this function as an "assembler", though instead of */
1545 /* taking raw text to produce machine code, it produces pCode. */
1547 /*-----------------------------------------------------------------*/
1548 extern void pic16initpCodePeepCommands(void);
1550 void pic16_peepRules2pCode(peepRule *rules)
1554 pCodePeep *currentRule;
1555 pCodePeepSnippets *pcps;
1557 pic16initpCodePeepCommands();
1559 /* The rules are in a linked-list. Each rule has two portions */
1560 /* There's the `target' and there's the `replace'. The target */
1561 /* is compared against the SDCC generated code and if it */
1562 /* matches, it gets replaced by the `replace' block of code. */
1564 /* Here we loop through each rule and convert the target's and*/
1565 /* replace's into pCode target and replace blocks */
1567 for (pr = rules; pr; pr = pr->next) {
1569 //DFPRINTF((stderr,"\nRule:\n\n"));
1571 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1572 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1574 currentRule = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1575 initpCodePeep(currentRule);
1577 /* Convert the target block */
1578 peepRuleBlock2pCodeBlock(pr->match, ¤tRule->target);
1580 //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1581 // pic16_printpBlock(stderr, currentRule->target.pb);
1583 //DFPRINTF((stderr,"target with labels merged:\n"));
1584 //pic16_pBlockMergeLabels(curBlock);
1585 pic16_pBlockMergeLabels(currentRule->target.pb);
1586 //pic16_printpBlock(stderr, currentRule->replace.pb);
1588 //#ifdef PCODE_DEBUG
1589 // pic16_printpBlock(stderr, curBlock);
1591 //DFPRINTF((stderr,"\nReplaced by:\n"));
1594 /* Convert the replace block */
1595 peepRuleBlock2pCodeBlock(pr->replace, ¤tRule->replace);
1597 //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1598 //pic16_printpBlock(stderr, curBlock);
1600 //DFPRINTF((stderr,"replace with labels merged:\n"));
1602 pic16_pBlockMergeLabels(currentRule->replace.pb);
1603 //pic16_printpBlock(stderr, currentRule->replace.pb);
1605 peepRuleCondition(pr->cond,currentRule);
1607 /* The rule has been converted to pCode. Now allocate
1608 * space for the wildcards */
1610 postinit_pCodeWildBlock(¤tRule->target);
1611 postinit_pCodeWildBlock(¤tRule->replace);
1613 //return; // debug ... don't want to go through all the rules yet
1617 pCodePeep *peepBlock;
1620 peeprules = (_DLL *)peepSnippets;
1621 //fprintf(stderr,"target rules\n");
1623 //fprintf(stderr," rule:\n");
1624 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1625 //pic16_printpBlock(stderr, peepBlock->target.pb);
1626 peeprules = peeprules->next;
1628 //fprintf(stderr," ... done\n");
1633 static void printpCodeString(FILE *of, pCode *pc, int max)
1637 while(pc && (i++<max)) {
1643 /*-----------------------------------------------------------------*/
1644 /* _DLL * DLL_append */
1646 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
1647 /* If The list to which we want to append is non-existant then one */
1648 /* is created. Other wise, the end of the list is sought out and */
1649 /* a new DLL object is appended to it. In either case, the void */
1650 /* *data is added to the newly created DLL object. */
1651 /*-----------------------------------------------------------------*/
1653 static void * DLL_append(_DLL *list, _DLL *next)
1658 /* If there's no list, then create one: */
1660 next->next = next->prev = NULL;
1665 /* Search for the end of the list. */
1670 /* Now append the new DLL object */
1681 /*-----------------------------------------------------------------
1683 pCode peephole optimization
1686 The pCode "peep hole" optimization is not too unlike the peep hole
1687 optimization in SDCCpeeph.c. The major difference is that here we
1688 use pCode's whereas there we use ASCII strings. The advantage with
1689 pCode's is that we can ascertain flow information in the instructions
1693 <FIX ME> - elaborate...
1695 -----------------------------------------------------------------*/
1699 /*-----------------------------------------------------------------*/
1700 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1702 /* return conditions */
1703 /* 1 - The Condition was found for a pCode's input */
1704 /* 0 - No matching condition was found for the whole chain */
1705 /* -1 - The Condition was found for a pCode's output */
1707 /*-----------------------------------------------------------------*/
1708 int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond)
1710 //fprintf(stderr,"Checking conditions %d\n",cond);
1713 /* If we reach a function end (presumably an end since we most
1714 probably began the search in the middle of a function), then
1715 the condition was not found. */
1716 if(pc->type == PC_FUNCTION)
1719 if(pc->type == PC_OPCODE) {
1720 //fprintf(stderr," checking conditions of: ");
1721 //pc->print(stderr,pc);
1722 //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
1723 if(PCI(pc)->inCond & cond)
1725 if(PCI(pc)->outCond & cond)
1735 /*-----------------------------------------------------------------
1736 * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1738 * Compare two pCodeOp's and return 1 if they're the same
1739 *-----------------------------------------------------------------*/
1740 static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1744 if(!pcops || !pcopd)
1748 fprintf(stderr,"%s:%d Comparing operands %s", __FILE__, __LINE__,
1749 pic16_get_op( pcops,NULL,0));
1751 fprintf(stderr," to %s\n",
1752 pic16_get_op( pcopd,NULL,0));
1755 if(pcops->type != pcopd->type) {
1756 //fprintf(stderr," - fail - diff types\n");
1757 return 0; // different types
1760 if(pcops->type == PO_LITERAL) {
1762 if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
1768 memset(b, 0, sizeof(b) ); //b[0]=0;
1769 pic16_get_op(pcops,b, sizeof(b) );
1771 n2 = pic16_get_op(pcopd,NULL,0);
1773 if( !n2 || strcmp(b,n2)) {
1774 // fprintf(stderr," - fail - diff names: %s, len=%d, %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1775 return 0; // different names
1778 switch(pcops->type) {
1780 if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1781 // fprintf(stderr, " - fail different instances\n");
1789 //fprintf(stderr," - pass\n");
1794 static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1798 /* Check for a label associated with this wild pCode */
1799 // If the wild card has a label, make sure the source code does too.
1800 if(PCI(pcd)->label) {
1801 pCode *pcl = PCI(pcd)->label->pc;
1804 int li = -PCL(pcl)->key;
1806 if(peepBlock->target.vars[li] == NULL) {
1807 if(PCI(pcs)->label) {
1808 DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1811 // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1812 DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1813 if(PCI(pcs)->label) {
1814 DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1820 if(!PCI(pcs)->label)
1823 labindex = -PCL(pcl)->key;
1824 if(peepBlock->target.vars[labindex] == NULL) {
1825 // First time to encounter this label
1826 peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1827 DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1830 if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1831 DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1834 DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1837 //DFPRINTF((stderr,"destination doesn't have a label\n"));
1842 //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1850 /*-----------------------------------------------------------------*/
1851 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1852 /* see they're the same. */
1854 /* In this context, "source" refers to the coded generated by gen.c*/
1855 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1856 /* ination has no wild cards, then MatchLine will compare the two */
1857 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1858 /* has wildcards, then those get expanded. When a wild card is */
1859 /* encountered for the first time it autmatically is considered a */
1860 /* match and the object that matches it is referenced in the */
1861 /* variables or opcodes array (depending on the type of match). */
1865 /* *peepBlock - A pointer to the peepBlock that contains the */
1866 /* entire rule to which the destination pcode belongs*/
1867 /* *pcs - a pointer to the source pcode */
1868 /* *pcd - a pointer to the destination pcode */
1871 /* 1 - pcodes match */
1872 /* 0 - pcodes don't match */
1875 /*-----------------------------------------------------------------*/
1877 static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1879 int index; // index into wild card arrays
1882 /* one-for-one match. Here the source and destination opcodes
1883 * are not wild. However, there may be a label or a wild operand */
1886 if(PCI(pcs)->label) {
1887 DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1891 if(pcs->type == pcd->type) {
1893 if(pcs->type == PC_OPCODE) {
1895 /* If the opcodes don't match then the line doesn't match */
1896 if(PCI(pcs)->op != PCI(pcd)->op)
1900 DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1901 pcs->print(stderr,pcs);
1902 pcd->print(stderr,pcd);
1905 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1908 /* Compare the operands */
1909 if(PCI(pcd)->pcop) {
1910 /* assert that optimizations do not touch operations that work on SFRs or INDF registers */
1911 if ((PCI(pcd)->pcop->type == PO_WILD) && (!(PCI(pcs)->pcop) || ((PCI(pcs)->pcop->type != PO_SFR_REGISTER) && (PCI(pcs)->pcop->type != PO_INDF0)))) {
1912 index = PCOW(PCI(pcd)->pcop)->id;
1913 //DFPRINTF((stderr,"destination is wild\n"));
1914 #ifdef DEBUG_PCODEPEEP
1915 if (index > peepBlock->nops) {
1916 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1921 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1923 if(!peepBlock->target.wildpCodeOps[index]) {
1924 peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1926 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1930 pcs->print(stderr,pcs);
1931 pcd->print(stderr,pcd);
1933 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1934 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1938 havematch = pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1939 // return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1942 if((havematch==-1) && PCI(pcs)->pcop) {
1945 switch(PCI(pcs)->pcop->type) {
1949 n = PCOR(PCI(pcs)->pcop)->r->name;
1953 n = PCI(pcs)->pcop->name;
1956 if(peepBlock->target.vars[index])
1957 return (strcmp(peepBlock->target.vars[index],n) == 0);
1959 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1960 peepBlock->target.vars[index] = n;
1966 /* now check whether the second operand matches */
1967 /* assert that optimizations do not touch operations that work on SFRs or INDF registers */
1968 if(PCOW2(PCI(pcd)->pcop) && (PCOR2(PCI(pcd)->pcop)->pcop2->type == PO_WILD) && (!(PCOR2(PCI(pcs)->pcop)->pcop2) || ((PCOR2(PCI(pcs)->pcop)->pcop2->type != PO_SFR_REGISTER) && (PCOR2(PCI(pcs)->pcop)->pcop2) && (PCOR2(PCI(pcs)->pcop)->pcop2->type != PO_INDF0)))) {
1970 // fprintf(stderr, "%s:%d %s second operand is wild\n", __FILE__, __LINE__, __FUNCTION__);
1972 index = PCOW2(PCI(pcd)->pcop)->id;
1973 //DFPRINTF((stderr,"destination is wild\n"));
1974 #ifdef DEBUG_PCODEPEEP
1975 if (index > peepBlock->nops) {
1976 DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1981 PCOW2(PCI(pcd)->pcop)->matched = PCOR2(PCI(pcs)->pcop)->pcop2;
1982 if(!peepBlock->target.wildpCodeOps[index]) {
1983 peepBlock->target.wildpCodeOps[index] = PCOR2(PCI(pcs)->pcop)->pcop2;
1985 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1989 pcs->print(stderr,pcs);
1990 pcd->print(stderr,pcd);
1992 fprintf(stderr, "comparing operands of these instructions, result %d\n",
1993 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1997 return ((havematch==1) && pCodeOpCompare(PCOR2(PCI(pcs)->pcop)->pcop2,
1998 peepBlock->target.wildpCodeOps[index]));
2001 if(PCOR2(PCI(pcs)->pcop)->pcop2) {
2004 switch(PCOR2(PCI(pcs)->pcop)->pcop2->type) {
2008 n = PCOR(PCOR2(PCI(pcs)->pcop)->pcop2)->r->name;
2011 n = PCOR2(PCI(pcs)->pcop)->pcop2->name;
2014 if(peepBlock->target.vars[index])
2015 return (havematch && (strcmp(peepBlock->target.vars[index],n) == 0));
2017 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
2018 peepBlock->target.vars[index] = n;
2019 return (havematch==1); //&& 1;
2023 } else if (PCOW2(PCI(pcd)->pcop) && (PCOR2(PCI(pcd)->pcop)->pcop2->type == PO_WILD) && PCOR2(PCI(pcs)->pcop)->pcop2)
2030 else if (PCI(pcd)->pcop->type == PO_LITERAL) {
2031 return (havematch &&
2032 pCodeOpCompare(PCOR2(PCI(pcs)->pcop)->pcop2, PCOR2(PCI(pcd)->pcop)->pcop2));
2037 } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
2038 return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
2043 /* FIXME - need an else to check the case when the destination
2044 * isn't a wild card */
2046 /* The pcd has no operand. Lines match if pcs has no operand either*/
2047 return (PCI(pcs)->pcop == NULL);
2050 /* Compare a wild instruction to a regular one. */
2052 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
2054 index = PCW(pcd)->id;
2056 DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
2057 pcs->print(stderr,pcs);
2058 pcd->print(stderr,pcd);
2060 peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
2062 if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
2063 DFPRINTF((stderr," Failing because labels don't match\n"));
2067 if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
2068 // doesn't match because the wild pcode must be a bit skip
2069 DFPRINTF((stderr," Failing match because bit skip is req\n"));
2070 //pcd->print(stderr,pcd);
2071 //pcs->print(stderr,pcs);
2075 if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
2076 // doesn't match because the wild pcode must *not* be a bit skip
2077 DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
2078 //pcd->print(stderr,pcd);
2079 //pcs->print(stderr,pcs);
2083 if(PCW(pcd)->operand) {
2084 PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
2085 if(peepBlock->target.vars[index]) {
2086 int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
2090 DFPRINTF((stderr," (matched)\n"));
2092 DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
2093 DFPRINTF((stderr," peepblock= %s, pcodeop= %s\n",
2094 peepBlock->target.vars[index],
2095 PCI(pcs)->pcop->name));
2100 DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
2101 peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
2106 pcs = pic16_findNextInstruction(pcs->next);
2108 //DFPRINTF((stderr," (next to match)\n"));
2109 //pcs->print(stderr,pcs);
2110 } else if(pcd->next) {
2111 /* oops, we ran out of code, but there's more to the rule */
2115 return 1; /* wild card matches */
2121 /*-----------------------------------------------------------------*/
2122 /*-----------------------------------------------------------------*/
2123 static void pCodePeepClrVars(pCodePeep *pcp)
2130 DFPRINTF((stderr," Clearing peep rule vars\n"));
2131 DFPRINTF((stderr," %d %d %d %d %d %d\n",
2132 pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
2133 pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
2135 for(i=0;i<pcp->target.nvars; i++)
2136 pcp->target.vars[i] = NULL;
2137 for(i=0;i<pcp->target.nops; i++)
2138 pcp->target.wildpCodeOps[i] = NULL;
2139 for(i=0;i<pcp->target.nwildpCodes; i++)
2140 pcp->target.wildpCodes[i] = NULL;
2142 for(i=0;i<pcp->replace.nvars; i++)
2143 pcp->replace.vars[i] = NULL;
2144 for(i=0;i<pcp->replace.nops; i++)
2145 pcp->replace.wildpCodeOps[i] = NULL;
2146 for(i=0;i<pcp->replace.nwildpCodes; i++)
2147 pcp->replace.wildpCodes[i] = NULL;
2153 /*-----------------------------------------------------------------*/
2154 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2155 /* into the pCode chain containing pc1 */
2156 /*-----------------------------------------------------------------*/
2157 void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2)
2163 pc2->next = pc1->next;
2165 pc1->next->prev = pc2;
2173 /*-----------------------------------------------------------------*/
2174 /* pic16_pCodeOpCopy - copy a pcode operator */
2175 /*-----------------------------------------------------------------*/
2176 pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
2178 pCodeOp *pcopnew=NULL;
2183 switch(pcop->type) {
2186 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2187 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2188 PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2189 PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2194 /* Here we expand the wild card into the appropriate type: */
2195 /* By recursively calling pCodeOpCopy */
2196 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2197 if(PCOW(pcop)->matched)
2198 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->matched);
2201 pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->subtype);
2202 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2203 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2210 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2211 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2212 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
2216 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2217 PCOI(pcopnew)->index = PCOI(pcop)->index;
2218 PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2219 PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2223 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2224 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2225 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2228 #if 0 // mdubuc - To add
2235 pcopnew = pic16_newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace, PO_GPR_REGISTER);
2236 PCOR(pcopnew)->r = PCOR(pcop)->r;
2237 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2238 DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2242 case PO_GPR_REGISTER:
2246 case PO_WREG: // moved from below
2247 case PO_PRODL: // moved from below
2248 case PO_PRODH: // moved from below
2249 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2250 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2251 PCOR(pcopnew)->r = PCOR(pcop)->r;
2252 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2253 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2254 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2258 //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2259 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2260 PCOR(pcopnew)->r = PCOR(pcop)->r;
2261 PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2262 PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2265 DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2267 DFPRINTF((stderr,"pCodeOpCopy PO_BSR\n"));
2268 case PO_SFR_REGISTER:
2272 //case PO_WREG: // moved up
2277 //case PO_PRODL: // moved up
2278 //case PO_PRODH: // moved up
2280 //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2281 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2285 pcopnew->type = pcop->type;
2287 pcopnew->name = Safe_strdup(pcop->name);
2289 pcopnew->name = NULL;
2295 /*-----------------------------------------------------------------*/
2296 /* pCodeCopy - copy a pcode */
2297 /*-----------------------------------------------------------------*/
2298 static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2300 pCodeInstruction *new_pci;
2303 new_pci = PCI(pic16_newpCode(pci->inverted_op,pci->pcop));
2305 new_pci = PCI(pic16_newpCode(pci->op,pci->pcop));
2307 new_pci->pc.pb = pci->pc.pb;
2308 new_pci->from = pci->from;
2309 new_pci->to = pci->to;
2310 new_pci->label = pci->label;
2311 new_pci->pcflow = pci->pcflow;
2313 return PCODE(new_pci);
2316 /*-----------------------------------------------------------------*/
2317 /*-----------------------------------------------------------------*/
2318 static void pCodeDeleteChain(pCode *f,pCode *t)
2324 DFPRINTF((stderr,"delete pCode:\n"));
2326 //f->print(stderr,f);
2327 //f->delete(f); this dumps core...
2334 /*-----------------------------------------------------------------*/
2335 /*-----------------------------------------------------------------*/
2336 int pic16_pCodePeepMatchRule(pCode *pc)
2338 pCodePeep *peepBlock;
2340 pCodeCSource *pc_cline=NULL;
2345 peeprules = (_DLL *)peepSnippets;
2348 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
2350 if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
2351 fprintf(stderr, "skipping rule because target pb is NULL\n");
2355 pCodePeepClrVars(peepBlock);
2358 if(IS_PCCOMMENT(pcin))
2359 pc = pcin = pic16_findNextInstruction(pcin->next);
2361 pcin = pc = pic16_findNextInstruction(pc);
2363 pct = peepBlock->target.pb->pcHead;
2366 pCode *pcr = peepBlock->replace.pb->pcHead;
2367 if(pcr) pct->print(stderr,pcr);
2371 while(pct && pcin) {
2373 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
2376 pcin = pic16_findNextInstruction(pcin->next);
2379 //DFPRINTF((stderr," matched\n"));
2382 DFPRINTF((stderr," partial match... no more code\n"));
2383 // fprintf(stderr," partial match... no more code\n");
2387 DFPRINTF((stderr," end of rule\n"));
2391 if(matched && pcin) {
2393 /* So far we matched the rule up to the point of the conditions .
2394 * In other words, all of the opcodes match. Now we need to see
2395 * if the post conditions are satisfied.
2396 * First we check the 'postFalseCond'. This means that we check
2397 * to see if any of the subsequent pCode's in the pCode chain
2398 * following the point just past where we have matched depend on
2399 * the `postFalseCond' as input then we abort the match
2401 DFPRINTF((stderr," matched rule so far, now checking conditions\n"));
2402 //pcin->print(stderr,pcin);
2404 if (pcin && peepBlock->postFalseCond &&
2405 (pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
2408 // fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
2411 //if(!matched) fprintf(stderr,"failed on conditions\n");
2420 /* We matched a rule! Now we have to go through and remove the
2421 inefficient code with the optimized version */
2423 DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
2424 // printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
2425 DFPRINTF((stderr,"first thing matched\n"));
2426 pc->print(stderr,pc);
2428 DFPRINTF((stderr,"last thing matched\n"));
2429 pcin->print(stderr,pcin);
2434 /* Unlink the original code */
2436 pcprev->next = pcin;
2438 pcin->prev = pc->prev;
2444 /* Converted the deleted pCodes into comments */
2447 pCodeCSource *pc_cline2=NULL;
2452 while(pc && pc!=pcin) {
2454 if(pc->type == PC_OPCODE && PCI(pc)->cline) {
2456 pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2457 pc_cline2 = PCCS(pc_cline2->pc.next);
2459 pc_cline = pc_cline2 = PCI(pc)->cline;
2460 pc_cline->pc.seq = pc->seq;
2464 pic16_pCode2str(&buf[1], sizeof( buf )-1, pc);
2465 pic16_pCodeInsertAfter(pcprev, pic16_newpCodeCharP(buf));
2466 pcprev = pcprev->next;
2471 pc_cline2->pc.next = NULL;
2476 pCodeDeleteChain(pc,pcin);
2478 // fprintf(stderr, "%s:%d rule matched\n", __FILE__, __LINE__);
2480 /* Generate the replacement code */
2482 pcr = peepBlock->replace.pb->pcHead; // This is the replacement code
2486 /* If the replace pcode is an instruction with an operand, */
2487 /* then duplicate the operand (and expand wild cards in the process). */
2488 if(pcr->type == PC_OPCODE) {
2489 if(PCI(pcr)->pcop) {
2490 /* The replacing instruction has an operand.
2492 if(PCI(pcr)->pcop->type == PO_WILD) {
2493 int index = PCOW(PCI(pcr)->pcop)->id;
2494 // fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
2495 //DFPRINTF((stderr,"copying wildopcode\n"));
2496 if(peepBlock->target.wildpCodeOps[index])
2497 pcop = pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2499 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2501 pcop = pic16_pCodeOpCopy(PCI(pcr)->pcop);
2504 if(PCI(pcr)->is2MemOp && PCOR2(PCI(pcr)->pcop)->pcop2) {
2505 /* The replacing instruction has also a second operand.
2507 // fprintf(stderr, "%s:%d pcop2= %p\n", __FILE__, __LINE__, PCOR2(PCI(pcr)->pcop)->pcop2);
2508 if(PCOR2(PCI(pcr)->pcop)->pcop2->type == PO_WILD) {
2509 int index = PCOW2(PCI(pcr)->pcop)->id;
2510 // fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
2511 //DFPRINTF((stderr,"copying wildopcode\n"));
2512 if(peepBlock->target.wildpCodeOps[index])
2513 pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
2514 pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]), 0);
2516 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2518 pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
2519 pic16_pCodeOpCopy(PCOR2(PCI(pcr)->pcop)->pcop2), 0);
2523 //DFPRINTF((stderr,"inserting pCode\n"));
2524 pic16_pCodeInsertAfter(pc, pic16_newpCode(PCI(pcr)->op,pcop));
2525 } else if (pcr->type == PC_WILD) {
2526 if(PCW(pcr)->invertBitSkipInst)
2527 DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2528 pic16_pCodeInsertAfter(pc,
2529 pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2530 PCW(pcr)->invertBitSkipInst));
2531 } else if (pcr->type == PC_COMMENT) {
2532 pic16_pCodeInsertAfter(pc, pic16_newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2538 DFPRINTF((stderr," NEW Code:"));
2539 if(pc) pc->print(stderr,pc);
2544 /* We have just replaced the inefficient code with the rule.
2545 * Now, we need to re-add the C-source symbols if there are any */
2549 pc = pic16_findNextInstruction(pc->next);
2550 PCI(pc)->cline = pc_cline;
2551 pc_cline = PCCS(pc_cline->pc.next);
2558 peeprules = peeprules->next;
2560 DFPRINTF((stderr," no rule matched\n"));