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_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
61 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
63 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
65 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
66 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
67 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
68 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
69 pCodeOpReg pic16_pc_postinc1 = {{PO_FSR0, "POSTINC1"}, -1, NULL, 0, NULL};
70 pCodeOpReg pic16_pc_preinc1 = {{PO_FSR0, "PREINC1"}, -1, NULL, 0, NULL};
72 pCodeOpReg pic16_pc_plusw2 = {{PO_FSR0, "PLUSW2"}, -1, NULL, 0, NULL};
73 pCodeOpReg pic16_pc_preinc2 = {{PO_FSR0, "PREINC1"}, -1, NULL, 0, NULL};
74 pCodeOpReg pic16_pc_postdec1 = {{PO_FSR0, "POSTDEV1"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
77 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
78 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
80 static int mnemonics_initialized = 0;
83 static hTab *pic16MnemonicsHash = NULL;
84 static hTab *pic16pCodePeepCommandsHash = NULL;
86 static pFile *the_pFile = NULL;
87 static pBlock *pb_dead_pcodes = NULL;
89 /* Hardcoded flags to change the behavior of the PIC port */
90 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
91 static int functionInlining = 1; /* inline functions if nonzero */
92 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
94 int pic16_pcode_verbose = 0;
96 //static int GpCodeSequenceNumber = 1;
97 static int GpcFlowSeq = 1;
99 extern void pic16_RemoveUnusedRegisters(void);
100 extern void pic16_RegsUnMapLiveRanges(void);
101 extern void pic16_BuildFlowTree(pBlock *pb);
102 extern void pic16_pCodeRegOptimizeRegUsage(int level);
103 extern int pic16_picIsInitialized(void);
104 #if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
106 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
107 extern int mnem2key(char const *mnem);
108 #endif // OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
110 /****************************************************************/
111 /* Forward declarations */
112 /****************************************************************/
114 void pic16_unlinkpCode(pCode *pc);
116 static void genericAnalyze(pCode *pc);
117 static void AnalyzeGOTO(pCode *pc);
118 static void AnalyzeSKIP(pCode *pc);
119 static void AnalyzeRETURN(pCode *pc);
122 static void genericDestruct(pCode *pc);
123 static void genericPrint(FILE *of,pCode *pc);
125 static void pCodePrintLabel(FILE *of, pCode *pc);
126 static void pCodePrintFunction(FILE *of, pCode *pc);
127 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
128 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
129 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
130 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
131 int pic16_pCodePeepMatchRule(pCode *pc);
132 static void pBlockStats(FILE *of, pBlock *pb);
133 static pBlock *newpBlock(void);
134 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
135 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
136 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
137 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
140 /****************************************************************/
141 /* PIC Instructions */
142 /****************************************************************/
144 pCodeInstruction pic16_pciADDWF = {
145 {PC_OPCODE, NULL, NULL, 0, NULL,
158 1,0, // dest, bit instruction
160 0, // literal operand
162 0, // fast call/return mode select bit
163 0, // second memory operand
164 0, // second literal operand
166 (PCC_W | PCC_REGISTER), // inCond
167 (PCC_REGISTER | PCC_Z), // outCond
171 pCodeInstruction pic16_pciADDFW = {
172 {PC_OPCODE, NULL, NULL, 0, NULL,
185 0,0, // dest, bit instruction
187 0, // literal operand
189 0, // fast call/return mode select bit
190 0, // second memory operand
191 0, // second literal operand
193 (PCC_W | PCC_REGISTER), // inCond
194 (PCC_W | PCC_Z), // outCond
198 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
199 {PC_OPCODE, NULL, NULL, 0, NULL,
212 1,0, // dest, bit instruction
214 0, // literal operand
216 0, // fast call/return mode select bit
217 0, // second memory operand
218 0, // second literal operand
220 (PCC_W | PCC_REGISTER | PCC_C), // inCond
221 (PCC_REGISTER | PCC_Z), // outCond
225 pCodeInstruction pic16_pciADDFWC = {
226 {PC_OPCODE, NULL, NULL, 0, NULL,
239 0,0, // dest, bit instruction
241 0, // literal operand
243 0, // fast call/return mode select bit
244 0, // second memory operand
245 0, // second literal operand
247 (PCC_W | PCC_REGISTER | PCC_C), // inCond
248 (PCC_W | PCC_Z), // outCond
252 pCodeInstruction pic16_pciADDLW = {
253 {PC_OPCODE, NULL, NULL, 0, NULL,
266 0,0, // dest, bit instruction
268 1, // literal operand
270 0, // fast call/return mode select bit
271 0, // second memory operand
272 0, // second literal operand
274 (PCC_W | PCC_LITERAL), // inCond
275 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
279 pCodeInstruction pic16_pciANDLW = {
280 {PC_OPCODE, NULL, NULL, 0, NULL,
293 0,0, // dest, bit instruction
295 1, // literal operand
297 0, // fast call/return mode select bit
298 0, // second memory operand
299 0, // second literal operand
301 (PCC_W | PCC_LITERAL), // inCond
302 (PCC_W | PCC_Z | PCC_N), // outCond
306 pCodeInstruction pic16_pciANDWF = {
307 {PC_OPCODE, NULL, NULL, 0, NULL,
320 1,0, // dest, bit instruction
322 0, // literal operand
324 0, // fast call/return mode select bit
325 0, // second memory operand
326 0, // second literal operand
328 (PCC_W | PCC_REGISTER), // inCond
329 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
333 pCodeInstruction pic16_pciANDFW = {
334 {PC_OPCODE, NULL, NULL, 0, NULL,
347 0,0, // dest, bit instruction
349 0, // literal operand
351 0, // fast call/return mode select bit
352 0, // second memory operand
353 0, // second literal operand
355 (PCC_W | PCC_REGISTER), // inCond
356 (PCC_W | PCC_Z) // outCond
359 pCodeInstruction pic16_pciBC = { // mdubuc - New
360 {PC_OPCODE, NULL, NULL, 0, NULL,
373 0,0, // dest, bit instruction
375 0, // literal operand
377 0, // fast call/return mode select bit
378 0, // second memory operand
379 0, // second literal operand
381 (PCC_REL_ADDR | PCC_C), // inCond
386 pCodeInstruction pic16_pciBCF = {
387 {PC_OPCODE, NULL, NULL, 0, NULL,
400 1,1, // dest, bit instruction
402 0, // literal operand
404 0, // fast call/return mode select bit
405 0, // second memory operand
406 0, // second literal operand
408 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
409 PCC_REGISTER, // outCond
413 pCodeInstruction pic16_pciBN = { // mdubuc - New
414 {PC_OPCODE, NULL, NULL, 0, NULL,
427 0,0, // dest, bit instruction
429 0, // literal operand
431 0, // fast call/return mode select bit
432 0, // second memory operand
433 0, // second literal operand
435 (PCC_REL_ADDR | PCC_N), // inCond
436 PCC_NONE , // outCond
440 pCodeInstruction pic16_pciBNC = { // mdubuc - New
441 {PC_OPCODE, NULL, NULL, 0, NULL,
454 0,0, // dest, bit instruction
456 0, // literal operand
458 0, // fast call/return mode select bit
459 0, // second memory operand
460 0, // second literal operand
462 (PCC_REL_ADDR | PCC_C), // inCond
463 PCC_NONE , // outCond
467 pCodeInstruction pic16_pciBNN = { // mdubuc - New
468 {PC_OPCODE, NULL, NULL, 0, NULL,
481 0,0, // dest, bit instruction
483 0, // literal operand
485 0, // fast call/return mode select bit
486 0, // second memory operand
487 0, // second literal operand
489 (PCC_REL_ADDR | PCC_N), // inCond
490 PCC_NONE , // outCond
494 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
495 {PC_OPCODE, NULL, NULL, 0, NULL,
508 0,0, // dest, bit instruction
510 0, // literal operand
512 0, // fast call/return mode select bit
513 0, // second memory operand
514 0, // second literal operand
516 (PCC_REL_ADDR | PCC_OV), // inCond
517 PCC_NONE , // outCond
521 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
522 {PC_OPCODE, NULL, NULL, 0, NULL,
535 0,0, // dest, bit instruction
537 0, // literal operand
539 0, // fast call/return mode select bit
540 0, // second memory operand
541 0, // second literal operand
543 (PCC_REL_ADDR | PCC_Z), // inCond
544 PCC_NONE , // outCond
548 pCodeInstruction pic16_pciBOV = { // mdubuc - New
549 {PC_OPCODE, NULL, NULL, 0, NULL,
562 0,0, // dest, bit instruction
564 0, // literal operand
566 0, // fast call/return mode select bit
567 0, // second memory operand
568 0, // second literal operand
570 (PCC_REL_ADDR | PCC_OV), // inCond
571 PCC_NONE , // outCond
575 pCodeInstruction pic16_pciBRA = { // mdubuc - New
576 {PC_OPCODE, NULL, NULL, 0, NULL,
589 0,0, // dest, bit instruction
591 0, // literal operand
593 0, // fast call/return mode select bit
594 0, // second memory operand
595 0, // second literal operand
597 PCC_REL_ADDR, // inCond
598 PCC_NONE , // outCond
602 pCodeInstruction pic16_pciBSF = {
603 {PC_OPCODE, NULL, NULL, 0, NULL,
616 1,1, // dest, bit instruction
618 0, // literal operand
620 0, // fast call/return mode select bit
621 0, // second memory operand
622 0, // second literal operand
624 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
625 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
629 pCodeInstruction pic16_pciBTFSC = {
630 {PC_OPCODE, NULL, NULL, 0, NULL,
643 0,1, // dest, bit instruction
645 0, // literal operand
647 0, // fast call/return mode select bit
648 0, // second memory operand
649 0, // second literal operand
651 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
652 PCC_EXAMINE_PCOP, // outCond
656 pCodeInstruction pic16_pciBTFSS = {
657 {PC_OPCODE, NULL, NULL, 0, NULL,
670 0,1, // dest, bit instruction
672 0, // literal operand
674 0, // fast call/return mode select bit
675 0, // second memory operand
676 0, // second literal operand
678 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
679 PCC_EXAMINE_PCOP, // outCond
683 pCodeInstruction pic16_pciBTG = { // mdubuc - New
684 {PC_OPCODE, NULL, NULL, 0, NULL,
697 0,1, // dest, bit instruction
699 0, // literal operand
701 0, // fast call/return mode select bit
702 0, // second memory operand
703 0, // second literal operand
705 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
706 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
710 pCodeInstruction pic16_pciBZ = { // mdubuc - New
711 {PC_OPCODE, NULL, NULL, 0, NULL,
724 0,0, // dest, bit instruction
726 0, // literal operand
728 0, // fast call/return mode select bit
729 0, // second memory operand
730 0, // second literal operand
737 pCodeInstruction pic16_pciCALL = {
738 {PC_OPCODE, NULL, NULL, 0, NULL,
751 0,0, // dest, bit instruction
753 0, // literal operand
755 1, // fast call/return mode select bit
756 0, // second memory operand
757 0, // second literal operand
760 PCC_NONE , // outCond
764 pCodeInstruction pic16_pciCOMF = {
765 {PC_OPCODE, NULL, NULL, 0, NULL,
778 1,0, // dest, bit instruction
780 0, // literal operand
782 0, // fast call/return mode select bit
783 0, // second memory operand
784 0, // second literal operand
786 PCC_REGISTER, // inCond
787 PCC_REGISTER , // outCond
791 pCodeInstruction pic16_pciCOMFW = {
792 {PC_OPCODE, NULL, NULL, 0, NULL,
805 0,0, // dest, bit instruction
807 0, // literal operand
809 0, // fast call/return mode select bit
810 0, // second memory operand
811 0, // second literal operand
813 PCC_REGISTER, // inCond
818 pCodeInstruction pic16_pciCLRF = {
819 {PC_OPCODE, NULL, NULL, 0, NULL,
832 0,0, // dest, bit instruction
834 0, // literal operand
836 0, // fast call/return mode select bit
837 0, // second memory operand
838 0, // second literal operand
840 PCC_REGISTER, // inCond
841 PCC_REGISTER , // outCond
845 pCodeInstruction pic16_pciCLRWDT = {
846 {PC_OPCODE, NULL, NULL, 0, NULL,
859 0,0, // dest, bit instruction
861 0, // literal operand
863 0, // fast call/return mode select bit
864 0, // second memory operand
865 0, // second literal operand
868 PCC_NONE , // outCond
872 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
873 {PC_OPCODE, NULL, NULL, 0, NULL,
886 0,0, // dest, bit instruction
888 0, // literal operand
890 0, // fast call/return mode select bit
891 0, // second memory operand
892 0, // second literal operand
894 (PCC_W | PCC_REGISTER), // inCond
895 PCC_NONE , // outCond
899 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
900 {PC_OPCODE, NULL, NULL, 0, NULL,
913 0,0, // dest, bit instruction
915 0, // literal operand
917 0, // fast call/return mode select bit
918 0, // second memory operand
919 0, // second literal operand
921 (PCC_W | PCC_REGISTER), // inCond
922 PCC_NONE , // outCond
926 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
927 {PC_OPCODE, NULL, NULL, 0, NULL,
940 1,0, // dest, bit instruction
942 0, // literal operand
944 0, // fast call/return mode select bit
945 0, // second memory operand
946 0, // second literal operand
948 (PCC_W | PCC_REGISTER), // inCond
949 PCC_NONE , // outCond
953 pCodeInstruction pic16_pciDAW = {
954 {PC_OPCODE, NULL, NULL, 0, NULL,
967 0,0, // dest, bit instruction
969 0, // literal operand
971 0, // fast call/return mode select bit
972 0, // second memory operand
973 0, // second literal operand
976 (PCC_W | PCC_C), // outCond
980 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
981 {PC_OPCODE, NULL, NULL, 0, NULL,
994 1,0, // dest, bit instruction
996 0, // literal operand
998 0, // fast call/return mode select bit
999 0, // second memory operand
1000 0, // second literal operand
1002 PCC_REGISTER, // inCond
1003 PCC_REGISTER , // outCond
1007 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1008 {PC_OPCODE, NULL, NULL, 0, NULL,
1014 NULL, // from branch
1021 0,0, // dest, bit instruction
1022 1,1, // branch, skip
1023 0, // literal operand
1024 1, // RAM access bit
1025 0, // fast call/return mode select bit
1026 0, // second memory operand
1027 0, // second literal operand
1029 PCC_REGISTER, // inCond
1034 pCodeInstruction pic16_pciDECF = {
1035 {PC_OPCODE, NULL, NULL, 0, NULL,
1041 NULL, // from branch
1048 1,0, // dest, bit instruction
1049 0,0, // branch, skip
1050 0, // literal operand
1051 1, // RAM access bit
1052 0, // fast call/return mode select bit
1053 0, // second memory operand
1054 0, // second literal operand
1056 PCC_REGISTER, // inCond
1057 PCC_REGISTER , // outCond
1061 pCodeInstruction pic16_pciDECFW = {
1062 {PC_OPCODE, NULL, NULL, 0, NULL,
1068 NULL, // from branch
1075 0,0, // dest, bit instruction
1076 0,0, // branch, skip
1077 0, // literal operand
1078 1, // RAM access bit
1079 0, // fast call/return mode select bit
1080 0, // second memory operand
1081 0, // second literal operand
1083 PCC_REGISTER, // inCond
1088 pCodeInstruction pic16_pciDECFSZ = {
1089 {PC_OPCODE, NULL, NULL, 0, NULL,
1095 NULL, // from branch
1102 1,0, // dest, bit instruction
1103 1,1, // branch, skip
1104 0, // literal operand
1105 1, // RAM access bit
1106 0, // fast call/return mode select bit
1107 0, // second memory operand
1108 0, // second literal operand
1110 PCC_REGISTER, // inCond
1111 PCC_REGISTER , // outCond
1115 pCodeInstruction pic16_pciDECFSZW = {
1116 {PC_OPCODE, NULL, NULL, 0, NULL,
1122 NULL, // from branch
1129 0,0, // dest, bit instruction
1130 1,1, // branch, skip
1131 0, // literal operand
1132 1, // RAM access bit
1133 0, // fast call/return mode select bit
1134 0, // second memory operand
1135 0, // second literal operand
1137 PCC_REGISTER, // inCond
1142 pCodeInstruction pic16_pciGOTO = {
1143 {PC_OPCODE, NULL, NULL, 0, NULL,
1149 NULL, // from branch
1156 0,0, // dest, bit instruction
1157 1,0, // branch, skip
1158 0, // literal operand
1159 0, // RAM access bit
1160 0, // fast call/return mode select bit
1161 0, // second memory operand
1162 0, // second literal operand
1164 PCC_REL_ADDR, // inCond
1165 PCC_NONE , // outCond
1169 pCodeInstruction pic16_pciINCF = {
1170 {PC_OPCODE, NULL, NULL, 0, NULL,
1176 NULL, // from branch
1183 1,0, // dest, bit instruction
1184 0,0, // branch, skip
1185 0, // literal operand
1186 1, // RAM access bit
1187 0, // fast call/return mode select bit
1188 0, // second memory operand
1189 0, // second literal operand
1191 PCC_REGISTER, // inCond
1192 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1196 pCodeInstruction pic16_pciINCFW = {
1197 {PC_OPCODE, NULL, NULL, 0, NULL,
1203 NULL, // from branch
1210 0,0, // dest, bit instruction
1211 0,0, // branch, skip
1212 0, // literal operand
1213 1, // RAM access bit
1214 0, // fast call/return mode select bit
1215 0, // second memory operand
1216 0, // second literal operand
1218 PCC_REGISTER, // inCond
1223 pCodeInstruction pic16_pciINCFSZ = {
1224 {PC_OPCODE, NULL, NULL, 0, NULL,
1230 NULL, // from branch
1237 1,0, // dest, bit instruction
1238 1,1, // branch, skip
1239 0, // literal operand
1240 1, // RAM access bit
1241 0, // fast call/return mode select bit
1242 0, // second memory operand
1243 0, // second literal operand
1245 PCC_REGISTER, // inCond
1246 PCC_REGISTER , // outCond
1250 pCodeInstruction pic16_pciINCFSZW = {
1251 {PC_OPCODE, NULL, NULL, 0, NULL,
1257 NULL, // from branch
1264 0,0, // dest, bit instruction
1265 1,1, // branch, skip
1266 0, // literal operand
1267 1, // RAM access bit
1268 0, // fast call/return mode select bit
1269 0, // second memory operand
1270 0, // second literal operand
1272 PCC_REGISTER, // inCond
1277 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1278 {PC_OPCODE, NULL, NULL, 0, NULL,
1284 NULL, // from branch
1291 1,0, // dest, bit instruction
1292 1,1, // branch, skip
1293 0, // literal operand
1294 1, // RAM access bit
1295 0, // fast call/return mode select bit
1296 0, // second memory operand
1297 0, // second literal operand
1299 PCC_REGISTER, // inCond
1300 PCC_REGISTER , // outCond
1304 pCodeInstruction pic16_pciIORWF = {
1305 {PC_OPCODE, NULL, NULL, 0, NULL,
1311 NULL, // from branch
1318 1,0, // dest, bit instruction
1319 0,0, // branch, skip
1320 0, // literal operand
1321 1, // RAM access bit
1322 0, // fast call/return mode select bit
1323 0, // second memory operand
1324 0, // second literal operand
1326 (PCC_W | PCC_REGISTER), // inCond
1327 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1331 pCodeInstruction pic16_pciIORFW = {
1332 {PC_OPCODE, NULL, NULL, 0, NULL,
1338 NULL, // from branch
1345 0,0, // dest, bit instruction
1346 0,0, // branch, skip
1347 0, // literal operand
1348 1, // RAM access bit
1349 0, // fast call/return mode select bit
1350 0, // second memory operand
1351 0, // second literal operand
1353 (PCC_W | PCC_REGISTER), // inCond
1354 (PCC_W | PCC_Z | PCC_N), // outCond
1358 pCodeInstruction pic16_pciIORLW = {
1359 {PC_OPCODE, NULL, NULL, 0, NULL,
1365 NULL, // from branch
1372 0,0, // dest, bit instruction
1373 0,0, // branch, skip
1374 1, // literal operand
1375 0, // RAM access bit
1376 0, // fast call/return mode select bit
1377 0, // second memory operand
1378 0, // second literal operand
1380 (PCC_W | PCC_LITERAL), // inCond
1381 (PCC_W | PCC_Z | PCC_N), // outCond
1385 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1386 {PC_OPCODE, NULL, NULL, 0, NULL,
1392 NULL, // from branch
1399 0,0, // dest, bit instruction
1400 0,0, // branch, skip
1401 1, // literal operand
1402 0, // RAM access bit
1403 0, // fast call/return mode select bit
1404 0, // second memory operand
1405 1, // second literal operand
1407 (PCC_REGISTER | PCC_LITERAL),
1408 PCC_REGISTER, // outCond
1412 pCodeInstruction pic16_pciMOVF = {
1413 {PC_OPCODE, NULL, NULL, 0, NULL,
1419 NULL, // from branch
1426 1,0, // dest, bit instruction
1427 0,0, // branch, skip
1428 0, // literal operand
1429 1, // RAM access bit
1430 0, // fast call/return mode select bit
1431 0, // second memory operand
1432 0, // second literal operand
1434 PCC_REGISTER, // inCond
1435 (PCC_Z | PCC_N), // outCond
1439 pCodeInstruction pic16_pciMOVFW = {
1440 {PC_OPCODE, NULL, NULL, 0, NULL,
1446 NULL, // from branch
1453 0,0, // dest, bit instruction
1454 0,0, // branch, skip
1455 0, // literal operand
1456 1, // RAM access bit
1457 0, // fast call/return mode select bit
1458 0, // second memory operand
1459 0, // second literal operand
1461 PCC_REGISTER, // inCond
1462 (PCC_W | PCC_Z), // outCond
1466 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1467 {PC_OPCODE, NULL, NULL, 0, NULL,
1473 NULL, // from branch
1480 0,0, // dest, bit instruction
1481 0,0, // branch, skip
1482 0, // literal operand
1483 0, // RAM access bit
1484 0, // fast call/return mode select bit
1485 1, // second memory operand
1486 0, // second literal operand
1488 PCC_REGISTER, // inCond
1489 PCC_REGISTER2, // outCond
1493 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1494 {PC_OPCODE, NULL, NULL, 0, NULL,
1499 NULL, // from branch
1506 0,0, // dest, bit instruction
1507 0,0, // branch, skip
1508 1, // literal operand
1509 0, // RAM access bit
1510 0, // fast call/return mode select bit
1511 0, // second memory operand
1512 0, // second literal operand
1514 (PCC_NONE | PCC_LITERAL), // inCond
1515 PCC_REGISTER, // outCond - BSR
1519 pCodeInstruction pic16_pciMOVLW = {
1520 {PC_OPCODE, NULL, NULL, 0, NULL,
1525 NULL, // from branch
1532 0,0, // dest, bit instruction
1533 0,0, // branch, skip
1534 1, // literal operand
1535 0, // RAM access bit
1536 0, // fast call/return mode select bit
1537 0, // second memory operand
1538 0, // second literal operand
1540 (PCC_NONE | PCC_LITERAL), // inCond
1545 pCodeInstruction pic16_pciMOVWF = {
1546 {PC_OPCODE, NULL, NULL, 0, NULL,
1552 NULL, // from branch
1559 0,0, // dest, bit instruction
1560 0,0, // branch, skip
1561 0, // literal operand
1562 1, // RAM access bit
1563 0, // fast call/return mode select bit
1564 0, // second memory operand
1565 0, // second literal operand
1567 PCC_REGISTER, // inCond
1572 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1573 {PC_OPCODE, NULL, NULL, 0, NULL,
1578 NULL, // from branch
1585 0,0, // dest, bit instruction
1586 0,0, // branch, skip
1587 1, // literal operand
1588 0, // RAM access bit
1589 0, // fast call/return mode select bit
1590 0, // second memory operand
1591 0, // second literal operand
1593 (PCC_W | PCC_LITERAL), // inCond
1594 PCC_REGISTER, // outCond - PROD
1598 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1599 {PC_OPCODE, NULL, NULL, 0, NULL,
1604 NULL, // from branch
1611 0,0, // dest, bit instruction
1612 0,0, // branch, skip
1613 0, // literal operand
1614 1, // RAM access bit
1615 0, // fast call/return mode select bit
1616 0, // second memory operand
1617 0, // second literal operand
1619 (PCC_W | PCC_REGISTER), // inCond
1620 PCC_REGISTER, // outCond - PROD
1624 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1625 {PC_OPCODE, NULL, NULL, 0, NULL,
1630 NULL, // from branch
1637 0,0, // dest, bit instruction
1638 0,0, // branch, skip
1639 0, // literal operand
1640 1, // RAM access bit
1641 0, // fast call/return mode select bit
1642 0, // second memory operand
1643 0, // second literal operand
1645 PCC_REGISTER, // inCond
1646 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1650 pCodeInstruction pic16_pciNOP = {
1651 {PC_OPCODE, NULL, NULL, 0, NULL,
1656 NULL, // from branch
1663 0,0, // dest, bit instruction
1664 0,0, // branch, skip
1665 0, // literal operand
1666 0, // RAM access bit
1667 0, // fast call/return mode select bit
1668 0, // second memory operand
1669 0, // second literal operand
1672 PCC_NONE, // outCond
1676 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1677 {PC_OPCODE, NULL, NULL, 0, NULL,
1682 NULL, // from branch
1689 0,0, // dest, bit instruction
1690 0,0, // branch, skip
1691 0, // literal operand
1692 0, // RAM access bit
1693 0, // fast call/return mode select bit
1694 0, // second memory operand
1695 0, // second literal operand
1698 PCC_NONE , // outCond
1702 pCodeInstruction pic16_pciPUSH = {
1703 {PC_OPCODE, NULL, NULL, 0, NULL,
1708 NULL, // from branch
1715 0,0, // dest, bit instruction
1716 0,0, // branch, skip
1717 0, // literal operand
1718 0, // RAM access bit
1719 0, // fast call/return mode select bit
1720 0, // second memory operand
1721 0, // second literal operand
1724 PCC_NONE , // outCond
1728 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1729 {PC_OPCODE, NULL, NULL, 0, NULL,
1734 NULL, // from branch
1741 0,0, // dest, bit instruction
1742 0,0, // branch, skip
1743 0, // literal operand
1744 0, // RAM access bit
1745 0, // fast call/return mode select bit
1746 0, // second memory operand
1747 0, // second literal operand
1749 PCC_REL_ADDR, // inCond
1750 PCC_NONE , // outCond
1754 pCodeInstruction pic16_pciRETFIE = {
1755 {PC_OPCODE, NULL, NULL, 0, NULL,
1761 NULL, // from branch
1768 0,0, // dest, bit instruction
1769 1,0, // branch, skip
1770 0, // literal operand
1771 0, // RAM access bit
1772 1, // fast call/return mode select bit
1773 0, // second memory operand
1774 0, // second literal operand
1777 PCC_NONE, // outCond (not true... affects the GIE bit too)
1781 pCodeInstruction pic16_pciRETLW = {
1782 {PC_OPCODE, NULL, NULL, 0, NULL,
1788 NULL, // from branch
1795 0,0, // dest, bit instruction
1796 1,0, // branch, skip
1797 1, // literal operand
1798 0, // RAM access bit
1799 0, // fast call/return mode select bit
1800 0, // second memory operand
1801 0, // second literal operand
1803 PCC_LITERAL, // inCond
1808 pCodeInstruction pic16_pciRETURN = {
1809 {PC_OPCODE, NULL, NULL, 0, NULL,
1815 NULL, // from branch
1822 0,0, // dest, bit instruction
1823 1,0, // branch, skip
1824 0, // literal operand
1825 0, // RAM access bit
1826 1, // fast call/return mode select bit
1827 0, // second memory operand
1828 0, // second literal operand
1831 PCC_NONE, // outCond
1834 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1835 {PC_OPCODE, NULL, NULL, 0, NULL,
1841 NULL, // from branch
1848 1,0, // dest, bit instruction
1849 0,0, // branch, skip
1850 0, // literal operand
1851 1, // RAM access bit
1852 0, // fast call/return mode select bit
1853 0, // second memory operand
1854 0, // second literal operand
1856 (PCC_C | PCC_REGISTER), // inCond
1857 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1861 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1862 {PC_OPCODE, NULL, NULL, 0, NULL,
1868 NULL, // from branch
1875 0,0, // dest, bit instruction
1876 0,0, // branch, skip
1877 0, // literal operand
1878 1, // RAM access bit
1879 0, // fast call/return mode select bit
1880 0, // second memory operand
1881 0, // second literal operand
1883 (PCC_C | PCC_REGISTER), // inCond
1884 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1888 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1889 {PC_OPCODE, NULL, NULL, 0, NULL,
1895 NULL, // from branch
1902 1,0, // dest, bit instruction
1903 0,0, // branch, skip
1904 0, // literal operand
1905 1, // RAM access bit
1906 0, // fast call/return mode select bit
1907 0, // second memory operand
1908 0, // second literal operand
1910 PCC_REGISTER, // inCond
1911 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1914 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1915 {PC_OPCODE, NULL, NULL, 0, NULL,
1921 NULL, // from branch
1928 0,0, // dest, bit instruction
1929 0,0, // branch, skip
1930 0, // literal operand
1931 1, // RAM access bit
1932 0, // fast call/return mode select bit
1933 0, // second memory operand
1934 0, // second literal operand
1936 PCC_REGISTER, // inCond
1937 (PCC_W | PCC_Z | PCC_N), // outCond
1940 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1941 {PC_OPCODE, NULL, NULL, 0, NULL,
1947 NULL, // from branch
1954 1,0, // dest, bit instruction
1955 0,0, // branch, skip
1956 0, // literal operand
1957 1, // RAM access bit
1958 0, // fast call/return mode select bit
1959 0, // second memory operand
1960 0, // second literal operand
1962 (PCC_C | PCC_REGISTER), // inCond
1963 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1966 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1967 {PC_OPCODE, NULL, NULL, 0, NULL,
1973 NULL, // from branch
1980 0,0, // dest, bit instruction
1981 0,0, // branch, skip
1982 0, // literal operand
1983 1, // RAM access bit
1984 0, // fast call/return mode select bit
1985 0, // second memory operand
1986 0, // second literal operand
1988 (PCC_C | PCC_REGISTER), // inCond
1989 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1992 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
1993 {PC_OPCODE, NULL, NULL, 0, NULL,
1999 NULL, // from branch
2006 1,0, // dest, bit instruction
2007 0,0, // branch, skip
2008 0, // literal operand
2009 1, // RAM access bit
2010 0, // fast call/return mode select bit
2011 0, // second memory operand
2012 0, // second literal operand
2014 PCC_REGISTER, // inCond
2015 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2019 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2020 {PC_OPCODE, NULL, NULL, 0, NULL,
2026 NULL, // from branch
2033 0,0, // dest, bit instruction
2034 0,0, // branch, skip
2035 0, // literal operand
2036 1, // RAM access bit
2037 0, // fast call/return mode select bit
2038 0, // second memory operand
2039 0, // second literal operand
2041 PCC_REGISTER, // inCond
2042 (PCC_W | PCC_Z | PCC_N), // outCond
2046 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2047 {PC_OPCODE, NULL, NULL, 0, NULL,
2053 NULL, // from branch
2060 0,0, // dest, bit instruction
2061 0,0, // branch, skip
2062 0, // literal operand
2063 1, // RAM access bit
2064 0, // fast call/return mode select bit
2065 0, // second memory operand
2066 0, // second literal operand
2068 PCC_REGISTER, // inCond
2069 PCC_REGISTER , // outCond
2073 pCodeInstruction pic16_pciSUBLW = {
2074 {PC_OPCODE, NULL, NULL, 0, NULL,
2080 NULL, // from branch
2087 0,0, // dest, bit instruction
2088 0,0, // branch, skip
2089 1, // literal operand
2090 0, // RAM access bit
2091 0, // fast call/return mode select bit
2092 0, // second memory operand
2093 0, // second literal operand
2095 (PCC_W | PCC_LITERAL), // inCond
2096 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2100 pCodeInstruction pic16_pciSUBFWB = {
2101 {PC_OPCODE, NULL, NULL, 0, NULL,
2107 NULL, // from branch
2114 1,0, // dest, bit instruction
2115 0,0, // branch, skip
2116 0, // literal operand
2117 1, // RAM access bit
2118 0, // fast call/return mode select bit
2119 0, // second memory operand
2120 0, // second literal operand
2122 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2123 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2127 pCodeInstruction pic16_pciSUBWF = {
2128 {PC_OPCODE, NULL, NULL, 0, NULL,
2134 NULL, // from branch
2141 1,0, // dest, bit instruction
2142 0,0, // branch, skip
2143 0, // literal operand
2144 1, // RAM access bit
2145 0, // fast call/return mode select bit
2146 0, // second memory operand
2147 0, // second literal operand
2149 (PCC_W | PCC_REGISTER), // inCond
2150 (PCC_REGISTER | PCC_Z), // outCond
2154 pCodeInstruction pic16_pciSUBFW = {
2155 {PC_OPCODE, NULL, NULL, 0, NULL,
2161 NULL, // from branch
2168 0,0, // dest, bit instruction
2169 0,0, // branch, skip
2170 0, // literal operand
2171 1, // RAM access bit
2172 0, // fast call/return mode select bit
2173 0, // second memory operand
2174 0, // second literal operand
2176 (PCC_W | PCC_REGISTER), // inCond
2177 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2181 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2182 {PC_OPCODE, NULL, NULL, 0, NULL,
2188 NULL, // from branch
2195 1,0, // dest, bit instruction
2196 0,0, // branch, skip
2197 0, // literal operand
2198 1, // RAM access bit
2199 0, // fast call/return mode select bit
2200 0, // second memory operand
2201 0, // second literal operand
2203 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2204 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2208 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2209 {PC_OPCODE, NULL, NULL, 0, NULL,
2215 NULL, // from branch
2222 0,0, // dest, bit instruction
2223 0,0, // branch, skip
2224 0, // literal operand
2225 1, // RAM access bit
2226 0, // fast call/return mode select bit
2227 0, // second memory operand
2228 0, // second literal operand
2230 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2231 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2235 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2236 {PC_OPCODE, NULL, NULL, 0, NULL,
2242 NULL, // from branch
2249 1,0, // dest, bit instruction
2250 0,0, // branch, skip
2251 0, // literal operand
2252 1, // RAM access bit
2253 0, // fast call/return mode select bit
2254 0, // second memory operand
2255 0, // second literal operand
2257 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2258 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2262 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2263 {PC_OPCODE, NULL, NULL, 0, NULL,
2269 NULL, // from branch
2276 0,0, // dest, bit instruction
2277 0,0, // branch, skip
2278 0, // literal operand
2279 1, // RAM access bit
2280 0, // fast call/return mode select bit
2281 0, // second memory operand
2282 0, // second literal operand
2284 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2285 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2289 pCodeInstruction pic16_pciSWAPF = {
2290 {PC_OPCODE, NULL, NULL, 0, NULL,
2296 NULL, // from branch
2303 1,0, // dest, bit instruction
2304 0,0, // branch, skip
2305 0, // literal operand
2306 1, // RAM access bit
2307 0, // fast call/return mode select bit
2308 0, // second memory operand
2309 0, // second literal operand
2311 (PCC_REGISTER), // inCond
2312 (PCC_REGISTER), // outCond
2316 pCodeInstruction pic16_pciSWAPFW = {
2317 {PC_OPCODE, NULL, NULL, 0, NULL,
2323 NULL, // from branch
2330 0,0, // dest, bit instruction
2331 0,0, // branch, skip
2332 0, // literal operand
2333 1, // RAM access bit
2334 0, // fast call/return mode select bit
2335 0, // second memory operand
2336 0, // second literal operand
2338 (PCC_REGISTER), // inCond
2343 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2344 {PC_OPCODE, NULL, NULL, 0, NULL,
2350 NULL, // from branch
2357 0,0, // dest, bit instruction
2358 1,1, // branch, skip
2359 0, // literal operand
2360 1, // RAM access bit
2361 0, // fast call/return mode select bit
2362 0, // second memory operand
2363 0, // second literal operand
2365 PCC_REGISTER, // inCond
2366 PCC_NONE, // outCond
2370 pCodeInstruction pic16_pciXORWF = {
2371 {PC_OPCODE, NULL, NULL, 0, NULL,
2377 NULL, // from branch
2384 1,0, // dest, bit instruction
2385 0,0, // branch, skip
2386 0, // literal operand
2387 1, // RAM access bit
2388 0, // fast call/return mode select bit
2389 0, // second memory operand
2390 0, // second literal operand
2392 (PCC_W | PCC_REGISTER), // inCond
2393 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2397 pCodeInstruction pic16_pciXORFW = {
2398 {PC_OPCODE, NULL, NULL, 0, NULL,
2404 NULL, // from branch
2411 0,0, // dest, bit instruction
2412 0,0, // branch, skip
2413 0, // literal operand
2414 1, // RAM access bit
2415 0, // fast call/return mode select bit
2416 0, // second memory operand
2417 0, // second literal operand
2419 (PCC_W | PCC_REGISTER), // inCond
2420 (PCC_W | PCC_Z | PCC_N), // outCond
2424 pCodeInstruction pic16_pciXORLW = {
2425 {PC_OPCODE, NULL, NULL, 0, NULL,
2431 NULL, // from branch
2438 0,0, // dest, bit instruction
2439 0,0, // branch, skip
2440 1, // literal operand
2441 1, // RAM access bit
2442 0, // fast call/return mode select bit
2443 0, // second memory operand
2444 0, // second literal operand
2446 (PCC_W | PCC_LITERAL), // inCond
2447 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2452 #define MAX_PIC16MNEMONICS 100
2453 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2456 /* This definition needs to be part of configure.in */
2457 // #define USE_VSNPRINTF
2459 #ifdef USE_VSNPRINTF
2460 // Alas, vsnprintf is not ANSI standard, and does not exist
2461 // on Solaris (and probably other non-Gnu flavored Unixes).
2463 /*-----------------------------------------------------------------*/
2464 /* SAFE_snprintf - like snprintf except the string pointer is */
2465 /* after the string has been printed to. This is */
2466 /* useful for printing to string as though if it */
2467 /* were a stream. */
2468 /*-----------------------------------------------------------------*/
2469 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2477 va_start(val, format);
2479 vsnprintf(*str, *size, format, val);
2485 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2486 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2494 #else // USE_VSNPRINTF
2496 // This version is *not* safe, despite the name.
2498 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2502 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2507 va_start(val, format);
2509 vsprintf(buffer, format, val);
2512 len = strlen(buffer);
2514 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2515 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2518 strcpy(*str, buffer);
2524 #endif // USE_VSNPRINTF
2526 #endif // OPT_DISABLE_PIC
2529 extern void pic16_initStack(int base_address, int size);
2530 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2531 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2532 extern void pic16_init_pic(char *);
2534 void pic16_pCodeInitRegisters(void)
2536 static int initialized=0;
2543 pic16_initStack(0xfff, 8);
2544 pic16_init_pic(port->processor);
2546 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2547 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2548 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2549 pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80);
2550 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2551 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2552 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2554 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2555 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2556 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2557 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2558 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_FSR0, 0x80);
2559 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_FSR0, 0x80);
2560 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_FSR0, 0x80);
2562 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_FSR0, 0x80);
2563 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_FSR0, 0x80);
2565 pic16_pc_status.rIdx = IDX_STATUS;
2566 pic16_pc_fsr0.rIdx = IDX_FSR0;
2567 pic16_pc_indf0.rIdx = IDX_INDF0;
2568 pic16_pc_intcon.rIdx = IDX_INTCON;
2569 pic16_pc_pcl.rIdx = IDX_PCL;
2570 pic16_pc_pclath.rIdx = IDX_PCLATH;
2571 pic16_pc_wreg.rIdx = IDX_WREG;
2572 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2573 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2574 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2575 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2576 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2577 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2578 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2579 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2580 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2582 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2583 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
2584 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2586 pic16_pc_kzero.rIdx = IDX_KZ;
2587 pic16_pc_wsave.rIdx = IDX_WSAVE;
2588 pic16_pc_ssave.rIdx = IDX_SSAVE;
2590 /* probably should put this in a separate initialization routine */
2591 pb_dead_pcodes = newpBlock();
2596 /*-----------------------------------------------------------------*/
2597 /* mnem2key - convert a pic mnemonic into a hash key */
2598 /* (BTW - this spreads the mnemonics quite well) */
2600 /*-----------------------------------------------------------------*/
2602 int mnem2key(char const *mnem)
2611 key += toupper(*mnem++) +1;
2615 return (key & 0x1f);
2618 #endif // OPT_DISABLE_PIC
2620 void pic16initMnemonics(void)
2625 pCodeInstruction *pci;
2627 if(mnemonics_initialized)
2630 // NULL out the array before making the assignments
2631 // since we check the array contents below this initialization.
2633 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2634 pic16Mnemonics[i] = NULL;
2637 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2638 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2639 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2640 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2641 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2642 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2643 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2644 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2645 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2646 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2647 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2648 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2649 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2650 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2651 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2652 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2653 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2654 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2655 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2656 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2657 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2658 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2659 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2660 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2661 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2662 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2663 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2664 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2665 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2666 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2667 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2668 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2669 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2670 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2671 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2672 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2673 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2674 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2675 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2676 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2677 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2678 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2679 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2680 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2681 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2682 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2683 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2684 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2685 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2686 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2687 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2688 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2689 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2690 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2691 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2692 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2693 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2694 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2695 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2696 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2697 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2698 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2699 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2700 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2701 pic16Mnemonics[POC_RLCF] = &pic16_pciRLNCF;
2702 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2703 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2704 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2705 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2706 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2707 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2708 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2709 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2710 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2711 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2712 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2713 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2714 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2715 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2716 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
2717 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
2718 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
2719 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
2720 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
2722 for(i=0; i<MAX_PIC16MNEMONICS; i++)
2723 if(pic16Mnemonics[i])
2724 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
2725 pci = hTabFirstItem(pic16MnemonicsHash, &key);
2728 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
2729 pci = hTabNextItem(pic16MnemonicsHash, &key);
2732 mnemonics_initialized = 1;
2735 int pic16_getpCodePeepCommand(char *cmd);
2737 int pic16_getpCode(char *mnem,unsigned dest)
2740 pCodeInstruction *pci;
2741 int key = mnem2key(mnem);
2743 if(!mnemonics_initialized)
2744 pic16initMnemonics();
2746 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
2750 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
2751 if((pci->num_ops <= 1)
2752 || (pci->isModReg == dest)
2754 || (pci->num_ops <= 2 && pci->isAccess)
2755 || (pci->num_ops <= 2 && pci->isFastCall)
2756 || (pci->num_ops <= 2 && pci->is2MemOp)
2757 || (pci->num_ops <= 2 && pci->is2LitOp) )
2761 pci = hTabNextItemWK (pic16MnemonicsHash);
2768 /*-----------------------------------------------------------------*
2769 * pic16initpCodePeepCommands
2771 *-----------------------------------------------------------------*/
2772 void pic16initpCodePeepCommands(void)
2780 hTabAddItem(&pic16pCodePeepCommandsHash,
2781 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
2783 } while (peepCommands[i].cmd);
2785 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
2788 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
2789 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
2794 /*-----------------------------------------------------------------
2797 *-----------------------------------------------------------------*/
2799 int pic16_getpCodePeepCommand(char *cmd)
2803 int key = mnem2key(cmd);
2806 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
2809 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2810 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2814 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
2821 static char getpBlock_dbName(pBlock *pb)
2827 return pb->cmemmap->dbName;
2831 void pic16_pBlockConvert2ISR(pBlock *pb)
2842 void pic16_pBlockConvert2Absolute(pBlock *pb)
2845 if(pb->cmemmap)pb->cmemmap = NULL;
2850 /*-----------------------------------------------------------------*/
2851 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
2852 /* instances to the front of the doubly linked */
2853 /* list of pBlocks */
2854 /*-----------------------------------------------------------------*/
2856 void pic16_movepBlock2Head(char dbName)
2861 /* this can happen in sources without code,
2862 * only variable definitions */
2863 if(!the_pFile)return;
2865 pb = the_pFile->pbHead;
2869 if(getpBlock_dbName(pb) == dbName) {
2870 pBlock *pbn = pb->next;
2871 pb->next = the_pFile->pbHead;
2872 the_pFile->pbHead->prev = pb;
2873 the_pFile->pbHead = pb;
2876 pb->prev->next = pbn;
2878 // If the pBlock that we just moved was the last
2879 // one in the link of all of the pBlocks, then we
2880 // need to point the tail to the block just before
2881 // the one we moved.
2882 // Note: if pb->next is NULL, then pb must have
2883 // been the last pBlock in the chain.
2886 pbn->prev = pb->prev;
2888 the_pFile->pbTail = pb->prev;
2899 void pic16_copypCode(FILE *of, char dbName)
2903 if(!of || !the_pFile)
2906 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2907 if(getpBlock_dbName(pb) == dbName) {
2908 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
2910 pic16_printpBlock(of,pb);
2915 void pic16_pcode_test(void)
2918 DFPRINTF((stderr,"pcode is alive!\n"));
2928 /* create the file name */
2929 strcpy(buffer,dstFileName);
2930 strcat(buffer,".p");
2932 if( !(pFile = fopen(buffer, "w" ))) {
2933 werror(E_FILE_OPEN_ERR,buffer);
2937 fprintf(pFile,"pcode dump\n\n");
2939 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2940 fprintf(pFile,"\n\tNew pBlock\n\n");
2942 fprintf(pFile,"%s",pb->cmemmap->sname);
2944 fprintf(pFile,"internal pblock");
2946 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2947 pic16_printpBlock(pFile,pb);
2951 /*-----------------------------------------------------------------*/
2952 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
2953 /* ister, RegCond will return the bit being referenced. */
2955 /* fixme - why not just OR in the pcop bit field */
2956 /*-----------------------------------------------------------------*/
2958 static int RegCond(pCodeOp *pcop)
2964 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
2965 switch(PCORB(pcop)->bit) {
2979 /*-----------------------------------------------------------------*/
2980 /* pic16_newpCode - create and return a newly initialized pCode */
2982 /* fixme - rename this */
2984 /* The purpose of this routine is to create a new Instruction */
2985 /* pCode. This is called by gen.c while the assembly code is being */
2989 /* PIC_OPCODE op - the assembly instruction we wish to create. */
2990 /* (note that the op is analogous to but not the */
2991 /* same thing as the opcode of the instruction.) */
2992 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
2995 /* a pointer to the new malloc'd pCode is returned. */
2999 /*-----------------------------------------------------------------*/
3000 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3002 pCodeInstruction *pci ;
3004 if(!mnemonics_initialized)
3005 pic16initMnemonics();
3007 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3009 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3010 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3013 if(pci->inCond & PCC_EXAMINE_PCOP)
3014 pci->inCond |= RegCond(pcop);
3016 if(pci->outCond & PCC_EXAMINE_PCOP)
3017 pci->outCond |= RegCond(pcop);
3019 pci->pc.prev = pci->pc.next = NULL;
3020 return (pCode *)pci;
3023 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3029 /*-----------------------------------------------------------------*/
3030 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3032 /* Wild pcodes are used during the peep hole optimizer to serve */
3033 /* as place holders for any instruction. When a snippet of code is */
3034 /* compared to a peep hole rule, the wild card opcode will match */
3035 /* any instruction. However, the optional operand and label are */
3036 /* additional qualifiers that must also be matched before the */
3037 /* line (of assembly code) is declared matched. Note that the */
3038 /* operand may be wild too. */
3040 /* Note, a wild instruction is specified just like a wild var: */
3041 /* %4 ; A wild instruction, */
3042 /* See the peeph.def file for additional examples */
3044 /*-----------------------------------------------------------------*/
3046 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3051 pcw = Safe_calloc(1,sizeof(pCodeWild));
3053 pcw->pci.pc.type = PC_WILD;
3054 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3055 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3056 pcw->pci.pc.pb = NULL;
3058 // pcw->pci.pc.analyze = genericAnalyze;
3059 pcw->pci.pc.destruct = genericDestruct;
3060 pcw->pci.pc.print = genericPrint;
3062 pcw->id = pCodeID; // this is the 'n' in %n
3063 pcw->operand = optional_operand;
3064 pcw->label = optional_label;
3066 pcw->mustBeBitSkipInst = 0;
3067 pcw->mustNotBeBitSkipInst = 0;
3068 pcw->invertBitSkipInst = 0;
3070 return ( (pCode *)pcw);
3074 /*-----------------------------------------------------------------*/
3075 /* newPcodeInlineP - create a new pCode from a char string */
3076 /*-----------------------------------------------------------------*/
3079 pCode *pic16_newpCodeInlineP(char *cP)
3084 pcc = Safe_calloc(1,sizeof(pCodeComment));
3086 pcc->pc.type = PC_INLINE;
3087 pcc->pc.prev = pcc->pc.next = NULL;
3088 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3091 // pcc->pc.analyze = genericAnalyze;
3092 pcc->pc.destruct = genericDestruct;
3093 pcc->pc.print = genericPrint;
3096 pcc->comment = Safe_strdup(cP);
3098 pcc->comment = NULL;
3100 return ( (pCode *)pcc);
3104 /*-----------------------------------------------------------------*/
3105 /* newPcodeCharP - create a new pCode from a char string */
3106 /*-----------------------------------------------------------------*/
3108 pCode *pic16_newpCodeCharP(char *cP)
3113 pcc = Safe_calloc(1,sizeof(pCodeComment));
3115 pcc->pc.type = PC_COMMENT;
3116 pcc->pc.prev = pcc->pc.next = NULL;
3117 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3120 // pcc->pc.analyze = genericAnalyze;
3121 pcc->pc.destruct = genericDestruct;
3122 pcc->pc.print = genericPrint;
3125 pcc->comment = Safe_strdup(cP);
3127 pcc->comment = NULL;
3129 return ( (pCode *)pcc);
3133 /*-----------------------------------------------------------------*/
3134 /* pic16_newpCodeFunction - */
3135 /*-----------------------------------------------------------------*/
3138 pCode *pic16_newpCodeFunction(char *mod,char *f)
3142 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3144 pcf->pc.type = PC_FUNCTION;
3145 pcf->pc.prev = pcf->pc.next = NULL;
3146 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3149 // pcf->pc.analyze = genericAnalyze;
3150 pcf->pc.destruct = genericDestruct;
3151 pcf->pc.print = pCodePrintFunction;
3156 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3157 strcpy(pcf->modname,mod);
3159 pcf->modname = NULL;
3162 pcf->fname = Safe_calloc(1,strlen(f)+1);
3163 strcpy(pcf->fname,f);
3167 return ( (pCode *)pcf);
3171 /*-----------------------------------------------------------------*/
3172 /* pic16_newpCodeFlow */
3173 /*-----------------------------------------------------------------*/
3174 static void destructpCodeFlow(pCode *pc)
3176 if(!pc || !isPCFL(pc))
3183 pic16_unlinkpCode(pc);
3185 deleteSet(&PCFL(pc)->registers);
3186 deleteSet(&PCFL(pc)->from);
3187 deleteSet(&PCFL(pc)->to);
3192 pCode *pic16_newpCodeFlow(void )
3196 //_ALLOC(pcflow,sizeof(pCodeFlow));
3197 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3199 pcflow->pc.type = PC_FLOW;
3200 pcflow->pc.prev = pcflow->pc.next = NULL;
3201 pcflow->pc.pb = NULL;
3203 // pcflow->pc.analyze = genericAnalyze;
3204 pcflow->pc.destruct = destructpCodeFlow;
3205 pcflow->pc.print = genericPrint;
3207 pcflow->pc.seq = GpcFlowSeq++;
3209 pcflow->from = pcflow->to = NULL;
3211 pcflow->inCond = PCC_NONE;
3212 pcflow->outCond = PCC_NONE;
3214 pcflow->firstBank = -1;
3215 pcflow->lastBank = -1;
3217 pcflow->FromConflicts = 0;
3218 pcflow->ToConflicts = 0;
3222 pcflow->registers = newSet();
3224 return ( (pCode *)pcflow);
3228 /*-----------------------------------------------------------------*/
3229 /*-----------------------------------------------------------------*/
3230 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3232 pCodeFlowLink *pcflowLink;
3234 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3236 pcflowLink->pcflow = pcflow;
3237 pcflowLink->bank_conflict = 0;
3242 /*-----------------------------------------------------------------*/
3243 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3244 /*-----------------------------------------------------------------*/
3246 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3251 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3253 pccs->pc.type = PC_CSOURCE;
3254 pccs->pc.prev = pccs->pc.next = NULL;
3257 pccs->pc.destruct = genericDestruct;
3258 pccs->pc.print = genericPrint;
3260 pccs->line_number = ln;
3262 pccs->line = Safe_strdup(l);
3267 pccs->file_name = Safe_strdup(f);
3269 pccs->file_name = NULL;
3271 return ( (pCode *)pccs);
3276 /*******************************************************************/
3277 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3278 /* added by VR 6-Jun-2003 */
3279 /*******************************************************************/
3281 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3288 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3289 pcad->pc.type = PC_ASMDIR;
3290 pcad->pc.prev = pcad->pc.next = NULL;
3293 pcad->pc.destruct = genericDestruct;
3294 pcad->pc.print = genericPrint;
3296 if(asdir && *asdir) {
3298 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3300 pcad->directive = Safe_strdup( asdir );
3303 va_start(ap, argfmt);
3305 memset(buffer, 0, sizeof(buffer));
3306 if(argfmt && *argfmt)
3307 vsprintf(buffer, argfmt, ap);
3311 while(isspace(*lbp))lbp++;
3314 pcad->arg = Safe_strdup( lbp );
3316 return ((pCode *)pcad);
3319 /*-----------------------------------------------------------------*/
3320 /* pCodeLabelDestruct - free memory used by a label. */
3321 /*-----------------------------------------------------------------*/
3322 static void pCodeLabelDestruct(pCode *pc)
3328 if((pc->type == PC_LABEL) && PCL(pc)->label)
3329 free(PCL(pc)->label);
3335 pCode *pic16_newpCodeLabel(char *name, int key)
3341 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3343 pcl->pc.type = PC_LABEL;
3344 pcl->pc.prev = pcl->pc.next = NULL;
3345 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3348 // pcl->pc.analyze = genericAnalyze;
3349 pcl->pc.destruct = pCodeLabelDestruct;
3350 pcl->pc.print = pCodePrintLabel;
3356 sprintf(s,"_%05d_DS_",key);
3361 pcl->label = Safe_strdup(s);
3363 return ( (pCode *)pcl);
3368 /*-----------------------------------------------------------------*/
3369 /* newpBlock - create and return a pointer to a new pBlock */
3370 /*-----------------------------------------------------------------*/
3371 static pBlock *newpBlock(void)
3376 PpB = Safe_calloc(1,sizeof(pBlock) );
3377 PpB->next = PpB->prev = NULL;
3379 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3380 PpB->tregisters = NULL;
3382 PpB->FlowTree = NULL;
3388 /*-----------------------------------------------------------------*/
3389 /* pic16_newpCodeChain - create a new chain of pCodes */
3390 /*-----------------------------------------------------------------*
3392 * This function will create a new pBlock and the pointer to the
3393 * pCode that is passed in will be the first pCode in the block.
3394 *-----------------------------------------------------------------*/
3397 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3400 pBlock *pB = newpBlock();
3402 pB->pcHead = pB->pcTail = pc;
3409 /*-----------------------------------------------------------------*/
3410 /* pic16_newpCodeOpLabel - Create a new label given the key */
3411 /* Note, a negative key means that the label is part of wild card */
3412 /* (and hence a wild card label) used in the pCodePeep */
3413 /* optimizations). */
3414 /*-----------------------------------------------------------------*/
3416 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3419 static int label_key=-1;
3423 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3424 pcop->type = PO_LABEL;
3429 sprintf(s=buffer,"_%05d_DS_",key);
3431 s = name, key = label_key--;
3434 pcop->name = Safe_strdup(s);
3436 ((pCodeOpLabel *)pcop)->key = key;
3438 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3442 /*-----------------------------------------------------------------*/
3443 /*-----------------------------------------------------------------*/
3444 pCodeOp *pic16_newpCodeOpLit(int lit)
3450 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3451 pcop->type = PO_LITERAL;
3455 sprintf(s,"0x%02x",lit);
3457 pcop->name = Safe_strdup(s);
3460 ((pCodeOpLit *)pcop)->lit = lit;
3465 /*-----------------------------------------------------------------*/
3466 /*-----------------------------------------------------------------*/
3467 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3469 char *s = buffer, tbuf[256], *tb=tbuf;
3473 tb = pic16_get_op(arg2, NULL, 0);
3474 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3475 pcop->type = PO_LITERAL;
3479 sprintf(s,"0x%02x, %s",lit, tb);
3481 pcop->name = Safe_strdup(s);
3484 ((pCodeOpLit2 *)pcop)->lit = lit;
3485 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3490 /*-----------------------------------------------------------------*/
3491 /*-----------------------------------------------------------------*/
3492 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3496 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3497 pcop->type = PO_IMMEDIATE;
3499 regs *r = pic16_dirregWithName(name);
3500 pcop->name = Safe_strdup(name);
3504 fprintf(stderr, "%s:%d %s reg %s exists\n",__FILE__, __LINE__, __FUNCTION__, name);
3505 PCOI(pcop)->rIdx = r->rIdx;
3507 fprintf(stderr, "%s:%d %s reg %s doesn't exist\n",
3508 __FILE__, __LINE__, __FUNCTION__, name);
3509 PCOI(pcop)->rIdx = -1;
3511 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3516 PCOI(pcop)->index = index;
3517 PCOI(pcop)->offset = offset;
3518 PCOI(pcop)->_const = code_space;
3523 /*-----------------------------------------------------------------*/
3524 /*-----------------------------------------------------------------*/
3525 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3531 if(!pcwb || !subtype) {
3532 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3536 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3537 pcop->type = PO_WILD;
3538 sprintf(s,"%%%d",id);
3539 pcop->name = Safe_strdup(s);
3541 PCOW(pcop)->id = id;
3542 PCOW(pcop)->pcwb = pcwb;
3543 PCOW(pcop)->subtype = subtype;
3544 PCOW(pcop)->matched = NULL;
3549 /*-----------------------------------------------------------------*/
3550 /*-----------------------------------------------------------------*/
3551 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3555 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3556 pcop->type = PO_GPR_BIT;
3558 pcop->name = Safe_strdup(s);
3562 PCORB(pcop)->bit = bit;
3563 PCORB(pcop)->inBitSpace = inBitSpace;
3565 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3566 PCOR(pcop)->r = NULL;
3567 PCOR(pcop)->rIdx = 0;
3571 /*-----------------------------------------------------------------*
3572 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3574 * If rIdx >=0 then a specific register from the set of registers
3575 * will be selected. If rIdx <0, then a new register will be searched
3577 *-----------------------------------------------------------------*/
3579 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3583 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3588 PCOR(pcop)->rIdx = rIdx;
3589 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3591 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3594 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3596 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
3597 __FUNCTION__, __LINE__);
3602 pcop->type = PCOR(pcop)->r->pc_type;
3607 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3612 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3613 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1);
3614 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3615 pcop->type = PCOR(pcop)->r->pc_type;
3616 pcop->name = PCOR(pcop)->r->name;
3618 fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3619 __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
3624 /*-----------------------------------------------------------------*/
3625 /*-----------------------------------------------------------------*/
3627 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3634 pcop = pic16_newpCodeOpBit(name, -1,0);
3638 pcop = pic16_newpCodeOpLit(-1);
3642 pcop = pic16_newpCodeOpLabel(NULL,-1);
3645 pcop = pic16_newpCodeOpReg(-1);
3648 case PO_GPR_REGISTER:
3650 pcop = pic16_newpCodeOpRegFromStr(name);
3652 pcop = pic16_newpCodeOpReg(-1);
3656 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3659 pcop->name = Safe_strdup(name);
3667 /*-----------------------------------------------------------------*/
3668 /*-----------------------------------------------------------------*/
3669 void pic16_pCodeConstString(char *name, char *value)
3673 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
3678 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3680 pic16_addpBlock(pb);
3682 sprintf(buffer,"; %s = %s",name,value);
3684 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3685 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3688 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3694 /*-----------------------------------------------------------------*/
3695 /*-----------------------------------------------------------------*/
3697 static void pCodeReadCodeTable(void)
3701 fprintf(stderr, " %s\n",__FUNCTION__);
3703 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3705 pic16_addpBlock(pb);
3707 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3708 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3709 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3710 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3712 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3713 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3714 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3715 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3720 /*-----------------------------------------------------------------*/
3721 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3722 /*-----------------------------------------------------------------*/
3723 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3730 /* If this is the first pcode to be added to a block that
3731 * was initialized with a NULL pcode, then go ahead and
3732 * make this pcode the head and tail */
3733 pb->pcHead = pb->pcTail = pc;
3736 pb->pcTail->next = pc;
3738 pc->prev = pb->pcTail;
3745 /*-----------------------------------------------------------------*/
3746 /* pic16_addpBlock - place a pBlock into the pFile */
3747 /*-----------------------------------------------------------------*/
3748 void pic16_addpBlock(pBlock *pb)
3750 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3753 /* First time called, we'll pass through here. */
3754 //_ALLOC(the_pFile,sizeof(pFile));
3755 the_pFile = Safe_calloc(1,sizeof(pFile));
3756 the_pFile->pbHead = the_pFile->pbTail = pb;
3757 the_pFile->functions = NULL;
3761 the_pFile->pbTail->next = pb;
3762 pb->prev = the_pFile->pbTail;
3764 the_pFile->pbTail = pb;
3767 /*-----------------------------------------------------------------*/
3768 /* removepBlock - remove a pBlock from the pFile */
3769 /*-----------------------------------------------------------------*/
3770 static void removepBlock(pBlock *pb)
3778 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3780 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3783 if(pbs == the_pFile->pbHead)
3784 the_pFile->pbHead = pbs->next;
3786 if (pbs == the_pFile->pbTail)
3787 the_pFile->pbTail = pbs->prev;
3790 pbs->next->prev = pbs->prev;
3793 pbs->prev->next = pbs->next;
3800 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3804 /*-----------------------------------------------------------------*/
3805 /* printpCode - write the contents of a pCode to a file */
3806 /*-----------------------------------------------------------------*/
3807 static void printpCode(FILE *of, pCode *pc)
3818 fprintf(of,"warning - unable to print pCode\n");
3821 /*-----------------------------------------------------------------*/
3822 /* pic16_printpBlock - write the contents of a pBlock to a file */
3823 /*-----------------------------------------------------------------*/
3824 void pic16_printpBlock(FILE *of, pBlock *pb)
3833 if(pb->dbName == 'A') {
3837 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3839 // fprintf(of, "%s\tcode\t%d"
3843 for(pc = pb->pcHead; pc; pc = pc->next) {
3844 if(isPCF(pc) && PCF(pc)->fname) {
3845 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
3846 if(pb->dbName == 'A') {
3848 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3849 if(strcmp(ab->name, PCF(pc)->fname)) {
3850 fprintf(of, "\t0X%06X", ab->address);
3860 /*-----------------------------------------------------------------*/
3862 /* pCode processing */
3866 /*-----------------------------------------------------------------*/
3868 void pic16_unlinkpCode(pCode *pc)
3874 fprintf(stderr,"Unlinking: ");
3875 printpCode(stderr, pc);
3878 pc->prev->next = pc->next;
3880 pc->next->prev = pc->prev;
3882 pc->prev = pc->next = NULL;
3886 /*-----------------------------------------------------------------*/
3887 /*-----------------------------------------------------------------*/
3889 static void genericDestruct(pCode *pc)
3892 pic16_unlinkpCode(pc);
3895 /* For instructions, tell the register (if there's one used)
3896 * that it's no longer needed */
3897 regs *reg = pic16_getRegFromInstruction(pc);
3899 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3901 if(PCI(pc)->is2MemOp) {
3902 reg = pic16_getRegFromInstruction2(pc);
3904 deleteSetItem(&(reg->reglives.usedpCodes), pc);
3908 /* Instead of deleting the memory used by this pCode, mark
3909 * the object as bad so that if there's a pointer to this pCode
3910 * dangling around somewhere then (hopefully) when the type is
3911 * checked we'll catch it.
3916 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3924 /*-----------------------------------------------------------------*/
3925 /*-----------------------------------------------------------------*/
3926 /* modifiers for constant immediate */
3927 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
3929 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3934 int use_buffer = 1; // copy the string to the passed buffer pointer
3939 use_buffer = 0; // Don't bother copying the string to the buffer.
3943 switch(pcop->type) {
3947 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3950 return PCOR(pcop)->r->name;
3953 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3956 SAFE_snprintf(&buffer,&size,"%s",r->name);
3966 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3967 if(PCOI(pcop)->index) {
3968 SAFE_snprintf(&s,&size, "%s(%s + %d)",
3969 immdmod[ PCOI(pcop)->offset ],
3973 SAFE_snprintf(&s,&size,"%s(%s)",
3974 immdmod[ PCOI(pcop)->offset ],
3978 if(PCOI(pcop)->index) {
3979 SAFE_snprintf(&s,&size, "%s(%s + %d)",
3984 SAFE_snprintf(&s,&size, "%s(%s)",
3991 if(PCOI(pcop)->_const) {
3992 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3993 if(PCOI(pcop)->index) {
3994 SAFE_snprintf(&s,&size,"%s(%s + %d)",
3995 immdmod[ PCOI(pcop)->offset ],
3999 SAFE_snprintf(&s,&size,"%s(%s)",
4000 immdmod[ PCOI(pcop)->offset ],
4005 if(PCOI(pcop)->index)
4006 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4008 SAFE_snprintf(&s,&size,"LOW(%s)",pcop->name);
4011 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4)
4012 SAFE_snprintf(&s,&size,"(%s + %d)",
4014 PCOI(pcop)->index );
4016 if(PCOI(pcop)->offset)
4017 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4019 SAFE_snprintf(&s,&size,"(%s)",pcop->name);
4028 //size = sizeof(buffer);
4029 if( PCOR(pcop)->instance) {
4030 SAFE_snprintf(&s,&size,"(%s + %d)",
4032 PCOR(pcop)->instance );
4034 //fprintf(stderr,"PO_DIR %s\n",buffer);
4036 SAFE_snprintf(&s,&size,"%s",pcop->name);
4042 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4051 return "NO operand";
4055 /*-----------------------------------------------------------------*/
4056 /* pic16_get_op2 - variant to support two memory operand commands */
4057 /*-----------------------------------------------------------------*/
4058 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4063 int use_buffer = 1; // copy the string to the passed buffer pointer
4068 use_buffer = 0; // Don't bother copying the string to the buffer.
4072 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",
4073 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4074 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4078 switch(PCOR2(pcop)->pcop2->type) {
4082 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4085 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4088 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4091 SAFE_snprintf(&buffer,&size,"%s",r->name);
4103 if(PCOI(pcop)->_const) {
4105 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4106 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4109 8 * PCOI(pcop)->offset );
4111 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4114 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
4115 SAFE_snprintf(&s,&size,"(%s + %d)",
4117 PCOI(pcop)->index );
4119 if(PCOI(pcop)->offset)
4120 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4122 SAFE_snprintf(&s,&size,"%s",pcop->name);
4131 //size = sizeof(buffer);
4132 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4133 SAFE_snprintf(&s,&size,"(%s + %d)",
4134 PCOR(PCOR2(pcop)->pcop2)->r->name,
4135 PCOR(PCOR2(pcop)->pcop2)->instance );
4137 //fprintf(stderr,"PO_DIR %s\n",buffer);
4139 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4144 if (PCOR2(pcop)->r1->name) {
4146 SAFE_snprintf(&buffer,&size,"%s",PCOR2(pcop)->r1->name);
4149 return PCOR2(pcop)->r1->name;
4157 return "NO operand";
4161 /*-----------------------------------------------------------------*/
4162 /*-----------------------------------------------------------------*/
4163 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4167 return pic16_get_op(pcc->pcop,NULL,0);
4169 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4170 * return ("ERROR Null: "__FUNCTION__);
4172 return ("ERROR Null: pic16_get_op_from_instruction");
4176 /*-----------------------------------------------------------------*/
4177 /*-----------------------------------------------------------------*/
4178 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4181 fprintf(of,"pcodeopprint- not implemented\n");
4184 /*-----------------------------------------------------------------*/
4185 /* pic16_pCode2str - convert a pCode instruction to string */
4186 /*-----------------------------------------------------------------*/
4187 static char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4193 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4194 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4195 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4203 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4205 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4207 if(PCI(pc)->is2MemOp) {
4208 SAFE_snprintf(&s,&size, "%s, %s",
4209 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4210 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4214 if(PCI(pc)->is2LitOp) {
4215 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4219 if(PCI(pc)->isBitInst) {
4220 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4221 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4222 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4223 PCI(pc)->pcop->name ,
4224 PCI(pc)->pcop->name );
4226 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4227 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4228 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4229 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4231 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4232 //PCI(pc)->pcop->t.bit );
4235 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4236 if( PCI(pc)->num_ops == 3)
4237 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4239 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4242 SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
4244 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4245 if(PCI(pc)->num_ops == 3)
4246 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4248 r = pic16_getRegFromInstruction(pc);
4249 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4250 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4252 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4261 /* assuming that comment ends with a \n */
4262 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4266 /* assuming that inline code ends with a \n */
4267 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4271 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4274 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4277 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4280 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4283 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4286 SAFE_snprintf(&s,&size,"\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4290 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4297 /*-----------------------------------------------------------------*/
4298 /* genericPrint - the contents of a pCode to a file */
4299 /*-----------------------------------------------------------------*/
4300 static void genericPrint(FILE *of, pCode *pc)
4308 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4312 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4316 // If the opcode has a label, print that first
4318 pBranch *pbl = PCI(pc)->label;
4319 while(pbl && pbl->pc) {
4320 if(pbl->pc->type == PC_LABEL)
4321 pCodePrintLabel(of, pbl->pc);
4327 genericPrint(of,PCODE(PCI(pc)->cline));
4332 pic16_pCode2str(str, 256, pc);
4334 fprintf(of,"%s",str);
4337 if(pic16_debug_verbose) {
4338 fprintf(of, "\t;key=%03x",pc->seq);
4340 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4347 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4348 if(PCW(pc)->pci.label)
4349 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4351 if(PCW(pc)->operand) {
4352 fprintf(of,";\toperand ");
4353 pCodeOpPrint(of,PCW(pc)->operand );
4358 if(pic16_debug_verbose) {
4359 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4360 if(PCFL(pc)->ancestor)
4361 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4368 fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4372 pBranch *pbl = PCAD(pc)->label;
4373 while(pbl && pbl->pc) {
4374 if(pbl->pc->type == PC_LABEL)
4375 pCodePrintLabel(of, pbl->pc);
4379 fprintf(of, "\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4384 fprintf(of,"unknown pCode type %d\n",pc->type);
4389 /*-----------------------------------------------------------------*/
4390 /* pCodePrintFunction - prints function begin/end */
4391 /*-----------------------------------------------------------------*/
4393 static void pCodePrintFunction(FILE *of, pCode *pc)
4400 if( ((pCodeFunction *)pc)->modname)
4401 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4404 if(PCF(pc)->fname) {
4405 pBranch *exits = PCF(pc)->to;
4407 fprintf(of,"%s", PCF(pc)->fname);
4409 // if(pic16_pcode_verbose)
4410 fprintf(of, "\t;Function start");
4416 exits = exits->next;
4420 if(pic16_pcode_verbose)
4421 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4424 if((PCF(pc)->from &&
4425 PCF(pc)->from->pc->type == PC_FUNCTION &&
4426 PCF(PCF(pc)->from->pc)->fname) ) {
4428 if(pic16_pcode_verbose)
4429 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4431 if(pic16_pcode_verbose)
4432 fprintf(of,"; exit point [can't find entry point]\n");
4437 /*-----------------------------------------------------------------*/
4438 /* pCodePrintLabel - prints label */
4439 /*-----------------------------------------------------------------*/
4441 static void pCodePrintLabel(FILE *of, pCode *pc)
4448 fprintf(of,"%s:\n",PCL(pc)->label);
4449 else if (PCL(pc)->key >=0)
4450 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4452 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4455 /*-----------------------------------------------------------------*/
4456 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4457 /* remove it if it is found. */
4458 /*-----------------------------------------------------------------*/
4459 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4466 if(pcl->type == PC_OPCODE)
4467 b = PCI(pcl)->label;
4469 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4474 //fprintf (stderr, "%s \n",__FUNCTION__);
4475 //pcl->print(stderr,pcl);
4476 //pc->print(stderr,pc);
4479 //fprintf (stderr, "found label\n");
4483 bprev->next = b->next; /* Not first pCode in chain */
4487 PCI(pcl)->label = b->next; /* First pCode in chain */
4490 return; /* A label can't occur more than once */
4498 /*-----------------------------------------------------------------*/
4499 /*-----------------------------------------------------------------*/
4500 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4519 /*-----------------------------------------------------------------*/
4520 /* pBranchLink - given two pcodes, this function will link them */
4521 /* together through their pBranches */
4522 /*-----------------------------------------------------------------*/
4523 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4527 // Declare a new branch object for the 'from' pCode.
4529 //_ALLOC(b,sizeof(pBranch));
4530 b = Safe_calloc(1,sizeof(pBranch));
4531 b->pc = PCODE(t); // The link to the 'to' pCode.
4534 f->to = pic16_pBranchAppend(f->to,b);
4536 // Now do the same for the 'to' pCode.
4538 //_ALLOC(b,sizeof(pBranch));
4539 b = Safe_calloc(1,sizeof(pBranch));
4543 t->from = pic16_pBranchAppend(t->from,b);
4548 /*-----------------------------------------------------------------*/
4549 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4551 /*-----------------------------------------------------------------*/
4552 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4565 /*-----------------------------------------------------------------*/
4566 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4567 /*-----------------------------------------------------------------*/
4568 static void pCodeUnlink(pCode *pc)
4573 if(!pc->prev || !pc->next) {
4574 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4578 /* first remove the pCode from the chain */
4579 pc->prev->next = pc->next;
4580 pc->next->prev = pc->prev;
4582 /* Now for the hard part... */
4584 /* Remove the branches */
4588 pc1 = pb1->pc; /* Get the pCode that branches to the
4589 * one we're unlinking */
4591 /* search for the link back to this pCode (the one we're
4593 if(pb2 = pBranchFind(pc1->to,pc)) {
4594 pb2->pc = pc->to->pc; // make the replacement
4596 /* if the pCode we're unlinking contains multiple 'to'
4597 * branches (e.g. this a skip instruction) then we need
4598 * to copy these extra branches to the chain. */
4600 pic16_pBranchAppend(pb2, pc->to->next);
4609 /*-----------------------------------------------------------------*/
4610 /*-----------------------------------------------------------------*/
4612 static void genericAnalyze(pCode *pc)
4622 // Go through the pCodes that are in pCode chain and link
4623 // them together through the pBranches. Note, the pCodes
4624 // are linked together as a contiguous stream like the
4625 // assembly source code lines. The linking here mimics this
4626 // except that comments are not linked in.
4628 pCode *npc = pc->next;
4630 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4631 pBranchLink(pc,npc);
4636 /* reached the end of the pcode chain without finding
4637 * an instruction we could link to. */
4641 fprintf(stderr,"analyze PC_FLOW\n");
4645 fprintf(stderr,,";A bad pCode is being used\n");
4651 /*-----------------------------------------------------------------*/
4652 /*-----------------------------------------------------------------*/
4653 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4657 if(pc->type == PC_LABEL) {
4658 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4661 if(pc->type == PC_OPCODE) {
4662 pbr = PCI(pc)->label;
4664 if(pbr->pc->type == PC_LABEL) {
4665 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4675 /*-----------------------------------------------------------------*/
4676 /*-----------------------------------------------------------------*/
4677 static int checkLabel(pCode *pc)
4681 if(pc && isPCI(pc)) {
4682 pbr = PCI(pc)->label;
4684 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4694 /*-----------------------------------------------------------------*/
4695 /* findLabelinpBlock - Search the pCode for a particular label */
4696 /*-----------------------------------------------------------------*/
4697 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4704 for(pc = pb->pcHead; pc; pc = pc->next)
4705 if(compareLabel(pc,pcop_label))
4711 /*-----------------------------------------------------------------*/
4712 /* findLabel - Search the pCode for a particular label */
4713 /*-----------------------------------------------------------------*/
4714 static pCode * findLabel(pCodeOpLabel *pcop_label)
4722 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4723 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4727 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4731 /*-----------------------------------------------------------------*/
4732 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4733 /* in the linked list */
4734 /*-----------------------------------------------------------------*/
4735 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4748 /*-----------------------------------------------------------------*/
4749 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4750 /* in the linked list */
4751 /*-----------------------------------------------------------------*/
4752 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4764 /*-----------------------------------------------------------------*/
4765 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4766 /* in the linked list */
4767 /*-----------------------------------------------------------------*/
4768 pCode * pic16_findNextInstruction(pCode *pci)
4773 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4777 fprintf(stderr,"pic16_findNextInstruction: ");
4778 printpCode(stderr, pc);
4783 //fprintf(stderr,"Couldn't find instruction\n");
4787 /*-----------------------------------------------------------------*/
4788 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4789 /* in the linked list */
4790 /*-----------------------------------------------------------------*/
4791 pCode * pic16_findPrevInstruction(pCode *pci)
4793 return findPrevpCode(pci, PC_OPCODE);
4796 /*-----------------------------------------------------------------*/
4797 /* findFunctionEnd - given a pCode find the end of the function */
4798 /* that contains it */
4799 /*-----------------------------------------------------------------*/
4800 static pCode * findFunctionEnd(pCode *pc)
4804 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4810 fprintf(stderr,"Couldn't find function end\n");
4815 /*-----------------------------------------------------------------*/
4816 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4817 /* instruction with which it is associated. */
4818 /*-----------------------------------------------------------------*/
4819 static void AnalyzeLabel(pCode *pc)
4828 static void AnalyzeGOTO(pCode *pc)
4831 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4835 static void AnalyzeSKIP(pCode *pc)
4838 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4839 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4843 static void AnalyzeRETURN(pCode *pc)
4846 // branch_link(pc,findFunctionEnd(pc->next));
4852 /*-----------------------------------------------------------------*/
4853 /*-----------------------------------------------------------------*/
4854 regs * pic16_getRegFromInstruction(pCode *pc)
4860 PCI(pc)->num_ops == 0 ||
4861 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4864 switch(PCI(pc)->pcop->type) {
4867 return PCOR(PCI(pc)->pcop)->r;
4869 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4873 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4874 return PCOR(PCI(pc)->pcop)->r;
4877 if(PCOI(PCI(pc)->pcop)->r)
4878 return (PCOI(PCI(pc)->pcop)->r);
4880 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4881 return pic16_dirregWithName(PCI(pc)->pcop->name);
4882 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4885 return PCOR(PCI(pc)->pcop)->r;
4888 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4889 return PCOR(PCI(pc)->pcop)->r;
4891 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4895 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4896 //genericPrint(stderr, pc);
4904 /*-------------------------------------------------------------------------------*/
4905 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
4906 /*-------------------------------------------------------------------------------*/
4907 regs * pic16_getRegFromInstruction2(pCode *pc)
4913 PCI(pc)->num_ops == 0 ||
4914 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
4919 * operands supported in MOVFF:
4926 switch(PCI(pc)->pcop->type) {
4929 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4931 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4935 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4936 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4941 if(PCOI(PCI(pc)->pcop)->r)
4942 return (PCOI(PCI(pc)->pcop)->r);
4944 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4945 return pic16_dirregWithName(PCI(pc)->pcop->name);
4946 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4951 // return PCOR2(PCI(pc)->pcop)->r;
4954 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4955 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4959 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4962 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4963 //genericPrint(stderr, pc);
4971 /*-----------------------------------------------------------------*/
4972 /*-----------------------------------------------------------------*/
4974 static void AnalyzepBlock(pBlock *pb)
4981 /* Find all of the registers used in this pBlock
4982 * by looking at each instruction and examining it's
4985 for(pc = pb->pcHead; pc; pc = pc->next) {
4987 /* Is this an instruction with operands? */
4988 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4990 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4992 /* Loop through all of the registers declared so far in
4993 this block and see if we find this one there */
4995 regs *r = setFirstItem(pb->tregisters);
4998 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4999 PCOR(PCI(pc)->pcop)->r = r;
5002 r = setNextItem(pb->tregisters);
5006 /* register wasn't found */
5007 //r = Safe_calloc(1, sizeof(regs));
5008 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5009 //addSet(&pb->tregisters, r);
5010 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5011 //PCOR(PCI(pc)->pcop)->r = r;
5012 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5014 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5017 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5018 if(PCOR(PCI(pc)->pcop)->r) {
5019 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5020 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5022 if(PCI(pc)->pcop->name)
5023 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5025 fprintf(stderr,"ERROR: NULL register\n");
5034 /*-----------------------------------------------------------------*/
5036 /*-----------------------------------------------------------------*/
5037 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5039 static void InsertpFlow(pCode *pc, pCode **pflow)
5042 PCFL(*pflow)->end = pc;
5044 if(!pc || !pc->next)
5047 *pflow = pic16_newpCodeFlow();
5048 pic16_pCodeInsertAfter(pc, *pflow);
5051 /*-----------------------------------------------------------------*/
5052 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5053 /* the flow blocks. */
5055 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5056 * point the instruction flow changes.
5058 /*-----------------------------------------------------------------*/
5059 void pic16_BuildFlow(pBlock *pb)
5062 pCode *last_pci=NULL;
5069 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5070 /* Insert a pCodeFlow object at the beginning of a pBlock */
5072 InsertpFlow(pb->pcHead, &pflow);
5074 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5075 //pflow->next = pb->pcHead; /* Make the current head the next object */
5076 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5077 //pb->pcHead = pflow; /* Make the Flow object the head */
5080 for( pc = pic16_findNextInstruction(pb->pcHead);
5082 pc=pic16_findNextInstruction(pc)) {
5085 PCI(pc)->pcflow = PCFL(pflow);
5087 //fprintf(stderr," build: ");
5088 //pflow->print(stderr,pflow);
5090 if( PCI(pc)->isSkip) {
5092 /* The two instructions immediately following this one
5093 * mark the beginning of a new flow segment */
5095 while(pc && PCI(pc)->isSkip) {
5097 PCI(pc)->pcflow = PCFL(pflow);
5101 InsertpFlow(pc, &pflow);
5102 pc=pic16_findNextInstruction(pc->next);
5110 PCI(pc)->pcflow = PCFL(pflow);
5112 InsertpFlow(pc, &pflow);
5114 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5116 InsertpFlow(pc, &pflow);
5119 } else if (checkLabel(pc)) {
5121 /* This instruction marks the beginning of a
5122 * new flow segment */
5127 /* If the previous pCode is not a flow object, then
5128 * insert a new flow object. (This check prevents
5129 * two consecutive flow objects from being insert in
5130 * the case where a skip instruction preceeds an
5131 * instruction containing a label.) */
5133 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5134 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5136 PCI(pc)->pcflow = PCFL(pflow);
5143 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5145 PCFL(pflow)->end = pb->pcTail;
5148 /*-------------------------------------------------------------------*/
5149 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5150 /* the flow blocks. */
5152 * unBuildFlow removes pCodeFlow objects from a pCode chain
5154 /*-----------------------------------------------------------------*/
5155 static void unBuildFlow(pBlock *pb)
5170 if(PCI(pc)->pcflow) {
5171 //free(PCI(pc)->pcflow);
5172 PCI(pc)->pcflow = NULL;
5175 } else if(isPCFL(pc) )
5184 /*-----------------------------------------------------------------*/
5185 /*-----------------------------------------------------------------*/
5186 static void dumpCond(int cond)
5189 static char *pcc_str[] = {
5204 int ncond = sizeof(pcc_str) / sizeof(char *);
5207 fprintf(stderr, "0x%04X\n",cond);
5209 for(i=0,j=1; i<ncond; i++, j<<=1)
5211 fprintf(stderr, " %s\n",pcc_str[i]);
5217 /*-----------------------------------------------------------------*/
5218 /*-----------------------------------------------------------------*/
5219 static void FlowStats(pCodeFlow *pcflow)
5227 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5229 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5232 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5237 fprintf(stderr, " FlowStats inCond: ");
5238 dumpCond(pcflow->inCond);
5239 fprintf(stderr, " FlowStats outCond: ");
5240 dumpCond(pcflow->outCond);
5244 /*-----------------------------------------------------------------*
5245 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5246 * if it affects the banking bits.
5248 * return: -1 == Banking bits are unaffected by this pCode.
5250 * return: > 0 == Banking bits are affected.
5252 * If the banking bits are affected, then the returned value describes
5253 * which bits are affected and how they're affected. The lower half
5254 * of the integer maps to the bits that are affected, the upper half
5255 * to whether they're set or cleared.
5257 *-----------------------------------------------------------------*/
5259 static int isBankInstruction(pCode *pc)
5267 if( PCI(pc)->op == POC_MOVLB ||
5268 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5269 bank = PCOL(pc)->lit;
5276 /*-----------------------------------------------------------------*/
5277 /*-----------------------------------------------------------------*/
5278 static void FillFlow(pCodeFlow *pcflow)
5287 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5289 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5292 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5299 isBankInstruction(pc);
5301 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5305 fprintf(stderr, " FillFlow - Bad end of flow\n");
5307 fprintf(stderr, " FillFlow - Ending flow with\n ");
5308 pc->print(stderr,pc);
5311 fprintf(stderr, " FillFlow inCond: ");
5312 dumpCond(pcflow->inCond);
5313 fprintf(stderr, " FillFlow outCond: ");
5314 dumpCond(pcflow->outCond);
5318 /*-----------------------------------------------------------------*/
5319 /*-----------------------------------------------------------------*/
5320 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5322 pCodeFlowLink *fromLink, *toLink;
5324 if(!from || !to || !to->pcflow || !from->pcflow)
5327 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5328 toLink = pic16_newpCodeFlowLink(to->pcflow);
5330 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5331 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5335 /*-----------------------------------------------------------------*
5336 * void LinkFlow(pBlock *pb)
5338 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5339 * non-branching segments. In LinkFlow, we determine the execution
5340 * order of these segments. For example, if one of the segments ends
5341 * with a skip, then we know that there are two possible flow segments
5342 * to which control may be passed.
5343 *-----------------------------------------------------------------*/
5344 static void LinkFlow(pBlock *pb)
5350 //fprintf(stderr,"linkflow \n");
5352 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5354 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5357 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5359 //fprintf(stderr," link: ");
5360 //pcflow->print(stderr,pcflow);
5362 //FillFlow(PCFL(pcflow));
5364 pc = PCFL(pcflow)->end;
5366 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5367 if(isPCI_SKIP(pc)) {
5368 //fprintf(stderr, "ends with skip\n");
5369 //pc->print(stderr,pc);
5370 pct=pic16_findNextInstruction(pc->next);
5371 LinkFlow_pCode(PCI(pc),PCI(pct));
5372 pct=pic16_findNextInstruction(pct->next);
5373 LinkFlow_pCode(PCI(pc),PCI(pct));
5377 if(isPCI_BRANCH(pc)) {
5378 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5380 //fprintf(stderr, "ends with branch\n ");
5381 //pc->print(stderr,pc);
5383 if(!(pcol && isPCOLAB(pcol))) {
5384 if((PCI(pc)->op != POC_RETLW)
5385 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5387 /* continue if label is '$' which assembler knows how to parse */
5388 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5390 pc->print(stderr,pc);
5391 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5396 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5397 LinkFlow_pCode(PCI(pc),PCI(pct));
5399 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5400 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5401 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5407 //fprintf(stderr, "ends with non-branching instruction:\n");
5408 //pc->print(stderr,pc);
5410 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5416 //fprintf(stderr, "ends with unknown\n");
5417 //pc->print(stderr,pc);
5421 //fprintf(stderr, "ends with nothing: ERROR\n");
5425 /*-----------------------------------------------------------------*/
5426 /*-----------------------------------------------------------------*/
5428 /*-----------------------------------------------------------------*/
5429 /*-----------------------------------------------------------------*/
5430 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5436 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5439 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5449 /*-----------------------------------------------------------------*/
5450 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5451 /*-----------------------------------------------------------------*/
5452 static void insertBankSwitch(int position, pCode *pc, int bsr)
5461 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5462 * insert a BANKSEL assembler directive for the symbol used by
5463 * the pCode. This will allow the linker to setup the correct
5464 * bank at linking time
5467 if(!pic16_options.gen_banksel || bsr != -1) {
5468 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5471 /* emit the BANKSEL [symbol] */
5474 /* IMPORTANT: The following code does not check if a symbol is
5475 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5477 reg = pic16_getRegFromInstruction(pc);
5479 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", reg->name);
5481 position = 0; // position is always before (sanity check!)
5485 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5486 pc->print(stderr, pc);
5490 /* insert the bank switch after this pc instruction */
5491 pCode *pcnext = pic16_findNextInstruction(pc);
5492 pic16_pCodeInsertAfter(pc, new_pc);
5497 pic16_pCodeInsertAfter(pc->prev, new_pc);
5499 /* Move the label, if there is one */
5501 if(PCI(pc)->label) {
5502 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5503 // __FILE__, __LINE__, pc, new_pc);
5504 PCAD(new_pc)->label = PCI(pc)->label;
5505 PCI(pc)->label = NULL;
5508 // fprintf(stderr, "BankSwitch has been inserted\n");
5512 /*-----------------------------------------------------------------*/
5513 /*int compareBankFlow - compare the banking requirements between */
5515 /*-----------------------------------------------------------------*/
5516 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5519 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5522 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5525 if(pcflow->firstBank == -1)
5529 if(pcflowLink->pcflow->firstBank == -1) {
5530 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5531 pcflowLink->pcflow->to :
5532 pcflowLink->pcflow->from);
5533 return compareBankFlow(pcflow, pctl, toORfrom);
5537 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5540 pcflowLink->bank_conflict++;
5541 pcflowLink->pcflow->FromConflicts++;
5542 pcflow->ToConflicts++;
5545 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5548 pcflowLink->bank_conflict++;
5549 pcflowLink->pcflow->ToConflicts++;
5550 pcflow->FromConflicts++;
5554 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5555 pcflowLink->pcflow->pc.seq,
5556 pcflowLink->pcflow->FromConflicts,
5557 pcflowLink->pcflow->ToConflicts);
5564 /*-----------------------------------------------------------------*/
5565 /*-----------------------------------------------------------------*/
5566 static void DumpFlow(pBlock *pb)
5570 pCodeFlowLink *pcfl;
5573 fprintf(stderr,"Dump flow \n");
5574 pb->pcHead->print(stderr, pb->pcHead);
5576 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5577 pcflow->print(stderr,pcflow);
5579 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5581 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5583 if(!isPCFL(pcflow)) {
5584 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5587 fprintf(stderr,"dumping: ");
5588 pcflow->print(stderr,pcflow);
5589 FlowStats(PCFL(pcflow));
5591 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5593 pc = PCODE(pcfl->pcflow);
5595 fprintf(stderr, " from seq %d:\n",pc->seq);
5597 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5598 pc->print(stderr,pc);
5603 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5605 pc = PCODE(pcfl->pcflow);
5607 fprintf(stderr, " to seq %d:\n",pc->seq);
5609 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5610 pc->print(stderr,pc);
5619 /*-----------------------------------------------------------------*/
5620 /*-----------------------------------------------------------------*/
5621 static int OptimizepBlock(pBlock *pb)
5626 if(!pb || !peepOptimizing)
5629 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5631 for(pc = pb->pcHead; pc; pc = pc->next)
5632 matches += pic16_pCodePeepMatchRule(pc);
5635 pc = pic16_findNextInstruction(pb->pcHead);
5643 if(pic16_pCodePeepMatchRule(pc)) {
5648 pc = pic16_findNextInstruction(pcprev->next);
5650 pc = pic16_findNextInstruction(pb->pcHead);
5652 pc = pic16_findNextInstruction(pc->next);
5656 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5661 /*-----------------------------------------------------------------*/
5662 /*-----------------------------------------------------------------*/
5663 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5667 for(pc = pcs; pc; pc = pc->next) {
5669 if((pc->type == PC_OPCODE) &&
5671 (PCI(pc)->pcop->type == PO_LABEL) &&
5672 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5680 /*-----------------------------------------------------------------*/
5681 /*-----------------------------------------------------------------*/
5682 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5689 (PCI(pc)->pcop->type == PO_LABEL)) {
5691 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5693 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5695 free(pcol->pcop.name);
5697 /* If the key is negative, then we (probably) have a label to
5698 * a function and the name is already defined */
5701 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5705 //sprintf(buffer,"_%05d_DS_",pcl->key);
5707 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5709 pcol->pcop.name = Safe_strdup(s);
5710 pcol->key = pcl->key;
5711 //pc->print(stderr,pc);
5718 /*-----------------------------------------------------------------*/
5719 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5720 /* pCode chain if they're not used. */
5721 /*-----------------------------------------------------------------*/
5722 static void pBlockRemoveUnusedLabels(pBlock *pb)
5724 pCode *pc; pCodeLabel *pcl;
5729 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5731 pBranch *pbr = PCI(pc)->label;
5732 if(pbr && pbr->next) {
5733 pCode *pcd = pb->pcHead;
5735 //fprintf(stderr, "multiple labels\n");
5736 //pc->print(stderr,pc);
5741 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5742 //fprintf(stderr,"Used by:\n");
5743 //pcd->print(stderr,pcd);
5745 exchangeLabels(PCL(pbr->pc),pcd);
5754 for(pc = pb->pcHead; pc; pc = pc->next) {
5756 if(isPCL(pc)) // pc->type == PC_LABEL)
5758 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5759 pcl = PCL(PCI(pc)->label->pc);
5762 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5764 /* This pCode is a label, so search the pBlock to see if anyone
5767 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5768 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5769 /* Couldn't find an instruction that refers to this label
5770 * So, unlink the pCode label from it's pCode chain
5771 * and destroy the label */
5772 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5774 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5775 if(pc->type == PC_LABEL) {
5776 pic16_unlinkpCode(pc);
5777 pCodeLabelDestruct(pc);
5779 unlinkpCodeFromBranch(pc, PCODE(pcl));
5780 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5791 /*-----------------------------------------------------------------*/
5792 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
5793 /* chain and put them into pBranches that are */
5794 /* associated with the appropriate pCode */
5796 /*-----------------------------------------------------------------*/
5797 void pic16_pBlockMergeLabels(pBlock *pb)
5800 pCode *pc, *pcnext=NULL;
5805 /* First, Try to remove any unused labels */
5806 //pBlockRemoveUnusedLabels(pb);
5808 /* Now loop through the pBlock and merge the labels with the opcodes */
5811 // for(pc = pb->pcHead; pc; pc = pc->next) {
5814 pCode *pcn = pc->next;
5816 if(pc->type == PC_LABEL) {
5818 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5819 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5821 if((pcnext = pic16_findNextInstruction(pc) )) {
5823 // Unlink the pCode label from it's pCode chain
5824 pic16_unlinkpCode(pc);
5826 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5827 // And link it into the instruction's pBranch labels. (Note, since
5828 // it's possible to have multiple labels associated with one instruction
5829 // we must provide a means to accomodate the additional labels. Thus
5830 // the labels are placed into the singly-linked list "label" as
5831 // opposed to being a single member of the pCodeInstruction.)
5833 //_ALLOC(pbr,sizeof(pBranch));
5835 pbr = Safe_calloc(1,sizeof(pBranch));
5839 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5842 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5844 } else if(pc->type == PC_CSOURCE) {
5846 /* merge the source line symbolic info into the next instruction */
5847 if((pcnext = pic16_findNextInstruction(pc) )) {
5849 // Unlink the pCode label from it's pCode chain
5850 pic16_unlinkpCode(pc);
5851 PCI(pcnext)->cline = PCCS(pc);
5852 //fprintf(stderr, "merging CSRC\n");
5853 //genericPrint(stderr,pcnext);
5859 pBlockRemoveUnusedLabels(pb);
5863 /*-----------------------------------------------------------------*/
5864 /*-----------------------------------------------------------------*/
5865 static int OptimizepCode(char dbName)
5867 #define MAX_PASSES 4
5876 DFPRINTF((stderr," Optimizing pCode\n"));
5880 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5881 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5882 matches += OptimizepBlock(pb);
5885 while(matches && ++passes < MAX_PASSES);
5890 /*-----------------------------------------------------------------*/
5891 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5892 /*-----------------------------------------------------------------*/
5894 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5898 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5900 if( !( (pcop->type == PO_LABEL) ||
5901 (pcop->type == PO_LITERAL) ||
5902 (pcop->type == PO_STR) ))
5903 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5904 PCOR(pcop)->r->wasUsed = 1;
5910 /*----------------------------------------------------------------------*
5911 * pic16_areRegsSame - check to see if the names of two registers match *
5912 *----------------------------------------------------------------------*/
5913 int pic16_areRegsSame(regs *r1, regs *r2)
5915 if(!strcmp(r1->name, r2->name))return 1;
5921 /*-----------------------------------------------------------------*/
5922 /*-----------------------------------------------------------------*/
5923 static void pic16_FixRegisterBanking(pBlock *pb)
5927 regs *reg, *prevreg;
5932 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5936 /* loop through all of the flow blocks with in one pblock */
5938 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
5942 /* at this point, pc should point to a PC_FLOW object */
5943 /* for each flow block, determine the register banking
5946 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
5947 reg = pic16_getRegFromInstruction(pc);
5950 fprintf(stderr, "reg = %p\n", reg);
5952 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
5953 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
5954 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
5955 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
5959 /* we can be 99% that within a pBlock, between two consequtive
5960 * refernces to the same register, the extra banksel is needless */
5962 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
5964 && (PCI(pc)->op != POC_CALL)
5966 && ( ((pic16_options.opt_banksel>0)
5967 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
5968 || (!pic16_options.opt_banksel)
5972 /* Examine the instruction before this one to make sure it is
5973 * not a skip type instruction */
5974 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5976 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
5977 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
5978 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5980 insertBankSwitch(0, pc, (pic16_options.gen_banksel)?-1:0);
5992 if(pcprev && cur_bank) {
5994 int pos = 1; /* Assume that the bank switch instruction(s)
5995 * are inserted after this instruction */
5997 if((PCI(pcprev)->op == POC_RETLW) ||
5998 (PCI(pcprev)->op == POC_RETURN) ||
5999 (PCI(pcprev)->op == POC_RETFIE)) {
6001 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6007 /* Brute force - make sure that we point to bank 0 at the
6008 * end of each flow block */
6010 // insertBankSwitch(pos, pcprev, 0);
6012 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6013 pic16_pCodeInsertAfter(pcprev, new_pc);
6016 //fprintf(stderr, "Brute force switch\n");
6023 static void pBlockDestruct(pBlock *pb)
6034 /*-----------------------------------------------------------------*/
6035 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6036 /* name dbName and combine them */
6037 /* into one block */
6038 /*-----------------------------------------------------------------*/
6039 static void mergepBlocks(char dbName)
6042 pBlock *pb, *pbmerged = NULL,*pbn;
6044 pb = the_pFile->pbHead;
6046 //fprintf(stderr," merging blocks named %c\n",dbName);
6050 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6051 if( getpBlock_dbName(pb) == dbName) {
6053 //fprintf(stderr," merged block %c\n",dbName);
6058 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6059 /* pic16_addpCode2pBlock doesn't handle the tail: */
6060 pbmerged->pcTail = pb->pcTail;
6062 pb->prev->next = pbn;
6064 pbn->prev = pb->prev;
6069 //pic16_printpBlock(stderr, pbmerged);
6076 /*-----------------------------------------------------------------*/
6077 /* AnalyzeFlow - Examine the flow of the code and optimize */
6079 /* level 0 == minimal optimization */
6080 /* optimize registers that are used only by two instructions */
6081 /* level 1 == maximal optimization */
6082 /* optimize by looking at pairs of instructions that use the */
6084 /*-----------------------------------------------------------------*/
6086 static void AnalyzeFlow(int level)
6088 static int times_called=0;
6093 /* remove unused allocated registers before exiting */
6094 pic16_RemoveUnusedRegisters();
6100 /* if this is not the first time this function has been called,
6101 then clean up old flow information */
6102 if(times_called++) {
6103 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6106 pic16_RegsUnMapLiveRanges();
6111 /* Phase 2 - Flow Analysis - Register Banking
6113 * In this phase, the individual flow blocks are examined
6114 * and register banking is fixed.
6118 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6119 pic16_FixRegisterBanking(pb);
6122 /* Phase 2 - Flow Analysis
6124 * In this phase, the pCode is partition into pCodeFlow
6125 * blocks. The flow blocks mark the points where a continuous
6126 * stream of instructions changes flow (e.g. because of
6127 * a call or goto or whatever).
6130 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6131 pic16_BuildFlow(pb);
6134 /* Phase 2 - Flow Analysis - linking flow blocks
6136 * In this phase, the individual flow blocks are examined
6137 * to determine their order of excution.
6140 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6143 /* Phase 3 - Flow Analysis - Flow Tree
6145 * In this phase, the individual flow blocks are examined
6146 * to determine their order of execution.
6149 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6150 pic16_BuildFlowTree(pb);
6153 /* Phase x - Flow Analysis - Used Banks
6155 * In this phase, the individual flow blocks are examined
6156 * to determine the Register Banks they use
6160 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6165 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6166 pic16_pCodeRegMapLiveRanges(pb);
6168 pic16_RemoveUnusedRegisters();
6170 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6171 pic16_pCodeRegOptimizeRegUsage(level);
6179 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6184 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6186 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6187 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6188 pcflow = pcflow->next) {
6190 FillFlow(PCFL(pcflow));
6195 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6198 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6199 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6200 pcflow = pcflow->next) {
6202 FlowStats(PCFL(pcflow));
6208 /* VR -- no need to analyze banking in flow, but left here :
6209 * 1. because it may be used in the future for other purposes
6210 * 2. because if omitted we'll miss some optimization done here
6212 * Perhaps I should rename it to something else
6215 /*-----------------------------------------------------------------*/
6216 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6217 /* assigned to the registers. */
6219 /*-----------------------------------------------------------------*/
6221 void pic16_AnalyzeBanking(void)
6225 if(!pic16_picIsInitialized()) {
6226 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6227 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6228 fprintf(stderr,"support/scripts/inc2h.pl\n");
6229 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6231 /* I think it took a long long time to fix this bug! ;-) -- VR */
6237 /* Phase x - Flow Analysis - Used Banks
6239 * In this phase, the individual flow blocks are examined
6240 * to determine the Register Banks they use
6246 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6247 // BanksUsedFlow(pb);
6249 if(!the_pFile)return;
6251 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6252 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6253 pic16_FixRegisterBanking(pb);
6258 /*-----------------------------------------------------------------*/
6259 /* buildCallTree - Look at the flow and extract all of the calls. */
6260 /*-----------------------------------------------------------------*/
6261 static set *register_usage(pBlock *pb);
6263 static void buildCallTree(void )
6274 /* Now build the call tree.
6275 First we examine all of the pCodes for functions.
6276 Keep in mind that the function boundaries coincide
6277 with pBlock boundaries.
6279 The algorithm goes something like this:
6280 We have two nested loops. The outer loop iterates
6281 through all of the pBlocks/functions. The inner
6282 loop iterates through all of the pCodes for
6283 a given pBlock. When we begin iterating through
6284 a pBlock, the variable pc_fstart, pCode of the start
6285 of a function, is cleared. We then search for pCodes
6286 of type PC_FUNCTION. When one is encountered, we
6287 initialize pc_fstart to this and at the same time
6288 associate a new pBranch object that signifies a
6289 branch entry. If a return is found, then this signifies
6290 a function exit point. We'll link the pCodes of these
6291 returns to the matching pc_fstart.
6293 When we're done, a doubly linked list of pBranches
6294 will exist. The head of this list is stored in
6295 `the_pFile', which is the meta structure for all
6296 of the pCode. Look at the pic16_printCallTree function
6297 on how the pBranches are linked together.
6300 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6301 pCode *pc_fstart=NULL;
6302 for(pc = pb->pcHead; pc; pc = pc->next) {
6304 if (PCF(pc)->fname) {
6306 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6307 //fprintf(stderr," found main \n");
6308 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6312 pbr = Safe_calloc(1,sizeof(pBranch));
6313 pbr->pc = pc_fstart = pc;
6316 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6318 // Here's a better way of doing the same:
6319 addSet(&pb->function_entries, pc);
6322 // Found an exit point in a function, e.g. return
6323 // (Note, there may be more than one return per function)
6325 pBranchLink(PCF(pc_fstart), PCF(pc));
6327 addSet(&pb->function_exits, pc);
6329 } else if(isCALL(pc)) {
6330 addSet(&pb->function_calls,pc);
6335 /* Re-allocate the registers so that there are no collisions
6336 * between local variables when one function call another */
6339 // pic16_deallocateAllRegs();
6341 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6348 /*-----------------------------------------------------------------*/
6349 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6350 /* all of the logical connections. */
6352 /* Essentially what's done here is that the pCode flow is */
6354 /*-----------------------------------------------------------------*/
6356 void pic16_AnalyzepCode(char dbName)
6367 /* Phase 1 - Register allocation and peep hole optimization
6369 * The first part of the analysis is to determine the registers
6370 * that are used in the pCode. Once that is done, the peep rules
6371 * are applied to the code. We continue to loop until no more
6372 * peep rule optimizations are found (or until we exceed the
6373 * MAX_PASSES threshold).
6375 * When done, the required registers will be determined.
6381 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6382 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6384 /* First, merge the labels with the instructions */
6385 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6386 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6388 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6389 //fprintf(stderr," analyze and merging block %c\n",dbName);
6390 pic16_pBlockMergeLabels(pb);
6393 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6398 changes = OptimizepCode(dbName);
6401 } while(changes && (i++ < MAX_PASSES));
6406 /*-----------------------------------------------------------------*/
6407 /* ispCodeFunction - returns true if *pc is the pCode of a */
6409 /*-----------------------------------------------------------------*/
6410 static bool ispCodeFunction(pCode *pc)
6413 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6419 /*-----------------------------------------------------------------*/
6420 /* findFunction - Search for a function by name (given the name) */
6421 /* in the set of all functions that are in a pBlock */
6422 /* (note - I expect this to change because I'm planning to limit */
6423 /* pBlock's to just one function declaration */
6424 /*-----------------------------------------------------------------*/
6425 static pCode *findFunction(char *fname)
6432 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6434 pc = setFirstItem(pb->function_entries);
6437 if((pc->type == PC_FUNCTION) &&
6439 (strcmp(fname, PCF(pc)->fname)==0))
6442 pc = setNextItem(pb->function_entries);
6450 static void MarkUsedRegisters(set *regset)
6455 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6456 // fprintf(stderr, "marking register = %s\t", r1->name);
6457 r2 = pic16_regWithIdx(r1->rIdx);
6458 // fprintf(stderr, "to register = %s\n", r2->name);
6464 static void pBlockStats(FILE *of, pBlock *pb)
6470 if(!pic16_pcode_verbose)return;
6472 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6474 // for now just print the first element of each set
6475 pc = setFirstItem(pb->function_entries);
6477 fprintf(of,";entry: ");
6480 pc = setFirstItem(pb->function_exits);
6482 fprintf(of,";has an exit\n");
6486 pc = setFirstItem(pb->function_calls);
6488 fprintf(of,";functions called:\n");
6491 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6492 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6494 pc = setNextItem(pb->function_calls);
6498 r = setFirstItem(pb->tregisters);
6500 int n = elementsInSet(pb->tregisters);
6502 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6505 fprintf(of,"; %s\n",r->name);
6506 r = setNextItem(pb->tregisters);
6511 /*-----------------------------------------------------------------*/
6512 /*-----------------------------------------------------------------*/
6514 static void sequencepCode(void)
6520 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6522 pb->seq = GpCodeSequenceNumber+1;
6524 for( pc = pb->pcHead; pc; pc = pc->next)
6525 pc->seq = ++GpCodeSequenceNumber;
6531 /*-----------------------------------------------------------------*/
6532 /*-----------------------------------------------------------------*/
6533 static set *register_usage(pBlock *pb)
6536 set *registers=NULL;
6537 set *registersInCallPath = NULL;
6539 /* check recursion */
6541 pc = setFirstItem(pb->function_entries);
6548 if(pc->type != PC_FUNCTION)
6549 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6551 pc = setFirstItem(pb->function_calls);
6552 for( ; pc; pc = setNextItem(pb->function_calls)) {
6554 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6555 char *dest = pic16_get_op_from_instruction(PCI(pc));
6557 pcn = findFunction(dest);
6559 registersInCallPath = register_usage(pcn->pb);
6561 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6566 pBlockStats(stderr,pb); // debug
6569 // Mark the registers in this block as used.
6571 MarkUsedRegisters(pb->tregisters);
6572 if(registersInCallPath) {
6573 /* registers were used in the functions this pBlock has called */
6574 /* so now, we need to see if these collide with the ones we are */
6577 regs *r1,*r2, *newreg;
6579 DFPRINTF((stderr,"comparing registers\n"));
6581 r1 = setFirstItem(registersInCallPath);
6584 r2 = setFirstItem(pb->tregisters);
6586 while(r2 && (r1->type != REG_STK)) {
6588 if(r2->rIdx == r1->rIdx) {
6589 newreg = pic16_findFreeReg(REG_GPR);
6593 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6597 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6598 r1->rIdx, newreg->rIdx));
6599 r2->rIdx = newreg->rIdx;
6600 //if(r2->name) free(r2->name);
6602 r2->name = Safe_strdup(newreg->name);
6606 newreg->wasUsed = 1;
6608 r2 = setNextItem(pb->tregisters);
6611 r1 = setNextItem(registersInCallPath);
6614 /* Collisions have been resolved. Now free the registers in the call path */
6615 r1 = setFirstItem(registersInCallPath);
6617 if(r1->type != REG_STK) {
6618 newreg = pic16_regWithIdx(r1->rIdx);
6621 r1 = setNextItem(registersInCallPath);
6625 // MarkUsedRegisters(pb->registers);
6627 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6630 DFPRINTF((stderr,"returning regs\n"));
6632 DFPRINTF((stderr,"not returning regs\n"));
6634 DFPRINTF((stderr,"pBlock after register optim.\n"));
6635 pBlockStats(stderr,pb); // debug
6641 /*-----------------------------------------------------------------*/
6642 /* pct2 - writes the call tree to a file */
6644 /*-----------------------------------------------------------------*/
6645 static void pct2(FILE *of,pBlock *pb,int indent)
6649 // set *registersInCallPath = NULL;
6655 return; //recursion ?
6657 pc = setFirstItem(pb->function_entries);
6664 for(i=0;i<indent;i++) // Indentation
6667 if(pc->type == PC_FUNCTION)
6668 fprintf(of,"%s\n",PCF(pc)->fname);
6673 pc = setFirstItem(pb->function_calls);
6674 for( ; pc; pc = setNextItem(pb->function_calls)) {
6676 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6677 char *dest = pic16_get_op_from_instruction(PCI(pc));
6679 pcn = findFunction(dest);
6681 pct2(of,pcn->pb,indent+1);
6683 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6691 /*-----------------------------------------------------------------*/
6692 /* pic16_printCallTree - writes the call tree to a file */
6694 /*-----------------------------------------------------------------*/
6696 void pic16_printCallTree(FILE *of)
6708 fprintf(of, "\npBlock statistics\n");
6709 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6714 fprintf(of,"Call Tree\n");
6715 pbr = the_pFile->functions;
6719 if(!ispCodeFunction(pc))
6720 fprintf(of,"bug in call tree");
6723 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6725 while(pc->next && !ispCodeFunction(pc->next)) {
6727 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6728 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6736 fprintf(of,"\n**************\n\na better call tree\n");
6737 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6742 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6743 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6749 /*-----------------------------------------------------------------*/
6751 /*-----------------------------------------------------------------*/
6753 static void InlineFunction(pBlock *pb)
6761 pc = setFirstItem(pb->function_calls);
6763 for( ; pc; pc = setNextItem(pb->function_calls)) {
6766 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6772 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
6774 //fprintf(stderr,"Cool can inline:\n");
6775 //pcn->print(stderr,pcn);
6777 //fprintf(stderr,"recursive call Inline\n");
6778 InlineFunction(pcn->pb);
6779 //fprintf(stderr,"return from recursive call Inline\n");
6782 At this point, *pc points to a CALL mnemonic, and
6783 *pcn points to the function that is being called.
6785 To in-line this call, we need to remove the CALL
6786 and RETURN(s), and link the function pCode in with
6792 /* Remove the CALL */
6796 /* remove callee pBlock from the pBlock linked list */
6797 removepBlock(pcn->pb);
6805 /* Remove the Function pCode */
6806 pct = pic16_findNextInstruction(pcn->next);
6808 /* Link the function with the callee */
6809 pc->next = pcn->next;
6810 pcn->next->prev = pc;
6812 /* Convert the function name into a label */
6814 pbr = Safe_calloc(1,sizeof(pBranch));
6815 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6817 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6818 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6820 /* turn all of the return's except the last into goto's */
6821 /* check case for 2 instruction pBlocks */
6822 pce = pic16_findNextInstruction(pcn->next);
6824 pCode *pce_next = pic16_findNextInstruction(pce->next);
6826 if(pce_next == NULL) {
6827 /* found the last return */
6828 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6830 //fprintf(stderr,"found last return\n");
6831 //pce->print(stderr,pce);
6832 pce->prev->next = pc_call->next;
6833 pc_call->next->prev = pce->prev;
6834 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6844 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6850 /*-----------------------------------------------------------------*/
6852 /*-----------------------------------------------------------------*/
6854 void pic16_InlinepCode(void)
6863 if(!functionInlining)
6866 /* Loop through all of the function definitions and count the
6867 * number of times each one is called */
6868 //fprintf(stderr,"inlining %d\n",__LINE__);
6870 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6872 pc = setFirstItem(pb->function_calls);
6874 for( ; pc; pc = setNextItem(pb->function_calls)) {
6877 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6878 if(pcn && isPCF(pcn)) {
6879 PCF(pcn)->ncalled++;
6882 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6887 //fprintf(stderr,"inlining %d\n",__LINE__);
6889 /* Now, Loop through the function definitions again, but this
6890 * time inline those functions that have only been called once. */
6892 InlineFunction(the_pFile->pbHead);
6893 //fprintf(stderr,"inlining %d\n",__LINE__);
6895 for(pb = the_pFile->pbHead; pb; pb = pb->next)