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