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