1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
25 #include "common.h" // Include everything in the SDCC src directory
31 #include "pcodeflow.h"
35 #if defined(__BORLANDC__) || defined(_MSC_VER)
36 #define STRCASECMP stricmp
38 #define STRCASECMP strcasecmp
41 /****************************************************************/
42 /****************************************************************/
44 static peepCommand peepCommands[] = {
46 {NOTBITSKIP, "_NOTBITSKIP_"},
47 {BITSKIP, "_BITSKIP_"},
48 {INVERTBITSKIP, "_INVERTBITSKIP_"},
55 // Eventually this will go into device dependent files:
56 pCodeOpReg pic16_pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pclatu = {{PO_PCLATU, "PCLATU"}, -1, NULL,0,NULL}; // patch 14
61 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_tosl = {{PO_SFR_REGISTER, "TOSL"}, -1, NULL,0,NULL}; // patch 14
65 pCodeOpReg pic16_pc_tosh = {{PO_SFR_REGISTER, "TOSH"}, -1, NULL,0,NULL}; //
66 pCodeOpReg pic16_pc_tosu = {{PO_SFR_REGISTER, "TOSU"}, -1, NULL,0,NULL}; // patch 14
68 pCodeOpReg pic16_pc_tblptrl = {{PO_SFR_REGISTER, "TBLPTRL"}, -1, NULL,0,NULL}; // patch 15
69 pCodeOpReg pic16_pc_tblptrh = {{PO_SFR_REGISTER, "TBLPTRH"}, -1, NULL,0,NULL}; //
70 pCodeOpReg pic16_pc_tblptru = {{PO_SFR_REGISTER, "TBLPTRU"}, -1, NULL,0,NULL}; //
71 pCodeOpReg pic16_pc_tablat = {{PO_SFR_REGISTER, "TABLAT"}, -1, NULL,0,NULL}; // patch 15
73 //pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL}; //deprecated !
75 pCodeOpReg pic16_pc_fsr0l = {{PO_FSR0, "FSR0L"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_fsr0h = {{PO_FSR0, "FSR0H"}, -1, NULL, 0, NULL};
77 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
78 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
79 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
80 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
82 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
83 pCodeOpReg pic16_pc_postinc0 = {{PO_INDF0, "POSTINC0"}, -1, NULL, 0, NULL};
84 pCodeOpReg pic16_pc_postdec0 = {{PO_INDF0, "POSTDEC0"}, -1, NULL, 0, NULL};
85 pCodeOpReg pic16_pc_preinc0 = {{PO_INDF0, "PREINC0"}, -1, NULL, 0, NULL};
86 pCodeOpReg pic16_pc_plusw0 = {{PO_INDF0, "PLUSW0"}, -1, NULL, 0, NULL};
88 pCodeOpReg pic16_pc_indf1 = {{PO_INDF0, "INDF1"}, -1, NULL,0,NULL};
89 pCodeOpReg pic16_pc_postinc1 = {{PO_INDF0, "POSTINC1"}, -1, NULL, 0, NULL};
90 pCodeOpReg pic16_pc_postdec1 = {{PO_INDF0, "POSTDEC1"}, -1, NULL, 0, NULL};
91 pCodeOpReg pic16_pc_preinc1 = {{PO_INDF0, "PREINC1"}, -1, NULL, 0, NULL};
92 pCodeOpReg pic16_pc_plusw1 = {{PO_INDF0, "PLUSW1"}, -1, NULL, 0, NULL};
94 pCodeOpReg pic16_pc_indf2 = {{PO_INDF0, "INDF2"}, -1, NULL,0,NULL};
95 pCodeOpReg pic16_pc_postinc2 = {{PO_INDF0, "POSTINC2"}, -1, NULL, 0, NULL};
96 pCodeOpReg pic16_pc_postdec2 = {{PO_INDF0, "POSTDEC2"}, -1, NULL, 0, NULL};
97 pCodeOpReg pic16_pc_preinc2 = {{PO_INDF0, "PREINC2"}, -1, NULL, 0, NULL};
98 pCodeOpReg pic16_pc_plusw2 = {{PO_INDF0, "PLUSW2"}, -1, NULL, 0, NULL};
100 pCodeOpReg pic16_pc_prodl = {{PO_PRODL, "PRODL"}, -1, NULL, 0, NULL};
101 pCodeOpReg pic16_pc_prodh = {{PO_PRODH, "PRODH"}, -1, NULL, 0, NULL};
103 /* EEPROM registers */
104 pCodeOpReg pic16_pc_eecon1 = {{PO_SFR_REGISTER, "EECON1"}, -1, NULL, 0, NULL};
105 pCodeOpReg pic16_pc_eecon2 = {{PO_SFR_REGISTER, "EECON2"}, -1, NULL, 0, NULL};
106 pCodeOpReg pic16_pc_eedata = {{PO_SFR_REGISTER, "EEDATA"}, -1, NULL, 0, NULL};
107 pCodeOpReg pic16_pc_eeadr = {{PO_SFR_REGISTER, "EEADR"}, -1, NULL, 0, NULL};
111 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
112 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
113 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
115 pCodeOpReg pic16_pc_gpsimio = {{PO_GPR_REGISTER, "GPSIMIO"}, -1, NULL, 0, NULL};
116 pCodeOpReg pic16_pc_gpsimio2 = {{PO_GPR_REGISTER, "GPSIMIO2"}, -1, NULL, 0, NULL};
118 char *OPT_TYPE_STR[] = { "begin", "end" };
119 char *LR_TYPE_STR[] = { "entry begin", "entry end", "exit begin", "exit end" };
122 static int mnemonics_initialized = 0;
125 static hTab *pic16MnemonicsHash = NULL;
126 static hTab *pic16pCodePeepCommandsHash = NULL;
128 static pFile *the_pFile = NULL;
129 static pBlock *pb_dead_pcodes = NULL;
131 /* Hardcoded flags to change the behavior of the PIC port */
132 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
133 static int functionInlining = 1; /* inline functions if nonzero */
134 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
136 int pic16_pcode_verbose = 0;
138 //static int GpCodeSequenceNumber = 1;
139 static int GpcFlowSeq = 1;
141 extern void pic16_RemoveUnusedRegisters(void);
142 extern void pic16_RegsUnMapLiveRanges(void);
143 extern void pic16_BuildFlowTree(pBlock *pb);
144 extern void pic16_pCodeRegOptimizeRegUsage(int level);
145 extern int pic16_picIsInitialized(void);
146 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
147 extern int mnem2key(char const *mnem);
149 /****************************************************************/
150 /* Forward declarations */
151 /****************************************************************/
153 void pic16_unlinkpCode(pCode *pc);
155 static void genericAnalyze(pCode *pc);
156 static void AnalyzeGOTO(pCode *pc);
157 static void AnalyzeSKIP(pCode *pc);
158 static void AnalyzeRETURN(pCode *pc);
161 static void genericDestruct(pCode *pc);
162 static void genericPrint(FILE *of,pCode *pc);
164 static void pCodePrintLabel(FILE *of, pCode *pc);
165 static void pCodePrintFunction(FILE *of, pCode *pc);
166 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
167 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
168 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
169 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
170 int pic16_pCodePeepMatchRule(pCode *pc);
171 static void pBlockStats(FILE *of, pBlock *pb);
172 static pBlock *newpBlock(void);
173 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
174 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
175 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
176 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
177 void OptimizeLocalRegs(void);
179 char *dumpPicOptype(PIC_OPTYPE type);
181 pCodeOp *pic16_popGetLit2(int, pCodeOp *);
182 pCodeOp *pic16_popGetLit(int);
183 pCodeOp *pic16_popGetWithString(char *);
186 /****************************************************************/
187 /* PIC Instructions */
188 /****************************************************************/
190 pCodeInstruction pic16_pciADDWF = {
191 {PC_OPCODE, NULL, NULL, 0, NULL,
204 1,0, // dest, bit instruction
206 0, // literal operand
208 0, // fast call/return mode select bit
209 0, // second memory operand
210 0, // second literal operand
212 (PCC_W | PCC_REGISTER), // inCond
213 (PCC_REGISTER | PCC_Z), // outCond
217 pCodeInstruction pic16_pciADDFW = {
218 {PC_OPCODE, NULL, NULL, 0, NULL,
231 0,0, // dest, bit instruction
233 0, // literal operand
235 0, // fast call/return mode select bit
236 0, // second memory operand
237 0, // second literal operand
239 (PCC_W | PCC_REGISTER), // inCond
240 (PCC_W | PCC_Z), // outCond
244 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
245 {PC_OPCODE, NULL, NULL, 0, NULL,
258 1,0, // dest, bit instruction
260 0, // literal operand
262 0, // fast call/return mode select bit
263 0, // second memory operand
264 0, // second literal operand
266 (PCC_W | PCC_REGISTER | PCC_C), // inCond
267 (PCC_REGISTER | PCC_Z), // outCond
271 pCodeInstruction pic16_pciADDFWC = {
272 {PC_OPCODE, NULL, NULL, 0, NULL,
285 0,0, // dest, bit instruction
287 0, // literal operand
289 0, // fast call/return mode select bit
290 0, // second memory operand
291 0, // second literal operand
293 (PCC_W | PCC_REGISTER | PCC_C), // inCond
294 (PCC_W | PCC_Z), // outCond
298 pCodeInstruction pic16_pciADDLW = {
299 {PC_OPCODE, NULL, NULL, 0, NULL,
312 0,0, // dest, bit instruction
314 1, // literal operand
316 0, // fast call/return mode select bit
317 0, // second memory operand
318 0, // second literal operand
320 (PCC_W | PCC_LITERAL), // inCond
321 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
325 pCodeInstruction pic16_pciANDLW = {
326 {PC_OPCODE, NULL, NULL, 0, NULL,
339 0,0, // dest, bit instruction
341 1, // literal operand
343 0, // fast call/return mode select bit
344 0, // second memory operand
345 0, // second literal operand
347 (PCC_W | PCC_LITERAL), // inCond
348 (PCC_W | PCC_Z | PCC_N), // outCond
352 pCodeInstruction pic16_pciANDWF = {
353 {PC_OPCODE, NULL, NULL, 0, NULL,
366 1,0, // dest, bit instruction
368 0, // literal operand
370 0, // fast call/return mode select bit
371 0, // second memory operand
372 0, // second literal operand
374 (PCC_W | PCC_REGISTER), // inCond
375 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
379 pCodeInstruction pic16_pciANDFW = {
380 {PC_OPCODE, NULL, NULL, 0, NULL,
393 0,0, // dest, bit instruction
395 0, // literal operand
397 0, // fast call/return mode select bit
398 0, // second memory operand
399 0, // second literal operand
401 (PCC_W | PCC_REGISTER), // inCond
402 (PCC_W | PCC_Z) // outCond
405 pCodeInstruction pic16_pciBC = { // mdubuc - New
406 {PC_OPCODE, NULL, NULL, 0, NULL,
419 0,0, // dest, bit instruction
421 0, // literal operand
423 0, // fast call/return mode select bit
424 0, // second memory operand
425 0, // second literal operand
427 (PCC_REL_ADDR | PCC_C), // inCond
432 pCodeInstruction pic16_pciBCF = {
433 {PC_OPCODE, NULL, NULL, 0, NULL,
446 1,1, // dest, bit instruction
448 0, // literal operand
450 0, // fast call/return mode select bit
451 0, // second memory operand
452 0, // second literal operand
454 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
455 PCC_REGISTER, // outCond
459 pCodeInstruction pic16_pciBN = { // mdubuc - New
460 {PC_OPCODE, NULL, NULL, 0, NULL,
473 0,0, // dest, bit instruction
475 0, // literal operand
477 0, // fast call/return mode select bit
478 0, // second memory operand
479 0, // second literal operand
481 (PCC_REL_ADDR | PCC_N), // inCond
482 PCC_NONE , // outCond
486 pCodeInstruction pic16_pciBNC = { // mdubuc - New
487 {PC_OPCODE, NULL, NULL, 0, NULL,
500 0,0, // dest, bit instruction
502 0, // literal operand
504 0, // fast call/return mode select bit
505 0, // second memory operand
506 0, // second literal operand
508 (PCC_REL_ADDR | PCC_C), // inCond
509 PCC_NONE , // outCond
513 pCodeInstruction pic16_pciBNN = { // mdubuc - New
514 {PC_OPCODE, NULL, NULL, 0, NULL,
527 0,0, // dest, bit instruction
529 0, // literal operand
531 0, // fast call/return mode select bit
532 0, // second memory operand
533 0, // second literal operand
535 (PCC_REL_ADDR | PCC_N), // inCond
536 PCC_NONE , // outCond
540 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
541 {PC_OPCODE, NULL, NULL, 0, NULL,
554 0,0, // dest, bit instruction
556 0, // literal operand
558 0, // fast call/return mode select bit
559 0, // second memory operand
560 0, // second literal operand
562 (PCC_REL_ADDR | PCC_OV), // inCond
563 PCC_NONE , // outCond
567 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
568 {PC_OPCODE, NULL, NULL, 0, NULL,
581 0,0, // dest, bit instruction
583 0, // literal operand
585 0, // fast call/return mode select bit
586 0, // second memory operand
587 0, // second literal operand
589 (PCC_REL_ADDR | PCC_Z), // inCond
590 PCC_NONE , // outCond
594 pCodeInstruction pic16_pciBOV = { // mdubuc - New
595 {PC_OPCODE, NULL, NULL, 0, NULL,
608 0,0, // dest, bit instruction
610 0, // literal operand
612 0, // fast call/return mode select bit
613 0, // second memory operand
614 0, // second literal operand
616 (PCC_REL_ADDR | PCC_OV), // inCond
617 PCC_NONE , // outCond
621 pCodeInstruction pic16_pciBRA = { // mdubuc - New
622 {PC_OPCODE, NULL, NULL, 0, NULL,
635 0,0, // dest, bit instruction
637 0, // literal operand
639 0, // fast call/return mode select bit
640 0, // second memory operand
641 0, // second literal operand
643 PCC_REL_ADDR, // inCond
644 PCC_NONE , // outCond
648 pCodeInstruction pic16_pciBSF = {
649 {PC_OPCODE, NULL, NULL, 0, NULL,
662 1,1, // dest, bit instruction
664 0, // literal operand
666 0, // fast call/return mode select bit
667 0, // second memory operand
668 0, // second literal operand
670 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
671 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
675 pCodeInstruction pic16_pciBTFSC = {
676 {PC_OPCODE, NULL, NULL, 0, NULL,
689 0,1, // dest, bit instruction
691 0, // literal operand
693 0, // fast call/return mode select bit
694 0, // second memory operand
695 0, // second literal operand
697 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
698 PCC_EXAMINE_PCOP, // outCond
702 pCodeInstruction pic16_pciBTFSS = {
703 {PC_OPCODE, NULL, NULL, 0, NULL,
716 0,1, // dest, bit instruction
718 0, // literal operand
720 0, // fast call/return mode select bit
721 0, // second memory operand
722 0, // second literal operand
724 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
725 PCC_EXAMINE_PCOP, // outCond
729 pCodeInstruction pic16_pciBTG = { // mdubuc - New
730 {PC_OPCODE, NULL, NULL, 0, NULL,
743 0,1, // dest, bit instruction
745 0, // literal operand
747 0, // fast call/return mode select bit
748 0, // second memory operand
749 0, // second literal operand
751 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
752 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
756 pCodeInstruction pic16_pciBZ = { // mdubuc - New
757 {PC_OPCODE, NULL, NULL, 0, NULL,
770 0,0, // dest, bit instruction
772 0, // literal operand
774 0, // fast call/return mode select bit
775 0, // second memory operand
776 0, // second literal operand
783 pCodeInstruction pic16_pciCALL = {
784 {PC_OPCODE, NULL, NULL, 0, NULL,
797 0,0, // dest, bit instruction
799 0, // literal operand
801 1, // fast call/return mode select bit
802 0, // second memory operand
803 0, // second literal operand
806 PCC_NONE , // outCond
810 pCodeInstruction pic16_pciCOMF = {
811 {PC_OPCODE, NULL, NULL, 0, NULL,
824 1,0, // dest, bit instruction
826 0, // literal operand
828 0, // fast call/return mode select bit
829 0, // second memory operand
830 0, // second literal operand
832 PCC_REGISTER, // inCond
833 PCC_REGISTER , // outCond
837 pCodeInstruction pic16_pciCOMFW = {
838 {PC_OPCODE, NULL, NULL, 0, NULL,
851 0,0, // dest, bit instruction
853 0, // literal operand
855 0, // fast call/return mode select bit
856 0, // second memory operand
857 0, // second literal operand
859 PCC_REGISTER, // inCond
864 pCodeInstruction pic16_pciCLRF = {
865 {PC_OPCODE, NULL, NULL, 0, NULL,
878 0,0, // dest, bit instruction
880 0, // literal operand
882 0, // fast call/return mode select bit
883 0, // second memory operand
884 0, // second literal operand
886 PCC_REGISTER, // inCond
887 PCC_REGISTER , // outCond
891 pCodeInstruction pic16_pciCLRWDT = {
892 {PC_OPCODE, NULL, NULL, 0, NULL,
905 0,0, // dest, bit instruction
907 0, // literal operand
909 0, // fast call/return mode select bit
910 0, // second memory operand
911 0, // second literal operand
914 PCC_NONE , // outCond
918 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
919 {PC_OPCODE, NULL, NULL, 0, NULL,
932 0,0, // dest, bit instruction
934 0, // literal operand
936 0, // fast call/return mode select bit
937 0, // second memory operand
938 0, // second literal operand
940 (PCC_W | PCC_REGISTER), // inCond
941 PCC_NONE , // outCond
945 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
946 {PC_OPCODE, NULL, NULL, 0, NULL,
959 0,0, // dest, bit instruction
961 0, // literal operand
963 0, // fast call/return mode select bit
964 0, // second memory operand
965 0, // second literal operand
967 (PCC_W | PCC_REGISTER), // inCond
968 PCC_NONE , // outCond
972 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
973 {PC_OPCODE, NULL, NULL, 0, NULL,
986 1,0, // dest, bit instruction
988 0, // literal operand
990 0, // fast call/return mode select bit
991 0, // second memory operand
992 0, // second literal operand
994 (PCC_W | PCC_REGISTER), // inCond
995 PCC_NONE , // outCond
999 pCodeInstruction pic16_pciDAW = {
1000 {PC_OPCODE, NULL, NULL, 0, NULL,
1006 NULL, // from branch
1013 0,0, // dest, bit instruction
1014 0,0, // branch, skip
1015 0, // literal operand
1016 0, // RAM access bit
1017 0, // fast call/return mode select bit
1018 0, // second memory operand
1019 0, // second literal operand
1022 (PCC_W | PCC_C), // outCond
1026 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1027 {PC_OPCODE, NULL, NULL, 0, NULL,
1033 NULL, // from branch
1040 1,0, // dest, bit instruction
1041 1,1, // branch, skip
1042 0, // literal operand
1043 1, // RAM access bit
1044 0, // fast call/return mode select bit
1045 0, // second memory operand
1046 0, // second literal operand
1048 PCC_REGISTER, // inCond
1049 PCC_REGISTER , // outCond
1053 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1054 {PC_OPCODE, NULL, NULL, 0, NULL,
1060 NULL, // from branch
1067 0,0, // dest, bit instruction
1068 1,1, // branch, skip
1069 0, // literal operand
1070 1, // RAM access bit
1071 0, // fast call/return mode select bit
1072 0, // second memory operand
1073 0, // second literal operand
1075 PCC_REGISTER, // inCond
1080 pCodeInstruction pic16_pciDECF = {
1081 {PC_OPCODE, NULL, NULL, 0, NULL,
1087 NULL, // from branch
1094 1,0, // dest, bit instruction
1095 0,0, // branch, skip
1096 0, // literal operand
1097 1, // RAM access bit
1098 0, // fast call/return mode select bit
1099 0, // second memory operand
1100 0, // second literal operand
1102 PCC_REGISTER, // inCond
1103 PCC_REGISTER , // outCond
1107 pCodeInstruction pic16_pciDECFW = {
1108 {PC_OPCODE, NULL, NULL, 0, NULL,
1114 NULL, // from branch
1121 0,0, // dest, bit instruction
1122 0,0, // branch, skip
1123 0, // literal operand
1124 1, // RAM access bit
1125 0, // fast call/return mode select bit
1126 0, // second memory operand
1127 0, // second literal operand
1129 PCC_REGISTER, // inCond
1134 pCodeInstruction pic16_pciDECFSZ = {
1135 {PC_OPCODE, NULL, NULL, 0, NULL,
1141 NULL, // from branch
1148 1,0, // dest, bit instruction
1149 1,1, // branch, skip
1150 0, // literal operand
1151 1, // RAM access bit
1152 0, // fast call/return mode select bit
1153 0, // second memory operand
1154 0, // second literal operand
1156 PCC_REGISTER, // inCond
1157 PCC_REGISTER , // outCond
1161 pCodeInstruction pic16_pciDECFSZW = {
1162 {PC_OPCODE, NULL, NULL, 0, NULL,
1168 NULL, // from branch
1175 0,0, // dest, bit instruction
1176 1,1, // branch, skip
1177 0, // literal operand
1178 1, // RAM access bit
1179 0, // fast call/return mode select bit
1180 0, // second memory operand
1181 0, // second literal operand
1183 PCC_REGISTER, // inCond
1188 pCodeInstruction pic16_pciGOTO = {
1189 {PC_OPCODE, NULL, NULL, 0, NULL,
1195 NULL, // from branch
1202 0,0, // dest, bit instruction
1203 1,0, // branch, skip
1204 0, // literal operand
1205 0, // RAM access bit
1206 0, // fast call/return mode select bit
1207 0, // second memory operand
1208 0, // second literal operand
1210 PCC_REL_ADDR, // inCond
1211 PCC_NONE , // outCond
1215 pCodeInstruction pic16_pciINCF = {
1216 {PC_OPCODE, NULL, NULL, 0, NULL,
1222 NULL, // from branch
1229 1,0, // dest, bit instruction
1230 0,0, // branch, skip
1231 0, // literal operand
1232 1, // RAM access bit
1233 0, // fast call/return mode select bit
1234 0, // second memory operand
1235 0, // second literal operand
1237 PCC_REGISTER, // inCond
1238 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1242 pCodeInstruction pic16_pciINCFW = {
1243 {PC_OPCODE, NULL, NULL, 0, NULL,
1249 NULL, // from branch
1256 0,0, // dest, bit instruction
1257 0,0, // branch, skip
1258 0, // literal operand
1259 1, // RAM access bit
1260 0, // fast call/return mode select bit
1261 0, // second memory operand
1262 0, // second literal operand
1264 PCC_REGISTER, // inCond
1269 pCodeInstruction pic16_pciINCFSZ = {
1270 {PC_OPCODE, NULL, NULL, 0, NULL,
1276 NULL, // from branch
1283 1,0, // dest, bit instruction
1284 1,1, // branch, skip
1285 0, // literal operand
1286 1, // RAM access bit
1287 0, // fast call/return mode select bit
1288 0, // second memory operand
1289 0, // second literal operand
1291 PCC_REGISTER, // inCond
1292 PCC_REGISTER , // outCond
1296 pCodeInstruction pic16_pciINCFSZW = {
1297 {PC_OPCODE, NULL, NULL, 0, NULL,
1303 NULL, // from branch
1310 0,0, // dest, bit instruction
1311 1,1, // branch, skip
1312 0, // literal operand
1313 1, // RAM access bit
1314 0, // fast call/return mode select bit
1315 0, // second memory operand
1316 0, // second literal operand
1318 PCC_REGISTER, // inCond
1323 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1324 {PC_OPCODE, NULL, NULL, 0, NULL,
1330 NULL, // from branch
1337 1,0, // dest, bit instruction
1338 1,1, // branch, skip
1339 0, // literal operand
1340 1, // RAM access bit
1341 0, // fast call/return mode select bit
1342 0, // second memory operand
1343 0, // second literal operand
1345 PCC_REGISTER, // inCond
1346 PCC_REGISTER , // outCond
1350 pCodeInstruction pic16_pciINFSNZW = { // vrokas - New
1351 {PC_OPCODE, NULL, NULL, 0, NULL,
1357 NULL, // from branch
1364 0,0, // dest, bit instruction
1365 1,1, // branch, skip
1366 0, // literal operand
1367 1, // RAM access bit
1368 0, // fast call/return mode select bit
1369 0, // second memory operand
1370 0, // second literal operand
1372 PCC_REGISTER, // inCond
1377 pCodeInstruction pic16_pciIORWF = {
1378 {PC_OPCODE, NULL, NULL, 0, NULL,
1384 NULL, // from branch
1391 1,0, // dest, bit instruction
1392 0,0, // branch, skip
1393 0, // literal operand
1394 1, // RAM access bit
1395 0, // fast call/return mode select bit
1396 0, // second memory operand
1397 0, // second literal operand
1399 (PCC_W | PCC_REGISTER), // inCond
1400 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1404 pCodeInstruction pic16_pciIORFW = {
1405 {PC_OPCODE, NULL, NULL, 0, NULL,
1411 NULL, // from branch
1418 0,0, // dest, bit instruction
1419 0,0, // branch, skip
1420 0, // literal operand
1421 1, // RAM access bit
1422 0, // fast call/return mode select bit
1423 0, // second memory operand
1424 0, // second literal operand
1426 (PCC_W | PCC_REGISTER), // inCond
1427 (PCC_W | PCC_Z | PCC_N), // outCond
1431 pCodeInstruction pic16_pciIORLW = {
1432 {PC_OPCODE, NULL, NULL, 0, NULL,
1438 NULL, // from branch
1445 0,0, // dest, bit instruction
1446 0,0, // branch, skip
1447 1, // literal operand
1448 0, // RAM access bit
1449 0, // fast call/return mode select bit
1450 0, // second memory operand
1451 0, // second literal operand
1453 (PCC_W | PCC_LITERAL), // inCond
1454 (PCC_W | PCC_Z | PCC_N), // outCond
1458 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1459 {PC_OPCODE, NULL, NULL, 0, NULL,
1465 NULL, // from branch
1472 0,0, // dest, bit instruction
1473 0,0, // branch, skip
1474 1, // literal operand
1475 0, // RAM access bit
1476 0, // fast call/return mode select bit
1477 0, // second memory operand
1478 1, // second literal operand
1480 (PCC_REGISTER | PCC_LITERAL),
1481 PCC_REGISTER, // outCond
1485 pCodeInstruction pic16_pciMOVF = {
1486 {PC_OPCODE, NULL, NULL, 0, NULL,
1492 NULL, // from branch
1499 1,0, // dest, bit instruction
1500 0,0, // branch, skip
1501 0, // literal operand
1502 1, // RAM access bit
1503 0, // fast call/return mode select bit
1504 0, // second memory operand
1505 0, // second literal operand
1507 PCC_REGISTER, // inCond
1508 (PCC_Z | PCC_N), // outCond
1512 pCodeInstruction pic16_pciMOVFW = {
1513 {PC_OPCODE, NULL, NULL, 0, NULL,
1519 NULL, // from branch
1526 0,0, // dest, bit instruction
1527 0,0, // branch, skip
1528 0, // literal operand
1529 1, // RAM access bit
1530 0, // fast call/return mode select bit
1531 0, // second memory operand
1532 0, // second literal operand
1534 PCC_REGISTER, // inCond
1535 (PCC_W | PCC_Z), // outCond
1539 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1540 {PC_OPCODE, NULL, NULL, 0, NULL,
1546 NULL, // from branch
1553 0,0, // dest, bit instruction
1554 0,0, // branch, skip
1555 0, // literal operand
1556 0, // RAM access bit
1557 0, // fast call/return mode select bit
1558 1, // second memory operand
1559 0, // second literal operand
1561 PCC_REGISTER, // inCond
1562 PCC_REGISTER, // outCond
1566 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1567 {PC_OPCODE, NULL, NULL, 0, NULL,
1572 NULL, // from branch
1579 0,0, // dest, bit instruction
1580 0,0, // branch, skip
1581 1, // literal operand
1582 0, // RAM access bit
1583 0, // fast call/return mode select bit
1584 0, // second memory operand
1585 0, // second literal operand
1587 (PCC_NONE | PCC_LITERAL), // inCond
1588 PCC_REGISTER, // outCond - BSR
1592 pCodeInstruction pic16_pciMOVLW = {
1593 {PC_OPCODE, NULL, NULL, 0, NULL,
1598 NULL, // from branch
1605 0,0, // dest, bit instruction
1606 0,0, // branch, skip
1607 1, // literal operand
1608 0, // RAM access bit
1609 0, // fast call/return mode select bit
1610 0, // second memory operand
1611 0, // second literal operand
1613 (PCC_NONE | PCC_LITERAL), // inCond
1618 pCodeInstruction pic16_pciMOVWF = {
1619 {PC_OPCODE, NULL, NULL, 0, NULL,
1625 NULL, // from branch
1632 0,0, // dest, bit instruction
1633 0,0, // branch, skip
1634 0, // literal operand
1635 1, // RAM access bit
1636 0, // fast call/return mode select bit
1637 0, // second memory operand
1638 0, // second literal operand
1640 PCC_REGISTER, // inCond
1645 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1646 {PC_OPCODE, NULL, NULL, 0, NULL,
1651 NULL, // from branch
1658 0,0, // dest, bit instruction
1659 0,0, // branch, skip
1660 1, // literal operand
1661 0, // RAM access bit
1662 0, // fast call/return mode select bit
1663 0, // second memory operand
1664 0, // second literal operand
1666 (PCC_W | PCC_LITERAL), // inCond
1667 PCC_REGISTER, // outCond - PROD
1671 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1672 {PC_OPCODE, NULL, NULL, 0, NULL,
1677 NULL, // from branch
1684 0,0, // dest, bit instruction
1685 0,0, // branch, skip
1686 0, // literal operand
1687 1, // RAM access bit
1688 0, // fast call/return mode select bit
1689 0, // second memory operand
1690 0, // second literal operand
1692 (PCC_W | PCC_REGISTER), // inCond
1693 PCC_REGISTER, // outCond - PROD
1697 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1698 {PC_OPCODE, NULL, NULL, 0, NULL,
1703 NULL, // from branch
1710 0,0, // dest, bit instruction
1711 0,0, // branch, skip
1712 0, // literal operand
1713 1, // RAM access bit
1714 0, // fast call/return mode select bit
1715 0, // second memory operand
1716 0, // second literal operand
1718 PCC_REGISTER, // inCond
1719 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1723 pCodeInstruction pic16_pciNOP = {
1724 {PC_OPCODE, NULL, NULL, 0, NULL,
1729 NULL, // from branch
1736 0,0, // dest, bit instruction
1737 0,0, // branch, skip
1738 0, // literal operand
1739 0, // RAM access bit
1740 0, // fast call/return mode select bit
1741 0, // second memory operand
1742 0, // second literal operand
1745 PCC_NONE, // outCond
1749 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1750 {PC_OPCODE, NULL, NULL, 0, NULL,
1755 NULL, // from branch
1762 0,0, // dest, bit instruction
1763 0,0, // branch, skip
1764 0, // literal operand
1765 0, // RAM access bit
1766 0, // fast call/return mode select bit
1767 0, // second memory operand
1768 0, // second literal operand
1771 PCC_NONE , // outCond
1775 pCodeInstruction pic16_pciPUSH = {
1776 {PC_OPCODE, NULL, NULL, 0, NULL,
1781 NULL, // from branch
1788 0,0, // dest, bit instruction
1789 0,0, // branch, skip
1790 0, // literal operand
1791 0, // RAM access bit
1792 0, // fast call/return mode select bit
1793 0, // second memory operand
1794 0, // second literal operand
1797 PCC_NONE , // outCond
1801 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1802 {PC_OPCODE, NULL, NULL, 0, NULL,
1807 NULL, // from branch
1814 0,0, // dest, bit instruction
1815 0,0, // branch, skip
1816 0, // literal operand
1817 0, // RAM access bit
1818 0, // fast call/return mode select bit
1819 0, // second memory operand
1820 0, // second literal operand
1822 PCC_REL_ADDR, // inCond
1823 PCC_NONE , // outCond
1827 pCodeInstruction pic16_pciRETFIE = {
1828 {PC_OPCODE, NULL, NULL, 0, NULL,
1834 NULL, // from branch
1841 0,0, // dest, bit instruction
1842 1,0, // branch, skip
1843 0, // literal operand
1844 0, // RAM access bit
1845 1, // fast call/return mode select bit
1846 0, // second memory operand
1847 0, // second literal operand
1850 PCC_NONE, // outCond (not true... affects the GIE bit too)
1854 pCodeInstruction pic16_pciRETLW = {
1855 {PC_OPCODE, NULL, NULL, 0, NULL,
1861 NULL, // from branch
1868 0,0, // dest, bit instruction
1869 1,0, // branch, skip
1870 1, // literal operand
1871 0, // RAM access bit
1872 0, // fast call/return mode select bit
1873 0, // second memory operand
1874 0, // second literal operand
1876 PCC_LITERAL, // inCond
1881 pCodeInstruction pic16_pciRETURN = {
1882 {PC_OPCODE, NULL, NULL, 0, NULL,
1888 NULL, // from branch
1895 0,0, // dest, bit instruction
1896 1,0, // branch, skip
1897 0, // literal operand
1898 0, // RAM access bit
1899 1, // fast call/return mode select bit
1900 0, // second memory operand
1901 0, // second literal operand
1904 PCC_NONE, // outCond
1907 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1908 {PC_OPCODE, NULL, NULL, 0, NULL,
1914 NULL, // from branch
1921 1,0, // dest, bit instruction
1922 0,0, // branch, skip
1923 0, // literal operand
1924 1, // RAM access bit
1925 0, // fast call/return mode select bit
1926 0, // second memory operand
1927 0, // second literal operand
1929 (PCC_C | PCC_REGISTER), // inCond
1930 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1934 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1935 {PC_OPCODE, NULL, NULL, 0, NULL,
1941 NULL, // from branch
1948 0,0, // dest, bit instruction
1949 0,0, // branch, skip
1950 0, // literal operand
1951 1, // RAM access bit
1952 0, // fast call/return mode select bit
1953 0, // second memory operand
1954 0, // second literal operand
1956 (PCC_C | PCC_REGISTER), // inCond
1957 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1961 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1962 {PC_OPCODE, NULL, NULL, 0, NULL,
1968 NULL, // from branch
1975 1,0, // dest, bit instruction
1976 0,0, // branch, skip
1977 0, // literal operand
1978 1, // RAM access bit
1979 0, // fast call/return mode select bit
1980 0, // second memory operand
1981 0, // second literal operand
1983 PCC_REGISTER, // inCond
1984 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1987 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1988 {PC_OPCODE, NULL, NULL, 0, NULL,
1994 NULL, // from branch
2001 0,0, // dest, bit instruction
2002 0,0, // branch, skip
2003 0, // literal operand
2004 1, // RAM access bit
2005 0, // fast call/return mode select bit
2006 0, // second memory operand
2007 0, // second literal operand
2009 PCC_REGISTER, // inCond
2010 (PCC_W | PCC_Z | PCC_N), // outCond
2013 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
2014 {PC_OPCODE, NULL, NULL, 0, NULL,
2020 NULL, // from branch
2027 1,0, // dest, bit instruction
2028 0,0, // branch, skip
2029 0, // literal operand
2030 1, // RAM access bit
2031 0, // fast call/return mode select bit
2032 0, // second memory operand
2033 0, // second literal operand
2035 (PCC_C | PCC_REGISTER), // inCond
2036 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2039 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2040 {PC_OPCODE, NULL, NULL, 0, NULL,
2046 NULL, // from branch
2053 0,0, // dest, bit instruction
2054 0,0, // branch, skip
2055 0, // literal operand
2056 1, // RAM access bit
2057 0, // fast call/return mode select bit
2058 0, // second memory operand
2059 0, // second literal operand
2061 (PCC_C | PCC_REGISTER), // inCond
2062 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2065 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2066 {PC_OPCODE, NULL, NULL, 0, NULL,
2072 NULL, // from branch
2079 1,0, // dest, bit instruction
2080 0,0, // branch, skip
2081 0, // literal operand
2082 1, // RAM access bit
2083 0, // fast call/return mode select bit
2084 0, // second memory operand
2085 0, // second literal operand
2087 PCC_REGISTER, // inCond
2088 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2092 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2093 {PC_OPCODE, NULL, NULL, 0, NULL,
2099 NULL, // from branch
2106 0,0, // dest, bit instruction
2107 0,0, // branch, skip
2108 0, // literal operand
2109 1, // RAM access bit
2110 0, // fast call/return mode select bit
2111 0, // second memory operand
2112 0, // second literal operand
2114 PCC_REGISTER, // inCond
2115 (PCC_W | PCC_Z | PCC_N), // outCond
2119 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2120 {PC_OPCODE, NULL, NULL, 0, NULL,
2126 NULL, // from branch
2133 0,0, // dest, bit instruction
2134 0,0, // branch, skip
2135 0, // literal operand
2136 1, // RAM access bit
2137 0, // fast call/return mode select bit
2138 0, // second memory operand
2139 0, // second literal operand
2141 PCC_REGISTER, // inCond
2142 PCC_REGISTER , // outCond
2146 pCodeInstruction pic16_pciSUBLW = {
2147 {PC_OPCODE, NULL, NULL, 0, NULL,
2153 NULL, // from branch
2160 0,0, // dest, bit instruction
2161 0,0, // branch, skip
2162 1, // literal operand
2163 0, // RAM access bit
2164 0, // fast call/return mode select bit
2165 0, // second memory operand
2166 0, // second literal operand
2168 (PCC_W | PCC_LITERAL), // inCond
2169 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2173 pCodeInstruction pic16_pciSUBFWB = {
2174 {PC_OPCODE, NULL, NULL, 0, NULL,
2180 NULL, // from branch
2187 1,0, // dest, bit instruction
2188 0,0, // branch, skip
2189 0, // literal operand
2190 1, // RAM access bit
2191 0, // fast call/return mode select bit
2192 0, // second memory operand
2193 0, // second literal operand
2195 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2196 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2200 pCodeInstruction pic16_pciSUBWF = {
2201 {PC_OPCODE, NULL, NULL, 0, NULL,
2207 NULL, // from branch
2214 1,0, // dest, bit instruction
2215 0,0, // branch, skip
2216 0, // literal operand
2217 1, // RAM access bit
2218 0, // fast call/return mode select bit
2219 0, // second memory operand
2220 0, // second literal operand
2222 (PCC_W | PCC_REGISTER), // inCond
2223 (PCC_REGISTER | PCC_Z), // outCond
2227 pCodeInstruction pic16_pciSUBFW = {
2228 {PC_OPCODE, NULL, NULL, 0, NULL,
2234 NULL, // from branch
2241 0,0, // dest, bit instruction
2242 0,0, // branch, skip
2243 0, // literal operand
2244 1, // RAM access bit
2245 0, // fast call/return mode select bit
2246 0, // second memory operand
2247 0, // second literal operand
2249 (PCC_W | PCC_REGISTER), // inCond
2250 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2254 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2255 {PC_OPCODE, NULL, NULL, 0, NULL,
2261 NULL, // from branch
2268 1,0, // dest, bit instruction
2269 0,0, // branch, skip
2270 0, // literal operand
2271 1, // RAM access bit
2272 0, // fast call/return mode select bit
2273 0, // second memory operand
2274 0, // second literal operand
2276 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2277 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2281 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2282 {PC_OPCODE, NULL, NULL, 0, NULL,
2288 NULL, // from branch
2295 0,0, // dest, bit instruction
2296 0,0, // branch, skip
2297 0, // literal operand
2298 1, // RAM access bit
2299 0, // fast call/return mode select bit
2300 0, // second memory operand
2301 0, // second literal operand
2303 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2304 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2308 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2309 {PC_OPCODE, NULL, NULL, 0, NULL,
2315 NULL, // from branch
2322 1,0, // dest, bit instruction
2323 0,0, // branch, skip
2324 0, // literal operand
2325 1, // RAM access bit
2326 0, // fast call/return mode select bit
2327 0, // second memory operand
2328 0, // second literal operand
2330 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2331 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2335 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2336 {PC_OPCODE, NULL, NULL, 0, NULL,
2342 NULL, // from branch
2349 0,0, // dest, bit instruction
2350 0,0, // branch, skip
2351 0, // literal operand
2352 1, // RAM access bit
2353 0, // fast call/return mode select bit
2354 0, // second memory operand
2355 0, // second literal operand
2357 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2358 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2362 pCodeInstruction pic16_pciSWAPF = {
2363 {PC_OPCODE, NULL, NULL, 0, NULL,
2369 NULL, // from branch
2376 1,0, // dest, bit instruction
2377 0,0, // branch, skip
2378 0, // literal operand
2379 1, // RAM access bit
2380 0, // fast call/return mode select bit
2381 0, // second memory operand
2382 0, // second literal operand
2384 (PCC_REGISTER), // inCond
2385 (PCC_REGISTER), // outCond
2389 pCodeInstruction pic16_pciSWAPFW = {
2390 {PC_OPCODE, NULL, NULL, 0, NULL,
2396 NULL, // from branch
2403 0,0, // dest, bit instruction
2404 0,0, // branch, skip
2405 0, // literal operand
2406 1, // RAM access bit
2407 0, // fast call/return mode select bit
2408 0, // second memory operand
2409 0, // second literal operand
2411 (PCC_REGISTER), // inCond
2416 pCodeInstruction pic16_pciTBLRD = { // patch 15
2417 {PC_OPCODE, NULL, NULL, 0, NULL,
2422 NULL, // from branch
2429 0,0, // dest, bit instruction
2430 0,0, // branch, skip
2431 0, // literal operand
2432 0, // RAM access bit
2433 0, // fast call/return mode select bit
2434 0, // second memory operand
2435 0, // second literal operand
2438 PCC_NONE , // outCond
2442 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2443 {PC_OPCODE, NULL, NULL, 0, NULL,
2448 NULL, // from branch
2455 0,0, // dest, bit instruction
2456 0,0, // branch, skip
2457 0, // literal operand
2458 0, // RAM access bit
2459 0, // fast call/return mode select bit
2460 0, // second memory operand
2461 0, // second literal operand
2464 PCC_NONE , // outCond
2468 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2469 {PC_OPCODE, NULL, NULL, 0, NULL,
2474 NULL, // from branch
2481 0,0, // dest, bit instruction
2482 0,0, // branch, skip
2483 0, // literal operand
2484 0, // RAM access bit
2485 0, // fast call/return mode select bit
2486 0, // second memory operand
2487 0, // second literal operand
2490 PCC_NONE , // outCond
2494 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2495 {PC_OPCODE, NULL, NULL, 0, NULL,
2500 NULL, // from branch
2507 0,0, // dest, bit instruction
2508 0,0, // branch, skip
2509 0, // literal operand
2510 0, // RAM access bit
2511 0, // fast call/return mode select bit
2512 0, // second memory operand
2513 0, // second literal operand
2516 PCC_NONE , // outCond
2520 pCodeInstruction pic16_pciTBLWT = { // patch 15
2521 {PC_OPCODE, NULL, NULL, 0, NULL,
2526 NULL, // from branch
2533 0,0, // dest, bit instruction
2534 0,0, // branch, skip
2535 0, // literal operand
2536 0, // RAM access bit
2537 0, // fast call/return mode select bit
2538 0, // second memory operand
2539 0, // second literal operand
2542 PCC_NONE , // outCond
2546 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2547 {PC_OPCODE, NULL, NULL, 0, NULL,
2552 NULL, // from branch
2559 0,0, // dest, bit instruction
2560 0,0, // branch, skip
2561 0, // literal operand
2562 0, // RAM access bit
2563 0, // fast call/return mode select bit
2564 0, // second memory operand
2565 0, // second literal operand
2568 PCC_NONE , // outCond
2572 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2573 {PC_OPCODE, NULL, NULL, 0, NULL,
2578 NULL, // from branch
2585 0,0, // dest, bit instruction
2586 0,0, // branch, skip
2587 0, // literal operand
2588 0, // RAM access bit
2589 0, // fast call/return mode select bit
2590 0, // second memory operand
2591 0, // second literal operand
2594 PCC_NONE , // outCond
2598 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2599 {PC_OPCODE, NULL, NULL, 0, NULL,
2604 NULL, // from branch
2611 0,0, // dest, bit instruction
2612 0,0, // branch, skip
2613 0, // literal operand
2614 0, // RAM access bit
2615 0, // fast call/return mode select bit
2616 0, // second memory operand
2617 0, // second literal operand
2620 PCC_NONE , // outCond
2624 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2625 {PC_OPCODE, NULL, NULL, 0, NULL,
2631 NULL, // from branch
2638 0,0, // dest, bit instruction
2639 1,1, // branch, skip
2640 0, // literal operand
2641 1, // RAM access bit
2642 0, // fast call/return mode select bit
2643 0, // second memory operand
2644 0, // second literal operand
2646 PCC_REGISTER, // inCond
2647 PCC_NONE, // outCond
2651 pCodeInstruction pic16_pciXORWF = {
2652 {PC_OPCODE, NULL, NULL, 0, NULL,
2658 NULL, // from branch
2665 1,0, // dest, bit instruction
2666 0,0, // branch, skip
2667 0, // literal operand
2668 1, // RAM access bit
2669 0, // fast call/return mode select bit
2670 0, // second memory operand
2671 0, // second literal operand
2673 (PCC_W | PCC_REGISTER), // inCond
2674 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2678 pCodeInstruction pic16_pciXORFW = {
2679 {PC_OPCODE, NULL, NULL, 0, NULL,
2685 NULL, // from branch
2692 0,0, // dest, bit instruction
2693 0,0, // branch, skip
2694 0, // literal operand
2695 1, // RAM access bit
2696 0, // fast call/return mode select bit
2697 0, // second memory operand
2698 0, // second literal operand
2700 (PCC_W | PCC_REGISTER), // inCond
2701 (PCC_W | PCC_Z | PCC_N), // outCond
2705 pCodeInstruction pic16_pciXORLW = {
2706 {PC_OPCODE, NULL, NULL, 0, NULL,
2712 NULL, // from branch
2719 0,0, // dest, bit instruction
2720 0,0, // branch, skip
2721 1, // literal operand
2722 1, // RAM access bit
2723 0, // fast call/return mode select bit
2724 0, // second memory operand
2725 0, // second literal operand
2727 (PCC_W | PCC_LITERAL), // inCond
2728 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2733 pCodeInstruction pic16_pciBANKSEL = {
2734 {PC_OPCODE, NULL, NULL, 0, NULL,
2739 NULL, // from branch
2746 0,0, // dest, bit instruction
2747 0,0, // branch, skip
2748 0, // literal operand
2749 0, // RAM access bit
2750 0, // fast call/return mode select bit
2751 0, // second memory operand
2752 0, // second literal operand
2755 PCC_NONE, // outCond
2760 #define MAX_PIC16MNEMONICS 100
2761 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2763 //#define USE_VSNPRINTF
2766 #ifdef USE_VSNPRINTF
2767 // Alas, vsnprintf is not ANSI standard, and does not exist
2768 // on Solaris (and probably other non-Gnu flavored Unixes).
2770 /*-----------------------------------------------------------------*/
2771 /* SAFE_snprintf - like snprintf except the string pointer is */
2772 /* after the string has been printed to. This is */
2773 /* useful for printing to string as though if it */
2774 /* were a stream. */
2775 /*-----------------------------------------------------------------*/
2776 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2784 va_start(val, format);
2786 vsnprintf(*str, *size, format, val);
2792 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2793 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2802 // This version is *not* safe, despite the name.
2804 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2808 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2813 va_start(val, format);
2815 vsprintf(buffer, format, val);
2818 len = strlen(buffer);
2820 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2821 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2824 strcpy(*str, buffer);
2830 #endif // USE_VSNPRINTF
2833 extern set *externs;
2834 extern void pic16_initStack(int base_address, int size);
2835 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2836 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2837 extern void pic16_init_pic(char *);
2839 void pic16_pCodeInitRegisters(void)
2841 static int initialized=0;
2848 // pic16_initStack(0xfff, 8);
2849 pic16_init_pic(port->processor);
2851 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2852 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2853 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2854 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2855 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2856 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2857 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2859 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2860 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2861 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2863 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2864 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2865 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2866 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2868 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2869 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2870 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2871 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2872 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2873 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2875 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2876 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2877 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2878 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2879 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2881 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2882 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2883 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2884 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2885 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2887 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2888 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2889 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2890 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2891 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2893 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2894 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2897 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
2898 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
2899 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
2900 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
2903 pic16_pc_status.rIdx = IDX_STATUS;
2904 pic16_pc_intcon.rIdx = IDX_INTCON;
2905 pic16_pc_pcl.rIdx = IDX_PCL;
2906 pic16_pc_pclath.rIdx = IDX_PCLATH;
2907 pic16_pc_pclatu.rIdx = IDX_PCLATU;
2908 pic16_pc_wreg.rIdx = IDX_WREG;
2909 pic16_pc_bsr.rIdx = IDX_BSR;
2911 pic16_pc_tosl.rIdx = IDX_TOSL;
2912 pic16_pc_tosh.rIdx = IDX_TOSH;
2913 pic16_pc_tosu.rIdx = IDX_TOSU;
2915 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
2916 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
2917 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
2918 pic16_pc_tablat.rIdx = IDX_TABLAT;
2920 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2921 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2922 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2923 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2924 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2925 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2926 pic16_pc_indf0.rIdx = IDX_INDF0;
2927 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2928 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2929 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2930 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2931 pic16_pc_indf1.rIdx = IDX_INDF1;
2932 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2933 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2934 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2935 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2936 pic16_pc_indf2.rIdx = IDX_INDF2;
2937 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2938 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2939 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2940 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2941 pic16_pc_prodl.rIdx = IDX_PRODL;
2942 pic16_pc_prodh.rIdx = IDX_PRODH;
2944 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2945 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
2946 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2948 pic16_pc_kzero.rIdx = IDX_KZ;
2949 pic16_pc_wsave.rIdx = IDX_WSAVE;
2950 pic16_pc_ssave.rIdx = IDX_SSAVE;
2952 pic16_pc_eecon1.rIdx = IDX_EECON1;
2953 pic16_pc_eecon2.rIdx = IDX_EECON2;
2954 pic16_pc_eedata.rIdx = IDX_EEDATA;
2955 pic16_pc_eeadr.rIdx = IDX_EEADR;
2958 pic16_pc_gpsimio.r = pic16_allocProcessorRegister(IDX_GPSIMIO, "GPSIMIO", PO_GPR_REGISTER, 0x80);
2959 pic16_pc_gpsimio2.r = pic16_allocProcessorRegister(IDX_GPSIMIO2, "GPSIMIO2", PO_GPR_REGISTER, 0x80);
2961 pic16_pc_gpsimio.rIdx = IDX_GPSIMIO;
2962 pic16_pc_gpsimio2.rIdx = IDX_GPSIMIO2;
2964 /* probably should put this in a separate initialization routine */
2965 pb_dead_pcodes = newpBlock();
2970 /*-----------------------------------------------------------------*/
2971 /* mnem2key - convert a pic mnemonic into a hash key */
2972 /* (BTW - this spreads the mnemonics quite well) */
2974 /*-----------------------------------------------------------------*/
2976 int mnem2key(char const *mnem)
2985 key += toupper(*mnem++) +1;
2989 return (key & 0x1f);
2994 void pic16initMnemonics(void)
2999 pCodeInstruction *pci;
3001 if(mnemonics_initialized)
3004 // NULL out the array before making the assignments
3005 // since we check the array contents below this initialization.
3007 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
3008 pic16Mnemonics[i] = NULL;
3011 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
3012 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
3013 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
3014 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
3015 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
3016 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
3017 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
3018 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
3019 pic16Mnemonics[POC_BC] = &pic16_pciBC;
3020 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
3021 pic16Mnemonics[POC_BN] = &pic16_pciBN;
3022 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
3023 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
3024 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
3025 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
3026 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
3027 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
3028 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
3029 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
3030 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
3031 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
3032 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
3033 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
3034 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
3035 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
3036 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
3037 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
3038 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
3039 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
3040 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
3041 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
3042 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
3043 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
3044 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
3045 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3046 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3047 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3048 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3049 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3050 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3051 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3052 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3053 pic16Mnemonics[POC_INFSNZW] = &pic16_pciINFSNZW;
3054 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3055 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3056 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3057 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3058 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3059 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3060 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3061 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3062 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3063 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3064 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3065 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3066 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3067 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3068 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3069 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3070 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3071 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3072 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3073 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3074 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3075 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3076 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3077 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3078 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3079 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3080 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3081 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3082 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3083 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3084 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3085 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3086 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3087 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3088 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3089 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3090 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3091 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3092 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3093 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3094 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3095 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3096 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3097 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3098 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3099 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3100 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3101 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3102 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3103 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3104 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3106 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3107 if(pic16Mnemonics[i])
3108 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3109 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3112 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3113 pci = hTabNextItem(pic16MnemonicsHash, &key);
3116 mnemonics_initialized = 1;
3119 int pic16_getpCodePeepCommand(char *cmd);
3121 int pic16_getpCode(char *mnem,unsigned dest)
3124 pCodeInstruction *pci;
3125 int key = mnem2key(mnem);
3127 if(!mnemonics_initialized)
3128 pic16initMnemonics();
3130 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3134 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3135 if((pci->num_ops <= 1)
3136 || (pci->isModReg == dest)
3138 || (pci->num_ops <= 2 && pci->isAccess)
3139 || (pci->num_ops <= 2 && pci->isFastCall)
3140 || (pci->num_ops <= 2 && pci->is2MemOp)
3141 || (pci->num_ops <= 2 && pci->is2LitOp) )
3145 pci = hTabNextItemWK (pic16MnemonicsHash);
3152 /*-----------------------------------------------------------------*
3153 * pic16initpCodePeepCommands
3155 *-----------------------------------------------------------------*/
3156 void pic16initpCodePeepCommands(void)
3164 hTabAddItem(&pic16pCodePeepCommandsHash,
3165 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3167 } while (peepCommands[i].cmd);
3169 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3172 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3173 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3178 /*-----------------------------------------------------------------
3181 *-----------------------------------------------------------------*/
3183 int pic16_getpCodePeepCommand(char *cmd)
3187 int key = mnem2key(cmd);
3190 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3193 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3194 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3198 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3205 static char getpBlock_dbName(pBlock *pb)
3211 return pb->cmemmap->dbName;
3215 void pic16_pBlockConvert2ISR(pBlock *pb)
3219 if(pb->cmemmap)pb->cmemmap = NULL;
3223 if(pic16_pcode_verbose)
3224 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3227 void pic16_pBlockConvert2Absolute(pBlock *pb)
3230 if(pb->cmemmap)pb->cmemmap = NULL;
3234 if(pic16_pcode_verbose)
3235 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3238 /*-----------------------------------------------------------------*/
3239 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3240 /* instances to the front of the doubly linked */
3241 /* list of pBlocks */
3242 /*-----------------------------------------------------------------*/
3244 void pic16_movepBlock2Head(char dbName)
3249 /* this can happen in sources without code,
3250 * only variable definitions */
3251 if(!the_pFile)return;
3253 pb = the_pFile->pbHead;
3257 if(getpBlock_dbName(pb) == dbName) {
3258 pBlock *pbn = pb->next;
3259 pb->next = the_pFile->pbHead;
3260 the_pFile->pbHead->prev = pb;
3261 the_pFile->pbHead = pb;
3264 pb->prev->next = pbn;
3266 // If the pBlock that we just moved was the last
3267 // one in the link of all of the pBlocks, then we
3268 // need to point the tail to the block just before
3269 // the one we moved.
3270 // Note: if pb->next is NULL, then pb must have
3271 // been the last pBlock in the chain.
3274 pbn->prev = pb->prev;
3276 the_pFile->pbTail = pb->prev;
3287 void pic16_copypCode(FILE *of, char dbName)
3291 if(!of || !the_pFile)
3294 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3295 if(getpBlock_dbName(pb) == dbName) {
3296 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3298 pic16_printpBlock(of,pb);
3303 void pic16_pcode_test(void)
3306 DFPRINTF((stderr,"pcode is alive!\n"));
3316 /* create the file name */
3317 strcpy(buffer,dstFileName);
3318 strcat(buffer,".p");
3320 if( !(pFile = fopen(buffer, "w" ))) {
3321 werror(E_FILE_OPEN_ERR,buffer);
3325 fprintf(pFile,"pcode dump\n\n");
3327 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3328 fprintf(pFile,"\n\tNew pBlock\n\n");
3330 fprintf(pFile,"%s",pb->cmemmap->sname);
3332 fprintf(pFile,"internal pblock");
3334 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3335 pic16_printpBlock(pFile,pb);
3339 /*-----------------------------------------------------------------*/
3340 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3341 /* ister, RegCond will return the bit being referenced. */
3343 /* fixme - why not just OR in the pcop bit field */
3344 /*-----------------------------------------------------------------*/
3346 static int RegCond(pCodeOp *pcop)
3352 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3353 switch(PCORB(pcop)->bit) {
3367 /*-----------------------------------------------------------------*/
3368 /* pic16_newpCode - create and return a newly initialized pCode */
3370 /* fixme - rename this */
3372 /* The purpose of this routine is to create a new Instruction */
3373 /* pCode. This is called by gen.c while the assembly code is being */
3377 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3378 /* (note that the op is analogous to but not the */
3379 /* same thing as the opcode of the instruction.) */
3380 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3383 /* a pointer to the new malloc'd pCode is returned. */
3387 /*-----------------------------------------------------------------*/
3388 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3390 pCodeInstruction *pci ;
3392 if(!mnemonics_initialized)
3393 pic16initMnemonics();
3395 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3397 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3398 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3401 if(pci->inCond & PCC_EXAMINE_PCOP)
3402 pci->inCond |= RegCond(pcop);
3404 if(pci->outCond & PCC_EXAMINE_PCOP)
3405 pci->outCond |= RegCond(pcop);
3407 pci->pc.prev = pci->pc.next = NULL;
3408 return (pCode *)pci;
3411 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3417 /*-----------------------------------------------------------------*/
3418 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3420 /* Wild pcodes are used during the peep hole optimizer to serve */
3421 /* as place holders for any instruction. When a snippet of code is */
3422 /* compared to a peep hole rule, the wild card opcode will match */
3423 /* any instruction. However, the optional operand and label are */
3424 /* additional qualifiers that must also be matched before the */
3425 /* line (of assembly code) is declared matched. Note that the */
3426 /* operand may be wild too. */
3428 /* Note, a wild instruction is specified just like a wild var: */
3429 /* %4 ; A wild instruction, */
3430 /* See the peeph.def file for additional examples */
3432 /*-----------------------------------------------------------------*/
3434 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3439 pcw = Safe_calloc(1,sizeof(pCodeWild));
3441 pcw->pci.pc.type = PC_WILD;
3442 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3443 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3444 pcw->pci.pc.pb = NULL;
3446 // pcw->pci.pc.analyze = genericAnalyze;
3447 pcw->pci.pc.destruct = genericDestruct;
3448 pcw->pci.pc.print = genericPrint;
3450 pcw->id = pCodeID; // this is the 'n' in %n
3451 pcw->operand = optional_operand;
3452 pcw->label = optional_label;
3454 pcw->mustBeBitSkipInst = 0;
3455 pcw->mustNotBeBitSkipInst = 0;
3456 pcw->invertBitSkipInst = 0;
3458 return ( (pCode *)pcw);
3462 /*-----------------------------------------------------------------*/
3463 /* newPcodeInlineP - create a new pCode from a char string */
3464 /*-----------------------------------------------------------------*/
3467 pCode *pic16_newpCodeInlineP(char *cP)
3472 pcc = Safe_calloc(1,sizeof(pCodeComment));
3474 pcc->pc.type = PC_INLINE;
3475 pcc->pc.prev = pcc->pc.next = NULL;
3476 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3479 // pcc->pc.analyze = genericAnalyze;
3480 pcc->pc.destruct = genericDestruct;
3481 pcc->pc.print = genericPrint;
3484 pcc->comment = Safe_strdup(cP);
3486 pcc->comment = NULL;
3488 return ( (pCode *)pcc);
3492 /*-----------------------------------------------------------------*/
3493 /* newPcodeCharP - create a new pCode from a char string */
3494 /*-----------------------------------------------------------------*/
3496 pCode *pic16_newpCodeCharP(char *cP)
3501 pcc = Safe_calloc(1,sizeof(pCodeComment));
3503 pcc->pc.type = PC_COMMENT;
3504 pcc->pc.prev = pcc->pc.next = NULL;
3505 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3508 // pcc->pc.analyze = genericAnalyze;
3509 pcc->pc.destruct = genericDestruct;
3510 pcc->pc.print = genericPrint;
3513 pcc->comment = Safe_strdup(cP);
3515 pcc->comment = NULL;
3517 return ( (pCode *)pcc);
3521 /*-----------------------------------------------------------------*/
3522 /* pic16_newpCodeFunction - */
3523 /*-----------------------------------------------------------------*/
3526 pCode *pic16_newpCodeFunction(char *mod,char *f)
3530 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3532 pcf->pc.type = PC_FUNCTION;
3533 pcf->pc.prev = pcf->pc.next = NULL;
3534 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3537 // pcf->pc.analyze = genericAnalyze;
3538 pcf->pc.destruct = genericDestruct;
3539 pcf->pc.print = pCodePrintFunction;
3545 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3546 strcpy(pcf->modname,mod);
3548 pcf->modname = NULL;
3551 pcf->fname = Safe_calloc(1,strlen(f)+1);
3552 strcpy(pcf->fname,f);
3556 pcf->stackusage = 0;
3558 return ( (pCode *)pcf);
3561 /*-----------------------------------------------------------------*/
3562 /* pic16_newpCodeFlow */
3563 /*-----------------------------------------------------------------*/
3564 static void destructpCodeFlow(pCode *pc)
3566 if(!pc || !isPCFL(pc))
3573 pic16_unlinkpCode(pc);
3575 deleteSet(&PCFL(pc)->registers);
3576 deleteSet(&PCFL(pc)->from);
3577 deleteSet(&PCFL(pc)->to);
3579 /* Instead of deleting the memory used by this pCode, mark
3580 * the object as bad so that if there's a pointer to this pCode
3581 * dangling around somewhere then (hopefully) when the type is
3582 * checked we'll catch it.
3586 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3592 pCode *pic16_newpCodeFlow(void )
3596 //_ALLOC(pcflow,sizeof(pCodeFlow));
3597 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3599 pcflow->pc.type = PC_FLOW;
3600 pcflow->pc.prev = pcflow->pc.next = NULL;
3601 pcflow->pc.pb = NULL;
3603 // pcflow->pc.analyze = genericAnalyze;
3604 pcflow->pc.destruct = destructpCodeFlow;
3605 pcflow->pc.print = genericPrint;
3607 pcflow->pc.seq = GpcFlowSeq++;
3609 pcflow->from = pcflow->to = NULL;
3611 pcflow->inCond = PCC_NONE;
3612 pcflow->outCond = PCC_NONE;
3614 pcflow->firstBank = -1;
3615 pcflow->lastBank = -1;
3617 pcflow->FromConflicts = 0;
3618 pcflow->ToConflicts = 0;
3622 pcflow->registers = newSet();
3624 return ( (pCode *)pcflow);
3628 /*-----------------------------------------------------------------*/
3629 /*-----------------------------------------------------------------*/
3630 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3632 pCodeFlowLink *pcflowLink;
3634 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3636 pcflowLink->pcflow = pcflow;
3637 pcflowLink->bank_conflict = 0;
3642 /*-----------------------------------------------------------------*/
3643 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3644 /*-----------------------------------------------------------------*/
3646 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3651 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3653 pccs->pc.type = PC_CSOURCE;
3654 pccs->pc.prev = pccs->pc.next = NULL;
3657 pccs->pc.destruct = genericDestruct;
3658 pccs->pc.print = genericPrint;
3660 pccs->line_number = ln;
3662 pccs->line = Safe_strdup(l);
3667 pccs->file_name = Safe_strdup(f);
3669 pccs->file_name = NULL;
3671 return ( (pCode *)pccs);
3676 /*******************************************************************/
3677 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3678 /* added by VR 6-Jun-2003 */
3679 /*******************************************************************/
3681 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3688 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3689 pcad->pci.pc.type = PC_ASMDIR;
3690 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3691 pcad->pci.pc.pb = NULL;
3693 pcad->pci.pc.destruct = genericDestruct;
3694 pcad->pci.pc.print = genericPrint;
3696 if(asdir && *asdir) {
3698 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3700 pcad->directive = Safe_strdup( asdir );
3703 va_start(ap, argfmt);
3705 memset(buffer, 0, sizeof(buffer));
3706 if(argfmt && *argfmt)
3707 vsprintf(buffer, argfmt, ap);
3711 while(isspace(*lbp))lbp++;
3714 pcad->arg = Safe_strdup( lbp );
3716 return ((pCode *)pcad);
3719 /*-----------------------------------------------------------------*/
3720 /* pCodeLabelDestruct - free memory used by a label. */
3721 /*-----------------------------------------------------------------*/
3722 static void pCodeLabelDestruct(pCode *pc)
3728 // if((pc->type == PC_LABEL) && PCL(pc)->label)
3729 // free(PCL(pc)->label);
3731 /* Instead of deleting the memory used by this pCode, mark
3732 * the object as bad so that if there's a pointer to this pCode
3733 * dangling around somewhere then (hopefully) when the type is
3734 * checked we'll catch it.
3738 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3744 pCode *pic16_newpCodeLabel(char *name, int key)
3750 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3752 pcl->pc.type = PC_LABEL;
3753 pcl->pc.prev = pcl->pc.next = NULL;
3754 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3757 // pcl->pc.analyze = genericAnalyze;
3758 pcl->pc.destruct = pCodeLabelDestruct;
3759 pcl->pc.print = pCodePrintLabel;
3766 sprintf(s,"_%05d_DS_",key);
3771 pcl->label = Safe_strdup(s);
3773 // if(pic16_pcode_verbose)
3774 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3777 return ( (pCode *)pcl);
3781 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3783 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3787 return ( (pCode *)pcl );
3790 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3794 pci = Safe_calloc(1, sizeof(pCodeInfo));
3795 pci->pci.pc.type = PC_INFO;
3796 pci->pci.pc.prev = pci->pci.pc.next = NULL;
3797 pci->pci.pc.pb = NULL;
3798 pci->pci.label = NULL;
3800 pci->pci.pc.destruct = genericDestruct;
3801 pci->pci.pc.print = genericPrint;
3806 return ((pCode *)pci);
3810 /*-----------------------------------------------------------------*/
3811 /* newpBlock - create and return a pointer to a new pBlock */
3812 /*-----------------------------------------------------------------*/
3813 static pBlock *newpBlock(void)
3818 PpB = Safe_calloc(1,sizeof(pBlock) );
3819 PpB->next = PpB->prev = NULL;
3821 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3822 PpB->tregisters = NULL;
3824 PpB->FlowTree = NULL;
3830 /*-----------------------------------------------------------------*/
3831 /* pic16_newpCodeChain - create a new chain of pCodes */
3832 /*-----------------------------------------------------------------*
3834 * This function will create a new pBlock and the pointer to the
3835 * pCode that is passed in will be the first pCode in the block.
3836 *-----------------------------------------------------------------*/
3839 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3842 pBlock *pB = newpBlock();
3844 pB->pcHead = pB->pcTail = pc;
3853 /*-----------------------------------------------------------------*/
3854 /* pic16_newpCodeOpLabel - Create a new label given the key */
3855 /* Note, a negative key means that the label is part of wild card */
3856 /* (and hence a wild card label) used in the pCodePeep */
3857 /* optimizations). */
3858 /*-----------------------------------------------------------------*/
3860 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3863 static int label_key=-1;
3867 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3868 pcop->type = PO_LABEL;
3873 sprintf(s=buffer,"_%05d_DS_",key);
3875 s = name, key = label_key--;
3878 pcop->name = Safe_strdup(s);
3880 ((pCodeOpLabel *)pcop)->key = key;
3882 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3886 /*-----------------------------------------------------------------*/
3887 /*-----------------------------------------------------------------*/
3888 pCodeOp *pic16_newpCodeOpLit(int lit)
3894 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3895 pcop->type = PO_LITERAL;
3899 sprintf(s,"0x%02hhx",(char)(lit));
3901 // sprintf(s, "%i", lit);
3904 pcop->name = Safe_strdup(s);
3906 ((pCodeOpLit *)pcop)->lit = lit;
3911 /*-----------------------------------------------------------------*/
3912 /*-----------------------------------------------------------------*/
3913 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3915 char *s = buffer, tbuf[256], *tb=tbuf;
3919 tb = pic16_get_op(arg2, NULL, 0);
3920 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3921 pcop->type = PO_LITERAL;
3925 sprintf(s,"0x%02x, %s",lit, tb);
3927 pcop->name = Safe_strdup(s);
3930 ((pCodeOpLit2 *)pcop)->lit = lit;
3931 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3936 /*-----------------------------------------------------------------*/
3937 /*-----------------------------------------------------------------*/
3938 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3942 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3943 pcop->type = PO_IMMEDIATE;
3945 regs *r = pic16_dirregWithName(name);
3946 pcop->name = Safe_strdup(name);
3950 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
3951 PCOI(pcop)->rIdx = r->rIdx;
3953 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
3954 PCOI(pcop)->rIdx = -1;
3956 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3961 PCOI(pcop)->index = index;
3962 PCOI(pcop)->offset = offset;
3963 PCOI(pcop)->_const = code_space;
3968 /*-----------------------------------------------------------------*/
3969 /*-----------------------------------------------------------------*/
3970 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3976 if(!pcwb || !subtype) {
3977 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3981 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3982 pcop->type = PO_WILD;
3983 sprintf(s,"%%%d",id);
3984 pcop->name = Safe_strdup(s);
3986 PCOW(pcop)->id = id;
3987 PCOW(pcop)->pcwb = pcwb;
3988 PCOW(pcop)->subtype = subtype;
3989 PCOW(pcop)->matched = NULL;
3991 PCOW(pcop)->pcop2 = NULL;
3996 /*-----------------------------------------------------------------*/
3997 /*-----------------------------------------------------------------*/
3998 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
4004 if(!pcwb || !subtype || !subtype2) {
4005 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4009 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4010 pcop->type = PO_WILD;
4011 sprintf(s,"%%%d",id);
4012 pcop->name = Safe_strdup(s);
4014 PCOW(pcop)->id = id;
4015 PCOW(pcop)->pcwb = pcwb;
4016 PCOW(pcop)->subtype = subtype;
4017 PCOW(pcop)->matched = NULL;
4019 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4021 if(!subtype2->name) {
4022 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4023 PCOW2(pcop)->pcop.type = PO_WILD;
4024 sprintf(s, "%%%d", id2);
4025 PCOW2(pcop)->pcop.name = Safe_strdup(s);
4026 PCOW2(pcop)->id = id2;
4027 PCOW2(pcop)->subtype = subtype2;
4029 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4030 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4032 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4034 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4035 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4044 /*-----------------------------------------------------------------*/
4045 /*-----------------------------------------------------------------*/
4046 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4050 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4051 pcop->type = PO_GPR_BIT;
4053 pcop->name = Safe_strdup(s);
4057 PCORB(pcop)->bit = bit;
4058 PCORB(pcop)->inBitSpace = inBitSpace;
4059 PCORB(pcop)->subtype = subt;
4061 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4062 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4063 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4064 // PCOR(pcop)->rIdx = 0;
4069 /*-----------------------------------------------------------------*
4070 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4072 * If rIdx >=0 then a specific register from the set of registers
4073 * will be selected. If rIdx <0, then a new register will be searched
4075 *-----------------------------------------------------------------*/
4077 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4081 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4086 PCOR(pcop)->rIdx = rIdx;
4087 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4089 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4092 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4094 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4095 __FUNCTION__, __LINE__);
4100 pcop->type = PCOR(pcop)->r->pc_type;
4105 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4110 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4111 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4112 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4113 pcop->type = PCOR(pcop)->r->pc_type;
4114 pcop->name = PCOR(pcop)->r->name;
4116 // if(pic16_pcode_verbose) {
4117 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4118 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4124 /*-----------------------------------------------------------------*/
4125 /*-----------------------------------------------------------------*/
4126 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4130 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4133 pcop->key = Safe_strdup( key );
4135 return (PCOP(pcop));
4138 /*-----------------------------------------------------------------*/
4139 /*-----------------------------------------------------------------*/
4140 pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type)
4142 pCodeOpLocalReg *pcop;
4144 pcop = Safe_calloc(1, sizeof(pCodeOpLocalReg));
4148 return (PCOP(pcop));
4152 /*-----------------------------------------------------------------*/
4153 /*-----------------------------------------------------------------*/
4155 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4162 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4166 pcop = pic16_newpCodeOpLit(-1);
4170 pcop = pic16_newpCodeOpLabel(NULL,-1);
4173 pcop = pic16_newpCodeOpReg(-1);
4176 case PO_GPR_REGISTER:
4178 pcop = pic16_newpCodeOpRegFromStr(name);
4180 pcop = pic16_newpCodeOpReg(-1);
4184 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4187 pcop->name = Safe_strdup(name);
4195 #define DB_ITEMS_PER_LINE 8
4197 typedef struct DBdata
4204 static int DBd_init = -1;
4206 /*-----------------------------------------------------------------*/
4207 /* Initialiase "DB" data buffer */
4208 /*-----------------------------------------------------------------*/
4209 void pic16_initDB(void)
4215 /*-----------------------------------------------------------------*/
4216 /* Flush pending "DB" data to a pBlock */
4218 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4219 /*-----------------------------------------------------------------*/
4220 void pic16_flushDB(char ptype, void *p)
4224 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4227 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4230 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4234 DBd.buffer[0] = '\0';
4239 /*-----------------------------------------------------------------*/
4240 /* Add "DB" directives to a pBlock */
4241 /*-----------------------------------------------------------------*/
4242 void pic16_emitDB(char c, char ptype, void *p)
4247 // we need to initialize
4250 DBd.buffer[0] = '\0';
4253 l = strlen(DBd.buffer);
4254 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4256 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4259 if (DBd.count>= DB_ITEMS_PER_LINE)
4260 pic16_flushDB(ptype, p);
4263 void pic16_emitDS(char *s, char ptype, void *p)
4268 // we need to initialize
4271 DBd.buffer[0] = '\0';
4274 l = strlen(DBd.buffer);
4275 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4277 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4279 DBd.count++; //=strlen(s);
4281 pic16_flushDB(ptype, p);
4285 /*-----------------------------------------------------------------*/
4286 /*-----------------------------------------------------------------*/
4287 void pic16_pCodeConstString(char *name, char *value)
4291 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4296 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4298 pic16_addpBlock(pb);
4300 // sprintf(buffer,"; %s = ", name);
4301 // strcat(buffer, value);
4302 // fputs(buffer, stderr);
4304 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4305 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4308 pic16_emitDB(*value, 'p', (void *)pb);
4310 pic16_flushDB('p', (void *)pb);
4313 /*-----------------------------------------------------------------*/
4314 /*-----------------------------------------------------------------*/
4316 static void pCodeReadCodeTable(void)
4320 fprintf(stderr, " %s\n",__FUNCTION__);
4322 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4324 pic16_addpBlock(pb);
4326 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4327 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4328 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4329 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4331 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4332 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4333 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4334 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4339 /*-----------------------------------------------------------------*/
4340 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4341 /*-----------------------------------------------------------------*/
4342 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4349 /* If this is the first pcode to be added to a block that
4350 * was initialized with a NULL pcode, then go ahead and
4351 * make this pcode the head and tail */
4352 pb->pcHead = pb->pcTail = pc;
4355 pb->pcTail->next = pc;
4357 pc->prev = pb->pcTail;
4364 /*-----------------------------------------------------------------*/
4365 /* pic16_addpBlock - place a pBlock into the pFile */
4366 /*-----------------------------------------------------------------*/
4367 void pic16_addpBlock(pBlock *pb)
4369 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4372 /* First time called, we'll pass through here. */
4373 //_ALLOC(the_pFile,sizeof(pFile));
4374 the_pFile = Safe_calloc(1,sizeof(pFile));
4375 the_pFile->pbHead = the_pFile->pbTail = pb;
4376 the_pFile->functions = NULL;
4380 the_pFile->pbTail->next = pb;
4381 pb->prev = the_pFile->pbTail;
4383 the_pFile->pbTail = pb;
4386 /*-----------------------------------------------------------------*/
4387 /* removepBlock - remove a pBlock from the pFile */
4388 /*-----------------------------------------------------------------*/
4389 static void removepBlock(pBlock *pb)
4397 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4399 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4402 if(pbs == the_pFile->pbHead)
4403 the_pFile->pbHead = pbs->next;
4405 if (pbs == the_pFile->pbTail)
4406 the_pFile->pbTail = pbs->prev;
4409 pbs->next->prev = pbs->prev;
4412 pbs->prev->next = pbs->next;
4419 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4423 /*-----------------------------------------------------------------*/
4424 /* printpCode - write the contents of a pCode to a file */
4425 /*-----------------------------------------------------------------*/
4426 static void printpCode(FILE *of, pCode *pc)
4437 fprintf(of,"warning - unable to print pCode\n");
4440 /*-----------------------------------------------------------------*/
4441 /* pic16_printpBlock - write the contents of a pBlock to a file */
4442 /*-----------------------------------------------------------------*/
4443 void pic16_printpBlock(FILE *of, pBlock *pb)
4451 for(pc = pb->pcHead; pc; pc = pc->next) {
4452 if(isPCF(pc) && PCF(pc)->fname) {
4453 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4454 if(pb->dbName == 'A') {
4456 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4457 // fprintf(stderr, "%s:%d testing %s <-> %s\n", __FILE__, __LINE__, PCF(pc)->fname, ab->name);
4458 if(!strcmp(ab->name, PCF(pc)->fname)) {
4459 // fprintf(stderr, "%s:%d address = %x\n", __FILE__, __LINE__, ab->address);
4460 fprintf(of, "\t0X%06X", ab->address);
4471 /*-----------------------------------------------------------------*/
4473 /* pCode processing */
4477 /*-----------------------------------------------------------------*/
4479 void pic16_unlinkpCode(pCode *pc)
4485 fprintf(stderr,"Unlinking: ");
4486 printpCode(stderr, pc);
4489 pc->prev->next = pc->next;
4491 pc->next->prev = pc->prev;
4493 pc->prev = pc->next = NULL;
4497 /*-----------------------------------------------------------------*/
4498 /*-----------------------------------------------------------------*/
4500 static void genericDestruct(pCode *pc)
4503 pic16_unlinkpCode(pc);
4506 /* For instructions, tell the register (if there's one used)
4507 * that it's no longer needed */
4508 regs *reg = pic16_getRegFromInstruction(pc);
4510 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4512 if(PCI(pc)->is2MemOp) {
4513 reg = pic16_getRegFromInstruction2(pc);
4515 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4519 /* Instead of deleting the memory used by this pCode, mark
4520 * the object as bad so that if there's a pointer to this pCode
4521 * dangling around somewhere then (hopefully) when the type is
4522 * checked we'll catch it.
4526 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4532 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4533 /*-----------------------------------------------------------------*/
4534 /*-----------------------------------------------------------------*/
4535 /* modifiers for constant immediate */
4536 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4538 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4543 int use_buffer = 1; // copy the string to the passed buffer pointer
4548 use_buffer = 0; // Don't bother copying the string to the buffer.
4552 switch(pcop->type) {
4560 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4563 return PCOR(pcop)->r->name;
4566 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4568 SAFE_snprintf(&buffer,&size,"%s",r->name);
4575 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4576 if(PCOI(pcop)->index) {
4577 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4578 immdmod[ PCOI(pcop)->offset ],
4582 SAFE_snprintf(&s,&size,"%s(%s)",
4583 immdmod[ PCOI(pcop)->offset ],
4587 if(PCOI(pcop)->index) {
4588 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4593 SAFE_snprintf(&s,&size, "%s(%s)",
4600 case PO_GPR_REGISTER:
4603 // size = sizeof(buffer);
4604 if( PCOR(pcop)->instance) {
4605 SAFE_snprintf(&s,&size,"(%s + %d)",
4607 PCOR(pcop)->instance );
4609 SAFE_snprintf(&s,&size,"%s",pcop->name);
4616 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4625 return "NO operand1";
4628 /*-----------------------------------------------------------------*/
4629 /* pic16_get_op2 - variant to support two memory operand commands */
4630 /*-----------------------------------------------------------------*/
4631 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4636 int use_buffer = 1; // copy the string to the passed buffer pointer
4641 use_buffer = 0; // Don't bother copying the string to the buffer.
4645 fprintf(stderr, "%s:%d second operand %s is %d\tPO_DIR(%d) PO_GPR_TEMP(%d) PO_IMMEDIATE(%d) PO_INDF0(%d) PO_FSR0(%d)\n",
4646 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4647 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4651 switch(PCOR2(pcop)->pcop2->type) {
4659 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4662 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4665 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4668 SAFE_snprintf(&buffer,&size,"%s",r->name);
4679 if(PCOI(pcop)->_const) {
4680 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4681 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4684 8 * PCOI(pcop)->offset );
4686 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4688 if( PCOI(pcop)->index) {
4689 SAFE_snprintf(&s,&size,"(%s + %d)",
4691 PCOI(pcop)->index );
4693 if(PCOI(pcop)->offset)
4694 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4696 SAFE_snprintf(&s,&size,"%s",pcop->name);
4703 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4704 SAFE_snprintf(&s,&size,"(%s + %d)",
4705 PCOR(PCOR2(pcop)->pcop2)->r->name,
4706 PCOR(PCOR2(pcop)->pcop2)->instance );
4708 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4713 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4715 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4718 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4723 return "NO operand2";
4726 /*-----------------------------------------------------------------*/
4727 /*-----------------------------------------------------------------*/
4728 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4732 return pic16_get_op(pcc->pcop,NULL,0);
4734 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4735 * return ("ERROR Null: "__FUNCTION__);
4737 return ("ERROR Null: pic16_get_op_from_instruction");
4741 /*-----------------------------------------------------------------*/
4742 /*-----------------------------------------------------------------*/
4743 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4746 fprintf(of,"pcodeopprint- not implemented\n");
4749 /*-----------------------------------------------------------------*/
4750 /* pic16_pCode2str - convert a pCode instruction to string */
4751 /*-----------------------------------------------------------------*/
4752 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4758 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4759 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4760 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4768 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4770 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4772 if(PCI(pc)->is2MemOp) {
4773 SAFE_snprintf(&s,&size, "%s, %s",
4774 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4775 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4779 if(PCI(pc)->is2LitOp) {
4780 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4784 if(PCI(pc)->isBitInst) {
4785 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4786 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4787 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4788 PCI(pc)->pcop->name ,
4789 PCI(pc)->pcop->name );
4791 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4792 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4793 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4794 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4796 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4797 //PCI(pc)->pcop->t.bit );
4800 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4801 if( PCI(pc)->num_ops == 3)
4802 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4804 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4807 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4809 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4810 if(PCI(pc)->num_ops == 3)
4811 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4813 r = pic16_getRegFromInstruction(pc);
4814 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4815 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4817 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4826 /* assuming that comment ends with a \n */
4827 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4831 SAFE_snprintf(&s,&size,"; info ==>");
4832 switch(((pCodeInfo *)pc)->type) {
4833 case INF_OPTIMIZATION:
4834 SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
4837 SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
4842 /* assuming that inline code ends with a \n */
4843 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4847 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4850 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4853 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4856 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4859 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4860 SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4861 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4864 if(PCAD(pc)->directive) {
4865 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4868 /* special case to handle inline labels without a tab */
4869 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4874 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4882 /*-----------------------------------------------------------------*/
4883 /* genericPrint - the contents of a pCode to a file */
4884 /*-----------------------------------------------------------------*/
4885 static void genericPrint(FILE *of, pCode *pc)
4893 // fputs(((pCodeComment *)pc)->comment, of);
4894 fprintf(of,"; %s\n", ((pCodeComment *)pc)->comment);
4899 pBranch *pbl = PCI(pc)->label;
4900 while(pbl && pbl->pc) {
4901 if(pbl->pc->type == PC_LABEL)
4902 pCodePrintLabel(of, pbl->pc);
4907 fprintf(of, "; info ==>");
4908 switch(((pCodeInfo *)pc)->type) {
4909 case INF_OPTIMIZATION:
4910 fprintf(of, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
4913 fprintf(of, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
4918 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4922 // If the opcode has a label, print that first
4924 pBranch *pbl = PCI(pc)->label;
4925 while(pbl && pbl->pc) {
4926 if(pbl->pc->type == PC_LABEL)
4927 pCodePrintLabel(of, pbl->pc);
4933 genericPrint(of,PCODE(PCI(pc)->cline));
4938 pic16_pCode2str(str, 256, pc);
4940 fprintf(of,"%s",str);
4942 if(pic16_debug_verbose) {
4943 fprintf(of, "\t;key=%03x",pc->seq);
4945 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4952 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4953 if(PCW(pc)->pci.label)
4954 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4956 if(PCW(pc)->operand) {
4957 fprintf(of,";\toperand ");
4958 pCodeOpPrint(of,PCW(pc)->operand );
4963 if(pic16_debug_verbose) {
4964 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4965 if(PCFL(pc)->ancestor)
4966 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4973 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4974 fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4975 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4981 pBranch *pbl = PCAD(pc)->pci.label;
4982 while(pbl && pbl->pc) {
4983 if(pbl->pc->type == PC_LABEL)
4984 pCodePrintLabel(of, pbl->pc);
4988 if(PCAD(pc)->directive) {
4989 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4992 /* special case to handle inline labels without tab */
4993 fprintf(of, "%s\n", PCAD(pc)->arg);
4999 fprintf(of,"unknown pCode type %d\n",pc->type);
5004 /*-----------------------------------------------------------------*/
5005 /* pCodePrintFunction - prints function begin/end */
5006 /*-----------------------------------------------------------------*/
5008 static void pCodePrintFunction(FILE *of, pCode *pc)
5015 if( ((pCodeFunction *)pc)->modname)
5016 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
5019 if(!PCF(pc)->absblock) {
5020 if(PCF(pc)->fname) {
5021 pBranch *exits = PCF(pc)->to;
5024 fprintf(of,"%s:", PCF(pc)->fname);
5026 if(pic16_pcode_verbose)
5027 fprintf(of, "\t;Function start");
5033 exits = exits->next;
5037 if(pic16_pcode_verbose)
5038 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
5041 if((PCF(pc)->from &&
5042 PCF(pc)->from->pc->type == PC_FUNCTION &&
5043 PCF(PCF(pc)->from->pc)->fname) ) {
5045 if(pic16_pcode_verbose)
5046 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
5048 if(pic16_pcode_verbose)
5049 fprintf(of,"; exit point [can't find entry point]\n");
5055 /*-----------------------------------------------------------------*/
5056 /* pCodePrintLabel - prints label */
5057 /*-----------------------------------------------------------------*/
5059 static void pCodePrintLabel(FILE *of, pCode *pc)
5066 fprintf(of,"%s:\n",PCL(pc)->label);
5067 else if (PCL(pc)->key >=0)
5068 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5070 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5073 /*-----------------------------------------------------------------*/
5074 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
5075 /* remove it if it is found. */
5076 /*-----------------------------------------------------------------*/
5077 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5084 if(pcl->type == PC_OPCODE)
5085 b = PCI(pcl)->label;
5087 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5092 //fprintf (stderr, "%s \n",__FUNCTION__);
5093 //pcl->print(stderr,pcl);
5094 //pc->print(stderr,pc);
5097 //fprintf (stderr, "found label\n");
5098 //pc->print(stderr, pc);
5102 bprev->next = b->next; /* Not first pCode in chain */
5106 PCI(pcl)->label = b->next; /* First pCode in chain */
5109 return; /* A label can't occur more than once */
5117 /*-----------------------------------------------------------------*/
5118 /*-----------------------------------------------------------------*/
5119 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5138 /*-----------------------------------------------------------------*/
5139 /* pBranchLink - given two pcodes, this function will link them */
5140 /* together through their pBranches */
5141 /*-----------------------------------------------------------------*/
5142 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5146 // Declare a new branch object for the 'from' pCode.
5148 //_ALLOC(b,sizeof(pBranch));
5149 b = Safe_calloc(1,sizeof(pBranch));
5150 b->pc = PCODE(t); // The link to the 'to' pCode.
5153 f->to = pic16_pBranchAppend(f->to,b);
5155 // Now do the same for the 'to' pCode.
5157 //_ALLOC(b,sizeof(pBranch));
5158 b = Safe_calloc(1,sizeof(pBranch));
5162 t->from = pic16_pBranchAppend(t->from,b);
5167 /*-----------------------------------------------------------------*/
5168 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5170 /*-----------------------------------------------------------------*/
5171 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5184 /*-----------------------------------------------------------------*/
5185 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5186 /*-----------------------------------------------------------------*/
5187 void pic16_pCodeUnlink(pCode *pc)
5192 if(!pc->prev || !pc->next) {
5193 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5197 /* first remove the pCode from the chain */
5198 pc->prev->next = pc->next;
5199 pc->next->prev = pc->prev;
5201 /* Now for the hard part... */
5203 /* Remove the branches */
5205 pb1 = PCI(pc)->from;
5207 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5208 * one we're unlinking */
5210 /* search for the link back to this pCode (the one we're
5212 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5213 pb2->pc = PCI(pc)->to->pc; // make the replacement
5215 /* if the pCode we're unlinking contains multiple 'to'
5216 * branches (e.g. this a skip instruction) then we need
5217 * to copy these extra branches to the chain. */
5218 if(PCI(pc)->to->next)
5219 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5228 /*-----------------------------------------------------------------*/
5229 /*-----------------------------------------------------------------*/
5231 static void genericAnalyze(pCode *pc)
5241 // Go through the pCodes that are in pCode chain and link
5242 // them together through the pBranches. Note, the pCodes
5243 // are linked together as a contiguous stream like the
5244 // assembly source code lines. The linking here mimics this
5245 // except that comments are not linked in.
5247 pCode *npc = pc->next;
5249 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5250 pBranchLink(pc,npc);
5255 /* reached the end of the pcode chain without finding
5256 * an instruction we could link to. */
5260 fprintf(stderr,"analyze PC_FLOW\n");
5264 fprintf(stderr,,";A bad pCode is being used\n");
5270 /*-----------------------------------------------------------------*/
5271 /*-----------------------------------------------------------------*/
5272 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5276 if(pc->type == PC_LABEL) {
5277 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5280 if((pc->type == PC_OPCODE)
5281 || (pc->type == PC_ASMDIR)
5283 pbr = PCI(pc)->label;
5285 if(pbr->pc->type == PC_LABEL) {
5286 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5296 /*-----------------------------------------------------------------*/
5297 /*-----------------------------------------------------------------*/
5298 static int checkLabel(pCode *pc)
5302 if(pc && isPCI(pc)) {
5303 pbr = PCI(pc)->label;
5305 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5315 /*-----------------------------------------------------------------*/
5316 /* findLabelinpBlock - Search the pCode for a particular label */
5317 /*-----------------------------------------------------------------*/
5318 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5325 for(pc = pb->pcHead; pc; pc = pc->next)
5326 if(compareLabel(pc,pcop_label))
5332 /*-----------------------------------------------------------------*/
5333 /* findLabel - Search the pCode for a particular label */
5334 /*-----------------------------------------------------------------*/
5335 static pCode * findLabel(pCodeOpLabel *pcop_label)
5343 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5344 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5348 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5352 /*-----------------------------------------------------------------*/
5353 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5354 /* in the linked list */
5355 /*-----------------------------------------------------------------*/
5356 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5369 /*-----------------------------------------------------------------*/
5370 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5371 /* in the linked list */
5372 /*-----------------------------------------------------------------*/
5373 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5387 //#define PCODE_DEBUG
5388 /*-----------------------------------------------------------------*/
5389 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5390 /* in the linked list */
5391 /*-----------------------------------------------------------------*/
5392 pCode * pic16_findNextInstruction(pCode *pci)
5397 if((pc->type == PC_OPCODE)
5398 || (pc->type == PC_WILD)
5399 || (pc->type == PC_ASMDIR)
5404 fprintf(stderr,"pic16_findNextInstruction: ");
5405 printpCode(stderr, pc);
5410 //fprintf(stderr,"Couldn't find instruction\n");
5414 /*-----------------------------------------------------------------*/
5415 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5416 /* in the linked list */
5417 /*-----------------------------------------------------------------*/
5418 pCode * pic16_findPrevInstruction(pCode *pci)
5424 if((pc->type == PC_OPCODE)
5425 || (pc->type == PC_WILD)
5426 || (pc->type == PC_ASMDIR)
5432 fprintf(stderr,"pic16_findPrevInstruction: ");
5433 printpCode(stderr, pc);
5438 //fprintf(stderr,"Couldn't find instruction\n");
5445 /*-----------------------------------------------------------------*/
5446 /* findFunctionEnd - given a pCode find the end of the function */
5447 /* that contains it */
5448 /*-----------------------------------------------------------------*/
5449 static pCode * findFunctionEnd(pCode *pc)
5453 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5459 fprintf(stderr,"Couldn't find function end\n");
5464 /*-----------------------------------------------------------------*/
5465 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5466 /* instruction with which it is associated. */
5467 /*-----------------------------------------------------------------*/
5468 static void AnalyzeLabel(pCode *pc)
5471 pic16_pCodeUnlink(pc);
5477 static void AnalyzeGOTO(pCode *pc)
5480 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5484 static void AnalyzeSKIP(pCode *pc)
5487 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5488 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5492 static void AnalyzeRETURN(pCode *pc)
5495 // branch_link(pc,findFunctionEnd(pc->next));
5501 /*-----------------------------------------------------------------*/
5502 /*-----------------------------------------------------------------*/
5503 regs * pic16_getRegFromInstruction(pCode *pc)
5509 PCI(pc)->num_ops == 0 ||
5510 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5514 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5515 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5518 switch(PCI(pc)->pcop->type) {
5524 return PCOR(PCI(pc)->pcop)->r;
5528 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5529 return PCOR(PCI(pc)->pcop)->r;
5532 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5534 if(PCOI(PCI(pc)->pcop)->r)
5535 return (PCOI(PCI(pc)->pcop)->r);
5540 return PCOR(PCI(pc)->pcop)->r;
5542 case PO_GPR_REGISTER:
5544 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5545 return PCOR(PCI(pc)->pcop)->r;
5548 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5552 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5553 // genericPrint(stderr, pc);
5561 /*-------------------------------------------------------------------------------*/
5562 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5563 /*-------------------------------------------------------------------------------*/
5564 regs * pic16_getRegFromInstruction2(pCode *pc)
5570 PCI(pc)->num_ops == 0 ||
5571 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5576 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5577 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5581 * operands supported in MOVFF:
5588 switch(PCI(pc)->pcop->type) {
5594 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5596 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5600 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5601 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5605 // if(PCOI(PCI(pc)->pcop)->r)
5606 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5608 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5609 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5612 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5613 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5620 // return PCOR2(PCI(pc)->pcop)->r;
5622 case PO_GPR_REGISTER:
5624 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5625 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5629 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5632 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5633 //genericPrint(stderr, pc);
5641 /*-----------------------------------------------------------------*/
5642 /*-----------------------------------------------------------------*/
5644 static void AnalyzepBlock(pBlock *pb)
5651 /* Find all of the registers used in this pBlock
5652 * by looking at each instruction and examining it's
5655 for(pc = pb->pcHead; pc; pc = pc->next) {
5657 /* Is this an instruction with operands? */
5658 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5660 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5662 /* Loop through all of the registers declared so far in
5663 this block and see if we find this one there */
5665 regs *r = setFirstItem(pb->tregisters);
5668 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5669 PCOR(PCI(pc)->pcop)->r = r;
5672 r = setNextItem(pb->tregisters);
5676 /* register wasn't found */
5677 //r = Safe_calloc(1, sizeof(regs));
5678 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5679 //addSet(&pb->tregisters, r);
5680 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5681 //PCOR(PCI(pc)->pcop)->r = r;
5682 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5684 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5687 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5688 if(PCOR(PCI(pc)->pcop)->r) {
5689 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5690 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5692 if(PCI(pc)->pcop->name)
5693 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5695 fprintf(stderr,"ERROR: NULL register\n");
5704 /*-----------------------------------------------------------------*/
5706 /*-----------------------------------------------------------------*/
5707 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5709 static void InsertpFlow(pCode *pc, pCode **pflow)
5712 PCFL(*pflow)->end = pc;
5714 if(!pc || !pc->next)
5717 *pflow = pic16_newpCodeFlow();
5718 pic16_pCodeInsertAfter(pc, *pflow);
5721 /*-----------------------------------------------------------------*/
5722 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5723 /* the flow blocks. */
5725 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5726 * point the instruction flow changes.
5728 /*-----------------------------------------------------------------*/
5729 void pic16_BuildFlow(pBlock *pb)
5732 pCode *last_pci=NULL;
5739 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5740 /* Insert a pCodeFlow object at the beginning of a pBlock */
5742 InsertpFlow(pb->pcHead, &pflow);
5744 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5745 //pflow->next = pb->pcHead; /* Make the current head the next object */
5746 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5747 //pb->pcHead = pflow; /* Make the Flow object the head */
5750 for( pc = pic16_findNextInstruction(pb->pcHead);
5752 pc=pic16_findNextInstruction(pc)) {
5755 PCI(pc)->pcflow = PCFL(pflow);
5757 //fprintf(stderr," build: ");
5758 //pflow->print(stderr,pflow);
5760 if( PCI(pc)->isSkip) {
5762 /* The two instructions immediately following this one
5763 * mark the beginning of a new flow segment */
5765 while(pc && PCI(pc)->isSkip) {
5767 PCI(pc)->pcflow = PCFL(pflow);
5771 InsertpFlow(pc, &pflow);
5772 pc=pic16_findNextInstruction(pc->next);
5780 PCI(pc)->pcflow = PCFL(pflow);
5782 InsertpFlow(pc, &pflow);
5784 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5786 InsertpFlow(pc, &pflow);
5789 } else if (checkLabel(pc)) {
5791 /* This instruction marks the beginning of a
5792 * new flow segment */
5797 /* If the previous pCode is not a flow object, then
5798 * insert a new flow object. (This check prevents
5799 * two consecutive flow objects from being insert in
5800 * the case where a skip instruction preceeds an
5801 * instruction containing a label.) */
5803 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5804 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5806 PCI(pc)->pcflow = PCFL(pflow);
5813 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5815 PCFL(pflow)->end = pb->pcTail;
5818 /*-------------------------------------------------------------------*/
5819 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5820 /* the flow blocks. */
5822 * unBuildFlow removes pCodeFlow objects from a pCode chain
5824 /*-----------------------------------------------------------------*/
5825 static void unBuildFlow(pBlock *pb)
5840 if(PCI(pc)->pcflow) {
5841 //free(PCI(pc)->pcflow);
5842 PCI(pc)->pcflow = NULL;
5845 } else if(isPCFL(pc) )
5854 /*-----------------------------------------------------------------*/
5855 /*-----------------------------------------------------------------*/
5856 static void dumpCond(int cond)
5859 static char *pcc_str[] = {
5873 int ncond = sizeof(pcc_str) / sizeof(char *);
5876 fprintf(stderr, "0x%04X\n",cond);
5878 for(i=0,j=1; i<ncond; i++, j<<=1)
5880 fprintf(stderr, " %s\n",pcc_str[i]);
5886 /*-----------------------------------------------------------------*/
5887 /*-----------------------------------------------------------------*/
5888 static void FlowStats(pCodeFlow *pcflow)
5896 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5898 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5901 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5906 fprintf(stderr, " FlowStats inCond: ");
5907 dumpCond(pcflow->inCond);
5908 fprintf(stderr, " FlowStats outCond: ");
5909 dumpCond(pcflow->outCond);
5913 /*-----------------------------------------------------------------*
5914 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5915 * if it affects the banking bits.
5917 * return: -1 == Banking bits are unaffected by this pCode.
5919 * return: > 0 == Banking bits are affected.
5921 * If the banking bits are affected, then the returned value describes
5922 * which bits are affected and how they're affected. The lower half
5923 * of the integer maps to the bits that are affected, the upper half
5924 * to whether they're set or cleared.
5926 *-----------------------------------------------------------------*/
5928 static int isBankInstruction(pCode *pc)
5936 if( PCI(pc)->op == POC_MOVLB ||
5937 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5938 bank = PCOL(pc)->lit;
5945 /*-----------------------------------------------------------------*/
5946 /*-----------------------------------------------------------------*/
5947 static void FillFlow(pCodeFlow *pcflow)
5956 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5958 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5961 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5968 isBankInstruction(pc);
5970 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5974 fprintf(stderr, " FillFlow - Bad end of flow\n");
5976 fprintf(stderr, " FillFlow - Ending flow with\n ");
5977 pc->print(stderr,pc);
5980 fprintf(stderr, " FillFlow inCond: ");
5981 dumpCond(pcflow->inCond);
5982 fprintf(stderr, " FillFlow outCond: ");
5983 dumpCond(pcflow->outCond);
5987 /*-----------------------------------------------------------------*/
5988 /*-----------------------------------------------------------------*/
5989 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5991 pCodeFlowLink *fromLink, *toLink;
5993 if(!from || !to || !to->pcflow || !from->pcflow)
5996 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5997 toLink = pic16_newpCodeFlowLink(to->pcflow);
5999 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
6000 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
6004 /*-----------------------------------------------------------------*
6005 * void LinkFlow(pBlock *pb)
6007 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
6008 * non-branching segments. In LinkFlow, we determine the execution
6009 * order of these segments. For example, if one of the segments ends
6010 * with a skip, then we know that there are two possible flow segments
6011 * to which control may be passed.
6012 *-----------------------------------------------------------------*/
6013 static void LinkFlow(pBlock *pb)
6019 //fprintf(stderr,"linkflow \n");
6021 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6023 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6026 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
6028 //fprintf(stderr," link: ");
6029 //pcflow->print(stderr,pcflow);
6031 //FillFlow(PCFL(pcflow));
6033 pc = PCFL(pcflow)->end;
6035 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
6036 if(isPCI_SKIP(pc)) {
6037 //fprintf(stderr, "ends with skip\n");
6038 //pc->print(stderr,pc);
6039 pct=pic16_findNextInstruction(pc->next);
6040 LinkFlow_pCode(PCI(pc),PCI(pct));
6041 pct=pic16_findNextInstruction(pct->next);
6042 LinkFlow_pCode(PCI(pc),PCI(pct));
6046 if(isPCI_BRANCH(pc)) {
6047 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6049 //fprintf(stderr, "ends with branch\n ");
6050 //pc->print(stderr,pc);
6052 if(!(pcol && isPCOLAB(pcol))) {
6053 if((PCI(pc)->op != POC_RETLW)
6054 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
6056 /* continue if label is '$' which assembler knows how to parse */
6057 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6059 if(pic16_pcode_verbose) {
6060 pc->print(stderr,pc);
6061 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6067 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6068 LinkFlow_pCode(PCI(pc),PCI(pct));
6070 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6071 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6073 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6079 //fprintf(stderr, "ends with non-branching instruction:\n");
6080 //pc->print(stderr,pc);
6082 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6088 //fprintf(stderr, "ends with unknown\n");
6089 //pc->print(stderr,pc);
6093 //fprintf(stderr, "ends with nothing: ERROR\n");
6097 /*-----------------------------------------------------------------*/
6098 /*-----------------------------------------------------------------*/
6100 /*-----------------------------------------------------------------*/
6101 /*-----------------------------------------------------------------*/
6102 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6108 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6111 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6121 /*-----------------------------------------------------------------*/
6122 /* insertBankSwitch - inserts a bank switch statement in the */
6123 /* assembly listing */
6125 /* position == 0: insert before */
6126 /* position == 1: insert after pc */
6127 /* position == 2: like 0 but previous was a skip instruction */
6128 /*-----------------------------------------------------------------*/
6129 pCodeOp *pic16_popGetLabel(unsigned int key);
6130 extern int pic16_labelOffset;
6132 static void insertBankSwitch(unsigned char position, pCode *pc)
6139 /* emit BANKSEL [symbol] */
6142 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6144 // position = 0; // position is always before (sanity check!)
6147 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6148 pc->print(stderr, pc);
6153 /* insert the bank switch after this pc instruction */
6154 pCode *pcnext = pic16_findNextInstruction(pc);
6156 pic16_pCodeInsertAfter(pc, new_pc);
6157 if(pcnext)pc = pcnext;
6161 /* insert the bank switch BEFORE this pc instruction */
6162 pic16_pCodeInsertAfter(pc->prev, new_pc);
6167 pCode *pcnext, *pcprev, *npci, *ppc;
6169 int ofs1=0, ofs2=0, len=0;
6171 /* just like 0, but previous was a skip instruction,
6172 * so some care should be taken */
6174 pic16_labelOffset += 10000;
6175 tlbl = newiTempLabel(NULL);
6177 /* invert skip instruction */
6178 pcprev = pic16_findPrevInstruction(pc->prev);
6179 ipci = PCI(pcprev)->inverted_op;
6180 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6182 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6184 /* copy info from old pCode */
6185 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6186 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6187 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6188 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6189 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6190 PCI(npci)->op = PCI(pcprev)->inverted_op;
6192 /* unlink old pCode */
6194 ppc->next = pcprev->next;
6195 pcprev->next->prev = ppc;
6196 pic16_pCodeInsertAfter(ppc, npci);
6198 /* extra instructions to handle invertion */
6199 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6200 pic16_pCodeInsertAfter(npci, pcnext);
6201 pic16_pCodeInsertAfter(pc->prev, new_pc);
6203 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6204 pic16_pCodeInsertAfter(pc, pcnext);
6209 /* Move the label, if there is one */
6210 if(PCI(pc)->label) {
6211 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6212 // __FILE__, __LINE__, pc, new_pc);
6213 PCAD(new_pc)->pci.label = PCI(pc)->label;
6214 PCI(pc)->label = NULL;
6219 /*-----------------------------------------------------------------*/
6220 /*int compareBankFlow - compare the banking requirements between */
6222 /*-----------------------------------------------------------------*/
6223 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6226 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6229 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6232 if(pcflow->firstBank == -1)
6236 if(pcflowLink->pcflow->firstBank == -1) {
6237 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6238 pcflowLink->pcflow->to :
6239 pcflowLink->pcflow->from);
6240 return compareBankFlow(pcflow, pctl, toORfrom);
6244 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6247 pcflowLink->bank_conflict++;
6248 pcflowLink->pcflow->FromConflicts++;
6249 pcflow->ToConflicts++;
6252 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6255 pcflowLink->bank_conflict++;
6256 pcflowLink->pcflow->ToConflicts++;
6257 pcflow->FromConflicts++;
6261 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6262 pcflowLink->pcflow->pc.seq,
6263 pcflowLink->pcflow->FromConflicts,
6264 pcflowLink->pcflow->ToConflicts);
6271 /*-----------------------------------------------------------------*/
6272 /*-----------------------------------------------------------------*/
6273 static void DumpFlow(pBlock *pb)
6277 pCodeFlowLink *pcfl;
6280 fprintf(stderr,"Dump flow \n");
6281 pb->pcHead->print(stderr, pb->pcHead);
6283 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6284 pcflow->print(stderr,pcflow);
6286 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6288 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6290 if(!isPCFL(pcflow)) {
6291 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6294 fprintf(stderr,"dumping: ");
6295 pcflow->print(stderr,pcflow);
6296 FlowStats(PCFL(pcflow));
6298 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6300 pc = PCODE(pcfl->pcflow);
6302 fprintf(stderr, " from seq %d:\n",pc->seq);
6304 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6305 pc->print(stderr,pc);
6310 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6312 pc = PCODE(pcfl->pcflow);
6314 fprintf(stderr, " to seq %d:\n",pc->seq);
6316 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6317 pc->print(stderr,pc);
6326 /*-----------------------------------------------------------------*/
6327 /*-----------------------------------------------------------------*/
6328 static int OptimizepBlock(pBlock *pb)
6333 if(!pb || !peepOptimizing)
6336 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6338 for(pc = pb->pcHead; pc; pc = pc->next)
6339 matches += pic16_pCodePeepMatchRule(pc);
6342 pc = pic16_findNextInstruction(pb->pcHead);
6350 if(pic16_pCodePeepMatchRule(pc)) {
6355 pc = pic16_findNextInstruction(pcprev->next);
6357 pc = pic16_findNextInstruction(pb->pcHead);
6359 pc = pic16_findNextInstruction(pc->next);
6363 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6368 /*-----------------------------------------------------------------*/
6369 /*-----------------------------------------------------------------*/
6370 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6374 for(pc = pcs; pc; pc = pc->next) {
6376 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6378 (PCI(pc)->pcop->type == PO_LABEL) &&
6379 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6387 /*-----------------------------------------------------------------*/
6388 /*-----------------------------------------------------------------*/
6389 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6396 (PCI(pc)->pcop->type == PO_LABEL)) {
6398 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6400 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6401 // if(pcol->pcop.name)
6402 // free(pcol->pcop.name);
6404 /* If the key is negative, then we (probably) have a label to
6405 * a function and the name is already defined */
6408 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6412 //sprintf(buffer,"_%05d_DS_",pcl->key);
6414 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6416 pcol->pcop.name = Safe_strdup(s);
6417 pcol->key = pcl->key;
6418 //pc->print(stderr,pc);
6425 /*-----------------------------------------------------------------*/
6426 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6427 /* pCode chain if they're not used. */
6428 /*-----------------------------------------------------------------*/
6429 static void pBlockRemoveUnusedLabels(pBlock *pb)
6431 pCode *pc; pCodeLabel *pcl;
6436 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6438 pBranch *pbr = PCI(pc)->label;
6439 if(pbr && pbr->next) {
6440 pCode *pcd = pb->pcHead;
6442 // fprintf(stderr, "multiple labels\n");
6443 // pc->print(stderr,pc);
6448 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6449 //fprintf(stderr,"Used by:\n");
6450 //pcd->print(stderr,pcd);
6452 exchangeLabels(PCL(pbr->pc),pcd);
6461 for(pc = pb->pcHead; pc; pc = pc->next) {
6463 if(isPCL(pc)) // pc->type == PC_LABEL)
6465 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6466 pcl = PCL(PCI(pc)->label->pc);
6469 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6471 /* This pCode is a label, so search the pBlock to see if anyone
6474 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6476 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6477 /* Couldn't find an instruction that refers to this label
6478 * So, unlink the pCode label from it's pCode chain
6479 * and destroy the label */
6480 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6482 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6483 if(pc->type == PC_LABEL) {
6484 pic16_unlinkpCode(pc);
6485 pCodeLabelDestruct(pc);
6487 unlinkpCodeFromBranch(pc, PCODE(pcl));
6488 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6499 /*-----------------------------------------------------------------*/
6500 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6501 /* chain and put them into pBranches that are */
6502 /* associated with the appropriate pCode */
6504 /*-----------------------------------------------------------------*/
6505 void pic16_pBlockMergeLabels(pBlock *pb)
6508 pCode *pc, *pcnext=NULL;
6513 /* First, Try to remove any unused labels */
6514 //pBlockRemoveUnusedLabels(pb);
6516 /* Now loop through the pBlock and merge the labels with the opcodes */
6519 // for(pc = pb->pcHead; pc; pc = pc->next) {
6522 pCode *pcn = pc->next;
6524 if(pc->type == PC_LABEL) {
6526 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6527 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6529 if((pcnext = pic16_findNextInstruction(pc) )) {
6531 // pcnext->print(stderr, pcnext);
6533 // Unlink the pCode label from it's pCode chain
6534 pic16_unlinkpCode(pc);
6536 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6537 // And link it into the instruction's pBranch labels. (Note, since
6538 // it's possible to have multiple labels associated with one instruction
6539 // we must provide a means to accomodate the additional labels. Thus
6540 // the labels are placed into the singly-linked list "label" as
6541 // opposed to being a single member of the pCodeInstruction.)
6543 //_ALLOC(pbr,sizeof(pBranch));
6545 pbr = Safe_calloc(1,sizeof(pBranch));
6549 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6552 if(pic16_pcode_verbose)
6553 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6555 } else if(pc->type == PC_CSOURCE) {
6557 /* merge the source line symbolic info into the next instruction */
6558 if((pcnext = pic16_findNextInstruction(pc) )) {
6560 // Unlink the pCode label from it's pCode chain
6561 pic16_unlinkpCode(pc);
6562 PCI(pcnext)->cline = PCCS(pc);
6563 //fprintf(stderr, "merging CSRC\n");
6564 //genericPrint(stderr,pcnext);
6570 pBlockRemoveUnusedLabels(pb);
6574 /*-----------------------------------------------------------------*/
6575 /*-----------------------------------------------------------------*/
6576 static int OptimizepCode(char dbName)
6578 #define MAX_PASSES 4
6587 DFPRINTF((stderr," Optimizing pCode\n"));
6591 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6592 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6593 matches += OptimizepBlock(pb);
6596 while(matches && ++passes < MAX_PASSES);
6603 const char *pic16_pCodeOpType(pCodeOp *pcop);
6604 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6607 /*-----------------------------------------------------------------*/
6608 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6609 /*-----------------------------------------------------------------*/
6611 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6615 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6616 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6618 if( !( (pcop->type == PO_LABEL) ||
6619 (pcop->type == PO_LITERAL) ||
6620 (pcop->type == PO_STR) ))
6621 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6622 PCOR(pcop)->r->wasUsed = 1;
6628 /*----------------------------------------------------------------------*
6629 * pic16_areRegsSame - check to see if the names of two registers match *
6630 *----------------------------------------------------------------------*/
6631 int pic16_areRegsSame(regs *r1, regs *r2)
6633 if(!strcmp(r1->name, r2->name))return 1;
6639 /*-----------------------------------------------------------------*/
6640 /*-----------------------------------------------------------------*/
6641 static void pic16_FixRegisterBanking(pBlock *pb)
6645 regs *reg, *prevreg;
6646 unsigned char flag=0;
6651 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6654 /* loop through all of the flow blocks with in one pblock */
6656 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6660 /* at this point, pc should point to a PC_FLOW object */
6661 /* for each flow block, determine the register banking
6664 if(!isPCI(pc))goto loop;
6666 if(PCI(pc)->is2MemOp)goto loop;
6668 reg = pic16_getRegFromInstruction(pc);
6671 pc->print(stderr, pc);
6672 fprintf(stderr, "reg = %p\n", reg);
6675 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6676 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6677 reg->address,reg->isBitField, reg->isFixed);
6681 /* now make some tests to make sure that instruction needs bank switch */
6683 /* if no register exists, and if not a bit opcode goto loop */
6685 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6688 if(isPCI_SKIP(pc)) {
6689 // fprintf(stderr, "instruction is SKIP instruction\n");
6691 if(reg && isACCESS_BANK(reg))goto loop;
6693 if(!isBankInstruction(pc))goto loop;
6695 if(isPCI_LIT(pc))goto loop;
6697 if(PCI(pc)->op == POC_CALL)goto loop;
6699 /* Examine the instruction before this one to make sure it is
6700 * not a skip type instruction */
6701 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6703 flag = 0; /* add before this instruction */
6705 /* if previous instruction is a skip one, then set flag
6706 * to 2 and call insertBankSwitch */
6707 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6710 insertBankSwitch(flag, pc);
6713 // fprintf(stderr, "BANK SWITCH inserted\n");
6722 static void pBlockDestruct(pBlock *pb)
6733 /*-----------------------------------------------------------------*/
6734 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6735 /* name dbName and combine them */
6736 /* into one block */
6737 /*-----------------------------------------------------------------*/
6738 static void mergepBlocks(char dbName)
6741 pBlock *pb, *pbmerged = NULL,*pbn;
6743 pb = the_pFile->pbHead;
6745 //fprintf(stderr," merging blocks named %c\n",dbName);
6749 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6750 if( getpBlock_dbName(pb) == dbName) {
6752 //fprintf(stderr," merged block %c\n",dbName);
6757 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6758 /* pic16_addpCode2pBlock doesn't handle the tail: */
6759 pbmerged->pcTail = pb->pcTail;
6761 pb->prev->next = pbn;
6763 pbn->prev = pb->prev;
6768 //pic16_printpBlock(stderr, pbmerged);
6775 /*-----------------------------------------------------------------*/
6776 /* AnalyzeFlow - Examine the flow of the code and optimize */
6778 /* level 0 == minimal optimization */
6779 /* optimize registers that are used only by two instructions */
6780 /* level 1 == maximal optimization */
6781 /* optimize by looking at pairs of instructions that use the */
6783 /*-----------------------------------------------------------------*/
6785 static void AnalyzeFlow(int level)
6787 static int times_called=0;
6792 /* remove unused allocated registers before exiting */
6793 pic16_RemoveUnusedRegisters();
6799 /* if this is not the first time this function has been called,
6800 then clean up old flow information */
6801 if(times_called++) {
6802 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6805 pic16_RegsUnMapLiveRanges();
6810 /* Phase 2 - Flow Analysis - Register Banking
6812 * In this phase, the individual flow blocks are examined
6813 * and register banking is fixed.
6817 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6818 pic16_FixRegisterBanking(pb);
6821 /* Phase 2 - Flow Analysis
6823 * In this phase, the pCode is partition into pCodeFlow
6824 * blocks. The flow blocks mark the points where a continuous
6825 * stream of instructions changes flow (e.g. because of
6826 * a call or goto or whatever).
6829 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6830 pic16_BuildFlow(pb);
6833 /* Phase 2 - Flow Analysis - linking flow blocks
6835 * In this phase, the individual flow blocks are examined
6836 * to determine their order of excution.
6839 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6842 /* Phase 3 - Flow Analysis - Flow Tree
6844 * In this phase, the individual flow blocks are examined
6845 * to determine their order of execution.
6848 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6849 pic16_BuildFlowTree(pb);
6852 /* Phase x - Flow Analysis - Used Banks
6854 * In this phase, the individual flow blocks are examined
6855 * to determine the Register Banks they use
6859 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6864 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6865 pic16_pCodeRegMapLiveRanges(pb);
6867 pic16_RemoveUnusedRegisters();
6869 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6870 pic16_pCodeRegOptimizeRegUsage(level);
6878 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6883 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6885 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6886 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6887 pcflow = pcflow->next) {
6889 FillFlow(PCFL(pcflow));
6894 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6897 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6898 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6899 pcflow = pcflow->next) {
6901 FlowStats(PCFL(pcflow));
6907 /* VR -- no need to analyze banking in flow, but left here :
6908 * 1. because it may be used in the future for other purposes
6909 * 2. because if omitted we'll miss some optimization done here
6911 * Perhaps I should rename it to something else
6914 /*-----------------------------------------------------------------*/
6915 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6916 /* assigned to the registers. */
6918 /*-----------------------------------------------------------------*/
6920 void pic16_AnalyzeBanking(void)
6925 /* Phase x - Flow Analysis - Used Banks
6927 * In this phase, the individual flow blocks are examined
6928 * to determine the Register Banks they use
6934 if(!the_pFile)return;
6936 if(!pic16_options.no_banksel) {
6937 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6938 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6939 pic16_FixRegisterBanking(pb);
6945 /*-----------------------------------------------------------------*/
6946 /* buildCallTree - Look at the flow and extract all of the calls. */
6947 /*-----------------------------------------------------------------*/
6948 static set *register_usage(pBlock *pb);
6950 static void buildCallTree(void )
6962 /* Now build the call tree.
6963 First we examine all of the pCodes for functions.
6964 Keep in mind that the function boundaries coincide
6965 with pBlock boundaries.
6967 The algorithm goes something like this:
6968 We have two nested loops. The outer loop iterates
6969 through all of the pBlocks/functions. The inner
6970 loop iterates through all of the pCodes for
6971 a given pBlock. When we begin iterating through
6972 a pBlock, the variable pc_fstart, pCode of the start
6973 of a function, is cleared. We then search for pCodes
6974 of type PC_FUNCTION. When one is encountered, we
6975 initialize pc_fstart to this and at the same time
6976 associate a new pBranch object that signifies a
6977 branch entry. If a return is found, then this signifies
6978 a function exit point. We'll link the pCodes of these
6979 returns to the matching pc_fstart.
6981 When we're done, a doubly linked list of pBranches
6982 will exist. The head of this list is stored in
6983 `the_pFile', which is the meta structure for all
6984 of the pCode. Look at the pic16_printCallTree function
6985 on how the pBranches are linked together.
6988 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6989 pCode *pc_fstart=NULL;
6990 for(pc = pb->pcHead; pc; pc = pc->next) {
6992 if(isPCI(pc) && pc_fstart) {
6993 if(PCI(pc)->is2MemOp) {
6994 r = pic16_getRegFromInstruction2(pc);
6995 if(r && !strcmp(r->name, "POSTDEC1"))
6996 PCF(pc_fstart)->stackusage++;
6998 r = pic16_getRegFromInstruction(pc);
6999 if(r && !strcmp(r->name, "PREINC1"))
7000 PCF(pc_fstart)->stackusage--;
7005 if (PCF(pc)->fname) {
7007 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
7008 //fprintf(stderr," found main \n");
7009 pb->cmemmap = NULL; /* FIXME do we need to free ? */
7013 pbr = Safe_calloc(1,sizeof(pBranch));
7014 pbr->pc = pc_fstart = pc;
7017 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7019 // Here's a better way of doing the same:
7020 addSet(&pb->function_entries, pc);
7023 // Found an exit point in a function, e.g. return
7024 // (Note, there may be more than one return per function)
7026 pBranchLink(PCF(pc_fstart), PCF(pc));
7028 addSet(&pb->function_exits, pc);
7030 } else if(isCALL(pc)) {
7031 addSet(&pb->function_calls,pc);
7038 /* This is not needed because currently all register used
7039 * by a function are stored in stack -- VR */
7041 /* Re-allocate the registers so that there are no collisions
7042 * between local variables when one function call another */
7045 // pic16_deallocateAllRegs();
7047 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7055 /*-----------------------------------------------------------------*/
7056 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7057 /* all of the logical connections. */
7059 /* Essentially what's done here is that the pCode flow is */
7061 /*-----------------------------------------------------------------*/
7063 void pic16_AnalyzepCode(char dbName)
7074 /* Phase 1 - Register allocation and peep hole optimization
7076 * The first part of the analysis is to determine the registers
7077 * that are used in the pCode. Once that is done, the peep rules
7078 * are applied to the code. We continue to loop until no more
7079 * peep rule optimizations are found (or until we exceed the
7080 * MAX_PASSES threshold).
7082 * When done, the required registers will be determined.
7088 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7089 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7091 /* First, merge the labels with the instructions */
7092 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7093 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7095 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7096 //fprintf(stderr," analyze and merging block %c\n",dbName);
7097 pic16_pBlockMergeLabels(pb);
7100 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7105 changes = OptimizepCode(dbName);
7108 } while(changes && (i++ < MAX_PASSES));
7115 /* convert a series of movff's of local regs to stack, with a single call to
7116 * a support functions which does the same thing via loop */
7117 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
7121 char *fname[]={"__lr_store", "__lr_restore"};
7123 // pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
7125 pct = pic16_findNextInstruction(pcstart->next);
7128 pct = pc->next; //pic16_findNextInstruction(pc->next);
7129 // pc->print(stderr, pc);
7130 if(isPCI(pc) && PCI(pc)->label) {
7131 pbr = PCI(pc)->label;
7132 while(pbr && pbr->pc) {
7133 PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
7137 // pc->print(stderr, pc);
7139 pc->prev->next = pct;
7140 pct->prev = pc->prev;
7144 } while ((pc) && (pc != pcend));
7146 /* unlink movff instructions */
7147 pcstart->next = pcend;
7148 pcend->prev = pcstart;
7150 pic16_pCodeInsertAfter(pcstart, (pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name))))); pc = pct;
7151 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
7152 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] )));
7157 sym = newSymbol( fname[ entry?0:1 ], 0 );
7158 strcpy(sym->rname, fname[ entry?0:1 ]);
7159 checkAddSym(&externs, sym);
7161 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
7167 /*-----------------------------------------------------------------*/
7168 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for */
7169 /* local registers to a support function call */
7170 /*-----------------------------------------------------------------*/
7171 void pic16_OptimizeLocalRegs(void)
7176 pCodeOpLocalReg *pclr;
7179 regs *r, *lastr=NULL, *firstr=NULL;
7180 pCode *pcstart=NULL, *pcend=NULL;
7184 * local_regs begin mark
7185 * MOVFF r0x01, POSTDEC1
7186 * MOVFF r0x02, POSTDEC1
7189 * MOVFF r0x0n, POSTDEC1
7190 * local_regs end mark
7192 * convert the above to the below:
7193 * MOVLW starting_register_index
7195 * MOVLW register_count
7196 * call __save_registers_in_stack
7202 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7203 inRegCount = regCount = 0;
7204 firstr = lastr = NULL;
7205 for(pc = pb->pcHead; pc; pc = pc->next) {
7206 if(pc && (pc->type == PC_INFO)) {
7209 if(pci->type == INF_LOCALREGS) {
7210 pclr = PCOLR(pci->oper1);
7212 if((pclr->type == LR_ENTRY_BEGIN)
7213 || (pclr->type == LR_ENTRY_END))inEntry = 1;
7216 switch(pclr->type) {
7217 case LR_ENTRY_BEGIN:
7219 inRegCount = 1; regCount = 0;
7220 pcstart = pc; //pic16_findNextInstruction(pc->next);
7221 firstr = lastr = NULL;
7227 pcend = pc; //pic16_findPrevInstruction(pc->prev);
7231 pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
7235 firstr = lastr = NULL;
7239 if(inRegCount == -1) {
7240 // fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
7246 if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
7248 r = pic16_getRegFromInstruction(pc);
7250 r = pic16_getRegFromInstruction2(pc);
7251 if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
7252 if(!firstr)firstr = r;
7254 // fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
7266 /*-----------------------------------------------------------------*/
7267 /* ispCodeFunction - returns true if *pc is the pCode of a */
7269 /*-----------------------------------------------------------------*/
7270 static bool ispCodeFunction(pCode *pc)
7273 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7279 /*-----------------------------------------------------------------*/
7280 /* findFunction - Search for a function by name (given the name) */
7281 /* in the set of all functions that are in a pBlock */
7282 /* (note - I expect this to change because I'm planning to limit */
7283 /* pBlock's to just one function declaration */
7284 /*-----------------------------------------------------------------*/
7285 static pCode *findFunction(char *fname)
7292 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7294 pc = setFirstItem(pb->function_entries);
7297 if((pc->type == PC_FUNCTION) &&
7299 (strcmp(fname, PCF(pc)->fname)==0))
7302 pc = setNextItem(pb->function_entries);
7310 static void MarkUsedRegisters(set *regset)
7315 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7316 // fprintf(stderr, "marking register = %s\t", r1->name);
7317 r2 = pic16_regWithIdx(r1->rIdx);
7318 // fprintf(stderr, "to register = %s\n", r2->name);
7324 static void pBlockStats(FILE *of, pBlock *pb)
7330 if(!pic16_pcode_verbose)return;
7332 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7334 // for now just print the first element of each set
7335 pc = setFirstItem(pb->function_entries);
7337 fprintf(of,";entry: ");
7340 pc = setFirstItem(pb->function_exits);
7342 fprintf(of,";has an exit\n");
7346 pc = setFirstItem(pb->function_calls);
7348 fprintf(of,";functions called:\n");
7351 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7352 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7354 pc = setNextItem(pb->function_calls);
7358 r = setFirstItem(pb->tregisters);
7360 int n = elementsInSet(pb->tregisters);
7362 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7365 fprintf(of,"; %s\n",r->name);
7366 r = setNextItem(pb->tregisters);
7370 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7373 /*-----------------------------------------------------------------*/
7374 /*-----------------------------------------------------------------*/
7376 static void sequencepCode(void)
7382 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7384 pb->seq = GpCodeSequenceNumber+1;
7386 for( pc = pb->pcHead; pc; pc = pc->next)
7387 pc->seq = ++GpCodeSequenceNumber;
7393 /*-----------------------------------------------------------------*/
7394 /*-----------------------------------------------------------------*/
7395 static set *register_usage(pBlock *pb)
7398 set *registers=NULL;
7399 set *registersInCallPath = NULL;
7401 /* check recursion */
7403 pc = setFirstItem(pb->function_entries);
7410 if(pc->type != PC_FUNCTION)
7411 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7413 pc = setFirstItem(pb->function_calls);
7414 for( ; pc; pc = setNextItem(pb->function_calls)) {
7416 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7417 char *dest = pic16_get_op_from_instruction(PCI(pc));
7419 pcn = findFunction(dest);
7421 registersInCallPath = register_usage(pcn->pb);
7423 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7428 pBlockStats(stderr,pb); // debug
7431 // Mark the registers in this block as used.
7433 MarkUsedRegisters(pb->tregisters);
7434 if(registersInCallPath) {
7435 /* registers were used in the functions this pBlock has called */
7436 /* so now, we need to see if these collide with the ones we are */
7439 regs *r1,*r2, *newreg;
7441 DFPRINTF((stderr,"comparing registers\n"));
7443 r1 = setFirstItem(registersInCallPath);
7446 r2 = setFirstItem(pb->tregisters);
7448 while(r2 && (r1->type != REG_STK)) {
7450 if(r2->rIdx == r1->rIdx) {
7451 newreg = pic16_findFreeReg(REG_GPR);
7455 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7459 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7460 r1->rIdx, newreg->rIdx));
7461 r2->rIdx = newreg->rIdx;
7462 //if(r2->name) free(r2->name);
7464 r2->name = Safe_strdup(newreg->name);
7468 newreg->wasUsed = 1;
7470 r2 = setNextItem(pb->tregisters);
7473 r1 = setNextItem(registersInCallPath);
7476 /* Collisions have been resolved. Now free the registers in the call path */
7477 r1 = setFirstItem(registersInCallPath);
7479 if(r1->type != REG_STK) {
7480 newreg = pic16_regWithIdx(r1->rIdx);
7483 r1 = setNextItem(registersInCallPath);
7487 // MarkUsedRegisters(pb->registers);
7489 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7492 DFPRINTF((stderr,"returning regs\n"));
7494 DFPRINTF((stderr,"not returning regs\n"));
7496 DFPRINTF((stderr,"pBlock after register optim.\n"));
7497 pBlockStats(stderr,pb); // debug
7503 /*-----------------------------------------------------------------*/
7504 /* pct2 - writes the call tree to a file */
7506 /*-----------------------------------------------------------------*/
7507 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7511 // set *registersInCallPath = NULL;
7517 fprintf(of, "recursive function\n");
7518 return; //recursion ?
7521 pc = setFirstItem(pb->function_entries);
7528 for(i=0;i<indent;i++) // Indentation
7532 if(pc->type == PC_FUNCTION) {
7533 usedstack += PCF(pc)->stackusage;
7534 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7535 } else return; // ???
7538 pc = setFirstItem(pb->function_calls);
7539 for( ; pc; pc = setNextItem(pb->function_calls)) {
7541 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7542 char *dest = pic16_get_op_from_instruction(PCI(pc));
7544 pcn = findFunction(dest);
7546 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7548 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7556 /*-----------------------------------------------------------------*/
7557 /* pic16_printCallTree - writes the call tree to a file */
7559 /*-----------------------------------------------------------------*/
7561 void pic16_printCallTree(FILE *of)
7573 fprintf(of, "\npBlock statistics\n");
7574 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7578 fprintf(of,"Call Tree\n");
7579 pbr = the_pFile->functions;
7583 if(!ispCodeFunction(pc))
7584 fprintf(of,"bug in call tree");
7587 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7589 while(pc->next && !ispCodeFunction(pc->next)) {
7591 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7592 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7600 fprintf(of,"\n**************\n\na better call tree\n");
7601 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7606 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7607 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7613 /*-----------------------------------------------------------------*/
7615 /*-----------------------------------------------------------------*/
7617 static void InlineFunction(pBlock *pb)
7625 pc = setFirstItem(pb->function_calls);
7627 for( ; pc; pc = setNextItem(pb->function_calls)) {
7630 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7636 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7638 //fprintf(stderr,"Cool can inline:\n");
7639 //pcn->print(stderr,pcn);
7641 //fprintf(stderr,"recursive call Inline\n");
7642 InlineFunction(pcn->pb);
7643 //fprintf(stderr,"return from recursive call Inline\n");
7646 At this point, *pc points to a CALL mnemonic, and
7647 *pcn points to the function that is being called.
7649 To in-line this call, we need to remove the CALL
7650 and RETURN(s), and link the function pCode in with
7656 /* Remove the CALL */
7660 /* remove callee pBlock from the pBlock linked list */
7661 removepBlock(pcn->pb);
7669 /* Remove the Function pCode */
7670 pct = pic16_findNextInstruction(pcn->next);
7672 /* Link the function with the callee */
7673 pc->next = pcn->next;
7674 pcn->next->prev = pc;
7676 /* Convert the function name into a label */
7678 pbr = Safe_calloc(1,sizeof(pBranch));
7679 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7681 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7682 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7684 /* turn all of the return's except the last into goto's */
7685 /* check case for 2 instruction pBlocks */
7686 pce = pic16_findNextInstruction(pcn->next);
7688 pCode *pce_next = pic16_findNextInstruction(pce->next);
7690 if(pce_next == NULL) {
7691 /* found the last return */
7692 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7694 //fprintf(stderr,"found last return\n");
7695 //pce->print(stderr,pce);
7696 pce->prev->next = pc_call->next;
7697 pc_call->next->prev = pce->prev;
7698 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7708 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7714 /*-----------------------------------------------------------------*/
7716 /*-----------------------------------------------------------------*/
7718 void pic16_InlinepCode(void)
7727 if(!functionInlining)
7730 /* Loop through all of the function definitions and count the
7731 * number of times each one is called */
7732 //fprintf(stderr,"inlining %d\n",__LINE__);
7734 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7736 pc = setFirstItem(pb->function_calls);
7738 for( ; pc; pc = setNextItem(pb->function_calls)) {
7741 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7742 if(pcn && isPCF(pcn)) {
7743 PCF(pcn)->ncalled++;
7746 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7751 //fprintf(stderr,"inlining %d\n",__LINE__);
7753 /* Now, Loop through the function definitions again, but this
7754 * time inline those functions that have only been called once. */
7756 InlineFunction(the_pFile->pbHead);
7757 //fprintf(stderr,"inlining %d\n",__LINE__);
7759 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7764 char *pic_optype_names[]={
7765 "PO_NONE", // No operand e.g. NOP
7766 "PO_W", // The working register (as a destination)
7767 "PO_WREG", // The working register (as a file register)
7768 "PO_STATUS", // The 'STATUS' register
7769 "PO_BSR", // The 'BSR' register
7770 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7772 "PO_INDF0", // The Indirect register
7773 "PO_INTCON", // Interrupt Control register
7774 "PO_GPR_REGISTER", // A general purpose register
7775 "PO_GPR_BIT", // A bit of a general purpose register
7776 "PO_GPR_TEMP", // A general purpose temporary register
7777 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7778 "PO_PCL", // Program counter Low register
7779 "PO_PCLATH", // Program counter Latch high register
7780 "PO_PCLATU", // Program counter Latch upper register
7781 "PO_PRODL", // Product Register Low
7782 "PO_PRODH", // Product Register High
7783 "PO_LITERAL", // A constant
7784 "PO_REL_ADDR", // A relative address
7785 "PO_IMMEDIATE", // (8051 legacy)
7786 "PO_DIR", // Direct memory (8051 legacy)
7787 "PO_CRY", // bit memory (8051 legacy)
7788 "PO_BIT", // bit operand.
7789 "PO_STR", // (8051 legacy)
7791 "PO_WILD" // Wild card operand in peep optimizer
7795 char *dumpPicOptype(PIC_OPTYPE type)
7797 return (pic_optype_names[ type ]);