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 static pFile *the_pFile = NULL;
74 static pBlock *pb_dead_pcodes = NULL;
76 /* Hardcoded flags to change the behavior of the PIC port */
77 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
78 static int functionInlining = 1; /* inline functions if nonzero */
79 int pic16_debug_verbose = 1; /* Set true to inundate .asm file */
81 //static int GpCodeSequenceNumber = 1;
82 static int GpcFlowSeq = 1;
84 extern void pic16_RemoveUnusedRegisters(void);
85 extern void pic16_RegsUnMapLiveRanges(void);
86 extern void pic16_BuildFlowTree(pBlock *pb);
87 extern void pic16_pCodeRegOptimizeRegUsage(int level);
88 extern int pic16_picIsInitialized(void);
89 #if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
91 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
92 extern int mnem2key(char const *mnem);
93 #endif // OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
95 /****************************************************************/
96 /* Forward declarations */
97 /****************************************************************/
99 void pic16_unlinkpCode(pCode *pc);
101 static void genericAnalyze(pCode *pc);
102 static void AnalyzeGOTO(pCode *pc);
103 static void AnalyzeSKIP(pCode *pc);
104 static void AnalyzeRETURN(pCode *pc);
107 static void genericDestruct(pCode *pc);
108 static void genericPrint(FILE *of,pCode *pc);
110 static void pCodePrintLabel(FILE *of, pCode *pc);
111 static void pCodePrintFunction(FILE *of, pCode *pc);
112 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
113 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
114 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
115 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
116 int pic16_pCodePeepMatchRule(pCode *pc);
117 static void pBlockStats(FILE *of, pBlock *pb);
118 static pBlock *newpBlock(void);
119 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
120 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
121 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
122 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
125 /****************************************************************/
126 /* PIC Instructions */
127 /****************************************************************/
129 pCodeInstruction pic16_pciADDWF = {
130 {PC_OPCODE, NULL, NULL, 0, NULL,
143 1,0, // dest, bit instruction
145 0, // literal operand
147 0, // fast call/return mode select bit
148 0, // second memory operand
150 (PCC_W | PCC_REGISTER), // inCond
151 (PCC_REGISTER | PCC_Z) // outCond
154 pCodeInstruction pic16_pciADDFW = {
155 {PC_OPCODE, NULL, NULL, 0, NULL,
168 0,0, // dest, bit instruction
170 0, // literal operand
172 0, // fast call/return mode select bit
173 0, // second memory operand
175 (PCC_W | PCC_REGISTER), // inCond
176 (PCC_W | PCC_Z) // outCond
179 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
180 {PC_OPCODE, NULL, NULL, 0, NULL,
193 1,0, // dest, bit instruction
195 0, // literal operand
197 0, // fast call/return mode select bit
198 0, // second memory operand
200 (PCC_W | PCC_REGISTER | PCC_C), // inCond
201 (PCC_REGISTER | PCC_Z) // outCond
204 pCodeInstruction pic16_pciADDFWC = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
218 0,0, // dest, bit instruction
220 0, // literal operand
222 0, // fast call/return mode select bit
223 0, // second memory operand
225 (PCC_W | PCC_REGISTER | PCC_C), // inCond
226 (PCC_W | PCC_Z) // outCond
229 pCodeInstruction pic16_pciADDLW = {
230 {PC_OPCODE, NULL, NULL, 0, NULL,
243 0,0, // dest, bit instruction
245 1, // literal operand
247 0, // fast call/return mode select bit
248 0, // second memory operand
250 (PCC_W | PCC_LITERAL), // inCond
251 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
254 pCodeInstruction pic16_pciANDLW = {
255 {PC_OPCODE, NULL, NULL, 0, NULL,
268 0,0, // dest, bit instruction
270 1, // literal operand
272 0, // fast call/return mode select bit
273 0, // second memory operand
275 (PCC_W | PCC_LITERAL), // inCond
276 (PCC_W | PCC_Z | PCC_N) // outCond
279 pCodeInstruction pic16_pciANDWF = {
280 {PC_OPCODE, NULL, NULL, 0, NULL,
293 1,0, // dest, bit instruction
295 0, // literal operand
297 0, // fast call/return mode select bit
298 0, // second memory operand
300 (PCC_W | PCC_REGISTER), // inCond
301 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
304 pCodeInstruction pic16_pciANDFW = {
305 {PC_OPCODE, NULL, NULL, 0, NULL,
318 0,0, // dest, bit instruction
320 0, // literal operand
322 0, // fast call/return mode select bit
323 0, // second memory operand
325 (PCC_W | PCC_REGISTER), // inCond
326 (PCC_W | PCC_Z) // outCond
329 pCodeInstruction pic16_pciBC = { // mdubuc - New
330 {PC_OPCODE, NULL, NULL, 0, NULL,
343 0,0, // dest, bit instruction
345 0, // literal operand
347 0, // fast call/return mode select bit
348 0, // second memory operand
350 (PCC_REL_ADDR | PCC_C), // inCond
354 pCodeInstruction pic16_pciBCF = {
355 {PC_OPCODE, NULL, NULL, 0, NULL,
368 1,1, // dest, bit instruction
370 0, // literal operand
372 0, // fast call/return mode select bit
373 0, // second memory operand
375 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
376 PCC_REGISTER // outCond
379 pCodeInstruction pic16_pciBN = { // mdubuc - New
380 {PC_OPCODE, NULL, NULL, 0, NULL,
393 0,0, // dest, bit instruction
395 0, // literal operand
397 0, // fast call/return mode select bit
398 0, // second memory operand
400 (PCC_REL_ADDR | PCC_N), // inCond
404 pCodeInstruction pic16_pciBNC = { // mdubuc - New
405 {PC_OPCODE, NULL, NULL, 0, NULL,
418 0,0, // dest, bit instruction
420 0, // literal operand
422 0, // fast call/return mode select bit
423 0, // second memory operand
425 (PCC_REL_ADDR | PCC_C), // inCond
429 pCodeInstruction pic16_pciBNN = { // mdubuc - New
430 {PC_OPCODE, NULL, NULL, 0, NULL,
443 0,0, // dest, bit instruction
445 0, // literal operand
447 0, // fast call/return mode select bit
448 0, // second memory operand
450 (PCC_REL_ADDR | PCC_N), // inCond
454 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
455 {PC_OPCODE, NULL, NULL, 0, NULL,
468 0,0, // dest, bit instruction
470 0, // literal operand
472 0, // fast call/return mode select bit
473 0, // second memory operand
475 (PCC_REL_ADDR | PCC_OV), // inCond
479 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
480 {PC_OPCODE, NULL, NULL, 0, NULL,
493 0,0, // dest, bit instruction
495 0, // literal operand
497 0, // fast call/return mode select bit
498 0, // second memory operand
500 (PCC_REL_ADDR | PCC_Z), // inCond
504 pCodeInstruction pic16_pciBOV = { // mdubuc - New
505 {PC_OPCODE, NULL, NULL, 0, NULL,
518 0,0, // dest, bit instruction
520 0, // literal operand
522 0, // fast call/return mode select bit
523 0, // second memory operand
525 (PCC_REL_ADDR | PCC_OV), // inCond
529 pCodeInstruction pic16_pciBRA = { // mdubuc - New
530 {PC_OPCODE, NULL, NULL, 0, NULL,
543 0,0, // dest, bit instruction
545 0, // literal operand
547 0, // fast call/return mode select bit
548 0, // second memory operand
550 PCC_REL_ADDR, // inCond
554 pCodeInstruction pic16_pciBSF = {
555 {PC_OPCODE, NULL, NULL, 0, NULL,
568 1,1, // dest, bit instruction
570 0, // literal operand
572 0, // fast call/return mode select bit
573 0, // second memory operand
575 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
576 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
579 pCodeInstruction pic16_pciBTFSC = {
580 {PC_OPCODE, NULL, NULL, 0, NULL,
593 0,1, // dest, bit instruction
595 0, // literal operand
597 0, // fast call/return mode select bit
598 0, // second memory operand
600 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
601 PCC_EXAMINE_PCOP // outCond
604 pCodeInstruction pic16_pciBTFSS = {
605 {PC_OPCODE, NULL, NULL, 0, NULL,
618 0,1, // dest, bit instruction
620 0, // literal operand
622 0, // fast call/return mode select bit
623 0, // second memory operand
625 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
626 PCC_EXAMINE_PCOP // outCond
629 pCodeInstruction pic16_pciBTG = { // mdubuc - New
630 {PC_OPCODE, NULL, NULL, 0, NULL,
643 0,1, // dest, bit instruction
645 0, // literal operand
647 0, // fast call/return mode select bit
648 0, // second memory operand
650 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
651 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
654 pCodeInstruction pic16_pciBZ = { // mdubuc - New
655 {PC_OPCODE, NULL, NULL, 0, NULL,
668 0,0, // dest, bit instruction
670 0, // literal operand
672 0, // fast call/return mode select bit
673 0, // second memory operand
679 pCodeInstruction pic16_pciCALL = {
680 {PC_OPCODE, NULL, NULL, 0, NULL,
693 0,0, // dest, bit instruction
695 0, // literal operand
697 1, // fast call/return mode select bit
698 0, // second memory operand
704 pCodeInstruction pic16_pciCOMF = {
705 {PC_OPCODE, NULL, NULL, 0, NULL,
718 1,0, // dest, bit instruction
720 0, // literal operand
722 0, // fast call/return mode select bit
723 0, // second memory operand
725 PCC_REGISTER, // inCond
726 PCC_REGISTER // outCond
729 pCodeInstruction pic16_pciCOMFW = {
730 {PC_OPCODE, NULL, NULL, 0, NULL,
743 0,0, // dest, bit instruction
745 0, // literal operand
747 0, // fast call/return mode select bit
748 0, // second memory operand
750 PCC_REGISTER, // inCond
754 pCodeInstruction pic16_pciCLRF = {
755 {PC_OPCODE, NULL, NULL, 0, NULL,
768 0,0, // dest, bit instruction
770 0, // literal operand
772 0, // fast call/return mode select bit
773 0, // second memory operand
775 PCC_REGISTER, // inCond
776 PCC_REGISTER // outCond
779 pCodeInstruction pic16_pciCLRWDT = {
780 {PC_OPCODE, NULL, NULL, 0, NULL,
793 0,0, // dest, bit instruction
795 0, // literal operand
797 0, // fast call/return mode select bit
798 0, // second memory operand
804 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
805 {PC_OPCODE, NULL, NULL, 0, NULL,
818 0,0, // dest, bit instruction
820 0, // literal operand
822 0, // fast call/return mode select bit
823 0, // second memory operand
825 (PCC_W | PCC_REGISTER), // inCond
829 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
830 {PC_OPCODE, NULL, NULL, 0, NULL,
843 0,0, // dest, bit instruction
845 0, // literal operand
847 0, // fast call/return mode select bit
848 0, // second memory operand
850 (PCC_W | PCC_REGISTER), // inCond
854 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
855 {PC_OPCODE, NULL, NULL, 0, NULL,
868 1,0, // dest, bit instruction
870 0, // literal operand
872 0, // fast call/return mode select bit
873 0, // second memory operand
875 (PCC_W | PCC_REGISTER), // inCond
879 pCodeInstruction pic16_pciDAW = {
880 {PC_OPCODE, NULL, NULL, 0, NULL,
893 0,0, // dest, bit instruction
895 0, // literal operand
897 0, // fast call/return mode select bit
898 0, // second memory operand
901 (PCC_W | PCC_C) // outCond
904 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
905 {PC_OPCODE, NULL, NULL, 0, NULL,
918 1,0, // dest, bit instruction
920 0, // literal operand
922 0, // fast call/return mode select bit
923 0, // second memory operand
925 PCC_REGISTER, // inCond
926 PCC_REGISTER // outCond
929 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
930 {PC_OPCODE, NULL, NULL, 0, NULL,
943 0,0, // dest, bit instruction
945 0, // literal operand
947 0, // fast call/return mode select bit
948 0, // second memory operand
950 PCC_REGISTER, // inCond
954 pCodeInstruction pic16_pciDECF = {
955 {PC_OPCODE, NULL, NULL, 0, NULL,
968 1,0, // dest, bit instruction
970 0, // literal operand
972 0, // fast call/return mode select bit
973 0, // second memory operand
975 PCC_REGISTER, // inCond
976 PCC_REGISTER // outCond
979 pCodeInstruction pic16_pciDECFW = {
980 {PC_OPCODE, NULL, NULL, 0, NULL,
993 0,0, // dest, bit instruction
995 0, // literal operand
997 0, // fast call/return mode select bit
998 0, // second memory operand
1000 PCC_REGISTER, // inCond
1004 pCodeInstruction pic16_pciDECFSZ = {
1005 {PC_OPCODE, NULL, NULL, 0, NULL,
1011 NULL, // from branch
1018 1,0, // dest, bit instruction
1019 1,1, // branch, skip
1020 0, // literal operand
1021 1, // RAM access bit
1022 0, // fast call/return mode select bit
1023 0, // second memory operand
1025 PCC_REGISTER, // inCond
1026 PCC_REGISTER // outCond
1029 pCodeInstruction pic16_pciDECFSZW = {
1030 {PC_OPCODE, NULL, NULL, 0, NULL,
1036 NULL, // from branch
1043 0,0, // dest, bit instruction
1044 1,1, // branch, skip
1045 0, // literal operand
1046 1, // RAM access bit
1047 0, // fast call/return mode select bit
1048 0, // second memory operand
1050 PCC_REGISTER, // inCond
1054 pCodeInstruction pic16_pciGOTO = {
1055 {PC_OPCODE, NULL, NULL, 0, NULL,
1061 NULL, // from branch
1068 0,0, // dest, bit instruction
1069 1,0, // branch, skip
1070 0, // literal operand
1071 0, // RAM access bit
1072 0, // fast call/return mode select bit
1073 0, // second memory operand
1075 PCC_REL_ADDR, // inCond
1079 pCodeInstruction pic16_pciINCF = {
1080 {PC_OPCODE, NULL, NULL, 0, NULL,
1086 NULL, // from branch
1093 1,0, // dest, bit instruction
1094 0,0, // branch, skip
1095 0, // literal operand
1096 1, // RAM access bit
1097 0, // fast call/return mode select bit
1098 0, // second memory operand
1100 PCC_REGISTER, // inCond
1101 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1104 pCodeInstruction pic16_pciINCFW = {
1105 {PC_OPCODE, NULL, NULL, 0, NULL,
1111 NULL, // from branch
1118 0,0, // dest, bit instruction
1119 0,0, // branch, skip
1120 0, // literal operand
1121 1, // RAM access bit
1122 0, // fast call/return mode select bit
1123 0, // second memory operand
1125 PCC_REGISTER, // inCond
1129 pCodeInstruction pic16_pciINCFSZ = {
1130 {PC_OPCODE, NULL, NULL, 0, NULL,
1136 NULL, // from branch
1143 1,0, // dest, bit instruction
1144 1,1, // branch, skip
1145 0, // literal operand
1146 1, // RAM access bit
1147 0, // fast call/return mode select bit
1148 0, // second memory operand
1150 PCC_REGISTER, // inCond
1151 PCC_REGISTER // outCond
1154 pCodeInstruction pic16_pciINCFSZW = {
1155 {PC_OPCODE, NULL, NULL, 0, NULL,
1161 NULL, // from branch
1168 0,0, // dest, bit instruction
1169 1,1, // branch, skip
1170 0, // literal operand
1171 1, // RAM access bit
1172 0, // fast call/return mode select bit
1173 0, // second memory operand
1175 PCC_REGISTER, // inCond
1179 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1180 {PC_OPCODE, NULL, NULL, 0, NULL,
1186 NULL, // from branch
1193 1,0, // dest, bit instruction
1194 1,1, // branch, skip
1195 0, // literal operand
1196 1, // RAM access bit
1197 0, // fast call/return mode select bit
1198 0, // second memory operand
1200 PCC_REGISTER, // inCond
1201 PCC_REGISTER // outCond
1204 pCodeInstruction pic16_pciIORWF = {
1205 {PC_OPCODE, NULL, NULL, 0, NULL,
1211 NULL, // from branch
1218 1,0, // dest, bit instruction
1219 0,0, // branch, skip
1220 0, // literal operand
1221 1, // RAM access bit
1222 0, // fast call/return mode select bit
1223 0, // second memory operand
1225 (PCC_W | PCC_REGISTER), // inCond
1226 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1229 pCodeInstruction pic16_pciIORFW = {
1230 {PC_OPCODE, NULL, NULL, 0, NULL,
1236 NULL, // from branch
1243 0,0, // dest, bit instruction
1244 0,0, // branch, skip
1245 0, // literal operand
1246 1, // RAM access bit
1247 0, // fast call/return mode select bit
1248 0, // second memory operand
1250 (PCC_W | PCC_REGISTER), // inCond
1251 (PCC_W | PCC_Z | PCC_N) // outCond
1254 pCodeInstruction pic16_pciIORLW = {
1255 {PC_OPCODE, NULL, NULL, 0, NULL,
1261 NULL, // from branch
1268 0,0, // dest, bit instruction
1269 0,0, // branch, skip
1270 1, // literal operand
1271 0, // RAM access bit
1272 0, // fast call/return mode select bit
1273 0, // second memory operand
1275 (PCC_W | PCC_LITERAL), // inCond
1276 (PCC_W | PCC_Z | PCC_N) // outCond
1279 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1280 {PC_OPCODE, NULL, NULL, 0, NULL,
1286 NULL, // from branch
1293 0,0, // dest, bit instruction
1294 0,0, // branch, skip
1295 1, // literal operand
1296 0, // RAM access bit
1297 0, // fast call/return mode select bit
1298 0, // second memory operand
1300 (PCC_REGISTER | PCC_LITERAL), // mdubuc - Should we use a special syntax for
1301 // f (identifies FSRx)?
1302 PCC_REGISTER // outCond
1305 pCodeInstruction pic16_pciMOVF = {
1306 {PC_OPCODE, NULL, NULL, 0, NULL,
1312 NULL, // from branch
1319 1,0, // dest, bit instruction
1320 0,0, // branch, skip
1321 0, // literal operand
1322 1, // RAM access bit
1323 0, // fast call/return mode select bit
1324 0, // second memory operand
1326 PCC_REGISTER, // inCond
1327 (PCC_Z | PCC_N) // outCond
1330 pCodeInstruction pic16_pciMOVFW = {
1331 {PC_OPCODE, NULL, NULL, 0, NULL,
1337 NULL, // from branch
1344 0,0, // dest, bit instruction
1345 0,0, // branch, skip
1346 0, // literal operand
1347 1, // RAM access bit
1348 0, // fast call/return mode select bit
1349 0, // second memory operand
1351 PCC_REGISTER, // inCond
1352 (PCC_W | PCC_Z) // outCond
1355 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1356 {PC_OPCODE, NULL, NULL, 0, NULL,
1362 NULL, // from branch
1369 0,0, // dest, bit instruction
1370 0,0, // branch, skip
1371 0, // literal operand
1372 0, // RAM access bit
1373 0, // fast call/return mode select bit
1374 1, // second memory operand
1376 PCC_REGISTER, // inCond
1377 PCC_REGISTER2 // outCond
1380 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1381 {PC_OPCODE, NULL, NULL, 0, NULL,
1386 NULL, // from branch
1393 0,0, // dest, bit instruction
1394 0,0, // branch, skip
1395 1, // literal operand
1396 0, // RAM access bit
1397 0, // fast call/return mode select bit
1398 0, // second memory operand
1400 (PCC_NONE | PCC_LITERAL), // inCond
1401 PCC_REGISTER // outCond - BSR
1404 pCodeInstruction pic16_pciMOVLW = {
1405 {PC_OPCODE, NULL, NULL, 0, NULL,
1410 NULL, // from branch
1417 0,0, // dest, bit instruction
1418 0,0, // branch, skip
1419 1, // literal operand
1420 0, // RAM access bit
1421 0, // fast call/return mode select bit
1422 0, // second memory operand
1424 (PCC_NONE | PCC_LITERAL), // inCond
1428 pCodeInstruction pic16_pciMOVWF = {
1429 {PC_OPCODE, NULL, NULL, 0, NULL,
1435 NULL, // from branch
1442 0,0, // dest, bit instruction
1443 0,0, // branch, skip
1444 0, // literal operand
1445 1, // RAM access bit
1446 0, // fast call/return mode select bit
1447 0, // second memory operand
1449 PCC_REGISTER, // inCond
1453 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1454 {PC_OPCODE, NULL, NULL, 0, NULL,
1459 NULL, // from branch
1466 0,0, // dest, bit instruction
1467 0,0, // branch, skip
1468 1, // literal operand
1469 0, // RAM access bit
1470 0, // fast call/return mode select bit
1471 0, // second memory operand
1473 (PCC_W | PCC_LITERAL), // inCond
1474 PCC_REGISTER // outCond - PROD
1477 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1478 {PC_OPCODE, NULL, NULL, 0, NULL,
1483 NULL, // from branch
1490 0,0, // dest, bit instruction
1491 0,0, // branch, skip
1492 0, // literal operand
1493 1, // RAM access bit
1494 0, // fast call/return mode select bit
1495 0, // second memory operand
1497 (PCC_W | PCC_REGISTER), // inCond
1498 PCC_REGISTER // outCond - PROD
1501 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1502 {PC_OPCODE, NULL, NULL, 0, NULL,
1507 NULL, // from branch
1514 0,0, // dest, bit instruction
1515 0,0, // branch, skip
1516 0, // literal operand
1517 1, // RAM access bit
1518 0, // fast call/return mode select bit
1519 0, // second memory operand
1521 PCC_REGISTER, // inCond
1522 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
1525 pCodeInstruction pic16_pciNOP = {
1526 {PC_OPCODE, NULL, NULL, 0, NULL,
1531 NULL, // from branch
1538 0,0, // dest, bit instruction
1539 0,0, // branch, skip
1540 0, // literal operand
1541 0, // RAM access bit
1542 0, // fast call/return mode select bit
1543 0, // second memory operand
1549 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1550 {PC_OPCODE, NULL, NULL, 0, NULL,
1555 NULL, // from branch
1562 0,0, // dest, bit instruction
1563 0,0, // branch, skip
1564 0, // literal operand
1565 0, // RAM access bit
1566 0, // fast call/return mode select bit
1567 0, // second memory operand
1573 pCodeInstruction pic16_pciPUSH = {
1574 {PC_OPCODE, NULL, NULL, 0, NULL,
1579 NULL, // from branch
1586 0,0, // dest, bit instruction
1587 0,0, // branch, skip
1588 0, // literal operand
1589 0, // RAM access bit
1590 0, // fast call/return mode select bit
1591 0, // second memory operand
1597 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1598 {PC_OPCODE, NULL, NULL, 0, NULL,
1603 NULL, // from branch
1610 0,0, // dest, bit instruction
1611 0,0, // branch, skip
1612 0, // literal operand
1613 0, // RAM access bit
1614 0, // fast call/return mode select bit
1615 0, // second memory operand
1617 PCC_REL_ADDR, // inCond
1621 pCodeInstruction pic16_pciRETFIE = {
1622 {PC_OPCODE, NULL, NULL, 0, NULL,
1628 NULL, // from branch
1635 0,0, // dest, bit instruction
1636 1,0, // branch, skip
1637 0, // literal operand
1638 0, // RAM access bit
1639 1, // fast call/return mode select bit
1640 0, // second memory operand
1643 PCC_NONE // outCond (not true... affects the GIE bit too)
1646 pCodeInstruction pic16_pciRETLW = {
1647 {PC_OPCODE, NULL, NULL, 0, NULL,
1653 NULL, // from branch
1660 0,0, // dest, bit instruction
1661 1,0, // branch, skip
1662 1, // literal operand
1663 0, // RAM access bit
1664 0, // fast call/return mode select bit
1665 0, // second memory operand
1667 PCC_LITERAL, // inCond
1671 pCodeInstruction pic16_pciRETURN = {
1672 {PC_OPCODE, NULL, NULL, 0, NULL,
1678 NULL, // from branch
1685 0,0, // dest, bit instruction
1686 1,0, // branch, skip
1687 0, // literal operand
1688 0, // RAM access bit
1689 1, // fast call/return mode select bit
1690 0, // second memory operand
1695 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1696 {PC_OPCODE, NULL, NULL, 0, NULL,
1702 NULL, // from branch
1709 1,0, // dest, bit instruction
1710 0,0, // branch, skip
1711 0, // literal operand
1712 1, // RAM access bit
1713 0, // fast call/return mode select bit
1714 0, // second memory operand
1716 (PCC_C | PCC_REGISTER), // inCond
1717 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1720 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1721 {PC_OPCODE, NULL, NULL, 0, NULL,
1727 NULL, // from branch
1734 0,0, // dest, bit instruction
1735 0,0, // branch, skip
1736 0, // literal operand
1737 1, // RAM access bit
1738 0, // fast call/return mode select bit
1739 0, // second memory operand
1741 (PCC_C | PCC_REGISTER), // inCond
1742 (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1745 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1746 {PC_OPCODE, NULL, NULL, 0, NULL,
1752 NULL, // from branch
1759 1,0, // dest, bit instruction
1760 0,0, // branch, skip
1761 0, // literal operand
1762 1, // RAM access bit
1763 0, // fast call/return mode select bit
1764 0, // second memory operand
1766 PCC_REGISTER, // inCond
1767 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1769 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1770 {PC_OPCODE, NULL, NULL, 0, NULL,
1776 NULL, // from branch
1783 0,0, // dest, bit instruction
1784 0,0, // branch, skip
1785 0, // literal operand
1786 1, // RAM access bit
1787 0, // fast call/return mode select bit
1788 0, // second memory operand
1790 PCC_REGISTER, // inCond
1791 (PCC_W | PCC_Z | PCC_N) // outCond
1793 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1794 {PC_OPCODE, NULL, NULL, 0, NULL,
1800 NULL, // from branch
1807 1,0, // dest, bit instruction
1808 0,0, // branch, skip
1809 0, // literal operand
1810 1, // RAM access bit
1811 0, // fast call/return mode select bit
1812 0, // second memory operand
1814 (PCC_C | PCC_REGISTER), // inCond
1815 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1817 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1818 {PC_OPCODE, NULL, NULL, 0, NULL,
1824 NULL, // from branch
1831 0,0, // dest, bit instruction
1832 0,0, // branch, skip
1833 0, // literal operand
1834 1, // RAM access bit
1835 0, // fast call/return mode select bit
1836 0, // second memory operand
1838 (PCC_C | PCC_REGISTER), // inCond
1839 (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1841 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
1842 {PC_OPCODE, NULL, NULL, 0, NULL,
1848 NULL, // from branch
1855 1,0, // dest, bit instruction
1856 0,0, // branch, skip
1857 0, // literal operand
1858 1, // RAM access bit
1859 0, // fast call/return mode select bit
1860 0, // second memory operand
1862 PCC_REGISTER, // inCond
1863 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1866 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
1867 {PC_OPCODE, NULL, NULL, 0, NULL,
1873 NULL, // from branch
1880 0,0, // dest, bit instruction
1881 0,0, // branch, skip
1882 0, // literal operand
1883 1, // RAM access bit
1884 0, // fast call/return mode select bit
1885 0, // second memory operand
1887 PCC_REGISTER, // inCond
1888 (PCC_W | PCC_Z | PCC_N) // outCond
1891 pCodeInstruction pic16_pciSETF = { // mdubuc - New
1892 {PC_OPCODE, NULL, NULL, 0, NULL,
1898 NULL, // from branch
1905 0,0, // dest, bit instruction
1906 0,0, // branch, skip
1907 0, // literal operand
1908 1, // RAM access bit
1909 0, // fast call/return mode select bit
1910 0, // second memory operand
1912 PCC_REGISTER, // inCond
1913 PCC_REGISTER // outCond
1916 pCodeInstruction pic16_pciSUBLW = {
1917 {PC_OPCODE, NULL, NULL, 0, NULL,
1923 NULL, // from branch
1930 0,0, // dest, bit instruction
1931 0,0, // branch, skip
1932 1, // literal operand
1933 0, // RAM access bit
1934 0, // fast call/return mode select bit
1935 0, // second memory operand
1937 (PCC_W | PCC_LITERAL), // inCond
1938 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1941 pCodeInstruction pic16_pciSUBFWB = {
1942 {PC_OPCODE, NULL, NULL, 0, NULL,
1948 NULL, // from branch
1955 1,0, // dest, bit instruction
1956 0,0, // branch, skip
1957 0, // literal operand
1958 1, // RAM access bit
1959 0, // fast call/return mode select bit
1960 0, // second memory operand
1962 (PCC_W | PCC_REGISTER | PCC_C), // inCond
1963 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1966 pCodeInstruction pic16_pciSUBWF = {
1967 {PC_OPCODE, NULL, NULL, 0, NULL,
1973 NULL, // from branch
1980 1,0, // dest, bit instruction
1981 0,0, // branch, skip
1982 0, // literal operand
1983 1, // RAM access bit
1984 0, // fast call/return mode select bit
1985 0, // second memory operand
1987 (PCC_W | PCC_REGISTER), // inCond
1988 (PCC_REGISTER | PCC_Z) // outCond
1991 pCodeInstruction pic16_pciSUBFW = {
1992 {PC_OPCODE, NULL, NULL, 0, NULL,
1998 NULL, // from branch
2005 0,0, // dest, bit instruction
2006 0,0, // branch, skip
2007 0, // literal operand
2008 1, // RAM access bit
2009 0, // fast call/return mode select bit
2010 0, // second memory operand
2012 (PCC_W | PCC_REGISTER), // inCond
2013 (PCC_W | PCC_Z | PCC_OV | PCC_N) // outCond
2016 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2017 {PC_OPCODE, NULL, NULL, 0, NULL,
2023 NULL, // from branch
2030 1,0, // dest, bit instruction
2031 0,0, // branch, skip
2032 0, // literal operand
2033 1, // RAM access bit
2034 0, // fast call/return mode select bit
2035 0, // second memory operand
2037 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2038 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2041 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2042 {PC_OPCODE, NULL, NULL, 0, NULL,
2048 NULL, // from branch
2055 0,0, // dest, bit instruction
2056 0,0, // branch, skip
2057 0, // literal operand
2058 1, // RAM access bit
2059 0, // fast call/return mode select bit
2060 0, // second memory operand
2062 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2063 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2066 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2067 {PC_OPCODE, NULL, NULL, 0, NULL,
2073 NULL, // from branch
2080 1,0, // dest, bit instruction
2081 0,0, // branch, skip
2082 0, // literal operand
2083 1, // RAM access bit
2084 0, // fast call/return mode select bit
2085 0, // second memory operand
2087 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2088 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2091 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2092 {PC_OPCODE, NULL, NULL, 0, NULL,
2098 NULL, // from branch
2105 0,0, // dest, bit instruction
2106 0,0, // branch, skip
2107 0, // literal operand
2108 1, // RAM access bit
2109 0, // fast call/return mode select bit
2110 0, // second memory operand
2112 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2113 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2116 pCodeInstruction pic16_pciSWAPF = {
2117 {PC_OPCODE, NULL, NULL, 0, NULL,
2123 NULL, // from branch
2130 1,0, // dest, bit instruction
2131 0,0, // branch, skip
2132 0, // literal operand
2133 1, // RAM access bit
2134 0, // fast call/return mode select bit
2135 0, // second memory operand
2137 (PCC_REGISTER), // inCond
2138 (PCC_REGISTER) // outCond
2141 pCodeInstruction pic16_pciSWAPFW = {
2142 {PC_OPCODE, NULL, NULL, 0, NULL,
2148 NULL, // from branch
2155 0,0, // dest, bit instruction
2156 0,0, // branch, skip
2157 0, // literal operand
2158 1, // RAM access bit
2159 0, // fast call/return mode select bit
2160 0, // second memory operand
2162 (PCC_REGISTER), // inCond
2168 // mdubuc - Remove TRIS
2170 pCodeInstruction pic16_pciTRIS = {
2171 {PC_OPCODE, NULL, NULL, 0, NULL,
2177 NULL, // from branch
2184 0,0, // dest, bit instruction
2185 0,0, // branch, skip
2186 0, // literal operand
2187 0, // second memory operand
2190 PCC_REGISTER // outCond
2194 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2195 {PC_OPCODE, NULL, NULL, 0, NULL,
2201 NULL, // from branch
2208 0,0, // dest, bit instruction
2209 1,1, // branch, skip
2210 0, // literal operand
2211 1, // RAM access bit
2212 0, // fast call/return mode select bit
2213 0, // second memory operand
2215 PCC_REGISTER, // inCond
2219 pCodeInstruction pic16_pciXORWF = {
2220 {PC_OPCODE, NULL, NULL, 0, NULL,
2226 NULL, // from branch
2233 1,0, // dest, bit instruction
2234 0,0, // branch, skip
2235 0, // literal operand
2236 1, // RAM access bit
2237 0, // fast call/return mode select bit
2238 0, // second memory operand
2240 (PCC_W | PCC_REGISTER), // inCond
2241 (PCC_REGISTER | PCC_Z | PCC_N) // outCond
2244 pCodeInstruction pic16_pciXORFW = {
2245 {PC_OPCODE, NULL, NULL, 0, NULL,
2251 NULL, // from branch
2258 0,0, // dest, bit instruction
2259 0,0, // branch, skip
2260 0, // literal operand
2261 1, // RAM access bit
2262 0, // fast call/return mode select bit
2263 0, // second memory operand
2265 (PCC_W | PCC_REGISTER), // inCond
2266 (PCC_W | PCC_Z | PCC_N) // outCond
2269 pCodeInstruction pic16_pciXORLW = {
2270 {PC_OPCODE, NULL, NULL, 0, NULL,
2276 NULL, // from branch
2283 0,0, // dest, bit instruction
2284 0,0, // branch, skip
2285 1, // literal operand
2286 1, // RAM access bit
2287 0, // fast call/return mode select bit
2288 0, // second memory operand
2290 (PCC_W | PCC_LITERAL), // inCond
2291 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N) // outCond
2295 #define MAX_PIC16MNEMONICS 100
2296 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2299 /* This definition needs to be part of configure.in */
2300 // #define USE_VSNPRINTF
2302 #ifdef USE_VSNPRINTF
2303 // Alas, vsnprintf is not ANSI standard, and does not exist
2304 // on Solaris (and probably other non-Gnu flavored Unixes).
2306 /*-----------------------------------------------------------------*/
2307 /* SAFE_snprintf - like snprintf except the string pointer is */
2308 /* after the string has been printed to. This is */
2309 /* useful for printing to string as though if it */
2310 /* were a stream. */
2311 /*-----------------------------------------------------------------*/
2312 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2320 va_start(val, format);
2322 vsnprintf(*str, *size, format, val);
2328 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2329 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2337 #else // USE_VSNPRINTF
2339 // This version is *not* safe, despite the name.
2341 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2345 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2350 va_start(val, format);
2352 vsprintf(buffer, format, val);
2355 len = strlen(buffer);
2357 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2358 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2361 strcpy(*str, buffer);
2367 #endif // USE_VSNPRINTF
2369 #endif // OPT_DISABLE_PIC
2372 extern void pic16_initStack(int base_address, int size);
2373 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2374 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2375 extern void pic16_init_pic(char *);
2377 void pic16_pCodeInitRegisters(void)
2379 static int initialized=0;
2385 pic16_initStack(0xfff, 8);
2386 pic16_init_pic(port->processor);
2388 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
2389 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2390 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
2391 pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80);
2392 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2393 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2394 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2396 pic16_pc_status.rIdx = IDX_STATUS;
2397 pic16_pc_fsr0.rIdx = IDX_FSR0;
2398 pic16_pc_indf0.rIdx = IDX_INDF0;
2399 pic16_pc_intcon.rIdx = IDX_INTCON;
2400 pic16_pc_pcl.rIdx = IDX_PCL;
2401 pic16_pc_pclath.rIdx = IDX_PCLATH;
2402 pic16_pc_wreg.rIdx = IDX_WREG;
2404 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2405 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
2406 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2408 pic16_pc_kzero.rIdx = IDX_KZ;
2409 pic16_pc_wsave.rIdx = IDX_WSAVE;
2410 pic16_pc_ssave.rIdx = IDX_SSAVE;
2412 /* probably should put this in a separate initialization routine */
2413 pb_dead_pcodes = newpBlock();
2418 /*-----------------------------------------------------------------*/
2419 /* mnem2key - convert a pic mnemonic into a hash key */
2420 /* (BTW - this spreads the mnemonics quite well) */
2422 /*-----------------------------------------------------------------*/
2424 int mnem2key(char const *mnem)
2433 key += toupper(*mnem++) +1;
2437 return (key & 0x1f);
2440 #endif // OPT_DISABLE_PIC
2442 void pic16initMnemonics(void)
2447 pCodeInstruction *pci;
2449 if(mnemonics_initialized)
2452 // NULL out the array before making the assignments
2453 // since we check the array contents below this initialization.
2455 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2456 pic16Mnemonics[i] = NULL;
2459 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2460 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2461 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2462 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2463 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2464 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2465 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2466 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2467 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2468 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2469 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2470 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2471 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2472 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2473 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2474 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2475 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2476 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2477 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2478 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2479 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2480 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2481 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2482 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2483 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2484 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2485 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2486 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2487 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2488 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2489 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2490 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2491 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2492 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2493 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2494 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2495 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2496 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2497 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2498 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2499 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2500 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2501 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2502 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2503 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2504 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2505 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2506 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2507 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2508 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2509 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2510 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2511 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2512 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2513 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2514 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2515 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2516 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2517 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2518 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2519 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2520 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2521 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2522 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2523 pic16Mnemonics[POC_RLCF] = &pic16_pciRLNCF;
2524 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2525 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2526 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2527 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2528 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2529 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2530 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2531 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2532 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2533 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2534 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2535 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2536 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2537 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2538 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
2539 // pic16Mnemonics[POC_TRIS] = &pic16_pciTRIS;
2540 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
2541 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
2542 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
2543 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
2545 for(i=0; i<MAX_PIC16MNEMONICS; i++)
2546 if(pic16Mnemonics[i])
2547 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
2548 pci = hTabFirstItem(pic16MnemonicsHash, &key);
2551 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
2552 pci = hTabNextItem(pic16MnemonicsHash, &key);
2555 mnemonics_initialized = 1;
2558 int pic16_getpCodePeepCommand(char *cmd);
2560 int pic16_getpCode(char *mnem,unsigned dest)
2563 pCodeInstruction *pci;
2564 int key = mnem2key(mnem);
2566 if(!mnemonics_initialized)
2567 pic16initMnemonics();
2569 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
2573 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
2574 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst) ||
2575 (pci->num_ops <= 2 && pci->isAccess) ||
2576 (pci->num_ops <= 2 && pci->isFastCall))
2580 pci = hTabNextItemWK (pic16MnemonicsHash);
2587 /*-----------------------------------------------------------------*
2588 * pic16initpCodePeepCommands
2590 *-----------------------------------------------------------------*/
2591 void pic16initpCodePeepCommands(void)
2599 hTabAddItem(&pic16pCodePeepCommandsHash,
2600 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
2602 } while (peepCommands[i].cmd);
2604 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
2607 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
2608 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
2613 /*-----------------------------------------------------------------
2616 *-----------------------------------------------------------------*/
2618 int pic16_getpCodePeepCommand(char *cmd)
2622 int key = mnem2key(cmd);
2625 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
2628 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2629 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2633 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
2640 static char getpBlock_dbName(pBlock *pb)
2646 return pb->cmemmap->dbName;
2650 void pic16_pBlockConvert2ISR(pBlock *pb)
2661 /*-----------------------------------------------------------------*/
2662 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
2663 /* instances to the front of the doubly linked */
2664 /* list of pBlocks */
2665 /*-----------------------------------------------------------------*/
2667 void pic16_movepBlock2Head(char dbName)
2671 pb = the_pFile->pbHead;
2675 if(getpBlock_dbName(pb) == dbName) {
2676 pBlock *pbn = pb->next;
2677 pb->next = the_pFile->pbHead;
2678 the_pFile->pbHead->prev = pb;
2679 the_pFile->pbHead = pb;
2682 pb->prev->next = pbn;
2684 // If the pBlock that we just moved was the last
2685 // one in the link of all of the pBlocks, then we
2686 // need to point the tail to the block just before
2687 // the one we moved.
2688 // Note: if pb->next is NULL, then pb must have
2689 // been the last pBlock in the chain.
2692 pbn->prev = pb->prev;
2694 the_pFile->pbTail = pb->prev;
2705 void pic16_copypCode(FILE *of, char dbName)
2709 if(!of || !the_pFile)
2712 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2713 if(getpBlock_dbName(pb) == dbName) {
2715 pic16_printpBlock(of,pb);
2720 void pic16_pcode_test(void)
2723 DFPRINTF((stderr,"pcode is alive!\n"));
2733 /* create the file name */
2734 strcpy(buffer,dstFileName);
2735 strcat(buffer,".p");
2737 if( !(pFile = fopen(buffer, "w" ))) {
2738 werror(E_FILE_OPEN_ERR,buffer);
2742 fprintf(pFile,"pcode dump\n\n");
2744 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2745 fprintf(pFile,"\n\tNew pBlock\n\n");
2747 fprintf(pFile,"%s",pb->cmemmap->sname);
2749 fprintf(pFile,"internal pblock");
2751 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2752 pic16_printpBlock(pFile,pb);
2756 /*-----------------------------------------------------------------*/
2757 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
2758 /* ister, RegCond will return the bit being referenced. */
2760 /* fixme - why not just OR in the pcop bit field */
2761 /*-----------------------------------------------------------------*/
2763 static int RegCond(pCodeOp *pcop)
2769 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
2770 switch(PCORB(pcop)->bit) {
2784 /*-----------------------------------------------------------------*/
2785 /* pic16_newpCode - create and return a newly initialized pCode */
2787 /* fixme - rename this */
2789 /* The purpose of this routine is to create a new Instruction */
2790 /* pCode. This is called by gen.c while the assembly code is being */
2794 /* PIC_OPCODE op - the assembly instruction we wish to create. */
2795 /* (note that the op is analogous to but not the */
2796 /* same thing as the opcode of the instruction.) */
2797 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
2800 /* a pointer to the new malloc'd pCode is returned. */
2804 /*-----------------------------------------------------------------*/
2805 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
2807 pCodeInstruction *pci ;
2809 if(!mnemonics_initialized)
2810 pic16initMnemonics();
2812 pci = Safe_calloc(1, sizeof(pCodeInstruction));
2814 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
2815 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
2818 if(pci->inCond & PCC_EXAMINE_PCOP)
2819 pci->inCond |= RegCond(pcop);
2821 if(pci->outCond & PCC_EXAMINE_PCOP)
2822 pci->outCond |= RegCond(pcop);
2824 pci->pc.prev = pci->pc.next = NULL;
2825 return (pCode *)pci;
2828 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
2834 /*-----------------------------------------------------------------*/
2835 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
2837 /* Wild pcodes are used during the peep hole optimizer to serve */
2838 /* as place holders for any instruction. When a snippet of code is */
2839 /* compared to a peep hole rule, the wild card opcode will match */
2840 /* any instruction. However, the optional operand and label are */
2841 /* additional qualifiers that must also be matched before the */
2842 /* line (of assembly code) is declared matched. Note that the */
2843 /* operand may be wild too. */
2845 /* Note, a wild instruction is specified just like a wild var: */
2846 /* %4 ; A wild instruction, */
2847 /* See the peeph.def file for additional examples */
2849 /*-----------------------------------------------------------------*/
2851 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
2856 pcw = Safe_calloc(1,sizeof(pCodeWild));
2858 pcw->pci.pc.type = PC_WILD;
2859 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
2860 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
2861 pcw->pci.pc.pb = NULL;
2863 // pcw->pci.pc.analyze = genericAnalyze;
2864 pcw->pci.pc.destruct = genericDestruct;
2865 pcw->pci.pc.print = genericPrint;
2867 pcw->id = pCodeID; // this is the 'n' in %n
2868 pcw->operand = optional_operand;
2869 pcw->label = optional_label;
2871 pcw->mustBeBitSkipInst = 0;
2872 pcw->mustNotBeBitSkipInst = 0;
2873 pcw->invertBitSkipInst = 0;
2875 return ( (pCode *)pcw);
2879 /*-----------------------------------------------------------------*/
2880 /* newPcodeInlineP - create a new pCode from a char string */
2881 /*-----------------------------------------------------------------*/
2884 pCode *pic16_newpCodeInlineP(char *cP)
2889 pcc = Safe_calloc(1,sizeof(pCodeComment));
2891 pcc->pc.type = PC_INLINE;
2892 pcc->pc.prev = pcc->pc.next = NULL;
2893 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2896 // pcc->pc.analyze = genericAnalyze;
2897 pcc->pc.destruct = genericDestruct;
2898 pcc->pc.print = genericPrint;
2901 pcc->comment = Safe_strdup(cP);
2903 pcc->comment = NULL;
2905 return ( (pCode *)pcc);
2909 /*-----------------------------------------------------------------*/
2910 /* newPcodeCharP - create a new pCode from a char string */
2911 /*-----------------------------------------------------------------*/
2913 pCode *pic16_newpCodeCharP(char *cP)
2918 pcc = Safe_calloc(1,sizeof(pCodeComment));
2920 pcc->pc.type = PC_COMMENT;
2921 pcc->pc.prev = pcc->pc.next = NULL;
2922 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2925 // pcc->pc.analyze = genericAnalyze;
2926 pcc->pc.destruct = genericDestruct;
2927 pcc->pc.print = genericPrint;
2930 pcc->comment = Safe_strdup(cP);
2932 pcc->comment = NULL;
2934 return ( (pCode *)pcc);
2938 /*-----------------------------------------------------------------*/
2939 /* pic16_newpCodeFunction - */
2940 /*-----------------------------------------------------------------*/
2943 pCode *pic16_newpCodeFunction(char *mod,char *f)
2947 pcf = Safe_calloc(1,sizeof(pCodeFunction));
2948 //_ALLOC(pcf,sizeof(pCodeFunction));
2950 pcf->pc.type = PC_FUNCTION;
2951 pcf->pc.prev = pcf->pc.next = NULL;
2952 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
2955 // pcf->pc.analyze = genericAnalyze;
2956 pcf->pc.destruct = genericDestruct;
2957 pcf->pc.print = pCodePrintFunction;
2962 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
2963 pcf->modname = Safe_calloc(1,strlen(mod)+1);
2964 strcpy(pcf->modname,mod);
2966 pcf->modname = NULL;
2969 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
2970 pcf->fname = Safe_calloc(1,strlen(f)+1);
2971 strcpy(pcf->fname,f);
2975 return ( (pCode *)pcf);
2979 /*-----------------------------------------------------------------*/
2980 /* pic16_newpCodeFlow */
2981 /*-----------------------------------------------------------------*/
2982 static void destructpCodeFlow(pCode *pc)
2984 if(!pc || !isPCFL(pc))
2991 pic16_unlinkpCode(pc);
2993 deleteSet(&PCFL(pc)->registers);
2994 deleteSet(&PCFL(pc)->from);
2995 deleteSet(&PCFL(pc)->to);
3000 pCode *pic16_newpCodeFlow(void )
3004 //_ALLOC(pcflow,sizeof(pCodeFlow));
3005 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3007 pcflow->pc.type = PC_FLOW;
3008 pcflow->pc.prev = pcflow->pc.next = NULL;
3009 pcflow->pc.pb = NULL;
3011 // pcflow->pc.analyze = genericAnalyze;
3012 pcflow->pc.destruct = destructpCodeFlow;
3013 pcflow->pc.print = genericPrint;
3015 pcflow->pc.seq = GpcFlowSeq++;
3017 pcflow->from = pcflow->to = NULL;
3019 pcflow->inCond = PCC_NONE;
3020 pcflow->outCond = PCC_NONE;
3022 pcflow->firstBank = -1;
3023 pcflow->lastBank = -1;
3025 pcflow->FromConflicts = 0;
3026 pcflow->ToConflicts = 0;
3030 pcflow->registers = newSet();
3032 return ( (pCode *)pcflow);
3036 /*-----------------------------------------------------------------*/
3037 /*-----------------------------------------------------------------*/
3038 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3040 pCodeFlowLink *pcflowLink;
3042 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3044 pcflowLink->pcflow = pcflow;
3045 pcflowLink->bank_conflict = 0;
3050 /*-----------------------------------------------------------------*/
3051 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3052 /*-----------------------------------------------------------------*/
3054 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3059 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3061 pccs->pc.type = PC_CSOURCE;
3062 pccs->pc.prev = pccs->pc.next = NULL;
3065 pccs->pc.destruct = genericDestruct;
3066 pccs->pc.print = genericPrint;
3068 pccs->line_number = ln;
3070 pccs->line = Safe_strdup(l);
3075 pccs->file_name = Safe_strdup(f);
3077 pccs->file_name = NULL;
3079 return ( (pCode *)pccs);
3084 /*******************************************************************/
3085 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3086 /* added by VR 6-Jun-2003 */
3087 /*******************************************************************/
3089 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3093 char buffer[256]; // how long can a directive be?!
3097 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3098 pcad->pc.type = PC_ASMDIR;
3099 pcad->pc.prev = pcad->pc.next = NULL;
3102 pcad->pc.destruct = genericDestruct;
3103 pcad->pc.print = genericPrint;
3105 if(asdir && *asdir) {
3106 pcad->directive = Safe_strdup( asdir );
3109 va_start(ap, argfmt);
3111 if(argfmt && *argfmt)
3112 vsprintf(buffer, argfmt, ap);
3116 while(isspace(*lbp))lbp++;
3119 pcad->arg = Safe_strdup( lbp );
3121 return ((pCode *)pcad);
3124 /*-----------------------------------------------------------------*/
3125 /* pCodeLabelDestruct - free memory used by a label. */
3126 /*-----------------------------------------------------------------*/
3127 static void pCodeLabelDestruct(pCode *pc)
3133 if((pc->type == PC_LABEL) && PCL(pc)->label)
3134 free(PCL(pc)->label);
3140 pCode *pic16_newpCodeLabel(char *name, int key)
3146 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3148 pcl->pc.type = PC_LABEL;
3149 pcl->pc.prev = pcl->pc.next = NULL;
3150 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3153 // pcl->pc.analyze = genericAnalyze;
3154 pcl->pc.destruct = pCodeLabelDestruct;
3155 pcl->pc.print = pCodePrintLabel;
3161 sprintf(s,"_%05d_DS_",key);
3166 pcl->label = Safe_strdup(s);
3168 //fprintf(stderr,"pic16_newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
3169 return ( (pCode *)pcl);
3174 /*-----------------------------------------------------------------*/
3175 /* newpBlock - create and return a pointer to a new pBlock */
3176 /*-----------------------------------------------------------------*/
3177 static pBlock *newpBlock(void)
3182 PpB = Safe_calloc(1,sizeof(pBlock) );
3183 PpB->next = PpB->prev = NULL;
3185 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3186 PpB->tregisters = NULL;
3188 PpB->FlowTree = NULL;
3194 /*-----------------------------------------------------------------*/
3195 /* pic16_newpCodeChain - create a new chain of pCodes */
3196 /*-----------------------------------------------------------------*
3198 * This function will create a new pBlock and the pointer to the
3199 * pCode that is passed in will be the first pCode in the block.
3200 *-----------------------------------------------------------------*/
3203 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3206 pBlock *pB = newpBlock();
3208 pB->pcHead = pB->pcTail = pc;
3215 /*-----------------------------------------------------------------*/
3216 /* pic16_newpCodeOpLabel - Create a new label given the key */
3217 /* Note, a negative key means that the label is part of wild card */
3218 /* (and hence a wild card label) used in the pCodePeep */
3219 /* optimizations). */
3220 /*-----------------------------------------------------------------*/
3222 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3225 static int label_key=-1;
3229 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3230 pcop->type = PO_LABEL;
3235 sprintf(s=buffer,"_%05d_DS_",key);
3237 s = name, key = label_key--;
3240 pcop->name = Safe_strdup(s);
3242 ((pCodeOpLabel *)pcop)->key = key;
3244 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3248 /*-----------------------------------------------------------------*/
3249 /*-----------------------------------------------------------------*/
3250 pCodeOp *pic16_newpCodeOpLit(int lit)
3256 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3257 pcop->type = PO_LITERAL;
3261 sprintf(s,"0x%02x",lit);
3263 pcop->name = Safe_strdup(s);
3266 ((pCodeOpLit *)pcop)->lit = lit;
3271 /*-----------------------------------------------------------------*/
3272 /*-----------------------------------------------------------------*/
3273 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3277 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3278 pcop->type = PO_IMMEDIATE;
3280 regs *r = pic16_dirregWithName(name);
3281 pcop->name = Safe_strdup(name);
3284 //fprintf(stderr, " pic16_newpCodeOpImmd reg %s exists\n",name);
3285 PCOI(pcop)->rIdx = r->rIdx;
3287 //fprintf(stderr, " pic16_newpCodeOpImmd reg %s doesn't exist\n",name);
3288 PCOI(pcop)->rIdx = -1;
3290 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3295 PCOI(pcop)->index = index;
3296 PCOI(pcop)->offset = offset;
3297 PCOI(pcop)->_const = code_space;
3302 /*-----------------------------------------------------------------*/
3303 /*-----------------------------------------------------------------*/
3304 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3310 if(!pcwb || !subtype) {
3311 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3315 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3316 pcop->type = PO_WILD;
3317 sprintf(s,"%%%d",id);
3318 pcop->name = Safe_strdup(s);
3320 PCOW(pcop)->id = id;
3321 PCOW(pcop)->pcwb = pcwb;
3322 PCOW(pcop)->subtype = subtype;
3323 PCOW(pcop)->matched = NULL;
3328 /*-----------------------------------------------------------------*/
3329 /*-----------------------------------------------------------------*/
3330 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3334 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3335 pcop->type = PO_GPR_BIT;
3337 pcop->name = Safe_strdup(s);
3341 PCORB(pcop)->bit = bit;
3342 PCORB(pcop)->inBitSpace = inBitSpace;
3344 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3345 PCOR(pcop)->r = NULL;
3346 PCOR(pcop)->rIdx = 0;
3350 /*-----------------------------------------------------------------*
3351 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3353 * If rIdx >=0 then a specific register from the set of registers
3354 * will be selected. If rIdx <0, then a new register will be searched
3356 *-----------------------------------------------------------------*/
3358 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3362 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3367 PCOR(pcop)->rIdx = rIdx;
3368 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3370 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3373 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3376 pcop->type = PCOR(pcop)->r->pc_type;
3381 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3385 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3386 PCOR(pcop)->r = pic16_allocRegByName(name, 1);
3387 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3388 pcop->type = PCOR(pcop)->r->pc_type;
3389 pcop->name = PCOR(pcop)->r->name;
3394 /*-----------------------------------------------------------------*/
3395 /*-----------------------------------------------------------------*/
3397 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3404 pcop = pic16_newpCodeOpBit(name, -1,0);
3408 pcop = pic16_newpCodeOpLit(-1);
3412 pcop = pic16_newpCodeOpLabel(NULL,-1);
3415 pcop = pic16_newpCodeOpReg(-1);
3418 case PO_GPR_REGISTER:
3420 pcop = pic16_newpCodeOpRegFromStr(name);
3422 pcop = pic16_newpCodeOpReg(-1);
3426 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3429 pcop->name = Safe_strdup(name);
3437 /*-----------------------------------------------------------------*/
3438 /*-----------------------------------------------------------------*/
3439 void pic16_pCodeConstString(char *name, char *value)
3443 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
3448 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3450 pic16_addpBlock(pb);
3452 sprintf(buffer,"; %s = %s",name,value);
3454 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3455 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3458 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3464 /*-----------------------------------------------------------------*/
3465 /*-----------------------------------------------------------------*/
3467 static void pCodeReadCodeTable(void)
3471 fprintf(stderr, " %s\n",__FUNCTION__);
3473 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3475 pic16_addpBlock(pb);
3477 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3478 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3479 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3480 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3482 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3483 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3484 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3485 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3490 /*-----------------------------------------------------------------*/
3491 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3492 /*-----------------------------------------------------------------*/
3493 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3500 /* If this is the first pcode to be added to a block that
3501 * was initialized with a NULL pcode, then go ahead and
3502 * make this pcode the head and tail */
3503 pb->pcHead = pb->pcTail = pc;
3506 pb->pcTail->next = pc;
3508 pc->prev = pb->pcTail;
3515 /*-----------------------------------------------------------------*/
3516 /* pic16_addpBlock - place a pBlock into the pFile */
3517 /*-----------------------------------------------------------------*/
3518 void pic16_addpBlock(pBlock *pb)
3520 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3523 /* First time called, we'll pass through here. */
3524 //_ALLOC(the_pFile,sizeof(pFile));
3525 the_pFile = Safe_calloc(1,sizeof(pFile));
3526 the_pFile->pbHead = the_pFile->pbTail = pb;
3527 the_pFile->functions = NULL;
3531 the_pFile->pbTail->next = pb;
3532 pb->prev = the_pFile->pbTail;
3534 the_pFile->pbTail = pb;
3537 /*-----------------------------------------------------------------*/
3538 /* removepBlock - remove a pBlock from the pFile */
3539 /*-----------------------------------------------------------------*/
3540 static void removepBlock(pBlock *pb)
3548 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3550 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3553 if(pbs == the_pFile->pbHead)
3554 the_pFile->pbHead = pbs->next;
3556 if (pbs == the_pFile->pbTail)
3557 the_pFile->pbTail = pbs->prev;
3560 pbs->next->prev = pbs->prev;
3563 pbs->prev->next = pbs->next;
3570 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3574 /*-----------------------------------------------------------------*/
3575 /* printpCode - write the contents of a pCode to a file */
3576 /*-----------------------------------------------------------------*/
3577 static void printpCode(FILE *of, pCode *pc)
3588 fprintf(of,"warning - unable to print pCode\n");
3591 /*-----------------------------------------------------------------*/
3592 /* pic16_printpBlock - write the contents of a pBlock to a file */
3593 /*-----------------------------------------------------------------*/
3594 void pic16_printpBlock(FILE *of, pBlock *pb)
3604 for(pc = pb->pcHead; pc; pc = pc->next)
3609 /*-----------------------------------------------------------------*/
3611 /* pCode processing */
3615 /*-----------------------------------------------------------------*/
3617 void pic16_unlinkpCode(pCode *pc)
3623 fprintf(stderr,"Unlinking: ");
3624 printpCode(stderr, pc);
3627 pc->prev->next = pc->next;
3629 pc->next->prev = pc->prev;
3631 pc->prev = pc->next = NULL;
3635 /*-----------------------------------------------------------------*/
3636 /*-----------------------------------------------------------------*/
3638 static void genericDestruct(pCode *pc)
3641 pic16_unlinkpCode(pc);
3644 /* For instructions, tell the register (if there's one used)
3645 * that it's no longer needed */
3646 regs *reg = pic16_getRegFromInstruction(pc);
3648 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3650 if(PCI(pc)->is2MemOp) {
3651 reg = pic16_getRegFromInstruction2(pc);
3653 deleteSetItem(&(reg->reglives.usedpCodes), pc);
3657 /* Instead of deleting the memory used by this pCode, mark
3658 * the object as bad so that if there's a pointer to this pCode
3659 * dangling around somewhere then (hopefully) when the type is
3660 * checked we'll catch it.
3665 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3674 /*-----------------------------------------------------------------*/
3675 /*-----------------------------------------------------------------*/
3676 static void pBlockRegs(FILE *of, pBlock *pb)
3681 r = setFirstItem(pb->tregisters);
3683 r = setNextItem(pb->tregisters);
3688 /*-----------------------------------------------------------------*/
3689 /*-----------------------------------------------------------------*/
3690 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3695 int use_buffer = 1; // copy the string to the passed buffer pointer
3700 use_buffer = 0; // Don't bother copying the string to the buffer.
3704 switch(pcop->type) {
3708 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3711 return PCOR(pcop)->r->name;
3714 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3717 SAFE_snprintf(&buffer,&size,"%s",r->name);
3727 if(PCOI(pcop)->_const) {
3729 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3730 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3733 8 * PCOI(pcop)->offset );
3735 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
3738 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
3739 SAFE_snprintf(&s,&size,"(%s + %d)",
3741 PCOI(pcop)->index );
3743 if(PCOI(pcop)->offset)
3744 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3746 SAFE_snprintf(&s,&size,"%s",pcop->name);
3754 //size = sizeof(buffer);
3755 if( PCOR(pcop)->instance) {
3756 SAFE_snprintf(&s,&size,"(%s + %d)",
3758 PCOR(pcop)->instance );
3760 //fprintf(stderr,"PO_DIR %s\n",buffer);
3762 SAFE_snprintf(&s,&size,"%s",pcop->name);
3768 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3777 return "NO operand";
3781 /*-----------------------------------------------------------------*/
3782 /* pic16_get_op2 - variant to support two memory operand commands */
3783 /*-----------------------------------------------------------------*/
3784 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
3789 int use_buffer = 1; // copy the string to the passed buffer pointer
3794 use_buffer = 0; // Don't bother copying the string to the buffer.
3798 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",
3799 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
3800 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
3804 switch(PCOR2(pcop)->pcop2->type) {
3808 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
3811 return PCOR(PCOR2(pcop)->pcop2)->r->name;
3814 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
3817 SAFE_snprintf(&buffer,&size,"%s",r->name);
3829 if(PCOI(pcop)->_const) {
3831 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3832 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3835 8 * PCOI(pcop)->offset );
3837 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
3840 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
3841 SAFE_snprintf(&s,&size,"(%s + %d)",
3843 PCOI(pcop)->index );
3845 if(PCOI(pcop)->offset)
3846 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3848 SAFE_snprintf(&s,&size,"%s",pcop->name);
3857 //size = sizeof(buffer);
3858 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
3859 SAFE_snprintf(&s,&size,"(%s + %d)",
3860 PCOR(PCOR2(pcop)->pcop2)->r->name,
3861 PCOR(PCOR2(pcop)->pcop2)->instance );
3863 //fprintf(stderr,"PO_DIR %s\n",buffer);
3865 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
3870 if (PCOR2(pcop)->r1->name) {
3872 SAFE_snprintf(&buffer,&size,"%s",PCOR2(pcop)->r1->name);
3875 return PCOR2(pcop)->r1->name;
3883 return "NO operand";
3887 /*-----------------------------------------------------------------*/
3888 /*-----------------------------------------------------------------*/
3889 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
3893 return pic16_get_op(pcc->pcop,NULL,0);
3895 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
3896 * return ("ERROR Null: "__FUNCTION__);
3898 return ("ERROR Null: pic16_get_op_from_instruction");
3902 /*-----------------------------------------------------------------*/
3903 /*-----------------------------------------------------------------*/
3904 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3907 fprintf(of,"pcodeopprint- not implemented\n");
3910 /*-----------------------------------------------------------------*/
3911 /*-----------------------------------------------------------------*/
3912 static char *pCode2str(char *str, size_t size, pCode *pc)
3919 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3921 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3923 if(PCI(pc)->is2MemOp) {
3924 SAFE_snprintf(&s,&size, "%s,%s",
3925 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
3926 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
3930 if(PCI(pc)->isBitInst) {
3931 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3932 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3933 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
3934 PCI(pc)->pcop->name ,
3935 PCI(pc)->pcop->name );
3937 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
3938 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
3939 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3940 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3942 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
3943 //PCI(pc)->pcop->t.bit );
3946 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3947 if( PCI(pc)->num_ops == 3)
3948 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3950 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
3953 SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
3955 if( PCI(pc)->num_ops == 3)
3956 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3964 /* assuming that comment ends with a \n */
3965 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3969 /* assuming that inline code ends with a \n */
3970 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3974 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3977 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3980 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3983 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3986 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3989 SAFE_snprintf(&s,&size,"\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
3993 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4000 /*-----------------------------------------------------------------*/
4001 /* genericPrint - the contents of a pCode to a file */
4002 /*-----------------------------------------------------------------*/
4003 static void genericPrint(FILE *of, pCode *pc)
4011 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4015 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4019 // If the opcode has a label, print that first
4021 pBranch *pbl = PCI(pc)->label;
4022 while(pbl && pbl->pc) {
4023 if(pbl->pc->type == PC_LABEL)
4024 pCodePrintLabel(of, pbl->pc);
4030 genericPrint(of,PCODE(PCI(pc)->cline));
4035 pCode2str(str, 256, pc);
4037 fprintf(of,"%s",str);
4040 if(pic16_debug_verbose) {
4041 fprintf(of, "\t;key=%03x %d",pc->seq, __LINE__);
4043 fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4051 pBranch *dpb = pc->to; // debug
4053 switch ( dpb->pc->type) {
4055 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
4058 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
4061 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
4064 fprintf(of, "\t;flow");
4074 // fprintf(of,"\n"); // these are moved prior to #if 0
4078 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4079 if(PCW(pc)->pci.label)
4080 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4082 if(PCW(pc)->operand) {
4083 fprintf(of,";\toperand ");
4084 pCodeOpPrint(of,PCW(pc)->operand );
4089 if(pic16_debug_verbose) {
4090 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4091 if(PCFL(pc)->ancestor)
4092 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4099 fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4102 fprintf(of, "\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4107 fprintf(of,"unknown pCode type %d\n",pc->type);
4112 /*-----------------------------------------------------------------*/
4113 /* pCodePrintFunction - prints function begin/end */
4114 /*-----------------------------------------------------------------*/
4116 static void pCodePrintFunction(FILE *of, pCode *pc)
4122 if( ((pCodeFunction *)pc)->modname)
4123 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4125 if(PCF(pc)->fname) {
4126 pBranch *exits = PCF(pc)->to;
4128 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
4131 exits = exits->next;
4134 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4137 if((PCF(pc)->from &&
4138 PCF(pc)->from->pc->type == PC_FUNCTION &&
4139 PCF(PCF(pc)->from->pc)->fname) )
4140 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4142 fprintf(of,"; exit point [can't find entry point]\n");
4145 /*-----------------------------------------------------------------*/
4146 /* pCodePrintLabel - prints label */
4147 /*-----------------------------------------------------------------*/
4149 static void pCodePrintLabel(FILE *of, pCode *pc)
4156 fprintf(of,"%s\n",PCL(pc)->label);
4157 else if (PCL(pc)->key >=0)
4158 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4160 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4163 /*-----------------------------------------------------------------*/
4164 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4165 /* remove it if it is found. */
4166 /*-----------------------------------------------------------------*/
4167 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4174 if(pcl->type == PC_OPCODE)
4175 b = PCI(pcl)->label;
4177 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4182 //fprintf (stderr, "%s \n",__FUNCTION__);
4183 //pcl->print(stderr,pcl);
4184 //pc->print(stderr,pc);
4187 //fprintf (stderr, "found label\n");
4191 bprev->next = b->next; /* Not first pCode in chain */
4195 PCI(pcl)->label = b->next; /* First pCode in chain */
4198 return; /* A label can't occur more than once */
4206 /*-----------------------------------------------------------------*/
4207 /*-----------------------------------------------------------------*/
4208 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4227 /*-----------------------------------------------------------------*/
4228 /* pBranchLink - given two pcodes, this function will link them */
4229 /* together through their pBranches */
4230 /*-----------------------------------------------------------------*/
4231 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4235 // Declare a new branch object for the 'from' pCode.
4237 //_ALLOC(b,sizeof(pBranch));
4238 b = Safe_calloc(1,sizeof(pBranch));
4239 b->pc = PCODE(t); // The link to the 'to' pCode.
4242 f->to = pic16_pBranchAppend(f->to,b);
4244 // Now do the same for the 'to' pCode.
4246 //_ALLOC(b,sizeof(pBranch));
4247 b = Safe_calloc(1,sizeof(pBranch));
4251 t->from = pic16_pBranchAppend(t->from,b);
4256 /*-----------------------------------------------------------------*/
4257 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4259 /*-----------------------------------------------------------------*/
4260 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4273 /*-----------------------------------------------------------------*/
4274 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4275 /*-----------------------------------------------------------------*/
4276 static void pCodeUnlink(pCode *pc)
4281 if(!pc->prev || !pc->next) {
4282 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4286 /* first remove the pCode from the chain */
4287 pc->prev->next = pc->next;
4288 pc->next->prev = pc->prev;
4290 /* Now for the hard part... */
4292 /* Remove the branches */
4296 pc1 = pb1->pc; /* Get the pCode that branches to the
4297 * one we're unlinking */
4299 /* search for the link back to this pCode (the one we're
4301 if(pb2 = pBranchFind(pc1->to,pc)) {
4302 pb2->pc = pc->to->pc; // make the replacement
4304 /* if the pCode we're unlinking contains multiple 'to'
4305 * branches (e.g. this a skip instruction) then we need
4306 * to copy these extra branches to the chain. */
4308 pic16_pBranchAppend(pb2, pc->to->next);
4317 /*-----------------------------------------------------------------*/
4318 /*-----------------------------------------------------------------*/
4320 static void genericAnalyze(pCode *pc)
4330 // Go through the pCodes that are in pCode chain and link
4331 // them together through the pBranches. Note, the pCodes
4332 // are linked together as a contiguous stream like the
4333 // assembly source code lines. The linking here mimics this
4334 // except that comments are not linked in.
4336 pCode *npc = pc->next;
4338 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4339 pBranchLink(pc,npc);
4344 /* reached the end of the pcode chain without finding
4345 * an instruction we could link to. */
4349 fprintf(stderr,"analyze PC_FLOW\n");
4353 fprintf(stderr,,";A bad pCode is being used\n");
4359 /*-----------------------------------------------------------------*/
4360 /*-----------------------------------------------------------------*/
4361 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4365 if(pc->type == PC_LABEL) {
4366 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4369 if(pc->type == PC_OPCODE) {
4370 pbr = PCI(pc)->label;
4372 if(pbr->pc->type == PC_LABEL) {
4373 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4383 /*-----------------------------------------------------------------*/
4384 /*-----------------------------------------------------------------*/
4385 static int checkLabel(pCode *pc)
4389 if(pc && isPCI(pc)) {
4390 pbr = PCI(pc)->label;
4392 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4402 /*-----------------------------------------------------------------*/
4403 /* findLabelinpBlock - Search the pCode for a particular label */
4404 /*-----------------------------------------------------------------*/
4405 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4412 for(pc = pb->pcHead; pc; pc = pc->next)
4413 if(compareLabel(pc,pcop_label))
4419 /*-----------------------------------------------------------------*/
4420 /* findLabel - Search the pCode for a particular label */
4421 /*-----------------------------------------------------------------*/
4422 static pCode * findLabel(pCodeOpLabel *pcop_label)
4430 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4431 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4435 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4439 /*-----------------------------------------------------------------*/
4440 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4441 /* in the linked list */
4442 /*-----------------------------------------------------------------*/
4443 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4456 /*-----------------------------------------------------------------*/
4457 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4458 /* in the linked list */
4459 /*-----------------------------------------------------------------*/
4460 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4472 /*-----------------------------------------------------------------*/
4473 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4474 /* in the linked list */
4475 /*-----------------------------------------------------------------*/
4476 pCode * pic16_findNextInstruction(pCode *pci)
4481 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4485 fprintf(stderr,"pic16_findNextInstruction: ");
4486 printpCode(stderr, pc);
4491 //fprintf(stderr,"Couldn't find instruction\n");
4495 /*-----------------------------------------------------------------*/
4496 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4497 /* in the linked list */
4498 /*-----------------------------------------------------------------*/
4499 pCode * pic16_findPrevInstruction(pCode *pci)
4501 return findPrevpCode(pci, PC_OPCODE);
4504 /*-----------------------------------------------------------------*/
4505 /* findFunctionEnd - given a pCode find the end of the function */
4506 /* that contains it */
4507 /*-----------------------------------------------------------------*/
4508 static pCode * findFunctionEnd(pCode *pc)
4512 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4518 fprintf(stderr,"Couldn't find function end\n");
4523 /*-----------------------------------------------------------------*/
4524 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4525 /* instruction with which it is associated. */
4526 /*-----------------------------------------------------------------*/
4527 static void AnalyzeLabel(pCode *pc)
4536 static void AnalyzeGOTO(pCode *pc)
4539 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4543 static void AnalyzeSKIP(pCode *pc)
4546 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4547 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4551 static void AnalyzeRETURN(pCode *pc)
4554 // branch_link(pc,findFunctionEnd(pc->next));
4560 /*-----------------------------------------------------------------*/
4561 /*-----------------------------------------------------------------*/
4562 regs * pic16_getRegFromInstruction(pCode *pc)
4568 PCI(pc)->num_ops == 0 ||
4569 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4572 switch(PCI(pc)->pcop->type) {
4575 return PCOR(PCI(pc)->pcop)->r;
4577 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4581 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4582 return PCOR(PCI(pc)->pcop)->r;
4585 if(PCOI(PCI(pc)->pcop)->r)
4586 return (PCOI(PCI(pc)->pcop)->r);
4588 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4589 return pic16_dirregWithName(PCI(pc)->pcop->name);
4590 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4593 return PCOR(PCI(pc)->pcop)->r;
4596 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4597 return PCOR(PCI(pc)->pcop)->r;
4599 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4603 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4604 //genericPrint(stderr, pc);
4612 /*-------------------------------------------------------------------------------*/
4613 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
4614 /*-------------------------------------------------------------------------------*/
4615 regs * pic16_getRegFromInstruction2(pCode *pc)
4621 PCI(pc)->num_ops == 0 ||
4622 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
4627 * operands supported in MOVFF:
4634 switch(PCI(pc)->pcop->type) {
4637 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4639 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4643 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4644 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4649 if(PCOI(PCI(pc)->pcop)->r)
4650 return (PCOI(PCI(pc)->pcop)->r);
4652 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4653 return pic16_dirregWithName(PCI(pc)->pcop->name);
4654 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4659 // return PCOR2(PCI(pc)->pcop)->r;
4662 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4663 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4667 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4670 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4671 //genericPrint(stderr, pc);
4679 /*-----------------------------------------------------------------*/
4680 /*-----------------------------------------------------------------*/
4682 static void AnalyzepBlock(pBlock *pb)
4689 /* Find all of the registers used in this pBlock
4690 * by looking at each instruction and examining it's
4693 for(pc = pb->pcHead; pc; pc = pc->next) {
4695 /* Is this an instruction with operands? */
4696 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4698 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4700 /* Loop through all of the registers declared so far in
4701 this block and see if we find this one there */
4703 regs *r = setFirstItem(pb->tregisters);
4706 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4707 PCOR(PCI(pc)->pcop)->r = r;
4710 r = setNextItem(pb->tregisters);
4714 /* register wasn't found */
4715 //r = Safe_calloc(1, sizeof(regs));
4716 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
4717 //addSet(&pb->tregisters, r);
4718 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
4719 //PCOR(PCI(pc)->pcop)->r = r;
4720 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
4722 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
4725 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
4726 if(PCOR(PCI(pc)->pcop)->r) {
4727 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
4728 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
4730 if(PCI(pc)->pcop->name)
4731 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
4733 fprintf(stderr,"ERROR: NULL register\n");
4742 /*-----------------------------------------------------------------*/
4744 /*-----------------------------------------------------------------*/
4745 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
4747 static void InsertpFlow(pCode *pc, pCode **pflow)
4750 PCFL(*pflow)->end = pc;
4752 if(!pc || !pc->next)
4755 *pflow = pic16_newpCodeFlow();
4756 pic16_pCodeInsertAfter(pc, *pflow);
4759 /*-----------------------------------------------------------------*/
4760 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4761 /* the flow blocks. */
4763 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
4764 * point the instruction flow changes.
4766 /*-----------------------------------------------------------------*/
4767 void pic16_BuildFlow(pBlock *pb)
4770 pCode *last_pci=NULL;
4777 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
4778 /* Insert a pCodeFlow object at the beginning of a pBlock */
4780 InsertpFlow(pb->pcHead, &pflow);
4782 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
4783 //pflow->next = pb->pcHead; /* Make the current head the next object */
4784 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
4785 //pb->pcHead = pflow; /* Make the Flow object the head */
4788 for( pc = pic16_findNextInstruction(pb->pcHead);
4790 pc=pic16_findNextInstruction(pc)) {
4793 PCI(pc)->pcflow = PCFL(pflow);
4795 //fprintf(stderr," build: ");
4796 //pflow->print(stderr,pflow);
4798 if( PCI(pc)->isSkip) {
4800 /* The two instructions immediately following this one
4801 * mark the beginning of a new flow segment */
4803 while(pc && PCI(pc)->isSkip) {
4805 PCI(pc)->pcflow = PCFL(pflow);
4809 InsertpFlow(pc, &pflow);
4810 pc=pic16_findNextInstruction(pc->next);
4818 PCI(pc)->pcflow = PCFL(pflow);
4820 InsertpFlow(pc, &pflow);
4822 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
4824 InsertpFlow(pc, &pflow);
4827 } else if (checkLabel(pc)) {
4829 /* This instruction marks the beginning of a
4830 * new flow segment */
4835 /* If the previous pCode is not a flow object, then
4836 * insert a new flow object. (This check prevents
4837 * two consecutive flow objects from being insert in
4838 * the case where a skip instruction preceeds an
4839 * instruction containing a label.) */
4841 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4842 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
4844 PCI(pc)->pcflow = PCFL(pflow);
4851 //fprintf (stderr,",end seq %d",GpcFlowSeq);
4853 PCFL(pflow)->end = pb->pcTail;
4856 /*-------------------------------------------------------------------*/
4857 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4858 /* the flow blocks. */
4860 * unBuildFlow removes pCodeFlow objects from a pCode chain
4862 /*-----------------------------------------------------------------*/
4863 static void unBuildFlow(pBlock *pb)
4878 if(PCI(pc)->pcflow) {
4879 //free(PCI(pc)->pcflow);
4880 PCI(pc)->pcflow = NULL;
4883 } else if(isPCFL(pc) )
4892 /*-----------------------------------------------------------------*/
4893 /*-----------------------------------------------------------------*/
4894 static void dumpCond(int cond)
4897 static char *pcc_str[] = {
4912 int ncond = sizeof(pcc_str) / sizeof(char *);
4915 fprintf(stderr, "0x%04X\n",cond);
4917 for(i=0,j=1; i<ncond; i++, j<<=1)
4919 fprintf(stderr, " %s\n",pcc_str[i]);
4925 /*-----------------------------------------------------------------*/
4926 /*-----------------------------------------------------------------*/
4927 static void FlowStats(pCodeFlow *pcflow)
4935 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4937 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
4940 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4945 fprintf(stderr, " FlowStats inCond: ");
4946 dumpCond(pcflow->inCond);
4947 fprintf(stderr, " FlowStats outCond: ");
4948 dumpCond(pcflow->outCond);
4952 /*-----------------------------------------------------------------*
4953 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4954 * if it affects the banking bits.
4956 * return: -1 == Banking bits are unaffected by this pCode.
4958 * return: > 0 == Banking bits are affected.
4960 * If the banking bits are affected, then the returned value describes
4961 * which bits are affected and how they're affected. The lower half
4962 * of the integer maps to the bits that are affected, the upper half
4963 * to whether they're set or cleared.
4965 *-----------------------------------------------------------------*/
4967 static int isBankInstruction(pCode *pc)
4975 if( PCI(pc)->op == POC_MOVLB ||
4976 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
4977 bank = PCOL(pc)->lit;
4984 /*-----------------------------------------------------------------*/
4985 /*-----------------------------------------------------------------*/
4986 static void FillFlow(pCodeFlow *pcflow)
4995 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4997 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5000 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5007 isBankInstruction(pc);
5009 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5013 fprintf(stderr, " FillFlow - Bad end of flow\n");
5015 fprintf(stderr, " FillFlow - Ending flow with\n ");
5016 pc->print(stderr,pc);
5019 fprintf(stderr, " FillFlow inCond: ");
5020 dumpCond(pcflow->inCond);
5021 fprintf(stderr, " FillFlow outCond: ");
5022 dumpCond(pcflow->outCond);
5026 /*-----------------------------------------------------------------*/
5027 /*-----------------------------------------------------------------*/
5028 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5030 pCodeFlowLink *fromLink, *toLink;
5032 if(!from || !to || !to->pcflow || !from->pcflow)
5035 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5036 toLink = pic16_newpCodeFlowLink(to->pcflow);
5038 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5039 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5043 /*-----------------------------------------------------------------*
5044 * void LinkFlow(pBlock *pb)
5046 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5047 * non-branching segments. In LinkFlow, we determine the execution
5048 * order of these segments. For example, if one of the segments ends
5049 * with a skip, then we know that there are two possible flow segments
5050 * to which control may be passed.
5051 *-----------------------------------------------------------------*/
5052 static void LinkFlow(pBlock *pb)
5058 //fprintf(stderr,"linkflow \n");
5060 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5062 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5065 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5067 //fprintf(stderr," link: ");
5068 //pcflow->print(stderr,pcflow);
5070 //FillFlow(PCFL(pcflow));
5072 pc = PCFL(pcflow)->end;
5074 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5075 if(isPCI_SKIP(pc)) {
5076 //fprintf(stderr, "ends with skip\n");
5077 //pc->print(stderr,pc);
5078 pct=pic16_findNextInstruction(pc->next);
5079 LinkFlow_pCode(PCI(pc),PCI(pct));
5080 pct=pic16_findNextInstruction(pct->next);
5081 LinkFlow_pCode(PCI(pc),PCI(pct));
5085 if(isPCI_BRANCH(pc)) {
5086 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5088 //fprintf(stderr, "ends with branch\n ");
5089 //pc->print(stderr,pc);
5091 if(!(pcol && isPCOLAB(pcol))) {
5092 if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5093 pc->print(stderr,pc);
5094 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5099 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5100 LinkFlow_pCode(PCI(pc),PCI(pct));
5102 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5103 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5104 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5110 //fprintf(stderr, "ends with non-branching instruction:\n");
5111 //pc->print(stderr,pc);
5113 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5119 //fprintf(stderr, "ends with unknown\n");
5120 //pc->print(stderr,pc);
5124 //fprintf(stderr, "ends with nothing: ERROR\n");
5128 /*-----------------------------------------------------------------*/
5129 /*-----------------------------------------------------------------*/
5131 /*-----------------------------------------------------------------*/
5132 /*-----------------------------------------------------------------*/
5133 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5139 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5142 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5148 /*-----------------------------------------------------------------*/
5149 /* BanksUsedFlow - Identify which banks are used in flow 2. */
5150 /*-----------------------------------------------------------------*/
5151 static void BanksUsedFlow2(pCode *pcflow)
5160 if(!isPCFL(pcflow)) {
5161 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
5165 pc = pic16_findNextInstruction(pcflow->next);
5167 PCFL(pcflow)->lastBank = -1;
5169 while(pic16_isPCinFlow(pc,pcflow)) {
5171 int bank_selected = isBankInstruction(pc);
5173 //if(PCI(pc)->pcflow)
5174 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
5176 if(bank_selected >= 0) {
5177 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
5179 /* This instruction is modifying banking bits before accessing registers */
5181 PCFL(pcflow)->firstBank = -1;
5183 if(PCFL(pcflow)->lastBank == -1)
5184 PCFL(pcflow)->lastBank = 0;
5186 bank = 1 << bank_selected;
5187 PCFL(pcflow)->lastBank |= bank;
5191 reg = pic16_getRegFromInstruction(pc);
5193 if(reg && !pic16_isREGinBank(reg, bank)) {
5194 int allbanks = pic16_REGallBanks(reg);
5196 PCFL(pcflow)->firstBank = allbanks;
5198 PCFL(pcflow)->lastBank = allbanks;
5205 pc = pic16_findNextInstruction(pc->next);
5208 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
5209 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
5214 /*-----------------------------------------------------------------*/
5215 /*-----------------------------------------------------------------*/
5216 static void BanksUsedFlow(pBlock *pb)
5221 //pb->pcHead->print(stderr, pb->pcHead);
5223 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5224 //pcflow->print(stderr,pcflow);
5226 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5228 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5230 BanksUsedFlow2(pcflow);
5236 /*-----------------------------------------------------------------*/
5237 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5238 /*-----------------------------------------------------------------*/
5239 static void insertBankSwitch(int position, pCode *pc, int bsr)
5248 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5249 * insert a BANKSEL assembler directive for the symbol used by
5250 * the pCode. This will allow the linker to setup the correct
5251 * bank at linking time
5254 if(!options.gen_banksel || bsr != -1) {
5255 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5258 /* emit the BANKSEL [symbol] */
5260 /* IMPORTANT: The following code does not check if a symbol is
5261 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5263 reg = pic16_getRegFromInstruction(pc);
5265 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", reg->name);
5267 position = 0; // position is always before (sanity check!)
5271 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5272 pc->print(stderr, pc);
5276 /* insert the bank switch after this pc instruction */
5277 pCode *pcnext = pic16_findNextInstruction(pc);
5278 pic16_pCodeInsertAfter(pc, new_pc);
5283 pic16_pCodeInsertAfter(pc->prev, new_pc);
5285 /* Move the label, if there is one */
5287 if(PCI(pc)->label) {
5288 PCI(new_pc)->label = PCI(pc)->label;
5289 PCI(pc)->label = NULL;
5292 /* The new instruction has the same pcflow block */
5293 PCI(new_pc)->pcflow = PCI(pc)->pcflow;
5296 /*-----------------------------------------------------------------*/
5297 /*-----------------------------------------------------------------*/
5298 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
5309 pc = pic16_findNextInstruction(pcfl->pc.next);
5311 while(pic16_isPCinFlow(pc,PCODE(pcfl))) {
5313 reg = pic16_getRegFromInstruction(pc);
5317 fprintf(stderr, "%s:%d %s ",__FUNCTION__, __LINE__, reg->name);
5318 fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
5323 if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) ||
5324 ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
5327 /* Examine the instruction before this one to make sure it is
5328 * not a skip type instruction */
5329 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5331 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev) /* && !isBankInstruction(pcprev)*/)) {
5334 reg_bank = (reg) ? REG_BANK(reg) : 0;
5337 if (cur_bank != reg_bank) {
5338 //fprintf(stderr, "Cool! can switch banks\n");
5339 cur_bank = reg_bank;
5340 insertBankSwitch(0, pc, cur_bank);
5344 //fprintf(stderr, "Bummer can't switch banks\n");
5350 pc = pic16_findNextInstruction(pc->next);
5354 if(pcprev && cur_bank) {
5355 /* Brute force - make sure that we point to bank 0 at the
5356 * end of each flow block */
5357 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
5358 pic16_pCodeInsertAfter(pcprev, new_pc);
5360 //fprintf(stderr, "Brute force switch\n");
5365 /*-----------------------------------------------------------------*/
5366 /*int compareBankFlow - compare the banking requirements between */
5368 /*-----------------------------------------------------------------*/
5369 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5372 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5375 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5378 if(pcflow->firstBank == -1)
5382 if(pcflowLink->pcflow->firstBank == -1) {
5383 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5384 pcflowLink->pcflow->to :
5385 pcflowLink->pcflow->from);
5386 return compareBankFlow(pcflow, pctl, toORfrom);
5390 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5393 pcflowLink->bank_conflict++;
5394 pcflowLink->pcflow->FromConflicts++;
5395 pcflow->ToConflicts++;
5398 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5401 pcflowLink->bank_conflict++;
5402 pcflowLink->pcflow->ToConflicts++;
5403 pcflow->FromConflicts++;
5407 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5408 pcflowLink->pcflow->pc.seq,
5409 pcflowLink->pcflow->FromConflicts,
5410 pcflowLink->pcflow->ToConflicts);
5415 /*-----------------------------------------------------------------*/
5416 /*-----------------------------------------------------------------*/
5417 static void FixBankFlow(pBlock *pb)
5421 pCodeFlowLink *pcfl;
5423 pCode *pcflow_max_To=NULL;
5424 pCode *pcflow_max_From=NULL;
5425 int max_ToConflicts=0;
5426 int max_FromConflicts=0;
5428 //fprintf(stderr,"Fix Bank flow \n");
5429 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5433 First loop through all of the flow objects in this pcode block
5434 and fix the ones that have banking conflicts between the
5438 // fprintf(stderr, "FixBankFlow - Phase 1\n");
5440 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5442 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5444 if(!isPCFL(pcflow)) {
5445 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5449 if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank &&
5450 PCFL(pcflow)->firstBank >= 0 &&
5451 PCFL(pcflow)->lastBank >= 0 ) {
5453 int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
5454 PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
5456 FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
5457 BanksUsedFlow2(pcflow);
5462 // fprintf(stderr, "FixBankFlow - Phase 2\n");
5464 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5466 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5471 if(!isPCFL(pcflow)) {
5472 fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5476 PCFL(pcflow)->FromConflicts = 0;
5477 PCFL(pcflow)->ToConflicts = 0;
5482 //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
5483 pcfl = setFirstItem(PCFL(pcflow)->from);
5486 pc = PCODE(pcfl->pcflow);
5489 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5490 pc->print(stderr,pc);
5493 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
5496 pcfl=setNextItem(PCFL(pcflow)->from);
5499 if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
5500 //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5502 FixRegisterBankingInFlow(PCFL(pcflow),0);
5503 BanksUsedFlow2(pcflow);
5505 continue; /* Don't need to check the flow from here - it's already been fixed */
5512 pcfl = setFirstItem(PCFL(pcflow)->to);
5515 pc = PCODE(pcfl->pcflow);
5517 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5518 pc->print(stderr,pc);
5521 nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
5524 pcfl=setNextItem(PCFL(pcflow)->to);
5527 if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
5528 //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5530 FixRegisterBankingInFlow(PCFL(pcflow),0);
5531 BanksUsedFlow2(pcflow);
5536 Loop through the flow objects again and find the ones with the
5540 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5542 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5544 if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
5545 pcflow_max_To = pcflow;
5547 if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
5548 pcflow_max_From = pcflow;
5552 fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
5553 PCFL(pcflow_max_To)->pc.seq,
5554 PCFL(pcflow_max_To)->ToConflicts);
5557 fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
5558 PCFL(pcflow_max_From)->pc.seq,
5559 PCFL(pcflow_max_From)->FromConflicts);
5563 /*-----------------------------------------------------------------*/
5564 /*-----------------------------------------------------------------*/
5565 static void DumpFlow(pBlock *pb)
5569 pCodeFlowLink *pcfl;
5572 fprintf(stderr,"Dump flow \n");
5573 pb->pcHead->print(stderr, pb->pcHead);
5575 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5576 pcflow->print(stderr,pcflow);
5578 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5580 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5582 if(!isPCFL(pcflow)) {
5583 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5586 fprintf(stderr,"dumping: ");
5587 pcflow->print(stderr,pcflow);
5588 FlowStats(PCFL(pcflow));
5590 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5592 pc = PCODE(pcfl->pcflow);
5594 fprintf(stderr, " from seq %d:\n",pc->seq);
5596 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5597 pc->print(stderr,pc);
5602 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5604 pc = PCODE(pcfl->pcflow);
5606 fprintf(stderr, " to seq %d:\n",pc->seq);
5608 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5609 pc->print(stderr,pc);
5618 /*-----------------------------------------------------------------*/
5619 /*-----------------------------------------------------------------*/
5620 static int OptimizepBlock(pBlock *pb)
5625 if(!pb || !peepOptimizing)
5628 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5630 for(pc = pb->pcHead; pc; pc = pc->next)
5631 matches += pic16_pCodePeepMatchRule(pc);
5634 pc = pic16_findNextInstruction(pb->pcHead);
5642 if(pic16_pCodePeepMatchRule(pc)) {
5647 pc = pic16_findNextInstruction(pcprev->next);
5649 pc = pic16_findNextInstruction(pb->pcHead);
5651 pc = pic16_findNextInstruction(pc->next);
5655 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5660 /*-----------------------------------------------------------------*/
5661 /*-----------------------------------------------------------------*/
5662 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5666 for(pc = pcs; pc; pc = pc->next) {
5668 if((pc->type == PC_OPCODE) &&
5670 (PCI(pc)->pcop->type == PO_LABEL) &&
5671 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5679 /*-----------------------------------------------------------------*/
5680 /*-----------------------------------------------------------------*/
5681 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5688 (PCI(pc)->pcop->type == PO_LABEL)) {
5690 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5692 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5694 free(pcol->pcop.name);
5696 /* If the key is negative, then we (probably) have a label to
5697 * a function and the name is already defined */
5700 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5704 //sprintf(buffer,"_%05d_DS_",pcl->key);
5706 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5708 pcol->pcop.name = Safe_strdup(s);
5709 pcol->key = pcl->key;
5710 //pc->print(stderr,pc);
5717 /*-----------------------------------------------------------------*/
5718 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5719 /* pCode chain if they're not used. */
5720 /*-----------------------------------------------------------------*/
5721 static void pBlockRemoveUnusedLabels(pBlock *pb)
5723 pCode *pc; pCodeLabel *pcl;
5728 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5730 pBranch *pbr = PCI(pc)->label;
5731 if(pbr && pbr->next) {
5732 pCode *pcd = pb->pcHead;
5734 //fprintf(stderr, "multiple labels\n");
5735 //pc->print(stderr,pc);
5740 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5741 //fprintf(stderr,"Used by:\n");
5742 //pcd->print(stderr,pcd);
5744 exchangeLabels(PCL(pbr->pc),pcd);
5753 for(pc = pb->pcHead; pc; pc = pc->next) {
5755 if(isPCL(pc)) // pc->type == PC_LABEL)
5757 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5758 pcl = PCL(PCI(pc)->label->pc);
5761 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5763 /* This pCode is a label, so search the pBlock to see if anyone
5766 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5767 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5768 /* Couldn't find an instruction that refers to this label
5769 * So, unlink the pCode label from it's pCode chain
5770 * and destroy the label */
5771 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5773 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5774 if(pc->type == PC_LABEL) {
5775 pic16_unlinkpCode(pc);
5776 pCodeLabelDestruct(pc);
5778 unlinkpCodeFromBranch(pc, PCODE(pcl));
5779 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5790 /*-----------------------------------------------------------------*/
5791 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
5792 /* chain and put them into pBranches that are */
5793 /* associated with the appropriate pCode */
5795 /*-----------------------------------------------------------------*/
5796 void pic16_pBlockMergeLabels(pBlock *pb)
5799 pCode *pc, *pcnext=NULL;
5804 /* First, Try to remove any unused labels */
5805 //pBlockRemoveUnusedLabels(pb);
5807 /* Now loop through the pBlock and merge the labels with the opcodes */
5810 // for(pc = pb->pcHead; pc; pc = pc->next) {
5813 pCode *pcn = pc->next;
5815 if(pc->type == PC_LABEL) {
5817 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5818 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5819 if((pcnext = pic16_findNextInstruction(pc) )) {
5821 // Unlink the pCode label from it's pCode chain
5822 pic16_unlinkpCode(pc);
5824 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5825 // And link it into the instruction's pBranch labels. (Note, since
5826 // it's possible to have multiple labels associated with one instruction
5827 // we must provide a means to accomodate the additional labels. Thus
5828 // the labels are placed into the singly-linked list "label" as
5829 // opposed to being a single member of the pCodeInstruction.)
5831 //_ALLOC(pbr,sizeof(pBranch));
5832 pbr = Safe_calloc(1,sizeof(pBranch));
5836 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5839 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5841 } else if(pc->type == PC_CSOURCE) {
5843 /* merge the source line symbolic info into the next instruction */
5844 if((pcnext = pic16_findNextInstruction(pc) )) {
5846 // Unlink the pCode label from it's pCode chain
5847 pic16_unlinkpCode(pc);
5848 PCI(pcnext)->cline = PCCS(pc);
5849 //fprintf(stderr, "merging CSRC\n");
5850 //genericPrint(stderr,pcnext);
5856 pBlockRemoveUnusedLabels(pb);
5860 /*-----------------------------------------------------------------*/
5861 /*-----------------------------------------------------------------*/
5862 static int OptimizepCode(char dbName)
5864 #define MAX_PASSES 4
5873 DFPRINTF((stderr," Optimizing pCode\n"));
5877 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5878 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5879 matches += OptimizepBlock(pb);
5882 while(matches && ++passes < MAX_PASSES);
5887 /*-----------------------------------------------------------------*/
5888 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5889 /*-----------------------------------------------------------------*/
5891 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5895 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5897 if( !( (pcop->type == PO_LABEL) ||
5898 (pcop->type == PO_LITERAL) ||
5899 (pcop->type == PO_STR) ))
5900 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5908 /*-----------------------------------------------------------------*/
5909 /*-----------------------------------------------------------------*/
5910 int InstructionRegBank(pCode *pc)
5914 if( (reg = pic16_getRegFromInstruction(pc)) == NULL)
5917 return REG_BANK(reg);
5922 /*-----------------------------------------------------------------*/
5923 /*-----------------------------------------------------------------*/
5924 static void pic16_FixRegisterBanking(pBlock *pb)
5935 //pc = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5936 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5939 /* loop through all of the flow blocks with in one pblock */
5941 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
5945 /* at this point, pc should point to a PC_FLOW object */
5948 /* for each flow block, determine the register banking
5952 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
5953 // genericPrint(stderr, pc);
5955 reg = pic16_getRegFromInstruction(pc);
5958 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
5959 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
5960 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
5961 pic16_finalMapping[ reg->rIdx ].isSFR, reg->isFixed);
5966 /* the !(reg->rIdx==-1) is a temporary hack. It should be changed - VR 6-Jun-2003 */
5967 if( ( (reg && !(reg->rIdx==-1) && !isACCESS_BANK(reg) /*&& REG_BANK(reg)!=cur_bank*/ && !isBankInstruction(pc)) ||
5968 ((PCI(pc)->op != POC_CALL) /*&& (cur_bank != 0)*/ ) ) &&
5969 (!isPCI_LIT(pc)) ) {
5972 /* Examine the instruction before this one to make sure it is
5973 * not a skip type instruction */
5974 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5976 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev) /*&& !isBankInstruction(pcprev)*/)) {
5979 reg_bank = (reg) ? REG_BANK(reg) : 0;
5981 // fprintf(stderr, "%s:%d add bank = %d\n", __FUNCTION__, __LINE__, reg_bank);
5982 // pc->print(stderr, pc);
5984 // if (cur_bank != reg_bank) {
5985 cur_bank = reg_bank;
5986 insertBankSwitch(0, pc, (options.gen_banksel)?-1:cur_bank); //cur_bank);
5990 //fprintf(stderr, "Bummer can't switch banks\n");
6000 // } while(pc && !(isPCFL(pc)));
6005 if(pcprev && cur_bank) {
6007 int pos = 1; /* Assume that the bank switch instruction(s)
6008 * are inserted after this instruction */
6010 if((PCI(pcprev)->op == POC_RETLW) ||
6011 (PCI(pcprev)->op == POC_RETURN) ||
6012 (PCI(pcprev)->op == POC_RETFIE)) {
6014 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6020 /* Brute force - make sure that we point to bank 0 at the
6021 * end of each flow block */
6023 insertBankSwitch(pos, pcprev, 0);
6025 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6026 pic16_pCodeInsertAfter(pcprev, new_pc);
6029 //fprintf(stderr, "Brute force switch\n");
6038 if(reg && REG_BANK(reg)!=cur_bank) {
6039 //fprintf(stderr,"need to switch banks\n");
6040 /* Examine the instruction before this one to make sure it is
6041 * not a skip type instruction */
6042 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6043 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
6044 int b = cur_bank ^ REG_BANK(reg);
6046 cur_bank = REG_BANK(reg);
6052 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
6055 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
6056 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
6060 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
6061 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
6063 insertBankSwitch(0, pc, -1, -1);
6072 static void pBlockDestruct(pBlock *pb)
6083 /*-----------------------------------------------------------------*/
6084 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6085 /* name dbName and combine them */
6086 /* into one block */
6087 /*-----------------------------------------------------------------*/
6088 static void mergepBlocks(char dbName)
6091 pBlock *pb, *pbmerged = NULL,*pbn;
6093 pb = the_pFile->pbHead;
6095 //fprintf(stderr," merging blocks named %c\n",dbName);
6099 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6100 if( getpBlock_dbName(pb) == dbName) {
6102 //fprintf(stderr," merged block %c\n",dbName);
6107 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6108 /* pic16_addpCode2pBlock doesn't handle the tail: */
6109 pbmerged->pcTail = pb->pcTail;
6111 pb->prev->next = pbn;
6113 pbn->prev = pb->prev;
6118 //pic16_printpBlock(stderr, pbmerged);
6125 /*-----------------------------------------------------------------*/
6126 /* AnalyzeFlow - Examine the flow of the code and optimize */
6128 /* level 0 == minimal optimization */
6129 /* optimize registers that are used only by two instructions */
6130 /* level 1 == maximal optimization */
6131 /* optimize by looking at pairs of instructions that use the */
6133 /*-----------------------------------------------------------------*/
6135 static void AnalyzeFlow(int level)
6137 static int times_called=0;
6145 /* if this is not the first time this function has been called,
6146 then clean up old flow information */
6147 if(times_called++) {
6148 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6151 pic16_RegsUnMapLiveRanges();
6157 /* Phase 2 - Flow Analysis - Register Banking
6159 * In this phase, the individual flow blocks are examined
6160 * and register banking is fixed.
6164 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6165 pic16_FixRegisterBanking(pb);
6168 /* Phase 2 - Flow Analysis
6170 * In this phase, the pCode is partition into pCodeFlow
6171 * blocks. The flow blocks mark the points where a continuous
6172 * stream of instructions changes flow (e.g. because of
6173 * a call or goto or whatever).
6176 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6177 pic16_BuildFlow(pb);
6180 /* Phase 2 - Flow Analysis - linking flow blocks
6182 * In this phase, the individual flow blocks are examined
6183 * to determine their order of excution.
6186 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6189 /* Phase 3 - Flow Analysis - Flow Tree
6191 * In this phase, the individual flow blocks are examined
6192 * to determine their order of excution.
6195 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6196 pic16_BuildFlowTree(pb);
6199 /* Phase x - Flow Analysis - Used Banks
6201 * In this phase, the individual flow blocks are examined
6202 * to determine the Register Banks they use
6205 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6209 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6210 pic16_pCodeRegMapLiveRanges(pb);
6212 pic16_RemoveUnusedRegisters();
6214 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6215 pic16_pCodeRegOptimizeRegUsage(level);
6223 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6227 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6229 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6230 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6231 pcflow = pcflow->next) {
6233 FillFlow(PCFL(pcflow));
6238 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6240 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6241 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6242 pcflow = pcflow->next) {
6244 FlowStats(PCFL(pcflow));
6250 /*-----------------------------------------------------------------*/
6251 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6252 /* assigned to the registers. */
6254 /*-----------------------------------------------------------------*/
6256 void pic16_AnalyzeBanking(void)
6260 if(!pic16_picIsInitialized()) {
6261 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6262 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6263 fprintf(stderr,"support/scripts/inc2h.pl\n");
6264 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6269 /* Phase x - Flow Analysis - Used Banks
6271 * In this phase, the individual flow blocks are examined
6272 * to determine the Register Banks they use
6278 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6281 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6282 pic16_FixRegisterBanking(pb);
6286 /*-----------------------------------------------------------------*/
6287 /* buildCallTree - Look at the flow and extract all of the calls. */
6288 /*-----------------------------------------------------------------*/
6289 static set *register_usage(pBlock *pb);
6291 static void buildCallTree(void )
6302 /* Now build the call tree.
6303 First we examine all of the pCodes for functions.
6304 Keep in mind that the function boundaries coincide
6305 with pBlock boundaries.
6307 The algorithm goes something like this:
6308 We have two nested loops. The outer loop iterates
6309 through all of the pBlocks/functions. The inner
6310 loop iterates through all of the pCodes for
6311 a given pBlock. When we begin iterating through
6312 a pBlock, the variable pc_fstart, pCode of the start
6313 of a function, is cleared. We then search for pCodes
6314 of type PC_FUNCTION. When one is encountered, we
6315 initialize pc_fstart to this and at the same time
6316 associate a new pBranch object that signifies a
6317 branch entry. If a return is found, then this signifies
6318 a function exit point. We'll link the pCodes of these
6319 returns to the matching pc_fstart.
6321 When we're done, a doubly linked list of pBranches
6322 will exist. The head of this list is stored in
6323 `the_pFile', which is the meta structure for all
6324 of the pCode. Look at the pic16_printCallTree function
6325 on how the pBranches are linked together.
6328 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6329 pCode *pc_fstart=NULL;
6330 for(pc = pb->pcHead; pc; pc = pc->next) {
6332 if (PCF(pc)->fname) {
6334 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6335 //fprintf(stderr," found main \n");
6336 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6340 pbr = Safe_calloc(1,sizeof(pBranch));
6341 pbr->pc = pc_fstart = pc;
6344 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6346 // Here's a better way of doing the same:
6347 addSet(&pb->function_entries, pc);
6350 // Found an exit point in a function, e.g. return
6351 // (Note, there may be more than one return per function)
6353 pBranchLink(PCF(pc_fstart), PCF(pc));
6355 addSet(&pb->function_exits, pc);
6357 } else if(isCALL(pc)) {
6358 addSet(&pb->function_calls,pc);
6363 /* Re-allocate the registers so that there are no collisions
6364 * between local variables when one function call another */
6367 // pic16_deallocateAllRegs();
6369 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6376 /*-----------------------------------------------------------------*/
6377 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6378 /* all of the logical connections. */
6380 /* Essentially what's done here is that the pCode flow is */
6382 /*-----------------------------------------------------------------*/
6384 void pic16_AnalyzepCode(char dbName)
6395 /* Phase 1 - Register allocation and peep hole optimization
6397 * The first part of the analysis is to determine the registers
6398 * that are used in the pCode. Once that is done, the peep rules
6399 * are applied to the code. We continue to loop until no more
6400 * peep rule optimizations are found (or until we exceed the
6401 * MAX_PASSES threshold).
6403 * When done, the required registers will be determined.
6409 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6410 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6412 /* First, merge the labels with the instructions */
6413 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6414 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6416 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6417 //fprintf(stderr," analyze and merging block %c\n",dbName);
6418 pic16_pBlockMergeLabels(pb);
6421 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6426 changes = OptimizepCode(dbName);
6429 } while(changes && (i++ < MAX_PASSES));
6434 /*-----------------------------------------------------------------*/
6435 /* ispCodeFunction - returns true if *pc is the pCode of a */
6437 /*-----------------------------------------------------------------*/
6438 static bool ispCodeFunction(pCode *pc)
6441 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6447 /*-----------------------------------------------------------------*/
6448 /* findFunction - Search for a function by name (given the name) */
6449 /* in the set of all functions that are in a pBlock */
6450 /* (note - I expect this to change because I'm planning to limit */
6451 /* pBlock's to just one function declaration */
6452 /*-----------------------------------------------------------------*/
6453 static pCode *findFunction(char *fname)
6460 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6462 pc = setFirstItem(pb->function_entries);
6465 if((pc->type == PC_FUNCTION) &&
6467 (strcmp(fname, PCF(pc)->fname)==0))
6470 pc = setNextItem(pb->function_entries);
6478 static void MarkUsedRegisters(set *regset)
6483 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6484 // fprintf(stderr, "marking register = %s\t", r1->name);
6485 r2 = pic16_regWithIdx(r1->rIdx);
6486 // fprintf(stderr, "to register = %s\n", r2->name);
6492 static void pBlockStats(FILE *of, pBlock *pb)
6498 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6500 // for now just print the first element of each set
6501 pc = setFirstItem(pb->function_entries);
6503 fprintf(of,";entry: ");
6506 pc = setFirstItem(pb->function_exits);
6508 fprintf(of,";has an exit\n");
6512 pc = setFirstItem(pb->function_calls);
6514 fprintf(of,";functions called:\n");
6517 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6518 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6520 pc = setNextItem(pb->function_calls);
6524 r = setFirstItem(pb->tregisters);
6526 int n = elementsInSet(pb->tregisters);
6528 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6531 fprintf(of,"; %s\n",r->name);
6532 r = setNextItem(pb->tregisters);
6537 /*-----------------------------------------------------------------*/
6538 /*-----------------------------------------------------------------*/
6540 static void sequencepCode(void)
6546 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6548 pb->seq = GpCodeSequenceNumber+1;
6550 for( pc = pb->pcHead; pc; pc = pc->next)
6551 pc->seq = ++GpCodeSequenceNumber;
6557 /*-----------------------------------------------------------------*/
6558 /*-----------------------------------------------------------------*/
6559 static set *register_usage(pBlock *pb)
6562 set *registers=NULL;
6563 set *registersInCallPath = NULL;
6565 /* check recursion */
6567 pc = setFirstItem(pb->function_entries);
6574 if(pc->type != PC_FUNCTION)
6575 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6577 pc = setFirstItem(pb->function_calls);
6578 for( ; pc; pc = setNextItem(pb->function_calls)) {
6580 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6581 char *dest = pic16_get_op_from_instruction(PCI(pc));
6583 pcn = findFunction(dest);
6585 registersInCallPath = register_usage(pcn->pb);
6587 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6592 pBlockStats(stderr,pb); // debug
6595 // Mark the registers in this block as used.
6597 MarkUsedRegisters(pb->tregisters);
6598 if(registersInCallPath) {
6599 /* registers were used in the functions this pBlock has called */
6600 /* so now, we need to see if these collide with the ones we are */
6603 regs *r1,*r2, *newreg;
6605 DFPRINTF((stderr,"comparing registers\n"));
6607 r1 = setFirstItem(registersInCallPath);
6610 r2 = setFirstItem(pb->tregisters);
6612 while(r2 && (r1->type != REG_STK)) {
6614 if(r2->rIdx == r1->rIdx) {
6615 newreg = pic16_findFreeReg(REG_GPR);
6619 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6623 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6624 r1->rIdx, newreg->rIdx));
6625 r2->rIdx = newreg->rIdx;
6626 //if(r2->name) free(r2->name);
6628 r2->name = Safe_strdup(newreg->name);
6632 newreg->wasUsed = 1;
6634 r2 = setNextItem(pb->tregisters);
6637 r1 = setNextItem(registersInCallPath);
6640 /* Collisions have been resolved. Now free the registers in the call path */
6641 r1 = setFirstItem(registersInCallPath);
6643 if(r1->type != REG_STK) {
6644 newreg = pic16_regWithIdx(r1->rIdx);
6647 r1 = setNextItem(registersInCallPath);
6651 // MarkUsedRegisters(pb->registers);
6653 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6656 DFPRINTF((stderr,"returning regs\n"));
6658 DFPRINTF((stderr,"not returning regs\n"));
6660 DFPRINTF((stderr,"pBlock after register optim.\n"));
6661 pBlockStats(stderr,pb); // debug
6667 /*-----------------------------------------------------------------*/
6668 /* pct2 - writes the call tree to a file */
6670 /*-----------------------------------------------------------------*/
6671 static void pct2(FILE *of,pBlock *pb,int indent)
6675 // set *registersInCallPath = NULL;
6681 return; //recursion ?
6683 pc = setFirstItem(pb->function_entries);
6690 for(i=0;i<indent;i++) // Indentation
6693 if(pc->type == PC_FUNCTION)
6694 fprintf(of,"%s\n",PCF(pc)->fname);
6699 pc = setFirstItem(pb->function_calls);
6700 for( ; pc; pc = setNextItem(pb->function_calls)) {
6702 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6703 char *dest = pic16_get_op_from_instruction(PCI(pc));
6705 pcn = findFunction(dest);
6707 pct2(of,pcn->pb,indent+1);
6709 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6717 /*-----------------------------------------------------------------*/
6718 /* pic16_printCallTree - writes the call tree to a file */
6720 /*-----------------------------------------------------------------*/
6722 void pic16_printCallTree(FILE *of)
6734 fprintf(of, "\npBlock statistics\n");
6735 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6740 fprintf(of,"Call Tree\n");
6741 pbr = the_pFile->functions;
6745 if(!ispCodeFunction(pc))
6746 fprintf(of,"bug in call tree");
6749 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6751 while(pc->next && !ispCodeFunction(pc->next)) {
6753 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6754 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6762 fprintf(of,"\n**************\n\na better call tree\n");
6763 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6768 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6769 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6775 /*-----------------------------------------------------------------*/
6777 /*-----------------------------------------------------------------*/
6779 static void InlineFunction(pBlock *pb)
6787 pc = setFirstItem(pb->function_calls);
6789 for( ; pc; pc = setNextItem(pb->function_calls)) {
6792 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6798 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
6800 //fprintf(stderr,"Cool can inline:\n");
6801 //pcn->print(stderr,pcn);
6803 //fprintf(stderr,"recursive call Inline\n");
6804 InlineFunction(pcn->pb);
6805 //fprintf(stderr,"return from recursive call Inline\n");
6808 At this point, *pc points to a CALL mnemonic, and
6809 *pcn points to the function that is being called.
6811 To in-line this call, we need to remove the CALL
6812 and RETURN(s), and link the function pCode in with
6818 /* Remove the CALL */
6822 /* remove callee pBlock from the pBlock linked list */
6823 removepBlock(pcn->pb);
6831 /* Remove the Function pCode */
6832 pct = pic16_findNextInstruction(pcn->next);
6834 /* Link the function with the callee */
6835 pc->next = pcn->next;
6836 pcn->next->prev = pc;
6838 /* Convert the function name into a label */
6840 pbr = Safe_calloc(1,sizeof(pBranch));
6841 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6843 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6844 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6846 /* turn all of the return's except the last into goto's */
6847 /* check case for 2 instruction pBlocks */
6848 pce = pic16_findNextInstruction(pcn->next);
6850 pCode *pce_next = pic16_findNextInstruction(pce->next);
6852 if(pce_next == NULL) {
6853 /* found the last return */
6854 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6856 //fprintf(stderr,"found last return\n");
6857 //pce->print(stderr,pce);
6858 pce->prev->next = pc_call->next;
6859 pc_call->next->prev = pce->prev;
6860 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6870 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6876 /*-----------------------------------------------------------------*/
6878 /*-----------------------------------------------------------------*/
6880 void pic16_InlinepCode(void)
6889 if(!functionInlining)
6892 /* Loop through all of the function definitions and count the
6893 * number of times each one is called */
6894 //fprintf(stderr,"inlining %d\n",__LINE__);
6896 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6898 pc = setFirstItem(pb->function_calls);
6900 for( ; pc; pc = setNextItem(pb->function_calls)) {
6903 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6904 if(pcn && isPCF(pcn)) {
6905 PCF(pcn)->ncalled++;
6908 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6913 //fprintf(stderr,"inlining %d\n",__LINE__);
6915 /* Now, Loop through the function definitions again, but this
6916 * time inline those functions that have only been called once. */
6918 InlineFunction(the_pFile->pbHead);
6919 //fprintf(stderr,"inlining %d\n",__LINE__);
6921 for(pb = the_pFile->pbHead; pb; pb = pb->next)