1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
25 #include "common.h" // Include everything in the SDCC src directory
31 #include "pcodeflow.h"
35 #if defined(__BORLANDC__) || defined(_MSC_VER)
36 #define STRCASECMP stricmp
38 #define STRCASECMP strcasecmp
41 /****************************************************************/
42 /****************************************************************/
44 static peepCommand peepCommands[] = {
46 {NOTBITSKIP, "_NOTBITSKIP_"},
47 {BITSKIP, "_BITSKIP_"},
48 {INVERTBITSKIP, "_INVERTBITSKIP_"},
55 // Eventually this will go into device dependent files:
56 pCodeOpReg pic16_pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
61 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
63 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
65 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
66 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
67 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
68 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
69 pCodeOpReg pic16_pc_postinc1 = {{PO_FSR0, "POSTINC1"}, -1, NULL, 0, NULL};
70 pCodeOpReg pic16_pc_preinc1 = {{PO_FSR0, "PREINC1"}, -1, NULL, 0, NULL};
72 pCodeOpReg pic16_pc_plusw2 = {{PO_FSR0, "PLUSW2"}, -1, NULL, 0, NULL};
73 pCodeOpReg pic16_pc_preinc2 = {{PO_FSR0, "PREINC1"}, -1, NULL, 0, NULL};
74 pCodeOpReg pic16_pc_postdec1 = {{PO_FSR0, "POSTDEV1"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
77 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
78 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
80 static int mnemonics_initialized = 0;
83 static hTab *pic16MnemonicsHash = NULL;
84 static hTab *pic16pCodePeepCommandsHash = NULL;
86 static pFile *the_pFile = NULL;
87 static pBlock *pb_dead_pcodes = NULL;
89 /* Hardcoded flags to change the behavior of the PIC port */
90 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
91 static int functionInlining = 1; /* inline functions if nonzero */
92 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
94 int pic16_pcode_verbose = 0;
96 //static int GpCodeSequenceNumber = 1;
97 static int GpcFlowSeq = 1;
99 extern void pic16_RemoveUnusedRegisters(void);
100 extern void pic16_RegsUnMapLiveRanges(void);
101 extern void pic16_BuildFlowTree(pBlock *pb);
102 extern void pic16_pCodeRegOptimizeRegUsage(int level);
103 extern int pic16_picIsInitialized(void);
104 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
105 extern int mnem2key(char const *mnem);
107 /****************************************************************/
108 /* Forward declarations */
109 /****************************************************************/
111 void pic16_unlinkpCode(pCode *pc);
113 static void genericAnalyze(pCode *pc);
114 static void AnalyzeGOTO(pCode *pc);
115 static void AnalyzeSKIP(pCode *pc);
116 static void AnalyzeRETURN(pCode *pc);
119 static void genericDestruct(pCode *pc);
120 static void genericPrint(FILE *of,pCode *pc);
122 static void pCodePrintLabel(FILE *of, pCode *pc);
123 static void pCodePrintFunction(FILE *of, pCode *pc);
124 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
125 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
126 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
127 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
128 int pic16_pCodePeepMatchRule(pCode *pc);
129 static void pBlockStats(FILE *of, pBlock *pb);
130 static pBlock *newpBlock(void);
131 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
132 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
133 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
134 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
137 /****************************************************************/
138 /* PIC Instructions */
139 /****************************************************************/
141 pCodeInstruction pic16_pciADDWF = {
142 {PC_OPCODE, NULL, NULL, 0, NULL,
155 1,0, // dest, bit instruction
157 0, // literal operand
159 0, // fast call/return mode select bit
160 0, // second memory operand
161 0, // second literal operand
163 (PCC_W | PCC_REGISTER), // inCond
164 (PCC_REGISTER | PCC_Z), // outCond
168 pCodeInstruction pic16_pciADDFW = {
169 {PC_OPCODE, NULL, NULL, 0, NULL,
182 0,0, // dest, bit instruction
184 0, // literal operand
186 0, // fast call/return mode select bit
187 0, // second memory operand
188 0, // second literal operand
190 (PCC_W | PCC_REGISTER), // inCond
191 (PCC_W | PCC_Z), // outCond
195 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
196 {PC_OPCODE, NULL, NULL, 0, NULL,
209 1,0, // dest, bit instruction
211 0, // literal operand
213 0, // fast call/return mode select bit
214 0, // second memory operand
215 0, // second literal operand
217 (PCC_W | PCC_REGISTER | PCC_C), // inCond
218 (PCC_REGISTER | PCC_Z), // outCond
222 pCodeInstruction pic16_pciADDFWC = {
223 {PC_OPCODE, NULL, NULL, 0, NULL,
236 0,0, // dest, bit instruction
238 0, // literal operand
240 0, // fast call/return mode select bit
241 0, // second memory operand
242 0, // second literal operand
244 (PCC_W | PCC_REGISTER | PCC_C), // inCond
245 (PCC_W | PCC_Z), // outCond
249 pCodeInstruction pic16_pciADDLW = {
250 {PC_OPCODE, NULL, NULL, 0, NULL,
263 0,0, // dest, bit instruction
265 1, // literal operand
267 0, // fast call/return mode select bit
268 0, // second memory operand
269 0, // second literal operand
271 (PCC_W | PCC_LITERAL), // inCond
272 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
276 pCodeInstruction pic16_pciANDLW = {
277 {PC_OPCODE, NULL, NULL, 0, NULL,
290 0,0, // dest, bit instruction
292 1, // literal operand
294 0, // fast call/return mode select bit
295 0, // second memory operand
296 0, // second literal operand
298 (PCC_W | PCC_LITERAL), // inCond
299 (PCC_W | PCC_Z | PCC_N), // outCond
303 pCodeInstruction pic16_pciANDWF = {
304 {PC_OPCODE, NULL, NULL, 0, NULL,
317 1,0, // dest, bit instruction
319 0, // literal operand
321 0, // fast call/return mode select bit
322 0, // second memory operand
323 0, // second literal operand
325 (PCC_W | PCC_REGISTER), // inCond
326 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
330 pCodeInstruction pic16_pciANDFW = {
331 {PC_OPCODE, NULL, NULL, 0, NULL,
344 0,0, // dest, bit instruction
346 0, // literal operand
348 0, // fast call/return mode select bit
349 0, // second memory operand
350 0, // second literal operand
352 (PCC_W | PCC_REGISTER), // inCond
353 (PCC_W | PCC_Z) // outCond
356 pCodeInstruction pic16_pciBC = { // mdubuc - New
357 {PC_OPCODE, NULL, NULL, 0, NULL,
370 0,0, // dest, bit instruction
372 0, // literal operand
374 0, // fast call/return mode select bit
375 0, // second memory operand
376 0, // second literal operand
378 (PCC_REL_ADDR | PCC_C), // inCond
383 pCodeInstruction pic16_pciBCF = {
384 {PC_OPCODE, NULL, NULL, 0, NULL,
397 1,1, // dest, bit instruction
399 0, // literal operand
401 0, // fast call/return mode select bit
402 0, // second memory operand
403 0, // second literal operand
405 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
406 PCC_REGISTER, // outCond
410 pCodeInstruction pic16_pciBN = { // mdubuc - New
411 {PC_OPCODE, NULL, NULL, 0, NULL,
424 0,0, // dest, bit instruction
426 0, // literal operand
428 0, // fast call/return mode select bit
429 0, // second memory operand
430 0, // second literal operand
432 (PCC_REL_ADDR | PCC_N), // inCond
433 PCC_NONE , // outCond
437 pCodeInstruction pic16_pciBNC = { // mdubuc - New
438 {PC_OPCODE, NULL, NULL, 0, NULL,
451 0,0, // dest, bit instruction
453 0, // literal operand
455 0, // fast call/return mode select bit
456 0, // second memory operand
457 0, // second literal operand
459 (PCC_REL_ADDR | PCC_C), // inCond
460 PCC_NONE , // outCond
464 pCodeInstruction pic16_pciBNN = { // mdubuc - New
465 {PC_OPCODE, NULL, NULL, 0, NULL,
478 0,0, // dest, bit instruction
480 0, // literal operand
482 0, // fast call/return mode select bit
483 0, // second memory operand
484 0, // second literal operand
486 (PCC_REL_ADDR | PCC_N), // inCond
487 PCC_NONE , // outCond
491 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
492 {PC_OPCODE, NULL, NULL, 0, NULL,
505 0,0, // dest, bit instruction
507 0, // literal operand
509 0, // fast call/return mode select bit
510 0, // second memory operand
511 0, // second literal operand
513 (PCC_REL_ADDR | PCC_OV), // inCond
514 PCC_NONE , // outCond
518 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
519 {PC_OPCODE, NULL, NULL, 0, NULL,
532 0,0, // dest, bit instruction
534 0, // literal operand
536 0, // fast call/return mode select bit
537 0, // second memory operand
538 0, // second literal operand
540 (PCC_REL_ADDR | PCC_Z), // inCond
541 PCC_NONE , // outCond
545 pCodeInstruction pic16_pciBOV = { // mdubuc - New
546 {PC_OPCODE, NULL, NULL, 0, NULL,
559 0,0, // dest, bit instruction
561 0, // literal operand
563 0, // fast call/return mode select bit
564 0, // second memory operand
565 0, // second literal operand
567 (PCC_REL_ADDR | PCC_OV), // inCond
568 PCC_NONE , // outCond
572 pCodeInstruction pic16_pciBRA = { // mdubuc - New
573 {PC_OPCODE, NULL, NULL, 0, NULL,
586 0,0, // dest, bit instruction
588 0, // literal operand
590 0, // fast call/return mode select bit
591 0, // second memory operand
592 0, // second literal operand
594 PCC_REL_ADDR, // inCond
595 PCC_NONE , // outCond
599 pCodeInstruction pic16_pciBSF = {
600 {PC_OPCODE, NULL, NULL, 0, NULL,
613 1,1, // dest, bit instruction
615 0, // literal operand
617 0, // fast call/return mode select bit
618 0, // second memory operand
619 0, // second literal operand
621 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
622 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
626 pCodeInstruction pic16_pciBTFSC = {
627 {PC_OPCODE, NULL, NULL, 0, NULL,
640 0,1, // dest, bit instruction
642 0, // literal operand
644 0, // fast call/return mode select bit
645 0, // second memory operand
646 0, // second literal operand
648 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
649 PCC_EXAMINE_PCOP, // outCond
653 pCodeInstruction pic16_pciBTFSS = {
654 {PC_OPCODE, NULL, NULL, 0, NULL,
667 0,1, // dest, bit instruction
669 0, // literal operand
671 0, // fast call/return mode select bit
672 0, // second memory operand
673 0, // second literal operand
675 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
676 PCC_EXAMINE_PCOP, // outCond
680 pCodeInstruction pic16_pciBTG = { // mdubuc - New
681 {PC_OPCODE, NULL, NULL, 0, NULL,
694 0,1, // dest, bit instruction
696 0, // literal operand
698 0, // fast call/return mode select bit
699 0, // second memory operand
700 0, // second literal operand
702 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
703 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
707 pCodeInstruction pic16_pciBZ = { // mdubuc - New
708 {PC_OPCODE, NULL, NULL, 0, NULL,
721 0,0, // dest, bit instruction
723 0, // literal operand
725 0, // fast call/return mode select bit
726 0, // second memory operand
727 0, // second literal operand
734 pCodeInstruction pic16_pciCALL = {
735 {PC_OPCODE, NULL, NULL, 0, NULL,
748 0,0, // dest, bit instruction
750 0, // literal operand
752 1, // fast call/return mode select bit
753 0, // second memory operand
754 0, // second literal operand
757 PCC_NONE , // outCond
761 pCodeInstruction pic16_pciCOMF = {
762 {PC_OPCODE, NULL, NULL, 0, NULL,
775 1,0, // dest, bit instruction
777 0, // literal operand
779 0, // fast call/return mode select bit
780 0, // second memory operand
781 0, // second literal operand
783 PCC_REGISTER, // inCond
784 PCC_REGISTER , // outCond
788 pCodeInstruction pic16_pciCOMFW = {
789 {PC_OPCODE, NULL, NULL, 0, NULL,
802 0,0, // dest, bit instruction
804 0, // literal operand
806 0, // fast call/return mode select bit
807 0, // second memory operand
808 0, // second literal operand
810 PCC_REGISTER, // inCond
815 pCodeInstruction pic16_pciCLRF = {
816 {PC_OPCODE, NULL, NULL, 0, NULL,
829 0,0, // dest, bit instruction
831 0, // literal operand
833 0, // fast call/return mode select bit
834 0, // second memory operand
835 0, // second literal operand
837 PCC_REGISTER, // inCond
838 PCC_REGISTER , // outCond
842 pCodeInstruction pic16_pciCLRWDT = {
843 {PC_OPCODE, NULL, NULL, 0, NULL,
856 0,0, // dest, bit instruction
858 0, // literal operand
860 0, // fast call/return mode select bit
861 0, // second memory operand
862 0, // second literal operand
865 PCC_NONE , // outCond
869 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
870 {PC_OPCODE, NULL, NULL, 0, NULL,
883 0,0, // dest, bit instruction
885 0, // literal operand
887 0, // fast call/return mode select bit
888 0, // second memory operand
889 0, // second literal operand
891 (PCC_W | PCC_REGISTER), // inCond
892 PCC_NONE , // outCond
896 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
897 {PC_OPCODE, NULL, NULL, 0, NULL,
910 0,0, // dest, bit instruction
912 0, // literal operand
914 0, // fast call/return mode select bit
915 0, // second memory operand
916 0, // second literal operand
918 (PCC_W | PCC_REGISTER), // inCond
919 PCC_NONE , // outCond
923 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
924 {PC_OPCODE, NULL, NULL, 0, NULL,
937 1,0, // dest, bit instruction
939 0, // literal operand
941 0, // fast call/return mode select bit
942 0, // second memory operand
943 0, // second literal operand
945 (PCC_W | PCC_REGISTER), // inCond
946 PCC_NONE , // outCond
950 pCodeInstruction pic16_pciDAW = {
951 {PC_OPCODE, NULL, NULL, 0, NULL,
964 0,0, // dest, bit instruction
966 0, // literal operand
968 0, // fast call/return mode select bit
969 0, // second memory operand
970 0, // second literal operand
973 (PCC_W | PCC_C), // outCond
977 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
978 {PC_OPCODE, NULL, NULL, 0, NULL,
991 1,0, // dest, bit instruction
993 0, // literal operand
995 0, // fast call/return mode select bit
996 0, // second memory operand
997 0, // second literal operand
999 PCC_REGISTER, // inCond
1000 PCC_REGISTER , // outCond
1004 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1005 {PC_OPCODE, NULL, NULL, 0, NULL,
1011 NULL, // from branch
1018 0,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
1024 0, // second literal operand
1026 PCC_REGISTER, // inCond
1031 pCodeInstruction pic16_pciDECF = {
1032 {PC_OPCODE, NULL, NULL, 0, NULL,
1038 NULL, // from branch
1045 1,0, // dest, bit instruction
1046 0,0, // branch, skip
1047 0, // literal operand
1048 1, // RAM access bit
1049 0, // fast call/return mode select bit
1050 0, // second memory operand
1051 0, // second literal operand
1053 PCC_REGISTER, // inCond
1054 PCC_REGISTER , // outCond
1058 pCodeInstruction pic16_pciDECFW = {
1059 {PC_OPCODE, NULL, NULL, 0, NULL,
1065 NULL, // from branch
1072 0,0, // dest, bit instruction
1073 0,0, // branch, skip
1074 0, // literal operand
1075 1, // RAM access bit
1076 0, // fast call/return mode select bit
1077 0, // second memory operand
1078 0, // second literal operand
1080 PCC_REGISTER, // inCond
1085 pCodeInstruction pic16_pciDECFSZ = {
1086 {PC_OPCODE, NULL, NULL, 0, NULL,
1092 NULL, // from branch
1099 1,0, // dest, bit instruction
1100 1,1, // branch, skip
1101 0, // literal operand
1102 1, // RAM access bit
1103 0, // fast call/return mode select bit
1104 0, // second memory operand
1105 0, // second literal operand
1107 PCC_REGISTER, // inCond
1108 PCC_REGISTER , // outCond
1112 pCodeInstruction pic16_pciDECFSZW = {
1113 {PC_OPCODE, NULL, NULL, 0, NULL,
1119 NULL, // from branch
1126 0,0, // dest, bit instruction
1127 1,1, // branch, skip
1128 0, // literal operand
1129 1, // RAM access bit
1130 0, // fast call/return mode select bit
1131 0, // second memory operand
1132 0, // second literal operand
1134 PCC_REGISTER, // inCond
1139 pCodeInstruction pic16_pciGOTO = {
1140 {PC_OPCODE, NULL, NULL, 0, NULL,
1146 NULL, // from branch
1153 0,0, // dest, bit instruction
1154 1,0, // branch, skip
1155 0, // literal operand
1156 0, // RAM access bit
1157 0, // fast call/return mode select bit
1158 0, // second memory operand
1159 0, // second literal operand
1161 PCC_REL_ADDR, // inCond
1162 PCC_NONE , // outCond
1166 pCodeInstruction pic16_pciINCF = {
1167 {PC_OPCODE, NULL, NULL, 0, NULL,
1173 NULL, // from branch
1180 1,0, // dest, bit instruction
1181 0,0, // branch, skip
1182 0, // literal operand
1183 1, // RAM access bit
1184 0, // fast call/return mode select bit
1185 0, // second memory operand
1186 0, // second literal operand
1188 PCC_REGISTER, // inCond
1189 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1193 pCodeInstruction pic16_pciINCFW = {
1194 {PC_OPCODE, NULL, NULL, 0, NULL,
1200 NULL, // from branch
1207 0,0, // dest, bit instruction
1208 0,0, // branch, skip
1209 0, // literal operand
1210 1, // RAM access bit
1211 0, // fast call/return mode select bit
1212 0, // second memory operand
1213 0, // second literal operand
1215 PCC_REGISTER, // inCond
1220 pCodeInstruction pic16_pciINCFSZ = {
1221 {PC_OPCODE, NULL, NULL, 0, NULL,
1227 NULL, // from branch
1234 1,0, // dest, bit instruction
1235 1,1, // branch, skip
1236 0, // literal operand
1237 1, // RAM access bit
1238 0, // fast call/return mode select bit
1239 0, // second memory operand
1240 0, // second literal operand
1242 PCC_REGISTER, // inCond
1243 PCC_REGISTER , // outCond
1247 pCodeInstruction pic16_pciINCFSZW = {
1248 {PC_OPCODE, NULL, NULL, 0, NULL,
1254 NULL, // from branch
1261 0,0, // dest, bit instruction
1262 1,1, // branch, skip
1263 0, // literal operand
1264 1, // RAM access bit
1265 0, // fast call/return mode select bit
1266 0, // second memory operand
1267 0, // second literal operand
1269 PCC_REGISTER, // inCond
1274 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1275 {PC_OPCODE, NULL, NULL, 0, NULL,
1281 NULL, // from branch
1288 1,0, // dest, bit instruction
1289 1,1, // branch, skip
1290 0, // literal operand
1291 1, // RAM access bit
1292 0, // fast call/return mode select bit
1293 0, // second memory operand
1294 0, // second literal operand
1296 PCC_REGISTER, // inCond
1297 PCC_REGISTER , // outCond
1301 pCodeInstruction pic16_pciIORWF = {
1302 {PC_OPCODE, NULL, NULL, 0, NULL,
1308 NULL, // from branch
1315 1,0, // dest, bit instruction
1316 0,0, // branch, skip
1317 0, // literal operand
1318 1, // RAM access bit
1319 0, // fast call/return mode select bit
1320 0, // second memory operand
1321 0, // second literal operand
1323 (PCC_W | PCC_REGISTER), // inCond
1324 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1328 pCodeInstruction pic16_pciIORFW = {
1329 {PC_OPCODE, NULL, NULL, 0, NULL,
1335 NULL, // from branch
1342 0,0, // dest, bit instruction
1343 0,0, // branch, skip
1344 0, // literal operand
1345 1, // RAM access bit
1346 0, // fast call/return mode select bit
1347 0, // second memory operand
1348 0, // second literal operand
1350 (PCC_W | PCC_REGISTER), // inCond
1351 (PCC_W | PCC_Z | PCC_N), // outCond
1355 pCodeInstruction pic16_pciIORLW = {
1356 {PC_OPCODE, NULL, NULL, 0, NULL,
1362 NULL, // from branch
1369 0,0, // dest, bit instruction
1370 0,0, // branch, skip
1371 1, // literal operand
1372 0, // RAM access bit
1373 0, // fast call/return mode select bit
1374 0, // second memory operand
1375 0, // second literal operand
1377 (PCC_W | PCC_LITERAL), // inCond
1378 (PCC_W | PCC_Z | PCC_N), // outCond
1382 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1383 {PC_OPCODE, NULL, NULL, 0, NULL,
1389 NULL, // from branch
1396 0,0, // dest, bit instruction
1397 0,0, // branch, skip
1398 1, // literal operand
1399 0, // RAM access bit
1400 0, // fast call/return mode select bit
1401 0, // second memory operand
1402 1, // second literal operand
1404 (PCC_REGISTER | PCC_LITERAL),
1405 PCC_REGISTER, // outCond
1409 pCodeInstruction pic16_pciMOVF = {
1410 {PC_OPCODE, NULL, NULL, 0, NULL,
1416 NULL, // from branch
1423 1,0, // dest, bit instruction
1424 0,0, // branch, skip
1425 0, // literal operand
1426 1, // RAM access bit
1427 0, // fast call/return mode select bit
1428 0, // second memory operand
1429 0, // second literal operand
1431 PCC_REGISTER, // inCond
1432 (PCC_Z | PCC_N), // outCond
1436 pCodeInstruction pic16_pciMOVFW = {
1437 {PC_OPCODE, NULL, NULL, 0, NULL,
1443 NULL, // from branch
1450 0,0, // dest, bit instruction
1451 0,0, // branch, skip
1452 0, // literal operand
1453 1, // RAM access bit
1454 0, // fast call/return mode select bit
1455 0, // second memory operand
1456 0, // second literal operand
1458 PCC_REGISTER, // inCond
1459 (PCC_W | PCC_Z), // outCond
1463 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1464 {PC_OPCODE, NULL, NULL, 0, NULL,
1470 NULL, // from branch
1477 0,0, // dest, bit instruction
1478 0,0, // branch, skip
1479 0, // literal operand
1480 0, // RAM access bit
1481 0, // fast call/return mode select bit
1482 1, // second memory operand
1483 0, // second literal operand
1485 PCC_REGISTER, // inCond
1486 PCC_REGISTER2, // outCond
1490 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1491 {PC_OPCODE, NULL, NULL, 0, NULL,
1496 NULL, // from branch
1503 0,0, // dest, bit instruction
1504 0,0, // branch, skip
1505 1, // literal operand
1506 0, // RAM access bit
1507 0, // fast call/return mode select bit
1508 0, // second memory operand
1509 0, // second literal operand
1511 (PCC_NONE | PCC_LITERAL), // inCond
1512 PCC_REGISTER, // outCond - BSR
1516 pCodeInstruction pic16_pciMOVLW = {
1517 {PC_OPCODE, NULL, NULL, 0, NULL,
1522 NULL, // from branch
1529 0,0, // dest, bit instruction
1530 0,0, // branch, skip
1531 1, // literal operand
1532 0, // RAM access bit
1533 0, // fast call/return mode select bit
1534 0, // second memory operand
1535 0, // second literal operand
1537 (PCC_NONE | PCC_LITERAL), // inCond
1542 pCodeInstruction pic16_pciMOVWF = {
1543 {PC_OPCODE, NULL, NULL, 0, NULL,
1549 NULL, // from branch
1556 0,0, // dest, bit instruction
1557 0,0, // branch, skip
1558 0, // literal operand
1559 1, // RAM access bit
1560 0, // fast call/return mode select bit
1561 0, // second memory operand
1562 0, // second literal operand
1564 PCC_REGISTER, // inCond
1569 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1570 {PC_OPCODE, NULL, NULL, 0, NULL,
1575 NULL, // from branch
1582 0,0, // dest, bit instruction
1583 0,0, // branch, skip
1584 1, // literal operand
1585 0, // RAM access bit
1586 0, // fast call/return mode select bit
1587 0, // second memory operand
1588 0, // second literal operand
1590 (PCC_W | PCC_LITERAL), // inCond
1591 PCC_REGISTER, // outCond - PROD
1595 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1596 {PC_OPCODE, NULL, NULL, 0, NULL,
1601 NULL, // from branch
1608 0,0, // dest, bit instruction
1609 0,0, // branch, skip
1610 0, // literal operand
1611 1, // RAM access bit
1612 0, // fast call/return mode select bit
1613 0, // second memory operand
1614 0, // second literal operand
1616 (PCC_W | PCC_REGISTER), // inCond
1617 PCC_REGISTER, // outCond - PROD
1621 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1622 {PC_OPCODE, NULL, NULL, 0, NULL,
1627 NULL, // from branch
1634 0,0, // dest, bit instruction
1635 0,0, // branch, skip
1636 0, // literal operand
1637 1, // RAM access bit
1638 0, // fast call/return mode select bit
1639 0, // second memory operand
1640 0, // second literal operand
1642 PCC_REGISTER, // inCond
1643 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1647 pCodeInstruction pic16_pciNOP = {
1648 {PC_OPCODE, NULL, NULL, 0, NULL,
1653 NULL, // from branch
1660 0,0, // dest, bit instruction
1661 0,0, // branch, skip
1662 0, // literal operand
1663 0, // RAM access bit
1664 0, // fast call/return mode select bit
1665 0, // second memory operand
1666 0, // second literal operand
1669 PCC_NONE, // outCond
1673 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1674 {PC_OPCODE, NULL, NULL, 0, NULL,
1679 NULL, // from branch
1686 0,0, // dest, bit instruction
1687 0,0, // branch, skip
1688 0, // literal operand
1689 0, // RAM access bit
1690 0, // fast call/return mode select bit
1691 0, // second memory operand
1692 0, // second literal operand
1695 PCC_NONE , // outCond
1699 pCodeInstruction pic16_pciPUSH = {
1700 {PC_OPCODE, NULL, NULL, 0, NULL,
1705 NULL, // from branch
1712 0,0, // dest, bit instruction
1713 0,0, // branch, skip
1714 0, // literal operand
1715 0, // RAM access bit
1716 0, // fast call/return mode select bit
1717 0, // second memory operand
1718 0, // second literal operand
1721 PCC_NONE , // outCond
1725 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1726 {PC_OPCODE, NULL, NULL, 0, NULL,
1731 NULL, // from branch
1738 0,0, // dest, bit instruction
1739 0,0, // branch, skip
1740 0, // literal operand
1741 0, // RAM access bit
1742 0, // fast call/return mode select bit
1743 0, // second memory operand
1744 0, // second literal operand
1746 PCC_REL_ADDR, // inCond
1747 PCC_NONE , // outCond
1751 pCodeInstruction pic16_pciRETFIE = {
1752 {PC_OPCODE, NULL, NULL, 0, NULL,
1758 NULL, // from branch
1765 0,0, // dest, bit instruction
1766 1,0, // branch, skip
1767 0, // literal operand
1768 0, // RAM access bit
1769 1, // fast call/return mode select bit
1770 0, // second memory operand
1771 0, // second literal operand
1774 PCC_NONE, // outCond (not true... affects the GIE bit too)
1778 pCodeInstruction pic16_pciRETLW = {
1779 {PC_OPCODE, NULL, NULL, 0, NULL,
1785 NULL, // from branch
1792 0,0, // dest, bit instruction
1793 1,0, // branch, skip
1794 1, // literal operand
1795 0, // RAM access bit
1796 0, // fast call/return mode select bit
1797 0, // second memory operand
1798 0, // second literal operand
1800 PCC_LITERAL, // inCond
1805 pCodeInstruction pic16_pciRETURN = {
1806 {PC_OPCODE, NULL, NULL, 0, NULL,
1812 NULL, // from branch
1819 0,0, // dest, bit instruction
1820 1,0, // branch, skip
1821 0, // literal operand
1822 0, // RAM access bit
1823 1, // fast call/return mode select bit
1824 0, // second memory operand
1825 0, // second literal operand
1828 PCC_NONE, // outCond
1831 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1832 {PC_OPCODE, NULL, NULL, 0, NULL,
1838 NULL, // from branch
1845 1,0, // dest, bit instruction
1846 0,0, // branch, skip
1847 0, // literal operand
1848 1, // RAM access bit
1849 0, // fast call/return mode select bit
1850 0, // second memory operand
1851 0, // second literal operand
1853 (PCC_C | PCC_REGISTER), // inCond
1854 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1858 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1859 {PC_OPCODE, NULL, NULL, 0, NULL,
1865 NULL, // from branch
1872 0,0, // dest, bit instruction
1873 0,0, // branch, skip
1874 0, // literal operand
1875 1, // RAM access bit
1876 0, // fast call/return mode select bit
1877 0, // second memory operand
1878 0, // second literal operand
1880 (PCC_C | PCC_REGISTER), // inCond
1881 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1885 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1886 {PC_OPCODE, NULL, NULL, 0, NULL,
1892 NULL, // from branch
1899 1,0, // dest, bit instruction
1900 0,0, // branch, skip
1901 0, // literal operand
1902 1, // RAM access bit
1903 0, // fast call/return mode select bit
1904 0, // second memory operand
1905 0, // second literal operand
1907 PCC_REGISTER, // inCond
1908 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1911 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1912 {PC_OPCODE, NULL, NULL, 0, NULL,
1918 NULL, // from branch
1925 0,0, // dest, bit instruction
1926 0,0, // branch, skip
1927 0, // literal operand
1928 1, // RAM access bit
1929 0, // fast call/return mode select bit
1930 0, // second memory operand
1931 0, // second literal operand
1933 PCC_REGISTER, // inCond
1934 (PCC_W | PCC_Z | PCC_N), // outCond
1937 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1938 {PC_OPCODE, NULL, NULL, 0, NULL,
1944 NULL, // from branch
1951 1,0, // dest, bit instruction
1952 0,0, // branch, skip
1953 0, // literal operand
1954 1, // RAM access bit
1955 0, // fast call/return mode select bit
1956 0, // second memory operand
1957 0, // second literal operand
1959 (PCC_C | PCC_REGISTER), // inCond
1960 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1963 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1964 {PC_OPCODE, NULL, NULL, 0, NULL,
1970 NULL, // from branch
1977 0,0, // dest, bit instruction
1978 0,0, // branch, skip
1979 0, // literal operand
1980 1, // RAM access bit
1981 0, // fast call/return mode select bit
1982 0, // second memory operand
1983 0, // second literal operand
1985 (PCC_C | PCC_REGISTER), // inCond
1986 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1989 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
1990 {PC_OPCODE, NULL, NULL, 0, NULL,
1996 NULL, // from branch
2003 1,0, // dest, bit instruction
2004 0,0, // branch, skip
2005 0, // literal operand
2006 1, // RAM access bit
2007 0, // fast call/return mode select bit
2008 0, // second memory operand
2009 0, // second literal operand
2011 PCC_REGISTER, // inCond
2012 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2016 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2017 {PC_OPCODE, NULL, NULL, 0, NULL,
2023 NULL, // from branch
2030 0,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
2036 0, // second literal operand
2038 PCC_REGISTER, // inCond
2039 (PCC_W | PCC_Z | PCC_N), // outCond
2043 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2044 {PC_OPCODE, NULL, NULL, 0, NULL,
2050 NULL, // from branch
2057 0,0, // dest, bit instruction
2058 0,0, // branch, skip
2059 0, // literal operand
2060 1, // RAM access bit
2061 0, // fast call/return mode select bit
2062 0, // second memory operand
2063 0, // second literal operand
2065 PCC_REGISTER, // inCond
2066 PCC_REGISTER , // outCond
2070 pCodeInstruction pic16_pciSUBLW = {
2071 {PC_OPCODE, NULL, NULL, 0, NULL,
2077 NULL, // from branch
2084 0,0, // dest, bit instruction
2085 0,0, // branch, skip
2086 1, // literal operand
2087 0, // RAM access bit
2088 0, // fast call/return mode select bit
2089 0, // second memory operand
2090 0, // second literal operand
2092 (PCC_W | PCC_LITERAL), // inCond
2093 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2097 pCodeInstruction pic16_pciSUBFWB = {
2098 {PC_OPCODE, NULL, NULL, 0, NULL,
2104 NULL, // from branch
2111 1,0, // dest, bit instruction
2112 0,0, // branch, skip
2113 0, // literal operand
2114 1, // RAM access bit
2115 0, // fast call/return mode select bit
2116 0, // second memory operand
2117 0, // second literal operand
2119 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2120 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2124 pCodeInstruction pic16_pciSUBWF = {
2125 {PC_OPCODE, NULL, NULL, 0, NULL,
2131 NULL, // from branch
2138 1,0, // dest, bit instruction
2139 0,0, // branch, skip
2140 0, // literal operand
2141 1, // RAM access bit
2142 0, // fast call/return mode select bit
2143 0, // second memory operand
2144 0, // second literal operand
2146 (PCC_W | PCC_REGISTER), // inCond
2147 (PCC_REGISTER | PCC_Z), // outCond
2151 pCodeInstruction pic16_pciSUBFW = {
2152 {PC_OPCODE, NULL, NULL, 0, NULL,
2158 NULL, // from branch
2165 0,0, // dest, bit instruction
2166 0,0, // branch, skip
2167 0, // literal operand
2168 1, // RAM access bit
2169 0, // fast call/return mode select bit
2170 0, // second memory operand
2171 0, // second literal operand
2173 (PCC_W | PCC_REGISTER), // inCond
2174 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2178 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2179 {PC_OPCODE, NULL, NULL, 0, NULL,
2185 NULL, // from branch
2192 1,0, // dest, bit instruction
2193 0,0, // branch, skip
2194 0, // literal operand
2195 1, // RAM access bit
2196 0, // fast call/return mode select bit
2197 0, // second memory operand
2198 0, // second literal operand
2200 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2201 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2205 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2206 {PC_OPCODE, NULL, NULL, 0, NULL,
2212 NULL, // from branch
2219 0,0, // dest, bit instruction
2220 0,0, // branch, skip
2221 0, // literal operand
2222 1, // RAM access bit
2223 0, // fast call/return mode select bit
2224 0, // second memory operand
2225 0, // second literal operand
2227 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2228 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2232 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2233 {PC_OPCODE, NULL, NULL, 0, NULL,
2239 NULL, // from branch
2246 1,0, // dest, bit instruction
2247 0,0, // branch, skip
2248 0, // literal operand
2249 1, // RAM access bit
2250 0, // fast call/return mode select bit
2251 0, // second memory operand
2252 0, // second literal operand
2254 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2255 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2259 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2260 {PC_OPCODE, NULL, NULL, 0, NULL,
2266 NULL, // from branch
2273 0,0, // dest, bit instruction
2274 0,0, // branch, skip
2275 0, // literal operand
2276 1, // RAM access bit
2277 0, // fast call/return mode select bit
2278 0, // second memory operand
2279 0, // second literal operand
2281 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2282 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2286 pCodeInstruction pic16_pciSWAPF = {
2287 {PC_OPCODE, NULL, NULL, 0, NULL,
2293 NULL, // from branch
2300 1,0, // dest, bit instruction
2301 0,0, // branch, skip
2302 0, // literal operand
2303 1, // RAM access bit
2304 0, // fast call/return mode select bit
2305 0, // second memory operand
2306 0, // second literal operand
2308 (PCC_REGISTER), // inCond
2309 (PCC_REGISTER), // outCond
2313 pCodeInstruction pic16_pciSWAPFW = {
2314 {PC_OPCODE, NULL, NULL, 0, NULL,
2320 NULL, // from branch
2327 0,0, // dest, bit instruction
2328 0,0, // branch, skip
2329 0, // literal operand
2330 1, // RAM access bit
2331 0, // fast call/return mode select bit
2332 0, // second memory operand
2333 0, // second literal operand
2335 (PCC_REGISTER), // inCond
2340 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2341 {PC_OPCODE, NULL, NULL, 0, NULL,
2347 NULL, // from branch
2354 0,0, // dest, bit instruction
2355 1,1, // branch, skip
2356 0, // literal operand
2357 1, // RAM access bit
2358 0, // fast call/return mode select bit
2359 0, // second memory operand
2360 0, // second literal operand
2362 PCC_REGISTER, // inCond
2363 PCC_NONE, // outCond
2367 pCodeInstruction pic16_pciXORWF = {
2368 {PC_OPCODE, NULL, NULL, 0, NULL,
2374 NULL, // from branch
2381 1,0, // dest, bit instruction
2382 0,0, // branch, skip
2383 0, // literal operand
2384 1, // RAM access bit
2385 0, // fast call/return mode select bit
2386 0, // second memory operand
2387 0, // second literal operand
2389 (PCC_W | PCC_REGISTER), // inCond
2390 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2394 pCodeInstruction pic16_pciXORFW = {
2395 {PC_OPCODE, NULL, NULL, 0, NULL,
2401 NULL, // from branch
2408 0,0, // dest, bit instruction
2409 0,0, // branch, skip
2410 0, // literal operand
2411 1, // RAM access bit
2412 0, // fast call/return mode select bit
2413 0, // second memory operand
2414 0, // second literal operand
2416 (PCC_W | PCC_REGISTER), // inCond
2417 (PCC_W | PCC_Z | PCC_N), // outCond
2421 pCodeInstruction pic16_pciXORLW = {
2422 {PC_OPCODE, NULL, NULL, 0, NULL,
2428 NULL, // from branch
2435 0,0, // dest, bit instruction
2436 0,0, // branch, skip
2437 1, // literal operand
2438 1, // RAM access bit
2439 0, // fast call/return mode select bit
2440 0, // second memory operand
2441 0, // second literal operand
2443 (PCC_W | PCC_LITERAL), // inCond
2444 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2449 #define MAX_PIC16MNEMONICS 100
2450 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2452 //#define USE_VSNPRINTF
2455 #ifdef USE_VSNPRINTF
2456 // Alas, vsnprintf is not ANSI standard, and does not exist
2457 // on Solaris (and probably other non-Gnu flavored Unixes).
2459 /*-----------------------------------------------------------------*/
2460 /* SAFE_snprintf - like snprintf except the string pointer is */
2461 /* after the string has been printed to. This is */
2462 /* useful for printing to string as though if it */
2463 /* were a stream. */
2464 /*-----------------------------------------------------------------*/
2465 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2473 va_start(val, format);
2475 vsnprintf(*str, *size, format, val);
2481 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2482 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2491 // This version is *not* safe, despite the name.
2493 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2497 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2502 va_start(val, format);
2504 vsprintf(buffer, format, val);
2507 len = strlen(buffer);
2509 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2510 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2513 strcpy(*str, buffer);
2519 #endif // USE_VSNPRINTF
2522 extern void pic16_initStack(int base_address, int size);
2523 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2524 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2525 extern void pic16_init_pic(char *);
2527 void pic16_pCodeInitRegisters(void)
2529 static int initialized=0;
2536 pic16_initStack(0xfff, 8);
2537 pic16_init_pic(port->processor);
2539 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2540 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2541 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2542 pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80);
2543 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2544 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2545 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2547 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2548 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2549 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2550 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2551 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_FSR0, 0x80);
2552 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_FSR0, 0x80);
2553 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_FSR0, 0x80);
2555 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_FSR0, 0x80);
2556 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_FSR0, 0x80);
2558 pic16_pc_status.rIdx = IDX_STATUS;
2559 pic16_pc_fsr0.rIdx = IDX_FSR0;
2560 pic16_pc_indf0.rIdx = IDX_INDF0;
2561 pic16_pc_intcon.rIdx = IDX_INTCON;
2562 pic16_pc_pcl.rIdx = IDX_PCL;
2563 pic16_pc_pclath.rIdx = IDX_PCLATH;
2564 pic16_pc_wreg.rIdx = IDX_WREG;
2565 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2566 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2567 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2568 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2569 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2570 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2571 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2572 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2573 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2575 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2576 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
2577 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2579 pic16_pc_kzero.rIdx = IDX_KZ;
2580 pic16_pc_wsave.rIdx = IDX_WSAVE;
2581 pic16_pc_ssave.rIdx = IDX_SSAVE;
2583 /* probably should put this in a separate initialization routine */
2584 pb_dead_pcodes = newpBlock();
2589 /*-----------------------------------------------------------------*/
2590 /* mnem2key - convert a pic mnemonic into a hash key */
2591 /* (BTW - this spreads the mnemonics quite well) */
2593 /*-----------------------------------------------------------------*/
2595 int mnem2key(char const *mnem)
2604 key += toupper(*mnem++) +1;
2608 return (key & 0x1f);
2613 void pic16initMnemonics(void)
2618 pCodeInstruction *pci;
2620 if(mnemonics_initialized)
2623 // NULL out the array before making the assignments
2624 // since we check the array contents below this initialization.
2626 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2627 pic16Mnemonics[i] = NULL;
2630 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2631 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2632 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2633 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2634 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2635 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2636 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2637 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2638 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2639 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2640 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2641 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2642 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2643 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2644 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2645 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2646 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2647 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2648 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2649 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2650 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2651 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2652 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2653 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2654 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2655 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2656 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2657 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2658 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2659 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2660 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2661 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2662 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2663 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2664 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2665 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2666 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2667 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2668 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2669 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2670 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2671 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2672 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2673 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2674 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2675 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2676 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2677 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2678 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2679 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2680 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2681 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2682 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2683 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2684 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2685 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2686 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2687 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2688 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2689 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2690 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2691 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2692 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2693 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2694 pic16Mnemonics[POC_RLCF] = &pic16_pciRLNCF;
2695 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2696 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2697 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2698 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2699 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2700 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2701 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2702 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2703 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2704 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2705 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2706 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2707 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2708 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2709 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
2710 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
2711 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
2712 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
2713 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
2715 for(i=0; i<MAX_PIC16MNEMONICS; i++)
2716 if(pic16Mnemonics[i])
2717 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
2718 pci = hTabFirstItem(pic16MnemonicsHash, &key);
2721 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
2722 pci = hTabNextItem(pic16MnemonicsHash, &key);
2725 mnemonics_initialized = 1;
2728 int pic16_getpCodePeepCommand(char *cmd);
2730 int pic16_getpCode(char *mnem,unsigned dest)
2733 pCodeInstruction *pci;
2734 int key = mnem2key(mnem);
2736 if(!mnemonics_initialized)
2737 pic16initMnemonics();
2739 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
2743 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
2744 if((pci->num_ops <= 1)
2745 || (pci->isModReg == dest)
2747 || (pci->num_ops <= 2 && pci->isAccess)
2748 || (pci->num_ops <= 2 && pci->isFastCall)
2749 || (pci->num_ops <= 2 && pci->is2MemOp)
2750 || (pci->num_ops <= 2 && pci->is2LitOp) )
2754 pci = hTabNextItemWK (pic16MnemonicsHash);
2761 /*-----------------------------------------------------------------*
2762 * pic16initpCodePeepCommands
2764 *-----------------------------------------------------------------*/
2765 void pic16initpCodePeepCommands(void)
2773 hTabAddItem(&pic16pCodePeepCommandsHash,
2774 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
2776 } while (peepCommands[i].cmd);
2778 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
2781 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
2782 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
2787 /*-----------------------------------------------------------------
2790 *-----------------------------------------------------------------*/
2792 int pic16_getpCodePeepCommand(char *cmd)
2796 int key = mnem2key(cmd);
2799 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
2802 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2803 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2807 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
2814 static char getpBlock_dbName(pBlock *pb)
2820 return pb->cmemmap->dbName;
2824 void pic16_pBlockConvert2ISR(pBlock *pb)
2835 void pic16_pBlockConvert2Absolute(pBlock *pb)
2838 if(pb->cmemmap)pb->cmemmap = NULL;
2843 /*-----------------------------------------------------------------*/
2844 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
2845 /* instances to the front of the doubly linked */
2846 /* list of pBlocks */
2847 /*-----------------------------------------------------------------*/
2849 void pic16_movepBlock2Head(char dbName)
2854 /* this can happen in sources without code,
2855 * only variable definitions */
2856 if(!the_pFile)return;
2858 pb = the_pFile->pbHead;
2862 if(getpBlock_dbName(pb) == dbName) {
2863 pBlock *pbn = pb->next;
2864 pb->next = the_pFile->pbHead;
2865 the_pFile->pbHead->prev = pb;
2866 the_pFile->pbHead = pb;
2869 pb->prev->next = pbn;
2871 // If the pBlock that we just moved was the last
2872 // one in the link of all of the pBlocks, then we
2873 // need to point the tail to the block just before
2874 // the one we moved.
2875 // Note: if pb->next is NULL, then pb must have
2876 // been the last pBlock in the chain.
2879 pbn->prev = pb->prev;
2881 the_pFile->pbTail = pb->prev;
2892 void pic16_copypCode(FILE *of, char dbName)
2896 if(!of || !the_pFile)
2899 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2900 if(getpBlock_dbName(pb) == dbName) {
2901 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
2903 pic16_printpBlock(of,pb);
2908 void pic16_pcode_test(void)
2911 DFPRINTF((stderr,"pcode is alive!\n"));
2921 /* create the file name */
2922 strcpy(buffer,dstFileName);
2923 strcat(buffer,".p");
2925 if( !(pFile = fopen(buffer, "w" ))) {
2926 werror(E_FILE_OPEN_ERR,buffer);
2930 fprintf(pFile,"pcode dump\n\n");
2932 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2933 fprintf(pFile,"\n\tNew pBlock\n\n");
2935 fprintf(pFile,"%s",pb->cmemmap->sname);
2937 fprintf(pFile,"internal pblock");
2939 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2940 pic16_printpBlock(pFile,pb);
2944 /*-----------------------------------------------------------------*/
2945 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
2946 /* ister, RegCond will return the bit being referenced. */
2948 /* fixme - why not just OR in the pcop bit field */
2949 /*-----------------------------------------------------------------*/
2951 static int RegCond(pCodeOp *pcop)
2957 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
2958 switch(PCORB(pcop)->bit) {
2972 /*-----------------------------------------------------------------*/
2973 /* pic16_newpCode - create and return a newly initialized pCode */
2975 /* fixme - rename this */
2977 /* The purpose of this routine is to create a new Instruction */
2978 /* pCode. This is called by gen.c while the assembly code is being */
2982 /* PIC_OPCODE op - the assembly instruction we wish to create. */
2983 /* (note that the op is analogous to but not the */
2984 /* same thing as the opcode of the instruction.) */
2985 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
2988 /* a pointer to the new malloc'd pCode is returned. */
2992 /*-----------------------------------------------------------------*/
2993 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
2995 pCodeInstruction *pci ;
2997 if(!mnemonics_initialized)
2998 pic16initMnemonics();
3000 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3002 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3003 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3006 if(pci->inCond & PCC_EXAMINE_PCOP)
3007 pci->inCond |= RegCond(pcop);
3009 if(pci->outCond & PCC_EXAMINE_PCOP)
3010 pci->outCond |= RegCond(pcop);
3012 pci->pc.prev = pci->pc.next = NULL;
3013 return (pCode *)pci;
3016 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3022 /*-----------------------------------------------------------------*/
3023 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3025 /* Wild pcodes are used during the peep hole optimizer to serve */
3026 /* as place holders for any instruction. When a snippet of code is */
3027 /* compared to a peep hole rule, the wild card opcode will match */
3028 /* any instruction. However, the optional operand and label are */
3029 /* additional qualifiers that must also be matched before the */
3030 /* line (of assembly code) is declared matched. Note that the */
3031 /* operand may be wild too. */
3033 /* Note, a wild instruction is specified just like a wild var: */
3034 /* %4 ; A wild instruction, */
3035 /* See the peeph.def file for additional examples */
3037 /*-----------------------------------------------------------------*/
3039 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3044 pcw = Safe_calloc(1,sizeof(pCodeWild));
3046 pcw->pci.pc.type = PC_WILD;
3047 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3048 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3049 pcw->pci.pc.pb = NULL;
3051 // pcw->pci.pc.analyze = genericAnalyze;
3052 pcw->pci.pc.destruct = genericDestruct;
3053 pcw->pci.pc.print = genericPrint;
3055 pcw->id = pCodeID; // this is the 'n' in %n
3056 pcw->operand = optional_operand;
3057 pcw->label = optional_label;
3059 pcw->mustBeBitSkipInst = 0;
3060 pcw->mustNotBeBitSkipInst = 0;
3061 pcw->invertBitSkipInst = 0;
3063 return ( (pCode *)pcw);
3067 /*-----------------------------------------------------------------*/
3068 /* newPcodeInlineP - create a new pCode from a char string */
3069 /*-----------------------------------------------------------------*/
3072 pCode *pic16_newpCodeInlineP(char *cP)
3077 pcc = Safe_calloc(1,sizeof(pCodeComment));
3079 pcc->pc.type = PC_INLINE;
3080 pcc->pc.prev = pcc->pc.next = NULL;
3081 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3084 // pcc->pc.analyze = genericAnalyze;
3085 pcc->pc.destruct = genericDestruct;
3086 pcc->pc.print = genericPrint;
3089 pcc->comment = Safe_strdup(cP);
3091 pcc->comment = NULL;
3093 return ( (pCode *)pcc);
3097 /*-----------------------------------------------------------------*/
3098 /* newPcodeCharP - create a new pCode from a char string */
3099 /*-----------------------------------------------------------------*/
3101 pCode *pic16_newpCodeCharP(char *cP)
3106 pcc = Safe_calloc(1,sizeof(pCodeComment));
3108 pcc->pc.type = PC_COMMENT;
3109 pcc->pc.prev = pcc->pc.next = NULL;
3110 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3113 // pcc->pc.analyze = genericAnalyze;
3114 pcc->pc.destruct = genericDestruct;
3115 pcc->pc.print = genericPrint;
3118 pcc->comment = Safe_strdup(cP);
3120 pcc->comment = NULL;
3122 return ( (pCode *)pcc);
3126 /*-----------------------------------------------------------------*/
3127 /* pic16_newpCodeFunction - */
3128 /*-----------------------------------------------------------------*/
3131 pCode *pic16_newpCodeFunction(char *mod,char *f)
3135 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3137 pcf->pc.type = PC_FUNCTION;
3138 pcf->pc.prev = pcf->pc.next = NULL;
3139 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3142 // pcf->pc.analyze = genericAnalyze;
3143 pcf->pc.destruct = genericDestruct;
3144 pcf->pc.print = pCodePrintFunction;
3149 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3150 strcpy(pcf->modname,mod);
3152 pcf->modname = NULL;
3155 pcf->fname = Safe_calloc(1,strlen(f)+1);
3156 strcpy(pcf->fname,f);
3160 return ( (pCode *)pcf);
3164 /*-----------------------------------------------------------------*/
3165 /* pic16_newpCodeFlow */
3166 /*-----------------------------------------------------------------*/
3167 static void destructpCodeFlow(pCode *pc)
3169 if(!pc || !isPCFL(pc))
3176 pic16_unlinkpCode(pc);
3178 deleteSet(&PCFL(pc)->registers);
3179 deleteSet(&PCFL(pc)->from);
3180 deleteSet(&PCFL(pc)->to);
3185 pCode *pic16_newpCodeFlow(void )
3189 //_ALLOC(pcflow,sizeof(pCodeFlow));
3190 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3192 pcflow->pc.type = PC_FLOW;
3193 pcflow->pc.prev = pcflow->pc.next = NULL;
3194 pcflow->pc.pb = NULL;
3196 // pcflow->pc.analyze = genericAnalyze;
3197 pcflow->pc.destruct = destructpCodeFlow;
3198 pcflow->pc.print = genericPrint;
3200 pcflow->pc.seq = GpcFlowSeq++;
3202 pcflow->from = pcflow->to = NULL;
3204 pcflow->inCond = PCC_NONE;
3205 pcflow->outCond = PCC_NONE;
3207 pcflow->firstBank = -1;
3208 pcflow->lastBank = -1;
3210 pcflow->FromConflicts = 0;
3211 pcflow->ToConflicts = 0;
3215 pcflow->registers = newSet();
3217 return ( (pCode *)pcflow);
3221 /*-----------------------------------------------------------------*/
3222 /*-----------------------------------------------------------------*/
3223 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3225 pCodeFlowLink *pcflowLink;
3227 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3229 pcflowLink->pcflow = pcflow;
3230 pcflowLink->bank_conflict = 0;
3235 /*-----------------------------------------------------------------*/
3236 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3237 /*-----------------------------------------------------------------*/
3239 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3244 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3246 pccs->pc.type = PC_CSOURCE;
3247 pccs->pc.prev = pccs->pc.next = NULL;
3250 pccs->pc.destruct = genericDestruct;
3251 pccs->pc.print = genericPrint;
3253 pccs->line_number = ln;
3255 pccs->line = Safe_strdup(l);
3260 pccs->file_name = Safe_strdup(f);
3262 pccs->file_name = NULL;
3264 return ( (pCode *)pccs);
3269 /*******************************************************************/
3270 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3271 /* added by VR 6-Jun-2003 */
3272 /*******************************************************************/
3274 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3281 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3282 pcad->pc.type = PC_ASMDIR;
3283 pcad->pc.prev = pcad->pc.next = NULL;
3286 pcad->pc.destruct = genericDestruct;
3287 pcad->pc.print = genericPrint;
3289 if(asdir && *asdir) {
3291 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3293 pcad->directive = Safe_strdup( asdir );
3296 va_start(ap, argfmt);
3298 memset(buffer, 0, sizeof(buffer));
3299 if(argfmt && *argfmt)
3300 vsprintf(buffer, argfmt, ap);
3304 while(isspace(*lbp))lbp++;
3307 pcad->arg = Safe_strdup( lbp );
3309 return ((pCode *)pcad);
3312 /*-----------------------------------------------------------------*/
3313 /* pCodeLabelDestruct - free memory used by a label. */
3314 /*-----------------------------------------------------------------*/
3315 static void pCodeLabelDestruct(pCode *pc)
3321 if((pc->type == PC_LABEL) && PCL(pc)->label)
3322 free(PCL(pc)->label);
3328 pCode *pic16_newpCodeLabel(char *name, int key)
3334 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3336 pcl->pc.type = PC_LABEL;
3337 pcl->pc.prev = pcl->pc.next = NULL;
3338 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3341 // pcl->pc.analyze = genericAnalyze;
3342 pcl->pc.destruct = pCodeLabelDestruct;
3343 pcl->pc.print = pCodePrintLabel;
3349 sprintf(s,"_%05d_DS_",key);
3354 pcl->label = Safe_strdup(s);
3356 return ( (pCode *)pcl);
3361 /*-----------------------------------------------------------------*/
3362 /* newpBlock - create and return a pointer to a new pBlock */
3363 /*-----------------------------------------------------------------*/
3364 static pBlock *newpBlock(void)
3369 PpB = Safe_calloc(1,sizeof(pBlock) );
3370 PpB->next = PpB->prev = NULL;
3372 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3373 PpB->tregisters = NULL;
3375 PpB->FlowTree = NULL;
3381 /*-----------------------------------------------------------------*/
3382 /* pic16_newpCodeChain - create a new chain of pCodes */
3383 /*-----------------------------------------------------------------*
3385 * This function will create a new pBlock and the pointer to the
3386 * pCode that is passed in will be the first pCode in the block.
3387 *-----------------------------------------------------------------*/
3390 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3393 pBlock *pB = newpBlock();
3395 pB->pcHead = pB->pcTail = pc;
3402 /*-----------------------------------------------------------------*/
3403 /* pic16_newpCodeOpLabel - Create a new label given the key */
3404 /* Note, a negative key means that the label is part of wild card */
3405 /* (and hence a wild card label) used in the pCodePeep */
3406 /* optimizations). */
3407 /*-----------------------------------------------------------------*/
3409 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3412 static int label_key=-1;
3416 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3417 pcop->type = PO_LABEL;
3422 sprintf(s=buffer,"_%05d_DS_",key);
3424 s = name, key = label_key--;
3427 pcop->name = Safe_strdup(s);
3429 ((pCodeOpLabel *)pcop)->key = key;
3431 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3435 /*-----------------------------------------------------------------*/
3436 /*-----------------------------------------------------------------*/
3437 pCodeOp *pic16_newpCodeOpLit(int lit)
3443 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3444 pcop->type = PO_LITERAL;
3448 sprintf(s,"0x%02x",lit);
3450 pcop->name = Safe_strdup(s);
3453 ((pCodeOpLit *)pcop)->lit = lit;
3458 /*-----------------------------------------------------------------*/
3459 /*-----------------------------------------------------------------*/
3460 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3462 char *s = buffer, tbuf[256], *tb=tbuf;
3466 tb = pic16_get_op(arg2, NULL, 0);
3467 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3468 pcop->type = PO_LITERAL;
3472 sprintf(s,"0x%02x, %s",lit, tb);
3474 pcop->name = Safe_strdup(s);
3477 ((pCodeOpLit2 *)pcop)->lit = lit;
3478 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3483 /*-----------------------------------------------------------------*/
3484 /*-----------------------------------------------------------------*/
3485 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3489 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3490 pcop->type = PO_IMMEDIATE;
3492 regs *r = pic16_dirregWithName(name);
3493 pcop->name = Safe_strdup(name);
3497 fprintf(stderr, "%s:%d %s reg %s exists\n",__FILE__, __LINE__, __FUNCTION__, name);
3498 PCOI(pcop)->rIdx = r->rIdx;
3500 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n",
3501 // __FILE__, __LINE__, __FUNCTION__, name);
3502 PCOI(pcop)->rIdx = -1;
3504 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3509 PCOI(pcop)->index = index;
3510 PCOI(pcop)->offset = offset;
3511 PCOI(pcop)->_const = code_space;
3516 /*-----------------------------------------------------------------*/
3517 /*-----------------------------------------------------------------*/
3518 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3524 if(!pcwb || !subtype) {
3525 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3529 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3530 pcop->type = PO_WILD;
3531 sprintf(s,"%%%d",id);
3532 pcop->name = Safe_strdup(s);
3534 PCOW(pcop)->id = id;
3535 PCOW(pcop)->pcwb = pcwb;
3536 PCOW(pcop)->subtype = subtype;
3537 PCOW(pcop)->matched = NULL;
3542 /*-----------------------------------------------------------------*/
3543 /*-----------------------------------------------------------------*/
3544 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3548 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3549 pcop->type = PO_GPR_BIT;
3551 pcop->name = Safe_strdup(s);
3555 PCORB(pcop)->bit = bit;
3556 PCORB(pcop)->inBitSpace = inBitSpace;
3558 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3559 PCOR(pcop)->r = NULL;
3560 PCOR(pcop)->rIdx = 0;
3564 /*-----------------------------------------------------------------*
3565 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3567 * If rIdx >=0 then a specific register from the set of registers
3568 * will be selected. If rIdx <0, then a new register will be searched
3570 *-----------------------------------------------------------------*/
3572 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3576 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3581 PCOR(pcop)->rIdx = rIdx;
3582 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3584 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3587 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3589 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
3590 __FUNCTION__, __LINE__);
3595 pcop->type = PCOR(pcop)->r->pc_type;
3600 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3605 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3606 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1);
3607 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3608 pcop->type = PCOR(pcop)->r->pc_type;
3609 pcop->name = PCOR(pcop)->r->name;
3611 if(pic16_pcode_verbose) {
3612 fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3613 __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
3619 /*-----------------------------------------------------------------*/
3620 /*-----------------------------------------------------------------*/
3622 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3629 pcop = pic16_newpCodeOpBit(name, -1,0);
3633 pcop = pic16_newpCodeOpLit(-1);
3637 pcop = pic16_newpCodeOpLabel(NULL,-1);
3640 pcop = pic16_newpCodeOpReg(-1);
3643 case PO_GPR_REGISTER:
3645 pcop = pic16_newpCodeOpRegFromStr(name);
3647 pcop = pic16_newpCodeOpReg(-1);
3651 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3654 pcop->name = Safe_strdup(name);
3662 /*-----------------------------------------------------------------*/
3663 /*-----------------------------------------------------------------*/
3664 void pic16_pCodeConstString(char *name, char *value)
3668 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
3673 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3675 pic16_addpBlock(pb);
3677 sprintf(buffer,"; %s = %s",name,value);
3679 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3680 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3683 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3689 /*-----------------------------------------------------------------*/
3690 /*-----------------------------------------------------------------*/
3692 static void pCodeReadCodeTable(void)
3696 fprintf(stderr, " %s\n",__FUNCTION__);
3698 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3700 pic16_addpBlock(pb);
3702 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3703 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3704 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3705 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3707 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3708 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3709 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3710 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3715 /*-----------------------------------------------------------------*/
3716 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3717 /*-----------------------------------------------------------------*/
3718 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3725 /* If this is the first pcode to be added to a block that
3726 * was initialized with a NULL pcode, then go ahead and
3727 * make this pcode the head and tail */
3728 pb->pcHead = pb->pcTail = pc;
3731 pb->pcTail->next = pc;
3733 pc->prev = pb->pcTail;
3740 /*-----------------------------------------------------------------*/
3741 /* pic16_addpBlock - place a pBlock into the pFile */
3742 /*-----------------------------------------------------------------*/
3743 void pic16_addpBlock(pBlock *pb)
3745 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3748 /* First time called, we'll pass through here. */
3749 //_ALLOC(the_pFile,sizeof(pFile));
3750 the_pFile = Safe_calloc(1,sizeof(pFile));
3751 the_pFile->pbHead = the_pFile->pbTail = pb;
3752 the_pFile->functions = NULL;
3756 the_pFile->pbTail->next = pb;
3757 pb->prev = the_pFile->pbTail;
3759 the_pFile->pbTail = pb;
3762 /*-----------------------------------------------------------------*/
3763 /* removepBlock - remove a pBlock from the pFile */
3764 /*-----------------------------------------------------------------*/
3765 static void removepBlock(pBlock *pb)
3773 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3775 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3778 if(pbs == the_pFile->pbHead)
3779 the_pFile->pbHead = pbs->next;
3781 if (pbs == the_pFile->pbTail)
3782 the_pFile->pbTail = pbs->prev;
3785 pbs->next->prev = pbs->prev;
3788 pbs->prev->next = pbs->next;
3795 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3799 /*-----------------------------------------------------------------*/
3800 /* printpCode - write the contents of a pCode to a file */
3801 /*-----------------------------------------------------------------*/
3802 static void printpCode(FILE *of, pCode *pc)
3813 fprintf(of,"warning - unable to print pCode\n");
3816 /*-----------------------------------------------------------------*/
3817 /* pic16_printpBlock - write the contents of a pBlock to a file */
3818 /*-----------------------------------------------------------------*/
3819 void pic16_printpBlock(FILE *of, pBlock *pb)
3828 if(pb->dbName == 'A') {
3832 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3834 // fprintf(of, "%s\tcode\t%d"
3838 for(pc = pb->pcHead; pc; pc = pc->next) {
3839 if(isPCF(pc) && PCF(pc)->fname) {
3840 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
3841 if(pb->dbName == 'A') {
3843 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3844 if(strcmp(ab->name, PCF(pc)->fname)) {
3845 fprintf(of, "\t0X%06X", ab->address);
3855 /*-----------------------------------------------------------------*/
3857 /* pCode processing */
3861 /*-----------------------------------------------------------------*/
3863 void pic16_unlinkpCode(pCode *pc)
3869 fprintf(stderr,"Unlinking: ");
3870 printpCode(stderr, pc);
3873 pc->prev->next = pc->next;
3875 pc->next->prev = pc->prev;
3877 pc->prev = pc->next = NULL;
3881 /*-----------------------------------------------------------------*/
3882 /*-----------------------------------------------------------------*/
3884 static void genericDestruct(pCode *pc)
3887 pic16_unlinkpCode(pc);
3890 /* For instructions, tell the register (if there's one used)
3891 * that it's no longer needed */
3892 regs *reg = pic16_getRegFromInstruction(pc);
3894 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3896 if(PCI(pc)->is2MemOp) {
3897 reg = pic16_getRegFromInstruction2(pc);
3899 deleteSetItem(&(reg->reglives.usedpCodes), pc);
3903 /* Instead of deleting the memory used by this pCode, mark
3904 * the object as bad so that if there's a pointer to this pCode
3905 * dangling around somewhere then (hopefully) when the type is
3906 * checked we'll catch it.
3911 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3919 /*-----------------------------------------------------------------*/
3920 /*-----------------------------------------------------------------*/
3921 /* modifiers for constant immediate */
3922 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
3924 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3929 int use_buffer = 1; // copy the string to the passed buffer pointer
3934 use_buffer = 0; // Don't bother copying the string to the buffer.
3938 switch(pcop->type) {
3942 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3945 return PCOR(pcop)->r->name;
3948 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3951 SAFE_snprintf(&buffer,&size,"%s",r->name);
3961 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3962 if(PCOI(pcop)->index) {
3963 SAFE_snprintf(&s,&size, "%s(%s + %d)",
3964 immdmod[ PCOI(pcop)->offset ],
3968 SAFE_snprintf(&s,&size,"%s(%s)",
3969 immdmod[ PCOI(pcop)->offset ],
3973 if(PCOI(pcop)->index) {
3974 SAFE_snprintf(&s,&size, "%s(%s + %d)",
3979 SAFE_snprintf(&s,&size, "%s(%s)",
3986 if(PCOI(pcop)->_const) {
3987 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3988 if(PCOI(pcop)->index) {
3989 SAFE_snprintf(&s,&size,"%s(%s + %d)",
3990 immdmod[ PCOI(pcop)->offset ],
3994 SAFE_snprintf(&s,&size,"%s(%s)",
3995 immdmod[ PCOI(pcop)->offset ],
4000 if(PCOI(pcop)->index)
4001 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4003 SAFE_snprintf(&s,&size,"LOW(%s)",pcop->name);
4006 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4)
4007 SAFE_snprintf(&s,&size,"(%s + %d)",
4009 PCOI(pcop)->index );
4011 if(PCOI(pcop)->offset)
4012 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4014 SAFE_snprintf(&s,&size,"(%s)",pcop->name);
4023 //size = sizeof(buffer);
4024 if( PCOR(pcop)->instance) {
4025 SAFE_snprintf(&s,&size,"(%s + %d)",
4027 PCOR(pcop)->instance );
4029 //fprintf(stderr,"PO_DIR %s\n",buffer);
4031 SAFE_snprintf(&s,&size,"%s",pcop->name);
4037 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4046 return "NO operand";
4050 /*-----------------------------------------------------------------*/
4051 /* pic16_get_op2 - variant to support two memory operand commands */
4052 /*-----------------------------------------------------------------*/
4053 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4058 int use_buffer = 1; // copy the string to the passed buffer pointer
4063 use_buffer = 0; // Don't bother copying the string to the buffer.
4067 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",
4068 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4069 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4073 switch(PCOR2(pcop)->pcop2->type) {
4077 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4080 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4083 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4086 SAFE_snprintf(&buffer,&size,"%s",r->name);
4098 if(PCOI(pcop)->_const) {
4100 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4101 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4104 8 * PCOI(pcop)->offset );
4106 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4109 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
4110 SAFE_snprintf(&s,&size,"(%s + %d)",
4112 PCOI(pcop)->index );
4114 if(PCOI(pcop)->offset)
4115 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4117 SAFE_snprintf(&s,&size,"%s",pcop->name);
4126 //size = sizeof(buffer);
4127 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4128 SAFE_snprintf(&s,&size,"(%s + %d)",
4129 PCOR(PCOR2(pcop)->pcop2)->r->name,
4130 PCOR(PCOR2(pcop)->pcop2)->instance );
4132 //fprintf(stderr,"PO_DIR %s\n",buffer);
4134 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4139 if (PCOR2(pcop)->r1->name) {
4141 SAFE_snprintf(&buffer,&size,"%s",PCOR2(pcop)->r1->name);
4144 return PCOR2(pcop)->r1->name;
4152 return "NO operand";
4156 /*-----------------------------------------------------------------*/
4157 /*-----------------------------------------------------------------*/
4158 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4162 return pic16_get_op(pcc->pcop,NULL,0);
4164 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4165 * return ("ERROR Null: "__FUNCTION__);
4167 return ("ERROR Null: pic16_get_op_from_instruction");
4171 /*-----------------------------------------------------------------*/
4172 /*-----------------------------------------------------------------*/
4173 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4176 fprintf(of,"pcodeopprint- not implemented\n");
4179 /*-----------------------------------------------------------------*/
4180 /* pic16_pCode2str - convert a pCode instruction to string */
4181 /*-----------------------------------------------------------------*/
4182 static char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4188 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4189 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4190 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4198 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4200 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4202 if(PCI(pc)->is2MemOp) {
4203 SAFE_snprintf(&s,&size, "%s, %s",
4204 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4205 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4209 if(PCI(pc)->is2LitOp) {
4210 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4214 if(PCI(pc)->isBitInst) {
4215 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4216 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4217 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4218 PCI(pc)->pcop->name ,
4219 PCI(pc)->pcop->name );
4221 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4222 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4223 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4224 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4226 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4227 //PCI(pc)->pcop->t.bit );
4230 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4231 if( PCI(pc)->num_ops == 3)
4232 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4234 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4237 SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
4239 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4240 if(PCI(pc)->num_ops == 3)
4241 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4243 r = pic16_getRegFromInstruction(pc);
4244 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4245 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4247 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4256 /* assuming that comment ends with a \n */
4257 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4261 /* assuming that inline code ends with a \n */
4262 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4266 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4269 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4272 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4275 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4278 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4281 SAFE_snprintf(&s,&size,"\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4285 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4292 /*-----------------------------------------------------------------*/
4293 /* genericPrint - the contents of a pCode to a file */
4294 /*-----------------------------------------------------------------*/
4295 static void genericPrint(FILE *of, pCode *pc)
4303 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4307 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4311 // If the opcode has a label, print that first
4313 pBranch *pbl = PCI(pc)->label;
4314 while(pbl && pbl->pc) {
4315 if(pbl->pc->type == PC_LABEL)
4316 pCodePrintLabel(of, pbl->pc);
4322 genericPrint(of,PCODE(PCI(pc)->cline));
4327 pic16_pCode2str(str, 256, pc);
4329 fprintf(of,"%s",str);
4332 if(pic16_debug_verbose) {
4333 fprintf(of, "\t;key=%03x",pc->seq);
4335 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4342 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4343 if(PCW(pc)->pci.label)
4344 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4346 if(PCW(pc)->operand) {
4347 fprintf(of,";\toperand ");
4348 pCodeOpPrint(of,PCW(pc)->operand );
4353 if(pic16_debug_verbose) {
4354 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4355 if(PCFL(pc)->ancestor)
4356 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4363 fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4367 pBranch *pbl = PCAD(pc)->label;
4368 while(pbl && pbl->pc) {
4369 if(pbl->pc->type == PC_LABEL)
4370 pCodePrintLabel(of, pbl->pc);
4374 fprintf(of, "\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4379 fprintf(of,"unknown pCode type %d\n",pc->type);
4384 /*-----------------------------------------------------------------*/
4385 /* pCodePrintFunction - prints function begin/end */
4386 /*-----------------------------------------------------------------*/
4388 static void pCodePrintFunction(FILE *of, pCode *pc)
4395 if( ((pCodeFunction *)pc)->modname)
4396 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4399 if(PCF(pc)->fname) {
4400 pBranch *exits = PCF(pc)->to;
4402 fprintf(of,"%s", PCF(pc)->fname);
4404 // if(pic16_pcode_verbose)
4405 fprintf(of, "\t;Function start");
4411 exits = exits->next;
4415 if(pic16_pcode_verbose)
4416 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4419 if((PCF(pc)->from &&
4420 PCF(pc)->from->pc->type == PC_FUNCTION &&
4421 PCF(PCF(pc)->from->pc)->fname) ) {
4423 if(pic16_pcode_verbose)
4424 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4426 if(pic16_pcode_verbose)
4427 fprintf(of,"; exit point [can't find entry point]\n");
4432 /*-----------------------------------------------------------------*/
4433 /* pCodePrintLabel - prints label */
4434 /*-----------------------------------------------------------------*/
4436 static void pCodePrintLabel(FILE *of, pCode *pc)
4443 fprintf(of,"%s:\n",PCL(pc)->label);
4444 else if (PCL(pc)->key >=0)
4445 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4447 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4450 /*-----------------------------------------------------------------*/
4451 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4452 /* remove it if it is found. */
4453 /*-----------------------------------------------------------------*/
4454 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4461 if(pcl->type == PC_OPCODE)
4462 b = PCI(pcl)->label;
4464 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4469 //fprintf (stderr, "%s \n",__FUNCTION__);
4470 //pcl->print(stderr,pcl);
4471 //pc->print(stderr,pc);
4474 //fprintf (stderr, "found label\n");
4478 bprev->next = b->next; /* Not first pCode in chain */
4482 PCI(pcl)->label = b->next; /* First pCode in chain */
4485 return; /* A label can't occur more than once */
4493 /*-----------------------------------------------------------------*/
4494 /*-----------------------------------------------------------------*/
4495 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4514 /*-----------------------------------------------------------------*/
4515 /* pBranchLink - given two pcodes, this function will link them */
4516 /* together through their pBranches */
4517 /*-----------------------------------------------------------------*/
4518 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4522 // Declare a new branch object for the 'from' pCode.
4524 //_ALLOC(b,sizeof(pBranch));
4525 b = Safe_calloc(1,sizeof(pBranch));
4526 b->pc = PCODE(t); // The link to the 'to' pCode.
4529 f->to = pic16_pBranchAppend(f->to,b);
4531 // Now do the same for the 'to' pCode.
4533 //_ALLOC(b,sizeof(pBranch));
4534 b = Safe_calloc(1,sizeof(pBranch));
4538 t->from = pic16_pBranchAppend(t->from,b);
4543 /*-----------------------------------------------------------------*/
4544 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4546 /*-----------------------------------------------------------------*/
4547 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4560 /*-----------------------------------------------------------------*/
4561 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4562 /*-----------------------------------------------------------------*/
4563 static void pCodeUnlink(pCode *pc)
4568 if(!pc->prev || !pc->next) {
4569 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4573 /* first remove the pCode from the chain */
4574 pc->prev->next = pc->next;
4575 pc->next->prev = pc->prev;
4577 /* Now for the hard part... */
4579 /* Remove the branches */
4583 pc1 = pb1->pc; /* Get the pCode that branches to the
4584 * one we're unlinking */
4586 /* search for the link back to this pCode (the one we're
4588 if(pb2 = pBranchFind(pc1->to,pc)) {
4589 pb2->pc = pc->to->pc; // make the replacement
4591 /* if the pCode we're unlinking contains multiple 'to'
4592 * branches (e.g. this a skip instruction) then we need
4593 * to copy these extra branches to the chain. */
4595 pic16_pBranchAppend(pb2, pc->to->next);
4604 /*-----------------------------------------------------------------*/
4605 /*-----------------------------------------------------------------*/
4607 static void genericAnalyze(pCode *pc)
4617 // Go through the pCodes that are in pCode chain and link
4618 // them together through the pBranches. Note, the pCodes
4619 // are linked together as a contiguous stream like the
4620 // assembly source code lines. The linking here mimics this
4621 // except that comments are not linked in.
4623 pCode *npc = pc->next;
4625 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4626 pBranchLink(pc,npc);
4631 /* reached the end of the pcode chain without finding
4632 * an instruction we could link to. */
4636 fprintf(stderr,"analyze PC_FLOW\n");
4640 fprintf(stderr,,";A bad pCode is being used\n");
4646 /*-----------------------------------------------------------------*/
4647 /*-----------------------------------------------------------------*/
4648 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4652 if(pc->type == PC_LABEL) {
4653 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4656 if(pc->type == PC_OPCODE) {
4657 pbr = PCI(pc)->label;
4659 if(pbr->pc->type == PC_LABEL) {
4660 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4670 /*-----------------------------------------------------------------*/
4671 /*-----------------------------------------------------------------*/
4672 static int checkLabel(pCode *pc)
4676 if(pc && isPCI(pc)) {
4677 pbr = PCI(pc)->label;
4679 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4689 /*-----------------------------------------------------------------*/
4690 /* findLabelinpBlock - Search the pCode for a particular label */
4691 /*-----------------------------------------------------------------*/
4692 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4699 for(pc = pb->pcHead; pc; pc = pc->next)
4700 if(compareLabel(pc,pcop_label))
4706 /*-----------------------------------------------------------------*/
4707 /* findLabel - Search the pCode for a particular label */
4708 /*-----------------------------------------------------------------*/
4709 static pCode * findLabel(pCodeOpLabel *pcop_label)
4717 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4718 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4722 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4726 /*-----------------------------------------------------------------*/
4727 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4728 /* in the linked list */
4729 /*-----------------------------------------------------------------*/
4730 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4743 /*-----------------------------------------------------------------*/
4744 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4745 /* in the linked list */
4746 /*-----------------------------------------------------------------*/
4747 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4759 /*-----------------------------------------------------------------*/
4760 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4761 /* in the linked list */
4762 /*-----------------------------------------------------------------*/
4763 pCode * pic16_findNextInstruction(pCode *pci)
4768 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4772 fprintf(stderr,"pic16_findNextInstruction: ");
4773 printpCode(stderr, pc);
4778 //fprintf(stderr,"Couldn't find instruction\n");
4782 /*-----------------------------------------------------------------*/
4783 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4784 /* in the linked list */
4785 /*-----------------------------------------------------------------*/
4786 pCode * pic16_findPrevInstruction(pCode *pci)
4788 return findPrevpCode(pci, PC_OPCODE);
4791 /*-----------------------------------------------------------------*/
4792 /* findFunctionEnd - given a pCode find the end of the function */
4793 /* that contains it */
4794 /*-----------------------------------------------------------------*/
4795 static pCode * findFunctionEnd(pCode *pc)
4799 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4805 fprintf(stderr,"Couldn't find function end\n");
4810 /*-----------------------------------------------------------------*/
4811 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4812 /* instruction with which it is associated. */
4813 /*-----------------------------------------------------------------*/
4814 static void AnalyzeLabel(pCode *pc)
4823 static void AnalyzeGOTO(pCode *pc)
4826 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4830 static void AnalyzeSKIP(pCode *pc)
4833 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4834 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4838 static void AnalyzeRETURN(pCode *pc)
4841 // branch_link(pc,findFunctionEnd(pc->next));
4847 /*-----------------------------------------------------------------*/
4848 /*-----------------------------------------------------------------*/
4849 regs * pic16_getRegFromInstruction(pCode *pc)
4855 PCI(pc)->num_ops == 0 ||
4856 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4859 switch(PCI(pc)->pcop->type) {
4862 return PCOR(PCI(pc)->pcop)->r;
4864 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4868 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4869 return PCOR(PCI(pc)->pcop)->r;
4872 if(PCOI(PCI(pc)->pcop)->r)
4873 return (PCOI(PCI(pc)->pcop)->r);
4875 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4876 return pic16_dirregWithName(PCI(pc)->pcop->name);
4877 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4880 return PCOR(PCI(pc)->pcop)->r;
4883 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4884 return PCOR(PCI(pc)->pcop)->r;
4886 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4890 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4891 //genericPrint(stderr, pc);
4899 /*-------------------------------------------------------------------------------*/
4900 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
4901 /*-------------------------------------------------------------------------------*/
4902 regs * pic16_getRegFromInstruction2(pCode *pc)
4908 PCI(pc)->num_ops == 0 ||
4909 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
4914 * operands supported in MOVFF:
4921 switch(PCI(pc)->pcop->type) {
4924 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4926 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4930 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4931 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4936 if(PCOI(PCI(pc)->pcop)->r)
4937 return (PCOI(PCI(pc)->pcop)->r);
4939 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4940 return pic16_dirregWithName(PCI(pc)->pcop->name);
4941 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4946 // return PCOR2(PCI(pc)->pcop)->r;
4949 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4950 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4954 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4957 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4958 //genericPrint(stderr, pc);
4966 /*-----------------------------------------------------------------*/
4967 /*-----------------------------------------------------------------*/
4969 static void AnalyzepBlock(pBlock *pb)
4976 /* Find all of the registers used in this pBlock
4977 * by looking at each instruction and examining it's
4980 for(pc = pb->pcHead; pc; pc = pc->next) {
4982 /* Is this an instruction with operands? */
4983 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4985 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4987 /* Loop through all of the registers declared so far in
4988 this block and see if we find this one there */
4990 regs *r = setFirstItem(pb->tregisters);
4993 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4994 PCOR(PCI(pc)->pcop)->r = r;
4997 r = setNextItem(pb->tregisters);
5001 /* register wasn't found */
5002 //r = Safe_calloc(1, sizeof(regs));
5003 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5004 //addSet(&pb->tregisters, r);
5005 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5006 //PCOR(PCI(pc)->pcop)->r = r;
5007 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5009 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5012 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5013 if(PCOR(PCI(pc)->pcop)->r) {
5014 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5015 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5017 if(PCI(pc)->pcop->name)
5018 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5020 fprintf(stderr,"ERROR: NULL register\n");
5029 /*-----------------------------------------------------------------*/
5031 /*-----------------------------------------------------------------*/
5032 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5034 static void InsertpFlow(pCode *pc, pCode **pflow)
5037 PCFL(*pflow)->end = pc;
5039 if(!pc || !pc->next)
5042 *pflow = pic16_newpCodeFlow();
5043 pic16_pCodeInsertAfter(pc, *pflow);
5046 /*-----------------------------------------------------------------*/
5047 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5048 /* the flow blocks. */
5050 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5051 * point the instruction flow changes.
5053 /*-----------------------------------------------------------------*/
5054 void pic16_BuildFlow(pBlock *pb)
5057 pCode *last_pci=NULL;
5064 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5065 /* Insert a pCodeFlow object at the beginning of a pBlock */
5067 InsertpFlow(pb->pcHead, &pflow);
5069 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5070 //pflow->next = pb->pcHead; /* Make the current head the next object */
5071 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5072 //pb->pcHead = pflow; /* Make the Flow object the head */
5075 for( pc = pic16_findNextInstruction(pb->pcHead);
5077 pc=pic16_findNextInstruction(pc)) {
5080 PCI(pc)->pcflow = PCFL(pflow);
5082 //fprintf(stderr," build: ");
5083 //pflow->print(stderr,pflow);
5085 if( PCI(pc)->isSkip) {
5087 /* The two instructions immediately following this one
5088 * mark the beginning of a new flow segment */
5090 while(pc && PCI(pc)->isSkip) {
5092 PCI(pc)->pcflow = PCFL(pflow);
5096 InsertpFlow(pc, &pflow);
5097 pc=pic16_findNextInstruction(pc->next);
5105 PCI(pc)->pcflow = PCFL(pflow);
5107 InsertpFlow(pc, &pflow);
5109 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5111 InsertpFlow(pc, &pflow);
5114 } else if (checkLabel(pc)) {
5116 /* This instruction marks the beginning of a
5117 * new flow segment */
5122 /* If the previous pCode is not a flow object, then
5123 * insert a new flow object. (This check prevents
5124 * two consecutive flow objects from being insert in
5125 * the case where a skip instruction preceeds an
5126 * instruction containing a label.) */
5128 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5129 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5131 PCI(pc)->pcflow = PCFL(pflow);
5138 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5140 PCFL(pflow)->end = pb->pcTail;
5143 /*-------------------------------------------------------------------*/
5144 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5145 /* the flow blocks. */
5147 * unBuildFlow removes pCodeFlow objects from a pCode chain
5149 /*-----------------------------------------------------------------*/
5150 static void unBuildFlow(pBlock *pb)
5165 if(PCI(pc)->pcflow) {
5166 //free(PCI(pc)->pcflow);
5167 PCI(pc)->pcflow = NULL;
5170 } else if(isPCFL(pc) )
5179 /*-----------------------------------------------------------------*/
5180 /*-----------------------------------------------------------------*/
5181 static void dumpCond(int cond)
5184 static char *pcc_str[] = {
5199 int ncond = sizeof(pcc_str) / sizeof(char *);
5202 fprintf(stderr, "0x%04X\n",cond);
5204 for(i=0,j=1; i<ncond; i++, j<<=1)
5206 fprintf(stderr, " %s\n",pcc_str[i]);
5212 /*-----------------------------------------------------------------*/
5213 /*-----------------------------------------------------------------*/
5214 static void FlowStats(pCodeFlow *pcflow)
5222 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5224 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5227 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5232 fprintf(stderr, " FlowStats inCond: ");
5233 dumpCond(pcflow->inCond);
5234 fprintf(stderr, " FlowStats outCond: ");
5235 dumpCond(pcflow->outCond);
5239 /*-----------------------------------------------------------------*
5240 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5241 * if it affects the banking bits.
5243 * return: -1 == Banking bits are unaffected by this pCode.
5245 * return: > 0 == Banking bits are affected.
5247 * If the banking bits are affected, then the returned value describes
5248 * which bits are affected and how they're affected. The lower half
5249 * of the integer maps to the bits that are affected, the upper half
5250 * to whether they're set or cleared.
5252 *-----------------------------------------------------------------*/
5254 static int isBankInstruction(pCode *pc)
5262 if( PCI(pc)->op == POC_MOVLB ||
5263 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5264 bank = PCOL(pc)->lit;
5271 /*-----------------------------------------------------------------*/
5272 /*-----------------------------------------------------------------*/
5273 static void FillFlow(pCodeFlow *pcflow)
5282 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5284 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5287 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5294 isBankInstruction(pc);
5296 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5300 fprintf(stderr, " FillFlow - Bad end of flow\n");
5302 fprintf(stderr, " FillFlow - Ending flow with\n ");
5303 pc->print(stderr,pc);
5306 fprintf(stderr, " FillFlow inCond: ");
5307 dumpCond(pcflow->inCond);
5308 fprintf(stderr, " FillFlow outCond: ");
5309 dumpCond(pcflow->outCond);
5313 /*-----------------------------------------------------------------*/
5314 /*-----------------------------------------------------------------*/
5315 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5317 pCodeFlowLink *fromLink, *toLink;
5319 if(!from || !to || !to->pcflow || !from->pcflow)
5322 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5323 toLink = pic16_newpCodeFlowLink(to->pcflow);
5325 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5326 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5330 /*-----------------------------------------------------------------*
5331 * void LinkFlow(pBlock *pb)
5333 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5334 * non-branching segments. In LinkFlow, we determine the execution
5335 * order of these segments. For example, if one of the segments ends
5336 * with a skip, then we know that there are two possible flow segments
5337 * to which control may be passed.
5338 *-----------------------------------------------------------------*/
5339 static void LinkFlow(pBlock *pb)
5345 //fprintf(stderr,"linkflow \n");
5347 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5349 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5352 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5354 //fprintf(stderr," link: ");
5355 //pcflow->print(stderr,pcflow);
5357 //FillFlow(PCFL(pcflow));
5359 pc = PCFL(pcflow)->end;
5361 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5362 if(isPCI_SKIP(pc)) {
5363 //fprintf(stderr, "ends with skip\n");
5364 //pc->print(stderr,pc);
5365 pct=pic16_findNextInstruction(pc->next);
5366 LinkFlow_pCode(PCI(pc),PCI(pct));
5367 pct=pic16_findNextInstruction(pct->next);
5368 LinkFlow_pCode(PCI(pc),PCI(pct));
5372 if(isPCI_BRANCH(pc)) {
5373 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5375 //fprintf(stderr, "ends with branch\n ");
5376 //pc->print(stderr,pc);
5378 if(!(pcol && isPCOLAB(pcol))) {
5379 if((PCI(pc)->op != POC_RETLW)
5380 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5382 /* continue if label is '$' which assembler knows how to parse */
5383 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5385 pc->print(stderr,pc);
5386 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5391 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5392 LinkFlow_pCode(PCI(pc),PCI(pct));
5394 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5395 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5396 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5402 //fprintf(stderr, "ends with non-branching instruction:\n");
5403 //pc->print(stderr,pc);
5405 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5411 //fprintf(stderr, "ends with unknown\n");
5412 //pc->print(stderr,pc);
5416 //fprintf(stderr, "ends with nothing: ERROR\n");
5420 /*-----------------------------------------------------------------*/
5421 /*-----------------------------------------------------------------*/
5423 /*-----------------------------------------------------------------*/
5424 /*-----------------------------------------------------------------*/
5425 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5431 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5434 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5444 /*-----------------------------------------------------------------*/
5445 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5446 /*-----------------------------------------------------------------*/
5447 static void insertBankSwitch(int position, pCode *pc, int bsr)
5456 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5457 * insert a BANKSEL assembler directive for the symbol used by
5458 * the pCode. This will allow the linker to setup the correct
5459 * bank at linking time
5462 if(!pic16_options.gen_banksel || bsr != -1) {
5463 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5466 /* emit the BANKSEL [symbol] */
5469 /* IMPORTANT: The following code does not check if a symbol is
5470 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5472 reg = pic16_getRegFromInstruction(pc);
5474 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", reg->name);
5476 position = 0; // position is always before (sanity check!)
5480 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5481 pc->print(stderr, pc);
5485 /* insert the bank switch after this pc instruction */
5486 pCode *pcnext = pic16_findNextInstruction(pc);
5487 pic16_pCodeInsertAfter(pc, new_pc);
5492 pic16_pCodeInsertAfter(pc->prev, new_pc);
5494 /* Move the label, if there is one */
5496 if(PCI(pc)->label) {
5497 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5498 // __FILE__, __LINE__, pc, new_pc);
5499 PCAD(new_pc)->label = PCI(pc)->label;
5500 PCI(pc)->label = NULL;
5503 // fprintf(stderr, "BankSwitch has been inserted\n");
5507 /*-----------------------------------------------------------------*/
5508 /*int compareBankFlow - compare the banking requirements between */
5510 /*-----------------------------------------------------------------*/
5511 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5514 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5517 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5520 if(pcflow->firstBank == -1)
5524 if(pcflowLink->pcflow->firstBank == -1) {
5525 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5526 pcflowLink->pcflow->to :
5527 pcflowLink->pcflow->from);
5528 return compareBankFlow(pcflow, pctl, toORfrom);
5532 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5535 pcflowLink->bank_conflict++;
5536 pcflowLink->pcflow->FromConflicts++;
5537 pcflow->ToConflicts++;
5540 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5543 pcflowLink->bank_conflict++;
5544 pcflowLink->pcflow->ToConflicts++;
5545 pcflow->FromConflicts++;
5549 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5550 pcflowLink->pcflow->pc.seq,
5551 pcflowLink->pcflow->FromConflicts,
5552 pcflowLink->pcflow->ToConflicts);
5559 /*-----------------------------------------------------------------*/
5560 /*-----------------------------------------------------------------*/
5561 static void DumpFlow(pBlock *pb)
5565 pCodeFlowLink *pcfl;
5568 fprintf(stderr,"Dump flow \n");
5569 pb->pcHead->print(stderr, pb->pcHead);
5571 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5572 pcflow->print(stderr,pcflow);
5574 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5576 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5578 if(!isPCFL(pcflow)) {
5579 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5582 fprintf(stderr,"dumping: ");
5583 pcflow->print(stderr,pcflow);
5584 FlowStats(PCFL(pcflow));
5586 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5588 pc = PCODE(pcfl->pcflow);
5590 fprintf(stderr, " from seq %d:\n",pc->seq);
5592 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5593 pc->print(stderr,pc);
5598 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5600 pc = PCODE(pcfl->pcflow);
5602 fprintf(stderr, " to seq %d:\n",pc->seq);
5604 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5605 pc->print(stderr,pc);
5614 /*-----------------------------------------------------------------*/
5615 /*-----------------------------------------------------------------*/
5616 static int OptimizepBlock(pBlock *pb)
5621 if(!pb || !peepOptimizing)
5624 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5626 for(pc = pb->pcHead; pc; pc = pc->next)
5627 matches += pic16_pCodePeepMatchRule(pc);
5630 pc = pic16_findNextInstruction(pb->pcHead);
5638 if(pic16_pCodePeepMatchRule(pc)) {
5643 pc = pic16_findNextInstruction(pcprev->next);
5645 pc = pic16_findNextInstruction(pb->pcHead);
5647 pc = pic16_findNextInstruction(pc->next);
5651 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5656 /*-----------------------------------------------------------------*/
5657 /*-----------------------------------------------------------------*/
5658 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5662 for(pc = pcs; pc; pc = pc->next) {
5664 if((pc->type == PC_OPCODE) &&
5666 (PCI(pc)->pcop->type == PO_LABEL) &&
5667 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5675 /*-----------------------------------------------------------------*/
5676 /*-----------------------------------------------------------------*/
5677 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5684 (PCI(pc)->pcop->type == PO_LABEL)) {
5686 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5688 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5690 free(pcol->pcop.name);
5692 /* If the key is negative, then we (probably) have a label to
5693 * a function and the name is already defined */
5696 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5700 //sprintf(buffer,"_%05d_DS_",pcl->key);
5702 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5704 pcol->pcop.name = Safe_strdup(s);
5705 pcol->key = pcl->key;
5706 //pc->print(stderr,pc);
5713 /*-----------------------------------------------------------------*/
5714 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5715 /* pCode chain if they're not used. */
5716 /*-----------------------------------------------------------------*/
5717 static void pBlockRemoveUnusedLabels(pBlock *pb)
5719 pCode *pc; pCodeLabel *pcl;
5724 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5726 pBranch *pbr = PCI(pc)->label;
5727 if(pbr && pbr->next) {
5728 pCode *pcd = pb->pcHead;
5730 //fprintf(stderr, "multiple labels\n");
5731 //pc->print(stderr,pc);
5736 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5737 //fprintf(stderr,"Used by:\n");
5738 //pcd->print(stderr,pcd);
5740 exchangeLabels(PCL(pbr->pc),pcd);
5749 for(pc = pb->pcHead; pc; pc = pc->next) {
5751 if(isPCL(pc)) // pc->type == PC_LABEL)
5753 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5754 pcl = PCL(PCI(pc)->label->pc);
5757 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5759 /* This pCode is a label, so search the pBlock to see if anyone
5762 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5763 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5764 /* Couldn't find an instruction that refers to this label
5765 * So, unlink the pCode label from it's pCode chain
5766 * and destroy the label */
5767 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5769 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5770 if(pc->type == PC_LABEL) {
5771 pic16_unlinkpCode(pc);
5772 pCodeLabelDestruct(pc);
5774 unlinkpCodeFromBranch(pc, PCODE(pcl));
5775 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5786 /*-----------------------------------------------------------------*/
5787 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
5788 /* chain and put them into pBranches that are */
5789 /* associated with the appropriate pCode */
5791 /*-----------------------------------------------------------------*/
5792 void pic16_pBlockMergeLabels(pBlock *pb)
5795 pCode *pc, *pcnext=NULL;
5800 /* First, Try to remove any unused labels */
5801 //pBlockRemoveUnusedLabels(pb);
5803 /* Now loop through the pBlock and merge the labels with the opcodes */
5806 // for(pc = pb->pcHead; pc; pc = pc->next) {
5809 pCode *pcn = pc->next;
5811 if(pc->type == PC_LABEL) {
5813 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5814 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5816 if((pcnext = pic16_findNextInstruction(pc) )) {
5818 // Unlink the pCode label from it's pCode chain
5819 pic16_unlinkpCode(pc);
5821 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5822 // And link it into the instruction's pBranch labels. (Note, since
5823 // it's possible to have multiple labels associated with one instruction
5824 // we must provide a means to accomodate the additional labels. Thus
5825 // the labels are placed into the singly-linked list "label" as
5826 // opposed to being a single member of the pCodeInstruction.)
5828 //_ALLOC(pbr,sizeof(pBranch));
5830 pbr = Safe_calloc(1,sizeof(pBranch));
5834 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5837 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5839 } else if(pc->type == PC_CSOURCE) {
5841 /* merge the source line symbolic info into the next instruction */
5842 if((pcnext = pic16_findNextInstruction(pc) )) {
5844 // Unlink the pCode label from it's pCode chain
5845 pic16_unlinkpCode(pc);
5846 PCI(pcnext)->cline = PCCS(pc);
5847 //fprintf(stderr, "merging CSRC\n");
5848 //genericPrint(stderr,pcnext);
5854 pBlockRemoveUnusedLabels(pb);
5858 /*-----------------------------------------------------------------*/
5859 /*-----------------------------------------------------------------*/
5860 static int OptimizepCode(char dbName)
5862 #define MAX_PASSES 4
5871 DFPRINTF((stderr," Optimizing pCode\n"));
5875 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5876 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5877 matches += OptimizepBlock(pb);
5880 while(matches && ++passes < MAX_PASSES);
5885 /*-----------------------------------------------------------------*/
5886 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5887 /*-----------------------------------------------------------------*/
5889 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5893 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5895 if( !( (pcop->type == PO_LABEL) ||
5896 (pcop->type == PO_LITERAL) ||
5897 (pcop->type == PO_STR) ))
5898 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5899 PCOR(pcop)->r->wasUsed = 1;
5905 /*----------------------------------------------------------------------*
5906 * pic16_areRegsSame - check to see if the names of two registers match *
5907 *----------------------------------------------------------------------*/
5908 int pic16_areRegsSame(regs *r1, regs *r2)
5910 if(!strcmp(r1->name, r2->name))return 1;
5916 /*-----------------------------------------------------------------*/
5917 /*-----------------------------------------------------------------*/
5918 static void pic16_FixRegisterBanking(pBlock *pb)
5922 regs *reg, *prevreg;
5927 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5931 /* loop through all of the flow blocks with in one pblock */
5933 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
5937 /* at this point, pc should point to a PC_FLOW object */
5938 /* for each flow block, determine the register banking
5941 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
5942 reg = pic16_getRegFromInstruction(pc);
5945 fprintf(stderr, "reg = %p\n", reg);
5947 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
5948 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
5949 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
5950 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
5954 /* we can be 99% that within a pBlock, between two consequtive
5955 * refernces to the same register, the extra banksel is needless */
5957 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
5959 && (PCI(pc)->op != POC_CALL)
5961 && ( ((pic16_options.opt_banksel>0)
5962 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
5963 || (!pic16_options.opt_banksel)
5967 /* Examine the instruction before this one to make sure it is
5968 * not a skip type instruction */
5969 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5971 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
5972 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
5973 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5975 insertBankSwitch(0, pc, (pic16_options.gen_banksel)?-1:0);
5987 if(pcprev && cur_bank) {
5989 int pos = 1; /* Assume that the bank switch instruction(s)
5990 * are inserted after this instruction */
5992 if((PCI(pcprev)->op == POC_RETLW) ||
5993 (PCI(pcprev)->op == POC_RETURN) ||
5994 (PCI(pcprev)->op == POC_RETFIE)) {
5996 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6002 /* Brute force - make sure that we point to bank 0 at the
6003 * end of each flow block */
6005 // insertBankSwitch(pos, pcprev, 0);
6007 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6008 pic16_pCodeInsertAfter(pcprev, new_pc);
6011 //fprintf(stderr, "Brute force switch\n");
6018 static void pBlockDestruct(pBlock *pb)
6029 /*-----------------------------------------------------------------*/
6030 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6031 /* name dbName and combine them */
6032 /* into one block */
6033 /*-----------------------------------------------------------------*/
6034 static void mergepBlocks(char dbName)
6037 pBlock *pb, *pbmerged = NULL,*pbn;
6039 pb = the_pFile->pbHead;
6041 //fprintf(stderr," merging blocks named %c\n",dbName);
6045 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6046 if( getpBlock_dbName(pb) == dbName) {
6048 //fprintf(stderr," merged block %c\n",dbName);
6053 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6054 /* pic16_addpCode2pBlock doesn't handle the tail: */
6055 pbmerged->pcTail = pb->pcTail;
6057 pb->prev->next = pbn;
6059 pbn->prev = pb->prev;
6064 //pic16_printpBlock(stderr, pbmerged);
6071 /*-----------------------------------------------------------------*/
6072 /* AnalyzeFlow - Examine the flow of the code and optimize */
6074 /* level 0 == minimal optimization */
6075 /* optimize registers that are used only by two instructions */
6076 /* level 1 == maximal optimization */
6077 /* optimize by looking at pairs of instructions that use the */
6079 /*-----------------------------------------------------------------*/
6081 static void AnalyzeFlow(int level)
6083 static int times_called=0;
6088 /* remove unused allocated registers before exiting */
6089 pic16_RemoveUnusedRegisters();
6095 /* if this is not the first time this function has been called,
6096 then clean up old flow information */
6097 if(times_called++) {
6098 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6101 pic16_RegsUnMapLiveRanges();
6106 /* Phase 2 - Flow Analysis - Register Banking
6108 * In this phase, the individual flow blocks are examined
6109 * and register banking is fixed.
6113 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6114 pic16_FixRegisterBanking(pb);
6117 /* Phase 2 - Flow Analysis
6119 * In this phase, the pCode is partition into pCodeFlow
6120 * blocks. The flow blocks mark the points where a continuous
6121 * stream of instructions changes flow (e.g. because of
6122 * a call or goto or whatever).
6125 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6126 pic16_BuildFlow(pb);
6129 /* Phase 2 - Flow Analysis - linking flow blocks
6131 * In this phase, the individual flow blocks are examined
6132 * to determine their order of excution.
6135 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6138 /* Phase 3 - Flow Analysis - Flow Tree
6140 * In this phase, the individual flow blocks are examined
6141 * to determine their order of execution.
6144 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6145 pic16_BuildFlowTree(pb);
6148 /* Phase x - Flow Analysis - Used Banks
6150 * In this phase, the individual flow blocks are examined
6151 * to determine the Register Banks they use
6155 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6160 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6161 pic16_pCodeRegMapLiveRanges(pb);
6163 pic16_RemoveUnusedRegisters();
6165 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6166 pic16_pCodeRegOptimizeRegUsage(level);
6174 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6179 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6181 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6182 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6183 pcflow = pcflow->next) {
6185 FillFlow(PCFL(pcflow));
6190 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6193 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6194 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6195 pcflow = pcflow->next) {
6197 FlowStats(PCFL(pcflow));
6203 /* VR -- no need to analyze banking in flow, but left here :
6204 * 1. because it may be used in the future for other purposes
6205 * 2. because if omitted we'll miss some optimization done here
6207 * Perhaps I should rename it to something else
6210 /*-----------------------------------------------------------------*/
6211 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6212 /* assigned to the registers. */
6214 /*-----------------------------------------------------------------*/
6216 void pic16_AnalyzeBanking(void)
6220 if(!pic16_picIsInitialized()) {
6221 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6222 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6223 fprintf(stderr,"support/scripts/inc2h.pl\n");
6224 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6226 /* I think it took a long long time to fix this bug! ;-) -- VR */
6232 /* Phase x - Flow Analysis - Used Banks
6234 * In this phase, the individual flow blocks are examined
6235 * to determine the Register Banks they use
6241 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6242 // BanksUsedFlow(pb);
6244 if(!the_pFile)return;
6246 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6247 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6248 pic16_FixRegisterBanking(pb);
6253 /*-----------------------------------------------------------------*/
6254 /* buildCallTree - Look at the flow and extract all of the calls. */
6255 /*-----------------------------------------------------------------*/
6256 static set *register_usage(pBlock *pb);
6258 static void buildCallTree(void )
6269 /* Now build the call tree.
6270 First we examine all of the pCodes for functions.
6271 Keep in mind that the function boundaries coincide
6272 with pBlock boundaries.
6274 The algorithm goes something like this:
6275 We have two nested loops. The outer loop iterates
6276 through all of the pBlocks/functions. The inner
6277 loop iterates through all of the pCodes for
6278 a given pBlock. When we begin iterating through
6279 a pBlock, the variable pc_fstart, pCode of the start
6280 of a function, is cleared. We then search for pCodes
6281 of type PC_FUNCTION. When one is encountered, we
6282 initialize pc_fstart to this and at the same time
6283 associate a new pBranch object that signifies a
6284 branch entry. If a return is found, then this signifies
6285 a function exit point. We'll link the pCodes of these
6286 returns to the matching pc_fstart.
6288 When we're done, a doubly linked list of pBranches
6289 will exist. The head of this list is stored in
6290 `the_pFile', which is the meta structure for all
6291 of the pCode. Look at the pic16_printCallTree function
6292 on how the pBranches are linked together.
6295 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6296 pCode *pc_fstart=NULL;
6297 for(pc = pb->pcHead; pc; pc = pc->next) {
6299 if (PCF(pc)->fname) {
6301 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6302 //fprintf(stderr," found main \n");
6303 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6307 pbr = Safe_calloc(1,sizeof(pBranch));
6308 pbr->pc = pc_fstart = pc;
6311 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6313 // Here's a better way of doing the same:
6314 addSet(&pb->function_entries, pc);
6317 // Found an exit point in a function, e.g. return
6318 // (Note, there may be more than one return per function)
6320 pBranchLink(PCF(pc_fstart), PCF(pc));
6322 addSet(&pb->function_exits, pc);
6324 } else if(isCALL(pc)) {
6325 addSet(&pb->function_calls,pc);
6330 /* Re-allocate the registers so that there are no collisions
6331 * between local variables when one function call another */
6334 // pic16_deallocateAllRegs();
6336 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6343 /*-----------------------------------------------------------------*/
6344 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6345 /* all of the logical connections. */
6347 /* Essentially what's done here is that the pCode flow is */
6349 /*-----------------------------------------------------------------*/
6351 void pic16_AnalyzepCode(char dbName)
6362 /* Phase 1 - Register allocation and peep hole optimization
6364 * The first part of the analysis is to determine the registers
6365 * that are used in the pCode. Once that is done, the peep rules
6366 * are applied to the code. We continue to loop until no more
6367 * peep rule optimizations are found (or until we exceed the
6368 * MAX_PASSES threshold).
6370 * When done, the required registers will be determined.
6376 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6377 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6379 /* First, merge the labels with the instructions */
6380 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6381 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6383 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6384 //fprintf(stderr," analyze and merging block %c\n",dbName);
6385 pic16_pBlockMergeLabels(pb);
6388 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6393 changes = OptimizepCode(dbName);
6396 } while(changes && (i++ < MAX_PASSES));
6401 /*-----------------------------------------------------------------*/
6402 /* ispCodeFunction - returns true if *pc is the pCode of a */
6404 /*-----------------------------------------------------------------*/
6405 static bool ispCodeFunction(pCode *pc)
6408 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6414 /*-----------------------------------------------------------------*/
6415 /* findFunction - Search for a function by name (given the name) */
6416 /* in the set of all functions that are in a pBlock */
6417 /* (note - I expect this to change because I'm planning to limit */
6418 /* pBlock's to just one function declaration */
6419 /*-----------------------------------------------------------------*/
6420 static pCode *findFunction(char *fname)
6427 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6429 pc = setFirstItem(pb->function_entries);
6432 if((pc->type == PC_FUNCTION) &&
6434 (strcmp(fname, PCF(pc)->fname)==0))
6437 pc = setNextItem(pb->function_entries);
6445 static void MarkUsedRegisters(set *regset)
6450 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6451 // fprintf(stderr, "marking register = %s\t", r1->name);
6452 r2 = pic16_regWithIdx(r1->rIdx);
6453 // fprintf(stderr, "to register = %s\n", r2->name);
6459 static void pBlockStats(FILE *of, pBlock *pb)
6465 if(!pic16_pcode_verbose)return;
6467 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6469 // for now just print the first element of each set
6470 pc = setFirstItem(pb->function_entries);
6472 fprintf(of,";entry: ");
6475 pc = setFirstItem(pb->function_exits);
6477 fprintf(of,";has an exit\n");
6481 pc = setFirstItem(pb->function_calls);
6483 fprintf(of,";functions called:\n");
6486 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6487 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6489 pc = setNextItem(pb->function_calls);
6493 r = setFirstItem(pb->tregisters);
6495 int n = elementsInSet(pb->tregisters);
6497 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6500 fprintf(of,"; %s\n",r->name);
6501 r = setNextItem(pb->tregisters);
6506 /*-----------------------------------------------------------------*/
6507 /*-----------------------------------------------------------------*/
6509 static void sequencepCode(void)
6515 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6517 pb->seq = GpCodeSequenceNumber+1;
6519 for( pc = pb->pcHead; pc; pc = pc->next)
6520 pc->seq = ++GpCodeSequenceNumber;
6526 /*-----------------------------------------------------------------*/
6527 /*-----------------------------------------------------------------*/
6528 static set *register_usage(pBlock *pb)
6531 set *registers=NULL;
6532 set *registersInCallPath = NULL;
6534 /* check recursion */
6536 pc = setFirstItem(pb->function_entries);
6543 if(pc->type != PC_FUNCTION)
6544 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6546 pc = setFirstItem(pb->function_calls);
6547 for( ; pc; pc = setNextItem(pb->function_calls)) {
6549 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6550 char *dest = pic16_get_op_from_instruction(PCI(pc));
6552 pcn = findFunction(dest);
6554 registersInCallPath = register_usage(pcn->pb);
6556 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6561 pBlockStats(stderr,pb); // debug
6564 // Mark the registers in this block as used.
6566 MarkUsedRegisters(pb->tregisters);
6567 if(registersInCallPath) {
6568 /* registers were used in the functions this pBlock has called */
6569 /* so now, we need to see if these collide with the ones we are */
6572 regs *r1,*r2, *newreg;
6574 DFPRINTF((stderr,"comparing registers\n"));
6576 r1 = setFirstItem(registersInCallPath);
6579 r2 = setFirstItem(pb->tregisters);
6581 while(r2 && (r1->type != REG_STK)) {
6583 if(r2->rIdx == r1->rIdx) {
6584 newreg = pic16_findFreeReg(REG_GPR);
6588 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6592 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6593 r1->rIdx, newreg->rIdx));
6594 r2->rIdx = newreg->rIdx;
6595 //if(r2->name) free(r2->name);
6597 r2->name = Safe_strdup(newreg->name);
6601 newreg->wasUsed = 1;
6603 r2 = setNextItem(pb->tregisters);
6606 r1 = setNextItem(registersInCallPath);
6609 /* Collisions have been resolved. Now free the registers in the call path */
6610 r1 = setFirstItem(registersInCallPath);
6612 if(r1->type != REG_STK) {
6613 newreg = pic16_regWithIdx(r1->rIdx);
6616 r1 = setNextItem(registersInCallPath);
6620 // MarkUsedRegisters(pb->registers);
6622 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6625 DFPRINTF((stderr,"returning regs\n"));
6627 DFPRINTF((stderr,"not returning regs\n"));
6629 DFPRINTF((stderr,"pBlock after register optim.\n"));
6630 pBlockStats(stderr,pb); // debug
6636 /*-----------------------------------------------------------------*/
6637 /* pct2 - writes the call tree to a file */
6639 /*-----------------------------------------------------------------*/
6640 static void pct2(FILE *of,pBlock *pb,int indent)
6644 // set *registersInCallPath = NULL;
6650 return; //recursion ?
6652 pc = setFirstItem(pb->function_entries);
6659 for(i=0;i<indent;i++) // Indentation
6662 if(pc->type == PC_FUNCTION)
6663 fprintf(of,"%s\n",PCF(pc)->fname);
6668 pc = setFirstItem(pb->function_calls);
6669 for( ; pc; pc = setNextItem(pb->function_calls)) {
6671 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6672 char *dest = pic16_get_op_from_instruction(PCI(pc));
6674 pcn = findFunction(dest);
6676 pct2(of,pcn->pb,indent+1);
6678 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6686 /*-----------------------------------------------------------------*/
6687 /* pic16_printCallTree - writes the call tree to a file */
6689 /*-----------------------------------------------------------------*/
6691 void pic16_printCallTree(FILE *of)
6703 fprintf(of, "\npBlock statistics\n");
6704 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6709 fprintf(of,"Call Tree\n");
6710 pbr = the_pFile->functions;
6714 if(!ispCodeFunction(pc))
6715 fprintf(of,"bug in call tree");
6718 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6720 while(pc->next && !ispCodeFunction(pc->next)) {
6722 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6723 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6731 fprintf(of,"\n**************\n\na better call tree\n");
6732 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6737 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6738 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6744 /*-----------------------------------------------------------------*/
6746 /*-----------------------------------------------------------------*/
6748 static void InlineFunction(pBlock *pb)
6756 pc = setFirstItem(pb->function_calls);
6758 for( ; pc; pc = setNextItem(pb->function_calls)) {
6761 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6767 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
6769 //fprintf(stderr,"Cool can inline:\n");
6770 //pcn->print(stderr,pcn);
6772 //fprintf(stderr,"recursive call Inline\n");
6773 InlineFunction(pcn->pb);
6774 //fprintf(stderr,"return from recursive call Inline\n");
6777 At this point, *pc points to a CALL mnemonic, and
6778 *pcn points to the function that is being called.
6780 To in-line this call, we need to remove the CALL
6781 and RETURN(s), and link the function pCode in with
6787 /* Remove the CALL */
6791 /* remove callee pBlock from the pBlock linked list */
6792 removepBlock(pcn->pb);
6800 /* Remove the Function pCode */
6801 pct = pic16_findNextInstruction(pcn->next);
6803 /* Link the function with the callee */
6804 pc->next = pcn->next;
6805 pcn->next->prev = pc;
6807 /* Convert the function name into a label */
6809 pbr = Safe_calloc(1,sizeof(pBranch));
6810 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6812 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6813 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6815 /* turn all of the return's except the last into goto's */
6816 /* check case for 2 instruction pBlocks */
6817 pce = pic16_findNextInstruction(pcn->next);
6819 pCode *pce_next = pic16_findNextInstruction(pce->next);
6821 if(pce_next == NULL) {
6822 /* found the last return */
6823 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6825 //fprintf(stderr,"found last return\n");
6826 //pce->print(stderr,pce);
6827 pce->prev->next = pc_call->next;
6828 pc_call->next->prev = pce->prev;
6829 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6839 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6845 /*-----------------------------------------------------------------*/
6847 /*-----------------------------------------------------------------*/
6849 void pic16_InlinepCode(void)
6858 if(!functionInlining)
6861 /* Loop through all of the function definitions and count the
6862 * number of times each one is called */
6863 //fprintf(stderr,"inlining %d\n",__LINE__);
6865 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6867 pc = setFirstItem(pb->function_calls);
6869 for( ; pc; pc = setNextItem(pb->function_calls)) {
6872 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6873 if(pcn && isPCF(pcn)) {
6874 PCF(pcn)->ncalled++;
6877 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6882 //fprintf(stderr,"inlining %d\n",__LINE__);
6884 /* Now, Loop through the function definitions again, but this
6885 * time inline those functions that have only been called once. */
6887 InlineFunction(the_pFile->pbHead);
6888 //fprintf(stderr,"inlining %d\n",__LINE__);
6890 for(pb = the_pFile->pbHead; pb; pb = pb->next)