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