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