1 /*-------------------------------------------------------------------------
2
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
20
21 #include "device.h"
22 #include "gen.h"
23 #include "pcode.h"
24 #include "pcodeflow.h"
25 #include "ralloc.h"
26
27 #define ASSERT(x) assert(x)
28
29 /****************************************************************/
30 /****************************************************************/
31
32 // Eventually this will go into device dependent files:
33 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
34 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
35 pCodeOpReg pc_fsr0l = {{PO_FSR, "FSR0L"}, -1, NULL,0,NULL};
36 pCodeOpReg pc_fsr0h = {{PO_FSR, "FSR0H"}, -1, NULL,0,NULL};
37 pCodeOpReg pc_indf_ = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
38 pCodeOpReg pc_indf0 = {{PO_INDF, "INDF0"}, -1, NULL,0,NULL};
39 pCodeOpReg pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
40 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
41 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
42
43 pCodeOpReg *pc_indf = &pc_indf_;
44
45 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
46 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
47 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
48
49 pFile *the_pFile = NULL;
50
51
52 #define SET_BANK_BIT (1 << 16)
53 #define CLR_BANK_BIT 0
54
55 static peepCommand peepCommands[] = {
56
57 {NOTBITSKIP, "_NOTBITSKIP_"},
58 {BITSKIP, "_BITSKIP_"},
59 {INVERTBITSKIP, "_INVERTBITSKIP_"},
60
61 {-1, NULL}
62 };
63
64 static int mnemonics_initialized = 0;
65
66 static hTab *pic14MnemonicsHash = NULL;
67 static hTab *pic14pCodePeepCommandsHash = NULL;
68
69 static pBlock *pb_dead_pcodes = NULL;
70
71 /* Hardcoded flags to change the behavior of the PIC port */
72 static int functionInlining = 1; /* inline functions if nonzero */
73
74 // static int GpCodeSequenceNumber = 1;
75 static int GpcFlowSeq = 1;
76
77 /* statistics (code size estimation) */
78 static unsigned int pcode_insns = 0;
79 static unsigned int pcode_doubles = 0;
80
81 static unsigned peakIdx = 0; /* This keeps track of the peak register index for call tree register reuse */
82
83
84 /****************************************************************/
85 /* Forward declarations */
86 /****************************************************************/
87
88 static void genericDestruct(pCode *pc);
89 static void genericPrint(FILE *of,pCode *pc);
90
91 static void pBlockStats(FILE *of, pBlock *pb);
92 static pCode *findFunction(const char *fname);
93 static void pCodePrintLabel(FILE *of, pCode *pc);
94 static void pCodePrintFunction(FILE *of, pCode *pc);
95 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
96 static char *get_op_from_instruction( pCodeInstruction *pcc);
97 static pBlock *newpBlock(void);
98
99
100 /****************************************************************/
101 /* PIC Instructions */
102 /****************************************************************/
103
104 static pCodeInstruction pciADDWF = {
105 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
106 genericDestruct,
107 genericPrint},
108 POC_ADDWF,
109 "ADDWF",
110 NULL, // from branch
111 NULL, // to branch
112 NULL, // label
113 NULL, // operand
114 NULL, // flow block
115 NULL, // C source
116 2, // num ops
117 TRUE, // dest
118 FALSE, // bit instruction
119 FALSE, // branch
120 FALSE, // skip
121 FALSE, // literal operand
122 POC_NOP,
123 (PCC_W | PCC_REGISTER), // inCond
124 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
125 };
126
127 static pCodeInstruction pciADDFW = {
128 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
129 genericDestruct,
130 genericPrint},
131 POC_ADDFW,
132 "ADDWF",
133 NULL, // from branch
134 NULL, // to branch
135 NULL, // label
136 NULL, // operand
137 NULL, // flow block
138 NULL, // C source
139 2, // num ops
140 FALSE, // dest
141 FALSE, // bit instruction
142 FALSE, // branch
143 FALSE, // skip
144 FALSE, // literal operand
145 POC_NOP,
146 (PCC_W | PCC_REGISTER), // inCond
147 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
148 };
149
150 static pCodeInstruction pciADDLW = {
151 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
152 genericDestruct,
153 genericPrint},
154 POC_ADDLW,
155 "ADDLW",
156 NULL, // from branch
157 NULL, // to branch
158 NULL, // label
159 NULL, // operand
160 NULL, // flow block
161 NULL, // C source
162 1, // num ops
163 FALSE, // dest
164 FALSE, // bit instruction
165 FALSE, // branch
166 FALSE, // skip
167 TRUE, // literal operand
168 POC_NOP,
169 (PCC_W | PCC_LITERAL), // inCond
170 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
171 };
172
173 static pCodeInstruction pciANDLW = {
174 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
175 genericDestruct,
176 genericPrint},
177 POC_ANDLW,
178 "ANDLW",
179 NULL, // from branch
180 NULL, // to branch
181 NULL, // label
182 NULL, // operand
183 NULL, // flow block
184 NULL, // C source
185 1, // num ops
186 FALSE, // dest
187 FALSE, // bit instruction
188 FALSE, // branch
189 FALSE, // skip
190 TRUE, // literal operand
191 POC_NOP,
192 (PCC_W | PCC_LITERAL), // inCond
193 (PCC_W | PCC_Z) // outCond
194 };
195
196 static pCodeInstruction pciANDWF = {
197 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
198 genericDestruct,
199 genericPrint},
200 POC_ANDWF,
201 "ANDWF",
202 NULL, // from branch
203 NULL, // to branch
204 NULL, // label
205 NULL, // operand
206 NULL, // flow block
207 NULL, // C source
208 2, // num ops
209 TRUE, // dest
210 FALSE, // bit instruction
211 FALSE, // branch
212 FALSE, // skip
213 FALSE, // literal operand
214 POC_NOP,
215 (PCC_W | PCC_REGISTER), // inCond
216 (PCC_REGISTER | PCC_Z) // outCond
217 };
218
219 static pCodeInstruction pciANDFW = {
220 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
221 genericDestruct,
222 genericPrint},
223 POC_ANDFW,
224 "ANDWF",
225 NULL, // from branch
226 NULL, // to branch
227 NULL, // label
228 NULL, // operand
229 NULL, // flow block
230 NULL, // C source
231 2, // num ops
232 FALSE, // dest
233 FALSE, // bit instruction
234 FALSE, // branch
235 FALSE, // skip
236 FALSE, // literal operand
237 POC_NOP,
238 (PCC_W | PCC_REGISTER), // inCond
239 (PCC_W | PCC_Z) // outCond
240 };
241
242 static pCodeInstruction pciBCF = {
243 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
244 genericDestruct,
245 genericPrint},
246 POC_BCF,
247 "BCF",
248 NULL, // from branch
249 NULL, // to branch
250 NULL, // label
251 NULL, // operand
252 NULL, // flow block
253 NULL, // C source
254 2, // num ops
255 TRUE, // dest
256 TRUE, // bit instruction
257 FALSE, // branch
258 FALSE, // skip
259 FALSE, // literal operand
260 POC_BSF,
261 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
262 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
263 };
264
265 static pCodeInstruction pciBSF = {
266 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
267 genericDestruct,
268 genericPrint},
269 POC_BSF,
270 "BSF",
271 NULL, // from branch
272 NULL, // to branch
273 NULL, // label
274 NULL, // operand
275 NULL, // flow block
276 NULL, // C source
277 2, // num ops
278 TRUE, // dest
279 TRUE, // bit instruction
280 FALSE, // branch
281 FALSE, // skip
282 FALSE, // literal operand
283 POC_BCF,
284 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
285 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
286 };
287
288 static pCodeInstruction pciBTFSC = {
289 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
290 genericDestruct,
291 genericPrint},
292 POC_BTFSC,
293 "BTFSC",
294 NULL, // from branch
295 NULL, // to branch
296 NULL, // label
297 NULL, // operand
298 NULL, // flow block
299 NULL, // C source
300 2, // num ops
301 FALSE, // dest
302 TRUE, // bit instruction
303 TRUE, // branch
304 TRUE, // skip
305 FALSE, // literal operand
306 POC_BTFSS,
307 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
308 PCC_NONE // outCond
309 };
310
311 static pCodeInstruction pciBTFSS = {
312 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
313 genericDestruct,
314 genericPrint},
315 POC_BTFSS,
316 "BTFSS",
317 NULL, // from branch
318 NULL, // to branch
319 NULL, // label
320 NULL, // operand
321 NULL, // flow block
322 NULL, // C source
323 2, // num ops
324 FALSE, // dest
325 TRUE, // bit instruction
326 TRUE, // branch
327 TRUE, // skip
328 FALSE, // literal operand
329 POC_BTFSC,
330 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
331 PCC_NONE // outCond
332 };
333
334 static pCodeInstruction pciCALL = {
335 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
336 genericDestruct,
337 genericPrint},
338 POC_CALL,
339 "CALL",
340 NULL, // from branch
341 NULL, // to branch
342 NULL, // label
343 NULL, // operand
344 NULL, // flow block
345 NULL, // C source
346 1, // num ops
347 FALSE, // dest
348 FALSE, // bit instruction
349 TRUE, // branch
350 FALSE, // skip
351 FALSE, // literal operand
352 POC_NOP,
353 (PCC_NONE | PCC_W), // inCond, reads argument from WREG
354 (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond, flags are destroyed by called function
355 };
356
357 static pCodeInstruction pciCOMF = {
358 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
359 genericDestruct,
360 genericPrint},
361 POC_COMF,
362 "COMF",
363 NULL, // from branch
364 NULL, // to branch
365 NULL, // label
366 NULL, // operand
367 NULL, // flow block
368 NULL, // C source
369 2, // num ops
370 TRUE, // dest
371 FALSE, // bit instruction
372 FALSE, // branch
373 FALSE, // skip
374 FALSE, // literal operand
375 POC_NOP,
376 PCC_REGISTER, // inCond
377 (PCC_REGISTER | PCC_Z) // outCond
378 };
379
380 static pCodeInstruction pciCOMFW = {
381 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
382 genericDestruct,
383 genericPrint},
384 POC_COMFW,
385 "COMF",
386 NULL, // from branch
387 NULL, // to branch
388 NULL, // label
389 NULL, // operand
390 NULL, // flow block
391 NULL, // C source
392 2, // num ops
393 FALSE, // dest
394 FALSE, // bit instruction
395 FALSE, // branch
396 FALSE, // skip
397 FALSE, // literal operand
398 POC_NOP,
399 PCC_REGISTER, // inCond
400 (PCC_W | PCC_Z) // outCond
401 };
402
403 static pCodeInstruction pciCLRF = {
404 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
405 genericDestruct,
406 genericPrint},
407 POC_CLRF,
408 "CLRF",
409 NULL, // from branch
410 NULL, // to branch
411 NULL, // label
412 NULL, // operand
413 NULL, // flow block
414 NULL, // C source
415 1, // num ops
416 FALSE, // dest
417 FALSE, // bit instruction
418 FALSE, // branch
419 FALSE, // skip
420 FALSE, // literal operand
421 POC_NOP,
422 PCC_NONE, // inCond
423 PCC_REGISTER | PCC_Z // outCond
424 };
425
426 static pCodeInstruction pciCLRW = {
427 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
428 genericDestruct,
429 genericPrint},
430 POC_CLRW,
431 "CLRW",
432 NULL, // from branch
433 NULL, // to branch
434 NULL, // label
435 NULL, // operand
436 NULL, // flow block
437 NULL, // C source
438 0, // num ops
439 FALSE, // dest
440 FALSE, // bit instruction
441 FALSE, // branch
442 FALSE, // skip
443 FALSE, // literal operand
444 POC_NOP,
445 PCC_NONE, // inCond
446 (PCC_W | PCC_Z) // outCond
447 };
448
449 static pCodeInstruction pciCLRWDT = {
450 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
451 genericDestruct,
452 genericPrint},
453 POC_CLRWDT,
454 "CLRWDT",
455 NULL, // from branch
456 NULL, // to branch
457 NULL, // label
458 NULL, // operand
459 NULL, // flow block
460 NULL, // C source
461 0, // num ops
462 FALSE, // dest
463 FALSE, // bit instruction
464 FALSE, // branch
465 FALSE, // skip
466 FALSE, // literal operand
467 POC_NOP,
468 PCC_NONE, // inCond
469 PCC_NONE // outCond
470 };
471
472 static pCodeInstruction pciDECF = {
473 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
474 genericDestruct,
475 genericPrint},
476 POC_DECF,
477 "DECF",
478 NULL, // from branch
479 NULL, // to branch
480 NULL, // label
481 NULL, // operand
482 NULL, // flow block
483 NULL, // C source
484 2, // num ops
485 TRUE, // dest
486 FALSE, // bit instruction
487 FALSE, // branch
488 FALSE, // skip
489 FALSE, // literal operand
490 POC_NOP,
491 PCC_REGISTER, // inCond
492 (PCC_REGISTER | PCC_Z) // outCond
493 };
494
495 static pCodeInstruction pciDECFW = {
496 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
497 genericDestruct,
498 genericPrint},
499 POC_DECFW,
500 "DECF",
501 NULL, // from branch
502 NULL, // to branch
503 NULL, // label
504 NULL, // operand
505 NULL, // flow block
506 NULL, // C source
507 2, // num ops
508 FALSE, // dest
509 FALSE, // bit instruction
510 FALSE, // branch
511 FALSE, // skip
512 FALSE, // literal operand
513 POC_NOP,
514 PCC_REGISTER, // inCond
515 (PCC_W | PCC_Z) // outCond
516 };
517
518 static pCodeInstruction pciDECFSZ = {
519 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
520 genericDestruct,
521 genericPrint},
522 POC_DECFSZ,
523 "DECFSZ",
524 NULL, // from branch
525 NULL, // to branch
526 NULL, // label
527 NULL, // operand
528 NULL, // flow block
529 NULL, // C source
530 2, // num ops
531 TRUE, // dest
532 FALSE, // bit instruction
533 TRUE, // branch
534 TRUE, // skip
535 FALSE, // literal operand
536 POC_DECF, // followed by BTFSC STATUS, Z --> also kills STATUS
537 PCC_REGISTER, // inCond
538 (PCC_REGISTER | PCC_Z) // outCond
539 };
540
541 static pCodeInstruction pciDECFSZW = {
542 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
543 genericDestruct,
544 genericPrint},
545 POC_DECFSZW,
546 "DECFSZ",
547 NULL, // from branch
548 NULL, // to branch
549 NULL, // label
550 NULL, // operand
551 NULL, // flow block
552 NULL, // C source
553 2, // num ops
554 FALSE, // dest
555 FALSE, // bit instruction
556 TRUE, // branch
557 TRUE, // skip
558 FALSE, // literal operand
559 POC_DECFW, // followed by BTFSC STATUS, Z --> also kills STATUS
560 PCC_REGISTER, // inCond
561 (PCC_W | PCC_Z) // outCond
562 };
563
564 static pCodeInstruction pciGOTO = {
565 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
566 genericDestruct,
567 genericPrint},
568 POC_GOTO,
569 "GOTO",
570 NULL, // from branch
571 NULL, // to branch
572 NULL, // label
573 NULL, // operand
574 NULL, // flow block
575 NULL, // C source
576 1, // num ops
577 FALSE, // dest
578 FALSE, // bit instruction
579 TRUE, // branch
580 FALSE, // skip
581 FALSE, // literal operand
582 POC_NOP,
583 PCC_NONE, // inCond
584 PCC_NONE // outCond
585 };
586
587 static pCodeInstruction pciINCF = {
588 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
589 genericDestruct,
590 genericPrint},
591 POC_INCF,
592 "INCF",
593 NULL, // from branch
594 NULL, // to branch
595 NULL, // label
596 NULL, // operand
597 NULL, // flow block
598 NULL, // C source
599 2, // num ops
600 TRUE, // dest
601 FALSE, // bit instruction
602 FALSE, // branch
603 FALSE, // skip
604 FALSE, // literal operand
605 POC_NOP,
606 PCC_REGISTER, // inCond
607 (PCC_REGISTER | PCC_Z) // outCond
608 };
609
610 static pCodeInstruction pciINCFW = {
611 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
612 genericDestruct,
613 genericPrint},
614 POC_INCFW,
615 "INCF",
616 NULL, // from branch
617 NULL, // to branch
618 NULL, // label
619 NULL, // operand
620 NULL, // flow block
621 NULL, // C source
622 2, // num ops
623 FALSE, // dest
624 FALSE, // bit instruction
625 FALSE, // branch
626 FALSE, // skip
627 FALSE, // literal operand
628 POC_NOP,
629 PCC_REGISTER, // inCond
630 (PCC_W | PCC_Z) // outCond
631 };
632
633 static pCodeInstruction pciINCFSZ = {
634 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
635 genericDestruct,
636 genericPrint},
637 POC_INCFSZ,
638 "INCFSZ",
639 NULL, // from branch
640 NULL, // to branch
641 NULL, // label
642 NULL, // operand
643 NULL, // flow block
644 NULL, // C source
645 2, // num ops
646 TRUE, // dest
647 FALSE, // bit instruction
648 TRUE, // branch
649 TRUE, // skip
650 FALSE, // literal operand
651 POC_INCF, // followed by BTFSC STATUS, Z --> also kills STATUS
652 PCC_REGISTER, // inCond
653 (PCC_REGISTER | PCC_Z) // outCond
654 };
655
656 static pCodeInstruction pciINCFSZW = {
657 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
658 genericDestruct,
659 genericPrint},
660 POC_INCFSZW,
661 "INCFSZ",
662 NULL, // from branch
663 NULL, // to branch
664 NULL, // label
665 NULL, // operand
666 NULL, // flow block
667 NULL, // C source
668 2, // num ops
669 FALSE, // dest
670 FALSE, // bit instruction
671 TRUE, // branch
672 TRUE, // skip
673 FALSE, // literal operand
674 POC_INCFW, // followed by BTFSC STATUS, Z --> also kills STATUS
675 PCC_REGISTER, // inCond
676 (PCC_W | PCC_Z) // outCond
677 };
678
679 static pCodeInstruction pciIORWF = {
680 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
681 genericDestruct,
682 genericPrint},
683 POC_IORWF,
684 "IORWF",
685 NULL, // from branch
686 NULL, // to branch
687 NULL, // label
688 NULL, // operand
689 NULL, // flow block
690 NULL, // C source
691 2, // num ops
692 TRUE, // dest
693 FALSE, // bit instruction
694 FALSE, // branch
695 FALSE, // skip
696 FALSE, // literal operand
697 POC_NOP,
698 (PCC_W | PCC_REGISTER), // inCond
699 (PCC_REGISTER | PCC_Z) // outCond
700 };
701
702 static pCodeInstruction pciIORFW = {
703 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
704 genericDestruct,
705 genericPrint},
706 POC_IORFW,
707 "IORWF",
708 NULL, // from branch
709 NULL, // to branch
710 NULL, // label
711 NULL, // operand
712 NULL, // flow block
713 NULL, // C source
714 2, // num ops
715 FALSE, // dest
716 FALSE, // bit instruction
717 FALSE, // branch
718 FALSE, // skip
719 FALSE, // literal operand
720 POC_NOP,
721 (PCC_W | PCC_REGISTER), // inCond
722 (PCC_W | PCC_Z) // outCond
723 };
724
725 static pCodeInstruction pciIORLW = {
726 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
727 genericDestruct,
728 genericPrint},
729 POC_IORLW,
730 "IORLW",
731 NULL, // from branch
732 NULL, // to branch
733 NULL, // label
734 NULL, // operand
735 NULL, // flow block
736 NULL, // C source
737 1, // num ops
738 FALSE, // dest
739 FALSE, // bit instruction
740 FALSE, // branch
741 FALSE, // skip
742 TRUE, // literal operand
743 POC_NOP,
744 (PCC_W | PCC_LITERAL), // inCond
745 (PCC_W | PCC_Z) // outCond
746 };
747
748 static pCodeInstruction pciMOVF = {
749 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
750 genericDestruct,
751 genericPrint},
752 POC_MOVF,
753 "MOVF",
754 NULL, // from branch
755 NULL, // to branch
756 NULL, // label
757 NULL, // operand
758 NULL, // flow block
759 NULL, // C source
760 2, // num ops
761 TRUE, // dest
762 FALSE, // bit instruction
763 FALSE, // branch
764 FALSE, // skip
765 FALSE, // literal operand
766 POC_NOP,
767 PCC_REGISTER, // inCond
768 PCC_Z // outCond
769 };
770
771 static pCodeInstruction pciMOVFW = {
772 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
773 genericDestruct,
774 genericPrint},
775 POC_MOVFW,
776 "MOVF",
777 NULL, // from branch
778 NULL, // to branch
779 NULL, // label
780 NULL, // operand
781 NULL, // flow block
782 NULL, // C source
783 2, // num ops
784 FALSE, // dest
785 FALSE, // bit instruction
786 FALSE, // branch
787 FALSE, // skip
788 FALSE, // literal operand
789 POC_NOP,
790 PCC_REGISTER, // inCond
791 (PCC_W | PCC_Z) // outCond
792 };
793
794 static pCodeInstruction pciMOVWF = {
795 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
796 genericDestruct,
797 genericPrint},
798 POC_MOVWF,
799 "MOVWF",
800 NULL, // from branch
801 NULL, // to branch
802 NULL, // label
803 NULL, // operand
804 NULL, // flow block
805 NULL, // C source
806 1, // num ops
807 FALSE, // dest
808 FALSE, // bit instruction
809 FALSE, // branch
810 FALSE, // skip
811 FALSE, // literal operand
812 POC_NOP,
813 PCC_W, // inCond
814 PCC_REGISTER // outCond
815 };
816
817 static pCodeInstruction pciMOVLW = {
818 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
819 genericDestruct,
820 genericPrint},
821 POC_MOVLW,
822 "MOVLW",
823 NULL, // from branch
824 NULL, // to branch
825 NULL, // label
826 NULL, // operand
827 NULL, // flow block
828 NULL, // C source
829 1, // num ops
830 FALSE, // dest
831 FALSE, // bit instruction
832 FALSE, // branch
833 FALSE, // skip
834 TRUE, // literal operand
835 POC_NOP,
836 (PCC_NONE | PCC_LITERAL), // inCond
837 PCC_W // outCond
838 };
839
840 static pCodeInstruction pciNOP = {
841 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
842 genericDestruct,
843 genericPrint},
844 POC_NOP,
845 "NOP",
846 NULL, // from branch
847 NULL, // to branch
848 NULL, // label
849 NULL, // operand
850 NULL, // flow block
851 NULL, // C source
852 0, // num ops
853 FALSE, // dest
854 FALSE, // bit instruction
855 FALSE, // branch
856 FALSE, // skip
857 FALSE, // literal operand
858 POC_NOP,
859 PCC_NONE, // inCond
860 PCC_NONE // outCond
861 };
862
863 static pCodeInstruction pciRETFIE = {
864 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
865 genericDestruct,
866 genericPrint},
867 POC_RETFIE,
868 "RETFIE",
869 NULL, // from branch
870 NULL, // to branch
871 NULL, // label
872 NULL, // operand
873 NULL, // flow block
874 NULL, // C source
875 0, // num ops
876 FALSE, // dest
877 FALSE, // bit instruction
878 TRUE, // branch
879 FALSE, // skip
880 FALSE, // literal operand
881 POC_NOP,
882 PCC_NONE, // inCond
883 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond (not true... affects the GIE bit too), STATUS bit are retored
884 };
885
886 static pCodeInstruction pciRETLW = {
887 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
888 genericDestruct,
889 genericPrint},
890 POC_RETLW,
891 "RETLW",
892 NULL, // from branch
893 NULL, // to branch
894 NULL, // label
895 NULL, // operand
896 NULL, // flow block
897 NULL, // C source
898 1, // num ops
899 FALSE, // dest
900 FALSE, // bit instruction
901 TRUE, // branch
902 FALSE, // skip
903 TRUE, // literal operand
904 POC_NOP,
905 PCC_LITERAL, // inCond
906 (PCC_W| PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETLW
907 };
908
909 static pCodeInstruction pciRETURN = {
910 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
911 genericDestruct,
912 genericPrint},
913 POC_RETURN,
914 "RETURN",
915 NULL, // from branch
916 NULL, // to branch
917 NULL, // label
918 NULL, // operand
919 NULL, // flow block
920 NULL, // C source
921 0, // num ops
922 FALSE, // dest
923 FALSE, // bit instruction
924 TRUE, // branch
925 FALSE, // skip
926 FALSE, // literal operand
927 POC_NOP,
928 (PCC_NONE | PCC_W), // inCond, return value is possibly present in W
929 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETURN
930 };
931
932 static pCodeInstruction pciRLF = {
933 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
934 genericDestruct,
935 genericPrint},
936 POC_RLF,
937 "RLF",
938 NULL, // from branch
939 NULL, // to branch
940 NULL, // label
941 NULL, // operand
942 NULL, // flow block
943 NULL, // C source
944 2, // num ops
945 TRUE, // dest
946 FALSE, // bit instruction
947 FALSE, // branch
948 FALSE, // skip
949 FALSE, // literal operand
950 POC_NOP,
951 (PCC_C | PCC_REGISTER), // inCond
952 (PCC_REGISTER | PCC_C) // outCond
953 };
954
955 static pCodeInstruction pciRLFW = {
956 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
957 genericDestruct,
958 genericPrint},
959 POC_RLFW,
960 "RLF",
961 NULL, // from branch
962 NULL, // to branch
963 NULL, // label
964 NULL, // operand
965 NULL, // flow block
966 NULL, // C source
967 2, // num ops
968 FALSE, // dest
969 FALSE, // bit instruction
970 FALSE, // branch
971 FALSE, // skip
972 FALSE, // literal operand
973 POC_NOP,
974 (PCC_C | PCC_REGISTER), // inCond
975 (PCC_W | PCC_C) // outCond
976 };
977
978 static pCodeInstruction pciRRF = {
979 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
980 genericDestruct,
981 genericPrint},
982 POC_RRF,
983 "RRF",
984 NULL, // from branch
985 NULL, // to branch
986 NULL, // label
987 NULL, // operand
988 NULL, // flow block
989 NULL, // C source
990 2, // num ops
991 TRUE, // dest
992 FALSE, // bit instruction
993 FALSE, // branch
994 FALSE, // skip
995 FALSE, // literal operand
996 POC_NOP,
997 (PCC_C | PCC_REGISTER), // inCond
998 (PCC_REGISTER | PCC_C) // outCond
999 };
1000
1001 static pCodeInstruction pciRRFW = {
1002 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1003 genericDestruct,
1004 genericPrint},
1005 POC_RRFW,
1006 "RRF",
1007 NULL, // from branch
1008 NULL, // to branch
1009 NULL, // label
1010 NULL, // operand
1011 NULL, // flow block
1012 NULL, // C source
1013 2, // num ops
1014 FALSE, // dest
1015 FALSE, // bit instruction
1016 FALSE, // branch
1017 FALSE, // skip
1018 FALSE, // literal operand
1019 POC_NOP,
1020 (PCC_C | PCC_REGISTER), // inCond
1021 (PCC_W | PCC_C) // outCond
1022 };
1023
1024 static pCodeInstruction pciSUBWF = {
1025 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1026 genericDestruct,
1027 genericPrint},
1028 POC_SUBWF,
1029 "SUBWF",
1030 NULL, // from branch
1031 NULL, // to branch
1032 NULL, // label
1033 NULL, // operand
1034 NULL, // flow block
1035 NULL, // C source
1036 2, // num ops
1037 TRUE, // dest
1038 FALSE, // bit instruction
1039 FALSE, // branch
1040 FALSE, // skip
1041 FALSE, // literal operand
1042 POC_NOP,
1043 (PCC_W | PCC_REGISTER), // inCond
1044 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
1045 };
1046
1047 static pCodeInstruction pciSUBFW = {
1048 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1049 genericDestruct,
1050 genericPrint},
1051 POC_SUBFW,
1052 "SUBWF",
1053 NULL, // from branch
1054 NULL, // to branch
1055 NULL, // label
1056 NULL, // operand
1057 NULL, // flow block
1058 NULL, // C source
1059 2, // num ops
1060 FALSE, // dest
1061 FALSE, // bit instruction
1062 FALSE, // branch
1063 FALSE, // skip
1064 FALSE, // literal operand
1065 POC_NOP,
1066 (PCC_W | PCC_REGISTER), // inCond
1067 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
1068 };
1069
1070 static pCodeInstruction pciSUBLW = {
1071 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1072 genericDestruct,
1073 genericPrint},
1074 POC_SUBLW,
1075 "SUBLW",
1076 NULL, // from branch
1077 NULL, // to branch
1078 NULL, // label
1079 NULL, // operand
1080 NULL, // flow block
1081 NULL, // C source
1082 1, // num ops
1083 FALSE, // dest
1084 FALSE, // bit instruction
1085 FALSE, // branch
1086 FALSE, // skip
1087 TRUE, // literal operand
1088 POC_NOP,
1089 (PCC_W | PCC_LITERAL), // inCond
1090 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1091 };
1092
1093 static pCodeInstruction pciSWAPF = {
1094 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1095 genericDestruct,
1096 genericPrint},
1097 POC_SWAPF,
1098 "SWAPF",
1099 NULL, // from branch
1100 NULL, // to branch
1101 NULL, // label
1102 NULL, // operand
1103 NULL, // flow block
1104 NULL, // C source
1105 2, // num ops
1106 TRUE, // dest
1107 FALSE, // bit instruction
1108 FALSE, // branch
1109 FALSE, // skip
1110 FALSE, // literal operand
1111 POC_NOP,
1112 PCC_REGISTER, // inCond
1113 PCC_REGISTER // outCond
1114 };
1115
1116 static pCodeInstruction pciSWAPFW = {
1117 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1118 genericDestruct,
1119 genericPrint},
1120 POC_SWAPFW,
1121 "SWAPF",
1122 NULL, // from branch
1123 NULL, // to branch
1124 NULL, // label
1125 NULL, // operand
1126 NULL, // flow block
1127 NULL, // C source
1128 2, // num ops
1129 FALSE, // dest
1130 FALSE, // bit instruction
1131 FALSE, // branch
1132 FALSE, // skip
1133 FALSE, // literal operand
1134 POC_NOP,
1135 PCC_REGISTER, // inCond
1136 PCC_W // outCond
1137 };
1138
1139 static pCodeInstruction pciTRIS = {
1140 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1141 genericDestruct,
1142 genericPrint},
1143 POC_TRIS,
1144 "TRIS",
1145 NULL, // from branch
1146 NULL, // to branch
1147 NULL, // label
1148 NULL, // operand
1149 NULL, // flow block
1150 NULL, // C source
1151 1, // num ops
1152 FALSE, // dest
1153 FALSE, // bit instruction
1154 FALSE, // branch
1155 FALSE, // skip
1156 FALSE, // literal operand
1157 POC_NOP,
1158 PCC_NONE, // inCond /* FIXME: what's TRIS doing? */
1159 PCC_REGISTER // outCond /* FIXME: what's TRIS doing */
1160 };
1161
1162 static pCodeInstruction pciXORWF = {
1163 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1164 genericDestruct,
1165 genericPrint},
1166 POC_XORWF,
1167 "XORWF",
1168 NULL, // from branch
1169 NULL, // to branch
1170 NULL, // label
1171 NULL, // operand
1172 NULL, // flow block
1173 NULL, // C source
1174 2, // num ops
1175 TRUE, // dest
1176 FALSE, // bit instruction
1177 FALSE, // branch
1178 FALSE, // skip
1179 FALSE, // literal operand
1180 POC_NOP,
1181 (PCC_W | PCC_REGISTER), // inCond
1182 (PCC_REGISTER | PCC_Z) // outCond
1183 };
1184
1185 static pCodeInstruction pciXORFW = {
1186 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1187 genericDestruct,
1188 genericPrint},
1189 POC_XORFW,
1190 "XORWF",
1191 NULL, // from branch
1192 NULL, // to branch
1193 NULL, // label
1194 NULL, // operand
1195 NULL, // flow block
1196 NULL, // C source
1197 2, // num ops
1198 FALSE, // dest
1199 FALSE, // bit instruction
1200 FALSE, // branch
1201 FALSE, // skip
1202 FALSE, // literal operand
1203 POC_NOP,
1204 (PCC_W | PCC_REGISTER), // inCond
1205 (PCC_W | PCC_Z) // outCond
1206 };
1207
1208 static pCodeInstruction pciXORLW = {
1209 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1210 genericDestruct,
1211 genericPrint},
1212 POC_XORLW,
1213 "XORLW",
1214 NULL, // from branch
1215 NULL, // to branch
1216 NULL, // label
1217 NULL, // operand
1218 NULL, // flow block
1219 NULL, // C source
1220 1, // num ops
1221 FALSE, // dest
1222 FALSE, // bit instruction
1223 FALSE, // branch
1224 FALSE, // skip
1225 TRUE, // literal operand
1226 POC_NOP,
1227 (PCC_W | PCC_LITERAL), // inCond
1228 (PCC_W | PCC_Z) // outCond
1229 };
1230
1231
1232 static pCodeInstruction pciBANKSEL = {
1233 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1234 genericDestruct,
1235 genericPrint},
1236 POC_BANKSEL,
1237 "BANKSEL",
1238 NULL, // from branch
1239 NULL, // to branch
1240 NULL, // label
1241 NULL, // operand
1242 NULL, // flow block
1243 NULL, // C source
1244 1, // num ops
1245 FALSE, // dest
1246 FALSE, // bit instruction
1247 FALSE, // branch
1248 FALSE, // skip
1249 FALSE, // literal operand
1250 POC_NOP,
1251 PCC_NONE, // inCond
1252 PCC_NONE // outCond
1253 };
1254
1255 static pCodeInstruction pciPAGESEL = {
1256 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1257 genericDestruct,
1258 genericPrint},
1259 POC_PAGESEL,
1260 "PAGESEL",
1261 NULL, // from branch
1262 NULL, // to branch
1263 NULL, // label
1264 NULL, // operand
1265 NULL, // flow block
1266 NULL, // C source
1267 1, // num ops
1268 FALSE, // dest
1269 FALSE, // bit instruction
1270 FALSE, // branch
1271 FALSE, // skip
1272 FALSE, // literal operand
1273 POC_NOP,
1274 PCC_NONE, // inCond
1275 PCC_NONE // outCond
1276 };
1277
1278 /****************************************************************/
1279 /* PIC Enhanced Instructions */
1280 /****************************************************************/
1281
1282 static pCodeInstruction pciADDFSR = {
1283 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1284 genericDestruct,
1285 genericPrint},
1286 POC_ADDFSR,
1287 "ADDFSR",
1288 NULL, // from branch
1289 NULL, // to branch
1290 NULL, // label
1291 NULL, // operand
1292 NULL, // flow block
1293 NULL, // C source
1294 2, // num ops
1295 FALSE, // dest
1296 FALSE, // bit instruction
1297 FALSE, // branch
1298 FALSE, // skip
1299 TRUE, // literal operand
1300 POC_NOP,
1301 PCC_NONE, // inCond
1302 PCC_NONE // outCond
1303 };
1304
1305 static pCodeInstruction pciADDWFC = {
1306 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1307 genericDestruct,
1308 genericPrint},
1309 POC_ADDWFC,
1310 "ADDWFC",
1311 NULL, // from branch
1312 NULL, // to branch
1313 NULL, // label
1314 NULL, // operand
1315 NULL, // flow block
1316 NULL, // C source
1317 2, // num ops
1318 TRUE, // dest
1319 FALSE, // bit instruction
1320 FALSE, // branch
1321 FALSE, // skip
1322 FALSE, // literal operand
1323 POC_NOP,
1324 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1325 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
1326 };
1327
1328 static pCodeInstruction pciADDFWC = {
1329 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1330 genericDestruct,
1331 genericPrint},
1332 POC_ADDFWC,
1333 "ADDWFC",
1334 NULL, // from branch
1335 NULL, // to branch
1336 NULL, // label
1337 NULL, // operand
1338 NULL, // flow block
1339 NULL, // C source
1340 2, // num ops
1341 FALSE, // dest
1342 FALSE, // bit instruction
1343 FALSE, // branch
1344 FALSE, // skip
1345 FALSE, // literal operand
1346 POC_NOP,
1347 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1348 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
1349 };
1350
1351 static pCodeInstruction pciASRF = {
1352 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1353 genericDestruct,
1354 genericPrint},
1355 POC_ASRF,
1356 "ASRF",
1357 NULL, // from branch
1358 NULL, // to branch
1359 NULL, // label
1360 NULL, // operand
1361 NULL, // flow block
1362 NULL, // C source
1363 2, // num ops
1364 TRUE, // dest
1365 FALSE, // bit instruction
1366 FALSE, // branch
1367 FALSE, // skip
1368 FALSE, // literal operand
1369 POC_NOP,
1370 PCC_REGISTER, // inCond
1371 (PCC_REGISTER | PCC_C | PCC_Z) // outCond
1372 };
1373
1374 static pCodeInstruction pciASRFW = {
1375 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1376 genericDestruct,
1377 genericPrint},
1378 POC_ASRFW,
1379 "ASRF",
1380 NULL, // from branch
1381 NULL, // to branch
1382 NULL, // label
1383 NULL, // operand
1384 NULL, // flow block
1385 NULL, // C source
1386 2, // num ops
1387 FALSE, // dest
1388 FALSE, // bit instruction
1389 FALSE, // branch
1390 FALSE, // skip
1391 FALSE, // literal operand
1392 POC_NOP,
1393 PCC_REGISTER, // inCond
1394 (PCC_W | PCC_C | PCC_Z) // outCond
1395 };
1396
1397 static pCodeInstruction pciBRA = {
1398 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1399 genericDestruct,
1400 genericPrint},
1401 POC_BRA,
1402 "BRA",
1403 NULL, // from branch
1404 NULL, // to branch
1405 NULL, // label
1406 NULL, // operand
1407 NULL, // flow block
1408 NULL, // C source
1409 1, // num ops
1410 FALSE, // dest
1411 FALSE, // bit instruction
1412 TRUE, // branch
1413 FALSE, // skip
1414 FALSE, // literal operand
1415 POC_NOP,
1416 PCC_NONE, // inCond
1417 PCC_NONE // outCond
1418 };
1419
1420 static pCodeInstruction pciBRW = {
1421 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1422 genericDestruct,
1423 genericPrint},
1424 POC_BRW,
1425 "BRW",
1426 NULL, // from branch
1427 NULL, // to branch
1428 NULL, // label
1429 NULL, // operand
1430 NULL, // flow block
1431 NULL, // C source
1432 0, // num ops
1433 FALSE, // dest
1434 FALSE, // bit instruction
1435 TRUE, // branch
1436 FALSE, // skip
1437 FALSE, // literal operand
1438 POC_NOP,
1439 (PCC_NONE | PCC_W), // inCond
1440 PCC_NONE // outCond
1441 };
1442
1443 static pCodeInstruction pciCALLW = {
1444 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1445 genericDestruct,
1446 genericPrint},
1447 POC_CALLW,
1448 "CALLW",
1449 NULL, // from branch
1450 NULL, // to branch
1451 NULL, // label
1452 NULL, // operand
1453 NULL, // flow block
1454 NULL, // C source
1455 0, // num ops
1456 FALSE, // dest
1457 FALSE, // bit instruction
1458 TRUE, // branch
1459 FALSE, // skip
1460 FALSE, // literal operand
1461 POC_NOP,
1462 (PCC_NONE | PCC_W), // inCond, reads lower bits of subroutine address from WREG
1463 (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond, flags are destroyed by called function
1464 };
1465
1466 static pCodeInstruction pciLSLF = {
1467 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1468 genericDestruct,
1469 genericPrint},
1470 POC_LSLF,
1471 "LSLF",
1472 NULL, // from branch
1473 NULL, // to branch
1474 NULL, // label
1475 NULL, // operand
1476 NULL, // flow block
1477 NULL, // C source
1478 2, // num ops
1479 TRUE, // dest
1480 FALSE, // bit instruction
1481 FALSE, // branch
1482 FALSE, // skip
1483 FALSE, // literal operand
1484 POC_NOP,
1485 PCC_REGISTER, // inCond
1486 (PCC_REGISTER | PCC_C | PCC_Z) // outCond
1487 };
1488
1489 static pCodeInstruction pciLSLFW = {
1490 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1491 genericDestruct,
1492 genericPrint},
1493 POC_LSLFW,
1494 "LSLF",
1495 NULL, // from branch
1496 NULL, // to branch
1497 NULL, // label
1498 NULL, // operand
1499 NULL, // flow block
1500 NULL, // C source
1501 2, // num ops
1502 FALSE, // dest
1503 FALSE, // bit instruction
1504 FALSE, // branch
1505 FALSE, // skip
1506 FALSE, // literal operand
1507 POC_NOP,
1508 PCC_REGISTER, // inCond
1509 (PCC_W | PCC_C | PCC_Z) // outCond
1510 };
1511
1512 static pCodeInstruction pciLSRF = {
1513 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1514 genericDestruct,
1515 genericPrint},
1516 POC_LSRF,
1517 "LSRF",
1518 NULL, // from branch
1519 NULL, // to branch
1520 NULL, // label
1521 NULL, // operand
1522 NULL, // flow block
1523 NULL, // C source
1524 2, // num ops
1525 TRUE, // dest
1526 FALSE, // bit instruction
1527 FALSE, // branch
1528 FALSE, // skip
1529 FALSE, // literal operand
1530 POC_NOP,
1531 PCC_REGISTER, // inCond
1532 (PCC_REGISTER | PCC_C | PCC_Z) // outCond
1533 };
1534
1535 static pCodeInstruction pciLSRFW = {
1536 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1537 genericDestruct,
1538 genericPrint},
1539 POC_LSRFW,
1540 "LSRF",
1541 NULL, // from branch
1542 NULL, // to branch
1543 NULL, // label
1544 NULL, // operand
1545 NULL, // flow block
1546 NULL, // C source
1547 2, // num ops
1548 FALSE, // dest
1549 FALSE, // bit instruction
1550 FALSE, // branch
1551 FALSE, // skip
1552 FALSE, // literal operand
1553 POC_NOP,
1554 PCC_REGISTER, // inCond
1555 (PCC_W | PCC_C | PCC_Z) // outCond
1556 };
1557
1558 static pCodeInstruction pciMOVIW = {
1559 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1560 genericDestruct,
1561 genericPrint},
1562 POC_MOVIW,
1563 "MOVIW",
1564 NULL, // from branch
1565 NULL, // to branch
1566 NULL, // label
1567 NULL, // operand
1568 NULL, // flow block
1569 NULL, // C source
1570 1, // num ops
1571 FALSE, // dest
1572 FALSE, // bit instruction
1573 FALSE, // branch
1574 FALSE, // skip
1575 TRUE, // literal operand
1576 POC_NOP,
1577 PCC_NONE, // inCond
1578 (PCC_NONE | PCC_W | PCC_Z) // outCond
1579 };
1580
1581 static pCodeInstruction pciMOVIW_K = {
1582 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1583 genericDestruct,
1584 genericPrint},
1585 POC_MOVIW_K,
1586 "MOVIW",
1587 NULL, // from branch
1588 NULL, // to branch
1589 NULL, // label
1590 NULL, // operand
1591 NULL, // flow block
1592 NULL, // C source
1593 2, // num ops
1594 FALSE, // dest
1595 FALSE, // bit instruction
1596 FALSE, // branch
1597 FALSE, // skip
1598 TRUE, // literal operand
1599 POC_NOP,
1600 PCC_NONE, // inCond
1601 (PCC_NONE | PCC_W | PCC_Z) // outCond
1602 };
1603
1604 static pCodeInstruction pciMOVLB = {
1605 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1606 genericDestruct,
1607 genericPrint},
1608 POC_MOVLB,
1609 "MOVLB",
1610 NULL, // from branch
1611 NULL, // to branch
1612 NULL, // label
1613 NULL, // operand
1614 NULL, // flow block
1615 NULL, // C source
1616 1, // num ops
1617 FALSE, // dest
1618 FALSE, // bit instruction
1619 FALSE, // branch
1620 FALSE, // skip
1621 TRUE, // literal operand
1622 POC_NOP,
1623 PCC_NONE, // inCond
1624 PCC_NONE // outCond
1625 };
1626
1627 static pCodeInstruction pciMOVLP = {
1628 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1629 genericDestruct,
1630 genericPrint},
1631 POC_MOVLP,
1632 "MOVLP",
1633 NULL, // from branch
1634 NULL, // to branch
1635 NULL, // label
1636 NULL, // operand
1637 NULL, // flow block
1638 NULL, // C source
1639 1, // num ops
1640 FALSE, // dest
1641 FALSE, // bit instruction
1642 FALSE, // branch
1643 FALSE, // skip
1644 TRUE, // literal operand
1645 POC_NOP,
1646 PCC_NONE, // inCond
1647 PCC_NONE // outCond
1648 };
1649
1650 static pCodeInstruction pciMOVWI = {
1651 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1652 genericDestruct,
1653 genericPrint},
1654 POC_MOVWI,
1655 "MOVWI",
1656 NULL, // from branch
1657 NULL, // to branch
1658 NULL, // label
1659 NULL, // operand
1660 NULL, // flow block
1661 NULL, // C source
1662 1, // num ops
1663 FALSE, // dest
1664 FALSE, // bit instruction
1665 FALSE, // branch
1666 FALSE, // skip
1667 TRUE, // literal operand
1668 POC_NOP,
1669 (PCC_NONE | PCC_W), // inCond
1670 PCC_NONE // outCond
1671 };
1672
1673 static pCodeInstruction pciMOVWI_K = {
1674 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1675 genericDestruct,
1676 genericPrint},
1677 POC_MOVWI_K,
1678 "MOVWI",
1679 NULL, // from branch
1680 NULL, // to branch
1681 NULL, // label
1682 NULL, // operand
1683 NULL, // flow block
1684 NULL, // C source
1685 2, // num ops
1686 FALSE, // dest
1687 FALSE, // bit instruction
1688 FALSE, // branch
1689 FALSE, // skip
1690 TRUE, // literal operand
1691 POC_NOP,
1692 (PCC_NONE | PCC_W), // inCond
1693 PCC_NONE // outCond
1694 };
1695
1696 static pCodeInstruction pciRESET = {
1697 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1698 genericDestruct,
1699 genericPrint},
1700 POC_RESET,
1701 "RESET",
1702 NULL, // from branch
1703 NULL, // to branch
1704 NULL, // label
1705 NULL, // operand
1706 NULL, // flow block
1707 NULL, // C source
1708 0, // num ops
1709 FALSE, // dest
1710 FALSE, // bit instruction
1711 FALSE, // branch
1712 FALSE, // skip
1713 FALSE, // literal operand
1714 POC_NOP,
1715 PCC_NONE, // inCond
1716 PCC_NONE // outCond
1717 };
1718
1719 static pCodeInstruction pciSUBWFB = {
1720 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1721 genericDestruct,
1722 genericPrint},
1723 POC_SUBWFB,
1724 "SUBWFB",
1725 NULL, // from branch
1726 NULL, // to branch
1727 NULL, // label
1728 NULL, // operand
1729 NULL, // flow block
1730 NULL, // C source
1731 2, // num ops
1732 TRUE, // dest
1733 FALSE, // bit instruction
1734 FALSE, // branch
1735 FALSE, // skip
1736 FALSE, // literal operand
1737 POC_NOP,
1738 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1739 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
1740 };
1741
1742 static pCodeInstruction pciSUBWFBW = {
1743 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1744 genericDestruct,
1745 genericPrint},
1746 POC_SUBWFBW,
1747 "SUBWFB",
1748 NULL, // from branch
1749 NULL, // to branch
1750 NULL, // label
1751 NULL, // operand
1752 NULL, // flow block
1753 NULL, // C source
1754 2, // num ops
1755 FALSE, // dest
1756 FALSE, // bit instruction
1757 FALSE, // branch
1758 FALSE, // skip
1759 FALSE, // literal operand
1760 POC_NOP,
1761 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1762 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
1763 };
1764
1765 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1766
1767
1768 /*-----------------------------------------------------------------*/
1769 /* return a unique ID number to assist pCodes debuging */
1770 /*-----------------------------------------------------------------*/
PCodeID(void)1771 static unsigned PCodeID(void) {
1772 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1773 /*
1774 static unsigned int stop;
1775 if (pcodeId == 1448)
1776 stop++; // Place break point here
1777 */
1778 return pcodeId++;
1779 }
1780
pCodeInitRegisters(void)1781 void pCodeInitRegisters(void)
1782 {
1783 static int initialized=0;
1784 int shareBankAddress, stkSize, haveShared;
1785 PIC_device *pic;
1786
1787 if(initialized)
1788 return;
1789 initialized = 1;
1790
1791 pic = init_pic(port->processor);
1792 haveShared = pic14_getSharedStack(NULL, &shareBankAddress, &stkSize);
1793 /* Set pseudo stack size to SHAREBANKSIZE - 3.
1794 * On multi memory bank ICs this leaves room for WSAVE/SSAVE/PSAVE
1795 * (used for interrupts) to fit into the shared portion of the
1796 * memory bank. This is not needed on enhanced processors. */
1797 if (!pic->isEnhancedCore)
1798 stkSize = stkSize - 3;
1799 assert(stkSize >= 0);
1800 initStack(shareBankAddress, stkSize, haveShared);
1801
1802 /* TODO: Read aliases for SFRs from regmap lines in device description. */
1803 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0xf80);
1804 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0xf80);
1805 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0xf80);
1806 pc_indf_.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0xf80);
1807 pc_indf0.r = allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF, 0xf80);
1808 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0xf80);
1809 pc_fsr0l.r = allocProcessorRegister(IDX_FSR0L,"FSR0L", PO_FSR, 0xf80);
1810 pc_fsr0h.r = allocProcessorRegister(IDX_FSR0H,"FSR0H", PO_FSR, 0xf80);
1811 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0xf80);
1812
1813 pc_status.rIdx = IDX_STATUS;
1814 pc_fsr.rIdx = IDX_FSR;
1815 pc_fsr0l.rIdx = IDX_FSR0L;
1816 pc_fsr0h.rIdx = IDX_FSR0H;
1817 pc_indf_.rIdx = IDX_INDF;
1818 pc_indf0.rIdx = IDX_INDF0;
1819 pc_intcon.rIdx = IDX_INTCON;
1820 pc_pcl.rIdx = IDX_PCL;
1821 pc_pclath.rIdx = IDX_PCLATH;
1822
1823 if (!pic->isEnhancedCore) {
1824 /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1825 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, pic ? pic->bankMask : 0xf80);
1826 /* Interrupt storage for status register. */
1827 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1828 /* Interrupt storage for pclath register. */
1829 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1830
1831 pc_wsave.rIdx = pc_wsave.r->rIdx;
1832 pc_ssave.rIdx = pc_ssave.r->rIdx;
1833 pc_psave.rIdx = pc_psave.r->rIdx;
1834
1835 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1836 pc_wsave.r->address = shareBankAddress-stkSize;
1837 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1838 pc_ssave.r->address = shareBankAddress-stkSize-1;
1839 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1840 pc_psave.r->address = shareBankAddress-stkSize-2;
1841 }
1842
1843 /* probably should put this in a separate initialization routine */
1844 pb_dead_pcodes = newpBlock();
1845
1846 }
1847
1848 /*-----------------------------------------------------------------*/
1849 /* mnem2key - convert a pic mnemonic into a hash key */
1850 /* (BTW - this spreads the mnemonics quite well) */
1851 /* */
1852 /*-----------------------------------------------------------------*/
1853
mnem2key(unsigned char const * mnem)1854 static int mnem2key(unsigned char const *mnem)
1855 {
1856 int key = 0;
1857
1858 if(!mnem)
1859 return 0;
1860
1861 while(*mnem) {
1862
1863 key += toupper(*mnem++) +1;
1864
1865 }
1866
1867 return (key & 0x1f);
1868
1869 }
1870
pic14initMnemonics(void)1871 static void pic14initMnemonics(void)
1872 {
1873 int i = 0;
1874 int key;
1875 // char *str;
1876 pCodeInstruction *pci;
1877
1878 if(mnemonics_initialized)
1879 return;
1880
1881 //FIXME - probably should NULL out the array before making the assignments
1882 //since we check the array contents below this initialization.
1883
1884 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1885 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1886 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1887 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1888 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1889 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1890 pic14Mnemonics[POC_BCF] = &pciBCF;
1891 pic14Mnemonics[POC_BSF] = &pciBSF;
1892 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1893 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1894 pic14Mnemonics[POC_CALL] = &pciCALL;
1895 pic14Mnemonics[POC_COMF] = &pciCOMF;
1896 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1897 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1898 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1899 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1900 pic14Mnemonics[POC_DECF] = &pciDECF;
1901 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1902 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1903 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1904 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1905 pic14Mnemonics[POC_INCF] = &pciINCF;
1906 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1907 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1908 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1909 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1910 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1911 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1912 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1913 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1914 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1915 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1916 pic14Mnemonics[POC_NOP] = &pciNOP;
1917 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1918 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1919 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1920 pic14Mnemonics[POC_RLF] = &pciRLF;
1921 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1922 pic14Mnemonics[POC_RRF] = &pciRRF;
1923 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1924 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1925 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1926 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1927 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1928 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1929 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1930 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1931 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1932 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1933 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1934 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1935
1936 /* Enhanced instruction set. */
1937
1938 pic14Mnemonics[POC_ADDFSR] = &pciADDFSR;
1939 pic14Mnemonics[POC_ADDWFC] = &pciADDWFC;
1940 pic14Mnemonics[POC_ADDFWC] = &pciADDFWC;
1941 pic14Mnemonics[POC_ASRF] = &pciASRF;
1942 pic14Mnemonics[POC_ASRFW] = &pciASRFW;
1943 pic14Mnemonics[POC_BRA] = &pciBRA;
1944 pic14Mnemonics[POC_BRW] = &pciBRW;
1945 pic14Mnemonics[POC_CALLW] = &pciCALLW;
1946 pic14Mnemonics[POC_LSLF] = &pciLSLF;
1947 pic14Mnemonics[POC_LSLFW] = &pciLSLFW;
1948 pic14Mnemonics[POC_LSRF] = &pciLSRF;
1949 pic14Mnemonics[POC_LSRFW] = &pciLSRFW;
1950 pic14Mnemonics[POC_MOVIW] = &pciMOVIW;
1951 pic14Mnemonics[POC_MOVIW_K] = &pciMOVIW_K;
1952 pic14Mnemonics[POC_MOVLB] = &pciMOVLB;
1953 pic14Mnemonics[POC_MOVLP] = &pciMOVLP;
1954 pic14Mnemonics[POC_MOVWI] = &pciMOVWI;
1955 pic14Mnemonics[POC_MOVWI_K] = &pciMOVWI_K;
1956 pic14Mnemonics[POC_RESET] = &pciRESET;
1957 pic14Mnemonics[POC_SUBWFB] = &pciSUBWFB;
1958 pic14Mnemonics[POC_SUBWFBW] = &pciSUBWFBW;
1959
1960
1961 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1962 if(pic14Mnemonics[i])
1963 hTabAddItem(&pic14MnemonicsHash, mnem2key((unsigned char *)pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1964 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1965
1966 while(pci) {
1967 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1968 pci = hTabNextItem(pic14MnemonicsHash, &key);
1969 }
1970
1971 mnemonics_initialized = 1;
1972 }
1973
getpCode(const char * mnem,unsigned dest)1974 int getpCode(const char *mnem, unsigned dest)
1975 {
1976
1977 pCodeInstruction *pci;
1978 int key = mnem2key((const unsigned char *)mnem);
1979
1980 if(!mnemonics_initialized)
1981 pic14initMnemonics();
1982
1983 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1984
1985 while(pci) {
1986
1987 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1988 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1989 return(pci->op);
1990 }
1991
1992 pci = hTabNextItemWK (pic14MnemonicsHash);
1993
1994 }
1995
1996 return -1;
1997 }
1998
1999 /*-----------------------------------------------------------------*
2000 * pic14initpCodePeepCommands
2001 *
2002 *-----------------------------------------------------------------*/
pic14initpCodePeepCommands(void)2003 void pic14initpCodePeepCommands(void)
2004 {
2005
2006 int key, i;
2007 peepCommand *pcmd;
2008
2009 i = 0;
2010 do {
2011 hTabAddItem(&pic14pCodePeepCommandsHash,
2012 mnem2key((const unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
2013 i++;
2014 } while (peepCommands[i].cmd);
2015
2016 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
2017
2018 while(pcmd) {
2019 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
2020 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
2021 }
2022
2023 }
2024
2025 /*-----------------------------------------------------------------
2026 *
2027 *
2028 *-----------------------------------------------------------------*/
2029
getpCodePeepCommand(const char * cmd)2030 int getpCodePeepCommand(const char *cmd)
2031 {
2032
2033 peepCommand *pcmd;
2034 int key = mnem2key((const unsigned char *)cmd);
2035
2036
2037 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
2038
2039 while(pcmd) {
2040 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2041 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2042 return pcmd->id;
2043 }
2044
2045 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
2046
2047 }
2048
2049 return -1;
2050 }
2051
getpBlock_dbName(pBlock * pb)2052 static char getpBlock_dbName(pBlock *pb)
2053 {
2054 if(!pb)
2055 return 0;
2056
2057 if(pb->cmemmap)
2058 return pb->cmemmap->dbName;
2059
2060 return pb->dbName;
2061 }
2062
pBlockConvert2ISR(pBlock * pb)2063 void pBlockConvert2ISR(pBlock *pb)
2064 {
2065 if(!pb)
2066 return;
2067
2068 if(pb->cmemmap)
2069 pb->cmemmap = NULL;
2070
2071 pb->dbName = 'I';
2072 }
2073
2074 /*-----------------------------------------------------------------*/
2075 /* movepBlock2Head - given the dbname of a pBlock, move all */
2076 /* instances to the front of the doubly linked */
2077 /* list of pBlocks */
2078 /*-----------------------------------------------------------------*/
2079
movepBlock2Head(char dbName)2080 void movepBlock2Head(char dbName)
2081 {
2082 pBlock *pb;
2083
2084 if (!the_pFile)
2085 return;
2086
2087 pb = the_pFile->pbHead;
2088
2089 while(pb) {
2090
2091 if(getpBlock_dbName(pb) == dbName) {
2092 pBlock *pbn = pb->next;
2093 pb->next = the_pFile->pbHead;
2094 the_pFile->pbHead->prev = pb;
2095 the_pFile->pbHead = pb;
2096
2097 if(pb->prev)
2098 pb->prev->next = pbn;
2099
2100 // If the pBlock that we just moved was the last
2101 // one in the link of all of the pBlocks, then we
2102 // need to point the tail to the block just before
2103 // the one we moved.
2104 // Note: if pb->next is NULL, then pb must have
2105 // been the last pBlock in the chain.
2106
2107 if(pbn)
2108 pbn->prev = pb->prev;
2109 else
2110 the_pFile->pbTail = pb->prev;
2111
2112 pb = pbn;
2113 } else
2114 pb = pb->next;
2115 }
2116 }
2117
copypCode(FILE * of,char dbName)2118 void copypCode(FILE *of, char dbName)
2119 {
2120 pBlock *pb;
2121
2122 if(!of || !the_pFile)
2123 return;
2124
2125 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2126 if(getpBlock_dbName(pb) == dbName) {
2127 pBlockStats(of,pb);
2128 printpBlock(of,pb);
2129 fprintf (of, "\n");
2130 }
2131 }
2132 }
2133
resetpCodeStatistics(void)2134 void resetpCodeStatistics (void)
2135 {
2136 pcode_insns = pcode_doubles = 0;
2137 }
2138
dumppCodeStatistics(FILE * of)2139 void dumppCodeStatistics (FILE *of)
2140 {
2141 /* dump statistics */
2142 fprintf (of, "\n");
2143 fprintf (of, ";\tcode size estimation:\n");
2144 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
2145 fprintf (of, "\n");
2146 }
2147
pcode_test(void)2148 void pcode_test(void)
2149 {
2150 DFPRINTF((stderr,"pcode is alive!\n"));
2151
2152 //initMnemonics();
2153
2154 if(the_pFile) {
2155
2156 pBlock *pb;
2157 FILE *pFile;
2158 char buffer[200];
2159
2160 /* create the file name */
2161 SNPRINTF(buffer, sizeof(buffer), "%s.p", dstFileName);
2162
2163 if( !(pFile = fopen(buffer, "w" ))) {
2164 werror(E_FILE_OPEN_ERR,buffer);
2165 exit(1);
2166 }
2167
2168 fprintf(pFile,"pcode dump\n\n");
2169
2170 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2171 fprintf(pFile,"\n\tNew pBlock\n\n");
2172 if(pb->cmemmap)
2173 fprintf(pFile,"%s",pb->cmemmap->sname);
2174 else
2175 fprintf(pFile,"internal pblock");
2176
2177 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2178 printpBlock(pFile,pb);
2179 }
2180 }
2181 }
2182
2183 /*-----------------------------------------------------------------*/
2184 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
2185 /* ister, RegCond will return the bit being referenced. */
2186 /* */
2187 /* fixme - why not just OR in the pcop bit field */
2188 /*-----------------------------------------------------------------*/
2189
RegCond(pCodeOp * pcop)2190 static int RegCond(pCodeOp *pcop)
2191 {
2192 if(!pcop)
2193 return 0;
2194
2195 if (pcop->type == PO_GPR_BIT) {
2196 const char *name = pcop->name;
2197 if (!name)
2198 name = PCOR(pcop)->r->name;
2199 if (strcmp(name, pc_status.pcop.name) == 0)
2200 {
2201 switch(PCORB(pcop)->bit) {
2202 case PIC_C_BIT:
2203 return PCC_C;
2204 case PIC_DC_BIT:
2205 return PCC_DC;
2206 case PIC_Z_BIT:
2207 return PCC_Z;
2208 }
2209 }
2210 }
2211
2212 return 0;
2213 }
2214
2215 /*-----------------------------------------------------------------*/
2216 /* newpCode - create and return a newly initialized pCode */
2217 /* */
2218 /* fixme - rename this */
2219 /* */
2220 /* The purpose of this routine is to create a new Instruction */
2221 /* pCode. This is called by gen.c while the assembly code is being */
2222 /* generated. */
2223 /* */
2224 /* Inouts: */
2225 /* PIC_OPCODE op - the assembly instruction we wish to create. */
2226 /* (note that the op is analogous to but not the */
2227 /* same thing as the opcode of the instruction.) */
2228 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
2229 /* */
2230 /* Outputs: */
2231 /* a pointer to the new malloc'd pCode is returned. */
2232 /* */
2233 /* */
2234 /* */
2235 /*-----------------------------------------------------------------*/
newpCode(PIC_OPCODE op,pCodeOp * pcop)2236 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
2237 {
2238 pCodeInstruction *pci ;
2239
2240 if(!mnemonics_initialized)
2241 pic14initMnemonics();
2242
2243 pci = Safe_alloc(sizeof(pCodeInstruction));
2244
2245 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
2246 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
2247 pci->pc.id = PCodeID();
2248 pci->pcop = pcop;
2249
2250 if(pci->inCond & PCC_EXAMINE_PCOP)
2251 pci->inCond |= RegCond(pcop);
2252
2253 if(pci->outCond & PCC_EXAMINE_PCOP)
2254 pci->outCond |= RegCond(pcop);
2255
2256 pci->pc.prev = pci->pc.next = NULL;
2257 return (pCode *)pci;
2258 }
2259
2260 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
2261 exit(1);
2262
2263 return NULL;
2264 }
2265
2266 /*-----------------------------------------------------------------*/
2267 /* newpCodeWild - create a "wild" as in wild card pCode */
2268 /* */
2269 /* Wild pcodes are used during the peep hole optimizer to serve */
2270 /* as place holders for any instruction. When a snippet of code is */
2271 /* compared to a peep hole rule, the wild card opcode will match */
2272 /* any instruction. However, the optional operand and label are */
2273 /* additional qualifiers that must also be matched before the */
2274 /* line (of assembly code) is declared matched. Note that the */
2275 /* operand may be wild too. */
2276 /* */
2277 /* Note, a wild instruction is specified just like a wild var: */
2278 /* %4 ; A wild instruction, */
2279 /* See the peeph.def file for additional examples */
2280 /* */
2281 /*-----------------------------------------------------------------*/
2282
newpCodeWild(int pCodeID,pCodeOp * optional_operand,pCodeOp * optional_label)2283 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
2284 {
2285 pCodeWild *pcw;
2286
2287 pcw = Safe_alloc(sizeof(pCodeWild));
2288
2289 pcw->pci.pc.type = PC_WILD;
2290 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
2291 pcw->id = PCodeID();
2292 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
2293 pcw->pci.pc.pb = NULL;
2294
2295 pcw->pci.pc.destruct = genericDestruct;
2296 pcw->pci.pc.print = genericPrint;
2297
2298 pcw->id = pCodeID; // this is the 'n' in %n
2299 pcw->operand = optional_operand;
2300 pcw->label = optional_label;
2301
2302 pcw->mustBeBitSkipInst = 0;
2303 pcw->mustNotBeBitSkipInst = 0;
2304 pcw->invertBitSkipInst = 0;
2305
2306 return ((pCode *)pcw);
2307 }
2308
2309 /*-----------------------------------------------------------------*/
2310 /* newPcodeCharP - create a new pCode from a char string */
2311 /*-----------------------------------------------------------------*/
2312
newpCodeCharP(const char * cP)2313 pCode *newpCodeCharP(const char *cP)
2314 {
2315 pCodeComment *pcc;
2316
2317 pcc = Safe_alloc(sizeof(pCodeComment));
2318
2319 pcc->pc.type = PC_COMMENT;
2320 pcc->pc.prev = pcc->pc.next = NULL;
2321 pcc->pc.id = PCodeID();
2322 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2323 pcc->pc.pb = NULL;
2324
2325 pcc->pc.destruct = genericDestruct;
2326 pcc->pc.print = genericPrint;
2327
2328 if(cP)
2329 pcc->comment = Safe_strdup(cP);
2330 else
2331 pcc->comment = NULL;
2332
2333 return ((pCode *)pcc);
2334 }
2335
2336 /*-----------------------------------------------------------------*/
2337 /* newpCodeFunction - */
2338 /*-----------------------------------------------------------------*/
2339
newpCodeFunction(const char * mod,const char * f,int isPublic,int isInterrupt)2340 pCode *newpCodeFunction(const char *mod, const char *f, int isPublic, int isInterrupt)
2341 {
2342 pCodeFunction *pcf;
2343
2344 pcf = Safe_alloc(sizeof(pCodeFunction));
2345
2346 pcf->pc.type = PC_FUNCTION;
2347 pcf->pc.prev = pcf->pc.next = NULL;
2348 pcf->pc.id = PCodeID();
2349 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
2350 pcf->pc.pb = NULL;
2351
2352 pcf->pc.destruct = genericDestruct;
2353 pcf->pc.print = pCodePrintFunction;
2354
2355 pcf->ncalled = 0;
2356
2357 pcf->modname = (mod != NULL) ? Safe_strdup(mod) : NULL;
2358 pcf->fname = (f != NULL) ? Safe_strdup(f) : NULL;
2359
2360 pcf->isPublic = (unsigned int)isPublic;
2361 pcf->isInterrupt = (unsigned int)isInterrupt;
2362
2363 return ((pCode *)pcf);
2364 }
2365
2366 /*-----------------------------------------------------------------*/
2367 /* newpCodeFlow */
2368 /*-----------------------------------------------------------------*/
destructpCodeFlow(pCode * pc)2369 static void destructpCodeFlow(pCode *pc)
2370 {
2371 if(!pc || !isPCFL(pc))
2372 return;
2373
2374 /*
2375 if(PCFL(pc)->from)
2376 if(PCFL(pc)->to)
2377 */
2378 unlinkpCode(pc);
2379
2380 deleteSet(&PCFL(pc)->registers);
2381 deleteSet(&PCFL(pc)->from);
2382 deleteSet(&PCFL(pc)->to);
2383 free(pc);
2384 }
2385
newpCodeFlow(void)2386 static pCode *newpCodeFlow(void )
2387 {
2388 pCodeFlow *pcflow;
2389
2390 pcflow = Safe_alloc(sizeof(pCodeFlow));
2391
2392 pcflow->pc.type = PC_FLOW;
2393 pcflow->pc.prev = pcflow->pc.next = NULL;
2394 pcflow->pc.pb = NULL;
2395
2396 pcflow->pc.destruct = destructpCodeFlow;
2397 pcflow->pc.print = genericPrint;
2398
2399 pcflow->pc.seq = GpcFlowSeq++;
2400
2401 pcflow->from = pcflow->to = NULL;
2402
2403 pcflow->inCond = PCC_NONE;
2404 pcflow->outCond = PCC_NONE;
2405
2406 pcflow->firstBank = 'U'; /* Undetermined */
2407 pcflow->lastBank = 'U'; /* Undetermined */
2408
2409 pcflow->FromConflicts = 0;
2410 pcflow->ToConflicts = 0;
2411
2412 pcflow->end = NULL;
2413
2414 pcflow->registers = newSet();
2415
2416 return ((pCode *)pcflow);
2417 }
2418
2419 /*-----------------------------------------------------------------*/
2420 /*-----------------------------------------------------------------*/
newpCodeFlowLink(pCodeFlow * pcflow)2421 static pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
2422 {
2423 pCodeFlowLink *pcflowLink;
2424
2425 pcflowLink = Safe_alloc(sizeof(pCodeFlowLink));
2426
2427 pcflowLink->pcflow = pcflow;
2428 pcflowLink->bank_conflict = 0;
2429
2430 return pcflowLink;
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* newpCodeCSource - create a new pCode Source Symbol */
2435 /*-----------------------------------------------------------------*/
2436
newpCodeCSource(int ln,const char * f,const char * l)2437 pCode *newpCodeCSource(int ln, const char *f, const char *l)
2438 {
2439 pCodeCSource *pccs;
2440
2441 pccs = Safe_alloc(sizeof(pCodeCSource));
2442
2443 pccs->pc.type = PC_CSOURCE;
2444 pccs->pc.prev = pccs->pc.next = NULL;
2445 pccs->pc.id = PCodeID();
2446 pccs->pc.pb = NULL;
2447
2448 pccs->pc.destruct = genericDestruct;
2449 pccs->pc.print = genericPrint;
2450
2451 pccs->line_number = ln;
2452 if(l)
2453 pccs->line = Safe_strdup(l);
2454 else
2455 pccs->line = NULL;
2456
2457 if(f)
2458 pccs->file_name = Safe_strdup(f);
2459 else
2460 pccs->file_name = NULL;
2461
2462 return ( (pCode *)pccs);
2463 }
2464
2465 /*******************************************************************/
2466 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
2467 /* added by VR 6-Jun-2003 */
2468 /*******************************************************************/
2469
newpCodeAsmDir(const char * asdir,const char * argfmt,...)2470 pCode *newpCodeAsmDir(const char *asdir, const char *argfmt, ...)
2471 {
2472 pCodeAsmDir *pcad;
2473 va_list ap;
2474 char buffer[512];
2475 char *lbp=buffer;
2476
2477 pcad = Safe_alloc(sizeof(pCodeAsmDir));
2478 pcad->pci.pc.type = PC_ASMDIR;
2479 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2480 pcad->pci.pc.pb = NULL;
2481 pcad->pci.pc.destruct = genericDestruct;
2482 pcad->pci.pc.print = genericPrint;
2483
2484 if(asdir && *asdir) {
2485 while(isspace((unsigned char)*asdir)) asdir++; // strip any white space from the beginning
2486
2487 pcad->directive = Safe_strdup(asdir);
2488 }
2489
2490 va_start(ap, argfmt);
2491
2492 memset(buffer, 0, sizeof(buffer));
2493 if(argfmt && *argfmt)
2494 vsnprintf(buffer, sizeof(buffer), argfmt, ap);
2495
2496 va_end(ap);
2497
2498 while(isspace((unsigned char)*lbp)) lbp++;
2499
2500 if(lbp && *lbp)
2501 pcad->arg = Safe_strdup(lbp);
2502
2503 return ((pCode *)pcad);
2504 }
2505
2506 /*-----------------------------------------------------------------*/
2507 /* pCodeLabelDestruct - free memory used by a label. */
2508 /*-----------------------------------------------------------------*/
pCodeLabelDestruct(pCode * pc)2509 static void pCodeLabelDestruct(pCode *pc)
2510 {
2511 if(!pc)
2512 return;
2513
2514 if((pc->type == PC_LABEL) && PCL(pc)->label)
2515 free(PCL(pc)->label);
2516
2517 free(pc);
2518 }
2519
newpCodeLabel(const char * name,int key)2520 pCode *newpCodeLabel(const char *name, int key)
2521 {
2522 const char *s;
2523 pCodeLabel *pcl;
2524
2525 pcl = Safe_alloc(sizeof(pCodeLabel));
2526
2527 pcl->pc.type = PC_LABEL;
2528 pcl->pc.prev = pcl->pc.next = NULL;
2529 pcl->pc.id = PCodeID();
2530 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2531 pcl->pc.pb = NULL;
2532
2533 pcl->pc.destruct = pCodeLabelDestruct;
2534 pcl->pc.print = pCodePrintLabel;
2535
2536 pcl->key = key;
2537
2538 pcl->label = NULL;
2539 if(key>0) {
2540 SNPRINTF(buffer, sizeof(buffer), "_%05d_DS_", key);
2541 s = buffer;
2542 } else {
2543 /* SNPRINTF(buffer, sizeof(buffer), "%s:", name);
2544 s = buffer;*/
2545 s = name;
2546 }
2547
2548 if(s)
2549 pcl->label = Safe_strdup(s);
2550
2551 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2552 return ((pCode *)pcl);
2553 }
2554
2555
2556 /*-----------------------------------------------------------------*/
2557 /* newpBlock - create and return a pointer to a new pBlock */
2558 /*-----------------------------------------------------------------*/
newpBlock(void)2559 static pBlock *newpBlock(void)
2560 {
2561 pBlock *PpB;
2562
2563 PpB = Safe_alloc(sizeof(pBlock));
2564 PpB->next = PpB->prev = NULL;
2565
2566 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2567 PpB->tregisters = NULL;
2568 PpB->visited = 0;
2569 PpB->FlowTree = NULL;
2570
2571 return PpB;
2572 }
2573
2574 /*-----------------------------------------------------------------*/
2575 /* newpCodeChain - create a new chain of pCodes */
2576 /*-----------------------------------------------------------------*
2577 *
2578 * This function will create a new pBlock and the pointer to the
2579 * pCode that is passed in will be the first pCode in the block.
2580 *-----------------------------------------------------------------*/
2581
2582
newpCodeChain(memmap * cm,char c,pCode * pc)2583 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2584 {
2585 pBlock *pB = newpBlock();
2586
2587 pB->pcHead = pB->pcTail = pc;
2588 pB->cmemmap = cm;
2589 pB->dbName = c;
2590
2591 return pB;
2592 }
2593
2594 /*-----------------------------------------------------------------*/
2595 /* newpCodeOpLabel - Create a new label given the key */
2596 /* Note, a negative key means that the label is part of wild card */
2597 /* (and hence a wild card label) used in the pCodePeep */
2598 /* optimizations). */
2599 /*-----------------------------------------------------------------*/
2600
newpCodeOpLabel(const char * name,int key)2601 pCodeOp *newpCodeOpLabel(const char *name, int key)
2602 {
2603 const char *s;
2604 static int label_key = -1;
2605
2606 pCodeOp *pcop;
2607
2608 pcop = Safe_alloc(sizeof(pCodeOpLabel));
2609 pcop->type = PO_LABEL;
2610
2611 pcop->name = NULL;
2612
2613 if(key>0) {
2614 SNPRINTF(buffer, sizeof(buffer), "_%05d_DS_", key);
2615 s = buffer;
2616 }
2617 else {
2618 s = name;
2619 key = label_key--;
2620 }
2621
2622 PCOLAB(pcop)->offset = 0;
2623 if(s)
2624 pcop->name = Safe_strdup(s);
2625
2626 ((pCodeOpLabel *)pcop)->key = key;
2627
2628 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2629 return pcop;
2630 }
2631
2632 /*-----------------------------------------------------------------*/
2633 /*-----------------------------------------------------------------*/
newpCodeOpLit(int lit)2634 pCodeOp *newpCodeOpLit(int lit)
2635 {
2636 pCodeOp *pcop;
2637
2638 pcop = Safe_alloc(sizeof(pCodeOpLit));
2639 pcop->type = PO_LITERAL;
2640
2641 pcop->name = NULL;
2642 if(lit>=0) {
2643 SNPRINTF(buffer, sizeof(buffer),"0x%02x", (unsigned char)lit);
2644 pcop->name = Safe_strdup(buffer);
2645 }
2646
2647 ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2648
2649 return pcop;
2650 }
2651
2652 /*-----------------------------------------------------------------*/
2653 /*-----------------------------------------------------------------*/
newpCodeOpImmd(const char * name,int offset,int index,int code_space,int is_func)2654 pCodeOp *newpCodeOpImmd(const char *name, int offset, int index, int code_space, int is_func)
2655 {
2656 pCodeOp *pcop;
2657
2658 pcop = Safe_alloc(sizeof(pCodeOpImmd));
2659 pcop->type = PO_IMMEDIATE;
2660 if(name) {
2661 reg_info *r = NULL;
2662 pcop->name = Safe_strdup(name);
2663
2664 if(!is_func)
2665 r = dirregWithName(name);
2666
2667 PCOI(pcop)->r = r;
2668 if(r) {
2669 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2670 PCOI(pcop)->rIdx = r->rIdx;
2671 } else {
2672 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2673 PCOI(pcop)->rIdx = -1;
2674 }
2675 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2676 } else {
2677 pcop->name = NULL;
2678 }
2679
2680 PCOI(pcop)->index = index;
2681 PCOI(pcop)->offset = offset;
2682 PCOI(pcop)->_const = code_space;
2683 PCOI(pcop)->_function = is_func;
2684
2685 return pcop;
2686 }
2687
2688 /*-----------------------------------------------------------------*/
2689 /*-----------------------------------------------------------------*/
newpCodeOpWild(int id,pCodeWildBlock * pcwb,pCodeOp * subtype)2690 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2691 {
2692 pCodeOp *pcop;
2693
2694 if(!pcwb || !subtype) {
2695 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2696 exit(1);
2697 }
2698
2699 pcop = Safe_alloc(sizeof(pCodeOpWild));
2700 pcop->type = PO_WILD;
2701 SNPRINTF(buffer, sizeof(buffer), "%%%d", id);
2702 pcop->name = Safe_strdup(buffer);
2703
2704 PCOW(pcop)->id = id;
2705 PCOW(pcop)->pcwb = pcwb;
2706 PCOW(pcop)->subtype = subtype;
2707 PCOW(pcop)->matched = NULL;
2708
2709 return pcop;
2710 }
2711
2712 /*-----------------------------------------------------------------*/
2713 /* Find a symbol with matching name */
2714 /*-----------------------------------------------------------------*/
symFindWithName(memmap * map,const char * name)2715 static symbol *symFindWithName(memmap * map, const char *name)
2716 {
2717 symbol *sym;
2718
2719 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2720 if (sym->rname && (strcmp(sym->rname,name)==0))
2721 return sym;
2722 }
2723 return 0;
2724 }
2725
2726 /*-----------------------------------------------------------------*/
2727 /*-----------------------------------------------------------------*/
newpCodeOpBit(const char * name,int ibit,int inBitSpace)2728 pCodeOp *newpCodeOpBit(const char *name, int ibit, int inBitSpace)
2729 {
2730 pCodeOp *pcop;
2731 struct reg_info *r = 0;
2732
2733 pcop = Safe_alloc(sizeof(pCodeOpRegBit));
2734 pcop->type = PO_GPR_BIT;
2735
2736 PCORB(pcop)->bit = ibit;
2737 PCORB(pcop)->inBitSpace = inBitSpace;
2738
2739 if (name) r = regFindWithName(name);
2740 if (name && !r) {
2741 // Register has not been allocated - check for symbol information
2742 symbol *sym;
2743 sym = symFindWithName(bit, name);
2744 if (!sym) sym = symFindWithName(sfrbit, name);
2745 if (!sym) sym = symFindWithName(sfr, name);
2746 if (!sym) sym = symFindWithName(reg, name);
2747 // Hack to fix accesses to _INTCON_bits (e.g. GIE=0), see #1579535.
2748 // XXX: This ignores nesting levels, but works for globals...
2749 if (!sym) sym = findSym(SymbolTab, NULL, name);
2750 if (!sym && name && name[0] == '_') sym = findSym(SymbolTab, NULL, &name[1]);
2751 if (sym) {
2752 r = allocNewDirReg(sym->etype,name);
2753 }
2754 }
2755 if (r) {
2756 pcop->name = NULL;
2757 PCOR(pcop)->r = r;
2758 PCOR(pcop)->rIdx = r->rIdx;
2759 } else if (name) {
2760 pcop->name = Safe_strdup(name);
2761 PCOR(pcop)->r = NULL;
2762 PCOR(pcop)->rIdx = 0;
2763 } else {
2764 //fprintf(stderr, "Unnamed register duplicated for bit-access?!? Hope for the best ...\n");
2765 }
2766 return pcop;
2767 }
2768
2769 /*-----------------------------------------------------------------*
2770 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2771 *
2772 * If rIdx >=0 then a specific register from the set of registers
2773 * will be selected. If rIdx <0, then a new register will be searched
2774 * for.
2775 *-----------------------------------------------------------------*/
2776
newpCodeOpReg(int rIdx)2777 static pCodeOp *newpCodeOpReg(int rIdx)
2778 {
2779 pCodeOp *pcop;
2780
2781 pcop = Safe_alloc(sizeof(pCodeOpReg));
2782
2783 pcop->name = NULL;
2784
2785 if(rIdx >= 0) {
2786 PCOR(pcop)->rIdx = rIdx;
2787 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2788 } else {
2789 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2790
2791 if(PCOR(pcop)->r)
2792 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2793 }
2794
2795 if(PCOR(pcop)->r)
2796 pcop->type = PCOR(pcop)->r->pc_type;
2797
2798 return pcop;
2799 }
2800
newpCodeOpRegFromStr(const char * name)2801 pCodeOp *newpCodeOpRegFromStr(const char *name)
2802 {
2803 pCodeOp *pcop;
2804
2805 pcop = Safe_alloc(sizeof(pCodeOpReg));
2806 PCOR(pcop)->r = allocRegByName(name, 1);
2807 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2808 pcop->type = PCOR(pcop)->r->pc_type;
2809 pcop->name = PCOR(pcop)->r->name;
2810
2811 return pcop;
2812 }
2813
newpCodeOpStr(const char * name)2814 static pCodeOp *newpCodeOpStr(const char *name)
2815 {
2816 pCodeOp *pcop;
2817
2818 pcop = Safe_alloc(sizeof(pCodeOpStr));
2819 pcop->type = PO_STR;
2820 pcop->name = Safe_strdup(name);
2821
2822 PCOS(pcop)->isPublic = 0;
2823
2824 return pcop;
2825 }
2826
2827
2828 /*-----------------------------------------------------------------*/
2829 /*-----------------------------------------------------------------*/
2830
newpCodeOp(const char * name,PIC_OPTYPE type)2831 pCodeOp *newpCodeOp(const char *name, PIC_OPTYPE type)
2832 {
2833 pCodeOp *pcop;
2834
2835 switch(type) {
2836 case PO_BIT:
2837 case PO_GPR_BIT:
2838 pcop = newpCodeOpBit(name, -1, 0);
2839 break;
2840
2841 case PO_LITERAL:
2842 pcop = newpCodeOpLit(-1);
2843 break;
2844
2845 case PO_LABEL:
2846 pcop = newpCodeOpLabel(NULL,-1);
2847 break;
2848
2849 case PO_GPR_TEMP:
2850 pcop = newpCodeOpReg(-1);
2851 break;
2852
2853 case PO_GPR_POINTER:
2854 case PO_GPR_REGISTER:
2855 if(name)
2856 pcop = newpCodeOpRegFromStr(name);
2857 else
2858 pcop = newpCodeOpReg(-1);
2859 break;
2860
2861 case PO_STR:
2862 pcop = newpCodeOpStr(name);
2863 break;
2864
2865 default:
2866 pcop = Safe_alloc(sizeof(pCodeOp));
2867 pcop->type = type;
2868 pcop->name = (name != NULL) ? Safe_strdup(name) : NULL;
2869 }
2870
2871 return pcop;
2872 }
2873
2874 /*-----------------------------------------------------------------*/
2875 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2876 /*-----------------------------------------------------------------*/
addpCode2pBlock(pBlock * pb,pCode * pc)2877 void addpCode2pBlock(pBlock *pb, pCode *pc)
2878 {
2879
2880 if(!pb || !pc)
2881 return;
2882
2883 if(!pb->pcHead) {
2884 /* If this is the first pcode to be added to a block that
2885 * was initialized with a NULL pcode, then go ahead and
2886 * make this pcode the head and tail */
2887 pb->pcHead = pb->pcTail = pc;
2888 } else {
2889 // if(pb->pcTail)
2890 pb->pcTail->next = pc;
2891
2892 pc->prev = pb->pcTail;
2893 pc->pb = pb;
2894
2895 pb->pcTail = pc;
2896 }
2897 }
2898
2899 /*-----------------------------------------------------------------*/
2900 /* addpBlock - place a pBlock into the pFile */
2901 /*-----------------------------------------------------------------*/
addpBlock(pBlock * pb)2902 void addpBlock(pBlock *pb)
2903 {
2904 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2905
2906 if(!the_pFile) {
2907 /* First time called, we'll pass through here. */
2908 //_ALLOC(the_pFile,sizeof(pFile));
2909 the_pFile = Safe_alloc(sizeof(pFile));
2910 the_pFile->pbHead = the_pFile->pbTail = pb;
2911 the_pFile->functions = NULL;
2912 return;
2913 }
2914
2915 the_pFile->pbTail->next = pb;
2916 pb->prev = the_pFile->pbTail;
2917 pb->next = NULL;
2918 the_pFile->pbTail = pb;
2919 }
2920
2921 /*-----------------------------------------------------------------*/
2922 /* removepBlock - remove a pBlock from the pFile */
2923 /*-----------------------------------------------------------------*/
removepBlock(pBlock * pb)2924 static void removepBlock(pBlock *pb)
2925 {
2926 pBlock *pbs;
2927
2928 if(!the_pFile)
2929 return;
2930
2931 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2932
2933 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2934 if(pbs == pb) {
2935
2936 if(pbs == the_pFile->pbHead)
2937 the_pFile->pbHead = pbs->next;
2938
2939 if (pbs == the_pFile->pbTail)
2940 the_pFile->pbTail = pbs->prev;
2941
2942 if(pbs->next)
2943 pbs->next->prev = pbs->prev;
2944
2945 if(pbs->prev)
2946 pbs->prev->next = pbs->next;
2947
2948 return;
2949 }
2950 }
2951
2952 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2953 }
2954
2955 /*-----------------------------------------------------------------*/
2956 /* printpCode - write the contents of a pCode to a file */
2957 /*-----------------------------------------------------------------*/
2958
printpCode(FILE * of,pCode * pc)2959 void printpCode(FILE *of, pCode *pc)
2960 {
2961 if(!pc || !of)
2962 return;
2963
2964 if(pc->print) {
2965 pc->print(of,pc);
2966 return;
2967 }
2968
2969 fprintf(of,"warning - unable to print pCode\n");
2970 }
2971
2972 /*-----------------------------------------------------------------*/
2973 /* printpBlock - write the contents of a pBlock to a file */
2974 /*-----------------------------------------------------------------*/
2975
printpBlock(FILE * of,pBlock * pb)2976 void printpBlock(FILE *of, pBlock *pb)
2977 {
2978 pCode *pc;
2979
2980 if(!pb)
2981 return;
2982
2983 if(!of)
2984 of = stderr;
2985
2986 for(pc = pb->pcHead; pc; pc = pc->next) {
2987 if(isPCF(pc) && PCF(pc)->fname && !PCF(pc)->isInterrupt) {
2988 fprintf(of, "S_%s_%s\tcode\n", PCF(pc)->modname, PCF(pc)->fname);
2989 }
2990 printpCode(of,pc);
2991
2992 if (isPCI(pc))
2993 {
2994 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2995 pcode_doubles++;
2996 } else {
2997 pcode_insns++;
2998 }
2999 }
3000 } // for
3001 }
3002
3003 /*-----------------------------------------------------------------*/
3004 /* */
3005 /* pCode processing */
3006 /* */
3007 /* */
3008 /* */
3009 /*-----------------------------------------------------------------*/
3010
unlinkpCode(pCode * pc)3011 void unlinkpCode(pCode *pc)
3012 {
3013 if(pc) {
3014 #ifdef PCODE_DEBUG
3015 fprintf(stderr,"Unlinking: ");
3016 printpCode(stderr, pc);
3017 #endif
3018 if(pc->prev)
3019 pc->prev->next = pc->next;
3020 if(pc->next)
3021 pc->next->prev = pc->prev;
3022
3023 #if 0
3024 /* RN: I believe this should be right here, but this did not
3025 * cure the bug I was hunting... */
3026 /* must keep labels -- attach to following instruction */
3027 if (isPCI(pc) && PCI(pc)->label && pc->next)
3028 {
3029 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
3030 if (pcnext)
3031 {
3032 pBranchAppend (pcnext->label, PCI(pc)->label);
3033 }
3034 }
3035 #endif
3036 pc->prev = pc->next = NULL;
3037 }
3038 }
3039
3040 /*-----------------------------------------------------------------*/
3041 /*-----------------------------------------------------------------*/
3042
genericDestruct(pCode * pc)3043 static void genericDestruct(pCode *pc)
3044 {
3045 unlinkpCode(pc);
3046
3047 if(isPCI(pc)) {
3048 /* For instructions, tell the register (if there's one used)
3049 * that it's no longer needed */
3050 reg_info *reg = getRegFromInstruction(pc);
3051 if(reg)
3052 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3053 }
3054
3055 /* Instead of deleting the memory used by this pCode, mark
3056 * the object as bad so that if there's a pointer to this pCode
3057 * dangling around somewhere then (hopefully) when the type is
3058 * checked we'll catch it.
3059 */
3060
3061 pc->type = PC_BAD;
3062
3063 addpCode2pBlock(pb_dead_pcodes, pc);
3064
3065 //free(pc);
3066 }
3067
3068
3069 /*-----------------------------------------------------------------*/
3070 /* Copies the pCodeInstruction flow pointer from source pCode */
3071 /*-----------------------------------------------------------------*/
CopyFlow(pCodeInstruction * pcd,pCode * pcs)3072 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
3073 pCode *p;
3074 pCodeFlow *pcflow = 0;
3075 for (p=pcs; p; p=p->prev) {
3076 if (isPCI(p)) {
3077 pcflow = PCI(p)->pcflow;
3078 break;
3079 }
3080 if (isPCF(p)) {
3081 pcflow = (pCodeFlow*)p;
3082 break;
3083 }
3084 }
3085 PCI(pcd)->pcflow = pcflow;
3086 }
3087
3088 /*-----------------------------------------------------------------*/
3089 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
3090 /* into the pCode chain containing pc1 */
3091 /*-----------------------------------------------------------------*/
pCodeInsertAfter(pCode * pc1,pCode * pc2)3092 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
3093 {
3094 if(!pc1 || !pc2)
3095 return;
3096
3097 pc2->next = pc1->next;
3098 if(pc1->next)
3099 pc1->next->prev = pc2;
3100
3101 pc2->pb = pc1->pb;
3102 pc2->prev = pc1;
3103 pc1->next = pc2;
3104
3105 /* If this is an instrution type propogate the flow */
3106 if (isPCI(pc2))
3107 CopyFlow(PCI(pc2),pc1);
3108 }
3109
3110 /*------------------------------------------------------------------*/
3111 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
3112 /* into the pCode chain containing pc1 */
3113 /*------------------------------------------------------------------*/
pCodeInsertBefore(pCode * pc1,pCode * pc2)3114 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
3115 {
3116 if(!pc1 || !pc2)
3117 return;
3118
3119 pc2->prev = pc1->prev;
3120 if(pc1->prev)
3121 pc1->prev->next = pc2;
3122
3123 pc2->pb = pc1->pb;
3124 pc2->next = pc1;
3125 pc1->prev = pc2;
3126
3127 /* If this is an instrution type propogate the flow */
3128 if (isPCI(pc2))
3129 CopyFlow(PCI(pc2),pc1);
3130 }
3131
3132 /*-----------------------------------------------------------------*/
3133 /* pCodeOpCopy - copy a pcode operator */
3134 /*-----------------------------------------------------------------*/
pCodeOpCopy(pCodeOp * pcop)3135 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
3136 {
3137 pCodeOp *pcopnew=NULL;
3138
3139 if(!pcop)
3140 return NULL;
3141
3142 switch(pcop->type) {
3143 case PO_NONE:
3144 case PO_STR:
3145 pcopnew = Safe_malloc(sizeof(pCodeOp));
3146 memcpy(pcopnew, pcop, sizeof(pCodeOp));
3147 break;
3148
3149 case PO_W:
3150 case PO_STATUS:
3151 case PO_FSR:
3152 case PO_INDF:
3153 case PO_INTCON:
3154 case PO_GPR_REGISTER:
3155 case PO_GPR_TEMP:
3156 case PO_GPR_POINTER:
3157 case PO_SFR_REGISTER:
3158 case PO_PCL:
3159 case PO_PCLATH:
3160 case PO_DIR:
3161 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
3162 pcopnew = Safe_malloc(sizeof(pCodeOpReg));
3163 memcpy(pcopnew, pcop, sizeof(pCodeOpReg));
3164 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
3165 break;
3166
3167 case PO_LITERAL:
3168 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
3169 pcopnew = Safe_malloc(sizeof(pCodeOpLit));
3170 memcpy(pcopnew, pcop, sizeof(pCodeOpLit));
3171 break;
3172
3173 case PO_IMMEDIATE:
3174 pcopnew = Safe_malloc(sizeof(pCodeOpImmd));
3175 memcpy(pcopnew, pcop, sizeof(pCodeOpImmd));
3176 break;
3177
3178 case PO_GPR_BIT:
3179 case PO_CRY:
3180 case PO_BIT:
3181 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
3182 pcopnew = Safe_malloc(sizeof(pCodeOpRegBit));
3183 memcpy(pcopnew, pcop, sizeof(pCodeOpRegBit));
3184 break;
3185
3186 case PO_LABEL:
3187 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
3188 pcopnew = Safe_malloc(sizeof(pCodeOpLabel));
3189 memcpy(pcopnew, pcop, sizeof(pCodeOpLabel));
3190 break;
3191
3192 case PO_WILD:
3193 /* Here we expand the wild card into the appropriate type: */
3194 /* By recursively calling pCodeOpCopy */
3195 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
3196 if(PCOW(pcop)->matched)
3197 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
3198 else {
3199 // Probably a label
3200 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
3201 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
3202 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
3203 }
3204
3205 return pcopnew;
3206 break;
3207
3208 default:
3209 assert ( !"unhandled pCodeOp type copied" );
3210 break;
3211 } // switch
3212
3213 pcopnew->name = (pcop->name != NULL) ? Safe_strdup(pcop->name) : NULL;
3214
3215 return pcopnew;
3216 }
3217
3218 /*-----------------------------------------------------------------*/
3219 /* popCopyReg - copy a pcode operator */
3220 /*-----------------------------------------------------------------*/
popCopyReg(pCodeOpReg * pc)3221 pCodeOp *popCopyReg(pCodeOpReg *pc)
3222 {
3223 pCodeOpReg *pcor;
3224
3225 pcor = Safe_alloc(sizeof(pCodeOpReg));
3226 pcor->pcop.type = pc->pcop.type;
3227 if(pc->pcop.name) {
3228 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
3229 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
3230 } else
3231 pcor->pcop.name = NULL;
3232
3233 if (pcor->pcop.type == PO_IMMEDIATE){
3234 PCOL(pcor)->lit = PCOL(pc)->lit;
3235 } else {
3236 pcor->r = pc->r;
3237 pcor->rIdx = pc->rIdx;
3238 if (pcor->r)
3239 pcor->r->wasUsed=1;
3240 }
3241 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
3242
3243 return PCOP(pcor);
3244 }
3245
3246 /*-----------------------------------------------------------------*/
3247 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
3248 /*-----------------------------------------------------------------*/
pCodeInstructionCopy(pCodeInstruction * pci,int invert)3249 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
3250 {
3251 pCodeInstruction *new_pci;
3252
3253 if(invert)
3254 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
3255 else
3256 new_pci = PCI(newpCode(pci->op,pci->pcop));
3257
3258 new_pci->pc.pb = pci->pc.pb;
3259 new_pci->from = pci->from;
3260 new_pci->to = pci->to;
3261 new_pci->label = pci->label;
3262 new_pci->pcflow = pci->pcflow;
3263
3264 return PCODE(new_pci);
3265 }
3266
3267 /*-----------------------------------------------------------------*/
3268 /*-----------------------------------------------------------------*/
pCodeDeleteChain(pCode * f,pCode * t)3269 void pCodeDeleteChain(pCode *f,pCode *t)
3270 {
3271 pCode *pc;
3272
3273 while(f && f!=t) {
3274 DFPRINTF((stderr,"delete pCode:\n"));
3275 pc = f->next;
3276 //f->print(stderr,f);
3277 //f->delete(f); this dumps core...
3278 f = pc;
3279 }
3280 }
3281
3282 /*-----------------------------------------------------------------*/
3283 /*-----------------------------------------------------------------*/
get_op(pCodeOp * pcop,char * buffer,size_t size)3284 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
3285 {
3286 reg_info *r;
3287 static char b[200];
3288 char *s;
3289 int use_buffer = 1; // copy the string to the passed buffer pointer
3290
3291 if(!buffer) {
3292 buffer = b;
3293 size = sizeof(b);
3294 use_buffer = 0; // Don't bother copying the string to the buffer.
3295 }
3296
3297 ASSERT(pcop);
3298 if(pcop) {
3299 switch(pcop->type) {
3300 case PO_INDF:
3301 case PO_FSR:
3302 ASSERT(PCOR(pcop)->r && PCOR(pcop)->r->name && 0 == strcmp(pcop->name,PCOR(pcop)->r->name));
3303 if(use_buffer) {
3304 SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
3305 return buffer;
3306 }
3307 return pcop->name;
3308 break;
3309 case PO_GPR_TEMP:
3310 ASSERT(PCOR(pcop)->r);
3311 if (PCOR(pcop)->r->type == REG_STK)
3312 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
3313 else
3314 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
3315
3316 ASSERT(r && r->name);
3317 if(use_buffer) {
3318 SNPRINTF(buffer,size,"%s",r->name);
3319 return buffer;
3320 }
3321
3322 return r->name;
3323 break;
3324
3325 case PO_IMMEDIATE:
3326 s = buffer;
3327 ASSERT(pcop->name && PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset <= 2 && PCOI(pcop)->index >= 0);
3328 if(PCOI(pcop)->_const) {
3329
3330 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
3331 switch(PCOI(pcop)->offset) {
3332 case 0:
3333 SNPRINTF(s,size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3334 break;
3335 case 1:
3336 SNPRINTF(s,size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3337 break;
3338 case 2:
3339 SNPRINTF(s,size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
3340 break;
3341 default:
3342 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3343 assert ( !"offset too large" );
3344 SNPRINTF(s,size,"(((%s+%d) >> %d)&0xff)",
3345 pcop->name,
3346 PCOI(pcop)->index,
3347 8 * PCOI(pcop)->offset );
3348 }
3349 } else
3350 SNPRINTF(s,size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3351 } else {
3352 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
3353 SNPRINTF(s,size,"(%s + %d)",
3354 pcop->name,
3355 PCOI(pcop)->index);
3356 } else {
3357 switch(PCOI(pcop)->offset) {
3358 case 0:
3359 SNPRINTF(s,size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3360 break;
3361 case 1:
3362 SNPRINTF(s,size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3363 break;
3364 case 2:
3365 SNPRINTF(s,size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
3366 break;
3367 default:
3368 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3369 assert ( !"offset too large" );
3370 SNPRINTF(s,size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3371 break;
3372 }
3373 }
3374 }
3375 return buffer;
3376 break;
3377
3378 case PO_DIR:
3379 s = buffer;
3380 ASSERT(pcop->name && PCOR(pcop)->instance >= 0);
3381 if( PCOR(pcop)->instance) {
3382 SNPRINTF(s,size,"(%s + %d)",
3383 pcop->name,
3384 PCOR(pcop)->instance );
3385 } else
3386 SNPRINTF(s,size,"%s",pcop->name);
3387 return buffer;
3388 break;
3389
3390 case PO_LABEL:
3391 s = buffer;
3392 ASSERT(pcop->name && PCOLAB(pcop)->offset >= 0 && PCOLAB(pcop)->offset <= 1);
3393 if (pcop->name) {
3394 if(PCOLAB(pcop)->offset == 1)
3395 SNPRINTF(s,size,"HIGH(%s)",pcop->name);
3396 else
3397 SNPRINTF(s,size,"%s",pcop->name);
3398 }
3399 return buffer;
3400 break;
3401
3402 case PO_GPR_BIT:
3403 ASSERT(PCOR(pcop)->r && PCOR(pcop)->r->name);
3404 if(PCOR(pcop)->r) {
3405 if(use_buffer) {
3406 SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
3407 return buffer;
3408 }
3409 return PCOR(pcop)->r->name;
3410 }
3411 /* fall through to the default case */
3412
3413 default:
3414 ASSERT(pcop->name);
3415 if(pcop->name) {
3416 if(use_buffer) {
3417 SNPRINTF(buffer,size,"%s",pcop->name);
3418 return buffer;
3419 }
3420 return pcop->name;
3421 }
3422 }
3423 }
3424
3425 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3426 __FILE__, __LINE__, __FUNCTION__,
3427 pCodeOpType(pcop));
3428
3429 return "NO operand";
3430 }
3431
3432 /*-----------------------------------------------------------------*/
3433 /*-----------------------------------------------------------------*/
get_op_from_instruction(pCodeInstruction * pcc)3434 static char *get_op_from_instruction( pCodeInstruction *pcc)
3435 {
3436 ASSERT(pcc != NULL);
3437 if(pcc)
3438 return get_op(pcc->pcop,NULL,0);
3439
3440 return ("ERROR Null: get_op_from_instruction");
3441 }
3442
3443 /*-----------------------------------------------------------------*/
3444 /*-----------------------------------------------------------------*/
pCodeOpPrint(FILE * of,pCodeOp * pcop)3445 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3446 {
3447 fprintf(of,"pcodeopprint- not implemented\n");
3448 }
3449
3450 /*-----------------------------------------------------------------*/
3451 /* pCode2str - convert a pCode instruction to string */
3452 /*-----------------------------------------------------------------*/
pCode2str(char * str,size_t size,pCode * pc)3453 char *pCode2str(char *str, size_t size, pCode *pc)
3454 {
3455 char *s = str;
3456
3457 switch(pc->type) {
3458
3459 case PC_OPCODE:
3460
3461 ASSERT(PCI(pc)->mnemonic);
3462 SNPRINTF(s,size, "\t%s\t", PCI(pc)->mnemonic);
3463 size -= strlen(s);
3464 s += strlen(s);
3465
3466 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3467 if(PCI(pc)->isBitInst) {
3468 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3469 char *name = PCI(pc)->pcop->name;
3470 if (!name)
3471 name = PCOR(PCI(pc)->pcop)->r->name;
3472 ASSERT(name);
3473 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3474 SNPRINTF(s,size,"(%s >> 3), (%s & 7)", name, name);
3475 else
3476 SNPRINTF(s,size,"%s,%d", name, (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3477 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3478 SNPRINTF(s,size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3479 } else
3480 SNPRINTF(s,size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3481 } else {
3482 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3483 if( PCI(pc)->num_ops == 2)
3484 SNPRINTF(s,size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3485 else
3486 SNPRINTF(s,size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3487 } else {
3488 SNPRINTF(s,size,"%s",get_op_from_instruction(PCI(pc)));
3489 size -= strlen(s);
3490 s += strlen(s);
3491 if( PCI(pc)->num_ops == 2)
3492 SNPRINTF(s,size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3493 }
3494 }
3495 }
3496 break;
3497
3498 case PC_COMMENT:
3499 /* assuming that comment ends with a \n */
3500 SNPRINTF(s,size,";%s", ((pCodeComment *)pc)->comment);
3501 break;
3502
3503 case PC_INLINE:
3504 /* assuming that inline code ends with a \n */
3505 SNPRINTF(s,size,"%s", ((pCodeComment *)pc)->comment);
3506 break;
3507
3508 case PC_LABEL:
3509 SNPRINTF(s,size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3510 break;
3511 case PC_FUNCTION:
3512 SNPRINTF(s,size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3513 break;
3514 case PC_WILD:
3515 SNPRINTF(s,size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3516 break;
3517 case PC_FLOW:
3518 SNPRINTF(s,size,";\t--FLOW change\n");
3519 break;
3520 case PC_CSOURCE:
3521 SNPRINTF(s,size,"%s\t.line\t%d; \"%s\"\t%s\n",(options.debug?"":";"),PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3522 break;
3523 case PC_ASMDIR:
3524 if(PCAD(pc)->directive) {
3525 SNPRINTF(s,size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3526 } else if(PCAD(pc)->arg) {
3527 /* special case to handle inline labels without a tab */
3528 SNPRINTF(s,size,"%s\n", PCAD(pc)->arg);
3529 }
3530 break;
3531
3532 case PC_BAD:
3533 SNPRINTF(s,size,";A bad pCode is being used\n");
3534 }
3535
3536 return str;
3537 }
3538
3539 /*-----------------------------------------------------------------*/
3540 /* genericPrint - the contents of a pCode to a file */
3541 /*-----------------------------------------------------------------*/
genericPrint(FILE * of,pCode * pc)3542 static void genericPrint(FILE *of, pCode *pc)
3543 {
3544 if(!pc || !of)
3545 return;
3546
3547 switch(pc->type) {
3548 case PC_COMMENT:
3549 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3550 break;
3551
3552 case PC_INLINE:
3553 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3554 break;
3555
3556 case PC_OPCODE:
3557 // If the opcode has a label, print that first
3558 {
3559 char str[256];
3560 pCodeInstruction *pci = PCI(pc);
3561 pBranch *pbl = pci->label;
3562 while(pbl && pbl->pc) {
3563 if(pbl->pc->type == PC_LABEL)
3564 pCodePrintLabel(of, pbl->pc);
3565 pbl = pbl->next;
3566 }
3567
3568 if(pci->cline)
3569 genericPrint(of,PCODE(pci->cline));
3570
3571
3572 pCode2str(str, sizeof(str), pc);
3573
3574 fprintf(of,"%s",str);
3575
3576 /* Debug */
3577 if(debug_verbose) {
3578 pCodeOpReg *pcor = PCOR(pci->pcop);
3579 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3580 if(pci->pcflow)
3581 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3582 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3583 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3584 }
3585 }
3586 fprintf(of,"\n");
3587 break;
3588
3589 case PC_WILD:
3590 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3591 if(PCW(pc)->pci.label)
3592 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3593
3594 if(PCW(pc)->operand) {
3595 fprintf(of,";\toperand ");
3596 pCodeOpPrint(of,PCW(pc)->operand );
3597 }
3598 break;
3599
3600 case PC_FLOW:
3601 if(debug_verbose) {
3602 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3603 if(PCFL(pc)->ancestor)
3604 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3605 fprintf(of,"\n");
3606 fprintf(of,"; from: ");
3607 {
3608 pCodeFlowLink *link;
3609 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3610 {
3611 fprintf(of,"%03x ",link->pcflow->pc.seq);
3612 }
3613 }
3614 fprintf(of,"; to: ");
3615 {
3616 pCodeFlowLink *link;
3617 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3618 {
3619 fprintf(of,"%03x ",link->pcflow->pc.seq);
3620 }
3621 }
3622 fprintf(of,"\n");
3623 }
3624 break;
3625
3626 case PC_CSOURCE:
3627 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3628 break;
3629
3630 case PC_ASMDIR:
3631 {
3632 pBranch *pbl = PCAD(pc)->pci.label;
3633 while(pbl && pbl->pc) {
3634 if(pbl->pc->type == PC_LABEL)
3635 pCodePrintLabel(of, pbl->pc);
3636 pbl = pbl->next;
3637 }
3638 }
3639 if(PCAD(pc)->directive) {
3640 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3641 } else
3642 if(PCAD(pc)->arg) {
3643 /* special case to handle inline labels without tab */
3644 fprintf(of, "%s\n", PCAD(pc)->arg);
3645 }
3646 break;
3647
3648 case PC_LABEL:
3649 default:
3650 fprintf(of,"unknown pCode type %d\n",pc->type);
3651 }
3652 }
3653
3654 /*-----------------------------------------------------------------*/
3655 /* pCodePrintFunction - prints function begin/end */
3656 /*-----------------------------------------------------------------*/
3657
pCodePrintFunction(FILE * of,pCode * pc)3658 static void pCodePrintFunction(FILE *of, pCode *pc)
3659 {
3660
3661 if(!pc || !of)
3662 return;
3663
3664 #if 0
3665 if( ((pCodeFunction *)pc)->modname)
3666 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3667 #endif
3668 if(PCF(pc)->fname) {
3669 pBranch *exits = PCF(pc)->to;
3670 int i=0;
3671
3672 fprintf(of, "%s:", PCF(pc)->fname);
3673
3674 if(options.verbose)
3675 fprintf(of, "\t;Function start");
3676
3677 fprintf(of, "\n");
3678
3679 while(exits) {
3680 i++;
3681 exits = exits->next;
3682 }
3683 //if(i) i--;
3684 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3685
3686 }else {
3687 if((PCF(pc)->from &&
3688 PCF(pc)->from->pc->type == PC_FUNCTION &&
3689 PCF(PCF(pc)->from->pc)->fname) )
3690 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3691 else
3692 fprintf(of,"; exit point [can't find entry point]\n");
3693 }
3694 }
3695
3696 /*-----------------------------------------------------------------*/
3697 /* pCodePrintLabel - prints label */
3698 /*-----------------------------------------------------------------*/
3699
pCodePrintLabel(FILE * of,pCode * pc)3700 static void pCodePrintLabel(FILE *of, pCode *pc)
3701 {
3702
3703 if(!pc || !of)
3704 return;
3705
3706 if(PCL(pc)->label)
3707 fprintf(of, "%s:\n", PCL(pc)->label);
3708 else if (PCL(pc)->key >= 0)
3709 fprintf(of, "_%05d_DS_:\n", PCL(pc)->key);
3710 else
3711 fprintf(of, ";wild card label: id=%d\n", -PCL(pc)->key);
3712
3713 }
3714
3715 /*-----------------------------------------------------------------*/
3716 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3717 /* remove it if it is found. */
3718 /*-----------------------------------------------------------------*/
unlinkpCodeFromBranch(pCode * pcl,pCode * pc)3719 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3720 {
3721 pBranch *b, *bprev;
3722
3723 bprev = NULL;
3724
3725 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3726 b = PCI(pcl)->label;
3727 else {
3728 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3729 exit(1);
3730 }
3731
3732 //fprintf (stderr, "%s \n",__FUNCTION__);
3733 //pcl->print(stderr,pcl);
3734 //pc->print(stderr,pc);
3735 while(b) {
3736 if(b->pc == pc) {
3737 //fprintf (stderr, "found label\n");
3738
3739 /* Found a label */
3740 if(bprev) {
3741 bprev->next = b->next; /* Not first pCode in chain */
3742 free(b);
3743 } else {
3744 pc->destruct(pc);
3745 PCI(pcl)->label = b->next; /* First pCode in chain */
3746 free(b);
3747 }
3748 return; /* A label can't occur more than once */
3749 }
3750 bprev = b;
3751 b = b->next;
3752 }
3753 }
3754
3755 /*-----------------------------------------------------------------*/
3756 /*-----------------------------------------------------------------*/
pBranchAppend(pBranch * h,pBranch * n)3757 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3758 {
3759 pBranch *b;
3760
3761 if(!h)
3762 return n;
3763
3764 if(h == n)
3765 return n;
3766
3767 b = h;
3768 while(b->next)
3769 b = b->next;
3770
3771 b->next = n;
3772
3773 return h;
3774
3775 }
3776
3777 /*-----------------------------------------------------------------*/
3778 /* pBranchLink - given two pcodes, this function will link them */
3779 /* together through their pBranches */
3780 /*-----------------------------------------------------------------*/
pBranchLink(pCodeFunction * f,pCodeFunction * t)3781 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3782 {
3783 pBranch *b;
3784
3785 // Declare a new branch object for the 'from' pCode.
3786
3787 //_ALLOC(b,sizeof(pBranch));
3788 b = Safe_alloc(sizeof(pBranch));
3789 b->pc = PCODE(t); // The link to the 'to' pCode.
3790 b->next = NULL;
3791
3792 f->to = pBranchAppend(f->to,b);
3793
3794 // Now do the same for the 'to' pCode.
3795
3796 //_ALLOC(b,sizeof(pBranch));
3797 b = Safe_alloc(sizeof(pBranch));
3798 b->pc = PCODE(f);
3799 b->next = NULL;
3800
3801 t->from = pBranchAppend(t->from,b);
3802
3803 }
3804
3805 /*-----------------------------------------------------------------*/
3806 /*-----------------------------------------------------------------*/
compareLabel(pCode * pc,pCodeOpLabel * pcop_label)3807 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3808 {
3809 pBranch *pbr;
3810
3811 if(pc->type == PC_LABEL) {
3812 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3813 return TRUE;
3814 }
3815 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3816 pbr = PCI(pc)->label;
3817 while(pbr) {
3818 if(pbr->pc->type == PC_LABEL) {
3819 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3820 return TRUE;
3821 }
3822 pbr = pbr->next;
3823 }
3824 }
3825
3826 return FALSE;
3827 }
3828
3829 /*-----------------------------------------------------------------*/
3830 /*-----------------------------------------------------------------*/
checkLabel(pCode * pc)3831 static int checkLabel(pCode *pc)
3832 {
3833 pBranch *pbr;
3834
3835 if(pc && isPCI(pc)) {
3836 pbr = PCI(pc)->label;
3837 while(pbr) {
3838 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3839 return TRUE;
3840
3841 pbr = pbr->next;
3842 }
3843 }
3844
3845 return FALSE;
3846 }
3847
3848 /*-----------------------------------------------------------------*/
3849 /* findLabelinpBlock - Search the pCode for a particular label */
3850 /*-----------------------------------------------------------------*/
findLabelinpBlock(pBlock * pb,pCodeOpLabel * pcop_label)3851 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3852 {
3853 pCode *pc;
3854
3855 if(!pb)
3856 return NULL;
3857
3858 for(pc = pb->pcHead; pc; pc = pc->next)
3859 if(compareLabel(pc,pcop_label))
3860 return pc;
3861
3862 return NULL;
3863 }
3864
3865 /*-----------------------------------------------------------------*/
3866 /* findNextpCode - given a pCode, find the next of type 'pct' */
3867 /* in the linked list */
3868 /*-----------------------------------------------------------------*/
findNextpCode(pCode * pc,PC_TYPE pct)3869 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3870 {
3871
3872 while(pc) {
3873 if(pc->type == pct)
3874 return pc;
3875
3876 pc = pc->next;
3877 }
3878
3879 return NULL;
3880 }
3881
3882 #if 0
3883 /*-----------------------------------------------------------------*/
3884 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3885 /* in the linked list */
3886 /*-----------------------------------------------------------------*/
3887 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3888 {
3889
3890 while(pc) {
3891 if(pc->type == pct) {
3892 /*
3893 static unsigned int stop;
3894 if (pc->id == 524)
3895 stop++; // Place break point here
3896 */
3897 return pc;
3898 }
3899
3900 pc = pc->prev;
3901 }
3902
3903 return NULL;
3904 }
3905 #endif
3906
3907 /*-----------------------------------------------------------------*/
3908 /* findNextInstruction - given a pCode, find the next instruction */
3909 /* in the linked list */
3910 /*-----------------------------------------------------------------*/
findNextInstruction(pCode * pci)3911 pCode * findNextInstruction(pCode *pci)
3912 {
3913 pCode *pc = pci;
3914
3915 while(pc) {
3916 if((pc->type == PC_OPCODE)
3917 || (pc->type == PC_WILD)
3918 || (pc->type == PC_ASMDIR))
3919 return pc;
3920
3921 #ifdef PCODE_DEBUG
3922 fprintf(stderr,"findNextInstruction: ");
3923 printpCode(stderr, pc);
3924 #endif
3925 pc = pc->next;
3926 }
3927
3928 //fprintf(stderr,"Couldn't find instruction\n");
3929 return NULL;
3930 }
3931
3932 /*-----------------------------------------------------------------*/
3933 /* findNextInstruction - given a pCode, find the next instruction */
3934 /* in the linked list */
3935 /*-----------------------------------------------------------------*/
findPrevInstruction(pCode * pci)3936 pCode * findPrevInstruction(pCode *pci)
3937 {
3938 pCode *pc = pci;
3939
3940 while(pc) {
3941
3942 if((pc->type == PC_OPCODE)
3943 || (pc->type == PC_WILD)
3944 || (pc->type == PC_ASMDIR))
3945 return pc;
3946
3947
3948 #ifdef PCODE_DEBUG
3949 fprintf(stderr,"pic16_findPrevInstruction: ");
3950 printpCode(stderr, pc);
3951 #endif
3952 pc = pc->prev;
3953 }
3954
3955 //fprintf(stderr,"Couldn't find instruction\n");
3956 return NULL;
3957 }
3958
3959 /*-----------------------------------------------------------------*/
3960 /*-----------------------------------------------------------------*/
getRegFromInstruction(pCode * pc)3961 reg_info * getRegFromInstruction(pCode *pc)
3962 {
3963 reg_info *r;
3964 if(!pc ||
3965 !isPCI(pc) ||
3966 !PCI(pc)->pcop ||
3967 PCI(pc)->num_ops == 0 )
3968 return NULL;
3969
3970 switch(PCI(pc)->pcop->type) {
3971 case PO_STATUS:
3972 case PO_FSR:
3973 case PO_INDF:
3974 case PO_INTCON:
3975 case PO_BIT:
3976 case PO_GPR_TEMP:
3977 case PO_SFR_REGISTER:
3978 case PO_PCL:
3979 case PO_PCLATH:
3980 return PCOR(PCI(pc)->pcop)->r;
3981
3982 case PO_GPR_REGISTER:
3983 case PO_GPR_BIT:
3984 case PO_DIR:
3985 r = PCOR(PCI(pc)->pcop)->r;
3986 if (r)
3987 return r;
3988 return dirregWithName(PCI(pc)->pcop->name);
3989
3990 case PO_LITERAL:
3991 break;
3992
3993 case PO_IMMEDIATE:
3994 r = PCOI(PCI(pc)->pcop)->r;
3995 if (r)
3996 return r;
3997 return dirregWithName(PCI(pc)->pcop->name);
3998
3999 default:
4000 break;
4001 }
4002
4003 return NULL;
4004
4005 }
4006
4007 /*-----------------------------------------------------------------*/
4008 /*-----------------------------------------------------------------*/
4009
AnalyzepBlock(pBlock * pb)4010 static void AnalyzepBlock(pBlock *pb)
4011 {
4012 pCode *pc;
4013
4014 if(!pb)
4015 return;
4016
4017 /* Find all of the registers used in this pBlock
4018 * by looking at each instruction and examining it's
4019 * operands
4020 */
4021 for(pc = pb->pcHead; pc; pc = pc->next) {
4022
4023 /* Is this an instruction with operands? */
4024 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4025
4026 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
4027 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
4028
4029 /* Loop through all of the registers declared so far in
4030 this block and see if we find this one there */
4031
4032 reg_info *r = setFirstItem(pb->tregisters);
4033
4034 while(r) {
4035 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
4036 PCOR(PCI(pc)->pcop)->r = r;
4037 break;
4038 }
4039 r = setNextItem(pb->tregisters);
4040 }
4041
4042 if(!r) {
4043 /* register wasn't found */
4044 //r = Safe_alloc(sizeof(regs));
4045 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
4046 //addSet(&pb->tregisters, r);
4047 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
4048 //PCOR(PCI(pc)->pcop)->r = r;
4049 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
4050 }/* else
4051 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
4052 */
4053 }
4054 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
4055 if(PCOR(PCI(pc)->pcop)->r) {
4056 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
4057 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
4058 } else {
4059 if(PCI(pc)->pcop->name)
4060 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
4061 else
4062 fprintf(stderr,"ERROR: NULL register\n");
4063 }
4064 }
4065 }
4066
4067
4068 }
4069 }
4070
4071 /*-----------------------------------------------------------------*/
4072 /* */
4073 /*-----------------------------------------------------------------*/
InsertpFlow(pCode * pc,pCode ** pflow)4074 static void InsertpFlow(pCode *pc, pCode **pflow)
4075 {
4076 if(*pflow)
4077 PCFL(*pflow)->end = pc;
4078
4079 if(!pc || !pc->next)
4080 return;
4081
4082 *pflow = newpCodeFlow();
4083 pCodeInsertAfter(pc, *pflow);
4084 }
4085
4086 /*-----------------------------------------------------------------*/
4087 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4088 /* the flow blocks. */
4089 /*
4090 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
4091 * point the instruction flow changes.
4092 */
4093 /*-----------------------------------------------------------------*/
BuildFlow(pBlock * pb)4094 static void BuildFlow(pBlock *pb)
4095 {
4096 pCode *pc;
4097 pCode *last_pci=NULL;
4098 pCode *pflow=NULL;
4099 int seq = 0;
4100
4101 if(!pb)
4102 return;
4103
4104 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
4105 /* Insert a pCodeFlow object at the beginning of a pBlock */
4106
4107 InsertpFlow(pb->pcHead, &pflow);
4108
4109 //pflow = newpCodeFlow(); /* Create a new Flow object */
4110 //pflow->next = pb->pcHead; /* Make the current head the next object */
4111 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
4112 //pb->pcHead = pflow; /* Make the Flow object the head */
4113 //pflow->pb = pb;
4114
4115 for( pc = findNextInstruction(pb->pcHead);
4116 pc != NULL;
4117 pc=findNextInstruction(pc)) {
4118
4119 pc->seq = seq++;
4120 PCI(pc)->pcflow = PCFL(pflow);
4121
4122 //fprintf(stderr," build: ");
4123 //pc->print(stderr, pc);
4124 //pflow->print(stderr,pflow);
4125
4126 if (checkLabel(pc)) {
4127
4128 /* This instruction marks the beginning of a
4129 * new flow segment */
4130
4131 pc->seq = 0;
4132 seq = 1;
4133
4134 /* If the previous pCode is not a flow object, then
4135 * insert a new flow object. (This check prevents
4136 * two consecutive flow objects from being insert in
4137 * the case where a skip instruction preceeds an
4138 * instruction containing a label.) */
4139
4140 last_pci = findPrevInstruction (pc->prev);
4141
4142 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4143 InsertpFlow(last_pci, &pflow);
4144
4145 PCI(pc)->pcflow = PCFL(pflow);
4146
4147 }
4148
4149 if(isPCI_SKIP(pc)) {
4150
4151 /* The two instructions immediately following this one
4152 * mark the beginning of a new flow segment */
4153
4154 while(pc && isPCI_SKIP(pc)) {
4155
4156 PCI(pc)->pcflow = PCFL(pflow);
4157 pc->seq = seq-1;
4158 seq = 1;
4159
4160 InsertpFlow(pc, &pflow);
4161 pc=findNextInstruction(pc->next);
4162 }
4163
4164 seq = 0;
4165
4166 if(!pc)
4167 break;
4168
4169 PCI(pc)->pcflow = PCFL(pflow);
4170 pc->seq = 0;
4171 InsertpFlow(pc, &pflow);
4172
4173 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
4174
4175 InsertpFlow(pc, &pflow);
4176 seq = 0;
4177
4178 }
4179
4180 last_pci = pc;
4181 pc = pc->next;
4182 }
4183
4184 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4185 if(pflow)
4186 PCFL(pflow)->end = pb->pcTail;
4187 }
4188
4189 /*-------------------------------------------------------------------*/
4190 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4191 /* the flow blocks. */
4192 /*
4193 * unBuildFlow removes pCodeFlow objects from a pCode chain
4194 */
4195 /*-----------------------------------------------------------------*/
unBuildFlow(pBlock * pb)4196 static void unBuildFlow(pBlock *pb)
4197 {
4198 pCode *pc,*pcnext;
4199
4200 if(!pb)
4201 return;
4202
4203 pc = pb->pcHead;
4204
4205 while(pc) {
4206 pcnext = pc->next;
4207
4208 if(isPCI(pc)) {
4209
4210 pc->seq = 0;
4211 if(PCI(pc)->pcflow) {
4212 //free(PCI(pc)->pcflow);
4213 PCI(pc)->pcflow = NULL;
4214 }
4215
4216 } else if(isPCFL(pc) )
4217 pc->destruct(pc);
4218
4219 pc = pcnext;
4220 }
4221
4222
4223 }
4224
4225 #if 0
4226 /*-----------------------------------------------------------------*/
4227 /*-----------------------------------------------------------------*/
4228 static void dumpCond(int cond)
4229 {
4230
4231 static char *pcc_str[] = {
4232 //"PCC_NONE",
4233 "PCC_REGISTER",
4234 "PCC_C",
4235 "PCC_Z",
4236 "PCC_DC",
4237 "PCC_W",
4238 "PCC_EXAMINE_PCOP",
4239 "PCC_REG_BANK0",
4240 "PCC_REG_BANK1",
4241 "PCC_REG_BANK2",
4242 "PCC_REG_BANK3"
4243 };
4244
4245 int ncond = sizeof(pcc_str) / sizeof(char *);
4246 int i,j;
4247
4248 fprintf(stderr, "0x%04X\n",cond);
4249
4250 for(i=0,j=1; i<ncond; i++, j<<=1)
4251 if(cond & j)
4252 fprintf(stderr, " %s\n",pcc_str[i]);
4253
4254 }
4255 #endif
4256
4257 #if 0
4258 /*-----------------------------------------------------------------*/
4259 /*-----------------------------------------------------------------*/
4260 static void FlowStats(pCodeFlow *pcflow)
4261 {
4262
4263 pCode *pc;
4264
4265 if(!isPCFL(pcflow))
4266 return;
4267
4268 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4269
4270 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4271
4272 if(!pc) {
4273 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4274 return;
4275 }
4276
4277
4278 fprintf(stderr, " FlowStats inCond: ");
4279 dumpCond(pcflow->inCond);
4280 fprintf(stderr, " FlowStats outCond: ");
4281 dumpCond(pcflow->outCond);
4282
4283 }
4284 #endif
4285
4286 /*-----------------------------------------------------------------*
4287 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4288 * if it affects the banking bits.
4289 *
4290 * return: -1 == Banking bits are unaffected by this pCode.
4291 *
4292 * return: > 0 == Banking bits are affected.
4293 *
4294 * If the banking bits are affected, then the returned value describes
4295 * which bits are affected and how they're affected. The lower half
4296 * of the integer maps to the bits that are affected, the upper half
4297 * to whether they're set or cleared.
4298 *
4299 *-----------------------------------------------------------------*/
4300 /*
4301 static int isBankInstruction(pCode *pc)
4302 {
4303 regs *reg;
4304 int bank = -1;
4305
4306 if(!isPCI(pc))
4307 return -1;
4308
4309 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4310
4311 // Check to see if the register banks are changing
4312 if(PCI(pc)->isModReg) {
4313
4314 pCodeOp *pcop = PCI(pc)->pcop;
4315 switch(PCI(pc)->op) {
4316
4317 case POC_BSF:
4318 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4319 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4320 return SET_BANK_BIT | PIC_RP0_BIT;
4321 }
4322
4323 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4324 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4325 return CLR_BANK_BIT | PIC_RP0_BIT;
4326 }
4327 break;
4328
4329 case POC_BCF:
4330 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4331 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4332 return CLR_BANK_BIT | PIC_RP1_BIT;
4333 }
4334 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4335 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4336 return CLR_BANK_BIT | PIC_RP1_BIT;
4337 }
4338 break;
4339 default:
4340 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4341 //genericPrint(stderr, pc);
4342 ;
4343 }
4344 }
4345
4346 }
4347
4348 return bank;
4349 }
4350 */
4351
4352 /*-----------------------------------------------------------------*/
4353 /*-----------------------------------------------------------------*/
4354 /*
4355 static void FillFlow(pCodeFlow *pcflow)
4356 {
4357 pCode *pc;
4358 int cur_bank;
4359
4360 if(!isPCFL(pcflow))
4361 return;
4362
4363 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4364
4365 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4366
4367 if(!pc) {
4368 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4369 return;
4370 }
4371
4372 cur_bank = -1;
4373
4374 do {
4375 isBankInstruction(pc);
4376 pc = pc->next;
4377 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4378 / *
4379 if(!pc ) {
4380 fprintf(stderr, " FillFlow - Bad end of flow\n");
4381 } else {
4382 fprintf(stderr, " FillFlow - Ending flow with\n ");
4383 pc->print(stderr,pc);
4384 }
4385
4386 fprintf(stderr, " FillFlow inCond: ");
4387 dumpCond(pcflow->inCond);
4388 fprintf(stderr, " FillFlow outCond: ");
4389 dumpCond(pcflow->outCond);
4390 * /
4391 }
4392 */
4393
4394 /*-----------------------------------------------------------------*/
4395 /*-----------------------------------------------------------------*/
LinkFlow_pCode(pCodeInstruction * from,pCodeInstruction * to)4396 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4397 {
4398 pCodeFlowLink *fromLink, *toLink;
4399 #if 0
4400 fprintf(stderr, "%s: linking ", __FUNCTION__ );
4401 if (from) from->pc.print(stderr, &from->pc);
4402 else fprintf(stderr, "(null)");
4403 fprintf(stderr, " -(%u)-> with -(%u)-> ",
4404 from && from->pcflow ? from->pcflow->pc.seq : 0,
4405 to && to->pcflow ? to->pcflow->pc.seq : 0);
4406 if (to) to->pc.print(stderr, &to->pc);
4407 else fprintf(stderr, "(null)");
4408 #endif
4409
4410 if(!from || !to || !to->pcflow || !from->pcflow)
4411 return;
4412
4413 fromLink = newpCodeFlowLink(from->pcflow);
4414 toLink = newpCodeFlowLink(to->pcflow);
4415
4416 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4417 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4418
4419 }
4420
4421 /*-----------------------------------------------------------------*
4422 * void LinkFlow(pBlock *pb)
4423 *
4424 * In BuildFlow, the PIC code has been partitioned into contiguous
4425 * non-branching segments. In LinkFlow, we determine the execution
4426 * order of these segments. For example, if one of the segments ends
4427 * with a skip, then we know that there are two possible flow segments
4428 * to which control may be passed.
4429 *-----------------------------------------------------------------*/
LinkFlow(pBlock * pb)4430 static void LinkFlow(pBlock *pb)
4431 {
4432 pCode *pc=NULL;
4433 pCode *pcflow;
4434 pCode *pct;
4435
4436 //fprintf(stderr,"linkflow \n");
4437
4438 if (!pb) return;
4439
4440 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4441 pcflow != NULL;
4442 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4443
4444 if(!isPCFL(pcflow))
4445 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4446
4447 //fprintf(stderr," link: ");
4448 //pcflow->print(stderr,pcflow);
4449
4450 //FillFlow(PCFL(pcflow));
4451
4452 /* find last instruction in flow */
4453 pc = findPrevInstruction (PCFL(pcflow)->end);
4454 if (!pc) {
4455 fprintf(stderr, "%s: flow without end (%u)?\n",
4456 __FUNCTION__, pcflow->seq );
4457 continue;
4458 }
4459
4460 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4461 //pc->print(stderr, pc);
4462 if(isPCI_SKIP(pc)) {
4463 //fprintf(stderr, "ends with skip\n");
4464 //pc->print(stderr,pc);
4465 pct=findNextInstruction(pc->next);
4466 LinkFlow_pCode(PCI(pc),PCI(pct));
4467 pct=findNextInstruction(pct->next);
4468 LinkFlow_pCode(PCI(pc),PCI(pct));
4469 continue;
4470 }
4471
4472 if(isPCI_BRANCH(pc)) {
4473 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4474
4475 //fprintf(stderr, "ends with branch\n ");
4476 //pc->print(stderr,pc);
4477
4478 if(!(pcol && isPCOLAB(pcol))) {
4479 if((PCI(pc)->op != POC_RETLW)
4480 && (PCI(pc)->op != POC_RETURN)
4481 && (PCI(pc)->op != POC_CALL)
4482 && (PCI(pc)->op != POC_RETFIE) )
4483 {
4484 pc->print(stderr,pc);
4485 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4486 }
4487 } else {
4488
4489 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4490 LinkFlow_pCode(PCI(pc),PCI(pct));
4491 else
4492 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4493 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4494 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4495 }
4496 /* link CALLs to next instruction */
4497 if (PCI(pc)->op != POC_CALL) continue;
4498 }
4499
4500 if(isPCI(pc)) {
4501 //fprintf(stderr, "ends with non-branching instruction:\n");
4502 //pc->print(stderr,pc);
4503
4504 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4505
4506 continue;
4507 }
4508
4509 if(pc) {
4510 //fprintf(stderr, "ends with unknown\n");
4511 //pc->print(stderr,pc);
4512 continue;
4513 }
4514
4515 fprintf(stderr, "ends with nothing: ERROR\n");
4516
4517 }
4518 }
4519
pCodeReplace(pCode * old,pCode * new)4520 static void pCodeReplace (pCode *old, pCode *new)
4521 {
4522 pCodeInsertAfter (old, new);
4523
4524 /* special handling for pCodeInstructions */
4525 if (isPCI(new) && isPCI(old))
4526 {
4527 //assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4528 PCI(new)->from = PCI(old)->from;
4529 PCI(new)->to = PCI(old)->to;
4530 PCI(new)->label = PCI(old)->label;
4531 PCI(new)->pcflow = PCI(old)->pcflow;
4532 PCI(new)->cline = PCI(old)->cline;
4533 } // if
4534
4535 old->destruct (old);
4536 }
4537
4538 /*-----------------------------------------------------------------*/
4539 /*-----------------------------------------------------------------*/
addpCodeComment(pCode * pc,const char * fmt,...)4540 static void addpCodeComment(pCode *pc, const char *fmt, ...)
4541 {
4542 va_list ap;
4543 char buffer[4096];
4544 pCode *newpc;
4545
4546 va_start(ap, fmt);
4547 if (options.verbose || debug_verbose) {
4548 buffer[0] = ';';
4549 buffer[1] = ' ';
4550 vsnprintf(&buffer[2], sizeof(buffer)-2, fmt, ap);
4551
4552 newpc = newpCodeCharP(&buffer[0]); // strdup's the string
4553 pCodeInsertAfter(pc, newpc);
4554 }
4555 va_end(ap);
4556 }
4557
4558 /*-----------------------------------------------------------------*/
4559 /* Inserts a new pCodeInstruction before an existing one */
4560 /*-----------------------------------------------------------------*/
insertPCodeInstruction(pCodeInstruction * pci,pCodeInstruction * new_pci)4561 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4562 {
4563 pCode *pcprev;
4564
4565 pcprev = findPrevInstruction(pci->pc.prev);
4566
4567 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4568
4569 /* Move the label, if there is one */
4570
4571 if(pci->label) {
4572 new_pci->label = pci->label;
4573 pci->label = NULL;
4574 }
4575
4576 /* Move the C code comment, if there is one */
4577
4578 if(pci->cline) {
4579 new_pci->cline = pci->cline;
4580 pci->cline = NULL;
4581 }
4582
4583 /* The new instruction has the same pcflow block */
4584 new_pci->pcflow = pci->pcflow;
4585
4586 /* Arrrrg: is pci's previous instruction is a skip, we need to
4587 * change that into a jump (over pci and the new instruction) ... */
4588 if (pcprev && isPCI_SKIP(pcprev))
4589 {
4590 symbol *lbl = newiTempLabel (NULL);
4591 pCode *label = newpCodeLabel (NULL, lbl->key);
4592 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4593
4594 pCodeInsertAfter (pcprev, jump);
4595
4596 // Yuck: Cannot simply replace INCFSZ/INCFSZW/DECFSZ/DECFSZW
4597 // We replace them with INCF/INCFW/DECF/DECFW followed by 'BTFSS STATUS, Z'
4598 switch (PCI(pcprev)->op) {
4599 case POC_INCFSZ:
4600 case POC_INCFSZW:
4601 case POC_DECFSZ:
4602 case POC_DECFSZW:
4603 // These are turned into non-skipping instructions, so
4604 // insert 'BTFSC STATUS, Z' after pcprev
4605 pCodeInsertAfter (jump->prev, newpCode(POC_BTFSC, popCopyGPR2Bit(PCOP(&pc_status), PIC_Z_BIT)));
4606 break;
4607 default:
4608 // no special actions required
4609 break;
4610 }
4611 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4612 pcprev = NULL;
4613 pCodeInsertAfter((pCode*)pci, label);
4614 pBlockMergeLabels(pci->pc.pb);
4615 }
4616 }
4617
4618 /*-----------------------------------------------------------------*/
4619 /*-----------------------------------------------------------------*/
insertBankSel(pCodeInstruction * pci,const char * name)4620 static int insertBankSel(pCodeInstruction *pci, const char *name)
4621 {
4622 pCode *new_pc;
4623
4624 pCodeOp *pcop;
4625
4626 // Never BANKSEL STATUS, this breaks all kinds of code (e.g., interrupt handlers).
4627 if (!strcmp("STATUS", name) || !strcmp("_STATUS", name)) return 0;
4628
4629 pcop = popCopyReg(PCOR(pci->pcop));
4630 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4631 if (pcop->name == 0)
4632 pcop->name = strdup(name);
4633 new_pc = newpCode(POC_BANKSEL, pcop);
4634
4635 insertPCodeInstruction(pci, PCI(new_pc));
4636 return 1;
4637 }
4638
4639 /*
4640 * isValidIdChar - check if c may be present in an identifier
4641 */
isValidIdChar(char c)4642 static int isValidIdChar (char c)
4643 {
4644 if (c >= 'a' && c <= 'z') return 1;
4645 if (c >= 'A' && c <= 'Z') return 1;
4646 if (c >= '0' && c <= '9') return 1;
4647 if (c == '_') return 1;
4648 return 0;
4649 }
4650
4651 /*
4652 * bankcompare - check if two operand string refer to the same register
4653 * This functions handles NAME and (NAME + x) in both operands.
4654 * Returns 1 on same register, 0 on different (or unknown) registers.
4655 */
bankCompare(const char * op1,const char * op2)4656 static int bankCompare(const char *op1, const char *op2)
4657 {
4658 int i;
4659
4660 if (!op1 && !op2) return 0; // both unknown, might be different though!
4661 if (!op1 || !op2) return 0;
4662
4663 // find start of operand name
4664 while (op1[0] == '(' || op1[0] == ' ') op1++;
4665 while (op2[0] == '(' || op2[0] == ' ') op2++;
4666
4667 // compare till first non-identifier character
4668 for (i = 0; (op1[i] == op2[i]) && isValidIdChar(op1[i]); i++);
4669 if (!isValidIdChar(op1[i]) && !isValidIdChar(op2[i])) return 1;
4670
4671 // play safe---assume different operands
4672 return 0;
4673 }
4674
4675 /*
4676 * Interface to BANKSEL generation.
4677 * This function should return != 0 iff str1 and str2 denote operands that
4678 * are known to be allocated into the same bank. Consequently, there will
4679 * be no BANKSEL emitted if str2 is accessed while str1 has been used to
4680 * select the current bank just previously.
4681 *
4682 * If in doubt, return 0.
4683 */
4684 static int
pic14_operandsAllocatedInSameBank(const char * str1,const char * str2)4685 pic14_operandsAllocatedInSameBank(const char *str1, const char *str2) {
4686 // see glue.c(pic14printLocals)
4687
4688 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
4689 // no clustering applied, each register resides in its own bank
4690 } else {
4691 // check whether BOTH names are local registers
4692 // XXX: This is some kind of shortcut, should be safe...
4693 // In this model, all r0xXXXX are allocated into a single section
4694 // per file, so no BANKSEL required if accessing a r0xXXXX after a
4695 // (different) r0xXXXX. Works great for multi-byte operands.
4696 if (str1 && str2 && str1[0] == 'r' && str2[0] == 'r') return (1);
4697 } // if
4698
4699 // assume operands in different banks
4700 return (0);
4701 }
4702
4703 /*-----------------------------------------------------------------*/
4704 /*-----------------------------------------------------------------*/
sameBank(reg_info * reg,reg_info * previous_reg,const char * new_bank,const char * cur_bank,unsigned max_mask)4705 static int sameBank(reg_info *reg, reg_info *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
4706 {
4707 if (!cur_bank) return 0;
4708
4709 if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask))) // only if exists
4710 return 1; // if we have address info, we use it for banksel optimization
4711
4712 // regard '(regname + X)' and '(regname + Y)' as equal
4713 if (reg && reg->name && bankCompare(reg->name, cur_bank)) return 1;
4714 if (new_bank && bankCompare(new_bank, cur_bank)) return 1;
4715
4716 // check allocation policy from glue.c
4717 if (reg && reg->name && pic14_operandsAllocatedInSameBank(reg->name, cur_bank)) return 1;
4718 if (new_bank && pic14_operandsAllocatedInSameBank(new_bank, cur_bank)) return 1;
4719
4720 // seems to be a different operand--might be a different bank
4721 //printf ("BANKSEL from %s to %s/%s\n", cur_bank, reg->name, new_bank);
4722 return 0;
4723 }
4724
4725 /*-----------------------------------------------------------------*/
4726 /*-----------------------------------------------------------------*/
FixRegisterBanking(pBlock * pb)4727 static void FixRegisterBanking(pBlock *pb)
4728 {
4729 pCode *pc;
4730 pCodeInstruction *pci;
4731 reg_info *reg;
4732 reg_info *previous_reg; // contains the previous variable access info
4733 const char *cur_bank, *new_bank;
4734 unsigned cur_mask, new_mask, max_mask;
4735 int allRAMmshared;
4736
4737 if (!pb) return;
4738
4739 max_mask = pic14_getPIC()->bankMask;
4740 cur_mask = max_mask;
4741 cur_bank = NULL;
4742 previous_reg = NULL;
4743
4744 allRAMmshared = pic14_allRAMShared();
4745
4746 for (pc = pb->pcHead; pc; pc = pc->next)
4747 {
4748 // this one has a label---might check bank at all jumps here...
4749 if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
4750 addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
4751 previous_reg = NULL;
4752 cur_bank = NULL; // start new flow
4753 cur_mask = max_mask;
4754 }
4755
4756 // this one is/might be a label or BANKSEL---assume nothing
4757 if (isPCL(pc) || isPCASMDIR(pc)) {
4758 addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
4759 previous_reg = NULL;
4760 cur_bank = NULL;
4761 cur_mask = max_mask;
4762 }
4763
4764 // this one modifies STATUS
4765 // XXX: this should be checked, but usually BANKSELs are not done this way in generated code
4766
4767 if (isPCI(pc)) {
4768 pci = PCI(pc);
4769 if ((pci->inCond | pci->outCond) & PCC_REGISTER) {
4770 // might need a BANKSEL
4771 reg = getRegFromInstruction(pc);
4772
4773 if (reg) {
4774 new_bank = reg->name;
4775 // reg->alias == 0: reg is in only one bank, we do not know which (may be any bank)
4776 // reg->alias != 0: reg is in 2/4/8/2**N banks, we select one of them
4777 new_mask = reg->alias;
4778 } else if (pci->pcop && pci->pcop->name) {
4779 new_bank = pci->pcop->name;
4780 new_mask = 0; // unknown, assume worst case
4781 } else {
4782 assert(!"Could not get register from instruction.");
4783 new_bank = "UNKNOWN";
4784 new_mask = 0; // unknown, assume worst case
4785 }
4786
4787 // optimizations...
4788 // XXX: add switch to disable these
4789 if (1) {
4790 // reg present in all banks possibly selected?
4791 if (new_mask == max_mask || (cur_mask && ((new_mask & cur_mask) == cur_mask))) {
4792 // no BANKSEL required
4793 addpCodeComment(pc->prev, "BANKOPT1 BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4794 continue;
4795 }
4796
4797 // only one bank of memory and no SFR accessed?
4798 // XXX: We can do better with fixed registers.
4799 if (allRAMmshared && reg && (reg->type != REG_SFR) && (!reg->isFixed)) {
4800 // no BANKSEL required
4801 addpCodeComment(pc->prev, "BANKOPT1b BANKSEL dropped; %s present in all (of %s's) banks", new_bank, cur_bank);
4802 continue;
4803 }
4804
4805 if (sameBank(reg, previous_reg, new_bank, cur_bank, max_mask)) {
4806 // no BANKSEL required
4807 addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
4808 continue;
4809 }
4810 } // if
4811
4812 if (insertBankSel(pci, new_bank)) {
4813 cur_mask = new_mask;
4814 cur_bank = new_bank;
4815 previous_reg = reg;
4816 } // if
4817 } // if
4818 } // if
4819 } // for
4820 }
4821
4822 /*-----------------------------------------------------------------*/
4823 /*-----------------------------------------------------------------*/
OptimizepBlock(pBlock * pb)4824 static int OptimizepBlock(pBlock *pb)
4825 {
4826 pCode *pc, *pcprev;
4827 int matches =0;
4828
4829 if(!pb || options.nopeep)
4830 return 0;
4831
4832 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4833 /*
4834 for(pc = pb->pcHead; pc; pc = pc->next)
4835 matches += pCodePeepMatchRule(pc);
4836 */
4837
4838 pc = findNextInstruction(pb->pcHead);
4839 if(!pc)
4840 return 0;
4841
4842 pcprev = pc->prev;
4843 do {
4844 if(pCodePeepMatchRule(pc)) {
4845 matches++;
4846
4847 if(pcprev)
4848 pc = findNextInstruction(pcprev->next);
4849 else
4850 pc = findNextInstruction(pb->pcHead);
4851 } else
4852 pc = findNextInstruction(pc->next);
4853 } while(pc);
4854
4855 if(matches)
4856 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4857
4858 return matches;
4859 }
4860
4861 /*-----------------------------------------------------------------*/
4862 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4863 /*-----------------------------------------------------------------*/
findInstructionUsingLabel(pCodeLabel * pcl,pCode * pcs)4864 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4865 {
4866 pCode *pc;
4867
4868 for(pc = pcs; pc; pc = pc->next) {
4869
4870 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4871 (PCI(pc)->pcop) &&
4872 (PCI(pc)->pcop->type == PO_LABEL) &&
4873 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4874 return pc;
4875 }
4876
4877 return NULL;
4878 }
4879
4880 /*-----------------------------------------------------------------*/
4881 /*-----------------------------------------------------------------*/
exchangeLabels(pCodeLabel * pcl,pCode * pc)4882 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4883 {
4884 const char *s;
4885
4886 if(isPCI(pc) &&
4887 (PCI(pc)->pcop) &&
4888 (PCI(pc)->pcop->type == PO_LABEL)) {
4889
4890 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4891
4892 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4893 if(pcol->pcop.name)
4894 free(pcol->pcop.name);
4895
4896 /* If the key is negative, then we (probably) have a label to
4897 * a function and the name is already defined */
4898
4899 if(pcl->key>0) {
4900 SNPRINTF(buffer, sizeof(buffer), "_%05d_DS_", pcl->key);
4901 s = buffer;
4902 } else
4903 s = pcl->label;
4904
4905 //SNPRINTF(buffer, sizeof(buffer), "_%05d_DS_", pcl->key);
4906 if(!s) {
4907 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4908 }
4909 pcol->pcop.name = Safe_strdup(s);
4910 pcol->key = pcl->key;
4911 //pc->print(stderr,pc);
4912 }
4913 }
4914
4915 /*-----------------------------------------------------------------*/
4916 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4917 /* pCode chain if they're not used. */
4918 /*-----------------------------------------------------------------*/
pBlockRemoveUnusedLabels(pBlock * pb)4919 static void pBlockRemoveUnusedLabels(pBlock *pb)
4920 {
4921 pCode *pc; pCodeLabel *pcl;
4922
4923 if(!pb || !pb->pcHead)
4924 return;
4925
4926 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4927 pBranch *pbr = PCI(pc)->label;
4928 if(pbr && pbr->next) {
4929 pCode *pcd = pb->pcHead;
4930
4931 //fprintf(stderr, "multiple labels\n");
4932 //pc->print(stderr,pc);
4933
4934 pbr = pbr->next;
4935 while(pbr) {
4936 while ((pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4937 //fprintf(stderr,"Used by:\n");
4938 //pcd->print(stderr,pcd);
4939
4940 exchangeLabels(PCL(pbr->pc),pcd);
4941 pcd = pcd->next;
4942 }
4943 pbr = pbr->next;
4944 }
4945 }
4946 }
4947
4948 for(pc = pb->pcHead; pc; pc = pc->next) {
4949 if(isPCL(pc)) // Label pcode
4950 pcl = PCL(pc);
4951 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4952 pcl = PCL(PCI(pc)->label->pc);
4953 else continue;
4954
4955 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4956
4957 /* This pCode is a label, so search the pBlock to see if anyone
4958 * refers to it */
4959
4960 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4961 /* Couldn't find an instruction that refers to this label
4962 * So, unlink the pCode label from it's pCode chain
4963 * and destroy the label */
4964 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4965
4966 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4967 if(pc->type == PC_LABEL) {
4968 unlinkpCode(pc);
4969 pCodeLabelDestruct(pc);
4970 } else {
4971 unlinkpCodeFromBranch(pc, PCODE(pcl));
4972 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4973 free(pc->label);
4974 }*/
4975 }
4976 }
4977 }
4978 }
4979
4980 /*-----------------------------------------------------------------*/
4981 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4982 /* chain and put them into pBranches that are */
4983 /* associated with the appropriate pCode */
4984 /* instructions. */
4985 /*-----------------------------------------------------------------*/
pBlockMergeLabels(pBlock * pb)4986 void pBlockMergeLabels(pBlock *pb)
4987 {
4988 pBranch *pbr;
4989 pCode *pc, *pcnext=NULL;
4990
4991 if(!pb)
4992 return;
4993
4994 /* First, Try to remove any unused labels */
4995 //pBlockRemoveUnusedLabels(pb);
4996
4997 /* Now loop through the pBlock and merge the labels with the opcodes */
4998
4999 pc = pb->pcHead;
5000
5001 while(pc) {
5002 pCode *pcn = pc->next;
5003
5004 if(pc->type == PC_LABEL) {
5005
5006 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5007 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5008 if((pcnext = findNextInstruction(pc) )) {
5009
5010 // Unlink the pCode label from it's pCode chain
5011 unlinkpCode(pc);
5012
5013 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5014 // And link it into the instruction's pBranch labels. (Note, since
5015 // it's possible to have multiple labels associated with one instruction
5016 // we must provide a means to accomodate the additional labels. Thus
5017 // the labels are placed into the singly-linked list "label" as
5018 // opposed to being a single member of the pCodeInstruction.)
5019
5020 //_ALLOC(pbr,sizeof(pBranch));
5021 pbr = Safe_alloc(sizeof(pBranch));
5022 pbr->pc = pc;
5023 pbr->next = NULL;
5024
5025 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5026 } else {
5027 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5028 }
5029 } else if(pc->type == PC_CSOURCE) {
5030
5031 /* merge the source line symbolic info into the next instruction */
5032 if((pcnext = findNextInstruction(pc) )) {
5033
5034 // Unlink the pCode label from it's pCode chain
5035 unlinkpCode(pc);
5036 PCI(pcnext)->cline = PCCS(pc);
5037 //fprintf(stderr, "merging CSRC\n");
5038 //genericPrint(stderr,pcnext);
5039 }
5040 }
5041 pc = pcn;
5042 }
5043 pBlockRemoveUnusedLabels(pb);
5044 }
5045
5046 /*-----------------------------------------------------------------*/
5047 /*-----------------------------------------------------------------*/
OptimizepCode(char dbName)5048 static int OptimizepCode(char dbName)
5049 {
5050 #define MAX_PASSES 4
5051
5052 int matches = 0;
5053 int passes = 0;
5054 pBlock *pb;
5055
5056 if(!the_pFile)
5057 return 0;
5058
5059 DFPRINTF((stderr," Optimizing pCode\n"));
5060
5061 do {
5062 matches = 0;
5063 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5064 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5065 matches += OptimizepBlock(pb);
5066 }
5067 }
5068 while(matches && ++passes < MAX_PASSES);
5069
5070 return matches;
5071 }
5072
5073 /*-----------------------------------------------------------------*/
5074 /* popCopyGPR2Bit - copy a pcode operator */
5075 /*-----------------------------------------------------------------*/
5076
popCopyGPR2Bit(pCodeOp * pc,int bitval)5077 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5078 {
5079 pCodeOp *pcop;
5080
5081 pcop = newpCodeOpBit(pc->name, bitval, 0);
5082
5083 if( !( (pcop->type == PO_LABEL) ||
5084 (pcop->type == PO_LITERAL) ||
5085 (pcop->type == PO_STR) ))
5086 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5087
5088 return pcop;
5089 }
5090
5091 /*-----------------------------------------------------------------*/
5092 /*-----------------------------------------------------------------*/
pBlockDestruct(pBlock * pb)5093 static void pBlockDestruct(pBlock *pb)
5094 {
5095
5096 if(!pb)
5097 return;
5098
5099
5100 free(pb);
5101
5102 }
5103
5104 /*-----------------------------------------------------------------*/
5105 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5106 /* name dbName and combine them */
5107 /* into one block */
5108 /*-----------------------------------------------------------------*/
mergepBlocks(char dbName)5109 static void mergepBlocks(char dbName)
5110 {
5111
5112 pBlock *pb, *pbmerged = NULL,*pbn;
5113
5114 pb = the_pFile->pbHead;
5115
5116 //fprintf(stderr," merging blocks named %c\n",dbName);
5117 while(pb) {
5118
5119 pbn = pb->next;
5120 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5121 if( getpBlock_dbName(pb) == dbName) {
5122
5123 //fprintf(stderr," merged block %c\n",dbName);
5124
5125 if(!pbmerged) {
5126 pbmerged = pb;
5127 } else {
5128 addpCode2pBlock(pbmerged, pb->pcHead);
5129 /* addpCode2pBlock doesn't handle the tail: */
5130 pbmerged->pcTail = pb->pcTail;
5131
5132 pb->prev->next = pbn;
5133 if(pbn)
5134 pbn->prev = pb->prev;
5135
5136
5137 pBlockDestruct(pb);
5138 }
5139 //printpBlock(stderr, pbmerged);
5140 }
5141 pb = pbn;
5142 }
5143
5144 }
5145
5146 /*-----------------------------------------------------------------*/
5147 /* AnalyzeFlow - Examine the flow of the code and optimize */
5148 /* */
5149 /* level 0 == minimal optimization */
5150 /* optimize registers that are used only by two instructions */
5151 /* level 1 == maximal optimization */
5152 /* optimize by looking at pairs of instructions that use the */
5153 /* register. */
5154 /*-----------------------------------------------------------------*/
5155
AnalyzeFlow(int level)5156 static void AnalyzeFlow(int level)
5157 {
5158 static int times_called=0;
5159
5160 pBlock *pb;
5161
5162 if(!the_pFile)
5163 return;
5164
5165
5166 /* if this is not the first time this function has been called,
5167 then clean up old flow information */
5168 if(times_called++) {
5169 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5170 unBuildFlow(pb);
5171
5172 RegsUnMapLiveRanges();
5173
5174 }
5175
5176 GpcFlowSeq = 1;
5177
5178 /* Phase 2 - Flow Analysis - Register Banking
5179 *
5180 * In this phase, the individual flow blocks are examined
5181 * and register banking is fixed.
5182 */
5183
5184 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5185 //FixRegisterBanking(pb);
5186
5187 /* Phase 2 - Flow Analysis
5188 *
5189 * In this phase, the pCode is partition into pCodeFlow
5190 * blocks. The flow blocks mark the points where a continuous
5191 * stream of instructions changes flow (e.g. because of
5192 * a call or goto or whatever).
5193 */
5194
5195 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5196 BuildFlow(pb);
5197
5198
5199 /* Phase 2 - Flow Analysis - linking flow blocks
5200 *
5201 * In this phase, the individual flow blocks are examined
5202 * to determine their order of excution.
5203 */
5204
5205 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5206 LinkFlow(pb);
5207
5208 /* Phase 3 - Flow Analysis - Flow Tree
5209 *
5210 * In this phase, the individual flow blocks are examined
5211 * to determine their order of excution.
5212 */
5213
5214 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5215 BuildFlowTree(pb);
5216
5217
5218 /* Phase x - Flow Analysis - Used Banks
5219 *
5220 * In this phase, the individual flow blocks are examined
5221 * to determine the Register Banks they use
5222 */
5223
5224 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5225 // FixBankFlow(pb);
5226
5227
5228 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5229 pCodeRegMapLiveRanges(pb);
5230
5231 RemoveUnusedRegisters();
5232
5233 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5234 pCodeRegOptimizeRegUsage(level);
5235
5236 OptimizepCode('*');
5237
5238 /*
5239 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5240 DumpFlow(pb);
5241 */
5242 /* debug stuff */
5243 /*
5244 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5245 pCode *pcflow;
5246 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5247 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5248 pcflow = pcflow->next) {
5249
5250 FillFlow(PCFL(pcflow));
5251 }
5252 }
5253 */
5254 /*
5255 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5256 pCode *pcflow;
5257 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5258 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5259 pcflow = pcflow->next) {
5260
5261 FlowStats(PCFL(pcflow));
5262 }
5263 }
5264 */
5265 }
5266
5267 /*-----------------------------------------------------------------*/
5268 /* AnalyzeBanking - Called after the memory addresses have been */
5269 /* assigned to the registers. */
5270 /* */
5271 /*-----------------------------------------------------------------*/
5272
AnalyzeBanking(void)5273 void AnalyzeBanking(void)
5274 {
5275 pBlock *pb;
5276
5277 if(!picIsInitialized()) {
5278 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
5279 exit(1);
5280 }
5281
5282 if (!the_pFile) return;
5283
5284 /* Phase x - Flow Analysis - Used Banks
5285 *
5286 * In this phase, the individual flow blocks are examined
5287 * to determine the Register Banks they use
5288 */
5289
5290 AnalyzeFlow(0);
5291 AnalyzeFlow(1);
5292
5293 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5294 FixRegisterBanking(pb);
5295
5296 AnalyzeFlow(0);
5297 AnalyzeFlow(1);
5298
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /*-----------------------------------------------------------------*/
DEFSETFUNC(resetrIdx)5303 static DEFSETFUNC (resetrIdx)
5304 {
5305 reg_info *r = (reg_info *)item;
5306 if (!r->isFixed) {
5307 r->rIdx = 0;
5308 }
5309
5310 return 0;
5311 }
5312
5313 /*-----------------------------------------------------------------*/
5314 /* InitRegReuse - Initialises variables for code analyzer */
5315 /*-----------------------------------------------------------------*/
InitReuseReg(void)5316 static void InitReuseReg(void)
5317 {
5318 /* Find end of statically allocated variables for start idx */
5319 /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5320 /* XXX: Avoid clashes with fixed registers, start late. */
5321 unsigned maxIdx = 0x1000;
5322 reg_info *r;
5323 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5324 if (r->type != REG_SFR) {
5325 maxIdx += r->size; /* Increment for all statically allocated variables */
5326 }
5327 }
5328 peakIdx = maxIdx;
5329 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5330 }
5331
5332 /*-----------------------------------------------------------------*/
5333 /*-----------------------------------------------------------------*/
5334 static unsigned
register_reassign(pBlock * pb,unsigned startIdx,unsigned level)5335 register_reassign(pBlock *pb, unsigned startIdx, unsigned level)
5336 {
5337 pCode *pc;
5338 unsigned temp;
5339 unsigned idx = startIdx;
5340
5341 /* check recursion */
5342 pc = setFirstItem(pb->function_entries);
5343 if (!pc)
5344 return idx;
5345
5346 if (pb->visited)
5347 {
5348 set *regset;
5349 /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */
5350
5351 // Find the highest rIdx used by this function for return.
5352 regset = pb->tregisters;
5353 idx = 0;
5354 while (regset)
5355 {
5356 temp = ((reg_info *)regset->item)->rIdx;
5357 if (temp > idx)
5358 idx = temp;
5359 regset = regset->next;
5360 } // while
5361 DFPRINTF((stderr,
5362 "%*s(%u) function \"%s\" already visited: max idx = %04x\n",
5363 4 * level, "", level,PCF(pc)->fname, idx));
5364 return idx + 1;
5365 } // if
5366
5367 /*
5368 * We now traverse the call tree depth first, assigning indices > startIdx
5369 * to the registers of all called functions before assigning indices to
5370 * the registers of the calling function, starting with one greater than
5371 * the max. index used by any child function.
5372 * This approach guarantees that, if f calls g, all registers of f have
5373 * greater indices than those of g (also holds transitively).
5374 *
5375 * XXX: If a function f calls a function g in a different module,
5376 * we should handle the case that g could call a function h
5377 * in f's module.
5378 * The consequence of this is that even though f and h might
5379 * share registers (they do not call each other locally) when
5380 * looking only at f's module, they actually must not do so!
5381 *
5382 * For a non-static function f, let ES(f) be the set of functions
5383 * (including f) that can only be reached via f in the module-local
5384 * call graph (ES(f) will hence be a subgraph).
5385 * Let further REG(ES(f)) be the set of registers assigned to
5386 * functions in ES(f).
5387 * Then we should make sure that REG(ES(f)) and REG(ES(g)) are
5388 * disjoint for all non-static functions f and g.
5389 *
5390 * Unfortunately, determining the sets ES(f) is non-trivial,
5391 * so we ignore this problem and declare all modules non-reentrant.
5392 * This is a bug.
5393 */
5394 pb->visited = 1;
5395
5396 DFPRINTF((stderr,
5397 "%*s(%u) reassigning registers for functions called by \"%s\":base idx = %04x\n",
5398 4 * level, "", level, PCF(pc)->fname, startIdx));
5399
5400 for (pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls))
5401 {
5402 if (pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5403 {
5404 char *dest = get_op_from_instruction(PCI(pc));
5405 pCode *pcn = findFunction(dest);
5406
5407 if (pcn)
5408 {
5409 /*
5410 * Reassign the registers of all called functions and record
5411 * the max. index I used by any child function --> I+1 will be
5412 * the first index available to this function.
5413 * (Problem shown with regression test src/regression/sub2.c)
5414 */
5415 unsigned childsMaxIdx;
5416 childsMaxIdx = register_reassign(pcn->pb,startIdx,level+1);
5417 if (childsMaxIdx > idx)
5418 idx = childsMaxIdx;
5419 } // if
5420 } // if
5421 } // for
5422
5423 pc = setFirstItem(pb->function_entries);
5424 DFPRINTF((stderr,
5425 "%*s(%u) reassigning registers for function \"%s\":idx = %04x\n",
5426 4 * level, "", level, PCF(pc)->fname, idx));
5427
5428 if (pb->tregisters)
5429 {
5430 reg_info *r;
5431 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters))
5432 {
5433 if ((r->type == REG_GPR) && (!r->isFixed) && (r->rIdx < (int)idx))
5434 {
5435 char s[20];
5436 set *regset;
5437 /*
5438 * Make sure, idx is not yet used in this routine ...
5439 * XXX: This should no longer be required, as all functions
5440 * are reassigned at most once ...
5441 */
5442 do
5443 {
5444 regset = pb->tregisters;
5445 // do not touch s->curr ==> outer loop!
5446 while (regset && ((reg_info *)regset->item)->rIdx != idx)
5447 regset = regset->next;
5448 if (regset)
5449 idx++;
5450 }
5451 while (regset);
5452 r->rIdx = idx++;
5453 if (peakIdx < idx)
5454 peakIdx = idx;
5455
5456 SNPRINTF(s, sizeof(s), "r0x%02X", r->rIdx);
5457 DFPRINTF((stderr,
5458 "%*s(%u) reassigning register %p \"%s\" to \"%s\"\n",
5459 4 * level, "", level, r, r->name, s));
5460 free(r->name);
5461 r->name = Safe_strdup(s);
5462 } // if
5463 } // for
5464 } // if
5465
5466 /* return lowest index available for caller's registers */
5467 return idx;
5468 }
5469
5470 /*------------------------------------------------------------------*/
5471 /* ReuseReg were call tree permits */
5472 /* */
5473 /* Re-allocate the GPR for optimum reuse for a given pblock */
5474 /* eg if a function m() calls function f1() and f2(), where f1 */
5475 /* allocates a local variable vf1 and f2 allocates a local */
5476 /* variable vf2. Then providing f1 and f2 do not call each other */
5477 /* they may share the same general purpose registers for vf1 and */
5478 /* vf2. */
5479 /* This is done by first setting the the regs rIdx to start after */
5480 /* all the global variables, then walking through the call tree */
5481 /* renaming the registers to match their new idx and incrementng */
5482 /* it as it goes. If a function has already been called it will */
5483 /* only rename the registers if it has already used up those */
5484 /* registers ie rIdx of the function's registers is lower than the */
5485 /* current rIdx. That way the register will not be reused while */
5486 /* still being used by an eariler function call. */
5487 /* */
5488 /* Note for this to work the functions need to be declared static. */
5489 /* */
5490 /*------------------------------------------------------------------*/
5491 void
ReuseReg(void)5492 ReuseReg(void)
5493 {
5494 pBlock *pb;
5495
5496 if (options.noOverlay || !the_pFile)
5497 return;
5498
5499 InitReuseReg();
5500
5501 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5502 {
5503 /* Non static functions can be called from other modules,
5504 * so their registers must reassign */
5505 if (pb->function_entries
5506 && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
5507 {
5508 register_reassign(pb,peakIdx,0);
5509 } // if
5510 } // for
5511 }
5512
5513 /*-----------------------------------------------------------------*/
5514 /* buildCallTree - look at the flow and extract all of the calls */
5515 /* */
5516 /*-----------------------------------------------------------------*/
5517
buildCallTree(void)5518 static void buildCallTree(void)
5519 {
5520 pBranch *pbr;
5521 pBlock *pb;
5522 pCode *pc;
5523
5524 if(!the_pFile)
5525 return;
5526
5527 /* Now build the call tree.
5528 First we examine all of the pCodes for functions.
5529 Keep in mind that the function boundaries coincide
5530 with pBlock boundaries.
5531
5532 The algorithm goes something like this:
5533 We have two nested loops. The outer loop iterates
5534 through all of the pBlocks/functions. The inner
5535 loop iterates through all of the pCodes for
5536 a given pBlock. When we begin iterating through
5537 a pBlock, the variable pc_fstart, pCode of the start
5538 of a function, is cleared. We then search for pCodes
5539 of type PC_FUNCTION. When one is encountered, we
5540 initialize pc_fstart to this and at the same time
5541 associate a new pBranch object that signifies a
5542 branch entry. If a return is found, then this signifies
5543 a function exit point. We'll link the pCodes of these
5544 returns to the matching pc_fstart.
5545
5546 When we're done, a doubly linked list of pBranches
5547 will exist. The head of this list is stored in
5548 `the_pFile', which is the meta structure for all
5549 of the pCode. Look at the printCallTree function
5550 on how the pBranches are linked together.
5551 */
5552
5553 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5554 pCode *pc_fstart=NULL;
5555 for(pc = pb->pcHead; pc; pc = pc->next) {
5556 if(isPCF(pc)) {
5557 pCodeFunction *pcf = PCF(pc);
5558 if (pcf->fname) {
5559
5560 if(STRCASECMP(pcf->fname, "_main") == 0) {
5561 //fprintf(stderr," found main \n");
5562 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5563 pb->dbName = 'M';
5564 }
5565
5566 pbr = Safe_alloc(sizeof(pBranch));
5567 pbr->pc = pc_fstart = pc;
5568 pbr->next = NULL;
5569
5570 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5571
5572 // Here's a better way of doing the same:
5573 addSet(&pb->function_entries, pc);
5574
5575 } else {
5576 // Found an exit point in a function, e.g. return
5577 // (Note, there may be more than one return per function)
5578 if(pc_fstart)
5579 pBranchLink(PCF(pc_fstart), pcf);
5580
5581 addSet(&pb->function_exits, pc);
5582 }
5583 } else if(isCALL(pc)) {
5584 addSet(&pb->function_calls,pc);
5585 }
5586 }
5587 }
5588 }
5589
5590 /*-----------------------------------------------------------------*/
5591 /* AnalyzepCode - parse the pCode that has been generated and form */
5592 /* all of the logical connections. */
5593 /* */
5594 /* Essentially what's done here is that the pCode flow is */
5595 /* determined. */
5596 /*-----------------------------------------------------------------*/
5597
AnalyzepCode(char dbName)5598 void AnalyzepCode(char dbName)
5599 {
5600 pBlock *pb;
5601 int i,changes;
5602
5603 if(!the_pFile)
5604 return;
5605
5606 mergepBlocks('D');
5607
5608
5609 /* Phase 1 - Register allocation and peep hole optimization
5610 *
5611 * The first part of the analysis is to determine the registers
5612 * that are used in the pCode. Once that is done, the peep rules
5613 * are applied to the code. We continue to loop until no more
5614 * peep rule optimizations are found (or until we exceed the
5615 * MAX_PASSES threshold).
5616 *
5617 * When done, the required registers will be determined.
5618 *
5619 */
5620 i = 0;
5621 do {
5622
5623 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5624
5625 /* First, merge the labels with the instructions */
5626 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5627 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5628
5629 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5630 pBlockMergeLabels(pb);
5631 AnalyzepBlock(pb);
5632 } else {
5633 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5634 }
5635 }
5636
5637 changes = OptimizepCode(dbName);
5638
5639 } while(changes && (i++ < MAX_PASSES));
5640
5641 buildCallTree();
5642 }
5643
5644 /*-----------------------------------------------------------------*/
5645 /* findFunction - Search for a function by name (given the name) */
5646 /* in the set of all functions that are in a pBlock */
5647 /* (note - I expect this to change because I'm planning to limit */
5648 /* pBlock's to just one function declaration */
5649 /*-----------------------------------------------------------------*/
findFunction(const char * fname)5650 static pCode *findFunction(const char *fname)
5651 {
5652 pBlock *pb;
5653 pCode *pc;
5654 if(!fname)
5655 return NULL;
5656
5657 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5658
5659 pc = setFirstItem(pb->function_entries);
5660 while(pc) {
5661
5662 if((pc->type == PC_FUNCTION) &&
5663 (PCF(pc)->fname) &&
5664 (strcmp(fname, PCF(pc)->fname)==0))
5665 return pc;
5666
5667 pc = setNextItem(pb->function_entries);
5668
5669 }
5670
5671 }
5672 return NULL;
5673 }
5674
pBlockStats(FILE * of,pBlock * pb)5675 static void pBlockStats(FILE *of, pBlock *pb)
5676 {
5677
5678 pCode *pc;
5679 reg_info *r;
5680
5681 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5682
5683 // for now just print the first element of each set
5684 /* pc = setFirstItem(pb->function_entries);
5685 if(pc) {
5686 fprintf(of,";entry: ");
5687 pc->print(of,pc);
5688 }*/
5689 pc = setFirstItem(pb->function_exits);
5690 if(pc) {
5691 fprintf(of,";has an exit\n");
5692 //pc->print(of,pc);
5693 }
5694
5695 pc = setFirstItem(pb->function_calls);
5696 if(pc) {
5697 fprintf(of,";functions called:\n");
5698
5699 while(pc) {
5700 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5701 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5702 }
5703 pc = setNextItem(pb->function_calls);
5704 }
5705 }
5706
5707 r = setFirstItem(pb->tregisters);
5708 if(r) {
5709 int n = elementsInSet(pb->tregisters);
5710
5711 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5712
5713 while (r) {
5714 fprintf(of,"; %s\n",r->name);
5715 r = setNextItem(pb->tregisters);
5716 }
5717 }
5718 }
5719
5720 #if 0
5721 /*-----------------------------------------------------------------*/
5722 /* printCallTree - writes the call tree to a file */
5723 /* */
5724 /*-----------------------------------------------------------------*/
5725 static void pct2(FILE *of,pBlock *pb,int indent)
5726 {
5727 pCode *pc,*pcn;
5728 int i;
5729 // set *registersInCallPath = NULL;
5730
5731 if(!of)
5732 return;
5733
5734 if(indent > 10)
5735 return; //recursion ?
5736
5737 pc = setFirstItem(pb->function_entries);
5738
5739 if(!pc)
5740 return;
5741
5742 pb->visited = 0;
5743
5744 for(i=0;i<indent;i++) // Indentation
5745 fputc(' ',of);
5746
5747 if(pc->type == PC_FUNCTION)
5748 fprintf(of,"%s\n",PCF(pc)->fname);
5749 else
5750 return; // ???
5751
5752
5753 pc = setFirstItem(pb->function_calls);
5754 for( ; pc; pc = setNextItem(pb->function_calls)) {
5755
5756 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5757 char *dest = get_op_from_instruction(PCI(pc));
5758
5759 pcn = findFunction(dest);
5760 if(pcn)
5761 pct2(of,pcn->pb,indent+1);
5762 } else
5763 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5764
5765 }
5766
5767
5768 }
5769 #endif
5770
5771 #if 0
5772 /*-----------------------------------------------------------------*/
5773 /* ispCodeFunction - returns true if *pc is the pCode of a */
5774 /* function */
5775 /*-----------------------------------------------------------------*/
5776 static bool ispCodeFunction(pCode *pc)
5777 {
5778
5779 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5780 return 1;
5781
5782 return 0;
5783 }
5784
5785 /*-----------------------------------------------------------------*/
5786 /* printCallTree - writes the call tree to a file */
5787 /* */
5788 /*-----------------------------------------------------------------*/
5789
5790 static void printCallTree(FILE *of)
5791 {
5792 pBranch *pbr;
5793 pBlock *pb;
5794 pCode *pc;
5795
5796 if(!the_pFile)
5797 return;
5798
5799 if(!of)
5800 of = stderr;
5801
5802 fprintf(of, "\npBlock statistics\n");
5803 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5804 pBlockStats(of,pb);
5805
5806
5807
5808 fprintf(of,"Call Tree\n");
5809 pbr = the_pFile->functions;
5810 while(pbr) {
5811 if(pbr->pc) {
5812 pc = pbr->pc;
5813 if(!ispCodeFunction(pc))
5814 fprintf(of,"bug in call tree");
5815
5816
5817 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5818
5819 while(pc->next && !ispCodeFunction(pc->next)) {
5820 pc = pc->next;
5821 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5822 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5823 }
5824 }
5825
5826 pbr = pbr->next;
5827 }
5828
5829
5830 fprintf(of,"\n**************\n\na better call tree\n");
5831 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5832 if(pb->visited)
5833 pct2(of,pb,0);
5834 }
5835
5836 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5837 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5838 }
5839 }
5840 #endif
5841
5842
5843 /*-----------------------------------------------------------------*/
5844 /* */
5845 /*-----------------------------------------------------------------*/
5846
InlineFunction(pBlock * pb)5847 static void InlineFunction(pBlock *pb)
5848 {
5849 pCode *pc;
5850 pCode *pc_call;
5851
5852 if(!pb)
5853 return;
5854
5855 pc = setFirstItem(pb->function_calls);
5856
5857 for( ; pc; pc = setNextItem(pb->function_calls)) {
5858
5859 if(isCALL(pc)) {
5860 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5861 pCode *pcp = pc->prev;
5862 pCode *pct;
5863 pCode *pce;
5864
5865 pBranch *pbr;
5866
5867 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1) && !PCF(pcn)->isPublic && (pcp && (isPCI_BITSKIP(pcp)||!isPCI_SKIP(pcp)))) { /* Bit skips can be inverted other skips can not */
5868
5869 InlineFunction(pcn->pb);
5870
5871 /*
5872 At this point, *pc points to a CALL mnemonic, and
5873 *pcn points to the function that is being called.
5874
5875 To in-line this call, we need to remove the CALL
5876 and RETURN(s), and link the function pCode in with
5877 the CALLee pCode.
5878
5879 */
5880
5881 pc_call = pc;
5882
5883 /* Check if previous instruction was a bit skip */
5884 if (isPCI_BITSKIP(pcp)) {
5885 pCodeLabel *pcl;
5886 /* Invert skip instruction and add a goto */
5887 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
5888
5889 if(isPCL(pc_call->next)) { // Label pcode
5890 pcl = PCL(pc_call->next);
5891 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
5892 pcl = PCL(PCI(pc_call->next)->label->pc);
5893 } else {
5894 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
5895 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
5896 }
5897 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
5898 }
5899
5900 /* remove callee pBlock from the pBlock linked list */
5901 removepBlock(pcn->pb);
5902
5903 pce = pcn;
5904 while(pce) {
5905 pce->pb = pb;
5906 pce = pce->next;
5907 }
5908
5909 /* Remove the Function pCode */
5910 pct = findNextInstruction(pcn->next);
5911
5912 /* Link the function with the callee */
5913 if (pcp) pcp->next = pcn->next;
5914 pcn->next->prev = pcp;
5915
5916 /* Convert the function name into a label */
5917
5918 pbr = Safe_alloc(sizeof(pBranch));
5919 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5920 pbr->next = NULL;
5921 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5922 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5923
5924 /* turn all of the return's except the last into goto's */
5925 /* check case for 2 instruction pBlocks */
5926 pce = findNextInstruction(pcn->next);
5927 while(pce) {
5928 pCode *pce_next = findNextInstruction(pce->next);
5929
5930 if(pce_next == NULL) {
5931 /* found the last return */
5932 pCode *pc_call_next = findNextInstruction(pc_call->next);
5933
5934 //fprintf(stderr,"found last return\n");
5935 //pce->print(stderr,pce);
5936 pce->prev->next = pc_call->next;
5937 pc_call->next->prev = pce->prev;
5938 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5939 PCI(pce)->label);
5940 }
5941
5942 pce = pce_next;
5943 }
5944 }
5945 } else
5946 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5947 }
5948 }
5949
5950 /*-----------------------------------------------------------------*/
5951 /* */
5952 /*-----------------------------------------------------------------*/
5953
InlinepCode(void)5954 void InlinepCode(void)
5955 {
5956
5957 pBlock *pb;
5958 pCode *pc;
5959
5960 if(!the_pFile)
5961 return;
5962
5963 if(!functionInlining)
5964 return;
5965
5966 /* Loop through all of the function definitions and count the
5967 * number of times each one is called */
5968 //fprintf(stderr,"inlining %d\n",__LINE__);
5969
5970 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5971
5972 pc = setFirstItem(pb->function_calls);
5973
5974 for( ; pc; pc = setNextItem(pb->function_calls)) {
5975
5976 if(isCALL(pc)) {
5977 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5978 if(pcn && isPCF(pcn)) {
5979 PCF(pcn)->ncalled++;
5980 }
5981 } else
5982 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5983
5984 }
5985 }
5986
5987 //fprintf(stderr,"inlining %d\n",__LINE__);
5988
5989 /* Now, Loop through the function definitions again, but this
5990 * time inline those functions that have only been called once. */
5991
5992 InlineFunction(the_pFile->pbHead);
5993 //fprintf(stderr,"inlining %d\n",__LINE__);
5994
5995 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5996 unBuildFlow(pb);
5997
5998 }
5999
6000