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