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