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 fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3612 __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
3617 /*-----------------------------------------------------------------*/
3618 /*-----------------------------------------------------------------*/
3620 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3627 pcop = pic16_newpCodeOpBit(name, -1,0);
3631 pcop = pic16_newpCodeOpLit(-1);
3635 pcop = pic16_newpCodeOpLabel(NULL,-1);
3638 pcop = pic16_newpCodeOpReg(-1);
3641 case PO_GPR_REGISTER:
3643 pcop = pic16_newpCodeOpRegFromStr(name);
3645 pcop = pic16_newpCodeOpReg(-1);
3649 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3652 pcop->name = Safe_strdup(name);
3660 /*-----------------------------------------------------------------*/
3661 /*-----------------------------------------------------------------*/
3662 void pic16_pCodeConstString(char *name, char *value)
3666 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
3671 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3673 pic16_addpBlock(pb);
3675 sprintf(buffer,"; %s = %s",name,value);
3677 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3678 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3681 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3687 /*-----------------------------------------------------------------*/
3688 /*-----------------------------------------------------------------*/
3690 static void pCodeReadCodeTable(void)
3694 fprintf(stderr, " %s\n",__FUNCTION__);
3696 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3698 pic16_addpBlock(pb);
3700 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3701 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3702 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3703 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3705 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3706 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3707 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3708 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3713 /*-----------------------------------------------------------------*/
3714 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3715 /*-----------------------------------------------------------------*/
3716 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3723 /* If this is the first pcode to be added to a block that
3724 * was initialized with a NULL pcode, then go ahead and
3725 * make this pcode the head and tail */
3726 pb->pcHead = pb->pcTail = pc;
3729 pb->pcTail->next = pc;
3731 pc->prev = pb->pcTail;
3738 /*-----------------------------------------------------------------*/
3739 /* pic16_addpBlock - place a pBlock into the pFile */
3740 /*-----------------------------------------------------------------*/
3741 void pic16_addpBlock(pBlock *pb)
3743 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3746 /* First time called, we'll pass through here. */
3747 //_ALLOC(the_pFile,sizeof(pFile));
3748 the_pFile = Safe_calloc(1,sizeof(pFile));
3749 the_pFile->pbHead = the_pFile->pbTail = pb;
3750 the_pFile->functions = NULL;
3754 the_pFile->pbTail->next = pb;
3755 pb->prev = the_pFile->pbTail;
3757 the_pFile->pbTail = pb;
3760 /*-----------------------------------------------------------------*/
3761 /* removepBlock - remove a pBlock from the pFile */
3762 /*-----------------------------------------------------------------*/
3763 static void removepBlock(pBlock *pb)
3771 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3773 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3776 if(pbs == the_pFile->pbHead)
3777 the_pFile->pbHead = pbs->next;
3779 if (pbs == the_pFile->pbTail)
3780 the_pFile->pbTail = pbs->prev;
3783 pbs->next->prev = pbs->prev;
3786 pbs->prev->next = pbs->next;
3793 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3797 /*-----------------------------------------------------------------*/
3798 /* printpCode - write the contents of a pCode to a file */
3799 /*-----------------------------------------------------------------*/
3800 static void printpCode(FILE *of, pCode *pc)
3811 fprintf(of,"warning - unable to print pCode\n");
3814 /*-----------------------------------------------------------------*/
3815 /* pic16_printpBlock - write the contents of a pBlock to a file */
3816 /*-----------------------------------------------------------------*/
3817 void pic16_printpBlock(FILE *of, pBlock *pb)
3826 if(pb->dbName == 'A') {
3830 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3832 // fprintf(of, "%s\tcode\t%d"
3836 for(pc = pb->pcHead; pc; pc = pc->next) {
3837 if(isPCF(pc) && PCF(pc)->fname) {
3838 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
3839 if(pb->dbName == 'A') {
3841 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3842 if(strcmp(ab->name, PCF(pc)->fname)) {
3843 fprintf(of, "\t0X%06X", ab->address);
3853 /*-----------------------------------------------------------------*/
3855 /* pCode processing */
3859 /*-----------------------------------------------------------------*/
3861 void pic16_unlinkpCode(pCode *pc)
3867 fprintf(stderr,"Unlinking: ");
3868 printpCode(stderr, pc);
3871 pc->prev->next = pc->next;
3873 pc->next->prev = pc->prev;
3875 pc->prev = pc->next = NULL;
3879 /*-----------------------------------------------------------------*/
3880 /*-----------------------------------------------------------------*/
3882 static void genericDestruct(pCode *pc)
3885 pic16_unlinkpCode(pc);
3888 /* For instructions, tell the register (if there's one used)
3889 * that it's no longer needed */
3890 regs *reg = pic16_getRegFromInstruction(pc);
3892 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3894 if(PCI(pc)->is2MemOp) {
3895 reg = pic16_getRegFromInstruction2(pc);
3897 deleteSetItem(&(reg->reglives.usedpCodes), pc);
3901 /* Instead of deleting the memory used by this pCode, mark
3902 * the object as bad so that if there's a pointer to this pCode
3903 * dangling around somewhere then (hopefully) when the type is
3904 * checked we'll catch it.
3909 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3917 /*-----------------------------------------------------------------*/
3918 /*-----------------------------------------------------------------*/
3919 /* modifiers for constant immediate */
3920 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
3922 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3927 int use_buffer = 1; // copy the string to the passed buffer pointer
3932 use_buffer = 0; // Don't bother copying the string to the buffer.
3936 switch(pcop->type) {
3940 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3943 return PCOR(pcop)->r->name;
3946 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3949 SAFE_snprintf(&buffer,&size,"%s",r->name);
3959 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3960 if(PCOI(pcop)->index) {
3961 SAFE_snprintf(&s,&size, "%s(%s + %d)",
3962 immdmod[ PCOI(pcop)->offset ],
3966 SAFE_snprintf(&s,&size,"%s(%s)",
3967 immdmod[ PCOI(pcop)->offset ],
3971 if(PCOI(pcop)->index) {
3972 SAFE_snprintf(&s,&size, "%s(%s + %d)",
3977 SAFE_snprintf(&s,&size, "%s(%s)",
3984 if(PCOI(pcop)->_const) {
3985 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3986 if(PCOI(pcop)->index) {
3987 SAFE_snprintf(&s,&size,"%s(%s + %d)",
3988 immdmod[ PCOI(pcop)->offset ],
3992 SAFE_snprintf(&s,&size,"%s(%s)",
3993 immdmod[ PCOI(pcop)->offset ],
3998 if(PCOI(pcop)->index)
3999 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4001 SAFE_snprintf(&s,&size,"LOW(%s)",pcop->name);
4004 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4)
4005 SAFE_snprintf(&s,&size,"(%s + %d)",
4007 PCOI(pcop)->index );
4009 if(PCOI(pcop)->offset)
4010 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4012 SAFE_snprintf(&s,&size,"(%s)",pcop->name);
4021 //size = sizeof(buffer);
4022 if( PCOR(pcop)->instance) {
4023 SAFE_snprintf(&s,&size,"(%s + %d)",
4025 PCOR(pcop)->instance );
4027 //fprintf(stderr,"PO_DIR %s\n",buffer);
4029 SAFE_snprintf(&s,&size,"%s",pcop->name);
4035 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4044 return "NO operand";
4048 /*-----------------------------------------------------------------*/
4049 /* pic16_get_op2 - variant to support two memory operand commands */
4050 /*-----------------------------------------------------------------*/
4051 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4056 int use_buffer = 1; // copy the string to the passed buffer pointer
4061 use_buffer = 0; // Don't bother copying the string to the buffer.
4065 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",
4066 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4067 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4071 switch(PCOR2(pcop)->pcop2->type) {
4075 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4078 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4081 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4084 SAFE_snprintf(&buffer,&size,"%s",r->name);
4096 if(PCOI(pcop)->_const) {
4098 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4099 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4102 8 * PCOI(pcop)->offset );
4104 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4107 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
4108 SAFE_snprintf(&s,&size,"(%s + %d)",
4110 PCOI(pcop)->index );
4112 if(PCOI(pcop)->offset)
4113 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4115 SAFE_snprintf(&s,&size,"%s",pcop->name);
4124 //size = sizeof(buffer);
4125 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4126 SAFE_snprintf(&s,&size,"(%s + %d)",
4127 PCOR(PCOR2(pcop)->pcop2)->r->name,
4128 PCOR(PCOR2(pcop)->pcop2)->instance );
4130 //fprintf(stderr,"PO_DIR %s\n",buffer);
4132 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4137 if (PCOR2(pcop)->r1->name) {
4139 SAFE_snprintf(&buffer,&size,"%s",PCOR2(pcop)->r1->name);
4142 return PCOR2(pcop)->r1->name;
4150 return "NO operand";
4154 /*-----------------------------------------------------------------*/
4155 /*-----------------------------------------------------------------*/
4156 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4160 return pic16_get_op(pcc->pcop,NULL,0);
4162 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4163 * return ("ERROR Null: "__FUNCTION__);
4165 return ("ERROR Null: pic16_get_op_from_instruction");
4169 /*-----------------------------------------------------------------*/
4170 /*-----------------------------------------------------------------*/
4171 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4174 fprintf(of,"pcodeopprint- not implemented\n");
4177 /*-----------------------------------------------------------------*/
4178 /* pic16_pCode2str - convert a pCode instruction to string */
4179 /*-----------------------------------------------------------------*/
4180 static char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4186 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4187 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4188 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4196 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4198 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4200 if(PCI(pc)->is2MemOp) {
4201 SAFE_snprintf(&s,&size, "%s, %s",
4202 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4203 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4207 if(PCI(pc)->is2LitOp) {
4208 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4212 if(PCI(pc)->isBitInst) {
4213 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4214 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4215 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4216 PCI(pc)->pcop->name ,
4217 PCI(pc)->pcop->name );
4219 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4220 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4221 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4222 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4224 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4225 //PCI(pc)->pcop->t.bit );
4228 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4229 if( PCI(pc)->num_ops == 3)
4230 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4232 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4235 SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
4237 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4238 if(PCI(pc)->num_ops == 3)
4239 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4241 r = pic16_getRegFromInstruction(pc);
4242 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4243 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4245 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4254 /* assuming that comment ends with a \n */
4255 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4259 /* assuming that inline code ends with a \n */
4260 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4264 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4267 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4270 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4273 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4276 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4279 SAFE_snprintf(&s,&size,"\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4283 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4290 /*-----------------------------------------------------------------*/
4291 /* genericPrint - the contents of a pCode to a file */
4292 /*-----------------------------------------------------------------*/
4293 static void genericPrint(FILE *of, pCode *pc)
4301 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4305 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4309 // If the opcode has a label, print that first
4311 pBranch *pbl = PCI(pc)->label;
4312 while(pbl && pbl->pc) {
4313 if(pbl->pc->type == PC_LABEL)
4314 pCodePrintLabel(of, pbl->pc);
4320 genericPrint(of,PCODE(PCI(pc)->cline));
4325 pic16_pCode2str(str, 256, pc);
4327 fprintf(of,"%s",str);
4330 if(pic16_debug_verbose) {
4331 fprintf(of, "\t;key=%03x",pc->seq);
4333 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4340 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4341 if(PCW(pc)->pci.label)
4342 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4344 if(PCW(pc)->operand) {
4345 fprintf(of,";\toperand ");
4346 pCodeOpPrint(of,PCW(pc)->operand );
4351 if(pic16_debug_verbose) {
4352 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4353 if(PCFL(pc)->ancestor)
4354 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4361 fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4365 pBranch *pbl = PCAD(pc)->label;
4366 while(pbl && pbl->pc) {
4367 if(pbl->pc->type == PC_LABEL)
4368 pCodePrintLabel(of, pbl->pc);
4372 fprintf(of, "\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4377 fprintf(of,"unknown pCode type %d\n",pc->type);
4382 /*-----------------------------------------------------------------*/
4383 /* pCodePrintFunction - prints function begin/end */
4384 /*-----------------------------------------------------------------*/
4386 static void pCodePrintFunction(FILE *of, pCode *pc)
4393 if( ((pCodeFunction *)pc)->modname)
4394 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4397 if(PCF(pc)->fname) {
4398 pBranch *exits = PCF(pc)->to;
4400 fprintf(of,"%s", PCF(pc)->fname);
4402 // if(pic16_pcode_verbose)
4403 fprintf(of, "\t;Function start");
4409 exits = exits->next;
4413 if(pic16_pcode_verbose)
4414 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4417 if((PCF(pc)->from &&
4418 PCF(pc)->from->pc->type == PC_FUNCTION &&
4419 PCF(PCF(pc)->from->pc)->fname) ) {
4421 if(pic16_pcode_verbose)
4422 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4424 if(pic16_pcode_verbose)
4425 fprintf(of,"; exit point [can't find entry point]\n");
4430 /*-----------------------------------------------------------------*/
4431 /* pCodePrintLabel - prints label */
4432 /*-----------------------------------------------------------------*/
4434 static void pCodePrintLabel(FILE *of, pCode *pc)
4441 fprintf(of,"%s:\n",PCL(pc)->label);
4442 else if (PCL(pc)->key >=0)
4443 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4445 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4448 /*-----------------------------------------------------------------*/
4449 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4450 /* remove it if it is found. */
4451 /*-----------------------------------------------------------------*/
4452 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4459 if(pcl->type == PC_OPCODE)
4460 b = PCI(pcl)->label;
4462 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4467 //fprintf (stderr, "%s \n",__FUNCTION__);
4468 //pcl->print(stderr,pcl);
4469 //pc->print(stderr,pc);
4472 //fprintf (stderr, "found label\n");
4476 bprev->next = b->next; /* Not first pCode in chain */
4480 PCI(pcl)->label = b->next; /* First pCode in chain */
4483 return; /* A label can't occur more than once */
4491 /*-----------------------------------------------------------------*/
4492 /*-----------------------------------------------------------------*/
4493 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4512 /*-----------------------------------------------------------------*/
4513 /* pBranchLink - given two pcodes, this function will link them */
4514 /* together through their pBranches */
4515 /*-----------------------------------------------------------------*/
4516 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4520 // Declare a new branch object for the 'from' pCode.
4522 //_ALLOC(b,sizeof(pBranch));
4523 b = Safe_calloc(1,sizeof(pBranch));
4524 b->pc = PCODE(t); // The link to the 'to' pCode.
4527 f->to = pic16_pBranchAppend(f->to,b);
4529 // Now do the same for the 'to' pCode.
4531 //_ALLOC(b,sizeof(pBranch));
4532 b = Safe_calloc(1,sizeof(pBranch));
4536 t->from = pic16_pBranchAppend(t->from,b);
4541 /*-----------------------------------------------------------------*/
4542 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4544 /*-----------------------------------------------------------------*/
4545 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4558 /*-----------------------------------------------------------------*/
4559 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4560 /*-----------------------------------------------------------------*/
4561 static void pCodeUnlink(pCode *pc)
4566 if(!pc->prev || !pc->next) {
4567 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4571 /* first remove the pCode from the chain */
4572 pc->prev->next = pc->next;
4573 pc->next->prev = pc->prev;
4575 /* Now for the hard part... */
4577 /* Remove the branches */
4581 pc1 = pb1->pc; /* Get the pCode that branches to the
4582 * one we're unlinking */
4584 /* search for the link back to this pCode (the one we're
4586 if(pb2 = pBranchFind(pc1->to,pc)) {
4587 pb2->pc = pc->to->pc; // make the replacement
4589 /* if the pCode we're unlinking contains multiple 'to'
4590 * branches (e.g. this a skip instruction) then we need
4591 * to copy these extra branches to the chain. */
4593 pic16_pBranchAppend(pb2, pc->to->next);
4602 /*-----------------------------------------------------------------*/
4603 /*-----------------------------------------------------------------*/
4605 static void genericAnalyze(pCode *pc)
4615 // Go through the pCodes that are in pCode chain and link
4616 // them together through the pBranches. Note, the pCodes
4617 // are linked together as a contiguous stream like the
4618 // assembly source code lines. The linking here mimics this
4619 // except that comments are not linked in.
4621 pCode *npc = pc->next;
4623 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4624 pBranchLink(pc,npc);
4629 /* reached the end of the pcode chain without finding
4630 * an instruction we could link to. */
4634 fprintf(stderr,"analyze PC_FLOW\n");
4638 fprintf(stderr,,";A bad pCode is being used\n");
4644 /*-----------------------------------------------------------------*/
4645 /*-----------------------------------------------------------------*/
4646 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4650 if(pc->type == PC_LABEL) {
4651 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4654 if(pc->type == PC_OPCODE) {
4655 pbr = PCI(pc)->label;
4657 if(pbr->pc->type == PC_LABEL) {
4658 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4668 /*-----------------------------------------------------------------*/
4669 /*-----------------------------------------------------------------*/
4670 static int checkLabel(pCode *pc)
4674 if(pc && isPCI(pc)) {
4675 pbr = PCI(pc)->label;
4677 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4687 /*-----------------------------------------------------------------*/
4688 /* findLabelinpBlock - Search the pCode for a particular label */
4689 /*-----------------------------------------------------------------*/
4690 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4697 for(pc = pb->pcHead; pc; pc = pc->next)
4698 if(compareLabel(pc,pcop_label))
4704 /*-----------------------------------------------------------------*/
4705 /* findLabel - Search the pCode for a particular label */
4706 /*-----------------------------------------------------------------*/
4707 static pCode * findLabel(pCodeOpLabel *pcop_label)
4715 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4716 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4720 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4724 /*-----------------------------------------------------------------*/
4725 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4726 /* in the linked list */
4727 /*-----------------------------------------------------------------*/
4728 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4741 /*-----------------------------------------------------------------*/
4742 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4743 /* in the linked list */
4744 /*-----------------------------------------------------------------*/
4745 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4757 /*-----------------------------------------------------------------*/
4758 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4759 /* in the linked list */
4760 /*-----------------------------------------------------------------*/
4761 pCode * pic16_findNextInstruction(pCode *pci)
4766 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4770 fprintf(stderr,"pic16_findNextInstruction: ");
4771 printpCode(stderr, pc);
4776 //fprintf(stderr,"Couldn't find instruction\n");
4780 /*-----------------------------------------------------------------*/
4781 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4782 /* in the linked list */
4783 /*-----------------------------------------------------------------*/
4784 pCode * pic16_findPrevInstruction(pCode *pci)
4786 return findPrevpCode(pci, PC_OPCODE);
4789 /*-----------------------------------------------------------------*/
4790 /* findFunctionEnd - given a pCode find the end of the function */
4791 /* that contains it */
4792 /*-----------------------------------------------------------------*/
4793 static pCode * findFunctionEnd(pCode *pc)
4797 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4803 fprintf(stderr,"Couldn't find function end\n");
4808 /*-----------------------------------------------------------------*/
4809 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4810 /* instruction with which it is associated. */
4811 /*-----------------------------------------------------------------*/
4812 static void AnalyzeLabel(pCode *pc)
4821 static void AnalyzeGOTO(pCode *pc)
4824 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4828 static void AnalyzeSKIP(pCode *pc)
4831 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4832 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4836 static void AnalyzeRETURN(pCode *pc)
4839 // branch_link(pc,findFunctionEnd(pc->next));
4845 /*-----------------------------------------------------------------*/
4846 /*-----------------------------------------------------------------*/
4847 regs * pic16_getRegFromInstruction(pCode *pc)
4853 PCI(pc)->num_ops == 0 ||
4854 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4857 switch(PCI(pc)->pcop->type) {
4860 return PCOR(PCI(pc)->pcop)->r;
4862 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4866 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4867 return PCOR(PCI(pc)->pcop)->r;
4870 if(PCOI(PCI(pc)->pcop)->r)
4871 return (PCOI(PCI(pc)->pcop)->r);
4873 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4874 return pic16_dirregWithName(PCI(pc)->pcop->name);
4875 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4878 return PCOR(PCI(pc)->pcop)->r;
4881 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4882 return PCOR(PCI(pc)->pcop)->r;
4884 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4888 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4889 //genericPrint(stderr, pc);
4897 /*-------------------------------------------------------------------------------*/
4898 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
4899 /*-------------------------------------------------------------------------------*/
4900 regs * pic16_getRegFromInstruction2(pCode *pc)
4906 PCI(pc)->num_ops == 0 ||
4907 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
4912 * operands supported in MOVFF:
4919 switch(PCI(pc)->pcop->type) {
4922 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4924 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4928 //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4929 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4934 if(PCOI(PCI(pc)->pcop)->r)
4935 return (PCOI(PCI(pc)->pcop)->r);
4937 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4938 return pic16_dirregWithName(PCI(pc)->pcop->name);
4939 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4944 // return PCOR2(PCI(pc)->pcop)->r;
4947 //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4948 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4952 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4955 //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4956 //genericPrint(stderr, pc);
4964 /*-----------------------------------------------------------------*/
4965 /*-----------------------------------------------------------------*/
4967 static void AnalyzepBlock(pBlock *pb)
4974 /* Find all of the registers used in this pBlock
4975 * by looking at each instruction and examining it's
4978 for(pc = pb->pcHead; pc; pc = pc->next) {
4980 /* Is this an instruction with operands? */
4981 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4983 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4985 /* Loop through all of the registers declared so far in
4986 this block and see if we find this one there */
4988 regs *r = setFirstItem(pb->tregisters);
4991 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4992 PCOR(PCI(pc)->pcop)->r = r;
4995 r = setNextItem(pb->tregisters);
4999 /* register wasn't found */
5000 //r = Safe_calloc(1, sizeof(regs));
5001 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5002 //addSet(&pb->tregisters, r);
5003 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5004 //PCOR(PCI(pc)->pcop)->r = r;
5005 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5007 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5010 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5011 if(PCOR(PCI(pc)->pcop)->r) {
5012 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5013 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5015 if(PCI(pc)->pcop->name)
5016 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5018 fprintf(stderr,"ERROR: NULL register\n");
5027 /*-----------------------------------------------------------------*/
5029 /*-----------------------------------------------------------------*/
5030 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5032 static void InsertpFlow(pCode *pc, pCode **pflow)
5035 PCFL(*pflow)->end = pc;
5037 if(!pc || !pc->next)
5040 *pflow = pic16_newpCodeFlow();
5041 pic16_pCodeInsertAfter(pc, *pflow);
5044 /*-----------------------------------------------------------------*/
5045 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5046 /* the flow blocks. */
5048 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5049 * point the instruction flow changes.
5051 /*-----------------------------------------------------------------*/
5052 void pic16_BuildFlow(pBlock *pb)
5055 pCode *last_pci=NULL;
5062 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5063 /* Insert a pCodeFlow object at the beginning of a pBlock */
5065 InsertpFlow(pb->pcHead, &pflow);
5067 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5068 //pflow->next = pb->pcHead; /* Make the current head the next object */
5069 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5070 //pb->pcHead = pflow; /* Make the Flow object the head */
5073 for( pc = pic16_findNextInstruction(pb->pcHead);
5075 pc=pic16_findNextInstruction(pc)) {
5078 PCI(pc)->pcflow = PCFL(pflow);
5080 //fprintf(stderr," build: ");
5081 //pflow->print(stderr,pflow);
5083 if( PCI(pc)->isSkip) {
5085 /* The two instructions immediately following this one
5086 * mark the beginning of a new flow segment */
5088 while(pc && PCI(pc)->isSkip) {
5090 PCI(pc)->pcflow = PCFL(pflow);
5094 InsertpFlow(pc, &pflow);
5095 pc=pic16_findNextInstruction(pc->next);
5103 PCI(pc)->pcflow = PCFL(pflow);
5105 InsertpFlow(pc, &pflow);
5107 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5109 InsertpFlow(pc, &pflow);
5112 } else if (checkLabel(pc)) {
5114 /* This instruction marks the beginning of a
5115 * new flow segment */
5120 /* If the previous pCode is not a flow object, then
5121 * insert a new flow object. (This check prevents
5122 * two consecutive flow objects from being insert in
5123 * the case where a skip instruction preceeds an
5124 * instruction containing a label.) */
5126 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5127 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5129 PCI(pc)->pcflow = PCFL(pflow);
5136 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5138 PCFL(pflow)->end = pb->pcTail;
5141 /*-------------------------------------------------------------------*/
5142 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5143 /* the flow blocks. */
5145 * unBuildFlow removes pCodeFlow objects from a pCode chain
5147 /*-----------------------------------------------------------------*/
5148 static void unBuildFlow(pBlock *pb)
5163 if(PCI(pc)->pcflow) {
5164 //free(PCI(pc)->pcflow);
5165 PCI(pc)->pcflow = NULL;
5168 } else if(isPCFL(pc) )
5177 /*-----------------------------------------------------------------*/
5178 /*-----------------------------------------------------------------*/
5179 static void dumpCond(int cond)
5182 static char *pcc_str[] = {
5197 int ncond = sizeof(pcc_str) / sizeof(char *);
5200 fprintf(stderr, "0x%04X\n",cond);
5202 for(i=0,j=1; i<ncond; i++, j<<=1)
5204 fprintf(stderr, " %s\n",pcc_str[i]);
5210 /*-----------------------------------------------------------------*/
5211 /*-----------------------------------------------------------------*/
5212 static void FlowStats(pCodeFlow *pcflow)
5220 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5222 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5225 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5230 fprintf(stderr, " FlowStats inCond: ");
5231 dumpCond(pcflow->inCond);
5232 fprintf(stderr, " FlowStats outCond: ");
5233 dumpCond(pcflow->outCond);
5237 /*-----------------------------------------------------------------*
5238 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5239 * if it affects the banking bits.
5241 * return: -1 == Banking bits are unaffected by this pCode.
5243 * return: > 0 == Banking bits are affected.
5245 * If the banking bits are affected, then the returned value describes
5246 * which bits are affected and how they're affected. The lower half
5247 * of the integer maps to the bits that are affected, the upper half
5248 * to whether they're set or cleared.
5250 *-----------------------------------------------------------------*/
5252 static int isBankInstruction(pCode *pc)
5260 if( PCI(pc)->op == POC_MOVLB ||
5261 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5262 bank = PCOL(pc)->lit;
5269 /*-----------------------------------------------------------------*/
5270 /*-----------------------------------------------------------------*/
5271 static void FillFlow(pCodeFlow *pcflow)
5280 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5282 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5285 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5292 isBankInstruction(pc);
5294 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5298 fprintf(stderr, " FillFlow - Bad end of flow\n");
5300 fprintf(stderr, " FillFlow - Ending flow with\n ");
5301 pc->print(stderr,pc);
5304 fprintf(stderr, " FillFlow inCond: ");
5305 dumpCond(pcflow->inCond);
5306 fprintf(stderr, " FillFlow outCond: ");
5307 dumpCond(pcflow->outCond);
5311 /*-----------------------------------------------------------------*/
5312 /*-----------------------------------------------------------------*/
5313 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5315 pCodeFlowLink *fromLink, *toLink;
5317 if(!from || !to || !to->pcflow || !from->pcflow)
5320 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5321 toLink = pic16_newpCodeFlowLink(to->pcflow);
5323 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5324 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5328 /*-----------------------------------------------------------------*
5329 * void LinkFlow(pBlock *pb)
5331 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5332 * non-branching segments. In LinkFlow, we determine the execution
5333 * order of these segments. For example, if one of the segments ends
5334 * with a skip, then we know that there are two possible flow segments
5335 * to which control may be passed.
5336 *-----------------------------------------------------------------*/
5337 static void LinkFlow(pBlock *pb)
5343 //fprintf(stderr,"linkflow \n");
5345 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5347 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5350 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5352 //fprintf(stderr," link: ");
5353 //pcflow->print(stderr,pcflow);
5355 //FillFlow(PCFL(pcflow));
5357 pc = PCFL(pcflow)->end;
5359 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5360 if(isPCI_SKIP(pc)) {
5361 //fprintf(stderr, "ends with skip\n");
5362 //pc->print(stderr,pc);
5363 pct=pic16_findNextInstruction(pc->next);
5364 LinkFlow_pCode(PCI(pc),PCI(pct));
5365 pct=pic16_findNextInstruction(pct->next);
5366 LinkFlow_pCode(PCI(pc),PCI(pct));
5370 if(isPCI_BRANCH(pc)) {
5371 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5373 //fprintf(stderr, "ends with branch\n ");
5374 //pc->print(stderr,pc);
5376 if(!(pcol && isPCOLAB(pcol))) {
5377 if((PCI(pc)->op != POC_RETLW)
5378 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5380 /* continue if label is '$' which assembler knows how to parse */
5381 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5383 pc->print(stderr,pc);
5384 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5389 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5390 LinkFlow_pCode(PCI(pc),PCI(pct));
5392 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5393 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5394 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5400 //fprintf(stderr, "ends with non-branching instruction:\n");
5401 //pc->print(stderr,pc);
5403 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5409 //fprintf(stderr, "ends with unknown\n");
5410 //pc->print(stderr,pc);
5414 //fprintf(stderr, "ends with nothing: ERROR\n");
5418 /*-----------------------------------------------------------------*/
5419 /*-----------------------------------------------------------------*/
5421 /*-----------------------------------------------------------------*/
5422 /*-----------------------------------------------------------------*/
5423 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5429 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5432 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5442 /*-----------------------------------------------------------------*/
5443 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5444 /*-----------------------------------------------------------------*/
5445 static void insertBankSwitch(int position, pCode *pc, int bsr)
5454 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5455 * insert a BANKSEL assembler directive for the symbol used by
5456 * the pCode. This will allow the linker to setup the correct
5457 * bank at linking time
5460 if(!pic16_options.gen_banksel || bsr != -1) {
5461 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5464 /* emit the BANKSEL [symbol] */
5467 /* IMPORTANT: The following code does not check if a symbol is
5468 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5470 reg = pic16_getRegFromInstruction(pc);
5472 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", reg->name);
5474 position = 0; // position is always before (sanity check!)
5478 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5479 pc->print(stderr, pc);
5483 /* insert the bank switch after this pc instruction */
5484 pCode *pcnext = pic16_findNextInstruction(pc);
5485 pic16_pCodeInsertAfter(pc, new_pc);
5490 pic16_pCodeInsertAfter(pc->prev, new_pc);
5492 /* Move the label, if there is one */
5494 if(PCI(pc)->label) {
5495 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5496 // __FILE__, __LINE__, pc, new_pc);
5497 PCAD(new_pc)->label = PCI(pc)->label;
5498 PCI(pc)->label = NULL;
5501 // fprintf(stderr, "BankSwitch has been inserted\n");
5505 /*-----------------------------------------------------------------*/
5506 /*int compareBankFlow - compare the banking requirements between */
5508 /*-----------------------------------------------------------------*/
5509 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5512 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5515 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5518 if(pcflow->firstBank == -1)
5522 if(pcflowLink->pcflow->firstBank == -1) {
5523 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5524 pcflowLink->pcflow->to :
5525 pcflowLink->pcflow->from);
5526 return compareBankFlow(pcflow, pctl, toORfrom);
5530 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5533 pcflowLink->bank_conflict++;
5534 pcflowLink->pcflow->FromConflicts++;
5535 pcflow->ToConflicts++;
5538 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5541 pcflowLink->bank_conflict++;
5542 pcflowLink->pcflow->ToConflicts++;
5543 pcflow->FromConflicts++;
5547 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5548 pcflowLink->pcflow->pc.seq,
5549 pcflowLink->pcflow->FromConflicts,
5550 pcflowLink->pcflow->ToConflicts);
5557 /*-----------------------------------------------------------------*/
5558 /*-----------------------------------------------------------------*/
5559 static void DumpFlow(pBlock *pb)
5563 pCodeFlowLink *pcfl;
5566 fprintf(stderr,"Dump flow \n");
5567 pb->pcHead->print(stderr, pb->pcHead);
5569 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5570 pcflow->print(stderr,pcflow);
5572 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5574 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5576 if(!isPCFL(pcflow)) {
5577 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5580 fprintf(stderr,"dumping: ");
5581 pcflow->print(stderr,pcflow);
5582 FlowStats(PCFL(pcflow));
5584 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5586 pc = PCODE(pcfl->pcflow);
5588 fprintf(stderr, " from seq %d:\n",pc->seq);
5590 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5591 pc->print(stderr,pc);
5596 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5598 pc = PCODE(pcfl->pcflow);
5600 fprintf(stderr, " to seq %d:\n",pc->seq);
5602 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5603 pc->print(stderr,pc);
5612 /*-----------------------------------------------------------------*/
5613 /*-----------------------------------------------------------------*/
5614 static int OptimizepBlock(pBlock *pb)
5619 if(!pb || !peepOptimizing)
5622 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5624 for(pc = pb->pcHead; pc; pc = pc->next)
5625 matches += pic16_pCodePeepMatchRule(pc);
5628 pc = pic16_findNextInstruction(pb->pcHead);
5636 if(pic16_pCodePeepMatchRule(pc)) {
5641 pc = pic16_findNextInstruction(pcprev->next);
5643 pc = pic16_findNextInstruction(pb->pcHead);
5645 pc = pic16_findNextInstruction(pc->next);
5649 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5654 /*-----------------------------------------------------------------*/
5655 /*-----------------------------------------------------------------*/
5656 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5660 for(pc = pcs; pc; pc = pc->next) {
5662 if((pc->type == PC_OPCODE) &&
5664 (PCI(pc)->pcop->type == PO_LABEL) &&
5665 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5673 /*-----------------------------------------------------------------*/
5674 /*-----------------------------------------------------------------*/
5675 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5682 (PCI(pc)->pcop->type == PO_LABEL)) {
5684 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5686 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5688 free(pcol->pcop.name);
5690 /* If the key is negative, then we (probably) have a label to
5691 * a function and the name is already defined */
5694 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5698 //sprintf(buffer,"_%05d_DS_",pcl->key);
5700 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5702 pcol->pcop.name = Safe_strdup(s);
5703 pcol->key = pcl->key;
5704 //pc->print(stderr,pc);
5711 /*-----------------------------------------------------------------*/
5712 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5713 /* pCode chain if they're not used. */
5714 /*-----------------------------------------------------------------*/
5715 static void pBlockRemoveUnusedLabels(pBlock *pb)
5717 pCode *pc; pCodeLabel *pcl;
5722 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5724 pBranch *pbr = PCI(pc)->label;
5725 if(pbr && pbr->next) {
5726 pCode *pcd = pb->pcHead;
5728 //fprintf(stderr, "multiple labels\n");
5729 //pc->print(stderr,pc);
5734 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5735 //fprintf(stderr,"Used by:\n");
5736 //pcd->print(stderr,pcd);
5738 exchangeLabels(PCL(pbr->pc),pcd);
5747 for(pc = pb->pcHead; pc; pc = pc->next) {
5749 if(isPCL(pc)) // pc->type == PC_LABEL)
5751 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5752 pcl = PCL(PCI(pc)->label->pc);
5755 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5757 /* This pCode is a label, so search the pBlock to see if anyone
5760 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5761 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5762 /* Couldn't find an instruction that refers to this label
5763 * So, unlink the pCode label from it's pCode chain
5764 * and destroy the label */
5765 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5767 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5768 if(pc->type == PC_LABEL) {
5769 pic16_unlinkpCode(pc);
5770 pCodeLabelDestruct(pc);
5772 unlinkpCodeFromBranch(pc, PCODE(pcl));
5773 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5784 /*-----------------------------------------------------------------*/
5785 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
5786 /* chain and put them into pBranches that are */
5787 /* associated with the appropriate pCode */
5789 /*-----------------------------------------------------------------*/
5790 void pic16_pBlockMergeLabels(pBlock *pb)
5793 pCode *pc, *pcnext=NULL;
5798 /* First, Try to remove any unused labels */
5799 //pBlockRemoveUnusedLabels(pb);
5801 /* Now loop through the pBlock and merge the labels with the opcodes */
5804 // for(pc = pb->pcHead; pc; pc = pc->next) {
5807 pCode *pcn = pc->next;
5809 if(pc->type == PC_LABEL) {
5811 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5812 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5814 if((pcnext = pic16_findNextInstruction(pc) )) {
5816 // Unlink the pCode label from it's pCode chain
5817 pic16_unlinkpCode(pc);
5819 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5820 // And link it into the instruction's pBranch labels. (Note, since
5821 // it's possible to have multiple labels associated with one instruction
5822 // we must provide a means to accomodate the additional labels. Thus
5823 // the labels are placed into the singly-linked list "label" as
5824 // opposed to being a single member of the pCodeInstruction.)
5826 //_ALLOC(pbr,sizeof(pBranch));
5828 pbr = Safe_calloc(1,sizeof(pBranch));
5832 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5835 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5837 } else if(pc->type == PC_CSOURCE) {
5839 /* merge the source line symbolic info into the next instruction */
5840 if((pcnext = pic16_findNextInstruction(pc) )) {
5842 // Unlink the pCode label from it's pCode chain
5843 pic16_unlinkpCode(pc);
5844 PCI(pcnext)->cline = PCCS(pc);
5845 //fprintf(stderr, "merging CSRC\n");
5846 //genericPrint(stderr,pcnext);
5852 pBlockRemoveUnusedLabels(pb);
5856 /*-----------------------------------------------------------------*/
5857 /*-----------------------------------------------------------------*/
5858 static int OptimizepCode(char dbName)
5860 #define MAX_PASSES 4
5869 DFPRINTF((stderr," Optimizing pCode\n"));
5873 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5874 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5875 matches += OptimizepBlock(pb);
5878 while(matches && ++passes < MAX_PASSES);
5883 /*-----------------------------------------------------------------*/
5884 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5885 /*-----------------------------------------------------------------*/
5887 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5891 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5893 if( !( (pcop->type == PO_LABEL) ||
5894 (pcop->type == PO_LITERAL) ||
5895 (pcop->type == PO_STR) ))
5896 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5897 PCOR(pcop)->r->wasUsed = 1;
5903 /*----------------------------------------------------------------------*
5904 * pic16_areRegsSame - check to see if the names of two registers match *
5905 *----------------------------------------------------------------------*/
5906 int pic16_areRegsSame(regs *r1, regs *r2)
5908 if(!strcmp(r1->name, r2->name))return 1;
5914 /*-----------------------------------------------------------------*/
5915 /*-----------------------------------------------------------------*/
5916 static void pic16_FixRegisterBanking(pBlock *pb)
5920 regs *reg, *prevreg;
5925 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5929 /* loop through all of the flow blocks with in one pblock */
5931 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
5935 /* at this point, pc should point to a PC_FLOW object */
5936 /* for each flow block, determine the register banking
5939 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
5940 reg = pic16_getRegFromInstruction(pc);
5943 fprintf(stderr, "reg = %p\n", reg);
5945 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
5946 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
5947 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
5948 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
5952 /* we can be 99% that within a pBlock, between two consequtive
5953 * refernces to the same register, the extra banksel is needless */
5955 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
5957 && (PCI(pc)->op != POC_CALL)
5959 && ( ((pic16_options.opt_banksel>0)
5960 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
5961 || (!pic16_options.opt_banksel)
5965 /* Examine the instruction before this one to make sure it is
5966 * not a skip type instruction */
5967 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5969 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
5970 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
5971 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5973 insertBankSwitch(0, pc, (pic16_options.gen_banksel)?-1:0);
5985 if(pcprev && cur_bank) {
5987 int pos = 1; /* Assume that the bank switch instruction(s)
5988 * are inserted after this instruction */
5990 if((PCI(pcprev)->op == POC_RETLW) ||
5991 (PCI(pcprev)->op == POC_RETURN) ||
5992 (PCI(pcprev)->op == POC_RETFIE)) {
5994 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6000 /* Brute force - make sure that we point to bank 0 at the
6001 * end of each flow block */
6003 // insertBankSwitch(pos, pcprev, 0);
6005 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6006 pic16_pCodeInsertAfter(pcprev, new_pc);
6009 //fprintf(stderr, "Brute force switch\n");
6016 static void pBlockDestruct(pBlock *pb)
6027 /*-----------------------------------------------------------------*/
6028 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6029 /* name dbName and combine them */
6030 /* into one block */
6031 /*-----------------------------------------------------------------*/
6032 static void mergepBlocks(char dbName)
6035 pBlock *pb, *pbmerged = NULL,*pbn;
6037 pb = the_pFile->pbHead;
6039 //fprintf(stderr," merging blocks named %c\n",dbName);
6043 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6044 if( getpBlock_dbName(pb) == dbName) {
6046 //fprintf(stderr," merged block %c\n",dbName);
6051 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6052 /* pic16_addpCode2pBlock doesn't handle the tail: */
6053 pbmerged->pcTail = pb->pcTail;
6055 pb->prev->next = pbn;
6057 pbn->prev = pb->prev;
6062 //pic16_printpBlock(stderr, pbmerged);
6069 /*-----------------------------------------------------------------*/
6070 /* AnalyzeFlow - Examine the flow of the code and optimize */
6072 /* level 0 == minimal optimization */
6073 /* optimize registers that are used only by two instructions */
6074 /* level 1 == maximal optimization */
6075 /* optimize by looking at pairs of instructions that use the */
6077 /*-----------------------------------------------------------------*/
6079 static void AnalyzeFlow(int level)
6081 static int times_called=0;
6086 /* remove unused allocated registers before exiting */
6087 pic16_RemoveUnusedRegisters();
6093 /* if this is not the first time this function has been called,
6094 then clean up old flow information */
6095 if(times_called++) {
6096 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6099 pic16_RegsUnMapLiveRanges();
6104 /* Phase 2 - Flow Analysis - Register Banking
6106 * In this phase, the individual flow blocks are examined
6107 * and register banking is fixed.
6111 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6112 pic16_FixRegisterBanking(pb);
6115 /* Phase 2 - Flow Analysis
6117 * In this phase, the pCode is partition into pCodeFlow
6118 * blocks. The flow blocks mark the points where a continuous
6119 * stream of instructions changes flow (e.g. because of
6120 * a call or goto or whatever).
6123 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6124 pic16_BuildFlow(pb);
6127 /* Phase 2 - Flow Analysis - linking flow blocks
6129 * In this phase, the individual flow blocks are examined
6130 * to determine their order of excution.
6133 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6136 /* Phase 3 - Flow Analysis - Flow Tree
6138 * In this phase, the individual flow blocks are examined
6139 * to determine their order of execution.
6142 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6143 pic16_BuildFlowTree(pb);
6146 /* Phase x - Flow Analysis - Used Banks
6148 * In this phase, the individual flow blocks are examined
6149 * to determine the Register Banks they use
6153 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6158 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6159 pic16_pCodeRegMapLiveRanges(pb);
6161 pic16_RemoveUnusedRegisters();
6163 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6164 pic16_pCodeRegOptimizeRegUsage(level);
6172 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6177 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6179 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6180 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6181 pcflow = pcflow->next) {
6183 FillFlow(PCFL(pcflow));
6188 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6191 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6192 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6193 pcflow = pcflow->next) {
6195 FlowStats(PCFL(pcflow));
6201 /* VR -- no need to analyze banking in flow, but left here :
6202 * 1. because it may be used in the future for other purposes
6203 * 2. because if omitted we'll miss some optimization done here
6205 * Perhaps I should rename it to something else
6208 /*-----------------------------------------------------------------*/
6209 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6210 /* assigned to the registers. */
6212 /*-----------------------------------------------------------------*/
6214 void pic16_AnalyzeBanking(void)
6218 if(!pic16_picIsInitialized()) {
6219 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6220 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6221 fprintf(stderr,"support/scripts/inc2h.pl\n");
6222 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6224 /* I think it took a long long time to fix this bug! ;-) -- VR */
6230 /* Phase x - Flow Analysis - Used Banks
6232 * In this phase, the individual flow blocks are examined
6233 * to determine the Register Banks they use
6239 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6240 // BanksUsedFlow(pb);
6242 if(!the_pFile)return;
6244 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6245 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6246 pic16_FixRegisterBanking(pb);
6251 /*-----------------------------------------------------------------*/
6252 /* buildCallTree - Look at the flow and extract all of the calls. */
6253 /*-----------------------------------------------------------------*/
6254 static set *register_usage(pBlock *pb);
6256 static void buildCallTree(void )
6267 /* Now build the call tree.
6268 First we examine all of the pCodes for functions.
6269 Keep in mind that the function boundaries coincide
6270 with pBlock boundaries.
6272 The algorithm goes something like this:
6273 We have two nested loops. The outer loop iterates
6274 through all of the pBlocks/functions. The inner
6275 loop iterates through all of the pCodes for
6276 a given pBlock. When we begin iterating through
6277 a pBlock, the variable pc_fstart, pCode of the start
6278 of a function, is cleared. We then search for pCodes
6279 of type PC_FUNCTION. When one is encountered, we
6280 initialize pc_fstart to this and at the same time
6281 associate a new pBranch object that signifies a
6282 branch entry. If a return is found, then this signifies
6283 a function exit point. We'll link the pCodes of these
6284 returns to the matching pc_fstart.
6286 When we're done, a doubly linked list of pBranches
6287 will exist. The head of this list is stored in
6288 `the_pFile', which is the meta structure for all
6289 of the pCode. Look at the pic16_printCallTree function
6290 on how the pBranches are linked together.
6293 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6294 pCode *pc_fstart=NULL;
6295 for(pc = pb->pcHead; pc; pc = pc->next) {
6297 if (PCF(pc)->fname) {
6299 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6300 //fprintf(stderr," found main \n");
6301 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6305 pbr = Safe_calloc(1,sizeof(pBranch));
6306 pbr->pc = pc_fstart = pc;
6309 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6311 // Here's a better way of doing the same:
6312 addSet(&pb->function_entries, pc);
6315 // Found an exit point in a function, e.g. return
6316 // (Note, there may be more than one return per function)
6318 pBranchLink(PCF(pc_fstart), PCF(pc));
6320 addSet(&pb->function_exits, pc);
6322 } else if(isCALL(pc)) {
6323 addSet(&pb->function_calls,pc);
6328 /* Re-allocate the registers so that there are no collisions
6329 * between local variables when one function call another */
6332 // pic16_deallocateAllRegs();
6334 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6341 /*-----------------------------------------------------------------*/
6342 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6343 /* all of the logical connections. */
6345 /* Essentially what's done here is that the pCode flow is */
6347 /*-----------------------------------------------------------------*/
6349 void pic16_AnalyzepCode(char dbName)
6360 /* Phase 1 - Register allocation and peep hole optimization
6362 * The first part of the analysis is to determine the registers
6363 * that are used in the pCode. Once that is done, the peep rules
6364 * are applied to the code. We continue to loop until no more
6365 * peep rule optimizations are found (or until we exceed the
6366 * MAX_PASSES threshold).
6368 * When done, the required registers will be determined.
6374 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6375 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6377 /* First, merge the labels with the instructions */
6378 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6379 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6381 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6382 //fprintf(stderr," analyze and merging block %c\n",dbName);
6383 pic16_pBlockMergeLabels(pb);
6386 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6391 changes = OptimizepCode(dbName);
6394 } while(changes && (i++ < MAX_PASSES));
6399 /*-----------------------------------------------------------------*/
6400 /* ispCodeFunction - returns true if *pc is the pCode of a */
6402 /*-----------------------------------------------------------------*/
6403 static bool ispCodeFunction(pCode *pc)
6406 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6412 /*-----------------------------------------------------------------*/
6413 /* findFunction - Search for a function by name (given the name) */
6414 /* in the set of all functions that are in a pBlock */
6415 /* (note - I expect this to change because I'm planning to limit */
6416 /* pBlock's to just one function declaration */
6417 /*-----------------------------------------------------------------*/
6418 static pCode *findFunction(char *fname)
6425 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6427 pc = setFirstItem(pb->function_entries);
6430 if((pc->type == PC_FUNCTION) &&
6432 (strcmp(fname, PCF(pc)->fname)==0))
6435 pc = setNextItem(pb->function_entries);
6443 static void MarkUsedRegisters(set *regset)
6448 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6449 // fprintf(stderr, "marking register = %s\t", r1->name);
6450 r2 = pic16_regWithIdx(r1->rIdx);
6451 // fprintf(stderr, "to register = %s\n", r2->name);
6457 static void pBlockStats(FILE *of, pBlock *pb)
6463 if(!pic16_pcode_verbose)return;
6465 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6467 // for now just print the first element of each set
6468 pc = setFirstItem(pb->function_entries);
6470 fprintf(of,";entry: ");
6473 pc = setFirstItem(pb->function_exits);
6475 fprintf(of,";has an exit\n");
6479 pc = setFirstItem(pb->function_calls);
6481 fprintf(of,";functions called:\n");
6484 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6485 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6487 pc = setNextItem(pb->function_calls);
6491 r = setFirstItem(pb->tregisters);
6493 int n = elementsInSet(pb->tregisters);
6495 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6498 fprintf(of,"; %s\n",r->name);
6499 r = setNextItem(pb->tregisters);
6504 /*-----------------------------------------------------------------*/
6505 /*-----------------------------------------------------------------*/
6507 static void sequencepCode(void)
6513 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6515 pb->seq = GpCodeSequenceNumber+1;
6517 for( pc = pb->pcHead; pc; pc = pc->next)
6518 pc->seq = ++GpCodeSequenceNumber;
6524 /*-----------------------------------------------------------------*/
6525 /*-----------------------------------------------------------------*/
6526 static set *register_usage(pBlock *pb)
6529 set *registers=NULL;
6530 set *registersInCallPath = NULL;
6532 /* check recursion */
6534 pc = setFirstItem(pb->function_entries);
6541 if(pc->type != PC_FUNCTION)
6542 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6544 pc = setFirstItem(pb->function_calls);
6545 for( ; pc; pc = setNextItem(pb->function_calls)) {
6547 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6548 char *dest = pic16_get_op_from_instruction(PCI(pc));
6550 pcn = findFunction(dest);
6552 registersInCallPath = register_usage(pcn->pb);
6554 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6559 pBlockStats(stderr,pb); // debug
6562 // Mark the registers in this block as used.
6564 MarkUsedRegisters(pb->tregisters);
6565 if(registersInCallPath) {
6566 /* registers were used in the functions this pBlock has called */
6567 /* so now, we need to see if these collide with the ones we are */
6570 regs *r1,*r2, *newreg;
6572 DFPRINTF((stderr,"comparing registers\n"));
6574 r1 = setFirstItem(registersInCallPath);
6577 r2 = setFirstItem(pb->tregisters);
6579 while(r2 && (r1->type != REG_STK)) {
6581 if(r2->rIdx == r1->rIdx) {
6582 newreg = pic16_findFreeReg(REG_GPR);
6586 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6590 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6591 r1->rIdx, newreg->rIdx));
6592 r2->rIdx = newreg->rIdx;
6593 //if(r2->name) free(r2->name);
6595 r2->name = Safe_strdup(newreg->name);
6599 newreg->wasUsed = 1;
6601 r2 = setNextItem(pb->tregisters);
6604 r1 = setNextItem(registersInCallPath);
6607 /* Collisions have been resolved. Now free the registers in the call path */
6608 r1 = setFirstItem(registersInCallPath);
6610 if(r1->type != REG_STK) {
6611 newreg = pic16_regWithIdx(r1->rIdx);
6614 r1 = setNextItem(registersInCallPath);
6618 // MarkUsedRegisters(pb->registers);
6620 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6623 DFPRINTF((stderr,"returning regs\n"));
6625 DFPRINTF((stderr,"not returning regs\n"));
6627 DFPRINTF((stderr,"pBlock after register optim.\n"));
6628 pBlockStats(stderr,pb); // debug
6634 /*-----------------------------------------------------------------*/
6635 /* pct2 - writes the call tree to a file */
6637 /*-----------------------------------------------------------------*/
6638 static void pct2(FILE *of,pBlock *pb,int indent)
6642 // set *registersInCallPath = NULL;
6648 return; //recursion ?
6650 pc = setFirstItem(pb->function_entries);
6657 for(i=0;i<indent;i++) // Indentation
6660 if(pc->type == PC_FUNCTION)
6661 fprintf(of,"%s\n",PCF(pc)->fname);
6666 pc = setFirstItem(pb->function_calls);
6667 for( ; pc; pc = setNextItem(pb->function_calls)) {
6669 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6670 char *dest = pic16_get_op_from_instruction(PCI(pc));
6672 pcn = findFunction(dest);
6674 pct2(of,pcn->pb,indent+1);
6676 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6684 /*-----------------------------------------------------------------*/
6685 /* pic16_printCallTree - writes the call tree to a file */
6687 /*-----------------------------------------------------------------*/
6689 void pic16_printCallTree(FILE *of)
6701 fprintf(of, "\npBlock statistics\n");
6702 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6707 fprintf(of,"Call Tree\n");
6708 pbr = the_pFile->functions;
6712 if(!ispCodeFunction(pc))
6713 fprintf(of,"bug in call tree");
6716 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6718 while(pc->next && !ispCodeFunction(pc->next)) {
6720 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6721 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6729 fprintf(of,"\n**************\n\na better call tree\n");
6730 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6735 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6736 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6742 /*-----------------------------------------------------------------*/
6744 /*-----------------------------------------------------------------*/
6746 static void InlineFunction(pBlock *pb)
6754 pc = setFirstItem(pb->function_calls);
6756 for( ; pc; pc = setNextItem(pb->function_calls)) {
6759 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6765 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
6767 //fprintf(stderr,"Cool can inline:\n");
6768 //pcn->print(stderr,pcn);
6770 //fprintf(stderr,"recursive call Inline\n");
6771 InlineFunction(pcn->pb);
6772 //fprintf(stderr,"return from recursive call Inline\n");
6775 At this point, *pc points to a CALL mnemonic, and
6776 *pcn points to the function that is being called.
6778 To in-line this call, we need to remove the CALL
6779 and RETURN(s), and link the function pCode in with
6785 /* Remove the CALL */
6789 /* remove callee pBlock from the pBlock linked list */
6790 removepBlock(pcn->pb);
6798 /* Remove the Function pCode */
6799 pct = pic16_findNextInstruction(pcn->next);
6801 /* Link the function with the callee */
6802 pc->next = pcn->next;
6803 pcn->next->prev = pc;
6805 /* Convert the function name into a label */
6807 pbr = Safe_calloc(1,sizeof(pBranch));
6808 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6810 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6811 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6813 /* turn all of the return's except the last into goto's */
6814 /* check case for 2 instruction pBlocks */
6815 pce = pic16_findNextInstruction(pcn->next);
6817 pCode *pce_next = pic16_findNextInstruction(pce->next);
6819 if(pce_next == NULL) {
6820 /* found the last return */
6821 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6823 //fprintf(stderr,"found last return\n");
6824 //pce->print(stderr,pce);
6825 pce->prev->next = pc_call->next;
6826 pc_call->next->prev = pce->prev;
6827 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6837 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6843 /*-----------------------------------------------------------------*/
6845 /*-----------------------------------------------------------------*/
6847 void pic16_InlinepCode(void)
6856 if(!functionInlining)
6859 /* Loop through all of the function definitions and count the
6860 * number of times each one is called */
6861 //fprintf(stderr,"inlining %d\n",__LINE__);
6863 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6865 pc = setFirstItem(pb->function_calls);
6867 for( ; pc; pc = setNextItem(pb->function_calls)) {
6870 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6871 if(pcn && isPCF(pcn)) {
6872 PCF(pcn)->ncalled++;
6875 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6880 //fprintf(stderr,"inlining %d\n",__LINE__);
6882 /* Now, Loop through the function definitions again, but this
6883 * time inline those functions that have only been called once. */
6885 InlineFunction(the_pFile->pbHead);
6886 //fprintf(stderr,"inlining %d\n",__LINE__);
6888 for(pb = the_pFile->pbHead; pb; pb = pb->next)