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