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