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