Operand comparisons were unnecessarily failing in the pCode peep hole optimizer.
[fw/sdcc] / src / pic / pcodepeep.c
1 /*-------------------------------------------------------------------------
2
3    pcodepeep.c - post code generation
4    Written By -  Scott Dattalo scott@dattalo.com
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include "common.h"   // Include everything in the SDCC src directory
25 #include "newalloc.h"
26 //#define PCODE_DEBUG
27 #include "pcode.h"
28 #include "pcodeflow.h"
29 #include "ralloc.h"
30
31 #if defined(__BORLANDC__) || defined(_MSC_VER)
32 #define STRCASECMP stricmp
33 #else
34 #define STRCASECMP strcasecmp
35 #endif
36
37 pCodeOp *popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
38
39
40 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype);
41 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
42 pCode * findNextInstruction(pCode *pc);
43 int getpCode(char *mnem,int dest);
44 int getpCodePeepCommand(char *cmd);
45 void pBlockMergeLabels(pBlock *pb);
46 char *pCode2str(char *str, int size, pCode *pc);
47 char *get_op( pCodeOp *pcop,char *buf,int buf_size);
48
49 extern pCodeInstruction *pic14Mnemonics[];
50
51
52 #define IS_PCCOMMENT(x) ( x && (x->type==PC_COMMENT))
53
54 /****************************************************************/
55 /*
56  * rootRules - defined in SDCCpeep.c
57  *  This is a pointer to the (parsed) peephole rules that are
58  * defined in peep.def.
59  */
60
61 //extern peepRule *rootRules;
62
63
64
65
66 /****************************************************************/
67 /****************************************************************/
68 typedef struct _DLL {
69   struct _DLL *prev;
70   struct _DLL *next;
71   //  void *data;
72 } _DLL;
73
74
75 typedef struct pCodePeepSnippets
76 {
77   _DLL dll;
78   pCodePeep *peep;
79 } pCodePeepSnippets;
80
81
82 /****************************************************************/
83 /*                                                              */
84 /* peepSnippets -                                               */
85 /*                                                              */
86 /****************************************************************/
87
88 static pCodePeepSnippets  *peepSnippets=NULL;
89
90 /****************************************************************/
91 /*                                                              */
92 /* curPeep                                                      */
93 /*                                                              */
94 /****************************************************************/
95
96 //static pCodePeep          *curPeep=NULL;
97
98 /****************************************************************/
99 /*                                                              */
100 /* curBlock                                                     */
101 /*                                                              */
102 /****************************************************************/
103
104 //static pBlock             *curBlock=NULL;
105
106
107 /****************************************************************/
108 /*                                                              */
109 /* max wild cards in a peep rule                                */
110 /*                                                              */
111 /****************************************************************/
112
113 //static int                sMaxWildVar   = 0;
114 //static int                sMaxWildMnem  = 0;
115
116
117 typedef struct pCodeToken 
118 {
119   int tt;  // token type;
120   union {
121     char c;  // character
122     int  n;  // number
123     char *s; // string
124   } tok;
125
126 } pCodeToken;
127
128 pCodeToken tokArr[50];
129 unsigned   tokIdx=0;
130
131
132 typedef enum  {
133   PCT_NULL=0,
134   PCT_SPACE=1,
135   PCT_PERCENT,
136   PCT_LESSTHAN,
137   PCT_GREATERTHAN,
138   PCT_COLON,
139   PCT_COMMA,
140   PCT_COMMENT,
141   PCT_STRING,
142   PCT_NUMBER
143
144 } pCodeTokens;
145
146
147 typedef struct parsedPattern {
148   struct pcPattern *pcp;
149   pCodeToken *pct;
150 } parsedPattern;
151
152 #define MAX_PARSEDPATARR 50
153 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
154 unsigned int parsedPatIdx=0;
155
156
157 typedef enum {
158   PCP_LABEL=1,
159   PCP_NUMBER,
160   PCP_STR,
161   PCP_WILDVAR,
162   PCP_WILDSTR,
163   PCP_COMMA,
164   PCP_COMMENT
165 } pCodePatterns;
166
167 static char pcpat_label[]      = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
168 static char pcpat_number[]     = {PCT_NUMBER, 0};
169 static char pcpat_string[]     = {PCT_STRING, 0};
170 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
171 static char pcpat_wildVar[]    = {PCT_PERCENT, PCT_NUMBER, 0};
172 static char pcpat_comma[]      = {PCT_COMMA, 0};
173 static char pcpat_comment[]    = {PCT_COMMENT, 0};
174
175
176 typedef struct pcPattern {
177   char pt;                 // Pattern type
178   char *tokens;           // list of tokens that describe the pattern
179   void * (*f) (void *,pCodeWildBlock *);
180 } pcPattern;
181
182 pcPattern pcpArr[] = {
183   {PCP_LABEL,     pcpat_label,      NULL},
184   {PCP_WILDSTR,   pcpat_wildString, NULL},
185   {PCP_STR,       pcpat_string,     NULL},
186   {PCP_WILDVAR,   pcpat_wildVar,    NULL},
187   {PCP_COMMA,     pcpat_comma,      NULL},
188   {PCP_COMMENT,   pcpat_comment,    NULL},
189   {PCP_NUMBER,    pcpat_number,     NULL}
190 };
191
192 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
193
194 // Assembly Line Token
195 typedef enum {
196   ALT_LABEL=1,
197   ALT_COMMENT,
198   ALT_MNEM0,
199   ALT_MNEM0A,
200   ALT_MNEM1,
201   ALT_MNEM1A,
202   ALT_MNEM1B,
203   ALT_MNEM2,
204   ALT_MNEM2A
205 } altPatterns;
206
207 static char alt_comment[]   = { PCP_COMMENT, 0};
208 static char alt_label[]     = { PCP_LABEL, 0};
209 static char alt_mnem0[]     = { PCP_STR, 0};
210 static char alt_mnem0a[]    = { PCP_WILDVAR, 0};
211 static char alt_mnem1[]     = { PCP_STR, PCP_STR, 0};
212 static char alt_mnem1a[]    = { PCP_STR, PCP_WILDVAR, 0};
213 static char alt_mnem1b[]    = { PCP_STR, PCP_NUMBER, 0};
214 static char alt_mnem2[]     = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
215 static char alt_mnem2a[]    = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
216
217 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb);
218 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb);
219 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb);
220 static void * cvt_altpat_mnem0a(void *pp,pCodeWildBlock *pcwb);
221 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb);
222 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb);
223 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb);
224 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb);
225 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb);
226
227 pcPattern altArr[] = {
228   {ALT_LABEL,        alt_label,  cvt_altpat_label},
229   {ALT_COMMENT,      alt_comment,cvt_altpat_comment},
230   {ALT_MNEM2A,       alt_mnem2a, cvt_altpat_mnem2a},
231   {ALT_MNEM2,        alt_mnem2,  cvt_altpat_mnem2},
232   {ALT_MNEM1B,       alt_mnem1b, cvt_altpat_mnem1b},
233   {ALT_MNEM1A,       alt_mnem1a, cvt_altpat_mnem1a},
234   {ALT_MNEM1,        alt_mnem1,  cvt_altpat_mnem1},
235   {ALT_MNEM0A,       alt_mnem0a, cvt_altpat_mnem0a},
236   {ALT_MNEM0,        alt_mnem0,  cvt_altpat_mnem0},
237
238 };
239
240 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
241
242 // forward declarations
243 static void * DLL_append(_DLL *list, _DLL *next);
244
245 /*-----------------------------------------------------------------*/
246 /* cvt_extract_destination - helper function extracts the register */
247 /*                           destination from a parsedPattern.     */
248 /*                                                                 */
249 /*-----------------------------------------------------------------*/
250 static int cvt_extract_destination(parsedPattern *pp)
251 {
252
253   if(pp->pct[0].tt == PCT_STRING) {
254
255     // just check first letter for now
256
257     if(toupper(*pp->pct[0].tok.s) == 'F')
258       return 1;
259
260   } else if (pp->pct[0].tt == PCT_NUMBER) {
261
262     if(pp->pct[0].tok.n)
263       return 1;
264   }
265
266   return 0;
267
268 }
269
270 /*-----------------------------------------------------------------*/
271 /*  pCodeOp *cvt_extract_status(char *reg, char *bit)              */
272 /*     if *reg is the "status" register and *bit is one of the     */
273 /*     status bits, then this function will create a new pCode op  */
274 /*     containing the status register.                             */
275 /*-----------------------------------------------------------------*/
276
277 static pCodeOp *cvt_extract_status(char *reg, char *bit)
278 {
279   int len;
280
281   if(STRCASECMP(reg, pc_status.pcop.name))
282     return NULL;
283
284   len = strlen(bit);
285
286   if(len == 1) {
287     // check C,Z
288     if(toupper(*bit) == 'C')
289       return PCOP(popCopyGPR2Bit(&pc_status,PIC_C_BIT));
290     if(toupper(*bit) == 'Z')
291       return PCOP(popCopyGPR2Bit(&pc_status,PIC_Z_BIT));
292   }
293
294   // Check DC
295   if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
296     return PCOP(popCopyGPR2Bit(&pc_status,PIC_DC_BIT));
297
298   return NULL;
299
300 }
301
302 /*-----------------------------------------------------------------*/
303 /* cvt_altpat_label - convert assembly line type to a pCode label  */
304 /* INPUT: pointer to the parsedPattern                             */
305 /*                                                                 */
306 /*  pp[0] - label                                                  */
307 /*                                                                 */
308 /* label pattern => '%' number ':'                                 */
309 /* at this point, we wish to extract only the 'number'             */
310 /*                                                                 */
311 /*-----------------------------------------------------------------*/
312 static void * cvt_altpat_label(void *pp,pCodeWildBlock *pcwb)
313 {
314   parsedPattern *p = pp;
315
316   DFPRINTF((stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n));
317   return newpCodeLabel(NULL,-p->pct[1].tok.n);
318
319 }
320
321 /*-----------------------------------------------------------------*/
322 /* cvt_altpat_comment - convert assembly line type to a comment    */
323 /* INPUT: pointer to the parsedPattern                             */
324 /*                                                                 */
325 /*  pp[0] - comment                                                */
326 /*                                                                 */
327 /*                                                                 */
328 /*-----------------------------------------------------------------*/
329 static void * cvt_altpat_comment(void *pp,pCodeWildBlock *pcwb)
330 {
331   parsedPattern *p = pp;
332
333   DFPRINTF((stderr,"altpat_comment  = %s\n",p->pct[0].tok.s));
334   return newpCodeCharP(p->pct[0].tok.s);
335
336 }
337
338 /*-----------------------------------------------------------------*/
339 /* cvt_altpat_mem0  - convert assembly line type to a wild pCode   */
340 /*                    instruction                                  */
341 /*                                                                 */
342 /*  pp[0] - str                                                    */
343 /*                                                                 */
344 /*-----------------------------------------------------------------*/
345 static void * cvt_altpat_mnem0(void *pp,pCodeWildBlock *pcwb)
346 {
347   parsedPattern *p = pp;
348   int opcode;
349
350   pCodeInstruction *pci=NULL;
351
352   DFPRINTF((stderr,"altpat_mnem0 %s\n",  p->pct[0].tok.s));
353
354   opcode = getpCode(p->pct[0].tok.s,0);
355
356   if(opcode < 0) {
357     /* look for special command strings like _NOTBITSKIP_ */
358
359     //fprintf(stderr, "Bad mnemonic\n");
360
361     opcode  = getpCodePeepCommand(p->pct[0].tok.s);
362     //if(opcode > 0)
363     //  fprintf(stderr,"  but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
364     return NULL;
365   }
366
367   pci = PCI(newpCode(opcode, NULL));
368
369   if(!pci)
370     fprintf(stderr,"couldn't find mnemonic\n");
371
372
373   return pci;
374 }
375
376 /*-----------------------------------------------------------------*/
377 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode   */
378 /*                    instruction                                  */
379 /*                                                                 */
380 /*  pp[0] - wild var                                               */
381 /*                                                                 */
382 /*-----------------------------------------------------------------*/
383 static void * cvt_altpat_mnem0a(void *pp, pCodeWildBlock *pcwb)
384 {
385   parsedPattern *p = pp;
386
387   DFPRINTF((stderr,"altpat_mnem0a wild mnem # %d\n",  p[0].pct[1].tok.n));
388
389   /* Save the index of the maximum wildcard mnemonic */
390
391   //if(p[0].pct[1].tok.n > sMaxWildVar)
392   //  sMaxWildMnem = p[0].pct[1].tok.n;
393
394   if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
395     pcwb->nwildpCodes = p[0].pct[1].tok.n;
396
397   return newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
398
399 }
400
401 /*-----------------------------------------------------------------*/
402 /* cvt_altpat_mem1 - convert assembly line type to a pCode         */
403 /*                   instruction with 1 operand.                   */
404 /*                                                                 */
405 /*  pp[0] - mnem                                                   */
406 /*  pp[1] - Operand                                                */
407 /*                                                                 */
408 /*-----------------------------------------------------------------*/
409 static void * cvt_altpat_mnem1(void *pp,pCodeWildBlock *pcwb)
410 {
411
412   parsedPattern *p = pp;
413   int opcode;
414
415   pCodeInstruction *pci=NULL;
416   pCodeOp *pcosubtype;
417
418   DFPRINTF((stderr,"altpat_mnem1 %s var %s\n",  p->pct[0].tok.s,p[1].pct[0].tok.s));
419
420   opcode = getpCode(p->pct[0].tok.s,0);
421   if(opcode < 0) {
422     //fprintf(stderr, "Bad mnemonic\n");
423     opcode  = getpCodePeepCommand(p->pct[0].tok.s);
424     //if(opcode > 0)
425     //fprintf(stderr,"  but valid peep command: %s, key = %d\n",p->pct[0].tok.s,opcode);
426
427     return NULL;
428   }
429
430   if(pic14Mnemonics[opcode]->isBitInst)
431     pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
432   else
433     pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
434
435
436   pci = PCI(newpCode(opcode, pcosubtype));
437
438   if(!pci)
439     fprintf(stderr,"couldn't find mnemonic\n");
440
441
442   return pci;
443 }
444
445 /*-----------------------------------------------------------------*/
446 /* cvt_altpat_mem1a - convert assembly line type to a pCode        */
447 /*                    instruction with 1 wild operand.             */
448 /*                                                                 */
449 /*  pp[0] - mnem                                                   */
450 /*  pp[1] - wild var                                               */
451 /*                                                                 */
452 /*-----------------------------------------------------------------*/
453 static void * cvt_altpat_mnem1a(void *pp,pCodeWildBlock *pcwb)
454 {
455   parsedPattern *p = pp;
456   int opcode;
457
458   pCodeInstruction *pci=NULL;
459   pCodeOp *pcosubtype;
460
461   DFPRINTF((stderr,"altpat_mnem1a %s var %d\n",  p->pct[0].tok.s,p[1].pct[1].tok.n));
462
463   opcode = getpCode(p->pct[0].tok.s,0);
464   if(opcode < 0) {
465     int cmd_id = getpCodePeepCommand(p->pct[0].tok.s);
466     pCode *pc=NULL;
467
468     if(cmd_id<0) {
469       fprintf(stderr, "Bad mnemonic\n");
470       return NULL;
471     }
472
473     if(p[0].pct[1].tok.n > pcwb->nwildpCodes)
474       pcwb->nwildpCodes = p[0].pct[1].tok.n;
475
476     pc =  newpCodeWild(p[1].pct[1].tok.n,NULL,NULL);
477
478     switch(cmd_id) {
479     case NOTBITSKIP:
480       PCW(pc)->mustNotBeBitSkipInst = 1;
481       break;
482     case BITSKIP:
483       PCW(pc)->mustBeBitSkipInst = 1;
484       break;
485     case INVERTBITSKIP:
486       PCW(pc)->invertBitSkipInst = 1;
487     }
488     return pc;
489   }
490
491   if(pic14Mnemonics[opcode]->isBitInst)
492     pcosubtype = newpCodeOpBit(NULL,-1,0);
493   else
494     pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
495
496
497   pci = PCI(newpCode(opcode,
498                      newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
499
500   /* Save the index of the maximum wildcard variable */
501   //if(p[1].pct[1].tok.n > sMaxWildVar)
502   //  sMaxWildVar = p[1].pct[1].tok.n;
503
504   if(p[1].pct[1].tok.n > pcwb->nvars)
505     pcwb->nvars = p[1].pct[1].tok.n;
506
507   if(!pci)
508     fprintf(stderr,"couldn't find mnemonic\n");
509
510
511   return pci;
512 }
513
514 /*-----------------------------------------------------------------*/
515 /*-----------------------------------------------------------------*/
516 static void * cvt_altpat_mnem1b(void *pp,pCodeWildBlock *pcwb)
517 {
518   parsedPattern *p = pp;
519   int opcode;
520
521   pCodeInstruction *pci=NULL;
522
523   DFPRINTF((stderr,"altpat_mnem1b %s var %d\n",  p->pct[0].tok.s,p[1].pct[0].tok.n));
524
525   opcode = getpCode(p->pct[0].tok.s,0);
526   if(opcode < 0) {
527     fprintf(stderr, "Bad mnemonic\n");
528     return NULL;
529   }
530
531   pci = PCI(newpCode(opcode, newpCodeOpLit(p[1].pct[0].tok.n) ));
532
533   if(!pci)
534     fprintf(stderr,"couldn't find mnemonic\n");
535
536
537   return pci;
538 }
539
540 /*-----------------------------------------------------------------*/
541 /*-----------------------------------------------------------------*/
542 static void * cvt_altpat_mnem2(void *pp,pCodeWildBlock *pcwb)
543 {
544   parsedPattern *p = pp;
545   int opcode;
546   int dest;
547
548   pCodeInstruction *pci=NULL;
549   pCodeOp *pcosubtype;
550
551   dest = cvt_extract_destination(&p[3]);
552
553   DFPRINTF((stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
554           p->pct[0].tok.s,
555           p[1].pct[0].tok.s,
556           p[3].pct[0].tok.s,
557           dest));
558
559
560   opcode = getpCode(p->pct[0].tok.s,dest);
561   if(opcode < 0) {
562     fprintf(stderr, "Bad mnemonic\n");
563     return NULL;
564   }
565
566   if(pic14Mnemonics[opcode]->isBitInst) {
567     pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
568     if(pcosubtype == NULL) {
569       fprintf(stderr, "bad operand?\n");
570       return NULL;
571     }
572       
573   } else
574     pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
575
576
577   pci = PCI(newpCode(opcode,pcosubtype));
578
579   if(!pci)
580     fprintf(stderr,"couldn't find mnemonic\n");
581
582   return pci;
583
584 }
585
586 /*-----------------------------------------------------------------*/
587 /* cvt_altpat_mem2a - convert assembly line type to a pCode        */
588 /*                    instruction with 1 wild operand and a        */
589 /*                    destination operand (e.g. w or f)            */
590 /*                                                                 */
591 /*  pp[0] - mnem                                                   */
592 /*  pp[1] - wild var                                               */
593 /*  pp[2] - comma                                                  */
594 /*  pp[3] - destination                                            */
595 /*                                                                 */
596 /*-----------------------------------------------------------------*/
597 static void * cvt_altpat_mnem2a(void *pp,pCodeWildBlock *pcwb)
598 {
599   parsedPattern *p = pp;
600   int opcode;
601   int dest;
602
603   pCodeInstruction *pci=NULL;
604   pCodeOp *pcosubtype;
605
606   dest = cvt_extract_destination(&p[3]);
607
608   DFPRINTF((stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
609           p->pct[0].tok.s,
610           p[1].pct[1].tok.n,
611           p[3].pct[0].tok.s,
612           dest));
613
614
615   opcode = getpCode(p->pct[0].tok.s,dest);
616   if(opcode < 0) {
617     fprintf(stderr, "Bad mnemonic\n");
618     return NULL;
619   }
620
621   if(pic14Mnemonics[opcode]->isBitInst)
622     pcosubtype = newpCodeOp(NULL,PO_BIT);
623   else
624     pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
625
626
627   pci = PCI(newpCode(opcode,
628                      newpCodeOpWild(p[1].pct[1].tok.n, pcwb, pcosubtype)));
629
630   /* Save the index of the maximum wildcard variable */
631   //if(p[1].pct[1].tok.n > sMaxWildVar)
632   //  sMaxWildVar = p[1].pct[1].tok.n;
633
634   if(p[1].pct[1].tok.n > pcwb->nvars)
635     pcwb->nvars = p[1].pct[1].tok.n;
636
637   if(!pci)
638     fprintf(stderr,"couldn't find mnemonic\n");
639
640   return pci;
641
642 }
643
644 /*-----------------------------------------------------------------*/
645 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
646 /*                    by SDCCpeeph.c into a string of tokens.      */
647 /*                                                                 */
648 /*                                                                 */
649 /* The tokenizer is of the classic type. When an item is encounterd*/
650 /* it is converted into a token. The token is a structure that     */
651 /* encodes the item's type and it's value (when appropriate).      */
652 /*                                                                 */
653 /* Accepted token types:                                           */
654 /*    SPACE  NUMBER STRING  %  : ,  ;                              */
655 /*                                                                 */
656 /*                                                                 */
657 /*                                                                 */
658 /*-----------------------------------------------------------------*/
659
660
661 static void tokenizeLineNode(char *ln)
662 {
663
664   tokIdx = 0;               // Starting off at the beginning
665   tokArr[0].tt = PCT_NULL;  // and assume invalid character for first token.
666
667   if(!ln || !*ln)
668     return;
669
670   while(*ln) {
671
672     if(isspace(*ln)) {
673       // add a SPACE token and eat the extra spaces.
674       tokArr[tokIdx++].tt = PCT_SPACE;
675       while (isspace (*ln))
676         ln++;
677       continue;
678     }
679
680     if(isdigit(*ln)) {
681
682       tokArr[tokIdx].tt = PCT_NUMBER;
683       tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
684
685       continue;
686
687     }
688
689     switch(*ln) {
690     case '%':
691       tokArr[tokIdx++].tt = PCT_PERCENT;
692       break;
693     case '<':
694       tokArr[tokIdx++].tt = PCT_LESSTHAN;
695       break;
696     case '>':
697       tokArr[tokIdx++].tt = PCT_GREATERTHAN;
698       break;
699     case ':':
700       tokArr[tokIdx++].tt = PCT_COLON;
701       break;
702     case ';':
703       tokArr[tokIdx].tok.s = Safe_strdup(ln);
704       tokArr[tokIdx++].tt = PCT_COMMENT;
705       tokArr[tokIdx].tt = PCT_NULL;
706       return;
707     case ',':
708       tokArr[tokIdx++].tt = PCT_COMMA;
709       break;
710
711
712     default:
713       if(isalpha(*ln) || (*ln == '_') ) {
714         char buffer[50];
715         int i=0;
716
717         while( (isalpha(*ln)  ||  isdigit(*ln) || (*ln == '_')) && i<49)
718           buffer[i++] = *ln++;
719
720         ln--;
721         buffer[i] = 0;
722
723         tokArr[tokIdx].tok.s = Safe_strdup(buffer);
724         tokArr[tokIdx++].tt = PCT_STRING;
725
726       }
727     }
728
729     /* Advance to next character in input string .
730      * Note, if none of the tests passed above, then 
731      * we effectively ignore the `bad' character.
732      * Since the line has already been parsed by SDCCpeeph,
733      * chance are that there are no invalid characters... */
734
735     ln++;
736
737   }
738
739   tokArr[tokIdx].tt = 0;
740 }
741
742
743 /*-----------------------------------------------------------------*/
744 /*-----------------------------------------------------------------*/
745
746
747
748 void dump1Token(pCodeTokens tt)
749 {
750 #ifdef PCODE_DEBUG
751   switch(tt) {
752   case PCT_SPACE:
753     fprintf(stderr, " space ");
754     break;
755   case PCT_PERCENT:
756     fprintf(stderr, " pct %%");
757     break;
758   case PCT_LESSTHAN:
759     fprintf(stderr, " pct <");
760     break;
761   case PCT_GREATERTHAN:
762     fprintf(stderr, " pct >");
763     break;
764   case PCT_COLON:
765     fprintf(stderr, " col :");
766     break;
767   case PCT_COMMA:
768     fprintf(stderr, " comma , ");
769     break;
770   case PCT_COMMENT:
771     fprintf(stderr, " comment ");
772     //fprintf(stderr,"%s",tokArr[i].tok.s);
773     break;
774   case PCT_STRING:
775     fprintf(stderr, " str ");
776     //fprintf(stderr,"%s",tokArr[i].tok.s);
777     break;
778   case PCT_NUMBER:
779     fprintf(stderr, " num ");
780     //fprintf(stderr,"%d",tokArr[i].tok.n);
781     break;
782   case PCT_NULL:
783     fprintf(stderr, " null ");
784
785   }
786 #endif
787 }
788
789
790 /*-----------------------------------------------------------------*/
791 /*-----------------------------------------------------------------*/
792
793 int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
794 {
795   int i=0;
796
797   if(!pct || !pat || !*pat)
798     return 0;
799
800   //DFPRINTF((stderr,"comparing against:\n"));
801
802   while(i < max_tokens) {
803
804     if(*pat == 0){
805       //DFPRINTF((stderr,"matched\n"));
806       return (i+1);
807     }
808
809     //dump1Token(*pat); DFPRINTF((stderr,"\n"));
810
811     if(pct->tt != *pat) 
812       return 0;
813
814
815     pct++;
816     pat++;
817   }
818
819   return 0;
820
821 }
822
823 /*-----------------------------------------------------------------*/
824 /*-----------------------------------------------------------------*/
825
826 int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
827 {
828   int i=0;
829   
830   if(!pct || !pat || !*pct)
831     return 0;
832
833
834   while(i < max_tokens) {
835
836     if(*pct == 0) {
837       //DFPRINTF((stderr,"matched\n"));
838       return i;
839     }
840
841     //dump1Token(*pat); DFPRINTF((stderr,"\n"));
842
843     if( !pat || !pat->pcp )
844       return 0;
845
846     if (pat->pcp->pt != *pct)  
847       return 0;
848
849     //DFPRINTF((stderr," pct=%d\n",*pct));
850     pct++;
851     pat++;
852     i++;
853   }
854
855   return 0;
856
857 }
858 /*-----------------------------------------------------------------*/
859 /*-----------------------------------------------------------------*/
860
861 int advTokIdx(int *v, int amt)
862 {
863
864   if((unsigned) (*v + amt) > tokIdx)
865     return 1;
866
867   *v += amt;
868   return 0;
869
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* parseTokens - convert the tokens corresponding to a single line */
874 /*               of a peep hole assembly into a pCode object.      */
875 /*                                                                 */
876 /*                                                                 */
877 /*                                                                 */
878 /*                                                                 */
879 /* This is a simple parser that looks for strings of the type      */
880 /* allowed in the peep hole definition file. Essentially the format*/
881 /* is the same as a line of assembly:                              */
882 /*                                                                 */
883 /*  label:    mnemonic   op1, op2, op3    ; comment                */
884 /*                                                                 */
885 /* Some of these items aren't present. It's the job of the parser  */
886 /* to determine which are and convert those into the appropriate   */
887 /* pcode.                                                          */
888 /*-----------------------------------------------------------------*/
889
890 void parseTokens(pCodeWildBlock *pcwb)
891 {
892   unsigned i;
893   pCode *pc;
894
895   if(!tokIdx)
896     return;
897
898   for(i=0; i<=tokIdx; i++)
899     dump1Token(tokArr[i].tt);
900 #ifdef PCODE_DEBUG
901   fputc('\n',stderr);
902 #endif
903   {
904     int lparsedPatIdx=0;
905     int lpcpIdx;
906     int ltokIdx =0;
907     int matching = 0;
908     int j=0;
909     int k=0;
910
911     char * cPmnem  = NULL;     // Pointer to non-wild mnemonic (if any)
912     char * cP1stop = NULL;
913     char * cP2ndop = NULL;
914
915     //pCodeOp *pcl   = NULL;       // Storage for a label
916     //pCodeOp *pco1  = NULL;       // 1st operand
917     //pCodeOp *pco2  = NULL;       // 2nd operand
918     //pCode   *pc    = NULL;       // Mnemonic
919
920     typedef enum {
921       PS_START,
922       PS_HAVE_LABEL,
923       PS_HAVE_MNEM,
924       PS_HAVE_1OPERAND,
925       PS_HAVE_COMMA,
926       PS_HAVE_2OPERANDS
927     } ParseStates;
928
929     ParseStates state = PS_START;
930
931     do {
932
933       lpcpIdx=0;
934       matching = 0;
935
936       if(  ((tokArr[ltokIdx].tt == PCT_SPACE) )
937            && (advTokIdx(&ltokIdx, 1)) ) // eat space
938         break;
939
940       do {
941         j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
942         if( j ) {
943
944           switch(pcpArr[lpcpIdx].pt) {
945           case  PCP_LABEL:
946             if(state == PS_START){
947               DFPRINTF((stderr,"  label\n"));
948               state = PS_HAVE_LABEL;
949             } else 
950               DFPRINTF((stderr,"  bad state (%d) for label\n",state));
951             break;
952
953           case  PCP_STR:
954             DFPRINTF((stderr,"  %s is",tokArr[ltokIdx].tok.s));
955             switch(state) {
956             case PS_START:
957             case PS_HAVE_LABEL:
958               DFPRINTF((stderr,"  mnem\n"));
959               cPmnem = tokArr[ltokIdx].tok.s;
960               state = PS_HAVE_MNEM;
961               break;
962             case PS_HAVE_MNEM:
963               DFPRINTF((stderr,"  1st operand\n"));
964               cP1stop = tokArr[ltokIdx].tok.s;
965               //pco1 = newpCodeOp(NULL,PO_GPR_REGISTER);
966               state = PS_HAVE_1OPERAND;
967               break;
968             case PS_HAVE_1OPERAND:
969               DFPRINTF((stderr,"  error expecting comma\n"));
970               break;
971             case PS_HAVE_COMMA:
972               DFPRINTF((stderr,"  2 operands\n"));
973               cP2ndop = tokArr[ltokIdx].tok.s;
974               break;
975             case PS_HAVE_2OPERANDS:
976               break;
977             }
978             break;
979
980           case  PCP_WILDVAR:
981             switch(state) {
982             case PS_START:
983             case PS_HAVE_LABEL:
984               DFPRINTF((stderr,"  wild mnem\n"));
985               state = PS_HAVE_MNEM;
986               break;
987             case PS_HAVE_MNEM:
988               DFPRINTF((stderr,"  1st operand is wild\n"));
989               state = PS_HAVE_1OPERAND;
990               break;
991             case PS_HAVE_1OPERAND:
992               DFPRINTF((stderr,"  error expecting comma\n"));
993               break;
994             case PS_HAVE_COMMA:
995               DFPRINTF((stderr,"  2nd operand is wild\n"));
996               break;
997             case PS_HAVE_2OPERANDS:
998               break;
999             }
1000             break;
1001
1002           case  PCP_NUMBER:
1003             switch(state) {
1004             case PS_START:
1005             case PS_HAVE_LABEL:
1006               fprintf(stderr,"  ERROR number\n");
1007               break;
1008             case PS_HAVE_MNEM:
1009               DFPRINTF((stderr,"  1st operand is a number\n"));
1010               state = PS_HAVE_1OPERAND;
1011               break;
1012             case PS_HAVE_1OPERAND:
1013               fprintf(stderr,"  error expecting comma\n");
1014               break;
1015             case PS_HAVE_COMMA:
1016               DFPRINTF((stderr,"  2nd operand is a number\n"));
1017               break;
1018             case PS_HAVE_2OPERANDS:
1019               break;
1020             }
1021             break;
1022
1023           case  PCP_WILDSTR:
1024             break;
1025           case  PCP_COMMA:
1026             if(state == PS_HAVE_1OPERAND){
1027               DFPRINTF((stderr,"  got a comma\n"));
1028               state = PS_HAVE_COMMA;
1029             } else
1030               fprintf(stderr,"  unexpected comma\n");
1031           }
1032
1033           matching = 1;
1034           parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1035           parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1036           lparsedPatIdx++;
1037
1038           //dump1Token(tokArr[ltokIdx].tt);
1039
1040           if(advTokIdx(&ltokIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1041             DFPRINTF((stderr," reached end \n"));
1042             matching = 0;
1043             //return;
1044           }
1045         }
1046
1047
1048       } while ((++lpcpIdx < PCPATTERNS) && !matching);
1049
1050     } while (matching);
1051
1052     parsedPatArr[lparsedPatIdx].pcp = NULL;
1053     parsedPatArr[lparsedPatIdx].pct = NULL;
1054
1055     j=k=0;
1056     do {
1057       int c;
1058
1059       if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1060
1061         if( altArr[k].f) {
1062           pc = altArr[k].f(&parsedPatArr[j],pcwb);
1063           //if(pc && pc->print)
1064           //  pc->print(stderr,pc);
1065           //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1066
1067           //if(curBlock && pc)
1068           //addpCode2pBlock(curBlock, pc);
1069           addpCode2pBlock(pcwb->pb, pc);
1070         }
1071         j += c;
1072       }
1073       k++;
1074     }
1075     while(j<=lparsedPatIdx && k<ALTPATTERNS);
1076
1077 /*
1078     DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1079
1080     j = 0;
1081     do {
1082       if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1083         parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1084       DFPRINTF((stderr,"  %d",parsedPatArr[j].pcp->pt));
1085       j++;
1086     }
1087     while(j<lparsedPatIdx);
1088 */
1089     DFPRINTF((stderr,"\n"));
1090
1091   }
1092
1093
1094 }
1095
1096 /*-----------------------------------------------------------------*/
1097 /*                                                                 */
1098 /*-----------------------------------------------------------------*/
1099 void  peepRuleBlock2pCodeBlock(  lineNode *ln, pCodeWildBlock *pcwb)
1100 {
1101
1102   if(!ln)
1103     return;
1104
1105   for( ; ln; ln = ln->next) {
1106
1107     //DFPRINTF((stderr,"%s\n",ln->line));
1108
1109     tokenizeLineNode(ln->line);
1110     parseTokens(pcwb);
1111
1112   }
1113 }
1114
1115 /*-----------------------------------------------------------------*/
1116 /* peepRuleCondition                                               */
1117 /*-----------------------------------------------------------------*/
1118 static void   peepRuleCondition(char *cond, pCodePeep *pcp)
1119 {
1120   if(!cond || !pcp)
1121     return;
1122
1123   //DFPRINTF((stderr,"\nCondition:  %s\n",cond));
1124   /* brute force compares for now */
1125
1126   if(STRCASECMP(cond, "NZ") == 0) {
1127     //DFPRINTF((stderr,"found NZ\n"));
1128     pcp->postFalseCond = PCC_Z;
1129
1130   }
1131
1132 }
1133
1134
1135 void initpCodeWildBlock(pCodeWildBlock *pcwb)
1136 {
1137   
1138   //  pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1139
1140   if(!pcwb)
1141     return;
1142
1143   pcwb->vars = NULL; 
1144   pcwb->wildpCodes = NULL;
1145   pcwb->wildpCodeOps = NULL;
1146
1147   pcwb->nvars = 0; 
1148   pcwb->nwildpCodes = 0;
1149   pcwb->nops = 0;
1150
1151 }
1152
1153 void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1154 {
1155   
1156   if(!pcwb)
1157     return;
1158
1159   pcwb->nvars+=2;
1160   pcwb->nops = pcwb->nvars;
1161
1162   pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1163   pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1164
1165   pcwb->nwildpCodes+=2;
1166   pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1167
1168 }
1169
1170 void initpCodePeep(pCodePeep *pcp)
1171 {
1172   
1173   //  pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1174
1175   if(!pcp)
1176     return;
1177
1178   initpCodeWildBlock(&pcp->target);
1179   pcp->target.pb = newpCodeChain(NULL, 'W', NULL);
1180
1181   initpCodeWildBlock(&pcp->replace);
1182   pcp->replace.pb = newpCodeChain(NULL, 'W', NULL);
1183
1184 }
1185
1186 /*-----------------------------------------------------------------*/
1187 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1188 /*                   pCode.                                        */
1189 /*                                                                 */
1190 /* SDCCpeeph parses the peep rules file and extracts variables,    */
1191 /* removes white space, and checks the syntax. This function       */
1192 /* extends that processing to produce pCode objects. You can kind  */
1193 /* think of this function as an "assembler", though instead of     */
1194 /* taking raw text to produce machine code, it produces pCode.     */
1195 /*                                                                 */
1196 /*-----------------------------------------------------------------*/
1197 extern void pic14initpCodePeepCommands(void);
1198
1199 void  peepRules2pCode(peepRule *rules)
1200 {
1201   peepRule *pr;
1202
1203   pCodePeep *currentRule;
1204   pCodePeepSnippets *pcps;
1205
1206   pic14initpCodePeepCommands();
1207
1208   /* The rules are in a linked-list. Each rule has two portions */
1209   /* There's the `target' and there's the `replace'. The target */
1210   /* is compared against the SDCC generated code and if it      */
1211   /* matches, it gets replaced by the `replace' block of code.  */
1212   /*                                                            */
1213   /* Here we loop through each rule and convert the target's and*/
1214   /* replace's into pCode target and replace blocks             */
1215
1216   for (pr = rules; pr; pr = pr->next) {
1217
1218     //DFPRINTF((stderr,"\nRule:\n\n"));
1219
1220     pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1221     peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1222
1223     currentRule = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
1224     initpCodePeep(currentRule);
1225
1226     /* Convert the target block */
1227     peepRuleBlock2pCodeBlock(pr->match, &currentRule->target);
1228
1229     //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1230     //printpBlock(stderr, curBlock);
1231
1232     //DFPRINTF((stderr,"target with labels merged:\n"));
1233     //pBlockMergeLabels(curBlock);
1234     pBlockMergeLabels(currentRule->target.pb);
1235     //printpBlock(stderr, currentRule->replace.pb);
1236
1237     //#ifdef PCODE_DEBUG
1238     //    printpBlock(stderr, curBlock);
1239     //#endif
1240     //DFPRINTF((stderr,"\nReplaced by:\n"));
1241
1242
1243     /* Convert the replace block */
1244     peepRuleBlock2pCodeBlock(pr->replace, &currentRule->replace);
1245
1246     //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1247     //printpBlock(stderr, curBlock);
1248
1249     //DFPRINTF((stderr,"replace with labels merged:\n"));
1250
1251     pBlockMergeLabels(currentRule->replace.pb);
1252     //printpBlock(stderr, currentRule->replace.pb);
1253
1254     peepRuleCondition(pr->cond,currentRule);
1255
1256     /* The rule has been converted to pCode. Now allocate
1257      * space for the wildcards */
1258     
1259     postinit_pCodeWildBlock(&currentRule->target);
1260     postinit_pCodeWildBlock(&currentRule->replace);
1261
1262     //return; // debug ... don't want to go through all the rules yet
1263   }
1264
1265   {
1266     pCodePeep *peepBlock;
1267     _DLL *peeprules;
1268
1269     peeprules = (_DLL *)peepSnippets;
1270     //fprintf(stderr,"target rules\n");
1271     while(peeprules) {
1272       //fprintf(stderr,"   rule:\n");
1273       peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1274       //printpBlock(stderr, peepBlock->target.pb);
1275       peeprules = peeprules->next;
1276     }
1277     //fprintf(stderr," ... done\n");
1278   }
1279
1280 }
1281
1282 void printpCodeString(FILE *of, pCode *pc, int max)
1283 {
1284   int i=0;
1285
1286   while(pc && (i++<max)) {
1287     pc->print(of,pc);
1288     pc = pc->next;
1289   }
1290 }
1291
1292 /*-----------------------------------------------------------------*/
1293 /* _DLL * DLL_append                                               */
1294 /*                                                                 */ 
1295 /*  Append a _DLL object to the end of a _DLL (doubly linked list) */ 
1296 /* If The list to which we want to append is non-existant then one */ 
1297 /* is created. Other wise, the end of the list is sought out and   */ 
1298 /* a new DLL object is appended to it. In either case, the void    */
1299 /* *data is added to the newly created DLL object.                 */
1300 /*-----------------------------------------------------------------*/
1301
1302 static void * DLL_append(_DLL *list, _DLL *next)
1303 {
1304   _DLL *b;
1305
1306
1307   /* If there's no list, then create one: */
1308   if(!list) {
1309     next->next = next->prev = NULL;
1310     return next;
1311   }
1312
1313
1314   /* Search for the end of the list. */
1315   b = list;
1316   while(b->next)
1317     b = b->next;
1318
1319   /* Now append the new DLL object */
1320   b->next = next;
1321   b->next->prev = b;
1322   b = b->next; 
1323   b->next = NULL;
1324
1325   return list;
1326   
1327 }  
1328
1329
1330 /*-----------------------------------------------------------------
1331
1332   pCode peephole optimization
1333
1334
1335   The pCode "peep hole" optimization is not too unlike the peep hole
1336   optimization in SDCCpeeph.c. The major difference is that here we
1337   use pCode's whereas there we use ASCII strings. The advantage with
1338   pCode's is that we can ascertain flow information in the instructions
1339   being optimized.
1340
1341
1342 <FIX ME> - elaborate...
1343
1344   -----------------------------------------------------------------*/
1345
1346
1347
1348 /*-----------------------------------------------------------------*/
1349 /* pCodeSearchCondition - Search a pCode chain for a 'condition'   */
1350 /*                                                                 */
1351 /* return conditions                                               */
1352 /*  1 - The Condition was found for a pCode's input                */
1353 /*  0 - No matching condition was found for the whole chain        */
1354 /* -1 - The Condition was found for a pCode's output               */
1355 /*                                                                 */
1356 /*-----------------------------------------------------------------*/
1357 int pCodeSearchCondition(pCode *pc, unsigned int cond)
1358 {
1359
1360   while(pc) {
1361
1362     /* If we reach a function end (presumably an end since we most
1363        probably began the search in the middle of a function), then
1364        the condition was not found. */
1365     if(pc->type == PC_FUNCTION)
1366       return 0;
1367
1368     if(pc->type == PC_OPCODE) {
1369       //fprintf(stderr," checking conditions of: ");
1370       //pc->print(stderr,pc);
1371       if(PCI(pc)->inCond & cond)
1372         return 1;
1373       if(PCI(pc)->outCond & cond)
1374         return -1;
1375     }
1376
1377     pc = pc->next;
1378   }
1379
1380   return 0;
1381 }
1382
1383 /*-----------------------------------------------------------------
1384  * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1385  *
1386  * Compare two pCodeOp's and return 1 if they're the same
1387  *-----------------------------------------------------------------*/
1388 int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1389 {
1390   char b[50], *n2;
1391
1392   if(!pcops || !pcopd)
1393     return 0;
1394 /*
1395   fprintf(stderr," Comparing operands %s",
1396           get_op( pcops,NULL,0));
1397
1398   fprintf(stderr," to %s\n",
1399           get_op( pcopd,NULL,0));
1400 */
1401
1402   if(pcops->type != pcopd->type) {
1403     //fprintf(stderr,"  - fail - diff types\n");
1404     return 0;  // different types
1405   }
1406
1407   b[0]=0;
1408   get_op(pcops,b,sizeof(b));
1409   n2 = get_op(pcopd,NULL,0);
1410
1411   if( !n2 || strcmp(b,n2)) {
1412     //fprintf(stderr,"  - fail - diff names: %s, len=%d,  %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1413     return 0;  // different names
1414   }
1415
1416   switch(pcops->type) {
1417   case PO_DIR:
1418     if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1419       //fprintf(stderr, "  - fail different instances\n");
1420       return 0;
1421     }
1422     break;
1423   default:
1424     break;
1425   }
1426
1427   //  fprintf(stderr,"  - pass\n");
1428
1429   return 1;
1430 }
1431
1432 int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1433 {
1434   int labindex;
1435
1436   /* Check for a label associated with this wild pCode */
1437   // If the wild card has a label, make sure the source code does too.
1438   if(PCI(pcd)->label) {
1439     pCode *pcl = PCI(pcd)->label->pc;
1440
1441 #ifdef PCODE_DEBUG
1442     int li = -PCL(pcl)->key;
1443
1444     if(peepBlock->target.vars[li] == NULL) {
1445       if(PCI(pcs)->label) {
1446         DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1447       }
1448     } else {
1449       // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1450       DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1451       if(PCI(pcs)->label) {
1452         DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1453       }
1454     }
1455 #endif
1456
1457
1458     if(!PCI(pcs)->label)
1459       return 0;
1460
1461     labindex = -PCL(pcl)->key;
1462     if(peepBlock->target.vars[labindex] == NULL) {
1463       // First time to encounter this label
1464       peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1465       DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1466
1467     } else {
1468       if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1469         DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1470         return 0;
1471       }
1472       DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1473     }
1474   } else {
1475     //DFPRINTF((stderr,"destination doesn't have a label\n"));
1476
1477     if(PCI(pcs)->label)
1478       return 0;
1479
1480     //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1481
1482   }
1483
1484   return 1;
1485     
1486 }
1487
1488 /*-----------------------------------------------------------------*/
1489 /* pCodePeepMatchLine - Compare source and destination pCodes to   */
1490 /*                      see they're the same.                      */
1491 /*                                                                 */
1492 /* In this context, "source" refers to the coded generated by gen.c*/
1493 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1494 /* ination has no wild cards, then MatchLine will compare the two  */
1495 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1496 /* has wildcards, then those get expanded. When a wild card is     */
1497 /* encountered for the first time it autmatically is considered a  */
1498 /* match and the object that matches it is referenced in the       */
1499 /* variables or opcodes array (depending on the type of match).    */
1500 /*                                                                 */
1501 /*                                                                 */
1502 /* Inputs:                                                         */
1503 /*  *peepBlock - A pointer to the peepBlock that contains the      */
1504 /*               entire rule to which the destination pcode belongs*/
1505 /*  *pcs - a pointer to the source pcode                           */
1506 /*  *pcd - a pointer to the destination pcode                      */
1507 /*                                                                 */
1508 /* Returns:                                                        */
1509 /*  1 - pcodes match                                               */
1510 /*  0 - pcodes don't match                                         */
1511 /*                                                                 */
1512 /*                                                                 */
1513 /*-----------------------------------------------------------------*/
1514
1515 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1516 {
1517   int index;   // index into wild card arrays
1518
1519   /* one-for-one match. Here the source and destination opcodes 
1520    * are not wild. However, there may be a label or a wild operand */
1521
1522   if(pcs) {
1523     if(PCI(pcs)->label) {
1524       DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1525     }
1526   }
1527
1528   if(pcs->type == pcd->type) {
1529
1530     if(pcs->type == PC_OPCODE) {
1531
1532       /* If the opcodes don't match then the line doesn't match */
1533       if(PCI(pcs)->op != PCI(pcd)->op)
1534         return 0;
1535
1536 #ifdef PCODE_DEBUG
1537       DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1538       pcs->print(stderr,pcs);
1539       pcd->print(stderr,pcd);
1540 #endif
1541
1542       if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1543         return 0;
1544
1545       /* Compare the operands */
1546       if(PCI(pcd)->pcop) {
1547         if (PCI(pcd)->pcop->type == PO_WILD) {
1548           index = PCOW(PCI(pcd)->pcop)->id;
1549
1550           //DFPRINTF((stderr,"destination is wild\n"));
1551 #ifdef DEBUG_PCODEPEEP
1552           if (index > peepBlock->nops) {
1553             DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1554             exit(1);
1555           }
1556 #endif
1557
1558           PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1559           if(!peepBlock->target.wildpCodeOps[index]) {
1560             peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1561
1562             //if(PCI(pcs)->pcop->type == PO_GPR_TEMP) 
1563
1564           } else {
1565             /*
1566               pcs->print(stderr,pcs);
1567               pcd->print(stderr,pcd);
1568
1569               fprintf(stderr, "comparing operands of these instructions, result %d\n",
1570               pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1571               );
1572             */
1573
1574             return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1575           }
1576
1577           {
1578             char *n;
1579
1580             switch(PCI(pcs)->pcop->type) {
1581             case PO_GPR_TEMP:
1582             case PO_FSR:
1583               //case PO_INDF:
1584               n = PCOR(PCI(pcs)->pcop)->r->name;
1585
1586               break;
1587             default:
1588               n = PCI(pcs)->pcop->name;
1589             }
1590
1591             if(peepBlock->target.vars[index])
1592               return  (strcmp(peepBlock->target.vars[index],n) == 0);
1593             else {
1594               DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1595               peepBlock->target.vars[index] = n;
1596               return 1;
1597             }
1598           }
1599
1600         }
1601         /* FIXME - need an else to check the case when the destination 
1602          * isn't a wild card */
1603       } else
1604         /* The pcd has no operand. Lines match if pcs has no operand either*/
1605         return (PCI(pcs)->pcop == NULL);
1606     }
1607   }
1608
1609   /* Compare a wild instruction to a regular one. */
1610
1611   if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1612
1613
1614     index = PCW(pcd)->id;
1615 #ifdef PCODE_DEBUG
1616     DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
1617     pcs->print(stderr,pcs);
1618     pcd->print(stderr,pcd);
1619 #endif
1620     peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
1621
1622     if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
1623       DFPRINTF((stderr," Failing because labels don't match\n"));
1624       return 0;
1625     }
1626
1627     if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1628       // doesn't match because the wild pcode must be a bit skip
1629       DFPRINTF((stderr," Failing match because bit skip is req\n"));
1630       //pcd->print(stderr,pcd);
1631       //pcs->print(stderr,pcs);
1632       return 0;
1633     } 
1634
1635     if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1636       // doesn't match because the wild pcode must *not* be a bit skip
1637       DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
1638       //pcd->print(stderr,pcd);
1639       //pcs->print(stderr,pcs);
1640       return 0;
1641     } 
1642
1643     if(PCW(pcd)->operand) {
1644       PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1645       if(peepBlock->target.vars[index]) {
1646         int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
1647 #ifdef PCODE_DEBUG
1648
1649         if(i)
1650           DFPRINTF((stderr," (matched)\n"));
1651         else {
1652           DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
1653           DFPRINTF((stderr,"  peepblock= %s,  pcodeop= %s\n",
1654                   peepBlock->target.vars[index],
1655                   PCI(pcs)->pcop->name));
1656         }
1657 #endif
1658         return i;
1659       } else {
1660         DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
1661         peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
1662         return 1;
1663       }
1664     }
1665
1666     pcs = findNextInstruction(pcs->next); 
1667     if(pcs) {
1668       //DFPRINTF((stderr," (next to match)\n"));
1669       //pcs->print(stderr,pcs);
1670     } else if(pcd->next) {
1671       /* oops, we ran out of code, but there's more to the rule */
1672       return 0;
1673     }
1674
1675     return 1; /*  wild card matches */
1676   }
1677
1678   return 0;
1679 }
1680
1681 /*-----------------------------------------------------------------*/
1682 /*-----------------------------------------------------------------*/
1683 void pCodePeepClrVars(pCodePeep *pcp)
1684 {
1685
1686   int i;
1687   if(!pcp)
1688     return;
1689
1690   DFPRINTF((stderr," Clearing peep rule vars\n"));
1691   DFPRINTF((stderr," %d %d %d  %d %d %d\n",
1692             pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
1693             pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
1694
1695   for(i=0;i<pcp->target.nvars; i++)
1696     pcp->target.vars[i] = NULL;
1697   for(i=0;i<pcp->target.nops; i++)
1698     pcp->target.wildpCodeOps[i] = NULL;
1699   for(i=0;i<pcp->target.nwildpCodes; i++)
1700     pcp->target.wildpCodes[i] = NULL;
1701
1702   for(i=0;i<pcp->replace.nvars; i++)
1703     pcp->replace.vars[i] = NULL;
1704   for(i=0;i<pcp->replace.nops; i++)
1705     pcp->replace.wildpCodeOps[i] = NULL;
1706   for(i=0;i<pcp->replace.nwildpCodes; i++)
1707     pcp->replace.wildpCodes[i] = NULL;
1708
1709
1710
1711 }
1712
1713 /*-----------------------------------------------------------------*/
1714 /*  pCodeInsertAfter - splice in the pCode chain starting with pc2 */
1715 /*                     into the pCode chain containing pc1         */
1716 /*-----------------------------------------------------------------*/
1717 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
1718 {
1719
1720   if(!pc1 || !pc2)
1721     return;
1722
1723   pc2->next = pc1->next;
1724   if(pc1->next)
1725     pc1->next->prev = pc2;
1726
1727   pc2->pb = pc1->pb;
1728   pc2->prev = pc1;
1729   pc1->next = pc2;
1730
1731 }
1732
1733 /*-----------------------------------------------------------------*/
1734 /* pCodeOpCopy - copy a pcode operator                             */
1735 /*-----------------------------------------------------------------*/
1736 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
1737 {
1738   pCodeOp *pcopnew=NULL;
1739
1740   if(!pcop)
1741     return NULL;
1742
1743   switch(pcop->type) { 
1744   case PO_CRY:
1745   case PO_BIT:
1746     //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
1747     pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1748     PCORB(pcopnew)->bit = PCORB(pcop)->bit;
1749     PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
1750
1751     break;
1752
1753   case PO_WILD:
1754     /* Here we expand the wild card into the appropriate type: */
1755     /* By recursively calling pCodeOpCopy */
1756     //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
1757     if(PCOW(pcop)->matched)
1758       pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
1759     else {
1760       // Probably a label
1761       pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
1762       pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
1763       //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
1764     }
1765
1766     return pcopnew;
1767     break;
1768
1769   case PO_LABEL:
1770     //DFPRINTF((stderr,"pCodeOpCopy label\n"));
1771     pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1772     PCOLAB(pcopnew)->key =  PCOLAB(pcop)->key;
1773     break;
1774
1775   case PO_IMMEDIATE:
1776     pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
1777     PCOI(pcopnew)->index = PCOI(pcop)->index;
1778     PCOI(pcopnew)->offset = PCOI(pcop)->offset;
1779     PCOI(pcopnew)->_const = PCOI(pcop)->_const;
1780     break;
1781
1782   case PO_LITERAL:
1783     //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
1784     pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1785     PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1786     break;
1787
1788   case PO_GPR_BIT:
1789
1790     pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
1791     PCOR(pcopnew)->r = PCOR(pcop)->r;
1792     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1793     DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
1794     return pcopnew;
1795     break;
1796
1797   case PO_GPR_REGISTER:
1798   case PO_GPR_TEMP:
1799   case PO_FSR:
1800   case PO_INDF:
1801     //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
1802     pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1803     PCOR(pcopnew)->r = PCOR(pcop)->r;
1804     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1805     PCOR(pcopnew)->instance = PCOR(pcop)->instance;
1806     DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
1807     break;
1808
1809   case PO_DIR:
1810     //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
1811     pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1812     PCOR(pcopnew)->r = PCOR(pcop)->r;
1813     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1814     PCOR(pcopnew)->instance = PCOR(pcop)->instance;
1815     break;
1816   case PO_STATUS:
1817     DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
1818   case PO_SFR_REGISTER:
1819   case PO_STR:
1820   case PO_NONE:
1821   case PO_W:
1822   case PO_INTCON:
1823   case PO_PCL:
1824   case PO_PCLATH:
1825
1826     //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
1827     pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1828
1829   }
1830
1831   pcopnew->type = pcop->type;
1832   if(pcop->name)
1833     pcopnew->name = Safe_strdup(pcop->name);
1834   else
1835     pcopnew->name = NULL;
1836
1837   return pcopnew;
1838 }
1839
1840
1841 /*-----------------------------------------------------------------*/
1842 /* pCodeCopy - copy a pcode                                        */
1843 /*-----------------------------------------------------------------*/
1844 static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
1845 {
1846   pCodeInstruction *new_pci;
1847
1848   if(invert)
1849     new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
1850   else
1851     new_pci = PCI(newpCode(pci->op,pci->pcop));
1852
1853   new_pci->pc.pb = pci->pc.pb;
1854   new_pci->from = pci->from;
1855   new_pci->to   = pci->to;
1856   new_pci->label = pci->label;
1857   new_pci->pcflow = pci->pcflow;
1858
1859   return PCODE(new_pci);
1860 }
1861
1862 /*-----------------------------------------------------------------*/
1863 /*-----------------------------------------------------------------*/
1864 void pCodeDeleteChain(pCode *f,pCode *t)
1865 {
1866   pCode *pc;
1867
1868
1869   while(f && f!=t) {
1870     DFPRINTF((stderr,"delete pCode:\n"));
1871     pc = f->next;
1872     //f->print(stderr,f);
1873     //f->delete(f);  this dumps core...
1874
1875     f = pc;
1876
1877   }
1878
1879 }
1880 /*-----------------------------------------------------------------*/
1881 /*-----------------------------------------------------------------*/
1882 int pCodePeepMatchRule(pCode *pc)
1883 {
1884   pCodePeep *peepBlock;
1885   pCode *pct, *pcin;
1886   pCodeCSource *pc_cline=NULL;
1887   _DLL *peeprules;
1888   int matched;
1889
1890   peeprules = (_DLL *)peepSnippets;
1891
1892   while(peeprules) {
1893     peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1894
1895     if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
1896       fprintf(stderr, "skipping rule because target pb is NULL\n");
1897       goto next_rule;
1898     }
1899
1900     pCodePeepClrVars(peepBlock);
1901 /*
1902     pcin = pc;
1903     if(IS_PCCOMMENT(pcin))
1904       pc = pcin = findNextInstruction(pcin->next);
1905 */
1906     pcin = pc = findNextInstruction(pc);
1907
1908     pct = peepBlock->target.pb->pcHead;
1909 #ifdef PCODE_DEBUG
1910     {
1911       pCode *pcr = peepBlock->replace.pb->pcHead;
1912       if(pcr) pct->print(stderr,pcr);
1913     }
1914 #endif
1915     matched = 0;
1916     while(pct && pcin) {
1917
1918       if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1919         break;
1920
1921       pcin = findNextInstruction(pcin->next);
1922       pct = pct->next;
1923       //debug:
1924       //DFPRINTF((stderr,"    matched\n"));
1925
1926       if(!pcin && pct) {
1927         DFPRINTF((stderr," partial match... no more code\n"));
1928         fprintf(stderr," partial match... no more code\n");
1929         matched = 0; 
1930       }
1931       if(!pct) {
1932         DFPRINTF((stderr," end of rule\n"));
1933       }
1934     }
1935
1936     if(matched) {
1937
1938       //pCode *pcr = peepBlock->replace.pb->pcHead;
1939       //if(pcr) pcr->print(stderr,pcr);
1940       
1941       /* So far we matched the rule up to the point of the conditions .
1942        * In other words, all of the opcodes match. Now we need to see
1943        * if the post conditions are satisfied.
1944        * First we check the 'postFalseCond'. This means that we check
1945        * to see if any of the subsequent pCode's in the pCode chain 
1946        * following the point just past where we have matched depend on
1947        * the `postFalseCond' as input then we abort the match
1948        */
1949       DFPRINTF((stderr,"    matched rule so far, now checking conditions\n"));
1950       if (pcin && peepBlock->postFalseCond && 
1951           (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
1952         matched = 0;
1953
1954       if(!matched) fprintf(stderr,"failed on conditions\n");
1955     }
1956
1957     if(matched) {
1958
1959       pCode *pcprev;
1960       pCode *pcr;
1961
1962
1963       /* We matched a rule! Now we have to go through and remove the
1964          inefficient code with the optimized version */
1965 #ifdef PCODE_DEBUG
1966       DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
1967       printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
1968       DFPRINTF((stderr,"first thing matched\n"));
1969       pc->print(stderr,pc);
1970       if(pcin) {
1971         DFPRINTF((stderr,"last thing matched\n"));
1972         pcin->print(stderr,pcin);
1973       }
1974 #endif
1975
1976
1977       /* Unlink the original code */
1978       pcprev = pc->prev;
1979       pcprev->next = pcin;
1980       if(pcin) 
1981         pcin->prev = pc->prev;
1982
1983
1984       //#if 0
1985       {
1986         /*     DEBUG    */
1987         /* Converted the deleted pCodes into comments */
1988
1989         char buf[256];
1990         pCodeCSource *pc_cline2=NULL;
1991
1992         buf[0] = ';';
1993         buf[1] = '#';
1994
1995         while(pc &&  pc!=pcin) {
1996
1997           if(pc->type == PC_OPCODE && PCI(pc)->cline) {
1998             if(pc_cline) {
1999               pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2000               pc_cline2 = PCCS(pc_cline2->pc.next);
2001             } else {
2002               pc_cline = pc_cline2 = PCI(pc)->cline;
2003               pc_cline->pc.seq = pc->seq;
2004             }
2005           }
2006
2007           pCode2str(&buf[2], 254, pc);
2008           pCodeInsertAfter(pcprev, newpCodeCharP(buf));
2009           pcprev = pcprev->next;
2010           pc = pc->next;
2011
2012         }
2013         if(pc_cline2)
2014           pc_cline2->pc.next = NULL;
2015       }
2016       //#endif
2017
2018       if(pcin)
2019         pCodeDeleteChain(pc,pcin);
2020
2021       /* Generate the replacement code */
2022       pc = pcprev;
2023       pcr = peepBlock->replace.pb->pcHead;  // This is the replacement code
2024       while (pcr) {
2025         pCodeOp *pcop=NULL;
2026         
2027         /* If the replace pcode is an instruction with an operand, */
2028         /* then duplicate the operand (and expand wild cards in the process). */
2029         if(pcr->type == PC_OPCODE) {
2030           if(PCI(pcr)->pcop) {
2031             /* The replacing instruction has an operand.
2032              * Is it wild? */
2033             if(PCI(pcr)->pcop->type == PO_WILD) {
2034               int index = PCOW(PCI(pcr)->pcop)->id;
2035               //DFPRINTF((stderr,"copying wildopcode\n"));
2036               if(peepBlock->target.wildpCodeOps[index])
2037                 pcop = pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2038               else
2039                 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2040             } else
2041               pcop = pCodeOpCopy(PCI(pcr)->pcop);
2042           }
2043           //DFPRINTF((stderr,"inserting pCode\n"));
2044           pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
2045         } else if (pcr->type == PC_WILD) {
2046           if(PCW(pcr)->invertBitSkipInst)
2047             DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2048           pCodeInsertAfter(pc,
2049                            pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2050                                                 PCW(pcr)->invertBitSkipInst));
2051         } else if (pcr->type == PC_COMMENT) {
2052           pCodeInsertAfter(pc, newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2053         }
2054
2055
2056         pc = pc->next;
2057 #ifdef PCODE_DEBUG
2058         DFPRINTF((stderr,"  NEW Code:"));
2059         if(pc) pc->print(stderr,pc);
2060 #endif
2061         pcr = pcr->next;
2062       }
2063
2064       /* We have just replaced the inefficient code with the rule.
2065        * Now, we need to re-add the C-source symbols if there are any */
2066       pc = pcprev;
2067       while(pc_cline ) {
2068        
2069         pc =  findNextInstruction(pc->next);
2070         PCI(pc)->cline = pc_cline;
2071         pc_cline = PCCS(pc_cline->pc.next);
2072         
2073       }
2074
2075       return 1;
2076     }
2077   next_rule:
2078     peeprules = peeprules->next;
2079   }
2080   DFPRINTF((stderr," no rule matched\n"));
2081
2082   return 0;
2083 }