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