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