1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
5 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 -------------------------------------------------------------------------*/
24 #include "common.h" // Include everything in the SDCC src directory
29 #include "pcodeflow.h"
33 #if defined(__BORLANDC__) || defined(_MSC_VER)
34 #define STRCASECMP stricmp
36 #define STRCASECMP strcasecmp
39 /****************************************************************/
40 /****************************************************************/
42 static peepCommand peepCommands[] = {
44 {NOTBITSKIP, "_NOTBITSKIP_"},
45 {BITSKIP, "_BITSKIP_"},
46 {INVERTBITSKIP, "_INVERTBITSKIP_"},
53 // Eventually this will go into device dependent files:
54 pCodeOpReg pic16_pc_status = {{PO_STATUS, "_STATUS"}, -1, NULL,0,NULL};
55 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
56 pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, ""}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "_PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
61 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
63 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
65 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
67 static int mnemonics_initialized = 0;
70 static hTab *pic16MnemonicsHash = NULL;
71 static hTab *pic16pCodePeepCommandsHash = NULL;
73 int options_gen_banksel = 1;
75 static pFile *the_pFile = NULL;
76 static pBlock *pb_dead_pcodes = NULL;
78 /* Hardcoded flags to change the behavior of the PIC port */
79 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
80 static int functionInlining = 1; /* inline functions if nonzero */
81 int pic16_debug_verbose = 1; /* Set true to inundate .asm file */
83 //static int GpCodeSequenceNumber = 1;
84 static int GpcFlowSeq = 1;
86 extern void pic16_RemoveUnusedRegisters(void);
87 extern void pic16_RegsUnMapLiveRanges(void);
88 extern void pic16_BuildFlowTree(pBlock *pb);
89 extern void pic16_pCodeRegOptimizeRegUsage(int level);
90 extern int pic16_picIsInitialized(void);
91 #if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
93 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
94 extern int mnem2key(char const *mnem);
95 #endif // OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
97 /****************************************************************/
98 /* Forward declarations */
99 /****************************************************************/
101 void pic16_unlinkpCode(pCode *pc);
103 static void genericAnalyze(pCode *pc);
104 static void AnalyzeGOTO(pCode *pc);
105 static void AnalyzeSKIP(pCode *pc);
106 static void AnalyzeRETURN(pCode *pc);
109 static void genericDestruct(pCode *pc);
110 static void genericPrint(FILE *of,pCode *pc);
112 static void pCodePrintLabel(FILE *of, pCode *pc);
113 static void pCodePrintFunction(FILE *of, pCode *pc);
114 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
115 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
116 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
117 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
118 int pic16_pCodePeepMatchRule(pCode *pc);
119 static void pBlockStats(FILE *of, pBlock *pb);
120 static pBlock *newpBlock(void);
121 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
122 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
123 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
124 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
127 /****************************************************************/
128 /* PIC Instructions */
129 /****************************************************************/
131 pCodeInstruction pic16_pciADDWF = {
132 {PC_OPCODE, NULL, NULL, 0, NULL,
145 1,0, // dest, bit instruction
147 0, // literal operand
149 0, // fast call/return mode select bit
150 0, // second memory operand
152 (PCC_W | PCC_REGISTER), // inCond
153 (PCC_REGISTER | PCC_Z) // outCond
156 pCodeInstruction pic16_pciADDFW = {
157 {PC_OPCODE, NULL, NULL, 0, NULL,
170 0,0, // dest, bit instruction
172 0, // literal operand
174 0, // fast call/return mode select bit
175 0, // second memory operand
177 (PCC_W | PCC_REGISTER), // inCond
178 (PCC_W | PCC_Z) // outCond
181 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
182 {PC_OPCODE, NULL, NULL, 0, NULL,
195 1,0, // dest, bit instruction
197 0, // literal operand
199 0, // fast call/return mode select bit
200 0, // second memory operand
202 (PCC_W | PCC_REGISTER | PCC_C), // inCond
203 (PCC_REGISTER | PCC_Z) // outCond
206 pCodeInstruction pic16_pciADDFWC = {
207 {PC_OPCODE, NULL, NULL, 0, NULL,
220 0,0, // dest, bit instruction
222 0, // literal operand
224 0, // fast call/return mode select bit
225 0, // second memory operand
227 (PCC_W | PCC_REGISTER | PCC_C), // inCond
228 (PCC_W | PCC_Z) // outCond
231 pCodeInstruction pic16_pciADDLW = {
232 {PC_OPCODE, NULL, NULL, 0, NULL,
245 0,0, // dest, bit instruction
247 1, // literal operand
249 0, // fast call/return mode select bit
250 0, // second memory operand
252 (PCC_W | PCC_LITERAL), // inCond
253 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
256 pCodeInstruction pic16_pciANDLW = {
257 {PC_OPCODE, NULL, NULL, 0, NULL,
270 0,0, // dest, bit instruction
272 1, // literal operand
274 0, // fast call/return mode select bit
275 0, // second memory operand
277 (PCC_W | PCC_LITERAL), // inCond
278 (PCC_W | PCC_Z | PCC_N) // outCond
281 pCodeInstruction pic16_pciANDWF = {
282 {PC_OPCODE, NULL, NULL, 0, NULL,
295 1,0, // dest, bit instruction
297 0, // literal operand
299 0, // fast call/return mode select bit
300 0, // second memory operand
302 (PCC_W | PCC_REGISTER), // inCond
303 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
306 pCodeInstruction pic16_pciANDFW = {
307 {PC_OPCODE, NULL, NULL, 0, NULL,
320 0,0, // dest, bit instruction
322 0, // literal operand
324 0, // fast call/return mode select bit
325 0, // second memory operand
327 (PCC_W | PCC_REGISTER), // inCond
328 (PCC_W | PCC_Z) // outCond
331 pCodeInstruction pic16_pciBC = { // mdubuc - New
332 {PC_OPCODE, NULL, NULL, 0, NULL,
345 0,0, // dest, bit instruction
347 0, // literal operand
349 0, // fast call/return mode select bit
350 0, // second memory operand
352 (PCC_REL_ADDR | PCC_C), // inCond
356 pCodeInstruction pic16_pciBCF = {
357 {PC_OPCODE, NULL, NULL, 0, NULL,
370 1,1, // dest, bit instruction
372 0, // literal operand
374 0, // fast call/return mode select bit
375 0, // second memory operand
377 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
378 PCC_REGISTER // outCond
381 pCodeInstruction pic16_pciBN = { // mdubuc - New
382 {PC_OPCODE, NULL, NULL, 0, NULL,
395 0,0, // dest, bit instruction
397 0, // literal operand
399 0, // fast call/return mode select bit
400 0, // second memory operand
402 (PCC_REL_ADDR | PCC_N), // inCond
406 pCodeInstruction pic16_pciBNC = { // mdubuc - New
407 {PC_OPCODE, NULL, NULL, 0, NULL,
420 0,0, // dest, bit instruction
422 0, // literal operand
424 0, // fast call/return mode select bit
425 0, // second memory operand
427 (PCC_REL_ADDR | PCC_C), // inCond
431 pCodeInstruction pic16_pciBNN = { // mdubuc - New
432 {PC_OPCODE, NULL, NULL, 0, NULL,
445 0,0, // dest, bit instruction
447 0, // literal operand
449 0, // fast call/return mode select bit
450 0, // second memory operand
452 (PCC_REL_ADDR | PCC_N), // inCond
456 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
457 {PC_OPCODE, NULL, NULL, 0, NULL,
470 0,0, // dest, bit instruction
472 0, // literal operand
474 0, // fast call/return mode select bit
475 0, // second memory operand
477 (PCC_REL_ADDR | PCC_OV), // inCond
481 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
482 {PC_OPCODE, NULL, NULL, 0, NULL,
495 0,0, // dest, bit instruction
497 0, // literal operand
499 0, // fast call/return mode select bit
500 0, // second memory operand
502 (PCC_REL_ADDR | PCC_Z), // inCond
506 pCodeInstruction pic16_pciBOV = { // mdubuc - New
507 {PC_OPCODE, NULL, NULL, 0, NULL,
520 0,0, // dest, bit instruction
522 0, // literal operand
524 0, // fast call/return mode select bit
525 0, // second memory operand
527 (PCC_REL_ADDR | PCC_OV), // inCond
531 pCodeInstruction pic16_pciBRA = { // mdubuc - New
532 {PC_OPCODE, NULL, NULL, 0, NULL,
545 0,0, // dest, bit instruction
547 0, // literal operand
549 0, // fast call/return mode select bit
550 0, // second memory operand
552 PCC_REL_ADDR, // inCond
556 pCodeInstruction pic16_pciBSF = {
557 {PC_OPCODE, NULL, NULL, 0, NULL,
570 1,1, // dest, bit instruction
572 0, // literal operand
574 0, // fast call/return mode select bit
575 0, // second memory operand
577 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
578 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
581 pCodeInstruction pic16_pciBTFSC = {
582 {PC_OPCODE, NULL, NULL, 0, NULL,
595 0,1, // dest, bit instruction
597 0, // literal operand
599 0, // fast call/return mode select bit
600 0, // second memory operand
602 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
603 PCC_EXAMINE_PCOP // outCond
606 pCodeInstruction pic16_pciBTFSS = {
607 {PC_OPCODE, NULL, NULL, 0, NULL,
620 0,1, // dest, bit instruction
622 0, // literal operand
624 0, // fast call/return mode select bit
625 0, // second memory operand
627 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
628 PCC_EXAMINE_PCOP // outCond
631 pCodeInstruction pic16_pciBTG = { // mdubuc - New
632 {PC_OPCODE, NULL, NULL, 0, NULL,
645 0,1, // dest, bit instruction
647 0, // literal operand
649 0, // fast call/return mode select bit
650 0, // second memory operand
652 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
653 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
656 pCodeInstruction pic16_pciBZ = { // mdubuc - New
657 {PC_OPCODE, NULL, NULL, 0, NULL,
670 0,0, // dest, bit instruction
672 0, // literal operand
674 0, // fast call/return mode select bit
675 0, // second memory operand
681 pCodeInstruction pic16_pciCALL = {
682 {PC_OPCODE, NULL, NULL, 0, NULL,
695 0,0, // dest, bit instruction
697 0, // literal operand
699 1, // fast call/return mode select bit
700 0, // second memory operand
706 pCodeInstruction pic16_pciCOMF = {
707 {PC_OPCODE, NULL, NULL, 0, NULL,
720 1,0, // dest, bit instruction
722 0, // literal operand
724 0, // fast call/return mode select bit
725 0, // second memory operand
727 PCC_REGISTER, // inCond
728 PCC_REGISTER // outCond
731 pCodeInstruction pic16_pciCOMFW = {
732 {PC_OPCODE, NULL, NULL, 0, NULL,
745 0,0, // dest, bit instruction
747 0, // literal operand
749 0, // fast call/return mode select bit
750 0, // second memory operand
752 PCC_REGISTER, // inCond
756 pCodeInstruction pic16_pciCLRF = {
757 {PC_OPCODE, NULL, NULL, 0, NULL,
770 0,0, // dest, bit instruction
772 0, // literal operand
774 0, // fast call/return mode select bit
775 0, // second memory operand
777 PCC_REGISTER, // inCond
778 PCC_REGISTER // outCond
781 pCodeInstruction pic16_pciCLRWDT = {
782 {PC_OPCODE, NULL, NULL, 0, NULL,
795 0,0, // dest, bit instruction
797 0, // literal operand
799 0, // fast call/return mode select bit
800 0, // second memory operand
806 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
807 {PC_OPCODE, NULL, NULL, 0, NULL,
820 0,0, // dest, bit instruction
822 0, // literal operand
824 0, // fast call/return mode select bit
825 0, // second memory operand
827 (PCC_W | PCC_REGISTER), // inCond
831 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
832 {PC_OPCODE, NULL, NULL, 0, NULL,
845 0,0, // dest, bit instruction
847 0, // literal operand
849 0, // fast call/return mode select bit
850 0, // second memory operand
852 (PCC_W | PCC_REGISTER), // inCond
856 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
857 {PC_OPCODE, NULL, NULL, 0, NULL,
870 1,0, // dest, bit instruction
872 0, // literal operand
874 0, // fast call/return mode select bit
875 0, // second memory operand
877 (PCC_W | PCC_REGISTER), // inCond
881 pCodeInstruction pic16_pciDAW = {
882 {PC_OPCODE, NULL, NULL, 0, NULL,
895 0,0, // dest, bit instruction
897 0, // literal operand
899 0, // fast call/return mode select bit
900 0, // second memory operand
903 (PCC_W | PCC_C) // outCond
906 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
907 {PC_OPCODE, NULL, NULL, 0, NULL,
920 1,0, // dest, bit instruction
922 0, // literal operand
924 0, // fast call/return mode select bit
925 0, // second memory operand
927 PCC_REGISTER, // inCond
928 PCC_REGISTER // outCond
931 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
932 {PC_OPCODE, NULL, NULL, 0, NULL,
945 0,0, // dest, bit instruction
947 0, // literal operand
949 0, // fast call/return mode select bit
950 0, // second memory operand
952 PCC_REGISTER, // inCond
956 pCodeInstruction pic16_pciDECF = {
957 {PC_OPCODE, NULL, NULL, 0, NULL,
970 1,0, // dest, bit instruction
972 0, // literal operand
974 0, // fast call/return mode select bit
975 0, // second memory operand
977 PCC_REGISTER, // inCond
978 PCC_REGISTER // outCond
981 pCodeInstruction pic16_pciDECFW = {
982 {PC_OPCODE, NULL, NULL, 0, NULL,
995 0,0, // dest, bit instruction
997 0, // literal operand
999 0, // fast call/return mode select bit
1000 0, // second memory operand
1002 PCC_REGISTER, // inCond
1006 pCodeInstruction pic16_pciDECFSZ = {
1007 {PC_OPCODE, NULL, NULL, 0, NULL,
1013 NULL, // from branch
1020 1,0, // dest, bit instruction
1021 1,1, // branch, skip
1022 0, // literal operand
1023 1, // RAM access bit
1024 0, // fast call/return mode select bit
1025 0, // second memory operand
1027 PCC_REGISTER, // inCond
1028 PCC_REGISTER // outCond
1031 pCodeInstruction pic16_pciDECFSZW = {
1032 {PC_OPCODE, NULL, NULL, 0, NULL,
1038 NULL, // from branch
1045 0,0, // dest, bit instruction
1046 1,1, // branch, skip
1047 0, // literal operand
1048 1, // RAM access bit
1049 0, // fast call/return mode select bit
1050 0, // second memory operand
1052 PCC_REGISTER, // inCond
1056 pCodeInstruction pic16_pciGOTO = {
1057 {PC_OPCODE, NULL, NULL, 0, NULL,
1063 NULL, // from branch
1070 0,0, // dest, bit instruction
1071 1,0, // branch, skip
1072 0, // literal operand
1073 0, // RAM access bit
1074 0, // fast call/return mode select bit
1075 0, // second memory operand
1077 PCC_REL_ADDR, // inCond
1081 pCodeInstruction pic16_pciINCF = {
1082 {PC_OPCODE, NULL, NULL, 0, NULL,
1088 NULL, // from branch
1095 1,0, // dest, bit instruction
1096 0,0, // branch, skip
1097 0, // literal operand
1098 1, // RAM access bit
1099 0, // fast call/return mode select bit
1100 0, // second memory operand
1102 PCC_REGISTER, // inCond
1103 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1106 pCodeInstruction pic16_pciINCFW = {
1107 {PC_OPCODE, NULL, NULL, 0, NULL,
1113 NULL, // from branch
1120 0,0, // dest, bit instruction
1121 0,0, // branch, skip
1122 0, // literal operand
1123 1, // RAM access bit
1124 0, // fast call/return mode select bit
1125 0, // second memory operand
1127 PCC_REGISTER, // inCond
1131 pCodeInstruction pic16_pciINCFSZ = {
1132 {PC_OPCODE, NULL, NULL, 0, NULL,
1138 NULL, // from branch
1145 1,0, // dest, bit instruction
1146 1,1, // branch, skip
1147 0, // literal operand
1148 1, // RAM access bit
1149 0, // fast call/return mode select bit
1150 0, // second memory operand
1152 PCC_REGISTER, // inCond
1153 PCC_REGISTER // outCond
1156 pCodeInstruction pic16_pciINCFSZW = {
1157 {PC_OPCODE, NULL, NULL, 0, NULL,
1163 NULL, // from branch
1170 0,0, // dest, bit instruction
1171 1,1, // branch, skip
1172 0, // literal operand
1173 1, // RAM access bit
1174 0, // fast call/return mode select bit
1175 0, // second memory operand
1177 PCC_REGISTER, // inCond
1181 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1182 {PC_OPCODE, NULL, NULL, 0, NULL,
1188 NULL, // from branch
1195 1,0, // dest, bit instruction
1196 1,1, // branch, skip
1197 0, // literal operand
1198 1, // RAM access bit
1199 0, // fast call/return mode select bit
1200 0, // second memory operand
1202 PCC_REGISTER, // inCond
1203 PCC_REGISTER // outCond
1206 pCodeInstruction pic16_pciIORWF = {
1207 {PC_OPCODE, NULL, NULL, 0, NULL,
1213 NULL, // from branch
1220 1,0, // dest, bit instruction
1221 0,0, // branch, skip
1222 0, // literal operand
1223 1, // RAM access bit
1224 0, // fast call/return mode select bit
1225 0, // second memory operand
1227 (PCC_W | PCC_REGISTER), // inCond
1228 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1231 pCodeInstruction pic16_pciIORFW = {
1232 {PC_OPCODE, NULL, NULL, 0, NULL,
1238 NULL, // from branch
1245 0,0, // dest, bit instruction
1246 0,0, // branch, skip
1247 0, // literal operand
1248 1, // RAM access bit
1249 0, // fast call/return mode select bit
1250 0, // second memory operand
1252 (PCC_W | PCC_REGISTER), // inCond
1253 (PCC_W | PCC_Z | PCC_N) // outCond
1256 pCodeInstruction pic16_pciIORLW = {
1257 {PC_OPCODE, NULL, NULL, 0, NULL,
1263 NULL, // from branch
1270 0,0, // dest, bit instruction
1271 0,0, // branch, skip
1272 1, // literal operand
1273 0, // RAM access bit
1274 0, // fast call/return mode select bit
1275 0, // second memory operand
1277 (PCC_W | PCC_LITERAL), // inCond
1278 (PCC_W | PCC_Z | PCC_N) // outCond
1281 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1282 {PC_OPCODE, NULL, NULL, 0, NULL,
1288 NULL, // from branch
1295 0,0, // dest, bit instruction
1296 0,0, // branch, skip
1297 1, // literal operand
1298 0, // RAM access bit
1299 0, // fast call/return mode select bit
1300 0, // second memory operand
1302 (PCC_REGISTER | PCC_LITERAL), // mdubuc - Should we use a special syntax for
1303 // f (identifies FSRx)?
1304 PCC_REGISTER // outCond
1307 pCodeInstruction pic16_pciMOVF = {
1308 {PC_OPCODE, NULL, NULL, 0, NULL,
1314 NULL, // from branch
1321 1,0, // dest, bit instruction
1322 0,0, // branch, skip
1323 0, // literal operand
1324 1, // RAM access bit
1325 0, // fast call/return mode select bit
1326 0, // second memory operand
1328 PCC_REGISTER, // inCond
1329 (PCC_Z | PCC_N) // outCond
1332 pCodeInstruction pic16_pciMOVFW = {
1333 {PC_OPCODE, NULL, NULL, 0, NULL,
1339 NULL, // from branch
1346 0,0, // dest, bit instruction
1347 0,0, // branch, skip
1348 0, // literal operand
1349 1, // RAM access bit
1350 0, // fast call/return mode select bit
1351 0, // second memory operand
1353 PCC_REGISTER, // inCond
1354 (PCC_W | PCC_Z) // outCond
1357 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1358 {PC_OPCODE, NULL, NULL, 0, NULL,
1364 NULL, // from branch
1371 0,0, // dest, bit instruction
1372 0,0, // branch, skip
1373 0, // literal operand
1374 0, // RAM access bit
1375 0, // fast call/return mode select bit
1376 1, // second memory operand
1378 PCC_REGISTER, // inCond
1379 PCC_REGISTER2 // outCond
1382 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1383 {PC_OPCODE, NULL, NULL, 0, NULL,
1388 NULL, // from branch
1395 0,0, // dest, bit instruction
1396 0,0, // branch, skip
1397 1, // literal operand
1398 0, // RAM access bit
1399 0, // fast call/return mode select bit
1400 0, // second memory operand
1402 (PCC_NONE | PCC_LITERAL), // inCond
1403 PCC_REGISTER // outCond - BSR
1406 pCodeInstruction pic16_pciMOVLW = {
1407 {PC_OPCODE, NULL, NULL, 0, NULL,
1412 NULL, // from branch
1419 0,0, // dest, bit instruction
1420 0,0, // branch, skip
1421 1, // literal operand
1422 0, // RAM access bit
1423 0, // fast call/return mode select bit
1424 0, // second memory operand
1426 (PCC_NONE | PCC_LITERAL), // inCond
1430 pCodeInstruction pic16_pciMOVWF = {
1431 {PC_OPCODE, NULL, NULL, 0, NULL,
1437 NULL, // from branch
1444 0,0, // dest, bit instruction
1445 0,0, // branch, skip
1446 0, // literal operand
1447 1, // RAM access bit
1448 0, // fast call/return mode select bit
1449 0, // second memory operand
1451 PCC_REGISTER, // inCond
1455 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1456 {PC_OPCODE, NULL, NULL, 0, NULL,
1461 NULL, // from branch
1468 0,0, // dest, bit instruction
1469 0,0, // branch, skip
1470 1, // literal operand
1471 0, // RAM access bit
1472 0, // fast call/return mode select bit
1473 0, // second memory operand
1475 (PCC_W | PCC_LITERAL), // inCond
1476 PCC_REGISTER // outCond - PROD
1479 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1480 {PC_OPCODE, NULL, NULL, 0, NULL,
1485 NULL, // from branch
1492 0,0, // dest, bit instruction
1493 0,0, // branch, skip
1494 0, // literal operand
1495 1, // RAM access bit
1496 0, // fast call/return mode select bit
1497 0, // second memory operand
1499 (PCC_W | PCC_REGISTER), // inCond
1500 PCC_REGISTER // outCond - PROD
1503 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1504 {PC_OPCODE, NULL, NULL, 0, NULL,
1509 NULL, // from branch
1516 0,0, // dest, bit instruction
1517 0,0, // branch, skip
1518 0, // literal operand
1519 1, // RAM access bit
1520 0, // fast call/return mode select bit
1521 0, // second memory operand
1523 PCC_REGISTER, // inCond
1524 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
1527 pCodeInstruction pic16_pciNOP = {
1528 {PC_OPCODE, NULL, NULL, 0, NULL,
1533 NULL, // from branch
1540 0,0, // dest, bit instruction
1541 0,0, // branch, skip
1542 0, // literal operand
1543 0, // RAM access bit
1544 0, // fast call/return mode select bit
1545 0, // second memory operand
1551 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1552 {PC_OPCODE, NULL, NULL, 0, NULL,
1557 NULL, // from branch
1564 0,0, // dest, bit instruction
1565 0,0, // branch, skip
1566 0, // literal operand
1567 0, // RAM access bit
1568 0, // fast call/return mode select bit
1569 0, // second memory operand
1575 pCodeInstruction pic16_pciPUSH = {
1576 {PC_OPCODE, NULL, NULL, 0, NULL,
1581 NULL, // from branch
1588 0,0, // dest, bit instruction
1589 0,0, // branch, skip
1590 0, // literal operand
1591 0, // RAM access bit
1592 0, // fast call/return mode select bit
1593 0, // second memory operand
1599 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1600 {PC_OPCODE, NULL, NULL, 0, NULL,
1605 NULL, // from branch
1612 0,0, // dest, bit instruction
1613 0,0, // branch, skip
1614 0, // literal operand
1615 0, // RAM access bit
1616 0, // fast call/return mode select bit
1617 0, // second memory operand
1619 PCC_REL_ADDR, // inCond
1623 pCodeInstruction pic16_pciRETFIE = {
1624 {PC_OPCODE, NULL, NULL, 0, NULL,
1630 NULL, // from branch
1637 0,0, // dest, bit instruction
1638 1,0, // branch, skip
1639 0, // literal operand
1640 0, // RAM access bit
1641 1, // fast call/return mode select bit
1642 0, // second memory operand
1645 PCC_NONE // outCond (not true... affects the GIE bit too)
1648 pCodeInstruction pic16_pciRETLW = {
1649 {PC_OPCODE, NULL, NULL, 0, NULL,
1655 NULL, // from branch
1662 0,0, // dest, bit instruction
1663 1,0, // branch, skip
1664 1, // literal operand
1665 0, // RAM access bit
1666 0, // fast call/return mode select bit
1667 0, // second memory operand
1669 PCC_LITERAL, // inCond
1673 pCodeInstruction pic16_pciRETURN = {
1674 {PC_OPCODE, NULL, NULL, 0, NULL,
1680 NULL, // from branch
1687 0,0, // dest, bit instruction
1688 1,0, // branch, skip
1689 0, // literal operand
1690 0, // RAM access bit
1691 1, // fast call/return mode select bit
1692 0, // second memory operand
1697 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1698 {PC_OPCODE, NULL, NULL, 0, NULL,
1704 NULL, // from branch
1711 1,0, // dest, bit instruction
1712 0,0, // branch, skip
1713 0, // literal operand
1714 1, // RAM access bit
1715 0, // fast call/return mode select bit
1716 0, // second memory operand
1718 (PCC_C | PCC_REGISTER), // inCond
1719 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1722 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1723 {PC_OPCODE, NULL, NULL, 0, NULL,
1729 NULL, // from branch
1736 0,0, // dest, bit instruction
1737 0,0, // branch, skip
1738 0, // literal operand
1739 1, // RAM access bit
1740 0, // fast call/return mode select bit
1741 0, // second memory operand
1743 (PCC_C | PCC_REGISTER), // inCond
1744 (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1747 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1748 {PC_OPCODE, NULL, NULL, 0, NULL,
1754 NULL, // from branch
1761 1,0, // dest, bit instruction
1762 0,0, // branch, skip
1763 0, // literal operand
1764 1, // RAM access bit
1765 0, // fast call/return mode select bit
1766 0, // second memory operand
1768 PCC_REGISTER, // inCond
1769 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1771 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1772 {PC_OPCODE, NULL, NULL, 0, NULL,
1778 NULL, // from branch
1785 0,0, // dest, bit instruction
1786 0,0, // branch, skip
1787 0, // literal operand
1788 1, // RAM access bit
1789 0, // fast call/return mode select bit
1790 0, // second memory operand
1792 PCC_REGISTER, // inCond
1793 (PCC_W | PCC_Z | PCC_N) // outCond
1795 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1796 {PC_OPCODE, NULL, NULL, 0, NULL,
1802 NULL, // from branch
1809 1,0, // dest, bit instruction
1810 0,0, // branch, skip
1811 0, // literal operand
1812 1, // RAM access bit
1813 0, // fast call/return mode select bit
1814 0, // second memory operand
1816 (PCC_C | PCC_REGISTER), // inCond
1817 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1819 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1820 {PC_OPCODE, NULL, NULL, 0, NULL,
1826 NULL, // from branch
1833 0,0, // dest, bit instruction
1834 0,0, // branch, skip
1835 0, // literal operand
1836 1, // RAM access bit
1837 0, // fast call/return mode select bit
1838 0, // second memory operand
1840 (PCC_C | PCC_REGISTER), // inCond
1841 (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1843 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
1844 {PC_OPCODE, NULL, NULL, 0, NULL,
1850 NULL, // from branch
1857 1,0, // dest, bit instruction
1858 0,0, // branch, skip
1859 0, // literal operand
1860 1, // RAM access bit
1861 0, // fast call/return mode select bit
1862 0, // second memory operand
1864 PCC_REGISTER, // inCond
1865 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1868 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
1869 {PC_OPCODE, NULL, NULL, 0, NULL,
1875 NULL, // from branch
1882 0,0, // dest, bit instruction
1883 0,0, // branch, skip
1884 0, // literal operand
1885 1, // RAM access bit
1886 0, // fast call/return mode select bit
1887 0, // second memory operand
1889 PCC_REGISTER, // inCond
1890 (PCC_W | PCC_Z | PCC_N) // outCond
1893 pCodeInstruction pic16_pciSETF = { // mdubuc - New
1894 {PC_OPCODE, NULL, NULL, 0, NULL,
1900 NULL, // from branch
1907 0,0, // dest, bit instruction
1908 0,0, // branch, skip
1909 0, // literal operand
1910 1, // RAM access bit
1911 0, // fast call/return mode select bit
1912 0, // second memory operand
1914 PCC_REGISTER, // inCond
1915 PCC_REGISTER // outCond
1918 pCodeInstruction pic16_pciSUBLW = {
1919 {PC_OPCODE, NULL, NULL, 0, NULL,
1925 NULL, // from branch
1932 0,0, // dest, bit instruction
1933 0,0, // branch, skip
1934 1, // literal operand
1935 0, // RAM access bit
1936 0, // fast call/return mode select bit
1937 0, // second memory operand
1939 (PCC_W | PCC_LITERAL), // inCond
1940 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1943 pCodeInstruction pic16_pciSUBFWB = {
1944 {PC_OPCODE, NULL, NULL, 0, NULL,
1950 NULL, // from branch
1957 1,0, // dest, bit instruction
1958 0,0, // branch, skip
1959 0, // literal operand
1960 1, // RAM access bit
1961 0, // fast call/return mode select bit
1962 0, // second memory operand
1964 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1965 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1968 pCodeInstruction pic16_pciSUBWF = {
1969 {PC_OPCODE, NULL, NULL, 0, NULL,
1975 NULL, // from branch
1982 1,0, // dest, bit instruction
1983 0,0, // branch, skip
1984 0, // literal operand
1985 1, // RAM access bit
1986 0, // fast call/return mode select bit
1987 0, // second memory operand
1989 (PCC_W | PCC_REGISTER), // inCond
1990 (PCC_REGISTER | PCC_Z) // outCond
1993 pCodeInstruction pic16_pciSUBFW = {
1994 {PC_OPCODE, NULL, NULL, 0, NULL,
2000 NULL, // from branch
2007 0,0, // dest, bit instruction
2008 0,0, // branch, skip
2009 0, // literal operand
2010 1, // RAM access bit
2011 0, // fast call/return mode select bit
2012 0, // second memory operand
2014 (PCC_W | PCC_REGISTER), // inCond
2015 (PCC_W | PCC_Z | PCC_OV | PCC_N) // outCond
2018 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2019 {PC_OPCODE, NULL, NULL, 0, NULL,
2025 NULL, // from branch
2032 1,0, // dest, bit instruction
2033 0,0, // branch, skip
2034 0, // literal operand
2035 1, // RAM access bit
2036 0, // fast call/return mode select bit
2037 0, // second memory operand
2039 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2040 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2043 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2044 {PC_OPCODE, NULL, NULL, 0, NULL,
2050 NULL, // from branch
2057 0,0, // dest, bit instruction
2058 0,0, // branch, skip
2059 0, // literal operand
2060 1, // RAM access bit
2061 0, // fast call/return mode select bit
2062 0, // second memory operand
2064 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2065 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2068 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2069 {PC_OPCODE, NULL, NULL, 0, NULL,
2075 NULL, // from branch
2082 1,0, // dest, bit instruction
2083 0,0, // branch, skip
2084 0, // literal operand
2085 1, // RAM access bit
2086 0, // fast call/return mode select bit
2087 0, // second memory operand
2089 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2090 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2093 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2094 {PC_OPCODE, NULL, NULL, 0, NULL,
2100 NULL, // from branch
2107 0,0, // dest, bit instruction
2108 0,0, // branch, skip
2109 0, // literal operand
2110 1, // RAM access bit
2111 0, // fast call/return mode select bit
2112 0, // second memory operand
2114 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2115 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2118 pCodeInstruction pic16_pciSWAPF = {
2119 {PC_OPCODE, NULL, NULL, 0, NULL,
2125 NULL, // from branch
2132 1,0, // dest, bit instruction
2133 0,0, // branch, skip
2134 0, // literal operand
2135 1, // RAM access bit
2136 0, // fast call/return mode select bit
2137 0, // second memory operand
2139 (PCC_REGISTER), // inCond
2140 (PCC_REGISTER) // outCond
2143 pCodeInstruction pic16_pciSWAPFW = {
2144 {PC_OPCODE, NULL, NULL, 0, NULL,
2150 NULL, // from branch
2157 0,0, // dest, bit instruction
2158 0,0, // branch, skip
2159 0, // literal operand
2160 1, // RAM access bit
2161 0, // fast call/return mode select bit
2162 0, // second memory operand
2164 (PCC_REGISTER), // inCond
2170 // mdubuc - Remove TRIS
2172 pCodeInstruction pic16_pciTRIS = {
2173 {PC_OPCODE, NULL, NULL, 0, NULL,
2179 NULL, // from branch
2186 0,0, // dest, bit instruction
2187 0,0, // branch, skip
2188 0, // literal operand
2189 0, // second memory operand
2192 PCC_REGISTER // outCond
2196 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2197 {PC_OPCODE, NULL, NULL, 0, NULL,
2203 NULL, // from branch
2210 0,0, // dest, bit instruction
2211 1,1, // branch, skip
2212 0, // literal operand
2213 1, // RAM access bit
2214 0, // fast call/return mode select bit
2215 0, // second memory operand
2217 PCC_REGISTER, // inCond
2221 pCodeInstruction pic16_pciXORWF = {
2222 {PC_OPCODE, NULL, NULL, 0, NULL,
2228 NULL, // from branch
2235 1,0, // dest, bit instruction
2236 0,0, // branch, skip
2237 0, // literal operand
2238 1, // RAM access bit
2239 0, // fast call/return mode select bit
2240 0, // second memory operand
2242 (PCC_W | PCC_REGISTER), // inCond
2243 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
2246 pCodeInstruction pic16_pciXORFW = {
2247 {PC_OPCODE, NULL, NULL, 0, NULL,
2253 NULL, // from branch
2260 0,0, // dest, bit instruction
2261 0,0, // branch, skip
2262 0, // literal operand
2263 1, // RAM access bit
2264 0, // fast call/return mode select bit
2265 0, // second memory operand
2267 (PCC_W | PCC_REGISTER), // inCond
2268 (PCC_W | PCC_Z | PCC_N) // outCond
2271 pCodeInstruction pic16_pciXORLW = {
2272 {PC_OPCODE, NULL, NULL, 0, NULL,
2278 NULL, // from branch
2285 0,0, // dest, bit instruction
2286 0,0, // branch, skip
2287 1, // literal operand
2288 1, // RAM access bit
2289 0, // fast call/return mode select bit
2290 0, // second memory operand
2292 (PCC_W | PCC_LITERAL), // inCond
2293 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N) // outCond
2297 #define MAX_PIC16MNEMONICS 100
2298 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2301 /* This definition needs to be part of configure.in */
2302 // #define USE_VSNPRINTF
2304 #ifdef USE_VSNPRINTF
2305 // Alas, vsnprintf is not ANSI standard, and does not exist
2306 // on Solaris (and probably other non-Gnu flavored Unixes).
2308 /*-----------------------------------------------------------------*/
2309 /* SAFE_snprintf - like snprintf except the string pointer is */
2310 /* after the string has been printed to. This is */
2311 /* useful for printing to string as though if it */
2312 /* were a stream. */
2313 /*-----------------------------------------------------------------*/
2314 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2322 va_start(val, format);
2324 vsnprintf(*str, *size, format, val);
2330 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2331 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2339 #else // USE_VSNPRINTF
2341 // This version is *not* safe, despite the name.
2343 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2347 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2352 va_start(val, format);
2354 vsprintf(buffer, format, val);
2357 len = strlen(buffer);
2359 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2360 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2363 strcpy(*str, buffer);
2369 #endif // USE_VSNPRINTF
2371 #endif // OPT_DISABLE_PIC
2374 extern void pic16_initStack(int base_address, int size);
2375 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2376 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2377 extern void pic16_init_pic(char *);
2379 void pic16_pCodeInitRegisters(void)
2381 static int initialized=0;
2387 pic16_initStack(0xfff, 8);
2388 pic16_init_pic(port->processor);
2390 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
2391 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2392 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
2393 pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80);
2394 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2395 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2396 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2398 pic16_pc_status.rIdx = IDX_STATUS;
2399 pic16_pc_fsr0.rIdx = IDX_FSR0;
2400 pic16_pc_indf0.rIdx = IDX_INDF0;
2401 pic16_pc_intcon.rIdx = IDX_INTCON;
2402 pic16_pc_pcl.rIdx = IDX_PCL;
2403 pic16_pc_pclath.rIdx = IDX_PCLATH;
2404 pic16_pc_wreg.rIdx = IDX_WREG;
2406 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2407 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
2408 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2410 pic16_pc_kzero.rIdx = IDX_KZ;
2411 pic16_pc_wsave.rIdx = IDX_WSAVE;
2412 pic16_pc_ssave.rIdx = IDX_SSAVE;
2414 /* probably should put this in a separate initialization routine */
2415 pb_dead_pcodes = newpBlock();
2420 /*-----------------------------------------------------------------*/
2421 /* mnem2key - convert a pic mnemonic into a hash key */
2422 /* (BTW - this spreads the mnemonics quite well) */
2424 /*-----------------------------------------------------------------*/
2426 int mnem2key(char const *mnem)
2435 key += toupper(*mnem++) +1;
2439 return (key & 0x1f);
2442 #endif // OPT_DISABLE_PIC
2444 void pic16initMnemonics(void)
2449 pCodeInstruction *pci;
2451 if(mnemonics_initialized)
2454 // NULL out the array before making the assignments
2455 // since we check the array contents below this initialization.
2457 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2458 pic16Mnemonics[i] = NULL;
2461 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2462 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2463 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2464 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2465 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2466 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2467 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2468 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2469 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2470 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2471 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2472 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2473 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2474 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2475 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2476 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2477 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2478 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2479 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2480 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2481 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2482 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2483 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2484 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2485 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2486 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2487 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2488 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2489 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2490 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2491 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2492 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2493 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2494 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2495 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2496 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2497 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2498 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2499 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2500 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2501 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2502 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2503 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2504 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2505 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2506 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2507 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2508 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2509 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2510 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2511 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2512 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2513 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2514 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2515 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2516 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2517 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2518 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2519 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2520 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2521 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2522 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2523 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2524 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2525 pic16Mnemonics[POC_RLCF] = &pic16_pciRLNCF;
2526 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2527 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2528 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2529 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2530 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2531 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2532 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2533 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2534 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2535 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2536 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2537 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2538 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2539 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2540 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
2541 pic16Mnemonics[POC_TRIS] = &pic16_pciTRIS;
2542 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
2543 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
2544 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
2545 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
2547 for(i=0; i<MAX_PIC16MNEMONICS; i++)
2548 if(pic16Mnemonics[i])
2549 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
2550 pci = hTabFirstItem(pic16MnemonicsHash, &key);
2553 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
2554 pci = hTabNextItem(pic16MnemonicsHash, &key);
2557 mnemonics_initialized = 1;
2560 int pic16_getpCodePeepCommand(char *cmd);
2562 int pic16_getpCode(char *mnem,unsigned dest)
2565 pCodeInstruction *pci;
2566 int key = mnem2key(mnem);
2568 if(!mnemonics_initialized)
2569 pic16initMnemonics();
2571 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
2575 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
2576 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst) ||
2577 (pci->num_ops <= 2 && pci->isAccess) ||
2578 (pci->num_ops <= 2 && pci->isFastCall))
2582 pci = hTabNextItemWK (pic16MnemonicsHash);
2589 /*-----------------------------------------------------------------*
2590 * pic16initpCodePeepCommands
2592 *-----------------------------------------------------------------*/
2593 void pic16initpCodePeepCommands(void)
2601 hTabAddItem(&pic16pCodePeepCommandsHash,
2602 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
2604 } while (peepCommands[i].cmd);
2606 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
2609 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
2610 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
2615 /*-----------------------------------------------------------------
2618 *-----------------------------------------------------------------*/
2620 int pic16_getpCodePeepCommand(char *cmd)
2624 int key = mnem2key(cmd);
2627 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
2630 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2631 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2635 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
2642 static char getpBlock_dbName(pBlock *pb)
2648 return pb->cmemmap->dbName;
2652 void pic16_pBlockConvert2ISR(pBlock *pb)
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
2665 /* instances to the front of the doubly linked */
2666 /* list of pBlocks */
2667 /*-----------------------------------------------------------------*/
2669 void pic16_movepBlock2Head(char dbName)
2673 pb = the_pFile->pbHead;
2677 if(getpBlock_dbName(pb) == dbName) {
2678 pBlock *pbn = pb->next;
2679 pb->next = the_pFile->pbHead;
2680 the_pFile->pbHead->prev = pb;
2681 the_pFile->pbHead = pb;
2684 pb->prev->next = pbn;
2686 // If the pBlock that we just moved was the last
2687 // one in the link of all of the pBlocks, then we
2688 // need to point the tail to the block just before
2689 // the one we moved.
2690 // Note: if pb->next is NULL, then pb must have
2691 // been the last pBlock in the chain.
2694 pbn->prev = pb->prev;
2696 the_pFile->pbTail = pb->prev;
2707 void pic16_copypCode(FILE *of, char dbName)
2711 if(!of || !the_pFile)
2714 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2715 if(getpBlock_dbName(pb) == dbName) {
2717 pic16_printpBlock(of,pb);
2722 void pic16_pcode_test(void)
2725 DFPRINTF((stderr,"pcode is alive!\n"));
2735 /* create the file name */
2736 strcpy(buffer,dstFileName);
2737 strcat(buffer,".p");
2739 if( !(pFile = fopen(buffer, "w" ))) {
2740 werror(E_FILE_OPEN_ERR,buffer);
2744 fprintf(pFile,"pcode dump\n\n");
2746 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2747 fprintf(pFile,"\n\tNew pBlock\n\n");
2749 fprintf(pFile,"%s",pb->cmemmap->sname);
2751 fprintf(pFile,"internal pblock");
2753 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2754 pic16_printpBlock(pFile,pb);
2758 /*-----------------------------------------------------------------*/
2759 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
2760 /* ister, RegCond will return the bit being referenced. */
2762 /* fixme - why not just OR in the pcop bit field */
2763 /*-----------------------------------------------------------------*/
2765 static int RegCond(pCodeOp *pcop)
2771 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
2772 switch(PCORB(pcop)->bit) {
2786 /*-----------------------------------------------------------------*/
2787 /* pic16_newpCode - create and return a newly initialized pCode */
2789 /* fixme - rename this */
2791 /* The purpose of this routine is to create a new Instruction */
2792 /* pCode. This is called by gen.c while the assembly code is being */
2796 /* PIC_OPCODE op - the assembly instruction we wish to create. */
2797 /* (note that the op is analogous to but not the */
2798 /* same thing as the opcode of the instruction.) */
2799 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
2802 /* a pointer to the new malloc'd pCode is returned. */
2806 /*-----------------------------------------------------------------*/
2807 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
2809 pCodeInstruction *pci ;
2811 if(!mnemonics_initialized)
2812 pic16initMnemonics();
2814 pci = Safe_calloc(1, sizeof(pCodeInstruction));
2816 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
2817 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
2820 if(pci->inCond & PCC_EXAMINE_PCOP)
2821 pci->inCond |= RegCond(pcop);
2823 if(pci->outCond & PCC_EXAMINE_PCOP)
2824 pci->outCond |= RegCond(pcop);
2826 pci->pc.prev = pci->pc.next = NULL;
2827 return (pCode *)pci;
2830 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
2836 /*-----------------------------------------------------------------*/
2837 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
2839 /* Wild pcodes are used during the peep hole optimizer to serve */
2840 /* as place holders for any instruction. When a snippet of code is */
2841 /* compared to a peep hole rule, the wild card opcode will match */
2842 /* any instruction. However, the optional operand and label are */
2843 /* additional qualifiers that must also be matched before the */
2844 /* line (of assembly code) is declared matched. Note that the */
2845 /* operand may be wild too. */
2847 /* Note, a wild instruction is specified just like a wild var: */
2848 /* %4 ; A wild instruction, */
2849 /* See the peeph.def file for additional examples */
2851 /*-----------------------------------------------------------------*/
2853 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
2858 pcw = Safe_calloc(1,sizeof(pCodeWild));
2860 pcw->pci.pc.type = PC_WILD;
2861 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
2862 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
2863 pcw->pci.pc.pb = NULL;
2865 // pcw->pci.pc.analyze = genericAnalyze;
2866 pcw->pci.pc.destruct = genericDestruct;
2867 pcw->pci.pc.print = genericPrint;
2869 pcw->id = pCodeID; // this is the 'n' in %n
2870 pcw->operand = optional_operand;
2871 pcw->label = optional_label;
2873 pcw->mustBeBitSkipInst = 0;
2874 pcw->mustNotBeBitSkipInst = 0;
2875 pcw->invertBitSkipInst = 0;
2877 return ( (pCode *)pcw);
2881 /*-----------------------------------------------------------------*/
2882 /* newPcodeInlineP - create a new pCode from a char string */
2883 /*-----------------------------------------------------------------*/
2886 pCode *pic16_newpCodeInlineP(char *cP)
2891 pcc = Safe_calloc(1,sizeof(pCodeComment));
2893 pcc->pc.type = PC_INLINE;
2894 pcc->pc.prev = pcc->pc.next = NULL;
2895 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2898 // pcc->pc.analyze = genericAnalyze;
2899 pcc->pc.destruct = genericDestruct;
2900 pcc->pc.print = genericPrint;
2903 pcc->comment = Safe_strdup(cP);
2905 pcc->comment = NULL;
2907 return ( (pCode *)pcc);
2911 /*-----------------------------------------------------------------*/
2912 /* newPcodeCharP - create a new pCode from a char string */
2913 /*-----------------------------------------------------------------*/
2915 pCode *pic16_newpCodeCharP(char *cP)
2920 pcc = Safe_calloc(1,sizeof(pCodeComment));
2922 pcc->pc.type = PC_COMMENT;
2923 pcc->pc.prev = pcc->pc.next = NULL;
2924 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2927 // pcc->pc.analyze = genericAnalyze;
2928 pcc->pc.destruct = genericDestruct;
2929 pcc->pc.print = genericPrint;
2932 pcc->comment = Safe_strdup(cP);
2934 pcc->comment = NULL;
2936 return ( (pCode *)pcc);
2940 /*-----------------------------------------------------------------*/
2941 /* pic16_newpCodeFunction - */
2942 /*-----------------------------------------------------------------*/
2945 pCode *pic16_newpCodeFunction(char *mod,char *f)
2949 pcf = Safe_calloc(1,sizeof(pCodeFunction));
2950 //_ALLOC(pcf,sizeof(pCodeFunction));
2952 pcf->pc.type = PC_FUNCTION;
2953 pcf->pc.prev = pcf->pc.next = NULL;
2954 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
2957 // pcf->pc.analyze = genericAnalyze;
2958 pcf->pc.destruct = genericDestruct;
2959 pcf->pc.print = pCodePrintFunction;
2964 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
2965 pcf->modname = Safe_calloc(1,strlen(mod)+1);
2966 strcpy(pcf->modname,mod);
2968 pcf->modname = NULL;
2971 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
2972 pcf->fname = Safe_calloc(1,strlen(f)+1);
2973 strcpy(pcf->fname,f);
2977 return ( (pCode *)pcf);
2981 /*-----------------------------------------------------------------*/
2982 /* pic16_newpCodeFlow */
2983 /*-----------------------------------------------------------------*/
2984 static void destructpCodeFlow(pCode *pc)
2986 if(!pc || !isPCFL(pc))
2993 pic16_unlinkpCode(pc);
2995 deleteSet(&PCFL(pc)->registers);
2996 deleteSet(&PCFL(pc)->from);
2997 deleteSet(&PCFL(pc)->to);
3002 pCode *pic16_newpCodeFlow(void )
3006 //_ALLOC(pcflow,sizeof(pCodeFlow));
3007 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3009 pcflow->pc.type = PC_FLOW;
3010 pcflow->pc.prev = pcflow->pc.next = NULL;
3011 pcflow->pc.pb = NULL;
3013 // pcflow->pc.analyze = genericAnalyze;
3014 pcflow->pc.destruct = destructpCodeFlow;
3015 pcflow->pc.print = genericPrint;
3017 pcflow->pc.seq = GpcFlowSeq++;
3019 pcflow->from = pcflow->to = NULL;
3021 pcflow->inCond = PCC_NONE;
3022 pcflow->outCond = PCC_NONE;
3024 pcflow->firstBank = -1;
3025 pcflow->lastBank = -1;
3027 pcflow->FromConflicts = 0;
3028 pcflow->ToConflicts = 0;
3032 pcflow->registers = newSet();
3034 return ( (pCode *)pcflow);
3038 /*-----------------------------------------------------------------*/
3039 /*-----------------------------------------------------------------*/
3040 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3042 pCodeFlowLink *pcflowLink;
3044 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3046 pcflowLink->pcflow = pcflow;
3047 pcflowLink->bank_conflict = 0;
3052 /*-----------------------------------------------------------------*/
3053 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3054 /*-----------------------------------------------------------------*/
3056 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3061 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3063 pccs->pc.type = PC_CSOURCE;
3064 pccs->pc.prev = pccs->pc.next = NULL;
3067 pccs->pc.destruct = genericDestruct;
3068 pccs->pc.print = genericPrint;
3070 pccs->line_number = ln;
3072 pccs->line = Safe_strdup(l);
3077 pccs->file_name = Safe_strdup(f);
3079 pccs->file_name = NULL;
3081 return ( (pCode *)pccs);
3086 /*******************************************************************/
3087 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3088 /* added by VR 6-Jun-2003 */
3089 /*******************************************************************/
3091 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3095 char buffer[256]; // how long can a directive be?!
3099 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3100 pcad->pc.type = PC_ASMDIR;
3101 pcad->pc.prev = pcad->pc.next = NULL;
3104 pcad->pc.destruct = genericDestruct;
3105 pcad->pc.print = genericPrint;
3107 if(asdir && *asdir) {
3108 pcad->directive = Safe_strdup( asdir );
3111 va_start(ap, argfmt);
3113 if(argfmt && *argfmt)
3114 vsprintf(buffer, argfmt, ap);
3118 while(isspace(*lbp))lbp++;
3121 pcad->arg = Safe_strdup( lbp );
3123 return ((pCode *)pcad);
3126 /*-----------------------------------------------------------------*/
3127 /* pCodeLabelDestruct - free memory used by a label. */
3128 /*-----------------------------------------------------------------*/
3129 static void pCodeLabelDestruct(pCode *pc)
3135 if((pc->type == PC_LABEL) && PCL(pc)->label)
3136 free(PCL(pc)->label);
3142 pCode *pic16_newpCodeLabel(char *name, int key)
3148 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3150 pcl->pc.type = PC_LABEL;
3151 pcl->pc.prev = pcl->pc.next = NULL;
3152 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3155 // pcl->pc.analyze = genericAnalyze;
3156 pcl->pc.destruct = pCodeLabelDestruct;
3157 pcl->pc.print = pCodePrintLabel;
3163 sprintf(s,"_%05d_DS_",key);
3168 pcl->label = Safe_strdup(s);
3170 //fprintf(stderr,"pic16_newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
3171 return ( (pCode *)pcl);
3176 /*-----------------------------------------------------------------*/
3177 /* newpBlock - create and return a pointer to a new pBlock */
3178 /*-----------------------------------------------------------------*/
3179 static pBlock *newpBlock(void)
3184 PpB = Safe_calloc(1,sizeof(pBlock) );
3185 PpB->next = PpB->prev = NULL;
3187 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3188 PpB->tregisters = NULL;
3190 PpB->FlowTree = NULL;
3196 /*-----------------------------------------------------------------*/
3197 /* pic16_newpCodeChain - create a new chain of pCodes */
3198 /*-----------------------------------------------------------------*
3200 * This function will create a new pBlock and the pointer to the
3201 * pCode that is passed in will be the first pCode in the block.
3202 *-----------------------------------------------------------------*/
3205 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3208 pBlock *pB = newpBlock();
3210 pB->pcHead = pB->pcTail = pc;
3217 /*-----------------------------------------------------------------*/
3218 /* pic16_newpCodeOpLabel - Create a new label given the key */
3219 /* Note, a negative key means that the label is part of wild card */
3220 /* (and hence a wild card label) used in the pCodePeep */
3221 /* optimizations). */
3222 /*-----------------------------------------------------------------*/
3224 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3227 static int label_key=-1;
3231 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3232 pcop->type = PO_LABEL;
3237 sprintf(s=buffer,"_%05d_DS_",key);
3239 s = name, key = label_key--;
3242 pcop->name = Safe_strdup(s);
3244 ((pCodeOpLabel *)pcop)->key = key;
3246 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3250 /*-----------------------------------------------------------------*/
3251 /*-----------------------------------------------------------------*/
3252 pCodeOp *pic16_newpCodeOpLit(int lit)
3258 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3259 pcop->type = PO_LITERAL;
3263 sprintf(s,"0x%02x",lit);
3265 pcop->name = Safe_strdup(s);
3268 ((pCodeOpLit *)pcop)->lit = lit;
3273 /*-----------------------------------------------------------------*/
3274 /*-----------------------------------------------------------------*/
3275 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3279 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3280 pcop->type = PO_IMMEDIATE;
3282 regs *r = pic16_dirregWithName(name);
3283 pcop->name = Safe_strdup(name);
3286 //fprintf(stderr, " pic16_newpCodeOpImmd reg %s exists\n",name);
3287 PCOI(pcop)->rIdx = r->rIdx;
3289 //fprintf(stderr, " pic16_newpCodeOpImmd reg %s doesn't exist\n",name);
3290 PCOI(pcop)->rIdx = -1;
3292 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3297 PCOI(pcop)->index = index;
3298 PCOI(pcop)->offset = offset;
3299 PCOI(pcop)->_const = code_space;
3304 /*-----------------------------------------------------------------*/
3305 /*-----------------------------------------------------------------*/
3306 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3312 if(!pcwb || !subtype) {
3313 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3317 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3318 pcop->type = PO_WILD;
3319 sprintf(s,"%%%d",id);
3320 pcop->name = Safe_strdup(s);
3322 PCOW(pcop)->id = id;
3323 PCOW(pcop)->pcwb = pcwb;
3324 PCOW(pcop)->subtype = subtype;
3325 PCOW(pcop)->matched = NULL;
3330 /*-----------------------------------------------------------------*/
3331 /*-----------------------------------------------------------------*/
3332 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3336 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3337 pcop->type = PO_GPR_BIT;
3339 pcop->name = Safe_strdup(s);
3343 PCORB(pcop)->bit = bit;
3344 PCORB(pcop)->inBitSpace = inBitSpace;
3346 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3347 PCOR(pcop)->r = NULL;
3348 PCOR(pcop)->rIdx = 0;
3352 /*-----------------------------------------------------------------*
3353 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3355 * If rIdx >=0 then a specific register from the set of registers
3356 * will be selected. If rIdx <0, then a new register will be searched
3358 *-----------------------------------------------------------------*/
3360 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3364 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3369 PCOR(pcop)->rIdx = rIdx;
3370 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3372 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3375 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3378 pcop->type = PCOR(pcop)->r->pc_type;
3383 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3387 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3388 PCOR(pcop)->r = pic16_allocRegByName(name, 1);
3389 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3390 pcop->type = PCOR(pcop)->r->pc_type;
3391 pcop->name = PCOR(pcop)->r->name;
3396 /*-----------------------------------------------------------------*/
3397 /*-----------------------------------------------------------------*/
3399 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3406 pcop = pic16_newpCodeOpBit(name, -1,0);
3410 pcop = pic16_newpCodeOpLit(-1);
3414 pcop = pic16_newpCodeOpLabel(NULL,-1);
3417 pcop = pic16_newpCodeOpReg(-1);
3420 case PO_GPR_REGISTER:
3422 pcop = pic16_newpCodeOpRegFromStr(name);
3424 pcop = pic16_newpCodeOpReg(-1);
3428 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3431 pcop->name = Safe_strdup(name);
3439 /*-----------------------------------------------------------------*/
3440 /*-----------------------------------------------------------------*/
3441 void pic16_pCodeConstString(char *name, char *value)
3445 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
3450 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3452 pic16_addpBlock(pb);
3454 sprintf(buffer,"; %s = %s",name,value);
3456 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3457 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3460 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3466 /*-----------------------------------------------------------------*/
3467 /*-----------------------------------------------------------------*/
3469 static void pCodeReadCodeTable(void)
3473 fprintf(stderr, " %s\n",__FUNCTION__);
3475 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3477 pic16_addpBlock(pb);
3479 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3480 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3481 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3482 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3484 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3485 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3486 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3487 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3492 /*-----------------------------------------------------------------*/
3493 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3494 /*-----------------------------------------------------------------*/
3495 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3502 /* If this is the first pcode to be added to a block that
3503 * was initialized with a NULL pcode, then go ahead and
3504 * make this pcode the head and tail */
3505 pb->pcHead = pb->pcTail = pc;
3508 pb->pcTail->next = pc;
3510 pc->prev = pb->pcTail;
3517 /*-----------------------------------------------------------------*/
3518 /* pic16_addpBlock - place a pBlock into the pFile */
3519 /*-----------------------------------------------------------------*/
3520 void pic16_addpBlock(pBlock *pb)
3522 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3525 /* First time called, we'll pass through here. */
3526 //_ALLOC(the_pFile,sizeof(pFile));
3527 the_pFile = Safe_calloc(1,sizeof(pFile));
3528 the_pFile->pbHead = the_pFile->pbTail = pb;
3529 the_pFile->functions = NULL;
3533 the_pFile->pbTail->next = pb;
3534 pb->prev = the_pFile->pbTail;
3536 the_pFile->pbTail = pb;
3539 /*-----------------------------------------------------------------*/
3540 /* removepBlock - remove a pBlock from the pFile */
3541 /*-----------------------------------------------------------------*/
3542 static void removepBlock(pBlock *pb)
3550 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3552 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3555 if(pbs == the_pFile->pbHead)
3556 the_pFile->pbHead = pbs->next;
3558 if (pbs == the_pFile->pbTail)
3559 the_pFile->pbTail = pbs->prev;
3562 pbs->next->prev = pbs->prev;
3565 pbs->prev->next = pbs->next;
3572 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3576 /*-----------------------------------------------------------------*/
3577 /* printpCode - write the contents of a pCode to a file */
3578 /*-----------------------------------------------------------------*/
3579 static void printpCode(FILE *of, pCode *pc)
3590 fprintf(of,"warning - unable to print pCode\n");
3593 /*-----------------------------------------------------------------*/
3594 /* pic16_printpBlock - write the contents of a pBlock to a file */
3595 /*-----------------------------------------------------------------*/
3596 void pic16_printpBlock(FILE *of, pBlock *pb)
3606 for(pc = pb->pcHead; pc; pc = pc->next)
3611 /*-----------------------------------------------------------------*/
3613 /* pCode processing */
3617 /*-----------------------------------------------------------------*/
3619 void pic16_unlinkpCode(pCode *pc)
3625 fprintf(stderr,"Unlinking: ");
3626 printpCode(stderr, pc);
3629 pc->prev->next = pc->next;
3631 pc->next->prev = pc->prev;
3633 pc->prev = pc->next = NULL;
3637 /*-----------------------------------------------------------------*/
3638 /*-----------------------------------------------------------------*/
3640 static void genericDestruct(pCode *pc)
3643 pic16_unlinkpCode(pc);
3646 /* For instructions, tell the register (if there's one used)
3647 * that it's no longer needed */
3648 regs *reg = pic16_getRegFromInstruction(pc);
3650 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3652 if(PCI(pc)->is2MemOp) {
3653 reg = pic16_getRegFromInstruction2(pc);
3655 deleteSetItem(&(reg->reglives.usedpCodes), pc);
3659 /* Instead of deleting the memory used by this pCode, mark
3660 * the object as bad so that if there's a pointer to this pCode
3661 * dangling around somewhere then (hopefully) when the type is
3662 * checked we'll catch it.
3667 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3676 /*-----------------------------------------------------------------*/
3677 /*-----------------------------------------------------------------*/
3678 static void pBlockRegs(FILE *of, pBlock *pb)
3683 r = setFirstItem(pb->tregisters);
3685 r = setNextItem(pb->tregisters);
3690 /*-----------------------------------------------------------------*/
3691 /*-----------------------------------------------------------------*/
3692 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3697 int use_buffer = 1; // copy the string to the passed buffer pointer
3702 use_buffer = 0; // Don't bother copying the string to the buffer.
3706 switch(pcop->type) {
3710 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3713 return PCOR(pcop)->r->name;
3716 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3719 SAFE_snprintf(&buffer,&size,"%s",r->name);
3729 if(PCOI(pcop)->_const) {
3731 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3732 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3735 8 * PCOI(pcop)->offset );
3737 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
3740 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
3741 SAFE_snprintf(&s,&size,"(%s + %d)",
3743 PCOI(pcop)->index );
3745 if(PCOI(pcop)->offset)
3746 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3748 SAFE_snprintf(&s,&size,"%s",pcop->name);
3756 //size = sizeof(buffer);
3757 if( PCOR(pcop)->instance) {
3758 SAFE_snprintf(&s,&size,"(%s + %d)",
3760 PCOR(pcop)->instance );
3762 //fprintf(stderr,"PO_DIR %s\n",buffer);
3764 SAFE_snprintf(&s,&size,"%s",pcop->name);
3770 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3779 return "NO operand";
3784 /*-----------------------------------------------------------------*/
3785 /* pic16_get_op2 - variant to support two memory operand commands */
3786 /*-----------------------------------------------------------------*/
3787 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
3792 int use_buffer = 1; // copy the string to the passed buffer pointer
3797 use_buffer = 0; // Don't bother copying the string to the buffer.
3801 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",
3802 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
3803 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
3807 switch(PCOR2(pcop)->pcop2->type) {
3811 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
3814 return PCOR(PCOR2(pcop)->pcop2)->r->name;
3817 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
3820 SAFE_snprintf(&buffer,&size,"%s",r->name);
3832 if(PCOI(pcop)->_const) {
3834 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3835 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3838 8 * PCOI(pcop)->offset );
3840 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
3843 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
3844 SAFE_snprintf(&s,&size,"(%s + %d)",
3846 PCOI(pcop)->index );
3848 if(PCOI(pcop)->offset)
3849 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3851 SAFE_snprintf(&s,&size,"%s",pcop->name);
3860 //size = sizeof(buffer);
3861 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
3862 SAFE_snprintf(&s,&size,"(%s + %d)",
3863 PCOR(PCOR2(pcop)->pcop2)->r->name,
3864 PCOR(PCOR2(pcop)->pcop2)->instance );
3866 //fprintf(stderr,"PO_DIR %s\n",buffer);
3868 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
3873 if (PCOR2(pcop)->r1->name) {
3875 SAFE_snprintf(&buffer,&size,"%s",PCOR2(pcop)->r1->name);
3878 return PCOR2(pcop)->r1->name;
3886 return "NO operand";
3890 /*-----------------------------------------------------------------*/
3891 /*-----------------------------------------------------------------*/
3892 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
3896 return pic16_get_op(pcc->pcop,NULL,0);
3898 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
3899 * return ("ERROR Null: "__FUNCTION__);
3901 return ("ERROR Null: pic16_get_op_from_instruction");
3905 /*-----------------------------------------------------------------*/
3906 /*-----------------------------------------------------------------*/
3907 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3910 fprintf(of,"pcodeopprint- not implemented\n");
3913 /*-----------------------------------------------------------------*/
3914 /*-----------------------------------------------------------------*/
3915 static char *pCode2str(char *str, size_t size, pCode *pc)
3922 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3924 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3927 if(PCI(pc)->is2MemOp) {
3928 // fprintf(stderr, "HELP !\n");
3930 SAFE_snprintf(&s,&size, "%s,%s",
3931 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
3932 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
3938 if(PCI(pc)->isBitInst) {
3939 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3940 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3941 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
3942 PCI(pc)->pcop->name ,
3943 PCI(pc)->pcop->name );
3945 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
3946 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
3947 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3948 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3950 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
3951 //PCI(pc)->pcop->t.bit );
3954 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3955 if( PCI(pc)->num_ops == 3)
3956 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3958 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
3961 SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
3963 if( PCI(pc)->num_ops == 3)
3964 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3972 /* assuming that comment ends with a \n */
3973 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3977 /* assuming that inline code ends with a \n */
3978 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3982 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3985 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3988 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3991 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3994 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3997 SAFE_snprintf(&s,&size,"\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4001 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4008 /*-----------------------------------------------------------------*/
4009 /* genericPrint - the contents of a pCode to a file */
4010 /*-----------------------------------------------------------------*/
4011 static void genericPrint(FILE *of, pCode *pc)
4019 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4023 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4027 // If the opcode has a label, print that first
4029 pBranch *pbl = PCI(pc)->label;
4030 while(pbl && pbl->pc) {
4031 if(pbl->pc->type == PC_LABEL)
4032 pCodePrintLabel(of, pbl->pc);
4038 genericPrint(of,PCODE(PCI(pc)->cline));
4043 pCode2str(str, 256, pc);
4045 fprintf(of,"%s",str);
4048 if(pic16_debug_verbose) {
4049 fprintf(of, "\t;key=%03x %d",pc->seq, __LINE__);
4051 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4059 pBranch *dpb = pc->to; // debug
4061 switch ( dpb->pc->type) {
4063 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
4066 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
4069 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
4072 fprintf(of, "\t;flow");
4082 // fprintf(of,"\n"); // these are moved prior to #if 0
4086 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4087 if(PCW(pc)->pci.label)
4088 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4090 if(PCW(pc)->operand) {
4091 fprintf(of,";\toperand ");
4092 pCodeOpPrint(of,PCW(pc)->operand );
4097 if(pic16_debug_verbose) {
4098 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4099 if(PCFL(pc)->ancestor)
4100 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4107 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4110 fprintf(of, "\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4115 fprintf(of,"unknown pCode type %d\n",pc->type);
4120 /*-----------------------------------------------------------------*/
4121 /* pCodePrintFunction - prints function begin/end */
4122 /*-----------------------------------------------------------------*/
4124 static void pCodePrintFunction(FILE *of, pCode *pc)
4130 if( ((pCodeFunction *)pc)->modname)
4131 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4133 if(PCF(pc)->fname) {
4134 pBranch *exits = PCF(pc)->to;
4136 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
4139 exits = exits->next;
4142 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4145 if((PCF(pc)->from &&
4146 PCF(pc)->from->pc->type == PC_FUNCTION &&
4147 PCF(PCF(pc)->from->pc)->fname) )
4148 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4150 fprintf(of,"; exit point [can't find entry point]\n");
4153 /*-----------------------------------------------------------------*/
4154 /* pCodePrintLabel - prints label */
4155 /*-----------------------------------------------------------------*/
4157 static void pCodePrintLabel(FILE *of, pCode *pc)
4164 fprintf(of,"%s\n",PCL(pc)->label);
4165 else if (PCL(pc)->key >=0)
4166 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4168 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4171 /*-----------------------------------------------------------------*/
4172 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4173 /* remove it if it is found. */
4174 /*-----------------------------------------------------------------*/
4175 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4182 if(pcl->type == PC_OPCODE)
4183 b = PCI(pcl)->label;
4185 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4190 //fprintf (stderr, "%s \n",__FUNCTION__);
4191 //pcl->print(stderr,pcl);
4192 //pc->print(stderr,pc);
4195 //fprintf (stderr, "found label\n");
4199 bprev->next = b->next; /* Not first pCode in chain */
4203 PCI(pcl)->label = b->next; /* First pCode in chain */
4206 return; /* A label can't occur more than once */
4214 /*-----------------------------------------------------------------*/
4215 /*-----------------------------------------------------------------*/
4216 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4235 /*-----------------------------------------------------------------*/
4236 /* pBranchLink - given two pcodes, this function will link them */
4237 /* together through their pBranches */
4238 /*-----------------------------------------------------------------*/
4239 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4243 // Declare a new branch object for the 'from' pCode.
4245 //_ALLOC(b,sizeof(pBranch));
4246 b = Safe_calloc(1,sizeof(pBranch));
4247 b->pc = PCODE(t); // The link to the 'to' pCode.
4250 f->to = pic16_pBranchAppend(f->to,b);
4252 // Now do the same for the 'to' pCode.
4254 //_ALLOC(b,sizeof(pBranch));
4255 b = Safe_calloc(1,sizeof(pBranch));
4259 t->from = pic16_pBranchAppend(t->from,b);
4264 /*-----------------------------------------------------------------*/
4265 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4267 /*-----------------------------------------------------------------*/
4268 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4281 /*-----------------------------------------------------------------*/
4282 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4283 /*-----------------------------------------------------------------*/
4284 static void pCodeUnlink(pCode *pc)
4289 if(!pc->prev || !pc->next) {
4290 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4294 /* first remove the pCode from the chain */
4295 pc->prev->next = pc->next;
4296 pc->next->prev = pc->prev;
4298 /* Now for the hard part... */
4300 /* Remove the branches */
4304 pc1 = pb1->pc; /* Get the pCode that branches to the
4305 * one we're unlinking */
4307 /* search for the link back to this pCode (the one we're
4309 if(pb2 = pBranchFind(pc1->to,pc)) {
4310 pb2->pc = pc->to->pc; // make the replacement
4312 /* if the pCode we're unlinking contains multiple 'to'
4313 * branches (e.g. this a skip instruction) then we need
4314 * to copy these extra branches to the chain. */
4316 pic16_pBranchAppend(pb2, pc->to->next);
4325 /*-----------------------------------------------------------------*/
4326 /*-----------------------------------------------------------------*/
4328 static void genericAnalyze(pCode *pc)
4338 // Go through the pCodes that are in pCode chain and link
4339 // them together through the pBranches. Note, the pCodes
4340 // are linked together as a contiguous stream like the
4341 // assembly source code lines. The linking here mimics this
4342 // except that comments are not linked in.
4344 pCode *npc = pc->next;
4346 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4347 pBranchLink(pc,npc);
4352 /* reached the end of the pcode chain without finding
4353 * an instruction we could link to. */
4357 fprintf(stderr,"analyze PC_FLOW\n");
4361 fprintf(stderr,,";A bad pCode is being used\n");
4367 /*-----------------------------------------------------------------*/
4368 /*-----------------------------------------------------------------*/
4369 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4373 if(pc->type == PC_LABEL) {
4374 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4377 if(pc->type == PC_OPCODE) {
4378 pbr = PCI(pc)->label;
4380 if(pbr->pc->type == PC_LABEL) {
4381 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4391 /*-----------------------------------------------------------------*/
4392 /*-----------------------------------------------------------------*/
4393 static int checkLabel(pCode *pc)
4397 if(pc && isPCI(pc)) {
4398 pbr = PCI(pc)->label;
4400 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4410 /*-----------------------------------------------------------------*/
4411 /* findLabelinpBlock - Search the pCode for a particular label */
4412 /*-----------------------------------------------------------------*/
4413 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4420 for(pc = pb->pcHead; pc; pc = pc->next)
4421 if(compareLabel(pc,pcop_label))
4427 /*-----------------------------------------------------------------*/
4428 /* findLabel - Search the pCode for a particular label */
4429 /*-----------------------------------------------------------------*/
4430 static pCode * findLabel(pCodeOpLabel *pcop_label)
4438 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4439 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4443 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4447 /*-----------------------------------------------------------------*/
4448 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4449 /* in the linked list */
4450 /*-----------------------------------------------------------------*/
4451 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4464 /*-----------------------------------------------------------------*/
4465 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4466 /* in the linked list */
4467 /*-----------------------------------------------------------------*/
4468 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4480 /*-----------------------------------------------------------------*/
4481 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4482 /* in the linked list */
4483 /*-----------------------------------------------------------------*/
4484 pCode * pic16_findNextInstruction(pCode *pci)
4489 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4493 fprintf(stderr,"pic16_findNextInstruction: ");
4494 printpCode(stderr, pc);
4499 //fprintf(stderr,"Couldn't find instruction\n");
4503 /*-----------------------------------------------------------------*/
4504 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4505 /* in the linked list */
4506 /*-----------------------------------------------------------------*/
4507 pCode * pic16_findPrevInstruction(pCode *pci)
4509 return findPrevpCode(pci, PC_OPCODE);
4512 /*-----------------------------------------------------------------*/
4513 /* findFunctionEnd - given a pCode find the end of the function */
4514 /* that contains it */
4515 /*-----------------------------------------------------------------*/
4516 static pCode * findFunctionEnd(pCode *pc)
4520 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4526 fprintf(stderr,"Couldn't find function end\n");
4531 /*-----------------------------------------------------------------*/
4532 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4533 /* instruction with which it is associated. */
4534 /*-----------------------------------------------------------------*/
4535 static void AnalyzeLabel(pCode *pc)
4544 static void AnalyzeGOTO(pCode *pc)
4547 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4551 static void AnalyzeSKIP(pCode *pc)
4554 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4555 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4559 static void AnalyzeRETURN(pCode *pc)
4562 // branch_link(pc,findFunctionEnd(pc->next));
4568 /*-----------------------------------------------------------------*/
4569 /*-----------------------------------------------------------------*/
4570 regs * pic16_getRegFromInstruction(pCode *pc)
4576 PCI(pc)->num_ops == 0 ||
4577 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4580 switch(PCI(pc)->pcop->type) {
4583 return PCOR(PCI(pc)->pcop)->r;
4585 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4589 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4590 return PCOR(PCI(pc)->pcop)->r;
4593 if(PCOI(PCI(pc)->pcop)->r)
4594 return (PCOI(PCI(pc)->pcop)->r);
4596 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4597 return pic16_dirregWithName(PCI(pc)->pcop->name);
4598 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4601 return PCOR(PCI(pc)->pcop)->r;
4604 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4605 return PCOR(PCI(pc)->pcop)->r;
4607 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4611 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4612 //genericPrint(stderr, pc);
4620 /*-------------------------------------------------------------------------------*/
4621 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
4622 /*-------------------------------------------------------------------------------*/
4623 regs * pic16_getRegFromInstruction2(pCode *pc)
4629 PCI(pc)->num_ops == 0 ||
4630 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
4635 * operands supported in MOVFF:
4642 switch(PCI(pc)->pcop->type) {
4645 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4647 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4651 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4652 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4657 if(PCOI(PCI(pc)->pcop)->r)
4658 return (PCOI(PCI(pc)->pcop)->r);
4660 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4661 return pic16_dirregWithName(PCI(pc)->pcop->name);
4662 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4667 // return PCOR2(PCI(pc)->pcop)->r;
4670 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4671 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4675 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4678 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4679 //genericPrint(stderr, pc);
4687 /*-----------------------------------------------------------------*/
4688 /*-----------------------------------------------------------------*/
4690 static void AnalyzepBlock(pBlock *pb)
4697 /* Find all of the registers used in this pBlock
4698 * by looking at each instruction and examining it's
4701 for(pc = pb->pcHead; pc; pc = pc->next) {
4703 /* Is this an instruction with operands? */
4704 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4706 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4708 /* Loop through all of the registers declared so far in
4709 this block and see if we find this one there */
4711 regs *r = setFirstItem(pb->tregisters);
4714 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4715 PCOR(PCI(pc)->pcop)->r = r;
4718 r = setNextItem(pb->tregisters);
4722 /* register wasn't found */
4723 //r = Safe_calloc(1, sizeof(regs));
4724 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
4725 //addSet(&pb->tregisters, r);
4726 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
4727 //PCOR(PCI(pc)->pcop)->r = r;
4728 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
4730 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
4733 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
4734 if(PCOR(PCI(pc)->pcop)->r) {
4735 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
4736 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
4738 if(PCI(pc)->pcop->name)
4739 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
4741 fprintf(stderr,"ERROR: NULL register\n");
4750 /*-----------------------------------------------------------------*/
4752 /*-----------------------------------------------------------------*/
4753 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
4755 static void InsertpFlow(pCode *pc, pCode **pflow)
4758 PCFL(*pflow)->end = pc;
4760 if(!pc || !pc->next)
4763 *pflow = pic16_newpCodeFlow();
4764 pic16_pCodeInsertAfter(pc, *pflow);
4767 /*-----------------------------------------------------------------*/
4768 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4769 /* the flow blocks. */
4771 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
4772 * point the instruction flow changes.
4774 /*-----------------------------------------------------------------*/
4775 void pic16_BuildFlow(pBlock *pb)
4778 pCode *last_pci=NULL;
4785 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
4786 /* Insert a pCodeFlow object at the beginning of a pBlock */
4788 InsertpFlow(pb->pcHead, &pflow);
4790 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
4791 //pflow->next = pb->pcHead; /* Make the current head the next object */
4792 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
4793 //pb->pcHead = pflow; /* Make the Flow object the head */
4796 for( pc = pic16_findNextInstruction(pb->pcHead);
4798 pc=pic16_findNextInstruction(pc)) {
4801 PCI(pc)->pcflow = PCFL(pflow);
4803 //fprintf(stderr," build: ");
4804 //pflow->print(stderr,pflow);
4806 if( PCI(pc)->isSkip) {
4808 /* The two instructions immediately following this one
4809 * mark the beginning of a new flow segment */
4811 while(pc && PCI(pc)->isSkip) {
4813 PCI(pc)->pcflow = PCFL(pflow);
4817 InsertpFlow(pc, &pflow);
4818 pc=pic16_findNextInstruction(pc->next);
4826 PCI(pc)->pcflow = PCFL(pflow);
4828 InsertpFlow(pc, &pflow);
4830 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
4832 InsertpFlow(pc, &pflow);
4835 } else if (checkLabel(pc)) {
4837 /* This instruction marks the beginning of a
4838 * new flow segment */
4843 /* If the previous pCode is not a flow object, then
4844 * insert a new flow object. (This check prevents
4845 * two consecutive flow objects from being insert in
4846 * the case where a skip instruction preceeds an
4847 * instruction containing a label.) */
4849 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4850 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
4852 PCI(pc)->pcflow = PCFL(pflow);
4859 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4861 PCFL(pflow)->end = pb->pcTail;
4864 /*-------------------------------------------------------------------*/
4865 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4866 /* the flow blocks. */
4868 * unBuildFlow removes pCodeFlow objects from a pCode chain
4870 /*-----------------------------------------------------------------*/
4871 static void unBuildFlow(pBlock *pb)
4886 if(PCI(pc)->pcflow) {
4887 //free(PCI(pc)->pcflow);
4888 PCI(pc)->pcflow = NULL;
4891 } else if(isPCFL(pc) )
4900 /*-----------------------------------------------------------------*/
4901 /*-----------------------------------------------------------------*/
4902 static void dumpCond(int cond)
4905 static char *pcc_str[] = {
4920 int ncond = sizeof(pcc_str) / sizeof(char *);
4923 fprintf(stderr, "0x%04X\n",cond);
4925 for(i=0,j=1; i<ncond; i++, j<<=1)
4927 fprintf(stderr, " %s\n",pcc_str[i]);
4933 /*-----------------------------------------------------------------*/
4934 /*-----------------------------------------------------------------*/
4935 static void FlowStats(pCodeFlow *pcflow)
4943 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4945 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
4948 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4953 fprintf(stderr, " FlowStats inCond: ");
4954 dumpCond(pcflow->inCond);
4955 fprintf(stderr, " FlowStats outCond: ");
4956 dumpCond(pcflow->outCond);
4960 /*-----------------------------------------------------------------*
4961 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4962 * if it affects the banking bits.
4964 * return: -1 == Banking bits are unaffected by this pCode.
4966 * return: > 0 == Banking bits are affected.
4968 * If the banking bits are affected, then the returned value describes
4969 * which bits are affected and how they're affected. The lower half
4970 * of the integer maps to the bits that are affected, the upper half
4971 * to whether they're set or cleared.
4973 *-----------------------------------------------------------------*/
4975 static int isBankInstruction(pCode *pc)
4983 if( PCI(pc)->op == POC_MOVLB ||
4984 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
4985 bank = PCOL(pc)->lit;
4992 /*-----------------------------------------------------------------*/
4993 /*-----------------------------------------------------------------*/
4994 static void FillFlow(pCodeFlow *pcflow)
5003 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5005 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5008 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5015 isBankInstruction(pc);
5017 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5021 fprintf(stderr, " FillFlow - Bad end of flow\n");
5023 fprintf(stderr, " FillFlow - Ending flow with\n ");
5024 pc->print(stderr,pc);
5027 fprintf(stderr, " FillFlow inCond: ");
5028 dumpCond(pcflow->inCond);
5029 fprintf(stderr, " FillFlow outCond: ");
5030 dumpCond(pcflow->outCond);
5034 /*-----------------------------------------------------------------*/
5035 /*-----------------------------------------------------------------*/
5036 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5038 pCodeFlowLink *fromLink, *toLink;
5040 if(!from || !to || !to->pcflow || !from->pcflow)
5043 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5044 toLink = pic16_newpCodeFlowLink(to->pcflow);
5046 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5047 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5051 /*-----------------------------------------------------------------*
5052 * void LinkFlow(pBlock *pb)
5054 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5055 * non-branching segments. In LinkFlow, we determine the execution
5056 * order of these segments. For example, if one of the segments ends
5057 * with a skip, then we know that there are two possible flow segments
5058 * to which control may be passed.
5059 *-----------------------------------------------------------------*/
5060 static void LinkFlow(pBlock *pb)
5066 //fprintf(stderr,"linkflow \n");
5068 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5070 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5073 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5075 //fprintf(stderr," link: ");
5076 //pcflow->print(stderr,pcflow);
5078 //FillFlow(PCFL(pcflow));
5080 pc = PCFL(pcflow)->end;
5082 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5083 if(isPCI_SKIP(pc)) {
5084 //fprintf(stderr, "ends with skip\n");
5085 //pc->print(stderr,pc);
5086 pct=pic16_findNextInstruction(pc->next);
5087 LinkFlow_pCode(PCI(pc),PCI(pct));
5088 pct=pic16_findNextInstruction(pct->next);
5089 LinkFlow_pCode(PCI(pc),PCI(pct));
5093 if(isPCI_BRANCH(pc)) {
5094 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5096 //fprintf(stderr, "ends with branch\n ");
5097 //pc->print(stderr,pc);
5099 if(!(pcol && isPCOLAB(pcol))) {
5100 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5101 pc->print(stderr,pc);
5102 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5107 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5108 LinkFlow_pCode(PCI(pc),PCI(pct));
5110 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5111 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5112 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5118 //fprintf(stderr, "ends with non-branching instruction:\n");
5119 //pc->print(stderr,pc);
5121 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5127 //fprintf(stderr, "ends with unknown\n");
5128 //pc->print(stderr,pc);
5132 //fprintf(stderr, "ends with nothing: ERROR\n");
5136 /*-----------------------------------------------------------------*/
5137 /*-----------------------------------------------------------------*/
5139 /*-----------------------------------------------------------------*/
5140 /*-----------------------------------------------------------------*/
5141 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5147 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5150 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5156 /*-----------------------------------------------------------------*/
5157 /* BanksUsedFlow - Identify which banks are used in flow 2. */
5158 /*-----------------------------------------------------------------*/
5159 static void BanksUsedFlow2(pCode *pcflow)
5168 if(!isPCFL(pcflow)) {
5169 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
5173 pc = pic16_findNextInstruction(pcflow->next);
5175 PCFL(pcflow)->lastBank = -1;
5177 while(pic16_isPCinFlow(pc,pcflow)) {
5179 int bank_selected = isBankInstruction(pc);
5181 //if(PCI(pc)->pcflow)
5182 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
5184 if(bank_selected >= 0) {
5185 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
5187 /* This instruction is modifying banking bits before accessing registers */
5189 PCFL(pcflow)->firstBank = -1;
5191 if(PCFL(pcflow)->lastBank == -1)
5192 PCFL(pcflow)->lastBank = 0;
5194 bank = 1 << bank_selected;
5195 PCFL(pcflow)->lastBank |= bank;
5199 reg = pic16_getRegFromInstruction(pc);
5201 if(reg && !pic16_isREGinBank(reg, bank)) {
5202 int allbanks = pic16_REGallBanks(reg);
5204 PCFL(pcflow)->firstBank = allbanks;
5206 PCFL(pcflow)->lastBank = allbanks;
5213 pc = pic16_findNextInstruction(pc->next);
5216 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
5217 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
5222 /*-----------------------------------------------------------------*/
5223 /*-----------------------------------------------------------------*/
5224 static void BanksUsedFlow(pBlock *pb)
5229 //pb->pcHead->print(stderr, pb->pcHead);
5231 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5232 //pcflow->print(stderr,pcflow);
5234 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5236 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5238 BanksUsedFlow2(pcflow);
5244 /*-----------------------------------------------------------------*/
5245 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5246 /*-----------------------------------------------------------------*/
5247 static void insertBankSwitch(int position, pCode *pc, int bsr)
5257 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5258 * insert a BANKSEL assembler directive for the symbol used by
5259 * the pCode. This will allow the linker to setup the correct
5260 * bank at linking time
5263 if(!options_gen_banksel || bsr != -1) {
5264 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5266 /* emit the BANKSEL [symbol] */
5268 /* IMPORTANT: The following code does not check if a symbol is
5269 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5271 reg = pic16_getRegFromInstruction(pc);
5273 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", reg->name);
5275 position = 0; // position is always before (sanity check!)
5279 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5280 pc->print(stderr, pc);
5284 /* insert the bank switch after this pc instruction */
5285 pCode *pcnext = pic16_findNextInstruction(pc);
5286 pic16_pCodeInsertAfter(pc, new_pc);
5291 pic16_pCodeInsertAfter(pc->prev, new_pc);
5293 /* Move the label, if there is one */
5295 if(PCI(pc)->label) {
5296 PCI(new_pc)->label = PCI(pc)->label;
5297 PCI(pc)->label = NULL;
5300 /* The new instruction has the same pcflow block */
5301 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
5304 /*-----------------------------------------------------------------*/
5305 /*-----------------------------------------------------------------*/
5306 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
5317 pc = pic16_findNextInstruction(pcfl->pc.next);
5319 while(pic16_isPCinFlow(pc,PCODE(pcfl))) {
5321 reg = pic16_getRegFromInstruction(pc);
5325 fprintf(stderr, "%s:%d %s ",__FUNCTION__, __LINE__, reg->name);
5326 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
5331 if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) ||
5332 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
5335 /* Examine the instruction before this one to make sure it is
5336 * not a skip type instruction */
5337 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5339 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev) /* && !isBankInstruction(pcprev)*/)) {
5342 reg_bank = (reg) ? REG_BANK(reg) : 0;
5345 if (cur_bank != reg_bank) {
5346 //fprintf(stderr, "Cool! can switch banks\n");
5347 cur_bank = reg_bank;
5348 insertBankSwitch(0, pc, cur_bank);
5352 //fprintf(stderr, "Bummer can't switch banks\n");
5358 pc = pic16_findNextInstruction(pc->next);
5362 if(pcprev && cur_bank) {
5363 /* Brute force - make sure that we point to bank 0 at the
5364 * end of each flow block */
5365 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
5366 pic16_pCodeInsertAfter(pcprev, new_pc);
5368 //fprintf(stderr, "Brute force switch\n");
5373 /*-----------------------------------------------------------------*/
5374 /*int compareBankFlow - compare the banking requirements between */
5376 /*-----------------------------------------------------------------*/
5377 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5380 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5383 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5386 if(pcflow->firstBank == -1)
5390 if(pcflowLink->pcflow->firstBank == -1) {
5391 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5392 pcflowLink->pcflow->to :
5393 pcflowLink->pcflow->from);
5394 return compareBankFlow(pcflow, pctl, toORfrom);
5398 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5401 pcflowLink->bank_conflict++;
5402 pcflowLink->pcflow->FromConflicts++;
5403 pcflow->ToConflicts++;
5406 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5409 pcflowLink->bank_conflict++;
5410 pcflowLink->pcflow->ToConflicts++;
5411 pcflow->FromConflicts++;
5415 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5416 pcflowLink->pcflow->pc.seq,
5417 pcflowLink->pcflow->FromConflicts,
5418 pcflowLink->pcflow->ToConflicts);
5423 /*-----------------------------------------------------------------*/
5424 /*-----------------------------------------------------------------*/
5425 static void FixBankFlow(pBlock *pb)
5429 pCodeFlowLink *pcfl;
5431 pCode *pcflow_max_To=NULL;
5432 pCode *pcflow_max_From=NULL;
5433 int max_ToConflicts=0;
5434 int max_FromConflicts=0;
5436 //fprintf(stderr,"Fix Bank flow \n");
5437 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5441 First loop through all of the flow objects in this pcode block
5442 and fix the ones that have banking conflicts between the
5446 // fprintf(stderr, "FixBankFlow - Phase 1\n");
5448 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5450 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5452 if(!isPCFL(pcflow)) {
5453 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5457 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
5458 PCFL(pcflow)->firstBank >= 0 &&
5459 PCFL(pcflow)->lastBank >= 0 ) {
5461 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
5462 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
5464 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
5465 BanksUsedFlow2(pcflow);
5470 // fprintf(stderr, "FixBankFlow - Phase 2\n");
5472 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5474 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5479 if(!isPCFL(pcflow)) {
5480 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5484 PCFL(pcflow)->FromConflicts = 0;
5485 PCFL(pcflow)->ToConflicts = 0;
5490 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
5491 pcfl = setFirstItem(PCFL(pcflow)->from);
5494 pc = PCODE(pcfl->pcflow);
5497 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5498 pc->print(stderr,pc);
5501 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
5504 pcfl=setNextItem(PCFL(pcflow)->from);
5507 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
5508 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5510 FixRegisterBankingInFlow(PCFL(pcflow),0);
5511 BanksUsedFlow2(pcflow);
5513 continue; /* Don't need to check the flow from here - it's already been fixed */
5520 pcfl = setFirstItem(PCFL(pcflow)->to);
5523 pc = PCODE(pcfl->pcflow);
5525 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5526 pc->print(stderr,pc);
5529 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
5532 pcfl=setNextItem(PCFL(pcflow)->to);
5535 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
5536 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5538 FixRegisterBankingInFlow(PCFL(pcflow),0);
5539 BanksUsedFlow2(pcflow);
5544 Loop through the flow objects again and find the ones with the
5548 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5550 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5552 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
5553 pcflow_max_To = pcflow;
5555 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
5556 pcflow_max_From = pcflow;
5560 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
5561 PCFL(pcflow_max_To)->pc.seq,
5562 PCFL(pcflow_max_To)->ToConflicts);
5565 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
5566 PCFL(pcflow_max_From)->pc.seq,
5567 PCFL(pcflow_max_From)->FromConflicts);
5571 /*-----------------------------------------------------------------*/
5572 /*-----------------------------------------------------------------*/
5573 static void DumpFlow(pBlock *pb)
5577 pCodeFlowLink *pcfl;
5580 fprintf(stderr,"Dump flow \n");
5581 pb->pcHead->print(stderr, pb->pcHead);
5583 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5584 pcflow->print(stderr,pcflow);
5586 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5588 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5590 if(!isPCFL(pcflow)) {
5591 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5594 fprintf(stderr,"dumping: ");
5595 pcflow->print(stderr,pcflow);
5596 FlowStats(PCFL(pcflow));
5598 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5600 pc = PCODE(pcfl->pcflow);
5602 fprintf(stderr, " from seq %d:\n",pc->seq);
5604 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5605 pc->print(stderr,pc);
5610 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5612 pc = PCODE(pcfl->pcflow);
5614 fprintf(stderr, " to seq %d:\n",pc->seq);
5616 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5617 pc->print(stderr,pc);
5626 /*-----------------------------------------------------------------*/
5627 /*-----------------------------------------------------------------*/
5628 static int OptimizepBlock(pBlock *pb)
5633 if(!pb || !peepOptimizing)
5636 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5638 for(pc = pb->pcHead; pc; pc = pc->next)
5639 matches += pic16_pCodePeepMatchRule(pc);
5642 pc = pic16_findNextInstruction(pb->pcHead);
5650 if(pic16_pCodePeepMatchRule(pc)) {
5655 pc = pic16_findNextInstruction(pcprev->next);
5657 pc = pic16_findNextInstruction(pb->pcHead);
5659 pc = pic16_findNextInstruction(pc->next);
5663 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5668 /*-----------------------------------------------------------------*/
5669 /*-----------------------------------------------------------------*/
5670 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5674 for(pc = pcs; pc; pc = pc->next) {
5676 if((pc->type == PC_OPCODE) &&
5678 (PCI(pc)->pcop->type == PO_LABEL) &&
5679 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5687 /*-----------------------------------------------------------------*/
5688 /*-----------------------------------------------------------------*/
5689 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5696 (PCI(pc)->pcop->type == PO_LABEL)) {
5698 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5700 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5702 free(pcol->pcop.name);
5704 /* If the key is negative, then we (probably) have a label to
5705 * a function and the name is already defined */
5708 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5712 //sprintf(buffer,"_%05d_DS_",pcl->key);
5714 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5716 pcol->pcop.name = Safe_strdup(s);
5717 pcol->key = pcl->key;
5718 //pc->print(stderr,pc);
5725 /*-----------------------------------------------------------------*/
5726 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5727 /* pCode chain if they're not used. */
5728 /*-----------------------------------------------------------------*/
5729 static void pBlockRemoveUnusedLabels(pBlock *pb)
5731 pCode *pc; pCodeLabel *pcl;
5736 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5738 pBranch *pbr = PCI(pc)->label;
5739 if(pbr && pbr->next) {
5740 pCode *pcd = pb->pcHead;
5742 //fprintf(stderr, "multiple labels\n");
5743 //pc->print(stderr,pc);
5748 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5749 //fprintf(stderr,"Used by:\n");
5750 //pcd->print(stderr,pcd);
5752 exchangeLabels(PCL(pbr->pc),pcd);
5761 for(pc = pb->pcHead; pc; pc = pc->next) {
5763 if(isPCL(pc)) // pc->type == PC_LABEL)
5765 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5766 pcl = PCL(PCI(pc)->label->pc);
5769 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5771 /* This pCode is a label, so search the pBlock to see if anyone
5774 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5775 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5776 /* Couldn't find an instruction that refers to this label
5777 * So, unlink the pCode label from it's pCode chain
5778 * and destroy the label */
5779 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5781 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5782 if(pc->type == PC_LABEL) {
5783 pic16_unlinkpCode(pc);
5784 pCodeLabelDestruct(pc);
5786 unlinkpCodeFromBranch(pc, PCODE(pcl));
5787 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5798 /*-----------------------------------------------------------------*/
5799 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
5800 /* chain and put them into pBranches that are */
5801 /* associated with the appropriate pCode */
5803 /*-----------------------------------------------------------------*/
5804 void pic16_pBlockMergeLabels(pBlock *pb)
5807 pCode *pc, *pcnext=NULL;
5812 /* First, Try to remove any unused labels */
5813 //pBlockRemoveUnusedLabels(pb);
5815 /* Now loop through the pBlock and merge the labels with the opcodes */
5818 // for(pc = pb->pcHead; pc; pc = pc->next) {
5821 pCode *pcn = pc->next;
5823 if(pc->type == PC_LABEL) {
5825 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5826 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5827 if((pcnext = pic16_findNextInstruction(pc) )) {
5829 // Unlink the pCode label from it's pCode chain
5830 pic16_unlinkpCode(pc);
5832 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5833 // And link it into the instruction's pBranch labels. (Note, since
5834 // it's possible to have multiple labels associated with one instruction
5835 // we must provide a means to accomodate the additional labels. Thus
5836 // the labels are placed into the singly-linked list "label" as
5837 // opposed to being a single member of the pCodeInstruction.)
5839 //_ALLOC(pbr,sizeof(pBranch));
5840 pbr = Safe_calloc(1,sizeof(pBranch));
5844 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5847 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5849 } else if(pc->type == PC_CSOURCE) {
5851 /* merge the source line symbolic info into the next instruction */
5852 if((pcnext = pic16_findNextInstruction(pc) )) {
5854 // Unlink the pCode label from it's pCode chain
5855 pic16_unlinkpCode(pc);
5856 PCI(pcnext)->cline = PCCS(pc);
5857 //fprintf(stderr, "merging CSRC\n");
5858 //genericPrint(stderr,pcnext);
5864 pBlockRemoveUnusedLabels(pb);
5868 /*-----------------------------------------------------------------*/
5869 /*-----------------------------------------------------------------*/
5870 static int OptimizepCode(char dbName)
5872 #define MAX_PASSES 4
5881 DFPRINTF((stderr," Optimizing pCode\n"));
5885 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5886 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5887 matches += OptimizepBlock(pb);
5890 while(matches && ++passes < MAX_PASSES);
5895 /*-----------------------------------------------------------------*/
5896 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5897 /*-----------------------------------------------------------------*/
5899 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5903 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5905 if( !( (pcop->type == PO_LABEL) ||
5906 (pcop->type == PO_LITERAL) ||
5907 (pcop->type == PO_STR) ))
5908 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5916 /*-----------------------------------------------------------------*/
5917 /*-----------------------------------------------------------------*/
5918 int InstructionRegBank(pCode *pc)
5922 if( (reg = pic16_getRegFromInstruction(pc)) == NULL)
5925 return REG_BANK(reg);
5930 /*-----------------------------------------------------------------*/
5931 /*-----------------------------------------------------------------*/
5932 static void pic16_FixRegisterBanking(pBlock *pb)
5943 //pc = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5944 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5947 /* loop through all of the flow blocks with in one pblock */
5949 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
5953 /* at this point, pc should point to a PC_FLOW object */
5956 /* for each flow block, determine the register banking
5960 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
5961 // genericPrint(stderr, pc);
5963 reg = pic16_getRegFromInstruction(pc);
5966 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
5967 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
5968 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
5969 pic16_finalMapping[ reg->rIdx ].isSFR, reg->isFixed);
5974 /* the !(reg->rIdx==-1) is a temporary hack. It should be changed - VR 6-Jun-2003 */
5975 if( ( (reg && !(reg->rIdx==-1) && !isACCESS_BANK(reg) /*&& REG_BANK(reg)!=cur_bank*/ && !isBankInstruction(pc)) ||
5976 ((PCI(pc)->op != POC_CALL) /*&& (cur_bank != 0)*/ ) ) &&
5977 (!isPCI_LIT(pc)) ) {
5980 /* Examine the instruction before this one to make sure it is
5981 * not a skip type instruction */
5982 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5984 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev) /*&& !isBankInstruction(pcprev)*/)) {
5987 reg_bank = (reg) ? REG_BANK(reg) : 0;
5989 // fprintf(stderr, "%s:%d add bank = %d\n", __FUNCTION__, __LINE__, reg_bank);
5990 // pc->print(stderr, pc);
5992 // if (cur_bank != reg_bank) {
5993 cur_bank = reg_bank;
5994 insertBankSwitch(0, pc, (options_gen_banksel)?-1:cur_bank); //cur_bank);
5998 //fprintf(stderr, "Bummer can't switch banks\n");
6008 // } while(pc && !(isPCFL(pc)));
6013 if(pcprev && cur_bank) {
6015 int pos = 1; /* Assume that the bank switch instruction(s)
6016 * are inserted after this instruction */
6018 if((PCI(pcprev)->op == POC_RETLW) ||
6019 (PCI(pcprev)->op == POC_RETURN) ||
6020 (PCI(pcprev)->op == POC_RETFIE)) {
6022 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6028 /* Brute force - make sure that we point to bank 0 at the
6029 * end of each flow block */
6031 insertBankSwitch(pos, pcprev, 0);
6033 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6034 pic16_pCodeInsertAfter(pcprev, new_pc);
6037 //fprintf(stderr, "Brute force switch\n");
6046 if(reg && REG_BANK(reg)!=cur_bank) {
6047 //fprintf(stderr,"need to switch banks\n");
6048 /* Examine the instruction before this one to make sure it is
6049 * not a skip type instruction */
6050 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6051 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
6052 int b = cur_bank ^ REG_BANK(reg);
6054 cur_bank = REG_BANK(reg);
6060 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
6063 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
6064 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
6068 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
6069 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
6071 insertBankSwitch(0, pc, -1, -1);
6080 static void pBlockDestruct(pBlock *pb)
6091 /*-----------------------------------------------------------------*/
6092 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6093 /* name dbName and combine them */
6094 /* into one block */
6095 /*-----------------------------------------------------------------*/
6096 static void mergepBlocks(char dbName)
6099 pBlock *pb, *pbmerged = NULL,*pbn;
6101 pb = the_pFile->pbHead;
6103 //fprintf(stderr," merging blocks named %c\n",dbName);
6107 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6108 if( getpBlock_dbName(pb) == dbName) {
6110 //fprintf(stderr," merged block %c\n",dbName);
6115 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6116 /* pic16_addpCode2pBlock doesn't handle the tail: */
6117 pbmerged->pcTail = pb->pcTail;
6119 pb->prev->next = pbn;
6121 pbn->prev = pb->prev;
6126 //pic16_printpBlock(stderr, pbmerged);
6133 /*-----------------------------------------------------------------*/
6134 /* AnalyzeFlow - Examine the flow of the code and optimize */
6136 /* level 0 == minimal optimization */
6137 /* optimize registers that are used only by two instructions */
6138 /* level 1 == maximal optimization */
6139 /* optimize by looking at pairs of instructions that use the */
6141 /*-----------------------------------------------------------------*/
6143 static void AnalyzeFlow(int level)
6145 static int times_called=0;
6153 /* if this is not the first time this function has been called,
6154 then clean up old flow information */
6155 if(times_called++) {
6156 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6159 pic16_RegsUnMapLiveRanges();
6165 /* Phase 2 - Flow Analysis - Register Banking
6167 * In this phase, the individual flow blocks are examined
6168 * and register banking is fixed.
6172 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6173 pic16_FixRegisterBanking(pb);
6176 /* Phase 2 - Flow Analysis
6178 * In this phase, the pCode is partition into pCodeFlow
6179 * blocks. The flow blocks mark the points where a continuous
6180 * stream of instructions changes flow (e.g. because of
6181 * a call or goto or whatever).
6184 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6185 pic16_BuildFlow(pb);
6188 /* Phase 2 - Flow Analysis - linking flow blocks
6190 * In this phase, the individual flow blocks are examined
6191 * to determine their order of excution.
6194 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6197 /* Phase 3 - Flow Analysis - Flow Tree
6199 * In this phase, the individual flow blocks are examined
6200 * to determine their order of excution.
6203 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6204 pic16_BuildFlowTree(pb);
6207 /* Phase x - Flow Analysis - Used Banks
6209 * In this phase, the individual flow blocks are examined
6210 * to determine the Register Banks they use
6213 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6217 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6218 pic16_pCodeRegMapLiveRanges(pb);
6220 pic16_RemoveUnusedRegisters();
6222 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6223 pic16_pCodeRegOptimizeRegUsage(level);
6229 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6233 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6235 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6236 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6237 pcflow = pcflow->next) {
6239 FillFlow(PCFL(pcflow));
6244 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6246 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6247 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6248 pcflow = pcflow->next) {
6250 FlowStats(PCFL(pcflow));
6256 /*-----------------------------------------------------------------*/
6257 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6258 /* assigned to the registers. */
6260 /*-----------------------------------------------------------------*/
6262 void pic16_AnalyzeBanking(void)
6266 if(!pic16_picIsInitialized()) {
6267 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6268 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6269 fprintf(stderr,"support/scripts/inc2h.pl\n");
6270 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6275 /* Phase x - Flow Analysis - Used Banks
6277 * In this phase, the individual flow blocks are examined
6278 * to determine the Register Banks they use
6284 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6287 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6288 pic16_FixRegisterBanking(pb);
6292 /*-----------------------------------------------------------------*/
6293 /* buildCallTree - Look at the flow and extract all of the calls. */
6294 /*-----------------------------------------------------------------*/
6295 static set *register_usage(pBlock *pb);
6297 static void buildCallTree(void )
6308 /* Now build the call tree.
6309 First we examine all of the pCodes for functions.
6310 Keep in mind that the function boundaries coincide
6311 with pBlock boundaries.
6313 The algorithm goes something like this:
6314 We have two nested loops. The outer loop iterates
6315 through all of the pBlocks/functions. The inner
6316 loop iterates through all of the pCodes for
6317 a given pBlock. When we begin iterating through
6318 a pBlock, the variable pc_fstart, pCode of the start
6319 of a function, is cleared. We then search for pCodes
6320 of type PC_FUNCTION. When one is encountered, we
6321 initialize pc_fstart to this and at the same time
6322 associate a new pBranch object that signifies a
6323 branch entry. If a return is found, then this signifies
6324 a function exit point. We'll link the pCodes of these
6325 returns to the matching pc_fstart.
6327 When we're done, a doubly linked list of pBranches
6328 will exist. The head of this list is stored in
6329 `the_pFile', which is the meta structure for all
6330 of the pCode. Look at the pic16_printCallTree function
6331 on how the pBranches are linked together.
6334 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6335 pCode *pc_fstart=NULL;
6336 for(pc = pb->pcHead; pc; pc = pc->next) {
6338 if (PCF(pc)->fname) {
6340 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6341 //fprintf(stderr," found main \n");
6342 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6346 pbr = Safe_calloc(1,sizeof(pBranch));
6347 pbr->pc = pc_fstart = pc;
6350 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6352 // Here's a better way of doing the same:
6353 addSet(&pb->function_entries, pc);
6356 // Found an exit point in a function, e.g. return
6357 // (Note, there may be more than one return per function)
6359 pBranchLink(PCF(pc_fstart), PCF(pc));
6361 addSet(&pb->function_exits, pc);
6363 } else if(isCALL(pc)) {
6364 addSet(&pb->function_calls,pc);
6369 /* Re-allocate the registers so that there are no collisions
6370 * between local variables when one function call another */
6373 // pic16_deallocateAllRegs();
6375 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6382 /*-----------------------------------------------------------------*/
6383 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6384 /* all of the logical connections. */
6386 /* Essentially what's done here is that the pCode flow is */
6388 /*-----------------------------------------------------------------*/
6390 void pic16_AnalyzepCode(char dbName)
6401 /* Phase 1 - Register allocation and peep hole optimization
6403 * The first part of the analysis is to determine the registers
6404 * that are used in the pCode. Once that is done, the peep rules
6405 * are applied to the code. We continue to loop until no more
6406 * peep rule optimizations are found (or until we exceed the
6407 * MAX_PASSES threshold).
6409 * When done, the required registers will be determined.
6415 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6416 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6418 /* First, merge the labels with the instructions */
6419 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6420 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6422 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6423 //fprintf(stderr," analyze and merging block %c\n",dbName);
6424 pic16_pBlockMergeLabels(pb);
6427 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6431 changes = OptimizepCode(dbName);
6433 } while(changes && (i++ < MAX_PASSES));
6438 /*-----------------------------------------------------------------*/
6439 /* ispCodeFunction - returns true if *pc is the pCode of a */
6441 /*-----------------------------------------------------------------*/
6442 static bool ispCodeFunction(pCode *pc)
6445 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6451 /*-----------------------------------------------------------------*/
6452 /* findFunction - Search for a function by name (given the name) */
6453 /* in the set of all functions that are in a pBlock */
6454 /* (note - I expect this to change because I'm planning to limit */
6455 /* pBlock's to just one function declaration */
6456 /*-----------------------------------------------------------------*/
6457 static pCode *findFunction(char *fname)
6464 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6466 pc = setFirstItem(pb->function_entries);
6469 if((pc->type == PC_FUNCTION) &&
6471 (strcmp(fname, PCF(pc)->fname)==0))
6474 pc = setNextItem(pb->function_entries);
6482 static void MarkUsedRegisters(set *regset)
6487 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6488 // fprintf(stderr, "marking register = %s\t", r1->name);
6489 r2 = pic16_regWithIdx(r1->rIdx);
6490 // fprintf(stderr, "to register = %s\n", r2->name);
6496 static void pBlockStats(FILE *of, pBlock *pb)
6502 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6504 // for now just print the first element of each set
6505 pc = setFirstItem(pb->function_entries);
6507 fprintf(of,";entry: ");
6510 pc = setFirstItem(pb->function_exits);
6512 fprintf(of,";has an exit\n");
6516 pc = setFirstItem(pb->function_calls);
6518 fprintf(of,";functions called:\n");
6521 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6522 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6524 pc = setNextItem(pb->function_calls);
6528 r = setFirstItem(pb->tregisters);
6530 int n = elementsInSet(pb->tregisters);
6532 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6535 fprintf(of,"; %s\n",r->name);
6536 r = setNextItem(pb->tregisters);
6541 /*-----------------------------------------------------------------*/
6542 /*-----------------------------------------------------------------*/
6544 static void sequencepCode(void)
6550 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6552 pb->seq = GpCodeSequenceNumber+1;
6554 for( pc = pb->pcHead; pc; pc = pc->next)
6555 pc->seq = ++GpCodeSequenceNumber;
6561 /*-----------------------------------------------------------------*/
6562 /*-----------------------------------------------------------------*/
6563 static set *register_usage(pBlock *pb)
6566 set *registers=NULL;
6567 set *registersInCallPath = NULL;
6569 /* check recursion */
6571 pc = setFirstItem(pb->function_entries);
6578 if(pc->type != PC_FUNCTION)
6579 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6581 pc = setFirstItem(pb->function_calls);
6582 for( ; pc; pc = setNextItem(pb->function_calls)) {
6584 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6585 char *dest = pic16_get_op_from_instruction(PCI(pc));
6587 pcn = findFunction(dest);
6589 registersInCallPath = register_usage(pcn->pb);
6591 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6596 pBlockStats(stderr,pb); // debug
6599 // Mark the registers in this block as used.
6601 MarkUsedRegisters(pb->tregisters);
6602 if(registersInCallPath) {
6603 /* registers were used in the functions this pBlock has called */
6604 /* so now, we need to see if these collide with the ones we are */
6607 regs *r1,*r2, *newreg;
6609 DFPRINTF((stderr,"comparing registers\n"));
6611 r1 = setFirstItem(registersInCallPath);
6614 r2 = setFirstItem(pb->tregisters);
6616 while(r2 && (r1->type != REG_STK)) {
6618 if(r2->rIdx == r1->rIdx) {
6619 newreg = pic16_findFreeReg(REG_GPR);
6623 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6627 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6628 r1->rIdx, newreg->rIdx));
6629 r2->rIdx = newreg->rIdx;
6630 //if(r2->name) free(r2->name);
6632 r2->name = Safe_strdup(newreg->name);
6636 newreg->wasUsed = 1;
6638 r2 = setNextItem(pb->tregisters);
6641 r1 = setNextItem(registersInCallPath);
6644 /* Collisions have been resolved. Now free the registers in the call path */
6645 r1 = setFirstItem(registersInCallPath);
6647 if(r1->type != REG_STK) {
6648 newreg = pic16_regWithIdx(r1->rIdx);
6651 r1 = setNextItem(registersInCallPath);
6655 // MarkUsedRegisters(pb->registers);
6657 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6660 DFPRINTF((stderr,"returning regs\n"));
6662 DFPRINTF((stderr,"not returning regs\n"));
6664 DFPRINTF((stderr,"pBlock after register optim.\n"));
6665 pBlockStats(stderr,pb); // debug
6671 /*-----------------------------------------------------------------*/
6672 /* pct2 - writes the call tree to a file */
6674 /*-----------------------------------------------------------------*/
6675 static void pct2(FILE *of,pBlock *pb,int indent)
6679 // set *registersInCallPath = NULL;
6685 return; //recursion ?
6687 pc = setFirstItem(pb->function_entries);
6694 for(i=0;i<indent;i++) // Indentation
6697 if(pc->type == PC_FUNCTION)
6698 fprintf(of,"%s\n",PCF(pc)->fname);
6703 pc = setFirstItem(pb->function_calls);
6704 for( ; pc; pc = setNextItem(pb->function_calls)) {
6706 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6707 char *dest = pic16_get_op_from_instruction(PCI(pc));
6709 pcn = findFunction(dest);
6711 pct2(of,pcn->pb,indent+1);
6713 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6721 /*-----------------------------------------------------------------*/
6722 /* pic16_printCallTree - writes the call tree to a file */
6724 /*-----------------------------------------------------------------*/
6726 void pic16_printCallTree(FILE *of)
6738 fprintf(of, "\npBlock statistics\n");
6739 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6744 fprintf(of,"Call Tree\n");
6745 pbr = the_pFile->functions;
6749 if(!ispCodeFunction(pc))
6750 fprintf(of,"bug in call tree");
6753 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6755 while(pc->next && !ispCodeFunction(pc->next)) {
6757 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6758 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6766 fprintf(of,"\n**************\n\na better call tree\n");
6767 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6772 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6773 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6779 /*-----------------------------------------------------------------*/
6781 /*-----------------------------------------------------------------*/
6783 static void InlineFunction(pBlock *pb)
6791 pc = setFirstItem(pb->function_calls);
6793 for( ; pc; pc = setNextItem(pb->function_calls)) {
6796 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6802 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
6804 //fprintf(stderr,"Cool can inline:\n");
6805 //pcn->print(stderr,pcn);
6807 //fprintf(stderr,"recursive call Inline\n");
6808 InlineFunction(pcn->pb);
6809 //fprintf(stderr,"return from recursive call Inline\n");
6812 At this point, *pc points to a CALL mnemonic, and
6813 *pcn points to the function that is being called.
6815 To in-line this call, we need to remove the CALL
6816 and RETURN(s), and link the function pCode in with
6822 /* Remove the CALL */
6826 /* remove callee pBlock from the pBlock linked list */
6827 removepBlock(pcn->pb);
6835 /* Remove the Function pCode */
6836 pct = pic16_findNextInstruction(pcn->next);
6838 /* Link the function with the callee */
6839 pc->next = pcn->next;
6840 pcn->next->prev = pc;
6842 /* Convert the function name into a label */
6844 pbr = Safe_calloc(1,sizeof(pBranch));
6845 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6847 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6848 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6850 /* turn all of the return's except the last into goto's */
6851 /* check case for 2 instruction pBlocks */
6852 pce = pic16_findNextInstruction(pcn->next);
6854 pCode *pce_next = pic16_findNextInstruction(pce->next);
6856 if(pce_next == NULL) {
6857 /* found the last return */
6858 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6860 //fprintf(stderr,"found last return\n");
6861 //pce->print(stderr,pce);
6862 pce->prev->next = pc_call->next;
6863 pc_call->next->prev = pce->prev;
6864 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6874 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6880 /*-----------------------------------------------------------------*/
6882 /*-----------------------------------------------------------------*/
6884 void pic16_InlinepCode(void)
6893 if(!functionInlining)
6896 /* Loop through all of the function definitions and count the
6897 * number of times each one is called */
6898 //fprintf(stderr,"inlining %d\n",__LINE__);
6900 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6902 pc = setFirstItem(pb->function_calls);
6904 for( ; pc; pc = setNextItem(pb->function_calls)) {
6907 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6908 if(pcn && isPCF(pcn)) {
6909 PCF(pcn)->ncalled++;
6912 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6917 //fprintf(stderr,"inlining %d\n",__LINE__);
6919 /* Now, Loop through the function definitions again, but this
6920 * time inline those functions that have only been called once. */
6922 InlineFunction(the_pFile->pbHead);
6923 //fprintf(stderr,"inlining %d\n",__LINE__);
6925 for(pb = the_pFile->pbHead; pb; pb = pb->next)