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