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