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_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
61 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
63 pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL}; //deprecated !
65 pCodeOpReg pic16_pc_fsr0l = {{PO_FSR0, "FSR0L"}, -1, NULL, 0, NULL};
66 pCodeOpReg pic16_pc_fsr0h = {{PO_FSR0, "FSR0H"}, -1, NULL, 0, NULL};
67 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
68 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
69 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
70 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
72 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
73 pCodeOpReg pic16_pc_postinc0 = {{PO_INDF0, "POSTINC0"}, -1, NULL, 0, NULL};
74 pCodeOpReg pic16_pc_postdec0 = {{PO_INDF0, "POSTDEC0"}, -1, NULL, 0, NULL};
75 pCodeOpReg pic16_pc_preinc0 = {{PO_INDF0, "PREINC0"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_plusw0 = {{PO_INDF0, "PLUSW0"}, -1, NULL, 0, NULL};
78 pCodeOpReg pic16_pc_indf1 = {{PO_INDF0, "INDF1"}, -1, NULL,0,NULL};
79 pCodeOpReg pic16_pc_postinc1 = {{PO_INDF0, "POSTINC1"}, -1, NULL, 0, NULL};
80 pCodeOpReg pic16_pc_postdec1 = {{PO_INDF0, "POSTDEC1"}, -1, NULL, 0, NULL};
81 pCodeOpReg pic16_pc_preinc1 = {{PO_INDF0, "PREINC1"}, -1, NULL, 0, NULL};
82 pCodeOpReg pic16_pc_plusw1 = {{PO_INDF0, "PLUSW1"}, -1, NULL, 0, NULL};
84 pCodeOpReg pic16_pc_indf2 = {{PO_INDF0, "INDF2"}, -1, NULL,0,NULL};
85 pCodeOpReg pic16_pc_postinc2 = {{PO_INDF0, "POSTINC2"}, -1, NULL, 0, NULL};
86 pCodeOpReg pic16_pc_postdec2 = {{PO_INDF0, "POSTDEC2"}, -1, NULL, 0, NULL};
87 pCodeOpReg pic16_pc_preinc2 = {{PO_INDF0, "PREINC2"}, -1, NULL, 0, NULL};
88 pCodeOpReg pic16_pc_plusw2 = {{PO_INDF0, "PLUSW2"}, -1, NULL, 0, NULL};
92 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
93 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
94 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
96 static int mnemonics_initialized = 0;
99 static hTab *pic16MnemonicsHash = NULL;
100 static hTab *pic16pCodePeepCommandsHash = NULL;
102 static pFile *the_pFile = NULL;
103 static pBlock *pb_dead_pcodes = NULL;
105 /* Hardcoded flags to change the behavior of the PIC port */
106 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
107 static int functionInlining = 1; /* inline functions if nonzero */
108 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
110 int pic16_pcode_verbose = 0;
112 //static int GpCodeSequenceNumber = 1;
113 static int GpcFlowSeq = 1;
115 extern void pic16_RemoveUnusedRegisters(void);
116 extern void pic16_RegsUnMapLiveRanges(void);
117 extern void pic16_BuildFlowTree(pBlock *pb);
118 extern void pic16_pCodeRegOptimizeRegUsage(int level);
119 extern int pic16_picIsInitialized(void);
120 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
121 extern int mnem2key(char const *mnem);
123 /****************************************************************/
124 /* Forward declarations */
125 /****************************************************************/
127 void pic16_unlinkpCode(pCode *pc);
129 static void genericAnalyze(pCode *pc);
130 static void AnalyzeGOTO(pCode *pc);
131 static void AnalyzeSKIP(pCode *pc);
132 static void AnalyzeRETURN(pCode *pc);
135 static void genericDestruct(pCode *pc);
136 static void genericPrint(FILE *of,pCode *pc);
138 static void pCodePrintLabel(FILE *of, pCode *pc);
139 static void pCodePrintFunction(FILE *of, pCode *pc);
140 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
141 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
142 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
143 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
144 int pic16_pCodePeepMatchRule(pCode *pc);
145 static void pBlockStats(FILE *of, pBlock *pb);
146 static pBlock *newpBlock(void);
147 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
148 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
149 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
150 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
153 /****************************************************************/
154 /* PIC Instructions */
155 /****************************************************************/
157 pCodeInstruction pic16_pciADDWF = {
158 {PC_OPCODE, NULL, NULL, 0, NULL,
171 1,0, // dest, bit instruction
173 0, // literal operand
175 0, // fast call/return mode select bit
176 0, // second memory operand
177 0, // second literal operand
179 (PCC_W | PCC_REGISTER), // inCond
180 (PCC_REGISTER | PCC_Z), // outCond
184 pCodeInstruction pic16_pciADDFW = {
185 {PC_OPCODE, NULL, NULL, 0, NULL,
198 0,0, // dest, bit instruction
200 0, // literal operand
202 0, // fast call/return mode select bit
203 0, // second memory operand
204 0, // second literal operand
206 (PCC_W | PCC_REGISTER), // inCond
207 (PCC_W | PCC_Z), // outCond
211 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
212 {PC_OPCODE, NULL, NULL, 0, NULL,
225 1,0, // dest, bit instruction
227 0, // literal operand
229 0, // fast call/return mode select bit
230 0, // second memory operand
231 0, // second literal operand
233 (PCC_W | PCC_REGISTER | PCC_C), // inCond
234 (PCC_REGISTER | PCC_Z), // outCond
238 pCodeInstruction pic16_pciADDFWC = {
239 {PC_OPCODE, NULL, NULL, 0, NULL,
252 0,0, // dest, bit instruction
254 0, // literal operand
256 0, // fast call/return mode select bit
257 0, // second memory operand
258 0, // second literal operand
260 (PCC_W | PCC_REGISTER | PCC_C), // inCond
261 (PCC_W | PCC_Z), // outCond
265 pCodeInstruction pic16_pciADDLW = {
266 {PC_OPCODE, NULL, NULL, 0, NULL,
279 0,0, // dest, bit instruction
281 1, // literal operand
283 0, // fast call/return mode select bit
284 0, // second memory operand
285 0, // second literal operand
287 (PCC_W | PCC_LITERAL), // inCond
288 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
292 pCodeInstruction pic16_pciANDLW = {
293 {PC_OPCODE, NULL, NULL, 0, NULL,
306 0,0, // dest, bit instruction
308 1, // literal operand
310 0, // fast call/return mode select bit
311 0, // second memory operand
312 0, // second literal operand
314 (PCC_W | PCC_LITERAL), // inCond
315 (PCC_W | PCC_Z | PCC_N), // outCond
319 pCodeInstruction pic16_pciANDWF = {
320 {PC_OPCODE, NULL, NULL, 0, NULL,
333 1,0, // dest, bit instruction
335 0, // literal operand
337 0, // fast call/return mode select bit
338 0, // second memory operand
339 0, // second literal operand
341 (PCC_W | PCC_REGISTER), // inCond
342 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
346 pCodeInstruction pic16_pciANDFW = {
347 {PC_OPCODE, NULL, NULL, 0, NULL,
360 0,0, // dest, bit instruction
362 0, // literal operand
364 0, // fast call/return mode select bit
365 0, // second memory operand
366 0, // second literal operand
368 (PCC_W | PCC_REGISTER), // inCond
369 (PCC_W | PCC_Z) // outCond
372 pCodeInstruction pic16_pciBC = { // mdubuc - New
373 {PC_OPCODE, NULL, NULL, 0, NULL,
386 0,0, // dest, bit instruction
388 0, // literal operand
390 0, // fast call/return mode select bit
391 0, // second memory operand
392 0, // second literal operand
394 (PCC_REL_ADDR | PCC_C), // inCond
399 pCodeInstruction pic16_pciBCF = {
400 {PC_OPCODE, NULL, NULL, 0, NULL,
413 1,1, // dest, bit instruction
415 0, // literal operand
417 0, // fast call/return mode select bit
418 0, // second memory operand
419 0, // second literal operand
421 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
422 PCC_REGISTER, // outCond
426 pCodeInstruction pic16_pciBN = { // mdubuc - New
427 {PC_OPCODE, NULL, NULL, 0, NULL,
440 0,0, // dest, bit instruction
442 0, // literal operand
444 0, // fast call/return mode select bit
445 0, // second memory operand
446 0, // second literal operand
448 (PCC_REL_ADDR | PCC_N), // inCond
449 PCC_NONE , // outCond
453 pCodeInstruction pic16_pciBNC = { // mdubuc - New
454 {PC_OPCODE, NULL, NULL, 0, NULL,
467 0,0, // dest, bit instruction
469 0, // literal operand
471 0, // fast call/return mode select bit
472 0, // second memory operand
473 0, // second literal operand
475 (PCC_REL_ADDR | PCC_C), // inCond
476 PCC_NONE , // outCond
480 pCodeInstruction pic16_pciBNN = { // mdubuc - New
481 {PC_OPCODE, NULL, NULL, 0, NULL,
494 0,0, // dest, bit instruction
496 0, // literal operand
498 0, // fast call/return mode select bit
499 0, // second memory operand
500 0, // second literal operand
502 (PCC_REL_ADDR | PCC_N), // inCond
503 PCC_NONE , // outCond
507 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
508 {PC_OPCODE, NULL, NULL, 0, NULL,
521 0,0, // dest, bit instruction
523 0, // literal operand
525 0, // fast call/return mode select bit
526 0, // second memory operand
527 0, // second literal operand
529 (PCC_REL_ADDR | PCC_OV), // inCond
530 PCC_NONE , // outCond
534 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
535 {PC_OPCODE, NULL, NULL, 0, NULL,
548 0,0, // dest, bit instruction
550 0, // literal operand
552 0, // fast call/return mode select bit
553 0, // second memory operand
554 0, // second literal operand
556 (PCC_REL_ADDR | PCC_Z), // inCond
557 PCC_NONE , // outCond
561 pCodeInstruction pic16_pciBOV = { // mdubuc - New
562 {PC_OPCODE, NULL, NULL, 0, NULL,
575 0,0, // dest, bit instruction
577 0, // literal operand
579 0, // fast call/return mode select bit
580 0, // second memory operand
581 0, // second literal operand
583 (PCC_REL_ADDR | PCC_OV), // inCond
584 PCC_NONE , // outCond
588 pCodeInstruction pic16_pciBRA = { // mdubuc - New
589 {PC_OPCODE, NULL, NULL, 0, NULL,
602 0,0, // dest, bit instruction
604 0, // literal operand
606 0, // fast call/return mode select bit
607 0, // second memory operand
608 0, // second literal operand
610 PCC_REL_ADDR, // inCond
611 PCC_NONE , // outCond
615 pCodeInstruction pic16_pciBSF = {
616 {PC_OPCODE, NULL, NULL, 0, NULL,
629 1,1, // dest, bit instruction
631 0, // literal operand
633 0, // fast call/return mode select bit
634 0, // second memory operand
635 0, // second literal operand
637 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
638 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
642 pCodeInstruction pic16_pciBTFSC = {
643 {PC_OPCODE, NULL, NULL, 0, NULL,
656 0,1, // dest, bit instruction
658 0, // literal operand
660 0, // fast call/return mode select bit
661 0, // second memory operand
662 0, // second literal operand
664 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
665 PCC_EXAMINE_PCOP, // outCond
669 pCodeInstruction pic16_pciBTFSS = {
670 {PC_OPCODE, NULL, NULL, 0, NULL,
683 0,1, // dest, bit instruction
685 0, // literal operand
687 0, // fast call/return mode select bit
688 0, // second memory operand
689 0, // second literal operand
691 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
692 PCC_EXAMINE_PCOP, // outCond
696 pCodeInstruction pic16_pciBTG = { // mdubuc - New
697 {PC_OPCODE, NULL, NULL, 0, NULL,
710 0,1, // dest, bit instruction
712 0, // literal operand
714 0, // fast call/return mode select bit
715 0, // second memory operand
716 0, // second literal operand
718 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
719 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
723 pCodeInstruction pic16_pciBZ = { // mdubuc - New
724 {PC_OPCODE, NULL, NULL, 0, NULL,
737 0,0, // dest, bit instruction
739 0, // literal operand
741 0, // fast call/return mode select bit
742 0, // second memory operand
743 0, // second literal operand
750 pCodeInstruction pic16_pciCALL = {
751 {PC_OPCODE, NULL, NULL, 0, NULL,
764 0,0, // dest, bit instruction
766 0, // literal operand
768 1, // fast call/return mode select bit
769 0, // second memory operand
770 0, // second literal operand
773 PCC_NONE , // outCond
777 pCodeInstruction pic16_pciCOMF = {
778 {PC_OPCODE, NULL, NULL, 0, NULL,
791 1,0, // dest, bit instruction
793 0, // literal operand
795 0, // fast call/return mode select bit
796 0, // second memory operand
797 0, // second literal operand
799 PCC_REGISTER, // inCond
800 PCC_REGISTER , // outCond
804 pCodeInstruction pic16_pciCOMFW = {
805 {PC_OPCODE, NULL, NULL, 0, NULL,
818 0,0, // dest, bit instruction
820 0, // literal operand
822 0, // fast call/return mode select bit
823 0, // second memory operand
824 0, // second literal operand
826 PCC_REGISTER, // inCond
831 pCodeInstruction pic16_pciCLRF = {
832 {PC_OPCODE, NULL, NULL, 0, NULL,
845 0,0, // dest, bit instruction
847 0, // literal operand
849 0, // fast call/return mode select bit
850 0, // second memory operand
851 0, // second literal operand
853 PCC_REGISTER, // inCond
854 PCC_REGISTER , // outCond
858 pCodeInstruction pic16_pciCLRWDT = {
859 {PC_OPCODE, NULL, NULL, 0, NULL,
872 0,0, // dest, bit instruction
874 0, // literal operand
876 0, // fast call/return mode select bit
877 0, // second memory operand
878 0, // second literal operand
881 PCC_NONE , // outCond
885 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
886 {PC_OPCODE, NULL, NULL, 0, NULL,
899 0,0, // dest, bit instruction
901 0, // literal operand
903 0, // fast call/return mode select bit
904 0, // second memory operand
905 0, // second literal operand
907 (PCC_W | PCC_REGISTER), // inCond
908 PCC_NONE , // outCond
912 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
913 {PC_OPCODE, NULL, NULL, 0, NULL,
926 0,0, // dest, bit instruction
928 0, // literal operand
930 0, // fast call/return mode select bit
931 0, // second memory operand
932 0, // second literal operand
934 (PCC_W | PCC_REGISTER), // inCond
935 PCC_NONE , // outCond
939 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
940 {PC_OPCODE, NULL, NULL, 0, NULL,
953 1,0, // dest, bit instruction
955 0, // literal operand
957 0, // fast call/return mode select bit
958 0, // second memory operand
959 0, // second literal operand
961 (PCC_W | PCC_REGISTER), // inCond
962 PCC_NONE , // outCond
966 pCodeInstruction pic16_pciDAW = {
967 {PC_OPCODE, NULL, NULL, 0, NULL,
980 0,0, // dest, bit instruction
982 0, // literal operand
984 0, // fast call/return mode select bit
985 0, // second memory operand
986 0, // second literal operand
989 (PCC_W | PCC_C), // outCond
993 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
994 {PC_OPCODE, NULL, NULL, 0, NULL,
1000 NULL, // from branch
1007 1,0, // dest, bit instruction
1008 1,1, // branch, skip
1009 0, // literal operand
1010 1, // RAM access bit
1011 0, // fast call/return mode select bit
1012 0, // second memory operand
1013 0, // second literal operand
1015 PCC_REGISTER, // inCond
1016 PCC_REGISTER , // outCond
1020 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1021 {PC_OPCODE, NULL, NULL, 0, NULL,
1027 NULL, // from branch
1034 0,0, // dest, bit instruction
1035 1,1, // branch, skip
1036 0, // literal operand
1037 1, // RAM access bit
1038 0, // fast call/return mode select bit
1039 0, // second memory operand
1040 0, // second literal operand
1042 PCC_REGISTER, // inCond
1047 pCodeInstruction pic16_pciDECF = {
1048 {PC_OPCODE, NULL, NULL, 0, NULL,
1054 NULL, // from branch
1061 1,0, // dest, bit instruction
1062 0,0, // branch, skip
1063 0, // literal operand
1064 1, // RAM access bit
1065 0, // fast call/return mode select bit
1066 0, // second memory operand
1067 0, // second literal operand
1069 PCC_REGISTER, // inCond
1070 PCC_REGISTER , // outCond
1074 pCodeInstruction pic16_pciDECFW = {
1075 {PC_OPCODE, NULL, NULL, 0, NULL,
1081 NULL, // from branch
1088 0,0, // dest, bit instruction
1089 0,0, // branch, skip
1090 0, // literal operand
1091 1, // RAM access bit
1092 0, // fast call/return mode select bit
1093 0, // second memory operand
1094 0, // second literal operand
1096 PCC_REGISTER, // inCond
1101 pCodeInstruction pic16_pciDECFSZ = {
1102 {PC_OPCODE, NULL, NULL, 0, NULL,
1108 NULL, // from branch
1115 1,0, // dest, bit instruction
1116 1,1, // branch, skip
1117 0, // literal operand
1118 1, // RAM access bit
1119 0, // fast call/return mode select bit
1120 0, // second memory operand
1121 0, // second literal operand
1123 PCC_REGISTER, // inCond
1124 PCC_REGISTER , // outCond
1128 pCodeInstruction pic16_pciDECFSZW = {
1129 {PC_OPCODE, NULL, NULL, 0, NULL,
1135 NULL, // from branch
1142 0,0, // dest, bit instruction
1143 1,1, // 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
1155 pCodeInstruction pic16_pciGOTO = {
1156 {PC_OPCODE, NULL, NULL, 0, NULL,
1162 NULL, // from branch
1169 0,0, // dest, bit instruction
1170 1,0, // branch, skip
1171 0, // literal operand
1172 0, // RAM access bit
1173 0, // fast call/return mode select bit
1174 0, // second memory operand
1175 0, // second literal operand
1177 PCC_REL_ADDR, // inCond
1178 PCC_NONE , // outCond
1182 pCodeInstruction pic16_pciINCF = {
1183 {PC_OPCODE, NULL, NULL, 0, NULL,
1189 NULL, // from branch
1196 1,0, // dest, bit instruction
1197 0,0, // branch, skip
1198 0, // literal operand
1199 1, // RAM access bit
1200 0, // fast call/return mode select bit
1201 0, // second memory operand
1202 0, // second literal operand
1204 PCC_REGISTER, // inCond
1205 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1209 pCodeInstruction pic16_pciINCFW = {
1210 {PC_OPCODE, NULL, NULL, 0, NULL,
1216 NULL, // from branch
1223 0,0, // dest, bit instruction
1224 0,0, // branch, skip
1225 0, // literal operand
1226 1, // RAM access bit
1227 0, // fast call/return mode select bit
1228 0, // second memory operand
1229 0, // second literal operand
1231 PCC_REGISTER, // inCond
1236 pCodeInstruction pic16_pciINCFSZ = {
1237 {PC_OPCODE, NULL, NULL, 0, NULL,
1243 NULL, // from branch
1250 1,0, // dest, bit instruction
1251 1,1, // branch, skip
1252 0, // literal operand
1253 1, // RAM access bit
1254 0, // fast call/return mode select bit
1255 0, // second memory operand
1256 0, // second literal operand
1258 PCC_REGISTER, // inCond
1259 PCC_REGISTER , // outCond
1263 pCodeInstruction pic16_pciINCFSZW = {
1264 {PC_OPCODE, NULL, NULL, 0, NULL,
1270 NULL, // from branch
1277 0,0, // dest, bit instruction
1278 1,1, // branch, skip
1279 0, // literal operand
1280 1, // RAM access bit
1281 0, // fast call/return mode select bit
1282 0, // second memory operand
1283 0, // second literal operand
1285 PCC_REGISTER, // inCond
1290 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1291 {PC_OPCODE, NULL, NULL, 0, NULL,
1297 NULL, // from branch
1304 1,0, // dest, bit instruction
1305 1,1, // branch, skip
1306 0, // literal operand
1307 1, // RAM access bit
1308 0, // fast call/return mode select bit
1309 0, // second memory operand
1310 0, // second literal operand
1312 PCC_REGISTER, // inCond
1313 PCC_REGISTER , // outCond
1317 pCodeInstruction pic16_pciIORWF = {
1318 {PC_OPCODE, NULL, NULL, 0, NULL,
1324 NULL, // from branch
1331 1,0, // dest, bit instruction
1332 0,0, // branch, skip
1333 0, // literal operand
1334 1, // RAM access bit
1335 0, // fast call/return mode select bit
1336 0, // second memory operand
1337 0, // second literal operand
1339 (PCC_W | PCC_REGISTER), // inCond
1340 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1344 pCodeInstruction pic16_pciIORFW = {
1345 {PC_OPCODE, NULL, NULL, 0, NULL,
1351 NULL, // from branch
1358 0,0, // dest, bit instruction
1359 0,0, // branch, skip
1360 0, // literal operand
1361 1, // RAM access bit
1362 0, // fast call/return mode select bit
1363 0, // second memory operand
1364 0, // second literal operand
1366 (PCC_W | PCC_REGISTER), // inCond
1367 (PCC_W | PCC_Z | PCC_N), // outCond
1371 pCodeInstruction pic16_pciIORLW = {
1372 {PC_OPCODE, NULL, NULL, 0, NULL,
1378 NULL, // from branch
1385 0,0, // dest, bit instruction
1386 0,0, // branch, skip
1387 1, // literal operand
1388 0, // RAM access bit
1389 0, // fast call/return mode select bit
1390 0, // second memory operand
1391 0, // second literal operand
1393 (PCC_W | PCC_LITERAL), // inCond
1394 (PCC_W | PCC_Z | PCC_N), // outCond
1398 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1399 {PC_OPCODE, NULL, NULL, 0, NULL,
1405 NULL, // from branch
1412 0,0, // dest, bit instruction
1413 0,0, // branch, skip
1414 1, // literal operand
1415 0, // RAM access bit
1416 0, // fast call/return mode select bit
1417 0, // second memory operand
1418 1, // second literal operand
1420 (PCC_REGISTER | PCC_LITERAL),
1421 PCC_REGISTER, // outCond
1425 pCodeInstruction pic16_pciMOVF = {
1426 {PC_OPCODE, NULL, NULL, 0, NULL,
1432 NULL, // from branch
1439 1,0, // dest, bit instruction
1440 0,0, // branch, skip
1441 0, // literal operand
1442 1, // RAM access bit
1443 0, // fast call/return mode select bit
1444 0, // second memory operand
1445 0, // second literal operand
1447 PCC_REGISTER, // inCond
1448 (PCC_Z | PCC_N), // outCond
1452 pCodeInstruction pic16_pciMOVFW = {
1453 {PC_OPCODE, NULL, NULL, 0, NULL,
1459 NULL, // from branch
1466 0,0, // dest, bit instruction
1467 0,0, // branch, skip
1468 0, // literal operand
1469 1, // RAM access bit
1470 0, // fast call/return mode select bit
1471 0, // second memory operand
1472 0, // second literal operand
1474 PCC_REGISTER, // inCond
1475 (PCC_W | PCC_Z), // outCond
1479 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1480 {PC_OPCODE, NULL, NULL, 0, NULL,
1486 NULL, // from branch
1493 0,0, // dest, bit instruction
1494 0,0, // branch, skip
1495 0, // literal operand
1496 0, // RAM access bit
1497 0, // fast call/return mode select bit
1498 1, // second memory operand
1499 0, // second literal operand
1501 PCC_REGISTER, // inCond
1502 PCC_REGISTER2, // outCond
1506 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1507 {PC_OPCODE, NULL, NULL, 0, NULL,
1512 NULL, // from branch
1519 0,0, // dest, bit instruction
1520 0,0, // branch, skip
1521 1, // literal operand
1522 0, // RAM access bit
1523 0, // fast call/return mode select bit
1524 0, // second memory operand
1525 0, // second literal operand
1527 (PCC_NONE | PCC_LITERAL), // inCond
1528 PCC_REGISTER, // outCond - BSR
1532 pCodeInstruction pic16_pciMOVLW = {
1533 {PC_OPCODE, NULL, NULL, 0, NULL,
1538 NULL, // from branch
1545 0,0, // dest, bit instruction
1546 0,0, // branch, skip
1547 1, // literal operand
1548 0, // RAM access bit
1549 0, // fast call/return mode select bit
1550 0, // second memory operand
1551 0, // second literal operand
1553 (PCC_NONE | PCC_LITERAL), // inCond
1558 pCodeInstruction pic16_pciMOVWF = {
1559 {PC_OPCODE, NULL, NULL, 0, NULL,
1565 NULL, // from branch
1572 0,0, // dest, bit instruction
1573 0,0, // branch, skip
1574 0, // literal operand
1575 1, // RAM access bit
1576 0, // fast call/return mode select bit
1577 0, // second memory operand
1578 0, // second literal operand
1580 PCC_REGISTER, // inCond
1585 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1586 {PC_OPCODE, NULL, NULL, 0, NULL,
1591 NULL, // from branch
1598 0,0, // dest, bit instruction
1599 0,0, // branch, skip
1600 1, // literal operand
1601 0, // RAM access bit
1602 0, // fast call/return mode select bit
1603 0, // second memory operand
1604 0, // second literal operand
1606 (PCC_W | PCC_LITERAL), // inCond
1607 PCC_REGISTER, // outCond - PROD
1611 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1612 {PC_OPCODE, NULL, NULL, 0, NULL,
1617 NULL, // from branch
1624 0,0, // dest, bit instruction
1625 0,0, // branch, skip
1626 0, // literal operand
1627 1, // RAM access bit
1628 0, // fast call/return mode select bit
1629 0, // second memory operand
1630 0, // second literal operand
1632 (PCC_W | PCC_REGISTER), // inCond
1633 PCC_REGISTER, // outCond - PROD
1637 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1638 {PC_OPCODE, NULL, NULL, 0, NULL,
1643 NULL, // from branch
1650 0,0, // dest, bit instruction
1651 0,0, // branch, skip
1652 0, // literal operand
1653 1, // RAM access bit
1654 0, // fast call/return mode select bit
1655 0, // second memory operand
1656 0, // second literal operand
1658 PCC_REGISTER, // inCond
1659 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1663 pCodeInstruction pic16_pciNOP = {
1664 {PC_OPCODE, NULL, NULL, 0, NULL,
1669 NULL, // from branch
1676 0,0, // dest, bit instruction
1677 0,0, // branch, skip
1678 0, // literal operand
1679 0, // RAM access bit
1680 0, // fast call/return mode select bit
1681 0, // second memory operand
1682 0, // second literal operand
1685 PCC_NONE, // outCond
1689 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1690 {PC_OPCODE, NULL, NULL, 0, NULL,
1695 NULL, // from branch
1702 0,0, // dest, bit instruction
1703 0,0, // branch, skip
1704 0, // literal operand
1705 0, // RAM access bit
1706 0, // fast call/return mode select bit
1707 0, // second memory operand
1708 0, // second literal operand
1711 PCC_NONE , // outCond
1715 pCodeInstruction pic16_pciPUSH = {
1716 {PC_OPCODE, NULL, NULL, 0, NULL,
1721 NULL, // from branch
1728 0,0, // dest, bit instruction
1729 0,0, // branch, skip
1730 0, // literal operand
1731 0, // RAM access bit
1732 0, // fast call/return mode select bit
1733 0, // second memory operand
1734 0, // second literal operand
1737 PCC_NONE , // outCond
1741 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1742 {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 0, // RAM access bit
1758 0, // fast call/return mode select bit
1759 0, // second memory operand
1760 0, // second literal operand
1762 PCC_REL_ADDR, // inCond
1763 PCC_NONE , // outCond
1767 pCodeInstruction pic16_pciRETFIE = {
1768 {PC_OPCODE, NULL, NULL, 0, NULL,
1774 NULL, // from branch
1781 0,0, // dest, bit instruction
1782 1,0, // branch, skip
1783 0, // literal operand
1784 0, // RAM access bit
1785 1, // fast call/return mode select bit
1786 0, // second memory operand
1787 0, // second literal operand
1790 PCC_NONE, // outCond (not true... affects the GIE bit too)
1794 pCodeInstruction pic16_pciRETLW = {
1795 {PC_OPCODE, NULL, NULL, 0, NULL,
1801 NULL, // from branch
1808 0,0, // dest, bit instruction
1809 1,0, // branch, skip
1810 1, // 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
1816 PCC_LITERAL, // inCond
1821 pCodeInstruction pic16_pciRETURN = {
1822 {PC_OPCODE, NULL, NULL, 0, NULL,
1828 NULL, // from branch
1835 0,0, // dest, bit instruction
1836 1,0, // branch, skip
1837 0, // literal operand
1838 0, // RAM access bit
1839 1, // fast call/return mode select bit
1840 0, // second memory operand
1841 0, // second literal operand
1844 PCC_NONE, // outCond
1847 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1848 {PC_OPCODE, NULL, NULL, 0, NULL,
1854 NULL, // from branch
1861 1,0, // dest, bit instruction
1862 0,0, // branch, skip
1863 0, // literal operand
1864 1, // RAM access bit
1865 0, // fast call/return mode select bit
1866 0, // second memory operand
1867 0, // second literal operand
1869 (PCC_C | PCC_REGISTER), // inCond
1870 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1874 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1875 {PC_OPCODE, NULL, NULL, 0, NULL,
1881 NULL, // from branch
1888 0,0, // dest, bit instruction
1889 0,0, // branch, skip
1890 0, // literal operand
1891 1, // RAM access bit
1892 0, // fast call/return mode select bit
1893 0, // second memory operand
1894 0, // second literal operand
1896 (PCC_C | PCC_REGISTER), // inCond
1897 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1901 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1902 {PC_OPCODE, NULL, NULL, 0, NULL,
1908 NULL, // from branch
1915 1,0, // dest, bit instruction
1916 0,0, // branch, skip
1917 0, // literal operand
1918 1, // RAM access bit
1919 0, // fast call/return mode select bit
1920 0, // second memory operand
1921 0, // second literal operand
1923 PCC_REGISTER, // inCond
1924 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1927 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1928 {PC_OPCODE, NULL, NULL, 0, NULL,
1934 NULL, // from branch
1941 0,0, // dest, bit instruction
1942 0,0, // branch, skip
1943 0, // literal operand
1944 1, // RAM access bit
1945 0, // fast call/return mode select bit
1946 0, // second memory operand
1947 0, // second literal operand
1949 PCC_REGISTER, // inCond
1950 (PCC_W | PCC_Z | PCC_N), // outCond
1953 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1954 {PC_OPCODE, NULL, NULL, 0, NULL,
1960 NULL, // from branch
1967 1,0, // dest, bit instruction
1968 0,0, // branch, skip
1969 0, // literal operand
1970 1, // RAM access bit
1971 0, // fast call/return mode select bit
1972 0, // second memory operand
1973 0, // second literal operand
1975 (PCC_C | PCC_REGISTER), // inCond
1976 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1979 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1980 {PC_OPCODE, NULL, NULL, 0, NULL,
1986 NULL, // from branch
1993 0,0, // dest, bit instruction
1994 0,0, // branch, skip
1995 0, // literal operand
1996 1, // RAM access bit
1997 0, // fast call/return mode select bit
1998 0, // second memory operand
1999 0, // second literal operand
2001 (PCC_C | PCC_REGISTER), // inCond
2002 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2005 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2006 {PC_OPCODE, NULL, NULL, 0, NULL,
2012 NULL, // from branch
2019 1,0, // dest, bit instruction
2020 0,0, // branch, skip
2021 0, // literal operand
2022 1, // RAM access bit
2023 0, // fast call/return mode select bit
2024 0, // second memory operand
2025 0, // second literal operand
2027 PCC_REGISTER, // inCond
2028 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2032 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2033 {PC_OPCODE, NULL, NULL, 0, NULL,
2039 NULL, // from branch
2046 0,0, // dest, bit instruction
2047 0,0, // branch, skip
2048 0, // literal operand
2049 1, // RAM access bit
2050 0, // fast call/return mode select bit
2051 0, // second memory operand
2052 0, // second literal operand
2054 PCC_REGISTER, // inCond
2055 (PCC_W | PCC_Z | PCC_N), // outCond
2059 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2060 {PC_OPCODE, NULL, NULL, 0, NULL,
2066 NULL, // from branch
2073 0,0, // dest, bit instruction
2074 0,0, // branch, skip
2075 0, // literal operand
2076 1, // RAM access bit
2077 0, // fast call/return mode select bit
2078 0, // second memory operand
2079 0, // second literal operand
2081 PCC_REGISTER, // inCond
2082 PCC_REGISTER , // outCond
2086 pCodeInstruction pic16_pciSUBLW = {
2087 {PC_OPCODE, NULL, NULL, 0, NULL,
2093 NULL, // from branch
2100 0,0, // dest, bit instruction
2101 0,0, // branch, skip
2102 1, // literal operand
2103 0, // RAM access bit
2104 0, // fast call/return mode select bit
2105 0, // second memory operand
2106 0, // second literal operand
2108 (PCC_W | PCC_LITERAL), // inCond
2109 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2113 pCodeInstruction pic16_pciSUBFWB = {
2114 {PC_OPCODE, NULL, NULL, 0, NULL,
2120 NULL, // from branch
2127 1,0, // dest, bit instruction
2128 0,0, // branch, skip
2129 0, // literal operand
2130 1, // RAM access bit
2131 0, // fast call/return mode select bit
2132 0, // second memory operand
2133 0, // second literal operand
2135 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2136 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2140 pCodeInstruction pic16_pciSUBWF = {
2141 {PC_OPCODE, NULL, NULL, 0, NULL,
2147 NULL, // from branch
2154 1,0, // dest, bit instruction
2155 0,0, // branch, skip
2156 0, // literal operand
2157 1, // RAM access bit
2158 0, // fast call/return mode select bit
2159 0, // second memory operand
2160 0, // second literal operand
2162 (PCC_W | PCC_REGISTER), // inCond
2163 (PCC_REGISTER | PCC_Z), // outCond
2167 pCodeInstruction pic16_pciSUBFW = {
2168 {PC_OPCODE, NULL, NULL, 0, NULL,
2174 NULL, // from branch
2181 0,0, // dest, bit instruction
2182 0,0, // branch, skip
2183 0, // literal operand
2184 1, // RAM access bit
2185 0, // fast call/return mode select bit
2186 0, // second memory operand
2187 0, // second literal operand
2189 (PCC_W | PCC_REGISTER), // inCond
2190 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2194 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2195 {PC_OPCODE, NULL, NULL, 0, NULL,
2201 NULL, // from branch
2208 1,0, // dest, bit instruction
2209 0,0, // branch, skip
2210 0, // literal operand
2211 1, // RAM access bit
2212 0, // fast call/return mode select bit
2213 0, // second memory operand
2214 0, // second literal operand
2216 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2217 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2221 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2222 {PC_OPCODE, NULL, NULL, 0, NULL,
2228 NULL, // from branch
2235 0,0, // dest, bit instruction
2236 0,0, // branch, skip
2237 0, // literal operand
2238 1, // RAM access bit
2239 0, // fast call/return mode select bit
2240 0, // second memory operand
2241 0, // second literal operand
2243 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2244 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2248 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2249 {PC_OPCODE, NULL, NULL, 0, NULL,
2255 NULL, // from branch
2262 1,0, // dest, bit instruction
2263 0,0, // branch, skip
2264 0, // literal operand
2265 1, // RAM access bit
2266 0, // fast call/return mode select bit
2267 0, // second memory operand
2268 0, // second literal operand
2270 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2271 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2275 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2276 {PC_OPCODE, NULL, NULL, 0, NULL,
2282 NULL, // from branch
2289 0,0, // dest, bit instruction
2290 0,0, // branch, skip
2291 0, // literal operand
2292 1, // RAM access bit
2293 0, // fast call/return mode select bit
2294 0, // second memory operand
2295 0, // second literal operand
2297 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2298 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2302 pCodeInstruction pic16_pciSWAPF = {
2303 {PC_OPCODE, NULL, NULL, 0, NULL,
2309 NULL, // from branch
2316 1,0, // dest, bit instruction
2317 0,0, // branch, skip
2318 0, // literal operand
2319 1, // RAM access bit
2320 0, // fast call/return mode select bit
2321 0, // second memory operand
2322 0, // second literal operand
2324 (PCC_REGISTER), // inCond
2325 (PCC_REGISTER), // outCond
2329 pCodeInstruction pic16_pciSWAPFW = {
2330 {PC_OPCODE, NULL, NULL, 0, NULL,
2336 NULL, // from branch
2343 0,0, // dest, bit instruction
2344 0,0, // branch, skip
2345 0, // literal operand
2346 1, // RAM access bit
2347 0, // fast call/return mode select bit
2348 0, // second memory operand
2349 0, // second literal operand
2351 (PCC_REGISTER), // inCond
2356 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2357 {PC_OPCODE, NULL, NULL, 0, NULL,
2363 NULL, // from branch
2370 0,0, // dest, bit instruction
2371 1,1, // branch, skip
2372 0, // literal operand
2373 1, // RAM access bit
2374 0, // fast call/return mode select bit
2375 0, // second memory operand
2376 0, // second literal operand
2378 PCC_REGISTER, // inCond
2379 PCC_NONE, // outCond
2383 pCodeInstruction pic16_pciXORWF = {
2384 {PC_OPCODE, NULL, NULL, 0, NULL,
2390 NULL, // from branch
2397 1,0, // dest, bit instruction
2398 0,0, // branch, skip
2399 0, // literal operand
2400 1, // RAM access bit
2401 0, // fast call/return mode select bit
2402 0, // second memory operand
2403 0, // second literal operand
2405 (PCC_W | PCC_REGISTER), // inCond
2406 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2410 pCodeInstruction pic16_pciXORFW = {
2411 {PC_OPCODE, NULL, NULL, 0, NULL,
2417 NULL, // from branch
2424 0,0, // dest, bit instruction
2425 0,0, // branch, skip
2426 0, // literal operand
2427 1, // RAM access bit
2428 0, // fast call/return mode select bit
2429 0, // second memory operand
2430 0, // second literal operand
2432 (PCC_W | PCC_REGISTER), // inCond
2433 (PCC_W | PCC_Z | PCC_N), // outCond
2437 pCodeInstruction pic16_pciXORLW = {
2438 {PC_OPCODE, NULL, NULL, 0, NULL,
2444 NULL, // from branch
2451 0,0, // dest, bit instruction
2452 0,0, // branch, skip
2453 1, // literal operand
2454 1, // RAM access bit
2455 0, // fast call/return mode select bit
2456 0, // second memory operand
2457 0, // second literal operand
2459 (PCC_W | PCC_LITERAL), // inCond
2460 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2465 #define MAX_PIC16MNEMONICS 100
2466 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2468 //#define USE_VSNPRINTF
2471 #ifdef USE_VSNPRINTF
2472 // Alas, vsnprintf is not ANSI standard, and does not exist
2473 // on Solaris (and probably other non-Gnu flavored Unixes).
2475 /*-----------------------------------------------------------------*/
2476 /* SAFE_snprintf - like snprintf except the string pointer is */
2477 /* after the string has been printed to. This is */
2478 /* useful for printing to string as though if it */
2479 /* were a stream. */
2480 /*-----------------------------------------------------------------*/
2481 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2489 va_start(val, format);
2491 vsnprintf(*str, *size, format, val);
2497 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2498 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2507 // This version is *not* safe, despite the name.
2509 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2513 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2518 va_start(val, format);
2520 vsprintf(buffer, format, val);
2523 len = strlen(buffer);
2525 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2526 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2529 strcpy(*str, buffer);
2535 #endif // USE_VSNPRINTF
2538 extern void pic16_initStack(int base_address, int size);
2539 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2540 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2541 extern void pic16_init_pic(char *);
2543 void pic16_pCodeInitRegisters(void)
2545 static int initialized=0;
2552 pic16_initStack(0xfff, 8);
2553 pic16_init_pic(port->processor);
2555 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2556 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2557 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2558 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2559 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2561 pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80); // deprecated !
2563 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2564 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2565 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2566 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2567 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2568 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2570 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2571 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2572 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2573 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2574 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2576 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2577 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2578 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2579 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2580 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2582 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2583 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2584 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2585 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2586 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2588 pic16_pc_status.rIdx = IDX_STATUS;
2589 pic16_pc_intcon.rIdx = IDX_INTCON;
2590 pic16_pc_pcl.rIdx = IDX_PCL;
2591 pic16_pc_pclath.rIdx = IDX_PCLATH;
2592 pic16_pc_wreg.rIdx = IDX_WREG;
2593 pic16_pc_fsr0.rIdx = IDX_FSR0;
2594 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2595 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2596 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2597 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2598 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2599 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2600 pic16_pc_indf0.rIdx = IDX_INDF0;
2601 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2602 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2603 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2604 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2605 pic16_pc_indf1.rIdx = IDX_INDF1;
2606 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2607 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2608 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2609 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2610 pic16_pc_indf2.rIdx = IDX_INDF2;
2611 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2612 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2613 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2614 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2616 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2617 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
2618 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2620 pic16_pc_kzero.rIdx = IDX_KZ;
2621 pic16_pc_wsave.rIdx = IDX_WSAVE;
2622 pic16_pc_ssave.rIdx = IDX_SSAVE;
2624 /* probably should put this in a separate initialization routine */
2625 pb_dead_pcodes = newpBlock();
2630 /*-----------------------------------------------------------------*/
2631 /* mnem2key - convert a pic mnemonic into a hash key */
2632 /* (BTW - this spreads the mnemonics quite well) */
2634 /*-----------------------------------------------------------------*/
2636 int mnem2key(char const *mnem)
2645 key += toupper(*mnem++) +1;
2649 return (key & 0x1f);
2654 void pic16initMnemonics(void)
2659 pCodeInstruction *pci;
2661 if(mnemonics_initialized)
2664 // NULL out the array before making the assignments
2665 // since we check the array contents below this initialization.
2667 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2668 pic16Mnemonics[i] = NULL;
2671 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2672 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2673 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2674 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2675 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2676 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2677 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2678 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2679 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2680 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2681 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2682 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2683 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2684 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2685 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2686 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2687 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2688 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2689 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2690 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2691 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2692 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2693 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2694 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2695 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2696 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2697 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2698 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2699 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2700 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2701 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2702 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2703 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2704 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2705 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2706 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2707 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2708 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2709 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2710 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2711 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2712 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2713 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2714 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2715 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2716 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2717 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2718 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2719 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2720 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2721 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2722 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2723 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2724 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2725 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2726 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2727 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2728 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2729 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2730 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2731 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2732 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2733 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2734 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2735 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF; // was [POC_RLCF] !!!
2736 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2737 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2738 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2739 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2740 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2741 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2742 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2743 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2744 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2745 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2746 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2747 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2748 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2749 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2750 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
2751 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
2752 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
2753 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
2754 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
2756 for(i=0; i<MAX_PIC16MNEMONICS; i++)
2757 if(pic16Mnemonics[i])
2758 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
2759 pci = hTabFirstItem(pic16MnemonicsHash, &key);
2762 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
2763 pci = hTabNextItem(pic16MnemonicsHash, &key);
2766 mnemonics_initialized = 1;
2769 int pic16_getpCodePeepCommand(char *cmd);
2771 int pic16_getpCode(char *mnem,unsigned dest)
2774 pCodeInstruction *pci;
2775 int key = mnem2key(mnem);
2777 if(!mnemonics_initialized)
2778 pic16initMnemonics();
2780 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
2784 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
2785 if((pci->num_ops <= 1)
2786 || (pci->isModReg == dest)
2788 || (pci->num_ops <= 2 && pci->isAccess)
2789 || (pci->num_ops <= 2 && pci->isFastCall)
2790 || (pci->num_ops <= 2 && pci->is2MemOp)
2791 || (pci->num_ops <= 2 && pci->is2LitOp) )
2795 pci = hTabNextItemWK (pic16MnemonicsHash);
2802 /*-----------------------------------------------------------------*
2803 * pic16initpCodePeepCommands
2805 *-----------------------------------------------------------------*/
2806 void pic16initpCodePeepCommands(void)
2814 hTabAddItem(&pic16pCodePeepCommandsHash,
2815 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
2817 } while (peepCommands[i].cmd);
2819 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
2822 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
2823 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
2828 /*-----------------------------------------------------------------
2831 *-----------------------------------------------------------------*/
2833 int pic16_getpCodePeepCommand(char *cmd)
2837 int key = mnem2key(cmd);
2840 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
2843 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2844 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2848 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
2855 static char getpBlock_dbName(pBlock *pb)
2861 return pb->cmemmap->dbName;
2865 void pic16_pBlockConvert2ISR(pBlock *pb)
2876 void pic16_pBlockConvert2Absolute(pBlock *pb)
2879 if(pb->cmemmap)pb->cmemmap = NULL;
2884 /*-----------------------------------------------------------------*/
2885 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
2886 /* instances to the front of the doubly linked */
2887 /* list of pBlocks */
2888 /*-----------------------------------------------------------------*/
2890 void pic16_movepBlock2Head(char dbName)
2895 /* this can happen in sources without code,
2896 * only variable definitions */
2897 if(!the_pFile)return;
2899 pb = the_pFile->pbHead;
2903 if(getpBlock_dbName(pb) == dbName) {
2904 pBlock *pbn = pb->next;
2905 pb->next = the_pFile->pbHead;
2906 the_pFile->pbHead->prev = pb;
2907 the_pFile->pbHead = pb;
2910 pb->prev->next = pbn;
2912 // If the pBlock that we just moved was the last
2913 // one in the link of all of the pBlocks, then we
2914 // need to point the tail to the block just before
2915 // the one we moved.
2916 // Note: if pb->next is NULL, then pb must have
2917 // been the last pBlock in the chain.
2920 pbn->prev = pb->prev;
2922 the_pFile->pbTail = pb->prev;
2933 void pic16_copypCode(FILE *of, char dbName)
2937 if(!of || !the_pFile)
2940 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2941 if(getpBlock_dbName(pb) == dbName) {
2942 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
2944 pic16_printpBlock(of,pb);
2949 void pic16_pcode_test(void)
2952 DFPRINTF((stderr,"pcode is alive!\n"));
2962 /* create the file name */
2963 strcpy(buffer,dstFileName);
2964 strcat(buffer,".p");
2966 if( !(pFile = fopen(buffer, "w" ))) {
2967 werror(E_FILE_OPEN_ERR,buffer);
2971 fprintf(pFile,"pcode dump\n\n");
2973 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2974 fprintf(pFile,"\n\tNew pBlock\n\n");
2976 fprintf(pFile,"%s",pb->cmemmap->sname);
2978 fprintf(pFile,"internal pblock");
2980 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2981 pic16_printpBlock(pFile,pb);
2985 /*-----------------------------------------------------------------*/
2986 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
2987 /* ister, RegCond will return the bit being referenced. */
2989 /* fixme - why not just OR in the pcop bit field */
2990 /*-----------------------------------------------------------------*/
2992 static int RegCond(pCodeOp *pcop)
2998 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
2999 switch(PCORB(pcop)->bit) {
3013 /*-----------------------------------------------------------------*/
3014 /* pic16_newpCode - create and return a newly initialized pCode */
3016 /* fixme - rename this */
3018 /* The purpose of this routine is to create a new Instruction */
3019 /* pCode. This is called by gen.c while the assembly code is being */
3023 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3024 /* (note that the op is analogous to but not the */
3025 /* same thing as the opcode of the instruction.) */
3026 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3029 /* a pointer to the new malloc'd pCode is returned. */
3033 /*-----------------------------------------------------------------*/
3034 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3036 pCodeInstruction *pci ;
3038 if(!mnemonics_initialized)
3039 pic16initMnemonics();
3041 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3043 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3044 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3047 if(pci->inCond & PCC_EXAMINE_PCOP)
3048 pci->inCond |= RegCond(pcop);
3050 if(pci->outCond & PCC_EXAMINE_PCOP)
3051 pci->outCond |= RegCond(pcop);
3053 pci->pc.prev = pci->pc.next = NULL;
3054 return (pCode *)pci;
3057 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3063 /*-----------------------------------------------------------------*/
3064 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3066 /* Wild pcodes are used during the peep hole optimizer to serve */
3067 /* as place holders for any instruction. When a snippet of code is */
3068 /* compared to a peep hole rule, the wild card opcode will match */
3069 /* any instruction. However, the optional operand and label are */
3070 /* additional qualifiers that must also be matched before the */
3071 /* line (of assembly code) is declared matched. Note that the */
3072 /* operand may be wild too. */
3074 /* Note, a wild instruction is specified just like a wild var: */
3075 /* %4 ; A wild instruction, */
3076 /* See the peeph.def file for additional examples */
3078 /*-----------------------------------------------------------------*/
3080 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3085 pcw = Safe_calloc(1,sizeof(pCodeWild));
3087 pcw->pci.pc.type = PC_WILD;
3088 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3089 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3090 pcw->pci.pc.pb = NULL;
3092 // pcw->pci.pc.analyze = genericAnalyze;
3093 pcw->pci.pc.destruct = genericDestruct;
3094 pcw->pci.pc.print = genericPrint;
3096 pcw->id = pCodeID; // this is the 'n' in %n
3097 pcw->operand = optional_operand;
3098 pcw->label = optional_label;
3100 pcw->mustBeBitSkipInst = 0;
3101 pcw->mustNotBeBitSkipInst = 0;
3102 pcw->invertBitSkipInst = 0;
3104 return ( (pCode *)pcw);
3108 /*-----------------------------------------------------------------*/
3109 /* newPcodeInlineP - create a new pCode from a char string */
3110 /*-----------------------------------------------------------------*/
3113 pCode *pic16_newpCodeInlineP(char *cP)
3118 pcc = Safe_calloc(1,sizeof(pCodeComment));
3120 pcc->pc.type = PC_INLINE;
3121 pcc->pc.prev = pcc->pc.next = NULL;
3122 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3125 // pcc->pc.analyze = genericAnalyze;
3126 pcc->pc.destruct = genericDestruct;
3127 pcc->pc.print = genericPrint;
3130 pcc->comment = Safe_strdup(cP);
3132 pcc->comment = NULL;
3134 return ( (pCode *)pcc);
3138 /*-----------------------------------------------------------------*/
3139 /* newPcodeCharP - create a new pCode from a char string */
3140 /*-----------------------------------------------------------------*/
3142 pCode *pic16_newpCodeCharP(char *cP)
3147 pcc = Safe_calloc(1,sizeof(pCodeComment));
3149 pcc->pc.type = PC_COMMENT;
3150 pcc->pc.prev = pcc->pc.next = NULL;
3151 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3154 // pcc->pc.analyze = genericAnalyze;
3155 pcc->pc.destruct = genericDestruct;
3156 pcc->pc.print = genericPrint;
3159 pcc->comment = Safe_strdup(cP);
3161 pcc->comment = NULL;
3163 return ( (pCode *)pcc);
3167 /*-----------------------------------------------------------------*/
3168 /* pic16_newpCodeFunction - */
3169 /*-----------------------------------------------------------------*/
3172 pCode *pic16_newpCodeFunction(char *mod,char *f)
3176 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3178 pcf->pc.type = PC_FUNCTION;
3179 pcf->pc.prev = pcf->pc.next = NULL;
3180 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3183 // pcf->pc.analyze = genericAnalyze;
3184 pcf->pc.destruct = genericDestruct;
3185 pcf->pc.print = pCodePrintFunction;
3190 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3191 strcpy(pcf->modname,mod);
3193 pcf->modname = NULL;
3196 pcf->fname = Safe_calloc(1,strlen(f)+1);
3197 strcpy(pcf->fname,f);
3201 return ( (pCode *)pcf);
3205 /*-----------------------------------------------------------------*/
3206 /* pic16_newpCodeFlow */
3207 /*-----------------------------------------------------------------*/
3208 static void destructpCodeFlow(pCode *pc)
3210 if(!pc || !isPCFL(pc))
3217 pic16_unlinkpCode(pc);
3219 deleteSet(&PCFL(pc)->registers);
3220 deleteSet(&PCFL(pc)->from);
3221 deleteSet(&PCFL(pc)->to);
3226 pCode *pic16_newpCodeFlow(void )
3230 //_ALLOC(pcflow,sizeof(pCodeFlow));
3231 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3233 pcflow->pc.type = PC_FLOW;
3234 pcflow->pc.prev = pcflow->pc.next = NULL;
3235 pcflow->pc.pb = NULL;
3237 // pcflow->pc.analyze = genericAnalyze;
3238 pcflow->pc.destruct = destructpCodeFlow;
3239 pcflow->pc.print = genericPrint;
3241 pcflow->pc.seq = GpcFlowSeq++;
3243 pcflow->from = pcflow->to = NULL;
3245 pcflow->inCond = PCC_NONE;
3246 pcflow->outCond = PCC_NONE;
3248 pcflow->firstBank = -1;
3249 pcflow->lastBank = -1;
3251 pcflow->FromConflicts = 0;
3252 pcflow->ToConflicts = 0;
3256 pcflow->registers = newSet();
3258 return ( (pCode *)pcflow);
3262 /*-----------------------------------------------------------------*/
3263 /*-----------------------------------------------------------------*/
3264 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3266 pCodeFlowLink *pcflowLink;
3268 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3270 pcflowLink->pcflow = pcflow;
3271 pcflowLink->bank_conflict = 0;
3276 /*-----------------------------------------------------------------*/
3277 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3278 /*-----------------------------------------------------------------*/
3280 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3285 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3287 pccs->pc.type = PC_CSOURCE;
3288 pccs->pc.prev = pccs->pc.next = NULL;
3291 pccs->pc.destruct = genericDestruct;
3292 pccs->pc.print = genericPrint;
3294 pccs->line_number = ln;
3296 pccs->line = Safe_strdup(l);
3301 pccs->file_name = Safe_strdup(f);
3303 pccs->file_name = NULL;
3305 return ( (pCode *)pccs);
3310 /*******************************************************************/
3311 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3312 /* added by VR 6-Jun-2003 */
3313 /*******************************************************************/
3315 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3322 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3323 pcad->pc.type = PC_ASMDIR;
3324 pcad->pc.prev = pcad->pc.next = NULL;
3327 pcad->pc.destruct = genericDestruct;
3328 pcad->pc.print = genericPrint;
3330 if(asdir && *asdir) {
3332 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3334 pcad->directive = Safe_strdup( asdir );
3337 va_start(ap, argfmt);
3339 memset(buffer, 0, sizeof(buffer));
3340 if(argfmt && *argfmt)
3341 vsprintf(buffer, argfmt, ap);
3345 while(isspace(*lbp))lbp++;
3348 pcad->arg = Safe_strdup( lbp );
3350 return ((pCode *)pcad);
3353 /*-----------------------------------------------------------------*/
3354 /* pCodeLabelDestruct - free memory used by a label. */
3355 /*-----------------------------------------------------------------*/
3356 static void pCodeLabelDestruct(pCode *pc)
3362 if((pc->type == PC_LABEL) && PCL(pc)->label)
3363 free(PCL(pc)->label);
3369 pCode *pic16_newpCodeLabel(char *name, int key)
3375 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3377 pcl->pc.type = PC_LABEL;
3378 pcl->pc.prev = pcl->pc.next = NULL;
3379 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3382 // pcl->pc.analyze = genericAnalyze;
3383 pcl->pc.destruct = pCodeLabelDestruct;
3384 pcl->pc.print = pCodePrintLabel;
3390 sprintf(s,"_%05d_DS_",key);
3395 pcl->label = Safe_strdup(s);
3397 return ( (pCode *)pcl);
3402 /*-----------------------------------------------------------------*/
3403 /* newpBlock - create and return a pointer to a new pBlock */
3404 /*-----------------------------------------------------------------*/
3405 static pBlock *newpBlock(void)
3410 PpB = Safe_calloc(1,sizeof(pBlock) );
3411 PpB->next = PpB->prev = NULL;
3413 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3414 PpB->tregisters = NULL;
3416 PpB->FlowTree = NULL;
3422 /*-----------------------------------------------------------------*/
3423 /* pic16_newpCodeChain - create a new chain of pCodes */
3424 /*-----------------------------------------------------------------*
3426 * This function will create a new pBlock and the pointer to the
3427 * pCode that is passed in will be the first pCode in the block.
3428 *-----------------------------------------------------------------*/
3431 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3434 pBlock *pB = newpBlock();
3436 pB->pcHead = pB->pcTail = pc;
3443 /*-----------------------------------------------------------------*/
3444 /* pic16_newpCodeOpLabel - Create a new label given the key */
3445 /* Note, a negative key means that the label is part of wild card */
3446 /* (and hence a wild card label) used in the pCodePeep */
3447 /* optimizations). */
3448 /*-----------------------------------------------------------------*/
3450 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3453 static int label_key=-1;
3457 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3458 pcop->type = PO_LABEL;
3463 sprintf(s=buffer,"_%05d_DS_",key);
3465 s = name, key = label_key--;
3468 pcop->name = Safe_strdup(s);
3470 ((pCodeOpLabel *)pcop)->key = key;
3472 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3476 /*-----------------------------------------------------------------*/
3477 /*-----------------------------------------------------------------*/
3478 pCodeOp *pic16_newpCodeOpLit(int lit)
3484 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3485 pcop->type = PO_LITERAL;
3489 sprintf(s,"0x%02x",lit);
3491 pcop->name = Safe_strdup(s);
3494 ((pCodeOpLit *)pcop)->lit = lit;
3499 /*-----------------------------------------------------------------*/
3500 /*-----------------------------------------------------------------*/
3501 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3503 char *s = buffer, tbuf[256], *tb=tbuf;
3507 tb = pic16_get_op(arg2, NULL, 0);
3508 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3509 pcop->type = PO_LITERAL;
3513 sprintf(s,"0x%02x, %s",lit, tb);
3515 pcop->name = Safe_strdup(s);
3518 ((pCodeOpLit2 *)pcop)->lit = lit;
3519 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3524 /*-----------------------------------------------------------------*/
3525 /*-----------------------------------------------------------------*/
3526 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3530 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3531 pcop->type = PO_IMMEDIATE;
3533 regs *r = pic16_dirregWithName(name);
3534 pcop->name = Safe_strdup(name);
3538 fprintf(stderr, "%s:%d %s reg %s exists\n",__FILE__, __LINE__, __FUNCTION__, name);
3539 PCOI(pcop)->rIdx = r->rIdx;
3541 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n",
3542 // __FILE__, __LINE__, __FUNCTION__, name);
3543 PCOI(pcop)->rIdx = -1;
3545 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3550 PCOI(pcop)->index = index;
3551 PCOI(pcop)->offset = offset;
3552 PCOI(pcop)->_const = code_space;
3557 /*-----------------------------------------------------------------*/
3558 /*-----------------------------------------------------------------*/
3559 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3565 if(!pcwb || !subtype) {
3566 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3570 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3571 pcop->type = PO_WILD;
3572 sprintf(s,"%%%d",id);
3573 pcop->name = Safe_strdup(s);
3575 PCOW(pcop)->id = id;
3576 PCOW(pcop)->pcwb = pcwb;
3577 PCOW(pcop)->subtype = subtype;
3578 PCOW(pcop)->matched = NULL;
3583 /*-----------------------------------------------------------------*/
3584 /*-----------------------------------------------------------------*/
3585 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3589 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3590 pcop->type = PO_GPR_BIT;
3592 pcop->name = Safe_strdup(s);
3596 PCORB(pcop)->bit = bit;
3597 PCORB(pcop)->inBitSpace = inBitSpace;
3599 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3600 PCOR(pcop)->r = NULL;
3601 PCOR(pcop)->rIdx = 0;
3605 /*-----------------------------------------------------------------*
3606 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3608 * If rIdx >=0 then a specific register from the set of registers
3609 * will be selected. If rIdx <0, then a new register will be searched
3611 *-----------------------------------------------------------------*/
3613 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3617 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3622 PCOR(pcop)->rIdx = rIdx;
3623 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3625 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3628 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3630 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
3631 __FUNCTION__, __LINE__);
3636 pcop->type = PCOR(pcop)->r->pc_type;
3641 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3646 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3647 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1);
3648 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3649 pcop->type = PCOR(pcop)->r->pc_type;
3650 pcop->name = PCOR(pcop)->r->name;
3652 if(pic16_pcode_verbose) {
3653 fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3654 __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
3660 /*-----------------------------------------------------------------*/
3661 /*-----------------------------------------------------------------*/
3663 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3670 pcop = pic16_newpCodeOpBit(name, -1,0);
3674 pcop = pic16_newpCodeOpLit(-1);
3678 pcop = pic16_newpCodeOpLabel(NULL,-1);
3681 pcop = pic16_newpCodeOpReg(-1);
3684 case PO_GPR_REGISTER:
3686 pcop = pic16_newpCodeOpRegFromStr(name);
3688 pcop = pic16_newpCodeOpReg(-1);
3692 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3695 pcop->name = Safe_strdup(name);
3703 /*-----------------------------------------------------------------*/
3704 /*-----------------------------------------------------------------*/
3705 void pic16_pCodeConstString(char *name, char *value)
3709 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
3714 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3716 pic16_addpBlock(pb);
3718 sprintf(buffer,"; %s = %s",name,value);
3720 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3721 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3724 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3730 /*-----------------------------------------------------------------*/
3731 /*-----------------------------------------------------------------*/
3733 static void pCodeReadCodeTable(void)
3737 fprintf(stderr, " %s\n",__FUNCTION__);
3739 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3741 pic16_addpBlock(pb);
3743 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3744 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3745 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3746 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3748 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3749 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3750 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3751 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3756 /*-----------------------------------------------------------------*/
3757 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3758 /*-----------------------------------------------------------------*/
3759 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3766 /* If this is the first pcode to be added to a block that
3767 * was initialized with a NULL pcode, then go ahead and
3768 * make this pcode the head and tail */
3769 pb->pcHead = pb->pcTail = pc;
3772 pb->pcTail->next = pc;
3774 pc->prev = pb->pcTail;
3781 /*-----------------------------------------------------------------*/
3782 /* pic16_addpBlock - place a pBlock into the pFile */
3783 /*-----------------------------------------------------------------*/
3784 void pic16_addpBlock(pBlock *pb)
3786 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3789 /* First time called, we'll pass through here. */
3790 //_ALLOC(the_pFile,sizeof(pFile));
3791 the_pFile = Safe_calloc(1,sizeof(pFile));
3792 the_pFile->pbHead = the_pFile->pbTail = pb;
3793 the_pFile->functions = NULL;
3797 the_pFile->pbTail->next = pb;
3798 pb->prev = the_pFile->pbTail;
3800 the_pFile->pbTail = pb;
3803 /*-----------------------------------------------------------------*/
3804 /* removepBlock - remove a pBlock from the pFile */
3805 /*-----------------------------------------------------------------*/
3806 static void removepBlock(pBlock *pb)
3814 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3816 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3819 if(pbs == the_pFile->pbHead)
3820 the_pFile->pbHead = pbs->next;
3822 if (pbs == the_pFile->pbTail)
3823 the_pFile->pbTail = pbs->prev;
3826 pbs->next->prev = pbs->prev;
3829 pbs->prev->next = pbs->next;
3836 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3840 /*-----------------------------------------------------------------*/
3841 /* printpCode - write the contents of a pCode to a file */
3842 /*-----------------------------------------------------------------*/
3843 static void printpCode(FILE *of, pCode *pc)
3854 fprintf(of,"warning - unable to print pCode\n");
3857 /*-----------------------------------------------------------------*/
3858 /* pic16_printpBlock - write the contents of a pBlock to a file */
3859 /*-----------------------------------------------------------------*/
3860 void pic16_printpBlock(FILE *of, pBlock *pb)
3869 if(pb->dbName == 'A') {
3873 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3875 // fprintf(of, "%s\tcode\t%d"
3879 for(pc = pb->pcHead; pc; pc = pc->next) {
3880 if(isPCF(pc) && PCF(pc)->fname) {
3881 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
3882 if(pb->dbName == 'A') {
3884 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3885 if(strcmp(ab->name, PCF(pc)->fname)) {
3886 fprintf(of, "\t0X%06X", ab->address);
3896 /*-----------------------------------------------------------------*/
3898 /* pCode processing */
3902 /*-----------------------------------------------------------------*/
3904 void pic16_unlinkpCode(pCode *pc)
3910 fprintf(stderr,"Unlinking: ");
3911 printpCode(stderr, pc);
3914 pc->prev->next = pc->next;
3916 pc->next->prev = pc->prev;
3918 pc->prev = pc->next = NULL;
3922 /*-----------------------------------------------------------------*/
3923 /*-----------------------------------------------------------------*/
3925 static void genericDestruct(pCode *pc)
3928 pic16_unlinkpCode(pc);
3931 /* For instructions, tell the register (if there's one used)
3932 * that it's no longer needed */
3933 regs *reg = pic16_getRegFromInstruction(pc);
3935 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3937 if(PCI(pc)->is2MemOp) {
3938 reg = pic16_getRegFromInstruction2(pc);
3940 deleteSetItem(&(reg->reglives.usedpCodes), pc);
3944 /* Instead of deleting the memory used by this pCode, mark
3945 * the object as bad so that if there's a pointer to this pCode
3946 * dangling around somewhere then (hopefully) when the type is
3947 * checked we'll catch it.
3952 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3960 /*-----------------------------------------------------------------*/
3961 /*-----------------------------------------------------------------*/
3962 /* modifiers for constant immediate */
3963 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
3965 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3970 int use_buffer = 1; // copy the string to the passed buffer pointer
3975 use_buffer = 0; // Don't bother copying the string to the buffer.
3979 switch(pcop->type) {
3983 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3986 return PCOR(pcop)->r->name;
3989 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3992 SAFE_snprintf(&buffer,&size,"%s",r->name);
4002 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4003 if(PCOI(pcop)->index) {
4004 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4005 immdmod[ PCOI(pcop)->offset ],
4009 SAFE_snprintf(&s,&size,"%s(%s)",
4010 immdmod[ PCOI(pcop)->offset ],
4014 if(PCOI(pcop)->index) {
4015 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4020 SAFE_snprintf(&s,&size, "%s(%s)",
4027 if(PCOI(pcop)->_const) {
4028 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4029 if(PCOI(pcop)->index) {
4030 SAFE_snprintf(&s,&size,"%s(%s + %d)",
4031 immdmod[ PCOI(pcop)->offset ],
4035 SAFE_snprintf(&s,&size,"%s(%s)",
4036 immdmod[ PCOI(pcop)->offset ],
4041 if(PCOI(pcop)->index)
4042 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4044 SAFE_snprintf(&s,&size,"LOW(%s)",pcop->name);
4047 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4)
4048 SAFE_snprintf(&s,&size,"(%s + %d)",
4050 PCOI(pcop)->index );
4052 if(PCOI(pcop)->offset)
4053 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4055 SAFE_snprintf(&s,&size,"(%s)",pcop->name);
4064 //size = sizeof(buffer);
4065 if( PCOR(pcop)->instance) {
4066 SAFE_snprintf(&s,&size,"(%s + %d)",
4068 PCOR(pcop)->instance );
4070 //fprintf(stderr,"PO_DIR %s\n",buffer);
4072 SAFE_snprintf(&s,&size,"%s",pcop->name);
4078 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4087 return "NO operand";
4091 /*-----------------------------------------------------------------*/
4092 /* pic16_get_op2 - variant to support two memory operand commands */
4093 /*-----------------------------------------------------------------*/
4094 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4099 int use_buffer = 1; // copy the string to the passed buffer pointer
4104 use_buffer = 0; // Don't bother copying the string to the buffer.
4108 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",
4109 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4110 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4114 switch(PCOR2(pcop)->pcop2->type) {
4118 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4121 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4124 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4127 SAFE_snprintf(&buffer,&size,"%s",r->name);
4139 if(PCOI(pcop)->_const) {
4141 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4142 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4145 8 * PCOI(pcop)->offset );
4147 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4150 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
4151 SAFE_snprintf(&s,&size,"(%s + %d)",
4153 PCOI(pcop)->index );
4155 if(PCOI(pcop)->offset)
4156 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4158 SAFE_snprintf(&s,&size,"%s",pcop->name);
4167 //size = sizeof(buffer);
4168 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4169 SAFE_snprintf(&s,&size,"(%s + %d)",
4170 PCOR(PCOR2(pcop)->pcop2)->r->name,
4171 PCOR(PCOR2(pcop)->pcop2)->instance );
4173 //fprintf(stderr,"PO_DIR %s\n",buffer);
4175 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4180 if (PCOR2(pcop)->r1->name) {
4182 SAFE_snprintf(&buffer,&size,"%s",PCOR2(pcop)->r1->name);
4185 return PCOR2(pcop)->r1->name;
4193 return "NO operand";
4197 /*-----------------------------------------------------------------*/
4198 /*-----------------------------------------------------------------*/
4199 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4203 return pic16_get_op(pcc->pcop,NULL,0);
4205 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4206 * return ("ERROR Null: "__FUNCTION__);
4208 return ("ERROR Null: pic16_get_op_from_instruction");
4212 /*-----------------------------------------------------------------*/
4213 /*-----------------------------------------------------------------*/
4214 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4217 fprintf(of,"pcodeopprint- not implemented\n");
4220 /*-----------------------------------------------------------------*/
4221 /* pic16_pCode2str - convert a pCode instruction to string */
4222 /*-----------------------------------------------------------------*/
4223 static char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4229 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4230 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4231 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4239 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4241 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4243 if(PCI(pc)->is2MemOp) {
4244 SAFE_snprintf(&s,&size, "%s, %s",
4245 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4246 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4250 if(PCI(pc)->is2LitOp) {
4251 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4255 if(PCI(pc)->isBitInst) {
4256 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4257 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4258 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4259 PCI(pc)->pcop->name ,
4260 PCI(pc)->pcop->name );
4262 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4263 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4264 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4265 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4267 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4268 //PCI(pc)->pcop->t.bit );
4271 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4272 if( PCI(pc)->num_ops == 3)
4273 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4275 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4278 SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
4280 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4281 if(PCI(pc)->num_ops == 3)
4282 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4284 r = pic16_getRegFromInstruction(pc);
4285 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4286 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4288 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4297 /* assuming that comment ends with a \n */
4298 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4302 /* assuming that inline code ends with a \n */
4303 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4307 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4310 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4313 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4316 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4319 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4322 SAFE_snprintf(&s,&size,"\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4326 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4333 /*-----------------------------------------------------------------*/
4334 /* genericPrint - the contents of a pCode to a file */
4335 /*-----------------------------------------------------------------*/
4336 static void genericPrint(FILE *of, pCode *pc)
4344 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4348 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4352 // If the opcode has a label, print that first
4354 pBranch *pbl = PCI(pc)->label;
4355 while(pbl && pbl->pc) {
4356 if(pbl->pc->type == PC_LABEL)
4357 pCodePrintLabel(of, pbl->pc);
4363 genericPrint(of,PCODE(PCI(pc)->cline));
4368 pic16_pCode2str(str, 256, pc);
4370 fprintf(of,"%s",str);
4373 if(pic16_debug_verbose) {
4374 fprintf(of, "\t;key=%03x",pc->seq);
4376 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4383 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4384 if(PCW(pc)->pci.label)
4385 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4387 if(PCW(pc)->operand) {
4388 fprintf(of,";\toperand ");
4389 pCodeOpPrint(of,PCW(pc)->operand );
4394 if(pic16_debug_verbose) {
4395 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4396 if(PCFL(pc)->ancestor)
4397 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4404 fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4408 pBranch *pbl = PCAD(pc)->label;
4409 while(pbl && pbl->pc) {
4410 if(pbl->pc->type == PC_LABEL)
4411 pCodePrintLabel(of, pbl->pc);
4415 fprintf(of, "\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4420 fprintf(of,"unknown pCode type %d\n",pc->type);
4425 /*-----------------------------------------------------------------*/
4426 /* pCodePrintFunction - prints function begin/end */
4427 /*-----------------------------------------------------------------*/
4429 static void pCodePrintFunction(FILE *of, pCode *pc)
4436 if( ((pCodeFunction *)pc)->modname)
4437 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4440 if(PCF(pc)->fname) {
4441 pBranch *exits = PCF(pc)->to;
4443 fprintf(of,"%s", PCF(pc)->fname);
4445 // if(pic16_pcode_verbose)
4446 fprintf(of, "\t;Function start");
4452 exits = exits->next;
4456 if(pic16_pcode_verbose)
4457 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4460 if((PCF(pc)->from &&
4461 PCF(pc)->from->pc->type == PC_FUNCTION &&
4462 PCF(PCF(pc)->from->pc)->fname) ) {
4464 if(pic16_pcode_verbose)
4465 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4467 if(pic16_pcode_verbose)
4468 fprintf(of,"; exit point [can't find entry point]\n");
4473 /*-----------------------------------------------------------------*/
4474 /* pCodePrintLabel - prints label */
4475 /*-----------------------------------------------------------------*/
4477 static void pCodePrintLabel(FILE *of, pCode *pc)
4484 fprintf(of,"%s:\n",PCL(pc)->label);
4485 else if (PCL(pc)->key >=0)
4486 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4488 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4491 /*-----------------------------------------------------------------*/
4492 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4493 /* remove it if it is found. */
4494 /*-----------------------------------------------------------------*/
4495 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4502 if(pcl->type == PC_OPCODE)
4503 b = PCI(pcl)->label;
4505 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4510 //fprintf (stderr, "%s \n",__FUNCTION__);
4511 //pcl->print(stderr,pcl);
4512 //pc->print(stderr,pc);
4515 //fprintf (stderr, "found label\n");
4519 bprev->next = b->next; /* Not first pCode in chain */
4523 PCI(pcl)->label = b->next; /* First pCode in chain */
4526 return; /* A label can't occur more than once */
4534 /*-----------------------------------------------------------------*/
4535 /*-----------------------------------------------------------------*/
4536 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4555 /*-----------------------------------------------------------------*/
4556 /* pBranchLink - given two pcodes, this function will link them */
4557 /* together through their pBranches */
4558 /*-----------------------------------------------------------------*/
4559 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4563 // Declare a new branch object for the 'from' pCode.
4565 //_ALLOC(b,sizeof(pBranch));
4566 b = Safe_calloc(1,sizeof(pBranch));
4567 b->pc = PCODE(t); // The link to the 'to' pCode.
4570 f->to = pic16_pBranchAppend(f->to,b);
4572 // Now do the same for the 'to' pCode.
4574 //_ALLOC(b,sizeof(pBranch));
4575 b = Safe_calloc(1,sizeof(pBranch));
4579 t->from = pic16_pBranchAppend(t->from,b);
4584 /*-----------------------------------------------------------------*/
4585 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4587 /*-----------------------------------------------------------------*/
4588 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4601 /*-----------------------------------------------------------------*/
4602 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4603 /*-----------------------------------------------------------------*/
4604 static void pCodeUnlink(pCode *pc)
4609 if(!pc->prev || !pc->next) {
4610 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4614 /* first remove the pCode from the chain */
4615 pc->prev->next = pc->next;
4616 pc->next->prev = pc->prev;
4618 /* Now for the hard part... */
4620 /* Remove the branches */
4624 pc1 = pb1->pc; /* Get the pCode that branches to the
4625 * one we're unlinking */
4627 /* search for the link back to this pCode (the one we're
4629 if(pb2 = pBranchFind(pc1->to,pc)) {
4630 pb2->pc = pc->to->pc; // make the replacement
4632 /* if the pCode we're unlinking contains multiple 'to'
4633 * branches (e.g. this a skip instruction) then we need
4634 * to copy these extra branches to the chain. */
4636 pic16_pBranchAppend(pb2, pc->to->next);
4645 /*-----------------------------------------------------------------*/
4646 /*-----------------------------------------------------------------*/
4648 static void genericAnalyze(pCode *pc)
4658 // Go through the pCodes that are in pCode chain and link
4659 // them together through the pBranches. Note, the pCodes
4660 // are linked together as a contiguous stream like the
4661 // assembly source code lines. The linking here mimics this
4662 // except that comments are not linked in.
4664 pCode *npc = pc->next;
4666 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4667 pBranchLink(pc,npc);
4672 /* reached the end of the pcode chain without finding
4673 * an instruction we could link to. */
4677 fprintf(stderr,"analyze PC_FLOW\n");
4681 fprintf(stderr,,";A bad pCode is being used\n");
4687 /*-----------------------------------------------------------------*/
4688 /*-----------------------------------------------------------------*/
4689 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4693 if(pc->type == PC_LABEL) {
4694 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4697 if(pc->type == PC_OPCODE) {
4698 pbr = PCI(pc)->label;
4700 if(pbr->pc->type == PC_LABEL) {
4701 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4711 /*-----------------------------------------------------------------*/
4712 /*-----------------------------------------------------------------*/
4713 static int checkLabel(pCode *pc)
4717 if(pc && isPCI(pc)) {
4718 pbr = PCI(pc)->label;
4720 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4730 /*-----------------------------------------------------------------*/
4731 /* findLabelinpBlock - Search the pCode for a particular label */
4732 /*-----------------------------------------------------------------*/
4733 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4740 for(pc = pb->pcHead; pc; pc = pc->next)
4741 if(compareLabel(pc,pcop_label))
4747 /*-----------------------------------------------------------------*/
4748 /* findLabel - Search the pCode for a particular label */
4749 /*-----------------------------------------------------------------*/
4750 static pCode * findLabel(pCodeOpLabel *pcop_label)
4758 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4759 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4763 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4767 /*-----------------------------------------------------------------*/
4768 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4769 /* in the linked list */
4770 /*-----------------------------------------------------------------*/
4771 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4784 /*-----------------------------------------------------------------*/
4785 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4786 /* in the linked list */
4787 /*-----------------------------------------------------------------*/
4788 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4800 /*-----------------------------------------------------------------*/
4801 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4802 /* in the linked list */
4803 /*-----------------------------------------------------------------*/
4804 pCode * pic16_findNextInstruction(pCode *pci)
4809 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4813 fprintf(stderr,"pic16_findNextInstruction: ");
4814 printpCode(stderr, pc);
4819 //fprintf(stderr,"Couldn't find instruction\n");
4823 /*-----------------------------------------------------------------*/
4824 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4825 /* in the linked list */
4826 /*-----------------------------------------------------------------*/
4827 pCode * pic16_findPrevInstruction(pCode *pci)
4829 return findPrevpCode(pci, PC_OPCODE);
4832 /*-----------------------------------------------------------------*/
4833 /* findFunctionEnd - given a pCode find the end of the function */
4834 /* that contains it */
4835 /*-----------------------------------------------------------------*/
4836 static pCode * findFunctionEnd(pCode *pc)
4840 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4846 fprintf(stderr,"Couldn't find function end\n");
4851 /*-----------------------------------------------------------------*/
4852 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4853 /* instruction with which it is associated. */
4854 /*-----------------------------------------------------------------*/
4855 static void AnalyzeLabel(pCode *pc)
4864 static void AnalyzeGOTO(pCode *pc)
4867 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4871 static void AnalyzeSKIP(pCode *pc)
4874 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4875 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4879 static void AnalyzeRETURN(pCode *pc)
4882 // branch_link(pc,findFunctionEnd(pc->next));
4888 /*-----------------------------------------------------------------*/
4889 /*-----------------------------------------------------------------*/
4890 regs * pic16_getRegFromInstruction(pCode *pc)
4896 PCI(pc)->num_ops == 0 ||
4897 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4900 switch(PCI(pc)->pcop->type) {
4903 return PCOR(PCI(pc)->pcop)->r;
4905 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4909 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4910 return PCOR(PCI(pc)->pcop)->r;
4913 if(PCOI(PCI(pc)->pcop)->r)
4914 return (PCOI(PCI(pc)->pcop)->r);
4916 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4917 return pic16_dirregWithName(PCI(pc)->pcop->name);
4918 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4921 return PCOR(PCI(pc)->pcop)->r;
4924 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4925 return PCOR(PCI(pc)->pcop)->r;
4927 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4931 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4932 //genericPrint(stderr, pc);
4940 /*-------------------------------------------------------------------------------*/
4941 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
4942 /*-------------------------------------------------------------------------------*/
4943 regs * pic16_getRegFromInstruction2(pCode *pc)
4949 PCI(pc)->num_ops == 0 ||
4950 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
4955 * operands supported in MOVFF:
4962 switch(PCI(pc)->pcop->type) {
4965 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4967 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4971 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4972 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4977 if(PCOI(PCI(pc)->pcop)->r)
4978 return (PCOI(PCI(pc)->pcop)->r);
4980 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4981 return pic16_dirregWithName(PCI(pc)->pcop->name);
4982 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4987 // return PCOR2(PCI(pc)->pcop)->r;
4990 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4991 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4995 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4998 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4999 //genericPrint(stderr, pc);
5007 /*-----------------------------------------------------------------*/
5008 /*-----------------------------------------------------------------*/
5010 static void AnalyzepBlock(pBlock *pb)
5017 /* Find all of the registers used in this pBlock
5018 * by looking at each instruction and examining it's
5021 for(pc = pb->pcHead; pc; pc = pc->next) {
5023 /* Is this an instruction with operands? */
5024 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5026 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5028 /* Loop through all of the registers declared so far in
5029 this block and see if we find this one there */
5031 regs *r = setFirstItem(pb->tregisters);
5034 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5035 PCOR(PCI(pc)->pcop)->r = r;
5038 r = setNextItem(pb->tregisters);
5042 /* register wasn't found */
5043 //r = Safe_calloc(1, sizeof(regs));
5044 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5045 //addSet(&pb->tregisters, r);
5046 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5047 //PCOR(PCI(pc)->pcop)->r = r;
5048 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5050 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5053 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5054 if(PCOR(PCI(pc)->pcop)->r) {
5055 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5056 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5058 if(PCI(pc)->pcop->name)
5059 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5061 fprintf(stderr,"ERROR: NULL register\n");
5070 /*-----------------------------------------------------------------*/
5072 /*-----------------------------------------------------------------*/
5073 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5075 static void InsertpFlow(pCode *pc, pCode **pflow)
5078 PCFL(*pflow)->end = pc;
5080 if(!pc || !pc->next)
5083 *pflow = pic16_newpCodeFlow();
5084 pic16_pCodeInsertAfter(pc, *pflow);
5087 /*-----------------------------------------------------------------*/
5088 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5089 /* the flow blocks. */
5091 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5092 * point the instruction flow changes.
5094 /*-----------------------------------------------------------------*/
5095 void pic16_BuildFlow(pBlock *pb)
5098 pCode *last_pci=NULL;
5105 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5106 /* Insert a pCodeFlow object at the beginning of a pBlock */
5108 InsertpFlow(pb->pcHead, &pflow);
5110 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5111 //pflow->next = pb->pcHead; /* Make the current head the next object */
5112 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5113 //pb->pcHead = pflow; /* Make the Flow object the head */
5116 for( pc = pic16_findNextInstruction(pb->pcHead);
5118 pc=pic16_findNextInstruction(pc)) {
5121 PCI(pc)->pcflow = PCFL(pflow);
5123 //fprintf(stderr," build: ");
5124 //pflow->print(stderr,pflow);
5126 if( PCI(pc)->isSkip) {
5128 /* The two instructions immediately following this one
5129 * mark the beginning of a new flow segment */
5131 while(pc && PCI(pc)->isSkip) {
5133 PCI(pc)->pcflow = PCFL(pflow);
5137 InsertpFlow(pc, &pflow);
5138 pc=pic16_findNextInstruction(pc->next);
5146 PCI(pc)->pcflow = PCFL(pflow);
5148 InsertpFlow(pc, &pflow);
5150 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5152 InsertpFlow(pc, &pflow);
5155 } else if (checkLabel(pc)) {
5157 /* This instruction marks the beginning of a
5158 * new flow segment */
5163 /* If the previous pCode is not a flow object, then
5164 * insert a new flow object. (This check prevents
5165 * two consecutive flow objects from being insert in
5166 * the case where a skip instruction preceeds an
5167 * instruction containing a label.) */
5169 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5170 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5172 PCI(pc)->pcflow = PCFL(pflow);
5179 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5181 PCFL(pflow)->end = pb->pcTail;
5184 /*-------------------------------------------------------------------*/
5185 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5186 /* the flow blocks. */
5188 * unBuildFlow removes pCodeFlow objects from a pCode chain
5190 /*-----------------------------------------------------------------*/
5191 static void unBuildFlow(pBlock *pb)
5206 if(PCI(pc)->pcflow) {
5207 //free(PCI(pc)->pcflow);
5208 PCI(pc)->pcflow = NULL;
5211 } else if(isPCFL(pc) )
5220 /*-----------------------------------------------------------------*/
5221 /*-----------------------------------------------------------------*/
5222 static void dumpCond(int cond)
5225 static char *pcc_str[] = {
5240 int ncond = sizeof(pcc_str) / sizeof(char *);
5243 fprintf(stderr, "0x%04X\n",cond);
5245 for(i=0,j=1; i<ncond; i++, j<<=1)
5247 fprintf(stderr, " %s\n",pcc_str[i]);
5253 /*-----------------------------------------------------------------*/
5254 /*-----------------------------------------------------------------*/
5255 static void FlowStats(pCodeFlow *pcflow)
5263 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5265 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5268 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5273 fprintf(stderr, " FlowStats inCond: ");
5274 dumpCond(pcflow->inCond);
5275 fprintf(stderr, " FlowStats outCond: ");
5276 dumpCond(pcflow->outCond);
5280 /*-----------------------------------------------------------------*
5281 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5282 * if it affects the banking bits.
5284 * return: -1 == Banking bits are unaffected by this pCode.
5286 * return: > 0 == Banking bits are affected.
5288 * If the banking bits are affected, then the returned value describes
5289 * which bits are affected and how they're affected. The lower half
5290 * of the integer maps to the bits that are affected, the upper half
5291 * to whether they're set or cleared.
5293 *-----------------------------------------------------------------*/
5295 static int isBankInstruction(pCode *pc)
5303 if( PCI(pc)->op == POC_MOVLB ||
5304 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5305 bank = PCOL(pc)->lit;
5312 /*-----------------------------------------------------------------*/
5313 /*-----------------------------------------------------------------*/
5314 static void FillFlow(pCodeFlow *pcflow)
5323 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5325 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5328 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5335 isBankInstruction(pc);
5337 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5341 fprintf(stderr, " FillFlow - Bad end of flow\n");
5343 fprintf(stderr, " FillFlow - Ending flow with\n ");
5344 pc->print(stderr,pc);
5347 fprintf(stderr, " FillFlow inCond: ");
5348 dumpCond(pcflow->inCond);
5349 fprintf(stderr, " FillFlow outCond: ");
5350 dumpCond(pcflow->outCond);
5354 /*-----------------------------------------------------------------*/
5355 /*-----------------------------------------------------------------*/
5356 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5358 pCodeFlowLink *fromLink, *toLink;
5360 if(!from || !to || !to->pcflow || !from->pcflow)
5363 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5364 toLink = pic16_newpCodeFlowLink(to->pcflow);
5366 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5367 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5371 /*-----------------------------------------------------------------*
5372 * void LinkFlow(pBlock *pb)
5374 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5375 * non-branching segments. In LinkFlow, we determine the execution
5376 * order of these segments. For example, if one of the segments ends
5377 * with a skip, then we know that there are two possible flow segments
5378 * to which control may be passed.
5379 *-----------------------------------------------------------------*/
5380 static void LinkFlow(pBlock *pb)
5386 //fprintf(stderr,"linkflow \n");
5388 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5390 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5393 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5395 //fprintf(stderr," link: ");
5396 //pcflow->print(stderr,pcflow);
5398 //FillFlow(PCFL(pcflow));
5400 pc = PCFL(pcflow)->end;
5402 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5403 if(isPCI_SKIP(pc)) {
5404 //fprintf(stderr, "ends with skip\n");
5405 //pc->print(stderr,pc);
5406 pct=pic16_findNextInstruction(pc->next);
5407 LinkFlow_pCode(PCI(pc),PCI(pct));
5408 pct=pic16_findNextInstruction(pct->next);
5409 LinkFlow_pCode(PCI(pc),PCI(pct));
5413 if(isPCI_BRANCH(pc)) {
5414 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5416 //fprintf(stderr, "ends with branch\n ");
5417 //pc->print(stderr,pc);
5419 if(!(pcol && isPCOLAB(pcol))) {
5420 if((PCI(pc)->op != POC_RETLW)
5421 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5423 /* continue if label is '$' which assembler knows how to parse */
5424 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5426 pc->print(stderr,pc);
5427 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5432 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5433 LinkFlow_pCode(PCI(pc),PCI(pct));
5435 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5436 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5437 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5443 //fprintf(stderr, "ends with non-branching instruction:\n");
5444 //pc->print(stderr,pc);
5446 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5452 //fprintf(stderr, "ends with unknown\n");
5453 //pc->print(stderr,pc);
5457 //fprintf(stderr, "ends with nothing: ERROR\n");
5461 /*-----------------------------------------------------------------*/
5462 /*-----------------------------------------------------------------*/
5464 /*-----------------------------------------------------------------*/
5465 /*-----------------------------------------------------------------*/
5466 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5472 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5475 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5485 /*-----------------------------------------------------------------*/
5486 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5487 /*-----------------------------------------------------------------*/
5488 static void insertBankSwitch(int position, pCode *pc, int bsr)
5497 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5498 * insert a BANKSEL assembler directive for the symbol used by
5499 * the pCode. This will allow the linker to setup the correct
5500 * bank at linking time
5503 if(!pic16_options.gen_banksel || bsr != -1) {
5504 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5507 /* emit the BANKSEL [symbol] */
5510 /* IMPORTANT: The following code does not check if a symbol is
5511 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5513 reg = pic16_getRegFromInstruction(pc);
5515 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", reg->name);
5517 position = 0; // position is always before (sanity check!)
5521 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5522 pc->print(stderr, pc);
5526 /* insert the bank switch after this pc instruction */
5527 pCode *pcnext = pic16_findNextInstruction(pc);
5528 pic16_pCodeInsertAfter(pc, new_pc);
5533 pic16_pCodeInsertAfter(pc->prev, new_pc);
5535 /* Move the label, if there is one */
5537 if(PCI(pc)->label) {
5538 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5539 // __FILE__, __LINE__, pc, new_pc);
5540 PCAD(new_pc)->label = PCI(pc)->label;
5541 PCI(pc)->label = NULL;
5544 // fprintf(stderr, "BankSwitch has been inserted\n");
5548 /*-----------------------------------------------------------------*/
5549 /*int compareBankFlow - compare the banking requirements between */
5551 /*-----------------------------------------------------------------*/
5552 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5555 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5558 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5561 if(pcflow->firstBank == -1)
5565 if(pcflowLink->pcflow->firstBank == -1) {
5566 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5567 pcflowLink->pcflow->to :
5568 pcflowLink->pcflow->from);
5569 return compareBankFlow(pcflow, pctl, toORfrom);
5573 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5576 pcflowLink->bank_conflict++;
5577 pcflowLink->pcflow->FromConflicts++;
5578 pcflow->ToConflicts++;
5581 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5584 pcflowLink->bank_conflict++;
5585 pcflowLink->pcflow->ToConflicts++;
5586 pcflow->FromConflicts++;
5590 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5591 pcflowLink->pcflow->pc.seq,
5592 pcflowLink->pcflow->FromConflicts,
5593 pcflowLink->pcflow->ToConflicts);
5600 /*-----------------------------------------------------------------*/
5601 /*-----------------------------------------------------------------*/
5602 static void DumpFlow(pBlock *pb)
5606 pCodeFlowLink *pcfl;
5609 fprintf(stderr,"Dump flow \n");
5610 pb->pcHead->print(stderr, pb->pcHead);
5612 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5613 pcflow->print(stderr,pcflow);
5615 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5617 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5619 if(!isPCFL(pcflow)) {
5620 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5623 fprintf(stderr,"dumping: ");
5624 pcflow->print(stderr,pcflow);
5625 FlowStats(PCFL(pcflow));
5627 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5629 pc = PCODE(pcfl->pcflow);
5631 fprintf(stderr, " from seq %d:\n",pc->seq);
5633 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5634 pc->print(stderr,pc);
5639 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5641 pc = PCODE(pcfl->pcflow);
5643 fprintf(stderr, " to seq %d:\n",pc->seq);
5645 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5646 pc->print(stderr,pc);
5655 /*-----------------------------------------------------------------*/
5656 /*-----------------------------------------------------------------*/
5657 static int OptimizepBlock(pBlock *pb)
5662 if(!pb || !peepOptimizing)
5665 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5667 for(pc = pb->pcHead; pc; pc = pc->next)
5668 matches += pic16_pCodePeepMatchRule(pc);
5671 pc = pic16_findNextInstruction(pb->pcHead);
5679 if(pic16_pCodePeepMatchRule(pc)) {
5684 pc = pic16_findNextInstruction(pcprev->next);
5686 pc = pic16_findNextInstruction(pb->pcHead);
5688 pc = pic16_findNextInstruction(pc->next);
5692 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5697 /*-----------------------------------------------------------------*/
5698 /*-----------------------------------------------------------------*/
5699 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5703 for(pc = pcs; pc; pc = pc->next) {
5705 if((pc->type == PC_OPCODE) &&
5707 (PCI(pc)->pcop->type == PO_LABEL) &&
5708 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5716 /*-----------------------------------------------------------------*/
5717 /*-----------------------------------------------------------------*/
5718 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5725 (PCI(pc)->pcop->type == PO_LABEL)) {
5727 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5729 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5731 free(pcol->pcop.name);
5733 /* If the key is negative, then we (probably) have a label to
5734 * a function and the name is already defined */
5737 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5741 //sprintf(buffer,"_%05d_DS_",pcl->key);
5743 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5745 pcol->pcop.name = Safe_strdup(s);
5746 pcol->key = pcl->key;
5747 //pc->print(stderr,pc);
5754 /*-----------------------------------------------------------------*/
5755 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5756 /* pCode chain if they're not used. */
5757 /*-----------------------------------------------------------------*/
5758 static void pBlockRemoveUnusedLabels(pBlock *pb)
5760 pCode *pc; pCodeLabel *pcl;
5765 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5767 pBranch *pbr = PCI(pc)->label;
5768 if(pbr && pbr->next) {
5769 pCode *pcd = pb->pcHead;
5771 //fprintf(stderr, "multiple labels\n");
5772 //pc->print(stderr,pc);
5777 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5778 //fprintf(stderr,"Used by:\n");
5779 //pcd->print(stderr,pcd);
5781 exchangeLabels(PCL(pbr->pc),pcd);
5790 for(pc = pb->pcHead; pc; pc = pc->next) {
5792 if(isPCL(pc)) // pc->type == PC_LABEL)
5794 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5795 pcl = PCL(PCI(pc)->label->pc);
5798 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5800 /* This pCode is a label, so search the pBlock to see if anyone
5803 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5804 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5805 /* Couldn't find an instruction that refers to this label
5806 * So, unlink the pCode label from it's pCode chain
5807 * and destroy the label */
5808 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5810 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5811 if(pc->type == PC_LABEL) {
5812 pic16_unlinkpCode(pc);
5813 pCodeLabelDestruct(pc);
5815 unlinkpCodeFromBranch(pc, PCODE(pcl));
5816 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5827 /*-----------------------------------------------------------------*/
5828 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
5829 /* chain and put them into pBranches that are */
5830 /* associated with the appropriate pCode */
5832 /*-----------------------------------------------------------------*/
5833 void pic16_pBlockMergeLabels(pBlock *pb)
5836 pCode *pc, *pcnext=NULL;
5841 /* First, Try to remove any unused labels */
5842 //pBlockRemoveUnusedLabels(pb);
5844 /* Now loop through the pBlock and merge the labels with the opcodes */
5847 // for(pc = pb->pcHead; pc; pc = pc->next) {
5850 pCode *pcn = pc->next;
5852 if(pc->type == PC_LABEL) {
5854 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5855 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5857 if((pcnext = pic16_findNextInstruction(pc) )) {
5859 // Unlink the pCode label from it's pCode chain
5860 pic16_unlinkpCode(pc);
5862 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5863 // And link it into the instruction's pBranch labels. (Note, since
5864 // it's possible to have multiple labels associated with one instruction
5865 // we must provide a means to accomodate the additional labels. Thus
5866 // the labels are placed into the singly-linked list "label" as
5867 // opposed to being a single member of the pCodeInstruction.)
5869 //_ALLOC(pbr,sizeof(pBranch));
5871 pbr = Safe_calloc(1,sizeof(pBranch));
5875 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5878 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5880 } else if(pc->type == PC_CSOURCE) {
5882 /* merge the source line symbolic info into the next instruction */
5883 if((pcnext = pic16_findNextInstruction(pc) )) {
5885 // Unlink the pCode label from it's pCode chain
5886 pic16_unlinkpCode(pc);
5887 PCI(pcnext)->cline = PCCS(pc);
5888 //fprintf(stderr, "merging CSRC\n");
5889 //genericPrint(stderr,pcnext);
5895 pBlockRemoveUnusedLabels(pb);
5899 /*-----------------------------------------------------------------*/
5900 /*-----------------------------------------------------------------*/
5901 static int OptimizepCode(char dbName)
5903 #define MAX_PASSES 4
5912 DFPRINTF((stderr," Optimizing pCode\n"));
5916 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5917 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5918 matches += OptimizepBlock(pb);
5921 while(matches && ++passes < MAX_PASSES);
5926 /*-----------------------------------------------------------------*/
5927 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5928 /*-----------------------------------------------------------------*/
5930 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5934 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5936 if( !( (pcop->type == PO_LABEL) ||
5937 (pcop->type == PO_LITERAL) ||
5938 (pcop->type == PO_STR) ))
5939 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5940 PCOR(pcop)->r->wasUsed = 1;
5946 /*----------------------------------------------------------------------*
5947 * pic16_areRegsSame - check to see if the names of two registers match *
5948 *----------------------------------------------------------------------*/
5949 int pic16_areRegsSame(regs *r1, regs *r2)
5951 if(!strcmp(r1->name, r2->name))return 1;
5957 /*-----------------------------------------------------------------*/
5958 /*-----------------------------------------------------------------*/
5959 static void pic16_FixRegisterBanking(pBlock *pb)
5963 regs *reg, *prevreg;
5968 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5972 /* loop through all of the flow blocks with in one pblock */
5974 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
5978 /* at this point, pc should point to a PC_FLOW object */
5979 /* for each flow block, determine the register banking
5982 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
5983 reg = pic16_getRegFromInstruction(pc);
5986 fprintf(stderr, "reg = %p\n", reg);
5988 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
5989 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
5990 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
5991 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
5995 /* we can be 99% that within a pBlock, between two consequtive
5996 * refernces to the same register, the extra banksel is needless */
5998 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
6000 && (PCI(pc)->op != POC_CALL)
6002 && ( ((pic16_options.opt_banksel>0)
6003 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
6004 || (!pic16_options.opt_banksel)
6008 /* Examine the instruction before this one to make sure it is
6009 * not a skip type instruction */
6010 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6012 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6013 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6014 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
6016 insertBankSwitch(0, pc, (pic16_options.gen_banksel)?-1:0);
6028 if(pcprev && cur_bank) {
6030 int pos = 1; /* Assume that the bank switch instruction(s)
6031 * are inserted after this instruction */
6033 if((PCI(pcprev)->op == POC_RETLW) ||
6034 (PCI(pcprev)->op == POC_RETURN) ||
6035 (PCI(pcprev)->op == POC_RETFIE)) {
6037 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6043 /* Brute force - make sure that we point to bank 0 at the
6044 * end of each flow block */
6046 // insertBankSwitch(pos, pcprev, 0);
6048 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6049 pic16_pCodeInsertAfter(pcprev, new_pc);
6052 //fprintf(stderr, "Brute force switch\n");
6059 static void pBlockDestruct(pBlock *pb)
6070 /*-----------------------------------------------------------------*/
6071 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6072 /* name dbName and combine them */
6073 /* into one block */
6074 /*-----------------------------------------------------------------*/
6075 static void mergepBlocks(char dbName)
6078 pBlock *pb, *pbmerged = NULL,*pbn;
6080 pb = the_pFile->pbHead;
6082 //fprintf(stderr," merging blocks named %c\n",dbName);
6086 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6087 if( getpBlock_dbName(pb) == dbName) {
6089 //fprintf(stderr," merged block %c\n",dbName);
6094 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6095 /* pic16_addpCode2pBlock doesn't handle the tail: */
6096 pbmerged->pcTail = pb->pcTail;
6098 pb->prev->next = pbn;
6100 pbn->prev = pb->prev;
6105 //pic16_printpBlock(stderr, pbmerged);
6112 /*-----------------------------------------------------------------*/
6113 /* AnalyzeFlow - Examine the flow of the code and optimize */
6115 /* level 0 == minimal optimization */
6116 /* optimize registers that are used only by two instructions */
6117 /* level 1 == maximal optimization */
6118 /* optimize by looking at pairs of instructions that use the */
6120 /*-----------------------------------------------------------------*/
6122 static void AnalyzeFlow(int level)
6124 static int times_called=0;
6129 /* remove unused allocated registers before exiting */
6130 pic16_RemoveUnusedRegisters();
6136 /* if this is not the first time this function has been called,
6137 then clean up old flow information */
6138 if(times_called++) {
6139 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6142 pic16_RegsUnMapLiveRanges();
6147 /* Phase 2 - Flow Analysis - Register Banking
6149 * In this phase, the individual flow blocks are examined
6150 * and register banking is fixed.
6154 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6155 pic16_FixRegisterBanking(pb);
6158 /* Phase 2 - Flow Analysis
6160 * In this phase, the pCode is partition into pCodeFlow
6161 * blocks. The flow blocks mark the points where a continuous
6162 * stream of instructions changes flow (e.g. because of
6163 * a call or goto or whatever).
6166 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6167 pic16_BuildFlow(pb);
6170 /* Phase 2 - Flow Analysis - linking flow blocks
6172 * In this phase, the individual flow blocks are examined
6173 * to determine their order of excution.
6176 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6179 /* Phase 3 - Flow Analysis - Flow Tree
6181 * In this phase, the individual flow blocks are examined
6182 * to determine their order of execution.
6185 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6186 pic16_BuildFlowTree(pb);
6189 /* Phase x - Flow Analysis - Used Banks
6191 * In this phase, the individual flow blocks are examined
6192 * to determine the Register Banks they use
6196 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6201 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6202 pic16_pCodeRegMapLiveRanges(pb);
6204 pic16_RemoveUnusedRegisters();
6206 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6207 pic16_pCodeRegOptimizeRegUsage(level);
6215 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6220 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6222 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6223 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6224 pcflow = pcflow->next) {
6226 FillFlow(PCFL(pcflow));
6231 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6234 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6235 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6236 pcflow = pcflow->next) {
6238 FlowStats(PCFL(pcflow));
6244 /* VR -- no need to analyze banking in flow, but left here :
6245 * 1. because it may be used in the future for other purposes
6246 * 2. because if omitted we'll miss some optimization done here
6248 * Perhaps I should rename it to something else
6251 /*-----------------------------------------------------------------*/
6252 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6253 /* assigned to the registers. */
6255 /*-----------------------------------------------------------------*/
6257 void pic16_AnalyzeBanking(void)
6261 if(!pic16_picIsInitialized()) {
6262 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6263 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6264 fprintf(stderr,"support/scripts/inc2h.pl\n");
6265 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6267 /* I think it took a long long time to fix this bug! ;-) -- VR */
6273 /* Phase x - Flow Analysis - Used Banks
6275 * In this phase, the individual flow blocks are examined
6276 * to determine the Register Banks they use
6282 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6283 // BanksUsedFlow(pb);
6285 if(!the_pFile)return;
6287 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6288 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6289 pic16_FixRegisterBanking(pb);
6294 /*-----------------------------------------------------------------*/
6295 /* buildCallTree - Look at the flow and extract all of the calls. */
6296 /*-----------------------------------------------------------------*/
6297 static set *register_usage(pBlock *pb);
6299 static void buildCallTree(void )
6310 /* Now build the call tree.
6311 First we examine all of the pCodes for functions.
6312 Keep in mind that the function boundaries coincide
6313 with pBlock boundaries.
6315 The algorithm goes something like this:
6316 We have two nested loops. The outer loop iterates
6317 through all of the pBlocks/functions. The inner
6318 loop iterates through all of the pCodes for
6319 a given pBlock. When we begin iterating through
6320 a pBlock, the variable pc_fstart, pCode of the start
6321 of a function, is cleared. We then search for pCodes
6322 of type PC_FUNCTION. When one is encountered, we
6323 initialize pc_fstart to this and at the same time
6324 associate a new pBranch object that signifies a
6325 branch entry. If a return is found, then this signifies
6326 a function exit point. We'll link the pCodes of these
6327 returns to the matching pc_fstart.
6329 When we're done, a doubly linked list of pBranches
6330 will exist. The head of this list is stored in
6331 `the_pFile', which is the meta structure for all
6332 of the pCode. Look at the pic16_printCallTree function
6333 on how the pBranches are linked together.
6336 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6337 pCode *pc_fstart=NULL;
6338 for(pc = pb->pcHead; pc; pc = pc->next) {
6340 if (PCF(pc)->fname) {
6342 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6343 //fprintf(stderr," found main \n");
6344 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6348 pbr = Safe_calloc(1,sizeof(pBranch));
6349 pbr->pc = pc_fstart = pc;
6352 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6354 // Here's a better way of doing the same:
6355 addSet(&pb->function_entries, pc);
6358 // Found an exit point in a function, e.g. return
6359 // (Note, there may be more than one return per function)
6361 pBranchLink(PCF(pc_fstart), PCF(pc));
6363 addSet(&pb->function_exits, pc);
6365 } else if(isCALL(pc)) {
6366 addSet(&pb->function_calls,pc);
6371 /* Re-allocate the registers so that there are no collisions
6372 * between local variables when one function call another */
6375 // pic16_deallocateAllRegs();
6377 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6384 /*-----------------------------------------------------------------*/
6385 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6386 /* all of the logical connections. */
6388 /* Essentially what's done here is that the pCode flow is */
6390 /*-----------------------------------------------------------------*/
6392 void pic16_AnalyzepCode(char dbName)
6403 /* Phase 1 - Register allocation and peep hole optimization
6405 * The first part of the analysis is to determine the registers
6406 * that are used in the pCode. Once that is done, the peep rules
6407 * are applied to the code. We continue to loop until no more
6408 * peep rule optimizations are found (or until we exceed the
6409 * MAX_PASSES threshold).
6411 * When done, the required registers will be determined.
6417 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6418 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6420 /* First, merge the labels with the instructions */
6421 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6422 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6424 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6425 //fprintf(stderr," analyze and merging block %c\n",dbName);
6426 pic16_pBlockMergeLabels(pb);
6429 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6434 changes = OptimizepCode(dbName);
6437 } while(changes && (i++ < MAX_PASSES));
6442 /*-----------------------------------------------------------------*/
6443 /* ispCodeFunction - returns true if *pc is the pCode of a */
6445 /*-----------------------------------------------------------------*/
6446 static bool ispCodeFunction(pCode *pc)
6449 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6455 /*-----------------------------------------------------------------*/
6456 /* findFunction - Search for a function by name (given the name) */
6457 /* in the set of all functions that are in a pBlock */
6458 /* (note - I expect this to change because I'm planning to limit */
6459 /* pBlock's to just one function declaration */
6460 /*-----------------------------------------------------------------*/
6461 static pCode *findFunction(char *fname)
6468 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6470 pc = setFirstItem(pb->function_entries);
6473 if((pc->type == PC_FUNCTION) &&
6475 (strcmp(fname, PCF(pc)->fname)==0))
6478 pc = setNextItem(pb->function_entries);
6486 static void MarkUsedRegisters(set *regset)
6491 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6492 // fprintf(stderr, "marking register = %s\t", r1->name);
6493 r2 = pic16_regWithIdx(r1->rIdx);
6494 // fprintf(stderr, "to register = %s\n", r2->name);
6500 static void pBlockStats(FILE *of, pBlock *pb)
6506 if(!pic16_pcode_verbose)return;
6508 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6510 // for now just print the first element of each set
6511 pc = setFirstItem(pb->function_entries);
6513 fprintf(of,";entry: ");
6516 pc = setFirstItem(pb->function_exits);
6518 fprintf(of,";has an exit\n");
6522 pc = setFirstItem(pb->function_calls);
6524 fprintf(of,";functions called:\n");
6527 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6528 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6530 pc = setNextItem(pb->function_calls);
6534 r = setFirstItem(pb->tregisters);
6536 int n = elementsInSet(pb->tregisters);
6538 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6541 fprintf(of,"; %s\n",r->name);
6542 r = setNextItem(pb->tregisters);
6547 /*-----------------------------------------------------------------*/
6548 /*-----------------------------------------------------------------*/
6550 static void sequencepCode(void)
6556 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6558 pb->seq = GpCodeSequenceNumber+1;
6560 for( pc = pb->pcHead; pc; pc = pc->next)
6561 pc->seq = ++GpCodeSequenceNumber;
6567 /*-----------------------------------------------------------------*/
6568 /*-----------------------------------------------------------------*/
6569 static set *register_usage(pBlock *pb)
6572 set *registers=NULL;
6573 set *registersInCallPath = NULL;
6575 /* check recursion */
6577 pc = setFirstItem(pb->function_entries);
6584 if(pc->type != PC_FUNCTION)
6585 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6587 pc = setFirstItem(pb->function_calls);
6588 for( ; pc; pc = setNextItem(pb->function_calls)) {
6590 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6591 char *dest = pic16_get_op_from_instruction(PCI(pc));
6593 pcn = findFunction(dest);
6595 registersInCallPath = register_usage(pcn->pb);
6597 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6602 pBlockStats(stderr,pb); // debug
6605 // Mark the registers in this block as used.
6607 MarkUsedRegisters(pb->tregisters);
6608 if(registersInCallPath) {
6609 /* registers were used in the functions this pBlock has called */
6610 /* so now, we need to see if these collide with the ones we are */
6613 regs *r1,*r2, *newreg;
6615 DFPRINTF((stderr,"comparing registers\n"));
6617 r1 = setFirstItem(registersInCallPath);
6620 r2 = setFirstItem(pb->tregisters);
6622 while(r2 && (r1->type != REG_STK)) {
6624 if(r2->rIdx == r1->rIdx) {
6625 newreg = pic16_findFreeReg(REG_GPR);
6629 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6633 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6634 r1->rIdx, newreg->rIdx));
6635 r2->rIdx = newreg->rIdx;
6636 //if(r2->name) free(r2->name);
6638 r2->name = Safe_strdup(newreg->name);
6642 newreg->wasUsed = 1;
6644 r2 = setNextItem(pb->tregisters);
6647 r1 = setNextItem(registersInCallPath);
6650 /* Collisions have been resolved. Now free the registers in the call path */
6651 r1 = setFirstItem(registersInCallPath);
6653 if(r1->type != REG_STK) {
6654 newreg = pic16_regWithIdx(r1->rIdx);
6657 r1 = setNextItem(registersInCallPath);
6661 // MarkUsedRegisters(pb->registers);
6663 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6666 DFPRINTF((stderr,"returning regs\n"));
6668 DFPRINTF((stderr,"not returning regs\n"));
6670 DFPRINTF((stderr,"pBlock after register optim.\n"));
6671 pBlockStats(stderr,pb); // debug
6677 /*-----------------------------------------------------------------*/
6678 /* pct2 - writes the call tree to a file */
6680 /*-----------------------------------------------------------------*/
6681 static void pct2(FILE *of,pBlock *pb,int indent)
6685 // set *registersInCallPath = NULL;
6691 return; //recursion ?
6693 pc = setFirstItem(pb->function_entries);
6700 for(i=0;i<indent;i++) // Indentation
6703 if(pc->type == PC_FUNCTION)
6704 fprintf(of,"%s\n",PCF(pc)->fname);
6709 pc = setFirstItem(pb->function_calls);
6710 for( ; pc; pc = setNextItem(pb->function_calls)) {
6712 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6713 char *dest = pic16_get_op_from_instruction(PCI(pc));
6715 pcn = findFunction(dest);
6717 pct2(of,pcn->pb,indent+1);
6719 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6727 /*-----------------------------------------------------------------*/
6728 /* pic16_printCallTree - writes the call tree to a file */
6730 /*-----------------------------------------------------------------*/
6732 void pic16_printCallTree(FILE *of)
6744 fprintf(of, "\npBlock statistics\n");
6745 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6750 fprintf(of,"Call Tree\n");
6751 pbr = the_pFile->functions;
6755 if(!ispCodeFunction(pc))
6756 fprintf(of,"bug in call tree");
6759 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6761 while(pc->next && !ispCodeFunction(pc->next)) {
6763 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6764 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6772 fprintf(of,"\n**************\n\na better call tree\n");
6773 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6778 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6779 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6785 /*-----------------------------------------------------------------*/
6787 /*-----------------------------------------------------------------*/
6789 static void InlineFunction(pBlock *pb)
6797 pc = setFirstItem(pb->function_calls);
6799 for( ; pc; pc = setNextItem(pb->function_calls)) {
6802 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6808 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
6810 //fprintf(stderr,"Cool can inline:\n");
6811 //pcn->print(stderr,pcn);
6813 //fprintf(stderr,"recursive call Inline\n");
6814 InlineFunction(pcn->pb);
6815 //fprintf(stderr,"return from recursive call Inline\n");
6818 At this point, *pc points to a CALL mnemonic, and
6819 *pcn points to the function that is being called.
6821 To in-line this call, we need to remove the CALL
6822 and RETURN(s), and link the function pCode in with
6828 /* Remove the CALL */
6832 /* remove callee pBlock from the pBlock linked list */
6833 removepBlock(pcn->pb);
6841 /* Remove the Function pCode */
6842 pct = pic16_findNextInstruction(pcn->next);
6844 /* Link the function with the callee */
6845 pc->next = pcn->next;
6846 pcn->next->prev = pc;
6848 /* Convert the function name into a label */
6850 pbr = Safe_calloc(1,sizeof(pBranch));
6851 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6853 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6854 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6856 /* turn all of the return's except the last into goto's */
6857 /* check case for 2 instruction pBlocks */
6858 pce = pic16_findNextInstruction(pcn->next);
6860 pCode *pce_next = pic16_findNextInstruction(pce->next);
6862 if(pce_next == NULL) {
6863 /* found the last return */
6864 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6866 //fprintf(stderr,"found last return\n");
6867 //pce->print(stderr,pce);
6868 pce->prev->next = pc_call->next;
6869 pc_call->next->prev = pce->prev;
6870 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6880 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6886 /*-----------------------------------------------------------------*/
6888 /*-----------------------------------------------------------------*/
6890 void pic16_InlinepCode(void)
6899 if(!functionInlining)
6902 /* Loop through all of the function definitions and count the
6903 * number of times each one is called */
6904 //fprintf(stderr,"inlining %d\n",__LINE__);
6906 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6908 pc = setFirstItem(pb->function_calls);
6910 for( ; pc; pc = setNextItem(pb->function_calls)) {
6913 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6914 if(pcn && isPCF(pcn)) {
6915 PCF(pcn)->ncalled++;
6918 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6923 //fprintf(stderr,"inlining %d\n",__LINE__);
6925 /* Now, Loop through the function definitions again, but this
6926 * time inline those functions that have only been called once. */
6928 InlineFunction(the_pFile->pbHead);
6929 //fprintf(stderr,"inlining %d\n",__LINE__);
6931 for(pb = the_pFile->pbHead; pb; pb = pb->next)