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