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};
109 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
110 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
111 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
113 pCodeOpReg *pic16_stackpnt_lo;
114 pCodeOpReg *pic16_stackpnt_hi;
115 pCodeOpReg *pic16_stack_postinc;
116 pCodeOpReg *pic16_stack_postdec;
117 pCodeOpReg *pic16_stack_preinc;
118 pCodeOpReg *pic16_stack_plusw;
120 pCodeOpReg *pic16_framepnt_lo;
121 pCodeOpReg *pic16_framepnt_hi;
122 pCodeOpReg *pic16_frame_postinc;
123 pCodeOpReg *pic16_frame_postdec;
124 pCodeOpReg *pic16_frame_preinc;
125 pCodeOpReg *pic16_frame_plusw;
127 pCodeOpReg pic16_pc_gpsimio = {{PO_GPR_REGISTER, "GPSIMIO"}, -1, NULL, 0, NULL};
128 pCodeOpReg pic16_pc_gpsimio2 = {{PO_GPR_REGISTER, "GPSIMIO2"}, -1, NULL, 0, NULL};
130 char *OPT_TYPE_STR[] = { "begin", "end", "jumptable_begin", "jumptable_end" };
131 char *LR_TYPE_STR[] = { "entry begin", "entry end", "exit begin", "exit end" };
134 static int mnemonics_initialized = 0;
137 static hTab *pic16MnemonicsHash = NULL;
138 static hTab *pic16pCodePeepCommandsHash = NULL;
140 static pFile *the_pFile = NULL;
141 static pBlock *pb_dead_pcodes = NULL;
143 /* Hardcoded flags to change the behavior of the PIC port */
144 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
145 static int functionInlining = 1; /* inline functions if nonzero */
146 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
148 int pic16_pcode_verbose = 0;
150 //static int GpCodeSequenceNumber = 1;
151 static int GpcFlowSeq = 1;
153 extern void pic16_RemoveUnusedRegisters(void);
154 extern void pic16_RegsUnMapLiveRanges(void);
155 extern void pic16_BuildFlowTree(pBlock *pb);
156 extern void pic16_pCodeRegOptimizeRegUsage(int level);
157 extern int pic16_picIsInitialized(void);
158 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
159 extern int mnem2key(char const *mnem);
161 /****************************************************************/
162 /* Forward declarations */
163 /****************************************************************/
165 void pic16_unlinkpCode(pCode *pc);
167 static void genericAnalyze(pCode *pc);
168 static void AnalyzeGOTO(pCode *pc);
169 static void AnalyzeSKIP(pCode *pc);
170 static void AnalyzeRETURN(pCode *pc);
173 static void genericDestruct(pCode *pc);
174 static void genericPrint(FILE *of,pCode *pc);
176 static void pCodePrintLabel(FILE *of, pCode *pc);
177 static void pCodePrintFunction(FILE *of, pCode *pc);
178 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
179 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
180 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
181 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
182 int pic16_pCodePeepMatchRule(pCode *pc);
183 static void pBlockStats(FILE *of, pBlock *pb);
184 static pBlock *newpBlock(void);
185 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
186 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
187 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
188 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
189 void OptimizeLocalRegs(void);
190 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
192 char *dumpPicOptype(PIC_OPTYPE type);
194 pCodeOp *pic16_popGetLit2(int, pCodeOp *);
195 pCodeOp *pic16_popGetLit(int);
196 pCodeOp *pic16_popGetWithString(char *);
197 extern int inWparamList(char *s);
200 /****************************************************************/
201 /* PIC Instructions */
202 /****************************************************************/
204 pCodeInstruction pic16_pciADDWF = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
219 1,0, // dest, bit instruction
221 0, // literal operand
223 0, // fast call/return mode select bit
224 0, // second memory operand
225 0, // second literal operand
227 (PCC_W | PCC_REGISTER), // inCond
228 (PCC_REGISTER | PCC_Z), // outCond
232 pCodeInstruction pic16_pciADDFW = {
233 {PC_OPCODE, NULL, NULL, 0, NULL,
247 0,0, // dest, bit instruction
249 0, // literal operand
251 0, // fast call/return mode select bit
252 0, // second memory operand
253 0, // second literal operand
255 (PCC_W | PCC_REGISTER), // inCond
256 (PCC_W | PCC_Z), // outCond
260 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
261 {PC_OPCODE, NULL, NULL, 0, NULL,
275 1,0, // dest, bit instruction
277 0, // literal operand
279 0, // fast call/return mode select bit
280 0, // second memory operand
281 0, // second literal operand
283 (PCC_W | PCC_REGISTER | PCC_C), // inCond
284 (PCC_REGISTER | PCC_Z | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
288 pCodeInstruction pic16_pciADDFWC = {
289 {PC_OPCODE, NULL, NULL, 0, NULL,
303 0,0, // dest, bit instruction
305 0, // literal operand
307 0, // fast call/return mode select bit
308 0, // second memory operand
309 0, // second literal operand
311 (PCC_W | PCC_REGISTER | PCC_C), // inCond
312 (PCC_W | PCC_Z | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
316 pCodeInstruction pic16_pciADDLW = {
317 {PC_OPCODE, NULL, NULL, 0, NULL,
331 0,0, // dest, bit instruction
333 1, // literal operand
335 0, // fast call/return mode select bit
336 0, // second memory operand
337 0, // second literal operand
339 (PCC_W | PCC_LITERAL), // inCond
340 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
344 pCodeInstruction pic16_pciANDLW = {
345 {PC_OPCODE, NULL, NULL, 0, NULL,
359 0,0, // dest, bit instruction
361 1, // literal operand
363 0, // fast call/return mode select bit
364 0, // second memory operand
365 0, // second literal operand
367 (PCC_W | PCC_LITERAL), // inCond
368 (PCC_W | PCC_Z | PCC_N), // outCond
372 pCodeInstruction pic16_pciANDWF = {
373 {PC_OPCODE, NULL, NULL, 0, NULL,
387 1,0, // dest, bit instruction
389 0, // literal operand
391 0, // fast call/return mode select bit
392 0, // second memory operand
393 0, // second literal operand
395 (PCC_W | PCC_REGISTER), // inCond
396 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
400 pCodeInstruction pic16_pciANDFW = {
401 {PC_OPCODE, NULL, NULL, 0, NULL,
415 0,0, // dest, bit instruction
417 0, // literal operand
419 0, // fast call/return mode select bit
420 0, // second memory operand
421 0, // second literal operand
423 (PCC_W | PCC_REGISTER), // inCond
424 (PCC_W | PCC_Z) // outCond
427 pCodeInstruction pic16_pciBC = { // mdubuc - New
428 {PC_OPCODE, NULL, NULL, 0, NULL,
442 0,0, // dest, bit instruction
444 0, // literal operand
446 0, // fast call/return mode select bit
447 0, // second memory operand
448 0, // second literal operand
450 (PCC_REL_ADDR | PCC_C), // inCond
455 pCodeInstruction pic16_pciBCF = {
456 {PC_OPCODE, NULL, NULL, 0, NULL,
470 1,1, // dest, bit instruction
472 0, // literal operand
474 0, // fast call/return mode select bit
475 0, // second memory operand
476 0, // second literal operand
478 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
479 PCC_REGISTER, // outCond
483 pCodeInstruction pic16_pciBN = { // mdubuc - New
484 {PC_OPCODE, NULL, NULL, 0, NULL,
498 0,0, // dest, bit instruction
500 0, // literal operand
502 0, // fast call/return mode select bit
503 0, // second memory operand
504 0, // second literal operand
506 (PCC_REL_ADDR | PCC_N), // inCond
507 PCC_NONE , // outCond
511 pCodeInstruction pic16_pciBNC = { // mdubuc - New
512 {PC_OPCODE, NULL, NULL, 0, NULL,
526 0,0, // dest, bit instruction
528 0, // literal operand
530 0, // fast call/return mode select bit
531 0, // second memory operand
532 0, // second literal operand
534 (PCC_REL_ADDR | PCC_C), // inCond
535 PCC_NONE , // outCond
539 pCodeInstruction pic16_pciBNN = { // mdubuc - New
540 {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_N), // inCond
563 PCC_NONE , // outCond
567 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
568 {PC_OPCODE, NULL, NULL, 0, NULL,
582 0,0, // dest, bit instruction
584 0, // literal operand
586 0, // fast call/return mode select bit
587 0, // second memory operand
588 0, // second literal operand
590 (PCC_REL_ADDR | PCC_OV), // inCond
591 PCC_NONE , // outCond
595 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
596 {PC_OPCODE, NULL, NULL, 0, NULL,
610 0,0, // dest, bit instruction
612 0, // literal operand
614 0, // fast call/return mode select bit
615 0, // second memory operand
616 0, // second literal operand
618 (PCC_REL_ADDR | PCC_Z), // inCond
619 PCC_NONE , // outCond
623 pCodeInstruction pic16_pciBOV = { // mdubuc - New
624 {PC_OPCODE, NULL, NULL, 0, NULL,
638 0,0, // dest, bit instruction
640 0, // literal operand
642 0, // fast call/return mode select bit
643 0, // second memory operand
644 0, // second literal operand
646 (PCC_REL_ADDR | PCC_OV), // inCond
647 PCC_NONE , // outCond
651 pCodeInstruction pic16_pciBRA = { // mdubuc - New
652 {PC_OPCODE, NULL, NULL, 0, NULL,
666 0,0, // dest, bit instruction
668 0, // literal operand
670 0, // fast call/return mode select bit
671 0, // second memory operand
672 0, // second literal operand
674 PCC_REL_ADDR, // inCond
675 PCC_NONE , // outCond
679 pCodeInstruction pic16_pciBSF = {
680 {PC_OPCODE, NULL, NULL, 0, NULL,
694 1,1, // dest, bit instruction
696 0, // literal operand
698 0, // fast call/return mode select bit
699 0, // second memory operand
700 0, // second literal operand
702 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
703 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
707 pCodeInstruction pic16_pciBTFSC = {
708 {PC_OPCODE, NULL, NULL, 0, NULL,
722 0,1, // dest, bit instruction
724 0, // literal operand
726 0, // fast call/return mode select bit
727 0, // second memory operand
728 0, // second literal operand
730 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
731 PCC_EXAMINE_PCOP, // outCond
735 pCodeInstruction pic16_pciBTFSS = {
736 {PC_OPCODE, NULL, NULL, 0, NULL,
750 0,1, // dest, bit instruction
752 0, // literal operand
754 0, // fast call/return mode select bit
755 0, // second memory operand
756 0, // second literal operand
758 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
759 PCC_EXAMINE_PCOP, // outCond
763 pCodeInstruction pic16_pciBTG = { // mdubuc - New
764 {PC_OPCODE, NULL, NULL, 0, NULL,
778 0,1, // dest, bit instruction
780 0, // literal operand
782 0, // fast call/return mode select bit
783 0, // second memory operand
784 0, // second literal operand
786 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
787 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
791 pCodeInstruction pic16_pciBZ = { // mdubuc - New
792 {PC_OPCODE, NULL, NULL, 0, NULL,
806 0,0, // dest, bit instruction
808 0, // literal operand
810 0, // fast call/return mode select bit
811 0, // second memory operand
812 0, // second literal operand
819 pCodeInstruction pic16_pciCALL = {
820 {PC_OPCODE, NULL, NULL, 0, NULL,
834 0,0, // dest, bit instruction
836 0, // literal operand
838 1, // fast call/return mode select bit
839 0, // second memory operand
840 0, // second literal operand
847 pCodeInstruction pic16_pciCOMF = {
848 {PC_OPCODE, NULL, NULL, 0, NULL,
862 1,0, // dest, bit instruction
864 0, // literal operand
866 0, // fast call/return mode select bit
867 0, // second memory operand
868 0, // second literal operand
870 PCC_REGISTER, // inCond
871 (PCC_REGISTER | PCC_Z | PCC_N) , // outCond
875 pCodeInstruction pic16_pciCOMFW = {
876 {PC_OPCODE, NULL, NULL, 0, NULL,
890 0,0, // dest, bit instruction
892 0, // literal operand
894 0, // fast call/return mode select bit
895 0, // second memory operand
896 0, // second literal operand
898 PCC_REGISTER, // inCond
903 pCodeInstruction pic16_pciCLRF = {
904 {PC_OPCODE, NULL, NULL, 0, NULL,
918 0,0, // dest, bit instruction
920 0, // literal operand
922 0, // fast call/return mode select bit
923 0, // second memory operand
924 0, // second literal operand
926 PCC_REGISTER, // inCond
927 (PCC_REGISTER | PCC_Z), // outCond
931 pCodeInstruction pic16_pciCLRWDT = {
932 {PC_OPCODE, NULL, NULL, 0, NULL,
946 0,0, // dest, bit instruction
948 0, // literal operand
950 0, // fast call/return mode select bit
951 0, // second memory operand
952 0, // second literal operand
955 PCC_NONE , // outCond
959 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
960 {PC_OPCODE, NULL, NULL, 0, NULL,
974 0,0, // dest, bit instruction
976 0, // literal operand
978 0, // fast call/return mode select bit
979 0, // second memory operand
980 0, // second literal operand
982 (PCC_W | PCC_REGISTER), // inCond
983 PCC_NONE , // outCond
987 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
988 {PC_OPCODE, NULL, NULL, 0, NULL,
1002 0,0, // dest, bit instruction
1003 1,1, // branch, skip
1004 0, // literal operand
1005 1, // RAM access bit
1006 0, // fast call/return mode select bit
1007 0, // second memory operand
1008 0, // second literal operand
1010 (PCC_W | PCC_REGISTER), // inCond
1011 PCC_NONE , // outCond
1015 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
1016 {PC_OPCODE, NULL, NULL, 0, NULL,
1023 NULL, // from branch
1030 1,0, // dest, bit instruction
1031 1,1, // branch, skip
1032 0, // literal operand
1033 1, // RAM access bit
1034 0, // fast call/return mode select bit
1035 0, // second memory operand
1036 0, // second literal operand
1038 (PCC_W | PCC_REGISTER), // inCond
1039 PCC_NONE , // outCond
1043 pCodeInstruction pic16_pciDAW = {
1044 {PC_OPCODE, NULL, NULL, 0, NULL,
1051 NULL, // from branch
1058 0,0, // dest, bit instruction
1059 0,0, // branch, skip
1060 0, // literal operand
1061 0, // RAM access bit
1062 0, // fast call/return mode select bit
1063 0, // second memory operand
1064 0, // second literal operand
1067 (PCC_W | PCC_C), // outCond
1071 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1072 {PC_OPCODE, NULL, NULL, 0, NULL,
1079 NULL, // from branch
1086 1,0, // dest, bit instruction
1087 1,1, // branch, skip
1088 0, // literal operand
1089 1, // RAM access bit
1090 0, // fast call/return mode select bit
1091 0, // second memory operand
1092 0, // second literal operand
1094 PCC_REGISTER, // inCond
1095 PCC_REGISTER , // outCond
1099 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1100 {PC_OPCODE, NULL, NULL, 0, NULL,
1107 NULL, // from branch
1114 0,0, // dest, bit instruction
1115 1,1, // branch, skip
1116 0, // literal operand
1117 1, // RAM access bit
1118 0, // fast call/return mode select bit
1119 0, // second memory operand
1120 0, // second literal operand
1122 PCC_REGISTER, // inCond
1127 pCodeInstruction pic16_pciDECF = {
1128 {PC_OPCODE, NULL, NULL, 0, NULL,
1135 NULL, // from branch
1142 1,0, // dest, bit instruction
1143 0,0, // branch, skip
1144 0, // literal operand
1145 1, // RAM access bit
1146 0, // fast call/return mode select bit
1147 0, // second memory operand
1148 0, // second literal operand
1150 PCC_REGISTER, // inCond
1151 PCC_REGISTER , // outCond
1155 pCodeInstruction pic16_pciDECFW = {
1156 {PC_OPCODE, NULL, NULL, 0, NULL,
1163 NULL, // from branch
1170 0,0, // dest, bit instruction
1171 0,0, // branch, skip
1172 0, // literal operand
1173 1, // RAM access bit
1174 0, // fast call/return mode select bit
1175 0, // second memory operand
1176 0, // second literal operand
1178 PCC_REGISTER, // inCond
1183 pCodeInstruction pic16_pciDECFSZ = {
1184 {PC_OPCODE, NULL, NULL, 0, NULL,
1191 NULL, // from branch
1198 1,0, // dest, bit instruction
1199 1,1, // branch, skip
1200 0, // literal operand
1201 1, // RAM access bit
1202 0, // fast call/return mode select bit
1203 0, // second memory operand
1204 0, // second literal operand
1206 PCC_REGISTER, // inCond
1207 PCC_REGISTER , // outCond
1211 pCodeInstruction pic16_pciDECFSZW = {
1212 {PC_OPCODE, NULL, NULL, 0, NULL,
1219 NULL, // from branch
1226 0,0, // dest, bit instruction
1227 1,1, // branch, skip
1228 0, // literal operand
1229 1, // RAM access bit
1230 0, // fast call/return mode select bit
1231 0, // second memory operand
1232 0, // second literal operand
1234 PCC_REGISTER, // inCond
1239 pCodeInstruction pic16_pciGOTO = {
1240 {PC_OPCODE, NULL, NULL, 0, NULL,
1247 NULL, // from branch
1254 0,0, // dest, bit instruction
1255 1,0, // branch, skip
1256 0, // literal operand
1257 0, // RAM access bit
1258 0, // fast call/return mode select bit
1259 0, // second memory operand
1260 0, // second literal operand
1262 PCC_REL_ADDR, // inCond
1263 PCC_NONE , // outCond
1267 pCodeInstruction pic16_pciINCF = {
1268 {PC_OPCODE, NULL, NULL, 0, NULL,
1275 NULL, // from branch
1282 1,0, // dest, bit instruction
1283 0,0, // branch, skip
1284 0, // literal operand
1285 1, // RAM access bit
1286 0, // fast call/return mode select bit
1287 0, // second memory operand
1288 0, // second literal operand
1290 PCC_REGISTER, // inCond
1291 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1295 pCodeInstruction pic16_pciINCFW = {
1296 {PC_OPCODE, NULL, NULL, 0, NULL,
1303 NULL, // from branch
1310 0,0, // dest, bit instruction
1311 0,0, // 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_pciINCFSZ = {
1324 {PC_OPCODE, NULL, NULL, 0, NULL,
1331 NULL, // from branch
1338 1,0, // dest, bit instruction
1339 1,1, // branch, skip
1340 0, // literal operand
1341 1, // RAM access bit
1342 0, // fast call/return mode select bit
1343 0, // second memory operand
1344 0, // second literal operand
1346 PCC_REGISTER, // inCond
1347 PCC_REGISTER , // outCond
1351 pCodeInstruction pic16_pciINCFSZW = {
1352 {PC_OPCODE, NULL, NULL, 0, NULL,
1359 NULL, // from branch
1366 0,0, // dest, bit instruction
1367 1,1, // branch, skip
1368 0, // literal operand
1369 1, // RAM access bit
1370 0, // fast call/return mode select bit
1371 0, // second memory operand
1372 0, // second literal operand
1374 PCC_REGISTER, // inCond
1379 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1380 {PC_OPCODE, NULL, NULL, 0, NULL,
1387 NULL, // from branch
1394 1,0, // dest, bit instruction
1395 1,1, // branch, skip
1396 0, // literal operand
1397 1, // RAM access bit
1398 0, // fast call/return mode select bit
1399 0, // second memory operand
1400 0, // second literal operand
1402 PCC_REGISTER, // inCond
1403 PCC_REGISTER , // outCond
1407 pCodeInstruction pic16_pciINFSNZW = { // vrokas - New
1408 {PC_OPCODE, NULL, NULL, 0, NULL,
1415 NULL, // from branch
1422 0,0, // dest, bit instruction
1423 1,1, // branch, skip
1424 0, // literal operand
1425 1, // RAM access bit
1426 0, // fast call/return mode select bit
1427 0, // second memory operand
1428 0, // second literal operand
1430 PCC_REGISTER, // inCond
1435 pCodeInstruction pic16_pciIORWF = {
1436 {PC_OPCODE, NULL, NULL, 0, NULL,
1443 NULL, // from branch
1450 1,0, // dest, bit instruction
1451 0,0, // branch, skip
1452 0, // literal operand
1453 1, // RAM access bit
1454 0, // fast call/return mode select bit
1455 0, // second memory operand
1456 0, // second literal operand
1458 (PCC_W | PCC_REGISTER), // inCond
1459 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1463 pCodeInstruction pic16_pciIORFW = {
1464 {PC_OPCODE, NULL, NULL, 0, NULL,
1471 NULL, // from branch
1478 0,0, // dest, bit instruction
1479 0,0, // branch, skip
1480 0, // literal operand
1481 1, // RAM access bit
1482 0, // fast call/return mode select bit
1483 0, // second memory operand
1484 0, // second literal operand
1486 (PCC_W | PCC_REGISTER), // inCond
1487 (PCC_W | PCC_Z | PCC_N), // outCond
1491 pCodeInstruction pic16_pciIORLW = {
1492 {PC_OPCODE, NULL, NULL, 0, NULL,
1499 NULL, // from branch
1506 0,0, // dest, bit instruction
1507 0,0, // branch, skip
1508 1, // literal operand
1509 0, // RAM access bit
1510 0, // fast call/return mode select bit
1511 0, // second memory operand
1512 0, // second literal operand
1514 (PCC_W | PCC_LITERAL), // inCond
1515 (PCC_W | PCC_Z | PCC_N), // outCond
1519 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1520 {PC_OPCODE, NULL, NULL, 0, NULL,
1527 NULL, // from branch
1534 0,0, // dest, bit instruction
1535 0,0, // branch, skip
1536 1, // literal operand
1537 0, // RAM access bit
1538 0, // fast call/return mode select bit
1539 0, // second memory operand
1540 1, // second literal operand
1542 (PCC_REGISTER | PCC_LITERAL),
1543 PCC_REGISTER, // outCond
1547 pCodeInstruction pic16_pciMOVF = {
1548 {PC_OPCODE, NULL, NULL, 0, NULL,
1555 NULL, // from branch
1562 1,0, // dest, bit instruction
1563 0,0, // branch, skip
1564 0, // literal operand
1565 1, // RAM access bit
1566 0, // fast call/return mode select bit
1567 0, // second memory operand
1568 0, // second literal operand
1570 PCC_REGISTER, // inCond
1571 (PCC_Z | PCC_N), // outCond
1575 pCodeInstruction pic16_pciMOVFW = {
1576 {PC_OPCODE, NULL, NULL, 0, NULL,
1583 NULL, // from branch
1590 0,0, // dest, bit instruction
1591 0,0, // branch, skip
1592 0, // literal operand
1593 1, // RAM access bit
1594 0, // fast call/return mode select bit
1595 0, // second memory operand
1596 0, // second literal operand
1598 PCC_REGISTER, // inCond
1599 (PCC_W | PCC_Z), // outCond
1603 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1604 {PC_OPCODE, NULL, NULL, 0, NULL,
1611 NULL, // from branch
1618 0,0, // dest, bit instruction
1619 0,0, // branch, skip
1620 0, // literal operand
1621 0, // RAM access bit
1622 0, // fast call/return mode select bit
1623 1, // second memory operand
1624 0, // second literal operand
1626 PCC_REGISTER, // inCond
1627 PCC_REGISTER, // outCond
1631 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1632 {PC_OPCODE, NULL, NULL, 0, NULL,
1638 NULL, // from branch
1645 0,0, // dest, bit instruction
1646 0,0, // branch, skip
1647 1, // literal operand
1648 0, // RAM access bit
1649 0, // fast call/return mode select bit
1650 0, // second memory operand
1651 0, // second literal operand
1653 (PCC_NONE | PCC_LITERAL), // inCond
1654 PCC_REGISTER, // outCond - BSR
1658 pCodeInstruction pic16_pciMOVLW = {
1659 {PC_OPCODE, NULL, NULL, 0, NULL,
1665 NULL, // from branch
1672 0,0, // dest, bit instruction
1673 0,0, // branch, skip
1674 1, // literal operand
1675 0, // RAM access bit
1676 0, // fast call/return mode select bit
1677 0, // second memory operand
1678 0, // second literal operand
1680 (PCC_NONE | PCC_LITERAL), // inCond
1685 pCodeInstruction pic16_pciMOVWF = {
1686 {PC_OPCODE, NULL, NULL, 0, NULL,
1693 NULL, // from branch
1700 0,0, // dest, bit instruction
1701 0,0, // branch, skip
1702 0, // literal operand
1703 1, // RAM access bit
1704 0, // fast call/return mode select bit
1705 0, // second memory operand
1706 0, // second literal operand
1708 PCC_REGISTER, // inCond
1713 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1714 {PC_OPCODE, NULL, NULL, 0, NULL,
1720 NULL, // from branch
1727 0,0, // dest, bit instruction
1728 0,0, // branch, skip
1729 1, // literal operand
1730 0, // RAM access bit
1731 0, // fast call/return mode select bit
1732 0, // second memory operand
1733 0, // second literal operand
1735 (PCC_W | PCC_LITERAL), // inCond
1736 PCC_REGISTER, // outCond - PROD
1740 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1741 {PC_OPCODE, NULL, NULL, 0, NULL,
1747 NULL, // from branch
1754 0,0, // dest, bit instruction
1755 0,0, // branch, skip
1756 0, // literal operand
1757 1, // RAM access bit
1758 0, // fast call/return mode select bit
1759 0, // second memory operand
1760 0, // second literal operand
1762 (PCC_W | PCC_REGISTER), // inCond
1763 PCC_REGISTER, // outCond - PROD
1767 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1768 {PC_OPCODE, NULL, NULL, 0, NULL,
1774 NULL, // from branch
1781 0,0, // dest, bit instruction
1782 0,0, // branch, skip
1783 0, // literal operand
1784 1, // RAM access bit
1785 0, // fast call/return mode select bit
1786 0, // second memory operand
1787 0, // second literal operand
1789 PCC_REGISTER, // inCond
1790 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1794 pCodeInstruction pic16_pciNOP = {
1795 {PC_OPCODE, NULL, NULL, 0, NULL,
1801 NULL, // from branch
1808 0,0, // dest, bit instruction
1809 0,0, // branch, skip
1810 0, // literal operand
1811 0, // RAM access bit
1812 0, // fast call/return mode select bit
1813 0, // second memory operand
1814 0, // second literal operand
1817 PCC_NONE, // outCond
1821 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1822 {PC_OPCODE, NULL, NULL, 0, NULL,
1828 NULL, // from branch
1835 0,0, // dest, bit instruction
1836 0,0, // branch, skip
1837 0, // literal operand
1838 0, // RAM access bit
1839 0, // fast call/return mode select bit
1840 0, // second memory operand
1841 0, // second literal operand
1844 PCC_NONE , // outCond
1848 pCodeInstruction pic16_pciPUSH = {
1849 {PC_OPCODE, NULL, NULL, 0, NULL,
1855 NULL, // from branch
1862 0,0, // dest, bit instruction
1863 0,0, // branch, skip
1864 0, // literal operand
1865 0, // RAM access bit
1866 0, // fast call/return mode select bit
1867 0, // second memory operand
1868 0, // second literal operand
1871 PCC_NONE , // outCond
1875 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1876 {PC_OPCODE, NULL, NULL, 0, NULL,
1882 NULL, // from branch
1889 0,0, // dest, bit instruction
1890 0,0, // branch, skip
1891 0, // literal operand
1892 0, // RAM access bit
1893 0, // fast call/return mode select bit
1894 0, // second memory operand
1895 0, // second literal operand
1897 PCC_REL_ADDR, // inCond
1898 PCC_NONE , // outCond
1902 pCodeInstruction pic16_pciRETFIE = {
1903 {PC_OPCODE, NULL, NULL, 0, NULL,
1910 NULL, // from branch
1917 0,0, // dest, bit instruction
1918 1,0, // branch, skip
1919 0, // literal operand
1920 0, // RAM access bit
1921 1, // fast call/return mode select bit
1922 0, // second memory operand
1923 0, // second literal operand
1926 PCC_NONE, // outCond (not true... affects the GIE bit too)
1930 pCodeInstruction pic16_pciRETLW = {
1931 {PC_OPCODE, NULL, NULL, 0, NULL,
1938 NULL, // from branch
1945 0,0, // dest, bit instruction
1946 1,0, // branch, skip
1947 1, // literal operand
1948 0, // RAM access bit
1949 0, // fast call/return mode select bit
1950 0, // second memory operand
1951 0, // second literal operand
1953 PCC_LITERAL, // inCond
1958 pCodeInstruction pic16_pciRETURN = {
1959 {PC_OPCODE, NULL, NULL, 0, NULL,
1966 NULL, // from branch
1973 0,0, // dest, bit instruction
1974 1,0, // branch, skip
1975 0, // literal operand
1976 0, // RAM access bit
1977 1, // fast call/return mode select bit
1978 0, // second memory operand
1979 0, // second literal operand
1982 PCC_NONE, // outCond
1985 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1986 {PC_OPCODE, NULL, NULL, 0, NULL,
1993 NULL, // from branch
2000 1,0, // dest, bit instruction
2001 0,0, // branch, skip
2002 0, // literal operand
2003 1, // RAM access bit
2004 0, // fast call/return mode select bit
2005 0, // second memory operand
2006 0, // second literal operand
2008 (PCC_C | PCC_REGISTER), // inCond
2009 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2013 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
2014 {PC_OPCODE, NULL, NULL, 0, NULL,
2021 NULL, // from branch
2028 0,0, // dest, bit instruction
2029 0,0, // branch, skip
2030 0, // literal operand
2031 1, // RAM access bit
2032 0, // fast call/return mode select bit
2033 0, // second memory operand
2034 0, // second literal operand
2036 (PCC_C | PCC_REGISTER), // inCond
2037 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2041 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
2042 {PC_OPCODE, NULL, NULL, 0, NULL,
2049 NULL, // from branch
2056 1,0, // dest, bit instruction
2057 0,0, // branch, skip
2058 0, // literal operand
2059 1, // RAM access bit
2060 0, // fast call/return mode select bit
2061 0, // second memory operand
2062 0, // second literal operand
2064 PCC_REGISTER, // inCond
2065 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2068 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
2069 {PC_OPCODE, NULL, NULL, 0, NULL,
2076 NULL, // from branch
2083 0,0, // dest, bit instruction
2084 0,0, // branch, skip
2085 0, // literal operand
2086 1, // RAM access bit
2087 0, // fast call/return mode select bit
2088 0, // second memory operand
2089 0, // second literal operand
2091 PCC_REGISTER, // inCond
2092 (PCC_W | PCC_Z | PCC_N), // outCond
2095 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
2096 {PC_OPCODE, NULL, NULL, 0, NULL,
2103 NULL, // from branch
2110 1,0, // dest, bit instruction
2111 0,0, // branch, skip
2112 0, // literal operand
2113 1, // RAM access bit
2114 0, // fast call/return mode select bit
2115 0, // second memory operand
2116 0, // second literal operand
2118 (PCC_C | PCC_REGISTER), // inCond
2119 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2122 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2123 {PC_OPCODE, NULL, NULL, 0, NULL,
2130 NULL, // from branch
2137 0,0, // dest, bit instruction
2138 0,0, // branch, skip
2139 0, // literal operand
2140 1, // RAM access bit
2141 0, // fast call/return mode select bit
2142 0, // second memory operand
2143 0, // second literal operand
2145 (PCC_C | PCC_REGISTER), // inCond
2146 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2149 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2150 {PC_OPCODE, NULL, NULL, 0, NULL,
2157 NULL, // from branch
2164 1,0, // dest, bit instruction
2165 0,0, // branch, skip
2166 0, // literal operand
2167 1, // RAM access bit
2168 0, // fast call/return mode select bit
2169 0, // second memory operand
2170 0, // second literal operand
2172 PCC_REGISTER, // inCond
2173 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2177 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2178 {PC_OPCODE, NULL, NULL, 0, NULL,
2185 NULL, // from branch
2192 0,0, // dest, bit instruction
2193 0,0, // branch, skip
2194 0, // literal operand
2195 1, // RAM access bit
2196 0, // fast call/return mode select bit
2197 0, // second memory operand
2198 0, // second literal operand
2200 PCC_REGISTER, // inCond
2201 (PCC_W | PCC_Z | PCC_N), // outCond
2205 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2206 {PC_OPCODE, NULL, NULL, 0, NULL,
2213 NULL, // from branch
2220 0,0, // dest, bit instruction
2221 0,0, // branch, skip
2222 0, // literal operand
2223 1, // RAM access bit
2224 0, // fast call/return mode select bit
2225 0, // second memory operand
2226 0, // second literal operand
2228 PCC_REGISTER, // inCond
2229 PCC_REGISTER , // outCond
2233 pCodeInstruction pic16_pciSUBLW = {
2234 {PC_OPCODE, NULL, NULL, 0, NULL,
2241 NULL, // from branch
2248 0,0, // dest, bit instruction
2249 0,0, // branch, skip
2250 1, // literal operand
2251 0, // RAM access bit
2252 0, // fast call/return mode select bit
2253 0, // second memory operand
2254 0, // second literal operand
2256 (PCC_W | PCC_LITERAL), // inCond
2257 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2261 pCodeInstruction pic16_pciSUBFWB = {
2262 {PC_OPCODE, NULL, NULL, 0, NULL,
2269 NULL, // from branch
2276 1,0, // dest, bit instruction
2277 0,0, // branch, skip
2278 0, // literal operand
2279 1, // RAM access bit
2280 0, // fast call/return mode select bit
2281 0, // second memory operand
2282 0, // second literal operand
2284 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2285 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2289 pCodeInstruction pic16_pciSUBWF = {
2290 {PC_OPCODE, NULL, NULL, 0, NULL,
2297 NULL, // from branch
2304 1,0, // dest, bit instruction
2305 0,0, // branch, skip
2306 0, // literal operand
2307 1, // RAM access bit
2308 0, // fast call/return mode select bit
2309 0, // second memory operand
2310 0, // second literal operand
2312 (PCC_W | PCC_REGISTER), // inCond
2313 (PCC_REGISTER | PCC_Z), // outCond
2317 pCodeInstruction pic16_pciSUBFW = {
2318 {PC_OPCODE, NULL, NULL, 0, NULL,
2325 NULL, // from branch
2332 0,0, // dest, bit instruction
2333 0,0, // branch, skip
2334 0, // literal operand
2335 1, // RAM access bit
2336 0, // fast call/return mode select bit
2337 0, // second memory operand
2338 0, // second literal operand
2340 (PCC_W | PCC_REGISTER), // inCond
2341 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2345 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2346 {PC_OPCODE, NULL, NULL, 0, NULL,
2353 NULL, // from branch
2360 1,0, // dest, bit instruction
2361 0,0, // branch, skip
2362 0, // literal operand
2363 1, // RAM access bit
2364 0, // fast call/return mode select bit
2365 0, // second memory operand
2366 0, // second literal operand
2368 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2369 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2373 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2374 {PC_OPCODE, NULL, NULL, 0, NULL,
2381 NULL, // from branch
2388 0,0, // dest, bit instruction
2389 0,0, // branch, skip
2390 0, // literal operand
2391 1, // RAM access bit
2392 0, // fast call/return mode select bit
2393 0, // second memory operand
2394 0, // second literal operand
2396 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2397 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2401 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2402 {PC_OPCODE, NULL, NULL, 0, NULL,
2409 NULL, // from branch
2416 1,0, // dest, bit instruction
2417 0,0, // branch, skip
2418 0, // literal operand
2419 1, // RAM access bit
2420 0, // fast call/return mode select bit
2421 0, // second memory operand
2422 0, // second literal operand
2424 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2425 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2429 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2430 {PC_OPCODE, NULL, NULL, 0, NULL,
2437 NULL, // from branch
2444 0,0, // dest, bit instruction
2445 0,0, // branch, skip
2446 0, // literal operand
2447 1, // RAM access bit
2448 0, // fast call/return mode select bit
2449 0, // second memory operand
2450 0, // second literal operand
2452 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2453 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2457 pCodeInstruction pic16_pciSWAPF = {
2458 {PC_OPCODE, NULL, NULL, 0, NULL,
2465 NULL, // from branch
2472 1,0, // dest, bit instruction
2473 0,0, // branch, skip
2474 0, // literal operand
2475 1, // RAM access bit
2476 0, // fast call/return mode select bit
2477 0, // second memory operand
2478 0, // second literal operand
2480 (PCC_REGISTER), // inCond
2481 (PCC_REGISTER), // outCond
2485 pCodeInstruction pic16_pciSWAPFW = {
2486 {PC_OPCODE, NULL, NULL, 0, NULL,
2493 NULL, // from branch
2500 0,0, // dest, bit instruction
2501 0,0, // branch, skip
2502 0, // literal operand
2503 1, // RAM access bit
2504 0, // fast call/return mode select bit
2505 0, // second memory operand
2506 0, // second literal operand
2508 (PCC_REGISTER), // inCond
2513 pCodeInstruction pic16_pciTBLRD = { // patch 15
2514 {PC_OPCODE, NULL, NULL, 0, NULL,
2520 NULL, // from branch
2527 0,0, // dest, bit instruction
2528 0,0, // branch, skip
2529 0, // literal operand
2530 0, // RAM access bit
2531 0, // fast call/return mode select bit
2532 0, // second memory operand
2533 0, // second literal operand
2536 PCC_NONE , // outCond
2540 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2541 {PC_OPCODE, NULL, NULL, 0, NULL,
2547 NULL, // from branch
2554 0,0, // dest, bit instruction
2555 0,0, // branch, skip
2556 0, // literal operand
2557 0, // RAM access bit
2558 0, // fast call/return mode select bit
2559 0, // second memory operand
2560 0, // second literal operand
2563 PCC_NONE , // outCond
2567 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2568 {PC_OPCODE, NULL, NULL, 0, NULL,
2574 NULL, // from branch
2581 0,0, // dest, bit instruction
2582 0,0, // branch, skip
2583 0, // literal operand
2584 0, // RAM access bit
2585 0, // fast call/return mode select bit
2586 0, // second memory operand
2587 0, // second literal operand
2590 PCC_NONE , // outCond
2594 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2595 {PC_OPCODE, NULL, NULL, 0, NULL,
2601 NULL, // from branch
2608 0,0, // dest, bit instruction
2609 0,0, // branch, skip
2610 0, // literal operand
2611 0, // RAM access bit
2612 0, // fast call/return mode select bit
2613 0, // second memory operand
2614 0, // second literal operand
2617 PCC_NONE , // outCond
2621 pCodeInstruction pic16_pciTBLWT = { // patch 15
2622 {PC_OPCODE, NULL, NULL, 0, NULL,
2628 NULL, // from branch
2635 0,0, // dest, bit instruction
2636 0,0, // branch, skip
2637 0, // literal operand
2638 0, // RAM access bit
2639 0, // fast call/return mode select bit
2640 0, // second memory operand
2641 0, // second literal operand
2644 PCC_NONE , // outCond
2648 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2649 {PC_OPCODE, NULL, NULL, 0, NULL,
2655 NULL, // from branch
2662 0,0, // dest, bit instruction
2663 0,0, // branch, skip
2664 0, // literal operand
2665 0, // RAM access bit
2666 0, // fast call/return mode select bit
2667 0, // second memory operand
2668 0, // second literal operand
2671 PCC_NONE , // outCond
2675 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2676 {PC_OPCODE, NULL, NULL, 0, NULL,
2682 NULL, // from branch
2689 0,0, // dest, bit instruction
2690 0,0, // branch, skip
2691 0, // literal operand
2692 0, // RAM access bit
2693 0, // fast call/return mode select bit
2694 0, // second memory operand
2695 0, // second literal operand
2698 PCC_NONE , // outCond
2702 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2703 {PC_OPCODE, NULL, NULL, 0, NULL,
2709 NULL, // from branch
2716 0,0, // dest, bit instruction
2717 0,0, // branch, skip
2718 0, // literal operand
2719 0, // RAM access bit
2720 0, // fast call/return mode select bit
2721 0, // second memory operand
2722 0, // second literal operand
2725 PCC_NONE , // outCond
2729 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2730 {PC_OPCODE, NULL, NULL, 0, NULL,
2737 NULL, // from branch
2744 0,0, // dest, bit instruction
2745 1,1, // branch, skip
2746 0, // literal operand
2747 1, // RAM access bit
2748 0, // fast call/return mode select bit
2749 0, // second memory operand
2750 0, // second literal operand
2752 PCC_REGISTER, // inCond
2753 PCC_NONE, // outCond
2757 pCodeInstruction pic16_pciXORWF = {
2758 {PC_OPCODE, NULL, NULL, 0, NULL,
2765 NULL, // from branch
2772 1,0, // dest, bit instruction
2773 0,0, // branch, skip
2774 0, // literal operand
2775 1, // RAM access bit
2776 0, // fast call/return mode select bit
2777 0, // second memory operand
2778 0, // second literal operand
2780 (PCC_W | PCC_REGISTER), // inCond
2781 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2785 pCodeInstruction pic16_pciXORFW = {
2786 {PC_OPCODE, NULL, NULL, 0, NULL,
2793 NULL, // from branch
2800 0,0, // dest, bit instruction
2801 0,0, // branch, skip
2802 0, // literal operand
2803 1, // RAM access bit
2804 0, // fast call/return mode select bit
2805 0, // second memory operand
2806 0, // second literal operand
2808 (PCC_W | PCC_REGISTER), // inCond
2809 (PCC_W | PCC_Z | PCC_N), // outCond
2813 pCodeInstruction pic16_pciXORLW = {
2814 {PC_OPCODE, NULL, NULL, 0, NULL,
2821 NULL, // from branch
2828 0,0, // dest, bit instruction
2829 0,0, // branch, skip
2830 1, // literal operand
2831 1, // RAM access bit
2832 0, // fast call/return mode select bit
2833 0, // second memory operand
2834 0, // second literal operand
2836 (PCC_W | PCC_LITERAL), // inCond
2837 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2842 pCodeInstruction pic16_pciBANKSEL = {
2843 {PC_OPCODE, NULL, NULL, 0, NULL,
2849 NULL, // from branch
2856 0,0, // dest, bit instruction
2857 0,0, // branch, skip
2858 0, // literal operand
2859 0, // RAM access bit
2860 0, // fast call/return mode select bit
2861 0, // second memory operand
2862 0, // second literal operand
2865 PCC_NONE, // outCond
2870 #define MAX_PIC16MNEMONICS 100
2871 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2873 //#define USE_VSNPRINTF
2876 #ifdef USE_VSNPRINTF
2877 // Alas, vsnprintf is not ANSI standard, and does not exist
2878 // on Solaris (and probably other non-Gnu flavored Unixes).
2880 /*-----------------------------------------------------------------*/
2881 /* SAFE_snprintf - like snprintf except the string pointer is */
2882 /* after the string has been printed to. This is */
2883 /* useful for printing to string as though if it */
2884 /* were a stream. */
2885 /*-----------------------------------------------------------------*/
2886 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2894 va_start(val, format);
2896 vsnprintf(*str, *size, format, val);
2902 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2903 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2912 // This version is *not* safe, despite the name.
2914 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2918 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2923 va_start(val, format);
2925 vsprintf(buffer, format, val);
2928 len = strlen(buffer);
2930 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2931 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2934 strcpy(*str, buffer);
2940 #endif // USE_VSNPRINTF
2943 extern set *externs;
2944 extern void pic16_initStack(int base_address, int size);
2945 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2946 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2947 extern void pic16_init_pic(char *);
2949 void pic16_pCodeInitRegisters(void)
2951 static int initialized=0;
2958 // pic16_initStack(0xfff, 8);
2959 pic16_init_pic(port->processor);
2961 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2962 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2963 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2964 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2965 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2966 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2967 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2969 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2970 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2971 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2973 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2974 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2975 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2976 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2978 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2979 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2980 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2981 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2982 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2983 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2985 pic16_stackpnt_lo = &pic16_pc_fsr1l;
2986 pic16_stackpnt_hi = &pic16_pc_fsr1h;
2987 pic16_stack_postdec = &pic16_pc_postdec1;
2988 pic16_stack_postinc = &pic16_pc_postinc1;
2989 pic16_stack_preinc = &pic16_pc_preinc1;
2990 pic16_stack_plusw = &pic16_pc_plusw1;
2992 pic16_framepnt_lo = &pic16_pc_fsr2l;
2993 pic16_framepnt_hi = &pic16_pc_fsr2h;
2994 pic16_frame_postdec = &pic16_pc_postdec2;
2995 pic16_frame_postinc = &pic16_pc_postinc2;
2996 pic16_frame_preinc = &pic16_pc_preinc2;
2997 pic16_frame_plusw = &pic16_pc_plusw2;
2999 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
3000 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
3001 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
3002 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
3003 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
3005 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
3006 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
3007 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
3008 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
3009 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
3011 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
3012 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
3013 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
3014 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
3015 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
3017 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
3018 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
3021 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
3022 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
3023 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
3024 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
3027 pic16_pc_status.rIdx = IDX_STATUS;
3028 pic16_pc_intcon.rIdx = IDX_INTCON;
3029 pic16_pc_pcl.rIdx = IDX_PCL;
3030 pic16_pc_pclath.rIdx = IDX_PCLATH;
3031 pic16_pc_pclatu.rIdx = IDX_PCLATU;
3032 pic16_pc_wreg.rIdx = IDX_WREG;
3033 pic16_pc_bsr.rIdx = IDX_BSR;
3035 pic16_pc_tosl.rIdx = IDX_TOSL;
3036 pic16_pc_tosh.rIdx = IDX_TOSH;
3037 pic16_pc_tosu.rIdx = IDX_TOSU;
3039 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
3040 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
3041 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
3042 pic16_pc_tablat.rIdx = IDX_TABLAT;
3044 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
3045 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
3046 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
3047 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
3048 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
3049 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
3050 pic16_pc_indf0.rIdx = IDX_INDF0;
3051 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
3052 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
3053 pic16_pc_preinc0.rIdx = IDX_PREINC0;
3054 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
3055 pic16_pc_indf1.rIdx = IDX_INDF1;
3056 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
3057 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
3058 pic16_pc_preinc1.rIdx = IDX_PREINC1;
3059 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
3060 pic16_pc_indf2.rIdx = IDX_INDF2;
3061 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
3062 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
3063 pic16_pc_preinc2.rIdx = IDX_PREINC2;
3064 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
3065 pic16_pc_prodl.rIdx = IDX_PRODL;
3066 pic16_pc_prodh.rIdx = IDX_PRODH;
3068 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
3069 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
3070 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
3072 pic16_pc_kzero.rIdx = IDX_KZ;
3073 pic16_pc_wsave.rIdx = IDX_WSAVE;
3074 pic16_pc_ssave.rIdx = IDX_SSAVE;
3076 pic16_pc_eecon1.rIdx = IDX_EECON1;
3077 pic16_pc_eecon2.rIdx = IDX_EECON2;
3078 pic16_pc_eedata.rIdx = IDX_EEDATA;
3079 pic16_pc_eeadr.rIdx = IDX_EEADR;
3082 pic16_pc_gpsimio.r = pic16_allocProcessorRegister(IDX_GPSIMIO, "GPSIMIO", PO_GPR_REGISTER, 0x80);
3083 pic16_pc_gpsimio2.r = pic16_allocProcessorRegister(IDX_GPSIMIO2, "GPSIMIO2", PO_GPR_REGISTER, 0x80);
3085 pic16_pc_gpsimio.rIdx = IDX_GPSIMIO;
3086 pic16_pc_gpsimio2.rIdx = IDX_GPSIMIO2;
3088 /* probably should put this in a separate initialization routine */
3089 pb_dead_pcodes = newpBlock();
3094 /*-----------------------------------------------------------------*/
3095 /* mnem2key - convert a pic mnemonic into a hash key */
3096 /* (BTW - this spreads the mnemonics quite well) */
3098 /*-----------------------------------------------------------------*/
3100 int mnem2key(char const *mnem)
3109 key += toupper(*mnem++) +1;
3113 return (key & 0x1f);
3118 void pic16initMnemonics(void)
3123 pCodeInstruction *pci;
3125 if(mnemonics_initialized)
3128 // NULL out the array before making the assignments
3129 // since we check the array contents below this initialization.
3131 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
3132 pic16Mnemonics[i] = NULL;
3135 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
3136 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
3137 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
3138 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
3139 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
3140 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
3141 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
3142 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
3143 pic16Mnemonics[POC_BC] = &pic16_pciBC;
3144 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
3145 pic16Mnemonics[POC_BN] = &pic16_pciBN;
3146 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
3147 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
3148 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
3149 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
3150 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
3151 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
3152 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
3153 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
3154 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
3155 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
3156 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
3157 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
3158 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
3159 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
3160 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
3161 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
3162 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
3163 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
3164 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
3165 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
3166 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
3167 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
3168 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
3169 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3170 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3171 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3172 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3173 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3174 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3175 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3176 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3177 pic16Mnemonics[POC_INFSNZW] = &pic16_pciINFSNZW;
3178 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3179 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3180 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3181 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3182 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3183 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3184 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3185 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3186 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3187 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3188 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3189 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3190 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3191 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3192 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3193 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3194 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3195 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3196 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3197 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3198 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3199 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3200 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3201 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3202 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3203 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3204 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3205 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3206 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3207 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3208 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3209 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3210 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3211 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3212 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3213 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3214 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3215 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3216 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3217 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3218 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3219 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3220 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3221 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3222 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3223 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3224 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3225 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3226 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3227 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3228 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3230 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3231 if(pic16Mnemonics[i])
3232 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3233 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3236 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3237 pci = hTabNextItem(pic16MnemonicsHash, &key);
3240 mnemonics_initialized = 1;
3243 int pic16_getpCodePeepCommand(char *cmd);
3245 int pic16_getpCode(char *mnem,unsigned dest)
3248 pCodeInstruction *pci;
3249 int key = mnem2key(mnem);
3251 if(!mnemonics_initialized)
3252 pic16initMnemonics();
3254 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3258 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3259 if((pci->num_ops <= 1)
3260 || (pci->isModReg == dest)
3262 || (pci->num_ops <= 2 && pci->isAccess)
3263 || (pci->num_ops <= 2 && pci->isFastCall)
3264 || (pci->num_ops <= 2 && pci->is2MemOp)
3265 || (pci->num_ops <= 2 && pci->is2LitOp) )
3269 pci = hTabNextItemWK (pic16MnemonicsHash);
3276 /*-----------------------------------------------------------------*
3277 * pic16initpCodePeepCommands
3279 *-----------------------------------------------------------------*/
3280 void pic16initpCodePeepCommands(void)
3288 hTabAddItem(&pic16pCodePeepCommandsHash,
3289 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3291 } while (peepCommands[i].cmd);
3293 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3296 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3297 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3302 /*-----------------------------------------------------------------
3305 *-----------------------------------------------------------------*/
3307 int pic16_getpCodePeepCommand(char *cmd)
3311 int key = mnem2key(cmd);
3314 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3317 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3318 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3322 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3329 static char getpBlock_dbName(pBlock *pb)
3335 return pb->cmemmap->dbName;
3339 void pic16_pBlockConvert2ISR(pBlock *pb)
3343 if(pb->cmemmap)pb->cmemmap = NULL;
3347 if(pic16_pcode_verbose)
3348 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3351 void pic16_pBlockConvert2Absolute(pBlock *pb)
3354 if(pb->cmemmap)pb->cmemmap = NULL;
3358 if(pic16_pcode_verbose)
3359 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3362 /*-----------------------------------------------------------------*/
3363 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3364 /* instances to the front of the doubly linked */
3365 /* list of pBlocks */
3366 /*-----------------------------------------------------------------*/
3368 void pic16_movepBlock2Head(char dbName)
3373 /* this can happen in sources without code,
3374 * only variable definitions */
3375 if(!the_pFile)return;
3377 pb = the_pFile->pbHead;
3381 if(getpBlock_dbName(pb) == dbName) {
3382 pBlock *pbn = pb->next;
3383 pb->next = the_pFile->pbHead;
3384 the_pFile->pbHead->prev = pb;
3385 the_pFile->pbHead = pb;
3388 pb->prev->next = pbn;
3390 // If the pBlock that we just moved was the last
3391 // one in the link of all of the pBlocks, then we
3392 // need to point the tail to the block just before
3393 // the one we moved.
3394 // Note: if pb->next is NULL, then pb must have
3395 // been the last pBlock in the chain.
3398 pbn->prev = pb->prev;
3400 the_pFile->pbTail = pb->prev;
3411 void pic16_copypCode(FILE *of, char dbName)
3415 if(!of || !the_pFile)
3418 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3419 if(getpBlock_dbName(pb) == dbName) {
3420 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3422 pic16_printpBlock(of,pb);
3427 void pic16_pcode_test(void)
3430 DFPRINTF((stderr,"pcode is alive!\n"));
3440 /* create the file name */
3441 strcpy(buffer,dstFileName);
3442 strcat(buffer,".p");
3444 if( !(pFile = fopen(buffer, "w" ))) {
3445 werror(E_FILE_OPEN_ERR,buffer);
3449 fprintf(pFile,"pcode dump\n\n");
3451 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3452 fprintf(pFile,"\n\tNew pBlock\n\n");
3454 fprintf(pFile,"%s",pb->cmemmap->sname);
3456 fprintf(pFile,"internal pblock");
3458 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3459 pic16_printpBlock(pFile,pb);
3465 unsigned long pic16_countInstructions(void)
3469 unsigned long isize=0;
3471 if(!the_pFile)return -1;
3473 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3474 for(pc = pb->pcHead; pc; pc = pc->next) {
3475 if(isPCI(pc) || isPCAD(pc))isize += PCI(pc)->isize;
3482 /*-----------------------------------------------------------------*/
3483 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3484 /* ister, RegCond will return the bit being referenced. */
3486 /* fixme - why not just OR in the pcop bit field */
3487 /*-----------------------------------------------------------------*/
3489 static int RegCond(pCodeOp *pcop)
3495 if(!pcop->name)return 0;
3497 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3498 switch(PCORB(pcop)->bit) {
3512 /*-----------------------------------------------------------------*/
3513 /* pic16_newpCode - create and return a newly initialized pCode */
3515 /* fixme - rename this */
3517 /* The purpose of this routine is to create a new Instruction */
3518 /* pCode. This is called by gen.c while the assembly code is being */
3522 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3523 /* (note that the op is analogous to but not the */
3524 /* same thing as the opcode of the instruction.) */
3525 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3528 /* a pointer to the new malloc'd pCode is returned. */
3532 /*-----------------------------------------------------------------*/
3533 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3535 pCodeInstruction *pci ;
3537 if(!mnemonics_initialized)
3538 pic16initMnemonics();
3540 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3542 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3543 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3546 if(pci->inCond & PCC_EXAMINE_PCOP)
3547 pci->inCond |= RegCond(pcop);
3549 if(pci->outCond & PCC_EXAMINE_PCOP)
3550 pci->outCond |= RegCond(pcop);
3552 pci->pc.prev = pci->pc.next = NULL;
3553 return (pCode *)pci;
3556 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3562 /*-----------------------------------------------------------------*/
3563 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3565 /* Wild pcodes are used during the peep hole optimizer to serve */
3566 /* as place holders for any instruction. When a snippet of code is */
3567 /* compared to a peep hole rule, the wild card opcode will match */
3568 /* any instruction. However, the optional operand and label are */
3569 /* additional qualifiers that must also be matched before the */
3570 /* line (of assembly code) is declared matched. Note that the */
3571 /* operand may be wild too. */
3573 /* Note, a wild instruction is specified just like a wild var: */
3574 /* %4 ; A wild instruction, */
3575 /* See the peeph.def file for additional examples */
3577 /*-----------------------------------------------------------------*/
3579 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3584 pcw = Safe_calloc(1,sizeof(pCodeWild));
3586 pcw->pci.pc.type = PC_WILD;
3587 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3588 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3589 pcw->pci.pc.pb = NULL;
3591 // pcw->pci.pc.analyze = genericAnalyze;
3592 pcw->pci.pc.destruct = genericDestruct;
3593 pcw->pci.pc.print = genericPrint;
3595 pcw->id = pCodeID; // this is the 'n' in %n
3596 pcw->operand = optional_operand;
3597 pcw->label = optional_label;
3599 pcw->mustBeBitSkipInst = 0;
3600 pcw->mustNotBeBitSkipInst = 0;
3601 pcw->invertBitSkipInst = 0;
3603 return ( (pCode *)pcw);
3607 /*-----------------------------------------------------------------*/
3608 /* newPcodeInlineP - create a new pCode from a char string */
3609 /*-----------------------------------------------------------------*/
3612 pCode *pic16_newpCodeInlineP(char *cP)
3617 pcc = Safe_calloc(1,sizeof(pCodeComment));
3619 pcc->pc.type = PC_INLINE;
3620 pcc->pc.prev = pcc->pc.next = NULL;
3621 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3624 // pcc->pc.analyze = genericAnalyze;
3625 pcc->pc.destruct = genericDestruct;
3626 pcc->pc.print = genericPrint;
3629 pcc->comment = Safe_strdup(cP);
3631 pcc->comment = NULL;
3633 return ( (pCode *)pcc);
3637 /*-----------------------------------------------------------------*/
3638 /* newPcodeCharP - create a new pCode from a char string */
3639 /*-----------------------------------------------------------------*/
3641 pCode *pic16_newpCodeCharP(char *cP)
3646 pcc = Safe_calloc(1,sizeof(pCodeComment));
3648 pcc->pc.type = PC_COMMENT;
3649 pcc->pc.prev = pcc->pc.next = NULL;
3650 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3653 // pcc->pc.analyze = genericAnalyze;
3654 pcc->pc.destruct = genericDestruct;
3655 pcc->pc.print = genericPrint;
3658 pcc->comment = Safe_strdup(cP);
3660 pcc->comment = NULL;
3662 return ( (pCode *)pcc);
3666 /*-----------------------------------------------------------------*/
3667 /* pic16_newpCodeFunction - */
3668 /*-----------------------------------------------------------------*/
3671 pCode *pic16_newpCodeFunction(char *mod,char *f)
3675 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3677 pcf->pc.type = PC_FUNCTION;
3678 pcf->pc.prev = pcf->pc.next = NULL;
3679 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3682 // pcf->pc.analyze = genericAnalyze;
3683 pcf->pc.destruct = genericDestruct;
3684 pcf->pc.print = pCodePrintFunction;
3690 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3691 strcpy(pcf->modname,mod);
3693 pcf->modname = NULL;
3696 pcf->fname = Safe_calloc(1,strlen(f)+1);
3697 strcpy(pcf->fname,f);
3701 pcf->stackusage = 0;
3703 return ( (pCode *)pcf);
3706 /*-----------------------------------------------------------------*/
3707 /* pic16_newpCodeFlow */
3708 /*-----------------------------------------------------------------*/
3709 static void destructpCodeFlow(pCode *pc)
3711 if(!pc || !isPCFL(pc))
3718 pic16_unlinkpCode(pc);
3720 deleteSet(&PCFL(pc)->registers);
3721 deleteSet(&PCFL(pc)->from);
3722 deleteSet(&PCFL(pc)->to);
3724 /* Instead of deleting the memory used by this pCode, mark
3725 * the object as bad so that if there's a pointer to this pCode
3726 * dangling around somewhere then (hopefully) when the type is
3727 * checked we'll catch it.
3731 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3737 pCode *pic16_newpCodeFlow(void )
3741 //_ALLOC(pcflow,sizeof(pCodeFlow));
3742 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3744 pcflow->pc.type = PC_FLOW;
3745 pcflow->pc.prev = pcflow->pc.next = NULL;
3746 pcflow->pc.pb = NULL;
3748 // pcflow->pc.analyze = genericAnalyze;
3749 pcflow->pc.destruct = destructpCodeFlow;
3750 pcflow->pc.print = genericPrint;
3752 pcflow->pc.seq = GpcFlowSeq++;
3754 pcflow->from = pcflow->to = NULL;
3756 pcflow->inCond = PCC_NONE;
3757 pcflow->outCond = PCC_NONE;
3759 pcflow->firstBank = -1;
3760 pcflow->lastBank = -1;
3762 pcflow->FromConflicts = 0;
3763 pcflow->ToConflicts = 0;
3767 pcflow->registers = newSet();
3769 return ( (pCode *)pcflow);
3773 /*-----------------------------------------------------------------*/
3774 /*-----------------------------------------------------------------*/
3775 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3777 pCodeFlowLink *pcflowLink;
3779 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3781 pcflowLink->pcflow = pcflow;
3782 pcflowLink->bank_conflict = 0;
3787 /*-----------------------------------------------------------------*/
3788 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3789 /*-----------------------------------------------------------------*/
3791 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3796 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3798 pccs->pc.type = PC_CSOURCE;
3799 pccs->pc.prev = pccs->pc.next = NULL;
3802 pccs->pc.destruct = genericDestruct;
3803 pccs->pc.print = genericPrint;
3805 pccs->line_number = ln;
3807 pccs->line = Safe_strdup(l);
3812 pccs->file_name = Safe_strdup(f);
3814 pccs->file_name = NULL;
3816 return ( (pCode *)pccs);
3821 /*******************************************************************/
3822 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3823 /* added by VR 6-Jun-2003 */
3824 /*******************************************************************/
3826 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3833 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3834 pcad->pci.pc.type = PC_ASMDIR;
3835 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3836 pcad->pci.pc.pb = NULL;
3837 pcad->pci.isize = 2;
3838 pcad->pci.pc.destruct = genericDestruct;
3839 pcad->pci.pc.print = genericPrint;
3841 if(asdir && *asdir) {
3843 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3845 pcad->directive = Safe_strdup( asdir );
3848 va_start(ap, argfmt);
3850 memset(buffer, 0, sizeof(buffer));
3851 if(argfmt && *argfmt)
3852 vsprintf(buffer, argfmt, ap);
3856 while(isspace(*lbp))lbp++;
3859 pcad->arg = Safe_strdup( lbp );
3861 return ((pCode *)pcad);
3864 /*-----------------------------------------------------------------*/
3865 /* pCodeLabelDestruct - free memory used by a label. */
3866 /*-----------------------------------------------------------------*/
3867 static void pCodeLabelDestruct(pCode *pc)
3873 // if((pc->type == PC_LABEL) && PCL(pc)->label)
3874 // Safe_free(PCL(pc)->label);
3876 /* Instead of deleting the memory used by this pCode, mark
3877 * the object as bad so that if there's a pointer to this pCode
3878 * dangling around somewhere then (hopefully) when the type is
3879 * checked we'll catch it.
3883 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3889 pCode *pic16_newpCodeLabel(char *name, int key)
3895 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3897 pcl->pc.type = PC_LABEL;
3898 pcl->pc.prev = pcl->pc.next = NULL;
3899 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3902 // pcl->pc.analyze = genericAnalyze;
3903 pcl->pc.destruct = pCodeLabelDestruct;
3904 pcl->pc.print = pCodePrintLabel;
3911 sprintf(s,"_%05d_DS_",key);
3916 pcl->label = Safe_strdup(s);
3918 // if(pic16_pcode_verbose)
3919 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3922 return ( (pCode *)pcl);
3926 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3928 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3932 return ( (pCode *)pcl );
3935 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3939 pci = Safe_calloc(1, sizeof(pCodeInfo));
3940 pci->pci.pc.type = PC_INFO;
3941 pci->pci.pc.prev = pci->pci.pc.next = NULL;
3942 pci->pci.pc.pb = NULL;
3943 pci->pci.label = NULL;
3945 pci->pci.pc.destruct = genericDestruct;
3946 pci->pci.pc.print = genericPrint;
3951 return ((pCode *)pci);
3955 /*-----------------------------------------------------------------*/
3956 /* newpBlock - create and return a pointer to a new pBlock */
3957 /*-----------------------------------------------------------------*/
3958 static pBlock *newpBlock(void)
3963 PpB = Safe_calloc(1,sizeof(pBlock) );
3964 PpB->next = PpB->prev = NULL;
3966 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3967 PpB->tregisters = NULL;
3969 PpB->FlowTree = NULL;
3975 /*-----------------------------------------------------------------*/
3976 /* pic16_newpCodeChain - create a new chain of pCodes */
3977 /*-----------------------------------------------------------------*
3979 * This function will create a new pBlock and the pointer to the
3980 * pCode that is passed in will be the first pCode in the block.
3981 *-----------------------------------------------------------------*/
3984 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3987 pBlock *pB = newpBlock();
3989 pB->pcHead = pB->pcTail = pc;
3998 /*-----------------------------------------------------------------*/
3999 /* pic16_newpCodeOpLabel - Create a new label given the key */
4000 /* Note, a negative key means that the label is part of wild card */
4001 /* (and hence a wild card label) used in the pCodePeep */
4002 /* optimizations). */
4003 /*-----------------------------------------------------------------*/
4005 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
4008 static int label_key=-1;
4012 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
4013 pcop->type = PO_LABEL;
4018 sprintf(s=buffer,"_%05d_DS_",key);
4020 s = name, key = label_key--;
4023 pcop->name = Safe_strdup(s);
4025 ((pCodeOpLabel *)pcop)->key = key;
4027 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4031 /*-----------------------------------------------------------------*/
4032 /*-----------------------------------------------------------------*/
4033 pCodeOp *pic16_newpCodeOpLit(int lit)
4039 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
4040 pcop->type = PO_LITERAL;
4044 sprintf(s,"0x%02hhx", (unsigned char)lit);
4046 // sprintf(s, "%i", lit);
4049 pcop->name = Safe_strdup(s);
4051 ((pCodeOpLit *)pcop)->lit = lit;
4056 /*-----------------------------------------------------------------*/
4057 /*-----------------------------------------------------------------*/
4058 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
4060 char *s = buffer, tbuf[256], *tb=tbuf;
4064 tb = pic16_get_op(arg2, NULL, 0);
4065 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
4066 pcop->type = PO_LITERAL;
4070 sprintf(s,"0x%02x, %s", (unsigned char)lit, tb);
4072 pcop->name = Safe_strdup(s);
4075 ((pCodeOpLit2 *)pcop)->lit = lit;
4076 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
4081 /*-----------------------------------------------------------------*/
4082 /*-----------------------------------------------------------------*/
4083 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
4087 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
4088 pcop->type = PO_IMMEDIATE;
4090 regs *r = pic16_dirregWithName(name);
4091 pcop->name = Safe_strdup(name);
4095 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
4096 PCOI(pcop)->rIdx = r->rIdx;
4098 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
4099 PCOI(pcop)->rIdx = -1;
4101 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
4106 PCOI(pcop)->index = index;
4107 PCOI(pcop)->offset = offset;
4108 PCOI(pcop)->_const = code_space;
4113 /*-----------------------------------------------------------------*/
4114 /*-----------------------------------------------------------------*/
4115 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
4121 if(!pcwb || !subtype) {
4122 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4126 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4127 pcop->type = PO_WILD;
4128 sprintf(s,"%%%d",id);
4129 pcop->name = Safe_strdup(s);
4131 PCOW(pcop)->id = id;
4132 PCOW(pcop)->pcwb = pcwb;
4133 PCOW(pcop)->subtype = subtype;
4134 PCOW(pcop)->matched = NULL;
4136 PCOW(pcop)->pcop2 = NULL;
4141 /*-----------------------------------------------------------------*/
4142 /*-----------------------------------------------------------------*/
4143 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
4149 if(!pcwb || !subtype || !subtype2) {
4150 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4154 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4155 pcop->type = PO_WILD;
4156 sprintf(s,"%%%d",id);
4157 pcop->name = Safe_strdup(s);
4159 PCOW(pcop)->id = id;
4160 PCOW(pcop)->pcwb = pcwb;
4161 PCOW(pcop)->subtype = subtype;
4162 PCOW(pcop)->matched = NULL;
4164 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4166 if(!subtype2->name) {
4167 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4168 PCOW2(pcop)->pcop.type = PO_WILD;
4169 sprintf(s, "%%%d", id2);
4170 PCOW2(pcop)->pcop.name = Safe_strdup(s);
4171 PCOW2(pcop)->id = id2;
4172 PCOW2(pcop)->subtype = subtype2;
4174 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4175 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4177 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4179 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4180 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4189 /*-----------------------------------------------------------------*/
4190 /*-----------------------------------------------------------------*/
4191 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4195 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4196 pcop->type = PO_GPR_BIT;
4198 pcop->name = Safe_strdup(s);
4202 PCORB(pcop)->bit = bit;
4203 PCORB(pcop)->inBitSpace = inBitSpace;
4204 PCORB(pcop)->subtype = subt;
4206 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4207 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4208 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4209 // PCOR(pcop)->rIdx = 0;
4214 /*-----------------------------------------------------------------*
4215 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4217 * If rIdx >=0 then a specific register from the set of registers
4218 * will be selected. If rIdx <0, then a new register will be searched
4220 *-----------------------------------------------------------------*/
4222 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4226 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4231 PCOR(pcop)->rIdx = rIdx;
4232 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4234 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4237 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4239 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4240 __FUNCTION__, __LINE__);
4245 pcop->type = PCOR(pcop)->r->pc_type;
4250 pCodeOp *pic16_newpCodeOpRegNotVect(bitVect *bv)
4255 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
4258 r = pic16_findFreeReg(REG_GPR);
4261 if(!bitVectBitValue(bv, r->rIdx)) {
4263 PCOR(pcop)->rIdx = r->rIdx;
4264 pcop->type = r->pc_type;
4268 r = pic16_findFreeRegNext(REG_GPR, r);
4276 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4281 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4282 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4283 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4284 pcop->type = PCOR(pcop)->r->pc_type;
4285 pcop->name = PCOR(pcop)->r->name;
4287 // if(pic16_pcode_verbose) {
4288 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4289 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4295 /*-----------------------------------------------------------------*/
4296 /*-----------------------------------------------------------------*/
4297 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4301 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4304 pcop->key = Safe_strdup( key );
4306 return (PCOP(pcop));
4309 /*-----------------------------------------------------------------*/
4310 /*-----------------------------------------------------------------*/
4311 pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type)
4313 pCodeOpLocalReg *pcop;
4315 pcop = Safe_calloc(1, sizeof(pCodeOpLocalReg));
4319 return (PCOP(pcop));
4323 /*-----------------------------------------------------------------*/
4324 /*-----------------------------------------------------------------*/
4326 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4333 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4337 pcop = pic16_newpCodeOpLit(-1);
4341 pcop = pic16_newpCodeOpLabel(NULL,-1);
4344 pcop = pic16_newpCodeOpReg(-1);
4347 case PO_GPR_REGISTER:
4349 pcop = pic16_newpCodeOpRegFromStr(name);
4351 pcop = pic16_newpCodeOpReg(-1);
4355 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4358 pcop->name = Safe_strdup(name);
4366 #define DB_ITEMS_PER_LINE 8
4368 typedef struct DBdata
4375 static int DBd_init = -1;
4377 /*-----------------------------------------------------------------*/
4378 /* Initialiase "DB" data buffer */
4379 /*-----------------------------------------------------------------*/
4380 void pic16_initDB(void)
4386 /*-----------------------------------------------------------------*/
4387 /* Flush pending "DB" data to a pBlock */
4389 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4390 /*-----------------------------------------------------------------*/
4391 void pic16_flushDB(char ptype, void *p)
4395 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4398 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4401 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4405 DBd.buffer[0] = '\0';
4410 /*-----------------------------------------------------------------*/
4411 /* Add "DB" directives to a pBlock */
4412 /*-----------------------------------------------------------------*/
4413 void pic16_emitDB(char c, char ptype, void *p)
4418 // we need to initialize
4421 DBd.buffer[0] = '\0';
4424 l = strlen(DBd.buffer);
4425 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4427 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4430 if (DBd.count>= DB_ITEMS_PER_LINE)
4431 pic16_flushDB(ptype, p);
4434 void pic16_emitDS(char *s, char ptype, void *p)
4439 // we need to initialize
4442 DBd.buffer[0] = '\0';
4445 l = strlen(DBd.buffer);
4446 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4448 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4450 DBd.count++; //=strlen(s);
4452 pic16_flushDB(ptype, p);
4456 /*-----------------------------------------------------------------*/
4457 /*-----------------------------------------------------------------*/
4458 void pic16_pCodeConstString(char *name, char *value)
4462 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4467 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4469 pic16_addpBlock(pb);
4471 // sprintf(buffer,"; %s = ", name);
4472 // strcat(buffer, value);
4473 // fputs(buffer, stderr);
4475 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4476 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4479 pic16_emitDB(*value, 'p', (void *)pb);
4481 pic16_flushDB('p', (void *)pb);
4484 /*-----------------------------------------------------------------*/
4485 /*-----------------------------------------------------------------*/
4487 static void pCodeReadCodeTable(void)
4491 fprintf(stderr, " %s\n",__FUNCTION__);
4493 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4495 pic16_addpBlock(pb);
4497 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4498 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4499 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4500 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4502 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4503 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4504 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4505 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4510 /*-----------------------------------------------------------------*/
4511 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4512 /*-----------------------------------------------------------------*/
4513 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4520 /* If this is the first pcode to be added to a block that
4521 * was initialized with a NULL pcode, then go ahead and
4522 * make this pcode the head and tail */
4523 pb->pcHead = pb->pcTail = pc;
4526 pb->pcTail->next = pc;
4528 pc->prev = pb->pcTail;
4535 /*-----------------------------------------------------------------*/
4536 /* pic16_addpBlock - place a pBlock into the pFile */
4537 /*-----------------------------------------------------------------*/
4538 void pic16_addpBlock(pBlock *pb)
4540 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4543 /* First time called, we'll pass through here. */
4544 //_ALLOC(the_pFile,sizeof(pFile));
4545 the_pFile = Safe_calloc(1,sizeof(pFile));
4546 the_pFile->pbHead = the_pFile->pbTail = pb;
4547 the_pFile->functions = NULL;
4551 the_pFile->pbTail->next = pb;
4552 pb->prev = the_pFile->pbTail;
4554 the_pFile->pbTail = pb;
4557 /*-----------------------------------------------------------------*/
4558 /* removepBlock - remove a pBlock from the pFile */
4559 /*-----------------------------------------------------------------*/
4560 static void removepBlock(pBlock *pb)
4568 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4570 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4573 if(pbs == the_pFile->pbHead)
4574 the_pFile->pbHead = pbs->next;
4576 if (pbs == the_pFile->pbTail)
4577 the_pFile->pbTail = pbs->prev;
4580 pbs->next->prev = pbs->prev;
4583 pbs->prev->next = pbs->next;
4590 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4594 /*-----------------------------------------------------------------*/
4595 /* printpCode - write the contents of a pCode to a file */
4596 /*-----------------------------------------------------------------*/
4597 static void printpCode(FILE *of, pCode *pc)
4608 fprintf(of,"warning - unable to print pCode\n");
4611 /*-----------------------------------------------------------------*/
4612 /* pic16_printpBlock - write the contents of a pBlock to a file */
4613 /*-----------------------------------------------------------------*/
4614 void pic16_printpBlock(FILE *of, pBlock *pb)
4622 for(pc = pb->pcHead; pc; pc = pc->next) {
4623 if(isPCF(pc) && PCF(pc)->fname) {
4624 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4625 if(pb->dbName == 'A') {
4627 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4628 // fprintf(stderr, "%s:%d testing %s <-> %s\n", __FILE__, __LINE__, PCF(pc)->fname, ab->name);
4629 if(!strcmp(ab->name, PCF(pc)->fname)) {
4630 // fprintf(stderr, "%s:%d address = %x\n", __FILE__, __LINE__, ab->address);
4631 if(ab->address != -1)
4632 fprintf(of, "\t0X%06X", ab->address);
4643 /*-----------------------------------------------------------------*/
4645 /* pCode processing */
4649 /*-----------------------------------------------------------------*/
4651 void pic16_unlinkpCode(pCode *pc)
4657 fprintf(stderr,"Unlinking: ");
4658 printpCode(stderr, pc);
4661 pc->prev->next = pc->next;
4663 pc->next->prev = pc->prev;
4665 pc->prev = pc->next = NULL;
4669 /*-----------------------------------------------------------------*/
4670 /*-----------------------------------------------------------------*/
4672 static void genericDestruct(pCode *pc)
4675 pic16_unlinkpCode(pc);
4678 /* For instructions, tell the register (if there's one used)
4679 * that it's no longer needed */
4680 regs *reg = pic16_getRegFromInstruction(pc);
4682 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4684 if(PCI(pc)->is2MemOp) {
4685 reg = pic16_getRegFromInstruction2(pc);
4687 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4691 /* Instead of deleting the memory used by this pCode, mark
4692 * the object as bad so that if there's a pointer to this pCode
4693 * dangling around somewhere then (hopefully) when the type is
4694 * checked we'll catch it.
4698 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4704 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4705 /*-----------------------------------------------------------------*/
4706 /*-----------------------------------------------------------------*/
4707 /* modifiers for constant immediate */
4708 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4710 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4715 int use_buffer = 1; // copy the string to the passed buffer pointer
4720 use_buffer = 0; // Don't bother copying the string to the buffer.
4724 switch(pcop->type) {
4732 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4735 return PCOR(pcop)->r->name;
4738 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4740 SAFE_snprintf(&buffer,&size,"%s",r->name);
4747 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4748 if(PCOI(pcop)->index) {
4749 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4750 immdmod[ PCOI(pcop)->offset ],
4754 SAFE_snprintf(&s,&size,"%s(%s)",
4755 immdmod[ PCOI(pcop)->offset ],
4759 if(PCOI(pcop)->index) {
4760 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4765 SAFE_snprintf(&s,&size, "%s(%s)",
4772 case PO_GPR_REGISTER:
4775 // size = sizeof(buffer);
4776 if( PCOR(pcop)->instance) {
4777 SAFE_snprintf(&s,&size,"(%s + %d)",
4779 PCOR(pcop)->instance );
4781 SAFE_snprintf(&s,&size,"%s",pcop->name);
4786 if(PCORB(pcop)->subtype == PO_GPR_TEMP) {
4787 SAFE_snprintf(&s, &size, "%s", pcop->name);
4789 if(PCORB(pcop)->pcor.instance)
4790 SAFE_snprintf(&s, &size, "(%s + %d)", pcop->name, PCORB(pcop)->pcor.instance);
4792 SAFE_snprintf(&s, &size, "%s", pcop->name);
4799 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4808 return "NO operand1";
4811 /*-----------------------------------------------------------------*/
4812 /* pic16_get_op2 - variant to support two memory operand commands */
4813 /*-----------------------------------------------------------------*/
4814 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4819 int use_buffer = 1; // copy the string to the passed buffer pointer
4824 use_buffer = 0; // Don't bother copying the string to the buffer.
4828 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",
4829 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4830 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4834 switch(PCOR2(pcop)->pcop2->type) {
4842 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4845 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4848 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4851 SAFE_snprintf(&buffer,&size,"%s",r->name);
4862 if(PCOI(pcop)->_const) {
4863 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4864 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4867 8 * PCOI(pcop)->offset );
4869 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4871 if( PCOI(pcop)->index) {
4872 SAFE_snprintf(&s,&size,"(%s + %d)",
4874 PCOI(pcop)->index );
4876 if(PCOI(pcop)->offset)
4877 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4879 SAFE_snprintf(&s,&size,"%s",pcop->name);
4886 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4887 SAFE_snprintf(&s,&size,"(%s + %d)",
4888 PCOR(PCOR2(pcop)->pcop2)->r->name,
4889 PCOR(PCOR2(pcop)->pcop2)->instance );
4891 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4896 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4898 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4901 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4906 return "NO operand2";
4909 /*-----------------------------------------------------------------*/
4910 /*-----------------------------------------------------------------*/
4911 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4915 return pic16_get_op(pcc->pcop,NULL,0);
4917 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4918 * return ("ERROR Null: "__FUNCTION__);
4920 return ("ERROR Null: pic16_get_op_from_instruction");
4924 /*-----------------------------------------------------------------*/
4925 /*-----------------------------------------------------------------*/
4926 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4929 fprintf(of,"pcodeopprint- not implemented\n");
4932 /*-----------------------------------------------------------------*/
4933 /* pic16_pCode2str - convert a pCode instruction to string */
4934 /*-----------------------------------------------------------------*/
4935 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4941 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4942 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4943 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4951 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4953 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4955 if(PCI(pc)->is2MemOp) {
4956 SAFE_snprintf(&s,&size, "%s, %s",
4957 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4958 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4962 if(PCI(pc)->is2LitOp) {
4963 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4967 if(PCI(pc)->isBitInst) {
4968 if(PCI(pc)->pcop->type != PO_GPR_BIT) {
4969 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4970 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4971 PCI(pc)->pcop->name ,
4972 PCI(pc)->pcop->name );
4974 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4975 // (((pCodeOpRegBit *)(PCI(pc)->pcop))->pcor.instance),
4976 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4978 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4979 SAFE_snprintf(&s,&size,"%s, %d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4981 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4982 //PCI(pc)->pcop->t.bit );
4985 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4986 if( PCI(pc)->num_ops == 3)
4987 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4989 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4994 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4997 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4998 if(PCI(pc)->num_ops == 3 && !PCI(pc)->isBitInst)
4999 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
5001 r = pic16_getRegFromInstruction(pc);
5002 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
5003 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
5005 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
5013 /* assuming that comment ends with a \n */
5014 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
5018 SAFE_snprintf(&s,&size,"; info ==>");
5019 switch( PCINF(pc)->type ) {
5020 case INF_OPTIMIZATION:
5021 SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
5024 SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5029 /* assuming that inline code ends with a \n */
5030 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
5034 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
5037 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
5040 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
5043 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
5046 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5047 SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5048 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5051 if(PCAD(pc)->directive) {
5052 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5055 /* special case to handle inline labels without a tab */
5056 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
5061 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
5069 /*-----------------------------------------------------------------*/
5070 /* genericPrint - the contents of a pCode to a file */
5071 /*-----------------------------------------------------------------*/
5072 static void genericPrint(FILE *of, pCode *pc)
5080 // fputs(((pCodeComment *)pc)->comment, of);
5081 fprintf(of,"; %s\n", ((pCodeComment *)pc)->comment);
5086 pBranch *pbl = PCI(pc)->label;
5087 while(pbl && pbl->pc) {
5088 if(pbl->pc->type == PC_LABEL)
5089 pCodePrintLabel(of, pbl->pc);
5094 if(pic16_pcode_verbose) {
5095 fprintf(of, "; info ==>");
5096 switch(((pCodeInfo *)pc)->type) {
5097 case INF_OPTIMIZATION:
5098 fprintf(of, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
5101 fprintf(of, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5109 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
5113 // If the opcode has a label, print that first
5115 pBranch *pbl = PCI(pc)->label;
5116 while(pbl && pbl->pc) {
5117 if(pbl->pc->type == PC_LABEL)
5118 pCodePrintLabel(of, pbl->pc);
5124 genericPrint(of,PCODE(PCI(pc)->cline));
5129 pic16_pCode2str(str, 256, pc);
5131 fprintf(of,"%s",str);
5133 if(pic16_debug_verbose) {
5134 fprintf(of, "\t;key=%03x",pc->seq);
5136 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
5143 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
5144 if(PCW(pc)->pci.label)
5145 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
5147 if(PCW(pc)->operand) {
5148 fprintf(of,";\toperand ");
5149 pCodeOpPrint(of,PCW(pc)->operand );
5154 if(pic16_debug_verbose) {
5155 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
5156 if(PCFL(pc)->ancestor)
5157 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
5164 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5165 fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5166 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5172 pBranch *pbl = PCAD(pc)->pci.label;
5173 while(pbl && pbl->pc) {
5174 if(pbl->pc->type == PC_LABEL)
5175 pCodePrintLabel(of, pbl->pc);
5179 if(PCAD(pc)->directive) {
5180 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5183 /* special case to handle inline labels without tab */
5184 fprintf(of, "%s\n", PCAD(pc)->arg);
5190 fprintf(of,"unknown pCode type %d\n",pc->type);
5195 /*-----------------------------------------------------------------*/
5196 /* pCodePrintFunction - prints function begin/end */
5197 /*-----------------------------------------------------------------*/
5199 static void pCodePrintFunction(FILE *of, pCode *pc)
5206 if( ((pCodeFunction *)pc)->modname)
5207 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
5210 if(!PCF(pc)->absblock) {
5211 if(PCF(pc)->fname) {
5212 pBranch *exits = PCF(pc)->to;
5215 fprintf(of,"%s:", PCF(pc)->fname);
5217 if(pic16_pcode_verbose)
5218 fprintf(of, "\t;Function start");
5224 exits = exits->next;
5228 if(pic16_pcode_verbose)
5229 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
5232 if((PCF(pc)->from &&
5233 PCF(pc)->from->pc->type == PC_FUNCTION &&
5234 PCF(PCF(pc)->from->pc)->fname) ) {
5236 if(pic16_pcode_verbose)
5237 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
5239 if(pic16_pcode_verbose)
5240 fprintf(of,"; exit point [can't find entry point]\n");
5246 /*-----------------------------------------------------------------*/
5247 /* pCodePrintLabel - prints label */
5248 /*-----------------------------------------------------------------*/
5250 static void pCodePrintLabel(FILE *of, pCode *pc)
5257 fprintf(of,"%s:\n",PCL(pc)->label);
5258 else if (PCL(pc)->key >=0)
5259 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5261 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5264 /*-----------------------------------------------------------------*/
5265 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
5266 /* remove it if it is found. */
5267 /*-----------------------------------------------------------------*/
5268 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5275 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
5276 b = PCI(pcl)->label;
5278 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5283 //fprintf (stderr, "%s \n",__FUNCTION__);
5284 //pcl->print(stderr,pcl);
5285 //pc->print(stderr,pc);
5288 //fprintf (stderr, "found label\n");
5289 //pc->print(stderr, pc);
5293 bprev->next = b->next; /* Not first pCode in chain */
5297 PCI(pcl)->label = b->next; /* First pCode in chain */
5300 return; /* A label can't occur more than once */
5308 /*-----------------------------------------------------------------*/
5309 /*-----------------------------------------------------------------*/
5310 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5329 /*-----------------------------------------------------------------*/
5330 /* pBranchLink - given two pcodes, this function will link them */
5331 /* together through their pBranches */
5332 /*-----------------------------------------------------------------*/
5333 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5337 // Declare a new branch object for the 'from' pCode.
5339 //_ALLOC(b,sizeof(pBranch));
5340 b = Safe_calloc(1,sizeof(pBranch));
5341 b->pc = PCODE(t); // The link to the 'to' pCode.
5344 f->to = pic16_pBranchAppend(f->to,b);
5346 // Now do the same for the 'to' pCode.
5348 //_ALLOC(b,sizeof(pBranch));
5349 b = Safe_calloc(1,sizeof(pBranch));
5353 t->from = pic16_pBranchAppend(t->from,b);
5358 /*-----------------------------------------------------------------*/
5359 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5361 /*-----------------------------------------------------------------*/
5362 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5375 /*-----------------------------------------------------------------*/
5376 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5377 /*-----------------------------------------------------------------*/
5378 void pic16_pCodeUnlink(pCode *pc)
5383 if(!pc->prev || !pc->next) {
5384 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5388 /* first remove the pCode from the chain */
5389 pc->prev->next = pc->next;
5390 pc->next->prev = pc->prev;
5392 /* Now for the hard part... */
5394 /* Remove the branches */
5396 pb1 = PCI(pc)->from;
5398 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5399 * one we're unlinking */
5401 /* search for the link back to this pCode (the one we're
5403 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5404 pb2->pc = PCI(pc)->to->pc; // make the replacement
5406 /* if the pCode we're unlinking contains multiple 'to'
5407 * branches (e.g. this a skip instruction) then we need
5408 * to copy these extra branches to the chain. */
5409 if(PCI(pc)->to->next)
5410 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5419 /*-----------------------------------------------------------------*/
5420 /*-----------------------------------------------------------------*/
5422 static void genericAnalyze(pCode *pc)
5432 // Go through the pCodes that are in pCode chain and link
5433 // them together through the pBranches. Note, the pCodes
5434 // are linked together as a contiguous stream like the
5435 // assembly source code lines. The linking here mimics this
5436 // except that comments are not linked in.
5438 pCode *npc = pc->next;
5440 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5441 pBranchLink(pc,npc);
5446 /* reached the end of the pcode chain without finding
5447 * an instruction we could link to. */
5451 fprintf(stderr,"analyze PC_FLOW\n");
5455 fprintf(stderr,,";A bad pCode is being used\n");
5461 /*-----------------------------------------------------------------*/
5462 /*-----------------------------------------------------------------*/
5463 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5467 if(pc->type == PC_LABEL) {
5468 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5471 if((pc->type == PC_OPCODE)
5472 || (pc->type == PC_ASMDIR)
5474 pbr = PCI(pc)->label;
5476 if(pbr->pc->type == PC_LABEL) {
5477 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5487 /*-----------------------------------------------------------------*/
5488 /*-----------------------------------------------------------------*/
5489 static int checkLabel(pCode *pc)
5493 if(pc && isPCI(pc)) {
5494 pbr = PCI(pc)->label;
5496 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5506 /*-----------------------------------------------------------------*/
5507 /* findLabelinpBlock - Search the pCode for a particular label */
5508 /*-----------------------------------------------------------------*/
5509 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5516 for(pc = pb->pcHead; pc; pc = pc->next)
5517 if(compareLabel(pc,pcop_label))
5523 /*-----------------------------------------------------------------*/
5524 /* findLabel - Search the pCode for a particular label */
5525 /*-----------------------------------------------------------------*/
5526 static pCode * findLabel(pCodeOpLabel *pcop_label)
5534 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5535 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5539 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5543 /*-----------------------------------------------------------------*/
5544 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5545 /* in the linked list */
5546 /*-----------------------------------------------------------------*/
5547 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5560 /*-----------------------------------------------------------------*/
5561 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5562 /* in the linked list */
5563 /*-----------------------------------------------------------------*/
5564 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5578 //#define PCODE_DEBUG
5579 /*-----------------------------------------------------------------*/
5580 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5581 /* in the linked list */
5582 /*-----------------------------------------------------------------*/
5583 pCode * pic16_findNextInstruction(pCode *pci)
5588 if((pc->type == PC_OPCODE)
5589 || (pc->type == PC_WILD)
5590 || (pc->type == PC_ASMDIR)
5595 fprintf(stderr,"pic16_findNextInstruction: ");
5596 printpCode(stderr, pc);
5601 //fprintf(stderr,"Couldn't find instruction\n");
5605 /*-----------------------------------------------------------------*/
5606 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5607 /* in the linked list */
5608 /*-----------------------------------------------------------------*/
5609 pCode * pic16_findPrevInstruction(pCode *pci)
5615 if((pc->type == PC_OPCODE)
5616 || (pc->type == PC_WILD)
5617 || (pc->type == PC_ASMDIR)
5623 fprintf(stderr,"pic16_findPrevInstruction: ");
5624 printpCode(stderr, pc);
5629 //fprintf(stderr,"Couldn't find instruction\n");
5636 /*-----------------------------------------------------------------*/
5637 /* findFunctionEnd - given a pCode find the end of the function */
5638 /* that contains it */
5639 /*-----------------------------------------------------------------*/
5640 static pCode * findFunctionEnd(pCode *pc)
5644 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5650 fprintf(stderr,"Couldn't find function end\n");
5655 /*-----------------------------------------------------------------*/
5656 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5657 /* instruction with which it is associated. */
5658 /*-----------------------------------------------------------------*/
5659 static void AnalyzeLabel(pCode *pc)
5662 pic16_pCodeUnlink(pc);
5668 static void AnalyzeGOTO(pCode *pc)
5671 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5675 static void AnalyzeSKIP(pCode *pc)
5678 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5679 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5683 static void AnalyzeRETURN(pCode *pc)
5686 // branch_link(pc,findFunctionEnd(pc->next));
5692 /*-----------------------------------------------------------------*/
5693 /*-----------------------------------------------------------------*/
5694 regs * pic16_getRegFromInstruction(pCode *pc)
5700 PCI(pc)->num_ops == 0 ||
5701 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5705 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5706 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5709 switch(PCI(pc)->pcop->type) {
5715 return PCOR(PCI(pc)->pcop)->r;
5719 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5720 return PCOR(PCI(pc)->pcop)->r;
5723 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5725 if(PCOI(PCI(pc)->pcop)->r)
5726 return (PCOI(PCI(pc)->pcop)->r);
5731 return PCOR(PCI(pc)->pcop)->r;
5733 case PO_GPR_REGISTER:
5735 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5736 return PCOR(PCI(pc)->pcop)->r;
5739 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5743 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5744 // genericPrint(stderr, pc);
5752 /*-------------------------------------------------------------------------------*/
5753 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5754 /*-------------------------------------------------------------------------------*/
5755 regs * pic16_getRegFromInstruction2(pCode *pc)
5761 PCI(pc)->num_ops == 0 ||
5762 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5767 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5768 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5772 * operands supported in MOVFF:
5779 switch(PCI(pc)->pcop->type) {
5785 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5787 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5791 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5792 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5796 // if(PCOI(PCI(pc)->pcop)->r)
5797 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5799 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5800 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5803 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5804 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5811 // return PCOR2(PCI(pc)->pcop)->r;
5813 case PO_GPR_REGISTER:
5815 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5816 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5820 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5823 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5824 //genericPrint(stderr, pc);
5832 /*-----------------------------------------------------------------*/
5833 /*-----------------------------------------------------------------*/
5835 static void AnalyzepBlock(pBlock *pb)
5842 /* Find all of the registers used in this pBlock
5843 * by looking at each instruction and examining it's
5846 for(pc = pb->pcHead; pc; pc = pc->next) {
5848 /* Is this an instruction with operands? */
5849 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5851 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5853 /* Loop through all of the registers declared so far in
5854 this block and see if we find this one there */
5856 regs *r = setFirstItem(pb->tregisters);
5859 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5860 PCOR(PCI(pc)->pcop)->r = r;
5863 r = setNextItem(pb->tregisters);
5867 /* register wasn't found */
5868 //r = Safe_calloc(1, sizeof(regs));
5869 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5870 //addSet(&pb->tregisters, r);
5871 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5872 //PCOR(PCI(pc)->pcop)->r = r;
5873 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5875 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5878 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5879 if(PCOR(PCI(pc)->pcop)->r) {
5880 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5881 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5883 if(PCI(pc)->pcop->name)
5884 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5886 fprintf(stderr,"ERROR: NULL register\n");
5895 /*-----------------------------------------------------------------*/
5897 /*-----------------------------------------------------------------*/
5898 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5900 static void InsertpFlow(pCode *pc, pCode **pflow)
5903 PCFL(*pflow)->end = pc;
5905 if(!pc || !pc->next)
5908 *pflow = pic16_newpCodeFlow();
5909 pic16_pCodeInsertAfter(pc, *pflow);
5912 /*-----------------------------------------------------------------*/
5913 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5914 /* the flow blocks. */
5916 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5917 * point the instruction flow changes.
5919 /*-----------------------------------------------------------------*/
5920 void pic16_BuildFlow(pBlock *pb)
5923 pCode *last_pci=NULL;
5930 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5931 /* Insert a pCodeFlow object at the beginning of a pBlock */
5933 InsertpFlow(pb->pcHead, &pflow);
5935 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5936 //pflow->next = pb->pcHead; /* Make the current head the next object */
5937 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5938 //pb->pcHead = pflow; /* Make the Flow object the head */
5941 for( pc = pic16_findNextInstruction(pb->pcHead);
5943 pc=pic16_findNextInstruction(pc)) {
5946 PCI(pc)->pcflow = PCFL(pflow);
5948 //fprintf(stderr," build: ");
5949 //pflow->print(stderr,pflow);
5951 if( PCI(pc)->isSkip) {
5953 /* The two instructions immediately following this one
5954 * mark the beginning of a new flow segment */
5956 while(pc && PCI(pc)->isSkip) {
5958 PCI(pc)->pcflow = PCFL(pflow);
5962 InsertpFlow(pc, &pflow);
5963 pc=pic16_findNextInstruction(pc->next);
5971 PCI(pc)->pcflow = PCFL(pflow);
5973 InsertpFlow(pc, &pflow);
5975 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5977 InsertpFlow(pc, &pflow);
5980 } else if (checkLabel(pc)) {
5982 /* This instruction marks the beginning of a
5983 * new flow segment */
5988 /* If the previous pCode is not a flow object, then
5989 * insert a new flow object. (This check prevents
5990 * two consecutive flow objects from being insert in
5991 * the case where a skip instruction preceeds an
5992 * instruction containing a label.) */
5994 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5995 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5997 PCI(pc)->pcflow = PCFL(pflow);
6004 //fprintf (stderr,",end seq %d",GpcFlowSeq);
6006 PCFL(pflow)->end = pb->pcTail;
6009 /*-------------------------------------------------------------------*/
6010 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
6011 /* the flow blocks. */
6013 * unBuildFlow removes pCodeFlow objects from a pCode chain
6015 /*-----------------------------------------------------------------*/
6016 static void unBuildFlow(pBlock *pb)
6031 if(PCI(pc)->pcflow) {
6032 //Safe_free(PCI(pc)->pcflow);
6033 PCI(pc)->pcflow = NULL;
6036 } else if(isPCFL(pc) )
6045 /*-----------------------------------------------------------------*/
6046 /*-----------------------------------------------------------------*/
6047 static void dumpCond(int cond)
6050 static char *pcc_str[] = {
6064 int ncond = sizeof(pcc_str) / sizeof(char *);
6067 fprintf(stderr, "0x%04X\n",cond);
6069 for(i=0,j=1; i<ncond; i++, j<<=1)
6071 fprintf(stderr, " %s\n",pcc_str[i]);
6077 /*-----------------------------------------------------------------*/
6078 /*-----------------------------------------------------------------*/
6079 static void FlowStats(pCodeFlow *pcflow)
6087 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
6089 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6092 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
6097 fprintf(stderr, " FlowStats inCond: ");
6098 dumpCond(pcflow->inCond);
6099 fprintf(stderr, " FlowStats outCond: ");
6100 dumpCond(pcflow->outCond);
6104 /*-----------------------------------------------------------------*
6105 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
6106 * if it affects the banking bits.
6108 * return: -1 == Banking bits are unaffected by this pCode.
6110 * return: > 0 == Banking bits are affected.
6112 * If the banking bits are affected, then the returned value describes
6113 * which bits are affected and how they're affected. The lower half
6114 * of the integer maps to the bits that are affected, the upper half
6115 * to whether they're set or cleared.
6117 *-----------------------------------------------------------------*/
6119 static int isBankInstruction(pCode *pc)
6127 if( PCI(pc)->op == POC_MOVLB ||
6128 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
6129 bank = PCOL(pc)->lit;
6136 /*-----------------------------------------------------------------*/
6137 /*-----------------------------------------------------------------*/
6138 static void FillFlow(pCodeFlow *pcflow)
6147 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
6149 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6152 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
6159 isBankInstruction(pc);
6161 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
6165 fprintf(stderr, " FillFlow - Bad end of flow\n");
6167 fprintf(stderr, " FillFlow - Ending flow with\n ");
6168 pc->print(stderr,pc);
6171 fprintf(stderr, " FillFlow inCond: ");
6172 dumpCond(pcflow->inCond);
6173 fprintf(stderr, " FillFlow outCond: ");
6174 dumpCond(pcflow->outCond);
6178 /*-----------------------------------------------------------------*/
6179 /*-----------------------------------------------------------------*/
6180 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
6182 pCodeFlowLink *fromLink, *toLink;
6184 if(!from || !to || !to->pcflow || !from->pcflow)
6187 fromLink = pic16_newpCodeFlowLink(from->pcflow);
6188 toLink = pic16_newpCodeFlowLink(to->pcflow);
6190 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
6191 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
6195 /*-----------------------------------------------------------------*
6196 * void LinkFlow(pBlock *pb)
6198 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
6199 * non-branching segments. In LinkFlow, we determine the execution
6200 * order of these segments. For example, if one of the segments ends
6201 * with a skip, then we know that there are two possible flow segments
6202 * to which control may be passed.
6203 *-----------------------------------------------------------------*/
6204 static void LinkFlow(pBlock *pb)
6210 //fprintf(stderr,"linkflow \n");
6212 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6214 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6217 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
6219 //fprintf(stderr," link: ");
6220 //pcflow->print(stderr,pcflow);
6222 //FillFlow(PCFL(pcflow));
6224 pc = PCFL(pcflow)->end;
6226 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
6227 if(isPCI_SKIP(pc)) {
6228 // fprintf(stderr, "ends with skip\n");
6229 // pc->print(stderr,pc);
6231 pct=pic16_findNextInstruction(pc->next);
6232 LinkFlow_pCode(PCI(pc),PCI(pct));
6233 pct=pic16_findNextInstruction(pct->next);
6234 LinkFlow_pCode(PCI(pc),PCI(pct));
6238 if(isPCI_BRANCH(pc)) {
6239 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6241 //fprintf(stderr, "ends with branch\n ");
6242 //pc->print(stderr,pc);
6244 if(!(pcol && isPCOLAB(pcol))) {
6245 if((PCI(pc)->op != POC_RETLW)
6246 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
6248 /* continue if label is '$' which assembler knows how to parse */
6249 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6251 if(pic16_pcode_verbose) {
6252 pc->print(stderr,pc);
6253 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6259 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6260 LinkFlow_pCode(PCI(pc),PCI(pct));
6262 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6263 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6265 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6271 //fprintf(stderr, "ends with non-branching instruction:\n");
6272 //pc->print(stderr,pc);
6274 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6280 //fprintf(stderr, "ends with unknown\n");
6281 //pc->print(stderr,pc);
6285 //fprintf(stderr, "ends with nothing: ERROR\n");
6289 /*-----------------------------------------------------------------*/
6290 /*-----------------------------------------------------------------*/
6292 /*-----------------------------------------------------------------*/
6293 /*-----------------------------------------------------------------*/
6294 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6300 if((!isPCI(pc) && !isPCAD(pc)) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6303 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6313 /*-----------------------------------------------------------------*/
6314 /* insertBankSwitch - inserts a bank switch statement in the */
6315 /* assembly listing */
6317 /* position == 0: insert before */
6318 /* position == 1: insert after pc */
6319 /* position == 2: like 0 but previous was a skip instruction */
6320 /*-----------------------------------------------------------------*/
6321 pCodeOp *pic16_popGetLabel(unsigned int key);
6322 extern int pic16_labelOffset;
6324 static void insertBankSwitch(unsigned char position, pCode *pc)
6331 /* emit BANKSEL [symbol] */
6334 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6336 // position = 0; // position is always before (sanity check!)
6339 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6340 pc->print(stderr, pc);
6345 /* insert the bank switch after this pc instruction */
6346 pCode *pcnext = pic16_findNextInstruction(pc);
6348 pic16_pCodeInsertAfter(pc, new_pc);
6349 if(pcnext)pc = pcnext;
6353 /* insert the bank switch BEFORE this pc instruction */
6354 pic16_pCodeInsertAfter(pc->prev, new_pc);
6359 pCode *pcnext, *pcprev, *npci, *ppc;
6361 int ofs1=0, ofs2=0, len=0;
6363 /* just like 0, but previous was a skip instruction,
6364 * so some care should be taken */
6366 pic16_labelOffset += 10000;
6367 tlbl = newiTempLabel(NULL);
6369 /* invert skip instruction */
6370 pcprev = pic16_findPrevInstruction(pc->prev);
6371 ipci = PCI(pcprev)->inverted_op;
6372 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6374 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6376 /* copy info from old pCode */
6377 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6378 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6379 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6380 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6381 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6382 PCI(npci)->op = PCI(pcprev)->inverted_op;
6384 /* unlink old pCode */
6386 ppc->next = pcprev->next;
6387 pcprev->next->prev = ppc;
6388 pic16_pCodeInsertAfter(ppc, npci);
6390 /* extra instructions to handle invertion */
6391 pcnext = pic16_newpCode(POC_BRA, pic16_popGetLabel(tlbl->key));
6392 pic16_pCodeInsertAfter(npci, pcnext);
6393 pic16_pCodeInsertAfter(pc->prev, new_pc);
6395 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6396 pic16_pCodeInsertAfter(pc, pcnext);
6401 /* Move the label, if there is one */
6402 if(PCI(pc)->label) {
6403 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6404 // __FILE__, __LINE__, pc, new_pc);
6405 PCAD(new_pc)->pci.label = PCI(pc)->label;
6406 PCI(pc)->label = NULL;
6411 /*-----------------------------------------------------------------*/
6412 /*int compareBankFlow - compare the banking requirements between */
6414 /*-----------------------------------------------------------------*/
6415 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6418 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6421 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6424 if(pcflow->firstBank == -1)
6428 if(pcflowLink->pcflow->firstBank == -1) {
6429 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6430 pcflowLink->pcflow->to :
6431 pcflowLink->pcflow->from);
6432 return compareBankFlow(pcflow, pctl, toORfrom);
6436 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6439 pcflowLink->bank_conflict++;
6440 pcflowLink->pcflow->FromConflicts++;
6441 pcflow->ToConflicts++;
6444 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6447 pcflowLink->bank_conflict++;
6448 pcflowLink->pcflow->ToConflicts++;
6449 pcflow->FromConflicts++;
6453 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6454 pcflowLink->pcflow->pc.seq,
6455 pcflowLink->pcflow->FromConflicts,
6456 pcflowLink->pcflow->ToConflicts);
6463 /*-----------------------------------------------------------------*/
6464 /*-----------------------------------------------------------------*/
6465 static void DumpFlow(pBlock *pb)
6469 pCodeFlowLink *pcfl;
6472 fprintf(stderr,"Dump flow \n");
6473 pb->pcHead->print(stderr, pb->pcHead);
6475 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6476 pcflow->print(stderr,pcflow);
6478 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6480 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6482 if(!isPCFL(pcflow)) {
6483 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6486 fprintf(stderr,"dumping: ");
6487 pcflow->print(stderr,pcflow);
6488 FlowStats(PCFL(pcflow));
6490 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6492 pc = PCODE(pcfl->pcflow);
6494 fprintf(stderr, " from seq %d:\n",pc->seq);
6496 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6497 pc->print(stderr,pc);
6502 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6504 pc = PCODE(pcfl->pcflow);
6506 fprintf(stderr, " to seq %d:\n",pc->seq);
6508 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6509 pc->print(stderr,pc);
6518 /*-----------------------------------------------------------------*/
6519 /*-----------------------------------------------------------------*/
6520 static int OptimizepBlock(pBlock *pb)
6525 if(!pb || !peepOptimizing)
6528 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6530 for(pc = pb->pcHead; pc; pc = pc->next)
6531 matches += pic16_pCodePeepMatchRule(pc);
6534 pc = pic16_findNextInstruction(pb->pcHead);
6542 if(pic16_pCodePeepMatchRule(pc)) {
6547 pc = pic16_findNextInstruction(pcprev->next);
6549 pc = pic16_findNextInstruction(pb->pcHead);
6551 pc = pic16_findNextInstruction(pc->next);
6555 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6560 /*-----------------------------------------------------------------*/
6561 /*-----------------------------------------------------------------*/
6562 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6566 for(pc = pcs; pc; pc = pc->next) {
6568 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
6570 (PCI(pc)->pcop->type == PO_LABEL) &&
6571 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6579 /*-----------------------------------------------------------------*/
6580 /*-----------------------------------------------------------------*/
6581 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6588 (PCI(pc)->pcop->type == PO_LABEL)) {
6590 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6592 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6593 // if(pcol->pcop.name)
6594 // Safe_free(pcol->pcop.name);
6596 /* If the key is negative, then we (probably) have a label to
6597 * a function and the name is already defined */
6600 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6604 //sprintf(buffer,"_%05d_DS_",pcl->key);
6606 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6608 pcol->pcop.name = Safe_strdup(s);
6609 pcol->key = pcl->key;
6610 //pc->print(stderr,pc);
6617 /*-----------------------------------------------------------------*/
6618 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6619 /* pCode chain if they're not used. */
6620 /*-----------------------------------------------------------------*/
6621 static void pBlockRemoveUnusedLabels(pBlock *pb)
6623 pCode *pc; pCodeLabel *pcl;
6628 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6630 pBranch *pbr = PCI(pc)->label;
6631 if(pbr && pbr->next) {
6632 pCode *pcd = pb->pcHead;
6634 // fprintf(stderr, "multiple labels\n");
6635 // pc->print(stderr,pc);
6640 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6641 //fprintf(stderr,"Used by:\n");
6642 //pcd->print(stderr,pcd);
6644 exchangeLabels(PCL(pbr->pc),pcd);
6653 for(pc = pb->pcHead; pc; pc = pc->next) {
6655 if(isPCL(pc)) // pc->type == PC_LABEL)
6657 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6658 pcl = PCL(PCI(pc)->label->pc);
6661 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6663 /* This pCode is a label, so search the pBlock to see if anyone
6666 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6668 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6669 /* Couldn't find an instruction that refers to this label
6670 * So, unlink the pCode label from it's pCode chain
6671 * and destroy the label */
6672 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6674 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6675 if(pc->type == PC_LABEL) {
6676 pic16_unlinkpCode(pc);
6677 pCodeLabelDestruct(pc);
6679 unlinkpCodeFromBranch(pc, PCODE(pcl));
6680 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6681 Safe_free(pc->label);
6691 /*-----------------------------------------------------------------*/
6692 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6693 /* chain and put them into pBranches that are */
6694 /* associated with the appropriate pCode */
6696 /*-----------------------------------------------------------------*/
6697 void pic16_pBlockMergeLabels(pBlock *pb)
6700 pCode *pc, *pcnext=NULL;
6705 /* First, Try to remove any unused labels */
6706 //pBlockRemoveUnusedLabels(pb);
6708 /* Now loop through the pBlock and merge the labels with the opcodes */
6711 // for(pc = pb->pcHead; pc; pc = pc->next) {
6714 pCode *pcn = pc->next;
6716 if(pc->type == PC_LABEL) {
6718 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6719 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6721 if((pcnext = pic16_findNextInstruction(pc) )) {
6723 // pcnext->print(stderr, pcnext);
6725 // Unlink the pCode label from it's pCode chain
6726 pic16_unlinkpCode(pc);
6728 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6729 // And link it into the instruction's pBranch labels. (Note, since
6730 // it's possible to have multiple labels associated with one instruction
6731 // we must provide a means to accomodate the additional labels. Thus
6732 // the labels are placed into the singly-linked list "label" as
6733 // opposed to being a single member of the pCodeInstruction.)
6735 //_ALLOC(pbr,sizeof(pBranch));
6737 pbr = Safe_calloc(1,sizeof(pBranch));
6741 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6744 if(pic16_pcode_verbose)
6745 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6747 } else if(pc->type == PC_CSOURCE) {
6749 /* merge the source line symbolic info into the next instruction */
6750 if((pcnext = pic16_findNextInstruction(pc) )) {
6752 // Unlink the pCode label from it's pCode chain
6753 pic16_unlinkpCode(pc);
6754 PCI(pcnext)->cline = PCCS(pc);
6755 //fprintf(stderr, "merging CSRC\n");
6756 //genericPrint(stderr,pcnext);
6762 pBlockRemoveUnusedLabels(pb);
6766 /*-----------------------------------------------------------------*/
6767 /*-----------------------------------------------------------------*/
6768 static int OptimizepCode(char dbName)
6770 #define MAX_PASSES 4
6779 DFPRINTF((stderr," Optimizing pCode\n"));
6783 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6784 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6785 matches += OptimizepBlock(pb);
6788 while(matches && ++passes < MAX_PASSES);
6795 const char *pic16_pCodeOpType(pCodeOp *pcop);
6796 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6799 /*-----------------------------------------------------------------*/
6800 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6801 /*-----------------------------------------------------------------*/
6803 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6807 // fprintf(stderr, "%s:%d pc type: %s\tname: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc), pc->name);
6810 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6812 if(PCOR(pc)->r)pcop = pic16_newpCodeOpBit(PCOR(pc)->r->name, bitval, 0, pc->type);
6815 assert(pcop != NULL);
6817 if( !( (pcop->type == PO_LABEL) ||
6818 (pcop->type == PO_LITERAL) ||
6819 (pcop->type == PO_STR) ))
6820 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6821 PCOR(pcop)->r->wasUsed = 1;
6822 PCOR(pcop)->instance = PCOR(pc)->instance;
6828 /*----------------------------------------------------------------------*
6829 * pic16_areRegsSame - check to see if the names of two registers match *
6830 *----------------------------------------------------------------------*/
6831 int pic16_areRegsSame(regs *r1, regs *r2)
6833 if(!strcmp(r1->name, r2->name))return 1;
6839 /*-----------------------------------------------------------------*/
6840 /*-----------------------------------------------------------------*/
6841 static void pic16_FixRegisterBanking(pBlock *pb)
6845 regs *reg, *prevreg;
6846 unsigned char flag=0;
6851 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6854 /* loop through all of the flow blocks with in one pblock */
6856 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6860 /* at this point, pc should point to a PC_FLOW object */
6861 /* for each flow block, determine the register banking
6865 /* if label, then might come from other point, force banksel */
6866 if(isPCL(pc))prevreg = NULL;
6868 if(!isPCI(pc))goto loop;
6870 if(PCI(pc)->label)prevreg = NULL;
6872 if(PCI(pc)->is2MemOp)goto loop;
6874 /* if goto, then force banksel */
6875 // if(PCI(pc)->op == POC_GOTO)prevreg = NULL;
6877 reg = pic16_getRegFromInstruction(pc);
6880 pc->print(stderr, pc);
6881 fprintf(stderr, "reg = %p\n", reg);
6884 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6885 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6886 reg->address,reg->isBitField, reg->isFixed);
6890 /* now make some tests to make sure that instruction needs bank switch */
6892 /* if no register exists, and if not a bit opcode goto loop */
6894 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6897 if(isPCI_SKIP(pc)) {
6898 // fprintf(stderr, "instruction is SKIP instruction\n");
6901 if(reg && isACCESS_BANK(reg))goto loop;
6903 if(!isBankInstruction(pc))goto loop;
6905 if(isPCI_LIT(pc))goto loop;
6907 if(PCI(pc)->op == POC_CALL)goto loop;
6909 /* Examine the instruction before this one to make sure it is
6910 * not a skip type instruction */
6911 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6913 flag = 0; /* add before this instruction */
6915 /* if previous instruction is a skip one, then set flag
6916 * to 2 and call insertBankSwitch */
6917 if(pcprev && isPCI_SKIP(pcprev)) {
6922 if(pic16_options.opt_banksel>0) {
6923 char op1[128], op2[128];
6926 strcpy(op1, pic16_get_op_from_instruction(PCI(pc)));
6927 strcpy(op2, pic16_get_op_from_instruction(PCI(pcprev)));
6928 if(!strcmp(op1, op2))goto loop;
6932 insertBankSwitch(flag, pc);
6934 // fprintf(stderr, "BANK SWITCH inserted\n");
6942 /** ADDITIONS BY RAPHAEL NEIDER, 2004-11-16: GOTO OPTIMIZATIONS **/
6944 /* Returns the (maximum of the) number of bytes used by the specified pCode. */
6945 int instrSize (pCode *pc)
6950 if (!PCAD(pc)->directive || strlen (PCAD(pc)->directive) < 3) return 0;
6951 return 4; // assumes only regular instructions using <= 4 bytes
6954 if (isPCI(pc)) return PCI(pc)->isize;
6959 /* Returns 1 if pc is referenced by the given label (either
6960 * pc is the label itself or is an instruction with an attached
6962 * Returns 0 if pc is not preceeded by the specified label.
6964 int isLabel (pCode *pc, char *label)
6968 // label attached to the pCode?
6969 if (isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO) {
6970 pBranch *lab = NULL;
6971 lab = PCI(pc)->label;
6974 if (isPCL(lab->pc) && strcmp(PCL(lab->pc)->label, label) == 0) {
6981 // is inline assembly label?
6982 if (isPCAD(pc) && PCAD(pc)->directive == NULL && PCAD(pc)->arg) {
6983 // do not compare trailing ':'
6984 if (strncmp (PCAD(pc)->arg, label, strlen (label)) == 0) {
6991 if (strcmp(PCL(pc)->label,label) == 0) {
6996 // no label/no label attached/wrong label(s)
7000 /* Returns the distance to the given label in terms of words.
7001 * Labels are searched only within -max .. max words from pc.
7002 * Returns max if the label could not be found or
7003 * its distance from pc in (-max..+max).
7005 int findpCodeLabel (pCode *pc, char *label, int max, pCode **target) {
7006 int dist = instrSize(pc);
7010 while (dist < max && curr && !isLabel (curr, label)) {
7012 dist += instrSize(curr); // sizeof (instruction)
7014 if (curr && dist < max) {
7015 if (target != NULL) *target = curr;
7020 curr = pic16_findNextInstruction (pc->next);
7022 while (dist < max && curr && !isLabel (curr, label)) {
7023 dist += instrSize(curr); // sizeof (instruction)
7026 if (curr && dist < max) {
7027 if (target != NULL) *target = curr;
7031 if (target != NULL) *target = NULL;
7035 /* Returns -1 if pc does NOT denote an instruction like
7037 * Otherwise we return
7038 * (a) 0x10 + i for BTFSS
7039 * (b) 0x00 + i for BTFSC
7041 int isSkipOnStatus (pCode *pc)
7045 if (!pc || !isPCI(pc)) return -1;
7046 if (PCI(pc)->op == POC_BTFSS) res = 0x10;
7047 else if (PCI(pc)->op == POC_BTFSC) res = 0x00;
7050 pcop = PCI(pc)->pcop;
7052 if (pcop->type == PO_STATUS || (pcop->type == PO_GPR_BIT && strcmp(pcop->name, "STATUS") == 0)) {
7053 return res + ((pCodeOpRegBit *)pcop)->bit;
7059 /* Returns 1 if pc is one of BC, BZ, BOV, BN, BNC, BNZ, BNOV or BNN,
7060 * returns 0 otherwise. */
7061 int isConditionalBranch (pCode *pc)
7063 if (!pc || !isPCI_BRANCH(pc)) return 0;
7065 switch (PCI(pc)->op) {
7083 /* Returns 1 if pc has a label attached to it.
7084 * This can be either a label stored in the pCode itself (.label)
7085 * or a label making up its own pCode preceding this pc.
7086 * Returns 0 if pc cannot be reached directly via a label.
7088 int hasNoLabel (pCode *pc)
7093 // are there any label pCodes between pc and the previous instruction?
7094 prev = pic16_findPrevInstruction (pc->prev);
7095 while (pc && pc != prev) {
7096 // pCode with attached label?
7097 if ((isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO)
7098 && PCI(pc)->label) {
7101 // is inline assembly label?
7102 if (isPCAD(pc) && PCAD(pc)->directive == NULL) return 0;
7103 if (isPCW(pc) && PCW(pc)->label) return 0;
7106 if (isPCL(pc)) return 0;
7115 /* Replaces the old pCode with the new one, moving the labels,
7116 * C source line and probably flow information to the new pCode.
7118 void pic16_pCodeReplace (pCode *oldPC, pCode *newPC) {
7119 if (!oldPC || !newPC || !isPCI(oldPC) || !isPCI(newPC))
7122 /* first move all labels from old to new */
7123 PCI(newPC)->label = pic16_pBranchAppend (PCI(oldPC)->label, PCI(newPC)->label);
7124 PCI(oldPC)->label = NULL;
7126 /* move C source line (if possible) */
7127 if (PCI(oldPC)->cline && !PCI(newPC)->cline)
7128 PCI(newPC)->cline = PCI(oldPC)->cline;
7130 /* insert new pCode into pBlock */
7131 pic16_pCodeInsertAfter (oldPC, newPC);
7132 pic16_unlinkpCode (oldPC);
7134 /* TODO: update flow (newPC->from, newPC->to) */
7135 PCI(newPC)->pcflow = PCI(oldPC)->pcflow;
7137 /* destruct replaced pCode */
7138 oldPC->destruct (oldPC);
7141 /* Returns the inverted conditional branch (if any) or NULL.
7142 * pcop must be set to the new jump target.
7144 pCode *getNegatedBcc (pCode *bcc, pCodeOp *pcop)
7148 if (!bcc || !isPCI(bcc)) return NULL;
7150 switch (PCI(bcc)->op) {
7151 case POC_BC: newBcc = pic16_newpCode (POC_BNC , pcop); break;
7152 case POC_BZ: newBcc = pic16_newpCode (POC_BNZ , pcop); break;
7153 case POC_BOV: newBcc = pic16_newpCode (POC_BNOV, pcop); break;
7154 case POC_BN: newBcc = pic16_newpCode (POC_BNN , pcop); break;
7155 case POC_BNC: newBcc = pic16_newpCode (POC_BC , pcop); break;
7156 case POC_BNZ: newBcc = pic16_newpCode (POC_BZ , pcop); break;
7157 case POC_BNOV: newBcc = pic16_newpCode (POC_BOV , pcop); break;
7158 case POC_BNN: newBcc = pic16_newpCode (POC_BN , pcop); break;
7165 #define MAX_DIST_GOTO 0x7FFFFFFF
7166 #define MAX_DIST_BRA 1020 // maximum offset (in bytes) possible with BRA
7167 #define MAX_DIST_BCC 120 // maximum offset (in bytes) possible with Bcc
7168 #define MAX_JUMPCHAIN_DEPTH 16 // number of GOTOs to follow in resolveJumpChain() (to prevent endless loops)
7169 #define IS_GOTO(arg) ((arg) && isPCI(arg) && (PCI(arg)->op == POC_GOTO || PCI(arg)->op == POC_BRA))
7171 /* Follows GOTO/BRA instructions to their target instructions, stores the
7172 * final destination (not a GOTO or BRA instruction) in target and returns
7173 * the distance from the original pc to *target.
7175 int resolveJumpChain (pCode *pc, pCode **target, pCodeOp **pcop) {
7178 pCodeOp *lastPCOP = NULL;
7182 //fprintf (stderr, "%s:%d: -=-", __FUNCTION__, __LINE__);
7184 /* only follow unconditional branches, except for the initial pCode (which may be a conditional branch) */
7185 while (curr && (last != curr) && (depth++ < MAX_JUMPCHAIN_DEPTH) && isPCI(curr)
7186 && (PCI(curr)->op == POC_GOTO || PCI(curr)->op == POC_BRA || (curr == pc && isConditionalBranch(curr)))) {
7188 lastPCOP = PCI(curr)->pcop;
7189 dist = findpCodeLabel (pc, PCI(curr)->pcop->name, MAX_DIST_GOTO, &curr);
7190 //fprintf (stderr, "last:%p, curr:%p, label:%s\n", last, curr, PCI(last)->pcop->name);
7193 if (target) *target = last;
7194 if (pcop) *pcop = lastPCOP;
7198 /* Returns pc if it is not a OPT_JUMPTABLE_BEGIN INFO pCode.
7199 * Otherwise the first pCode after the jumptable (after
7200 * the OPT_JUMPTABLE_END tag) is returned.
7202 pCode *skipJumptables (pCode *pc, int *isJumptable)
7205 if (!pc) return NULL;
7207 while (pc->type == PC_INFO && PCINF(pc)->type == INF_OPTIMIZATION && PCOO(PCINF(pc)->oper1)->type == OPT_JUMPTABLE_BEGIN) {
7209 //fprintf (stderr, "SKIPPING jumptable\n");
7211 //pc->print(stderr, pc);
7213 } while (pc && (pc->type != PC_INFO || PCINF(pc)->type != INF_OPTIMIZATION
7214 || PCOO(PCINF(pc)->oper1)->type != OPT_JUMPTABLE_END));
7215 //fprintf (stderr, "<<JUMPTAB:\n");
7216 // skip OPT_END as well
7217 if (pc) pc = pc->next;
7223 pCode *pic16_findNextInstructionSkipJumptables (pCode *pc, int *isJumptable)
7227 while (pc && !isPCI(pc) && !isPCAD(pc) && !isPCW(pc)) {
7228 // set pc to the first pCode after a jumptable, leave pc untouched otherwise
7229 pc = skipJumptables (pc, &isJumptab);
7231 // pc is the first pCode after the jumptable
7234 // pc has not been changed by skipJumptables()
7242 /* Turn GOTOs into BRAs if distance between GOTO and label
7243 * is less than 1024 bytes.
7245 * This method is especially useful if GOTOs after BTFS[SC]
7246 * can be turned into BRAs as GOTO would cost another NOP
7249 void pic16_OptimizeJumps ()
7252 pCode *pc_prev = NULL;
7253 pCode *pc_next = NULL;
7256 int change, iteration, isJumptab;
7259 int opt=0, toofar=0, opt_cond = 0, cond_toofar=0, opt_reorder = 0, opt_gotonext = 0, opt_gotochain = 0;
7261 if (!the_pFile) return;
7263 //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7265 for (pb = the_pFile->pbHead; pb != NULL; pb = pb->next) {
7266 int matchedInvertRule = 1;
7269 //fprintf (stderr, "%s:%d: iterating over pBlock %p\n", __FUNCTION__, __LINE__, pb);
7271 pc = pic16_findNextInstruction (pb->pcHead);
7274 pc_next = pic16_findNextInstructionSkipJumptables (pc->next, &isJumptab);
7276 // skip jumptable, i.e. start over with no pc_prev!
7282 /* (1) resolve chained jumps
7283 * Do not perform this until pattern (4) is no longer present! Otherwise we will
7284 * (a) leave dead code in and
7285 * (b) skip over the dead code with an (unneccessary) jump.
7287 if (!matchedInvertRule && (IS_GOTO(pc) || isConditionalBranch(pc))) {
7288 pCodeOp *lastTargetOp = NULL;
7289 int newDist = resolveJumpChain (pc, &target, &lastTargetOp);
7290 int maxDist = MAX_DIST_BCC;
7291 if (PCI(pc)->op == POC_BRA) maxDist = MAX_DIST_BRA;
7292 if (PCI(pc)->op == POC_GOTO) maxDist = MAX_DIST_GOTO;
7294 /* be careful NOT to make the jump instruction longer (might break previously shortened jumps!) */
7295 if (lastTargetOp && newDist <= maxDist && lastTargetOp != PCI(pc)->pcop
7296 && strcmp (lastTargetOp->name, PCI(pc)->pcop->name) != 0) {
7297 //fprintf (stderr, "(1) ");pc->print(stderr, pc); fprintf (stderr, " --> %s\n", lastTargetOp->name);
7298 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(1) jump chain resolved")); }
7299 PCI(pc)->pcop->name = lastTargetOp->name;
7308 int condBraType = isSkipOnStatus(pc_prev);
7309 label = PCI(pc)->pcop->name;
7310 dist = findpCodeLabel(pc, label, MAX_DIST_BRA, &target);
7311 if (dist < 0) dist = -dist;
7312 //fprintf (stderr, "distance: %d (", dist); pc->print(stderr, pc);fprintf (stderr, ")\n");
7316 /* (2) remove "GOTO label; label:" */
7317 if (isLabel (pc_next, label)) {
7318 //fprintf (stderr, "(2) GOTO next instruction: ");pc->print(stderr, pc);fprintf (stderr, " --> ");pc_next->print(stderr, pc_next); fprintf(stderr, "\n");
7319 // first remove all preceeding SKIP instructions
7320 while (pc_prev && isPCI_SKIP(pc_prev)) {
7321 // attach labels on this instruction to pc_next
7322 //fprintf (stderr, "(2) preceeding SKIP removed: ");pc_prev->print(stderr, pc_prev);fprintf(stderr, "\n");
7323 PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc_prev)->label, PCI(pc_next)->label);
7324 PCI(pc_prev)->label = NULL;
7325 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(2) SKIP removed")); }
7326 pic16_unlinkpCode (pc_prev);
7327 pc_prev = pic16_findPrevInstruction (pc);
7329 // now remove the redundant goto itself
7330 PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc)->label, PCI(pc_next)->label);
7331 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP("(2) GOTO next instruction removed")); }
7332 pic16_unlinkpCode (pc);
7333 pc = pic16_findPrevInstruction(pc_next->prev);
7334 isHandled = 1; // do not perform further optimizations
7340 /* (3) turn BTFSx STATUS,i; GOTO label into Bcc label if possible */
7341 if (!isHandled && condBraType != -1 && hasNoLabel(pc)) {
7342 if (dist < MAX_DIST_BCC) {
7344 switch (condBraType) {
7345 case 0x00: bcc = pic16_newpCode (POC_BC, PCI(pc)->pcop);break;
7346 // no BDC on DIGIT CARRY available
7347 case 0x02: bcc = pic16_newpCode (POC_BZ, PCI(pc)->pcop);break;
7348 case 0x03: bcc = pic16_newpCode (POC_BOV, PCI(pc)->pcop);break;
7349 case 0x04: bcc = pic16_newpCode (POC_BN, PCI(pc)->pcop);break;
7350 case 0x10: bcc = pic16_newpCode (POC_BNC, PCI(pc)->pcop);break;
7351 // no BNDC on DIGIT CARRY available
7352 case 0x12: bcc = pic16_newpCode (POC_BNZ, PCI(pc)->pcop);break;
7353 case 0x13: bcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop);break;
7354 case 0x14: bcc = pic16_newpCode (POC_BNN, PCI(pc)->pcop);break;
7356 // no replacement possible
7361 // ATTENTION: keep labels attached to BTFSx!
7362 // HINT: GOTO is label free (checked above)
7363 //fprintf (stderr, "%s:%d: (3) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(bcc)->mnemonic, label);
7364 isHandled = 1; // do not perform further optimizations
7365 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(3) conditional branch introduced")); }
7366 pic16_pCodeReplace (pc_prev, bcc);
7373 //fprintf (stderr, "(%d, too far for Bcc)\n", dist);
7379 // (4) eliminate the following (common) tripel:
7381 // labels1: Bcc label2;
7382 // GOTO somewhere; ; <-- instruction referenced by pc
7384 // and replace it by
7385 // labels1: B#(cc) somewhere; ; #(cc) is the negated condition cc
7387 // ATTENTION: all labels pointing to "Bcc label2" must be attached
7388 // to <cont.> instead
7389 // ATTENTION: This optimization is only valid if <pred.> is
7390 // not a skip operation!
7391 // ATTENTION: somewhere must be within MAX_DIST_BCC bytes!
7392 // ATTENTION: no label may be attached to the GOTO instruction!
7393 if (isConditionalBranch(pc_prev)
7394 && (!isPCI_SKIP(pic16_findPrevInstruction(pc_prev->prev)))
7395 && (dist < MAX_DIST_BCC)
7396 && isLabel(pc_next,PCI(pc_prev)->pcop->name)
7397 && hasNoLabel(pc)) {
7398 pCode *newBcc = getNegatedBcc (pc_prev, PCI(pc)->pcop);
7401 //fprintf (stderr, "%s:%d: (4) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBcc)->mnemonic, label);
7402 isHandled = 1; // do not perform further optimizations
7403 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(4) conditional skipping branch inverted")); }
7404 pic16_pCodeReplace (pc_prev, newBcc);
7409 matchedInvertRule++;
7414 /* (5) now just turn GOTO into BRA */
7415 if (!isHandled && (PCI(pc)->op == POC_GOTO)) {
7416 if (dist < MAX_DIST_BRA) {
7417 pCode *newBra = pic16_newpCode (POC_BRA, PCI(pc)->pcop);
7418 //fprintf (stderr, "%s:%d: (5) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBra)->mnemonic, label);
7419 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc->prev, pic16_newpCodeCharP("(5) GOTO replaced by BRA")); }
7420 pic16_pCodeReplace (pc, newBra);
7425 //fprintf (stderr, "(%d, too far for BRA)\n", dist);
7428 } // if (!isHandled)
7435 pBlockRemoveUnusedLabels (pb);
7437 // This line enables goto chain resolution!
7438 if (matchedInvertRule > 1) matchedInvertRule = 1; else matchedInvertRule = 0;
7441 } while (change); /* fixpoint iteration per pBlock */
7444 // emit some statistics concerning goto-optimization
7446 if (pic16_debug_verbose || pic16_pcode_verbose) {
7447 fprintf (stderr, "optimize-goto:\n"
7448 "\t%5d GOTO->BRA; (%d GOTOs too far)\n"
7449 "\t%5d BTFSx, GOTO->Bcc (%d too far)\n"
7450 "\t%5d conditional \"skipping\" jumps inverted\n"
7451 "\t%5d GOTOs to next instruction removed\n"
7452 "\t%5d chained GOTOs resolved\n",
7453 opt, toofar, opt_cond, cond_toofar, opt_reorder, opt_gotonext, opt_gotochain);
7456 //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7460 #undef MAX_JUMPCHAIN_DEPTH
7461 #undef MAX_DIST_GOTO
7465 /** END OF RAPHAEL NEIDER'S ADDITIONS **/
7467 static void pBlockDestruct(pBlock *pb)
7478 /*-----------------------------------------------------------------*/
7479 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
7480 /* name dbName and combine them */
7481 /* into one block */
7482 /*-----------------------------------------------------------------*/
7483 static void mergepBlocks(char dbName)
7486 pBlock *pb, *pbmerged = NULL,*pbn;
7488 pb = the_pFile->pbHead;
7490 //fprintf(stderr," merging blocks named %c\n",dbName);
7494 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
7495 if( getpBlock_dbName(pb) == dbName) {
7497 //fprintf(stderr," merged block %c\n",dbName);
7502 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
7503 /* pic16_addpCode2pBlock doesn't handle the tail: */
7504 pbmerged->pcTail = pb->pcTail;
7506 pb->prev->next = pbn;
7508 pbn->prev = pb->prev;
7513 //pic16_printpBlock(stderr, pbmerged);
7520 /*-----------------------------------------------------------------*/
7521 /* AnalyzeFlow - Examine the flow of the code and optimize */
7523 /* level 0 == minimal optimization */
7524 /* optimize registers that are used only by two instructions */
7525 /* level 1 == maximal optimization */
7526 /* optimize by looking at pairs of instructions that use the */
7528 /*-----------------------------------------------------------------*/
7530 static void AnalyzeFlow(int level)
7532 static int times_called=0;
7536 /* remove unused allocated registers before exiting */
7537 pic16_RemoveUnusedRegisters();
7542 /* if this is not the first time this function has been called,
7543 * then clean up old flow information */
7544 if(times_called++) {
7545 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7547 pic16_RegsUnMapLiveRanges();
7551 /* Phase 2 - Flow Analysis - Register Banking
7553 * In this phase, the individual flow blocks are examined
7554 * and register banking is fixed.
7558 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7559 pic16_FixRegisterBanking(pb);
7562 /* Phase 2 - Flow Analysis
7564 * In this phase, the pCode is partition into pCodeFlow
7565 * blocks. The flow blocks mark the points where a continuous
7566 * stream of instructions changes flow (e.g. because of
7567 * a call or goto or whatever).
7570 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7571 pic16_BuildFlow(pb);
7574 /* Phase 2 - Flow Analysis - linking flow blocks
7576 * In this phase, the individual flow blocks are examined
7577 * to determine their order of excution.
7580 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7583 /* Phase 3 - Flow Analysis - Flow Tree
7585 * In this phase, the individual flow blocks are examined
7586 * to determine their order of execution.
7589 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7590 pic16_BuildFlowTree(pb);
7593 /* Phase x - Flow Analysis - Used Banks
7595 * In this phase, the individual flow blocks are examined
7596 * to determine the Register Banks they use
7600 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7605 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7606 pic16_pCodeRegMapLiveRanges(pb);
7608 pic16_RemoveUnusedRegisters();
7610 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
7611 pic16_pCodeRegOptimizeRegUsage(level);
7620 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7625 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7628 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7629 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7630 pcflow = pcflow->next) {
7631 FillFlow(PCFL(pcflow));
7636 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7639 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7640 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7641 pcflow = pcflow->next) {
7642 FlowStats(PCFL(pcflow));
7648 /* VR -- no need to analyze banking in flow, but left here :
7649 * 1. because it may be used in the future for other purposes
7650 * 2. because if omitted we'll miss some optimization done here
7652 * Perhaps I should rename it to something else
7655 /*-----------------------------------------------------------------*/
7656 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
7657 /* assigned to the registers. */
7659 /*-----------------------------------------------------------------*/
7661 void pic16_AnalyzeBanking(void)
7665 /* Phase x - Flow Analysis - Used Banks
7667 * In this phase, the individual flow blocks are examined
7668 * to determine the Register Banks they use
7678 if(!the_pFile)return;
7680 if(!pic16_options.no_banksel) {
7681 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7682 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
7683 pic16_FixRegisterBanking(pb);
7688 /*-----------------------------------------------------------------*/
7689 /* buildCallTree - Look at the flow and extract all of the calls. */
7690 /*-----------------------------------------------------------------*/
7691 static set *register_usage(pBlock *pb);
7693 static void buildCallTree(void )
7705 /* Now build the call tree.
7706 First we examine all of the pCodes for functions.
7707 Keep in mind that the function boundaries coincide
7708 with pBlock boundaries.
7710 The algorithm goes something like this:
7711 We have two nested loops. The outer loop iterates
7712 through all of the pBlocks/functions. The inner
7713 loop iterates through all of the pCodes for
7714 a given pBlock. When we begin iterating through
7715 a pBlock, the variable pc_fstart, pCode of the start
7716 of a function, is cleared. We then search for pCodes
7717 of type PC_FUNCTION. When one is encountered, we
7718 initialize pc_fstart to this and at the same time
7719 associate a new pBranch object that signifies a
7720 branch entry. If a return is found, then this signifies
7721 a function exit point. We'll link the pCodes of these
7722 returns to the matching pc_fstart.
7724 When we're done, a doubly linked list of pBranches
7725 will exist. The head of this list is stored in
7726 `the_pFile', which is the meta structure for all
7727 of the pCode. Look at the pic16_printCallTree function
7728 on how the pBranches are linked together.
7731 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7732 pCode *pc_fstart=NULL;
7733 for(pc = pb->pcHead; pc; pc = pc->next) {
7735 if(isPCI(pc) && pc_fstart) {
7736 if(PCI(pc)->is2MemOp) {
7737 r = pic16_getRegFromInstruction2(pc);
7738 if(r && !strcmp(r->name, "POSTDEC1"))
7739 PCF(pc_fstart)->stackusage++;
7741 r = pic16_getRegFromInstruction(pc);
7742 if(r && !strcmp(r->name, "PREINC1"))
7743 PCF(pc_fstart)->stackusage--;
7748 if (PCF(pc)->fname) {
7751 sprintf(buf, "%smain", port->fun_prefix);
7752 if(STRCASECMP(PCF(pc)->fname, buf) == 0) {
7753 //fprintf(stderr," found main \n");
7754 pb->cmemmap = NULL; /* FIXME do we need to free ? */
7758 pbr = Safe_calloc(1,sizeof(pBranch));
7759 pbr->pc = pc_fstart = pc;
7762 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7764 // Here's a better way of doing the same:
7765 addSet(&pb->function_entries, pc);
7768 // Found an exit point in a function, e.g. return
7769 // (Note, there may be more than one return per function)
7771 pBranchLink(PCF(pc_fstart), PCF(pc));
7773 addSet(&pb->function_exits, pc);
7775 } else if(isCALL(pc)) {
7776 addSet(&pb->function_calls,pc);
7783 /* This is not needed because currently all register used
7784 * by a function are stored in stack -- VR */
7786 /* Re-allocate the registers so that there are no collisions
7787 * between local variables when one function call another */
7790 // pic16_deallocateAllRegs();
7792 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7800 /*-----------------------------------------------------------------*/
7801 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7802 /* all of the logical connections. */
7804 /* Essentially what's done here is that the pCode flow is */
7806 /*-----------------------------------------------------------------*/
7808 void pic16_AnalyzepCode(char dbName)
7819 /* Phase 1 - Register allocation and peep hole optimization
7821 * The first part of the analysis is to determine the registers
7822 * that are used in the pCode. Once that is done, the peep rules
7823 * are applied to the code. We continue to loop until no more
7824 * peep rule optimizations are found (or until we exceed the
7825 * MAX_PASSES threshold).
7827 * When done, the required registers will be determined.
7833 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7834 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7836 /* First, merge the labels with the instructions */
7837 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7838 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7840 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7841 //fprintf(stderr," analyze and merging block %c\n",dbName);
7842 pic16_pBlockMergeLabels(pb);
7845 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7850 changes = OptimizepCode(dbName);
7853 } while(changes && (i++ < MAX_PASSES));
7860 /* convert a series of movff's of local regs to stack, with a single call to
7861 * a support functions which does the same thing via loop */
7862 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
7866 char *fname[]={"__lr_store", "__lr_restore"};
7868 // pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
7870 pct = pic16_findNextInstruction(pcstart->next);
7873 pct = pc->next; //pic16_findNextInstruction(pc->next);
7874 // pc->print(stderr, pc);
7875 if(isPCI(pc) && PCI(pc)->label) {
7876 pbr = PCI(pc)->label;
7877 while(pbr && pbr->pc) {
7878 PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
7882 // pc->print(stderr, pc);
7884 pc->prev->next = pct;
7885 pct->prev = pc->prev;
7889 } while ((pc) && (pc != pcend));
7891 /* unlink movff instructions */
7892 pcstart->next = pcend;
7893 pcend->prev = pcstart;
7897 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7898 // pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popCopyReg(pic16_framepnt_lo)))); pc = pct;
7901 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name)))); pc = pct;
7902 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
7903 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] ))); pc = pct;
7906 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7907 // pic16_popCopyReg(pic16_framepnt_lo), pic16_popCopyReg(&pic16_pc_fsr0l)))); pc = pct;
7914 sym = newSymbol( fname[ entry?0:1 ], 0 );
7915 strcpy(sym->rname, fname[ entry?0:1 ]);
7916 checkAddSym(&externs, sym);
7918 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
7923 /*-----------------------------------------------------------------*/
7924 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for */
7925 /* local registers to a support function call */
7926 /*-----------------------------------------------------------------*/
7927 void pic16_OptimizeLocalRegs(void)
7932 pCodeOpLocalReg *pclr;
7935 regs *r, *lastr=NULL, *firstr=NULL;
7936 pCode *pcstart=NULL, *pcend=NULL;
7941 * local_regs begin mark
7942 * MOVFF r0x01, POSTDEC1
7943 * MOVFF r0x02, POSTDEC1
7946 * MOVFF r0x0n, POSTDEC1
7947 * local_regs end mark
7949 * convert the above to the below:
7950 * MOVLW starting_register_index
7952 * MOVLW register_count
7953 * call __save_registers_in_stack
7959 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7960 inRegCount = regCount = 0;
7961 firstr = lastr = NULL;
7962 for(pc = pb->pcHead; pc; pc = pc->next) {
7964 /* hold current function name */
7965 if(pc && isPCF(pc))curFunc = PCF(pc)->fname;
7967 if(pc && (pc->type == PC_INFO)) {
7970 if(pci->type == INF_LOCALREGS) {
7971 pclr = PCOLR(pci->oper1);
7973 if((pclr->type == LR_ENTRY_BEGIN)
7974 || (pclr->type == LR_ENTRY_END))inEntry = 1;
7977 switch(pclr->type) {
7978 case LR_ENTRY_BEGIN:
7980 inRegCount = 1; regCount = 0;
7981 pcstart = pc; //pic16_findNextInstruction(pc->next);
7982 firstr = lastr = NULL;
7988 pcend = pc; //pic16_findPrevInstruction(pc->prev);
7991 if(curFunc && inWparamList(curFunc+1)) {
7992 fprintf(stderr, "sdcc: %s: warning: disabling lr-support for functionn %s\n",
7996 pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
8001 firstr = lastr = NULL;
8005 if(inRegCount == -1) {
8006 // fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
8012 if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
8014 r = pic16_getRegFromInstruction(pc);
8016 r = pic16_getRegFromInstruction2(pc);
8017 if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
8018 if(!firstr)firstr = r;
8020 // fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
8032 /*-----------------------------------------------------------------*/
8033 /* ispCodeFunction - returns true if *pc is the pCode of a */
8035 /*-----------------------------------------------------------------*/
8036 static bool ispCodeFunction(pCode *pc)
8039 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
8045 /*-----------------------------------------------------------------*/
8046 /* findFunction - Search for a function by name (given the name) */
8047 /* in the set of all functions that are in a pBlock */
8048 /* (note - I expect this to change because I'm planning to limit */
8049 /* pBlock's to just one function declaration */
8050 /*-----------------------------------------------------------------*/
8051 static pCode *findFunction(char *fname)
8058 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8060 pc = setFirstItem(pb->function_entries);
8063 if((pc->type == PC_FUNCTION) &&
8065 (strcmp(fname, PCF(pc)->fname)==0))
8068 pc = setNextItem(pb->function_entries);
8076 static void MarkUsedRegisters(set *regset)
8081 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
8082 // fprintf(stderr, "marking register = %s\t", r1->name);
8083 r2 = pic16_regWithIdx(r1->rIdx);
8084 // fprintf(stderr, "to register = %s\n", r2->name);
8090 static void pBlockStats(FILE *of, pBlock *pb)
8096 if(!pic16_pcode_verbose)return;
8098 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
8100 // for now just print the first element of each set
8101 pc = setFirstItem(pb->function_entries);
8103 fprintf(of,";entry: ");
8106 pc = setFirstItem(pb->function_exits);
8108 fprintf(of,";has an exit\n");
8112 pc = setFirstItem(pb->function_calls);
8114 fprintf(of,";functions called:\n");
8117 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8118 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
8120 pc = setNextItem(pb->function_calls);
8124 r = setFirstItem(pb->tregisters);
8126 int n = elementsInSet(pb->tregisters);
8128 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
8131 fprintf(of, "; %s\n",r->name);
8132 r = setNextItem(pb->tregisters);
8136 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
8139 /*-----------------------------------------------------------------*/
8140 /*-----------------------------------------------------------------*/
8142 static void sequencepCode(void)
8148 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8150 pb->seq = GpCodeSequenceNumber+1;
8152 for( pc = pb->pcHead; pc; pc = pc->next)
8153 pc->seq = ++GpCodeSequenceNumber;
8159 /*-----------------------------------------------------------------*/
8160 /*-----------------------------------------------------------------*/
8161 static set *register_usage(pBlock *pb)
8164 set *registers=NULL;
8165 set *registersInCallPath = NULL;
8167 /* check recursion */
8169 pc = setFirstItem(pb->function_entries);
8176 if(pc->type != PC_FUNCTION)
8177 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
8179 pc = setFirstItem(pb->function_calls);
8180 for( ; pc; pc = setNextItem(pb->function_calls)) {
8182 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8183 char *dest = pic16_get_op_from_instruction(PCI(pc));
8185 pcn = findFunction(dest);
8187 registersInCallPath = register_usage(pcn->pb);
8189 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8194 pBlockStats(stderr,pb); // debug
8197 // Mark the registers in this block as used.
8199 MarkUsedRegisters(pb->tregisters);
8200 if(registersInCallPath) {
8201 /* registers were used in the functions this pBlock has called */
8202 /* so now, we need to see if these collide with the ones we are */
8205 regs *r1,*r2, *newreg;
8207 DFPRINTF((stderr,"comparing registers\n"));
8209 r1 = setFirstItem(registersInCallPath);
8212 r2 = setFirstItem(pb->tregisters);
8214 while(r2 && (r1->type != REG_STK)) {
8216 if(r2->rIdx == r1->rIdx) {
8217 newreg = pic16_findFreeReg(REG_GPR);
8221 DFPRINTF((stderr,"Bummer, no more registers.\n"));
8225 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
8226 r1->rIdx, newreg->rIdx));
8227 r2->rIdx = newreg->rIdx;
8228 //if(r2->name) Safe_free(r2->name);
8230 r2->name = Safe_strdup(newreg->name);
8234 newreg->wasUsed = 1;
8236 r2 = setNextItem(pb->tregisters);
8239 r1 = setNextItem(registersInCallPath);
8242 /* Collisions have been resolved. Now free the registers in the call path */
8243 r1 = setFirstItem(registersInCallPath);
8245 if(r1->type != REG_STK) {
8246 newreg = pic16_regWithIdx(r1->rIdx);
8249 r1 = setNextItem(registersInCallPath);
8253 // MarkUsedRegisters(pb->registers);
8255 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
8258 DFPRINTF((stderr,"returning regs\n"));
8260 DFPRINTF((stderr,"not returning regs\n"));
8262 DFPRINTF((stderr,"pBlock after register optim.\n"));
8263 pBlockStats(stderr,pb); // debug
8269 /*-----------------------------------------------------------------*/
8270 /* pct2 - writes the call tree to a file */
8272 /*-----------------------------------------------------------------*/
8273 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
8277 // set *registersInCallPath = NULL;
8283 fprintf(of, "recursive function\n");
8284 return; //recursion ?
8287 pc = setFirstItem(pb->function_entries);
8294 for(i=0;i<indent;i++) // Indentation
8298 if(pc->type == PC_FUNCTION) {
8299 usedstack += PCF(pc)->stackusage;
8300 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
8301 } else return; // ???
8304 pc = setFirstItem(pb->function_calls);
8305 for( ; pc; pc = setNextItem(pb->function_calls)) {
8307 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8308 char *dest = pic16_get_op_from_instruction(PCI(pc));
8310 pcn = findFunction(dest);
8312 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
8314 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8322 /*-----------------------------------------------------------------*/
8323 /* pic16_printCallTree - writes the call tree to a file */
8325 /*-----------------------------------------------------------------*/
8327 void pic16_printCallTree(FILE *of)
8339 fprintf(of, "\npBlock statistics\n");
8340 for(pb = the_pFile->pbHead; pb; pb = pb->next )
8344 fprintf(of,"Call Tree\n");
8345 pbr = the_pFile->functions;
8349 if(!ispCodeFunction(pc))
8350 fprintf(of,"bug in call tree");
8353 fprintf(of,"Function: %s\n", PCF(pc)->fname);
8355 while(pc->next && !ispCodeFunction(pc->next)) {
8357 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
8358 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
8366 fprintf(of,"\n**************\n\na better call tree\n");
8367 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8372 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8373 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
8379 /*-----------------------------------------------------------------*/
8381 /*-----------------------------------------------------------------*/
8383 static void InlineFunction(pBlock *pb)
8391 pc = setFirstItem(pb->function_calls);
8393 for( ; pc; pc = setNextItem(pb->function_calls)) {
8396 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8402 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
8404 //fprintf(stderr,"Cool can inline:\n");
8405 //pcn->print(stderr,pcn);
8407 //fprintf(stderr,"recursive call Inline\n");
8408 InlineFunction(pcn->pb);
8409 //fprintf(stderr,"return from recursive call Inline\n");
8412 At this point, *pc points to a CALL mnemonic, and
8413 *pcn points to the function that is being called.
8415 To in-line this call, we need to remove the CALL
8416 and RETURN(s), and link the function pCode in with
8422 /* Remove the CALL */
8426 /* remove callee pBlock from the pBlock linked list */
8427 removepBlock(pcn->pb);
8435 /* Remove the Function pCode */
8436 pct = pic16_findNextInstruction(pcn->next);
8438 /* Link the function with the callee */
8439 pc->next = pcn->next;
8440 pcn->next->prev = pc;
8442 /* Convert the function name into a label */
8444 pbr = Safe_calloc(1,sizeof(pBranch));
8445 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
8447 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
8448 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
8450 /* turn all of the return's except the last into goto's */
8451 /* check case for 2 instruction pBlocks */
8452 pce = pic16_findNextInstruction(pcn->next);
8454 pCode *pce_next = pic16_findNextInstruction(pce->next);
8456 if(pce_next == NULL) {
8457 /* found the last return */
8458 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
8460 //fprintf(stderr,"found last return\n");
8461 //pce->print(stderr,pce);
8462 pce->prev->next = pc_call->next;
8463 pc_call->next->prev = pce->prev;
8464 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
8474 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8480 /*-----------------------------------------------------------------*/
8482 /*-----------------------------------------------------------------*/
8484 void pic16_InlinepCode(void)
8493 if(!functionInlining)
8496 /* Loop through all of the function definitions and count the
8497 * number of times each one is called */
8498 //fprintf(stderr,"inlining %d\n",__LINE__);
8500 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8502 pc = setFirstItem(pb->function_calls);
8504 for( ; pc; pc = setNextItem(pb->function_calls)) {
8507 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8508 if(pcn && isPCF(pcn)) {
8509 PCF(pcn)->ncalled++;
8512 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8517 //fprintf(stderr,"inlining %d\n",__LINE__);
8519 /* Now, Loop through the function definitions again, but this
8520 * time inline those functions that have only been called once. */
8522 InlineFunction(the_pFile->pbHead);
8523 //fprintf(stderr,"inlining %d\n",__LINE__);
8525 for(pb = the_pFile->pbHead; pb; pb = pb->next)
8530 char *pic_optype_names[]={
8531 "PO_NONE", // No operand e.g. NOP
8532 "PO_W", // The working register (as a destination)
8533 "PO_WREG", // The working register (as a file register)
8534 "PO_STATUS", // The 'STATUS' register
8535 "PO_BSR", // The 'BSR' register
8536 "PO_FSR0", // The "file select register" (in PIC18 family it's one
8538 "PO_INDF0", // The Indirect register
8539 "PO_INTCON", // Interrupt Control register
8540 "PO_GPR_REGISTER", // A general purpose register
8541 "PO_GPR_BIT", // A bit of a general purpose register
8542 "PO_GPR_TEMP", // A general purpose temporary register
8543 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
8544 "PO_PCL", // Program counter Low register
8545 "PO_PCLATH", // Program counter Latch high register
8546 "PO_PCLATU", // Program counter Latch upper register
8547 "PO_PRODL", // Product Register Low
8548 "PO_PRODH", // Product Register High
8549 "PO_LITERAL", // A constant
8550 "PO_REL_ADDR", // A relative address
8551 "PO_IMMEDIATE", // (8051 legacy)
8552 "PO_DIR", // Direct memory (8051 legacy)
8553 "PO_CRY", // bit memory (8051 legacy)
8554 "PO_BIT", // bit operand.
8555 "PO_STR", // (8051 legacy)
8557 "PO_WILD" // Wild card operand in peep optimizer
8561 char *dumpPicOptype(PIC_OPTYPE type)
8563 return (pic_optype_names[ type ]);
8567 /*** BEGIN of stuff belonging to the BANKSEL optimization ***/
8570 #define MAX_COMMON_BANK_SIZE 32
8571 #define FIRST_PSEUDO_BANK_NR 1000
8573 hTab *sym2bank = NULL; // <OPERAND NAME> --> <PSEUDO BANK NR>
8574 hTab *bank2sym = NULL; // <PSEUDO BANK NR> --> <OPERAND NAME>
8575 hTab *coerce = NULL; // <PSEUDO BANK NR> --> <&PSEUDOBANK>
8578 typedef enum { INVALID_BANK = -1, UNKNOWN_BANK = -2, FIXED_BANK = -3 } pseudoBankNr;
8581 pseudoBankNr bank; // number assigned to this pseudoBank
8582 unsigned int size; // number of operands assigned to this bank
8583 unsigned int ref; // number of symbols referring to this pseudoBank (for garbage collection)
8586 /*----------------------------------------------------------------------*/
8587 /* hashSymbol - hash function used to map SYMBOLs (or operands) to ints */
8588 /*----------------------------------------------------------------------*/
8589 unsigned int hashSymbol (const char *str)
8591 unsigned int res = 0;
8596 res = (res << 4) | (res >> (8 * sizeof(unsigned int) - 4));
8603 /*-----------------------------------------------------------------------*/
8604 /* compareSymbol - return 1 iff sym1 equals sym2 */
8605 /*-----------------------------------------------------------------------*/
8606 int compareSymbol (const void *sym1, const void *sym2)
8608 char *s1 = (char*) sym1;
8609 char *s2 = (char*) sym2;
8611 return (strcmp (s1,s2) == 0);
8614 /*-----------------------------------------------------------------------*/
8615 /* comparePre - return 1 iff p1 == p2 */
8616 /*-----------------------------------------------------------------------*/
8617 int comparePtr (const void *p1, const void *p2)
8622 /*----------------------------------------------------------*/
8623 /* getSymbolFromOperand - return a pointer to the symbol in */
8624 /* the given operand and its length */
8625 /*----------------------------------------------------------*/
8626 char *getSymbolFromOperand (char *op, unsigned int *len)
8631 if (!op) return NULL;
8633 // we recognize two forms of operands: SYMBOL and (SYMBOL + offset)
8635 if (*sym == '(') sym++;
8638 while (((*curr >= 'A') && (*curr <= 'Z'))
8639 || ((*curr >= 'a') && (*curr <= 'z'))
8640 || ((curr != sym) && (*curr >= '0') && (*curr <= '9'))
8641 || (*curr == '_')) {
8642 // find end of symbol [A-Za-z_]?[A-Za-z0-9]*
8650 /*--------------------------------------------------------------------------*/
8651 /* getSymFromBank - get (one) name of a symbol assigned to the given bank */
8652 /*--------------------------------------------------------------------------*/
8653 char *getSymFromBank (pseudoBankNr bank)
8657 if (bank < 0) return "<INVALID BANK NR>";
8658 return hTabFindByKey (bank2sym, bank % bank2sym->size, (void *) bank, &comparePtr);
8661 /*-----------------------------------------------------------------------*/
8662 /* getPseudoBsrFromOperand - maps a string to its corresponding pseudo */
8663 /* bank number (uses hTab sym2bank), if the */
8664 /* symbol is not yet assigned a pseudo bank it */
8665 /* is assigned one here */
8666 /*-----------------------------------------------------------------------*/
8667 pseudoBankNr getPseudoBankNrFromOperand (const char *op)
8669 static pseudoBankNr next_bank = FIRST_PSEUDO_BANK_NR;
8675 hash = hashSymbol (op) % sym2bank->size;
8676 bank = (pseudoBankNr) hTabFindByKey (sym2bank, hash, op, &compareSymbol);
8677 if (bank == (pseudoBankNr)NULL) bank = UNKNOWN_BANK;
8679 if (bank == UNKNOWN_BANK) {
8680 // create a pseudo bank for the operand
8682 hTabAddItemLong (&sym2bank, hash, (char *)op, (void *)bank);
8683 hTabAddItemLong (&bank2sym, bank, (void *) bank, (void *)op);
8684 getOrAddGNode (adj, NULL, bank); // adds the node if it does not exist yet
8685 //fprintf (stderr, "%s:%d: adding %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8687 //fprintf (stderr, "%s:%d: found %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8695 /*--------------------------------------------------------------------*/
8696 /* isBanksel - check whether the given pCode is a BANKSEL instruction */
8697 /*--------------------------------------------------------------------*/
8698 int isBanksel (pCode *pc)
8702 if (isPCI(pc) && (PCI(pc)->op == POC_BANKSEL || PCI(pc)->op == POC_MOVLB)) {
8703 // BANKSEL <variablename> or MOVLB <banknr>
8704 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8708 // check for inline assembler BANKSELs
8709 if (isPCAD(pc) && PCAD(pc)->directive && (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0 ||
8710 STRCASECMP(PCAD(pc)->directive,"MOVLB") == 0)) {
8711 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8715 // assume pc is no BANKSEL instruction
8719 /*---------------------------------------------------------------------------------*/
8720 /* invalidatesBSR - check whether the pCodeInstruction passed in modifies the BSR */
8721 /* This method can not guarantee to find all modifications of the */
8722 /* BSR (e.g. via INDirection registers) but covers all compiler */
8723 /* generated plus some cases. */
8724 /*---------------------------------------------------------------------------------*/
8725 int invalidatesBSR(pCode *pc)
8727 // assembler directives invalidate BSR (well, they might, we don't know)
8728 if (isPCAD(pc)) return 1;
8730 // only ASMDIRs and pCodeInstructions can invalidate BSR
8731 if (!isPCI(pc)) return 0;
8733 // we have a pCodeInstruction
8735 // check for BSR modifying instructions
8736 switch (PCI(pc)->op) {
8740 case POC_RETFIE: // might be used as CALL replacement
8741 case POC_RETLW: // might be used as CALL replacement
8742 case POC_RETURN: // might be used as CALL replacement
8747 default: // other instruction do not change BSR unless BSR is an explicit operand!
8748 // TODO: check for BSR as an explicit operand (e.g. INCF BSR,F), which should be rather unlikely...!
8752 // no change of BSR possible/probable
8756 /*------------------------------------------------------------*/
8757 /* getBankFromBanksel - return the pseudo bank nr assigned to */
8758 /* the symbol referenced in this BANKSEL */
8759 /*------------------------------------------------------------*/
8760 pseudoBankNr getBankFromBanksel (pCode *pc)
8763 int data = (int)NULL;
8765 if (!pc) return INVALID_BANK;
8767 if (isPCAD(pc) && PCAD(pc)->directive) {
8768 if (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0) {
8769 // get symbolname from PCAD(pc)->arg
8770 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8771 sym = PCAD(pc)->arg;
8772 data = getPseudoBankNrFromOperand (sym);
8773 //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8774 } else if (STRCASECMP(PCAD(pc)->directive,"MOVLB")) {
8775 // get (literal) bank number from PCAD(pc)->arg
8776 fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8777 assert (0 && "not yet implemented - turn off banksel optimization for now");
8779 } else if (isPCI(pc)) {
8780 if (PCI(pc)->op == POC_BANKSEL) {
8781 // get symbolname from PCI(pc)->pcop->name (?)
8782 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8783 sym = PCI(pc)->pcop->name;
8784 data = getPseudoBankNrFromOperand (sym);
8785 //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8786 } else if (PCI(pc)->op == POC_MOVLB) {
8787 // get (literal) bank number from PCI(pc)->pcop->name
8788 fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8789 assert (0 && "not yet implemented - turn off banksel optimization for now");
8794 // no assigned bank could be found
8795 return UNKNOWN_BANK;
8800 /*------------------------------------------------------------------------------*/
8801 /* getEffectiveBank - resolves the currently assigned effective pseudo bank nr */
8802 /*------------------------------------------------------------------------------*/
8803 pseudoBankNr getEffectiveBank (pseudoBankNr bank)
8807 if (bank < FIRST_PSEUDO_BANK_NR) return bank;
8810 //fprintf (stderr, "%s:%d: bank=%d\n", __FUNCTION__, __LINE__, bank);
8811 data = (pseudoBank *) hTabFindByKey (coerce, bank % coerce->size, (void *) bank, &comparePtr);
8813 if (data->bank != bank)
8820 //fprintf (stderr, "%s:%d: effective bank=%d\n", __FUNCTION__, __LINE__, bank);
8824 /*------------------------------------------------------------------*/
8825 /* attachBsrInfo2pBlock - create a look-up table as to which pseudo */
8826 /* bank is selected at a given pCode */
8827 /*------------------------------------------------------------------*/
8829 /* Create a graph with pseudo banks as its nodes and switches between
8830 * these as edges (with the edge weight representing the absolute
8831 * number of BANKSELs from one to the other).
8832 * Removes redundand BANKSELs instead iff mod == 1.
8833 * BANKSELs update the pseudo BSR, labels invalidate the current BSR
8834 * value (setting it to 0=UNNKOWN), (R)CALLs also invalidate the
8836 * TODO: check ALL instructions operands if they modify BSR directly...
8838 * pb - the pBlock to annotate
8839 * mod - select either graph creation (0) or BANKSEL removal (1)
8841 unsigned int attachBsrInfo2pBlock (pBlock *pb, int mod)
8843 pCode *pc, *pc_next;
8844 unsigned int prevBSR = UNKNOWN_BANK, pseudoBSR = UNKNOWN_BANK;
8845 int isBankselect = 0;
8846 unsigned int banksels=0;
8850 pc = pic16_findNextInstruction(pb->pcHead);
8852 isBankselect = isBanksel (pc);
8853 pc_next = pic16_findNextInstruction (pc->next);
8855 if (!hasNoLabel (pc)) {
8856 // we don't know our predecessors -- assume different BSRs
8857 prevBSR = UNKNOWN_BANK;
8858 pseudoBSR = UNKNOWN_BANK;
8859 //fprintf (stderr, "invalidated by label at "); pc->print (stderr, pc);
8862 // check if this is a BANKSEL instruction
8864 pseudoBSR = getEffectiveBank (getBankFromBanksel(pc));
8865 //fprintf (stderr, "BANKSEL via "); pc->print (stderr, pc);
8867 if (prevBSR == pseudoBSR && pseudoBSR >= 0) {
8868 //fprintf (stderr, "removing redundant "); pc->print (stderr, pc);
8869 if (1 || pic16_pcode_verbose) pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("removed redundant BANKSEL"));
8870 pic16_unlinkpCode (pc);
8874 addGEdge2 (getOrAddGNode (adj, NULL, prevBSR), getOrAddGNode (adj, NULL, pseudoBSR), 1, 0);
8879 if (!isBankselect && invalidatesBSR(pc)) {
8880 // check if this instruction invalidates the pseudoBSR
8881 pseudoBSR = UNKNOWN_BANK;
8882 //fprintf (stderr, "invalidated via "); pc->print (stderr, pc);
8885 prevBSR = pseudoBSR;
8892 /*------------------------------------------------------------------------------------*/
8893 /* assignToSameBank - returns 0 on success or an error code */
8894 /* 1 - common bank would be too large */
8895 /* 2 - assignment to fixed (absolute) bank not performed */
8897 /* This functions assumes that unsplittable operands are already assigned to the same */
8898 /* bank (e.g. all objects being referenced as (SYMBOL + offset) must be in the same */
8899 /* bank so that we can make sure the bytes are laid out sequentially in memory) */
8900 /* TODO: Symbols with an abslute address must be handled specially! */
8901 /*------------------------------------------------------------------------------------*/
8902 int assignToSameBank (int bank0, int bank1, int doAbs)
8904 int eff0, eff1, dummy;
8905 pseudoBank *pbank0, *pbank1;
8908 eff0 = getEffectiveBank (bank0);
8909 eff1 = getEffectiveBank (bank1);
8911 //fprintf (stderr, "%s:%d: bank0=%d/%d, bank1=%d/%d, doAbs=%d\n", __FUNCTION__, __LINE__, bank0, eff0, bank1, eff1, doAbs);
8913 // nothing to do if already same bank
8914 if (eff0 == eff1) return 0;
8916 if (!doAbs && (eff0 < FIRST_PSEUDO_BANK_NR || eff1 < FIRST_PSEUDO_BANK_NR))
8919 // ensure eff0 < eff1
8921 // swap eff0 and eff1
8930 // now assign bank eff1 to bank eff0
8931 pbank0 = (pseudoBank *) hTabFindByKey (coerce, eff0 % coerce->size, (void *)((char*)0+eff0), &comparePtr);
8933 pbank0 = Safe_calloc (1, sizeof (pseudoBank));
8934 pbank0->bank = eff0;
8937 hTabAddItemLong (&coerce, eff0 % coerce->size, (void *)((char*)0+eff0), (void *) pbank0);
8941 hitem = hTabSearch (coerce, eff1 % coerce->size);
8942 while (hitem && hitem->pkey != (void *)((char*)0+eff1))
8943 hitem = hitem->next;
8945 if (hitem) pbank1 = (pseudoBank *) hitem->item;
8948 fprintf (stderr, "bank #%d/%d & bank #%d/%d --> bank #%d: %u (%s & %s)\n", bank0, eff0, bank1, eff1,
8949 pbank0->bank, pbank0->size,
8950 getSymFromBank (eff0), getSymFromBank (eff1));
8954 if (pbank0->size + pbank1->size > MAX_COMMON_BANK_SIZE) {
8956 fprintf (stderr, "bank #%d: %u, bank #%d: %u --> bank #%d': %u > %u (%s,%s)\n",
8957 pbank0->bank, pbank0->size, pbank1->bank, pbank1->size,
8958 pbank0->bank, pbank0->size + pbank1->size, MAX_COMMON_BANK_SIZE,
8959 getSymFromBank (pbank0->bank), getSymFromBank (pbank1->bank));
8963 pbank0->size += pbank1->size;
8965 if (pbank1->ref == 0) Safe_free (pbank1);
8971 hitem->item = pbank0;
8973 hTabAddItemLong (&coerce, eff1 % coerce->size, (void *)((char*)0+eff1), (void *) pbank0);
8976 //fprintf (stderr, "%s:%d: leaving.\n", __FUNCTION__, __LINE__);
8981 /*----------------------------------------------------------------*/
8982 /* mergeGraphNodes - combines two nodes into one and modifies all */
8983 /* edges to and from the nodes accordingly */
8984 /* This method needs complete backedges, i.e. if (A,B) is an edge */
8985 /* then also (B,A) must be an edge (possibly with weight 0). */
8986 /*----------------------------------------------------------------*/
8987 void mergeGraphNodes (GraphNode *node1, GraphNode *node2)
8989 GraphEdge *edge, *backedge, *nextedge;
8993 assert (node1 && node2);
8994 assert (node1 != node2);
8996 // add all edges starting at node2 to node1
8999 nextedge = edge->next;
9001 backedge = getGEdge (node, node2);
9003 backweight = backedge->weight;
9006 // insert edges (node1,node) and (node,node1)
9007 addGEdge2 (node1, node, edge->weight, backweight);
9008 // remove edges (node, node2) and (node2, node)
9009 remGEdge (node2, node);
9010 remGEdge (node, node2);
9014 // now node2 should not be referenced by any other GraphNode...
9015 //remGNode (adj, node2->data, node2->hash);
9018 /*----------------------------------------------------------------*/
9019 /* showGraph - dump the current BANKSEL graph as a node/edge list */
9020 /*----------------------------------------------------------------*/
9021 void showGraph (Graph *g)
9025 pseudoBankNr bankNr;
9032 bankNr = getEffectiveBank (node->hash);
9033 assert (bankNr >= 0);
9034 pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9036 bankNr = pbank->bank;
9042 fprintf (stderr, "edges from %s (bank %u, size %u) to:\n", getSymFromBank (node->hash), bankNr, size);
9045 if (edge->weight > 0)
9046 fprintf (stderr, " %4u x %s\n", edge->weight, getSymFromBank (edge->node->hash));
9053 /*---------------------------------------------------------------*/
9054 /* pic16_OptimizeBanksel - remove redundant BANKSEL instructions */
9055 /*---------------------------------------------------------------*/
9056 void pic16_OptimizeBanksel ()
9058 GraphNode *node, *node1, *node1next;
9061 // needed for more effective bank assignment (needs adjusted pic16_emit_usection())
9062 GraphEdge *edge, *backedge;
9064 int maxWeight, weight, mergeMore, absMaxWeight;
9065 pseudoBankNr curr0, curr1;
9068 pseudoBankNr bankNr;
9069 char *base_symbol0, *base_symbol1;
9074 unsigned int bankselsTotal = 0, bankselsRemoved = 0;
9076 //fprintf (stderr, "%s:%s:%d: entered.\n", __FILE__, __FUNCTION__, __LINE__);
9078 if (!the_pFile || !the_pFile->pbHead) return;
9080 adj = newGraph (NULL);
9081 sym2bank = newHashTable ( 255 );
9082 bank2sym = newHashTable ( 255 );
9083 coerce = newHashTable ( 255 );
9085 // create graph of BANKSEL relationships (node = operands, edge (A,B) iff BANKSEL B follows BANKSEL A)
9086 for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9087 bankselsTotal += attachBsrInfo2pBlock (pb, 0);
9091 // assign symbols with absolute addresses to their respective bank nrs
9092 set = pic16_fix_udata;
9093 for (reg = setFirstItem (set); reg; reg = setNextItem (set)) {
9094 bankNr = reg->address >> 8;
9095 node = getOrAddGNode (adj, NULL, bankNr);
9096 bankNr = (pseudoBankNr) getEffectiveBank (getPseudoBankNrFromOperand(reg->name));
9097 assignToSameBank (node->hash, bankNr, 1);
9099 assert (bankNr >= 0);
9100 pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9102 pbank = Safe_calloc (1, sizeof (pseudoBank));
9103 pbank->bank = reg->address >> 8; //FIXED_BANK;
9106 hTabAddItemLong (&coerce, bankNr % coerce->size, (void *) bankNr, pbank);
9108 assert (pbank->bank == (reg->address >> 8));
9109 pbank->bank = reg->address >> 8; //FIXED_BANK;
9111 //fprintf (stderr, "ABS: %s (%d bytes) at %x in bank %u\n", reg->name, reg->size, reg->address, bankNr);
9116 // assign operands referring to the same symbol (which is not given an absolute address) to the same bank
9117 //fprintf (stderr, "assign operands with the same symbol to the same bank\n");
9120 if (node->hash < 0) { node = node->next; continue; }
9121 base_symbol0 = getSymbolFromOperand (getSymFromBank (getEffectiveBank(node->hash)), &len0);
9124 if (node1->hash < 0) { node1 = node1->next; continue; }
9125 node1next = node1->next;
9126 base_symbol1 = getSymbolFromOperand (getSymFromBank (getEffectiveBank (node1->hash)), &len1);
9127 if (len0 == len1 && len0 > 0 && strncmp (base_symbol0, base_symbol1, len0) == 0) {
9128 // TODO: check for symbols with absolute addresses -- these might be placed across bank boundaries!
9129 //fprintf (stderr, "merging %s and %s\n", getSymFromBank (getEffectiveBank(node->hash)), getSymFromBank (getEffectiveBank(node1->hash)));
9130 if (assignToSameBank (node->hash, node1->hash, 0)) {
9131 fprintf (stderr, "%s(%d) == %s(%d)\n", base_symbol0, len0, base_symbol1, len1);
9132 assert (0 && "Could not assign a symbol to a bank!");
9134 mergeGraphNodes (node, node1);
9136 if (node->hash < node1->hash)
9137 mergeGraphNodes (node, node1);
9139 mergeGraphNodes (node1, node); // this removes node so node->next will fail...
9149 // >>> THIS ALSO NEEDS AN UPDATED pic16_emit_usection() TO REFLECT THE BANK ASSIGNMENTS <<<
9150 // assign tightly coupled operands to the same (pseudo) bank
9151 //fprintf (stderr, "assign tightly coupled operands to the same bank\n");
9159 curr0 = getEffectiveBank (node->hash);
9160 if (curr0 < 0) { node = node->next; continue; }
9163 assert (edge->src == node);
9164 backedge = getGEdge (edge->node, edge->src);
9165 weight = edge->weight + (backedge ? backedge->weight : 0);
9166 curr1 = getEffectiveBank (edge->node->hash);
9167 if (curr1 < 0) { edge = edge->next; continue; }
9169 // merging is only useful if the items are not assigned to the same bank already...
9170 if (curr0 != curr1 && weight > maxWeight) {
9171 if (maxWeight > absMaxWeight) absMaxWeight = maxWeight;
9180 if (maxWeight > 0) {
9182 fprintf (stderr, "%s:%d: merging (%4u) %d(%s) and %d(%s)\n", __FUNCTION__, __LINE__, maxWeight,
9183 max->src->hash, getSymFromBank (max->src->hash),
9184 max->node->hash, getSymFromBank (max->node->hash));
9187 node = getGNode (adj, max->src->data, max->src->hash);
9188 node1 = getGNode (adj, max->node->data, max->node->hash);
9190 if (0 == assignToSameBank (max->src->hash, max->node->hash, 0)) {
9191 if (max->src->hash < max->node->hash)
9192 mergeGraphNodes (node, node1);
9194 mergeGraphNodes (node1, node);
9196 remGEdge (node, node1);
9197 remGEdge (node1, node);
9208 // remove redundant BANKSELs
9209 //fprintf (stderr, "removing redundant BANKSELs\n");
9210 for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9211 bankselsRemoved += attachBsrInfo2pBlock (pb, 1);
9216 fprintf (stderr, "display graph\n");
9221 //fprintf (stderr, "%s:%s:%d: leaving, %u/%u BANKSELs removed...\n", __FILE__, __FUNCTION__, __LINE__, bankselsRemoved, bankselsTotal);
9224 /*** END of stuff belonging to the BANKSEL optimization ***/