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