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