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" };
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), // 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), // 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 , // 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 , // 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 // 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_newpCodeOpRegFromStr(char *name)
4255 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4256 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4257 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4258 pcop->type = PCOR(pcop)->r->pc_type;
4259 pcop->name = PCOR(pcop)->r->name;
4261 // if(pic16_pcode_verbose) {
4262 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4263 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4269 /*-----------------------------------------------------------------*/
4270 /*-----------------------------------------------------------------*/
4271 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4275 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4278 pcop->key = Safe_strdup( key );
4280 return (PCOP(pcop));
4283 /*-----------------------------------------------------------------*/
4284 /*-----------------------------------------------------------------*/
4285 pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type)
4287 pCodeOpLocalReg *pcop;
4289 pcop = Safe_calloc(1, sizeof(pCodeOpLocalReg));
4293 return (PCOP(pcop));
4297 /*-----------------------------------------------------------------*/
4298 /*-----------------------------------------------------------------*/
4300 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4307 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4311 pcop = pic16_newpCodeOpLit(-1);
4315 pcop = pic16_newpCodeOpLabel(NULL,-1);
4318 pcop = pic16_newpCodeOpReg(-1);
4321 case PO_GPR_REGISTER:
4323 pcop = pic16_newpCodeOpRegFromStr(name);
4325 pcop = pic16_newpCodeOpReg(-1);
4329 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4332 pcop->name = Safe_strdup(name);
4340 #define DB_ITEMS_PER_LINE 8
4342 typedef struct DBdata
4349 static int DBd_init = -1;
4351 /*-----------------------------------------------------------------*/
4352 /* Initialiase "DB" data buffer */
4353 /*-----------------------------------------------------------------*/
4354 void pic16_initDB(void)
4360 /*-----------------------------------------------------------------*/
4361 /* Flush pending "DB" data to a pBlock */
4363 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4364 /*-----------------------------------------------------------------*/
4365 void pic16_flushDB(char ptype, void *p)
4369 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4372 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4375 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4379 DBd.buffer[0] = '\0';
4384 /*-----------------------------------------------------------------*/
4385 /* Add "DB" directives to a pBlock */
4386 /*-----------------------------------------------------------------*/
4387 void pic16_emitDB(char c, char ptype, void *p)
4392 // we need to initialize
4395 DBd.buffer[0] = '\0';
4398 l = strlen(DBd.buffer);
4399 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4401 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4404 if (DBd.count>= DB_ITEMS_PER_LINE)
4405 pic16_flushDB(ptype, p);
4408 void pic16_emitDS(char *s, char ptype, void *p)
4413 // we need to initialize
4416 DBd.buffer[0] = '\0';
4419 l = strlen(DBd.buffer);
4420 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4422 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4424 DBd.count++; //=strlen(s);
4426 pic16_flushDB(ptype, p);
4430 /*-----------------------------------------------------------------*/
4431 /*-----------------------------------------------------------------*/
4432 void pic16_pCodeConstString(char *name, char *value)
4436 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4441 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4443 pic16_addpBlock(pb);
4445 // sprintf(buffer,"; %s = ", name);
4446 // strcat(buffer, value);
4447 // fputs(buffer, stderr);
4449 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4450 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4453 pic16_emitDB(*value, 'p', (void *)pb);
4455 pic16_flushDB('p', (void *)pb);
4458 /*-----------------------------------------------------------------*/
4459 /*-----------------------------------------------------------------*/
4461 static void pCodeReadCodeTable(void)
4465 fprintf(stderr, " %s\n",__FUNCTION__);
4467 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4469 pic16_addpBlock(pb);
4471 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4472 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4473 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4474 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4476 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4477 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4478 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4479 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4484 /*-----------------------------------------------------------------*/
4485 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4486 /*-----------------------------------------------------------------*/
4487 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4494 /* If this is the first pcode to be added to a block that
4495 * was initialized with a NULL pcode, then go ahead and
4496 * make this pcode the head and tail */
4497 pb->pcHead = pb->pcTail = pc;
4500 pb->pcTail->next = pc;
4502 pc->prev = pb->pcTail;
4509 /*-----------------------------------------------------------------*/
4510 /* pic16_addpBlock - place a pBlock into the pFile */
4511 /*-----------------------------------------------------------------*/
4512 void pic16_addpBlock(pBlock *pb)
4514 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4517 /* First time called, we'll pass through here. */
4518 //_ALLOC(the_pFile,sizeof(pFile));
4519 the_pFile = Safe_calloc(1,sizeof(pFile));
4520 the_pFile->pbHead = the_pFile->pbTail = pb;
4521 the_pFile->functions = NULL;
4525 the_pFile->pbTail->next = pb;
4526 pb->prev = the_pFile->pbTail;
4528 the_pFile->pbTail = pb;
4531 /*-----------------------------------------------------------------*/
4532 /* removepBlock - remove a pBlock from the pFile */
4533 /*-----------------------------------------------------------------*/
4534 static void removepBlock(pBlock *pb)
4542 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4544 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4547 if(pbs == the_pFile->pbHead)
4548 the_pFile->pbHead = pbs->next;
4550 if (pbs == the_pFile->pbTail)
4551 the_pFile->pbTail = pbs->prev;
4554 pbs->next->prev = pbs->prev;
4557 pbs->prev->next = pbs->next;
4564 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4568 /*-----------------------------------------------------------------*/
4569 /* printpCode - write the contents of a pCode to a file */
4570 /*-----------------------------------------------------------------*/
4571 static void printpCode(FILE *of, pCode *pc)
4582 fprintf(of,"warning - unable to print pCode\n");
4585 /*-----------------------------------------------------------------*/
4586 /* pic16_printpBlock - write the contents of a pBlock to a file */
4587 /*-----------------------------------------------------------------*/
4588 void pic16_printpBlock(FILE *of, pBlock *pb)
4596 for(pc = pb->pcHead; pc; pc = pc->next) {
4597 if(isPCF(pc) && PCF(pc)->fname) {
4598 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4599 if(pb->dbName == 'A') {
4601 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4602 // fprintf(stderr, "%s:%d testing %s <-> %s\n", __FILE__, __LINE__, PCF(pc)->fname, ab->name);
4603 if(!strcmp(ab->name, PCF(pc)->fname)) {
4604 // fprintf(stderr, "%s:%d address = %x\n", __FILE__, __LINE__, ab->address);
4605 if(ab->address != -1)
4606 fprintf(of, "\t0X%06X", ab->address);
4617 /*-----------------------------------------------------------------*/
4619 /* pCode processing */
4623 /*-----------------------------------------------------------------*/
4625 void pic16_unlinkpCode(pCode *pc)
4631 fprintf(stderr,"Unlinking: ");
4632 printpCode(stderr, pc);
4635 pc->prev->next = pc->next;
4637 pc->next->prev = pc->prev;
4639 pc->prev = pc->next = NULL;
4643 /*-----------------------------------------------------------------*/
4644 /*-----------------------------------------------------------------*/
4646 static void genericDestruct(pCode *pc)
4649 pic16_unlinkpCode(pc);
4652 /* For instructions, tell the register (if there's one used)
4653 * that it's no longer needed */
4654 regs *reg = pic16_getRegFromInstruction(pc);
4656 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4658 if(PCI(pc)->is2MemOp) {
4659 reg = pic16_getRegFromInstruction2(pc);
4661 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4665 /* Instead of deleting the memory used by this pCode, mark
4666 * the object as bad so that if there's a pointer to this pCode
4667 * dangling around somewhere then (hopefully) when the type is
4668 * checked we'll catch it.
4672 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4678 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4679 /*-----------------------------------------------------------------*/
4680 /*-----------------------------------------------------------------*/
4681 /* modifiers for constant immediate */
4682 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4684 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4689 int use_buffer = 1; // copy the string to the passed buffer pointer
4694 use_buffer = 0; // Don't bother copying the string to the buffer.
4698 switch(pcop->type) {
4706 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4709 return PCOR(pcop)->r->name;
4712 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4714 SAFE_snprintf(&buffer,&size,"%s",r->name);
4721 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4722 if(PCOI(pcop)->index) {
4723 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4724 immdmod[ PCOI(pcop)->offset ],
4728 SAFE_snprintf(&s,&size,"%s(%s)",
4729 immdmod[ PCOI(pcop)->offset ],
4733 if(PCOI(pcop)->index) {
4734 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4739 SAFE_snprintf(&s,&size, "%s(%s)",
4746 case PO_GPR_REGISTER:
4749 // size = sizeof(buffer);
4750 if( PCOR(pcop)->instance) {
4751 SAFE_snprintf(&s,&size,"(%s + %d)",
4753 PCOR(pcop)->instance );
4755 SAFE_snprintf(&s,&size,"%s",pcop->name);
4760 if(PCORB(pcop)->subtype == PO_GPR_TEMP) {
4761 SAFE_snprintf(&s, &size, "%s", pcop->name);
4763 if(PCORB(pcop)->pcor.instance)
4764 SAFE_snprintf(&s, &size, "(%s + %d)", pcop->name, PCORB(pcop)->pcor.instance);
4766 SAFE_snprintf(&s, &size, "%s", pcop->name);
4773 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4782 return "NO operand1";
4785 /*-----------------------------------------------------------------*/
4786 /* pic16_get_op2 - variant to support two memory operand commands */
4787 /*-----------------------------------------------------------------*/
4788 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4793 int use_buffer = 1; // copy the string to the passed buffer pointer
4798 use_buffer = 0; // Don't bother copying the string to the buffer.
4802 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",
4803 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4804 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4808 switch(PCOR2(pcop)->pcop2->type) {
4816 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4819 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4822 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4825 SAFE_snprintf(&buffer,&size,"%s",r->name);
4836 if(PCOI(pcop)->_const) {
4837 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4838 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4841 8 * PCOI(pcop)->offset );
4843 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4845 if( PCOI(pcop)->index) {
4846 SAFE_snprintf(&s,&size,"(%s + %d)",
4848 PCOI(pcop)->index );
4850 if(PCOI(pcop)->offset)
4851 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4853 SAFE_snprintf(&s,&size,"%s",pcop->name);
4860 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4861 SAFE_snprintf(&s,&size,"(%s + %d)",
4862 PCOR(PCOR2(pcop)->pcop2)->r->name,
4863 PCOR(PCOR2(pcop)->pcop2)->instance );
4865 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4870 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4872 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4875 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4880 return "NO operand2";
4883 /*-----------------------------------------------------------------*/
4884 /*-----------------------------------------------------------------*/
4885 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4889 return pic16_get_op(pcc->pcop,NULL,0);
4891 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4892 * return ("ERROR Null: "__FUNCTION__);
4894 return ("ERROR Null: pic16_get_op_from_instruction");
4898 /*-----------------------------------------------------------------*/
4899 /*-----------------------------------------------------------------*/
4900 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4903 fprintf(of,"pcodeopprint- not implemented\n");
4906 /*-----------------------------------------------------------------*/
4907 /* pic16_pCode2str - convert a pCode instruction to string */
4908 /*-----------------------------------------------------------------*/
4909 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4915 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4916 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4917 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4925 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4927 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4929 if(PCI(pc)->is2MemOp) {
4930 SAFE_snprintf(&s,&size, "%s, %s",
4931 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4932 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4936 if(PCI(pc)->is2LitOp) {
4937 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4941 if(PCI(pc)->isBitInst) {
4942 if(PCI(pc)->pcop->type != PO_GPR_BIT) {
4943 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4944 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4945 PCI(pc)->pcop->name ,
4946 PCI(pc)->pcop->name );
4948 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4949 // (((pCodeOpRegBit *)(PCI(pc)->pcop))->pcor.instance),
4950 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4952 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4953 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4955 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4956 //PCI(pc)->pcop->t.bit );
4959 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4960 if( PCI(pc)->num_ops == 3)
4961 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4963 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4966 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4968 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4969 if(PCI(pc)->num_ops == 3)
4970 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4972 r = pic16_getRegFromInstruction(pc);
4973 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4974 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4976 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4985 /* assuming that comment ends with a \n */
4986 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4990 SAFE_snprintf(&s,&size,"; info ==>");
4991 switch(((pCodeInfo *)pc)->type) {
4992 case INF_OPTIMIZATION:
4993 SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
4996 SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5001 /* assuming that inline code ends with a \n */
5002 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
5006 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
5009 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
5012 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
5015 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
5018 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5019 SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5020 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5023 if(PCAD(pc)->directive) {
5024 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5027 /* special case to handle inline labels without a tab */
5028 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
5033 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
5041 /*-----------------------------------------------------------------*/
5042 /* genericPrint - the contents of a pCode to a file */
5043 /*-----------------------------------------------------------------*/
5044 static void genericPrint(FILE *of, pCode *pc)
5052 // fputs(((pCodeComment *)pc)->comment, of);
5053 fprintf(of,"; %s\n", ((pCodeComment *)pc)->comment);
5058 pBranch *pbl = PCI(pc)->label;
5059 while(pbl && pbl->pc) {
5060 if(pbl->pc->type == PC_LABEL)
5061 pCodePrintLabel(of, pbl->pc);
5066 if(pic16_pcode_verbose) {
5067 fprintf(of, "; info ==>");
5068 switch(((pCodeInfo *)pc)->type) {
5069 case INF_OPTIMIZATION:
5070 fprintf(of, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
5073 fprintf(of, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5081 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
5085 // If the opcode has a label, print that first
5087 pBranch *pbl = PCI(pc)->label;
5088 while(pbl && pbl->pc) {
5089 if(pbl->pc->type == PC_LABEL)
5090 pCodePrintLabel(of, pbl->pc);
5096 genericPrint(of,PCODE(PCI(pc)->cline));
5101 pic16_pCode2str(str, 256, pc);
5103 fprintf(of,"%s",str);
5105 if(pic16_debug_verbose) {
5106 fprintf(of, "\t;key=%03x",pc->seq);
5108 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
5115 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
5116 if(PCW(pc)->pci.label)
5117 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
5119 if(PCW(pc)->operand) {
5120 fprintf(of,";\toperand ");
5121 pCodeOpPrint(of,PCW(pc)->operand );
5126 if(pic16_debug_verbose) {
5127 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
5128 if(PCFL(pc)->ancestor)
5129 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
5136 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5137 fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5138 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5144 pBranch *pbl = PCAD(pc)->pci.label;
5145 while(pbl && pbl->pc) {
5146 if(pbl->pc->type == PC_LABEL)
5147 pCodePrintLabel(of, pbl->pc);
5151 if(PCAD(pc)->directive) {
5152 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5155 /* special case to handle inline labels without tab */
5156 fprintf(of, "%s\n", PCAD(pc)->arg);
5162 fprintf(of,"unknown pCode type %d\n",pc->type);
5167 /*-----------------------------------------------------------------*/
5168 /* pCodePrintFunction - prints function begin/end */
5169 /*-----------------------------------------------------------------*/
5171 static void pCodePrintFunction(FILE *of, pCode *pc)
5178 if( ((pCodeFunction *)pc)->modname)
5179 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
5182 if(!PCF(pc)->absblock) {
5183 if(PCF(pc)->fname) {
5184 pBranch *exits = PCF(pc)->to;
5187 fprintf(of,"%s:", PCF(pc)->fname);
5189 if(pic16_pcode_verbose)
5190 fprintf(of, "\t;Function start");
5196 exits = exits->next;
5200 if(pic16_pcode_verbose)
5201 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
5204 if((PCF(pc)->from &&
5205 PCF(pc)->from->pc->type == PC_FUNCTION &&
5206 PCF(PCF(pc)->from->pc)->fname) ) {
5208 if(pic16_pcode_verbose)
5209 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
5211 if(pic16_pcode_verbose)
5212 fprintf(of,"; exit point [can't find entry point]\n");
5218 /*-----------------------------------------------------------------*/
5219 /* pCodePrintLabel - prints label */
5220 /*-----------------------------------------------------------------*/
5222 static void pCodePrintLabel(FILE *of, pCode *pc)
5229 fprintf(of,"%s:\n",PCL(pc)->label);
5230 else if (PCL(pc)->key >=0)
5231 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5233 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5236 /*-----------------------------------------------------------------*/
5237 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
5238 /* remove it if it is found. */
5239 /*-----------------------------------------------------------------*/
5240 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5247 if(pcl->type == PC_OPCODE)
5248 b = PCI(pcl)->label;
5250 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5255 //fprintf (stderr, "%s \n",__FUNCTION__);
5256 //pcl->print(stderr,pcl);
5257 //pc->print(stderr,pc);
5260 //fprintf (stderr, "found label\n");
5261 //pc->print(stderr, pc);
5265 bprev->next = b->next; /* Not first pCode in chain */
5269 PCI(pcl)->label = b->next; /* First pCode in chain */
5272 return; /* A label can't occur more than once */
5280 /*-----------------------------------------------------------------*/
5281 /*-----------------------------------------------------------------*/
5282 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5301 /*-----------------------------------------------------------------*/
5302 /* pBranchLink - given two pcodes, this function will link them */
5303 /* together through their pBranches */
5304 /*-----------------------------------------------------------------*/
5305 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5309 // Declare a new branch object for the 'from' pCode.
5311 //_ALLOC(b,sizeof(pBranch));
5312 b = Safe_calloc(1,sizeof(pBranch));
5313 b->pc = PCODE(t); // The link to the 'to' pCode.
5316 f->to = pic16_pBranchAppend(f->to,b);
5318 // Now do the same for the 'to' pCode.
5320 //_ALLOC(b,sizeof(pBranch));
5321 b = Safe_calloc(1,sizeof(pBranch));
5325 t->from = pic16_pBranchAppend(t->from,b);
5330 /*-----------------------------------------------------------------*/
5331 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5333 /*-----------------------------------------------------------------*/
5334 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5347 /*-----------------------------------------------------------------*/
5348 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5349 /*-----------------------------------------------------------------*/
5350 void pic16_pCodeUnlink(pCode *pc)
5355 if(!pc->prev || !pc->next) {
5356 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5360 /* first remove the pCode from the chain */
5361 pc->prev->next = pc->next;
5362 pc->next->prev = pc->prev;
5364 /* Now for the hard part... */
5366 /* Remove the branches */
5368 pb1 = PCI(pc)->from;
5370 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5371 * one we're unlinking */
5373 /* search for the link back to this pCode (the one we're
5375 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5376 pb2->pc = PCI(pc)->to->pc; // make the replacement
5378 /* if the pCode we're unlinking contains multiple 'to'
5379 * branches (e.g. this a skip instruction) then we need
5380 * to copy these extra branches to the chain. */
5381 if(PCI(pc)->to->next)
5382 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5391 /*-----------------------------------------------------------------*/
5392 /*-----------------------------------------------------------------*/
5394 static void genericAnalyze(pCode *pc)
5404 // Go through the pCodes that are in pCode chain and link
5405 // them together through the pBranches. Note, the pCodes
5406 // are linked together as a contiguous stream like the
5407 // assembly source code lines. The linking here mimics this
5408 // except that comments are not linked in.
5410 pCode *npc = pc->next;
5412 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5413 pBranchLink(pc,npc);
5418 /* reached the end of the pcode chain without finding
5419 * an instruction we could link to. */
5423 fprintf(stderr,"analyze PC_FLOW\n");
5427 fprintf(stderr,,";A bad pCode is being used\n");
5433 /*-----------------------------------------------------------------*/
5434 /*-----------------------------------------------------------------*/
5435 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5439 if(pc->type == PC_LABEL) {
5440 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5443 if((pc->type == PC_OPCODE)
5444 || (pc->type == PC_ASMDIR)
5446 pbr = PCI(pc)->label;
5448 if(pbr->pc->type == PC_LABEL) {
5449 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5459 /*-----------------------------------------------------------------*/
5460 /*-----------------------------------------------------------------*/
5461 static int checkLabel(pCode *pc)
5465 if(pc && isPCI(pc)) {
5466 pbr = PCI(pc)->label;
5468 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5478 /*-----------------------------------------------------------------*/
5479 /* findLabelinpBlock - Search the pCode for a particular label */
5480 /*-----------------------------------------------------------------*/
5481 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5488 for(pc = pb->pcHead; pc; pc = pc->next)
5489 if(compareLabel(pc,pcop_label))
5495 /*-----------------------------------------------------------------*/
5496 /* findLabel - Search the pCode for a particular label */
5497 /*-----------------------------------------------------------------*/
5498 static pCode * findLabel(pCodeOpLabel *pcop_label)
5506 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5507 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5511 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5515 /*-----------------------------------------------------------------*/
5516 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5517 /* in the linked list */
5518 /*-----------------------------------------------------------------*/
5519 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5532 /*-----------------------------------------------------------------*/
5533 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5534 /* in the linked list */
5535 /*-----------------------------------------------------------------*/
5536 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5550 //#define PCODE_DEBUG
5551 /*-----------------------------------------------------------------*/
5552 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5553 /* in the linked list */
5554 /*-----------------------------------------------------------------*/
5555 pCode * pic16_findNextInstruction(pCode *pci)
5560 if((pc->type == PC_OPCODE)
5561 || (pc->type == PC_WILD)
5562 || (pc->type == PC_ASMDIR)
5567 fprintf(stderr,"pic16_findNextInstruction: ");
5568 printpCode(stderr, pc);
5573 //fprintf(stderr,"Couldn't find instruction\n");
5577 /*-----------------------------------------------------------------*/
5578 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5579 /* in the linked list */
5580 /*-----------------------------------------------------------------*/
5581 pCode * pic16_findPrevInstruction(pCode *pci)
5587 if((pc->type == PC_OPCODE)
5588 || (pc->type == PC_WILD)
5589 || (pc->type == PC_ASMDIR)
5595 fprintf(stderr,"pic16_findPrevInstruction: ");
5596 printpCode(stderr, pc);
5601 //fprintf(stderr,"Couldn't find instruction\n");
5608 /*-----------------------------------------------------------------*/
5609 /* findFunctionEnd - given a pCode find the end of the function */
5610 /* that contains it */
5611 /*-----------------------------------------------------------------*/
5612 static pCode * findFunctionEnd(pCode *pc)
5616 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5622 fprintf(stderr,"Couldn't find function end\n");
5627 /*-----------------------------------------------------------------*/
5628 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5629 /* instruction with which it is associated. */
5630 /*-----------------------------------------------------------------*/
5631 static void AnalyzeLabel(pCode *pc)
5634 pic16_pCodeUnlink(pc);
5640 static void AnalyzeGOTO(pCode *pc)
5643 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5647 static void AnalyzeSKIP(pCode *pc)
5650 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5651 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5655 static void AnalyzeRETURN(pCode *pc)
5658 // branch_link(pc,findFunctionEnd(pc->next));
5664 /*-----------------------------------------------------------------*/
5665 /*-----------------------------------------------------------------*/
5666 regs * pic16_getRegFromInstruction(pCode *pc)
5672 PCI(pc)->num_ops == 0 ||
5673 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5677 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5678 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5681 switch(PCI(pc)->pcop->type) {
5687 return PCOR(PCI(pc)->pcop)->r;
5691 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5692 return PCOR(PCI(pc)->pcop)->r;
5695 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5697 if(PCOI(PCI(pc)->pcop)->r)
5698 return (PCOI(PCI(pc)->pcop)->r);
5703 return PCOR(PCI(pc)->pcop)->r;
5705 case PO_GPR_REGISTER:
5707 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5708 return PCOR(PCI(pc)->pcop)->r;
5711 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5715 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5716 // genericPrint(stderr, pc);
5724 /*-------------------------------------------------------------------------------*/
5725 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5726 /*-------------------------------------------------------------------------------*/
5727 regs * pic16_getRegFromInstruction2(pCode *pc)
5733 PCI(pc)->num_ops == 0 ||
5734 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5739 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5740 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5744 * operands supported in MOVFF:
5751 switch(PCI(pc)->pcop->type) {
5757 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5759 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5763 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5764 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5768 // if(PCOI(PCI(pc)->pcop)->r)
5769 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5771 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5772 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5775 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5776 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5783 // return PCOR2(PCI(pc)->pcop)->r;
5785 case PO_GPR_REGISTER:
5787 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5788 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5792 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5795 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5796 //genericPrint(stderr, pc);
5804 /*-----------------------------------------------------------------*/
5805 /*-----------------------------------------------------------------*/
5807 static void AnalyzepBlock(pBlock *pb)
5814 /* Find all of the registers used in this pBlock
5815 * by looking at each instruction and examining it's
5818 for(pc = pb->pcHead; pc; pc = pc->next) {
5820 /* Is this an instruction with operands? */
5821 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5823 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5825 /* Loop through all of the registers declared so far in
5826 this block and see if we find this one there */
5828 regs *r = setFirstItem(pb->tregisters);
5831 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5832 PCOR(PCI(pc)->pcop)->r = r;
5835 r = setNextItem(pb->tregisters);
5839 /* register wasn't found */
5840 //r = Safe_calloc(1, sizeof(regs));
5841 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5842 //addSet(&pb->tregisters, r);
5843 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5844 //PCOR(PCI(pc)->pcop)->r = r;
5845 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5847 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5850 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5851 if(PCOR(PCI(pc)->pcop)->r) {
5852 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5853 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5855 if(PCI(pc)->pcop->name)
5856 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5858 fprintf(stderr,"ERROR: NULL register\n");
5867 /*-----------------------------------------------------------------*/
5869 /*-----------------------------------------------------------------*/
5870 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5872 static void InsertpFlow(pCode *pc, pCode **pflow)
5875 PCFL(*pflow)->end = pc;
5877 if(!pc || !pc->next)
5880 *pflow = pic16_newpCodeFlow();
5881 pic16_pCodeInsertAfter(pc, *pflow);
5884 /*-----------------------------------------------------------------*/
5885 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5886 /* the flow blocks. */
5888 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5889 * point the instruction flow changes.
5891 /*-----------------------------------------------------------------*/
5892 void pic16_BuildFlow(pBlock *pb)
5895 pCode *last_pci=NULL;
5902 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5903 /* Insert a pCodeFlow object at the beginning of a pBlock */
5905 InsertpFlow(pb->pcHead, &pflow);
5907 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5908 //pflow->next = pb->pcHead; /* Make the current head the next object */
5909 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5910 //pb->pcHead = pflow; /* Make the Flow object the head */
5913 for( pc = pic16_findNextInstruction(pb->pcHead);
5915 pc=pic16_findNextInstruction(pc)) {
5918 PCI(pc)->pcflow = PCFL(pflow);
5920 //fprintf(stderr," build: ");
5921 //pflow->print(stderr,pflow);
5923 if( PCI(pc)->isSkip) {
5925 /* The two instructions immediately following this one
5926 * mark the beginning of a new flow segment */
5928 while(pc && PCI(pc)->isSkip) {
5930 PCI(pc)->pcflow = PCFL(pflow);
5934 InsertpFlow(pc, &pflow);
5935 pc=pic16_findNextInstruction(pc->next);
5943 PCI(pc)->pcflow = PCFL(pflow);
5945 InsertpFlow(pc, &pflow);
5947 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5949 InsertpFlow(pc, &pflow);
5952 } else if (checkLabel(pc)) {
5954 /* This instruction marks the beginning of a
5955 * new flow segment */
5960 /* If the previous pCode is not a flow object, then
5961 * insert a new flow object. (This check prevents
5962 * two consecutive flow objects from being insert in
5963 * the case where a skip instruction preceeds an
5964 * instruction containing a label.) */
5966 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5967 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5969 PCI(pc)->pcflow = PCFL(pflow);
5976 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5978 PCFL(pflow)->end = pb->pcTail;
5981 /*-------------------------------------------------------------------*/
5982 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5983 /* the flow blocks. */
5985 * unBuildFlow removes pCodeFlow objects from a pCode chain
5987 /*-----------------------------------------------------------------*/
5988 static void unBuildFlow(pBlock *pb)
6003 if(PCI(pc)->pcflow) {
6004 //free(PCI(pc)->pcflow);
6005 PCI(pc)->pcflow = NULL;
6008 } else if(isPCFL(pc) )
6017 /*-----------------------------------------------------------------*/
6018 /*-----------------------------------------------------------------*/
6019 static void dumpCond(int cond)
6022 static char *pcc_str[] = {
6036 int ncond = sizeof(pcc_str) / sizeof(char *);
6039 fprintf(stderr, "0x%04X\n",cond);
6041 for(i=0,j=1; i<ncond; i++, j<<=1)
6043 fprintf(stderr, " %s\n",pcc_str[i]);
6049 /*-----------------------------------------------------------------*/
6050 /*-----------------------------------------------------------------*/
6051 static void FlowStats(pCodeFlow *pcflow)
6059 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
6061 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6064 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
6069 fprintf(stderr, " FlowStats inCond: ");
6070 dumpCond(pcflow->inCond);
6071 fprintf(stderr, " FlowStats outCond: ");
6072 dumpCond(pcflow->outCond);
6076 /*-----------------------------------------------------------------*
6077 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
6078 * if it affects the banking bits.
6080 * return: -1 == Banking bits are unaffected by this pCode.
6082 * return: > 0 == Banking bits are affected.
6084 * If the banking bits are affected, then the returned value describes
6085 * which bits are affected and how they're affected. The lower half
6086 * of the integer maps to the bits that are affected, the upper half
6087 * to whether they're set or cleared.
6089 *-----------------------------------------------------------------*/
6091 static int isBankInstruction(pCode *pc)
6099 if( PCI(pc)->op == POC_MOVLB ||
6100 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
6101 bank = PCOL(pc)->lit;
6108 /*-----------------------------------------------------------------*/
6109 /*-----------------------------------------------------------------*/
6110 static void FillFlow(pCodeFlow *pcflow)
6119 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
6121 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6124 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
6131 isBankInstruction(pc);
6133 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
6137 fprintf(stderr, " FillFlow - Bad end of flow\n");
6139 fprintf(stderr, " FillFlow - Ending flow with\n ");
6140 pc->print(stderr,pc);
6143 fprintf(stderr, " FillFlow inCond: ");
6144 dumpCond(pcflow->inCond);
6145 fprintf(stderr, " FillFlow outCond: ");
6146 dumpCond(pcflow->outCond);
6150 /*-----------------------------------------------------------------*/
6151 /*-----------------------------------------------------------------*/
6152 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
6154 pCodeFlowLink *fromLink, *toLink;
6156 if(!from || !to || !to->pcflow || !from->pcflow)
6159 fromLink = pic16_newpCodeFlowLink(from->pcflow);
6160 toLink = pic16_newpCodeFlowLink(to->pcflow);
6162 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
6163 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
6167 /*-----------------------------------------------------------------*
6168 * void LinkFlow(pBlock *pb)
6170 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
6171 * non-branching segments. In LinkFlow, we determine the execution
6172 * order of these segments. For example, if one of the segments ends
6173 * with a skip, then we know that there are two possible flow segments
6174 * to which control may be passed.
6175 *-----------------------------------------------------------------*/
6176 static void LinkFlow(pBlock *pb)
6182 //fprintf(stderr,"linkflow \n");
6184 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6186 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6189 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
6191 //fprintf(stderr," link: ");
6192 //pcflow->print(stderr,pcflow);
6194 //FillFlow(PCFL(pcflow));
6196 pc = PCFL(pcflow)->end;
6198 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
6199 if(isPCI_SKIP(pc)) {
6200 //fprintf(stderr, "ends with skip\n");
6201 //pc->print(stderr,pc);
6202 pct=pic16_findNextInstruction(pc->next);
6203 LinkFlow_pCode(PCI(pc),PCI(pct));
6204 pct=pic16_findNextInstruction(pct->next);
6205 LinkFlow_pCode(PCI(pc),PCI(pct));
6209 if(isPCI_BRANCH(pc)) {
6210 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6212 //fprintf(stderr, "ends with branch\n ");
6213 //pc->print(stderr,pc);
6215 if(!(pcol && isPCOLAB(pcol))) {
6216 if((PCI(pc)->op != POC_RETLW)
6217 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
6219 /* continue if label is '$' which assembler knows how to parse */
6220 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6222 if(pic16_pcode_verbose) {
6223 pc->print(stderr,pc);
6224 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6230 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6231 LinkFlow_pCode(PCI(pc),PCI(pct));
6233 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6234 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6236 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6242 //fprintf(stderr, "ends with non-branching instruction:\n");
6243 //pc->print(stderr,pc);
6245 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6251 //fprintf(stderr, "ends with unknown\n");
6252 //pc->print(stderr,pc);
6256 //fprintf(stderr, "ends with nothing: ERROR\n");
6260 /*-----------------------------------------------------------------*/
6261 /*-----------------------------------------------------------------*/
6263 /*-----------------------------------------------------------------*/
6264 /*-----------------------------------------------------------------*/
6265 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6271 if((!isPCI(pc) && !isPCAD(pc)) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6274 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6284 /*-----------------------------------------------------------------*/
6285 /* insertBankSwitch - inserts a bank switch statement in the */
6286 /* assembly listing */
6288 /* position == 0: insert before */
6289 /* position == 1: insert after pc */
6290 /* position == 2: like 0 but previous was a skip instruction */
6291 /*-----------------------------------------------------------------*/
6292 pCodeOp *pic16_popGetLabel(unsigned int key);
6293 extern int pic16_labelOffset;
6295 static void insertBankSwitch(unsigned char position, pCode *pc)
6302 /* emit BANKSEL [symbol] */
6305 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6307 // position = 0; // position is always before (sanity check!)
6310 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6311 pc->print(stderr, pc);
6316 /* insert the bank switch after this pc instruction */
6317 pCode *pcnext = pic16_findNextInstruction(pc);
6319 pic16_pCodeInsertAfter(pc, new_pc);
6320 if(pcnext)pc = pcnext;
6324 /* insert the bank switch BEFORE this pc instruction */
6325 pic16_pCodeInsertAfter(pc->prev, new_pc);
6330 pCode *pcnext, *pcprev, *npci, *ppc;
6332 int ofs1=0, ofs2=0, len=0;
6334 /* just like 0, but previous was a skip instruction,
6335 * so some care should be taken */
6337 pic16_labelOffset += 10000;
6338 tlbl = newiTempLabel(NULL);
6340 /* invert skip instruction */
6341 pcprev = pic16_findPrevInstruction(pc->prev);
6342 ipci = PCI(pcprev)->inverted_op;
6343 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6345 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6347 /* copy info from old pCode */
6348 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6349 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6350 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6351 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6352 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6353 PCI(npci)->op = PCI(pcprev)->inverted_op;
6355 /* unlink old pCode */
6357 ppc->next = pcprev->next;
6358 pcprev->next->prev = ppc;
6359 pic16_pCodeInsertAfter(ppc, npci);
6361 /* extra instructions to handle invertion */
6362 pcnext = pic16_newpCode(POC_BRA, pic16_popGetLabel(tlbl->key));
6363 pic16_pCodeInsertAfter(npci, pcnext);
6364 pic16_pCodeInsertAfter(pc->prev, new_pc);
6366 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6367 pic16_pCodeInsertAfter(pc, pcnext);
6372 /* Move the label, if there is one */
6373 if(PCI(pc)->label) {
6374 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6375 // __FILE__, __LINE__, pc, new_pc);
6376 PCAD(new_pc)->pci.label = PCI(pc)->label;
6377 PCI(pc)->label = NULL;
6382 /*-----------------------------------------------------------------*/
6383 /*int compareBankFlow - compare the banking requirements between */
6385 /*-----------------------------------------------------------------*/
6386 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6389 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6392 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6395 if(pcflow->firstBank == -1)
6399 if(pcflowLink->pcflow->firstBank == -1) {
6400 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6401 pcflowLink->pcflow->to :
6402 pcflowLink->pcflow->from);
6403 return compareBankFlow(pcflow, pctl, toORfrom);
6407 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6410 pcflowLink->bank_conflict++;
6411 pcflowLink->pcflow->FromConflicts++;
6412 pcflow->ToConflicts++;
6415 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6418 pcflowLink->bank_conflict++;
6419 pcflowLink->pcflow->ToConflicts++;
6420 pcflow->FromConflicts++;
6424 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6425 pcflowLink->pcflow->pc.seq,
6426 pcflowLink->pcflow->FromConflicts,
6427 pcflowLink->pcflow->ToConflicts);
6434 /*-----------------------------------------------------------------*/
6435 /*-----------------------------------------------------------------*/
6436 static void DumpFlow(pBlock *pb)
6440 pCodeFlowLink *pcfl;
6443 fprintf(stderr,"Dump flow \n");
6444 pb->pcHead->print(stderr, pb->pcHead);
6446 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6447 pcflow->print(stderr,pcflow);
6449 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6451 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6453 if(!isPCFL(pcflow)) {
6454 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6457 fprintf(stderr,"dumping: ");
6458 pcflow->print(stderr,pcflow);
6459 FlowStats(PCFL(pcflow));
6461 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6463 pc = PCODE(pcfl->pcflow);
6465 fprintf(stderr, " from seq %d:\n",pc->seq);
6467 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6468 pc->print(stderr,pc);
6473 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6475 pc = PCODE(pcfl->pcflow);
6477 fprintf(stderr, " to seq %d:\n",pc->seq);
6479 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6480 pc->print(stderr,pc);
6489 /*-----------------------------------------------------------------*/
6490 /*-----------------------------------------------------------------*/
6491 static int OptimizepBlock(pBlock *pb)
6496 if(!pb || !peepOptimizing)
6499 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6501 for(pc = pb->pcHead; pc; pc = pc->next)
6502 matches += pic16_pCodePeepMatchRule(pc);
6505 pc = pic16_findNextInstruction(pb->pcHead);
6513 if(pic16_pCodePeepMatchRule(pc)) {
6518 pc = pic16_findNextInstruction(pcprev->next);
6520 pc = pic16_findNextInstruction(pb->pcHead);
6522 pc = pic16_findNextInstruction(pc->next);
6526 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6531 /*-----------------------------------------------------------------*/
6532 /*-----------------------------------------------------------------*/
6533 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6537 for(pc = pcs; pc; pc = pc->next) {
6539 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6541 (PCI(pc)->pcop->type == PO_LABEL) &&
6542 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6550 /*-----------------------------------------------------------------*/
6551 /*-----------------------------------------------------------------*/
6552 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6559 (PCI(pc)->pcop->type == PO_LABEL)) {
6561 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6563 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6564 // if(pcol->pcop.name)
6565 // free(pcol->pcop.name);
6567 /* If the key is negative, then we (probably) have a label to
6568 * a function and the name is already defined */
6571 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6575 //sprintf(buffer,"_%05d_DS_",pcl->key);
6577 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6579 pcol->pcop.name = Safe_strdup(s);
6580 pcol->key = pcl->key;
6581 //pc->print(stderr,pc);
6588 /*-----------------------------------------------------------------*/
6589 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6590 /* pCode chain if they're not used. */
6591 /*-----------------------------------------------------------------*/
6592 static void pBlockRemoveUnusedLabels(pBlock *pb)
6594 pCode *pc; pCodeLabel *pcl;
6599 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6601 pBranch *pbr = PCI(pc)->label;
6602 if(pbr && pbr->next) {
6603 pCode *pcd = pb->pcHead;
6605 // fprintf(stderr, "multiple labels\n");
6606 // pc->print(stderr,pc);
6611 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6612 //fprintf(stderr,"Used by:\n");
6613 //pcd->print(stderr,pcd);
6615 exchangeLabels(PCL(pbr->pc),pcd);
6624 for(pc = pb->pcHead; pc; pc = pc->next) {
6626 if(isPCL(pc)) // pc->type == PC_LABEL)
6628 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6629 pcl = PCL(PCI(pc)->label->pc);
6632 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6634 /* This pCode is a label, so search the pBlock to see if anyone
6637 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6639 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6640 /* Couldn't find an instruction that refers to this label
6641 * So, unlink the pCode label from it's pCode chain
6642 * and destroy the label */
6643 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6645 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6646 if(pc->type == PC_LABEL) {
6647 pic16_unlinkpCode(pc);
6648 pCodeLabelDestruct(pc);
6650 unlinkpCodeFromBranch(pc, PCODE(pcl));
6651 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6662 /*-----------------------------------------------------------------*/
6663 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6664 /* chain and put them into pBranches that are */
6665 /* associated with the appropriate pCode */
6667 /*-----------------------------------------------------------------*/
6668 void pic16_pBlockMergeLabels(pBlock *pb)
6671 pCode *pc, *pcnext=NULL;
6676 /* First, Try to remove any unused labels */
6677 //pBlockRemoveUnusedLabels(pb);
6679 /* Now loop through the pBlock and merge the labels with the opcodes */
6682 // for(pc = pb->pcHead; pc; pc = pc->next) {
6685 pCode *pcn = pc->next;
6687 if(pc->type == PC_LABEL) {
6689 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6690 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6692 if((pcnext = pic16_findNextInstruction(pc) )) {
6694 // pcnext->print(stderr, pcnext);
6696 // Unlink the pCode label from it's pCode chain
6697 pic16_unlinkpCode(pc);
6699 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6700 // And link it into the instruction's pBranch labels. (Note, since
6701 // it's possible to have multiple labels associated with one instruction
6702 // we must provide a means to accomodate the additional labels. Thus
6703 // the labels are placed into the singly-linked list "label" as
6704 // opposed to being a single member of the pCodeInstruction.)
6706 //_ALLOC(pbr,sizeof(pBranch));
6708 pbr = Safe_calloc(1,sizeof(pBranch));
6712 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6715 if(pic16_pcode_verbose)
6716 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6718 } else if(pc->type == PC_CSOURCE) {
6720 /* merge the source line symbolic info into the next instruction */
6721 if((pcnext = pic16_findNextInstruction(pc) )) {
6723 // Unlink the pCode label from it's pCode chain
6724 pic16_unlinkpCode(pc);
6725 PCI(pcnext)->cline = PCCS(pc);
6726 //fprintf(stderr, "merging CSRC\n");
6727 //genericPrint(stderr,pcnext);
6733 pBlockRemoveUnusedLabels(pb);
6737 /*-----------------------------------------------------------------*/
6738 /*-----------------------------------------------------------------*/
6739 static int OptimizepCode(char dbName)
6741 #define MAX_PASSES 4
6750 DFPRINTF((stderr," Optimizing pCode\n"));
6754 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6755 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6756 matches += OptimizepBlock(pb);
6759 while(matches && ++passes < MAX_PASSES);
6766 const char *pic16_pCodeOpType(pCodeOp *pcop);
6767 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6770 /*-----------------------------------------------------------------*/
6771 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6772 /*-----------------------------------------------------------------*/
6774 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6778 // fprintf(stderr, "%s:%d pc type: %s\tname: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc), pc->name);
6781 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6783 if(PCOR(pc)->r)pcop = pic16_newpCodeOpBit(PCOR(pc)->r->name, bitval, 0, pc->type);
6786 assert(pcop != NULL);
6788 if( !( (pcop->type == PO_LABEL) ||
6789 (pcop->type == PO_LITERAL) ||
6790 (pcop->type == PO_STR) ))
6791 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6792 PCOR(pcop)->r->wasUsed = 1;
6793 PCOR(pcop)->instance = PCOR(pc)->instance;
6799 /*----------------------------------------------------------------------*
6800 * pic16_areRegsSame - check to see if the names of two registers match *
6801 *----------------------------------------------------------------------*/
6802 int pic16_areRegsSame(regs *r1, regs *r2)
6804 if(!strcmp(r1->name, r2->name))return 1;
6810 /*-----------------------------------------------------------------*/
6811 /*-----------------------------------------------------------------*/
6812 static void pic16_FixRegisterBanking(pBlock *pb)
6816 regs *reg, *prevreg;
6817 unsigned char flag=0;
6822 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6825 /* loop through all of the flow blocks with in one pblock */
6827 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6831 /* at this point, pc should point to a PC_FLOW object */
6832 /* for each flow block, determine the register banking
6836 /* if label, then might come from other point, force banksel */
6837 if(isPCL(pc))prevreg = NULL;
6839 if(!isPCI(pc))goto loop;
6841 if(PCI(pc)->label)prevreg = NULL;
6843 if(PCI(pc)->is2MemOp)goto loop;
6845 /* if goto, then force banksel */
6846 // if(PCI(pc)->op == POC_GOTO)prevreg = NULL;
6848 reg = pic16_getRegFromInstruction(pc);
6851 pc->print(stderr, pc);
6852 fprintf(stderr, "reg = %p\n", reg);
6855 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6856 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6857 reg->address,reg->isBitField, reg->isFixed);
6861 /* now make some tests to make sure that instruction needs bank switch */
6863 /* if no register exists, and if not a bit opcode goto loop */
6865 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6868 if(isPCI_SKIP(pc)) {
6869 // fprintf(stderr, "instruction is SKIP instruction\n");
6872 if(reg && isACCESS_BANK(reg))goto loop;
6874 if(!isBankInstruction(pc))goto loop;
6876 if(isPCI_LIT(pc))goto loop;
6878 if(PCI(pc)->op == POC_CALL)goto loop;
6880 /* Examine the instruction before this one to make sure it is
6881 * not a skip type instruction */
6882 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6884 flag = 0; /* add before this instruction */
6886 /* if previous instruction is a skip one, then set flag
6887 * to 2 and call insertBankSwitch */
6888 if(pcprev && isPCI_SKIP(pcprev)) {
6893 if(pic16_options.opt_banksel>0) {
6894 char op1[128], op2[128];
6897 strcpy(op1, pic16_get_op_from_instruction(PCI(pc)));
6898 strcpy(op2, pic16_get_op_from_instruction(PCI(pcprev)));
6899 if(!strcmp(op1, op2))goto loop;
6903 insertBankSwitch(flag, pc);
6905 // fprintf(stderr, "BANK SWITCH inserted\n");
6913 /** ADDITIONS BY RAPHAEL NEIDER, 2004-11-16: GOTO OPTIMIZATIONS **/
6915 /* Returns the (maximum of the) number of bytes used by the specified pCode. */
6916 int instrSize (pCode *pc)
6921 if (!PCAD(pc)->directive || strlen (PCAD(pc)->directive) < 3) return 0;
6922 return 4; // assumes only regular instructions using <= 4 bytes
6925 if (isPCI(pc)) return PCI(pc)->isize;
6930 /* Returns 1 if pc is referenced by the given label (either
6931 * pc is the label itself or is an instruction with an attached
6933 * Returns 0 if pc is not preceeded by the specified label.
6935 int isLabel (pCode *pc, char *label)
6939 // label attached to the pCode?
6940 if (isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO) {
6941 pBranch *lab = NULL;
6942 lab = PCI(pc)->label;
6945 if (isPCL(lab->pc) && strcmp(PCL(lab->pc)->label, label) == 0) {
6952 // is inline assembly label?
6953 if (isPCAD(pc) && PCAD(pc)->directive == NULL && PCAD(pc)->arg) {
6954 // do not compare trailing ':'
6955 if (strncmp (PCAD(pc)->arg, label, strlen (label)) == 0) {
6962 if (strcmp(PCL(pc)->label,label) == 0) {
6967 // no label/no label attached/wrong label(s)
6971 /* Returns the distance to the given label in terms of words.
6972 * Labels are searched only within -max .. max words from pc.
6973 * Returns max if the label could not be found or
6974 * its distance from pc in (-max..+max).
6976 int findpCodeLabel (pCode *pc, char *label, int max, pCode **target) {
6977 int dist = instrSize(pc);
6981 while (dist < max && curr && !isLabel (curr, label)) {
6983 dist += instrSize(curr); // sizeof (instruction)
6985 if (curr && dist < max) {
6986 if (target != NULL) *target = curr;
6991 curr = pic16_findNextInstruction (pc->next);
6993 while (dist < max && curr && !isLabel (curr, label)) {
6994 dist += instrSize(curr); // sizeof (instruction)
6997 if (curr && dist < max) {
6998 if (target != NULL) *target = curr;
7002 if (target != NULL) *target = NULL;
7006 /* Returns -1 if pc does NOT denote an instruction like
7008 * Otherwise we return
7009 * (a) 0x10 + i for BTFSS
7010 * (b) 0x00 + i for BTFSC
7012 int isSkipOnStatus (pCode *pc)
7016 if (!pc || !isPCI(pc)) return -1;
7017 if (PCI(pc)->op == POC_BTFSS) res = 0x10;
7018 else if (PCI(pc)->op == POC_BTFSC) res = 0x00;
7021 pcop = PCI(pc)->pcop;
7023 if (pcop->type == PO_STATUS || (pcop->type == PO_GPR_BIT && strcmp(pcop->name, "STATUS") == 0)) {
7024 return res + ((pCodeOpRegBit *)pcop)->bit;
7030 /* Returns 1 if pc is one of BC, BZ, BOV, BN, BNC, BNZ, BNOV or BNN,
7031 * returns 0 otherwise. */
7032 int isConditionalBranch (pCode *pc)
7034 if (!pc || !isPCI_BRANCH(pc)) return 0;
7036 switch (PCI(pc)->op) {
7054 /* Returns 1 if pc has a label attached to it.
7055 * This can be either a label stored in the pCode itself (.label)
7056 * or a label making up its own pCode preceding this pc.
7057 * Returns 0 if pc cannot be reached directly via a label.
7059 int hasNoLabel (pCode *pc)
7064 // are there any label pCodes between pc and the previous instruction?
7065 prev = pic16_findPrevInstruction (pc->prev);
7066 while (pc && pc != prev) {
7067 // pCode with attached label?
7068 if ((isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO)
7069 && PCI(pc)->label) {
7072 // is inline assembly label?
7073 if (isPCAD(pc) && PCAD(pc)->directive == NULL) return 0;
7074 if (isPCW(pc) && PCW(pc)->label) return 0;
7077 if (isPCL(pc)) return 0;
7086 /* Replaces the old pCode with the new one, moving the labels,
7087 * C source line and probably flow information to the new pCode.
7089 void pic16_pCodeReplace (pCode *oldPC, pCode *newPC) {
7090 if (!oldPC || !newPC || !isPCI(oldPC) || !isPCI(newPC))
7093 /* first move all labels from old to new */
7094 PCI(newPC)->label = pic16_pBranchAppend (PCI(oldPC)->label, PCI(newPC)->label);
7095 PCI(oldPC)->label = NULL;
7097 /* move C source line (if possible) */
7098 if (PCI(oldPC)->cline && !PCI(newPC)->cline)
7099 PCI(newPC)->cline = PCI(oldPC)->cline;
7101 /* insert new pCode into pBlock */
7102 pic16_pCodeInsertAfter (oldPC, newPC);
7103 pic16_unlinkpCode (oldPC);
7105 /* TODO: update flow (newPC->from, newPC->to) */
7106 PCI(newPC)->pcflow = PCI(oldPC)->pcflow;
7108 /* destruct replaced pCode */
7109 oldPC->destruct (oldPC);
7112 /* Returns the inverted conditional branch (if any) or NULL.
7113 * pcop must be set to the new jump target.
7115 pCode *getNegatedBcc (pCode *bcc, pCodeOp *pcop)
7119 if (!bcc || !isPCI(bcc)) return NULL;
7121 switch (PCI(bcc)->op) {
7122 case POC_BC: newBcc = pic16_newpCode (POC_BNC , pcop); break;
7123 case POC_BZ: newBcc = pic16_newpCode (POC_BNZ , pcop); break;
7124 case POC_BOV: newBcc = pic16_newpCode (POC_BNOV, pcop); break;
7125 case POC_BN: newBcc = pic16_newpCode (POC_BNN , pcop); break;
7126 case POC_BNC: newBcc = pic16_newpCode (POC_BC , pcop); break;
7127 case POC_BNZ: newBcc = pic16_newpCode (POC_BZ , pcop); break;
7128 case POC_BNOV: newBcc = pic16_newpCode (POC_BOV , pcop); break;
7129 case POC_BNN: newBcc = pic16_newpCode (POC_BN , pcop); break;
7136 #define MAX_DIST_GOTO 0x7FFFFFFF
7137 #define MAX_DIST_BRA 1020 // maximum offset (in bytes) possible with BRA
7138 #define MAX_DIST_BCC 120 // maximum offset (in bytes) possible with Bcc
7139 #define MAX_JUMPCHAIN_DEPTH 16 // number of GOTOs to follow in resolveJumpChain() (to prevent endless loops)
7140 #define IS_GOTO(arg) ((arg) && isPCI(arg) && (PCI(arg)->op == POC_GOTO || PCI(arg)->op == POC_BRA))
7142 /* Follows GOTO/BRA instructions to their target instructions, stores the
7143 * final destination (not a GOTO or BRA instruction) in target and returns
7144 * the distance from the original pc to *target.
7146 int resolveJumpChain (pCode *pc, pCode **target, pCodeOp **pcop) {
7149 pCodeOp *lastPCOP = NULL;
7153 //fprintf (stderr, "%s:%d: -=-", __FUNCTION__, __LINE__);
7155 /* only follow unconditional branches, except for the initial pCode (which may be a conditional branch) */
7156 while (curr && (last != curr) && (depth++ < MAX_JUMPCHAIN_DEPTH) && isPCI(curr)
7157 && (PCI(curr)->op == POC_GOTO || PCI(curr)->op == POC_BRA || (curr == pc && isConditionalBranch(curr)))) {
7159 lastPCOP = PCI(curr)->pcop;
7160 dist = findpCodeLabel (pc, PCI(curr)->pcop->name, MAX_DIST_GOTO, &curr);
7161 //fprintf (stderr, "last:%p, curr:%p, label:%s\n", last, curr, PCI(last)->pcop->name);
7164 if (target) *target = last;
7165 if (pcop) *pcop = lastPCOP;
7169 /* Returns pc if it is not a OPT_JUMPTABLE_BEGIN INFO pCode.
7170 * Otherwise the first pCode after the jumptable (after
7171 * the OPT_JUMPTABLE_END tag) is returned.
7173 pCode *skipJumptables (pCode *pc, int *isJumptable)
7176 if (!pc) return NULL;
7178 while (pc->type == PC_INFO && PCINF(pc)->type == INF_OPTIMIZATION && PCOO(PCINF(pc)->oper1)->type == OPT_JUMPTABLE_BEGIN) {
7180 //fprintf (stderr, "SKIPPING jumptable\n");
7182 //pc->print(stderr, pc);
7184 } while (pc && (pc->type != PC_INFO || PCINF(pc)->type != INF_OPTIMIZATION
7185 || PCOO(PCINF(pc)->oper1)->type != OPT_JUMPTABLE_END));
7186 //fprintf (stderr, "<<JUMPTAB:\n");
7187 // skip OPT_END as well
7188 if (pc) pc = pc->next;
7194 pCode *pic16_findNextInstructionSkipJumptables (pCode *pc, int *isJumptable)
7198 while (pc && !isPCI(pc) && !isPCAD(pc) && !isPCW(pc)) {
7199 // set pc to the first pCode after a jumptable, leave pc untouched otherwise
7200 pc = skipJumptables (pc, &isJumptab);
7202 // pc is the first pCode after the jumptable
7205 // pc has not been changed by skipJumptables()
7213 /* Turn GOTOs into BRAs if distance between GOTO and label
7214 * is less than 1024 bytes.
7216 * This method is especially useful if GOTOs after BTFS[SC]
7217 * can be turned into BRAs as GOTO would cost another NOP
7220 void pic16_OptimizeJumps ()
7223 pCode *pc_prev = NULL;
7224 pCode *pc_next = NULL;
7227 int change, iteration, isJumptab;
7230 int opt=0, toofar=0, opt_cond = 0, cond_toofar=0, opt_reorder = 0, opt_gotonext = 0, opt_gotochain = 0;
7232 if (!the_pFile) return;
7234 //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7236 for (pb = the_pFile->pbHead; pb != NULL; pb = pb->next) {
7237 int matchedInvertRule = 1;
7240 //fprintf (stderr, "%s:%d: iterating over pBlock %p\n", __FUNCTION__, __LINE__, pb);
7242 pc = pic16_findNextInstruction (pb->pcHead);
7245 pc_next = pic16_findNextInstructionSkipJumptables (pc->next, &isJumptab);
7247 // skip jumptable, i.e. start over with no pc_prev!
7253 /* (1) resolve chained jumps
7254 * Do not perform this until pattern (4) is no longer present! Otherwise we will
7255 * (a) leave dead code in and
7256 * (b) skip over the dead code with an (unneccessary) jump.
7258 if (!matchedInvertRule && (IS_GOTO(pc) || isConditionalBranch(pc))) {
7259 pCodeOp *lastTargetOp = NULL;
7260 int newDist = resolveJumpChain (pc, &target, &lastTargetOp);
7261 int maxDist = MAX_DIST_BCC;
7262 if (PCI(pc)->op == POC_BRA) maxDist = MAX_DIST_BRA;
7263 if (PCI(pc)->op == POC_GOTO) maxDist = MAX_DIST_GOTO;
7265 /* be careful NOT to make the jump instruction longer (might break previously shortened jumps!) */
7266 if (lastTargetOp && newDist <= maxDist && lastTargetOp != PCI(pc)->pcop
7267 && strcmp (lastTargetOp->name, PCI(pc)->pcop->name) != 0) {
7268 //fprintf (stderr, "(1) ");pc->print(stderr, pc); fprintf (stderr, " --> %s\n", lastTargetOp->name);
7269 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(1) jump chain resolved")); }
7270 PCI(pc)->pcop->name = lastTargetOp->name;
7279 int condBraType = isSkipOnStatus(pc_prev);
7280 label = PCI(pc)->pcop->name;
7281 dist = findpCodeLabel(pc, label, MAX_DIST_BRA, &target);
7282 if (dist < 0) dist = -dist;
7283 //fprintf (stderr, "distance: %d (", dist); pc->print(stderr, pc);fprintf (stderr, ")\n");
7287 /* (2) remove "GOTO label; label:" */
7288 if (isLabel (pc_next, label)) {
7289 //fprintf (stderr, "(2) GOTO next instruction: ");pc->print(stderr, pc);fprintf (stderr, " --> ");pc_next->print(stderr, pc_next); fprintf(stderr, "\n");
7290 // first remove all preceeding SKIP instructions
7291 while (pc_prev && isPCI_SKIP(pc_prev)) {
7292 // attach labels on this instruction to pc_next
7293 //fprintf (stderr, "(2) preceeding SKIP removed: ");pc_prev->print(stderr, pc_prev);fprintf(stderr, "\n");
7294 PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc_prev)->label, PCI(pc_next)->label);
7295 PCI(pc_prev)->label = NULL;
7296 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(2) SKIP removed")); }
7297 pic16_unlinkpCode (pc_prev);
7298 pc_prev = pic16_findPrevInstruction (pc);
7300 // now remove the redundant goto itself
7301 PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc)->label, PCI(pc_next)->label);
7302 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP("(2) GOTO next instruction removed")); }
7303 pic16_unlinkpCode (pc);
7304 pc = pic16_findPrevInstruction(pc_next->prev);
7305 isHandled = 1; // do not perform further optimizations
7311 /* (3) turn BTFSx STATUS,i; GOTO label into Bcc label if possible */
7312 if (!isHandled && condBraType != -1 && hasNoLabel(pc)) {
7313 if (dist < MAX_DIST_BCC) {
7315 switch (condBraType) {
7316 case 0x00: bcc = pic16_newpCode (POC_BC, PCI(pc)->pcop);break;
7317 // no BDC on DIGIT CARRY available
7318 case 0x02: bcc = pic16_newpCode (POC_BZ, PCI(pc)->pcop);break;
7319 case 0x03: bcc = pic16_newpCode (POC_BOV, PCI(pc)->pcop);break;
7320 case 0x04: bcc = pic16_newpCode (POC_BN, PCI(pc)->pcop);break;
7321 case 0x10: bcc = pic16_newpCode (POC_BNC, PCI(pc)->pcop);break;
7322 // no BNDC on DIGIT CARRY available
7323 case 0x12: bcc = pic16_newpCode (POC_BNZ, PCI(pc)->pcop);break;
7324 case 0x13: bcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop);break;
7325 case 0x14: bcc = pic16_newpCode (POC_BNN, PCI(pc)->pcop);break;
7327 // no replacement possible
7332 // ATTENTION: keep labels attached to BTFSx!
7333 // HINT: GOTO is label free (checked above)
7334 //fprintf (stderr, "%s:%d: (3) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(bcc)->mnemonic, label);
7335 isHandled = 1; // do not perform further optimizations
7336 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(3) conditional branch introduced")); }
7337 pic16_pCodeReplace (pc_prev, bcc);
7344 //fprintf (stderr, "(%d, too far for Bcc)\n", dist);
7350 // (4) eliminate the following (common) tripel:
7352 // labels1: Bcc label2;
7353 // GOTO somewhere; ; <-- instruction referenced by pc
7355 // and replace it by
7356 // labels1: B#(cc) somewhere; ; #(cc) is the negated condition cc
7358 // ATTENTION: all labels pointing to "Bcc label2" must be attached
7359 // to <cont.> instead
7360 // ATTENTION: This optimization is only valid if <pred.> is
7361 // not a skip operation!
7362 // ATTENTION: somewhere must be within MAX_DIST_BCC bytes!
7363 // ATTENTION: no label may be attached to the GOTO instruction!
7364 if (isConditionalBranch(pc_prev)
7365 && (!isPCI_SKIP(pic16_findPrevInstruction(pc_prev->prev)))
7366 && (dist < MAX_DIST_BCC)
7367 && isLabel(pc_next,PCI(pc_prev)->pcop->name)
7368 && hasNoLabel(pc)) {
7369 pCode *newBcc = getNegatedBcc (pc_prev, PCI(pc)->pcop);
7372 //fprintf (stderr, "%s:%d: (4) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBcc)->mnemonic, label);
7373 isHandled = 1; // do not perform further optimizations
7374 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(4) conditional skipping branch inverted")); }
7375 pic16_pCodeReplace (pc_prev, newBcc);
7380 matchedInvertRule++;
7385 /* (5) now just turn GOTO into BRA */
7386 if (!isHandled && (PCI(pc)->op == POC_GOTO)) {
7387 if (dist < MAX_DIST_BRA) {
7388 pCode *newBra = pic16_newpCode (POC_BRA, PCI(pc)->pcop);
7389 //fprintf (stderr, "%s:%d: (5) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBra)->mnemonic, label);
7390 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc->prev, pic16_newpCodeCharP("(5) GOTO replaced by BRA")); }
7391 pic16_pCodeReplace (pc, newBra);
7396 //fprintf (stderr, "(%d, too far for BRA)\n", dist);
7399 } // if (!isHandled)
7406 pBlockRemoveUnusedLabels (pb);
7408 // This line enables goto chain resolution!
7409 if (matchedInvertRule > 1) matchedInvertRule = 1; else matchedInvertRule = 0;
7412 } while (change); /* fixpoint iteration per pBlock */
7415 // emit some statistics concerning goto-optimization
7417 if (pic16_debug_verbose || pic16_pcode_verbose) {
7418 fprintf (stderr, "optimize-goto:\n"
7419 "\t%5d GOTO->BRA; (%d GOTOs too far)\n"
7420 "\t%5d BTFSx, GOTO->Bcc (%d too far)\n"
7421 "\t%5d conditional \"skipping\" jumps inverted\n"
7422 "\t%5d GOTOs to next instruction removed\n"
7423 "\t%5d chained GOTOs resolved\n",
7424 opt, toofar, opt_cond, cond_toofar, opt_reorder, opt_gotonext, opt_gotochain);
7427 //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7431 #undef MAX_JUMPCHAIN_DEPTH
7432 #undef MAX_DIST_GOTO
7436 /** END OF RAPHAEL NEIDER'S ADDITIONS **/
7438 static void pBlockDestruct(pBlock *pb)
7449 /*-----------------------------------------------------------------*/
7450 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
7451 /* name dbName and combine them */
7452 /* into one block */
7453 /*-----------------------------------------------------------------*/
7454 static void mergepBlocks(char dbName)
7457 pBlock *pb, *pbmerged = NULL,*pbn;
7459 pb = the_pFile->pbHead;
7461 //fprintf(stderr," merging blocks named %c\n",dbName);
7465 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
7466 if( getpBlock_dbName(pb) == dbName) {
7468 //fprintf(stderr," merged block %c\n",dbName);
7473 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
7474 /* pic16_addpCode2pBlock doesn't handle the tail: */
7475 pbmerged->pcTail = pb->pcTail;
7477 pb->prev->next = pbn;
7479 pbn->prev = pb->prev;
7484 //pic16_printpBlock(stderr, pbmerged);
7491 /*-----------------------------------------------------------------*/
7492 /* AnalyzeFlow - Examine the flow of the code and optimize */
7494 /* level 0 == minimal optimization */
7495 /* optimize registers that are used only by two instructions */
7496 /* level 1 == maximal optimization */
7497 /* optimize by looking at pairs of instructions that use the */
7499 /*-----------------------------------------------------------------*/
7501 static void AnalyzeFlow(int level)
7503 static int times_called=0;
7508 /* remove unused allocated registers before exiting */
7509 pic16_RemoveUnusedRegisters();
7515 /* if this is not the first time this function has been called,
7516 then clean up old flow information */
7517 if(times_called++) {
7518 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7521 pic16_RegsUnMapLiveRanges();
7526 /* Phase 2 - Flow Analysis - Register Banking
7528 * In this phase, the individual flow blocks are examined
7529 * and register banking is fixed.
7533 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7534 pic16_FixRegisterBanking(pb);
7537 /* Phase 2 - Flow Analysis
7539 * In this phase, the pCode is partition into pCodeFlow
7540 * blocks. The flow blocks mark the points where a continuous
7541 * stream of instructions changes flow (e.g. because of
7542 * a call or goto or whatever).
7545 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7546 pic16_BuildFlow(pb);
7549 /* Phase 2 - Flow Analysis - linking flow blocks
7551 * In this phase, the individual flow blocks are examined
7552 * to determine their order of excution.
7555 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7558 /* Phase 3 - Flow Analysis - Flow Tree
7560 * In this phase, the individual flow blocks are examined
7561 * to determine their order of execution.
7564 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7565 pic16_BuildFlowTree(pb);
7568 /* Phase x - Flow Analysis - Used Banks
7570 * In this phase, the individual flow blocks are examined
7571 * to determine the Register Banks they use
7575 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7580 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7581 pic16_pCodeRegMapLiveRanges(pb);
7583 pic16_RemoveUnusedRegisters();
7585 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
7586 pic16_pCodeRegOptimizeRegUsage(level);
7594 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7599 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7601 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7602 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7603 pcflow = pcflow->next) {
7605 FillFlow(PCFL(pcflow));
7610 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7613 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7614 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7615 pcflow = pcflow->next) {
7617 FlowStats(PCFL(pcflow));
7623 /* VR -- no need to analyze banking in flow, but left here :
7624 * 1. because it may be used in the future for other purposes
7625 * 2. because if omitted we'll miss some optimization done here
7627 * Perhaps I should rename it to something else
7630 /*-----------------------------------------------------------------*/
7631 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
7632 /* assigned to the registers. */
7634 /*-----------------------------------------------------------------*/
7636 void pic16_AnalyzeBanking(void)
7641 /* Phase x - Flow Analysis - Used Banks
7643 * In this phase, the individual flow blocks are examined
7644 * to determine the Register Banks they use
7650 if(!the_pFile)return;
7652 if(!pic16_options.no_banksel) {
7653 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7654 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
7655 pic16_FixRegisterBanking(pb);
7661 /*-----------------------------------------------------------------*/
7662 /* buildCallTree - Look at the flow and extract all of the calls. */
7663 /*-----------------------------------------------------------------*/
7664 static set *register_usage(pBlock *pb);
7666 static void buildCallTree(void )
7678 /* Now build the call tree.
7679 First we examine all of the pCodes for functions.
7680 Keep in mind that the function boundaries coincide
7681 with pBlock boundaries.
7683 The algorithm goes something like this:
7684 We have two nested loops. The outer loop iterates
7685 through all of the pBlocks/functions. The inner
7686 loop iterates through all of the pCodes for
7687 a given pBlock. When we begin iterating through
7688 a pBlock, the variable pc_fstart, pCode of the start
7689 of a function, is cleared. We then search for pCodes
7690 of type PC_FUNCTION. When one is encountered, we
7691 initialize pc_fstart to this and at the same time
7692 associate a new pBranch object that signifies a
7693 branch entry. If a return is found, then this signifies
7694 a function exit point. We'll link the pCodes of these
7695 returns to the matching pc_fstart.
7697 When we're done, a doubly linked list of pBranches
7698 will exist. The head of this list is stored in
7699 `the_pFile', which is the meta structure for all
7700 of the pCode. Look at the pic16_printCallTree function
7701 on how the pBranches are linked together.
7704 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7705 pCode *pc_fstart=NULL;
7706 for(pc = pb->pcHead; pc; pc = pc->next) {
7708 if(isPCI(pc) && pc_fstart) {
7709 if(PCI(pc)->is2MemOp) {
7710 r = pic16_getRegFromInstruction2(pc);
7711 if(r && !strcmp(r->name, "POSTDEC1"))
7712 PCF(pc_fstart)->stackusage++;
7714 r = pic16_getRegFromInstruction(pc);
7715 if(r && !strcmp(r->name, "PREINC1"))
7716 PCF(pc_fstart)->stackusage--;
7721 if (PCF(pc)->fname) {
7723 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
7724 //fprintf(stderr," found main \n");
7725 pb->cmemmap = NULL; /* FIXME do we need to free ? */
7729 pbr = Safe_calloc(1,sizeof(pBranch));
7730 pbr->pc = pc_fstart = pc;
7733 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7735 // Here's a better way of doing the same:
7736 addSet(&pb->function_entries, pc);
7739 // Found an exit point in a function, e.g. return
7740 // (Note, there may be more than one return per function)
7742 pBranchLink(PCF(pc_fstart), PCF(pc));
7744 addSet(&pb->function_exits, pc);
7746 } else if(isCALL(pc)) {
7747 addSet(&pb->function_calls,pc);
7754 /* This is not needed because currently all register used
7755 * by a function are stored in stack -- VR */
7757 /* Re-allocate the registers so that there are no collisions
7758 * between local variables when one function call another */
7761 // pic16_deallocateAllRegs();
7763 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7771 /*-----------------------------------------------------------------*/
7772 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7773 /* all of the logical connections. */
7775 /* Essentially what's done here is that the pCode flow is */
7777 /*-----------------------------------------------------------------*/
7779 void pic16_AnalyzepCode(char dbName)
7790 /* Phase 1 - Register allocation and peep hole optimization
7792 * The first part of the analysis is to determine the registers
7793 * that are used in the pCode. Once that is done, the peep rules
7794 * are applied to the code. We continue to loop until no more
7795 * peep rule optimizations are found (or until we exceed the
7796 * MAX_PASSES threshold).
7798 * When done, the required registers will be determined.
7804 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7805 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7807 /* First, merge the labels with the instructions */
7808 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7809 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7811 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7812 //fprintf(stderr," analyze and merging block %c\n",dbName);
7813 pic16_pBlockMergeLabels(pb);
7816 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7821 changes = OptimizepCode(dbName);
7824 } while(changes && (i++ < MAX_PASSES));
7831 /* convert a series of movff's of local regs to stack, with a single call to
7832 * a support functions which does the same thing via loop */
7833 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
7837 char *fname[]={"__lr_store", "__lr_restore"};
7839 // pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
7841 pct = pic16_findNextInstruction(pcstart->next);
7844 pct = pc->next; //pic16_findNextInstruction(pc->next);
7845 // pc->print(stderr, pc);
7846 if(isPCI(pc) && PCI(pc)->label) {
7847 pbr = PCI(pc)->label;
7848 while(pbr && pbr->pc) {
7849 PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
7853 // pc->print(stderr, pc);
7855 pc->prev->next = pct;
7856 pct->prev = pc->prev;
7860 } while ((pc) && (pc != pcend));
7862 /* unlink movff instructions */
7863 pcstart->next = pcend;
7864 pcend->prev = pcstart;
7868 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7869 // pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popCopyReg(pic16_framepnt_lo)))); pc = pct;
7872 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name)))); pc = pct;
7873 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
7874 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] ))); pc = pct;
7877 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7878 // pic16_popCopyReg(pic16_framepnt_lo), pic16_popCopyReg(&pic16_pc_fsr0l)))); pc = pct;
7885 sym = newSymbol( fname[ entry?0:1 ], 0 );
7886 strcpy(sym->rname, fname[ entry?0:1 ]);
7887 checkAddSym(&externs, sym);
7889 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
7894 /*-----------------------------------------------------------------*/
7895 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for */
7896 /* local registers to a support function call */
7897 /*-----------------------------------------------------------------*/
7898 void pic16_OptimizeLocalRegs(void)
7903 pCodeOpLocalReg *pclr;
7906 regs *r, *lastr=NULL, *firstr=NULL;
7907 pCode *pcstart=NULL, *pcend=NULL;
7912 * local_regs begin mark
7913 * MOVFF r0x01, POSTDEC1
7914 * MOVFF r0x02, POSTDEC1
7917 * MOVFF r0x0n, POSTDEC1
7918 * local_regs end mark
7920 * convert the above to the below:
7921 * MOVLW starting_register_index
7923 * MOVLW register_count
7924 * call __save_registers_in_stack
7930 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7931 inRegCount = regCount = 0;
7932 firstr = lastr = NULL;
7933 for(pc = pb->pcHead; pc; pc = pc->next) {
7935 /* hold current function name */
7936 if(pc && isPCF(pc))curFunc = PCF(pc)->fname;
7938 if(pc && (pc->type == PC_INFO)) {
7941 if(pci->type == INF_LOCALREGS) {
7942 pclr = PCOLR(pci->oper1);
7944 if((pclr->type == LR_ENTRY_BEGIN)
7945 || (pclr->type == LR_ENTRY_END))inEntry = 1;
7948 switch(pclr->type) {
7949 case LR_ENTRY_BEGIN:
7951 inRegCount = 1; regCount = 0;
7952 pcstart = pc; //pic16_findNextInstruction(pc->next);
7953 firstr = lastr = NULL;
7959 pcend = pc; //pic16_findPrevInstruction(pc->prev);
7962 if(curFunc && inWparamList(curFunc+1)) {
7963 fprintf(stderr, "sdcc: %s: warning: disabling lr-support for functionn %s\n",
7967 pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
7972 firstr = lastr = NULL;
7976 if(inRegCount == -1) {
7977 // fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
7983 if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
7985 r = pic16_getRegFromInstruction(pc);
7987 r = pic16_getRegFromInstruction2(pc);
7988 if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
7989 if(!firstr)firstr = r;
7991 // fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
8003 /*-----------------------------------------------------------------*/
8004 /* ispCodeFunction - returns true if *pc is the pCode of a */
8006 /*-----------------------------------------------------------------*/
8007 static bool ispCodeFunction(pCode *pc)
8010 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
8016 /*-----------------------------------------------------------------*/
8017 /* findFunction - Search for a function by name (given the name) */
8018 /* in the set of all functions that are in a pBlock */
8019 /* (note - I expect this to change because I'm planning to limit */
8020 /* pBlock's to just one function declaration */
8021 /*-----------------------------------------------------------------*/
8022 static pCode *findFunction(char *fname)
8029 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8031 pc = setFirstItem(pb->function_entries);
8034 if((pc->type == PC_FUNCTION) &&
8036 (strcmp(fname, PCF(pc)->fname)==0))
8039 pc = setNextItem(pb->function_entries);
8047 static void MarkUsedRegisters(set *regset)
8052 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
8053 // fprintf(stderr, "marking register = %s\t", r1->name);
8054 r2 = pic16_regWithIdx(r1->rIdx);
8055 // fprintf(stderr, "to register = %s\n", r2->name);
8061 static void pBlockStats(FILE *of, pBlock *pb)
8067 if(!pic16_pcode_verbose)return;
8069 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
8071 // for now just print the first element of each set
8072 pc = setFirstItem(pb->function_entries);
8074 fprintf(of,";entry: ");
8077 pc = setFirstItem(pb->function_exits);
8079 fprintf(of,";has an exit\n");
8083 pc = setFirstItem(pb->function_calls);
8085 fprintf(of,";functions called:\n");
8088 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8089 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
8091 pc = setNextItem(pb->function_calls);
8095 r = setFirstItem(pb->tregisters);
8097 int n = elementsInSet(pb->tregisters);
8099 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
8102 fprintf(of,"; %s\n",r->name);
8103 r = setNextItem(pb->tregisters);
8107 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
8110 /*-----------------------------------------------------------------*/
8111 /*-----------------------------------------------------------------*/
8113 static void sequencepCode(void)
8119 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8121 pb->seq = GpCodeSequenceNumber+1;
8123 for( pc = pb->pcHead; pc; pc = pc->next)
8124 pc->seq = ++GpCodeSequenceNumber;
8130 /*-----------------------------------------------------------------*/
8131 /*-----------------------------------------------------------------*/
8132 static set *register_usage(pBlock *pb)
8135 set *registers=NULL;
8136 set *registersInCallPath = NULL;
8138 /* check recursion */
8140 pc = setFirstItem(pb->function_entries);
8147 if(pc->type != PC_FUNCTION)
8148 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
8150 pc = setFirstItem(pb->function_calls);
8151 for( ; pc; pc = setNextItem(pb->function_calls)) {
8153 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8154 char *dest = pic16_get_op_from_instruction(PCI(pc));
8156 pcn = findFunction(dest);
8158 registersInCallPath = register_usage(pcn->pb);
8160 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8165 pBlockStats(stderr,pb); // debug
8168 // Mark the registers in this block as used.
8170 MarkUsedRegisters(pb->tregisters);
8171 if(registersInCallPath) {
8172 /* registers were used in the functions this pBlock has called */
8173 /* so now, we need to see if these collide with the ones we are */
8176 regs *r1,*r2, *newreg;
8178 DFPRINTF((stderr,"comparing registers\n"));
8180 r1 = setFirstItem(registersInCallPath);
8183 r2 = setFirstItem(pb->tregisters);
8185 while(r2 && (r1->type != REG_STK)) {
8187 if(r2->rIdx == r1->rIdx) {
8188 newreg = pic16_findFreeReg(REG_GPR);
8192 DFPRINTF((stderr,"Bummer, no more registers.\n"));
8196 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
8197 r1->rIdx, newreg->rIdx));
8198 r2->rIdx = newreg->rIdx;
8199 //if(r2->name) free(r2->name);
8201 r2->name = Safe_strdup(newreg->name);
8205 newreg->wasUsed = 1;
8207 r2 = setNextItem(pb->tregisters);
8210 r1 = setNextItem(registersInCallPath);
8213 /* Collisions have been resolved. Now free the registers in the call path */
8214 r1 = setFirstItem(registersInCallPath);
8216 if(r1->type != REG_STK) {
8217 newreg = pic16_regWithIdx(r1->rIdx);
8220 r1 = setNextItem(registersInCallPath);
8224 // MarkUsedRegisters(pb->registers);
8226 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
8229 DFPRINTF((stderr,"returning regs\n"));
8231 DFPRINTF((stderr,"not returning regs\n"));
8233 DFPRINTF((stderr,"pBlock after register optim.\n"));
8234 pBlockStats(stderr,pb); // debug
8240 /*-----------------------------------------------------------------*/
8241 /* pct2 - writes the call tree to a file */
8243 /*-----------------------------------------------------------------*/
8244 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
8248 // set *registersInCallPath = NULL;
8254 fprintf(of, "recursive function\n");
8255 return; //recursion ?
8258 pc = setFirstItem(pb->function_entries);
8265 for(i=0;i<indent;i++) // Indentation
8269 if(pc->type == PC_FUNCTION) {
8270 usedstack += PCF(pc)->stackusage;
8271 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
8272 } else return; // ???
8275 pc = setFirstItem(pb->function_calls);
8276 for( ; pc; pc = setNextItem(pb->function_calls)) {
8278 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8279 char *dest = pic16_get_op_from_instruction(PCI(pc));
8281 pcn = findFunction(dest);
8283 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
8285 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8293 /*-----------------------------------------------------------------*/
8294 /* pic16_printCallTree - writes the call tree to a file */
8296 /*-----------------------------------------------------------------*/
8298 void pic16_printCallTree(FILE *of)
8310 fprintf(of, "\npBlock statistics\n");
8311 for(pb = the_pFile->pbHead; pb; pb = pb->next )
8315 fprintf(of,"Call Tree\n");
8316 pbr = the_pFile->functions;
8320 if(!ispCodeFunction(pc))
8321 fprintf(of,"bug in call tree");
8324 fprintf(of,"Function: %s\n", PCF(pc)->fname);
8326 while(pc->next && !ispCodeFunction(pc->next)) {
8328 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
8329 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
8337 fprintf(of,"\n**************\n\na better call tree\n");
8338 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8343 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8344 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
8350 /*-----------------------------------------------------------------*/
8352 /*-----------------------------------------------------------------*/
8354 static void InlineFunction(pBlock *pb)
8362 pc = setFirstItem(pb->function_calls);
8364 for( ; pc; pc = setNextItem(pb->function_calls)) {
8367 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8373 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
8375 //fprintf(stderr,"Cool can inline:\n");
8376 //pcn->print(stderr,pcn);
8378 //fprintf(stderr,"recursive call Inline\n");
8379 InlineFunction(pcn->pb);
8380 //fprintf(stderr,"return from recursive call Inline\n");
8383 At this point, *pc points to a CALL mnemonic, and
8384 *pcn points to the function that is being called.
8386 To in-line this call, we need to remove the CALL
8387 and RETURN(s), and link the function pCode in with
8393 /* Remove the CALL */
8397 /* remove callee pBlock from the pBlock linked list */
8398 removepBlock(pcn->pb);
8406 /* Remove the Function pCode */
8407 pct = pic16_findNextInstruction(pcn->next);
8409 /* Link the function with the callee */
8410 pc->next = pcn->next;
8411 pcn->next->prev = pc;
8413 /* Convert the function name into a label */
8415 pbr = Safe_calloc(1,sizeof(pBranch));
8416 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
8418 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
8419 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
8421 /* turn all of the return's except the last into goto's */
8422 /* check case for 2 instruction pBlocks */
8423 pce = pic16_findNextInstruction(pcn->next);
8425 pCode *pce_next = pic16_findNextInstruction(pce->next);
8427 if(pce_next == NULL) {
8428 /* found the last return */
8429 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
8431 //fprintf(stderr,"found last return\n");
8432 //pce->print(stderr,pce);
8433 pce->prev->next = pc_call->next;
8434 pc_call->next->prev = pce->prev;
8435 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
8445 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8451 /*-----------------------------------------------------------------*/
8453 /*-----------------------------------------------------------------*/
8455 void pic16_InlinepCode(void)
8464 if(!functionInlining)
8467 /* Loop through all of the function definitions and count the
8468 * number of times each one is called */
8469 //fprintf(stderr,"inlining %d\n",__LINE__);
8471 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8473 pc = setFirstItem(pb->function_calls);
8475 for( ; pc; pc = setNextItem(pb->function_calls)) {
8478 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8479 if(pcn && isPCF(pcn)) {
8480 PCF(pcn)->ncalled++;
8483 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8488 //fprintf(stderr,"inlining %d\n",__LINE__);
8490 /* Now, Loop through the function definitions again, but this
8491 * time inline those functions that have only been called once. */
8493 InlineFunction(the_pFile->pbHead);
8494 //fprintf(stderr,"inlining %d\n",__LINE__);
8496 for(pb = the_pFile->pbHead; pb; pb = pb->next)
8501 char *pic_optype_names[]={
8502 "PO_NONE", // No operand e.g. NOP
8503 "PO_W", // The working register (as a destination)
8504 "PO_WREG", // The working register (as a file register)
8505 "PO_STATUS", // The 'STATUS' register
8506 "PO_BSR", // The 'BSR' register
8507 "PO_FSR0", // The "file select register" (in PIC18 family it's one
8509 "PO_INDF0", // The Indirect register
8510 "PO_INTCON", // Interrupt Control register
8511 "PO_GPR_REGISTER", // A general purpose register
8512 "PO_GPR_BIT", // A bit of a general purpose register
8513 "PO_GPR_TEMP", // A general purpose temporary register
8514 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
8515 "PO_PCL", // Program counter Low register
8516 "PO_PCLATH", // Program counter Latch high register
8517 "PO_PCLATU", // Program counter Latch upper register
8518 "PO_PRODL", // Product Register Low
8519 "PO_PRODH", // Product Register High
8520 "PO_LITERAL", // A constant
8521 "PO_REL_ADDR", // A relative address
8522 "PO_IMMEDIATE", // (8051 legacy)
8523 "PO_DIR", // Direct memory (8051 legacy)
8524 "PO_CRY", // bit memory (8051 legacy)
8525 "PO_BIT", // bit operand.
8526 "PO_STR", // (8051 legacy)
8528 "PO_WILD" // Wild card operand in peep optimizer
8532 char *dumpPicOptype(PIC_OPTYPE type)
8534 return (pic_optype_names[ type ]);
8538 /*** BEGIN of stuff belonging to the BANKSEL optimization ***/
8541 #define MAX_COMMON_BANK_SIZE 32
8542 #define FIRST_PSEUDO_BANK_NR 1000
8544 hTab *sym2bank = NULL; // <OPERAND NAME> --> <PSEUDO BANK NR>
8545 hTab *bank2sym = NULL; // <PSEUDO BANK NR> --> <OPERAND NAME>
8546 hTab *coerce = NULL; // <PSEUDO BANK NR> --> <&PSEUDOBANK>
8549 typedef enum { INVALID_BANK = -1, UNKNOWN_BANK = -2, FIXED_BANK = -3 } pseudoBankNr;
8552 pseudoBankNr bank; // number assigned to this pseudoBank
8553 unsigned int size; // number of operands assigned to this bank
8554 unsigned int ref; // number of symbols referring to this pseudoBank (for garbage collection)
8557 /*----------------------------------------------------------------------*/
8558 /* hashSymbol - hash function used to map SYMBOLs (or operands) to ints */
8559 /*----------------------------------------------------------------------*/
8560 unsigned int hashSymbol (const char *str)
8562 unsigned int res = 0;
8567 res = (res << 4) | (res >> (8 * sizeof(unsigned int) - 4));
8574 /*-----------------------------------------------------------------------*/
8575 /* compareSymbol - return 1 iff sym1 equals sym2 */
8576 /*-----------------------------------------------------------------------*/
8577 int compareSymbol (const void *sym1, const void *sym2)
8579 char *s1 = (char*) sym1;
8580 char *s2 = (char*) sym2;
8582 return (strcmp (s1,s2) == 0);
8585 /*-----------------------------------------------------------------------*/
8586 /* comparePre - return 1 iff p1 == p2 */
8587 /*-----------------------------------------------------------------------*/
8588 int comparePtr (const void *p1, const void *p2)
8593 /*----------------------------------------------------------*/
8594 /* getSymbolFromOperand - return a pointer to the symbol in */
8595 /* the given operand and its length */
8596 /*----------------------------------------------------------*/
8597 char *getSymbolFromOperand (char *op, unsigned int *len)
8602 if (!op) return NULL;
8604 // we recognize two forms of operands: SYMBOL and (SYMBOL + offset)
8606 if (*sym == '(') sym++;
8609 while (((*curr >= 'A') && (*curr <= 'Z'))
8610 || ((*curr >= 'a') && (*curr <= 'z'))
8611 || ((curr != sym) && (*curr >= '0') && (*curr <= '9'))
8612 || (*curr == '_')) {
8613 // find end of symbol [A-Za-z_]?[A-Za-z0-9]*
8621 /*--------------------------------------------------------------------------*/
8622 /* getSymFromBank - get (one) name of a symbol assigned to the given bank */
8623 /*--------------------------------------------------------------------------*/
8624 char *getSymFromBank (pseudoBankNr bank)
8628 if (bank < 0) return "<INVALID BANK NR>";
8629 return hTabFindByKey (bank2sym, bank % bank2sym->size, (void *) bank, &comparePtr);
8632 /*-----------------------------------------------------------------------*/
8633 /* getPseudoBsrFromOperand - maps a string to its corresponding pseudo */
8634 /* bank number (uses hTab sym2bank), if the */
8635 /* symbol is not yet assigned a pseudo bank it */
8636 /* is assigned one here */
8637 /*-----------------------------------------------------------------------*/
8638 pseudoBankNr getPseudoBankNrFromOperand (const char *op)
8640 static pseudoBankNr next_bank = FIRST_PSEUDO_BANK_NR;
8646 hash = hashSymbol (op) % sym2bank->size;
8647 bank = (pseudoBankNr) hTabFindByKey (sym2bank, hash, op, &compareSymbol);
8648 if (bank == (pseudoBankNr)NULL) bank = UNKNOWN_BANK;
8650 if (bank == UNKNOWN_BANK) {
8651 // create a pseudo bank for the operand
8653 hTabAddItemLong (&sym2bank, hash, (char *)op, (void *)bank);
8654 hTabAddItemLong (&bank2sym, bank, (void *) bank, (void *)op);
8655 getOrAddGNode (adj, NULL, bank); // adds the node if it does not exist yet
8656 //fprintf (stderr, "%s:%d: adding %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8658 //fprintf (stderr, "%s:%d: found %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8666 /*--------------------------------------------------------------------*/
8667 /* isBanksel - check whether the given pCode is a BANKSEL instruction */
8668 /*--------------------------------------------------------------------*/
8669 int isBanksel (pCode *pc)
8673 if (isPCI(pc) && (PCI(pc)->op == POC_BANKSEL || PCI(pc)->op == POC_MOVLB)) {
8674 // BANKSEL <variablename> or MOVLB <banknr>
8675 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8679 // check for inline assembler BANKSELs
8680 if (isPCAD(pc) && PCAD(pc)->directive && (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0 ||
8681 STRCASECMP(PCAD(pc)->directive,"MOVLB") == 0)) {
8682 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8686 // assume pc is no BANKSEL instruction
8690 /*---------------------------------------------------------------------------------*/
8691 /* invalidatesBSR - check whether the pCodeInstruction passed in modifies the BSR */
8692 /* This method can not guarantee to find all modifications of the */
8693 /* BSR (e.g. via INDirection registers) but covers all compiler */
8694 /* generated plus some cases. */
8695 /*---------------------------------------------------------------------------------*/
8696 int invalidatesBSR(pCode *pc)
8698 // assembler directives invalidate BSR (well, they might, we don't know)
8699 if (isPCAD(pc)) return 1;
8701 // only ASMDIRs and pCodeInstructions can invalidate BSR
8702 if (!isPCI(pc)) return 0;
8704 // we have a pCodeInstruction
8706 // check for BSR modifying instructions
8707 switch (PCI(pc)->op) {
8711 case POC_RETFIE: // might be used as CALL replacement
8712 case POC_RETLW: // might be used as CALL replacement
8713 case POC_RETURN: // might be used as CALL replacement
8718 default: // other instruction do not change BSR unless BSR is an explicit operand!
8719 // TODO: check for BSR as an explicit operand (e.g. INCF BSR,F), which should be rather unlikely...!
8723 // no change of BSR possible/probable
8727 /*------------------------------------------------------------*/
8728 /* getBankFromBanksel - return the pseudo bank nr assigned to */
8729 /* the symbol referenced in this BANKSEL */
8730 /*------------------------------------------------------------*/
8731 pseudoBankNr getBankFromBanksel (pCode *pc)
8734 int data = (int)NULL;
8736 if (!pc) return INVALID_BANK;
8738 if (isPCAD(pc) && PCAD(pc)->directive) {
8739 if (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0) {
8740 // get symbolname from PCAD(pc)->arg
8741 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8742 sym = PCAD(pc)->arg;
8743 data = getPseudoBankNrFromOperand (sym);
8744 //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8745 } else if (STRCASECMP(PCAD(pc)->directive,"MOVLB")) {
8746 // get (literal) bank number from PCAD(pc)->arg
8747 fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8748 assert (0 && "not yet implemented - turn off banksel optimization for now");
8750 } else if (isPCI(pc)) {
8751 if (PCI(pc)->op == POC_BANKSEL) {
8752 // get symbolname from PCI(pc)->pcop->name (?)
8753 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8754 sym = PCI(pc)->pcop->name;
8755 data = getPseudoBankNrFromOperand (sym);
8756 //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8757 } else if (PCI(pc)->op == POC_MOVLB) {
8758 // get (literal) bank number from PCI(pc)->pcop->name
8759 fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8760 assert (0 && "not yet implemented - turn off banksel optimization for now");
8765 // no assigned bank could be found
8766 return UNKNOWN_BANK;
8771 /*------------------------------------------------------------------------------*/
8772 /* getEffectiveBank - resolves the currently assigned effective pseudo bank nr */
8773 /*------------------------------------------------------------------------------*/
8774 pseudoBankNr getEffectiveBank (pseudoBankNr bank)
8778 if (bank < FIRST_PSEUDO_BANK_NR) return bank;
8781 //fprintf (stderr, "%s:%d: bank=%d\n", __FUNCTION__, __LINE__, bank);
8782 data = (pseudoBank *) hTabFindByKey (coerce, bank % coerce->size, (void *) bank, &comparePtr);
8784 if (data->bank != bank)
8791 //fprintf (stderr, "%s:%d: effective bank=%d\n", __FUNCTION__, __LINE__, bank);
8795 /*------------------------------------------------------------------*/
8796 /* attachBsrInfo2pBlock - create a look-up table as to which pseudo */
8797 /* bank is selected at a given pCode */
8798 /*------------------------------------------------------------------*/
8800 /* Create a graph with pseudo banks as its nodes and switches between
8801 * these as edges (with the edge weight representing the absolute
8802 * number of BANKSELs from one to the other).
8803 * Removes redundand BANKSELs instead iff mod == 1.
8804 * BANKSELs update the pseudo BSR, labels invalidate the current BSR
8805 * value (setting it to 0=UNNKOWN), (R)CALLs also invalidate the
8807 * TODO: check ALL instructions operands if they modify BSR directly...
8809 * pb - the pBlock to annotate
8810 * mod - select either graph creation (0) or BANKSEL removal (1)
8812 unsigned int attachBsrInfo2pBlock (pBlock *pb, int mod)
8814 pCode *pc, *pc_next;
8815 unsigned int prevBSR = UNKNOWN_BANK, pseudoBSR = UNKNOWN_BANK;
8816 int isBankselect = 0;
8817 unsigned int banksels=0;
8821 pc = pic16_findNextInstruction(pb->pcHead);
8823 isBankselect = isBanksel (pc);
8824 pc_next = pic16_findNextInstruction (pc->next);
8826 if (!hasNoLabel (pc)) {
8827 // we don't know our predecessors -- assume different BSRs
8828 prevBSR = UNKNOWN_BANK;
8829 pseudoBSR = UNKNOWN_BANK;
8830 //fprintf (stderr, "invalidated by label at "); pc->print (stderr, pc);
8833 // check if this is a BANKSEL instruction
8835 pseudoBSR = getEffectiveBank (getBankFromBanksel(pc));
8836 //fprintf (stderr, "BANKSEL via "); pc->print (stderr, pc);
8838 if (prevBSR == pseudoBSR && pseudoBSR >= 0) {
8839 //fprintf (stderr, "removing redundant "); pc->print (stderr, pc);
8840 if (1 || pic16_pcode_verbose) pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("removed redundant BANKSEL"));
8841 pic16_unlinkpCode (pc);
8845 addGEdge2 (getOrAddGNode (adj, NULL, prevBSR), getOrAddGNode (adj, NULL, pseudoBSR), 1, 0);
8850 if (!isBankselect && invalidatesBSR(pc)) {
8851 // check if this instruction invalidates the pseudoBSR
8852 pseudoBSR = UNKNOWN_BANK;
8853 //fprintf (stderr, "invalidated via "); pc->print (stderr, pc);
8856 prevBSR = pseudoBSR;
8863 /*------------------------------------------------------------------------------------*/
8864 /* assignToSameBank - returns 0 on success or an error code */
8865 /* 1 - common bank would be too large */
8866 /* 2 - assignment to fixed (absolute) bank not performed */
8868 /* This functions assumes that unsplittable operands are already assigned to the same */
8869 /* bank (e.g. all objects being referenced as (SYMBOL + offset) must be in the same */
8870 /* bank so that we can make sure the bytes are laid out sequentially in memory) */
8871 /* TODO: Symbols with an abslute address must be handled specially! */
8872 /*------------------------------------------------------------------------------------*/
8873 int assignToSameBank (int bank0, int bank1, int doAbs)
8875 int eff0, eff1, dummy;
8876 pseudoBank *pbank0, *pbank1;
8879 eff0 = getEffectiveBank (bank0);
8880 eff1 = getEffectiveBank (bank1);
8882 //fprintf (stderr, "%s:%d: bank0=%d/%d, bank1=%d/%d, doAbs=%d\n", __FUNCTION__, __LINE__, bank0, eff0, bank1, eff1, doAbs);
8884 // nothing to do if already same bank
8885 if (eff0 == eff1) return 0;
8887 if (!doAbs && (eff0 < FIRST_PSEUDO_BANK_NR || eff1 < FIRST_PSEUDO_BANK_NR))
8890 // ensure eff0 < eff1
8892 // swap eff0 and eff1
8901 // now assign bank eff1 to bank eff0
8902 pbank0 = (pseudoBank *) hTabFindByKey (coerce, eff0 % coerce->size, (void *) eff0, &comparePtr);
8904 pbank0 = Safe_calloc (1, sizeof (pseudoBank));
8905 pbank0->bank = eff0;
8908 hTabAddItemLong (&coerce, eff0 % coerce->size, (void *) eff0, (void *) pbank0);
8912 hitem = hTabSearch (coerce, eff1 % coerce->size);
8913 while (hitem && hitem->pkey != (void *)eff1)
8914 hitem = hitem->next;
8916 if (hitem) pbank1 = (pseudoBank *) hitem->item;
8919 fprintf (stderr, "bank #%d/%d & bank #%d/%d --> bank #%d: %u (%s & %s)\n", bank0, eff0, bank1, eff1,
8920 pbank0->bank, pbank0->size,
8921 getSymFromBank (eff0), getSymFromBank (eff1));
8925 if (pbank0->size + pbank1->size > MAX_COMMON_BANK_SIZE) {
8927 fprintf (stderr, "bank #%d: %u, bank #%d: %u --> bank #%d': %u > %u (%s,%s)\n",
8928 pbank0->bank, pbank0->size, pbank1->bank, pbank1->size,
8929 pbank0->bank, pbank0->size + pbank1->size, MAX_COMMON_BANK_SIZE,
8930 getSymFromBank (pbank0->bank), getSymFromBank (pbank1->bank));
8934 pbank0->size += pbank1->size;
8936 if (pbank1->ref == 0) Safe_free (pbank1);
8942 hitem->item = pbank0;
8944 hTabAddItemLong (&coerce, eff1 % coerce->size, (void *) eff1, (void *) pbank0);
8947 //fprintf (stderr, "%s:%d: leaving.\n", __FUNCTION__, __LINE__);
8952 /*----------------------------------------------------------------*/
8953 /* mergeGraphNodes - combines two nodes into one and modifies all */
8954 /* edges to and from the nodes accordingly */
8955 /* This method needs complete backedges, i.e. if (A,B) is an edge */
8956 /* then also (B,A) must be an edge (possibly with weight 0). */
8957 /*----------------------------------------------------------------*/
8958 void mergeGraphNodes (GraphNode *node1, GraphNode *node2)
8960 GraphEdge *edge, *backedge, *nextedge;
8964 assert (node1 && node2);
8965 assert (node1 != node2);
8967 // add all edges starting at node2 to node1
8970 nextedge = edge->next;
8972 backedge = getGEdge (node, node2);
8974 backweight = backedge->weight;
8977 // insert edges (node1,node) and (node,node1)
8978 addGEdge2 (node1, node, edge->weight, backweight);
8979 // remove edges (node, node2) and (node2, node)
8980 remGEdge (node2, node);
8981 remGEdge (node, node2);
8985 // now node2 should not be referenced by any other GraphNode...
8986 //remGNode (adj, node2->data, node2->hash);
8989 /*----------------------------------------------------------------*/
8990 /* showGraph - dump the current BANKSEL graph as a node/edge list */
8991 /*----------------------------------------------------------------*/
8992 void showGraph (Graph *g)
8996 pseudoBankNr bankNr;
9003 bankNr = getEffectiveBank (node->hash);
9004 assert (bankNr >= 0);
9005 pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9007 bankNr = pbank->bank;
9013 fprintf (stderr, "edges from %s (bank %u, size %u) to:\n", getSymFromBank (node->hash), bankNr, size);
9016 if (edge->weight > 0)
9017 fprintf (stderr, " %4u x %s\n", edge->weight, getSymFromBank (edge->node->hash));
9024 /*---------------------------------------------------------------*/
9025 /* pic16_OptimizeBanksel - remove redundant BANKSEL instructions */
9026 /*---------------------------------------------------------------*/
9027 void pic16_OptimizeBanksel ()
9029 GraphNode *node, *node1, *node1next;
9032 // needed for more effective bank assignment (needs adjusted pic16_emit_usection())
9033 GraphEdge *edge, *backedge;
9035 int maxWeight, weight, mergeMore, absMaxWeight;
9036 pseudoBankNr curr0, curr1;
9039 pseudoBankNr bankNr;
9040 char *base_symbol0, *base_symbol1;
9045 unsigned int bankselsTotal = 0, bankselsRemoved = 0;
9047 //fprintf (stderr, "%s:%s:%d: entered.\n", __FILE__, __FUNCTION__, __LINE__);
9049 if (!the_pFile || !the_pFile->pbHead) return;
9051 adj = newGraph (NULL);
9052 sym2bank = newHashTable ( 255 );
9053 bank2sym = newHashTable ( 255 );
9054 coerce = newHashTable ( 255 );
9056 // create graph of BANKSEL relationships (node = operands, edge (A,B) iff BANKSEL B follows BANKSEL A)
9057 for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9058 bankselsTotal += attachBsrInfo2pBlock (pb, 0);
9062 // assign symbols with absolute addresses to their respective bank nrs
9063 set = pic16_fix_udata;
9064 for (reg = setFirstItem (set); reg; reg = setNextItem (set)) {
9065 bankNr = reg->address >> 8;
9066 node = getOrAddGNode (adj, NULL, bankNr);
9067 bankNr = (pseudoBankNr) getEffectiveBank (getPseudoBankNrFromOperand(reg->name));
9068 assignToSameBank (node->hash, bankNr, 1);
9070 assert (bankNr >= 0);
9071 pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9073 pbank = Safe_calloc (1, sizeof (pseudoBank));
9074 pbank->bank = reg->address >> 8; //FIXED_BANK;
9077 hTabAddItemLong (&coerce, bankNr % coerce->size, (void *) bankNr, pbank);
9079 assert (pbank->bank == (reg->address >> 8));
9080 pbank->bank = reg->address >> 8; //FIXED_BANK;
9082 //fprintf (stderr, "ABS: %s (%d bytes) at %x in bank %u\n", reg->name, reg->size, reg->address, bankNr);
9087 // assign operands referring to the same symbol (which is not given an absolute address) to the same bank
9088 //fprintf (stderr, "assign operands with the same symbol to the same bank\n");
9091 if (node->hash < 0) { node = node->next; continue; }
9092 base_symbol0 = getSymbolFromOperand (getSymFromBank (getEffectiveBank(node->hash)), &len0);
9095 if (node1->hash < 0) { node1 = node1->next; continue; }
9096 node1next = node1->next;
9097 base_symbol1 = getSymbolFromOperand (getSymFromBank (getEffectiveBank (node1->hash)), &len1);
9098 if (len0 == len1 && len0 > 0 && strncmp (base_symbol0, base_symbol1, len0) == 0) {
9099 // TODO: check for symbols with absolute addresses -- these might be placed across bank boundaries!
9100 //fprintf (stderr, "merging %s and %s\n", getSymFromBank (getEffectiveBank(node->hash)), getSymFromBank (getEffectiveBank(node1->hash)));
9101 if (assignToSameBank (node->hash, node1->hash, 0)) {
9102 fprintf (stderr, "%s(%d) == %s(%d)\n", base_symbol0, len0, base_symbol1, len1);
9103 assert (0 && "Could not assign a symbol to a bank!");
9105 mergeGraphNodes (node, node1);
9107 if (node->hash < node1->hash)
9108 mergeGraphNodes (node, node1);
9110 mergeGraphNodes (node1, node); // this removes node so node->next will fail...
9120 // >>> THIS ALSO NEEDS AN UPDATED pic16_emit_usection() TO REFLECT THE BANK ASSIGNMENTS <<<
9121 // assign tightly coupled operands to the same (pseudo) bank
9122 //fprintf (stderr, "assign tightly coupled operands to the same bank\n");
9130 curr0 = getEffectiveBank (node->hash);
9131 if (curr0 < 0) { node = node->next; continue; }
9134 assert (edge->src == node);
9135 backedge = getGEdge (edge->node, edge->src);
9136 weight = edge->weight + (backedge ? backedge->weight : 0);
9137 curr1 = getEffectiveBank (edge->node->hash);
9138 if (curr1 < 0) { edge = edge->next; continue; }
9140 // merging is only useful if the items are not assigned to the same bank already...
9141 if (curr0 != curr1 && weight > maxWeight) {
9142 if (maxWeight > absMaxWeight) absMaxWeight = maxWeight;
9151 if (maxWeight > 0) {
9153 fprintf (stderr, "%s:%d: merging (%4u) %d(%s) and %d(%s)\n", __FUNCTION__, __LINE__, maxWeight,
9154 max->src->hash, getSymFromBank (max->src->hash),
9155 max->node->hash, getSymFromBank (max->node->hash));
9158 node = getGNode (adj, max->src->data, max->src->hash);
9159 node1 = getGNode (adj, max->node->data, max->node->hash);
9161 if (0 == assignToSameBank (max->src->hash, max->node->hash, 0)) {
9162 if (max->src->hash < max->node->hash)
9163 mergeGraphNodes (node, node1);
9165 mergeGraphNodes (node1, node);
9167 remGEdge (node, node1);
9168 remGEdge (node1, node);
9179 // remove redundant BANKSELs
9180 //fprintf (stderr, "removing redundant BANKSELs\n");
9181 for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9182 bankselsRemoved += attachBsrInfo2pBlock (pb, 1);
9187 fprintf (stderr, "display graph\n");
9192 //fprintf (stderr, "%s:%s:%d: leaving, %u/%u BANKSELs removed...\n", __FILE__, __FUNCTION__, __LINE__, bankselsRemoved, bankselsTotal);
9195 /*** END of stuff belonging to the BANKSEL optimization ***/