pCode peep is fully working for the PIC port.
[fw/sdcc] / src / pic / pcodepeep.c
1 /*-------------------------------------------------------------------------
2
3    pcodepeep.c - post code generation
4    Written By -  Scott Dattalo scott@dattalo.com
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include "common.h"   // Include everything in the SDCC src directory
25 #include "newalloc.h"
26
27
28 #include "pcode.h"
29 #include "ralloc.h"
30
31 #if defined(__BORLANDC__) || defined(_MSC_VER)
32 #define STRCASECMP stricmp
33 #else
34 #define STRCASECMP strcasecmp
35 #endif
36
37 pCodeOp *popCopyGPR2Bit(pCodeOpReg *pc, int bitval);
38
39
40 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype);
41 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label);
42 pCode * findNextInstruction(pCode *pc);
43 char *Safe_strdup(char *str);
44 int getpCode(char *mnem,int dest);
45 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   fprintf(stderr,"altpat_label with ID = %d\n",p->pct[1].tok.n);
312   return newpCodeLabel(-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   fprintf(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   fprintf(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   fprintf(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   fprintf(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]->bit_inst)
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   fprintf(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]->bit_inst)
446     pcosubtype = newpCodeOpBit(NULL,-1);
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   fprintf(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   fprintf(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]->bit_inst) {
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   fprintf(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]->bit_inst)
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
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 }
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   //fprintf(stderr,"comparing against:\n");
738
739   while(i < max_tokens) {
740
741     if(*pat == 0){
742       //fprintf(stderr,"matched\n");
743       return (i+1);
744     }
745
746     //dump1Token(*pat); fprintf(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       //fprintf(stderr,"matched\n");
775       return i;
776     }
777
778     //dump1Token(*pat); fprintf(stderr,"\n");
779
780     if( !pat || !pat->pcp )
781       return 0;
782
783     if (pat->pcp->pt != *pct)  
784       return 0;
785
786     //fprintf(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
838   fputc('\n',stderr);
839
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               fprintf(stderr,"  label\n");
885               state = PS_HAVE_LABEL;
886             } else 
887               fprintf(stderr,"  bad state (%d) for label\n",state);
888             break;
889
890           case  PCP_STR:
891             fprintf(stderr,"  %s is",tokArr[ltokIdx].tok.s);
892             switch(state) {
893             case PS_START:
894             case PS_HAVE_LABEL:
895               fprintf(stderr,"  mnem\n");
896               cPmnem = tokArr[ltokIdx].tok.s;
897               state = PS_HAVE_MNEM;
898               break;
899             case PS_HAVE_MNEM:
900               fprintf(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               fprintf(stderr,"  error expecting comma\n");
907               break;
908             case PS_HAVE_COMMA:
909               fprintf(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               fprintf(stderr,"  wild mnem\n");
922               state = PS_HAVE_MNEM;
923               break;
924             case PS_HAVE_MNEM:
925               fprintf(stderr,"  1st operand is wild\n");
926               state = PS_HAVE_1OPERAND;
927               break;
928             case PS_HAVE_1OPERAND:
929               fprintf(stderr,"  error expecting comma\n");
930               break;
931             case PS_HAVE_COMMA:
932               fprintf(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               fprintf(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               fprintf(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               fprintf(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             fprintf(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     fprintf(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       fprintf(stderr,"  %d",parsedPatArr[j].pcp->pt);
1020       j++;
1021     }
1022     while(j<lparsedPatIdx);
1023 */
1024     fprintf(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     fprintf(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   fprintf(stderr,"\nCondition:  %s\n",cond);
1059
1060   /* brute force compares for now */
1061
1062   if(STRCASECMP(cond, "NZ") == 0) {
1063     fprintf(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     fprintf(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     fprintf(stderr,"finished target, here it is in pcode form:\n");
1117     printpBlock(stderr, curBlock);
1118
1119     fprintf(stderr,"target with labels merged:\n");
1120     pBlockMergeLabels(curBlock);
1121     printpBlock(stderr, curBlock);
1122
1123     fprintf(stderr,"\nReplaced by:\n");
1124
1125
1126     curPeep->replace = curBlock = newpCodeChain(NULL, 'W', NULL);
1127
1128     /* Convert the replace block */
1129     peepRuleBlock2pCodeBlock(pr->replace);
1130
1131     fprintf(stderr,"finished replace block, here it is in pcode form:\n");
1132     printpBlock(stderr, curBlock);
1133
1134     fprintf(stderr,"replace with labels merged:\n");
1135     pBlockMergeLabels(curBlock);
1136     printpBlock(stderr, curBlock);
1137
1138     peepRuleCondition(pr->cond);
1139
1140     /* The rule has been converted to pCode. Now allocate
1141      * space for the wildcards */
1142
1143      ++sMaxWildVar;
1144     curPeep->nvars = sMaxWildVar;
1145     curPeep->vars = Safe_calloc(sMaxWildVar, sizeof(char *));
1146
1147     curPeep->nops = sMaxWildVar;
1148     curPeep->wildpCodeOps = Safe_calloc(sMaxWildVar, sizeof(pCodeOp *));
1149
1150     curPeep->nwildpCodes = ++sMaxWildMnem;
1151     curPeep->wildpCodes = Safe_calloc(sMaxWildMnem, sizeof(char *));
1152
1153
1154     //return; // debug ... don't want to go through all the rules yet
1155   }
1156
1157 }
1158
1159 void printpCodeString(FILE *of, pCode *pc, int max)
1160 {
1161   int i=0;
1162
1163   while(pc && (i++<max)) {
1164     pc->print(of,pc);
1165     pc = pc->next;
1166   }
1167 }
1168
1169 /*-----------------------------------------------------------------*/
1170 /* _DLL * DLL_append                                               */
1171 /*                                                                 */ 
1172 /*  Append a _DLL object to the end of a _DLL (doubly linked list) */ 
1173 /* If The list to which we want to append is non-existant then one */ 
1174 /* is created. Other wise, the end of the list is sought out and   */ 
1175 /* a new DLL object is appended to it. In either case, the void    */
1176 /* *data is added to the newly created DLL object.                 */
1177 /*-----------------------------------------------------------------*/
1178
1179 static void * DLL_append(_DLL *list, _DLL *next)
1180 {
1181   _DLL *b;
1182
1183
1184   /* If there's no list, then create one: */
1185   if(!list) {
1186     next->next = next->prev = NULL;
1187     return next;
1188   }
1189
1190
1191   /* Search for the end of the list. */
1192   b = list;
1193   while(b->next)
1194     b = b->next;
1195
1196   /* Now append the new DLL object */
1197   b->next = next;
1198   b->next->prev = b;
1199   b = b->next; 
1200   b->next = NULL;
1201
1202   return list;
1203   
1204 }  
1205
1206
1207 /*-----------------------------------------------------------------
1208
1209   pCode peephole optimization
1210
1211
1212   The pCode "peep hole" optimization is not too unlike the peep hole
1213   optimization in SDCCpeeph.c. The major difference is that here we
1214   use pCode's whereas there we use ASCII strings. The advantage with
1215   pCode's is that we can ascertain flow information in the instructions
1216   being optimized.
1217
1218
1219 <FIX ME> - elaborate...
1220
1221   -----------------------------------------------------------------*/
1222
1223 #if 0
1224 /*-----------------------------------------------------------------*/
1225 /* pCodePeep */
1226 /*-----------------------------------------------------------------*/
1227 int pCodePeepCompare(pCode *pc, pCodePeep *pcp)
1228 {
1229   pCode *pcfrom,*pcto;
1230
1231   pcfrom = pc;
1232   for( pcto=pcp->target; pcto; pcto=pcto->next) {
1233
1234     pcfrom = findNextInstruction(pcfrom);
1235
1236     if( pcfrom &&  
1237         (PCI(pcfrom)->op == PCI(pcto)->op || 
1238          PCI(pcto)->op == POC_WILD))
1239       continue;
1240     return 0;
1241   }
1242   return 0;
1243 }
1244
1245 /*-----------------------------------------------------------------*/
1246 /* pCodePeep */
1247 /*-----------------------------------------------------------------*/
1248 void pCodePeepSearch(pCodePeep *snippet)
1249 {
1250   pBlock *pb;
1251   pCode *pc;
1252
1253   if(!the_pFile)
1254     return;
1255
1256   /* compare the chain to the pCode that we've 
1257      got so far. If a match is found, then replace
1258      the pCode chain.
1259   */
1260   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1261     for(pc = pb->pcHead; pc; pc = pc->next) {
1262       pCodePeepCompare(pc,snippet);
1263     }
1264   }
1265
1266 }
1267 #endif
1268
1269 #if 0
1270 pBlock *pBlockAppend(pBlock *pb1, pBlock *pb2)
1271 {
1272   pBlock *pb;
1273
1274   if(!pb1->tail)
1275     return pb2;
1276
1277   pb = pb1->tail;
1278
1279   pb2->head = pb1;
1280   pb2->tail = NULL;
1281   pb1->tail = pb2;
1282
1283 }
1284
1285 #endif
1286
1287 void pCodePeepInit(void)
1288 {
1289 #if 0
1290   pBlock *pb;
1291   //  pCode *pc;
1292   pCodePeep *pcp;
1293   pCodePeepSnippets *pcps;
1294
1295   /* Declare a peep code snippet */
1296   /* <FIXME> do I really need a separate struct just to DLL the snippets? */
1297   /* e.g. I could put the DLL into the pCodePeep structure */
1298
1299   /* 
1300
1301      target:
1302   
1303      movwf %1
1304      movf  %1,w
1305   
1306      replace:
1307
1308      movwf %1
1309
1310      Condition:
1311      false condition - PCC_Z (Z bit is not used as input to subsequent code)
1312      true condition - none
1313   */
1314   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1315   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
1316   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1317
1318
1319   pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1320   addpCode2pBlock( pb,     newpCode(POC_MOVFW, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1321
1322   pcp->target = pb;
1323
1324   pcp->replace = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1325
1326   /* Allocate space to store pointers to the wildcard variables */
1327   pcp->nvars = 1;
1328   pcp->vars  = Safe_calloc(pcp->nvars, sizeof(char *));
1329   pcp->nwildpCodes = 0;
1330   pcp->wildpCodes  = NULL;
1331
1332   pcp->postFalseCond = PCC_Z;
1333   pcp->postTrueCond  = PCC_NONE;
1334
1335   fprintf(stderr,"Peep rule\nTarget:\n");
1336   printpCodeString(stderr,pcp->target->pcHead, 10);
1337   fprintf(stderr,"Replaced with:\n");
1338   printpCodeString(stderr,pcp->replace->pcHead, 10);
1339
1340   /* Now for another peep example */
1341   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1342   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
1343   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1344
1345   {
1346     /*
1347       target:
1348
1349           btfsc  %0
1350            goto  %1
1351           %3
1352       %1: %4
1353
1354       replace:
1355           btfss  %0
1356           %3
1357       %1:  %4
1358
1359           The %3 and %4 are wild opcodes. Since the opcodes
1360           are stored in a different array than the wild operands,
1361           they can have the same indices and not conflict. So
1362           below, the %3 is really a %0, %4 is a %1.
1363
1364      */
1365     pCodeOp *pcl;
1366     pCodeOp *pcw;
1367     pCodeOp *pcwb;
1368
1369     // Create a new wild operand subtyped as a bit
1370     pcwb =  newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1));
1371
1372     // Create a 
1373     pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSC,pcwb));
1374
1375     pcl = newpCodeOpLabel(-1);
1376     pcw = newpCodeOpWild(1, pcp, pcl);
1377     addpCode2pBlock( pb,     newpCode(POC_GOTO,  pcw));
1378     addpCode2pBlock( pb,     newpCodeWild(0,NULL,NULL));
1379     addpCode2pBlock( pb,     newpCodeWild(1,NULL,pcw));
1380
1381
1382     pcp->target = pb;
1383
1384     pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSS, pcwb));
1385     addpCode2pBlock( pb,     newpCodeWild(0,NULL,NULL));
1386     addpCode2pBlock( pb,     newpCodeWild(1,NULL,pcw));
1387
1388     pcp->replace = pb;
1389
1390     /* Allocate space to store pointers to the wildcard variables */
1391     pcp->nvars = 2;
1392     pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1393     pcp->nwildpCodes = 2;
1394     pcp->wildpCodes = Safe_calloc(pcp->nwildpCodes, sizeof(pCode *));
1395
1396     pcp->postFalseCond = PCC_NONE;
1397     pcp->postTrueCond  = PCC_NONE;
1398   }
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409   //-------------
1410
1411   /* Now for another peep example */
1412   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1413   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
1414   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1415
1416   {
1417     pCodeOp *pcw;
1418
1419     pcw = newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER));
1420
1421     pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, pcw));
1422     addpCode2pBlock( pb,     newpCode(POC_MOVWF, pcw));
1423
1424     pcp->target = pb;
1425
1426     pb = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, pcw));
1427
1428     pcp->replace = pb;
1429
1430     /* Allocate space to store pointers to the wildcard variables */
1431     pcp->nvars = 1;
1432     pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1433     pcp->nwildpCodes = 0;
1434     pcp->wildpCodes = NULL;
1435
1436     pcp->postFalseCond = PCC_NONE;
1437     pcp->postTrueCond  = PCC_NONE;
1438   }
1439
1440
1441
1442 #endif
1443 }
1444
1445 /*-----------------------------------------------------------------*/
1446 /* pCodeSearchCondition - Search a pCode chain for a 'condition'   */
1447 /*                                                                 */
1448 /* return conditions                                               */
1449 /*  1 - The Condition was found for a pCode's input                */
1450 /*  0 - No matching condition was found for the whole chain        */
1451 /* -1 - The Condition was found for a pCode's output               */
1452 /*                                                                 */
1453 /*-----------------------------------------------------------------*/
1454 int pCodeSearchCondition(pCode *pc, unsigned int cond)
1455 {
1456
1457   while(pc) {
1458
1459     /* If we reach a function end (presumably an end since we most
1460        probably began the search in the middle of a function), then
1461        the condition was not found. */
1462     if(pc->type == PC_FUNCTION)
1463       return 0;
1464
1465     if(pc->type == PC_OPCODE) {
1466       if(PCI(pc)->inCond & cond)
1467         return 1;
1468       if(PCI(pc)->outCond & cond)
1469         return -1;
1470     }
1471
1472     pc = pc->next;
1473   }
1474
1475   return 0;
1476 }
1477 /*-----------------------------------------------------------------*/
1478 /* pCodePeepMatchLine - Compare source and destination pCodes to   */
1479 /*                      see they're the same.                      */
1480 /*-----------------------------------------------------------------*/
1481 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1482 {
1483   int index;   // index into wild card arrays
1484
1485   if(pcs->type == pcd->type) {
1486
1487     if(pcs->type == PC_OPCODE) {
1488
1489       /* If the opcodes don't match then the line doesn't match */
1490       if(PCI(pcs)->op != PCI(pcd)->op)
1491         return 0;
1492
1493       fprintf(stderr,"%s comparing\n",__FUNCTION__);
1494       pcs->print(stderr,pcs);
1495       pcd->print(stderr,pcd);
1496
1497       /* Compare the operands */
1498       if(PCI(pcd)->pcop) {
1499         if (PCI(pcd)->pcop->type == PO_WILD) {
1500           index = PCOW(PCI(pcd)->pcop)->id;
1501
1502           fprintf(stderr,"destination is wild\n");
1503 #ifdef DEBUG_PCODEPEEP
1504           if (index > peepBlock->nops) {
1505             fprintf(stderr,"%s - variables exceeded\n",__FUNCTION__);
1506             exit(1);
1507           }
1508 #endif
1509           PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1510           if(!peepBlock->wildpCodeOps[index]) {
1511             peepBlock->wildpCodeOps[index] = PCI(pcs)->pcop;
1512
1513             //if(PCI(pcs)->pcop->type == PO_GPR_TEMP) 
1514
1515           }
1516           {
1517             char *n;
1518
1519             if(PCI(pcs)->pcop->type == PO_GPR_TEMP) 
1520               n = PCOR(PCI(pcs)->pcop)->r->name;
1521             else
1522               n = PCI(pcs)->pcop->name;
1523
1524             if(peepBlock->vars[index])
1525               return  (strcmp(peepBlock->vars[index],n) == 0);
1526             else {
1527               peepBlock->vars[index] = n; //PCI(pcs)->pcop->name;
1528               return 1;
1529             }
1530           }
1531         }
1532       } else
1533         /* The pcd has no operand. Lines match if pcs has no operand either*/
1534         return (PCI(pcs)->pcop == NULL);
1535     }
1536   }
1537
1538
1539   if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1540
1541     int labindex;
1542
1543     index = PCW(pcd)->id;
1544
1545     fprintf(stderr,"%s comparing wild cards\n",__FUNCTION__);
1546     pcs->print(stderr,pcs);
1547     pcd->print(stderr,pcd);
1548
1549     peepBlock->wildpCodes[PCW(pcd)->id] = pcs;
1550
1551     /* Check for a label associated with this wild pCode */
1552     // If the wild card has a label, make sure the source code does too.
1553     if(pcd->label) {
1554       pCode *pcl;
1555
1556       if(!pcs->label)
1557         return 0;
1558
1559       pcl = pcd->label->pc;
1560
1561       labindex = PCOW(pcl)->id;
1562       if(peepBlock->vars[labindex] == NULL) {
1563         // First time to encounter this label
1564         peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
1565         fprintf(stderr,"first time for a label\n");
1566       } else {
1567         if(strcmp(peepBlock->vars[labindex],PCL(pcs->label->pc)->label) != 0) {
1568           fprintf(stderr,"labels don't match\n");
1569           return 0;
1570         }
1571         fprintf(stderr,"matched a label\n");
1572       }
1573     } else 
1574       fprintf(stderr,"wild card doesn't have a label\n");
1575
1576     if(PCW(pcd)->operand) {
1577       PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1578       if(peepBlock->vars[index]) {
1579         int i = (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
1580         if(i)
1581           fprintf(stderr," (matched)\n");
1582         else {
1583           fprintf(stderr," (no match: wild card operand mismatch\n");
1584           fprintf(stderr,"  peepblock= %s,  pcodeop= %s\n",
1585                   peepBlock->vars[index],
1586                   PCI(pcs)->pcop->name);
1587         }
1588         return i;
1589       } else {
1590         peepBlock->vars[index] = PCI(pcs)->pcop->name;
1591         return 1;
1592       }
1593     }
1594
1595     pcs = findNextInstruction(pcs->next); 
1596     if(pcs) {
1597       fprintf(stderr," (next to match)\n");
1598       pcs->print(stderr,pcs);
1599     }
1600
1601     return 1; /*  wild card matches */
1602   }
1603
1604   return 0;
1605 }
1606
1607 /*-----------------------------------------------------------------*/
1608 /*-----------------------------------------------------------------*/
1609 void pCodePeepClrVars(pCodePeep *pcp)
1610 {
1611
1612   int i;
1613   if(!pcp)
1614     return;
1615
1616   for(i=0;i<pcp->nvars; i++) {
1617     pcp->vars[i] = NULL;
1618     pcp->wildpCodeOps[i] = NULL;
1619   }
1620 }
1621
1622 /*-----------------------------------------------------------------*/
1623 /*  pCodeInsertAfter - splice in the pCode chain starting with pc2 */
1624 /*                     into the pCode chain containing pc1         */
1625 /*-----------------------------------------------------------------*/
1626 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
1627 {
1628
1629   if(!pc1 || !pc2)
1630     return;
1631
1632   pc2->next = pc1->next;
1633   if(pc1->next)
1634     pc1->next->prev = pc2;
1635
1636   pc2->pb = pc1->pb;
1637   pc2->prev = pc1;
1638   pc1->next = pc2;
1639
1640 }
1641
1642 /*-----------------------------------------------------------------*/
1643 /* pCodeOpCopy - copy a pcode operator                             */
1644 /*-----------------------------------------------------------------*/
1645 static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
1646 {
1647   pCodeOp *pcopnew=NULL;
1648
1649   if(!pcop)
1650     return NULL;
1651
1652   switch(pcop->type) { 
1653   case PO_CRY:
1654   case PO_BIT:
1655     fprintf(stderr,"pCodeOpCopy bit\n");
1656     pcopnew = Safe_calloc(1,sizeof(pCodeOpBit) );
1657     PCOB(pcopnew)->bit = PCOB(pcop)->bit;
1658     PCOB(pcopnew)->inBitSpace = PCOB(pcop)->inBitSpace;
1659
1660     break;
1661
1662   case PO_WILD:
1663     /* Here we expand the wild card into the appropriate type: */
1664     /* By recursively calling pCodeOpCopy */
1665     fprintf(stderr,"pCodeOpCopy wild\n");
1666     if(PCOW(pcop)->matched)
1667       pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
1668     else {
1669       // Probably a label
1670       pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
1671       pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
1672       fprintf(stderr,"copied a wild op named %s\n",pcopnew->name);
1673     }
1674
1675     return pcopnew;
1676     break;
1677
1678   case PO_LABEL:
1679     fprintf(stderr,"pCodeOpCopy label\n");
1680     pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1681     PCOLAB(pcopnew)->key =  PCOLAB(pcop)->key;
1682     break;
1683
1684   case PO_LITERAL:
1685   case PO_IMMEDIATE:
1686     fprintf(stderr,"pCodeOpCopy lit\n");
1687     pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1688     PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1689     break;
1690
1691   case PO_GPR_REGISTER:
1692   case PO_GPR_TEMP:
1693     fprintf(stderr,"pCodeOpCopy GPR register\n");
1694     pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
1695     PCOR(pcopnew)->r = PCOR(pcop)->r;
1696     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
1697     fprintf(stderr," register index %d\n", PCOR(pcop)->r->rIdx);
1698     break;
1699
1700   case PO_DIR:
1701     fprintf(stderr,"pCodeOpCopy PO_DIR\n");
1702   case PO_SFR_REGISTER:
1703   case PO_STR:
1704   case PO_NONE:
1705   case PO_W:
1706   case PO_STATUS:
1707   case PO_FSR:
1708   case PO_INDF:
1709
1710     fprintf(stderr,"pCodeOpCopy register type %d\n", pcop->type);
1711     pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1712
1713   }
1714
1715   pcopnew->type = pcop->type;
1716   pcopnew->name = Safe_strdup(pcop->name);
1717
1718   return pcopnew;
1719 }
1720
1721 #if 0
1722 /*-----------------------------------------------------------------*/
1723 /* pCodeCopy - copy a pcode                                        */
1724 /*-----------------------------------------------------------------*/
1725 static pCode *pCodeCopy(pCode *pc)
1726 {
1727
1728   pCode *pcnew;
1729
1730   pcnew = newpCode(pc->type,pc->pcop);
1731 }
1732 #endif
1733 /*-----------------------------------------------------------------*/
1734 /*-----------------------------------------------------------------*/
1735 void pCodeDeleteChain(pCode *f,pCode *t)
1736 {
1737   pCode *pc;
1738
1739
1740   while(f && f!=t) {
1741     fprintf(stderr,"delete pCode:\n");
1742     pc = f->next;
1743     f->print(stderr,f);
1744     //f->delete(f);  this dumps core...
1745
1746     f = pc;
1747
1748   }
1749
1750 }
1751 /*-----------------------------------------------------------------*/
1752 /*-----------------------------------------------------------------*/
1753 int pCodePeepMatchRule(pCode *pc)
1754 {
1755   pCodePeep *peepBlock;
1756   pCode *pct, *pcin;
1757   _DLL *peeprules;
1758   int matched;
1759
1760   peeprules = (_DLL *)peepSnippets;
1761
1762   while(peeprules) {
1763     peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1764     if(!peepBlock || !peepBlock->target || !peepBlock->target->pcHead)
1765       goto next_rule;
1766
1767     pCodePeepClrVars(peepBlock);
1768
1769     pcin = pc;
1770     pct = peepBlock->target->pcHead;
1771     matched = 0;
1772     while(pct && pcin) {
1773
1774       if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1775         break;
1776
1777       pcin = findNextInstruction(pcin->next);
1778       pct = pct->next;
1779       //debug:
1780       fprintf(stderr,"    matched\n");
1781       if(!pcin)
1782         fprintf(stderr," end of code\n");
1783       if(!pct)
1784         fprintf(stderr," end of rule\n");
1785     }
1786
1787     if(matched && pcin) {
1788
1789       /* So far we matched the rule up to the point of the conditions .
1790        * In other words, all of the opcodes match. Now we need to see
1791        * if the post conditions are satisfied.
1792        * First we check the 'postFalseCond'. This means that we check
1793        * to see if any of the subsequent pCode's in the pCode chain 
1794        * following the point just past where we have matched depend on
1795        * the `postFalseCond' as input then we abort the match
1796        */
1797       fprintf(stderr,"    matched rule so far, now checking conditions\n");
1798       if (peepBlock->postFalseCond && 
1799           (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
1800         matched = 0;
1801     }
1802
1803     if(matched && pcin) {
1804
1805       pCode *pcprev;
1806       pCode *pcr;
1807
1808
1809       /* We matched a rule! Now we have to go through and remove the
1810          inefficient code with the optimized version */
1811
1812       fprintf(stderr, "Found a pcode peep match:\nRule:\n");
1813       printpCodeString(stderr,peepBlock->target->pcHead,10);
1814       fprintf(stderr,"first thing matched\n");
1815       pc->print(stderr,pc);
1816       fprintf(stderr,"last thing matched\n");
1817       pcin->print(stderr,pcin);
1818
1819       /* Unlink the original code */
1820       pcprev = pc->prev;
1821       pcprev->next = pcin;
1822       pcin->prev = pc->prev;
1823
1824       {
1825         /*     DEBUG    */
1826         /* Converted the deleted pCodes into comments */
1827
1828         char buf[256];
1829
1830         buf[0] = ';';
1831         buf[1] = '#';
1832
1833         while(pc &&  pc!=pcin) {
1834           pCode2str(&buf[2], 254, pc);
1835           pCodeInsertAfter(pcprev, newpCodeCharP(buf));
1836           pcprev = pcprev->next;
1837           pc = pc->next;
1838         }
1839       }
1840
1841       pCodeDeleteChain(pc,pcin);
1842
1843       /* Generate the replacement code */
1844       pc = pcprev;
1845       pcr = peepBlock->replace->pcHead;  // This is the replacement code
1846       while (pcr) {
1847         pCodeOp *pcop=NULL;
1848         /* If the replace pcode is an instruction with an operand, */
1849         /* then duplicate the operand (and expand wild cards in the process). */
1850         if(pcr->type == PC_OPCODE) {
1851           if(PCI(pcr)->pcop) {
1852             /* The replacing instruction has an operand.
1853              * Is it wild? */
1854             if(PCI(pcr)->pcop->type == PO_WILD) {
1855               int index = PCOW(PCI(pcr)->pcop)->id;
1856               fprintf(stderr,"copying wildopcode\n");
1857               if(peepBlock->wildpCodeOps[index])
1858                 pcop = pCodeOpCopy(peepBlock->wildpCodeOps[index]);
1859               else
1860                 fprintf(stderr,"error, wildopcode in replace but not source?\n");
1861             } else
1862               pcop = pCodeOpCopy(PCI(pcr)->pcop);
1863           }
1864           fprintf(stderr,"inserting pCode\n");
1865           pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
1866         } else if (pcr->type == PC_WILD) {
1867           pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
1868         } else if (pcr->type == PC_COMMENT) {
1869           pCodeInsertAfter(pc, newpCodeCharP( ((pCodeComment *)(pcr))->comment));
1870         }
1871
1872
1873         pc = pc->next;
1874         pc->print(stderr,pc);
1875         pcr = pcr->next;
1876       }
1877
1878       return 1;
1879     }
1880   next_rule:
1881     peeprules = peeprules->next;
1882   }
1883
1884   return 0;
1885 }
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896 #if 0
1897 /*******************/
1898 pCode *parseLineNode(char *ln)
1899 {
1900   char buffer[50], *s;
1901   int state=0;          //0 label, 1 mnemonic, 2 operand, 3 operand, 4 comment
1902   int var;
1903   pCode *pc = NULL;
1904   //  pCodeLabel *pcl = NULL;
1905
1906   if(!ln || !*ln)
1907     return pc;
1908
1909   s = buffer;
1910   *s = 0;
1911
1912   while(*ln) {
1913
1914     /* skip white space */
1915     while (isspace (*ln))
1916       ln++;
1917
1918     switch(state) {
1919
1920     case 0:   // look for a label
1921     case 1:   // look for mnemonic
1922
1923       if(*ln == '%') {
1924
1925         // Wild
1926
1927         ln++;
1928         if(!isdigit(*ln) )
1929           break;
1930           //goto next_state;
1931
1932         var = strtol(ln, &ln, 10);
1933         if(*ln  == ':') {
1934           // valid wild card label
1935           fprintf(stderr, " wildcard label: %d\n",var);
1936           ln++;
1937         } else
1938           fprintf(stderr, " wild opcode: %d\n",var), state++;
1939
1940       } else {
1941         // not wild
1942         // Extract the label/mnemonic from the line
1943
1944         s = buffer;
1945         while(*ln && !(isspace(*ln) || *ln == ':'))
1946           *s++ = *ln++;
1947
1948         *s = 0;
1949         if(*ln == ':')
1950           fprintf(stderr," regular label: %s\n",buffer), ln++;
1951         else
1952           fprintf(stderr," regular mnem: %s\n",buffer), state++;
1953       }
1954       state++;
1955       break;
1956
1957     default:
1958       ln++;
1959
1960     }
1961   }
1962
1963   return pc;
1964   
1965 }
1966 #endif