More enhancements to register optimization algorithms.
[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   char *lnstart=ln;
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
671   while(*ln) {
672
673     if(isspace(*ln)) {
674       // add a SPACE token and eat the extra spaces.
675       tokArr[tokIdx++].tt = PCT_SPACE;
676       while (isspace (*ln))
677         ln++;
678       continue;
679     }
680
681     if(isdigit(*ln)) {
682
683       tokArr[tokIdx].tt = PCT_NUMBER;
684       tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
685
686       continue;
687
688     }
689
690     switch(*ln) {
691     case '%':
692       tokArr[tokIdx++].tt = PCT_PERCENT;
693       break;
694     case '<':
695       tokArr[tokIdx++].tt = PCT_LESSTHAN;
696       break;
697     case '>':
698       tokArr[tokIdx++].tt = PCT_GREATERTHAN;
699       break;
700     case ':':
701       tokArr[tokIdx++].tt = PCT_COLON;
702       break;
703     case ';':
704       tokArr[tokIdx].tok.s = Safe_strdup(ln);
705       tokArr[tokIdx++].tt = PCT_COMMENT;
706       tokArr[tokIdx].tt = PCT_NULL;
707       return;
708     case ',':
709       tokArr[tokIdx++].tt = PCT_COMMA;
710       break;
711
712
713     default:
714       if(isalpha(*ln) || (*ln == '_') ) {
715         char buffer[50];
716         int i=0;
717
718         while( (isalpha(*ln)  ||  isdigit(*ln) || (*ln == '_')) && i<49)
719           buffer[i++] = *ln++;
720
721         ln--;
722         buffer[i] = 0;
723
724         tokArr[tokIdx].tok.s = Safe_strdup(buffer);
725         tokArr[tokIdx++].tt = PCT_STRING;
726
727       } else {
728         fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
729         fprintf(stderr, "Line: %s\n",lnstart);
730         fprintf(stderr, "Token: '%c'\n",*ln);
731         exit(1);
732       }
733     }
734
735     /* Advance to next character in input string .
736      * Note, if none of the tests passed above, then 
737      * we effectively ignore the `bad' character.
738      * Since the line has already been parsed by SDCCpeeph,
739      * chance are that there are no invalid characters... */
740
741     ln++;
742
743   }
744
745   tokArr[tokIdx].tt = 0;
746 }
747
748
749 /*-----------------------------------------------------------------*/
750 /*-----------------------------------------------------------------*/
751
752
753
754 void dump1Token(pCodeTokens tt)
755 {
756 #ifdef PCODE_DEBUG
757   switch(tt) {
758   case PCT_SPACE:
759     fprintf(stderr, " space ");
760     break;
761   case PCT_PERCENT:
762     fprintf(stderr, " pct %%");
763     break;
764   case PCT_LESSTHAN:
765     fprintf(stderr, " pct <");
766     break;
767   case PCT_GREATERTHAN:
768     fprintf(stderr, " pct >");
769     break;
770   case PCT_COLON:
771     fprintf(stderr, " col :");
772     break;
773   case PCT_COMMA:
774     fprintf(stderr, " comma , ");
775     break;
776   case PCT_COMMENT:
777     fprintf(stderr, " comment ");
778     //fprintf(stderr,"%s",tokArr[i].tok.s);
779     break;
780   case PCT_STRING:
781     fprintf(stderr, " str ");
782     //fprintf(stderr,"%s",tokArr[i].tok.s);
783     break;
784   case PCT_NUMBER:
785     fprintf(stderr, " num ");
786     //fprintf(stderr,"%d",tokArr[i].tok.n);
787     break;
788   case PCT_NULL:
789     fprintf(stderr, " null ");
790
791   }
792 #endif
793 }
794
795
796 /*-----------------------------------------------------------------*/
797 /*-----------------------------------------------------------------*/
798
799 int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
800 {
801   int i=0;
802
803   if(!pct || !pat || !*pat)
804     return 0;
805
806   //DFPRINTF((stderr,"comparing against:\n"));
807
808   while(i < max_tokens) {
809
810     if(*pat == 0){
811       //DFPRINTF((stderr,"matched\n"));
812       return (i+1);
813     }
814
815     //dump1Token(*pat); DFPRINTF((stderr,"\n"));
816
817     if(pct->tt != *pat) 
818       return 0;
819
820
821     pct++;
822     pat++;
823   }
824
825   return 0;
826
827 }
828
829 /*-----------------------------------------------------------------*/
830 /*-----------------------------------------------------------------*/
831
832 int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
833 {
834   int i=0;
835   
836   if(!pct || !pat || !*pct)
837     return 0;
838
839
840   while(i < max_tokens) {
841
842     if(*pct == 0) {
843       //DFPRINTF((stderr,"matched\n"));
844       return i;
845     }
846
847     //dump1Token(*pat); DFPRINTF((stderr,"\n"));
848
849     if( !pat || !pat->pcp )
850       return 0;
851
852     if (pat->pcp->pt != *pct)  
853       return 0;
854
855     //DFPRINTF((stderr," pct=%d\n",*pct));
856     pct++;
857     pat++;
858     i++;
859   }
860
861   return 0;
862
863 }
864 /*-----------------------------------------------------------------*/
865 /*-----------------------------------------------------------------*/
866
867 int advTokIdx(int *v, int amt)
868 {
869
870   if((unsigned) (*v + amt) > tokIdx)
871     return 1;
872
873   *v += amt;
874   return 0;
875
876 }
877
878 /*-----------------------------------------------------------------*/
879 /* parseTokens - convert the tokens corresponding to a single line */
880 /*               of a peep hole assembly into a pCode object.      */
881 /*                                                                 */
882 /*                                                                 */
883 /*                                                                 */
884 /*                                                                 */
885 /* This is a simple parser that looks for strings of the type      */
886 /* allowed in the peep hole definition file. Essentially the format*/
887 /* is the same as a line of assembly:                              */
888 /*                                                                 */
889 /*  label:    mnemonic   op1, op2, op3    ; comment                */
890 /*                                                                 */
891 /* Some of these items aren't present. It's the job of the parser  */
892 /* to determine which are and convert those into the appropriate   */
893 /* pcode.                                                          */
894 /*-----------------------------------------------------------------*/
895
896 void parseTokens(pCodeWildBlock *pcwb)
897 {
898   unsigned i;
899   pCode *pc;
900
901   if(!tokIdx)
902     return;
903
904   for(i=0; i<=tokIdx; i++)
905     dump1Token(tokArr[i].tt);
906 #ifdef PCODE_DEBUG
907   fputc('\n',stderr);
908 #endif
909   {
910     int lparsedPatIdx=0;
911     int lpcpIdx;
912     int ltokIdx =0;
913     int matching = 0;
914     int j=0;
915     int k=0;
916
917     char * cPmnem  = NULL;     // Pointer to non-wild mnemonic (if any)
918     char * cP1stop = NULL;
919     char * cP2ndop = NULL;
920
921     //pCodeOp *pcl   = NULL;       // Storage for a label
922     //pCodeOp *pco1  = NULL;       // 1st operand
923     //pCodeOp *pco2  = NULL;       // 2nd operand
924     //pCode   *pc    = NULL;       // Mnemonic
925
926     typedef enum {
927       PS_START,
928       PS_HAVE_LABEL,
929       PS_HAVE_MNEM,
930       PS_HAVE_1OPERAND,
931       PS_HAVE_COMMA,
932       PS_HAVE_2OPERANDS
933     } ParseStates;
934
935     ParseStates state = PS_START;
936
937     do {
938
939       lpcpIdx=0;
940       matching = 0;
941
942       if(  ((tokArr[ltokIdx].tt == PCT_SPACE) )
943            && (advTokIdx(&ltokIdx, 1)) ) // eat space
944         break;
945
946       do {
947         j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
948         if( j ) {
949
950           switch(pcpArr[lpcpIdx].pt) {
951           case  PCP_LABEL:
952             if(state == PS_START){
953               DFPRINTF((stderr,"  label\n"));
954               state = PS_HAVE_LABEL;
955             } else 
956               DFPRINTF((stderr,"  bad state (%d) for label\n",state));
957             break;
958
959           case  PCP_STR:
960             DFPRINTF((stderr,"  %s is",tokArr[ltokIdx].tok.s));
961             switch(state) {
962             case PS_START:
963             case PS_HAVE_LABEL:
964               DFPRINTF((stderr,"  mnem\n"));
965               cPmnem = tokArr[ltokIdx].tok.s;
966               state = PS_HAVE_MNEM;
967               break;
968             case PS_HAVE_MNEM:
969               DFPRINTF((stderr,"  1st operand\n"));
970               cP1stop = tokArr[ltokIdx].tok.s;
971               //pco1 = newpCodeOp(NULL,PO_GPR_REGISTER);
972               state = PS_HAVE_1OPERAND;
973               break;
974             case PS_HAVE_1OPERAND:
975               DFPRINTF((stderr,"  error expecting comma\n"));
976               break;
977             case PS_HAVE_COMMA:
978               DFPRINTF((stderr,"  2 operands\n"));
979               cP2ndop = tokArr[ltokIdx].tok.s;
980               break;
981             case PS_HAVE_2OPERANDS:
982               break;
983             }
984             break;
985
986           case  PCP_WILDVAR:
987             switch(state) {
988             case PS_START:
989             case PS_HAVE_LABEL:
990               DFPRINTF((stderr,"  wild mnem\n"));
991               state = PS_HAVE_MNEM;
992               break;
993             case PS_HAVE_MNEM:
994               DFPRINTF((stderr,"  1st operand is wild\n"));
995               state = PS_HAVE_1OPERAND;
996               break;
997             case PS_HAVE_1OPERAND:
998               DFPRINTF((stderr,"  error expecting comma\n"));
999               break;
1000             case PS_HAVE_COMMA:
1001               DFPRINTF((stderr,"  2nd operand is wild\n"));
1002               break;
1003             case PS_HAVE_2OPERANDS:
1004               break;
1005             }
1006             break;
1007
1008           case  PCP_NUMBER:
1009             switch(state) {
1010             case PS_START:
1011             case PS_HAVE_LABEL:
1012               fprintf(stderr,"  ERROR number\n");
1013               break;
1014             case PS_HAVE_MNEM:
1015               DFPRINTF((stderr,"  1st operand is a number\n"));
1016               state = PS_HAVE_1OPERAND;
1017               break;
1018             case PS_HAVE_1OPERAND:
1019               fprintf(stderr,"  error expecting comma\n");
1020               break;
1021             case PS_HAVE_COMMA:
1022               DFPRINTF((stderr,"  2nd operand is a number\n"));
1023               break;
1024             case PS_HAVE_2OPERANDS:
1025               break;
1026             }
1027             break;
1028
1029           case  PCP_WILDSTR:
1030             break;
1031           case  PCP_COMMA:
1032             if(state == PS_HAVE_1OPERAND){
1033               DFPRINTF((stderr,"  got a comma\n"));
1034               state = PS_HAVE_COMMA;
1035             } else
1036               fprintf(stderr,"  unexpected comma\n");
1037             break;
1038
1039           }
1040
1041           matching = 1;
1042           parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1043           parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1044           lparsedPatIdx++;
1045
1046           //dump1Token(tokArr[ltokIdx].tt);
1047
1048           if(advTokIdx(&ltokIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1049             DFPRINTF((stderr," reached end \n"));
1050             matching = 0;
1051             //return;
1052           }
1053         }
1054
1055
1056       } while ((++lpcpIdx < PCPATTERNS) && !matching);
1057
1058     } while (matching);
1059
1060     parsedPatArr[lparsedPatIdx].pcp = NULL;
1061     parsedPatArr[lparsedPatIdx].pct = NULL;
1062
1063     j=k=0;
1064     do {
1065       int c;
1066
1067       if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1068
1069         if( altArr[k].f) {
1070           pc = altArr[k].f(&parsedPatArr[j],pcwb);
1071           //if(pc && pc->print)
1072           //  pc->print(stderr,pc);
1073           //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1074
1075           //if(curBlock && pc)
1076           //addpCode2pBlock(curBlock, pc);
1077           addpCode2pBlock(pcwb->pb, pc);
1078         }
1079         j += c;
1080       }
1081       k++;
1082     }
1083     while(j<=lparsedPatIdx && k<ALTPATTERNS);
1084
1085 /*
1086     DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1087
1088     j = 0;
1089     do {
1090       if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1091         parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1092       DFPRINTF((stderr,"  %d",parsedPatArr[j].pcp->pt));
1093       j++;
1094     }
1095     while(j<lparsedPatIdx);
1096 */
1097     DFPRINTF((stderr,"\n"));
1098
1099   }
1100
1101
1102 }
1103
1104 /*-----------------------------------------------------------------*/
1105 /*                                                                 */
1106 /*-----------------------------------------------------------------*/
1107 void  peepRuleBlock2pCodeBlock(  lineNode *ln, pCodeWildBlock *pcwb)
1108 {
1109
1110   if(!ln)
1111     return;
1112
1113   for( ; ln; ln = ln->next) {
1114
1115     //DFPRINTF((stderr,"%s\n",ln->line));
1116
1117     tokenizeLineNode(ln->line);
1118     parseTokens(pcwb);
1119
1120   }
1121 }
1122
1123 /*-----------------------------------------------------------------*/
1124 /* peepRuleCondition                                               */
1125 /*-----------------------------------------------------------------*/
1126 static void   peepRuleCondition(char *cond, pCodePeep *pcp)
1127 {
1128   if(!cond || !pcp)
1129     return;
1130
1131   //DFPRINTF((stderr,"\nCondition:  %s\n",cond));
1132   /* brute force compares for now */
1133
1134   if(STRCASECMP(cond, "NZ") == 0) {
1135     //DFPRINTF((stderr,"found NZ\n"));
1136     pcp->postFalseCond = PCC_Z;
1137
1138   }
1139
1140 }
1141
1142
1143 void initpCodeWildBlock(pCodeWildBlock *pcwb)
1144 {
1145   
1146   //  pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1147
1148   if(!pcwb)
1149     return;
1150
1151   pcwb->vars = NULL; 
1152   pcwb->wildpCodes = NULL;
1153   pcwb->wildpCodeOps = NULL;
1154
1155   pcwb->nvars = 0; 
1156   pcwb->nwildpCodes = 0;
1157   pcwb->nops = 0;
1158
1159 }
1160
1161 void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1162 {
1163   
1164   if(!pcwb)
1165     return;
1166
1167   pcwb->nvars+=2;
1168   pcwb->nops = pcwb->nvars;
1169
1170   pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1171   pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1172
1173   pcwb->nwildpCodes+=2;
1174   pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1175
1176 }
1177
1178 void initpCodePeep(pCodePeep *pcp)
1179 {
1180   
1181   //  pcwb = Safe_calloc(1,sizeof(pCodeWildBlock));
1182
1183   if(!pcp)
1184     return;
1185
1186   initpCodeWildBlock(&pcp->target);
1187   pcp->target.pb = newpCodeChain(NULL, 'W', NULL);
1188
1189   initpCodeWildBlock(&pcp->replace);
1190   pcp->replace.pb = newpCodeChain(NULL, 'W', NULL);
1191
1192 }
1193
1194 /*-----------------------------------------------------------------*/
1195 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1196 /*                   pCode.                                        */
1197 /*                                                                 */
1198 /* SDCCpeeph parses the peep rules file and extracts variables,    */
1199 /* removes white space, and checks the syntax. This function       */
1200 /* extends that processing to produce pCode objects. You can kind  */
1201 /* think of this function as an "assembler", though instead of     */
1202 /* taking raw text to produce machine code, it produces pCode.     */
1203 /*                                                                 */
1204 /*-----------------------------------------------------------------*/
1205 extern void pic14initpCodePeepCommands(void);
1206
1207 void  peepRules2pCode(peepRule *rules)
1208 {
1209   peepRule *pr;
1210
1211   pCodePeep *currentRule;
1212   pCodePeepSnippets *pcps;
1213
1214   pic14initpCodePeepCommands();
1215
1216   /* The rules are in a linked-list. Each rule has two portions */
1217   /* There's the `target' and there's the `replace'. The target */
1218   /* is compared against the SDCC generated code and if it      */
1219   /* matches, it gets replaced by the `replace' block of code.  */
1220   /*                                                            */
1221   /* Here we loop through each rule and convert the target's and*/
1222   /* replace's into pCode target and replace blocks             */
1223
1224   for (pr = rules; pr; pr = pr->next) {
1225
1226     //DFPRINTF((stderr,"\nRule:\n\n"));
1227
1228     pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1229     peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1230
1231     currentRule = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
1232     initpCodePeep(currentRule);
1233
1234     /* Convert the target block */
1235     peepRuleBlock2pCodeBlock(pr->match, &currentRule->target);
1236
1237     //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1238     //printpBlock(stderr, currentRule->target.pb);
1239
1240     //DFPRINTF((stderr,"target with labels merged:\n"));
1241     //pBlockMergeLabels(curBlock);
1242     pBlockMergeLabels(currentRule->target.pb);
1243     //printpBlock(stderr, currentRule->replace.pb);
1244
1245     //#ifdef PCODE_DEBUG
1246     //    printpBlock(stderr, curBlock);
1247     //#endif
1248     //DFPRINTF((stderr,"\nReplaced by:\n"));
1249
1250
1251     /* Convert the replace block */
1252     peepRuleBlock2pCodeBlock(pr->replace, &currentRule->replace);
1253
1254     //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1255     //printpBlock(stderr, curBlock);
1256
1257     //DFPRINTF((stderr,"replace with labels merged:\n"));
1258
1259     pBlockMergeLabels(currentRule->replace.pb);
1260     //printpBlock(stderr, currentRule->replace.pb);
1261
1262     peepRuleCondition(pr->cond,currentRule);
1263
1264     /* The rule has been converted to pCode. Now allocate
1265      * space for the wildcards */
1266     
1267     postinit_pCodeWildBlock(&currentRule->target);
1268     postinit_pCodeWildBlock(&currentRule->replace);
1269
1270     //return; // debug ... don't want to go through all the rules yet
1271   }
1272
1273   {
1274     pCodePeep *peepBlock;
1275     _DLL *peeprules;
1276
1277     peeprules = (_DLL *)peepSnippets;
1278     //fprintf(stderr,"target rules\n");
1279     while(peeprules) {
1280       //fprintf(stderr,"   rule:\n");
1281       peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1282       //printpBlock(stderr, peepBlock->target.pb);
1283       peeprules = peeprules->next;
1284     }
1285     //fprintf(stderr," ... done\n");
1286   }
1287
1288 }
1289
1290 void printpCodeString(FILE *of, pCode *pc, int max)
1291 {
1292   int i=0;
1293
1294   while(pc && (i++<max)) {
1295     pc->print(of,pc);
1296     pc = pc->next;
1297   }
1298 }
1299
1300 /*-----------------------------------------------------------------*/
1301 /* _DLL * DLL_append                                               */
1302 /*                                                                 */ 
1303 /*  Append a _DLL object to the end of a _DLL (doubly linked list) */ 
1304 /* If The list to which we want to append is non-existant then one */ 
1305 /* is created. Other wise, the end of the list is sought out and   */ 
1306 /* a new DLL object is appended to it. In either case, the void    */
1307 /* *data is added to the newly created DLL object.                 */
1308 /*-----------------------------------------------------------------*/
1309
1310 static void * DLL_append(_DLL *list, _DLL *next)
1311 {
1312   _DLL *b;
1313
1314
1315   /* If there's no list, then create one: */
1316   if(!list) {
1317     next->next = next->prev = NULL;
1318     return next;
1319   }
1320
1321
1322   /* Search for the end of the list. */
1323   b = list;
1324   while(b->next)
1325     b = b->next;
1326
1327   /* Now append the new DLL object */
1328   b->next = next;
1329   b->next->prev = b;
1330   b = b->next; 
1331   b->next = NULL;
1332
1333   return list;
1334   
1335 }  
1336
1337
1338 /*-----------------------------------------------------------------
1339
1340   pCode peephole optimization
1341
1342
1343   The pCode "peep hole" optimization is not too unlike the peep hole
1344   optimization in SDCCpeeph.c. The major difference is that here we
1345   use pCode's whereas there we use ASCII strings. The advantage with
1346   pCode's is that we can ascertain flow information in the instructions
1347   being optimized.
1348
1349
1350 <FIX ME> - elaborate...
1351
1352   -----------------------------------------------------------------*/
1353
1354
1355
1356 /*-----------------------------------------------------------------*/
1357 /* pCodeSearchCondition - Search a pCode chain for a 'condition'   */
1358 /*                                                                 */
1359 /* return conditions                                               */
1360 /*  1 - The Condition was found for a pCode's input                */
1361 /*  0 - No matching condition was found for the whole chain        */
1362 /* -1 - The Condition was found for a pCode's output               */
1363 /*                                                                 */
1364 /*-----------------------------------------------------------------*/
1365 int pCodeSearchCondition(pCode *pc, unsigned int cond)
1366 {
1367   //fprintf(stderr,"Checking conditions %d\n",cond);
1368   while(pc) {
1369
1370     /* If we reach a function end (presumably an end since we most
1371        probably began the search in the middle of a function), then
1372        the condition was not found. */
1373     if(pc->type == PC_FUNCTION)
1374       return 0;
1375
1376     if(pc->type == PC_OPCODE) {
1377       //fprintf(stderr," checking conditions of: ");
1378       //pc->print(stderr,pc);
1379       //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
1380       if(PCI(pc)->inCond & cond)
1381         return 1;
1382       if(PCI(pc)->outCond & cond)
1383         return -1;
1384     }
1385
1386     pc = pc->next;
1387   }
1388
1389   return 0;
1390 }
1391
1392 /*-----------------------------------------------------------------
1393  * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1394  *
1395  * Compare two pCodeOp's and return 1 if they're the same
1396  *-----------------------------------------------------------------*/
1397 int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1398 {
1399   char b[50], *n2;
1400
1401   if(!pcops || !pcopd)
1402     return 0;
1403 /*
1404   fprintf(stderr," Comparing operands %s",
1405           get_op( pcops,NULL,0));
1406
1407   fprintf(stderr," to %s\n",
1408           get_op( pcopd,NULL,0));
1409 */
1410
1411   if(pcops->type != pcopd->type) {
1412     //fprintf(stderr,"  - fail - diff types\n");
1413     return 0;  // different types
1414   }
1415
1416   if(pcops->type == PO_LITERAL) {
1417
1418     if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
1419       return 1;
1420
1421     return 0;
1422   }
1423
1424   b[0]=0;
1425   get_op(pcops,b,50);
1426
1427   n2 = get_op(pcopd,NULL,0);
1428
1429   if( !n2 || strcmp(b,n2)) {
1430     //fprintf(stderr,"  - fail - diff names: %s, len=%d,  %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1431     return 0;  // different names
1432   }
1433
1434   switch(pcops->type) {
1435   case PO_DIR:
1436     if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1437       //fprintf(stderr, "  - fail different instances\n");
1438       return 0;
1439     }
1440     break;
1441   default:
1442     break;
1443   }
1444
1445   //fprintf(stderr,"  - pass\n");
1446
1447   return 1;
1448 }
1449
1450 int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1451 {
1452   int labindex;
1453
1454   /* Check for a label associated with this wild pCode */
1455   // If the wild card has a label, make sure the source code does too.
1456   if(PCI(pcd)->label) {
1457     pCode *pcl = PCI(pcd)->label->pc;
1458
1459 #ifdef PCODE_DEBUG
1460     int li = -PCL(pcl)->key;
1461
1462     if(peepBlock->target.vars[li] == NULL) {
1463       if(PCI(pcs)->label) {
1464         DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1465       }
1466     } else {
1467       // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1468       DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1469       if(PCI(pcs)->label) {
1470         DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1471       }
1472     }
1473 #endif
1474
1475
1476     if(!PCI(pcs)->label)
1477       return 0;
1478
1479     labindex = -PCL(pcl)->key;
1480     if(peepBlock->target.vars[labindex] == NULL) {
1481       // First time to encounter this label
1482       peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1483       DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1484
1485     } else {
1486       if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1487         DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1488         return 0;
1489       }
1490       DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1491     }
1492   } else {
1493     //DFPRINTF((stderr,"destination doesn't have a label\n"));
1494
1495     if(PCI(pcs)->label)
1496       return 0;
1497
1498     //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1499
1500   }
1501
1502   return 1;
1503     
1504 }
1505
1506 /*-----------------------------------------------------------------*/
1507 /* pCodePeepMatchLine - Compare source and destination pCodes to   */
1508 /*                      see they're the same.                      */
1509 /*                                                                 */
1510 /* In this context, "source" refers to the coded generated by gen.c*/
1511 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1512 /* ination has no wild cards, then MatchLine will compare the two  */
1513 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1514 /* has wildcards, then those get expanded. When a wild card is     */
1515 /* encountered for the first time it autmatically is considered a  */
1516 /* match and the object that matches it is referenced in the       */
1517 /* variables or opcodes array (depending on the type of match).    */
1518 /*                                                                 */
1519 /*                                                                 */
1520 /* Inputs:                                                         */
1521 /*  *peepBlock - A pointer to the peepBlock that contains the      */
1522 /*               entire rule to which the destination pcode belongs*/
1523 /*  *pcs - a pointer to the source pcode                           */
1524 /*  *pcd - a pointer to the destination pcode                      */
1525 /*                                                                 */
1526 /* Returns:                                                        */
1527 /*  1 - pcodes match                                               */
1528 /*  0 - pcodes don't match                                         */
1529 /*                                                                 */
1530 /*                                                                 */
1531 /*-----------------------------------------------------------------*/
1532
1533 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1534 {
1535   int index;   // index into wild card arrays
1536
1537   /* one-for-one match. Here the source and destination opcodes 
1538    * are not wild. However, there may be a label or a wild operand */
1539
1540   if(pcs) {
1541     if(PCI(pcs)->label) {
1542       DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1543     }
1544   }
1545
1546   if(pcs->type == pcd->type) {
1547
1548     if(pcs->type == PC_OPCODE) {
1549
1550       /* If the opcodes don't match then the line doesn't match */
1551       if(PCI(pcs)->op != PCI(pcd)->op)
1552         return 0;
1553
1554 #ifdef PCODE_DEBUG
1555       DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1556       pcs->print(stderr,pcs);
1557       pcd->print(stderr,pcd);
1558 #endif
1559
1560       if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1561         return 0;
1562
1563       /* Compare the operands */
1564       if(PCI(pcd)->pcop) {
1565         if (PCI(pcd)->pcop->type == PO_WILD) {
1566           index = PCOW(PCI(pcd)->pcop)->id;
1567           //DFPRINTF((stderr,"destination is wild\n"));
1568 #ifdef DEBUG_PCODEPEEP
1569           if (index > peepBlock->nops) {
1570             DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1571             exit(1);
1572           }
1573 #endif
1574
1575           PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1576           if(!peepBlock->target.wildpCodeOps[index]) {
1577             peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1578
1579             //if(PCI(pcs)->pcop->type == PO_GPR_TEMP) 
1580
1581           } else {
1582             /*
1583               pcs->print(stderr,pcs);
1584               pcd->print(stderr,pcd);
1585
1586               fprintf(stderr, "comparing operands of these instructions, result %d\n",
1587               pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1588               );
1589             */
1590
1591             return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1592           }
1593
1594           {
1595             char *n;
1596
1597             switch(PCI(pcs)->pcop->type) {
1598             case PO_GPR_TEMP:
1599             case PO_FSR:
1600               //case PO_INDF:
1601               n = PCOR(PCI(pcs)->pcop)->r->name;
1602
1603               break;
1604             default:
1605               n = PCI(pcs)->pcop->name;
1606             }
1607
1608             if(peepBlock->target.vars[index])
1609               return  (strcmp(peepBlock->target.vars[index],n) == 0);
1610             else {
1611               DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1612               peepBlock->target.vars[index] = n;
1613               return 1;
1614             }
1615           }
1616
1617         } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
1618           return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
1619
1620         }
1621         /* FIXME - need an else to check the case when the destination 
1622          * isn't a wild card */
1623       } else
1624         /* The pcd has no operand. Lines match if pcs has no operand either*/
1625         return (PCI(pcs)->pcop == NULL);
1626     }
1627   }
1628
1629   /* Compare a wild instruction to a regular one. */
1630
1631   if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1632
1633     index = PCW(pcd)->id;
1634 #ifdef PCODE_DEBUG
1635     DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
1636     pcs->print(stderr,pcs);
1637     pcd->print(stderr,pcd);
1638 #endif
1639     peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
1640
1641     if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
1642       DFPRINTF((stderr," Failing because labels don't match\n"));
1643       return 0;
1644     }
1645
1646     if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1647       // doesn't match because the wild pcode must be a bit skip
1648       DFPRINTF((stderr," Failing match because bit skip is req\n"));
1649       //pcd->print(stderr,pcd);
1650       //pcs->print(stderr,pcs);
1651       return 0;
1652     } 
1653
1654     if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
1655       // doesn't match because the wild pcode must *not* be a bit skip
1656       DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
1657       //pcd->print(stderr,pcd);
1658       //pcs->print(stderr,pcs);
1659       return 0;
1660     } 
1661
1662     if(PCW(pcd)->operand) {
1663       PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1664       if(peepBlock->target.vars[index]) {
1665         int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
1666 #ifdef PCODE_DEBUG
1667
1668         if(i)
1669           DFPRINTF((stderr," (matched)\n"));
1670         else {
1671           DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
1672           DFPRINTF((stderr,"  peepblock= %s,  pcodeop= %s\n",
1673                   peepBlock->target.vars[index],
1674                   PCI(pcs)->pcop->name));
1675         }
1676 #endif
1677         return i;
1678       } else {
1679         DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
1680         peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
1681         return 1;
1682       }
1683     }
1684
1685     pcs = findNextInstruction(pcs->next); 
1686     if(pcs) {
1687       //DFPRINTF((stderr," (next to match)\n"));
1688       //pcs->print(stderr,pcs);
1689     } else if(pcd->next) {
1690       /* oops, we ran out of code, but there's more to the rule */
1691       return 0;
1692     }
1693
1694     return 1; /*  wild card matches */
1695   }
1696
1697   return 0;
1698 }
1699
1700 /*-----------------------------------------------------------------*/
1701 /*-----------------------------------------------------------------*/
1702 void pCodePeepClrVars(pCodePeep *pcp)
1703 {
1704
1705   int i;
1706   if(!pcp)
1707     return;
1708 /*
1709   DFPRINTF((stderr," Clearing peep rule vars\n"));
1710   DFPRINTF((stderr," %d %d %d  %d %d %d\n",
1711             pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
1712             pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
1713 */
1714   for(i=0;i<pcp->target.nvars; i++)
1715     pcp->target.vars[i] = NULL;
1716   for(i=0;i<pcp->target.nops; i++)
1717     pcp->target.wildpCodeOps[i] = NULL;
1718   for(i=0;i<pcp->target.nwildpCodes; i++)
1719     pcp->target.wildpCodes[i] = NULL;
1720
1721   for(i=0;i<pcp->replace.nvars; i++)
1722     pcp->replace.vars[i] = NULL;
1723   for(i=0;i<pcp->replace.nops; i++)
1724     pcp->replace.wildpCodeOps[i] = NULL;
1725   for(i=0;i<pcp->replace.nwildpCodes; i++)
1726     pcp->replace.wildpCodes[i] = NULL;
1727
1728
1729
1730 }
1731
1732 /*-----------------------------------------------------------------*/
1733 /*  pCodeInsertAfter - splice in the pCode chain starting with pc2 */
1734 /*                     into the pCode chain containing pc1         */
1735 /*-----------------------------------------------------------------*/
1736 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
1737 {
1738
1739   if(!pc1 || !pc2)
1740     return;
1741
1742   pc2->next = pc1->next;
1743   if(pc1->next)
1744     pc1->next->prev = pc2;
1745
1746   pc2->pb = pc1->pb;
1747   pc2->prev = pc1;
1748   pc1->next = pc2;
1749
1750 }
1751
1752 /*-----------------------------------------------------------------*/
1753 /* pCodeOpCopy - copy a pcode operator                             */
1754 /*-----------------------------------------------------------------*/
1755 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
1756 {
1757   pCodeOp *pcopnew=NULL;
1758
1759   if(!pcop)
1760     return NULL;
1761
1762   switch(pcop->type) { 
1763   case PO_CRY:
1764   case PO_BIT:
1765     //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
1766     pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1767     PCORB(pcopnew)->bit = PCORB(pcop)->bit;
1768     PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
1769
1770     break;
1771
1772   case PO_WILD:
1773     /* Here we expand the wild card into the appropriate type: */
1774     /* By recursively calling pCodeOpCopy */
1775     //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
1776     if(PCOW(pcop)->matched)
1777       pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
1778     else {
1779       // Probably a label
1780       pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
1781       pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
1782       //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
1783     }
1784
1785     return pcopnew;
1786     break;
1787
1788   case PO_LABEL:
1789     //DFPRINTF((stderr,"pCodeOpCopy label\n"));
1790     pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1791     PCOLAB(pcopnew)->key =  PCOLAB(pcop)->key;
1792     break;
1793
1794   case PO_IMMEDIATE:
1795     pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
1796     PCOI(pcopnew)->index = PCOI(pcop)->index;
1797     PCOI(pcopnew)->offset = PCOI(pcop)->offset;
1798     PCOI(pcopnew)->_const = PCOI(pcop)->_const;
1799     break;
1800
1801   case PO_LITERAL:
1802     //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
1803     pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1804     PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1805     break;
1806
1807   case PO_GPR_BIT:
1808
1809     pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
1810     PCOR(pcopnew)->r = PCOR(pcop)->r;
1811     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1812     DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
1813     return pcopnew;
1814     break;
1815
1816   case PO_GPR_REGISTER:
1817   case PO_GPR_TEMP:
1818   case PO_FSR:
1819   case PO_INDF:
1820     //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
1821     pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1822     PCOR(pcopnew)->r = PCOR(pcop)->r;
1823     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1824     PCOR(pcopnew)->instance = PCOR(pcop)->instance;
1825     DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
1826     break;
1827
1828   case PO_DIR:
1829     //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
1830     pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1831     PCOR(pcopnew)->r = PCOR(pcop)->r;
1832     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1833     PCOR(pcopnew)->instance = PCOR(pcop)->instance;
1834     break;
1835   case PO_STATUS:
1836     DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
1837   case PO_SFR_REGISTER:
1838   case PO_STR:
1839   case PO_NONE:
1840   case PO_W:
1841   case PO_INTCON:
1842   case PO_PCL:
1843   case PO_PCLATH:
1844
1845     //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
1846     pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1847
1848   }
1849
1850   pcopnew->type = pcop->type;
1851   if(pcop->name)
1852     pcopnew->name = Safe_strdup(pcop->name);
1853   else
1854     pcopnew->name = NULL;
1855
1856   return pcopnew;
1857 }
1858
1859
1860 /*-----------------------------------------------------------------*/
1861 /* pCodeCopy - copy a pcode                                        */
1862 /*-----------------------------------------------------------------*/
1863 static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
1864 {
1865   pCodeInstruction *new_pci;
1866
1867   if(invert)
1868     new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
1869   else
1870     new_pci = PCI(newpCode(pci->op,pci->pcop));
1871
1872   new_pci->pc.pb = pci->pc.pb;
1873   new_pci->from = pci->from;
1874   new_pci->to   = pci->to;
1875   new_pci->label = pci->label;
1876   new_pci->pcflow = pci->pcflow;
1877
1878   return PCODE(new_pci);
1879 }
1880
1881 /*-----------------------------------------------------------------*/
1882 /*-----------------------------------------------------------------*/
1883 void pCodeDeleteChain(pCode *f,pCode *t)
1884 {
1885   pCode *pc;
1886
1887
1888   while(f && f!=t) {
1889     DFPRINTF((stderr,"delete pCode:\n"));
1890     pc = f->next;
1891     //f->print(stderr,f);
1892     //f->delete(f);  this dumps core...
1893
1894     f = pc;
1895
1896   }
1897
1898 }
1899 /*-----------------------------------------------------------------*/
1900 /*-----------------------------------------------------------------*/
1901 int pCodePeepMatchRule(pCode *pc)
1902 {
1903   pCodePeep *peepBlock;
1904   pCode *pct, *pcin;
1905   pCodeCSource *pc_cline=NULL;
1906   _DLL *peeprules;
1907   int matched;
1908
1909   peeprules = (_DLL *)peepSnippets;
1910
1911   while(peeprules) {
1912     peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1913
1914     if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
1915       fprintf(stderr, "skipping rule because target pb is NULL\n");
1916       goto next_rule;
1917     }
1918
1919     pCodePeepClrVars(peepBlock);
1920 /*
1921     pcin = pc;
1922     if(IS_PCCOMMENT(pcin))
1923       pc = pcin = findNextInstruction(pcin->next);
1924 */
1925     pcin = pc = findNextInstruction(pc);
1926
1927     pct = peepBlock->target.pb->pcHead;
1928 #ifdef PCODE_DEBUG
1929     {
1930       pCode *pcr = peepBlock->replace.pb->pcHead;
1931       if(pcr) pct->print(stderr,pcr);
1932     }
1933 #endif
1934     matched = 0;
1935     while(pct && pcin) {
1936
1937       if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1938         break;
1939
1940       pcin = findNextInstruction(pcin->next);
1941       pct = pct->next;
1942       //debug:
1943       //DFPRINTF((stderr,"    matched\n"));
1944
1945       if(!pcin && pct) {
1946         DFPRINTF((stderr," partial match... no more code\n"));
1947         fprintf(stderr," partial match... no more code\n");
1948         matched = 0; 
1949       }
1950       if(!pct) {
1951         DFPRINTF((stderr," end of rule\n"));
1952       }
1953     }
1954
1955     if(matched && pcin) {
1956
1957       /* So far we matched the rule up to the point of the conditions .
1958        * In other words, all of the opcodes match. Now we need to see
1959        * if the post conditions are satisfied.
1960        * First we check the 'postFalseCond'. This means that we check
1961        * to see if any of the subsequent pCode's in the pCode chain 
1962        * following the point just past where we have matched depend on
1963        * the `postFalseCond' as input then we abort the match
1964        */
1965       DFPRINTF((stderr,"    matched rule so far, now checking conditions\n"));
1966       //pcin->print(stderr,pcin);
1967       
1968       if (pcin && peepBlock->postFalseCond && 
1969           (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
1970         matched = 0;
1971
1972       //fprintf(stderr," condition results = %d\n",pCodeSearchCondition(pcin,peepBlock->postFalseCond));
1973
1974
1975       //if(!matched) fprintf(stderr,"failed on conditions\n");
1976     }
1977
1978     if(matched) {
1979
1980       pCode *pcprev;
1981       pCode *pcr;
1982
1983
1984       /* We matched a rule! Now we have to go through and remove the
1985          inefficient code with the optimized version */
1986 #ifdef PCODE_DEBUG
1987       DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
1988       printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
1989       DFPRINTF((stderr,"first thing matched\n"));
1990       pc->print(stderr,pc);
1991       if(pcin) {
1992         DFPRINTF((stderr,"last thing matched\n"));
1993         pcin->print(stderr,pcin);
1994       }
1995 #endif
1996
1997
1998       /* Unlink the original code */
1999       pcprev = pc->prev;
2000       pcprev->next = pcin;
2001       if(pcin) 
2002         pcin->prev = pc->prev;
2003
2004
2005       //#if 0
2006       {
2007         /*     DEBUG    */
2008         /* Converted the deleted pCodes into comments */
2009
2010         char buf[256];
2011         pCodeCSource *pc_cline2=NULL;
2012
2013         buf[0] = ';';
2014         buf[1] = '#';
2015
2016         while(pc &&  pc!=pcin) {
2017
2018           if(pc->type == PC_OPCODE && PCI(pc)->cline) {
2019             if(pc_cline) {
2020               pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2021               pc_cline2 = PCCS(pc_cline2->pc.next);
2022             } else {
2023               pc_cline = pc_cline2 = PCI(pc)->cline;
2024               pc_cline->pc.seq = pc->seq;
2025             }
2026           }
2027
2028           pCode2str(&buf[2], 254, pc);
2029           pCodeInsertAfter(pcprev, newpCodeCharP(buf));
2030           pcprev = pcprev->next;
2031           pc = pc->next;
2032
2033         }
2034         if(pc_cline2)
2035           pc_cline2->pc.next = NULL;
2036       }
2037       //#endif
2038
2039       if(pcin)
2040         pCodeDeleteChain(pc,pcin);
2041
2042       /* Generate the replacement code */
2043       pc = pcprev;
2044       pcr = peepBlock->replace.pb->pcHead;  // This is the replacement code
2045       while (pcr) {
2046         pCodeOp *pcop=NULL;
2047         
2048         /* If the replace pcode is an instruction with an operand, */
2049         /* then duplicate the operand (and expand wild cards in the process). */
2050         if(pcr->type == PC_OPCODE) {
2051           if(PCI(pcr)->pcop) {
2052             /* The replacing instruction has an operand.
2053              * Is it wild? */
2054             if(PCI(pcr)->pcop->type == PO_WILD) {
2055               int index = PCOW(PCI(pcr)->pcop)->id;
2056               //DFPRINTF((stderr,"copying wildopcode\n"));
2057               if(peepBlock->target.wildpCodeOps[index])
2058                 pcop = pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2059               else
2060                 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2061             } else
2062               pcop = pCodeOpCopy(PCI(pcr)->pcop);
2063           }
2064           //DFPRINTF((stderr,"inserting pCode\n"));
2065           pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
2066         } else if (pcr->type == PC_WILD) {
2067           if(PCW(pcr)->invertBitSkipInst)
2068             DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2069           pCodeInsertAfter(pc,
2070                            pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2071                                                 PCW(pcr)->invertBitSkipInst));
2072         } else if (pcr->type == PC_COMMENT) {
2073           pCodeInsertAfter(pc, newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2074         }
2075
2076
2077         pc = pc->next;
2078 #ifdef PCODE_DEBUG
2079         DFPRINTF((stderr,"  NEW Code:"));
2080         if(pc) pc->print(stderr,pc);
2081 #endif
2082         pcr = pcr->next;
2083       }
2084
2085       /* We have just replaced the inefficient code with the rule.
2086        * Now, we need to re-add the C-source symbols if there are any */
2087       pc = pcprev;
2088       while(pc_cline ) {
2089        
2090         pc =  findNextInstruction(pc->next);
2091         PCI(pc)->cline = pc_cline;
2092         pc_cline = PCCS(pc_cline->pc.next);
2093         
2094       }
2095
2096       return 1;
2097     }
2098   next_rule:
2099     peeprules = peeprules->next;
2100   }
2101   DFPRINTF((stderr," no rule matched\n"));
2102
2103   return 0;
2104 }