More peep to pCode parsing.
[fw/sdcc] / src / pic / pcodepeep.c
1 /*-------------------------------------------------------------------------
2
3    pcodepeep.c - post code generation
4    Written By -  Scott Dattalo scott@dattalo.com
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include "common.h"   // Include everything in the SDCC src directory
25 #include "newalloc.h"
26
27
28 #include "pcode.h"
29 #include "ralloc.h"
30
31
32 pCodeOp *popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
33
34
35 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype);
36 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
37 pCode * findNextInstruction(pCode *pc);
38 char *Safe_strdup(char *str);
39 int getpCode(char *mnem,int dest);
40 extern pCodeInstruction *pic14Mnemonics[];
41
42
43 /****************************************************************/
44 /*
45  * rootRules - defined in SDCCpeep.c
46  *  This is a pointer to the (parsed) peephole rules that are
47  * defined in peep.def.
48  */
49
50 //extern peepRule *rootRules;
51
52
53
54
55 /****************************************************************/
56 /****************************************************************/
57 typedef struct _DLL {
58   struct _DLL *prev;
59   struct _DLL *next;
60   //  void *data;
61 } _DLL;
62
63
64 typedef struct pCodePeepSnippets
65 {
66   _DLL dll;
67   pCodePeep *peep;
68 } pCodePeepSnippets;
69
70
71 /****************************************************************/
72 /*                                                              */
73 /* peepSnippets -                                               */
74 /*                                                              */
75 /****************************************************************/
76
77 static pCodePeepSnippets  *peepSnippets=NULL;
78
79 /****************************************************************/
80 /*                                                              */
81 /* curPeep                                                      */
82 /*                                                              */
83 /****************************************************************/
84
85 static pCodePeep          *curPeep=NULL;
86
87 /****************************************************************/
88 /*                                                              */
89 /* curBlock                                                     */
90 /*                                                              */
91 /****************************************************************/
92
93 static pBlock             *curBlock=NULL;
94
95
96 typedef struct pCodeToken 
97 {
98   int tt;  // token type;
99   union {
100     char c;  // character
101     int  n;  // number
102     char *s; // string
103   } tok;
104
105 } pCodeToken;
106
107 pCodeToken tokArr[50];
108 unsigned   tokIdx=0;
109
110
111 typedef enum  {
112   PCT_SPACE=1,
113   PCT_PERCENT,
114   PCT_COLON,
115   PCT_COMMA,
116   PCT_COMMENT,
117   PCT_STRING,
118   PCT_NUMBER
119
120 } pCodeTokens;
121
122
123 typedef struct parsedPattern {
124   struct pcPattern *pcp;
125   pCodeToken *pct;
126 } parsedPattern;
127
128 #define MAX_PARSEDPATARR 50
129 parsedPattern parsedPatArr[MAX_PARSEDPATARR];
130 unsigned int parsedPatIdx=0;
131
132
133 typedef enum {
134   PCP_LABEL=1,
135   PCP_NUMBER,
136   PCP_STR,
137   PCP_WILDVAR,
138   PCP_WILDSTR,
139   PCP_COMMA
140 } pCodePatterns;
141
142 static char pcpat_label[]      = {PCT_PERCENT, PCT_NUMBER, PCT_COLON, 0};
143 static char pcpat_number[]     = {PCT_NUMBER, 0};
144 static char pcpat_string[]     = {PCT_STRING, 0};
145 static char pcpat_wildString[] = {PCT_PERCENT, PCT_STRING, 0};
146 static char pcpat_wildVar[]    = {PCT_PERCENT, PCT_NUMBER, 0};
147 static char pcpat_comma[]      = {PCT_COMMA, 0};
148
149
150 typedef struct pcPattern {
151   char pt;                 // Pattern type
152   char *tokens;           // list of tokens that describe the pattern
153   void * (*f) (void *);
154 } pcPattern;
155
156 pcPattern pcpArr[] = {
157   {PCP_LABEL,     pcpat_label,      NULL},
158   {PCP_WILDSTR,   pcpat_wildString, NULL},
159   {PCP_STR,       pcpat_string,     NULL},
160   {PCP_WILDVAR,   pcpat_wildVar,    NULL},
161   {PCP_COMMA,     pcpat_comma,      NULL},
162   {PCP_NUMBER,    pcpat_number,     NULL}
163 };
164
165 #define PCPATTERNS (sizeof(pcpArr)/sizeof(pcPattern))
166
167 // Assembly Line Token
168 typedef enum {
169   ALT_LABEL=1,
170   ALT_MNEM0,
171   ALT_MNEM0A,
172   ALT_MNEM1,
173   ALT_MNEM1A,
174   ALT_MNEM1B,
175   ALT_MNEM2,
176   ALT_MNEM2A
177 } altPatterns;
178
179 static char alt_label[]     = { PCP_LABEL, 0};
180 static char alt_mnem0[]     = { PCP_STR, 0};
181 static char alt_mnem0a[]    = { PCP_WILDVAR, 0};
182 static char alt_mnem1[]     = { PCP_STR, PCP_STR, 0};
183 static char alt_mnem1a[]    = { PCP_STR, PCP_WILDVAR, 0};
184 static char alt_mnem1b[]    = { PCP_STR, PCP_NUMBER, 0};
185 static char alt_mnem2[]     = { PCP_STR, PCP_STR, PCP_COMMA, PCP_STR, 0};
186 static char alt_mnem2a[]    = { PCP_STR, PCP_WILDVAR, PCP_COMMA, PCP_STR, 0};
187
188 static void * cvt_altpat_label(void *pp);
189 static void * cvt_altpat_mnem0(void *pp);
190 static void * cvt_altpat_mnem0a(void *pp);
191 static void * cvt_altpat_mnem1(void *pp);
192 static void * cvt_altpat_mnem1a(void *pp);
193 static void * cvt_altpat_mnem1b(void *pp);
194 static void * cvt_altpat_mnem2(void *pp);
195 static void * cvt_altpat_mnem2a(void *pp);
196
197 pcPattern altArr[] = {
198   {ALT_LABEL,        alt_label,  cvt_altpat_label},
199   {ALT_MNEM2A,       alt_mnem2a, cvt_altpat_mnem2a},
200   {ALT_MNEM2,        alt_mnem2,  cvt_altpat_mnem2},
201   {ALT_MNEM1B,       alt_mnem1b, cvt_altpat_mnem1b},
202   {ALT_MNEM1A,       alt_mnem1a, cvt_altpat_mnem1a},
203   {ALT_MNEM1,        alt_mnem1,  cvt_altpat_mnem1},
204   {ALT_MNEM0A,       alt_mnem0a, cvt_altpat_mnem0a},
205   {ALT_MNEM0,        alt_mnem0,  cvt_altpat_mnem0},
206
207 };
208
209 #define ALTPATTERNS (sizeof(altArr)/sizeof(pcPattern))
210
211 // forward declarations
212 static void * DLL_append(_DLL *list, _DLL *next);
213
214 /*-----------------------------------------------------------------*/
215 /* cvt_extract_destination - helper function extracts the register */
216 /*                           destination from a parsedPattern.     */
217 /*                                                                 */
218 /*-----------------------------------------------------------------*/
219 static int cvt_extract_destination(parsedPattern *pp)
220 {
221
222   if(pp->pct[0].tt == PCT_STRING) {
223
224     // just check first letter for now
225
226     if(toupper(*pp->pct[0].tok.s) == 'F')
227       return 1;
228
229   } else if (pp->pct[0].tt == PCT_NUMBER) {
230
231     if(pp->pct[0].tok.n)
232       return 1;
233   }
234
235   return 0;
236
237 }
238
239 /*-----------------------------------------------------------------*/
240 /*  pCodeOp *cvt_extract_status(char *reg, char *bit)              */
241 /*     if *reg is the "status" register and *bit is one of the     */
242 /*     status bits, then this function will create a new pCode op  */
243 /*     containing the status register.                             */
244 /*-----------------------------------------------------------------*/
245
246 static pCodeOp *cvt_extract_status(char *reg, char *bit)
247 {
248   int len;
249
250   if(strcasecmp(reg, pc_status.pcop.name))
251     return NULL;
252
253   len = strlen(bit);
254
255   if(len == 1) {
256     // check C,Z
257     if(toupper(*bit) == 'C')
258       return PCOP(popCopyGPR2Bit(&pc_status,PIC_C_BIT));
259     if(toupper(*bit) == 'Z')
260       return PCOP(popCopyGPR2Bit(&pc_status,PIC_Z_BIT));
261   }
262
263   // Check DC
264   if(len ==2 && toupper(bit[0]) == 'D' && toupper(bit[1]) == 'C')
265     return PCOP(popCopyGPR2Bit(&pc_status,PIC_DC_BIT));
266
267   return NULL;
268
269 }
270
271 /*-----------------------------------------------------------------*/
272 /* cvt_altpat_label - convert assembly line type to a pCode label  */
273 /* INPUT: pointer to the parsedPattern                             */
274 /*                                                                 */
275 /*  pp[0] - label                                                  */
276 /*                                                                 */
277 /* label pattern => '%' number ':'                                 */
278 /* at this point, we wish to extract only the 'number'             */
279 /*                                                                 */
280 /*-----------------------------------------------------------------*/
281 static void * cvt_altpat_label(void *pp)
282 {
283   parsedPattern *p = pp;
284
285   fprintf(stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n);
286   return newpCodeOpLabel(-p->pct[1].tok.n);
287
288 }
289
290 /*-----------------------------------------------------------------*/
291 /*-----------------------------------------------------------------*/
292 static void * cvt_altpat_mnem0(void *pp)
293 {
294   parsedPattern *p = pp;
295   int opcode;
296
297   pCodeInstruction *pci=NULL;
298
299   fprintf(stderr,"altpat_mnem0 %s\n",  p->pct[0].tok.s);
300
301   opcode = getpCode(p->pct[0].tok.s,0);
302   if(opcode < 0) {
303     fprintf(stderr, "Bad mnemonic\n");
304     return NULL;
305   }
306
307   pci = PCI(newpCode(opcode, NULL));
308
309   if(!pci)
310     fprintf(stderr,"couldn't find mnemonic\n");
311
312
313   return pci;
314 }
315
316 /*-----------------------------------------------------------------*/
317 /* cvt_altpat_mem0a - convert assembly line type to a wild pCode   */
318 /*                    instruction                                  */
319 /*                                                                 */
320 /*  pp[0] - wild var                                               */
321 /*                                                                 */
322 /*-----------------------------------------------------------------*/
323 static void * cvt_altpat_mnem0a(void *pp)
324 {
325   parsedPattern *p = pp;
326
327   fprintf(stderr,"altpat_mnem0a wild mnem # %d\n",  p[0].pct[1].tok.n);
328
329   return newpCodeWild(p[0].pct[1].tok.n,NULL,NULL);
330
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* cvt_altpat_mem1 - convert assembly line type to a pCode         */
335 /*                   instruction with 1 operand.                   */
336 /*                                                                 */
337 /*  pp[0] - mnem                                                   */
338 /*  pp[1] - Operand                                                */
339 /*                                                                 */
340 /*-----------------------------------------------------------------*/
341 static void * cvt_altpat_mnem1(void *pp)
342 {
343
344   parsedPattern *p = pp;
345   int opcode;
346
347   pCodeInstruction *pci=NULL;
348   pCodeOp *pcosubtype;
349
350   fprintf(stderr,"altpat_mnem1 %s var %s\n",  p->pct[0].tok.s,p[1].pct[0].tok.s);
351
352   opcode = getpCode(p->pct[0].tok.s,0);
353   if(opcode < 0) {
354     fprintf(stderr, "Bad mnemonic\n");
355     return NULL;
356   }
357
358   if(pic14Mnemonics[opcode]->bit_inst)
359     pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_BIT);
360   else
361     pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
362
363
364   pci = PCI(newpCode(opcode, pcosubtype));
365
366   if(!pci)
367     fprintf(stderr,"couldn't find mnemonic\n");
368
369
370   return pci;
371 }
372
373 /*-----------------------------------------------------------------*/
374 /* cvt_altpat_mem1a - convert assembly line type to a pCode        */
375 /*                    instruction with 1 wild operand.             */
376 /*                                                                 */
377 /*  pp[0] - mnem                                                   */
378 /*  pp[1] - wild var                                               */
379 /*                                                                 */
380 /*-----------------------------------------------------------------*/
381 static void * cvt_altpat_mnem1a(void *pp)
382 {
383   parsedPattern *p = pp;
384   int opcode;
385
386   pCodeInstruction *pci=NULL;
387   pCodeOp *pcosubtype;
388
389   fprintf(stderr,"altpat_mnem1a %s var %d\n",  p->pct[0].tok.s,p[1].pct[1].tok.n);
390
391   opcode = getpCode(p->pct[0].tok.s,0);
392   if(opcode < 0) {
393     fprintf(stderr, "Bad mnemonic\n");
394     return NULL;
395   }
396
397   if(pic14Mnemonics[opcode]->bit_inst)
398     pcosubtype = newpCodeOp(NULL,PO_BIT);
399   else
400     pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
401
402
403   pci = PCI(newpCode(opcode,
404                      newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
405
406   if(!pci)
407     fprintf(stderr,"couldn't find mnemonic\n");
408
409
410   return pci;
411 }
412
413 /*-----------------------------------------------------------------*/
414 /*-----------------------------------------------------------------*/
415 static void * cvt_altpat_mnem1b(void *pp)
416 {
417   parsedPattern *p = pp;
418   int opcode;
419
420   pCodeInstruction *pci=NULL;
421
422   fprintf(stderr,"altpat_mnem1b %s var %d\n",  p->pct[0].tok.s,p[1].pct[0].tok.n);
423
424   opcode = getpCode(p->pct[0].tok.s,0);
425   if(opcode < 0) {
426     fprintf(stderr, "Bad mnemonic\n");
427     return NULL;
428   }
429
430   pci = PCI(newpCode(opcode, newpCodeOpLit(p[1].pct[0].tok.n) ));
431
432   if(!pci)
433     fprintf(stderr,"couldn't find mnemonic\n");
434
435
436   return pci;
437 }
438
439 /*-----------------------------------------------------------------*/
440 /*-----------------------------------------------------------------*/
441 static void * cvt_altpat_mnem2(void *pp)
442 {
443   parsedPattern *p = pp;
444   int opcode;
445   int dest;
446
447   pCodeInstruction *pci=NULL;
448   pCodeOp *pcosubtype;
449
450   dest = cvt_extract_destination(&p[3]);
451
452   fprintf(stderr,"altpat_mnem2 %s var %s destination %s(%d)\n",
453           p->pct[0].tok.s,
454           p[1].pct[0].tok.s,
455           p[3].pct[0].tok.s,
456           dest);
457
458
459   opcode = getpCode(p->pct[0].tok.s,dest);
460   if(opcode < 0) {
461     fprintf(stderr, "Bad mnemonic\n");
462     return NULL;
463   }
464
465   if(pic14Mnemonics[opcode]->bit_inst) {
466     pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
467     if(pcosubtype == NULL) {
468       fprintf(stderr, "bad operand?\n");
469       return NULL;
470     }
471       
472   } else
473     pcosubtype = newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
474
475
476   pci = PCI(newpCode(opcode,pcosubtype));
477
478   if(!pci)
479     fprintf(stderr,"couldn't find mnemonic\n");
480
481   return pci;
482
483 }
484
485 /*-----------------------------------------------------------------*/
486 /* cvt_altpat_mem2a - convert assembly line type to a pCode        */
487 /*                    instruction with 1 wild operand and a        */
488 /*                    destination operand (e.g. w or f)            */
489 /*                                                                 */
490 /*  pp[0] - mnem                                                   */
491 /*  pp[1] - wild var                                               */
492 /*  pp[2] - comma                                                  */
493 /*  pp[3] - destination                                            */
494 /*                                                                 */
495 /*-----------------------------------------------------------------*/
496 static void * cvt_altpat_mnem2a(void *pp)
497 {
498   parsedPattern *p = pp;
499   int opcode;
500   int dest;
501
502   pCodeInstruction *pci=NULL;
503   pCodeOp *pcosubtype;
504
505   dest = cvt_extract_destination(&p[3]);
506
507   fprintf(stderr,"altpat_mnem2a %s var %d destination %s(%d)\n",
508           p->pct[0].tok.s,
509           p[1].pct[1].tok.n,
510           p[3].pct[0].tok.s,
511           dest);
512
513
514   opcode = getpCode(p->pct[0].tok.s,dest);
515   if(opcode < 0) {
516     fprintf(stderr, "Bad mnemonic\n");
517     return NULL;
518   }
519
520   if(pic14Mnemonics[opcode]->bit_inst)
521     pcosubtype = newpCodeOp(NULL,PO_BIT);
522   else
523     pcosubtype = newpCodeOp(NULL,PO_GPR_REGISTER);
524
525
526   pci = PCI(newpCode(opcode,
527                      newpCodeOpWild(p[1].pct[1].tok.n, curPeep, pcosubtype)));
528
529   if(!pci)
530     fprintf(stderr,"couldn't find mnemonic\n");
531
532   return pci;
533
534 }
535
536 /*-----------------------------------------------------------------*/
537 /*-----------------------------------------------------------------*/
538
539
540 static void parseLineNode(char *ln)
541 {
542
543   tokIdx = 0;
544
545   if(!ln || !*ln)
546     return;
547
548   while(*ln) {
549
550     if(isspace(*ln)) {
551       tokArr[tokIdx++].tt = PCT_SPACE;
552       while (isspace (*ln))
553         ln++;
554       continue;
555     }
556
557     if(isdigit(*ln)) {
558
559       tokArr[tokIdx].tt = PCT_NUMBER;
560       tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
561
562       continue;
563
564     }
565
566     switch(*ln) {
567     case '%':
568       tokArr[tokIdx++].tt = PCT_PERCENT;
569       break;
570     case ':':
571       tokArr[tokIdx++].tt = PCT_COLON;
572       break;
573     case ';':
574       tokArr[tokIdx].tok.s = Safe_strdup(ln);
575       tokArr[tokIdx++].tt = PCT_COMMENT;
576       return;
577     case ',':
578       tokArr[tokIdx++].tt = PCT_COMMA;
579       break;
580
581
582     default:
583       if(isalpha(*ln)) {
584         char buffer[50];
585         int i=0;
586
587         while( (isalpha(*ln)  ||  isdigit(*ln)) && i<49)
588           buffer[i++] = *ln++;
589
590         ln--;
591         buffer[i] = 0;
592
593         tokArr[tokIdx].tok.s = Safe_strdup(buffer);
594         //fprintf(stderr," string %s",tokArr[tokIdx].tok.s);
595
596         tokArr[tokIdx++].tt = PCT_STRING;
597
598       }
599     }
600     ln++;
601   }
602
603   tokArr[tokIdx].tt = 0;
604 }
605
606
607 /*-----------------------------------------------------------------*/
608 /*-----------------------------------------------------------------*/
609
610
611
612 void dump1Token(pCodeTokens tt)
613 {
614
615   switch(tt) {
616   case PCT_SPACE:
617     fprintf(stderr, " space ");
618     break;
619   case PCT_PERCENT:
620     fprintf(stderr, " pct ");
621     fputc('%', stderr);
622     break;
623   case PCT_COLON:
624     fprintf(stderr, " col ");
625     fputc(':',stderr);
626     break;
627   case PCT_COMMA:
628     fprintf(stderr, " com ");
629     fputc(',',stderr);
630     break;
631   case PCT_COMMENT:
632   case PCT_STRING:
633     fprintf(stderr, " str ");
634     //fprintf(stderr,"%s",tokArr[i].tok.s);
635     break;
636   case PCT_NUMBER:
637     fprintf(stderr, " num ");
638     //fprintf(stderr,"%d",tokArr[i].tok.n);
639
640
641   }
642 }
643
644
645 /*-----------------------------------------------------------------*/
646 /*-----------------------------------------------------------------*/
647
648 int pcComparePattern(pCodeToken *pct, char *pat, int max_tokens)
649 {
650   int i=0;
651
652   if(!pct || !pat || !*pat)
653     return 0;
654
655   //fprintf(stderr,"comparing against:\n");
656
657   while(i < max_tokens) {
658
659     if(*pat == 0){
660       //fprintf(stderr,"matched\n");
661       return (i+1);
662     }
663
664     //dump1Token(*pat); fprintf(stderr,"\n");
665
666     if(pct->tt != *pat) 
667       return 0;
668
669
670     pct++;
671     pat++;
672   }
673
674   return 0;
675
676 }
677
678 /*-----------------------------------------------------------------*/
679 /*-----------------------------------------------------------------*/
680
681 int altComparePattern( char *pct, parsedPattern *pat, int max_tokens)
682 {
683   int i=0;
684   
685   if(!pct || !pat || !*pct)
686     return 0;
687
688
689   while(i < max_tokens) {
690
691     if(*pct == 0) {
692       //fprintf(stderr,"matched\n");
693       return i;
694     }
695
696     //dump1Token(*pat); fprintf(stderr,"\n");
697
698     if( !pat || !pat->pcp )
699       return 0;
700
701     if (pat->pcp->pt != *pct)  
702       return 0;
703
704     //fprintf(stderr," pct=%d\n",*pct);
705     pct++;
706     pat++;
707     i++;
708   }
709
710   return 0;
711
712 }
713 /*-----------------------------------------------------------------*/
714 /*-----------------------------------------------------------------*/
715
716 int advTokIdx(int *v, int amt)
717 {
718
719   if(*v + amt > tokIdx)
720     return 1;
721
722   *v += amt;
723   return 0;
724
725 }
726
727 /*-----------------------------------------------------------------*/
728 /*-----------------------------------------------------------------*/
729
730 void dumpTokens(void)
731 {
732   int i;
733   pCode *pc;
734
735   if(!tokIdx)
736     return;
737
738   for(i=0; i<=tokIdx; i++)
739     dump1Token(tokArr[i].tt);
740
741
742   fputc('\n',stderr);
743
744   {
745     int lparsedPatIdx=0;
746     int lpcpIdx;
747     int ltokIdx =0;
748     int matching = 0;
749     int j=0;
750     int k=0;
751
752     char * cPmnem  = NULL;     // Pointer to non-wild mnemonic (if any)
753     char * cP1stop = NULL;
754     char * cP2ndop = NULL;
755
756     //pCodeOp *pcl   = NULL;       // Storage for a label
757     //pCodeOp *pco1  = NULL;       // 1st operand
758     //pCodeOp *pco2  = NULL;       // 2nd operand
759     //pCode   *pc    = NULL;       // Mnemonic
760
761     typedef enum {
762       PS_START,
763       PS_HAVE_LABEL,
764       PS_HAVE_MNEM,
765       PS_HAVE_1OPERAND,
766       PS_HAVE_COMMA,
767       PS_HAVE_2OPERANDS
768     } ParseStates;
769
770     ParseStates state = PS_START;
771
772     do {
773
774       lpcpIdx=0;
775       matching = 0;
776       //fprintf(stderr,"ltokIdx = %d\n",ltokIdx);
777
778       if(  ((tokArr[ltokIdx].tt == PCT_SPACE) )
779            && (advTokIdx(&ltokIdx, 1)) ) // eat space
780         break;
781
782       do {
783         j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
784         if( j ) {
785           //fprintf(stderr,"found token pattern match\n");
786           switch(pcpArr[lpcpIdx].pt) {
787           case  PCP_LABEL:
788             if(state == PS_START){
789               fprintf(stderr,"  label\n");
790               state = PS_HAVE_LABEL;
791             } else 
792               fprintf(stderr,"  bad state (%d) for label\n",state);
793             break;
794
795           case  PCP_STR:
796             fprintf(stderr,"  %s is",tokArr[ltokIdx].tok.s);
797             switch(state) {
798             case PS_START:
799             case PS_HAVE_LABEL:
800               fprintf(stderr,"  mnem\n");
801               cPmnem = tokArr[ltokIdx].tok.s;
802               state = PS_HAVE_MNEM;
803               break;
804             case PS_HAVE_MNEM:
805               fprintf(stderr,"  1st operand\n");
806               cP1stop = tokArr[ltokIdx].tok.s;
807               //pco1 = newpCodeOp(NULL,PO_GPR_REGISTER);
808               state = PS_HAVE_1OPERAND;
809               break;
810             case PS_HAVE_1OPERAND:
811               fprintf(stderr,"  error expecting comma\n");
812               break;
813             case PS_HAVE_COMMA:
814               fprintf(stderr,"  2 operands\n");
815               cP2ndop = tokArr[ltokIdx].tok.s;
816               break;
817             case PS_HAVE_2OPERANDS:
818               break;
819             }
820             break;
821
822           case  PCP_WILDVAR:
823             switch(state) {
824             case PS_START:
825             case PS_HAVE_LABEL:
826               fprintf(stderr,"  wild mnem\n");
827               state = PS_HAVE_MNEM;
828               break;
829             case PS_HAVE_MNEM:
830               fprintf(stderr,"  1st operand is wild\n");
831               state = PS_HAVE_1OPERAND;
832               break;
833             case PS_HAVE_1OPERAND:
834               fprintf(stderr,"  error expecting comma\n");
835               break;
836             case PS_HAVE_COMMA:
837               fprintf(stderr,"  2nd operand is wild\n");
838               break;
839             case PS_HAVE_2OPERANDS:
840               break;
841             }
842             break;
843
844           case  PCP_NUMBER:
845             switch(state) {
846             case PS_START:
847             case PS_HAVE_LABEL:
848               fprintf(stderr,"  ERROR number\n");
849               break;
850             case PS_HAVE_MNEM:
851               fprintf(stderr,"  1st operand is a number\n");
852               state = PS_HAVE_1OPERAND;
853               break;
854             case PS_HAVE_1OPERAND:
855               fprintf(stderr,"  error expecting comma\n");
856               break;
857             case PS_HAVE_COMMA:
858               fprintf(stderr,"  2nd operand is a number\n");
859               break;
860             case PS_HAVE_2OPERANDS:
861               break;
862             }
863             break;
864
865           case  PCP_WILDSTR:
866             break;
867           case  PCP_COMMA:
868             if(state == PS_HAVE_1OPERAND){
869               fprintf(stderr,"  got a comma\n");
870               state = PS_HAVE_COMMA;
871             } else
872               fprintf(stderr,"  unexpected comma\n");
873           }
874
875           matching = 1;
876           parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
877           parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
878           lparsedPatIdx++;
879
880           //dump1Token(tokArr[ltokIdx].tt);
881
882           if(advTokIdx(&ltokIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
883             fprintf(stderr," reached end \n");
884             matching = 0;
885             //return;
886           }
887         }
888
889
890       } while ((++lpcpIdx < PCPATTERNS) && !matching);
891
892     } while (matching);
893
894     parsedPatArr[lparsedPatIdx].pcp = NULL;
895     parsedPatArr[lparsedPatIdx].pct = NULL;
896
897     j=k=0;
898     do {
899       int c;
900
901       if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
902
903         if( altArr[k].f) {
904           pc = altArr[k].f(&parsedPatArr[j]);
905           if(pc && pc->print)
906             pc->print(stderr,pc);
907           //if(pc && pc->destruct) pc->destruct(pc); dumps core?
908         }
909         j += c;
910       }
911       k++;
912     }
913     while(j<=lparsedPatIdx && k<ALTPATTERNS);
914
915 /*
916     fprintf(stderr,"\nConverting parsed line to pCode:\n\n");
917
918     j = 0;
919     do {
920       if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
921         parsedPatArr[j].pcp->f(&parsedPatArr[j]);
922       fprintf(stderr,"  %d",parsedPatArr[j].pcp->pt);
923       j++;
924     }
925     while(j<lparsedPatIdx);
926 */
927     fprintf(stderr,"\n");
928
929   }
930
931
932 }
933
934 /*-----------------------------------------------------------------*/
935 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
936 /*                   pCode.                                        */
937 /*                                                                 */
938 /* SDCCpeeph parses the peep rules file and extracts variables,    */
939 /* removes white space, and checks the syntax. This function       */
940 /* extends that processing to produce pCode objects. You can kind  */
941 /* think of this function as an "assembler", though instead of     */
942 /* taking raw text to produce machine code, it produces pCode.     */
943 /*                                                                 */
944 /*-----------------------------------------------------------------*/
945
946 void  peepRules2pCode(peepRule *rules)
947 {
948   peepRule *pr;
949   lineNode *ln;
950
951   pCodePeepSnippets *pcps;
952
953   for (pr = rules; pr; pr = pr->next) {
954     fprintf(stderr,"\nRule:\n\n");
955
956     pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
957     curPeep = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
958     //curPeep->target = curPeep->replace = NULL;
959     curPeep->vars = NULL; curPeep->wildpCodes = NULL;
960     peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
961
962     curPeep->target = curBlock = newpCodeChain(NULL, 'W', NULL);
963
964     for(ln = pr->match; ln; ln = ln->next) {
965
966       fprintf(stderr,"%s\n",ln->line);
967
968       parseLineNode(ln->line);
969       dumpTokens();
970
971     }
972
973     fprintf(stderr,"\nReplaced by:\n");
974
975     curPeep->replace = curBlock = newpCodeChain(NULL, 'W', NULL);
976
977     for(ln = pr->replace; ln; ln = ln->next)
978       fprintf(stderr,"%s\n",ln->line);
979
980     if(pr->cond)
981       fprintf(stderr,"\nCondition:  %s\n",pr->cond);
982
983     return;
984   }
985
986 }
987
988 void printpCodeString(FILE *of, pCode *pc, int max)
989 {
990   int i=0;
991
992   while(pc && (i++<max)) {
993     pc->print(of,pc);
994     pc = pc->next;
995   }
996 }
997
998 /*-----------------------------------------------------------------*/
999 /* _DLL * DLL_append                                               */
1000 /*                                                                 */ 
1001 /*  Append a _DLL object to the end of a _DLL (doubly linked list) */ 
1002 /* If The list to which we want to append is non-existant then one */ 
1003 /* is created. Other wise, the end of the list is sought out and   */ 
1004 /* a new DLL object is appended to it. In either case, the void    */
1005 /* *data is added to the newly created DLL object.                 */
1006 /*-----------------------------------------------------------------*/
1007
1008 static void * DLL_append(_DLL *list, _DLL *next)
1009 {
1010   _DLL *b;
1011
1012
1013   /* If there's no list, then create one: */
1014   if(!list) {
1015     next->next = next->prev = NULL;
1016     return next;
1017   }
1018
1019
1020   /* Search for the end of the list. */
1021   b = list;
1022   while(b->next)
1023     b = b->next;
1024
1025   /* Now append the new DLL object */
1026   b->next = next;
1027   b->next->prev = b;
1028   b = b->next; 
1029   b->next = NULL;
1030
1031   return list;
1032   
1033 }  
1034
1035
1036 /*-----------------------------------------------------------------
1037
1038   pCode peephole optimization
1039
1040
1041   The pCode "peep hole" optimization is not too unlike the peep hole
1042   optimization in SDCCpeeph.c. The major difference is that here we
1043   use pCode's whereas there we use ASCII strings. The advantage with
1044   pCode's is that we can ascertain flow information in the instructions
1045   being optimized.
1046
1047
1048 <FIX ME> - elaborate...
1049
1050   -----------------------------------------------------------------*/
1051
1052 #if 0
1053 /*-----------------------------------------------------------------*/
1054 /* pCodePeep */
1055 /*-----------------------------------------------------------------*/
1056 int pCodePeepCompare(pCode *pc, pCodePeep *pcp)
1057 {
1058   pCode *pcfrom,*pcto;
1059
1060   pcfrom = pc;
1061   for( pcto=pcp->target; pcto; pcto=pcto->next) {
1062
1063     pcfrom = findNextInstruction(pcfrom);
1064
1065     if( pcfrom &&  
1066         (PCI(pcfrom)->op == PCI(pcto)->op || 
1067          PCI(pcto)->op == POC_WILD))
1068       continue;
1069     return 0;
1070   }
1071   return 0;
1072 }
1073
1074 /*-----------------------------------------------------------------*/
1075 /* pCodePeep */
1076 /*-----------------------------------------------------------------*/
1077 void pCodePeepSearch(pCodePeep *snippet)
1078 {
1079   pBlock *pb;
1080   pCode *pc;
1081
1082   if(!the_pFile)
1083     return;
1084
1085   /* compare the chain to the pCode that we've 
1086      got so far. If a match is found, then replace
1087      the pCode chain.
1088   */
1089   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1090     for(pc = pb->pcHead; pc; pc = pc->next) {
1091       pCodePeepCompare(pc,snippet);
1092     }
1093   }
1094
1095 }
1096 #endif
1097
1098 #if 0
1099 pBlock *pBlockAppend(pBlock *pb1, pBlock *pb2)
1100 {
1101   pBlock *pb;
1102
1103   if(!pb1->tail)
1104     return pb2;
1105
1106   pb = pb1->tail;
1107
1108   pb2->head = pb1;
1109   pb2->tail = NULL;
1110   pb1->tail = pb2;
1111
1112 }
1113
1114 #endif
1115
1116 void pCodePeepInit(void)
1117 {
1118 #if 0
1119   pBlock *pb;
1120   //  pCode *pc;
1121   pCodePeep *pcp;
1122   pCodePeepSnippets *pcps;
1123
1124   /* Declare a peep code snippet */
1125   /* <FIXME> do I really need a separate struct just to DLL the snippets? */
1126   /* e.g. I could put the DLL into the pCodePeep structure */
1127   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1128   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
1129   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1130
1131
1132   pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1133   addpCode2pBlock( pb,     newpCode(POC_MOVFW, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1134
1135   pcp->target = pb;
1136
1137   pcp->replace = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1138
1139   /* Allocate space to store pointers to the wildcard variables */
1140   pcp->nvars = 1;
1141   pcp->vars  = Safe_calloc(pcp->nvars, sizeof(char *));
1142   pcp->nwildpCodes = 0;
1143   pcp->wildpCodes  = NULL;
1144
1145   pcp->postFalseCond = PCC_Z;
1146   pcp->postTrueCond  = PCC_NONE;
1147
1148   fprintf(stderr,"Peep rule\nTarget:\n");
1149   printpCodeString(stderr,pcp->target->pcHead, 10);
1150   fprintf(stderr,"Replaced with:\n");
1151   printpCodeString(stderr,pcp->replace->pcHead, 10);
1152
1153   /* Now for another peep example */
1154   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1155   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
1156   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1157
1158   {
1159     /*
1160       target:
1161
1162           btfsc  %0
1163            goto  %1
1164           %3
1165       %1: %4
1166
1167       replace:
1168           btfss  %0
1169       %1:  %4
1170           %3
1171
1172           The %3 and %4 are wild opcodes. Since the opcodes
1173           are stored in a different array than the wild operands,
1174           they can have the same indices and not conflict. So
1175           below, the %3 is really a %0, %4 is a %1.
1176
1177      */
1178     pCodeOp *pcl;
1179     pCodeOp *pcw;
1180     pCodeOp *pcwb;
1181
1182     // Create a new wild operand subtyped as a bit
1183     pcwb =  newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1));
1184
1185     // Create a 
1186     pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSC,pcwb));
1187
1188     pcl = newpCodeOpLabel(-1);
1189     pcw = newpCodeOpWild(1, pcp, pcl);
1190     addpCode2pBlock( pb,     newpCode(POC_GOTO,  pcw));
1191     addpCode2pBlock( pb,     newpCodeWild(0,NULL,NULL));
1192     addpCode2pBlock( pb,     newpCodeWild(1,NULL,pcw));
1193
1194
1195     pcp->target = pb;
1196
1197     pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSS, pcwb));
1198     addpCode2pBlock( pb,     newpCodeWild(0,NULL,NULL));
1199     addpCode2pBlock( pb,     newpCodeWild(1,NULL,pcw));
1200
1201     pcp->replace = pb;
1202
1203     /* Allocate space to store pointers to the wildcard variables */
1204     pcp->nvars = 2;
1205     pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1206     pcp->nwildpCodes = 2;
1207     pcp->wildpCodes = Safe_calloc(pcp->nwildpCodes, sizeof(pCode *));
1208
1209     pcp->postFalseCond = PCC_NONE;
1210     pcp->postTrueCond  = PCC_NONE;
1211   }
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222   //-------------
1223
1224   /* Now for another peep example */
1225   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1226   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
1227   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1228
1229   {
1230     pCodeOp *pcw;
1231
1232     pcw = newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER));
1233
1234     pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, pcw));
1235     addpCode2pBlock( pb,     newpCode(POC_MOVWF, pcw));
1236
1237     pcp->target = pb;
1238
1239     pb = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, pcw));
1240
1241     pcp->replace = pb;
1242
1243     /* Allocate space to store pointers to the wildcard variables */
1244     pcp->nvars = 1;
1245     pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1246     pcp->nwildpCodes = 0;
1247     pcp->wildpCodes = NULL;
1248
1249     pcp->postFalseCond = PCC_NONE;
1250     pcp->postTrueCond  = PCC_NONE;
1251   }
1252
1253
1254
1255 #endif
1256 }
1257
1258 /*-----------------------------------------------------------------*/
1259 /* pCodeSearchCondition - Search a pCode chain for a 'condition'   */
1260 /*                                                                 */
1261 /* return conditions                                               */
1262 /*  1 - The Condition was found for a pCode's input                */
1263 /*  0 - No matching condition was found for the whole chain        */
1264 /* -1 - The Condition was found for a pCode's output               */
1265 /*                                                                 */
1266 /*-----------------------------------------------------------------*/
1267 int pCodeSearchCondition(pCode *pc, unsigned int cond)
1268 {
1269
1270   while(pc) {
1271
1272     /* If we reach a function end (presumably an end since we most
1273        probably began the search in the middle of a function), then
1274        the condition was not found. */
1275     if(pc->type == PC_FUNCTION)
1276       return 0;
1277
1278     if(pc->type == PC_OPCODE) {
1279       if(PCI(pc)->inCond & cond)
1280         return 1;
1281       if(PCI(pc)->outCond & cond)
1282         return -1;
1283     }
1284
1285     pc = pc->next;
1286   }
1287
1288   return 0;
1289 }
1290 /*-----------------------------------------------------------------*/
1291 /* pCodePeepMatchLine - Compare source and destination pCodes to   */
1292 /*                      see they're the same.                      */
1293 /*-----------------------------------------------------------------*/
1294 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1295 {
1296   int index;   // index into wild card arrays
1297
1298   if(pcs->type == pcd->type) {
1299
1300     if(pcs->type == PC_OPCODE) {
1301
1302       /* If the opcodes don't match then the line doesn't match */
1303       if(PCI(pcs)->op != PCI(pcd)->op)
1304         return 0;
1305
1306       fprintf(stderr,"%s comparing\n",__FUNCTION__);
1307       pcs->print(stderr,pcs);
1308       pcd->print(stderr,pcd);
1309
1310       /* Compare the operands */
1311       if(PCI(pcd)->pcop) {
1312         if (PCI(pcd)->pcop->type == PO_WILD) {
1313           index = PCOW(PCI(pcd)->pcop)->id;
1314
1315           fprintf(stderr,"destination is wild\n");
1316 #ifdef DEBUG_PCODEPEEP
1317           if (index > peepBlock->nvars) {
1318             fprintf(stderr,"%s - variables exceeded\n",__FUNCTION__);
1319             exit(1);
1320           }
1321 #endif
1322           PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1323           {
1324             char *n;
1325
1326             if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1327               n = PCOR(PCI(pcs)->pcop)->r->name;
1328             else
1329               n = PCI(pcs)->pcop->name;
1330
1331             if(peepBlock->vars[index])
1332               return  (strcmp(peepBlock->vars[index],n) == 0);
1333             else {
1334               peepBlock->vars[index] = n; //PCI(pcs)->pcop->name;
1335               return 1;
1336             }
1337           }
1338         }
1339       } else
1340         /* The pcd has no operand. Lines match if pcs has no operand either*/
1341         return (PCI(pcs)->pcop == NULL);
1342     }
1343   }
1344
1345
1346   if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1347
1348     int labindex;
1349
1350     index = PCW(pcd)->id;
1351
1352     fprintf(stderr,"%s comparing wild cards\n",__FUNCTION__);
1353     pcs->print(stderr,pcs);
1354     pcd->print(stderr,pcd);
1355
1356     peepBlock->wildpCodes[PCW(pcd)->id] = pcs;
1357
1358     /* Check for a label associated with this wild pCode */
1359     // If the wild card has a label, make sure the source code does too.
1360     if(PCW(pcd)->label) {
1361       if(!pcs->label)
1362         return 0;
1363
1364       labindex = PCOW(PCW(pcd)->label)->id;
1365       if(peepBlock->vars[labindex] == NULL) {
1366         // First time to encounter this label
1367         peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
1368         fprintf(stderr,"first time for a label\n");
1369       } else {
1370         if(strcmp(peepBlock->vars[labindex],PCL(pcs->label->pc)->label) != 0) {
1371           fprintf(stderr,"labels don't match\n");
1372           return 0;
1373         }
1374         fprintf(stderr,"matched a label\n");
1375       }
1376
1377     }
1378
1379     if(PCW(pcd)->operand) {
1380       PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1381       if(peepBlock->vars[index]) {
1382         int i = (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
1383         if(i)
1384           fprintf(stderr," (matched)\n");
1385         else {
1386           fprintf(stderr," (no match: wild card operand mismatch\n");
1387           fprintf(stderr,"  peepblock= %s,  pcodeop= %s\n",
1388                   peepBlock->vars[index],
1389                   PCI(pcs)->pcop->name);
1390         }
1391         return i;
1392       } else {
1393         peepBlock->vars[index] = PCI(pcs)->pcop->name;
1394         return 1;
1395       }
1396     }
1397
1398     pcs = findNextInstruction(pcs->next); 
1399     if(pcs) {
1400       fprintf(stderr," (next to match)\n");
1401       pcs->print(stderr,pcs);
1402     }
1403
1404     return 1; /*  wild card matches */
1405   }
1406
1407   return 0;
1408 }
1409
1410 /*-----------------------------------------------------------------*/
1411 /*-----------------------------------------------------------------*/
1412 void pCodePeepClrVars(pCodePeep *pcp)
1413 {
1414
1415   int i;
1416   if(!pcp)
1417     return;
1418
1419   for(i=0;i<pcp->nvars; i++)
1420     pcp->vars[i] = NULL;
1421
1422 }
1423
1424 /*-----------------------------------------------------------------*/
1425 /*-----------------------------------------------------------------*/
1426 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
1427 {
1428
1429   if(!pc1 || !pc2)
1430     return;
1431
1432   pc2->next = pc1->next;
1433   if(pc1->next)
1434     pc1->next->prev = pc2;
1435
1436   pc2->prev = pc1;
1437   pc1->next = pc2;
1438
1439 }
1440
1441 /*-----------------------------------------------------------------*/
1442 /* pCodeOpCopy - copy a pcode operator                             */
1443 /*-----------------------------------------------------------------*/
1444 static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
1445 {
1446   pCodeOp *pcopnew=NULL;
1447
1448   if(!pcop)
1449     return NULL;
1450
1451   switch(pcop->type) { 
1452   case PO_CRY:
1453   case PO_BIT:
1454     pcopnew = Safe_calloc(1,sizeof(pCodeOpBit) );
1455     PCOB(pcopnew)->bit = PCOB(pcop)->bit;
1456     PCOB(pcopnew)->inBitSpace = PCOB(pcop)->inBitSpace;
1457
1458     break;
1459
1460   case PO_WILD:
1461     /* Here we expand the wild card into the appropriate type: */
1462     /* By recursively calling pCodeOpCopy */
1463     if(PCOW(pcop)->matched)
1464       pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
1465     else {
1466       // Probably a label
1467       pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
1468       pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
1469       fprintf(stderr,"copied a wild op named %s\n",pcopnew->name);
1470     }
1471
1472     return pcopnew;
1473     break;
1474
1475   case PO_LABEL:
1476     pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1477     PCOLAB(pcopnew)->key =  PCOLAB(pcop)->key;
1478     break;
1479
1480   case PO_LITERAL:
1481   case PO_IMMEDIATE:
1482     pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1483     PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1484     break;
1485
1486   case PO_GPR_REGISTER:
1487   case PO_GPR_TEMP:
1488   case PO_SFR_REGISTER:
1489   case PO_DIR:
1490   case PO_STR:
1491   case PO_NONE:
1492   case PO_W:
1493   case PO_STATUS:
1494   case PO_FSR:
1495   case PO_INDF:
1496
1497     pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1498
1499   }
1500
1501   pcopnew->type = pcop->type;
1502   pcopnew->name = Safe_strdup(pcop->name);
1503
1504   return pcopnew;
1505 }
1506
1507 #if 0
1508 /*-----------------------------------------------------------------*/
1509 /* pCodeCopy - copy a pcode                                        */
1510 /*-----------------------------------------------------------------*/
1511 static pCode *pCodeCopy(pCode *pc)
1512 {
1513
1514   pCode *pcnew;
1515
1516   pcnew = newpCode(pc->type,pc->pcop);
1517 }
1518 #endif
1519 /*-----------------------------------------------------------------*/
1520 /*-----------------------------------------------------------------*/
1521 void pCodeDeleteChain(pCode *f,pCode *t)
1522 {
1523   pCode *pc;
1524
1525   while(f && f!=t) {
1526     fprintf(stderr,"delete pCode:\n");
1527     pc = f->next;
1528     f->print(stderr,f);
1529     //f->delete(f);
1530     f = pc;
1531   }
1532
1533 }
1534 /*-----------------------------------------------------------------*/
1535 /*-----------------------------------------------------------------*/
1536 int pCodePeepMatchRule(pCode *pc)
1537 {
1538   pCodePeep *peepBlock;
1539   pCode *pct, *pcin;
1540   _DLL *peeprules;
1541   int matched;
1542
1543   peeprules = (_DLL *)peepSnippets;
1544
1545   while(peeprules) {
1546     peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1547     if(!peepBlock || !peepBlock->target || !peepBlock->target->pcHead)
1548       goto next_rule;
1549
1550     pCodePeepClrVars(peepBlock);
1551
1552     pcin = pc;
1553     pct = peepBlock->target->pcHead;
1554     matched = 0;
1555     while(pct && pcin) {
1556
1557       if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1558         break;
1559
1560       pcin = findNextInstruction(pcin->next);
1561       pct = pct->next;
1562       //debug:
1563       fprintf(stderr,"    matched\n");
1564       if(!pcin)
1565         fprintf(stderr," end of code\n");
1566       if(!pct)
1567         fprintf(stderr," end of rule\n");
1568     }
1569
1570     if(matched && pcin) {
1571
1572       /* So far we matched the rule up to the point of the conditions .
1573        * In other words, all of the opcodes match. Now we need to see
1574        * if the post conditions are satisfied.
1575        * First we check the 'postFalseCond'. This means that we check
1576        * to see if any of the subsequent pCode's in the pCode chain 
1577        * following the point just past where we have matched depend on
1578        * the `postFalseCond' as input then we abort the match
1579        */
1580       fprintf(stderr,"    matched rule so far, now checking conditions\n");
1581       if (peepBlock->postFalseCond && 
1582           (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
1583         matched = 0;
1584     }
1585
1586     if(matched && pcin) {
1587
1588       pCode *pcprev;
1589       pCode *pcr;
1590
1591
1592       /* We matched a rule! Now we have to go through and remove the
1593          inefficient code with the optimized version */
1594
1595       fprintf(stderr, "Found a pcode peep match:\nRule:\n");
1596       printpCodeString(stderr,peepBlock->target->pcHead,10);
1597       fprintf(stderr,"first thing matched\n");
1598       pc->print(stderr,pc);
1599       fprintf(stderr,"last thing matched\n");
1600       pcin->print(stderr,pcin);
1601
1602       /* Unlink the original code */
1603       pcprev = pc->prev;
1604       pcprev->next = pcin;
1605       pcin->prev = pc->prev;
1606       pCodeDeleteChain(pc,pcin);
1607
1608       /* Generate the replacement code */
1609       pc = pcprev;
1610       pcr = peepBlock->replace->pcHead;  // This is the replacement code
1611       while (pcr) {
1612         pCodeOp *pcop=NULL;
1613         /* If the replace pcode is an instruction with an operand, */
1614         /* then duplicate the operand (and expand wild cards in the process). */
1615         if(pcr->type == PC_OPCODE) {
1616           if(PCI(pcr)->pcop)
1617             pcop = pCodeOpCopy(PCI(pcr)->pcop);
1618           fprintf(stderr,"inserting pCode\n");
1619           pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
1620         } else if (pcr->type == PC_WILD) {
1621           pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
1622         }
1623
1624
1625         pc = pc->next;
1626         pc->print(stderr,pc);
1627         pcr = pcr->next;
1628       }
1629
1630       return 1;
1631     }
1632   next_rule:
1633     peeprules = peeprules->next;
1634   }
1635
1636   return 0;
1637 }
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648 #if 0
1649 /*******************/
1650 pCode *parseLineNode(char *ln)
1651 {
1652   char buffer[50], *s;
1653   int state=0;          //0 label, 1 mnemonic, 2 operand, 3 operand, 4 comment
1654   int var;
1655   pCode *pc = NULL;
1656   //  pCodeLabel *pcl = NULL;
1657
1658   if(!ln || !*ln)
1659     return pc;
1660
1661   s = buffer;
1662   *s = 0;
1663
1664   while(*ln) {
1665
1666     /* skip white space */
1667     while (isspace (*ln))
1668       ln++;
1669
1670     switch(state) {
1671
1672     case 0:   // look for a label
1673     case 1:   // look for mnemonic
1674
1675       if(*ln == '%') {
1676
1677         // Wild
1678
1679         ln++;
1680         if(!isdigit(*ln) )
1681           break;
1682           //goto next_state;
1683
1684         var = strtol(ln, &ln, 10);
1685         if(*ln  == ':') {
1686           // valid wild card label
1687           fprintf(stderr, " wildcard label: %d\n",var);
1688           ln++;
1689         } else
1690           fprintf(stderr, " wild opcode: %d\n",var), state++;
1691
1692       } else {
1693         // not wild
1694         // Extract the label/mnemonic from the line
1695
1696         s = buffer;
1697         while(*ln && !(isspace(*ln) || *ln == ':'))
1698           *s++ = *ln++;
1699
1700         *s = 0;
1701         if(*ln == ':')
1702           fprintf(stderr," regular label: %s\n",buffer), ln++;
1703         else
1704           fprintf(stderr," regular mnem: %s\n",buffer), state++;
1705       }
1706       state++;
1707       break;
1708
1709     default:
1710       ln++;
1711
1712     }
1713   }
1714
1715   return pc;
1716   
1717 }
1718 #endif