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