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 DLList {
68   struct DLList *prev;
69   struct DLList *next;
70   //  void *data;
71 } DLList;
72 
73 
74 typedef struct pCodePeepSnippets
75 {
76   DLList 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(DLList *list, DLList *next);
260 
261 /*-----------------------------------------------------------------*/
262 /* cvt_extract_destination - helper function extracts the register */
263 /*                           destination from a parsedPattern.     */
264 /*                                                                 */
265 /*-----------------------------------------------------------------*/
cvt_extract_destination(parsedPattern * pp)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 
cvt_extract_status(const char * reg,char * bit)293 static pCodeOp *cvt_extract_status(const 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 /*-----------------------------------------------------------------*/
cvt_altpat_label(void * pp,pCodeWildBlock * pcwb)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 /*-----------------------------------------------------------------*/
cvt_altpat_comment(void * pp,pCodeWildBlock * pcwb)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 /*-----------------------------------------------------------------*/
cvt_altpat_mnem0(void * pp,pCodeWildBlock * pcwb)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 /*-----------------------------------------------------------------*/
cvt_altpat_mnem0a(void * pp,pCodeWildBlock * pcwb)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 /*-----------------------------------------------------------------*/
cvt_altpat_mnem1(void * pp,pCodeWildBlock * pcwb)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 /*-----------------------------------------------------------------*/
cvt_altpat_mnem1a(void * pp,pCodeWildBlock * pcwb)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 = TRUE;
499       break;
500     case BITSKIP:
501       PCW(pc)->mustBeBitSkipInst = TRUE;
502       break;
503     case INVERTBITSKIP:
504       PCW(pc)->invertBitSkipInst = TRUE;
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 /*-----------------------------------------------------------------*/
cvt_altpat_mnem1b(void * pp,pCodeWildBlock * pcwb)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 /*-----------------------------------------------------------------*/
cvt_altpat_mnem2(void * pp,pCodeWildBlock * pcwb)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 /*-----------------------------------------------------------------*/
cvt_altpat_mnem2a(void * pp,pCodeWildBlock * pcwb)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 
784   pCodeInstruction *pci=NULL;
785   pCodeOp *pcosubtype=NULL;
786 
787   DFPRINTF((stderr,"altpat_mnem3 %s var %s bit (%d)\n",
788           p->pct[0].tok.s,
789           p[1].pct[0].tok.s,
790           p[3].pct[0].tok.n));
791 
792 
793   opcode = pic16_getpCode(p->pct[0].tok.s,0);
794   if(opcode < 0) {
795     fprintf(stderr, "Bad mnemonic\n");
796     return NULL;
797   }
798 
799 
800   if(pic16Mnemonics[opcode]->isBitInst) {
801     //pcosubtype = cvt_extract_status(p[1].pct[0].tok.s, p[3].pct[0].tok.s);
802 
803     //if(pcosubtype == NULL) {
804     pcosubtype = pic16_newpCodeOpBit(p[1].pct[0].tok.s,p[3].pct[0].tok.n,0, PO_GPR_REGISTER);
805     //}
806   } else
807     pcosubtype = pic16_newpCodeOp(p[1].pct[0].tok.s,PO_GPR_REGISTER);
808 
809   if(pcosubtype == NULL) {
810     fprintf(stderr, "Bad operand\n");
811     return NULL;
812   }
813 
814   pci = PCI(pic16_newpCode(opcode, pcosubtype));
815 
816   if(!pci)
817     fprintf(stderr,"couldn't find mnemonic\n");
818 
819   return pci;
820 
821 }
822 
823 /*-----------------------------------------------------------------*/
824 /* cvt_altpat_mem4 -  convert assembly line type to a pCode        */
825 /*                    This rule is for lfsr instruction            */
826 /*                                                                 */
827 /*                                                                 */
828 /*  pp[0] - mnem                                                   */
829 /*  pp[1] - number                                                 */
830 /*  pp[2] - comma                                                  */
831 /*  pp[3] - source                                                 */
832 /*                                                                 */
833 /*-----------------------------------------------------------------*/
834 static void * cvt_altpat_mnem4(void *pp, pCodeWildBlock *pcwb)
835 {
836   parsedPattern *p = pp;
837   int opcode;
838 
839   pCodeInstruction *pci=NULL;
840   pCodeOp *pcosubtype=NULL;
841 
842   DFPRINTF((stderr,"altpat_mnem4 %s fsr %d source %s\n",
843           p->pct[0].tok.s,
844           p[1].pct[0].tok.n,
845           p[3].pct[0].tok.s));
846 
847   opcode = pic16_getpCode(p->pct[0].tok.s,0);
848   if(opcode < 0) {
849     fprintf(stderr, "Bad mnemonic\n");
850     return NULL;
851   }
852   DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
853 
854   if(pic16Mnemonics[opcode]->is2LitOp) {
855     pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOp(p[3].pct[0].tok.s, PO_STR));
856   }
857 
858   if(pcosubtype == NULL) {
859     fprintf(stderr, "Bad operand\n");
860     return NULL;
861   }
862 
863   pci = PCI(pic16_newpCode(opcode, pcosubtype));
864 
865   if(!pci)
866     fprintf(stderr,"couldn't find mnemonic\n");
867 
868   return pci;
869 
870 }
871 
872 /*-----------------------------------------------------------------*/
873 /* cvt_altpat_mem4a -  convert assembly line type to a pCode       */
874 /*                    This rule is for lfsr instruction            */
875 /*                                                                 */
876 /*                                                                 */
877 /*  pp[0] - mnem                                                   */
878 /*  pp[1] - number                                                 */
879 /*  pp[2] - comma                                                  */
880 /*  pp[3] - value                                                  */
881 /*                                                                 */
882 /*-----------------------------------------------------------------*/
883 static void * cvt_altpat_mnem4a(void *pp, pCodeWildBlock *pcwb)
884 {
885   parsedPattern *p = pp;
886   int opcode;
887 
888   pCodeInstruction *pci=NULL;
889   pCodeOp *pcosubtype=NULL;
890 
891   DFPRINTF((stderr,"altpat_mnem4a %s fsr %d value 0x%02x\n",
892           p->pct[0].tok.s,
893           p[1].pct[0].tok.n,
894           p[3].pct[0].tok.n));
895 
896   opcode = pic16_getpCode(p->pct[0].tok.s,0);
897   if(opcode < 0) {
898     fprintf(stderr, "Bad mnemonic\n");
899     return NULL;
900   }
901   DFPRINTF((stderr, "Found mnemonic opcode= %d\n", opcode));
902 
903   if(pic16Mnemonics[opcode]->is2LitOp) {
904     pcosubtype = pic16_newpCodeOpLit2(p[1].pct[0].tok.n, pic16_newpCodeOpLit(p[3].pct[0].tok.n));
905   }
906 
907   if(pcosubtype == NULL) {
908     fprintf(stderr, "Bad operand\n");
909     return NULL;
910   }
911 
912   pci = PCI(pic16_newpCode(opcode, pcosubtype));
913 
914   if(!pci)
915     fprintf(stderr,"couldn't find mnemonic\n");
916 
917   return pci;
918 
919 }
920 
921 /*-----------------------------------------------------------------*/
922 /* tokenizeLineNode - Convert a string (of char's) that was parsed */
923 /*                    by SDCCpeeph.c into a string of tokens.      */
924 /*                                                                 */
925 /*                                                                 */
926 /* The tokenizer is of the classic type. When an item is encounterd*/
927 /* it is converted into a token. The token is a structure that     */
928 /* encodes the item's type and it's value (when appropriate).      */
929 /*                                                                 */
930 /* Accepted token types:                                           */
931 /*    SPACE  NUMBER STRING  %  : ,  ;                              */
932 /*                                                                 */
933 /*                                                                 */
934 /*                                                                 */
935 /*-----------------------------------------------------------------*/
936 
937 
938 static void tokenizeLineNode(char *ln)
939 {
940   char *lnstart=ln;
941   tokIdx = 0;               // Starting off at the beginning
942   tokArr[0].tt = PCT_NULL;  // and assume invalid character for first token.
943 
944   if(!ln || !*ln)
945     return;
946 
947 //      fprintf(stderr, "%s:%d: processing %s\n", __FILE__, __LINE__, ln);
948 
949   while(*ln) {
950     if(isspace((unsigned char)*ln)) {
951       // add a SPACE token and eat the extra spaces.
952       tokArr[tokIdx++].tt = PCT_SPACE;
953       while (isspace ((unsigned char)*ln))
954         ln++;
955       continue;
956     }
957 
958     if(isdigit((unsigned char)*ln)) {
959 
960       tokArr[tokIdx].tt = PCT_NUMBER;
961       tokArr[tokIdx++].tok.n = strtol(ln, &ln, 0);
962 
963       continue;
964 
965     }
966 
967     switch(*ln) {
968     case '%':
969       tokArr[tokIdx++].tt = PCT_PERCENT;
970       break;
971     case '<':
972       tokArr[tokIdx++].tt = PCT_LESSTHAN;
973       break;
974     case '>':
975       tokArr[tokIdx++].tt = PCT_GREATERTHAN;
976       break;
977     case ':':
978       tokArr[tokIdx++].tt = PCT_COLON;
979       break;
980     case ';':
981       tokArr[tokIdx].tok.s = Safe_strdup(ln);
982       tokArr[tokIdx++].tt = PCT_COMMENT;
983       tokArr[tokIdx].tt = PCT_NULL;
984       return;
985     case ',':
986       tokArr[tokIdx++].tt = PCT_COMMA;
987       break;
988 
989 
990     default:                            // hack to allow : goto $
991       if(isalpha((unsigned char)*ln) || (*ln == '_')  || (!parsing_peeps && (*ln == '$'))) {
992         char buffer[50];
993         int i=0;
994 
995         while( (isalpha((unsigned char)*ln) || isdigit((unsigned char)*ln) || (*ln == '_') || (*ln == '$')) && i<49)
996           buffer[i++] = *ln++;
997 
998         ln--;
999         buffer[i] = 0;
1000 
1001         tokArr[tokIdx].tok.s = Safe_strdup(buffer);
1002         tokArr[tokIdx++].tt = PCT_STRING;
1003 
1004       } else {
1005         if(parsing_peeps) {
1006                 fprintf(stderr, "Error while parsing peep rules (check peeph.def)\n");
1007                 fprintf(stderr, "Line: %s\n",lnstart);
1008                 fprintf(stderr, "Token: '%c'\n",*ln);
1009                 exit(1);
1010         }
1011       }
1012     }
1013 
1014     /* Advance to next character in input string .
1015      * Note, if none of the tests passed above, then
1016      * we effectively ignore the `bad' character.
1017      * Since the line has already been parsed by SDCCpeeph,
1018      * chance are that there are no invalid characters... */
1019 
1020     ln++;
1021 
1022   }
1023 
1024   tokArr[tokIdx].tt = 0;
1025 }
1026 
1027 
1028 /*-----------------------------------------------------------------*/
1029 /*-----------------------------------------------------------------*/
1030 
1031 
1032 
1033 static void dump1Token(pCodeTokens tt)
1034 {
1035 
1036   switch(tt) {
1037   case PCT_SPACE:
1038     fprintf(stderr, " space ");
1039     break;
1040   case PCT_PERCENT:
1041     fprintf(stderr, " pct %%");
1042     break;
1043   case PCT_LESSTHAN:
1044     fprintf(stderr, " pct <");
1045     break;
1046   case PCT_GREATERTHAN:
1047     fprintf(stderr, " pct >");
1048     break;
1049   case PCT_COLON:
1050     fprintf(stderr, " col :");
1051     break;
1052   case PCT_COMMA:
1053     fprintf(stderr, " comma , ");
1054     break;
1055   case PCT_COMMENT:
1056     fprintf(stderr, " comment ");
1057     //fprintf(stderr,"%s",tokArr[i].tok.s);
1058     break;
1059   case PCT_STRING:
1060     fprintf(stderr, " str ");
1061     //fprintf(stderr,"%s",tokArr[i].tok.s);
1062     break;
1063   case PCT_NUMBER:
1064     fprintf(stderr, " num ");
1065     //fprintf(stderr,"%d",tokArr[i].tok.n);
1066     break;
1067   case PCT_NULL:
1068     fprintf(stderr, " null ");
1069 
1070   }
1071 
1072 }
1073 
1074 
1075 /*-----------------------------------------------------------------*/
1076 /*-----------------------------------------------------------------*/
1077 
1078 static int pcComparePattern(pCodeToken *pct, const char *pat, int max_tokens)
1079 {
1080   int i=0;
1081 
1082   if(!pct || !pat || !*pat)
1083     return 0;
1084 
1085   //DFPRINTF((stderr,"comparing against:\n"));
1086 
1087   while(i < max_tokens) {
1088 
1089     if(*pat == 0){
1090       //DFPRINTF((stderr,"matched\n"));
1091       return (i+1);
1092     }
1093 
1094 //      dump1Token(*pat); fputc('\n', stderr); DFPRINTF((stderr,"\n"));
1095 
1096     if(pct->tt != *pat)
1097       return 0;
1098 
1099 
1100     pct++;
1101     pat++;
1102   }
1103 
1104   return 0;
1105 
1106 }
1107 
1108 /*-----------------------------------------------------------------*/
1109 /*-----------------------------------------------------------------*/
1110 
1111 static int altComparePattern(const char *pct, parsedPattern *pat, int max_tokens)
1112 {
1113   int i=0;
1114 
1115   if(!pct || !pat || !*pct)
1116     return 0;
1117 
1118 
1119   while(i < max_tokens) {
1120 
1121     if(*pct == 0) {
1122         DFPRINTF((stderr,"matched\n"));
1123       return i;
1124     }
1125 
1126 //      dump1Token(*pat); DFPRINTF((stderr,"\n"));
1127 
1128     if( !pat || !pat->pcp )
1129       return 0;
1130 
1131     if (pat->pcp->pt != *pct)
1132       return 0;
1133 
1134         DFPRINTF((stderr," pct=%d\n",*pct));
1135     pct++;
1136     pat++;
1137     i++;
1138   }
1139 
1140   return 0;
1141 
1142 }
1143 /*-----------------------------------------------------------------*/
1144 /*-----------------------------------------------------------------*/
1145 
1146 static int advTokIdx(int *v, int amt)
1147 {
1148 
1149   if((unsigned) (*v + amt) > tokIdx)
1150     return 1;
1151 
1152   *v += amt;
1153   return 0;
1154 
1155 }
1156 
1157 /*-----------------------------------------------------------------*/
1158 /* parseTokens - convert the tokens corresponding to a single line */
1159 /*               of a peep hole assembly into a pCode object.      */
1160 /*                                                                 */
1161 /*                                                                 */
1162 /*                                                                 */
1163 /*                                                                 */
1164 /* This is a simple parser that looks for strings of the type      */
1165 /* allowed in the peep hole definition file. Essentially the format*/
1166 /* is the same as a line of assembly:                              */
1167 /*                                                                 */
1168 /*  label:    mnemonic   op1, op2, op3    ; comment                */
1169 /*                                                                 */
1170 /* Some of these items aren't present. It's the job of the parser  */
1171 /* to determine which are and convert those into the appropriate   */
1172 /* pcode.                                                          */
1173 /*-----------------------------------------------------------------*/
1174 
1175 static int parseTokens(pCodeWildBlock *pcwb, pCode **pcret)
1176 {
1177   pCode *pc;
1178   int error = 0;
1179 
1180   if(!tokIdx)
1181     return error;
1182 
1183 #ifdef PCODE_DEBUG
1184   {
1185     unsigned i;
1186     for(i=0; i<=tokIdx; i++)
1187       dump1Token(tokArr[i].tt);
1188     fputc('\n',stderr);
1189   }
1190 #endif
1191 
1192   {
1193     int lparsedPatIdx = 0;
1194     int lpcpIdx;
1195     int ltokIdx = 0;
1196     int matching = 0;
1197     int j = 0;
1198     int k = 0;
1199 
1200     typedef enum {
1201       PS_START,
1202       PS_HAVE_LABEL,
1203       PS_HAVE_MNEM,
1204       PS_HAVE_1OPERAND,
1205       PS_HAVE_COMMA,
1206       PS_HAVE_2OPERANDS
1207     } ParseStates;
1208 
1209     ParseStates state = PS_START;
1210 
1211     do {
1212 
1213       lpcpIdx=0;
1214       matching = 0;
1215 
1216       if(  ((tokArr[ltokIdx].tt == PCT_SPACE) )
1217            && (advTokIdx(&ltokIdx, 1)) ) // eat space
1218         break;
1219 
1220       do {
1221         j = pcComparePattern(&tokArr[ltokIdx], pcpArr[lpcpIdx].tokens, tokIdx +1);
1222         if( j ) {
1223 
1224           switch(pcpArr[lpcpIdx].pt) {
1225           case  PCP_LABEL:
1226             if(state == PS_START){
1227               DFPRINTF((stderr,"  label\n"));
1228               state = PS_HAVE_LABEL;
1229             } else
1230               DFPRINTF((stderr,"  bad state (%d) for label\n",state));
1231             break;
1232 
1233           case  PCP_STR:
1234             DFPRINTF((stderr,"  %s is",tokArr[ltokIdx].tok.s));
1235             switch(state) {
1236             case PS_START:
1237             case PS_HAVE_LABEL:
1238               DFPRINTF((stderr,"  mnem\n"));
1239               state = PS_HAVE_MNEM;
1240               break;
1241             case PS_HAVE_MNEM:
1242               DFPRINTF((stderr,"  1st operand\n"));
1243               //pco1 = pic16_newpCodeOp(NULL,PO_GPR_REGISTER);
1244               state = PS_HAVE_1OPERAND;
1245               break;
1246             case PS_HAVE_1OPERAND:
1247               DFPRINTF((stderr,"  error expecting comma\n"));
1248               break;
1249             case PS_HAVE_COMMA:
1250               DFPRINTF((stderr,"  2 operands\n"));
1251               break;
1252             case PS_HAVE_2OPERANDS:
1253               break;
1254             }
1255             break;
1256 
1257           case  PCP_WILDVAR:
1258             switch(state) {
1259             case PS_START:
1260             case PS_HAVE_LABEL:
1261               DFPRINTF((stderr,"  wild mnem\n"));
1262               state = PS_HAVE_MNEM;
1263               break;
1264             case PS_HAVE_MNEM:
1265               DFPRINTF((stderr,"  1st operand is wild\n"));
1266               state = PS_HAVE_1OPERAND;
1267               break;
1268             case PS_HAVE_1OPERAND:
1269               DFPRINTF((stderr,"  error expecting comma\n"));
1270               break;
1271             case PS_HAVE_COMMA:
1272               DFPRINTF((stderr,"  2nd operand is wild\n"));
1273               break;
1274             case PS_HAVE_2OPERANDS:
1275               break;
1276             }
1277             break;
1278 
1279           case  PCP_NUMBER:
1280             switch(state) {
1281             case PS_START:
1282             case PS_HAVE_LABEL:
1283               fprintf(stderr,"  ERROR number\n");
1284               break;
1285             case PS_HAVE_MNEM:
1286               DFPRINTF((stderr,"  1st operand is a number\n"));
1287               state = PS_HAVE_1OPERAND;
1288               break;
1289             case PS_HAVE_1OPERAND:
1290               fprintf(stderr,"  error expecting comma\n");
1291               break;
1292             case PS_HAVE_COMMA:
1293               DFPRINTF((stderr,"  2nd operand is a number\n"));
1294               break;
1295             case PS_HAVE_2OPERANDS:
1296               break;
1297             }
1298             break;
1299 
1300           case  PCP_WILDSTR:
1301             break;
1302           case  PCP_COMMA:
1303             if(state == PS_HAVE_1OPERAND){
1304               DFPRINTF((stderr,"  got a comma\n"));
1305               state = PS_HAVE_COMMA;
1306             } else
1307               fprintf(stderr,"  unexpected comma\n");
1308             break;
1309 
1310           }
1311 
1312           matching = 1;
1313           parsedPatArr[lparsedPatIdx].pcp = &pcpArr[lpcpIdx];
1314           parsedPatArr[lparsedPatIdx].pct = &tokArr[ltokIdx];
1315           lparsedPatIdx++;
1316 
1317 //              dump1Token(tokArr[ltokIdx].tt);
1318 
1319           if(advTokIdx(&ltokIdx, strlen(pcpArr[lpcpIdx].tokens) ) ) {
1320             DFPRINTF((stderr," reached end \n"));
1321             matching = 0;
1322             //return;
1323           }
1324         }
1325 
1326 
1327       } while ((++lpcpIdx < PCPATTERNS) && !matching);
1328 
1329     } while (matching);
1330 
1331     parsedPatArr[lparsedPatIdx].pcp = NULL;
1332     parsedPatArr[lparsedPatIdx].pct = NULL;
1333 
1334     j=k=0;
1335     do {
1336       int c;
1337 
1338       if( (c=altComparePattern( altArr[k].tokens, &parsedPatArr[j],10) ) ) {
1339 
1340         if( altArr[k].f) {
1341           pc = altArr[k].f(&parsedPatArr[j],pcwb);
1342           //if(pc && pc->print)
1343           //  pc->print(stderr,pc);
1344           //if(pc && pc->destruct) pc->destruct(pc); dumps core?
1345 
1346           //if(curBlock && pc)
1347           //pic16_addpCode2pBlock(curBlock, pc);
1348           if(pc) {
1349             if (pcret) {
1350               *pcret = pc;
1351               return 0;       // Only accept one line for now.
1352             } else
1353               pic16_addpCode2pBlock(pcwb->pb, pc);
1354           } else
1355             error++;
1356         }
1357         j += c;
1358       }
1359       k++;
1360     }
1361     while(j<=lparsedPatIdx && k<ALTPATTERNS);
1362 
1363 /*
1364     DFPRINTF((stderr,"\nConverting parsed line to pCode:\n\n"));
1365 
1366     j = 0;
1367     do {
1368       if(parsedPatArr[j].pcp && parsedPatArr[j].pcp->f )
1369         parsedPatArr[j].pcp->f(&parsedPatArr[j]);
1370       DFPRINTF((stderr,"  %d",parsedPatArr[j].pcp->pt));
1371       j++;
1372     }
1373     while(j<lparsedPatIdx);
1374 */
1375     DFPRINTF((stderr,"\n"));
1376 
1377   }
1378 
1379   return error;
1380 }
1381 
1382 /*-----------------------------------------------------------------*/
1383 /*                                                                 */
1384 /*-----------------------------------------------------------------*/
1385 static void  peepRuleBlock2pCodeBlock(  lineNode *ln, pCodeWildBlock *pcwb)
1386 {
1387 
1388   if(!ln)
1389     return;
1390 
1391   for( ; ln; ln = ln->next) {
1392 
1393     //DFPRINTF((stderr,"%s\n",ln->line));
1394 //      fprintf(stderr, "peep rule : %s\n", ln->line);
1395 
1396     tokenizeLineNode(ln->line);
1397 
1398     if(parseTokens(pcwb,NULL)) {
1399       int i;
1400       fprintf(stderr,"ERROR assembling line:\n%s\n",ln->line);
1401       fprintf(stderr,"Tokens:\n");
1402       for(i=0; i<8; i++)
1403         dump1Token(tokArr[i].tt);
1404       fputc('\n',stderr);
1405       exit (1);
1406     }
1407   }
1408 }
1409 
1410 /*-----------------------------------------------------------------*/
1411 /* pic16_AssembleLine - parse line and return the pCode equivalent */
1412 /*                      peeps=1 if parsing peep rules, 0 otherwise */
1413 /*-----------------------------------------------------------------*/
1414 pCode *pic16_AssembleLine(char *line, int peeps)
1415 {
1416   pCode *pc=NULL;
1417 
1418   if(!line || !*line) {
1419     fprintf(stderr,"WARNING returning NULL in AssembleLine\n");
1420     return NULL;
1421   }
1422 
1423   parsing_peeps = peeps;
1424 
1425   tokenizeLineNode(line);
1426 
1427   if(parseTokens(NULL,&pc))
1428     fprintf(stderr, "WARNING: unable to assemble line:\n%s\n",line);
1429   else {
1430         DFPRINTF((stderr, "pc= %p\n", pc));
1431 //      if(pc)pc->print(stderr, pc);
1432   }
1433 
1434   parsing_peeps = 1;
1435   return pc;
1436 
1437 }
1438 
1439 /*-----------------------------------------------------------------*/
1440 /* peepRuleCondition                                               */
1441 /*-----------------------------------------------------------------*/
1442 static void peepRuleCondition(const char *cond, pCodePeep *pcp)
1443 {
1444   if(!cond || !pcp)
1445     return;
1446 
1447   //DFPRINTF((stderr,"\nCondition:  %s\n",cond));
1448   /* brute force compares for now */
1449 
1450   if(STRCASECMP(cond, "NZ") == 0) {
1451     //DFPRINTF((stderr,"found NZ\n"));
1452     pcp->postFalseCond = PCC_Z;
1453 
1454   }
1455 
1456 }
1457 
1458 
1459 static void initpCodeWildBlock(pCodeWildBlock *pcwb)
1460 {
1461 
1462   //  pcwb = Safe_alloc(sizeof(pCodeWildBlock));
1463 
1464   if(!pcwb)
1465     return;
1466 
1467   pcwb->vars = NULL;
1468   pcwb->wildpCodes = NULL;
1469   pcwb->wildpCodeOps = NULL;
1470 
1471   pcwb->nvars = 0;
1472   pcwb->nwildpCodes = 0;
1473   pcwb->nops = 0;
1474 
1475 }
1476 
1477 static void postinit_pCodeWildBlock(pCodeWildBlock *pcwb)
1478 {
1479 
1480   if(!pcwb)
1481     return;
1482 
1483   pcwb->nvars+=2;
1484   pcwb->nops = pcwb->nvars;
1485 
1486   pcwb->vars = Safe_calloc(pcwb->nvars, sizeof(char *));
1487   pcwb->wildpCodeOps = Safe_calloc(pcwb->nvars, sizeof(pCodeOp *));
1488 
1489   pcwb->nwildpCodes+=2;
1490   pcwb->wildpCodes = Safe_calloc(pcwb->nwildpCodes, sizeof(pCode *));
1491 
1492 }
1493 
1494 static void initpCodePeep(pCodePeep *pcp)
1495 {
1496 
1497   //  pcwb = Safe_alloc(sizeof(pCodeWildBlock));
1498 
1499   if(!pcp)
1500     return;
1501 
1502   initpCodeWildBlock(&pcp->target);
1503   pcp->target.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1504 
1505   initpCodeWildBlock(&pcp->replace);
1506   pcp->replace.pb = pic16_newpCodeChain(NULL, 'W', NULL);
1507 
1508 }
1509 
1510 /*-----------------------------------------------------------------*/
1511 /* peepRules2pCode - parse the "parsed" peep hole rules to generate*/
1512 /*                   pCode.                                        */
1513 /*                                                                 */
1514 /* SDCCpeeph parses the peep rules file and extracts variables,    */
1515 /* removes white space, and checks the syntax. This function       */
1516 /* extends that processing to produce pCode objects. You can kind  */
1517 /* think of this function as an "assembler", though instead of     */
1518 /* taking raw text to produce machine code, it produces pCode.     */
1519 /*                                                                 */
1520 /*-----------------------------------------------------------------*/
1521 extern void pic16initpCodePeepCommands(void);
1522 
1523 void  pic16_peepRules2pCode(peepRule *rules)
1524 {
1525   peepRule *pr;
1526 
1527   pCodePeep *currentRule;
1528   pCodePeepSnippets *pcps;
1529 
1530   pic16initpCodePeepCommands();
1531 
1532   /* The rules are in a linked-list. Each rule has two portions */
1533   /* There's the `target' and there's the `replace'. The target */
1534   /* is compared against the SDCC generated code and if it      */
1535   /* matches, it gets replaced by the `replace' block of code.  */
1536   /*                                                            */
1537   /* Here we loop through each rule and convert the target's and*/
1538   /* replace's into pCode target and replace blocks             */
1539 
1540   for (pr = rules; pr; pr = pr->next) {
1541 
1542     //DFPRINTF((stderr,"\nRule:\n\n"));
1543 
1544     pcps = Safe_alloc(sizeof(pCodePeepSnippets));
1545     peepSnippets = DLL_append((DLList*)peepSnippets,(DLList*)pcps);
1546 
1547     currentRule = pcps->peep  = Safe_alloc(sizeof(pCodePeep));
1548     initpCodePeep(currentRule);
1549 
1550     /* Convert the target block */
1551     peepRuleBlock2pCodeBlock(pr->match, &currentRule->target);
1552 
1553     //DFPRINTF((stderr,"finished target, here it is in pcode form:\n"));
1554 //      pic16_printpBlock(stderr, currentRule->target.pb);
1555 
1556     //DFPRINTF((stderr,"target with labels merged:\n"));
1557     //pic16_pBlockMergeLabels(curBlock);
1558     pic16_pBlockMergeLabels(currentRule->target.pb);
1559     //pic16_printpBlock(stderr, currentRule->replace.pb);
1560 
1561     //#ifdef PCODE_DEBUG
1562     //    pic16_printpBlock(stderr, curBlock);
1563     //#endif
1564     //DFPRINTF((stderr,"\nReplaced by:\n"));
1565 
1566 
1567     /* Convert the replace block */
1568     peepRuleBlock2pCodeBlock(pr->replace, &currentRule->replace);
1569 
1570     //DFPRINTF((stderr,"finished replace block, here it is in pcode form:\n"));
1571     //pic16_printpBlock(stderr, curBlock);
1572 
1573     //DFPRINTF((stderr,"replace with labels merged:\n"));
1574 
1575     pic16_pBlockMergeLabels(currentRule->replace.pb);
1576     //pic16_printpBlock(stderr, currentRule->replace.pb);
1577 
1578     peepRuleCondition(pr->cond,currentRule);
1579 
1580     /* The rule has been converted to pCode. Now allocate
1581      * space for the wildcards */
1582 
1583     postinit_pCodeWildBlock(&currentRule->target);
1584     postinit_pCodeWildBlock(&currentRule->replace);
1585 
1586     //return; // debug ... don't want to go through all the rules yet
1587   }
1588 
1589   if (0)
1590     {
1591       pCodePeep *peepBlock;
1592       DLList *peeprules;
1593 
1594       peeprules = (DLList *)peepSnippets;
1595       fprintf(stderr,"target rules\n");
1596       while (peeprules)
1597         {
1598           fprintf(stderr,"   rule:\n");
1599           peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1600           pic16_printpBlock(stderr, peepBlock->target.pb);
1601           peeprules = peeprules->next;
1602         } // while
1603       fprintf(stderr," ... done\n");
1604     } // if
1605 }
1606 #if 0
1607 static void printpCodeString(FILE *of, pCode *pc, int max)
1608 {
1609   int i=0;
1610 
1611   while(pc && (i++<max)) {
1612     pc->print(of,pc);
1613     pc = pc->next;
1614   }
1615 }
1616 #endif
1617 /*-----------------------------------------------------------------*/
1618 /* DLList * DLL_append                                             */
1619 /*                                                                 */
1620 /* Append a DLList object to the end of a DLList (doubly linked    */
1621 /* list). If The list to which we want to append is non-existant   */
1622 /* then one is created. Other wise, the end of the list is sought  */
1623 /* out and a new DLList object is appended to it. In either case,  */
1624 /* the void *data is added to the newly created DLL object.        */
1625 /*-----------------------------------------------------------------*/
1626 
1627 static void * DLL_append(DLList *list, DLList *next)
1628 {
1629   DLList *b;
1630 
1631 
1632   /* If there's no list, then create one: */
1633   if(!list) {
1634     next->next = next->prev = NULL;
1635     return next;
1636   }
1637 
1638 
1639   /* Search for the end of the list. */
1640   b = list;
1641   while(b->next)
1642     b = b->next;
1643 
1644   /* Now append the new DLL object */
1645   b->next = next;
1646   b->next->prev = b;
1647   b = b->next;
1648   b->next = NULL;
1649 
1650   return list;
1651 
1652 }
1653 
1654 
1655 /*-----------------------------------------------------------------
1656 
1657   pCode peephole optimization
1658 
1659 
1660   The pCode "peep hole" optimization is not too unlike the peep hole
1661   optimization in SDCCpeeph.c. The major difference is that here we
1662   use pCode's whereas there we use ASCII strings. The advantage with
1663   pCode's is that we can ascertain flow information in the instructions
1664   being optimized.
1665 
1666 
1667 <FIX ME> - elaborate...
1668 
1669   -----------------------------------------------------------------*/
1670 
1671 
1672 
1673 /*-----------------------------------------------------------------*/
1674 /* pCodeSearchCondition - Search a pCode chain for a 'condition'   */
1675 /*                                                                 */
1676 /* return conditions                                               */
1677 /*  1 - The Condition was found for a pCode's input                */
1678 /*  0 - No matching condition was found for the whole chain        */
1679 /* -1 - The Condition was found for a pCode's output               */
1680 /*                                                                 */
1681 /*-----------------------------------------------------------------*/
1682 int pic16_pCodeSearchCondition(pCode *pc, unsigned int cond)
1683 {
1684   //fprintf(stderr,"Checking conditions %d\n",cond);
1685   while(pc) {
1686 
1687     /* If we reach a function end (presumably an end since we most
1688        probably began the search in the middle of a function), then
1689        the condition was not found. */
1690     if(pc->type == PC_FUNCTION)
1691       return 0;
1692 
1693     if(pc->type == PC_OPCODE) {
1694       //fprintf(stderr," checking conditions of: ");
1695       //pc->print(stderr,pc);
1696       //fprintf(stderr,"\t\tinCond=%d\toutCond=%d\n",PCI(pc)->inCond,PCI(pc)->outCond);
1697       if(PCI(pc)->inCond & cond)
1698         return 1;
1699       if(PCI(pc)->outCond & cond)
1700         return -1;
1701     }
1702 
1703     pc = pc->next;
1704   }
1705 
1706   return 0;
1707 }
1708 
1709 /*-----------------------------------------------------------------
1710  * int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1711  *
1712  * Compare two pCodeOp's and return 1 if they're the same
1713  *-----------------------------------------------------------------*/
1714 static int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
1715 {
1716   char b[1024], *n2;
1717 
1718   if(!pcops || !pcopd)
1719     return 0;
1720 
1721 #if 0
1722   fprintf(stderr,"%s:%d Comparing operands %s", __FILE__, __LINE__,
1723           pic16_get_op( pcops,NULL,0));
1724 
1725   fprintf(stderr," to %s\n",
1726           pic16_get_op( pcopd,NULL,0));
1727 #endif
1728 
1729   if(pcops->type != pcopd->type) {
1730     //fprintf(stderr,"  - fail - diff types\n");
1731     return 0;  // different types
1732   }
1733 
1734   if(pcops->type == PO_LITERAL) {
1735 
1736     if((PCOL(pcops)->lit >= 0) && (PCOL(pcops)->lit == PCOL(pcopd)->lit))
1737       return 1;
1738 
1739     return 0;
1740   }
1741 
1742   memset(b, 0, sizeof(b) );       //b[0]=0;
1743   pic16_get_op(pcops,b, sizeof(b) );
1744 
1745   n2 = pic16_get_op(pcopd,NULL,0);
1746 
1747   if( !n2 || strcmp(b,n2)) {
1748 //      fprintf(stderr,"  - fail - diff names: %s, len=%d,  %s, len=%d\n",b,strlen(b), n2, strlen(n2) );
1749     return 0;  // different names
1750   }
1751 
1752   switch(pcops->type) {
1753   case PO_DIR:
1754     if( PCOR(pcops)->instance != PCOR(pcopd)->instance) {
1755 //      fprintf(stderr, "  - fail different instances\n");
1756       return 0;
1757     }
1758     break;
1759   default:
1760     break;
1761   }
1762 
1763   //fprintf(stderr,"  - pass\n");
1764 
1765   return 1;
1766 }
1767 
1768 static int pCodePeepMatchLabels(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1769 {
1770   int labindex;
1771 
1772   /* Check for a label associated with this wild pCode */
1773   // If the wild card has a label, make sure the source code does too.
1774   if(PCI(pcd)->label) {
1775     pCode *pcl = PCI(pcd)->label->pc;
1776 
1777 #ifdef PCODE_DEBUG
1778     int li = -PCL(pcl)->key;
1779 
1780     if(peepBlock->target.vars[li] == NULL) {
1781       if(PCI(pcs)->label) {
1782         DFPRINTF((stderr,"first time for a label: %d %s\n",li,PCL(PCI(pcs)->label->pc)->label));
1783       }
1784     } else {
1785       // DFPRINTF((stderr,"label id = %d \n",PCL(PCI(pcd)->label->pc)->key));
1786       DFPRINTF((stderr," label id: %d %s\n",li,peepBlock->target.vars[li]));
1787       if(PCI(pcs)->label) {
1788         DFPRINTF((stderr," src %s\n",PCL(PCI(pcs)->label->pc)->label));
1789       }
1790     }
1791 #endif
1792 
1793 
1794     if(!PCI(pcs)->label)
1795       return 0;
1796 
1797     labindex = -PCL(pcl)->key;
1798     if(peepBlock->target.vars[labindex] == NULL) {
1799       // First time to encounter this label
1800       peepBlock->target.vars[labindex] = PCL(PCI(pcs)->label->pc)->label;
1801       DFPRINTF((stderr,"first time for a label: %d %s\n",labindex,PCL(PCI(pcs)->label->pc)->label));
1802 
1803     } else {
1804       if(strcmp(peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label) != 0) {
1805         DFPRINTF((stderr,"labels don't match dest %s != src %s\n",peepBlock->target.vars[labindex],PCL(PCI(pcs)->label->pc)->label));
1806         return 0;
1807       }
1808       DFPRINTF((stderr,"matched a label %d %s -hey\n",labindex,peepBlock->target.vars[labindex]));
1809     }
1810   } else {
1811     //DFPRINTF((stderr,"destination doesn't have a label\n"));
1812 
1813     if(PCI(pcs)->label)
1814       return 0;
1815 
1816     //DFPRINTF((stderr,"neither src nor dest have labels\n"));
1817 
1818   }
1819 
1820   return 1;
1821 
1822 }
1823 
1824 /*-----------------------------------------------------------------*/
1825 /* pCodePeepMatchLine - Compare source and destination pCodes to   */
1826 /*                      see they're the same.                      */
1827 /*                                                                 */
1828 /* In this context, "source" refers to the coded generated by gen.c*/
1829 /* and "destination" refers to a pcode in a peep rule. If the dest-*/
1830 /* ination has no wild cards, then MatchLine will compare the two  */
1831 /* pcodes (src and dest) for a one-to-one match. If the destination*/
1832 /* has wildcards, then those get expanded. When a wild card is     */
1833 /* encountered for the first time it autmatically is considered a  */
1834 /* match and the object that matches it is referenced in the       */
1835 /* variables or opcodes array (depending on the type of match).    */
1836 /*                                                                 */
1837 /*                                                                 */
1838 /* Inputs:                                                         */
1839 /*  *peepBlock - A pointer to the peepBlock that contains the      */
1840 /*               entire rule to which the destination pcode belongs*/
1841 /*  *pcs - a pointer to the source pcode                           */
1842 /*  *pcd - a pointer to the destination pcode                      */
1843 /*                                                                 */
1844 /* Returns:                                                        */
1845 /*  1 - pcodes match                                               */
1846 /*  0 - pcodes don't match                                         */
1847 /*                                                                 */
1848 /*                                                                 */
1849 /*-----------------------------------------------------------------*/
1850 
1851 static int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1852 {
1853   int index;   // index into wild card arrays
1854   int havematch=0;
1855 
1856   /* one-for-one match. Here the source and destination opcodes
1857    * are not wild. However, there may be a label or a wild operand */
1858 
1859   if(pcs) {
1860     if(PCI(pcs)->label) {
1861       DFPRINTF((stderr,"Match line source label: %s\n",PCL(PCI(pcs)->label->pc)->label));
1862     }
1863   }
1864 
1865   if(pcs->type == pcd->type) {
1866 
1867     if(pcs->type == PC_OPCODE) {
1868 
1869       /* If the opcodes don't match then the line doesn't match */
1870       if(PCI(pcs)->op != PCI(pcd)->op)
1871         return 0;
1872 
1873 #ifdef PCODE_DEBUG
1874       DFPRINTF((stderr,"%s comparing\n",__FUNCTION__));
1875       pcs->print(stderr,pcs);
1876       pcd->print(stderr,pcd);
1877 #endif
1878 
1879       if(!pCodePeepMatchLabels(peepBlock, pcs, pcd))
1880         return 0;
1881 
1882       /* Compare the operands */
1883       if(PCI(pcd)->pcop) {
1884         /* assert that optimizations do not touch operations that work on SFRs or INDF registers */
1885         if ((PCI(pcd)->pcop->type == PO_WILD) && (!(PCI(pcs)->pcop) || ((PCI(pcs)->pcop->type != PO_SFR_REGISTER) && (PCI(pcs)->pcop->type != PO_INDF0)))) {
1886           index = PCOW(PCI(pcd)->pcop)->id;
1887           //DFPRINTF((stderr,"destination is wild\n"));
1888 #ifdef DEBUG_PCODEPEEP
1889           if (index > peepBlock->nops) {
1890             DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1891             exit(1);
1892           }
1893 #endif
1894 
1895           PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
1896           havematch = -1;
1897           if(!peepBlock->target.wildpCodeOps[index]) {
1898             peepBlock->target.wildpCodeOps[index] = PCI(pcs)->pcop;
1899 
1900             //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1901 
1902           } else {
1903             /*
1904               pcs->print(stderr,pcs);
1905               pcd->print(stderr,pcd);
1906 
1907               fprintf(stderr, "comparing operands of these instructions, result %d\n",
1908               pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1909               );
1910             */
1911 
1912             havematch = pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1913 //          return pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index]);
1914           }
1915 
1916           if((havematch==-1) && PCI(pcs)->pcop) {
1917             char *n;
1918 
1919             switch(PCI(pcs)->pcop->type) {
1920             case PO_GPR_TEMP:
1921             case PO_FSR0:
1922               //case PO_INDF0:
1923                 n = PCOR(PCI(pcs)->pcop)->r->name;
1924 
1925               break;
1926             default:
1927               assert (PCI(pcs)->pcop != NULL);
1928               n = PCI(pcs)->pcop->name;
1929             }
1930 
1931             if(peepBlock->target.vars[index])
1932               return  (strcmp(peepBlock->target.vars[index],n) == 0);
1933             else {
1934               DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1935               peepBlock->target.vars[index] = n;
1936               havematch = 1;
1937 //            return 1;
1938             }
1939           }
1940 
1941           /* now check whether the second operand matches */
1942           /* assert that optimizations do not touch operations that work on SFRs or INDF registers */
1943           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)))) {
1944 
1945 //              fprintf(stderr, "%s:%d %s second operand is wild\n", __FILE__, __LINE__, __FUNCTION__);
1946 
1947                   index = PCOW2(PCI(pcd)->pcop)->id;
1948                 //DFPRINTF((stderr,"destination is wild\n"));
1949 #ifdef DEBUG_PCODEPEEP
1950                 if (index > peepBlock->nops) {
1951                         DFPRINTF((stderr,"%s - variables exceeded\n",__FUNCTION__));
1952                         exit(1);
1953                 }
1954 #endif
1955 
1956                 PCOW2(PCI(pcd)->pcop)->matched = PCOP2(PCI(pcs)->pcop)->pcopR;
1957                 if(!peepBlock->target.wildpCodeOps[index]) {
1958                         peepBlock->target.wildpCodeOps[index] = PCOP2(PCI(pcs)->pcop)->pcopR;
1959 
1960                 //if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
1961 
1962                 } else {
1963                         /*
1964                         pcs->print(stderr,pcs);
1965                         pcd->print(stderr,pcd);
1966 
1967                         fprintf(stderr, "comparing operands of these instructions, result %d\n",
1968                                 pCodeOpCompare(PCI(pcs)->pcop, peepBlock->target.wildpCodeOps[index])
1969                                 );
1970                         */
1971 
1972                   return ((havematch==1) && pCodeOpCompare(PCOP2(PCI(pcs)->pcop)->pcopR,
1973                                 peepBlock->target.wildpCodeOps[index]));
1974                 }
1975 
1976                 if(PCOP2(PCI(pcs)->pcop)->pcopR) {
1977                   char *n;
1978 
1979                         switch(PCOP2(PCI(pcs)->pcop)->pcopR->type) {
1980                         case PO_GPR_TEMP:
1981                         case PO_FSR0:
1982                       //case PO_INDF0:
1983                                 n = PCOR(PCOP2(PCI(pcs)->pcop)->pcopR)->r->name;
1984                                 break;
1985                         default:
1986                                 n = PCOP2(PCI(pcs)->pcop)->pcopR->name;
1987                         }
1988 
1989                         if(peepBlock->target.vars[index])
1990                                 return  (havematch && (strcmp(peepBlock->target.vars[index],n) == 0));
1991                         else {
1992                                 DFPRINTF((stderr,"first time for a variable: %d, %s\n",index,n));
1993                                 peepBlock->target.vars[index] = n;
1994                                 return (havematch==1);          //&& 1;
1995                         }
1996                 }
1997 
1998           } else if (PCOW2(PCI(pcd)->pcop) && (PCOP2(PCI(pcd)->pcop)->pcopR->type == PO_WILD) && PCOP2(PCI(pcs)->pcop)->pcopR)
1999             {
2000               return 0;
2001             } else {
2002               return havematch;
2003             }
2004 #if 0
2005          else if (PCI(pcd)->pcop->type == PO_LITERAL) {
2006           return (havematch &&
2007                 pCodeOpCompare(PCOR2(PCI(pcs)->pcop)->pcop2, PCOR2(PCI(pcd)->pcop)->pcop2));
2008 
2009         }
2010 #endif
2011 
2012         } else if (PCI(pcd)->pcop->type == PO_LITERAL) {
2013           return pCodeOpCompare(PCI(pcs)->pcop, PCI(pcd)->pcop);
2014 
2015         }
2016   }
2017 
2018         /* FIXME - need an else to check the case when the destination
2019          * isn't a wild card */
2020       } else
2021         /* The pcd has no operand. Lines match if pcs has no operand either*/
2022         return (PCI(pcs)->pcop == NULL);
2023   }
2024 
2025   /* Compare a wild instruction to a regular one. */
2026 
2027   if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
2028 
2029     index = PCW(pcd)->id;
2030 #ifdef PCODE_DEBUG
2031     DFPRINTF((stderr,"%s comparing wild cards\n",__FUNCTION__));
2032     pcs->print(stderr,pcs);
2033     pcd->print(stderr,pcd);
2034 #endif
2035     peepBlock->target.wildpCodes[PCW(pcd)->id] = pcs;
2036 
2037     if(!pCodePeepMatchLabels(peepBlock, pcs, pcd)) {
2038       DFPRINTF((stderr," Failing because labels don't match\n"));
2039       return 0;
2040     }
2041 
2042     if(PCW(pcd)->mustBeBitSkipInst & !(PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
2043       // doesn't match because the wild pcode must be a bit skip
2044       DFPRINTF((stderr," Failing match because bit skip is req\n"));
2045       //pcd->print(stderr,pcd);
2046       //pcs->print(stderr,pcs);
2047       return 0;
2048     }
2049 
2050     if(PCW(pcd)->mustNotBeBitSkipInst & (PCI(pcs)->isBitInst && PCI(pcs)->isSkip)) {
2051       // doesn't match because the wild pcode must *not* be a bit skip
2052       DFPRINTF((stderr," Failing match because shouldn't be bit skip\n"));
2053       //pcd->print(stderr,pcd);
2054       //pcs->print(stderr,pcs);
2055       return 0;
2056     }
2057 
2058     if(PCW(pcd)->operand) {
2059       PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
2060       if(peepBlock->target.vars[index]) {
2061         int i = (strcmp(peepBlock->target.vars[index],PCI(pcs)->pcop->name) == 0);
2062 #ifdef PCODE_DEBUG
2063 
2064         if(i)
2065           DFPRINTF((stderr," (matched)\n"));
2066         else {
2067           DFPRINTF((stderr," (no match: wild card operand mismatch\n"));
2068           DFPRINTF((stderr,"  peepblock= %s,  pcodeop= %s\n",
2069                   peepBlock->target.vars[index],
2070                   PCI(pcs)->pcop->name));
2071         }
2072 #endif
2073         return i;
2074       } else {
2075         DFPRINTF((stderr," (matched %s\n",PCI(pcs)->pcop->name));
2076         peepBlock->target.vars[index] = PCI(pcs)->pcop->name;
2077         return 1;
2078       }
2079     }
2080 
2081     pcs = pic16_findNextInstruction(pcs->next);
2082     if(pcs) {
2083       //DFPRINTF((stderr," (next to match)\n"));
2084       //pcs->print(stderr,pcs);
2085     } else if(pcd->next) {
2086       /* oops, we ran out of code, but there's more to the rule */
2087       return 0;
2088     }
2089 
2090     return 1; /*  wild card matches */
2091   }
2092 
2093   return 0;
2094 }
2095 
2096 /*-----------------------------------------------------------------*/
2097 /*-----------------------------------------------------------------*/
2098 static void pCodePeepClrVars(pCodePeep *pcp)
2099 {
2100 
2101   int i;
2102   if(!pcp)
2103     return;
2104 /*
2105   DFPRINTF((stderr," Clearing peep rule vars\n"));
2106   DFPRINTF((stderr," %d %d %d  %d %d %d\n",
2107             pcp->target.nvars,pcp->target.nops,pcp->target.nwildpCodes,
2108             pcp->replace.nvars,pcp->replace.nops,pcp->replace.nwildpCodes));
2109 */
2110   for(i=0;i<pcp->target.nvars; i++)
2111     pcp->target.vars[i] = NULL;
2112   for(i=0;i<pcp->target.nops; i++)
2113     pcp->target.wildpCodeOps[i] = NULL;
2114   for(i=0;i<pcp->target.nwildpCodes; i++)
2115     pcp->target.wildpCodes[i] = NULL;
2116 
2117   for(i=0;i<pcp->replace.nvars; i++)
2118     pcp->replace.vars[i] = NULL;
2119   for(i=0;i<pcp->replace.nops; i++)
2120     pcp->replace.wildpCodeOps[i] = NULL;
2121   for(i=0;i<pcp->replace.nwildpCodes; i++)
2122     pcp->replace.wildpCodes[i] = NULL;
2123 
2124 
2125 
2126 }
2127 
2128 /*-----------------------------------------------------------------*/
2129 /*  pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2130 /*                     into the pCode chain containing pc1         */
2131 /*-----------------------------------------------------------------*/
2132 void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2)
2133 {
2134 
2135   if(!pc1 || !pc2)
2136     return;
2137 
2138   pc2->next = pc1->next;
2139   if(pc1->next)
2140     pc1->next->prev = pc2;
2141 
2142   pc2->pb = pc1->pb;
2143   pc2->prev = pc1;
2144   pc1->next = pc2;
2145 
2146 }
2147 
2148 /*-----------------------------------------------------------------*/
2149 /* pic16_pCodeOpCopy - copy a pcode operator                       */
2150 /*-----------------------------------------------------------------*/
2151 pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop)
2152 {
2153   pCodeOp *pcopnew=NULL;
2154 
2155   if(!pcop)
2156     return NULL;
2157 
2158   switch(pcop->type) {
2159   case PO_NONE:
2160   case PO_STR:
2161   case PO_REL_ADDR:
2162         pcopnew = Safe_malloc(sizeof(pCodeOp));
2163         memcpy(pcopnew, pcop, sizeof(pCodeOp));
2164         break;
2165 
2166   case PO_W:
2167   case PO_WREG:
2168   case PO_STATUS:
2169   case PO_BSR:
2170   case PO_FSR0:
2171   case PO_INDF0:
2172   case PO_INTCON:
2173   case PO_GPR_REGISTER:
2174   case PO_GPR_TEMP:
2175   case PO_SFR_REGISTER:
2176   case PO_PCL:
2177   case PO_PCLATH:
2178   case PO_PCLATU:
2179   case PO_PRODL:
2180   case PO_PRODH:
2181   case PO_DIR:
2182     //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2183     /* XXX: might also be pCodeOpReg2 -- that's why the two structs are identical */
2184     pcopnew = Safe_malloc(sizeof(pCodeOpReg));
2185     memcpy(pcopnew, pcop, sizeof(pCodeOpReg));
2186     break;
2187 
2188   case PO_LITERAL:
2189     //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2190     /* XXX: might also be pCodeOpLit2, that's why the two structs are identical... */
2191     pcopnew = Safe_malloc(sizeof(pCodeOpLit));
2192     memcpy(pcopnew, pcop, sizeof(pCodeOpLit));
2193     break;
2194 
2195   case PO_IMMEDIATE:
2196     pcopnew = Safe_malloc(sizeof(pCodeOpImmd));
2197     memcpy(pcopnew, pcop, sizeof(pCodeOpImmd));
2198     break;
2199 
2200   case PO_GPR_BIT:
2201   case PO_CRY:
2202   case PO_BIT:
2203     pcopnew = Safe_malloc(sizeof(pCodeOpRegBit));
2204     memcpy(pcopnew, pcop, sizeof(pCodeOpRegBit));
2205     break;
2206 
2207   case PO_LABEL:
2208     //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2209     pcopnew = Safe_malloc(sizeof(pCodeOpLabel));
2210     memcpy(pcopnew, pcop, sizeof(pCodeOpLabel));
2211     break;
2212 
2213   case PO_WILD:
2214     /* Here we expand the wild card into the appropriate type: */
2215     /* By recursively calling pCodeOpCopy */
2216     //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2217     if(PCOW(pcop)->matched)
2218       pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->matched);
2219     else {
2220       // Probably a label
2221       pcopnew = pic16_pCodeOpCopy(PCOW(pcop)->subtype);
2222       pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2223       //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2224     }
2225     return pcopnew;
2226     break;
2227 
2228   case PO_TWO_OPS:
2229     pcopnew = pic16_newpCodeOp2( pic16_pCodeOpCopy( PCOP2(pcop)->pcopL ),
2230     pic16_pCodeOpCopy( PCOP2(pcop)->pcopR ) );
2231     return pcopnew;
2232 
2233   default:
2234     assert ( !"unhandled pCodeOp type copied" );
2235   } // switch
2236 
2237   /* strdup pcop->name (prevent access to shared but released memory) */
2238   if(pcop->name)
2239     pcopnew->name = Safe_strdup(pcop->name);
2240   else
2241     pcopnew->name = NULL;
2242 
2243   return pcopnew;
2244 }
2245 
2246 
2247 /*-----------------------------------------------------------------*/
2248 /* pCodeCopy - copy a pcode                                        */
2249 /*-----------------------------------------------------------------*/
2250 static pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2251 {
2252   pCodeInstruction *new_pci;
2253 
2254   if(invert)
2255     new_pci = PCI(pic16_newpCode(pci->inverted_op,pci->pcop));
2256   else
2257     new_pci = PCI(pic16_newpCode(pci->op,pci->pcop));
2258 
2259   new_pci->pc.pb = pci->pc.pb;
2260   new_pci->from = pci->from;
2261   new_pci->to   = pci->to;
2262   new_pci->label = pci->label;
2263   new_pci->pcflow = pci->pcflow;
2264 
2265   return PCODE(new_pci);
2266 }
2267 
2268 /*-----------------------------------------------------------------*/
2269 /*-----------------------------------------------------------------*/
2270 static void pCodeDeleteChain(pCode *f,pCode *t)
2271 {
2272   pCode *pc;
2273 
2274 
2275   while(f && f!=t) {
2276     DFPRINTF((stderr,"delete pCode:\n"));
2277     pc = f->next;
2278     //f->print(stderr,f);
2279     //f->delete(f);  this dumps core...
2280 
2281     f = pc;
2282 
2283   }
2284 
2285 }
2286 /*-----------------------------------------------------------------*/
2287 /*-----------------------------------------------------------------*/
2288 int pic16_pCodePeepMatchRule(pCode *pc)
2289 {
2290   pCodePeep *peepBlock;
2291   pCode *pct, *pcin;
2292   pCodeCSource *pc_cline=NULL;
2293   DLList *peeprules;
2294   int matched;
2295   pCode *pcr;
2296 
2297   peeprules = (DLList *)peepSnippets;
2298 
2299   while(peeprules) {
2300     peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
2301 
2302     if(!peepBlock || /*!peepBlock->target ||*/ !peepBlock->target.pb->pcHead) {
2303       fprintf(stderr, "skipping rule because target pb is NULL\n");
2304       goto next_rule;
2305     }
2306 
2307     pCodePeepClrVars(peepBlock);
2308 /*
2309     pcin = pc;
2310     if(IS_PCCOMMENT(pcin))
2311       pc = pcin = pic16_findNextInstruction(pcin->next);
2312 */
2313     pcin = pc = pic16_findNextInstruction(pc);
2314 
2315     pct = peepBlock->target.pb->pcHead;
2316 #ifdef PCODE_DEBUG
2317     {
2318       pCode *pcr = peepBlock->replace.pb->pcHead;
2319       if(pcr) pct->print(stderr,pcr);
2320     }
2321 #endif
2322     matched = 0;
2323     while(pct && pcin) {
2324 
2325       if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
2326         break;
2327 
2328       pcin = pic16_findNextInstruction(pcin->next);
2329       pct = pct->next;
2330       //debug:
2331       //DFPRINTF((stderr,"    matched\n"));
2332 
2333       if(!pcin && pct) {
2334         DFPRINTF((stderr," partial match... no more code\n"));
2335 //      fprintf(stderr," partial match... no more code\n");
2336         matched = 0;
2337       }
2338       if(!pct) {
2339         DFPRINTF((stderr," end of rule\n"));
2340       }
2341     }
2342 
2343     if(matched && pcin) {
2344 
2345       /* So far we matched the rule up to the point of the conditions .
2346        * In other words, all of the opcodes match. Now we need to see
2347        * if the post conditions are satisfied.
2348        * First we check the 'postFalseCond'. This means that we check
2349        * to see if any of the subsequent pCode's in the pCode chain
2350        * following the point just past where we have matched depend on
2351        * the `postFalseCond' as input then we abort the match
2352        */
2353       DFPRINTF((stderr,"    matched rule so far, now checking conditions\n"));
2354       //pcin->print(stderr,pcin);
2355 
2356       if (pcin && peepBlock->postFalseCond &&
2357           (pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
2358         matched = 0;
2359 
2360 //      fprintf(stderr," condition results = %d\n",pic16_pCodeSearchCondition(pcin,peepBlock->postFalseCond));
2361 
2362 
2363       //if(!matched) fprintf(stderr,"failed on conditions\n");
2364     }
2365 
2366     if(matched) {
2367 
2368       pCode *pcprev;
2369 //      pCode *pcr;
2370 
2371 
2372       /* We matched a rule! Now we have to go through and remove the
2373          inefficient code with the optimized version */
2374 #ifdef PCODE_DEBUG
2375       DFPRINTF((stderr, "Found a pcode peep match:\nRule:\n"));
2376 //      printpCodeString(stderr,peepBlock->target.pb->pcHead,10);
2377       DFPRINTF((stderr,"first thing matched\n"));
2378       pc->print(stderr,pc);
2379       if(pcin) {
2380         DFPRINTF((stderr,"last thing matched\n"));
2381         pcin->print(stderr,pcin);
2382       }
2383 #endif
2384 
2385 
2386       /* Unlink the original code */
2387       pcprev = pc->prev;
2388       pcprev->next = pcin;
2389       if(pcin)
2390         pcin->prev = pc->prev;
2391 
2392 
2393 #if 1
2394       {
2395         /*     DEBUG    */
2396         /* Converted the deleted pCodes into comments */
2397 
2398         char buf[1024];
2399         pCodeCSource *pc_cline2=NULL;
2400 
2401 //      buf[0] = ';';
2402         buf[0] = '#';
2403 
2404         while(pc &&  pc!=pcin) {
2405 
2406           if(pc->type == PC_OPCODE && PCI(pc)->cline) {
2407             if(pc_cline) {
2408               pc_cline2->pc.next = PCODE(PCI(pc)->cline);
2409               pc_cline2 = PCCS(pc_cline2->pc.next);
2410             } else {
2411               pc_cline = pc_cline2 = PCI(pc)->cline;
2412               pc_cline->pc.seq = pc->seq;
2413             }
2414           }
2415 
2416           pic16_pCode2str(&buf[1], sizeof( buf )-1, pc);
2417           pic16_pCodeInsertAfter(pcprev, pic16_newpCodeCharP(buf));
2418           pcprev = pcprev->next;
2419           pc = pc->next;
2420 
2421         }
2422         if(pc_cline2)
2423           pc_cline2->pc.next = NULL;
2424       }
2425 #endif
2426 
2427       if(pcin)
2428         pCodeDeleteChain(pc,pcin);
2429 
2430 //      fprintf(stderr, "%s:%d rule matched\n", __FILE__, __LINE__);
2431 
2432       /* Generate the replacement code */
2433       pc = pcprev;
2434       pcr = peepBlock->replace.pb->pcHead;  // This is the replacement code
2435       while (pcr) {
2436         pCodeOp *pcop=NULL;
2437 
2438         /* If the replace pcode is an instruction with an operand, */
2439         /* then duplicate the operand (and expand wild cards in the process). */
2440         if(pcr->type == PC_OPCODE) {
2441           if(PCI(pcr)->pcop) {
2442             /* The replacing instruction has an operand.
2443              * Is it wild? */
2444             if(PCI(pcr)->pcop->type == PO_WILD) {
2445               int index = PCOW(PCI(pcr)->pcop)->id;
2446 //              fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
2447               //DFPRINTF((stderr,"copying wildopcode\n"));
2448               if(peepBlock->target.wildpCodeOps[index])
2449                 pcop = pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]);
2450               else
2451                 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2452             } else
2453               pcop = pic16_pCodeOpCopy(PCI(pcr)->pcop);
2454           }
2455 
2456           if(PCI(pcr)->is2MemOp && PCOP2(PCI(pcr)->pcop)->pcopR) {
2457             /* The replacing instruction has also a second operand.
2458              * Is it wild? */
2459 //              fprintf(stderr, "%s:%d pcop2= %p\n", __FILE__, __LINE__, PCOR2(PCI(pcr)->pcop)->pcop2);
2460             if(PCOP2(PCI(pcr)->pcop)->pcopR->type == PO_WILD) {
2461               int index = PCOW2(PCI(pcr)->pcop)->id;
2462 //              fprintf(stderr, "%s:%d replacing index= %d\n", __FUNCTION__, __LINE__, index);
2463               //DFPRINTF((stderr,"copying wildopcode\n"));
2464               if(peepBlock->target.wildpCodeOps[index])
2465                 pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
2466                         pic16_pCodeOpCopy(peepBlock->target.wildpCodeOps[index]), 0);
2467               else
2468                 DFPRINTF((stderr,"error, wildopcode in replace but not source?\n"));
2469             } else
2470               pcop = pic16_popCombine2(pic16_pCodeOpCopy(pcop),
2471                 pic16_pCodeOpCopy(PCOP2(PCI(pcr)->pcop)->pcopR), 0);
2472 
2473           }
2474 
2475           //DFPRINTF((stderr,"inserting pCode\n"));
2476           pic16_pCodeInsertAfter(pc, pic16_newpCode(PCI(pcr)->op,pcop));
2477         } else if (pcr->type == PC_WILD) {
2478           if(PCW(pcr)->invertBitSkipInst)
2479             DFPRINTF((stderr,"We need to invert the bit skip instruction\n"));
2480           pic16_pCodeInsertAfter(pc,
2481                            pCodeInstructionCopy(PCI(peepBlock->target.wildpCodes[PCW(pcr)->id]),
2482                                                 PCW(pcr)->invertBitSkipInst));
2483         } else if (pcr->type == PC_COMMENT) {
2484           pic16_pCodeInsertAfter(pc, pic16_newpCodeCharP( ((pCodeComment *)(pcr))->comment));
2485         }
2486 
2487 
2488         pc = pc->next;
2489 #ifdef PCODE_DEBUG
2490         DFPRINTF((stderr,"  NEW Code:"));
2491         if(pc) pc->print(stderr,pc);
2492 #endif
2493         pcr = pcr->next;
2494       }
2495 
2496       /* We have just replaced the inefficient code with the rule.
2497        * Now, we need to re-add the C-source symbols if there are any */
2498       pc = pcprev;
2499       while(pc_cline ) {
2500 
2501         pc =  pic16_findNextInstruction(pc->next);
2502         PCI(pc)->cline = pc_cline;
2503         pc_cline = PCCS(pc_cline->pc.next);
2504 
2505       }
2506 
2507       return 1;
2508     }
2509   next_rule:
2510     peeprules = peeprules->next;
2511   }
2512   DFPRINTF((stderr," no rule matched\n"));
2513 
2514   return 0;
2515 }
2516