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