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 // Safe_free(PCL(pc)->label);
3876 /* Instead of deleting the memory used by this pCode, mark
3877 * the object as bad so that if there's a pointer to this pCode
3878 * dangling around somewhere then (hopefully) when the type is
3879 * checked we'll catch it.
3883 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3889 pCode *pic16_newpCodeLabel(char *name, int key)
3895 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3897 pcl->pc.type = PC_LABEL;
3898 pcl->pc.prev = pcl->pc.next = NULL;
3899 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3902 // pcl->pc.analyze = genericAnalyze;
3903 pcl->pc.destruct = pCodeLabelDestruct;
3904 pcl->pc.print = pCodePrintLabel;
3911 sprintf(s,"_%05d_DS_",key);
3916 pcl->label = Safe_strdup(s);
3918 // if(pic16_pcode_verbose)
3919 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3922 return ( (pCode *)pcl);
3926 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3928 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3932 return ( (pCode *)pcl );
3935 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3939 pci = Safe_calloc(1, sizeof(pCodeInfo));
3940 pci->pci.pc.type = PC_INFO;
3941 pci->pci.pc.prev = pci->pci.pc.next = NULL;
3942 pci->pci.pc.pb = NULL;
3943 pci->pci.label = NULL;
3945 pci->pci.pc.destruct = genericDestruct;
3946 pci->pci.pc.print = genericPrint;
3951 return ((pCode *)pci);
3955 /*-----------------------------------------------------------------*/
3956 /* newpBlock - create and return a pointer to a new pBlock */
3957 /*-----------------------------------------------------------------*/
3958 static pBlock *newpBlock(void)
3963 PpB = Safe_calloc(1,sizeof(pBlock) );
3964 PpB->next = PpB->prev = NULL;
3966 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3967 PpB->tregisters = NULL;
3969 PpB->FlowTree = NULL;
3975 /*-----------------------------------------------------------------*/
3976 /* pic16_newpCodeChain - create a new chain of pCodes */
3977 /*-----------------------------------------------------------------*
3979 * This function will create a new pBlock and the pointer to the
3980 * pCode that is passed in will be the first pCode in the block.
3981 *-----------------------------------------------------------------*/
3984 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3987 pBlock *pB = newpBlock();
3989 pB->pcHead = pB->pcTail = pc;
3998 /*-----------------------------------------------------------------*/
3999 /* pic16_newpCodeOpLabel - Create a new label given the key */
4000 /* Note, a negative key means that the label is part of wild card */
4001 /* (and hence a wild card label) used in the pCodePeep */
4002 /* optimizations). */
4003 /*-----------------------------------------------------------------*/
4005 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
4008 static int label_key=-1;
4012 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
4013 pcop->type = PO_LABEL;
4018 sprintf(s=buffer,"_%05d_DS_",key);
4020 s = name, key = label_key--;
4023 pcop->name = Safe_strdup(s);
4025 ((pCodeOpLabel *)pcop)->key = key;
4027 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4031 /*-----------------------------------------------------------------*/
4032 /*-----------------------------------------------------------------*/
4033 pCodeOp *pic16_newpCodeOpLit(int lit)
4039 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
4040 pcop->type = PO_LITERAL;
4044 sprintf(s,"0x%02hhx", (unsigned char)lit);
4046 // sprintf(s, "%i", lit);
4049 pcop->name = Safe_strdup(s);
4051 ((pCodeOpLit *)pcop)->lit = lit;
4056 /*-----------------------------------------------------------------*/
4057 /*-----------------------------------------------------------------*/
4058 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
4060 char *s = buffer, tbuf[256], *tb=tbuf;
4064 tb = pic16_get_op(arg2, NULL, 0);
4065 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
4066 pcop->type = PO_LITERAL;
4070 sprintf(s,"0x%02x, %s", (unsigned char)lit, tb);
4072 pcop->name = Safe_strdup(s);
4075 ((pCodeOpLit2 *)pcop)->lit = lit;
4076 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
4081 /*-----------------------------------------------------------------*/
4082 /*-----------------------------------------------------------------*/
4083 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
4087 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
4088 pcop->type = PO_IMMEDIATE;
4090 regs *r = pic16_dirregWithName(name);
4091 pcop->name = Safe_strdup(name);
4095 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
4096 PCOI(pcop)->rIdx = r->rIdx;
4098 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
4099 PCOI(pcop)->rIdx = -1;
4101 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
4106 PCOI(pcop)->index = index;
4107 PCOI(pcop)->offset = offset;
4108 PCOI(pcop)->_const = code_space;
4113 /*-----------------------------------------------------------------*/
4114 /*-----------------------------------------------------------------*/
4115 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
4121 if(!pcwb || !subtype) {
4122 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4126 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4127 pcop->type = PO_WILD;
4128 sprintf(s,"%%%d",id);
4129 pcop->name = Safe_strdup(s);
4131 PCOW(pcop)->id = id;
4132 PCOW(pcop)->pcwb = pcwb;
4133 PCOW(pcop)->subtype = subtype;
4134 PCOW(pcop)->matched = NULL;
4136 PCOW(pcop)->pcop2 = NULL;
4141 /*-----------------------------------------------------------------*/
4142 /*-----------------------------------------------------------------*/
4143 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
4149 if(!pcwb || !subtype || !subtype2) {
4150 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4154 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4155 pcop->type = PO_WILD;
4156 sprintf(s,"%%%d",id);
4157 pcop->name = Safe_strdup(s);
4159 PCOW(pcop)->id = id;
4160 PCOW(pcop)->pcwb = pcwb;
4161 PCOW(pcop)->subtype = subtype;
4162 PCOW(pcop)->matched = NULL;
4164 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4166 if(!subtype2->name) {
4167 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4168 PCOW2(pcop)->pcop.type = PO_WILD;
4169 sprintf(s, "%%%d", id2);
4170 PCOW2(pcop)->pcop.name = Safe_strdup(s);
4171 PCOW2(pcop)->id = id2;
4172 PCOW2(pcop)->subtype = subtype2;
4174 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4175 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4177 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4179 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4180 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4189 /*-----------------------------------------------------------------*/
4190 /*-----------------------------------------------------------------*/
4191 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4195 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4196 pcop->type = PO_GPR_BIT;
4198 pcop->name = Safe_strdup(s);
4202 PCORB(pcop)->bit = bit;
4203 PCORB(pcop)->inBitSpace = inBitSpace;
4204 PCORB(pcop)->subtype = subt;
4206 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4207 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4208 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4209 // PCOR(pcop)->rIdx = 0;
4214 /*-----------------------------------------------------------------*
4215 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4217 * If rIdx >=0 then a specific register from the set of registers
4218 * will be selected. If rIdx <0, then a new register will be searched
4220 *-----------------------------------------------------------------*/
4222 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4226 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4231 PCOR(pcop)->rIdx = rIdx;
4232 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4234 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4237 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4239 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4240 __FUNCTION__, __LINE__);
4245 pcop->type = PCOR(pcop)->r->pc_type;
4250 pCodeOp *pic16_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 //Safe_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);
6203 pct=pic16_findNextInstruction(pc->next);
6204 LinkFlow_pCode(PCI(pc),PCI(pct));
6205 pct=pic16_findNextInstruction(pct->next);
6206 LinkFlow_pCode(PCI(pc),PCI(pct));
6210 if(isPCI_BRANCH(pc)) {
6211 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6213 //fprintf(stderr, "ends with branch\n ");
6214 //pc->print(stderr,pc);
6216 if(!(pcol && isPCOLAB(pcol))) {
6217 if((PCI(pc)->op != POC_RETLW)
6218 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
6220 /* continue if label is '$' which assembler knows how to parse */
6221 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6223 if(pic16_pcode_verbose) {
6224 pc->print(stderr,pc);
6225 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6231 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6232 LinkFlow_pCode(PCI(pc),PCI(pct));
6234 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6235 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6237 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6243 //fprintf(stderr, "ends with non-branching instruction:\n");
6244 //pc->print(stderr,pc);
6246 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6252 //fprintf(stderr, "ends with unknown\n");
6253 //pc->print(stderr,pc);
6257 //fprintf(stderr, "ends with nothing: ERROR\n");
6261 /*-----------------------------------------------------------------*/
6262 /*-----------------------------------------------------------------*/
6264 /*-----------------------------------------------------------------*/
6265 /*-----------------------------------------------------------------*/
6266 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6272 if((!isPCI(pc) && !isPCAD(pc)) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6275 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6285 /*-----------------------------------------------------------------*/
6286 /* insertBankSwitch - inserts a bank switch statement in the */
6287 /* assembly listing */
6289 /* position == 0: insert before */
6290 /* position == 1: insert after pc */
6291 /* position == 2: like 0 but previous was a skip instruction */
6292 /*-----------------------------------------------------------------*/
6293 pCodeOp *pic16_popGetLabel(unsigned int key);
6294 extern int pic16_labelOffset;
6296 static void insertBankSwitch(unsigned char position, pCode *pc)
6303 /* emit BANKSEL [symbol] */
6306 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6308 // position = 0; // position is always before (sanity check!)
6311 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6312 pc->print(stderr, pc);
6317 /* insert the bank switch after this pc instruction */
6318 pCode *pcnext = pic16_findNextInstruction(pc);
6320 pic16_pCodeInsertAfter(pc, new_pc);
6321 if(pcnext)pc = pcnext;
6325 /* insert the bank switch BEFORE this pc instruction */
6326 pic16_pCodeInsertAfter(pc->prev, new_pc);
6331 pCode *pcnext, *pcprev, *npci, *ppc;
6333 int ofs1=0, ofs2=0, len=0;
6335 /* just like 0, but previous was a skip instruction,
6336 * so some care should be taken */
6338 pic16_labelOffset += 10000;
6339 tlbl = newiTempLabel(NULL);
6341 /* invert skip instruction */
6342 pcprev = pic16_findPrevInstruction(pc->prev);
6343 ipci = PCI(pcprev)->inverted_op;
6344 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6346 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6348 /* copy info from old pCode */
6349 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6350 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6351 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6352 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6353 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6354 PCI(npci)->op = PCI(pcprev)->inverted_op;
6356 /* unlink old pCode */
6358 ppc->next = pcprev->next;
6359 pcprev->next->prev = ppc;
6360 pic16_pCodeInsertAfter(ppc, npci);
6362 /* extra instructions to handle invertion */
6363 pcnext = pic16_newpCode(POC_BRA, pic16_popGetLabel(tlbl->key));
6364 pic16_pCodeInsertAfter(npci, pcnext);
6365 pic16_pCodeInsertAfter(pc->prev, new_pc);
6367 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6368 pic16_pCodeInsertAfter(pc, pcnext);
6373 /* Move the label, if there is one */
6374 if(PCI(pc)->label) {
6375 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6376 // __FILE__, __LINE__, pc, new_pc);
6377 PCAD(new_pc)->pci.label = PCI(pc)->label;
6378 PCI(pc)->label = NULL;
6383 /*-----------------------------------------------------------------*/
6384 /*int compareBankFlow - compare the banking requirements between */
6386 /*-----------------------------------------------------------------*/
6387 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6390 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6393 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6396 if(pcflow->firstBank == -1)
6400 if(pcflowLink->pcflow->firstBank == -1) {
6401 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6402 pcflowLink->pcflow->to :
6403 pcflowLink->pcflow->from);
6404 return compareBankFlow(pcflow, pctl, toORfrom);
6408 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6411 pcflowLink->bank_conflict++;
6412 pcflowLink->pcflow->FromConflicts++;
6413 pcflow->ToConflicts++;
6416 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6419 pcflowLink->bank_conflict++;
6420 pcflowLink->pcflow->ToConflicts++;
6421 pcflow->FromConflicts++;
6425 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6426 pcflowLink->pcflow->pc.seq,
6427 pcflowLink->pcflow->FromConflicts,
6428 pcflowLink->pcflow->ToConflicts);
6435 /*-----------------------------------------------------------------*/
6436 /*-----------------------------------------------------------------*/
6437 static void DumpFlow(pBlock *pb)
6441 pCodeFlowLink *pcfl;
6444 fprintf(stderr,"Dump flow \n");
6445 pb->pcHead->print(stderr, pb->pcHead);
6447 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6448 pcflow->print(stderr,pcflow);
6450 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6452 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6454 if(!isPCFL(pcflow)) {
6455 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6458 fprintf(stderr,"dumping: ");
6459 pcflow->print(stderr,pcflow);
6460 FlowStats(PCFL(pcflow));
6462 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6464 pc = PCODE(pcfl->pcflow);
6466 fprintf(stderr, " from seq %d:\n",pc->seq);
6468 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6469 pc->print(stderr,pc);
6474 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6476 pc = PCODE(pcfl->pcflow);
6478 fprintf(stderr, " to seq %d:\n",pc->seq);
6480 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6481 pc->print(stderr,pc);
6490 /*-----------------------------------------------------------------*/
6491 /*-----------------------------------------------------------------*/
6492 static int OptimizepBlock(pBlock *pb)
6497 if(!pb || !peepOptimizing)
6500 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6502 for(pc = pb->pcHead; pc; pc = pc->next)
6503 matches += pic16_pCodePeepMatchRule(pc);
6506 pc = pic16_findNextInstruction(pb->pcHead);
6514 if(pic16_pCodePeepMatchRule(pc)) {
6519 pc = pic16_findNextInstruction(pcprev->next);
6521 pc = pic16_findNextInstruction(pb->pcHead);
6523 pc = pic16_findNextInstruction(pc->next);
6527 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6532 /*-----------------------------------------------------------------*/
6533 /*-----------------------------------------------------------------*/
6534 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6538 for(pc = pcs; pc; pc = pc->next) {
6540 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6542 (PCI(pc)->pcop->type == PO_LABEL) &&
6543 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6551 /*-----------------------------------------------------------------*/
6552 /*-----------------------------------------------------------------*/
6553 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6560 (PCI(pc)->pcop->type == PO_LABEL)) {
6562 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6564 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6565 // if(pcol->pcop.name)
6566 // Safe_free(pcol->pcop.name);
6568 /* If the key is negative, then we (probably) have a label to
6569 * a function and the name is already defined */
6572 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6576 //sprintf(buffer,"_%05d_DS_",pcl->key);
6578 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6580 pcol->pcop.name = Safe_strdup(s);
6581 pcol->key = pcl->key;
6582 //pc->print(stderr,pc);
6589 /*-----------------------------------------------------------------*/
6590 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6591 /* pCode chain if they're not used. */
6592 /*-----------------------------------------------------------------*/
6593 static void pBlockRemoveUnusedLabels(pBlock *pb)
6595 pCode *pc; pCodeLabel *pcl;
6600 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6602 pBranch *pbr = PCI(pc)->label;
6603 if(pbr && pbr->next) {
6604 pCode *pcd = pb->pcHead;
6606 // fprintf(stderr, "multiple labels\n");
6607 // pc->print(stderr,pc);
6612 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6613 //fprintf(stderr,"Used by:\n");
6614 //pcd->print(stderr,pcd);
6616 exchangeLabels(PCL(pbr->pc),pcd);
6625 for(pc = pb->pcHead; pc; pc = pc->next) {
6627 if(isPCL(pc)) // pc->type == PC_LABEL)
6629 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6630 pcl = PCL(PCI(pc)->label->pc);
6633 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6635 /* This pCode is a label, so search the pBlock to see if anyone
6638 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6640 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6641 /* Couldn't find an instruction that refers to this label
6642 * So, unlink the pCode label from it's pCode chain
6643 * and destroy the label */
6644 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6646 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6647 if(pc->type == PC_LABEL) {
6648 pic16_unlinkpCode(pc);
6649 pCodeLabelDestruct(pc);
6651 unlinkpCodeFromBranch(pc, PCODE(pcl));
6652 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6653 Safe_free(pc->label);
6663 /*-----------------------------------------------------------------*/
6664 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6665 /* chain and put them into pBranches that are */
6666 /* associated with the appropriate pCode */
6668 /*-----------------------------------------------------------------*/
6669 void pic16_pBlockMergeLabels(pBlock *pb)
6672 pCode *pc, *pcnext=NULL;
6677 /* First, Try to remove any unused labels */
6678 //pBlockRemoveUnusedLabels(pb);
6680 /* Now loop through the pBlock and merge the labels with the opcodes */
6683 // for(pc = pb->pcHead; pc; pc = pc->next) {
6686 pCode *pcn = pc->next;
6688 if(pc->type == PC_LABEL) {
6690 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6691 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6693 if((pcnext = pic16_findNextInstruction(pc) )) {
6695 // pcnext->print(stderr, pcnext);
6697 // Unlink the pCode label from it's pCode chain
6698 pic16_unlinkpCode(pc);
6700 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6701 // And link it into the instruction's pBranch labels. (Note, since
6702 // it's possible to have multiple labels associated with one instruction
6703 // we must provide a means to accomodate the additional labels. Thus
6704 // the labels are placed into the singly-linked list "label" as
6705 // opposed to being a single member of the pCodeInstruction.)
6707 //_ALLOC(pbr,sizeof(pBranch));
6709 pbr = Safe_calloc(1,sizeof(pBranch));
6713 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6716 if(pic16_pcode_verbose)
6717 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6719 } else if(pc->type == PC_CSOURCE) {
6721 /* merge the source line symbolic info into the next instruction */
6722 if((pcnext = pic16_findNextInstruction(pc) )) {
6724 // Unlink the pCode label from it's pCode chain
6725 pic16_unlinkpCode(pc);
6726 PCI(pcnext)->cline = PCCS(pc);
6727 //fprintf(stderr, "merging CSRC\n");
6728 //genericPrint(stderr,pcnext);
6734 pBlockRemoveUnusedLabels(pb);
6738 /*-----------------------------------------------------------------*/
6739 /*-----------------------------------------------------------------*/
6740 static int OptimizepCode(char dbName)
6742 #define MAX_PASSES 4
6751 DFPRINTF((stderr," Optimizing pCode\n"));
6755 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6756 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6757 matches += OptimizepBlock(pb);
6760 while(matches && ++passes < MAX_PASSES);
6767 const char *pic16_pCodeOpType(pCodeOp *pcop);
6768 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6771 /*-----------------------------------------------------------------*/
6772 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6773 /*-----------------------------------------------------------------*/
6775 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6779 // fprintf(stderr, "%s:%d pc type: %s\tname: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc), pc->name);
6782 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6784 if(PCOR(pc)->r)pcop = pic16_newpCodeOpBit(PCOR(pc)->r->name, bitval, 0, pc->type);
6787 assert(pcop != NULL);
6789 if( !( (pcop->type == PO_LABEL) ||
6790 (pcop->type == PO_LITERAL) ||
6791 (pcop->type == PO_STR) ))
6792 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6793 PCOR(pcop)->r->wasUsed = 1;
6794 PCOR(pcop)->instance = PCOR(pc)->instance;
6800 /*----------------------------------------------------------------------*
6801 * pic16_areRegsSame - check to see if the names of two registers match *
6802 *----------------------------------------------------------------------*/
6803 int pic16_areRegsSame(regs *r1, regs *r2)
6805 if(!strcmp(r1->name, r2->name))return 1;
6811 /*-----------------------------------------------------------------*/
6812 /*-----------------------------------------------------------------*/
6813 static void pic16_FixRegisterBanking(pBlock *pb)
6817 regs *reg, *prevreg;
6818 unsigned char flag=0;
6823 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6826 /* loop through all of the flow blocks with in one pblock */
6828 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6832 /* at this point, pc should point to a PC_FLOW object */
6833 /* for each flow block, determine the register banking
6837 /* if label, then might come from other point, force banksel */
6838 if(isPCL(pc))prevreg = NULL;
6840 if(!isPCI(pc))goto loop;
6842 if(PCI(pc)->label)prevreg = NULL;
6844 if(PCI(pc)->is2MemOp)goto loop;
6846 /* if goto, then force banksel */
6847 // if(PCI(pc)->op == POC_GOTO)prevreg = NULL;
6849 reg = pic16_getRegFromInstruction(pc);
6852 pc->print(stderr, pc);
6853 fprintf(stderr, "reg = %p\n", reg);
6856 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6857 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6858 reg->address,reg->isBitField, reg->isFixed);
6862 /* now make some tests to make sure that instruction needs bank switch */
6864 /* if no register exists, and if not a bit opcode goto loop */
6866 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6869 if(isPCI_SKIP(pc)) {
6870 // fprintf(stderr, "instruction is SKIP instruction\n");
6873 if(reg && isACCESS_BANK(reg))goto loop;
6875 if(!isBankInstruction(pc))goto loop;
6877 if(isPCI_LIT(pc))goto loop;
6879 if(PCI(pc)->op == POC_CALL)goto loop;
6881 /* Examine the instruction before this one to make sure it is
6882 * not a skip type instruction */
6883 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6885 flag = 0; /* add before this instruction */
6887 /* if previous instruction is a skip one, then set flag
6888 * to 2 and call insertBankSwitch */
6889 if(pcprev && isPCI_SKIP(pcprev)) {
6894 if(pic16_options.opt_banksel>0) {
6895 char op1[128], op2[128];
6898 strcpy(op1, pic16_get_op_from_instruction(PCI(pc)));
6899 strcpy(op2, pic16_get_op_from_instruction(PCI(pcprev)));
6900 if(!strcmp(op1, op2))goto loop;
6904 insertBankSwitch(flag, pc);
6906 // fprintf(stderr, "BANK SWITCH inserted\n");
6914 /** ADDITIONS BY RAPHAEL NEIDER, 2004-11-16: GOTO OPTIMIZATIONS **/
6916 /* Returns the (maximum of the) number of bytes used by the specified pCode. */
6917 int instrSize (pCode *pc)
6922 if (!PCAD(pc)->directive || strlen (PCAD(pc)->directive) < 3) return 0;
6923 return 4; // assumes only regular instructions using <= 4 bytes
6926 if (isPCI(pc)) return PCI(pc)->isize;
6931 /* Returns 1 if pc is referenced by the given label (either
6932 * pc is the label itself or is an instruction with an attached
6934 * Returns 0 if pc is not preceeded by the specified label.
6936 int isLabel (pCode *pc, char *label)
6940 // label attached to the pCode?
6941 if (isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO) {
6942 pBranch *lab = NULL;
6943 lab = PCI(pc)->label;
6946 if (isPCL(lab->pc) && strcmp(PCL(lab->pc)->label, label) == 0) {
6953 // is inline assembly label?
6954 if (isPCAD(pc) && PCAD(pc)->directive == NULL && PCAD(pc)->arg) {
6955 // do not compare trailing ':'
6956 if (strncmp (PCAD(pc)->arg, label, strlen (label)) == 0) {
6963 if (strcmp(PCL(pc)->label,label) == 0) {
6968 // no label/no label attached/wrong label(s)
6972 /* Returns the distance to the given label in terms of words.
6973 * Labels are searched only within -max .. max words from pc.
6974 * Returns max if the label could not be found or
6975 * its distance from pc in (-max..+max).
6977 int findpCodeLabel (pCode *pc, char *label, int max, pCode **target) {
6978 int dist = instrSize(pc);
6982 while (dist < max && curr && !isLabel (curr, label)) {
6984 dist += instrSize(curr); // sizeof (instruction)
6986 if (curr && dist < max) {
6987 if (target != NULL) *target = curr;
6992 curr = pic16_findNextInstruction (pc->next);
6994 while (dist < max && curr && !isLabel (curr, label)) {
6995 dist += instrSize(curr); // sizeof (instruction)
6998 if (curr && dist < max) {
6999 if (target != NULL) *target = curr;
7003 if (target != NULL) *target = NULL;
7007 /* Returns -1 if pc does NOT denote an instruction like
7009 * Otherwise we return
7010 * (a) 0x10 + i for BTFSS
7011 * (b) 0x00 + i for BTFSC
7013 int isSkipOnStatus (pCode *pc)
7017 if (!pc || !isPCI(pc)) return -1;
7018 if (PCI(pc)->op == POC_BTFSS) res = 0x10;
7019 else if (PCI(pc)->op == POC_BTFSC) res = 0x00;
7022 pcop = PCI(pc)->pcop;
7024 if (pcop->type == PO_STATUS || (pcop->type == PO_GPR_BIT && strcmp(pcop->name, "STATUS") == 0)) {
7025 return res + ((pCodeOpRegBit *)pcop)->bit;
7031 /* Returns 1 if pc is one of BC, BZ, BOV, BN, BNC, BNZ, BNOV or BNN,
7032 * returns 0 otherwise. */
7033 int isConditionalBranch (pCode *pc)
7035 if (!pc || !isPCI_BRANCH(pc)) return 0;
7037 switch (PCI(pc)->op) {
7055 /* Returns 1 if pc has a label attached to it.
7056 * This can be either a label stored in the pCode itself (.label)
7057 * or a label making up its own pCode preceding this pc.
7058 * Returns 0 if pc cannot be reached directly via a label.
7060 int hasNoLabel (pCode *pc)
7065 // are there any label pCodes between pc and the previous instruction?
7066 prev = pic16_findPrevInstruction (pc->prev);
7067 while (pc && pc != prev) {
7068 // pCode with attached label?
7069 if ((isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO)
7070 && PCI(pc)->label) {
7073 // is inline assembly label?
7074 if (isPCAD(pc) && PCAD(pc)->directive == NULL) return 0;
7075 if (isPCW(pc) && PCW(pc)->label) return 0;
7078 if (isPCL(pc)) return 0;
7087 /* Replaces the old pCode with the new one, moving the labels,
7088 * C source line and probably flow information to the new pCode.
7090 void pic16_pCodeReplace (pCode *oldPC, pCode *newPC) {
7091 if (!oldPC || !newPC || !isPCI(oldPC) || !isPCI(newPC))
7094 /* first move all labels from old to new */
7095 PCI(newPC)->label = pic16_pBranchAppend (PCI(oldPC)->label, PCI(newPC)->label);
7096 PCI(oldPC)->label = NULL;
7098 /* move C source line (if possible) */
7099 if (PCI(oldPC)->cline && !PCI(newPC)->cline)
7100 PCI(newPC)->cline = PCI(oldPC)->cline;
7102 /* insert new pCode into pBlock */
7103 pic16_pCodeInsertAfter (oldPC, newPC);
7104 pic16_unlinkpCode (oldPC);
7106 /* TODO: update flow (newPC->from, newPC->to) */
7107 PCI(newPC)->pcflow = PCI(oldPC)->pcflow;
7109 /* destruct replaced pCode */
7110 oldPC->destruct (oldPC);
7113 /* Returns the inverted conditional branch (if any) or NULL.
7114 * pcop must be set to the new jump target.
7116 pCode *getNegatedBcc (pCode *bcc, pCodeOp *pcop)
7120 if (!bcc || !isPCI(bcc)) return NULL;
7122 switch (PCI(bcc)->op) {
7123 case POC_BC: newBcc = pic16_newpCode (POC_BNC , pcop); break;
7124 case POC_BZ: newBcc = pic16_newpCode (POC_BNZ , pcop); break;
7125 case POC_BOV: newBcc = pic16_newpCode (POC_BNOV, pcop); break;
7126 case POC_BN: newBcc = pic16_newpCode (POC_BNN , pcop); break;
7127 case POC_BNC: newBcc = pic16_newpCode (POC_BC , pcop); break;
7128 case POC_BNZ: newBcc = pic16_newpCode (POC_BZ , pcop); break;
7129 case POC_BNOV: newBcc = pic16_newpCode (POC_BOV , pcop); break;
7130 case POC_BNN: newBcc = pic16_newpCode (POC_BN , pcop); break;
7137 #define MAX_DIST_GOTO 0x7FFFFFFF
7138 #define MAX_DIST_BRA 1020 // maximum offset (in bytes) possible with BRA
7139 #define MAX_DIST_BCC 120 // maximum offset (in bytes) possible with Bcc
7140 #define MAX_JUMPCHAIN_DEPTH 16 // number of GOTOs to follow in resolveJumpChain() (to prevent endless loops)
7141 #define IS_GOTO(arg) ((arg) && isPCI(arg) && (PCI(arg)->op == POC_GOTO || PCI(arg)->op == POC_BRA))
7143 /* Follows GOTO/BRA instructions to their target instructions, stores the
7144 * final destination (not a GOTO or BRA instruction) in target and returns
7145 * the distance from the original pc to *target.
7147 int resolveJumpChain (pCode *pc, pCode **target, pCodeOp **pcop) {
7150 pCodeOp *lastPCOP = NULL;
7154 //fprintf (stderr, "%s:%d: -=-", __FUNCTION__, __LINE__);
7156 /* only follow unconditional branches, except for the initial pCode (which may be a conditional branch) */
7157 while (curr && (last != curr) && (depth++ < MAX_JUMPCHAIN_DEPTH) && isPCI(curr)
7158 && (PCI(curr)->op == POC_GOTO || PCI(curr)->op == POC_BRA || (curr == pc && isConditionalBranch(curr)))) {
7160 lastPCOP = PCI(curr)->pcop;
7161 dist = findpCodeLabel (pc, PCI(curr)->pcop->name, MAX_DIST_GOTO, &curr);
7162 //fprintf (stderr, "last:%p, curr:%p, label:%s\n", last, curr, PCI(last)->pcop->name);
7165 if (target) *target = last;
7166 if (pcop) *pcop = lastPCOP;
7170 /* Returns pc if it is not a OPT_JUMPTABLE_BEGIN INFO pCode.
7171 * Otherwise the first pCode after the jumptable (after
7172 * the OPT_JUMPTABLE_END tag) is returned.
7174 pCode *skipJumptables (pCode *pc, int *isJumptable)
7177 if (!pc) return NULL;
7179 while (pc->type == PC_INFO && PCINF(pc)->type == INF_OPTIMIZATION && PCOO(PCINF(pc)->oper1)->type == OPT_JUMPTABLE_BEGIN) {
7181 //fprintf (stderr, "SKIPPING jumptable\n");
7183 //pc->print(stderr, pc);
7185 } while (pc && (pc->type != PC_INFO || PCINF(pc)->type != INF_OPTIMIZATION
7186 || PCOO(PCINF(pc)->oper1)->type != OPT_JUMPTABLE_END));
7187 //fprintf (stderr, "<<JUMPTAB:\n");
7188 // skip OPT_END as well
7189 if (pc) pc = pc->next;
7195 pCode *pic16_findNextInstructionSkipJumptables (pCode *pc, int *isJumptable)
7199 while (pc && !isPCI(pc) && !isPCAD(pc) && !isPCW(pc)) {
7200 // set pc to the first pCode after a jumptable, leave pc untouched otherwise
7201 pc = skipJumptables (pc, &isJumptab);
7203 // pc is the first pCode after the jumptable
7206 // pc has not been changed by skipJumptables()
7214 /* Turn GOTOs into BRAs if distance between GOTO and label
7215 * is less than 1024 bytes.
7217 * This method is especially useful if GOTOs after BTFS[SC]
7218 * can be turned into BRAs as GOTO would cost another NOP
7221 void pic16_OptimizeJumps ()
7224 pCode *pc_prev = NULL;
7225 pCode *pc_next = NULL;
7228 int change, iteration, isJumptab;
7231 int opt=0, toofar=0, opt_cond = 0, cond_toofar=0, opt_reorder = 0, opt_gotonext = 0, opt_gotochain = 0;
7233 if (!the_pFile) return;
7235 //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7237 for (pb = the_pFile->pbHead; pb != NULL; pb = pb->next) {
7238 int matchedInvertRule = 1;
7241 //fprintf (stderr, "%s:%d: iterating over pBlock %p\n", __FUNCTION__, __LINE__, pb);
7243 pc = pic16_findNextInstruction (pb->pcHead);
7246 pc_next = pic16_findNextInstructionSkipJumptables (pc->next, &isJumptab);
7248 // skip jumptable, i.e. start over with no pc_prev!
7254 /* (1) resolve chained jumps
7255 * Do not perform this until pattern (4) is no longer present! Otherwise we will
7256 * (a) leave dead code in and
7257 * (b) skip over the dead code with an (unneccessary) jump.
7259 if (!matchedInvertRule && (IS_GOTO(pc) || isConditionalBranch(pc))) {
7260 pCodeOp *lastTargetOp = NULL;
7261 int newDist = resolveJumpChain (pc, &target, &lastTargetOp);
7262 int maxDist = MAX_DIST_BCC;
7263 if (PCI(pc)->op == POC_BRA) maxDist = MAX_DIST_BRA;
7264 if (PCI(pc)->op == POC_GOTO) maxDist = MAX_DIST_GOTO;
7266 /* be careful NOT to make the jump instruction longer (might break previously shortened jumps!) */
7267 if (lastTargetOp && newDist <= maxDist && lastTargetOp != PCI(pc)->pcop
7268 && strcmp (lastTargetOp->name, PCI(pc)->pcop->name) != 0) {
7269 //fprintf (stderr, "(1) ");pc->print(stderr, pc); fprintf (stderr, " --> %s\n", lastTargetOp->name);
7270 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(1) jump chain resolved")); }
7271 PCI(pc)->pcop->name = lastTargetOp->name;
7280 int condBraType = isSkipOnStatus(pc_prev);
7281 label = PCI(pc)->pcop->name;
7282 dist = findpCodeLabel(pc, label, MAX_DIST_BRA, &target);
7283 if (dist < 0) dist = -dist;
7284 //fprintf (stderr, "distance: %d (", dist); pc->print(stderr, pc);fprintf (stderr, ")\n");
7288 /* (2) remove "GOTO label; label:" */
7289 if (isLabel (pc_next, label)) {
7290 //fprintf (stderr, "(2) GOTO next instruction: ");pc->print(stderr, pc);fprintf (stderr, " --> ");pc_next->print(stderr, pc_next); fprintf(stderr, "\n");
7291 // first remove all preceeding SKIP instructions
7292 while (pc_prev && isPCI_SKIP(pc_prev)) {
7293 // attach labels on this instruction to pc_next
7294 //fprintf (stderr, "(2) preceeding SKIP removed: ");pc_prev->print(stderr, pc_prev);fprintf(stderr, "\n");
7295 PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc_prev)->label, PCI(pc_next)->label);
7296 PCI(pc_prev)->label = NULL;
7297 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(2) SKIP removed")); }
7298 pic16_unlinkpCode (pc_prev);
7299 pc_prev = pic16_findPrevInstruction (pc);
7301 // now remove the redundant goto itself
7302 PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc)->label, PCI(pc_next)->label);
7303 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP("(2) GOTO next instruction removed")); }
7304 pic16_unlinkpCode (pc);
7305 pc = pic16_findPrevInstruction(pc_next->prev);
7306 isHandled = 1; // do not perform further optimizations
7312 /* (3) turn BTFSx STATUS,i; GOTO label into Bcc label if possible */
7313 if (!isHandled && condBraType != -1 && hasNoLabel(pc)) {
7314 if (dist < MAX_DIST_BCC) {
7316 switch (condBraType) {
7317 case 0x00: bcc = pic16_newpCode (POC_BC, PCI(pc)->pcop);break;
7318 // no BDC on DIGIT CARRY available
7319 case 0x02: bcc = pic16_newpCode (POC_BZ, PCI(pc)->pcop);break;
7320 case 0x03: bcc = pic16_newpCode (POC_BOV, PCI(pc)->pcop);break;
7321 case 0x04: bcc = pic16_newpCode (POC_BN, PCI(pc)->pcop);break;
7322 case 0x10: bcc = pic16_newpCode (POC_BNC, PCI(pc)->pcop);break;
7323 // no BNDC on DIGIT CARRY available
7324 case 0x12: bcc = pic16_newpCode (POC_BNZ, PCI(pc)->pcop);break;
7325 case 0x13: bcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop);break;
7326 case 0x14: bcc = pic16_newpCode (POC_BNN, PCI(pc)->pcop);break;
7328 // no replacement possible
7333 // ATTENTION: keep labels attached to BTFSx!
7334 // HINT: GOTO is label free (checked above)
7335 //fprintf (stderr, "%s:%d: (3) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(bcc)->mnemonic, label);
7336 isHandled = 1; // do not perform further optimizations
7337 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(3) conditional branch introduced")); }
7338 pic16_pCodeReplace (pc_prev, bcc);
7345 //fprintf (stderr, "(%d, too far for Bcc)\n", dist);
7351 // (4) eliminate the following (common) tripel:
7353 // labels1: Bcc label2;
7354 // GOTO somewhere; ; <-- instruction referenced by pc
7356 // and replace it by
7357 // labels1: B#(cc) somewhere; ; #(cc) is the negated condition cc
7359 // ATTENTION: all labels pointing to "Bcc label2" must be attached
7360 // to <cont.> instead
7361 // ATTENTION: This optimization is only valid if <pred.> is
7362 // not a skip operation!
7363 // ATTENTION: somewhere must be within MAX_DIST_BCC bytes!
7364 // ATTENTION: no label may be attached to the GOTO instruction!
7365 if (isConditionalBranch(pc_prev)
7366 && (!isPCI_SKIP(pic16_findPrevInstruction(pc_prev->prev)))
7367 && (dist < MAX_DIST_BCC)
7368 && isLabel(pc_next,PCI(pc_prev)->pcop->name)
7369 && hasNoLabel(pc)) {
7370 pCode *newBcc = getNegatedBcc (pc_prev, PCI(pc)->pcop);
7373 //fprintf (stderr, "%s:%d: (4) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBcc)->mnemonic, label);
7374 isHandled = 1; // do not perform further optimizations
7375 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(4) conditional skipping branch inverted")); }
7376 pic16_pCodeReplace (pc_prev, newBcc);
7381 matchedInvertRule++;
7386 /* (5) now just turn GOTO into BRA */
7387 if (!isHandled && (PCI(pc)->op == POC_GOTO)) {
7388 if (dist < MAX_DIST_BRA) {
7389 pCode *newBra = pic16_newpCode (POC_BRA, PCI(pc)->pcop);
7390 //fprintf (stderr, "%s:%d: (5) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBra)->mnemonic, label);
7391 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc->prev, pic16_newpCodeCharP("(5) GOTO replaced by BRA")); }
7392 pic16_pCodeReplace (pc, newBra);
7397 //fprintf (stderr, "(%d, too far for BRA)\n", dist);
7400 } // if (!isHandled)
7407 pBlockRemoveUnusedLabels (pb);
7409 // This line enables goto chain resolution!
7410 if (matchedInvertRule > 1) matchedInvertRule = 1; else matchedInvertRule = 0;
7413 } while (change); /* fixpoint iteration per pBlock */
7416 // emit some statistics concerning goto-optimization
7418 if (pic16_debug_verbose || pic16_pcode_verbose) {
7419 fprintf (stderr, "optimize-goto:\n"
7420 "\t%5d GOTO->BRA; (%d GOTOs too far)\n"
7421 "\t%5d BTFSx, GOTO->Bcc (%d too far)\n"
7422 "\t%5d conditional \"skipping\" jumps inverted\n"
7423 "\t%5d GOTOs to next instruction removed\n"
7424 "\t%5d chained GOTOs resolved\n",
7425 opt, toofar, opt_cond, cond_toofar, opt_reorder, opt_gotonext, opt_gotochain);
7428 //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7432 #undef MAX_JUMPCHAIN_DEPTH
7433 #undef MAX_DIST_GOTO
7437 /** END OF RAPHAEL NEIDER'S ADDITIONS **/
7439 static void pBlockDestruct(pBlock *pb)
7450 /*-----------------------------------------------------------------*/
7451 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
7452 /* name dbName and combine them */
7453 /* into one block */
7454 /*-----------------------------------------------------------------*/
7455 static void mergepBlocks(char dbName)
7458 pBlock *pb, *pbmerged = NULL,*pbn;
7460 pb = the_pFile->pbHead;
7462 //fprintf(stderr," merging blocks named %c\n",dbName);
7466 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
7467 if( getpBlock_dbName(pb) == dbName) {
7469 //fprintf(stderr," merged block %c\n",dbName);
7474 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
7475 /* pic16_addpCode2pBlock doesn't handle the tail: */
7476 pbmerged->pcTail = pb->pcTail;
7478 pb->prev->next = pbn;
7480 pbn->prev = pb->prev;
7485 //pic16_printpBlock(stderr, pbmerged);
7492 /*-----------------------------------------------------------------*/
7493 /* AnalyzeFlow - Examine the flow of the code and optimize */
7495 /* level 0 == minimal optimization */
7496 /* optimize registers that are used only by two instructions */
7497 /* level 1 == maximal optimization */
7498 /* optimize by looking at pairs of instructions that use the */
7500 /*-----------------------------------------------------------------*/
7502 static void AnalyzeFlow(int level)
7504 static int times_called=0;
7509 /* remove unused allocated registers before exiting */
7510 pic16_RemoveUnusedRegisters();
7516 /* if this is not the first time this function has been called,
7517 then clean up old flow information */
7518 if(times_called++) {
7519 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7522 pic16_RegsUnMapLiveRanges();
7527 /* Phase 2 - Flow Analysis - Register Banking
7529 * In this phase, the individual flow blocks are examined
7530 * and register banking is fixed.
7534 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7535 pic16_FixRegisterBanking(pb);
7538 /* Phase 2 - Flow Analysis
7540 * In this phase, the pCode is partition into pCodeFlow
7541 * blocks. The flow blocks mark the points where a continuous
7542 * stream of instructions changes flow (e.g. because of
7543 * a call or goto or whatever).
7546 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7547 pic16_BuildFlow(pb);
7550 /* Phase 2 - Flow Analysis - linking flow blocks
7552 * In this phase, the individual flow blocks are examined
7553 * to determine their order of excution.
7556 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7559 /* Phase 3 - Flow Analysis - Flow Tree
7561 * In this phase, the individual flow blocks are examined
7562 * to determine their order of execution.
7565 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7566 pic16_BuildFlowTree(pb);
7569 /* Phase x - Flow Analysis - Used Banks
7571 * In this phase, the individual flow blocks are examined
7572 * to determine the Register Banks they use
7576 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7581 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7582 pic16_pCodeRegMapLiveRanges(pb);
7584 pic16_RemoveUnusedRegisters();
7586 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
7587 pic16_pCodeRegOptimizeRegUsage(level);
7595 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7600 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7602 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7603 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7604 pcflow = pcflow->next) {
7606 FillFlow(PCFL(pcflow));
7611 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7614 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7615 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7616 pcflow = pcflow->next) {
7618 FlowStats(PCFL(pcflow));
7624 /* VR -- no need to analyze banking in flow, but left here :
7625 * 1. because it may be used in the future for other purposes
7626 * 2. because if omitted we'll miss some optimization done here
7628 * Perhaps I should rename it to something else
7631 /*-----------------------------------------------------------------*/
7632 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
7633 /* assigned to the registers. */
7635 /*-----------------------------------------------------------------*/
7637 void pic16_AnalyzeBanking(void)
7642 /* Phase x - Flow Analysis - Used Banks
7644 * In this phase, the individual flow blocks are examined
7645 * to determine the Register Banks they use
7651 if(!the_pFile)return;
7653 if(!pic16_options.no_banksel) {
7654 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7655 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
7656 pic16_FixRegisterBanking(pb);
7662 /*-----------------------------------------------------------------*/
7663 /* buildCallTree - Look at the flow and extract all of the calls. */
7664 /*-----------------------------------------------------------------*/
7665 static set *register_usage(pBlock *pb);
7667 static void buildCallTree(void )
7679 /* Now build the call tree.
7680 First we examine all of the pCodes for functions.
7681 Keep in mind that the function boundaries coincide
7682 with pBlock boundaries.
7684 The algorithm goes something like this:
7685 We have two nested loops. The outer loop iterates
7686 through all of the pBlocks/functions. The inner
7687 loop iterates through all of the pCodes for
7688 a given pBlock. When we begin iterating through
7689 a pBlock, the variable pc_fstart, pCode of the start
7690 of a function, is cleared. We then search for pCodes
7691 of type PC_FUNCTION. When one is encountered, we
7692 initialize pc_fstart to this and at the same time
7693 associate a new pBranch object that signifies a
7694 branch entry. If a return is found, then this signifies
7695 a function exit point. We'll link the pCodes of these
7696 returns to the matching pc_fstart.
7698 When we're done, a doubly linked list of pBranches
7699 will exist. The head of this list is stored in
7700 `the_pFile', which is the meta structure for all
7701 of the pCode. Look at the pic16_printCallTree function
7702 on how the pBranches are linked together.
7705 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7706 pCode *pc_fstart=NULL;
7707 for(pc = pb->pcHead; pc; pc = pc->next) {
7709 if(isPCI(pc) && pc_fstart) {
7710 if(PCI(pc)->is2MemOp) {
7711 r = pic16_getRegFromInstruction2(pc);
7712 if(r && !strcmp(r->name, "POSTDEC1"))
7713 PCF(pc_fstart)->stackusage++;
7715 r = pic16_getRegFromInstruction(pc);
7716 if(r && !strcmp(r->name, "PREINC1"))
7717 PCF(pc_fstart)->stackusage--;
7722 if (PCF(pc)->fname) {
7724 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
7725 //fprintf(stderr," found main \n");
7726 pb->cmemmap = NULL; /* FIXME do we need to free ? */
7730 pbr = Safe_calloc(1,sizeof(pBranch));
7731 pbr->pc = pc_fstart = pc;
7734 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7736 // Here's a better way of doing the same:
7737 addSet(&pb->function_entries, pc);
7740 // Found an exit point in a function, e.g. return
7741 // (Note, there may be more than one return per function)
7743 pBranchLink(PCF(pc_fstart), PCF(pc));
7745 addSet(&pb->function_exits, pc);
7747 } else if(isCALL(pc)) {
7748 addSet(&pb->function_calls,pc);
7755 /* This is not needed because currently all register used
7756 * by a function are stored in stack -- VR */
7758 /* Re-allocate the registers so that there are no collisions
7759 * between local variables when one function call another */
7762 // pic16_deallocateAllRegs();
7764 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7772 /*-----------------------------------------------------------------*/
7773 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7774 /* all of the logical connections. */
7776 /* Essentially what's done here is that the pCode flow is */
7778 /*-----------------------------------------------------------------*/
7780 void pic16_AnalyzepCode(char dbName)
7791 /* Phase 1 - Register allocation and peep hole optimization
7793 * The first part of the analysis is to determine the registers
7794 * that are used in the pCode. Once that is done, the peep rules
7795 * are applied to the code. We continue to loop until no more
7796 * peep rule optimizations are found (or until we exceed the
7797 * MAX_PASSES threshold).
7799 * When done, the required registers will be determined.
7805 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7806 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7808 /* First, merge the labels with the instructions */
7809 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7810 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7812 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7813 //fprintf(stderr," analyze and merging block %c\n",dbName);
7814 pic16_pBlockMergeLabels(pb);
7817 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7822 changes = OptimizepCode(dbName);
7825 } while(changes && (i++ < MAX_PASSES));
7832 /* convert a series of movff's of local regs to stack, with a single call to
7833 * a support functions which does the same thing via loop */
7834 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
7838 char *fname[]={"__lr_store", "__lr_restore"};
7840 // pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
7842 pct = pic16_findNextInstruction(pcstart->next);
7845 pct = pc->next; //pic16_findNextInstruction(pc->next);
7846 // pc->print(stderr, pc);
7847 if(isPCI(pc) && PCI(pc)->label) {
7848 pbr = PCI(pc)->label;
7849 while(pbr && pbr->pc) {
7850 PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
7854 // pc->print(stderr, pc);
7856 pc->prev->next = pct;
7857 pct->prev = pc->prev;
7861 } while ((pc) && (pc != pcend));
7863 /* unlink movff instructions */
7864 pcstart->next = pcend;
7865 pcend->prev = pcstart;
7869 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7870 // pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popCopyReg(pic16_framepnt_lo)))); pc = pct;
7873 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name)))); pc = pct;
7874 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
7875 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] ))); pc = pct;
7878 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7879 // pic16_popCopyReg(pic16_framepnt_lo), pic16_popCopyReg(&pic16_pc_fsr0l)))); pc = pct;
7886 sym = newSymbol( fname[ entry?0:1 ], 0 );
7887 strcpy(sym->rname, fname[ entry?0:1 ]);
7888 checkAddSym(&externs, sym);
7890 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
7895 /*-----------------------------------------------------------------*/
7896 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for */
7897 /* local registers to a support function call */
7898 /*-----------------------------------------------------------------*/
7899 void pic16_OptimizeLocalRegs(void)
7904 pCodeOpLocalReg *pclr;
7907 regs *r, *lastr=NULL, *firstr=NULL;
7908 pCode *pcstart=NULL, *pcend=NULL;
7913 * local_regs begin mark
7914 * MOVFF r0x01, POSTDEC1
7915 * MOVFF r0x02, POSTDEC1
7918 * MOVFF r0x0n, POSTDEC1
7919 * local_regs end mark
7921 * convert the above to the below:
7922 * MOVLW starting_register_index
7924 * MOVLW register_count
7925 * call __save_registers_in_stack
7931 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7932 inRegCount = regCount = 0;
7933 firstr = lastr = NULL;
7934 for(pc = pb->pcHead; pc; pc = pc->next) {
7936 /* hold current function name */
7937 if(pc && isPCF(pc))curFunc = PCF(pc)->fname;
7939 if(pc && (pc->type == PC_INFO)) {
7942 if(pci->type == INF_LOCALREGS) {
7943 pclr = PCOLR(pci->oper1);
7945 if((pclr->type == LR_ENTRY_BEGIN)
7946 || (pclr->type == LR_ENTRY_END))inEntry = 1;
7949 switch(pclr->type) {
7950 case LR_ENTRY_BEGIN:
7952 inRegCount = 1; regCount = 0;
7953 pcstart = pc; //pic16_findNextInstruction(pc->next);
7954 firstr = lastr = NULL;
7960 pcend = pc; //pic16_findPrevInstruction(pc->prev);
7963 if(curFunc && inWparamList(curFunc+1)) {
7964 fprintf(stderr, "sdcc: %s: warning: disabling lr-support for functionn %s\n",
7968 pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
7973 firstr = lastr = NULL;
7977 if(inRegCount == -1) {
7978 // fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
7984 if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
7986 r = pic16_getRegFromInstruction(pc);
7988 r = pic16_getRegFromInstruction2(pc);
7989 if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
7990 if(!firstr)firstr = r;
7992 // fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
8004 /*-----------------------------------------------------------------*/
8005 /* ispCodeFunction - returns true if *pc is the pCode of a */
8007 /*-----------------------------------------------------------------*/
8008 static bool ispCodeFunction(pCode *pc)
8011 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
8017 /*-----------------------------------------------------------------*/
8018 /* findFunction - Search for a function by name (given the name) */
8019 /* in the set of all functions that are in a pBlock */
8020 /* (note - I expect this to change because I'm planning to limit */
8021 /* pBlock's to just one function declaration */
8022 /*-----------------------------------------------------------------*/
8023 static pCode *findFunction(char *fname)
8030 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8032 pc = setFirstItem(pb->function_entries);
8035 if((pc->type == PC_FUNCTION) &&
8037 (strcmp(fname, PCF(pc)->fname)==0))
8040 pc = setNextItem(pb->function_entries);
8048 static void MarkUsedRegisters(set *regset)
8053 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
8054 // fprintf(stderr, "marking register = %s\t", r1->name);
8055 r2 = pic16_regWithIdx(r1->rIdx);
8056 // fprintf(stderr, "to register = %s\n", r2->name);
8062 static void pBlockStats(FILE *of, pBlock *pb)
8068 if(!pic16_pcode_verbose)return;
8070 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
8072 // for now just print the first element of each set
8073 pc = setFirstItem(pb->function_entries);
8075 fprintf(of,";entry: ");
8078 pc = setFirstItem(pb->function_exits);
8080 fprintf(of,";has an exit\n");
8084 pc = setFirstItem(pb->function_calls);
8086 fprintf(of,";functions called:\n");
8089 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8090 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
8092 pc = setNextItem(pb->function_calls);
8096 r = setFirstItem(pb->tregisters);
8098 int n = elementsInSet(pb->tregisters);
8100 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
8103 fprintf(of,"; %s\n",r->name);
8104 r = setNextItem(pb->tregisters);
8108 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
8111 /*-----------------------------------------------------------------*/
8112 /*-----------------------------------------------------------------*/
8114 static void sequencepCode(void)
8120 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8122 pb->seq = GpCodeSequenceNumber+1;
8124 for( pc = pb->pcHead; pc; pc = pc->next)
8125 pc->seq = ++GpCodeSequenceNumber;
8131 /*-----------------------------------------------------------------*/
8132 /*-----------------------------------------------------------------*/
8133 static set *register_usage(pBlock *pb)
8136 set *registers=NULL;
8137 set *registersInCallPath = NULL;
8139 /* check recursion */
8141 pc = setFirstItem(pb->function_entries);
8148 if(pc->type != PC_FUNCTION)
8149 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
8151 pc = setFirstItem(pb->function_calls);
8152 for( ; pc; pc = setNextItem(pb->function_calls)) {
8154 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8155 char *dest = pic16_get_op_from_instruction(PCI(pc));
8157 pcn = findFunction(dest);
8159 registersInCallPath = register_usage(pcn->pb);
8161 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8166 pBlockStats(stderr,pb); // debug
8169 // Mark the registers in this block as used.
8171 MarkUsedRegisters(pb->tregisters);
8172 if(registersInCallPath) {
8173 /* registers were used in the functions this pBlock has called */
8174 /* so now, we need to see if these collide with the ones we are */
8177 regs *r1,*r2, *newreg;
8179 DFPRINTF((stderr,"comparing registers\n"));
8181 r1 = setFirstItem(registersInCallPath);
8184 r2 = setFirstItem(pb->tregisters);
8186 while(r2 && (r1->type != REG_STK)) {
8188 if(r2->rIdx == r1->rIdx) {
8189 newreg = pic16_findFreeReg(REG_GPR);
8193 DFPRINTF((stderr,"Bummer, no more registers.\n"));
8197 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
8198 r1->rIdx, newreg->rIdx));
8199 r2->rIdx = newreg->rIdx;
8200 //if(r2->name) Safe_free(r2->name);
8202 r2->name = Safe_strdup(newreg->name);
8206 newreg->wasUsed = 1;
8208 r2 = setNextItem(pb->tregisters);
8211 r1 = setNextItem(registersInCallPath);
8214 /* Collisions have been resolved. Now free the registers in the call path */
8215 r1 = setFirstItem(registersInCallPath);
8217 if(r1->type != REG_STK) {
8218 newreg = pic16_regWithIdx(r1->rIdx);
8221 r1 = setNextItem(registersInCallPath);
8225 // MarkUsedRegisters(pb->registers);
8227 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
8230 DFPRINTF((stderr,"returning regs\n"));
8232 DFPRINTF((stderr,"not returning regs\n"));
8234 DFPRINTF((stderr,"pBlock after register optim.\n"));
8235 pBlockStats(stderr,pb); // debug
8241 /*-----------------------------------------------------------------*/
8242 /* pct2 - writes the call tree to a file */
8244 /*-----------------------------------------------------------------*/
8245 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
8249 // set *registersInCallPath = NULL;
8255 fprintf(of, "recursive function\n");
8256 return; //recursion ?
8259 pc = setFirstItem(pb->function_entries);
8266 for(i=0;i<indent;i++) // Indentation
8270 if(pc->type == PC_FUNCTION) {
8271 usedstack += PCF(pc)->stackusage;
8272 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
8273 } else return; // ???
8276 pc = setFirstItem(pb->function_calls);
8277 for( ; pc; pc = setNextItem(pb->function_calls)) {
8279 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8280 char *dest = pic16_get_op_from_instruction(PCI(pc));
8282 pcn = findFunction(dest);
8284 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
8286 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8294 /*-----------------------------------------------------------------*/
8295 /* pic16_printCallTree - writes the call tree to a file */
8297 /*-----------------------------------------------------------------*/
8299 void pic16_printCallTree(FILE *of)
8311 fprintf(of, "\npBlock statistics\n");
8312 for(pb = the_pFile->pbHead; pb; pb = pb->next )
8316 fprintf(of,"Call Tree\n");
8317 pbr = the_pFile->functions;
8321 if(!ispCodeFunction(pc))
8322 fprintf(of,"bug in call tree");
8325 fprintf(of,"Function: %s\n", PCF(pc)->fname);
8327 while(pc->next && !ispCodeFunction(pc->next)) {
8329 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
8330 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
8338 fprintf(of,"\n**************\n\na better call tree\n");
8339 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8344 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8345 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
8351 /*-----------------------------------------------------------------*/
8353 /*-----------------------------------------------------------------*/
8355 static void InlineFunction(pBlock *pb)
8363 pc = setFirstItem(pb->function_calls);
8365 for( ; pc; pc = setNextItem(pb->function_calls)) {
8368 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8374 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
8376 //fprintf(stderr,"Cool can inline:\n");
8377 //pcn->print(stderr,pcn);
8379 //fprintf(stderr,"recursive call Inline\n");
8380 InlineFunction(pcn->pb);
8381 //fprintf(stderr,"return from recursive call Inline\n");
8384 At this point, *pc points to a CALL mnemonic, and
8385 *pcn points to the function that is being called.
8387 To in-line this call, we need to remove the CALL
8388 and RETURN(s), and link the function pCode in with
8394 /* Remove the CALL */
8398 /* remove callee pBlock from the pBlock linked list */
8399 removepBlock(pcn->pb);
8407 /* Remove the Function pCode */
8408 pct = pic16_findNextInstruction(pcn->next);
8410 /* Link the function with the callee */
8411 pc->next = pcn->next;
8412 pcn->next->prev = pc;
8414 /* Convert the function name into a label */
8416 pbr = Safe_calloc(1,sizeof(pBranch));
8417 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
8419 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
8420 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
8422 /* turn all of the return's except the last into goto's */
8423 /* check case for 2 instruction pBlocks */
8424 pce = pic16_findNextInstruction(pcn->next);
8426 pCode *pce_next = pic16_findNextInstruction(pce->next);
8428 if(pce_next == NULL) {
8429 /* found the last return */
8430 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
8432 //fprintf(stderr,"found last return\n");
8433 //pce->print(stderr,pce);
8434 pce->prev->next = pc_call->next;
8435 pc_call->next->prev = pce->prev;
8436 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
8446 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8452 /*-----------------------------------------------------------------*/
8454 /*-----------------------------------------------------------------*/
8456 void pic16_InlinepCode(void)
8465 if(!functionInlining)
8468 /* Loop through all of the function definitions and count the
8469 * number of times each one is called */
8470 //fprintf(stderr,"inlining %d\n",__LINE__);
8472 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8474 pc = setFirstItem(pb->function_calls);
8476 for( ; pc; pc = setNextItem(pb->function_calls)) {
8479 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8480 if(pcn && isPCF(pcn)) {
8481 PCF(pcn)->ncalled++;
8484 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8489 //fprintf(stderr,"inlining %d\n",__LINE__);
8491 /* Now, Loop through the function definitions again, but this
8492 * time inline those functions that have only been called once. */
8494 InlineFunction(the_pFile->pbHead);
8495 //fprintf(stderr,"inlining %d\n",__LINE__);
8497 for(pb = the_pFile->pbHead; pb; pb = pb->next)
8502 char *pic_optype_names[]={
8503 "PO_NONE", // No operand e.g. NOP
8504 "PO_W", // The working register (as a destination)
8505 "PO_WREG", // The working register (as a file register)
8506 "PO_STATUS", // The 'STATUS' register
8507 "PO_BSR", // The 'BSR' register
8508 "PO_FSR0", // The "file select register" (in PIC18 family it's one
8510 "PO_INDF0", // The Indirect register
8511 "PO_INTCON", // Interrupt Control register
8512 "PO_GPR_REGISTER", // A general purpose register
8513 "PO_GPR_BIT", // A bit of a general purpose register
8514 "PO_GPR_TEMP", // A general purpose temporary register
8515 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
8516 "PO_PCL", // Program counter Low register
8517 "PO_PCLATH", // Program counter Latch high register
8518 "PO_PCLATU", // Program counter Latch upper register
8519 "PO_PRODL", // Product Register Low
8520 "PO_PRODH", // Product Register High
8521 "PO_LITERAL", // A constant
8522 "PO_REL_ADDR", // A relative address
8523 "PO_IMMEDIATE", // (8051 legacy)
8524 "PO_DIR", // Direct memory (8051 legacy)
8525 "PO_CRY", // bit memory (8051 legacy)
8526 "PO_BIT", // bit operand.
8527 "PO_STR", // (8051 legacy)
8529 "PO_WILD" // Wild card operand in peep optimizer
8533 char *dumpPicOptype(PIC_OPTYPE type)
8535 return (pic_optype_names[ type ]);
8539 /*** BEGIN of stuff belonging to the BANKSEL optimization ***/
8542 #define MAX_COMMON_BANK_SIZE 32
8543 #define FIRST_PSEUDO_BANK_NR 1000
8545 hTab *sym2bank = NULL; // <OPERAND NAME> --> <PSEUDO BANK NR>
8546 hTab *bank2sym = NULL; // <PSEUDO BANK NR> --> <OPERAND NAME>
8547 hTab *coerce = NULL; // <PSEUDO BANK NR> --> <&PSEUDOBANK>
8550 typedef enum { INVALID_BANK = -1, UNKNOWN_BANK = -2, FIXED_BANK = -3 } pseudoBankNr;
8553 pseudoBankNr bank; // number assigned to this pseudoBank
8554 unsigned int size; // number of operands assigned to this bank
8555 unsigned int ref; // number of symbols referring to this pseudoBank (for garbage collection)
8558 /*----------------------------------------------------------------------*/
8559 /* hashSymbol - hash function used to map SYMBOLs (or operands) to ints */
8560 /*----------------------------------------------------------------------*/
8561 unsigned int hashSymbol (const char *str)
8563 unsigned int res = 0;
8568 res = (res << 4) | (res >> (8 * sizeof(unsigned int) - 4));
8575 /*-----------------------------------------------------------------------*/
8576 /* compareSymbol - return 1 iff sym1 equals sym2 */
8577 /*-----------------------------------------------------------------------*/
8578 int compareSymbol (const void *sym1, const void *sym2)
8580 char *s1 = (char*) sym1;
8581 char *s2 = (char*) sym2;
8583 return (strcmp (s1,s2) == 0);
8586 /*-----------------------------------------------------------------------*/
8587 /* comparePre - return 1 iff p1 == p2 */
8588 /*-----------------------------------------------------------------------*/
8589 int comparePtr (const void *p1, const void *p2)
8594 /*----------------------------------------------------------*/
8595 /* getSymbolFromOperand - return a pointer to the symbol in */
8596 /* the given operand and its length */
8597 /*----------------------------------------------------------*/
8598 char *getSymbolFromOperand (char *op, unsigned int *len)
8603 if (!op) return NULL;
8605 // we recognize two forms of operands: SYMBOL and (SYMBOL + offset)
8607 if (*sym == '(') sym++;
8610 while (((*curr >= 'A') && (*curr <= 'Z'))
8611 || ((*curr >= 'a') && (*curr <= 'z'))
8612 || ((curr != sym) && (*curr >= '0') && (*curr <= '9'))
8613 || (*curr == '_')) {
8614 // find end of symbol [A-Za-z_]?[A-Za-z0-9]*
8622 /*--------------------------------------------------------------------------*/
8623 /* getSymFromBank - get (one) name of a symbol assigned to the given bank */
8624 /*--------------------------------------------------------------------------*/
8625 char *getSymFromBank (pseudoBankNr bank)
8629 if (bank < 0) return "<INVALID BANK NR>";
8630 return hTabFindByKey (bank2sym, bank % bank2sym->size, (void *) bank, &comparePtr);
8633 /*-----------------------------------------------------------------------*/
8634 /* getPseudoBsrFromOperand - maps a string to its corresponding pseudo */
8635 /* bank number (uses hTab sym2bank), if the */
8636 /* symbol is not yet assigned a pseudo bank it */
8637 /* is assigned one here */
8638 /*-----------------------------------------------------------------------*/
8639 pseudoBankNr getPseudoBankNrFromOperand (const char *op)
8641 static pseudoBankNr next_bank = FIRST_PSEUDO_BANK_NR;
8647 hash = hashSymbol (op) % sym2bank->size;
8648 bank = (pseudoBankNr) hTabFindByKey (sym2bank, hash, op, &compareSymbol);
8649 if (bank == (pseudoBankNr)NULL) bank = UNKNOWN_BANK;
8651 if (bank == UNKNOWN_BANK) {
8652 // create a pseudo bank for the operand
8654 hTabAddItemLong (&sym2bank, hash, (char *)op, (void *)bank);
8655 hTabAddItemLong (&bank2sym, bank, (void *) bank, (void *)op);
8656 getOrAddGNode (adj, NULL, bank); // adds the node if it does not exist yet
8657 //fprintf (stderr, "%s:%d: adding %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8659 //fprintf (stderr, "%s:%d: found %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8667 /*--------------------------------------------------------------------*/
8668 /* isBanksel - check whether the given pCode is a BANKSEL instruction */
8669 /*--------------------------------------------------------------------*/
8670 int isBanksel (pCode *pc)
8674 if (isPCI(pc) && (PCI(pc)->op == POC_BANKSEL || PCI(pc)->op == POC_MOVLB)) {
8675 // BANKSEL <variablename> or MOVLB <banknr>
8676 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8680 // check for inline assembler BANKSELs
8681 if (isPCAD(pc) && PCAD(pc)->directive && (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0 ||
8682 STRCASECMP(PCAD(pc)->directive,"MOVLB") == 0)) {
8683 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8687 // assume pc is no BANKSEL instruction
8691 /*---------------------------------------------------------------------------------*/
8692 /* invalidatesBSR - check whether the pCodeInstruction passed in modifies the BSR */
8693 /* This method can not guarantee to find all modifications of the */
8694 /* BSR (e.g. via INDirection registers) but covers all compiler */
8695 /* generated plus some cases. */
8696 /*---------------------------------------------------------------------------------*/
8697 int invalidatesBSR(pCode *pc)
8699 // assembler directives invalidate BSR (well, they might, we don't know)
8700 if (isPCAD(pc)) return 1;
8702 // only ASMDIRs and pCodeInstructions can invalidate BSR
8703 if (!isPCI(pc)) return 0;
8705 // we have a pCodeInstruction
8707 // check for BSR modifying instructions
8708 switch (PCI(pc)->op) {
8712 case POC_RETFIE: // might be used as CALL replacement
8713 case POC_RETLW: // might be used as CALL replacement
8714 case POC_RETURN: // might be used as CALL replacement
8719 default: // other instruction do not change BSR unless BSR is an explicit operand!
8720 // TODO: check for BSR as an explicit operand (e.g. INCF BSR,F), which should be rather unlikely...!
8724 // no change of BSR possible/probable
8728 /*------------------------------------------------------------*/
8729 /* getBankFromBanksel - return the pseudo bank nr assigned to */
8730 /* the symbol referenced in this BANKSEL */
8731 /*------------------------------------------------------------*/
8732 pseudoBankNr getBankFromBanksel (pCode *pc)
8735 int data = (int)NULL;
8737 if (!pc) return INVALID_BANK;
8739 if (isPCAD(pc) && PCAD(pc)->directive) {
8740 if (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0) {
8741 // get symbolname from PCAD(pc)->arg
8742 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8743 sym = PCAD(pc)->arg;
8744 data = getPseudoBankNrFromOperand (sym);
8745 //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8746 } else if (STRCASECMP(PCAD(pc)->directive,"MOVLB")) {
8747 // get (literal) bank number from PCAD(pc)->arg
8748 fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8749 assert (0 && "not yet implemented - turn off banksel optimization for now");
8751 } else if (isPCI(pc)) {
8752 if (PCI(pc)->op == POC_BANKSEL) {
8753 // get symbolname from PCI(pc)->pcop->name (?)
8754 //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8755 sym = PCI(pc)->pcop->name;
8756 data = getPseudoBankNrFromOperand (sym);
8757 //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8758 } else if (PCI(pc)->op == POC_MOVLB) {
8759 // get (literal) bank number from PCI(pc)->pcop->name
8760 fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8761 assert (0 && "not yet implemented - turn off banksel optimization for now");
8766 // no assigned bank could be found
8767 return UNKNOWN_BANK;
8772 /*------------------------------------------------------------------------------*/
8773 /* getEffectiveBank - resolves the currently assigned effective pseudo bank nr */
8774 /*------------------------------------------------------------------------------*/
8775 pseudoBankNr getEffectiveBank (pseudoBankNr bank)
8779 if (bank < FIRST_PSEUDO_BANK_NR) return bank;
8782 //fprintf (stderr, "%s:%d: bank=%d\n", __FUNCTION__, __LINE__, bank);
8783 data = (pseudoBank *) hTabFindByKey (coerce, bank % coerce->size, (void *) bank, &comparePtr);
8785 if (data->bank != bank)
8792 //fprintf (stderr, "%s:%d: effective bank=%d\n", __FUNCTION__, __LINE__, bank);
8796 /*------------------------------------------------------------------*/
8797 /* attachBsrInfo2pBlock - create a look-up table as to which pseudo */
8798 /* bank is selected at a given pCode */
8799 /*------------------------------------------------------------------*/
8801 /* Create a graph with pseudo banks as its nodes and switches between
8802 * these as edges (with the edge weight representing the absolute
8803 * number of BANKSELs from one to the other).
8804 * Removes redundand BANKSELs instead iff mod == 1.
8805 * BANKSELs update the pseudo BSR, labels invalidate the current BSR
8806 * value (setting it to 0=UNNKOWN), (R)CALLs also invalidate the
8808 * TODO: check ALL instructions operands if they modify BSR directly...
8810 * pb - the pBlock to annotate
8811 * mod - select either graph creation (0) or BANKSEL removal (1)
8813 unsigned int attachBsrInfo2pBlock (pBlock *pb, int mod)
8815 pCode *pc, *pc_next;
8816 unsigned int prevBSR = UNKNOWN_BANK, pseudoBSR = UNKNOWN_BANK;
8817 int isBankselect = 0;
8818 unsigned int banksels=0;
8822 pc = pic16_findNextInstruction(pb->pcHead);
8824 isBankselect = isBanksel (pc);
8825 pc_next = pic16_findNextInstruction (pc->next);
8827 if (!hasNoLabel (pc)) {
8828 // we don't know our predecessors -- assume different BSRs
8829 prevBSR = UNKNOWN_BANK;
8830 pseudoBSR = UNKNOWN_BANK;
8831 //fprintf (stderr, "invalidated by label at "); pc->print (stderr, pc);
8834 // check if this is a BANKSEL instruction
8836 pseudoBSR = getEffectiveBank (getBankFromBanksel(pc));
8837 //fprintf (stderr, "BANKSEL via "); pc->print (stderr, pc);
8839 if (prevBSR == pseudoBSR && pseudoBSR >= 0) {
8840 //fprintf (stderr, "removing redundant "); pc->print (stderr, pc);
8841 if (1 || pic16_pcode_verbose) pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("removed redundant BANKSEL"));
8842 pic16_unlinkpCode (pc);
8846 addGEdge2 (getOrAddGNode (adj, NULL, prevBSR), getOrAddGNode (adj, NULL, pseudoBSR), 1, 0);
8851 if (!isBankselect && invalidatesBSR(pc)) {
8852 // check if this instruction invalidates the pseudoBSR
8853 pseudoBSR = UNKNOWN_BANK;
8854 //fprintf (stderr, "invalidated via "); pc->print (stderr, pc);
8857 prevBSR = pseudoBSR;
8864 /*------------------------------------------------------------------------------------*/
8865 /* assignToSameBank - returns 0 on success or an error code */
8866 /* 1 - common bank would be too large */
8867 /* 2 - assignment to fixed (absolute) bank not performed */
8869 /* This functions assumes that unsplittable operands are already assigned to the same */
8870 /* bank (e.g. all objects being referenced as (SYMBOL + offset) must be in the same */
8871 /* bank so that we can make sure the bytes are laid out sequentially in memory) */
8872 /* TODO: Symbols with an abslute address must be handled specially! */
8873 /*------------------------------------------------------------------------------------*/
8874 int assignToSameBank (int bank0, int bank1, int doAbs)
8876 int eff0, eff1, dummy;
8877 pseudoBank *pbank0, *pbank1;
8880 eff0 = getEffectiveBank (bank0);
8881 eff1 = getEffectiveBank (bank1);
8883 //fprintf (stderr, "%s:%d: bank0=%d/%d, bank1=%d/%d, doAbs=%d\n", __FUNCTION__, __LINE__, bank0, eff0, bank1, eff1, doAbs);
8885 // nothing to do if already same bank
8886 if (eff0 == eff1) return 0;
8888 if (!doAbs && (eff0 < FIRST_PSEUDO_BANK_NR || eff1 < FIRST_PSEUDO_BANK_NR))
8891 // ensure eff0 < eff1
8893 // swap eff0 and eff1
8902 // now assign bank eff1 to bank eff0
8903 pbank0 = (pseudoBank *) hTabFindByKey (coerce, eff0 % coerce->size, (void *)((char*)0+eff0), &comparePtr);
8905 pbank0 = Safe_calloc (1, sizeof (pseudoBank));
8906 pbank0->bank = eff0;
8909 hTabAddItemLong (&coerce, eff0 % coerce->size, (void *)((char*)0+eff0), (void *) pbank0);
8913 hitem = hTabSearch (coerce, eff1 % coerce->size);
8914 while (hitem && hitem->pkey != (void *)((char*)0+eff1))
8915 hitem = hitem->next;
8917 if (hitem) pbank1 = (pseudoBank *) hitem->item;
8920 fprintf (stderr, "bank #%d/%d & bank #%d/%d --> bank #%d: %u (%s & %s)\n", bank0, eff0, bank1, eff1,
8921 pbank0->bank, pbank0->size,
8922 getSymFromBank (eff0), getSymFromBank (eff1));
8926 if (pbank0->size + pbank1->size > MAX_COMMON_BANK_SIZE) {
8928 fprintf (stderr, "bank #%d: %u, bank #%d: %u --> bank #%d': %u > %u (%s,%s)\n",
8929 pbank0->bank, pbank0->size, pbank1->bank, pbank1->size,
8930 pbank0->bank, pbank0->size + pbank1->size, MAX_COMMON_BANK_SIZE,
8931 getSymFromBank (pbank0->bank), getSymFromBank (pbank1->bank));
8935 pbank0->size += pbank1->size;
8937 if (pbank1->ref == 0) Safe_free (pbank1);
8943 hitem->item = pbank0;
8945 hTabAddItemLong (&coerce, eff1 % coerce->size, (void *)((char*)0+eff1), (void *) pbank0);
8948 //fprintf (stderr, "%s:%d: leaving.\n", __FUNCTION__, __LINE__);
8953 /*----------------------------------------------------------------*/
8954 /* mergeGraphNodes - combines two nodes into one and modifies all */
8955 /* edges to and from the nodes accordingly */
8956 /* This method needs complete backedges, i.e. if (A,B) is an edge */
8957 /* then also (B,A) must be an edge (possibly with weight 0). */
8958 /*----------------------------------------------------------------*/
8959 void mergeGraphNodes (GraphNode *node1, GraphNode *node2)
8961 GraphEdge *edge, *backedge, *nextedge;
8965 assert (node1 && node2);
8966 assert (node1 != node2);
8968 // add all edges starting at node2 to node1
8971 nextedge = edge->next;
8973 backedge = getGEdge (node, node2);
8975 backweight = backedge->weight;
8978 // insert edges (node1,node) and (node,node1)
8979 addGEdge2 (node1, node, edge->weight, backweight);
8980 // remove edges (node, node2) and (node2, node)
8981 remGEdge (node2, node);
8982 remGEdge (node, node2);
8986 // now node2 should not be referenced by any other GraphNode...
8987 //remGNode (adj, node2->data, node2->hash);
8990 /*----------------------------------------------------------------*/
8991 /* showGraph - dump the current BANKSEL graph as a node/edge list */
8992 /*----------------------------------------------------------------*/
8993 void showGraph (Graph *g)
8997 pseudoBankNr bankNr;
9004 bankNr = getEffectiveBank (node->hash);
9005 assert (bankNr >= 0);
9006 pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9008 bankNr = pbank->bank;
9014 fprintf (stderr, "edges from %s (bank %u, size %u) to:\n", getSymFromBank (node->hash), bankNr, size);
9017 if (edge->weight > 0)
9018 fprintf (stderr, " %4u x %s\n", edge->weight, getSymFromBank (edge->node->hash));
9025 /*---------------------------------------------------------------*/
9026 /* pic16_OptimizeBanksel - remove redundant BANKSEL instructions */
9027 /*---------------------------------------------------------------*/
9028 void pic16_OptimizeBanksel ()
9030 GraphNode *node, *node1, *node1next;
9033 // needed for more effective bank assignment (needs adjusted pic16_emit_usection())
9034 GraphEdge *edge, *backedge;
9036 int maxWeight, weight, mergeMore, absMaxWeight;
9037 pseudoBankNr curr0, curr1;
9040 pseudoBankNr bankNr;
9041 char *base_symbol0, *base_symbol1;
9046 unsigned int bankselsTotal = 0, bankselsRemoved = 0;
9048 //fprintf (stderr, "%s:%s:%d: entered.\n", __FILE__, __FUNCTION__, __LINE__);
9050 if (!the_pFile || !the_pFile->pbHead) return;
9052 adj = newGraph (NULL);
9053 sym2bank = newHashTable ( 255 );
9054 bank2sym = newHashTable ( 255 );
9055 coerce = newHashTable ( 255 );
9057 // create graph of BANKSEL relationships (node = operands, edge (A,B) iff BANKSEL B follows BANKSEL A)
9058 for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9059 bankselsTotal += attachBsrInfo2pBlock (pb, 0);
9063 // assign symbols with absolute addresses to their respective bank nrs
9064 set = pic16_fix_udata;
9065 for (reg = setFirstItem (set); reg; reg = setNextItem (set)) {
9066 bankNr = reg->address >> 8;
9067 node = getOrAddGNode (adj, NULL, bankNr);
9068 bankNr = (pseudoBankNr) getEffectiveBank (getPseudoBankNrFromOperand(reg->name));
9069 assignToSameBank (node->hash, bankNr, 1);
9071 assert (bankNr >= 0);
9072 pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9074 pbank = Safe_calloc (1, sizeof (pseudoBank));
9075 pbank->bank = reg->address >> 8; //FIXED_BANK;
9078 hTabAddItemLong (&coerce, bankNr % coerce->size, (void *) bankNr, pbank);
9080 assert (pbank->bank == (reg->address >> 8));
9081 pbank->bank = reg->address >> 8; //FIXED_BANK;
9083 //fprintf (stderr, "ABS: %s (%d bytes) at %x in bank %u\n", reg->name, reg->size, reg->address, bankNr);
9088 // assign operands referring to the same symbol (which is not given an absolute address) to the same bank
9089 //fprintf (stderr, "assign operands with the same symbol to the same bank\n");
9092 if (node->hash < 0) { node = node->next; continue; }
9093 base_symbol0 = getSymbolFromOperand (getSymFromBank (getEffectiveBank(node->hash)), &len0);
9096 if (node1->hash < 0) { node1 = node1->next; continue; }
9097 node1next = node1->next;
9098 base_symbol1 = getSymbolFromOperand (getSymFromBank (getEffectiveBank (node1->hash)), &len1);
9099 if (len0 == len1 && len0 > 0 && strncmp (base_symbol0, base_symbol1, len0) == 0) {
9100 // TODO: check for symbols with absolute addresses -- these might be placed across bank boundaries!
9101 //fprintf (stderr, "merging %s and %s\n", getSymFromBank (getEffectiveBank(node->hash)), getSymFromBank (getEffectiveBank(node1->hash)));
9102 if (assignToSameBank (node->hash, node1->hash, 0)) {
9103 fprintf (stderr, "%s(%d) == %s(%d)\n", base_symbol0, len0, base_symbol1, len1);
9104 assert (0 && "Could not assign a symbol to a bank!");
9106 mergeGraphNodes (node, node1);
9108 if (node->hash < node1->hash)
9109 mergeGraphNodes (node, node1);
9111 mergeGraphNodes (node1, node); // this removes node so node->next will fail...
9121 // >>> THIS ALSO NEEDS AN UPDATED pic16_emit_usection() TO REFLECT THE BANK ASSIGNMENTS <<<
9122 // assign tightly coupled operands to the same (pseudo) bank
9123 //fprintf (stderr, "assign tightly coupled operands to the same bank\n");
9131 curr0 = getEffectiveBank (node->hash);
9132 if (curr0 < 0) { node = node->next; continue; }
9135 assert (edge->src == node);
9136 backedge = getGEdge (edge->node, edge->src);
9137 weight = edge->weight + (backedge ? backedge->weight : 0);
9138 curr1 = getEffectiveBank (edge->node->hash);
9139 if (curr1 < 0) { edge = edge->next; continue; }
9141 // merging is only useful if the items are not assigned to the same bank already...
9142 if (curr0 != curr1 && weight > maxWeight) {
9143 if (maxWeight > absMaxWeight) absMaxWeight = maxWeight;
9152 if (maxWeight > 0) {
9154 fprintf (stderr, "%s:%d: merging (%4u) %d(%s) and %d(%s)\n", __FUNCTION__, __LINE__, maxWeight,
9155 max->src->hash, getSymFromBank (max->src->hash),
9156 max->node->hash, getSymFromBank (max->node->hash));
9159 node = getGNode (adj, max->src->data, max->src->hash);
9160 node1 = getGNode (adj, max->node->data, max->node->hash);
9162 if (0 == assignToSameBank (max->src->hash, max->node->hash, 0)) {
9163 if (max->src->hash < max->node->hash)
9164 mergeGraphNodes (node, node1);
9166 mergeGraphNodes (node1, node);
9168 remGEdge (node, node1);
9169 remGEdge (node1, node);
9180 // remove redundant BANKSELs
9181 //fprintf (stderr, "removing redundant BANKSELs\n");
9182 for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9183 bankselsRemoved += attachBsrInfo2pBlock (pb, 1);
9188 fprintf (stderr, "display graph\n");
9193 //fprintf (stderr, "%s:%s:%d: leaving, %u/%u BANKSELs removed...\n", __FILE__, __FUNCTION__, __LINE__, bankselsRemoved, bankselsTotal);
9196 /*** END of stuff belonging to the BANKSEL optimization ***/