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