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
30 #include "pcodeflow.h"
34 #if defined(__BORLANDC__) || defined(_MSC_VER)
35 #define STRCASECMP stricmp
37 #define STRCASECMP strcasecmp
40 /****************************************************************/
41 /****************************************************************/
43 static peepCommand peepCommands[] = {
45 {NOTBITSKIP, "_NOTBITSKIP_"},
46 {BITSKIP, "_BITSKIP_"},
47 {INVERTBITSKIP, "_INVERTBITSKIP_"},
54 // Eventually this will go into device dependent files:
55 pCodeOpReg pic16_pc_status = {{PO_STATUS, "_STATUS"}, -1, NULL,0,NULL};
56 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "_PCLATH"}, -1, NULL,0,NULL};
61 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
65 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
68 static int mnemonics_initialized = 0;
71 static hTab *pic16MnemonicsHash = NULL;
72 static hTab *pic16pCodePeepCommandsHash = NULL;
74 static pFile *the_pFile = NULL;
75 static pBlock *pb_dead_pcodes = NULL;
77 /* Hardcoded flags to change the behavior of the PIC port */
78 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
79 static int functionInlining = 1; /* inline functions if nonzero */
80 int pic16_debug_verbose = 1; /* Set true to inundate .asm file */
82 //static int GpCodeSequenceNumber = 1;
83 static int GpcFlowSeq = 1;
85 extern void pic16_RemoveUnusedRegisters(void);
86 extern void pic16_RegsUnMapLiveRanges(void);
87 extern void pic16_BuildFlowTree(pBlock *pb);
88 extern void pic16_pCodeRegOptimizeRegUsage(int level);
89 extern int pic16_picIsInitialized(void);
90 #if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
92 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
93 extern int mnem2key(char const *mnem);
94 #endif // OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
96 /****************************************************************/
97 /* Forward declarations */
98 /****************************************************************/
100 void pic16_unlinkpCode(pCode *pc);
102 static void genericAnalyze(pCode *pc);
103 static void AnalyzeGOTO(pCode *pc);
104 static void AnalyzeSKIP(pCode *pc);
105 static void AnalyzeRETURN(pCode *pc);
108 static void genericDestruct(pCode *pc);
109 static void genericPrint(FILE *of,pCode *pc);
111 static void pCodePrintLabel(FILE *of, pCode *pc);
112 static void pCodePrintFunction(FILE *of, pCode *pc);
113 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
114 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
115 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
116 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
117 int pic16_pCodePeepMatchRule(pCode *pc);
118 static void pBlockStats(FILE *of, pBlock *pb);
119 static pBlock *newpBlock(void);
120 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
121 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
122 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
123 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
126 /****************************************************************/
127 /* PIC Instructions */
128 /****************************************************************/
130 pCodeInstruction pic16_pciADDWF = {
131 {PC_OPCODE, NULL, NULL, 0, NULL,
144 1,0, // dest, bit instruction
146 0, // literal operand
148 0, // fast call/return mode select bit
149 0, // second memory operand
151 (PCC_W | PCC_REGISTER), // inCond
152 (PCC_REGISTER | PCC_Z) // outCond
155 pCodeInstruction pic16_pciADDFW = {
156 {PC_OPCODE, NULL, NULL, 0, NULL,
169 0,0, // dest, bit instruction
171 0, // literal operand
173 0, // fast call/return mode select bit
174 0, // second memory operand
176 (PCC_W | PCC_REGISTER), // inCond
177 (PCC_W | PCC_Z) // outCond
180 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
181 {PC_OPCODE, NULL, NULL, 0, NULL,
194 1,0, // dest, bit instruction
196 0, // literal operand
198 0, // fast call/return mode select bit
199 0, // second memory operand
201 (PCC_W | PCC_REGISTER | PCC_C), // inCond
202 (PCC_REGISTER | PCC_Z) // outCond
205 pCodeInstruction pic16_pciADDFWC = {
206 {PC_OPCODE, NULL, NULL, 0, NULL,
219 0,0, // dest, bit instruction
221 0, // literal operand
223 0, // fast call/return mode select bit
224 0, // second memory operand
226 (PCC_W | PCC_REGISTER | PCC_C), // inCond
227 (PCC_W | PCC_Z) // outCond
230 pCodeInstruction pic16_pciADDLW = {
231 {PC_OPCODE, NULL, NULL, 0, NULL,
244 0,0, // dest, bit instruction
246 1, // literal operand
248 0, // fast call/return mode select bit
249 0, // second memory operand
251 (PCC_W | PCC_LITERAL), // inCond
252 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
255 pCodeInstruction pic16_pciANDLW = {
256 {PC_OPCODE, NULL, NULL, 0, NULL,
269 0,0, // dest, bit instruction
271 1, // literal operand
273 0, // fast call/return mode select bit
274 0, // second memory operand
276 (PCC_W | PCC_LITERAL), // inCond
277 (PCC_W | PCC_Z | PCC_N) // outCond
280 pCodeInstruction pic16_pciANDWF = {
281 {PC_OPCODE, NULL, NULL, 0, NULL,
294 1,0, // dest, bit instruction
296 0, // literal operand
298 0, // fast call/return mode select bit
299 0, // second memory operand
301 (PCC_W | PCC_REGISTER), // inCond
302 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
305 pCodeInstruction pic16_pciANDFW = {
306 {PC_OPCODE, NULL, NULL, 0, NULL,
319 0,0, // dest, bit instruction
321 0, // literal operand
323 0, // fast call/return mode select bit
324 0, // second memory operand
326 (PCC_W | PCC_REGISTER), // inCond
327 (PCC_W | PCC_Z) // outCond
330 pCodeInstruction pic16_pciBC = { // mdubuc - New
331 {PC_OPCODE, NULL, NULL, 0, NULL,
344 0,0, // dest, bit instruction
346 0, // literal operand
348 0, // fast call/return mode select bit
349 0, // second memory operand
351 (PCC_REL_ADDR | PCC_C), // inCond
355 pCodeInstruction pic16_pciBCF = {
356 {PC_OPCODE, NULL, NULL, 0, NULL,
369 1,1, // dest, bit instruction
371 0, // literal operand
373 0, // fast call/return mode select bit
374 0, // second memory operand
376 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
377 PCC_REGISTER // outCond
380 pCodeInstruction pic16_pciBN = { // mdubuc - New
381 {PC_OPCODE, NULL, NULL, 0, NULL,
394 0,0, // dest, bit instruction
396 0, // literal operand
398 0, // fast call/return mode select bit
399 0, // second memory operand
401 (PCC_REL_ADDR | PCC_N), // inCond
405 pCodeInstruction pic16_pciBNC = { // mdubuc - New
406 {PC_OPCODE, NULL, NULL, 0, NULL,
419 0,0, // dest, bit instruction
421 0, // literal operand
423 0, // fast call/return mode select bit
424 0, // second memory operand
426 (PCC_REL_ADDR | PCC_C), // inCond
430 pCodeInstruction pic16_pciBNN = { // mdubuc - New
431 {PC_OPCODE, NULL, NULL, 0, NULL,
444 0,0, // dest, bit instruction
446 0, // literal operand
448 0, // fast call/return mode select bit
449 0, // second memory operand
451 (PCC_REL_ADDR | PCC_N), // inCond
455 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
456 {PC_OPCODE, NULL, NULL, 0, NULL,
469 0,0, // dest, bit instruction
471 0, // literal operand
473 0, // fast call/return mode select bit
474 0, // second memory operand
476 (PCC_REL_ADDR | PCC_OV), // inCond
480 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
481 {PC_OPCODE, NULL, NULL, 0, NULL,
494 0,0, // dest, bit instruction
496 0, // literal operand
498 0, // fast call/return mode select bit
499 0, // second memory operand
501 (PCC_REL_ADDR | PCC_Z), // inCond
505 pCodeInstruction pic16_pciBOV = { // mdubuc - New
506 {PC_OPCODE, NULL, NULL, 0, NULL,
519 0,0, // dest, bit instruction
521 0, // literal operand
523 0, // fast call/return mode select bit
524 0, // second memory operand
526 (PCC_REL_ADDR | PCC_OV), // inCond
530 pCodeInstruction pic16_pciBRA = { // mdubuc - New
531 {PC_OPCODE, NULL, NULL, 0, NULL,
544 0,0, // dest, bit instruction
546 0, // literal operand
548 0, // fast call/return mode select bit
549 0, // second memory operand
551 PCC_REL_ADDR, // inCond
555 pCodeInstruction pic16_pciBSF = {
556 {PC_OPCODE, NULL, NULL, 0, NULL,
569 1,1, // dest, bit instruction
571 0, // literal operand
573 0, // fast call/return mode select bit
574 0, // second memory operand
576 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
577 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
580 pCodeInstruction pic16_pciBTFSC = {
581 {PC_OPCODE, NULL, NULL, 0, NULL,
594 0,1, // dest, bit instruction
596 0, // literal operand
598 0, // fast call/return mode select bit
599 0, // second memory operand
601 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
602 PCC_EXAMINE_PCOP // outCond
605 pCodeInstruction pic16_pciBTFSS = {
606 {PC_OPCODE, NULL, NULL, 0, NULL,
619 0,1, // dest, bit instruction
621 0, // literal operand
623 0, // fast call/return mode select bit
624 0, // second memory operand
626 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
627 PCC_EXAMINE_PCOP // outCond
630 pCodeInstruction pic16_pciBTG = { // mdubuc - New
631 {PC_OPCODE, NULL, NULL, 0, NULL,
644 0,1, // dest, bit instruction
646 0, // literal operand
648 0, // fast call/return mode select bit
649 0, // second memory operand
651 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
652 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
655 pCodeInstruction pic16_pciBZ = { // mdubuc - New
656 {PC_OPCODE, NULL, NULL, 0, NULL,
669 0,0, // dest, bit instruction
671 0, // literal operand
673 0, // fast call/return mode select bit
674 0, // second memory operand
680 pCodeInstruction pic16_pciCALL = {
681 {PC_OPCODE, NULL, NULL, 0, NULL,
694 0,0, // dest, bit instruction
696 0, // literal operand
698 1, // fast call/return mode select bit
699 0, // second memory operand
705 pCodeInstruction pic16_pciCOMF = {
706 {PC_OPCODE, NULL, NULL, 0, NULL,
719 1,0, // dest, bit instruction
721 0, // literal operand
723 0, // fast call/return mode select bit
724 0, // second memory operand
726 PCC_REGISTER, // inCond
727 PCC_REGISTER // outCond
730 pCodeInstruction pic16_pciCOMFW = {
731 {PC_OPCODE, NULL, NULL, 0, NULL,
744 0,0, // dest, bit instruction
746 0, // literal operand
748 0, // fast call/return mode select bit
749 0, // second memory operand
751 PCC_REGISTER, // inCond
755 pCodeInstruction pic16_pciCLRF = {
756 {PC_OPCODE, NULL, NULL, 0, NULL,
769 0,0, // dest, bit instruction
771 0, // literal operand
773 0, // fast call/return mode select bit
774 0, // second memory operand
776 PCC_REGISTER, // inCond
777 PCC_REGISTER // outCond
780 pCodeInstruction pic16_pciCLRWDT = {
781 {PC_OPCODE, NULL, NULL, 0, NULL,
794 0,0, // dest, bit instruction
796 0, // literal operand
798 0, // fast call/return mode select bit
799 0, // second memory operand
805 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
806 {PC_OPCODE, NULL, NULL, 0, NULL,
819 0,0, // dest, bit instruction
821 0, // literal operand
823 0, // fast call/return mode select bit
824 0, // second memory operand
826 (PCC_W | PCC_REGISTER), // inCond
830 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
831 {PC_OPCODE, NULL, NULL, 0, NULL,
844 0,0, // dest, bit instruction
846 0, // literal operand
848 0, // fast call/return mode select bit
849 0, // second memory operand
851 (PCC_W | PCC_REGISTER), // inCond
855 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
856 {PC_OPCODE, NULL, NULL, 0, NULL,
869 1,0, // dest, bit instruction
871 0, // literal operand
873 0, // fast call/return mode select bit
874 0, // second memory operand
876 (PCC_W | PCC_REGISTER), // inCond
880 pCodeInstruction pic16_pciDAW = {
881 {PC_OPCODE, NULL, NULL, 0, NULL,
894 0,0, // dest, bit instruction
896 0, // literal operand
898 0, // fast call/return mode select bit
899 0, // second memory operand
902 (PCC_W | PCC_C) // outCond
905 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
906 {PC_OPCODE, NULL, NULL, 0, NULL,
919 1,0, // dest, bit instruction
921 0, // literal operand
923 0, // fast call/return mode select bit
924 0, // second memory operand
926 PCC_REGISTER, // inCond
927 PCC_REGISTER // outCond
930 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
931 {PC_OPCODE, NULL, NULL, 0, NULL,
944 0,0, // dest, bit instruction
946 0, // literal operand
948 0, // fast call/return mode select bit
949 0, // second memory operand
951 PCC_REGISTER, // inCond
955 pCodeInstruction pic16_pciDECF = {
956 {PC_OPCODE, NULL, NULL, 0, NULL,
969 1,0, // dest, bit instruction
971 0, // literal operand
973 0, // fast call/return mode select bit
974 0, // second memory operand
976 PCC_REGISTER, // inCond
977 PCC_REGISTER // outCond
980 pCodeInstruction pic16_pciDECFW = {
981 {PC_OPCODE, NULL, NULL, 0, NULL,
994 0,0, // dest, bit instruction
996 0, // literal operand
998 0, // fast call/return mode select bit
999 0, // second memory operand
1001 PCC_REGISTER, // inCond
1005 pCodeInstruction pic16_pciDECFSZ = {
1006 {PC_OPCODE, NULL, NULL, 0, NULL,
1012 NULL, // from branch
1019 1,0, // dest, bit instruction
1020 1,1, // branch, skip
1021 0, // literal operand
1022 1, // RAM access bit
1023 0, // fast call/return mode select bit
1024 0, // second memory operand
1026 PCC_REGISTER, // inCond
1027 PCC_REGISTER // outCond
1030 pCodeInstruction pic16_pciDECFSZW = {
1031 {PC_OPCODE, NULL, NULL, 0, NULL,
1037 NULL, // from branch
1044 0,0, // dest, bit instruction
1045 1,1, // branch, skip
1046 0, // literal operand
1047 1, // RAM access bit
1048 0, // fast call/return mode select bit
1049 0, // second memory operand
1051 PCC_REGISTER, // inCond
1055 pCodeInstruction pic16_pciGOTO = {
1056 {PC_OPCODE, NULL, NULL, 0, NULL,
1062 NULL, // from branch
1069 0,0, // dest, bit instruction
1070 1,0, // branch, skip
1071 0, // literal operand
1072 0, // RAM access bit
1073 0, // fast call/return mode select bit
1074 0, // second memory operand
1076 PCC_REL_ADDR, // inCond
1080 pCodeInstruction pic16_pciINCF = {
1081 {PC_OPCODE, NULL, NULL, 0, NULL,
1087 NULL, // from branch
1094 1,0, // dest, bit instruction
1095 0,0, // branch, skip
1096 0, // literal operand
1097 1, // RAM access bit
1098 0, // fast call/return mode select bit
1099 0, // second memory operand
1101 PCC_REGISTER, // inCond
1102 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1105 pCodeInstruction pic16_pciINCFW = {
1106 {PC_OPCODE, NULL, NULL, 0, NULL,
1112 NULL, // from branch
1119 0,0, // dest, bit instruction
1120 0,0, // branch, skip
1121 0, // literal operand
1122 1, // RAM access bit
1123 0, // fast call/return mode select bit
1124 0, // second memory operand
1126 PCC_REGISTER, // inCond
1130 pCodeInstruction pic16_pciINCFSZ = {
1131 {PC_OPCODE, NULL, NULL, 0, NULL,
1137 NULL, // from branch
1144 1,0, // dest, bit instruction
1145 1,1, // branch, skip
1146 0, // literal operand
1147 1, // RAM access bit
1148 0, // fast call/return mode select bit
1149 0, // second memory operand
1151 PCC_REGISTER, // inCond
1152 PCC_REGISTER // outCond
1155 pCodeInstruction pic16_pciINCFSZW = {
1156 {PC_OPCODE, NULL, NULL, 0, NULL,
1162 NULL, // from branch
1169 0,0, // dest, bit instruction
1170 1,1, // branch, skip
1171 0, // literal operand
1172 1, // RAM access bit
1173 0, // fast call/return mode select bit
1174 0, // second memory operand
1176 PCC_REGISTER, // inCond
1180 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1181 {PC_OPCODE, NULL, NULL, 0, NULL,
1187 NULL, // from branch
1194 1,0, // dest, bit instruction
1195 1,1, // branch, skip
1196 0, // literal operand
1197 1, // RAM access bit
1198 0, // fast call/return mode select bit
1199 0, // second memory operand
1201 PCC_REGISTER, // inCond
1202 PCC_REGISTER // outCond
1205 pCodeInstruction pic16_pciIORWF = {
1206 {PC_OPCODE, NULL, NULL, 0, NULL,
1212 NULL, // from branch
1219 1,0, // dest, bit instruction
1220 0,0, // branch, skip
1221 0, // literal operand
1222 1, // RAM access bit
1223 0, // fast call/return mode select bit
1224 0, // second memory operand
1226 (PCC_W | PCC_REGISTER), // inCond
1227 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1230 pCodeInstruction pic16_pciIORFW = {
1231 {PC_OPCODE, NULL, NULL, 0, NULL,
1237 NULL, // from branch
1244 0,0, // dest, bit instruction
1245 0,0, // branch, skip
1246 0, // literal operand
1247 1, // RAM access bit
1248 0, // fast call/return mode select bit
1249 0, // second memory operand
1251 (PCC_W | PCC_REGISTER), // inCond
1252 (PCC_W | PCC_Z | PCC_N) // outCond
1255 pCodeInstruction pic16_pciIORLW = {
1256 {PC_OPCODE, NULL, NULL, 0, NULL,
1262 NULL, // from branch
1269 0,0, // dest, bit instruction
1270 0,0, // branch, skip
1271 1, // literal operand
1272 0, // RAM access bit
1273 0, // fast call/return mode select bit
1274 0, // second memory operand
1276 (PCC_W | PCC_LITERAL), // inCond
1277 (PCC_W | PCC_Z | PCC_N) // outCond
1280 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1281 {PC_OPCODE, NULL, NULL, 0, NULL,
1287 NULL, // from branch
1294 0,0, // dest, bit instruction
1295 0,0, // branch, skip
1296 1, // literal operand
1297 0, // RAM access bit
1298 0, // fast call/return mode select bit
1299 0, // second memory operand
1301 (PCC_REGISTER | PCC_LITERAL), // mdubuc - Should we use a special syntax for
1302 // f (identifies FSRx)?
1303 PCC_REGISTER // outCond
1306 pCodeInstruction pic16_pciMOVF = {
1307 {PC_OPCODE, NULL, NULL, 0, NULL,
1313 NULL, // from branch
1320 1,0, // dest, bit instruction
1321 0,0, // branch, skip
1322 0, // literal operand
1323 1, // RAM access bit
1324 0, // fast call/return mode select bit
1325 0, // second memory operand
1327 PCC_REGISTER, // inCond
1328 (PCC_Z | PCC_N) // outCond
1331 pCodeInstruction pic16_pciMOVFW = {
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
1352 PCC_REGISTER, // inCond
1353 (PCC_W | PCC_Z) // outCond
1356 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1357 {PC_OPCODE, NULL, NULL, 0, NULL,
1363 NULL, // from branch
1370 0,0, // dest, bit instruction
1371 0,0, // branch, skip
1372 0, // literal operand
1373 0, // RAM access bit
1374 0, // fast call/return mode select bit
1375 1, // second memory operand
1377 PCC_REGISTER, // inCond
1378 PCC_REGISTER2 // outCond
1381 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1382 {PC_OPCODE, NULL, NULL, 0, NULL,
1387 NULL, // from branch
1394 0,0, // dest, bit instruction
1395 0,0, // branch, skip
1396 1, // literal operand
1397 0, // RAM access bit
1398 0, // fast call/return mode select bit
1399 0, // second memory operand
1401 (PCC_NONE | PCC_LITERAL), // inCond
1402 PCC_REGISTER // outCond - BSR
1405 pCodeInstruction pic16_pciMOVLW = {
1406 {PC_OPCODE, NULL, NULL, 0, NULL,
1411 NULL, // from branch
1418 0,0, // dest, bit instruction
1419 0,0, // branch, skip
1420 1, // literal operand
1421 0, // RAM access bit
1422 0, // fast call/return mode select bit
1423 0, // second memory operand
1425 (PCC_NONE | PCC_LITERAL), // inCond
1429 pCodeInstruction pic16_pciMOVWF = {
1430 {PC_OPCODE, NULL, NULL, 0, NULL,
1436 NULL, // from branch
1443 0,0, // dest, bit instruction
1444 0,0, // branch, skip
1445 0, // literal operand
1446 1, // RAM access bit
1447 0, // fast call/return mode select bit
1448 0, // second memory operand
1450 PCC_REGISTER, // inCond
1454 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1455 {PC_OPCODE, NULL, NULL, 0, NULL,
1460 NULL, // from branch
1467 0,0, // dest, bit instruction
1468 0,0, // branch, skip
1469 1, // literal operand
1470 0, // RAM access bit
1471 0, // fast call/return mode select bit
1472 0, // second memory operand
1474 (PCC_W | PCC_LITERAL), // inCond
1475 PCC_REGISTER // outCond - PROD
1478 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1479 {PC_OPCODE, NULL, NULL, 0, NULL,
1484 NULL, // from branch
1491 0,0, // dest, bit instruction
1492 0,0, // branch, skip
1493 0, // literal operand
1494 1, // RAM access bit
1495 0, // fast call/return mode select bit
1496 0, // second memory operand
1498 (PCC_W | PCC_REGISTER), // inCond
1499 PCC_REGISTER // outCond - PROD
1502 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1503 {PC_OPCODE, NULL, NULL, 0, NULL,
1508 NULL, // from branch
1515 0,0, // dest, bit instruction
1516 0,0, // branch, skip
1517 0, // literal operand
1518 1, // RAM access bit
1519 0, // fast call/return mode select bit
1520 0, // second memory operand
1522 PCC_REGISTER, // inCond
1523 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
1526 pCodeInstruction pic16_pciNOP = {
1527 {PC_OPCODE, NULL, NULL, 0, NULL,
1532 NULL, // from branch
1539 0,0, // dest, bit instruction
1540 0,0, // branch, skip
1541 0, // literal operand
1542 0, // RAM access bit
1543 0, // fast call/return mode select bit
1544 0, // second memory operand
1550 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1551 {PC_OPCODE, NULL, NULL, 0, NULL,
1556 NULL, // from branch
1563 0,0, // dest, bit instruction
1564 0,0, // branch, skip
1565 0, // literal operand
1566 0, // RAM access bit
1567 0, // fast call/return mode select bit
1568 0, // second memory operand
1574 pCodeInstruction pic16_pciPUSH = {
1575 {PC_OPCODE, NULL, NULL, 0, NULL,
1580 NULL, // from branch
1587 0,0, // dest, bit instruction
1588 0,0, // branch, skip
1589 0, // literal operand
1590 0, // RAM access bit
1591 0, // fast call/return mode select bit
1592 0, // second memory operand
1598 pCodeInstruction pic16_pciRCALL = { // 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 0, // RAM access bit
1615 0, // fast call/return mode select bit
1616 0, // second memory operand
1618 PCC_REL_ADDR, // inCond
1622 pCodeInstruction pic16_pciRETFIE = {
1623 {PC_OPCODE, NULL, NULL, 0, NULL,
1629 NULL, // from branch
1636 0,0, // dest, bit instruction
1637 1,0, // branch, skip
1638 0, // literal operand
1639 0, // RAM access bit
1640 1, // fast call/return mode select bit
1641 0, // second memory operand
1644 PCC_NONE // outCond (not true... affects the GIE bit too)
1647 pCodeInstruction pic16_pciRETLW = {
1648 {PC_OPCODE, NULL, NULL, 0, NULL,
1654 NULL, // from branch
1661 0,0, // dest, bit instruction
1662 1,0, // branch, skip
1663 1, // literal operand
1664 0, // RAM access bit
1665 0, // fast call/return mode select bit
1666 0, // second memory operand
1668 PCC_LITERAL, // inCond
1672 pCodeInstruction pic16_pciRETURN = {
1673 {PC_OPCODE, NULL, NULL, 0, NULL,
1679 NULL, // from branch
1686 0,0, // dest, bit instruction
1687 1,0, // branch, skip
1688 0, // literal operand
1689 0, // RAM access bit
1690 1, // fast call/return mode select bit
1691 0, // second memory operand
1696 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1697 {PC_OPCODE, NULL, NULL, 0, NULL,
1703 NULL, // from branch
1710 1,0, // dest, bit instruction
1711 0,0, // branch, skip
1712 0, // literal operand
1713 1, // RAM access bit
1714 0, // fast call/return mode select bit
1715 0, // second memory operand
1717 (PCC_C | PCC_REGISTER), // inCond
1718 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1721 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1722 {PC_OPCODE, NULL, NULL, 0, NULL,
1728 NULL, // from branch
1735 0,0, // dest, bit instruction
1736 0,0, // branch, skip
1737 0, // literal operand
1738 1, // RAM access bit
1739 0, // fast call/return mode select bit
1740 0, // second memory operand
1742 (PCC_C | PCC_REGISTER), // inCond
1743 (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1746 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1747 {PC_OPCODE, NULL, NULL, 0, NULL,
1753 NULL, // from branch
1760 1,0, // dest, bit instruction
1761 0,0, // branch, skip
1762 0, // literal operand
1763 1, // RAM access bit
1764 0, // fast call/return mode select bit
1765 0, // second memory operand
1767 PCC_REGISTER, // inCond
1768 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1770 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1771 {PC_OPCODE, NULL, NULL, 0, NULL,
1777 NULL, // from branch
1784 0,0, // dest, bit instruction
1785 0,0, // branch, skip
1786 0, // literal operand
1787 1, // RAM access bit
1788 0, // fast call/return mode select bit
1789 0, // second memory operand
1791 PCC_REGISTER, // inCond
1792 (PCC_W | PCC_Z | PCC_N) // outCond
1794 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1795 {PC_OPCODE, NULL, NULL, 0, NULL,
1801 NULL, // from branch
1808 1,0, // dest, bit instruction
1809 0,0, // branch, skip
1810 0, // literal operand
1811 1, // RAM access bit
1812 0, // fast call/return mode select bit
1813 0, // second memory operand
1815 (PCC_C | PCC_REGISTER), // inCond
1816 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1818 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1819 {PC_OPCODE, NULL, NULL, 0, NULL,
1825 NULL, // from branch
1832 0,0, // dest, bit instruction
1833 0,0, // branch, skip
1834 0, // literal operand
1835 1, // RAM access bit
1836 0, // fast call/return mode select bit
1837 0, // second memory operand
1839 (PCC_C | PCC_REGISTER), // inCond
1840 (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1842 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
1843 {PC_OPCODE, NULL, NULL, 0, NULL,
1849 NULL, // from branch
1856 1,0, // dest, bit instruction
1857 0,0, // branch, skip
1858 0, // literal operand
1859 1, // RAM access bit
1860 0, // fast call/return mode select bit
1861 0, // second memory operand
1863 PCC_REGISTER, // inCond
1864 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1867 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
1868 {PC_OPCODE, NULL, NULL, 0, NULL,
1874 NULL, // from branch
1881 0,0, // dest, bit instruction
1882 0,0, // branch, skip
1883 0, // literal operand
1884 1, // RAM access bit
1885 0, // fast call/return mode select bit
1886 0, // second memory operand
1888 PCC_REGISTER, // inCond
1889 (PCC_W | PCC_Z | PCC_N) // outCond
1892 pCodeInstruction pic16_pciSETF = { // mdubuc - New
1893 {PC_OPCODE, NULL, NULL, 0, NULL,
1899 NULL, // from branch
1906 0,0, // dest, bit instruction
1907 0,0, // branch, skip
1908 0, // literal operand
1909 1, // RAM access bit
1910 0, // fast call/return mode select bit
1911 0, // second memory operand
1913 PCC_REGISTER, // inCond
1914 PCC_REGISTER // outCond
1917 pCodeInstruction pic16_pciSUBLW = {
1918 {PC_OPCODE, NULL, NULL, 0, NULL,
1924 NULL, // from branch
1931 0,0, // dest, bit instruction
1932 0,0, // branch, skip
1933 1, // literal operand
1934 0, // RAM access bit
1935 0, // fast call/return mode select bit
1936 0, // second memory operand
1938 (PCC_W | PCC_LITERAL), // inCond
1939 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1942 pCodeInstruction pic16_pciSUBFWB = {
1943 {PC_OPCODE, NULL, NULL, 0, NULL,
1949 NULL, // from branch
1956 1,0, // dest, bit instruction
1957 0,0, // branch, skip
1958 0, // literal operand
1959 1, // RAM access bit
1960 0, // fast call/return mode select bit
1961 0, // second memory operand
1963 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1964 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1967 pCodeInstruction pic16_pciSUBWF = {
1968 {PC_OPCODE, NULL, NULL, 0, NULL,
1974 NULL, // from branch
1981 1,0, // dest, bit instruction
1982 0,0, // branch, skip
1983 0, // literal operand
1984 1, // RAM access bit
1985 0, // fast call/return mode select bit
1986 0, // second memory operand
1988 (PCC_W | PCC_REGISTER), // inCond
1989 (PCC_REGISTER | PCC_Z) // outCond
1992 pCodeInstruction pic16_pciSUBFW = {
1993 {PC_OPCODE, NULL, NULL, 0, NULL,
1999 NULL, // from branch
2006 0,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
2013 (PCC_W | PCC_REGISTER), // inCond
2014 (PCC_W | PCC_Z | PCC_OV | PCC_N) // outCond
2017 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2018 {PC_OPCODE, NULL, NULL, 0, NULL,
2024 NULL, // from branch
2031 1,0, // dest, bit instruction
2032 0,0, // branch, skip
2033 0, // literal operand
2034 1, // RAM access bit
2035 0, // fast call/return mode select bit
2036 0, // second memory operand
2038 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2039 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2042 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2043 {PC_OPCODE, NULL, NULL, 0, NULL,
2049 NULL, // from branch
2056 0,0, // dest, bit instruction
2057 0,0, // branch, skip
2058 0, // literal operand
2059 1, // RAM access bit
2060 0, // fast call/return mode select bit
2061 0, // second memory operand
2063 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2064 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2067 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2068 {PC_OPCODE, NULL, NULL, 0, NULL,
2074 NULL, // from branch
2081 1,0, // dest, bit instruction
2082 0,0, // branch, skip
2083 0, // literal operand
2084 1, // RAM access bit
2085 0, // fast call/return mode select bit
2086 0, // second memory operand
2088 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2089 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2092 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2093 {PC_OPCODE, NULL, NULL, 0, NULL,
2099 NULL, // from branch
2106 0,0, // dest, bit instruction
2107 0,0, // branch, skip
2108 0, // literal operand
2109 1, // RAM access bit
2110 0, // fast call/return mode select bit
2111 0, // second memory operand
2113 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2114 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2117 pCodeInstruction pic16_pciSWAPF = {
2118 {PC_OPCODE, NULL, NULL, 0, NULL,
2124 NULL, // from branch
2131 1,0, // dest, bit instruction
2132 0,0, // branch, skip
2133 0, // literal operand
2134 1, // RAM access bit
2135 0, // fast call/return mode select bit
2136 0, // second memory operand
2138 (PCC_REGISTER), // inCond
2139 (PCC_REGISTER) // outCond
2142 pCodeInstruction pic16_pciSWAPFW = {
2143 {PC_OPCODE, NULL, NULL, 0, NULL,
2149 NULL, // from branch
2156 0,0, // dest, bit instruction
2157 0,0, // branch, skip
2158 0, // literal operand
2159 1, // RAM access bit
2160 0, // fast call/return mode select bit
2161 0, // second memory operand
2163 (PCC_REGISTER), // inCond
2169 // mdubuc - Remove TRIS
2171 pCodeInstruction pic16_pciTRIS = {
2172 {PC_OPCODE, NULL, NULL, 0, NULL,
2178 NULL, // from branch
2185 0,0, // dest, bit instruction
2186 0,0, // branch, skip
2187 0, // literal operand
2188 0, // second memory operand
2191 PCC_REGISTER // outCond
2195 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2196 {PC_OPCODE, NULL, NULL, 0, NULL,
2202 NULL, // from branch
2209 0,0, // dest, bit instruction
2210 1,1, // branch, skip
2211 0, // literal operand
2212 1, // RAM access bit
2213 0, // fast call/return mode select bit
2214 0, // second memory operand
2216 PCC_REGISTER, // inCond
2220 pCodeInstruction pic16_pciXORWF = {
2221 {PC_OPCODE, NULL, NULL, 0, NULL,
2227 NULL, // from branch
2234 1,0, // dest, bit instruction
2235 0,0, // branch, skip
2236 0, // literal operand
2237 1, // RAM access bit
2238 0, // fast call/return mode select bit
2239 0, // second memory operand
2241 (PCC_W | PCC_REGISTER), // inCond
2242 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
2245 pCodeInstruction pic16_pciXORFW = {
2246 {PC_OPCODE, NULL, NULL, 0, NULL,
2252 NULL, // from branch
2259 0,0, // dest, bit instruction
2260 0,0, // branch, skip
2261 0, // literal operand
2262 1, // RAM access bit
2263 0, // fast call/return mode select bit
2264 0, // second memory operand
2266 (PCC_W | PCC_REGISTER), // inCond
2267 (PCC_W | PCC_Z | PCC_N) // outCond
2270 pCodeInstruction pic16_pciXORLW = {
2271 {PC_OPCODE, NULL, NULL, 0, NULL,
2277 NULL, // from branch
2284 0,0, // dest, bit instruction
2285 0,0, // branch, skip
2286 1, // literal operand
2287 1, // RAM access bit
2288 0, // fast call/return mode select bit
2289 0, // second memory operand
2291 (PCC_W | PCC_LITERAL), // inCond
2292 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N) // outCond
2296 #define MAX_PIC16MNEMONICS 100
2297 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2300 /* This definition needs to be part of configure.in */
2301 // #define USE_VSNPRINTF
2303 #ifdef USE_VSNPRINTF
2304 // Alas, vsnprintf is not ANSI standard, and does not exist
2305 // on Solaris (and probably other non-Gnu flavored Unixes).
2307 /*-----------------------------------------------------------------*/
2308 /* SAFE_snprintf - like snprintf except the string pointer is */
2309 /* after the string has been printed to. This is */
2310 /* useful for printing to string as though if it */
2311 /* were a stream. */
2312 /*-----------------------------------------------------------------*/
2313 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2321 va_start(val, format);
2323 vsnprintf(*str, *size, format, val);
2329 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2330 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2338 #else // USE_VSNPRINTF
2340 // This version is *not* safe, despite the name.
2342 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2346 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2351 va_start(val, format);
2353 vsprintf(buffer, format, val);
2356 len = strlen(buffer);
2358 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2359 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2362 strcpy(*str, buffer);
2368 #endif // USE_VSNPRINTF
2370 #endif // OPT_DISABLE_PIC
2373 extern void pic16_initStack(int base_address, int size);
2374 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2375 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2376 extern void pic16_init_pic(char *);
2378 void pic16_pCodeInitRegisters(void)
2380 static int initialized=0;
2386 pic16_initStack(0xfff, 8);
2387 pic16_init_pic(port->processor);
2389 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
2390 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2391 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
2392 pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80);
2393 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2394 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2395 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2397 pic16_pc_status.rIdx = IDX_STATUS;
2398 pic16_pc_fsr0.rIdx = IDX_FSR0;
2399 pic16_pc_indf0.rIdx = IDX_INDF0;
2400 pic16_pc_intcon.rIdx = IDX_INTCON;
2401 pic16_pc_pcl.rIdx = IDX_PCL;
2402 pic16_pc_pclath.rIdx = IDX_PCLATH;
2403 pic16_pc_wreg.rIdx = IDX_WREG;
2405 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2406 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
2407 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2409 pic16_pc_kzero.rIdx = IDX_KZ;
2410 pic16_pc_wsave.rIdx = IDX_WSAVE;
2411 pic16_pc_ssave.rIdx = IDX_SSAVE;
2413 /* probably should put this in a separate initialization routine */
2414 pb_dead_pcodes = newpBlock();
2419 /*-----------------------------------------------------------------*/
2420 /* mnem2key - convert a pic mnemonic into a hash key */
2421 /* (BTW - this spreads the mnemonics quite well) */
2423 /*-----------------------------------------------------------------*/
2425 int mnem2key(char const *mnem)
2434 key += toupper(*mnem++) +1;
2438 return (key & 0x1f);
2441 #endif // OPT_DISABLE_PIC
2443 void pic16initMnemonics(void)
2448 pCodeInstruction *pci;
2450 if(mnemonics_initialized)
2453 // NULL out the array before making the assignments
2454 // since we check the array contents below this initialization.
2456 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2457 pic16Mnemonics[i] = NULL;
2460 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2461 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2462 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2463 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2464 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2465 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2466 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2467 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2468 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2469 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2470 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2471 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2472 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2473 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2474 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2475 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2476 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2477 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2478 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2479 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2480 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2481 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2482 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2483 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2484 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2485 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2486 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2487 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2488 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2489 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2490 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2491 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2492 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2493 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2494 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2495 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2496 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2497 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2498 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2499 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2500 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2501 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2502 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2503 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2504 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2505 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2506 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2507 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2508 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2509 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2510 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2511 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2512 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2513 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2514 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2515 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2516 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2517 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2518 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2519 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2520 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2521 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2522 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2523 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2524 pic16Mnemonics[POC_RLCF] = &pic16_pciRLNCF;
2525 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2526 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2527 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2528 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2529 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2530 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2531 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2532 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2533 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2534 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2535 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2536 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2537 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2538 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2539 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
2540 // pic16Mnemonics[POC_TRIS] = &pic16_pciTRIS;
2541 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
2542 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
2543 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
2544 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
2546 for(i=0; i<MAX_PIC16MNEMONICS; i++)
2547 if(pic16Mnemonics[i])
2548 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
2549 pci = hTabFirstItem(pic16MnemonicsHash, &key);
2552 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
2553 pci = hTabNextItem(pic16MnemonicsHash, &key);
2556 mnemonics_initialized = 1;
2559 int pic16_getpCodePeepCommand(char *cmd);
2561 int pic16_getpCode(char *mnem,unsigned dest)
2564 pCodeInstruction *pci;
2565 int key = mnem2key(mnem);
2567 if(!mnemonics_initialized)
2568 pic16initMnemonics();
2570 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
2574 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
2575 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst) ||
2576 (pci->num_ops <= 2 && pci->isAccess) ||
2577 (pci->num_ops <= 2 && pci->isFastCall))
2581 pci = hTabNextItemWK (pic16MnemonicsHash);
2588 /*-----------------------------------------------------------------*
2589 * pic16initpCodePeepCommands
2591 *-----------------------------------------------------------------*/
2592 void pic16initpCodePeepCommands(void)
2600 hTabAddItem(&pic16pCodePeepCommandsHash,
2601 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
2603 } while (peepCommands[i].cmd);
2605 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
2608 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
2609 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
2614 /*-----------------------------------------------------------------
2617 *-----------------------------------------------------------------*/
2619 int pic16_getpCodePeepCommand(char *cmd)
2623 int key = mnem2key(cmd);
2626 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
2629 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2630 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2634 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
2641 static char getpBlock_dbName(pBlock *pb)
2647 return pb->cmemmap->dbName;
2651 void pic16_pBlockConvert2ISR(pBlock *pb)
2662 /*-----------------------------------------------------------------*/
2663 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
2664 /* instances to the front of the doubly linked */
2665 /* list of pBlocks */
2666 /*-----------------------------------------------------------------*/
2668 void pic16_movepBlock2Head(char dbName)
2672 pb = the_pFile->pbHead;
2676 if(getpBlock_dbName(pb) == dbName) {
2677 pBlock *pbn = pb->next;
2678 pb->next = the_pFile->pbHead;
2679 the_pFile->pbHead->prev = pb;
2680 the_pFile->pbHead = pb;
2683 pb->prev->next = pbn;
2685 // If the pBlock that we just moved was the last
2686 // one in the link of all of the pBlocks, then we
2687 // need to point the tail to the block just before
2688 // the one we moved.
2689 // Note: if pb->next is NULL, then pb must have
2690 // been the last pBlock in the chain.
2693 pbn->prev = pb->prev;
2695 the_pFile->pbTail = pb->prev;
2706 void pic16_copypCode(FILE *of, char dbName)
2710 if(!of || !the_pFile)
2713 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2714 if(getpBlock_dbName(pb) == dbName) {
2716 pic16_printpBlock(of,pb);
2721 void pic16_pcode_test(void)
2724 DFPRINTF((stderr,"pcode is alive!\n"));
2734 /* create the file name */
2735 strcpy(buffer,dstFileName);
2736 strcat(buffer,".p");
2738 if( !(pFile = fopen(buffer, "w" ))) {
2739 werror(E_FILE_OPEN_ERR,buffer);
2743 fprintf(pFile,"pcode dump\n\n");
2745 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2746 fprintf(pFile,"\n\tNew pBlock\n\n");
2748 fprintf(pFile,"%s",pb->cmemmap->sname);
2750 fprintf(pFile,"internal pblock");
2752 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2753 pic16_printpBlock(pFile,pb);
2757 /*-----------------------------------------------------------------*/
2758 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
2759 /* ister, RegCond will return the bit being referenced. */
2761 /* fixme - why not just OR in the pcop bit field */
2762 /*-----------------------------------------------------------------*/
2764 static int RegCond(pCodeOp *pcop)
2770 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
2771 switch(PCORB(pcop)->bit) {
2785 /*-----------------------------------------------------------------*/
2786 /* pic16_newpCode - create and return a newly initialized pCode */
2788 /* fixme - rename this */
2790 /* The purpose of this routine is to create a new Instruction */
2791 /* pCode. This is called by gen.c while the assembly code is being */
2795 /* PIC_OPCODE op - the assembly instruction we wish to create. */
2796 /* (note that the op is analogous to but not the */
2797 /* same thing as the opcode of the instruction.) */
2798 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
2801 /* a pointer to the new malloc'd pCode is returned. */
2805 /*-----------------------------------------------------------------*/
2806 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
2808 pCodeInstruction *pci ;
2810 if(!mnemonics_initialized)
2811 pic16initMnemonics();
2813 pci = Safe_calloc(1, sizeof(pCodeInstruction));
2815 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
2816 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
2819 if(pci->inCond & PCC_EXAMINE_PCOP)
2820 pci->inCond |= RegCond(pcop);
2822 if(pci->outCond & PCC_EXAMINE_PCOP)
2823 pci->outCond |= RegCond(pcop);
2825 pci->pc.prev = pci->pc.next = NULL;
2826 return (pCode *)pci;
2829 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
2835 /*-----------------------------------------------------------------*/
2836 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
2838 /* Wild pcodes are used during the peep hole optimizer to serve */
2839 /* as place holders for any instruction. When a snippet of code is */
2840 /* compared to a peep hole rule, the wild card opcode will match */
2841 /* any instruction. However, the optional operand and label are */
2842 /* additional qualifiers that must also be matched before the */
2843 /* line (of assembly code) is declared matched. Note that the */
2844 /* operand may be wild too. */
2846 /* Note, a wild instruction is specified just like a wild var: */
2847 /* %4 ; A wild instruction, */
2848 /* See the peeph.def file for additional examples */
2850 /*-----------------------------------------------------------------*/
2852 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
2857 pcw = Safe_calloc(1,sizeof(pCodeWild));
2859 pcw->pci.pc.type = PC_WILD;
2860 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
2861 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
2862 pcw->pci.pc.pb = NULL;
2864 // pcw->pci.pc.analyze = genericAnalyze;
2865 pcw->pci.pc.destruct = genericDestruct;
2866 pcw->pci.pc.print = genericPrint;
2868 pcw->id = pCodeID; // this is the 'n' in %n
2869 pcw->operand = optional_operand;
2870 pcw->label = optional_label;
2872 pcw->mustBeBitSkipInst = 0;
2873 pcw->mustNotBeBitSkipInst = 0;
2874 pcw->invertBitSkipInst = 0;
2876 return ( (pCode *)pcw);
2880 /*-----------------------------------------------------------------*/
2881 /* newPcodeInlineP - create a new pCode from a char string */
2882 /*-----------------------------------------------------------------*/
2885 pCode *pic16_newpCodeInlineP(char *cP)
2890 pcc = Safe_calloc(1,sizeof(pCodeComment));
2892 pcc->pc.type = PC_INLINE;
2893 pcc->pc.prev = pcc->pc.next = NULL;
2894 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2897 // pcc->pc.analyze = genericAnalyze;
2898 pcc->pc.destruct = genericDestruct;
2899 pcc->pc.print = genericPrint;
2902 pcc->comment = Safe_strdup(cP);
2904 pcc->comment = NULL;
2906 return ( (pCode *)pcc);
2910 /*-----------------------------------------------------------------*/
2911 /* newPcodeCharP - create a new pCode from a char string */
2912 /*-----------------------------------------------------------------*/
2914 pCode *pic16_newpCodeCharP(char *cP)
2919 pcc = Safe_calloc(1,sizeof(pCodeComment));
2921 pcc->pc.type = PC_COMMENT;
2922 pcc->pc.prev = pcc->pc.next = NULL;
2923 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2926 // pcc->pc.analyze = genericAnalyze;
2927 pcc->pc.destruct = genericDestruct;
2928 pcc->pc.print = genericPrint;
2931 pcc->comment = Safe_strdup(cP);
2933 pcc->comment = NULL;
2935 return ( (pCode *)pcc);
2939 /*-----------------------------------------------------------------*/
2940 /* pic16_newpCodeFunction - */
2941 /*-----------------------------------------------------------------*/
2944 pCode *pic16_newpCodeFunction(char *mod,char *f)
2948 pcf = Safe_calloc(1,sizeof(pCodeFunction));
2949 //_ALLOC(pcf,sizeof(pCodeFunction));
2951 pcf->pc.type = PC_FUNCTION;
2952 pcf->pc.prev = pcf->pc.next = NULL;
2953 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
2956 // pcf->pc.analyze = genericAnalyze;
2957 pcf->pc.destruct = genericDestruct;
2958 pcf->pc.print = pCodePrintFunction;
2963 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
2964 pcf->modname = Safe_calloc(1,strlen(mod)+1);
2965 strcpy(pcf->modname,mod);
2967 pcf->modname = NULL;
2970 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
2971 pcf->fname = Safe_calloc(1,strlen(f)+1);
2972 strcpy(pcf->fname,f);
2976 return ( (pCode *)pcf);
2980 /*-----------------------------------------------------------------*/
2981 /* pic16_newpCodeFlow */
2982 /*-----------------------------------------------------------------*/
2983 static void destructpCodeFlow(pCode *pc)
2985 if(!pc || !isPCFL(pc))
2992 pic16_unlinkpCode(pc);
2994 deleteSet(&PCFL(pc)->registers);
2995 deleteSet(&PCFL(pc)->from);
2996 deleteSet(&PCFL(pc)->to);
3001 pCode *pic16_newpCodeFlow(void )
3005 //_ALLOC(pcflow,sizeof(pCodeFlow));
3006 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3008 pcflow->pc.type = PC_FLOW;
3009 pcflow->pc.prev = pcflow->pc.next = NULL;
3010 pcflow->pc.pb = NULL;
3012 // pcflow->pc.analyze = genericAnalyze;
3013 pcflow->pc.destruct = destructpCodeFlow;
3014 pcflow->pc.print = genericPrint;
3016 pcflow->pc.seq = GpcFlowSeq++;
3018 pcflow->from = pcflow->to = NULL;
3020 pcflow->inCond = PCC_NONE;
3021 pcflow->outCond = PCC_NONE;
3023 pcflow->firstBank = -1;
3024 pcflow->lastBank = -1;
3026 pcflow->FromConflicts = 0;
3027 pcflow->ToConflicts = 0;
3031 pcflow->registers = newSet();
3033 return ( (pCode *)pcflow);
3037 /*-----------------------------------------------------------------*/
3038 /*-----------------------------------------------------------------*/
3039 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3041 pCodeFlowLink *pcflowLink;
3043 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3045 pcflowLink->pcflow = pcflow;
3046 pcflowLink->bank_conflict = 0;
3051 /*-----------------------------------------------------------------*/
3052 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3053 /*-----------------------------------------------------------------*/
3055 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3060 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3062 pccs->pc.type = PC_CSOURCE;
3063 pccs->pc.prev = pccs->pc.next = NULL;
3066 pccs->pc.destruct = genericDestruct;
3067 pccs->pc.print = genericPrint;
3069 pccs->line_number = ln;
3071 pccs->line = Safe_strdup(l);
3076 pccs->file_name = Safe_strdup(f);
3078 pccs->file_name = NULL;
3080 return ( (pCode *)pccs);
3085 /*******************************************************************/
3086 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3087 /* added by VR 6-Jun-2003 */
3088 /*******************************************************************/
3090 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3094 char buffer[256]; // how long can a directive be?!
3098 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3099 pcad->pc.type = PC_ASMDIR;
3100 pcad->pc.prev = pcad->pc.next = NULL;
3103 pcad->pc.destruct = genericDestruct;
3104 pcad->pc.print = genericPrint;
3106 if(asdir && *asdir) {
3107 pcad->directive = Safe_strdup( asdir );
3110 va_start(ap, argfmt);
3112 if(argfmt && *argfmt)
3113 vsprintf(buffer, argfmt, ap);
3117 while(isspace(*lbp))lbp++;
3120 pcad->arg = Safe_strdup( lbp );
3122 return ((pCode *)pcad);
3125 /*-----------------------------------------------------------------*/
3126 /* pCodeLabelDestruct - free memory used by a label. */
3127 /*-----------------------------------------------------------------*/
3128 static void pCodeLabelDestruct(pCode *pc)
3134 if((pc->type == PC_LABEL) && PCL(pc)->label)
3135 free(PCL(pc)->label);
3141 pCode *pic16_newpCodeLabel(char *name, int key)
3147 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3149 pcl->pc.type = PC_LABEL;
3150 pcl->pc.prev = pcl->pc.next = NULL;
3151 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3154 // pcl->pc.analyze = genericAnalyze;
3155 pcl->pc.destruct = pCodeLabelDestruct;
3156 pcl->pc.print = pCodePrintLabel;
3162 sprintf(s,"_%05d_DS_",key);
3167 pcl->label = Safe_strdup(s);
3169 //fprintf(stderr,"pic16_newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
3170 return ( (pCode *)pcl);
3175 /*-----------------------------------------------------------------*/
3176 /* newpBlock - create and return a pointer to a new pBlock */
3177 /*-----------------------------------------------------------------*/
3178 static pBlock *newpBlock(void)
3183 PpB = Safe_calloc(1,sizeof(pBlock) );
3184 PpB->next = PpB->prev = NULL;
3186 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3187 PpB->tregisters = NULL;
3189 PpB->FlowTree = NULL;
3195 /*-----------------------------------------------------------------*/
3196 /* pic16_newpCodeChain - create a new chain of pCodes */
3197 /*-----------------------------------------------------------------*
3199 * This function will create a new pBlock and the pointer to the
3200 * pCode that is passed in will be the first pCode in the block.
3201 *-----------------------------------------------------------------*/
3204 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3207 pBlock *pB = newpBlock();
3209 pB->pcHead = pB->pcTail = pc;
3216 /*-----------------------------------------------------------------*/
3217 /* pic16_newpCodeOpLabel - Create a new label given the key */
3218 /* Note, a negative key means that the label is part of wild card */
3219 /* (and hence a wild card label) used in the pCodePeep */
3220 /* optimizations). */
3221 /*-----------------------------------------------------------------*/
3223 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3226 static int label_key=-1;
3230 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3231 pcop->type = PO_LABEL;
3236 sprintf(s=buffer,"_%05d_DS_",key);
3238 s = name, key = label_key--;
3241 pcop->name = Safe_strdup(s);
3243 ((pCodeOpLabel *)pcop)->key = key;
3245 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3249 /*-----------------------------------------------------------------*/
3250 /*-----------------------------------------------------------------*/
3251 pCodeOp *pic16_newpCodeOpLit(int lit)
3257 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3258 pcop->type = PO_LITERAL;
3262 sprintf(s,"0x%02x",lit);
3264 pcop->name = Safe_strdup(s);
3267 ((pCodeOpLit *)pcop)->lit = lit;
3272 /*-----------------------------------------------------------------*/
3273 /*-----------------------------------------------------------------*/
3274 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3278 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3279 pcop->type = PO_IMMEDIATE;
3281 regs *r = pic16_dirregWithName(name);
3282 pcop->name = Safe_strdup(name);
3285 //fprintf(stderr, " pic16_newpCodeOpImmd reg %s exists\n",name);
3286 PCOI(pcop)->rIdx = r->rIdx;
3288 //fprintf(stderr, " pic16_newpCodeOpImmd reg %s doesn't exist\n",name);
3289 PCOI(pcop)->rIdx = -1;
3291 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3296 PCOI(pcop)->index = index;
3297 PCOI(pcop)->offset = offset;
3298 PCOI(pcop)->_const = code_space;
3303 /*-----------------------------------------------------------------*/
3304 /*-----------------------------------------------------------------*/
3305 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3311 if(!pcwb || !subtype) {
3312 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3316 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3317 pcop->type = PO_WILD;
3318 sprintf(s,"%%%d",id);
3319 pcop->name = Safe_strdup(s);
3321 PCOW(pcop)->id = id;
3322 PCOW(pcop)->pcwb = pcwb;
3323 PCOW(pcop)->subtype = subtype;
3324 PCOW(pcop)->matched = NULL;
3329 /*-----------------------------------------------------------------*/
3330 /*-----------------------------------------------------------------*/
3331 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3335 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3336 pcop->type = PO_GPR_BIT;
3338 pcop->name = Safe_strdup(s);
3342 PCORB(pcop)->bit = bit;
3343 PCORB(pcop)->inBitSpace = inBitSpace;
3345 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3346 PCOR(pcop)->r = NULL;
3347 PCOR(pcop)->rIdx = 0;
3351 /*-----------------------------------------------------------------*
3352 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3354 * If rIdx >=0 then a specific register from the set of registers
3355 * will be selected. If rIdx <0, then a new register will be searched
3357 *-----------------------------------------------------------------*/
3359 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3363 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3368 PCOR(pcop)->rIdx = rIdx;
3369 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3371 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3374 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3377 pcop->type = PCOR(pcop)->r->pc_type;
3382 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3386 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3387 PCOR(pcop)->r = pic16_allocRegByName(name, 1);
3388 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3389 pcop->type = PCOR(pcop)->r->pc_type;
3390 pcop->name = PCOR(pcop)->r->name;
3395 /*-----------------------------------------------------------------*/
3396 /*-----------------------------------------------------------------*/
3398 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3405 pcop = pic16_newpCodeOpBit(name, -1,0);
3409 pcop = pic16_newpCodeOpLit(-1);
3413 pcop = pic16_newpCodeOpLabel(NULL,-1);
3416 pcop = pic16_newpCodeOpReg(-1);
3419 case PO_GPR_REGISTER:
3421 pcop = pic16_newpCodeOpRegFromStr(name);
3423 pcop = pic16_newpCodeOpReg(-1);
3427 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3430 pcop->name = Safe_strdup(name);
3438 /*-----------------------------------------------------------------*/
3439 /*-----------------------------------------------------------------*/
3440 void pic16_pCodeConstString(char *name, char *value)
3444 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
3449 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3451 pic16_addpBlock(pb);
3453 sprintf(buffer,"; %s = %s",name,value);
3455 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3456 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3459 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3465 /*-----------------------------------------------------------------*/
3466 /*-----------------------------------------------------------------*/
3468 static void pCodeReadCodeTable(void)
3472 fprintf(stderr, " %s\n",__FUNCTION__);
3474 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3476 pic16_addpBlock(pb);
3478 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3479 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3480 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3481 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3483 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3484 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3485 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3486 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3491 /*-----------------------------------------------------------------*/
3492 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3493 /*-----------------------------------------------------------------*/
3494 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3501 /* If this is the first pcode to be added to a block that
3502 * was initialized with a NULL pcode, then go ahead and
3503 * make this pcode the head and tail */
3504 pb->pcHead = pb->pcTail = pc;
3507 pb->pcTail->next = pc;
3509 pc->prev = pb->pcTail;
3516 /*-----------------------------------------------------------------*/
3517 /* pic16_addpBlock - place a pBlock into the pFile */
3518 /*-----------------------------------------------------------------*/
3519 void pic16_addpBlock(pBlock *pb)
3521 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3524 /* First time called, we'll pass through here. */
3525 //_ALLOC(the_pFile,sizeof(pFile));
3526 the_pFile = Safe_calloc(1,sizeof(pFile));
3527 the_pFile->pbHead = the_pFile->pbTail = pb;
3528 the_pFile->functions = NULL;
3532 the_pFile->pbTail->next = pb;
3533 pb->prev = the_pFile->pbTail;
3535 the_pFile->pbTail = pb;
3538 /*-----------------------------------------------------------------*/
3539 /* removepBlock - remove a pBlock from the pFile */
3540 /*-----------------------------------------------------------------*/
3541 static void removepBlock(pBlock *pb)
3549 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3551 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3554 if(pbs == the_pFile->pbHead)
3555 the_pFile->pbHead = pbs->next;
3557 if (pbs == the_pFile->pbTail)
3558 the_pFile->pbTail = pbs->prev;
3561 pbs->next->prev = pbs->prev;
3564 pbs->prev->next = pbs->next;
3571 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3575 /*-----------------------------------------------------------------*/
3576 /* printpCode - write the contents of a pCode to a file */
3577 /*-----------------------------------------------------------------*/
3578 static void printpCode(FILE *of, pCode *pc)
3589 fprintf(of,"warning - unable to print pCode\n");
3592 /*-----------------------------------------------------------------*/
3593 /* pic16_printpBlock - write the contents of a pBlock to a file */
3594 /*-----------------------------------------------------------------*/
3595 void pic16_printpBlock(FILE *of, pBlock *pb)
3605 for(pc = pb->pcHead; pc; pc = pc->next)
3610 /*-----------------------------------------------------------------*/
3612 /* pCode processing */
3616 /*-----------------------------------------------------------------*/
3618 void pic16_unlinkpCode(pCode *pc)
3624 fprintf(stderr,"Unlinking: ");
3625 printpCode(stderr, pc);
3628 pc->prev->next = pc->next;
3630 pc->next->prev = pc->prev;
3632 pc->prev = pc->next = NULL;
3636 /*-----------------------------------------------------------------*/
3637 /*-----------------------------------------------------------------*/
3639 static void genericDestruct(pCode *pc)
3642 pic16_unlinkpCode(pc);
3645 /* For instructions, tell the register (if there's one used)
3646 * that it's no longer needed */
3647 regs *reg = pic16_getRegFromInstruction(pc);
3649 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3651 if(PCI(pc)->is2MemOp) {
3652 reg = pic16_getRegFromInstruction2(pc);
3654 deleteSetItem(&(reg->reglives.usedpCodes), pc);
3658 /* Instead of deleting the memory used by this pCode, mark
3659 * the object as bad so that if there's a pointer to this pCode
3660 * dangling around somewhere then (hopefully) when the type is
3661 * checked we'll catch it.
3666 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3675 /*-----------------------------------------------------------------*/
3676 /*-----------------------------------------------------------------*/
3677 static void pBlockRegs(FILE *of, pBlock *pb)
3682 r = setFirstItem(pb->tregisters);
3684 r = setNextItem(pb->tregisters);
3689 /*-----------------------------------------------------------------*/
3690 /*-----------------------------------------------------------------*/
3691 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3696 int use_buffer = 1; // copy the string to the passed buffer pointer
3701 use_buffer = 0; // Don't bother copying the string to the buffer.
3705 switch(pcop->type) {
3709 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3712 return PCOR(pcop)->r->name;
3715 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3718 SAFE_snprintf(&buffer,&size,"%s",r->name);
3728 if(PCOI(pcop)->_const) {
3730 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3731 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3734 8 * PCOI(pcop)->offset );
3736 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
3739 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
3740 SAFE_snprintf(&s,&size,"(%s + %d)",
3742 PCOI(pcop)->index );
3744 if(PCOI(pcop)->offset)
3745 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3747 SAFE_snprintf(&s,&size,"%s",pcop->name);
3755 //size = sizeof(buffer);
3756 if( PCOR(pcop)->instance) {
3757 SAFE_snprintf(&s,&size,"(%s + %d)",
3759 PCOR(pcop)->instance );
3761 //fprintf(stderr,"PO_DIR %s\n",buffer);
3763 SAFE_snprintf(&s,&size,"%s",pcop->name);
3769 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3778 return "NO operand";
3782 /*-----------------------------------------------------------------*/
3783 /* pic16_get_op2 - variant to support two memory operand commands */
3784 /*-----------------------------------------------------------------*/
3785 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
3790 int use_buffer = 1; // copy the string to the passed buffer pointer
3795 use_buffer = 0; // Don't bother copying the string to the buffer.
3799 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",
3800 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
3801 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
3805 switch(PCOR2(pcop)->pcop2->type) {
3809 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
3812 return PCOR(PCOR2(pcop)->pcop2)->r->name;
3815 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
3818 SAFE_snprintf(&buffer,&size,"%s",r->name);
3830 if(PCOI(pcop)->_const) {
3832 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3833 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3836 8 * PCOI(pcop)->offset );
3838 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
3841 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
3842 SAFE_snprintf(&s,&size,"(%s + %d)",
3844 PCOI(pcop)->index );
3846 if(PCOI(pcop)->offset)
3847 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3849 SAFE_snprintf(&s,&size,"%s",pcop->name);
3858 //size = sizeof(buffer);
3859 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
3860 SAFE_snprintf(&s,&size,"(%s + %d)",
3861 PCOR(PCOR2(pcop)->pcop2)->r->name,
3862 PCOR(PCOR2(pcop)->pcop2)->instance );
3864 //fprintf(stderr,"PO_DIR %s\n",buffer);
3866 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
3871 if (PCOR2(pcop)->r1->name) {
3873 SAFE_snprintf(&buffer,&size,"%s",PCOR2(pcop)->r1->name);
3876 return PCOR2(pcop)->r1->name;
3884 return "NO operand";
3888 /*-----------------------------------------------------------------*/
3889 /*-----------------------------------------------------------------*/
3890 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
3894 return pic16_get_op(pcc->pcop,NULL,0);
3896 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
3897 * return ("ERROR Null: "__FUNCTION__);
3899 return ("ERROR Null: pic16_get_op_from_instruction");
3903 /*-----------------------------------------------------------------*/
3904 /*-----------------------------------------------------------------*/
3905 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3908 fprintf(of,"pcodeopprint- not implemented\n");
3911 /*-----------------------------------------------------------------*/
3912 /*-----------------------------------------------------------------*/
3913 static char *pCode2str(char *str, size_t size, pCode *pc)
3920 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3922 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3924 if(PCI(pc)->is2MemOp) {
3925 SAFE_snprintf(&s,&size, "%s,%s",
3926 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
3927 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
3931 if(PCI(pc)->isBitInst) {
3932 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3933 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3934 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
3935 PCI(pc)->pcop->name ,
3936 PCI(pc)->pcop->name );
3938 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
3939 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
3940 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3941 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3943 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
3944 //PCI(pc)->pcop->t.bit );
3947 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3948 if( PCI(pc)->num_ops == 3)
3949 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3951 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
3954 SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
3956 if( PCI(pc)->num_ops == 3)
3957 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3965 /* assuming that comment ends with a \n */
3966 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3970 /* assuming that inline code ends with a \n */
3971 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3975 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3978 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3981 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3984 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3987 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3990 SAFE_snprintf(&s,&size,"\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
3994 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4001 /*-----------------------------------------------------------------*/
4002 /* genericPrint - the contents of a pCode to a file */
4003 /*-----------------------------------------------------------------*/
4004 static void genericPrint(FILE *of, pCode *pc)
4012 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4016 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4020 // If the opcode has a label, print that first
4022 pBranch *pbl = PCI(pc)->label;
4023 while(pbl && pbl->pc) {
4024 if(pbl->pc->type == PC_LABEL)
4025 pCodePrintLabel(of, pbl->pc);
4031 genericPrint(of,PCODE(PCI(pc)->cline));
4036 pCode2str(str, 256, pc);
4038 fprintf(of,"%s",str);
4041 if(pic16_debug_verbose) {
4042 fprintf(of, "\t;key=%03x %d",pc->seq, __LINE__);
4044 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4052 pBranch *dpb = pc->to; // debug
4054 switch ( dpb->pc->type) {
4056 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
4059 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
4062 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
4065 fprintf(of, "\t;flow");
4075 // fprintf(of,"\n"); // these are moved prior to #if 0
4079 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4080 if(PCW(pc)->pci.label)
4081 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4083 if(PCW(pc)->operand) {
4084 fprintf(of,";\toperand ");
4085 pCodeOpPrint(of,PCW(pc)->operand );
4090 if(pic16_debug_verbose) {
4091 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4092 if(PCFL(pc)->ancestor)
4093 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4100 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4103 fprintf(of, "\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4108 fprintf(of,"unknown pCode type %d\n",pc->type);
4113 /*-----------------------------------------------------------------*/
4114 /* pCodePrintFunction - prints function begin/end */
4115 /*-----------------------------------------------------------------*/
4117 static void pCodePrintFunction(FILE *of, pCode *pc)
4123 if( ((pCodeFunction *)pc)->modname)
4124 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4126 if(PCF(pc)->fname) {
4127 pBranch *exits = PCF(pc)->to;
4129 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
4132 exits = exits->next;
4135 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4138 if((PCF(pc)->from &&
4139 PCF(pc)->from->pc->type == PC_FUNCTION &&
4140 PCF(PCF(pc)->from->pc)->fname) )
4141 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4143 fprintf(of,"; exit point [can't find entry point]\n");
4146 /*-----------------------------------------------------------------*/
4147 /* pCodePrintLabel - prints label */
4148 /*-----------------------------------------------------------------*/
4150 static void pCodePrintLabel(FILE *of, pCode *pc)
4157 fprintf(of,"%s\n",PCL(pc)->label);
4158 else if (PCL(pc)->key >=0)
4159 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4161 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4164 /*-----------------------------------------------------------------*/
4165 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4166 /* remove it if it is found. */
4167 /*-----------------------------------------------------------------*/
4168 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4175 if(pcl->type == PC_OPCODE)
4176 b = PCI(pcl)->label;
4178 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4183 //fprintf (stderr, "%s \n",__FUNCTION__);
4184 //pcl->print(stderr,pcl);
4185 //pc->print(stderr,pc);
4188 //fprintf (stderr, "found label\n");
4192 bprev->next = b->next; /* Not first pCode in chain */
4196 PCI(pcl)->label = b->next; /* First pCode in chain */
4199 return; /* A label can't occur more than once */
4207 /*-----------------------------------------------------------------*/
4208 /*-----------------------------------------------------------------*/
4209 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4228 /*-----------------------------------------------------------------*/
4229 /* pBranchLink - given two pcodes, this function will link them */
4230 /* together through their pBranches */
4231 /*-----------------------------------------------------------------*/
4232 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4236 // Declare a new branch object for the 'from' pCode.
4238 //_ALLOC(b,sizeof(pBranch));
4239 b = Safe_calloc(1,sizeof(pBranch));
4240 b->pc = PCODE(t); // The link to the 'to' pCode.
4243 f->to = pic16_pBranchAppend(f->to,b);
4245 // Now do the same for the 'to' pCode.
4247 //_ALLOC(b,sizeof(pBranch));
4248 b = Safe_calloc(1,sizeof(pBranch));
4252 t->from = pic16_pBranchAppend(t->from,b);
4257 /*-----------------------------------------------------------------*/
4258 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4260 /*-----------------------------------------------------------------*/
4261 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4274 /*-----------------------------------------------------------------*/
4275 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4276 /*-----------------------------------------------------------------*/
4277 static void pCodeUnlink(pCode *pc)
4282 if(!pc->prev || !pc->next) {
4283 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4287 /* first remove the pCode from the chain */
4288 pc->prev->next = pc->next;
4289 pc->next->prev = pc->prev;
4291 /* Now for the hard part... */
4293 /* Remove the branches */
4297 pc1 = pb1->pc; /* Get the pCode that branches to the
4298 * one we're unlinking */
4300 /* search for the link back to this pCode (the one we're
4302 if(pb2 = pBranchFind(pc1->to,pc)) {
4303 pb2->pc = pc->to->pc; // make the replacement
4305 /* if the pCode we're unlinking contains multiple 'to'
4306 * branches (e.g. this a skip instruction) then we need
4307 * to copy these extra branches to the chain. */
4309 pic16_pBranchAppend(pb2, pc->to->next);
4318 /*-----------------------------------------------------------------*/
4319 /*-----------------------------------------------------------------*/
4321 static void genericAnalyze(pCode *pc)
4331 // Go through the pCodes that are in pCode chain and link
4332 // them together through the pBranches. Note, the pCodes
4333 // are linked together as a contiguous stream like the
4334 // assembly source code lines. The linking here mimics this
4335 // except that comments are not linked in.
4337 pCode *npc = pc->next;
4339 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4340 pBranchLink(pc,npc);
4345 /* reached the end of the pcode chain without finding
4346 * an instruction we could link to. */
4350 fprintf(stderr,"analyze PC_FLOW\n");
4354 fprintf(stderr,,";A bad pCode is being used\n");
4360 /*-----------------------------------------------------------------*/
4361 /*-----------------------------------------------------------------*/
4362 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4366 if(pc->type == PC_LABEL) {
4367 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4370 if(pc->type == PC_OPCODE) {
4371 pbr = PCI(pc)->label;
4373 if(pbr->pc->type == PC_LABEL) {
4374 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4384 /*-----------------------------------------------------------------*/
4385 /*-----------------------------------------------------------------*/
4386 static int checkLabel(pCode *pc)
4390 if(pc && isPCI(pc)) {
4391 pbr = PCI(pc)->label;
4393 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4403 /*-----------------------------------------------------------------*/
4404 /* findLabelinpBlock - Search the pCode for a particular label */
4405 /*-----------------------------------------------------------------*/
4406 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4413 for(pc = pb->pcHead; pc; pc = pc->next)
4414 if(compareLabel(pc,pcop_label))
4420 /*-----------------------------------------------------------------*/
4421 /* findLabel - Search the pCode for a particular label */
4422 /*-----------------------------------------------------------------*/
4423 static pCode * findLabel(pCodeOpLabel *pcop_label)
4431 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4432 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4436 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4440 /*-----------------------------------------------------------------*/
4441 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4442 /* in the linked list */
4443 /*-----------------------------------------------------------------*/
4444 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4457 /*-----------------------------------------------------------------*/
4458 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4459 /* in the linked list */
4460 /*-----------------------------------------------------------------*/
4461 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4473 /*-----------------------------------------------------------------*/
4474 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4475 /* in the linked list */
4476 /*-----------------------------------------------------------------*/
4477 pCode * pic16_findNextInstruction(pCode *pci)
4482 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4486 fprintf(stderr,"pic16_findNextInstruction: ");
4487 printpCode(stderr, pc);
4492 //fprintf(stderr,"Couldn't find instruction\n");
4496 /*-----------------------------------------------------------------*/
4497 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4498 /* in the linked list */
4499 /*-----------------------------------------------------------------*/
4500 pCode * pic16_findPrevInstruction(pCode *pci)
4502 return findPrevpCode(pci, PC_OPCODE);
4505 /*-----------------------------------------------------------------*/
4506 /* findFunctionEnd - given a pCode find the end of the function */
4507 /* that contains it */
4508 /*-----------------------------------------------------------------*/
4509 static pCode * findFunctionEnd(pCode *pc)
4513 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4519 fprintf(stderr,"Couldn't find function end\n");
4524 /*-----------------------------------------------------------------*/
4525 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4526 /* instruction with which it is associated. */
4527 /*-----------------------------------------------------------------*/
4528 static void AnalyzeLabel(pCode *pc)
4537 static void AnalyzeGOTO(pCode *pc)
4540 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4544 static void AnalyzeSKIP(pCode *pc)
4547 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4548 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4552 static void AnalyzeRETURN(pCode *pc)
4555 // branch_link(pc,findFunctionEnd(pc->next));
4561 /*-----------------------------------------------------------------*/
4562 /*-----------------------------------------------------------------*/
4563 regs * pic16_getRegFromInstruction(pCode *pc)
4569 PCI(pc)->num_ops == 0 ||
4570 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4573 switch(PCI(pc)->pcop->type) {
4576 return PCOR(PCI(pc)->pcop)->r;
4578 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4582 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4583 return PCOR(PCI(pc)->pcop)->r;
4586 if(PCOI(PCI(pc)->pcop)->r)
4587 return (PCOI(PCI(pc)->pcop)->r);
4589 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4590 return pic16_dirregWithName(PCI(pc)->pcop->name);
4591 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4594 return PCOR(PCI(pc)->pcop)->r;
4597 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4598 return PCOR(PCI(pc)->pcop)->r;
4600 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4604 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4605 //genericPrint(stderr, pc);
4613 /*-------------------------------------------------------------------------------*/
4614 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
4615 /*-------------------------------------------------------------------------------*/
4616 regs * pic16_getRegFromInstruction2(pCode *pc)
4622 PCI(pc)->num_ops == 0 ||
4623 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
4628 * operands supported in MOVFF:
4635 switch(PCI(pc)->pcop->type) {
4638 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4640 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4644 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4645 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4650 if(PCOI(PCI(pc)->pcop)->r)
4651 return (PCOI(PCI(pc)->pcop)->r);
4653 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4654 return pic16_dirregWithName(PCI(pc)->pcop->name);
4655 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4660 // return PCOR2(PCI(pc)->pcop)->r;
4663 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4664 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4668 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4671 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4672 //genericPrint(stderr, pc);
4680 /*-----------------------------------------------------------------*/
4681 /*-----------------------------------------------------------------*/
4683 static void AnalyzepBlock(pBlock *pb)
4690 /* Find all of the registers used in this pBlock
4691 * by looking at each instruction and examining it's
4694 for(pc = pb->pcHead; pc; pc = pc->next) {
4696 /* Is this an instruction with operands? */
4697 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4699 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4701 /* Loop through all of the registers declared so far in
4702 this block and see if we find this one there */
4704 regs *r = setFirstItem(pb->tregisters);
4707 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4708 PCOR(PCI(pc)->pcop)->r = r;
4711 r = setNextItem(pb->tregisters);
4715 /* register wasn't found */
4716 //r = Safe_calloc(1, sizeof(regs));
4717 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
4718 //addSet(&pb->tregisters, r);
4719 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
4720 //PCOR(PCI(pc)->pcop)->r = r;
4721 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
4723 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
4726 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
4727 if(PCOR(PCI(pc)->pcop)->r) {
4728 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
4729 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
4731 if(PCI(pc)->pcop->name)
4732 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
4734 fprintf(stderr,"ERROR: NULL register\n");
4743 /*-----------------------------------------------------------------*/
4745 /*-----------------------------------------------------------------*/
4746 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
4748 static void InsertpFlow(pCode *pc, pCode **pflow)
4751 PCFL(*pflow)->end = pc;
4753 if(!pc || !pc->next)
4756 *pflow = pic16_newpCodeFlow();
4757 pic16_pCodeInsertAfter(pc, *pflow);
4760 /*-----------------------------------------------------------------*/
4761 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4762 /* the flow blocks. */
4764 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
4765 * point the instruction flow changes.
4767 /*-----------------------------------------------------------------*/
4768 void pic16_BuildFlow(pBlock *pb)
4771 pCode *last_pci=NULL;
4778 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
4779 /* Insert a pCodeFlow object at the beginning of a pBlock */
4781 InsertpFlow(pb->pcHead, &pflow);
4783 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
4784 //pflow->next = pb->pcHead; /* Make the current head the next object */
4785 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
4786 //pb->pcHead = pflow; /* Make the Flow object the head */
4789 for( pc = pic16_findNextInstruction(pb->pcHead);
4791 pc=pic16_findNextInstruction(pc)) {
4794 PCI(pc)->pcflow = PCFL(pflow);
4796 //fprintf(stderr," build: ");
4797 //pflow->print(stderr,pflow);
4799 if( PCI(pc)->isSkip) {
4801 /* The two instructions immediately following this one
4802 * mark the beginning of a new flow segment */
4804 while(pc && PCI(pc)->isSkip) {
4806 PCI(pc)->pcflow = PCFL(pflow);
4810 InsertpFlow(pc, &pflow);
4811 pc=pic16_findNextInstruction(pc->next);
4819 PCI(pc)->pcflow = PCFL(pflow);
4821 InsertpFlow(pc, &pflow);
4823 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
4825 InsertpFlow(pc, &pflow);
4828 } else if (checkLabel(pc)) {
4830 /* This instruction marks the beginning of a
4831 * new flow segment */
4836 /* If the previous pCode is not a flow object, then
4837 * insert a new flow object. (This check prevents
4838 * two consecutive flow objects from being insert in
4839 * the case where a skip instruction preceeds an
4840 * instruction containing a label.) */
4842 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4843 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
4845 PCI(pc)->pcflow = PCFL(pflow);
4852 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4854 PCFL(pflow)->end = pb->pcTail;
4857 /*-------------------------------------------------------------------*/
4858 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4859 /* the flow blocks. */
4861 * unBuildFlow removes pCodeFlow objects from a pCode chain
4863 /*-----------------------------------------------------------------*/
4864 static void unBuildFlow(pBlock *pb)
4879 if(PCI(pc)->pcflow) {
4880 //free(PCI(pc)->pcflow);
4881 PCI(pc)->pcflow = NULL;
4884 } else if(isPCFL(pc) )
4893 /*-----------------------------------------------------------------*/
4894 /*-----------------------------------------------------------------*/
4895 static void dumpCond(int cond)
4898 static char *pcc_str[] = {
4913 int ncond = sizeof(pcc_str) / sizeof(char *);
4916 fprintf(stderr, "0x%04X\n",cond);
4918 for(i=0,j=1; i<ncond; i++, j<<=1)
4920 fprintf(stderr, " %s\n",pcc_str[i]);
4926 /*-----------------------------------------------------------------*/
4927 /*-----------------------------------------------------------------*/
4928 static void FlowStats(pCodeFlow *pcflow)
4936 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4938 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
4941 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4946 fprintf(stderr, " FlowStats inCond: ");
4947 dumpCond(pcflow->inCond);
4948 fprintf(stderr, " FlowStats outCond: ");
4949 dumpCond(pcflow->outCond);
4953 /*-----------------------------------------------------------------*
4954 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4955 * if it affects the banking bits.
4957 * return: -1 == Banking bits are unaffected by this pCode.
4959 * return: > 0 == Banking bits are affected.
4961 * If the banking bits are affected, then the returned value describes
4962 * which bits are affected and how they're affected. The lower half
4963 * of the integer maps to the bits that are affected, the upper half
4964 * to whether they're set or cleared.
4966 *-----------------------------------------------------------------*/
4968 static int isBankInstruction(pCode *pc)
4976 if( PCI(pc)->op == POC_MOVLB ||
4977 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
4978 bank = PCOL(pc)->lit;
4985 /*-----------------------------------------------------------------*/
4986 /*-----------------------------------------------------------------*/
4987 static void FillFlow(pCodeFlow *pcflow)
4996 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4998 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5001 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5008 isBankInstruction(pc);
5010 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5014 fprintf(stderr, " FillFlow - Bad end of flow\n");
5016 fprintf(stderr, " FillFlow - Ending flow with\n ");
5017 pc->print(stderr,pc);
5020 fprintf(stderr, " FillFlow inCond: ");
5021 dumpCond(pcflow->inCond);
5022 fprintf(stderr, " FillFlow outCond: ");
5023 dumpCond(pcflow->outCond);
5027 /*-----------------------------------------------------------------*/
5028 /*-----------------------------------------------------------------*/
5029 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5031 pCodeFlowLink *fromLink, *toLink;
5033 if(!from || !to || !to->pcflow || !from->pcflow)
5036 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5037 toLink = pic16_newpCodeFlowLink(to->pcflow);
5039 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5040 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5044 /*-----------------------------------------------------------------*
5045 * void LinkFlow(pBlock *pb)
5047 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5048 * non-branching segments. In LinkFlow, we determine the execution
5049 * order of these segments. For example, if one of the segments ends
5050 * with a skip, then we know that there are two possible flow segments
5051 * to which control may be passed.
5052 *-----------------------------------------------------------------*/
5053 static void LinkFlow(pBlock *pb)
5059 //fprintf(stderr,"linkflow \n");
5061 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5063 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5066 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5068 //fprintf(stderr," link: ");
5069 //pcflow->print(stderr,pcflow);
5071 //FillFlow(PCFL(pcflow));
5073 pc = PCFL(pcflow)->end;
5075 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5076 if(isPCI_SKIP(pc)) {
5077 //fprintf(stderr, "ends with skip\n");
5078 //pc->print(stderr,pc);
5079 pct=pic16_findNextInstruction(pc->next);
5080 LinkFlow_pCode(PCI(pc),PCI(pct));
5081 pct=pic16_findNextInstruction(pct->next);
5082 LinkFlow_pCode(PCI(pc),PCI(pct));
5086 if(isPCI_BRANCH(pc)) {
5087 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5089 //fprintf(stderr, "ends with branch\n ");
5090 //pc->print(stderr,pc);
5092 if(!(pcol && isPCOLAB(pcol))) {
5093 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5094 pc->print(stderr,pc);
5095 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5100 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5101 LinkFlow_pCode(PCI(pc),PCI(pct));
5103 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5104 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5105 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5111 //fprintf(stderr, "ends with non-branching instruction:\n");
5112 //pc->print(stderr,pc);
5114 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5120 //fprintf(stderr, "ends with unknown\n");
5121 //pc->print(stderr,pc);
5125 //fprintf(stderr, "ends with nothing: ERROR\n");
5129 /*-----------------------------------------------------------------*/
5130 /*-----------------------------------------------------------------*/
5132 /*-----------------------------------------------------------------*/
5133 /*-----------------------------------------------------------------*/
5134 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5140 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5143 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5149 /*-----------------------------------------------------------------*/
5150 /* BanksUsedFlow - Identify which banks are used in flow 2. */
5151 /*-----------------------------------------------------------------*/
5152 static void BanksUsedFlow2(pCode *pcflow)
5161 if(!isPCFL(pcflow)) {
5162 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
5166 pc = pic16_findNextInstruction(pcflow->next);
5168 PCFL(pcflow)->lastBank = -1;
5170 while(pic16_isPCinFlow(pc,pcflow)) {
5172 int bank_selected = isBankInstruction(pc);
5174 //if(PCI(pc)->pcflow)
5175 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
5177 if(bank_selected >= 0) {
5178 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
5180 /* This instruction is modifying banking bits before accessing registers */
5182 PCFL(pcflow)->firstBank = -1;
5184 if(PCFL(pcflow)->lastBank == -1)
5185 PCFL(pcflow)->lastBank = 0;
5187 bank = 1 << bank_selected;
5188 PCFL(pcflow)->lastBank |= bank;
5192 reg = pic16_getRegFromInstruction(pc);
5194 if(reg && !pic16_isREGinBank(reg, bank)) {
5195 int allbanks = pic16_REGallBanks(reg);
5197 PCFL(pcflow)->firstBank = allbanks;
5199 PCFL(pcflow)->lastBank = allbanks;
5206 pc = pic16_findNextInstruction(pc->next);
5209 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
5210 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
5215 /*-----------------------------------------------------------------*/
5216 /*-----------------------------------------------------------------*/
5217 static void BanksUsedFlow(pBlock *pb)
5222 //pb->pcHead->print(stderr, pb->pcHead);
5224 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5225 //pcflow->print(stderr,pcflow);
5227 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5229 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5231 BanksUsedFlow2(pcflow);
5237 /*-----------------------------------------------------------------*/
5238 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5239 /*-----------------------------------------------------------------*/
5240 static void insertBankSwitch(int position, pCode *pc, int bsr)
5249 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5250 * insert a BANKSEL assembler directive for the symbol used by
5251 * the pCode. This will allow the linker to setup the correct
5252 * bank at linking time
5255 if(!options.gen_banksel || bsr != -1) {
5256 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5259 /* emit the BANKSEL [symbol] */
5261 /* IMPORTANT: The following code does not check if a symbol is
5262 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5264 reg = pic16_getRegFromInstruction(pc);
5266 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", reg->name);
5268 position = 0; // position is always before (sanity check!)
5272 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5273 pc->print(stderr, pc);
5277 /* insert the bank switch after this pc instruction */
5278 pCode *pcnext = pic16_findNextInstruction(pc);
5279 pic16_pCodeInsertAfter(pc, new_pc);
5284 pic16_pCodeInsertAfter(pc->prev, new_pc);
5286 /* Move the label, if there is one */
5288 if(PCI(pc)->label) {
5289 PCI(new_pc)->label = PCI(pc)->label;
5290 PCI(pc)->label = NULL;
5293 /* The new instruction has the same pcflow block */
5294 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
5297 /*-----------------------------------------------------------------*/
5298 /*-----------------------------------------------------------------*/
5299 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
5310 pc = pic16_findNextInstruction(pcfl->pc.next);
5312 while(pic16_isPCinFlow(pc,PCODE(pcfl))) {
5314 reg = pic16_getRegFromInstruction(pc);
5318 fprintf(stderr, "%s:%d %s ",__FUNCTION__, __LINE__, reg->name);
5319 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
5324 if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) ||
5325 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
5328 /* Examine the instruction before this one to make sure it is
5329 * not a skip type instruction */
5330 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5332 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev) /* && !isBankInstruction(pcprev)*/)) {
5335 reg_bank = (reg) ? REG_BANK(reg) : 0;
5338 if (cur_bank != reg_bank) {
5339 //fprintf(stderr, "Cool! can switch banks\n");
5340 cur_bank = reg_bank;
5341 insertBankSwitch(0, pc, cur_bank);
5345 //fprintf(stderr, "Bummer can't switch banks\n");
5351 pc = pic16_findNextInstruction(pc->next);
5355 if(pcprev && cur_bank) {
5356 /* Brute force - make sure that we point to bank 0 at the
5357 * end of each flow block */
5358 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
5359 pic16_pCodeInsertAfter(pcprev, new_pc);
5361 //fprintf(stderr, "Brute force switch\n");
5366 /*-----------------------------------------------------------------*/
5367 /*int compareBankFlow - compare the banking requirements between */
5369 /*-----------------------------------------------------------------*/
5370 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5373 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5376 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5379 if(pcflow->firstBank == -1)
5383 if(pcflowLink->pcflow->firstBank == -1) {
5384 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5385 pcflowLink->pcflow->to :
5386 pcflowLink->pcflow->from);
5387 return compareBankFlow(pcflow, pctl, toORfrom);
5391 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5394 pcflowLink->bank_conflict++;
5395 pcflowLink->pcflow->FromConflicts++;
5396 pcflow->ToConflicts++;
5399 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5402 pcflowLink->bank_conflict++;
5403 pcflowLink->pcflow->ToConflicts++;
5404 pcflow->FromConflicts++;
5408 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5409 pcflowLink->pcflow->pc.seq,
5410 pcflowLink->pcflow->FromConflicts,
5411 pcflowLink->pcflow->ToConflicts);
5416 /*-----------------------------------------------------------------*/
5417 /*-----------------------------------------------------------------*/
5418 static void FixBankFlow(pBlock *pb)
5422 pCodeFlowLink *pcfl;
5424 pCode *pcflow_max_To=NULL;
5425 pCode *pcflow_max_From=NULL;
5426 int max_ToConflicts=0;
5427 int max_FromConflicts=0;
5429 //fprintf(stderr,"Fix Bank flow \n");
5430 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5434 First loop through all of the flow objects in this pcode block
5435 and fix the ones that have banking conflicts between the
5439 // fprintf(stderr, "FixBankFlow - Phase 1\n");
5441 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5443 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5445 if(!isPCFL(pcflow)) {
5446 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5450 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
5451 PCFL(pcflow)->firstBank >= 0 &&
5452 PCFL(pcflow)->lastBank >= 0 ) {
5454 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
5455 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
5457 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
5458 BanksUsedFlow2(pcflow);
5463 // fprintf(stderr, "FixBankFlow - Phase 2\n");
5465 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5467 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5472 if(!isPCFL(pcflow)) {
5473 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5477 PCFL(pcflow)->FromConflicts = 0;
5478 PCFL(pcflow)->ToConflicts = 0;
5483 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
5484 pcfl = setFirstItem(PCFL(pcflow)->from);
5487 pc = PCODE(pcfl->pcflow);
5490 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5491 pc->print(stderr,pc);
5494 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
5497 pcfl=setNextItem(PCFL(pcflow)->from);
5500 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
5501 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5503 FixRegisterBankingInFlow(PCFL(pcflow),0);
5504 BanksUsedFlow2(pcflow);
5506 continue; /* Don't need to check the flow from here - it's already been fixed */
5513 pcfl = setFirstItem(PCFL(pcflow)->to);
5516 pc = PCODE(pcfl->pcflow);
5518 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5519 pc->print(stderr,pc);
5522 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
5525 pcfl=setNextItem(PCFL(pcflow)->to);
5528 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
5529 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5531 FixRegisterBankingInFlow(PCFL(pcflow),0);
5532 BanksUsedFlow2(pcflow);
5537 Loop through the flow objects again and find the ones with the
5541 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5543 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5545 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
5546 pcflow_max_To = pcflow;
5548 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
5549 pcflow_max_From = pcflow;
5553 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
5554 PCFL(pcflow_max_To)->pc.seq,
5555 PCFL(pcflow_max_To)->ToConflicts);
5558 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
5559 PCFL(pcflow_max_From)->pc.seq,
5560 PCFL(pcflow_max_From)->FromConflicts);
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);
5820 if((pcnext = pic16_findNextInstruction(pc) )) {
5822 // Unlink the pCode label from it's pCode chain
5823 pic16_unlinkpCode(pc);
5825 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5826 // And link it into the instruction's pBranch labels. (Note, since
5827 // it's possible to have multiple labels associated with one instruction
5828 // we must provide a means to accomodate the additional labels. Thus
5829 // the labels are placed into the singly-linked list "label" as
5830 // opposed to being a single member of the pCodeInstruction.)
5832 //_ALLOC(pbr,sizeof(pBranch));
5833 pbr = Safe_calloc(1,sizeof(pBranch));
5837 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5840 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5842 } else if(pc->type == PC_CSOURCE) {
5844 /* merge the source line symbolic info into the next instruction */
5845 if((pcnext = pic16_findNextInstruction(pc) )) {
5847 // Unlink the pCode label from it's pCode chain
5848 pic16_unlinkpCode(pc);
5849 PCI(pcnext)->cline = PCCS(pc);
5850 //fprintf(stderr, "merging CSRC\n");
5851 //genericPrint(stderr,pcnext);
5857 pBlockRemoveUnusedLabels(pb);
5861 /*-----------------------------------------------------------------*/
5862 /*-----------------------------------------------------------------*/
5863 static int OptimizepCode(char dbName)
5865 #define MAX_PASSES 4
5874 DFPRINTF((stderr," Optimizing pCode\n"));
5878 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5879 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5880 matches += OptimizepBlock(pb);
5883 while(matches && ++passes < MAX_PASSES);
5888 /*-----------------------------------------------------------------*/
5889 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5890 /*-----------------------------------------------------------------*/
5892 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5896 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5898 if( !( (pcop->type == PO_LABEL) ||
5899 (pcop->type == PO_LITERAL) ||
5900 (pcop->type == PO_STR) ))
5901 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5909 /*-----------------------------------------------------------------*/
5910 /*-----------------------------------------------------------------*/
5911 int InstructionRegBank(pCode *pc)
5915 if( (reg = pic16_getRegFromInstruction(pc)) == NULL)
5918 return REG_BANK(reg);
5923 /*-----------------------------------------------------------------*/
5924 /*-----------------------------------------------------------------*/
5925 static void pic16_FixRegisterBanking(pBlock *pb)
5936 //pc = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5937 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5940 /* loop through all of the flow blocks with in one pblock */
5942 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
5946 /* at this point, pc should point to a PC_FLOW object */
5949 /* for each flow block, determine the register banking
5953 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
5954 // genericPrint(stderr, pc);
5956 reg = pic16_getRegFromInstruction(pc);
5959 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
5960 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
5961 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
5962 pic16_finalMapping[ reg->rIdx ].isSFR, reg->isFixed);
5968 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5969 #warning Fix this if-conditional
5971 #pragma message( "warning Fix this if-conditional" )
5975 /* the !(reg->rIdx==-1) is a temporary hack. It should be changed - VR 6-Jun-2003 */
5976 if( ( (reg /*&& !(reg->rIdx==-1)*/ && !isACCESS_BANK(reg) && (isBankInstruction(pc)==-1) && !(reg->alias == 0x80) )
5977 /*|| (PCI(pc)->op != POC_CALL)*/ )
5978 && (!isPCI_LIT(pc)) ) {
5981 /* Examine the instruction before this one to make sure it is
5982 * not a skip type instruction */
5983 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5985 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev) /*&& !isBankInstruction(pcprev)*/)) {
5988 reg_bank = (reg) ? REG_BANK(reg) : 0;
5991 fprintf(stderr, "%s:%d add bank = %d\n", __FUNCTION__, __LINE__, reg_bank);
5992 pc->print(stderr, pc);
5995 // if (cur_bank != reg_bank) {
5996 cur_bank = reg_bank;
5997 insertBankSwitch(0, pc, (options.gen_banksel)?-1:cur_bank); //cur_bank);
6001 //fprintf(stderr, "Bummer can't switch banks\n");
6011 // } while(pc && !(isPCFL(pc)));
6016 if(pcprev && cur_bank) {
6018 int pos = 1; /* Assume that the bank switch instruction(s)
6019 * are inserted after this instruction */
6021 if((PCI(pcprev)->op == POC_RETLW) ||
6022 (PCI(pcprev)->op == POC_RETURN) ||
6023 (PCI(pcprev)->op == POC_RETFIE)) {
6025 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6031 /* Brute force - make sure that we point to bank 0 at the
6032 * end of each flow block */
6034 insertBankSwitch(pos, pcprev, 0);
6036 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6037 pic16_pCodeInsertAfter(pcprev, new_pc);
6040 //fprintf(stderr, "Brute force switch\n");
6049 if(reg && REG_BANK(reg)!=cur_bank) {
6050 //fprintf(stderr,"need to switch banks\n");
6051 /* Examine the instruction before this one to make sure it is
6052 * not a skip type instruction */
6053 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6054 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
6055 int b = cur_bank ^ REG_BANK(reg);
6057 cur_bank = REG_BANK(reg);
6063 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
6066 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
6067 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
6071 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
6072 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
6074 insertBankSwitch(0, pc, -1, -1);
6083 static void pBlockDestruct(pBlock *pb)
6094 /*-----------------------------------------------------------------*/
6095 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6096 /* name dbName and combine them */
6097 /* into one block */
6098 /*-----------------------------------------------------------------*/
6099 static void mergepBlocks(char dbName)
6102 pBlock *pb, *pbmerged = NULL,*pbn;
6104 pb = the_pFile->pbHead;
6106 //fprintf(stderr," merging blocks named %c\n",dbName);
6110 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6111 if( getpBlock_dbName(pb) == dbName) {
6113 //fprintf(stderr," merged block %c\n",dbName);
6118 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6119 /* pic16_addpCode2pBlock doesn't handle the tail: */
6120 pbmerged->pcTail = pb->pcTail;
6122 pb->prev->next = pbn;
6124 pbn->prev = pb->prev;
6129 //pic16_printpBlock(stderr, pbmerged);
6136 /*-----------------------------------------------------------------*/
6137 /* AnalyzeFlow - Examine the flow of the code and optimize */
6139 /* level 0 == minimal optimization */
6140 /* optimize registers that are used only by two instructions */
6141 /* level 1 == maximal optimization */
6142 /* optimize by looking at pairs of instructions that use the */
6144 /*-----------------------------------------------------------------*/
6146 static void AnalyzeFlow(int level)
6148 static int times_called=0;
6156 /* if this is not the first time this function has been called,
6157 then clean up old flow information */
6158 if(times_called++) {
6159 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6162 pic16_RegsUnMapLiveRanges();
6168 /* Phase 2 - Flow Analysis - Register Banking
6170 * In this phase, the individual flow blocks are examined
6171 * and register banking is fixed.
6175 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6176 pic16_FixRegisterBanking(pb);
6179 /* Phase 2 - Flow Analysis
6181 * In this phase, the pCode is partition into pCodeFlow
6182 * blocks. The flow blocks mark the points where a continuous
6183 * stream of instructions changes flow (e.g. because of
6184 * a call or goto or whatever).
6187 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6188 pic16_BuildFlow(pb);
6191 /* Phase 2 - Flow Analysis - linking flow blocks
6193 * In this phase, the individual flow blocks are examined
6194 * to determine their order of excution.
6197 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6200 /* Phase 3 - Flow Analysis - Flow Tree
6202 * In this phase, the individual flow blocks are examined
6203 * to determine their order of excution.
6206 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6207 pic16_BuildFlowTree(pb);
6210 /* Phase x - Flow Analysis - Used Banks
6212 * In this phase, the individual flow blocks are examined
6213 * to determine the Register Banks they use
6216 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6220 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6221 pic16_pCodeRegMapLiveRanges(pb);
6223 pic16_RemoveUnusedRegisters();
6225 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6226 pic16_pCodeRegOptimizeRegUsage(level);
6234 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6238 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6240 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6241 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6242 pcflow = pcflow->next) {
6244 FillFlow(PCFL(pcflow));
6249 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6251 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6252 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6253 pcflow = pcflow->next) {
6255 FlowStats(PCFL(pcflow));
6261 /*-----------------------------------------------------------------*/
6262 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6263 /* assigned to the registers. */
6265 /*-----------------------------------------------------------------*/
6267 void pic16_AnalyzeBanking(void)
6271 if(!pic16_picIsInitialized()) {
6272 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6273 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6274 fprintf(stderr,"support/scripts/inc2h.pl\n");
6275 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6280 /* Phase x - Flow Analysis - Used Banks
6282 * In this phase, the individual flow blocks are examined
6283 * to determine the Register Banks they use
6289 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6292 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6293 pic16_FixRegisterBanking(pb);
6297 /*-----------------------------------------------------------------*/
6298 /* buildCallTree - Look at the flow and extract all of the calls. */
6299 /*-----------------------------------------------------------------*/
6300 static set *register_usage(pBlock *pb);
6302 static void buildCallTree(void )
6313 /* Now build the call tree.
6314 First we examine all of the pCodes for functions.
6315 Keep in mind that the function boundaries coincide
6316 with pBlock boundaries.
6318 The algorithm goes something like this:
6319 We have two nested loops. The outer loop iterates
6320 through all of the pBlocks/functions. The inner
6321 loop iterates through all of the pCodes for
6322 a given pBlock. When we begin iterating through
6323 a pBlock, the variable pc_fstart, pCode of the start
6324 of a function, is cleared. We then search for pCodes
6325 of type PC_FUNCTION. When one is encountered, we
6326 initialize pc_fstart to this and at the same time
6327 associate a new pBranch object that signifies a
6328 branch entry. If a return is found, then this signifies
6329 a function exit point. We'll link the pCodes of these
6330 returns to the matching pc_fstart.
6332 When we're done, a doubly linked list of pBranches
6333 will exist. The head of this list is stored in
6334 `the_pFile', which is the meta structure for all
6335 of the pCode. Look at the pic16_printCallTree function
6336 on how the pBranches are linked together.
6339 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6340 pCode *pc_fstart=NULL;
6341 for(pc = pb->pcHead; pc; pc = pc->next) {
6343 if (PCF(pc)->fname) {
6345 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6346 //fprintf(stderr," found main \n");
6347 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6351 pbr = Safe_calloc(1,sizeof(pBranch));
6352 pbr->pc = pc_fstart = pc;
6355 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6357 // Here's a better way of doing the same:
6358 addSet(&pb->function_entries, pc);
6361 // Found an exit point in a function, e.g. return
6362 // (Note, there may be more than one return per function)
6364 pBranchLink(PCF(pc_fstart), PCF(pc));
6366 addSet(&pb->function_exits, pc);
6368 } else if(isCALL(pc)) {
6369 addSet(&pb->function_calls,pc);
6374 /* Re-allocate the registers so that there are no collisions
6375 * between local variables when one function call another */
6378 // pic16_deallocateAllRegs();
6380 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6387 /*-----------------------------------------------------------------*/
6388 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6389 /* all of the logical connections. */
6391 /* Essentially what's done here is that the pCode flow is */
6393 /*-----------------------------------------------------------------*/
6395 void pic16_AnalyzepCode(char dbName)
6406 /* Phase 1 - Register allocation and peep hole optimization
6408 * The first part of the analysis is to determine the registers
6409 * that are used in the pCode. Once that is done, the peep rules
6410 * are applied to the code. We continue to loop until no more
6411 * peep rule optimizations are found (or until we exceed the
6412 * MAX_PASSES threshold).
6414 * When done, the required registers will be determined.
6420 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6421 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6423 /* First, merge the labels with the instructions */
6424 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6425 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6427 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6428 //fprintf(stderr," analyze and merging block %c\n",dbName);
6429 pic16_pBlockMergeLabels(pb);
6432 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6437 changes = OptimizepCode(dbName);
6440 } while(changes && (i++ < MAX_PASSES));
6445 /*-----------------------------------------------------------------*/
6446 /* ispCodeFunction - returns true if *pc is the pCode of a */
6448 /*-----------------------------------------------------------------*/
6449 static bool ispCodeFunction(pCode *pc)
6452 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6458 /*-----------------------------------------------------------------*/
6459 /* findFunction - Search for a function by name (given the name) */
6460 /* in the set of all functions that are in a pBlock */
6461 /* (note - I expect this to change because I'm planning to limit */
6462 /* pBlock's to just one function declaration */
6463 /*-----------------------------------------------------------------*/
6464 static pCode *findFunction(char *fname)
6471 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6473 pc = setFirstItem(pb->function_entries);
6476 if((pc->type == PC_FUNCTION) &&
6478 (strcmp(fname, PCF(pc)->fname)==0))
6481 pc = setNextItem(pb->function_entries);
6489 static void MarkUsedRegisters(set *regset)
6494 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6495 // fprintf(stderr, "marking register = %s\t", r1->name);
6496 r2 = pic16_regWithIdx(r1->rIdx);
6497 // fprintf(stderr, "to register = %s\n", r2->name);
6503 static void pBlockStats(FILE *of, pBlock *pb)
6509 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6511 // for now just print the first element of each set
6512 pc = setFirstItem(pb->function_entries);
6514 fprintf(of,";entry: ");
6517 pc = setFirstItem(pb->function_exits);
6519 fprintf(of,";has an exit\n");
6523 pc = setFirstItem(pb->function_calls);
6525 fprintf(of,";functions called:\n");
6528 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6529 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6531 pc = setNextItem(pb->function_calls);
6535 r = setFirstItem(pb->tregisters);
6537 int n = elementsInSet(pb->tregisters);
6539 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6542 fprintf(of,"; %s\n",r->name);
6543 r = setNextItem(pb->tregisters);
6548 /*-----------------------------------------------------------------*/
6549 /*-----------------------------------------------------------------*/
6551 static void sequencepCode(void)
6557 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6559 pb->seq = GpCodeSequenceNumber+1;
6561 for( pc = pb->pcHead; pc; pc = pc->next)
6562 pc->seq = ++GpCodeSequenceNumber;
6568 /*-----------------------------------------------------------------*/
6569 /*-----------------------------------------------------------------*/
6570 static set *register_usage(pBlock *pb)
6573 set *registers=NULL;
6574 set *registersInCallPath = NULL;
6576 /* check recursion */
6578 pc = setFirstItem(pb->function_entries);
6585 if(pc->type != PC_FUNCTION)
6586 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6588 pc = setFirstItem(pb->function_calls);
6589 for( ; pc; pc = setNextItem(pb->function_calls)) {
6591 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6592 char *dest = pic16_get_op_from_instruction(PCI(pc));
6594 pcn = findFunction(dest);
6596 registersInCallPath = register_usage(pcn->pb);
6598 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6603 pBlockStats(stderr,pb); // debug
6606 // Mark the registers in this block as used.
6608 MarkUsedRegisters(pb->tregisters);
6609 if(registersInCallPath) {
6610 /* registers were used in the functions this pBlock has called */
6611 /* so now, we need to see if these collide with the ones we are */
6614 regs *r1,*r2, *newreg;
6616 DFPRINTF((stderr,"comparing registers\n"));
6618 r1 = setFirstItem(registersInCallPath);
6621 r2 = setFirstItem(pb->tregisters);
6623 while(r2 && (r1->type != REG_STK)) {
6625 if(r2->rIdx == r1->rIdx) {
6626 newreg = pic16_findFreeReg(REG_GPR);
6630 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6634 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6635 r1->rIdx, newreg->rIdx));
6636 r2->rIdx = newreg->rIdx;
6637 //if(r2->name) free(r2->name);
6639 r2->name = Safe_strdup(newreg->name);
6643 newreg->wasUsed = 1;
6645 r2 = setNextItem(pb->tregisters);
6648 r1 = setNextItem(registersInCallPath);
6651 /* Collisions have been resolved. Now free the registers in the call path */
6652 r1 = setFirstItem(registersInCallPath);
6654 if(r1->type != REG_STK) {
6655 newreg = pic16_regWithIdx(r1->rIdx);
6658 r1 = setNextItem(registersInCallPath);
6662 // MarkUsedRegisters(pb->registers);
6664 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6667 DFPRINTF((stderr,"returning regs\n"));
6669 DFPRINTF((stderr,"not returning regs\n"));
6671 DFPRINTF((stderr,"pBlock after register optim.\n"));
6672 pBlockStats(stderr,pb); // debug
6678 /*-----------------------------------------------------------------*/
6679 /* pct2 - writes the call tree to a file */
6681 /*-----------------------------------------------------------------*/
6682 static void pct2(FILE *of,pBlock *pb,int indent)
6686 // set *registersInCallPath = NULL;
6692 return; //recursion ?
6694 pc = setFirstItem(pb->function_entries);
6701 for(i=0;i<indent;i++) // Indentation
6704 if(pc->type == PC_FUNCTION)
6705 fprintf(of,"%s\n",PCF(pc)->fname);
6710 pc = setFirstItem(pb->function_calls);
6711 for( ; pc; pc = setNextItem(pb->function_calls)) {
6713 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6714 char *dest = pic16_get_op_from_instruction(PCI(pc));
6716 pcn = findFunction(dest);
6718 pct2(of,pcn->pb,indent+1);
6720 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6728 /*-----------------------------------------------------------------*/
6729 /* pic16_printCallTree - writes the call tree to a file */
6731 /*-----------------------------------------------------------------*/
6733 void pic16_printCallTree(FILE *of)
6745 fprintf(of, "\npBlock statistics\n");
6746 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6751 fprintf(of,"Call Tree\n");
6752 pbr = the_pFile->functions;
6756 if(!ispCodeFunction(pc))
6757 fprintf(of,"bug in call tree");
6760 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6762 while(pc->next && !ispCodeFunction(pc->next)) {
6764 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6765 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6773 fprintf(of,"\n**************\n\na better call tree\n");
6774 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6779 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6780 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6786 /*-----------------------------------------------------------------*/
6788 /*-----------------------------------------------------------------*/
6790 static void InlineFunction(pBlock *pb)
6798 pc = setFirstItem(pb->function_calls);
6800 for( ; pc; pc = setNextItem(pb->function_calls)) {
6803 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6809 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
6811 //fprintf(stderr,"Cool can inline:\n");
6812 //pcn->print(stderr,pcn);
6814 //fprintf(stderr,"recursive call Inline\n");
6815 InlineFunction(pcn->pb);
6816 //fprintf(stderr,"return from recursive call Inline\n");
6819 At this point, *pc points to a CALL mnemonic, and
6820 *pcn points to the function that is being called.
6822 To in-line this call, we need to remove the CALL
6823 and RETURN(s), and link the function pCode in with
6829 /* Remove the CALL */
6833 /* remove callee pBlock from the pBlock linked list */
6834 removepBlock(pcn->pb);
6842 /* Remove the Function pCode */
6843 pct = pic16_findNextInstruction(pcn->next);
6845 /* Link the function with the callee */
6846 pc->next = pcn->next;
6847 pcn->next->prev = pc;
6849 /* Convert the function name into a label */
6851 pbr = Safe_calloc(1,sizeof(pBranch));
6852 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6854 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6855 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6857 /* turn all of the return's except the last into goto's */
6858 /* check case for 2 instruction pBlocks */
6859 pce = pic16_findNextInstruction(pcn->next);
6861 pCode *pce_next = pic16_findNextInstruction(pce->next);
6863 if(pce_next == NULL) {
6864 /* found the last return */
6865 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6867 //fprintf(stderr,"found last return\n");
6868 //pce->print(stderr,pce);
6869 pce->prev->next = pc_call->next;
6870 pc_call->next->prev = pce->prev;
6871 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6881 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6887 /*-----------------------------------------------------------------*/
6889 /*-----------------------------------------------------------------*/
6891 void pic16_InlinepCode(void)
6900 if(!functionInlining)
6903 /* Loop through all of the function definitions and count the
6904 * number of times each one is called */
6905 //fprintf(stderr,"inlining %d\n",__LINE__);
6907 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6909 pc = setFirstItem(pb->function_calls);
6911 for( ; pc; pc = setNextItem(pb->function_calls)) {
6914 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6915 if(pcn && isPCF(pcn)) {
6916 PCF(pcn)->ncalled++;
6919 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6924 //fprintf(stderr,"inlining %d\n",__LINE__);
6926 /* Now, Loop through the function definitions again, but this
6927 * time inline those functions that have only been called once. */
6929 InlineFunction(the_pFile->pbHead);
6930 //fprintf(stderr,"inlining %d\n",__LINE__);
6932 for(pb = the_pFile->pbHead; pb; pb = pb->next)