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(<okIdx, 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(<okIdx, 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, ¤tRule->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, ¤tRule->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(¤tRule->target);
1584 postinit_pCodeWildBlock(¤tRule->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