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