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